234 lines
11 KiB
Markdown
234 lines
11 KiB
Markdown
---
|
|
name: molecular-cot-logging
|
|
description: Structured logging protocol for agent-driven development, based on molecular Long CoT bonds (REASON/REFLECT/EXPLORE). Replaces legacy Entry/Exit/Coherence markers. Python + Svelte.
|
|
---
|
|
|
|
#region Std.Semantics.MolecularCoTLogging [C:5] [TYPE Skill] [SEMANTICS reasoning,runtime,logging,agentic]
|
|
@BRIEF Structured logging protocol for agent-driven development, based on molecular Long CoT bonds (Deep-Reasoning, Self-Reflection, Self-Exploration). Replaces legacy Entry/Exit/Coherence markers. Wire format is specified here; the Python implementation lives in `ss_tools.shared.cot_logger`.
|
|
@RELATION DEPENDS_ON -> [Std.Semantics.Core]
|
|
@RELATION DISPATCHES -> [Std.Semantics.Python]
|
|
@RELATION DISPATCHES -> [Std.Semantics.Svelte]
|
|
@RATIONALE Long CoT chains need stabilisation through explicit reasoning bonds. The three-marker system (REASON/REFLECT/EXPLORE) maps directly to the molecular CoT paper and produces machine-readable execution traces that LLM agents can parse, analyse, and use for fine-tuning (MoLE-Syn bond distributions). Without structured markers, agent-generated code exhibits invisible failures: a function returns `None` instead of raising — the agent's attention never sees it because there's no log; a fallback path activates silently — no EXPLORE marker, no trace. JSON-line format ensures every log entry is a self-contained, parseable unit that survives log rotation, aggregation, and agent parsing — unlike plain-text logs that require regex heuristics.
|
|
@REJECTED Legacy Entry/Exit/Action/Coherence markers rejected — they are too generic, do not map to reasoning structure, and prevent traceability graph analysis. Plain-text logging rejected — JSON lines are mandatory for agent parsing. Unstructured printf-style logging rejected — agents cannot reliably extract structured fields (trace_id, marker, intent) from free-form text, making automated diagnosis impossible. cot_span decorator rejected — replaced by belief_scope context manager + logger.reason/reflect/explore which gives more granular intent control per logical branch.
|
|
@DATA_CONTRACT LogEntry -> { ts: str, level: str, trace_id: str, span_id?: str, src: str, marker: REASON|REFLECT|EXPLORE, intent: str, payload?: object, error?: str }
|
|
@INVARIANT Every log line MUST carry exactly one valid marker (REASON | REFLECT | EXPLORE). No markerless log lines in C4/C5 code.
|
|
@INVARIANT trace_id MUST propagate via ContextVar across async boundaries. Every incoming request or background job seeds a new trace_id.
|
|
|
|
## Purpose
|
|
|
|
Enable **transparent agent-driven development** by producing machine-readable execution traces that directly reflect the reasoning structure of the code. Every log line becomes an edge in a traceability graph that an LLM agent can parse, analyse, and optionally use for fine-tuning (via MoLE-Syn-like bond distributions).
|
|
|
|
## Core principles (from the Molecular CoT paper)
|
|
|
|
Long CoT chains are stabilised by three "chemical bonds":
|
|
|
|
| Bond | Marker | Function |
|
|
|------|--------|----------|
|
|
| **Deep-Reasoning** | `REASON` | Extends the logical backbone |
|
|
| **Self-Reflection** | `REFLECT` | Folds back to validate or correct previous steps |
|
|
| **Self-Exploration** | `EXPLORE` | Branches into alternatives when an assumption fails |
|
|
|
|
Our logs annotate every semantically meaningful step with exactly one of these markers.
|
|
|
|
## I. Log Entry Specification
|
|
|
|
Every log record MUST be a JSON object **on a single line** with the following keys:
|
|
|
|
| Field | Required | Type | Description |
|
|
|-------|----------|------|-------------|
|
|
| `ts` | yes | string | ISO-8601 timestamp with millisecond precision |
|
|
| `level` | yes | string | Standard log level (`INFO`, `DEBUG`, `WARNING`, `ERROR`) |
|
|
| `trace_id` | yes | string | UUID of the incoming HTTP request or background job |
|
|
| `span_id` | no | string | UUID of the current function/block scope (optional) |
|
|
| `src` | yes | string | Qualified function name, e.g. `AuthRepository.get_user_by_username` |
|
|
| `marker` | yes | string | One of `REASON`, `REFLECT`, `EXPLORE` (see below) |
|
|
| `intent` | yes | string | Human-readable one-line description of what this step intends to do/verify |
|
|
| `payload` | no | object | Arbitrary key-value data relevant to the step (params, result snippet) |
|
|
| `error` | conditional | string | Error message or reason. **Optional** for `REASON`/`REFLECT`, **required** for `EXPLORE` markers when a fallback or violation is taken |
|
|
|
|
### Example
|
|
|
|
```json
|
|
{"ts":"2026-05-12T14:31:39.577","level":"INFO","trace_id":"d874a1b2-...","span_id":"...","src":"AuthRepository.get_user_by_username","marker":"REASON","intent":"Fetch user by username","payload":{"username":"admin"}}
|
|
```
|
|
|
|
## II. Semantic Marker Usage
|
|
|
|
### REASON (Deep-Reasoning)
|
|
- **When**: BEFORE an operation that extends the logical chain (DB query, API call, computation).
|
|
- **Level**: `INFO` by default, `DEBUG` for high-frequency loops.
|
|
- **`intent`**: Describes what the code is about to do.
|
|
- **`payload`**: Input parameters, context values.
|
|
- **Effect**: This is the primary "deep-reasoning" step that forms the backbone of the trace.
|
|
|
|
```python
|
|
log("AuthRepository.get_user_by_username", "REASON",
|
|
"Fetch user by username", {"username": username})
|
|
```
|
|
|
|
### REFLECT (Self-Reflection)
|
|
- **When**: AFTER an operation to **verify the outcome** or check invariants.
|
|
- **Level**: `INFO` on success, `WARNING` if invariants partially degrade.
|
|
- **`intent`**: Describes what is being verified.
|
|
- **`payload`**: Result summary, status codes, row counts.
|
|
- **Effect**: Folds the logical chain back on itself — the agent sees cause + effect in two adjacent lines.
|
|
|
|
```python
|
|
log("AuthRepository.get_user_by_username", "REFLECT",
|
|
"User found", {"found": user is not None, "user_id": user.id if user else None})
|
|
```
|
|
|
|
### EXPLORE (Self-Exploration)
|
|
- **When**: An expected condition is **violated** and the code enters a fallback, error handler, or alternative path.
|
|
- **Level**: `WARNING` for recoverable fallbacks, `ERROR` for unrecoverable failures.
|
|
- **`intent`**: Describes what assumption failed.
|
|
- **`payload`**: Relevant state at the branch point.
|
|
- **`error`**: **Required.** Explain what assumption was violated.
|
|
- **Effect**: Creates a branch in the trace — a future agent can see why the happy path was not taken.
|
|
|
|
```python
|
|
log("AuthRepository.get_user_by_username", "EXPLORE",
|
|
"User not found, returning None", {"username": username}, error="User does not exist in database")
|
|
```
|
|
|
|
### Quick Reference
|
|
|
|
| Situation | Marker | Level | `error` field |
|
|
|-----------|--------|-------|---------------|
|
|
| About to execute DB query | `REASON` | INFO | — |
|
|
| DB query returned results | `REFLECT` | INFO | — |
|
|
| DB query returned empty set (happy path) | `REFLECT` | INFO | — |
|
|
| DB query failed, fallback to cache | `EXPLORE` | WARNING | required |
|
|
| About to call external API | `REASON` | INFO | — |
|
|
| API responded 200 | `REFLECT` | INFO | — |
|
|
| API responded 5xx, retrying | `EXPLORE` | WARNING | required |
|
|
| API exhausted retries | `EXPLORE` | ERROR | required |
|
|
| Precondition check fails (e.g., not found) | `EXPLORE` | WARNING | required |
|
|
| State validation passes | `REFLECT` | INFO | — |
|
|
| Decomposing a complex loop iteration | `REASON` | DEBUG | — |
|
|
|
|
**Never use** generic tags like `Entry`, `Exit`, `Action`, `Coherence:OK/FAIL`. Those are replaced entirely by the molecular bond markers.
|
|
|
|
## III. Trace Propagation (Python)
|
|
|
|
**SSOT implementation:** `shared/src/ss_tools/shared/cot_logger.py` (`ss_tools.shared.cot_logger`). Backend facade: `src.core.logger`. Do not copy the logger into skills or call sites.
|
|
|
|
```python
|
|
from ss_tools.shared.cot_logger import log, seed_trace_id, get_trace_id, push_span, pop_span
|
|
|
|
# Backend:
|
|
# from src.core.logger import log, belief_scope, logger
|
|
```
|
|
|
|
`log()`, `seed_trace_id()`, `push_span()` / `pop_span()`, and ContextVar propagation are defined in that module. If the wire format in §I disagrees with the module, **the module wins** and this skill must be updated.
|
|
|
|
### FastAPI middleware (trace seeding)
|
|
|
|
```python
|
|
from starlette.middleware.base import BaseHTTPMiddleware
|
|
|
|
class TraceMiddleware(BaseHTTPMiddleware):
|
|
async def dispatch(self, request, call_next):
|
|
seed_trace_id()
|
|
response = await call_next(request)
|
|
return response
|
|
```
|
|
|
|
## IV. Svelte / Frontend Pattern
|
|
|
|
The frontend implementation lives at `frontend/src/lib/cot-logger.ts` (installed as `$lib/cot-logger`).
|
|
|
|
### API
|
|
|
|
```typescript
|
|
function log(
|
|
src: string, // e.g. "MigrationModel.executeMigration"
|
|
marker: LogMarker, // "REASON" | "REFLECT" | "EXPLORE"
|
|
intent: string, // human-readable one-liner
|
|
payload?: Record<string, unknown>, // params, result snippet
|
|
error?: string, // required for EXPLORE
|
|
): void;
|
|
```
|
|
|
|
### Import
|
|
|
|
```typescript
|
|
import { log, setTraceId, getTraceId } from "$lib/cot-logger";
|
|
```
|
|
|
|
### Usage in a Svelte component
|
|
|
|
```svelte
|
|
<script lang="ts">
|
|
import { log } from "$lib/cot-logger";
|
|
import { fetchApi } from "$lib/api";
|
|
|
|
let { jobId }: { jobId: string } = $props();
|
|
|
|
async function loadJob(): Promise<void> {
|
|
log("JobDetail", "REASON", "Fetch job details", { jobId });
|
|
|
|
try {
|
|
const resp = await fetchApi(`/api/jobs/${jobId}`);
|
|
if (!resp.ok) throw new Error(`Status ${resp.status}`);
|
|
|
|
const data = await resp.json();
|
|
log("JobDetail", "REFLECT", "Job details loaded",
|
|
{ rows: data.records?.length });
|
|
return data;
|
|
} catch (e: unknown) {
|
|
log("JobDetail", "EXPLORE", "Failed to load job",
|
|
{ jobId }, e instanceof Error ? e.message : "Unknown");
|
|
throw e;
|
|
}
|
|
}
|
|
</script>
|
|
```
|
|
|
|
### trace_id Propagation
|
|
|
|
The trace ID is set automatically when the backend returns it. Call `setTraceId(id)` manually if needed:
|
|
|
|
```typescript
|
|
import { setTraceId } from "$lib/cot-logger";
|
|
import { requestApi } from "$lib/api";
|
|
|
|
const res = await requestApi("/api/endpoint");
|
|
if (res.trace_id) setTraceId(res.trace_id);
|
|
```
|
|
|
|
## V. CLI / Stdout Reader (for humans)
|
|
|
|
To make JSON lines readable in development:
|
|
|
|
```bash
|
|
# Pretty-print the last 50 CoT lines
|
|
tail -50 app.log | python3 -c "
|
|
import sys, json
|
|
for line in sys.stdin:
|
|
line = line.strip()
|
|
if not line: continue
|
|
rec = json.loads(line)
|
|
m = rec.get('marker','?')
|
|
icon = {'REASON':'→','REFLECT':'✓','EXPLORE':'⚠'}.get(m, '·')
|
|
err = f\" | {rec['error']}\" if 'error' in rec else ''
|
|
pay = f\" | {rec.get('payload','')}\" if 'payload' in rec else ''
|
|
print(f\"{icon} {rec['level']:7} {rec['src']} — {rec['intent']}{pay}{err}\")
|
|
"
|
|
```
|
|
|
|
## VI. Anti-patterns
|
|
|
|
| ❌ Don't | ✅ Do |
|
|
|----------|-------|
|
|
| `COHERENCE:OK` on happy path | `REFLECT` with verification summary |
|
|
| `Action: something` | `REASON` with intent |
|
|
| `Entry` / `Exit` | REASON at entry, REFLECT at exit |
|
|
| Wrapping EVERY line with a marker | Only log semantically meaningful steps |
|
|
| Plain-text log lines | Always JSON lines |
|
|
| `marker` without `intent` | Every marker has a human-readable `intent` |
|
|
| Logging raw passwords or tokens in `payload` | Always sanitise sensitive data |
|
|
| Spread markers across multiple modules without trace_id | Always propagate `trace_id` |
|
|
|
|
#endregion Std.Semantics.MolecularCoTLogging
|