chore(rebar): Pier_T_rebar 작업 폴더 초기 구성 및 외부 의존 파일 통합
- Code\rebar_pipeline, review_pipeline, pier-program을 정션에서 실제 폴더로 전환 - Code\rhino_mcp 및 CLAUDE_rhino배경.md 추가, .mcp.json은 PYTHONPATH로 새 위치 사용 - pier-program 내부 .git 제거(이력은 backup\pier-program_20261028.bundle에 보관) - worktree 가이드 반영(CLAUDE.local.md, HANDOFF.md) - D:\Rhino-MCP 경로 참조를 새 위치로 치환 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
964a841de1
3978 files changed
+58013356
No files matched your search
@@ -0,0 +1,86 @@
|
||||
# API Design Patterns
|
||||
|
||||
> Shared API design patterns for Skills and Agents
|
||||
>
|
||||
> Usage: Add to frontmatter imports in SKILL.md or Agent.md
|
||||
> ```yaml
|
||||
> imports:
|
||||
> - ${PLUGIN_ROOT}/templates/shared/api-patterns.md
|
||||
> ```
|
||||
|
||||
## RESTful Endpoint Conventions
|
||||
|
||||
| Action | HTTP Method | Path | Example |
|
||||
|--------|-------------|------|---------|
|
||||
| List | GET | /resources | GET /users |
|
||||
| Get one | GET | /resources/:id | GET /users/123 |
|
||||
| Create | POST | /resources | POST /users |
|
||||
| Update | PUT/PATCH | /resources/:id | PUT /users/123 |
|
||||
| Delete | DELETE | /resources/:id | DELETE /users/123 |
|
||||
|
||||
## Request/Response Standards
|
||||
|
||||
### Request Headers
|
||||
|
||||
```http
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {token}
|
||||
X-Request-ID: {uuid}
|
||||
```
|
||||
|
||||
### Success Response
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": { /* response payload */ },
|
||||
"meta": {
|
||||
"timestamp": "2026-01-26T00:00:00Z",
|
||||
"requestId": "uuid"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Pagination
|
||||
|
||||
```json
|
||||
{
|
||||
"data": [...],
|
||||
"pagination": {
|
||||
"page": 1,
|
||||
"pageSize": 20,
|
||||
"totalCount": 100,
|
||||
"totalPages": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Documentation Pattern
|
||||
|
||||
```markdown
|
||||
## POST /api/resource
|
||||
|
||||
**Description**: Create a new resource
|
||||
|
||||
**Request Body**:
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| name | string | Yes | Resource name |
|
||||
|
||||
**Response** (201 Created):
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| id | string | Created resource ID |
|
||||
|
||||
**Errors**:
|
||||
- 400: Invalid request body
|
||||
- 401: Authentication required
|
||||
```
|
||||
|
||||
## Rate Limiting Headers
|
||||
|
||||
```http
|
||||
X-RateLimit-Limit: 100
|
||||
X-RateLimit-Remaining: 99
|
||||
X-RateLimit-Reset: 1706227200
|
||||
```
|
||||
@@ -0,0 +1,139 @@
|
||||
# bkend.ai Common Patterns
|
||||
|
||||
## MCP Fixed Tools (Always Available)
|
||||
|
||||
| Tool | Purpose | Parameters |
|
||||
|------|---------|------------|
|
||||
| `get_context` | Session context (org/project/env, API endpoint) | None |
|
||||
| `search_docs` | Search bkend documentation (Auth/Storage guides) | query: string |
|
||||
| `get_operation_schema` | Get tool input/output schema | operation: string, schemaType: "input" \| "output" |
|
||||
|
||||
**Important**: `get_context` MUST be called first. It returns the API endpoint URL dynamically.
|
||||
|
||||
## MCP Resources (Read-Only, Cached)
|
||||
|
||||
| URI Pattern | Description | Cache TTL |
|
||||
|-------------|-------------|-----------|
|
||||
| `bkend://orgs` | Organization list | 60s |
|
||||
| `bkend://orgs/{orgId}/projects` | Project list | 60s |
|
||||
| `bkend://orgs/{orgId}/projects/{pId}/environments` | Environment list | 60s |
|
||||
| `bkend://orgs/{orgId}/projects/{pId}/environments/{eId}/tables` | Table list with schema | 60s |
|
||||
|
||||
Access via `resources/list` and `resources/read` MCP methods.
|
||||
Prefer Resources over Tools for read-only listing (lighter, cached).
|
||||
|
||||
## REST Service API
|
||||
|
||||
Base URL is provided dynamically by `get_context` response.
|
||||
Typical endpoints:
|
||||
- MCP: https://api.bkend.ai/mcp
|
||||
- Service API: Use the endpoint from `get_context` (e.g., https://api-client.bkend.ai/v1)
|
||||
|
||||
**Important**: Do NOT hardcode the Service API base URL. Always reference `get_context` output.
|
||||
|
||||
## Required Headers (REST Service API)
|
||||
|
||||
```
|
||||
x-project-id: {projectId}
|
||||
x-environment: dev | staging | prod
|
||||
Authorization: Bearer {accessToken}
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
## API Response Format
|
||||
|
||||
List responses use consistent pagination:
|
||||
```json
|
||||
{
|
||||
"items": [...],
|
||||
"pagination": { "page": 1, "limit": 20, "total": 100, "totalPages": 5 }
|
||||
}
|
||||
```
|
||||
|
||||
**ID Field**: Always use `id` (NOT `_id`).
|
||||
|
||||
## Query Parameters
|
||||
|
||||
### Filtering
|
||||
- AND filter: `?filter[field]=value` (multiple fields = AND)
|
||||
- Operators: `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`
|
||||
- Text search: `?search=keyword`
|
||||
|
||||
### Pagination & Sorting
|
||||
- Page: `?page=1` (default: 1)
|
||||
- Limit: `?limit=20` (default: 20, max: 100)
|
||||
- Sort: `?sort=field:asc` (or `desc`)
|
||||
|
||||
## File Upload (Presigned URL)
|
||||
|
||||
- Presigned URL validity: 15 minutes
|
||||
- Upload via PUT method with Content-Type header
|
||||
- Complete upload by registering metadata: POST /v1/files
|
||||
|
||||
## Error Response Format
|
||||
|
||||
```json
|
||||
{ "error": { "code": "ERROR_CODE", "message": "Human readable message" } }
|
||||
```
|
||||
|
||||
## HTTP Status Mapping
|
||||
|
||||
| Status | Meaning |
|
||||
|--------|---------|
|
||||
| 200 | Success |
|
||||
| 400 | Bad Request (validation) |
|
||||
| 401 | Unauthorized (token expired/missing) |
|
||||
| 403 | Forbidden (insufficient permissions) |
|
||||
| 404 | Not Found |
|
||||
| 409 | Conflict (unique constraint violation) |
|
||||
| 429 | Rate Limit Exceeded (100 requests/hour) |
|
||||
| 500 | Internal Server Error |
|
||||
|
||||
## MCP Endpoint
|
||||
|
||||
```
|
||||
URL: https://api.bkend.ai/mcp
|
||||
Transport: Streamable HTTP
|
||||
Protocol: JSON-RPC 2.0
|
||||
Auth: OAuth 2.1 + PKCE
|
||||
```
|
||||
|
||||
## MCP Setup (Antigravity Platform)
|
||||
|
||||
```bash
|
||||
ai-agent mcp add bkend --transport http https://api.bkend.ai/mcp
|
||||
```
|
||||
|
||||
## .mcp.json (Project Config)
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"bkend": {
|
||||
"type": "http",
|
||||
"url": "https://api.bkend.ai/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
- OAuth 2.1 + PKCE (browser auto-auth)
|
||||
- No API Key needed
|
||||
- Access Token: 1 hour
|
||||
- Refresh Token: 30 days
|
||||
|
||||
## Environment Auto-Provisioning
|
||||
|
||||
| Plan | Available Environments |
|
||||
|------|----------------------|
|
||||
| Free | dev (1) |
|
||||
| Pro | dev, staging, prod |
|
||||
| Enterprise | dev, staging, prod + custom |
|
||||
|
||||
## Resource Hierarchy
|
||||
|
||||
```
|
||||
Organization (team/billing) → Project (service unit) → Environment (dev/staging/prod, data isolation)
|
||||
```
|
||||
@@ -0,0 +1,149 @@
|
||||
# Error Handling Patterns
|
||||
|
||||
> Shared error handling patterns for Skills and Agents
|
||||
>
|
||||
> Usage: Add to frontmatter imports in SKILL.md or Agent.md
|
||||
> ```yaml
|
||||
> imports:
|
||||
> - ${PLUGIN_ROOT}/templates/shared/error-handling-patterns.md
|
||||
> ```
|
||||
|
||||
## Standard Error Response Format
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": {
|
||||
"code": "ERROR_CODE",
|
||||
"message": "Human readable message",
|
||||
"details": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Error Code Conventions
|
||||
|
||||
| Category | Prefix | Example |
|
||||
|----------|--------|---------|
|
||||
| Authentication | AUTH_ | AUTH_INVALID_TOKEN |
|
||||
| Validation | VALIDATION_ | VALIDATION_REQUIRED_FIELD |
|
||||
| Permission | PERMISSION_ | PERMISSION_DENIED |
|
||||
| Resource | RESOURCE_ | RESOURCE_NOT_FOUND |
|
||||
| Server | SERVER_ | SERVER_INTERNAL_ERROR |
|
||||
|
||||
## Error Handling Rules
|
||||
|
||||
1. **Always return structured errors** - Never expose raw exceptions
|
||||
2. **Use appropriate HTTP status codes**:
|
||||
- 400: Client error (validation, bad request)
|
||||
- 401: Authentication required
|
||||
- 403: Permission denied
|
||||
- 404: Resource not found
|
||||
- 500: Server error
|
||||
3. **Log errors with context** - Include request ID, user ID, timestamp
|
||||
4. **Sanitize error messages** - Remove sensitive data before response
|
||||
|
||||
## Try-Catch Pattern
|
||||
|
||||
```javascript
|
||||
try {
|
||||
// Operation
|
||||
} catch (error) {
|
||||
debugLog('ModuleName', 'Operation failed', {
|
||||
error: error.message,
|
||||
context: { /* relevant data */ }
|
||||
});
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: categorizeError(error),
|
||||
message: sanitizeErrorMessage(error)
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Sentry Integration (Enterprise Level)
|
||||
|
||||
### Frontend — Next.js Error Boundary + Sentry
|
||||
|
||||
```typescript
|
||||
// app/error.tsx (Next.js App Router)
|
||||
'use client';
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export default function Error({ error, reset }: { error: Error; reset: () => void }) {
|
||||
useEffect(() => {
|
||||
Sentry.captureException(error);
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>Something went wrong</h2>
|
||||
<button onClick={reset}>Try again</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Backend — FastAPI Error Middleware + Sentry
|
||||
|
||||
```python
|
||||
# services/shared/middleware/error_handler.py
|
||||
import sentry_sdk
|
||||
from fastapi import Request
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
async def error_handler(request: Request, exc: Exception):
|
||||
# Sentry captures automatically via ASGI integration
|
||||
# Add custom context for Self-Healing Agent
|
||||
sentry_sdk.set_context("request", {
|
||||
"url": str(request.url),
|
||||
"method": request.method,
|
||||
"headers": dict(request.headers),
|
||||
})
|
||||
sentry_sdk.set_tag("service", SERVICE_NAME)
|
||||
|
||||
return JSONResponse(
|
||||
status_code=500,
|
||||
content={
|
||||
"success": False,
|
||||
"error": {
|
||||
"code": "SERVER_INTERNAL_ERROR",
|
||||
"message": "An unexpected error occurred",
|
||||
"request_id": request.state.request_id,
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### Error Severity → Self-Healing Mapping
|
||||
|
||||
| Sentry Level | Self-Healing Action | Auto-Rollback |
|
||||
|-------------|---------------------|---------------|
|
||||
| Fatal | Immediate escalation (PagerDuty) | Yes |
|
||||
| Error (new) | Self-Healing trigger | No (wait for fix) |
|
||||
| Error (regression) | Self-Healing + PagerDuty | Yes if spike |
|
||||
| Warning | Log only | No |
|
||||
| Info | Ignore | No |
|
||||
|
||||
### Structured Logging for Sentry Correlation
|
||||
|
||||
```python
|
||||
# JSON log format — correlates with Sentry events
|
||||
import structlog
|
||||
|
||||
logger = structlog.get_logger()
|
||||
|
||||
logger.error(
|
||||
"payment_failed",
|
||||
user_id=user.id,
|
||||
amount=amount,
|
||||
error=str(exc),
|
||||
trace_id=span.trace_id, # Links to Tempo trace
|
||||
sentry_event_id=sentry_sdk.last_event_id(), # Links to Sentry
|
||||
request_id=request.state.request_id,
|
||||
)
|
||||
```
|
||||
@@ -0,0 +1,68 @@
|
||||
# Naming Conventions
|
||||
|
||||
> Shared naming conventions for Skills and Agents
|
||||
>
|
||||
> Usage: Add to frontmatter imports in SKILL.md or Agent.md
|
||||
> ```yaml
|
||||
> imports:
|
||||
> - ${PLUGIN_ROOT}/templates/shared/naming-conventions.md
|
||||
> ```
|
||||
|
||||
## Code Naming
|
||||
|
||||
| Category | Convention | Example |
|
||||
|----------|------------|---------|
|
||||
| Components | PascalCase | `UserProfile`, `LoginForm` |
|
||||
| Functions | camelCase | `getUserById`, `validateInput` |
|
||||
| Constants | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT`, `API_BASE_URL` |
|
||||
| Variables | camelCase | `userName`, `isLoading` |
|
||||
| Files | kebab-case | `user-profile.tsx`, `api-client.js` |
|
||||
| CSS Classes | kebab-case | `user-card`, `nav-menu` |
|
||||
| Database Tables | snake_case | `user_profiles`, `order_items` |
|
||||
|
||||
## File Structure Naming
|
||||
|
||||
```
|
||||
src/
|
||||
├── components/ # PascalCase
|
||||
│ └── UserCard.tsx
|
||||
├── hooks/ # camelCase with use- prefix
|
||||
│ └── useAuth.ts
|
||||
├── utils/ # camelCase
|
||||
│ └── formatDate.ts
|
||||
├── types/ # PascalCase
|
||||
│ └── User.ts
|
||||
└── api/ # kebab-case
|
||||
└── user-api.ts
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Prefix | Purpose | Example |
|
||||
|--------|---------|---------|
|
||||
| NEXT_PUBLIC_ | Client-side (Next.js) | NEXT_PUBLIC_API_URL |
|
||||
| DB_ | Database | DB_HOST, DB_PORT |
|
||||
| API_ | External APIs | API_KEY, API_SECRET |
|
||||
| AUTH_ | Authentication | AUTH_SECRET, AUTH_PROVIDER |
|
||||
| SMTP_ | Email | SMTP_HOST, SMTP_PORT |
|
||||
| STORAGE_ | File storage | STORAGE_BUCKET |
|
||||
|
||||
## Boolean Naming
|
||||
|
||||
```javascript
|
||||
// Preferred prefixes for booleans
|
||||
is - isActive, isLoading, isValid
|
||||
has - hasPermission, hasError
|
||||
can - canEdit, canDelete
|
||||
should - shouldRefresh, shouldValidate
|
||||
```
|
||||
|
||||
## Event Handler Naming
|
||||
|
||||
```javascript
|
||||
// Prefix with 'handle' or 'on'
|
||||
handleClick // internal handler
|
||||
onClick // prop passed to component
|
||||
handleSubmit // form submission
|
||||
onSuccess // callback prop
|
||||
```
|
||||
Reference in new issue
Block a user