This commit is contained in:
2026-06-05 15:01:34 +03:00
parent 50180aaa14
commit 4cef6af041
27 changed files with 13547 additions and 892 deletions

View File

@@ -7,7 +7,10 @@ description: Python-specific GRACE-Poly protocol: few-shot complexity examples,
@BRIEF Python-specific HOW: few-shot complexity examples, belief runtime patterns, module decomposition, and FastAPI/SQLAlchemy conventions for the GRACE-Poly protocol in ss-tools.
@RELATION DEPENDS_ON -> [Std.Semantics.Core]
@RELATION DEPENDS_ON -> [Std.Semantics.Contracts]
@RELATION DISPATCHES -> [MolecularCoTLogging]
@RESTRICTION EXAMPLES ONLY — this file provides language-specific code patterns. All protocol rules (tier definitions, tag catalog, anchor syntax) are defined exclusively in `semantics-core`. This file MUST NOT redefine or contradict any rule from `semantics-core`.
@RATIONALE Python's async/await model, FastAPI dependency injection, and SQLAlchemy session management create unique failure modes for Transformer agents: (1) async/await boundary confusion — agents write sync code in async contexts or forget `await` on ORM calls, producing silent no-ops; (2) dependency injection blindness — FastAPI's `Depends()` creates implicit call graphs that the agent's attention cannot trace without explicit @RELATION edges; (3) session lifecycle drift — SQLAlchemy sessions have strict boundaries that agents violate by passing detached objects across function calls. Concrete examples at each complexity tier act as few-shot anchors that override the agent's pre-trained (and often wrong) Python patterns.
@REJECTED Generic Python patterns without GRACE anchors were rejected — agents produce working code that violates module size limits (INV_7), omits belief runtime markers, and creates orphan contracts invisible to the semantic index. Relying on the agent's pre-trained FastAPI/SQLAlchemy knowledge without project-specific examples was rejected — ss-tools has specific conventions (trace_id propagation, plugin architecture, WebSocket logging) that general training data cannot capture.
## 0. WHEN TO USE THIS SKILL
@@ -54,34 +57,34 @@ def belief_scope(contract_id: str):
### C1 (Atomic) — DTOs, Pydantic schemas, simple constants
```python
# #region UserResponseSchema [C:1] [TYPE Class]
# #region Users.UserResponseSchema [C:1] [TYPE Class]
from pydantic import BaseModel
class UserResponseSchema(BaseModel):
id: str
username: str
email: str
# #endregion UserResponseSchema
# #endregion Users.UserResponseSchema
```
### C2 (Simple) — Pure functions, utility helpers
```python
# #region format_timestamp [C:2] [TYPE Function] [SEMANTICS time,formatting]
# #region Time.FormatTimestamp [C:2] [TYPE Function] [SEMANTICS time,formatting]
# @BRIEF Format a UTC datetime into a human-readable ISO-8601 string.
from datetime import datetime
def format_timestamp(ts: datetime) -> str:
return ts.strftime("%Y-%m-%dT%H:%M:%SZ")
# #endregion format_timestamp
# #endregion Time.FormatTimestamp
```
### C3 (Flow) — Module with nested functions, service layer
```python
# #region dashboard_migration [C:3] [TYPE Module] [SEMANTICS migration,dashboard]
# #region Migration.Dashboard [C:3] [TYPE Module] [SEMANTICS migration,dashboard]
# @BRIEF Dashboard migration service — export/import dashboards with validation.
# @LAYER Service
# #region migrate_dashboard [C:3] [TYPE Function] [SEMANTICS migration,dashboard]
# #region Migration.Dashboard.Migrate [C:3] [TYPE Function] [SEMANTICS migration,dashboard]
# @BRIEF Migrate a single dashboard from source to target Superset instance.
# @RELATION DEPENDS_ON -> [SupersetClient]
# @RELATION DEPENDS_ON -> [DashboardValidator]
@@ -91,14 +94,14 @@ def migrate_dashboard(source_client, target_client, dashboard_id: str, db_mappin
mapped = apply_db_mapping(dashboard, db_mapping)
result = target_client.import_dashboard(mapped)
return result
# #endregion migrate_dashboard
# #endregion Migration.Dashboard.Migrate
# #endregion dashboard_migration
# #endregion Migration.Dashboard
```
### C4 (Orchestration) — Stateful operations with belief runtime
```python
# #region run_migration_task [C:4] [TYPE Function] [SEMANTICS migration,task,state]
# #region Migration.RunTask [C:4] [TYPE Function] [SEMANTICS migration,task,state]
# @BRIEF Execute a full migration task with rollback capability and progress reporting.
# @PRE Database connection is established. Task record exists with valid migration plan.
# @POST Task status updated to COMPLETED or FAILED. Migration audit log written.
@@ -107,35 +110,35 @@ def migrate_dashboard(source_client, target_client, dashboard_id: str, db_mappin
# @RELATION DEPENDS_ON -> [MigrationService]
# @RELATION DEPENDS_ON -> [WebSocketNotifier]
async def run_migration_task(task_id: str, db_session) -> dict:
log("run_migration_task", "REASON", "Starting migration task", {"task_id": task_id})
log("Migration.RunTask", "REASON", "Starting migration task", {"task_id": task_id})
task = await db_session.get(Task, task_id)
if not task:
log("run_migration_task", "EXPLORE", "Task not found", error="TaskNotFound")
log("Migration.RunTask", "EXPLORE", "Task not found", error="TaskNotFound")
raise TaskNotFoundError(task_id)
try:
task.status = "RUNNING"
await db_session.commit()
log("run_migration_task", "REASON", "Task status set to RUNNING", {"task_id": task_id})
log("Migration.RunTask", "REASON", "Task status set to RUNNING", {"task_id": task_id})
result = await execute_migration_plan(task.migration_plan)
task.status = "COMPLETED"
task.result = result
await db_session.commit()
await notify_frontend(task_id, "completed", result)
log("run_migration_task", "REFLECT", "Migration completed successfully", {"task_id": task_id, "dashboards": len(result)})
log("Migration.RunTask", "REFLECT", "Migration completed", {"task_id": task_id, "dashboards": len(result)})
return result
except Exception as e:
log("run_migration_task", "EXPLORE", "Migration failed, rolling back", {"task_id": task_id}, error=str(e))
log("Migration.RunTask", "EXPLORE", "Migration failed, rolling back", {"task_id": task_id}, error=str(e))
task.status = "FAILED"
task.error = str(e)
await db_session.commit()
await notify_frontend(task_id, "failed", {"error": str(e)})
raise
# #endregion run_migration_task
# #endregion Migration.RunTask
```
### C5 (Critical) — With decision memory
```python
# #region rebuild_index [C:5] [TYPE Function] [SEMANTICS indexing,recovery,semantic]
# #region Index.Rebuild [C:5] [TYPE Function] [SEMANTICS indexing,recovery,semantic]
# @BRIEF Rebuild the full semantic index from source with atomic swap and rollback.
# @PRE Workspace root is accessible. Source files exist.
# @POST New index atomically swapped; old preserved for rollback.
@@ -149,19 +152,19 @@ async def run_migration_task(task_id: str, db_session) -> dict:
# @REJECTED Incremental-only update was rejected — it leaves stale edges when contracts
# are deleted; only full scan guarantees consistency.
def rebuild_index(root_path: str) -> dict:
log("rebuild_index", "REASON", "Scanning source files", {"root": root_path})
log("Index.Rebuild", "REASON", "Scanning source files", {"root": root_path})
contracts = []
for filepath in scan_files(root_path):
try:
parsed = parse_contract(filepath)
contracts.append(parsed)
except Exception as e:
log("rebuild_index", "EXPLORE", "Parse failure, skipping file", {"file": filepath}, error=str(e))
log("Index.Rebuild", "EXPLORE", "Parse failure, skipping file", {"file": filepath}, error=str(e))
snapshot = {"contracts": contracts, "timestamp": datetime.utcnow().isoformat()}
write_checkpoint(root_path, snapshot)
log("rebuild_index", "REFLECT", "Rebuild complete", {"contracts": len(contracts)})
log("Index.Rebuild", "REFLECT", "Rebuild complete", {"contracts": len(contracts)})
return snapshot
# #endregion rebuild_index
# #endregion Index.Rebuild
```
## III. PYTHON MODULE PATTERNS
@@ -196,7 +199,7 @@ backend/
### FastAPI route pattern
```python
# #region dashboard_routes [C:3] [TYPE Module] [SEMANTICS api,dashboard]
# #region Api.Dashboards [C:3] [TYPE Module] [SEMANTICS api,dashboard]
# @BRIEF Dashboard CRUD and migration API routes.
# @RELATION DEPENDS_ON -> [DashboardService]
# @RELATION DEPENDS_ON -> [AuthMiddleware]
@@ -204,7 +207,7 @@ from fastapi import APIRouter, Depends
router = APIRouter(prefix="/api/dashboards", tags=["dashboards"])
# #region list_dashboards [C:2] [TYPE Function] [SEMANTICS api,query]
# #region Dashboards.List [C:2] [TYPE Function] [SEMANTICS api,query]
# @BRIEF List dashboards with optional filters.
@router.get("/")
async def list_dashboards(
@@ -213,14 +216,14 @@ async def list_dashboards(
service=Depends(get_dashboard_service)
):
return await service.list_dashboards(page, page_size)
# #endregion list_dashboards
# #endregion Dashboards.List
# #endregion dashboard_routes
# #endregion Api.Dashboards
```
### SQLAlchemy model pattern
```python
# #region Dashboard [C:1] [TYPE Class]
# #region Models.Dashboard [C:1] [TYPE Class]
from sqlalchemy import Column, String, DateTime, JSON
from sqlalchemy.orm import declarative_base
@@ -232,7 +235,7 @@ class Dashboard(Base):
title = Column(String, nullable=False)
metadata = Column(JSON)
created_at = Column(DateTime, server_default="now()")
# #endregion Dashboard
# #endregion Models.Dashboard
```
## IV. PYTHON VERIFICATION