log refactor
This commit is contained in:
@@ -8,6 +8,7 @@ description: Python-specific GRACE-Poly protocol: few-shot complexity examples,
|
||||
@RELATION DEPENDS_ON -> [Std.Semantics.Core]
|
||||
@RELATION DEPENDS_ON -> [Std.Semantics.Belief]
|
||||
@RELATION DEPENDS_ON -> [Std.Semantics.Contracts]
|
||||
@RELATION DEPENDS_ON -> [MolecularCoTLogging]
|
||||
|
||||
## 0. WHEN TO USE THIS SKILL
|
||||
|
||||
@@ -15,39 +16,40 @@ Load this skill when implementing Python backend code under the GRACE-Poly proto
|
||||
|
||||
## I. PYTHON BELIEF RUNTIME PATTERNS
|
||||
|
||||
ss-tools uses structured JSON logging for belief markers. The canonical pattern:
|
||||
ss-tools uses the canonical **Molecular CoT Logging** protocol for belief markers. For the full wire-format specification, see the `molecular-cot-logging` skill.
|
||||
|
||||
**ALWAYS import from the shared module — never copy-paste inline:**
|
||||
|
||||
```python
|
||||
import logging
|
||||
import json
|
||||
from contextlib import contextmanager
|
||||
from ss_tools.lib.cot_logger import log, push_span, pop_span
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
# Usage:
|
||||
# log("src_id", "REASON", "intent", payload_dict)
|
||||
# log("src_id", "EXPLORE", "message", payload_dict, error="assumption violated")
|
||||
# log("src_id", "REFLECT", "outcome", payload_dict)
|
||||
```
|
||||
|
||||
Thin context-manager wrappers (backward-compatible aliases for `push_span`/`pop_span`):
|
||||
|
||||
```python
|
||||
from contextlib import contextmanager
|
||||
|
||||
@contextmanager
|
||||
def belief_scope(contract_id: str):
|
||||
"""Thread-local belief frame for C4/C5 functions."""
|
||||
logger.info(json.dumps({"marker": "REASON", "contract": contract_id, "event": "enter"}))
|
||||
prev_span = push_span(contract_id)
|
||||
log(contract_id, "REASON", "enter")
|
||||
try:
|
||||
yield
|
||||
except Exception as e:
|
||||
logger.error(json.dumps({"marker": "EXPLORE", "contract": contract_id, "error": str(e)}))
|
||||
log(contract_id, "EXPLORE", "error", error=str(e))
|
||||
raise
|
||||
else:
|
||||
logger.info(json.dumps({"marker": "REFLECT", "contract": contract_id, "event": "exit"}))
|
||||
|
||||
# Usage:
|
||||
def reason(message: str, extra: dict = None):
|
||||
logger.info(json.dumps({"marker": "REASON", "message": message, **(extra or {})}))
|
||||
|
||||
def explore(message: str, extra: dict = None):
|
||||
logger.warning(json.dumps({"marker": "EXPLORE", "message": message, **(extra or {})}))
|
||||
|
||||
def reflect(message: str, extra: dict = None):
|
||||
logger.info(json.dumps({"marker": "REFLECT", "message": message, **(extra or {})}))
|
||||
log(contract_id, "REFLECT", "exit")
|
||||
finally:
|
||||
pop_span(prev_span)
|
||||
```
|
||||
|
||||
**CRITICAL:** Do NOT manually type `[REASON]` in message strings. ALWAYS pass structured data through the `extra` dict. The `marker` field is the canonical protocol marker.
|
||||
**CRITICAL:** All helpers MUST be imported from `ss_tools.lib.cot_logger`. Never define `reason()`, `explore()`, `reflect()` inline — use the canonical `log()` function. Do NOT manually type `[REASON]` in message strings; `log()` emits the marker field automatically in the molecular-cot JSON wire format.
|
||||
|
||||
## II. PYTHON COMPLEXITY EXAMPLES
|
||||
|
||||
@@ -106,24 +108,24 @@ 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:
|
||||
reason("Starting migration task", {"task_id": task_id})
|
||||
log("run_migration_task", "REASON", "Starting migration task", {"task_id": task_id})
|
||||
task = await db_session.get(Task, task_id)
|
||||
if not task:
|
||||
explore("Task not found", {"task_id": task_id})
|
||||
log("run_migration_task", "EXPLORE", "Task not found", error="TaskNotFound")
|
||||
raise TaskNotFoundError(task_id)
|
||||
try:
|
||||
task.status = "RUNNING"
|
||||
await db_session.commit()
|
||||
reason("Task status set to RUNNING", {"task_id": task_id})
|
||||
log("run_migration_task", "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)
|
||||
reflect("Migration completed successfully", {"task_id": task_id, "dashboards": len(result)})
|
||||
log("run_migration_task", "REFLECT", "Migration completed successfully", {"task_id": task_id, "dashboards": len(result)})
|
||||
return result
|
||||
except Exception as e:
|
||||
explore("Migration failed, rolling back", {"task_id": task_id, "error": str(e)})
|
||||
log("run_migration_task", "EXPLORE", "Migration failed, rolling back", {"task_id": task_id}, error=str(e))
|
||||
task.status = "FAILED"
|
||||
task.error = str(e)
|
||||
await db_session.commit()
|
||||
@@ -148,17 +150,17 @@ 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:
|
||||
reason("Scanning source files", {"root": root_path})
|
||||
log("rebuild_index", "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:
|
||||
explore("Parse failure, skipping file", {"file": filepath, "error": str(e)})
|
||||
log("rebuild_index", "EXPLORE", "Parse failure, skipping file", {"file": filepath}, error=str(e))
|
||||
snapshot = {"contracts": contracts, "timestamp": datetime.utcnow().isoformat()}
|
||||
write_checkpoint(root_path, snapshot)
|
||||
reflect("Rebuild complete", {"contracts": len(contracts)})
|
||||
log("rebuild_index", "REFLECT", "Rebuild complete", {"contracts": len(contracts)})
|
||||
return snapshot
|
||||
# #endregion rebuild_index
|
||||
```
|
||||
@@ -254,20 +256,22 @@ python -m mypy src/
|
||||
|
||||
### Async belief scope
|
||||
```python
|
||||
import asyncio
|
||||
from contextlib import asynccontextmanager
|
||||
from ss_tools.lib.cot_logger import log, push_span, pop_span
|
||||
|
||||
@asynccontextmanager
|
||||
async def async_belief_scope(contract_id: str):
|
||||
"""Async belief frame for C4/C5 async functions."""
|
||||
reason("enter", {"contract": contract_id})
|
||||
prev_span = push_span(contract_id)
|
||||
log(contract_id, "REASON", "enter")
|
||||
try:
|
||||
yield
|
||||
except Exception as e:
|
||||
explore("error", {"contract": contract_id, "error": str(e)})
|
||||
log(contract_id, "EXPLORE", "error", error=str(e))
|
||||
raise
|
||||
else:
|
||||
reflect("exit", {"contract": contract_id})
|
||||
log(contract_id, "REFLECT", "exit")
|
||||
finally:
|
||||
pop_span(prev_span)
|
||||
```
|
||||
|
||||
### Dependency injection convention
|
||||
|
||||
Reference in New Issue
Block a user