diff --git a/CHANGELOG.md b/CHANGELOG.md index 49d399a..6a2b304 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). Thi ## [Unreleased] ### Added +- `ReasoningEvent.controlFlow` (optional) + a reserved control-flow `eventType` vocabulary (`reasoning.tool.called` / `reasoning.decision.branched` / `reasoning.subrun.spawned` / `reasoning.subrun.joined` / `reasoning.run.completed`) so emitters can carry a run's operational control flow for downstream narration-fidelity verification (SP-TRACE-CFR). Backward-compatible; operational structure only (no raw reasoning). See `docs/reasoning-control-flow-events.md` and `examples/reasoning_event_control_flow.json`. - SourceOS interaction substrate top-level index and README discovery links for `SourceOSInteractionEvent`, generated TypeScript/Python artifacts, and the Noetica → Superconscious → AgentPlane → AgentTerm reference flow. - Runtime observability and capability governance contracts: `CapabilityLedger`, `BrowserAutomationReceipt`, `GitWorkspaceState`, `OrphanEventReceipt`, and `RuntimeInstallReceipt` with canonical examples, validation wiring (`tools/validate_runtime_observability_examples.py`), a contract catalog, and ADR-0012. - Reasoning run contracts: `ReasoningRun`, `ReasoningEvent`, `ReasoningReceipt`, `ReasoningReplayPlan`, and `ReasoningBenchmark` with canonical examples and a contract-additions note for the Superconscious reference loop. diff --git a/docs/reasoning-control-flow-events.md b/docs/reasoning-control-flow-events.md new file mode 100644 index 0000000..5ad0fb3 --- /dev/null +++ b/docs/reasoning-control-flow-events.md @@ -0,0 +1,45 @@ +# Reasoning Control-Flow Events + +**Status:** additive extension to `ReasoningEvent` (v2). Backward-compatible: `eventType` +stays a free string and `controlFlow` is optional. + +## Purpose + +`ReasoningRun` records run lifecycle; it did not carry the *control-flow* of a run +(the sequence of tool calls, branches, and delegated sub-runs). Downstream +narration-fidelity verification (SP-TRACE-CFR) recovers orchestration structure from +this control flow to check that an agent's stated narration matches what it actually +did. This extension lets emitters (Noetica → Superconscious → AgentPlane → AgentTerm, +TurtleTerm, BearBrowser) produce that structure. + +**Privacy posture (intentional):** control-flow events carry *operational structure +only* — a site id, a branch label, a guard position, a sub-run id — never raw model +reasoning. `traceLevel` and `trustLevel` continue to scope disclosure and provenance. +This is the "verify what the agent did, not what it thought" guarantee. + +## Reserved control-flow eventTypes + +| `eventType` | `controlFlow` fields | Recovered structure | +|---|---|---| +| `reasoning.tool.called` | `site` | a tool-call node | +| `reasoning.decision.branched` | `site`, `branchTaken`, `guardPosition?` | branch / loop guard (pre=WHILE, post=DO_WHILE) | +| `reasoning.subrun.spawned` | `site`, `sidechainId` | delegated sub-run entry (SESE) | +| `reasoning.subrun.joined` | `site`, `sidechainId` | delegated sub-run return | +| `reasoning.run.completed` | `site` | terminal | + +`site` is a stable orchestration-site identity (the decision-fold key — not a payload +hash). Events are consumed in the run's causal order. + +## Argument-level provenance + +A `reasoning.tool.called` event MAY set `controlFlow.arg` to name the argument whose +provenance carries this event's `trustLevel`. Consumers map `trustLevel` onto an +integrity lattice for argument-level information-flow control (e.g. an argument derived +from `untrusted-observation` is denied at a trusted sink). + +## Consumer + +AgentPlane's `sp-run narration-gate` / `sp-run attest-run` project a stream of these +events into a control-flow segment, recover it with two engines, compare it against the +agent's narration claims, and emit a signed run attestation. See +`agentplane/tools/trace_cfr_reasoning_bridge.py`. diff --git a/examples/reasoning_event_control_flow.json b/examples/reasoning_event_control_flow.json new file mode 100644 index 0000000..8521cb2 --- /dev/null +++ b/examples/reasoning_event_control_flow.json @@ -0,0 +1,16 @@ +{ + "id": "urn:srcos:reasoning-event:demo-dowhile-guard", + "type": "ReasoningEvent", + "specVersion": "2.0.0", + "runRef": "urn:srcos:reasoning-run:superconscious-demo", + "eventType": "reasoning.decision.branched", + "summary": "Loop guard evaluated after the body executed (post-checked).", + "traceLevel": "workspace-safe", + "trustLevel": "trusted-control-input", + "capturedAt": "2026-07-04T00:00:00Z", + "controlFlow": { + "site": "retry-loop-guard", + "branchTaken": "false", + "guardPosition": "post" + } +} diff --git a/schemas/ReasoningEvent.json b/schemas/ReasoningEvent.json index 6718d13..0c1981d 100644 --- a/schemas/ReasoningEvent.json +++ b/schemas/ReasoningEvent.json @@ -15,6 +15,19 @@ "summary": { "type": "string" }, "traceLevel": { "enum": ["public-safe", "workspace-safe", "operator-private", "restricted"] }, "trustLevel": { "enum": ["trusted-control-input", "trusted-workspace-source", "semi-trusted-project-source", "untrusted-observation", "restricted-material"] }, - "capturedAt": { "type": "string", "format": "date-time" } + "capturedAt": { "type": "string", "format": "date-time" }, + "controlFlow": { + "type": "object", + "description": "Optional operational control-flow annotation. Present on the reserved control-flow eventTypes so downstream consumers can recover orchestration structure (e.g. SP-TRACE-CFR narration-fidelity verification) WITHOUT collecting raw reasoning — operational structure only, honoring traceLevel/trustLevel. Reserved eventTypes: 'reasoning.tool.called' (site), 'reasoning.decision.branched' (site, branchTaken, guardPosition), 'reasoning.subrun.spawned' / 'reasoning.subrun.joined' (site, sidechainId), 'reasoning.run.completed' (site).", + "properties": { + "site": { "type": "string", "description": "Stable orchestration-site identity; the decision-fold key (not a payload hash)." }, + "branchTaken": { "type": ["string", "null"], "description": "Edge label on a decision successor (e.g. true/false/case:k)." }, + "guardPosition": { "enum": ["pre", "post", null], "description": "Loop guard relative to first body execution: pre = pre-checked (WHILE), post = post-checked (DO_WHILE)." }, + "sidechainId": { "type": ["string", "null"], "description": "Delegated sub-run id for spawn/join (SESE sidechain)." }, + "arg": { "type": ["string", "null"], "description": "Argument name whose provenance carries this event's trustLevel (argument-level taint / IFC)." } + }, + "required": ["site"], + "additionalProperties": true + } } }