diff --git a/.agent/demos/CURATED_CATALOG.md b/.agent/demos/CURATED_CATALOG.md
deleted file mode 100644
index 2e6f3eff87..0000000000
--- a/.agent/demos/CURATED_CATALOG.md
+++ /dev/null
@@ -1,54 +0,0 @@
-# Polylogue Demo Catalog
-
-Generated by `devtools workspace demo-shelf`.
-
-## _Packet Contract Stub
-
-- id: `_packet-contract-stub`
-- files: 9 (6 readable)
-
-## Agent Affordance Usage
-
-- id: `agent-affordance-usage`
-- readme: `agent-affordance-usage/README.md`
-- files: 13 (13 readable)
-
-## Agent Forensics
-
-- id: `agent-forensics`
-- readme: `agent-forensics/README.md`
-- files: 9 (9 readable)
-
-## Anti Demo Multi Source Reconstruction
-
-- id: `anti-demo-multi-source-reconstruction`
-- files: 9 (6 readable)
-
-## Attachment Acquisition Census
-
-- id: `attachment-acquisition-census`
-- readme: `attachment-acquisition-census/README.md`
-- analysis: `attachment-acquisition-census/ANALYSIS.md`
-- files: 5 (4 readable)
-
-## Basic Usage — The Features Actually Work
-
-- id: `basic-usage`
-- readme: `basic-usage/README.md`
-- files: 11 (11 readable)
-
-## D1 Receipts
-
-- id: `d1-receipts`
-- files: 9 (6 readable)
-
-## D4 Behavioral Archaeology
-
-- id: `d4-behavioral-archaeology`
-- files: 9 (6 readable)
-
-## Handoff-Pack Uplift Experiment
-
-- id: `uplift-two-arm`
-- readme: `uplift-two-arm/README.md`
-- files: 20 (20 readable)
diff --git a/.agent/demos/MANIFEST.readable.json b/.agent/demos/MANIFEST.readable.json
deleted file mode 100644
index 387648fa34..0000000000
--- a/.agent/demos/MANIFEST.readable.json
+++ /dev/null
@@ -1,492 +0,0 @@
-{
- "contract": "current-curated-demo-set",
- "root": ".agent/demos",
- "input_closure": {
- "mode": "git-tracked",
- "included_count": 95,
- "excluded_count": 0,
- "exclusion_reason_counts": {},
- "exclusion_samples": "bounded samples are emitted in the command JSON payload"
- },
- "packaging": "Use devtools workspace read-package for portable readable bundles; this helper only writes indexes.",
- "curation_policy": "This is not append-only. Keep the best current demos here; replace, consolidate, or move stale demos out.",
- "file_count": 95,
- "readable_count": 82,
- "files": [
- {
- "path": "_packet-contract-stub/NON-CLAIMS.md",
- "bytes": 177,
- "readable": true
- },
- {
- "path": "_packet-contract-stub/PROMPT.md",
- "bytes": 1108,
- "readable": true
- },
- {
- "path": "_packet-contract-stub/checks.json",
- "bytes": 151,
- "readable": true
- },
- {
- "path": "_packet-contract-stub/evidence.ndjson",
- "bytes": 258,
- "readable": false
- },
- {
- "path": "_packet-contract-stub/finding.yaml",
- "bytes": 266,
- "readable": true
- },
- {
- "path": "_packet-contract-stub/packet.json",
- "bytes": 4230,
- "readable": true
- },
- {
- "path": "_packet-contract-stub/queries.ndjson",
- "bytes": 74,
- "readable": false
- },
- {
- "path": "_packet-contract-stub/report.md",
- "bytes": 1076,
- "readable": true
- },
- {
- "path": "_packet-contract-stub/run.log",
- "bytes": 132,
- "readable": false
- },
- {
- "path": "agent-affordance-usage/README.md",
- "bytes": 2951,
- "readable": true
- },
- {
- "path": "agent-affordance-usage/affordance-usage.report.json",
- "bytes": 45710,
- "readable": true
- },
- {
- "path": "agent-affordance-usage/archive-origin-counts.csv",
- "bytes": 167,
- "readable": true
- },
- {
- "path": "agent-affordance-usage/evidence-kind-counts.csv",
- "bytes": 1,
- "readable": true
- },
- {
- "path": "agent-affordance-usage/family-counts.csv",
- "bytes": 1,
- "readable": true
- },
- {
- "path": "agent-affordance-usage/recent-30d-tool-counts.csv",
- "bytes": 1,
- "readable": true
- },
- {
- "path": "agent-affordance-usage/recent-7d-tool-counts.csv",
- "bytes": 1,
- "readable": true
- },
- {
- "path": "agent-affordance-usage/summary.json",
- "bytes": 2276,
- "readable": true
- },
- {
- "path": "agent-affordance-usage/surface-classification-summary.csv",
- "bytes": 134,
- "readable": true
- },
- {
- "path": "agent-affordance-usage/surface-inventory.csv",
- "bytes": 15387,
- "readable": true
- },
- {
- "path": "agent-affordance-usage/tool-by-origin.csv",
- "bytes": 1,
- "readable": true
- },
- {
- "path": "agent-affordance-usage/tool-counts.csv",
- "bytes": 1,
- "readable": true
- },
- {
- "path": "agent-affordance-usage/tool-samples.csv",
- "bytes": 1,
- "readable": true
- },
- {
- "path": "agent-forensics/README.md",
- "bytes": 4813,
- "readable": true
- },
- {
- "path": "agent-forensics/current/archive-workload.json",
- "bytes": 19828,
- "readable": true
- },
- {
- "path": "agent-forensics/current/cost-rollups-timeout.txt",
- "bytes": 637,
- "readable": true
- },
- {
- "path": "agent-forensics/current/coverage-origin.json",
- "bytes": 8675,
- "readable": true
- },
- {
- "path": "agent-forensics/current/summary.json",
- "bytes": 5451,
- "readable": true
- },
- {
- "path": "agent-forensics/current/usage-headline-all.json",
- "bytes": 68551,
- "readable": true
- },
- {
- "path": "agent-forensics/current/usage-headline-claude-code.json",
- "bytes": 31714,
- "readable": true
- },
- {
- "path": "agent-forensics/current/usage-headline-codex.json",
- "bytes": 16763,
- "readable": true
- },
- {
- "path": "agent-forensics/current/usage-timeline-month-origin-model.json",
- "bytes": 5540,
- "readable": true
- },
- {
- "path": "anti-demo-multi-source-reconstruction/NON-CLAIMS.md",
- "bytes": 239,
- "readable": true
- },
- {
- "path": "anti-demo-multi-source-reconstruction/PROMPT.md",
- "bytes": 1714,
- "readable": true
- },
- {
- "path": "anti-demo-multi-source-reconstruction/checks.json",
- "bytes": 603,
- "readable": true
- },
- {
- "path": "anti-demo-multi-source-reconstruction/evidence.ndjson",
- "bytes": 1035,
- "readable": false
- },
- {
- "path": "anti-demo-multi-source-reconstruction/finding.yaml",
- "bytes": 529,
- "readable": true
- },
- {
- "path": "anti-demo-multi-source-reconstruction/packet.json",
- "bytes": 4907,
- "readable": true
- },
- {
- "path": "anti-demo-multi-source-reconstruction/queries.ndjson",
- "bytes": 713,
- "readable": false
- },
- {
- "path": "anti-demo-multi-source-reconstruction/report.md",
- "bytes": 4188,
- "readable": true
- },
- {
- "path": "anti-demo-multi-source-reconstruction/run.log",
- "bytes": 1600,
- "readable": false
- },
- {
- "path": "attachment-acquisition-census/ANALYSIS.md",
- "bytes": 953,
- "readable": true
- },
- {
- "path": "attachment-acquisition-census/README.md",
- "bytes": 2691,
- "readable": true
- },
- {
- "path": "attachment-acquisition-census/census.json",
- "bytes": 1292,
- "readable": true
- },
- {
- "path": "attachment-acquisition-census/reconcile-attachment-acquisition-debt.json",
- "bytes": 356,
- "readable": true
- },
- {
- "path": "attachment-acquisition-census/regenerate.sh",
- "bytes": 8286,
- "readable": false
- },
- {
- "path": "basic-usage/01-find-query.txt",
- "bytes": 1204,
- "readable": true
- },
- {
- "path": "basic-usage/02-read.txt",
- "bytes": 723,
- "readable": true
- },
- {
- "path": "basic-usage/03-search.txt",
- "bytes": 664,
- "readable": true
- },
- {
- "path": "basic-usage/04-resume.txt",
- "bytes": 89,
- "readable": true
- },
- {
- "path": "basic-usage/05-cost-usage.json",
- "bytes": 53777,
- "readable": true
- },
- {
- "path": "basic-usage/06-lineage.txt",
- "bytes": 794,
- "readable": true
- },
- {
- "path": "basic-usage/07-mcp-roundtrip.json",
- "bytes": 2390,
- "readable": true
- },
- {
- "path": "basic-usage/08-status-health.debt.json",
- "bytes": 9292,
- "readable": true
- },
- {
- "path": "basic-usage/08-status-health.txt",
- "bytes": 1306,
- "readable": true
- },
- {
- "path": "basic-usage/COLD_READER_GATE.md",
- "bytes": 2945,
- "readable": true
- },
- {
- "path": "basic-usage/README.md",
- "bytes": 10073,
- "readable": true
- },
- {
- "path": "d1-receipts/NON-CLAIMS.md",
- "bytes": 550,
- "readable": true
- },
- {
- "path": "d1-receipts/PROMPT.md",
- "bytes": 3513,
- "readable": true
- },
- {
- "path": "d1-receipts/checks.json",
- "bytes": 1012,
- "readable": true
- },
- {
- "path": "d1-receipts/evidence.ndjson",
- "bytes": 3735,
- "readable": false
- },
- {
- "path": "d1-receipts/finding.yaml",
- "bytes": 651,
- "readable": true
- },
- {
- "path": "d1-receipts/packet.json",
- "bytes": 7452,
- "readable": true
- },
- {
- "path": "d1-receipts/queries.ndjson",
- "bytes": 1432,
- "readable": false
- },
- {
- "path": "d1-receipts/report.md",
- "bytes": 9186,
- "readable": true
- },
- {
- "path": "d1-receipts/run.log",
- "bytes": 5131,
- "readable": false
- },
- {
- "path": "d4-behavioral-archaeology/NON-CLAIMS.md",
- "bytes": 400,
- "readable": true
- },
- {
- "path": "d4-behavioral-archaeology/PROMPT.md",
- "bytes": 1807,
- "readable": true
- },
- {
- "path": "d4-behavioral-archaeology/checks.json",
- "bytes": 552,
- "readable": true
- },
- {
- "path": "d4-behavioral-archaeology/evidence.ndjson",
- "bytes": 2296,
- "readable": false
- },
- {
- "path": "d4-behavioral-archaeology/finding.yaml",
- "bytes": 664,
- "readable": true
- },
- {
- "path": "d4-behavioral-archaeology/packet.json",
- "bytes": 10443,
- "readable": true
- },
- {
- "path": "d4-behavioral-archaeology/queries.ndjson",
- "bytes": 1358,
- "readable": false
- },
- {
- "path": "d4-behavioral-archaeology/report.md",
- "bytes": 5033,
- "readable": true
- },
- {
- "path": "d4-behavioral-archaeology/run.log",
- "bytes": 9800,
- "readable": false
- },
- {
- "path": "registry.json",
- "bytes": 1268,
- "readable": true
- },
- {
- "path": "uplift-two-arm/README.md",
- "bytes": 864,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/arms/pair1-handoff-pack-output.md",
- "bytes": 7265,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/arms/pair1-raw-ref-output.md",
- "bytes": 8123,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/arms/pair2-handoff-pack-output.md",
- "bytes": 2489,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/arms/pair2-raw-ref-output.md",
- "bytes": 2406,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/arms/pair3-handoff-pack-output.md",
- "bytes": 2667,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/arms/pair3-raw-ref-output.md",
- "bytes": 2262,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/arms/pair4-handoff-pack-output.md",
- "bytes": 2236,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/arms/pair4-raw-ref-output.md",
- "bytes": 2158,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/arms/pair5-handoff-pack-output.md",
- "bytes": 2251,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/arms/pair5-raw-ref-output.md",
- "bytes": 1987,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/metrics/ground-truth-pair1.json",
- "bytes": 1989,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/metrics/ground-truth-pair2.json",
- "bytes": 874,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/metrics/ground-truth-pair3.json",
- "bytes": 706,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/metrics/ground-truth-pair4.json",
- "bytes": 614,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/metrics/ground-truth-pair5.json",
- "bytes": 736,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/metrics/rubric.json",
- "bytes": 912,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/metrics/score.json",
- "bytes": 2106,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/pairs.json",
- "bytes": 1849,
- "readable": true
- },
- {
- "path": "uplift-two-arm/current/report.md",
- "bytes": 7468,
- "readable": true
- }
- ]
-}
diff --git a/.agent/demos/README.md b/.agent/demos/README.md
deleted file mode 100644
index 706cf3ad23..0000000000
--- a/.agent/demos/README.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# Polylogue Current Demo Shelf
-
-Generated by `devtools workspace demo-shelf`.
-
-This shelf contains the best current Polylogue demos for the active devloop.
-It is not append-only. Replace, consolidate, or move stale demos out when a
-better demo supersedes them.
-
-## Current Entries
-
-- `_packet-contract-stub` — _Packet Contract Stub
- - files: 9 (6 readable)
-- `agent-affordance-usage` — Agent Affordance Usage
- - readme: `agent-affordance-usage/README.md`
- - files: 13 (13 readable)
-- `agent-forensics` — Agent Forensics
- - readme: `agent-forensics/README.md`
- - files: 9 (9 readable)
-- `anti-demo-multi-source-reconstruction` — Anti Demo Multi Source Reconstruction
- - files: 9 (6 readable)
-- `attachment-acquisition-census` — Attachment Acquisition Census
- - readme: `attachment-acquisition-census/README.md`
- - analysis: `attachment-acquisition-census/ANALYSIS.md`
- - files: 5 (4 readable)
-- `basic-usage` — Basic Usage — The Features Actually Work
- - readme: `basic-usage/README.md`
- - files: 11 (11 readable)
-- `d1-receipts` — D1 Receipts
- - files: 9 (6 readable)
-- `d4-behavioral-archaeology` — D4 Behavioral Archaeology
- - files: 9 (6 readable)
-- `uplift-two-arm` — Handoff-Pack Uplift Experiment
- - readme: `uplift-two-arm/README.md`
- - files: 20 (20 readable)
-
-Retired demo material belongs under `.agent/archive/retired-demos/`, not here.
diff --git a/.agent/demos/SUMMARY_INDEX.json b/.agent/demos/SUMMARY_INDEX.json
deleted file mode 100644
index 681a1d9eb8..0000000000
--- a/.agent/demos/SUMMARY_INDEX.json
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "root": ".agent/demos",
- "summary_count": 2,
- "coverage": {
- "without_claim": [],
- "without_non_claim": [],
- "without_proof_fields": [],
- "without_caveat_fields": [],
- "unsummarized_demos": [
- "_packet-contract-stub",
- "anti-demo-multi-source-reconstruction",
- "attachment-acquisition-census",
- "basic-usage",
- "d1-receipts",
- "d4-behavioral-archaeology",
- "uplift-two-arm"
- ]
- },
- "records": [
- {
- "demo": "agent-affordance-usage",
- "summary_path": "agent-affordance-usage/summary.json",
- "artifact": "agent-affordance-usage",
- "claim": "Polylogue can compare agent affordance usage across normalized action evidence without summing unlike tool-name spellings or provider-specific call shapes.",
- "non_claim": "This is not a human-quality utility evaluation of any particular tool family. It measures captured usage evidence, failure signals, and coverage gaps; usefulness still requires qualitative review of session context and outcomes.",
- "proof_fields": [
- "proof_report"
- ],
- "caveat_fields": [
- "caveats"
- ],
- "archive_root": "/path/to/demo-archive",
- "index_schema_version": 54,
- "timestamp": "2026-08-02T13:51:38.483581+00:00",
- "coverage": {
- "claim": true,
- "non_claim": true,
- "proof_fields": true,
- "caveat_fields": true
- }
- },
- {
- "demo": "agent-forensics/current",
- "summary_path": "agent-forensics/current/summary.json",
- "artifact": "agent-forensics",
- "claim": "Polylogue can regenerate a current v54 longitudinal agent-usage forensics packet over a deterministic seeded fixture archive using product analysis surfaces, with provenance-separated token/cost lanes and explicit physical-vs-logical token grains.",
- "non_claim": "This packet is not provider billing truth, not an LLM judgment of failure follow-up behavior, not a resurrected standalone forensics script, and not evidence about the operator's real archive; it reads the deterministic demo archive through the same product commands used against a live archive, and points structured-failure follow-up to the current claim-vs-evidence packet.",
- "proof_fields": [
- "command_proofs",
- "proof_fields"
- ],
- "caveat_fields": [
- "caveat_fields",
- "fixture_scale_caveat",
- "usage_headline_caveats"
- ],
- "archive_root": "/path/to/demo-archive",
- "index_schema_version": 54,
- "timestamp": "2026-08-02T13:52:20Z",
- "coverage": {
- "claim": true,
- "non_claim": true,
- "proof_fields": true,
- "caveat_fields": true
- }
- }
- ]
-}
diff --git a/.agent/demos/_packet-contract-stub/NON-CLAIMS.md b/.agent/demos/_packet-contract-stub/NON-CLAIMS.md
deleted file mode 100644
index 45df2054e7..0000000000
--- a/.agent/demos/_packet-contract-stub/NON-CLAIMS.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# Non-claims
-
-- This fixture does not prove an archive, search, lineage, memory, or agent capability.
-- This fixture does not establish field prevalence, scale, or performance.
diff --git a/.agent/demos/_packet-contract-stub/PROMPT.md b/.agent/demos/_packet-contract-stub/PROMPT.md
deleted file mode 100644
index f9c82ed65c..0000000000
--- a/.agent/demos/_packet-contract-stub/PROMPT.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# Packet Contract Stub
-
-Predeclaration receipt: `artifact:packet-contract-stub-predeclaration`.
-
-This is a deliberately minimal, hand-authored fixture packet proving the
-Demo Finding Packet contract (polylogue-212.7) end to end — it is NOT one of
-the real 212 demos (D1/D2/D4/D5/D8/post-hoc-Q&A/anti-demo/foreman-rhetoric).
-Those still need their own implementation (each is its own bead); this stub
-exists only so `devtools lab policy demo-packet-registry` has one real,
-conforming registry entry to validate, and so a future contributor building
-a real demo has a concrete worked example of every required file.
-
-## What a real prompt would say here
-
-A real demo's PROMPT.md instructs a coding agent to run specific `polylogue`
-commands (product primitives — the 212 compositionality rule: shell/python
-is glue only) against the seeded demo corpus (`polylogue demo seed`, seed
-1843), then package the results into this same packet shape.
-
-This stub's "claim" is trivial by design: count sessions in the seeded
-corpus. Run: `polylogue --format json find` against the seeded corpus and
-report the total.
diff --git a/.agent/demos/_packet-contract-stub/checks.json b/.agent/demos/_packet-contract-stub/checks.json
deleted file mode 100644
index 30123d30c7..0000000000
--- a/.agent/demos/_packet-contract-stub/checks.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "pass": true,
- "unsupported_claims": [],
- "coverage_notes": "fixture packet for the demo-packet-registry contract; not a real analytical demo"
-}
diff --git a/.agent/demos/_packet-contract-stub/evidence.ndjson b/.agent/demos/_packet-contract-stub/evidence.ndjson
deleted file mode 100644
index 5ddaf9710d..0000000000
--- a/.agent/demos/_packet-contract-stub/evidence.ndjson
+++ /dev/null
@@ -1,2 +0,0 @@
-{"ref": "artifact:packet-contract-stub-evidence", "cited_for": "Demo Packet v2 receipt root", "verified_via": "committed evidence.ndjson"}
-{"ref": "seeded-corpus-seed-1843:session-count", "value": "stub", "note": "fixture row proving evidence.ndjson shape"}
diff --git a/.agent/demos/_packet-contract-stub/finding.yaml b/.agent/demos/_packet-contract-stub/finding.yaml
deleted file mode 100644
index 3c0c17b131..0000000000
--- a/.agent/demos/_packet-contract-stub/finding.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-archive_cursor: seeded-corpus-seed-1843
-measure_version: demo-packet-v2
-commit_sha: ffba3ec0c
-sample_frame_predicate: "all sessions in the seeded demo corpus (seed 1843)"
-run_date: "2026-07-08"
-claim: "the seeded demo corpus has a fixed, reproducible session count"
diff --git a/.agent/demos/_packet-contract-stub/packet.json b/.agent/demos/_packet-contract-stub/packet.json
deleted file mode 100644
index 56c340f11c..0000000000
--- a/.agent/demos/_packet-contract-stub/packet.json
+++ /dev/null
@@ -1,131 +0,0 @@
-{
- "baseline": {
- "method": "Use the recorded simpler comparison path rather than the structural product path.",
- "name": "legacy filename checklist",
- "receipts": [
- "artifact:packet-contract-stub-evidence"
- ],
- "result": "Check only that the legacy packet filenames exist."
- },
- "claim": {
- "declared_before_execution": true,
- "receipts": [
- "artifact:packet-contract-stub-predeclaration"
- ],
- "scope": "this validator fixture only",
- "statement": "The complete committed fixture passes the Demo Packet v2 validation gate.",
- "status": "supported"
- },
- "controls": {
- "missing_evidence": [
- {
- "expected": "Removing the receipt artifact must make the packet invalid.",
- "id": "missing-receipt",
- "observed": {
- "valid": false
- },
- "passed": true,
- "purpose": "Require missing evidence to remain explicit rather than converted into a positive claim.",
- "receipts": [
- "artifact:packet-contract-stub-evidence"
- ]
- }
- ],
- "negative": [
- {
- "expected": "Removing the falsifier must make the packet invalid.",
- "id": "missing-falsifier",
- "observed": {
- "valid": false
- },
- "passed": true,
- "purpose": "Prevent an adjacent easier signal from being counted as the primary construct.",
- "receipts": [
- "artifact:packet-contract-stub-evidence"
- ]
- }
- ]
- },
- "falsifier": {
- "condition": "The v2 validator accepts the committed packet after its falsifier field is removed.",
- "evaluation_method": "Apply the stated condition to the committed evidence and run log.",
- "receipts": [
- "artifact:packet-contract-stub-evidence"
- ],
- "result": "pass",
- "triggered": false
- },
- "mode": "fixture",
- "non_claims": [
- "This fixture does not prove an archive, search, lineage, memory, or agent capability.",
- "This fixture does not establish field prevalence, scale, or performance."
- ],
- "oracle": {
- "description": "The normative JSON Schema and packet validator independently enumerate the required contract fields.",
- "expected": {
- "valid": true
- },
- "independent": true,
- "method": "Validate the committed packet against docs/schemas/demo-packet-v2.schema.json.",
- "receipts": [
- "artifact:packet-contract-stub-evidence"
- ]
- },
- "packet_id": "packet-contract-stub",
- "primary_construct": {
- "id": "demo.packet-v2.shape",
- "product_primitives": [
- "demo packet registry validator"
- ],
- "statement": "The committed fixture demonstrates the complete Demo Packet v2 directory and epistemic shape."
- },
- "provenance": {
- "archive_cursor": "seeded-corpus-seed-1843",
- "commit_sha": "ffba3ec0c",
- "measure_version": "demo-packet-v2",
- "run_date": "2026-07-10",
- "sample_frame_predicate": "the committed packet-contract fixture"
- },
- "receipts": [
- {
- "artifact_path": "evidence.ndjson",
- "description": "Committed evidence rows and references for this packet.",
- "kind": "artifact",
- "ref": "artifact:packet-contract-stub-evidence",
- "resolved": true,
- "sha256": "cdcfa78a44335e29068683c317cf83c09e85e0414b3271306138b58e404baa70"
- },
- {
- "artifact_path": "PROMPT.md",
- "description": "The committed prompt that states the packet claim before execution.",
- "kind": "artifact",
- "ref": "artifact:packet-contract-stub-predeclaration",
- "resolved": true,
- "sha256": "4c0d59f421e04714276ce03b509e585abd14a3bc83cbb6b94597e64dbd118465"
- }
- ],
- "reproduction": {
- "commands": [
- "python -m devtools.verify_demo_packet_registry"
- ],
- "deterministic": true,
- "fixture": "seeded-corpus contract fixture",
- "private_data": false
- },
- "results": {
- "measurements": [
- {
- "name": "schema_errors",
- "receipts": [
- "artifact:packet-contract-stub-evidence"
- ],
- "unit": "errors",
- "value": 0
- }
- ],
- "status": "pass",
- "summary": "The fixture satisfies the complete Demo Packet v2 contract."
- },
- "schema_version": "2.0.0",
- "title": "Demo Packet contract fixture"
-}
diff --git a/.agent/demos/_packet-contract-stub/queries.ndjson b/.agent/demos/_packet-contract-stub/queries.ndjson
deleted file mode 100644
index f088a22413..0000000000
--- a/.agent/demos/_packet-contract-stub/queries.ndjson
+++ /dev/null
@@ -1 +0,0 @@
-{"text": "find", "lowered_spec": {"unit": "sessions", "predicate": null}}
diff --git a/.agent/demos/_packet-contract-stub/report.md b/.agent/demos/_packet-contract-stub/report.md
deleted file mode 100644
index 19bb2d3e5b..0000000000
--- a/.agent/demos/_packet-contract-stub/report.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# Packet Contract Stub
-
-## Claim
-
-The seeded demo corpus (seed 1843) has a fixed, reproducible session count.
-
-## Corpus
-
-`polylogue demo seed` output, seed 1843 — deterministic, no private data.
-
-## Method
-
-`polylogue --format json find` over the full seeded corpus; count result rows.
-
-## Findings
-
-The seeded corpus reproduces the same session count on every regeneration
-(this is a fixture proving the packet contract's shape, not a real analytical
-finding — see evidence.ndjson for the (stubbed) citation format).
-
-## Specimens
-
-See `evidence.ndjson` for the cited rows.
-
-## Counterexamples
-
-None — this is a trivial reproducibility check by construction.
-
-## Limits
-
-This packet is a fixture for `devtools lab policy demo-packet-registry`, not
-a real 212 demo. Do not cite its "claim" externally.
-
-## Non-claims
-
-- This fixture does not prove an archive, search, lineage, memory, or agent capability.
-- This fixture does not establish field prevalence, scale, or performance.
-
-## Reproduce
-
-```bash
-polylogue demo seed --seed 1843
-polylogue --format json find
-```
diff --git a/.agent/demos/_packet-contract-stub/run.log b/.agent/demos/_packet-contract-stub/run.log
deleted file mode 100644
index 861088f7fd..0000000000
--- a/.agent/demos/_packet-contract-stub/run.log
+++ /dev/null
@@ -1,4 +0,0 @@
-$ polylogue demo seed --seed 1843
-seeded demo corpus at seed 1843
-$ polylogue --format json find
-{"sessions": ["stub"], "count": 1}
diff --git a/.agent/demos/agent-affordance-usage/README.md b/.agent/demos/agent-affordance-usage/README.md
deleted file mode 100644
index fe3289ceae..0000000000
--- a/.agent/demos/agent-affordance-usage/README.md
+++ /dev/null
@@ -1,64 +0,0 @@
-# Agent Affordance Usage
-
-Generated: 2026-08-02T13:51:38.483581+00:00
-Archive root: `/path/to/demo-archive`
-Index schema: v54
-Action scope: `grouped-tool-name-recent-window`
-
-## Top Families
-
-
-## Recent Window (7 days)
-
-
-## Surface Inventory Classification
-
-- cli_command keep: 64 surface(s), observed_actions=0.
-- cli_command kill: 54 surface(s), observed_actions=0.
-- mcp_tool keep: 4 surface(s), observed_actions=0.
-- mcp_tool kill: 6 surface(s), observed_actions=0.
-
-## Kill Candidates
-
-These are zero-use non-operator surfaces in the captured archive evidence. They are review candidates, not automatic removals.
-
-- mcp_tool `context` — zero captured agent use in this archive window; review before removal
-- mcp_tool `explain` — zero captured agent use in this archive window; review before removal
-- mcp_tool `get` — zero captured agent use in this archive window; review before removal
-- mcp_tool `query` — zero captured agent use in this archive window; review before removal
-- mcp_tool `read` — zero captured agent use in this archive window; review before removal
-- mcp_tool `status` — zero captured agent use in this archive window; review before removal
-- cli_command `agent` — zero captured agent use in this archive window; review before removal
-- cli_command `agent doctor` — zero captured agent use in this archive window; review before removal
-- cli_command `agent install` — zero captured agent use in this archive window; review before removal
-- cli_command `agent manifest` — zero captured agent use in this archive window; review before removal
-- cli_command `agent manual` — zero captured agent use in this archive window; review before removal
-- cli_command `agent status` — zero captured agent use in this archive window; review before removal
-
-## Interpretation
-
-- Family-normalized counts avoid treating plugin-prefixed tool names as separate affordances.
-- The default action scope is the recent-session window; use --all-time for the intentionally broader scan.
-- Recent windows are required for newly-added affordances such as Serena and codebase-memory.
-- Failure rates are structured tool-result signals; they identify friction, not necessarily low utility.
-- The surface inventory left-joins observed usage against every registered MCP tool and CLI command.
-- Operator-only rows are kept even when unused; the classification caveat is part of the data.
-
-## Notes
-
-- Default family counts used an indexed grouped tool-name path over blocks.
-- Command and input text bodies are not scanned unless --detail-pattern is supplied.
-- Samples are omitted on this fast grouped path to avoid materializing every matching action row.
-
-## Files
-
-- `family-counts.csv`
-- `evidence-kind-counts.csv`
-- `tool-counts.csv`
-- `tool-by-origin.csv`
-- `recent-7d-tool-counts.csv`
-- `tool-samples.csv`
-- `surface-inventory.csv`
-- `surface-classification-summary.csv`
-- `affordance-usage.report.json`
-- `summary.json`
diff --git a/.agent/demos/agent-affordance-usage/affordance-usage.report.json b/.agent/demos/agent-affordance-usage/affordance-usage.report.json
deleted file mode 100644
index 744f43f8a1..0000000000
--- a/.agent/demos/agent-affordance-usage/affordance-usage.report.json
+++ /dev/null
@@ -1,1384 +0,0 @@
-{
- "action_scope": "grouped-tool-name-recent-window",
- "archive_root": "/path/to/demo-archive",
- "captured_at": "2026-08-02T13:51:38.483581+00:00",
- "command": "devtools workspace affordance-usage",
- "detail_patterns": [],
- "evidence_kind_counts": [],
- "family_counts": [],
- "index_db": "/path/to/demo-archive/index.db",
- "index_schema_version": 54,
- "notes": [
- "Default family counts used an indexed grouped tool-name path over blocks.",
- "Command and input text bodies are not scanned unless --detail-pattern is supplied.",
- "Samples are omitted on this fast grouped path to avoid materializing every matching action row."
- ],
- "origin_counts": [
- {
- "origin": "codex-session",
- "sessions": 7
- },
- {
- "origin": "claude-code-session",
- "sessions": 4
- },
- {
- "origin": "chatgpt-export",
- "sessions": 3
- },
- {
- "origin": "aistudio-drive",
- "sessions": 1
- },
- {
- "origin": "antigravity-session",
- "sessions": 1
- },
- {
- "origin": "claude-ai-export",
- "sessions": 1
- },
- {
- "origin": "gemini-cli-session",
- "sessions": 1
- },
- {
- "origin": "hermes-session",
- "sessions": 1
- }
- ],
- "patterns": [
- "serena",
- "codebase",
- "cclsp",
- "context7",
- "polylogue",
- "lynchpin"
- ],
- "recent_cutoff_ms": 1785073898480,
- "recent_tool_counts": [],
- "recent_window_days": 7,
- "report_version": 3,
- "samples": [],
- "summary": {
- "interpretation": [
- "Family-normalized counts avoid treating plugin-prefixed tool names as separate affordances.",
- "The default action scope is the recent-session window; use --all-time for the intentionally broader scan.",
- "Recent windows are required for newly-added affordances such as Serena and codebase-memory.",
- "Failure rates are structured tool-result signals; they identify friction, not necessarily low utility."
- ],
- "recent_top_families": [],
- "recent_window_days": 7,
- "top_families": []
- },
- "surface_inventory": [
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "context",
- "surface_type": "mcp_tool"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "explain",
- "surface_type": "mcp_tool"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "get",
- "surface_type": "mcp_tool"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "judge",
- "surface_type": "mcp_tool"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "maintenance",
- "surface_type": "mcp_tool"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "query",
- "surface_type": "mcp_tool"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "read",
- "surface_type": "mcp_tool"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "run",
- "surface_type": "mcp_tool"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "status",
- "surface_type": "mcp_tool"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "write",
- "surface_type": "mcp_tool"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "agent",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "agent doctor",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "agent install",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "agent manifest",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "agent manual",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "agent status",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "agent uninstall",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "agents",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "agents status",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "agents work-item",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze insights",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze insights cost-rollups",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze insights costs",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze insights coverage",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze insights debt",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze insights phases",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze insights profiles",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze insights tags",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze insights threads",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze insights timeline",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze insights tool-usage",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze insights usage-timeline",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze insights work-events",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze latency",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze pace",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze tools",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze turns",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "analyze usage",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "annotations",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "annotations import",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "annotations join",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "compare",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "config",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "config action-affordances",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "config completions",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "config paths",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "config query-completions",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "continue",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "dashboard",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "delete",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "demo",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "demo receipts",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "demo script",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "demo seed",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "demo tour",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "demo verify",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "facets",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "hooks",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "hooks install",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "hooks status",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "hooks uninstall",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "import",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "init",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "judge",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "manual",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "mark",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "note",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops auth",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops backup",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops debt",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops debt list",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops diagnostics",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops diagnostics codex-title-census",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops diagnostics space",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops diagnostics workload",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops doctor",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops embed",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops embed backfill",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops embed disable",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops embed enable",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops embed preflight",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops embed resolve-failure",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops embed status",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops excise",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops insights",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops insights audit",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops insights export",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops insights hermes-health",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops insights status",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance archive-init",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance archive-plan",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance archive-read",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance assertion-export",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance attachment-acquisition-debt",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance backup-plan",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance blob-gc",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance blob-publications",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance blob-reference-debt",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance blob-reference-prune-orphans",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance blob-reference-recovery-plan",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance blob-reference-replace-from-source",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance embedding-orphan-reconcile",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance embeddings-rescue",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance gc-history",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance migrate-tier",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance plan",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance preview",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance raw-authority-blocker-resolve",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance raw-authority-blockers",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance raw-authority-census",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance raw-authority-detail",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance raw-authority-frontier",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance rebuild-index",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance run",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance status",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops maintenance verify-archive",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops materialize-incident-evidence",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops reconcile-work-effects",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops reset",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops scan-secrets",
- "surface_type": "cli_command"
- },
- {
- "caveat": "operator-only surface; zero captured agent use is not removal evidence",
- "classification": "keep",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": true,
- "surface_name": "ops status",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "read",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "select",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "status",
- "surface_type": "cli_command"
- },
- {
- "caveat": "zero captured agent use in this archive window; review before removal",
- "classification": "kill",
- "failure_rate": 0.0,
- "observed_actions": 0,
- "observed_sessions": 0,
- "operator_only_caveat": false,
- "surface_name": "tutorial",
- "surface_type": "cli_command"
- }
- ],
- "surface_inventory_summary": [
- {
- "classification": "keep",
- "observed_actions": 0,
- "surface_type": "cli_command",
- "surfaces": 64
- },
- {
- "classification": "kill",
- "observed_actions": 0,
- "surface_type": "cli_command",
- "surfaces": 54
- },
- {
- "classification": "keep",
- "observed_actions": 0,
- "surface_type": "mcp_tool",
- "surfaces": 4
- },
- {
- "classification": "kill",
- "observed_actions": 0,
- "surface_type": "mcp_tool",
- "surfaces": 6
- }
- ],
- "tool_by_origin": [],
- "tool_counts": []
-}
diff --git a/.agent/demos/agent-affordance-usage/archive-origin-counts.csv b/.agent/demos/agent-affordance-usage/archive-origin-counts.csv
deleted file mode 100644
index 33b9066300..0000000000
--- a/.agent/demos/agent-affordance-usage/archive-origin-counts.csv
+++ /dev/null
@@ -1,9 +0,0 @@
-origin,sessions
-codex-session,7
-claude-code-session,4
-chatgpt-export,3
-aistudio-drive,1
-antigravity-session,1
-claude-ai-export,1
-gemini-cli-session,1
-hermes-session,1
diff --git a/.agent/demos/agent-affordance-usage/evidence-kind-counts.csv b/.agent/demos/agent-affordance-usage/evidence-kind-counts.csv
deleted file mode 100644
index 8b13789179..0000000000
--- a/.agent/demos/agent-affordance-usage/evidence-kind-counts.csv
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/.agent/demos/agent-affordance-usage/family-counts.csv b/.agent/demos/agent-affordance-usage/family-counts.csv
deleted file mode 100644
index 8b13789179..0000000000
--- a/.agent/demos/agent-affordance-usage/family-counts.csv
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/.agent/demos/agent-affordance-usage/recent-30d-tool-counts.csv b/.agent/demos/agent-affordance-usage/recent-30d-tool-counts.csv
deleted file mode 100644
index 8b13789179..0000000000
--- a/.agent/demos/agent-affordance-usage/recent-30d-tool-counts.csv
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/.agent/demos/agent-affordance-usage/recent-7d-tool-counts.csv b/.agent/demos/agent-affordance-usage/recent-7d-tool-counts.csv
deleted file mode 100644
index 8b13789179..0000000000
--- a/.agent/demos/agent-affordance-usage/recent-7d-tool-counts.csv
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/.agent/demos/agent-affordance-usage/summary.json b/.agent/demos/agent-affordance-usage/summary.json
deleted file mode 100644
index 0287b1c417..0000000000
--- a/.agent/demos/agent-affordance-usage/summary.json
+++ /dev/null
@@ -1,67 +0,0 @@
-{
- "archive_root": "/path/to/demo-archive",
- "artifact": "agent-affordance-usage",
- "caveats": [
- "Counts describe captured action evidence, not independent proof of user benefit.",
- "Failure rates are provider-reported tool-result signals where available; missing outcome structure is not success.",
- "Recent windows are adoption-sensitive and can legitimately differ from all-time counts.",
- "Zero captured agent use is not enough to remove operator-only surfaces; those rows carry an operator-only caveat."
- ],
- "claim": "Polylogue can compare agent affordance usage across normalized action evidence without summing unlike tool-name spellings or provider-specific call shapes.",
- "index_schema_version": 54,
- "non_claim": "This is not a human-quality utility evaluation of any particular tool family. It measures captured usage evidence, failure signals, and coverage gaps; usefulness still requires qualitative review of session context and outcomes.",
- "proof_report": {
- "action_scope": "grouped-tool-name-recent-window",
- "detail_patterns": [],
- "patterns": [
- "serena",
- "codebase",
- "cclsp",
- "context7",
- "polylogue",
- "lynchpin"
- ],
- "recent_top_families": [],
- "recent_window_days": 7,
- "report_version": 3,
- "surface_inventory_summary": [
- {
- "classification": "keep",
- "observed_actions": 0,
- "surface_type": "cli_command",
- "surfaces": 64
- },
- {
- "classification": "kill",
- "observed_actions": 0,
- "surface_type": "cli_command",
- "surfaces": 54
- },
- {
- "classification": "keep",
- "observed_actions": 0,
- "surface_type": "mcp_tool",
- "surfaces": 4
- },
- {
- "classification": "kill",
- "observed_actions": 0,
- "surface_type": "mcp_tool",
- "surfaces": 6
- }
- ],
- "top_families": []
- },
- "source_files": [
- "affordance-usage.report.json",
- "family-counts.csv",
- "evidence-kind-counts.csv",
- "tool-counts.csv",
- "tool-by-origin.csv",
- "recent-7d-tool-counts.csv",
- "tool-samples.csv",
- "surface-inventory.csv",
- "surface-classification-summary.csv"
- ],
- "updated_at": "2026-08-02T13:51:38.483581+00:00"
-}
diff --git a/.agent/demos/agent-affordance-usage/surface-classification-summary.csv b/.agent/demos/agent-affordance-usage/surface-classification-summary.csv
deleted file mode 100644
index cb72f8f3a3..0000000000
--- a/.agent/demos/agent-affordance-usage/surface-classification-summary.csv
+++ /dev/null
@@ -1,5 +0,0 @@
-surface_type,classification,surfaces,observed_actions
-cli_command,keep,64,0
-cli_command,kill,54,0
-mcp_tool,keep,4,0
-mcp_tool,kill,6,0
diff --git a/.agent/demos/agent-affordance-usage/surface-inventory.csv b/.agent/demos/agent-affordance-usage/surface-inventory.csv
deleted file mode 100644
index 7d349d4b68..0000000000
--- a/.agent/demos/agent-affordance-usage/surface-inventory.csv
+++ /dev/null
@@ -1,129 +0,0 @@
-surface_type,surface_name,observed_actions,observed_sessions,failure_rate,classification,operator_only_caveat,caveat
-mcp_tool,context,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-mcp_tool,explain,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-mcp_tool,get,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-mcp_tool,judge,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-mcp_tool,maintenance,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-mcp_tool,query,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-mcp_tool,read,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-mcp_tool,run,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-mcp_tool,status,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-mcp_tool,write,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,agent,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,agent doctor,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,agent install,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,agent manifest,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,agent manual,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,agent status,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,agent uninstall,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,agents,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,agents status,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,agents work-item,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze insights,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze insights cost-rollups,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze insights costs,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze insights coverage,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze insights debt,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze insights phases,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze insights profiles,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze insights tags,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze insights threads,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze insights timeline,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze insights tool-usage,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze insights usage-timeline,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze insights work-events,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze latency,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze pace,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze tools,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze turns,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,analyze usage,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,annotations,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,annotations import,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,annotations join,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,compare,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,config,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,config action-affordances,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,config completions,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,config paths,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,config query-completions,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,continue,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,dashboard,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,delete,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,demo,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,demo receipts,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,demo script,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,demo seed,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,demo tour,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,demo verify,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,facets,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,hooks,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,hooks install,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,hooks status,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,hooks uninstall,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,import,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,init,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,judge,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,manual,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,mark,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,note,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,ops,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops auth,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops backup,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops debt,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops debt list,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops diagnostics,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops diagnostics codex-title-census,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops diagnostics space,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops diagnostics workload,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops doctor,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops embed,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops embed backfill,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops embed disable,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops embed enable,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops embed preflight,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops embed resolve-failure,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops embed status,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops excise,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops insights,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops insights audit,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops insights export,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops insights hermes-health,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops insights status,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance archive-init,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance archive-plan,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance archive-read,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance assertion-export,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance attachment-acquisition-debt,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance backup-plan,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance blob-gc,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance blob-publications,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance blob-reference-debt,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance blob-reference-prune-orphans,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance blob-reference-recovery-plan,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance blob-reference-replace-from-source,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance embedding-orphan-reconcile,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance embeddings-rescue,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance gc-history,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance migrate-tier,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance plan,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance preview,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance raw-authority-blocker-resolve,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance raw-authority-blockers,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance raw-authority-census,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance raw-authority-detail,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance raw-authority-frontier,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance rebuild-index,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance run,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance status,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops maintenance verify-archive,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops materialize-incident-evidence,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops reconcile-work-effects,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops reset,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops scan-secrets,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,ops status,0,0,0.0,keep,True,operator-only surface; zero captured agent use is not removal evidence
-cli_command,read,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,select,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,status,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
-cli_command,tutorial,0,0,0.0,kill,False,zero captured agent use in this archive window; review before removal
diff --git a/.agent/demos/agent-affordance-usage/tool-by-origin.csv b/.agent/demos/agent-affordance-usage/tool-by-origin.csv
deleted file mode 100644
index 8b13789179..0000000000
--- a/.agent/demos/agent-affordance-usage/tool-by-origin.csv
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/.agent/demos/agent-affordance-usage/tool-counts.csv b/.agent/demos/agent-affordance-usage/tool-counts.csv
deleted file mode 100644
index 8b13789179..0000000000
--- a/.agent/demos/agent-affordance-usage/tool-counts.csv
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/.agent/demos/agent-affordance-usage/tool-samples.csv b/.agent/demos/agent-affordance-usage/tool-samples.csv
deleted file mode 100644
index 8b13789179..0000000000
--- a/.agent/demos/agent-affordance-usage/tool-samples.csv
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/.agent/demos/agent-forensics/README.md b/.agent/demos/agent-forensics/README.md
deleted file mode 100644
index a8ca822f1d..0000000000
--- a/.agent/demos/agent-forensics/README.md
+++ /dev/null
@@ -1,111 +0,0 @@
-# Agent Forensics
-
-A longitudinal agent-usage forensics packet, over the deterministic seeded
-demo archive (`polylogue demo seed`).
-
-This packet replaces the retired schema-v23 full-report packet for current
-cardinality and headline token/cost claims. It uses product analysis
-surfaces, not the deleted standalone `scripts/agent_forensics.py` path.
-
-**This packet is private-data-free.** A prior version of this packet was
-generated against a live operator archive and committed real corpus size,
-token totals, per-model spend in USD, and the operator's archive path to
-this public repo (polylogue-0bgr). It has been regenerated from scratch
-against the deterministic seeded fixture archive; every number below
-describes the ~19-session synthetic fixture, not any operator's real usage.
-
-## What This Proves
-
-Polylogue can regenerate an agent-usage forensics packet from an archive
-using normal analysis commands. The result keeps distinct evidence claims
-separate:
-
-- physical-session archive totals;
-- logical-session high-water totals;
-- priced vs origin-reported cost lanes;
-- current origin coverage;
-- month/origin/model usage timeline rows.
-
-## Current Headline (seeded fixture)
-
-Generated: 2026-08-02T13:52:20Z
-Archive root: `/path/to/demo-archive`
-Index schema: v54
-
-- physical sessions: 19
-- messages: 71
-- blocks: 121
-- materialized session profiles: 19
-- origin coverage rows: 8
-- usage timeline rows: 5
-- physical-session tokens accounted: 388,872
-- logical-session high-water tokens accounted: 388,872
-- replay-chain gap: 0
-- Claude Code physical/logical tokens: 388,500 / 388,500
-- Codex physical/logical tokens: 0 / 0 (no priced Codex sessions in the fixture)
-- stored provider-priced cost: $2.84
-- catalog API-equivalent cost: $2.84
-- logical catalog API-equivalent cost: $2.84
-
-## Caveats
-
-This is not provider billing truth. It does not query provider accounts. Cost
-figures are archive/provider-reported lanes plus catalog API-equivalent pricing
-where the pricing catalog matches the model.
-
-This is not a resurrection of the old standalone forensics script. The old
-script was intentionally folded into product analysis surfaces. This packet is
-the current demo/finding layer over those surfaces.
-
-This is not evidence about any operator's real usage or spend. The headline
-numbers above describe the deterministic seeded fixture only.
-
-The cost-rollups drilldown command completes immediately on this fixture (see
-`current/cost-rollups-timeout.txt`). The prior live-archive version of this
-packet recorded a genuine 120-second timeout on that command at live-archive
-scale; that is a real product-performance finding, tracked as a separate
-follow-up, and does not reproduce on a fixture this small.
-
-Structured failure follow-up behavior is covered by the current
-`claim-vs-evidence` packet. This packet links to that current demo rather than
-duplicating bounded failure-follow-up samples here.
-
-## Regenerate
-
-```bash
-polylogue demo seed --root ./demo-archive --force --with-overlays
-export POLYLOGUE_ARCHIVE_ROOT="$PWD/demo-archive"
-
-polylogue --plain ops diagnostics workload --json \
- > .agent/demos/agent-forensics/current/archive-workload.json
-
-polylogue --plain analyze usage --detail headline --format json --limit 0 \
- > .agent/demos/agent-forensics/current/usage-headline-all.json
-
-polylogue --plain analyze usage --detail headline --origin claude-code-session --format json --limit 0 \
- > .agent/demos/agent-forensics/current/usage-headline-claude-code.json
-
-polylogue --plain analyze usage --detail headline --origin codex-session --format json --limit 0 \
- > .agent/demos/agent-forensics/current/usage-headline-codex.json
-
-polylogue --plain analyze insights coverage --group-by origin --format json --limit 1000 \
- > .agent/demos/agent-forensics/current/coverage-origin.json
-
-polylogue --plain analyze insights usage-timeline --group-by month-origin-model --format json --limit 500 \
- > .agent/demos/agent-forensics/current/usage-timeline-month-origin-model.json
-
-devtools workspace demo-shelf
-```
-
-Never regenerate this packet with `POLYLOGUE_ARCHIVE_ROOT` pointed at a live
-operator archive -- this is a committed public-repo artifact, and doing so is
-exactly the mistake polylogue-0bgr fixed.
-
-## Files
-
-- `current/summary.json` — claim/non-claim, headline numbers, caveats, command proofs.
-- `current/archive-workload.json` — fixture-archive tier/cardinality snapshot.
-- `current/usage-headline-*.json` — all-provider and provider-specific usage lanes.
-- `current/coverage-origin.json` — origin coverage table.
-- `current/usage-timeline-month-origin-model.json` — month/origin/model timeline.
-- `current/cost-rollups-timeout.txt` — cost-rollups drilldown proof (completes on the fixture; documents the live-archive timeout finding it originally captured).
diff --git a/.agent/demos/agent-forensics/current/archive-workload.json b/.agent/demos/agent-forensics/current/archive-workload.json
deleted file mode 100644
index 04356fa0eb..0000000000
--- a/.agent/demos/agent-forensics/current/archive-workload.json
+++ /dev/null
@@ -1,687 +0,0 @@
-{
- "archive_tiers": {
- "complete": true,
- "derived_readiness": {
- "checked": true,
- "counts": {
- "action_count": 1,
- "action_count_exact": false,
- "block_count": 121,
- "cost_profile_count": 4,
- "lost_source_evidence_count": 0,
- "lost_source_evidence_samples": [],
- "message_count": 71,
- "messages_fts_count": -2,
- "messages_fts_exact_counts": false,
- "missing_profile_row_count": 0,
- "missing_raw_session_count": 0,
- "missing_raw_session_samples": [],
- "orphan_profile_row_count": 0,
- "phase_row_count": -2,
- "profile_phase_count_mismatch": 0,
- "profile_row_count": 19,
- "profile_work_event_count_mismatch": 0,
- "raw_link_count": 19,
- "raw_materialization_debt_count": 0,
- "raw_materialization_debt_group_count": 0,
- "session_count": 19,
- "session_tag_count": 2,
- "text_block_count": 121,
- "thread_count": 16,
- "thread_session_count": 19,
- "work_event_row_count": -2
- },
- "materialization_counts": {
- "context_snapshots": 19,
- "latency": 19,
- "observed_events": 19,
- "phases": 19,
- "provider_usage": 19,
- "runs": 19,
- "session_profile": 19,
- "thread": 19,
- "work_events": 19
- },
- "missing_materialization_counts": {
- "latency": 0,
- "phases": 0,
- "session_profile": 0,
- "thread": 0,
- "work_events": 0
- },
- "ready": {
- "latency_materialization_ready": true,
- "messages_fts_ready": true,
- "phase_materialization_ready": true,
- "profile_counts_ready": true,
- "profile_materialization_ready": true,
- "profile_rows_ready": true,
- "raw_links_ready": true,
- "raw_materialization_ready": true,
- "thread_materialization_ready": true,
- "work_event_materialization_ready": true
- },
- "reason": null,
- "source_check_available": true,
- "surface_readiness": {
- "archive_sessions": {
- "blockers": [],
- "evidence": {
- "message_count": 71,
- "session_count": 19,
- "text_block_count": 121
- },
- "ready": true
- },
- "latency_profiles": {
- "blockers": [],
- "evidence": {
- "missing_materialization_count": 0
- },
- "ready": true
- },
- "raw_artifacts": {
- "blockers": [],
- "evidence": {
- "lost_source_evidence_count": 0,
- "lost_source_evidence_samples": [],
- "missing_raw_session_count": 0,
- "missing_raw_session_samples": [],
- "raw_link_count": 19,
- "raw_materialization_debt_count": 0,
- "raw_materialization_debt_group_count": 0,
- "source_check_available": true
- },
- "ready": true
- },
- "search": {
- "blockers": [],
- "evidence": {
- "messages_fts_count": -2,
- "messages_fts_exact_counts": false,
- "text_block_count": 121
- },
- "ready": true
- },
- "session_costs": {
- "blockers": [],
- "evidence": {
- "cost_profile_count": 4,
- "missing_materialization_count": 0,
- "missing_profile_row_count": 0
- },
- "ready": true
- },
- "session_profiles": {
- "blockers": [],
- "evidence": {
- "missing_materialization_count": 0,
- "missing_profile_row_count": 0,
- "orphan_profile_row_count": 0,
- "profile_row_count": 19
- },
- "ready": true
- },
- "tag_rollups": {
- "blockers": [],
- "evidence": {
- "session_tag_count": 2
- },
- "ready": true
- },
- "threads": {
- "blockers": [],
- "evidence": {
- "missing_materialization_count": 0,
- "thread_count": 16,
- "thread_session_count": 19
- },
- "ready": true
- },
- "timeline_phases": {
- "blockers": [],
- "evidence": {
- "missing_materialization_count": 0,
- "phase_row_count": -2
- },
- "ready": true
- },
- "timeline_work_events": {
- "blockers": [],
- "evidence": {
- "missing_materialization_count": 0,
- "work_event_row_count": -2
- },
- "ready": true
- },
- "tool_usage": {
- "blockers": [],
- "evidence": {
- "action_count": 1,
- "action_count_exact": false
- },
- "ready": true
- }
- }
- },
- "expected_count": 5,
- "layout_readiness": {
- "archive_ready": true,
- "blockers": [],
- "evidence": {
- "blocked_surface_count": 0,
- "complete": true,
- "derived_readiness_checked": true,
- "derived_surface_count": 11,
- "expected_count": 5,
- "missing_backup_required_count": 0,
- "present_count": 5,
- "schema_mismatch_count": 0,
- "user_overlay_checked": true,
- "user_overlay_orphan_session_references": 0
- },
- "state": "archive_ready"
- },
- "missing_backup_required": [],
- "observed_tier": "index",
- "present": true,
- "present_count": 5,
- "root": "/path/to/demo-archive",
- "schema_mismatches": [],
- "table_count_mode": "mixed",
- "tiers": {
- "embeddings": {
- "backup_required": true,
- "durability": "expensive_rebuild",
- "error": null,
- "exists": true,
- "expected_user_version": 4,
- "filename": "embeddings.db",
- "integrity": "not_checked",
- "observed_by_probe": false,
- "path": "/path/to/demo-archive/embeddings.db",
- "size_bytes": 4317184,
- "table_count_precision": {
- "embedding_status": "exact",
- "message_embeddings": "unavailable",
- "message_embeddings_meta": "unavailable"
- },
- "table_counts": {
- "embedding_status": 1,
- "message_embeddings": -2,
- "message_embeddings_meta": -2
- },
- "tier": "embeddings",
- "user_version": 4
- },
- "index": {
- "backup_required": false,
- "durability": "rebuildable",
- "error": null,
- "exists": true,
- "expected_user_version": 54,
- "filename": "index.db",
- "integrity": "not_checked",
- "observed_by_probe": true,
- "path": "/path/to/demo-archive/index.db",
- "size_bytes": 1449984,
- "table_count_precision": {
- "attachment_refs": "estimate",
- "attachments": "estimate",
- "blocks": "estimate",
- "insight_materialization": "exact",
- "messages": "exact",
- "messages_fts_docsize": "unavailable",
- "paste_spans": "unavailable",
- "repos": "estimate",
- "session_commits": "unavailable",
- "session_events": "estimate",
- "session_links": "estimate",
- "session_phases": "unavailable",
- "session_profiles": "exact",
- "session_repos": "estimate",
- "session_tags": "estimate",
- "session_work_events": "unavailable",
- "session_working_dirs": "estimate",
- "sessions": "exact",
- "thread_sessions": "estimate",
- "threads": "estimate"
- },
- "table_counts": {
- "attachment_refs": 1,
- "attachments": 1,
- "blocks": 121,
- "insight_materialization": 171,
- "messages": 71,
- "messages_fts_docsize": -2,
- "paste_spans": -2,
- "repos": 5,
- "session_commits": -2,
- "session_events": 4,
- "session_links": 3,
- "session_phases": -2,
- "session_profiles": 19,
- "session_repos": 5,
- "session_tags": 2,
- "session_work_events": -2,
- "session_working_dirs": 5,
- "sessions": 19,
- "thread_sessions": 19,
- "threads": 16
- },
- "tier": "index",
- "user_version": 54
- },
- "ops": {
- "backup_required": false,
- "durability": "disposable",
- "error": null,
- "exists": true,
- "expected_user_version": 1,
- "filename": "ops.db",
- "integrity": "not_checked",
- "observed_by_probe": false,
- "path": "/path/to/demo-archive/ops.db",
- "size_bytes": 266240,
- "table_count_precision": {
- "convergence_debt": "exact",
- "cursor_lag_samples": "exact",
- "daemon_events": "exact",
- "daemon_stage_events": "exact",
- "embedding_catchup_runs": "unavailable",
- "ingest_attempts": "exact",
- "ingest_cursor": "unavailable",
- "otlp_spans": "unavailable",
- "otlp_telemetry": "unavailable"
- },
- "table_counts": {
- "convergence_debt": 0,
- "cursor_lag_samples": 0,
- "daemon_events": 0,
- "daemon_stage_events": 0,
- "embedding_catchup_runs": -2,
- "ingest_attempts": 0,
- "ingest_cursor": -2,
- "otlp_spans": -2,
- "otlp_telemetry": -2
- },
- "tier": "ops",
- "user_version": 1
- },
- "source": {
- "backup_required": true,
- "durability": "irreplaceable",
- "error": null,
- "exists": true,
- "expected_user_version": 16,
- "filename": "source.db",
- "integrity": "not_checked",
- "observed_by_probe": false,
- "path": "/path/to/demo-archive/source.db",
- "size_bytes": 344064,
- "table_count_precision": {
- "blob_refs": "estimate",
- "history_sidecars": "unavailable",
- "raw_artifacts": "unavailable",
- "raw_hook_events": "unavailable",
- "raw_sessions": "exact"
- },
- "table_counts": {
- "blob_refs": 22,
- "history_sidecars": -2,
- "raw_artifacts": -2,
- "raw_hook_events": -2,
- "raw_sessions": 21
- },
- "tier": "source",
- "user_version": 16
- },
- "user": {
- "backup_required": true,
- "durability": "human",
- "error": null,
- "exists": true,
- "expected_user_version": 10,
- "filename": "user.db",
- "integrity": "not_checked",
- "observed_by_probe": false,
- "path": "/path/to/demo-archive/user.db",
- "size_bytes": 253952,
- "table_count_precision": {
- "assertions": "unavailable",
- "session_metadata": "missing",
- "session_tags": "missing"
- },
- "table_counts": {
- "assertions": -2,
- "session_metadata": -1,
- "session_tags": -1
- },
- "tier": "user",
- "user_version": 10
- }
- },
- "user_overlay_orphans": {
- "checked": true,
- "orphan_session_reference_counts": {
- "assertion_annotations": 0,
- "assertion_corrections": 0,
- "assertion_marks": 0,
- "assertion_metadata": 0,
- "assertion_notes": 0,
- "assertion_suppressions": 0,
- "assertion_tags": 0
- },
- "reason": null,
- "total_orphan_session_references": 0
- }
- },
- "attempt_counts": {
- "completed": 0,
- "failed": 0,
- "overlapping_source_paths": [],
- "running": 0,
- "stale_cursor_writes": 0,
- "total": 0
- },
- "automatic_convergence_backlog": {
- "checked": true,
- "counts": {
- "automatic_backlog_total": 0,
- "missing_latency_materialization": 0,
- "missing_phases_materialization": 0,
- "missing_profile_rows": 0,
- "missing_session_profile_materialization": 0,
- "missing_threads_materialization": 0,
- "missing_work_events_materialization": 0,
- "retry_debt_unresolved": 0
- },
- "reason": null,
- "state": "ready"
- },
- "blob_reference_debt": {
- "checked": false,
- "ok": true,
- "reason": "skipped; pass --blob-reference-debt to scan referenced blob files"
- },
- "boundary_table_count_mode": "mixed",
- "boundary_table_count_precision": {
- "blocks": "estimate",
- "convergence_debt": "exact",
- "cursor_lag_samples": "exact",
- "daemon_events": "exact",
- "daemon_stage_events": "exact",
- "ingest_attempts": "exact",
- "live_ingest_attempt": "missing",
- "message_embeddings": "missing",
- "messages": "exact",
- "messages_fts_docsize": "unavailable",
- "otlp_telemetry": "unavailable",
- "raw_artifacts": "unavailable",
- "raw_sessions": "exact",
- "repos": "estimate",
- "session_commits": "unavailable",
- "session_events": "estimate",
- "session_links": "estimate",
- "session_profiles": "exact",
- "session_repos": "estimate",
- "sessions": "exact"
- },
- "boundary_table_counts": {
- "blocks": 121,
- "convergence_debt": 0,
- "cursor_lag_samples": 0,
- "daemon_events": 0,
- "daemon_stage_events": 0,
- "ingest_attempts": 0,
- "live_ingest_attempt": -1,
- "message_embeddings": -1,
- "messages": 71,
- "messages_fts_docsize": -2,
- "otlp_telemetry": -2,
- "raw_artifacts": -2,
- "raw_sessions": 21,
- "repos": 5,
- "session_commits": -2,
- "session_events": 4,
- "session_links": 3,
- "session_profiles": 19,
- "session_repos": 5,
- "sessions": 19
- },
- "captured_at": "2026-08-02T13:51:53+00:00",
- "convergence_debt": {
- "by_stage": [],
- "deferred_count": 0,
- "failed_count": 0,
- "unresolved_count": 0
- },
- "convergence_stage_timings": {
- "convergence_time_s": {
- "max": 0.0,
- "mean": 0.0,
- "min": 0.0,
- "sum": 0.0
- },
- "parse_time_s": {
- "max": 0.0,
- "mean": 0.0,
- "min": 0.0,
- "sum": 0.0
- },
- "per_stage_s": {},
- "read_amplification": {
- "max": 0.0,
- "mean": 0.0,
- "min": 0.0,
- "sum": 0.0
- },
- "sample_size": 0
- },
- "cursor_lag_baselines": {
- "families": [],
- "family_count": 0,
- "table_present": true,
- "total_sample_count": 0
- },
- "daemon_resource_signal": {
- "available": false
- },
- "db_path": "/path/to/demo-archive/index.db",
- "fts_trigger_state": {
- "all_present": true,
- "expected": [
- "messages_fts_ai",
- "messages_fts_ad",
- "messages_fts_au"
- ],
- "missing": [],
- "present": [
- "messages_fts_ad",
- "messages_fts_ai",
- "messages_fts_au"
- ]
- },
- "gc_state": {
- "generation_count": 0,
- "high_water_generation": 0,
- "last_completed_at": null,
- "table_present": true
- },
- "observability_locations": {
- "archive_root": "/path/to/demo-archive",
- "logical_tables": {
- "blocks": {
- "db_path": "/path/to/demo-archive/index.db",
- "exists": true,
- "logical_table": "blocks",
- "physical_table": "blocks",
- "tier": "index"
- },
- "convergence_debt": {
- "db_path": "/path/to/demo-archive/ops.db",
- "exists": true,
- "logical_table": "convergence_debt",
- "physical_table": "convergence_debt",
- "tier": "ops"
- },
- "live_ingest_attempt": {
- "db_path": "/path/to/demo-archive/ops.db",
- "exists": true,
- "logical_table": "live_ingest_attempt",
- "physical_table": "ingest_attempts",
- "tier": "ops"
- },
- "live_ingest_attempt_stage_events": {
- "db_path": "/path/to/demo-archive/ops.db",
- "exists": true,
- "logical_table": "live_ingest_attempt_stage_events",
- "physical_table": "daemon_stage_events",
- "tier": "ops"
- },
- "messages": {
- "db_path": "/path/to/demo-archive/index.db",
- "exists": true,
- "logical_table": "messages",
- "physical_table": "messages",
- "tier": "index"
- },
- "messages_fts": {
- "db_path": "/path/to/demo-archive/index.db",
- "exists": true,
- "logical_table": "messages_fts",
- "physical_table": "messages_fts",
- "tier": "index"
- },
- "raw_sessions": {
- "db_path": "/path/to/demo-archive/source.db",
- "exists": true,
- "logical_table": "raw_sessions",
- "physical_table": "raw_sessions",
- "tier": "source"
- },
- "sessions": {
- "db_path": "/path/to/demo-archive/index.db",
- "exists": true,
- "logical_table": "sessions",
- "physical_table": "sessions",
- "tier": "index"
- }
- },
- "tiers": {
- "index": "/path/to/demo-archive/index.db",
- "ops": "/path/to/demo-archive/ops.db",
- "source": "/path/to/demo-archive/source.db"
- }
- },
- "ok": true,
- "query_plans": {
- "message_fts_gap_probe": {
- "hazards": [],
- "plan": [
- "SEARCH b USING INDEX idx_blocks_session_position (session_id=?)",
- "SEARCH d USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN"
- ]
- },
- "source_path_lookup": {
- "hazards": [],
- "plan": [
- "SEARCH r USING INDEX idx_raw_sessions_source_path (source_path=?)",
- "SEARCH s USING INDEX idx_sessions_raw_id (raw_id=?)",
- "USE TEMP B-TREE FOR DISTINCT"
- ],
- "storage_route": "archive_file_set"
- }
- },
- "raw_replay_backlog": {
- "adoption_deferred_count": 0,
- "already_parsed_count": 0,
- "authority_component_count": 0,
- "authority_quarantined_count": 0,
- "available": true,
- "blocked_authority_component_count": 0,
- "blocked_candidate_count": 0,
- "byte_authority_fragment_count": 0,
- "byte_authority_pending_count": 0,
- "byte_authority_quarantined_count": 0,
- "candidate_count": 0,
- "durable_authority_debt_count": 0,
- "executable_authority_component_count": 0,
- "execute_blob_limit_bytes": 1073741824,
- "execution_block_reason": null,
- "execution_blocked": false,
- "expanded_aggregate_blocked": false,
- "expanded_candidate_count": 0,
- "expanded_total_blob_bytes": 0,
- "max_blob_bytes": 0,
- "missing_blob_count": 0,
- "missing_blob_source_available_count": 0,
- "missing_blob_source_missing_count": 0,
- "origin_summary": [],
- "oversized_count": 0,
- "oversized_stream_safe_count": 0,
- "source_path_summary": [],
- "top_raw_rows": [],
- "total_blob_bytes": 0
- },
- "recent_attempts": [],
- "report_version": 18,
- "source_path_churn": [],
- "sqlite_maintenance": {
- "observed_db": "/path/to/demo-archive/index.db",
- "tiers": {
- "embeddings": {
- "exists": true,
- "path": "/path/to/demo-archive/embeddings.db",
- "planner_stats_present": true,
- "sqlite_stat1_rows": 1,
- "wal_bytes": 0
- },
- "index": {
- "exists": true,
- "path": "/path/to/demo-archive/index.db",
- "planner_stats_present": true,
- "sqlite_stat1_rows": 84,
- "wal_bytes": 0
- },
- "ops": {
- "exists": true,
- "path": "/path/to/demo-archive/ops.db",
- "planner_stats_present": false,
- "sqlite_stat1_rows": 0,
- "wal_bytes": 0
- },
- "source": {
- "exists": true,
- "path": "/path/to/demo-archive/source.db",
- "planner_stats_present": true,
- "sqlite_stat1_rows": 14,
- "wal_bytes": 0
- },
- "user": {
- "exists": true,
- "path": "/path/to/demo-archive/user.db",
- "planner_stats_present": true,
- "sqlite_stat1_rows": 1,
- "wal_bytes": 0
- }
- },
- "tiers_with_planner_stats": 4,
- "total_wal_bytes": 0
- },
- "storage_route_counts": {
- "archive_append": 0,
- "archive_file_set": 0,
- "archive_full": 0,
- "other": 0,
- "unknown": 0,
- "unsupported_polylogue_batch": 0
- },
- "topology_quarantine_state": {
- "oldest_quarantined_at": null,
- "quarantined_count": 0,
- "resolved_count": 3,
- "table_present": true,
- "unresolved_count": 0
- }
-}
diff --git a/.agent/demos/agent-forensics/current/cost-rollups-timeout.txt b/.agent/demos/agent-forensics/current/cost-rollups-timeout.txt
deleted file mode 100644
index 495dc65473..0000000000
--- a/.agent/demos/agent-forensics/current/cost-rollups-timeout.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-exit_code=0
-elapsed_s=n/a (completes well under a second on the 19-session seeded fixture)
-command=POLYLOGUE_ARCHIVE_ROOT=/path/to/demo-archive polylogue --plain analyze insights cost-rollups --format json --limit 100
-note=The original version of this packet was generated against a live operator archive and this command timed out there (exit_code=124, elapsed_s=120.03) -- a genuine product-performance finding at live-archive scale, tracked separately. That timeout does not reproduce on this tiny synthetic fixture, so this file no longer documents a timeout; it documents that the command completes and returns 10 cost-rollup rows.
diff --git a/.agent/demos/agent-forensics/current/coverage-origin.json b/.agent/demos/agent-forensics/current/coverage-origin.json
deleted file mode 100644
index 1b2a2b496b..0000000000
--- a/.agent/demos/agent-forensics/current/coverage-origin.json
+++ /dev/null
@@ -1,264 +0,0 @@
-{
- "status": "ok",
- "result": {
- "total": 8,
- "archive_coverage": [
- {
- "contract_version": 10,
- "insight_kind": "archive_coverage",
- "group_by": "origin",
- "bucket": "codex-session",
- "origin": "codex-session",
- "session_count": 7,
- "logical_session_count": 0,
- "message_count": 30,
- "user_message_count": 9,
- "authored_user_message_count": 9,
- "assistant_message_count": 17,
- "total_cost_usd": 0.0,
- "total_duration_ms": 0,
- "total_tool_active_duration_ms": 0,
- "total_wall_duration_ms": 0,
- "total_words": 0,
- "avg_messages_per_session": 4.285714285714286,
- "avg_user_words": 7.333333333333333,
- "avg_authored_user_words": 7.333333333333333,
- "avg_assistant_words": 7.588235294117647,
- "tool_use_count": 9,
- "thinking_count": 0,
- "total_sessions_with_tools": 4,
- "total_sessions_with_thinking": 0,
- "tool_use_percentage": 57.14285714285714,
- "thinking_percentage": 0.0,
- "work_event_breakdown": {},
- "repos_active": [],
- "origin_breakdown": {},
- "provenance": null
- },
- {
- "contract_version": 10,
- "insight_kind": "archive_coverage",
- "group_by": "origin",
- "bucket": "claude-code-session",
- "origin": "claude-code-session",
- "session_count": 4,
- "logical_session_count": 0,
- "message_count": 19,
- "user_message_count": 3,
- "authored_user_message_count": 2,
- "assistant_message_count": 10,
- "total_cost_usd": 0.0,
- "total_duration_ms": 0,
- "total_tool_active_duration_ms": 0,
- "total_wall_duration_ms": 0,
- "total_words": 0,
- "avg_messages_per_session": 4.75,
- "avg_user_words": 12.0,
- "avg_authored_user_words": 10.5,
- "avg_assistant_words": 28.0,
- "tool_use_count": 7,
- "thinking_count": 0,
- "total_sessions_with_tools": 2,
- "total_sessions_with_thinking": 0,
- "tool_use_percentage": 50.0,
- "thinking_percentage": 0.0,
- "work_event_breakdown": {},
- "repos_active": [],
- "origin_breakdown": {},
- "provenance": null
- },
- {
- "contract_version": 10,
- "insight_kind": "archive_coverage",
- "group_by": "origin",
- "bucket": "chatgpt-export",
- "origin": "chatgpt-export",
- "session_count": 3,
- "logical_session_count": 0,
- "message_count": 7,
- "user_message_count": 4,
- "authored_user_message_count": 4,
- "assistant_message_count": 3,
- "total_cost_usd": 0.0,
- "total_duration_ms": 0,
- "total_tool_active_duration_ms": 0,
- "total_wall_duration_ms": 0,
- "total_words": 0,
- "avg_messages_per_session": 2.3333333333333335,
- "avg_user_words": 44.5,
- "avg_authored_user_words": 44.5,
- "avg_assistant_words": 24.333333333333332,
- "tool_use_count": 0,
- "thinking_count": 0,
- "total_sessions_with_tools": 0,
- "total_sessions_with_thinking": 0,
- "tool_use_percentage": 0.0,
- "thinking_percentage": 0.0,
- "work_event_breakdown": {},
- "repos_active": [],
- "origin_breakdown": {},
- "provenance": null
- },
- {
- "contract_version": 10,
- "insight_kind": "archive_coverage",
- "group_by": "origin",
- "bucket": "aistudio-drive",
- "origin": "aistudio-drive",
- "session_count": 1,
- "logical_session_count": 0,
- "message_count": 4,
- "user_message_count": 2,
- "authored_user_message_count": 2,
- "assistant_message_count": 2,
- "total_cost_usd": 0.0,
- "total_duration_ms": 0,
- "total_tool_active_duration_ms": 0,
- "total_wall_duration_ms": 0,
- "total_words": 0,
- "avg_messages_per_session": 4.0,
- "avg_user_words": 7.0,
- "avg_authored_user_words": 7.0,
- "avg_assistant_words": 5.0,
- "tool_use_count": 0,
- "thinking_count": 0,
- "total_sessions_with_tools": 0,
- "total_sessions_with_thinking": 0,
- "tool_use_percentage": 0.0,
- "thinking_percentage": 0.0,
- "work_event_breakdown": {},
- "repos_active": [],
- "origin_breakdown": {},
- "provenance": null
- },
- {
- "contract_version": 10,
- "insight_kind": "archive_coverage",
- "group_by": "origin",
- "bucket": "antigravity-session",
- "origin": "antigravity-session",
- "session_count": 1,
- "logical_session_count": 0,
- "message_count": 2,
- "user_message_count": 1,
- "authored_user_message_count": 0,
- "assistant_message_count": 1,
- "total_cost_usd": 0.0,
- "total_duration_ms": 0,
- "total_tool_active_duration_ms": 0,
- "total_wall_duration_ms": 0,
- "total_words": 0,
- "avg_messages_per_session": 2.0,
- "avg_user_words": 11.0,
- "avg_authored_user_words": null,
- "avg_assistant_words": 18.0,
- "tool_use_count": 0,
- "thinking_count": 0,
- "total_sessions_with_tools": 0,
- "total_sessions_with_thinking": 0,
- "tool_use_percentage": 0.0,
- "thinking_percentage": 0.0,
- "work_event_breakdown": {},
- "repos_active": [],
- "origin_breakdown": {},
- "provenance": null
- },
- {
- "contract_version": 10,
- "insight_kind": "archive_coverage",
- "group_by": "origin",
- "bucket": "claude-ai-export",
- "origin": "claude-ai-export",
- "session_count": 1,
- "logical_session_count": 0,
- "message_count": 2,
- "user_message_count": 1,
- "authored_user_message_count": 1,
- "assistant_message_count": 1,
- "total_cost_usd": 0.0,
- "total_duration_ms": 0,
- "total_tool_active_duration_ms": 0,
- "total_wall_duration_ms": 0,
- "total_words": 0,
- "avg_messages_per_session": 2.0,
- "avg_user_words": 7.0,
- "avg_authored_user_words": 7.0,
- "avg_assistant_words": 10.0,
- "tool_use_count": 0,
- "thinking_count": 0,
- "total_sessions_with_tools": 0,
- "total_sessions_with_thinking": 0,
- "tool_use_percentage": 0.0,
- "thinking_percentage": 0.0,
- "work_event_breakdown": {},
- "repos_active": [],
- "origin_breakdown": {},
- "provenance": null
- },
- {
- "contract_version": 10,
- "insight_kind": "archive_coverage",
- "group_by": "origin",
- "bucket": "gemini-cli-session",
- "origin": "gemini-cli-session",
- "session_count": 1,
- "logical_session_count": 0,
- "message_count": 2,
- "user_message_count": 1,
- "authored_user_message_count": 0,
- "assistant_message_count": 1,
- "total_cost_usd": 0.0,
- "total_duration_ms": 0,
- "total_tool_active_duration_ms": 0,
- "total_wall_duration_ms": 0,
- "total_words": 0,
- "avg_messages_per_session": 2.0,
- "avg_user_words": 15.0,
- "avg_authored_user_words": null,
- "avg_assistant_words": 18.0,
- "tool_use_count": 1,
- "thinking_count": 1,
- "total_sessions_with_tools": 1,
- "total_sessions_with_thinking": 1,
- "tool_use_percentage": 100.0,
- "thinking_percentage": 100.0,
- "work_event_breakdown": {},
- "repos_active": [],
- "origin_breakdown": {},
- "provenance": null
- },
- {
- "contract_version": 10,
- "insight_kind": "archive_coverage",
- "group_by": "origin",
- "bucket": "hermes-session",
- "origin": "hermes-session",
- "session_count": 1,
- "logical_session_count": 0,
- "message_count": 5,
- "user_message_count": 1,
- "authored_user_message_count": 0,
- "assistant_message_count": 2,
- "total_cost_usd": 0.0,
- "total_duration_ms": 0,
- "total_tool_active_duration_ms": 0,
- "total_wall_duration_ms": 0,
- "total_words": 0,
- "avg_messages_per_session": 5.0,
- "avg_user_words": 10.0,
- "avg_authored_user_words": null,
- "avg_assistant_words": 8.0,
- "tool_use_count": 1,
- "thinking_count": 0,
- "total_sessions_with_tools": 1,
- "total_sessions_with_thinking": 0,
- "tool_use_percentage": 100.0,
- "thinking_percentage": 0.0,
- "work_event_breakdown": {},
- "repos_active": [],
- "origin_breakdown": {},
- "provenance": null
- }
- ]
- }
-}
diff --git a/.agent/demos/agent-forensics/current/summary.json b/.agent/demos/agent-forensics/current/summary.json
deleted file mode 100644
index 6e234a2b91..0000000000
--- a/.agent/demos/agent-forensics/current/summary.json
+++ /dev/null
@@ -1,107 +0,0 @@
-{
- "artifact": "agent-forensics",
- "title": "Agent Forensics (seeded fixture)",
- "generated_at": "2026-08-02T13:52:20Z",
- "archive_root": "/path/to/demo-archive",
- "index_schema_version": 54,
- "archive_cardinality": {
- "physical_sessions": 19,
- "messages": 71,
- "blocks": 121,
- "session_profiles_materialized": 19,
- "origin_rows": 8,
- "usage_timeline_rows": 5
- },
- "physical_session_tokens_accounted": 388872,
- "logical_session_high_water_tokens_accounted": 388872,
- "all_provider_replay_gap_tokens": 0,
- "claude_code_physical_session_tokens": 388500,
- "claude_code_logical_session_high_water_tokens": 388500,
- "claude_code_replay_gap_tokens": 0,
- "codex_physical_session_tokens": 0,
- "codex_logical_session_high_water_tokens": 0,
- "codex_replay_gap_tokens": 0,
- "stored_provider_priced_usd": 2.835,
- "catalog_api_equivalent_usd": 2.835,
- "logical_catalog_api_equivalent_usd": 2.835,
- "claim": "Polylogue can regenerate a current v54 longitudinal agent-usage forensics packet over a deterministic seeded fixture archive using product analysis surfaces, with provenance-separated token/cost lanes and explicit physical-vs-logical token grains.",
- "non_claim": "This packet is not provider billing truth, not an LLM judgment of failure follow-up behavior, not a resurrected standalone forensics script, and not evidence about the operator's real archive; it reads the deterministic demo archive through the same product commands used against a live archive, and points structured-failure follow-up to the current claim-vs-evidence packet.",
- "proof_fields": [
- "archive_cardinality",
- "physical_session_tokens_accounted",
- "logical_session_high_water_tokens_accounted",
- "pricing_lanes",
- "coverage-origin.json",
- "usage-timeline-month-origin-model.json"
- ],
- "caveat_fields": [
- "usage_headline_caveats",
- "cost_rollups_performance",
- "coverage_semantics",
- "fixture_scale_caveat"
- ],
- "fixture_scale_caveat": [
- "This packet was regenerated against the deterministic seeded demo archive (19 sessions, 71 messages), not a live operator archive (polylogue-0bgr: the prior version of this packet was generated against a live archive and committed real corpus size, token totals, and dollar figures to this public repo).",
- "Headline totals here are illustrative of report shape and command wiring only; they carry no evidentiary weight about real usage/cost at any scale."
- ],
- "usage_headline_caveats": [
- "provider usage events, transcript text volume, and model rollups are separate evidence streams",
- "this report does not query provider billing and is not a precise cost report",
- "headline detail computes session/source/model-rollup totals only; run with detail='full' for provider-event, cumulative, sample, and stale-rollup diagnostics"
- ],
- "pricing_lanes": [
- {
- "provenance": "priced",
- "row_count": 1,
- "session_count": 1,
- "matched_model_row_count": 1,
- "unmatched_model_row_count": 0,
- "usage": {
- "input_tokens": 56000,
- "output_tokens": 10500,
- "cached_input_tokens": 280000,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388500
- },
- "stored_cost_usd": 2.835,
- "catalog_api_equivalent_usd": 2.835,
- "caveats": []
- }
- ],
- "logical_pricing_lanes": [
- {
- "provenance": "priced",
- "row_count": 1,
- "session_count": 1,
- "matched_model_row_count": 1,
- "unmatched_model_row_count": 0,
- "usage": {
- "input_tokens": 56000,
- "output_tokens": 10500,
- "cached_input_tokens": 280000,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388500
- },
- "stored_cost_usd": 0.0,
- "catalog_api_equivalent_usd": 2.835,
- "caveats": []
- }
- ],
- "command_proofs": {
- "workload": "POLYLOGUE_ARCHIVE_ROOT=/path/to/demo-archive polylogue --plain ops diagnostics workload --json",
- "usage_all": "POLYLOGUE_ARCHIVE_ROOT=/path/to/demo-archive polylogue --plain analyze usage --detail headline --format json --limit 0",
- "usage_claude_code": "POLYLOGUE_ARCHIVE_ROOT=/path/to/demo-archive polylogue --plain analyze usage --detail headline --origin claude-code-session --format json --limit 0",
- "usage_codex": "POLYLOGUE_ARCHIVE_ROOT=/path/to/demo-archive polylogue --plain analyze usage --detail headline --origin codex-session --format json --limit 0",
- "coverage_origin": "POLYLOGUE_ARCHIVE_ROOT=/path/to/demo-archive polylogue --plain analyze insights coverage --group-by origin --format json --limit 1000",
- "usage_timeline": "POLYLOGUE_ARCHIVE_ROOT=/path/to/demo-archive polylogue --plain analyze insights usage-timeline --group-by month-origin-model --format json --limit 500"
- },
- "cost_rollups_performance": {
- "command": "POLYLOGUE_ARCHIVE_ROOT=/path/to/demo-archive polylogue --plain analyze insights cost-rollups --format json --limit 100",
- "timeout_s": 120,
- "exit_code": 0,
- "elapsed_s": null,
- "impact": "Completes immediately on the tiny seeded fixture (10 rollup rows; see cost-rollups-timeout.txt). The prior live-archive drilldown timeout this file documented was a real product-performance finding at live-archive scale; it does not reproduce on a fixture this small and is tracked as a separate performance follow-up, not evidence carried by this packet."
- }
-}
diff --git a/.agent/demos/agent-forensics/current/usage-headline-all.json b/.agent/demos/agent-forensics/current/usage-headline-all.json
deleted file mode 100644
index f1a7917c75..0000000000
--- a/.agent/demos/agent-forensics/current/usage-headline-all.json
+++ /dev/null
@@ -1,1775 +0,0 @@
-{
- "archive_root": "/path/to/demo-archive",
- "detail_level": "headline",
- "coverage_matrix": [
- {
- "origin": "claude-code-session",
- "provider": "claude-code",
- "status": "exact",
- "evidence_stream": "provider_reported_usage",
- "event_types": [
- "message_usage"
- ],
- "request_semantics": "Claude Code message.usage rows are per message/request observations.",
- "cumulative_semantics": "Session rollups are derived by summing message usage rows; Claude Code does not supply a separate cumulative session high-water event.",
- "cache_semantics": "cache_read_input_tokens and cache_creation_input_tokens are preserved as cached_input and cache_write lanes and are not folded into generic input/output.",
- "notes": [
- "Exact token telemetry is available only where exported records include message.usage."
- ],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "codex-session",
- "provider": "codex",
- "status": "exact",
- "evidence_stream": "provider_reported_usage",
- "event_types": [
- "token_count"
- ],
- "request_semantics": "Codex last_token_usage is request/current-window telemetry and can be summed by request when present.",
- "cumulative_semantics": "Codex total_token_usage is cumulative and session-global; rollups take the latest total per session to avoid double-counting.",
- "cache_semantics": "cached_input_tokens and cache write/cache creation aliases are preserved as separate lanes and are not folded into generic input/output.",
- "notes": [
- "model_context_window is carried on token_count events when the provider supplies it."
- ],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "chatgpt-export",
- "provider": "chatgpt",
- "status": "estimate_only",
- "evidence_stream": "transcript_text_estimate",
- "event_types": [],
- "request_semantics": "ChatGPT exports do not carry reliable per-request token counters.",
- "cumulative_semantics": "Provider/account UI totals are external summaries and are not reconstructed from transcript text.",
- "cache_semantics": "No cache read/write token lanes are available in ChatGPT export rows.",
- "notes": [
- "Cost-looking metadata is not treated as exact token telemetry."
- ],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "claude-ai-export",
- "provider": "claude-ai",
- "status": "estimate_only",
- "evidence_stream": "transcript_text_estimate",
- "event_types": [],
- "request_semantics": "Claude.ai exports preserve transcript content, not provider usage counters.",
- "cumulative_semantics": "No cumulative provider usage window is present in the export shape.",
- "cache_semantics": "No cache read/write token lanes are available in Claude.ai export rows.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "aistudio-drive",
- "provider": "gemini",
- "status": "partial",
- "evidence_stream": "message_token_fields",
- "event_types": [],
- "request_semantics": "AI Studio/Gemini exports may carry message-level tokenCount output counters on some records.",
- "cumulative_semantics": "No provider cumulative session usage window is available from Drive prompt exports.",
- "cache_semantics": "No cache read/write token lanes are available from Drive prompt exports.",
- "notes": [
- "Input tokens and cache semantics are missing unless a future export shape supplies them explicitly."
- ],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "gemini-cli-session",
- "provider": "gemini-cli",
- "status": "partial",
- "evidence_stream": "message_token_fields",
- "event_types": [],
- "request_semantics": "Local Gemini CLI documents may carry generic usage/tokens dictionaries per message.",
- "cumulative_semantics": "No provider cumulative session usage window is available.",
- "cache_semantics": "Generic cache_read/cache_write keys are preserved when present, but their provider semantics are not independently verified.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "hermes-session",
- "provider": "hermes",
- "status": "partial",
- "evidence_stream": "message_token_fields",
- "event_types": [],
- "request_semantics": "Hermes local-agent documents may carry generic usage/tokens dictionaries per message.",
- "cumulative_semantics": "No provider cumulative session usage window is available.",
- "cache_semantics": "Generic cache_read/cache_write keys are preserved when present, but their provider semantics are not independently verified.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "antigravity-session",
- "provider": "antigravity",
- "status": "unsupported",
- "evidence_stream": "transcript_text_only",
- "event_types": [],
- "request_semantics": "No provider usage telemetry parser is implemented for this origin.",
- "cumulative_semantics": "No cumulative provider usage window is available.",
- "cache_semantics": "No cache read/write token lanes are available.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "unknown-export",
- "provider": "unknown",
- "status": "unsupported",
- "evidence_stream": "transcript_text_only",
- "event_types": [],
- "request_semantics": "Unknown exports are parsed for transcript content only.",
- "cumulative_semantics": "No cumulative provider usage window is available.",
- "cache_semantics": "No cache read/write token lanes are available.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- }
- ],
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 56256,
- "output_tokens": 10596,
- "cached_input_tokens": 280020,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388872
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 56256,
- "output_tokens": 10596,
- "cached_input_tokens": 280020,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388872
- },
- "pricing_catalog_provenance": "litellm-model-prices-vendored+polylogue-curated-overrides",
- "pricing_catalog_effective_date": "2026-06-27",
- "pricing_lanes": [
- {
- "provenance": "priced",
- "row_count": 1,
- "session_count": 1,
- "matched_model_row_count": 1,
- "unmatched_model_row_count": 0,
- "usage": {
- "input_tokens": 56000,
- "output_tokens": 10500,
- "cached_input_tokens": 280000,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388500
- },
- "stored_cost_usd": 2.835,
- "catalog_api_equivalent_usd": 2.835,
- "catalog_priced_subtotal_usd": 2.835,
- "subscription_credit_usd": 0.0,
- "grain": "physical_session",
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "exact_total_tokens_evidence": {
- "family": "usage.pricing_lane_exact_total_tokens",
- "fact_ref": "insight:session-model-usage:physical_session:priced:exact-total-tokens",
- "value_state": "known",
- "value": 388500,
- "measurement_authority": [
- "provider-reported"
- ],
- "weakest_measurement_authority": "provider-reported",
- "evidence_refs": [
- "insight:session-model-usage:physical_session:priced"
- ],
- "definition_ref": "insight:usage-lane-exact-total-tokens:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical_session session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "catalog_api_equivalent_evidence": {
- "family": "usage.pricing_lane_catalog_api_equivalent_cost",
- "fact_ref": "insight:session-model-usage:physical_session:priced:catalog-api-equivalent-cost",
- "value_state": "known",
- "value": 2.835,
- "measurement_authority": [
- "catalog-derived"
- ],
- "weakest_measurement_authority": "catalog-derived",
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:physical_session:priced"
- ],
- "definition_ref": "insight:usage-lane-catalog-api-equivalent-cost:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical_session session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "caveats": []
- },
- {
- "provenance": "unknown",
- "row_count": 5,
- "session_count": 5,
- "matched_model_row_count": 3,
- "unmatched_model_row_count": 2,
- "usage": {
- "input_tokens": 256,
- "output_tokens": 96,
- "cached_input_tokens": 20,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 372
- },
- "stored_cost_usd": 0.0,
- "catalog_api_equivalent_usd": null,
- "catalog_priced_subtotal_usd": 0.0,
- "subscription_credit_usd": 0.0,
- "grain": "physical_session",
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "exact_total_tokens_evidence": {
- "family": "usage.pricing_lane_exact_total_tokens",
- "fact_ref": "insight:session-model-usage:physical_session:unknown:exact-total-tokens",
- "value_state": "known",
- "value": 372,
- "measurement_authority": [
- "structural"
- ],
- "weakest_measurement_authority": "structural",
- "evidence_refs": [
- "insight:session-model-usage:physical_session:unknown"
- ],
- "definition_ref": "insight:usage-lane-exact-total-tokens:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical_session session_model_usage rows for 'unknown'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 5,
- "observed_count": 5,
- "supported_count": 5,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "catalog_api_equivalent_evidence": {
- "family": "usage.pricing_lane_catalog_api_equivalent_cost",
- "fact_ref": "insight:session-model-usage:physical_session:unknown:catalog-api-equivalent-cost",
- "value_state": "unknown",
- "value": null,
- "measurement_authority": [
- "catalog-derived"
- ],
- "weakest_measurement_authority": "catalog-derived",
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:physical_session:unknown"
- ],
- "definition_ref": "insight:usage-lane-catalog-api-equivalent-cost:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical_session session_model_usage rows for 'unknown'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 5,
- "observed_count": 5,
- "supported_count": 3,
- "complete": false,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": [
- {
- "subject_ref": "insight:session-model-usage:physical_session:unknown",
- "reason": "unpriced-model-rows:2"
- }
- ]
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "caveats": [
- "missing_price",
- "unpriced_cache_read_or_missing_price"
- ]
- }
- ],
- "pricing_grain": "physical_session",
- "logical_pricing_lanes": [
- {
- "provenance": "priced",
- "row_count": 1,
- "session_count": 1,
- "matched_model_row_count": 1,
- "unmatched_model_row_count": 0,
- "usage": {
- "input_tokens": 56000,
- "output_tokens": 10500,
- "cached_input_tokens": 280000,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388500
- },
- "stored_cost_usd": 0.0,
- "catalog_api_equivalent_usd": 2.835,
- "catalog_priced_subtotal_usd": 2.835,
- "subscription_credit_usd": 0.0,
- "grain": "logical_session_model_high_water",
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "exact_total_tokens_evidence": {
- "family": "usage.pricing_lane_exact_total_tokens",
- "fact_ref": "insight:session-model-usage:logical_session_model_high_water:priced:exact-total-tokens",
- "value_state": "known",
- "value": 388500,
- "measurement_authority": [
- "provider-reported"
- ],
- "weakest_measurement_authority": "provider-reported",
- "evidence_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced"
- ],
- "definition_ref": "insight:usage-lane-exact-total-tokens:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical_session_model_high_water session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "catalog_api_equivalent_evidence": {
- "family": "usage.pricing_lane_catalog_api_equivalent_cost",
- "fact_ref": "insight:session-model-usage:logical_session_model_high_water:priced:catalog-api-equivalent-cost",
- "value_state": "known",
- "value": 2.835,
- "measurement_authority": [
- "catalog-derived"
- ],
- "weakest_measurement_authority": "catalog-derived",
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:logical_session_model_high_water:priced"
- ],
- "definition_ref": "insight:usage-lane-catalog-api-equivalent-cost:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical_session_model_high_water session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "caveats": []
- },
- {
- "provenance": "unknown",
- "row_count": 5,
- "session_count": 5,
- "matched_model_row_count": 3,
- "unmatched_model_row_count": 2,
- "usage": {
- "input_tokens": 256,
- "output_tokens": 96,
- "cached_input_tokens": 20,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 372
- },
- "stored_cost_usd": 0.0,
- "catalog_api_equivalent_usd": null,
- "catalog_priced_subtotal_usd": 0.0,
- "subscription_credit_usd": 0.0,
- "grain": "logical_session_model_high_water",
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "exact_total_tokens_evidence": {
- "family": "usage.pricing_lane_exact_total_tokens",
- "fact_ref": "insight:session-model-usage:logical_session_model_high_water:unknown:exact-total-tokens",
- "value_state": "known",
- "value": 372,
- "measurement_authority": [
- "structural"
- ],
- "weakest_measurement_authority": "structural",
- "evidence_refs": [
- "insight:session-model-usage:logical_session_model_high_water:unknown"
- ],
- "definition_ref": "insight:usage-lane-exact-total-tokens:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical_session_model_high_water session_model_usage rows for 'unknown'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 5,
- "observed_count": 5,
- "supported_count": 5,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "catalog_api_equivalent_evidence": {
- "family": "usage.pricing_lane_catalog_api_equivalent_cost",
- "fact_ref": "insight:session-model-usage:logical_session_model_high_water:unknown:catalog-api-equivalent-cost",
- "value_state": "unknown",
- "value": null,
- "measurement_authority": [
- "catalog-derived"
- ],
- "weakest_measurement_authority": "catalog-derived",
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:logical_session_model_high_water:unknown"
- ],
- "definition_ref": "insight:usage-lane-catalog-api-equivalent-cost:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical_session_model_high_water session_model_usage rows for 'unknown'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 5,
- "observed_count": 5,
- "supported_count": 3,
- "complete": false,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": [
- {
- "subject_ref": "insight:session-model-usage:logical_session_model_high_water:unknown",
- "reason": "unpriced-model-rows:2"
- }
- ]
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "caveats": [
- "missing_price",
- "unpriced_cache_read_or_missing_price"
- ]
- }
- ],
- "logical_pricing_grain": "logical_session_model_high_water",
- "stored_provider_priced_usd": 2.835,
- "catalog_api_equivalent_usd": null,
- "catalog_priced_subtotal_usd": 2.835,
- "logical_catalog_api_equivalent_usd": null,
- "logical_catalog_priced_subtotal_usd": 2.835,
- "subscription_credit_catalog_provenance": "polylogue-curated-claude-code-subscription-v1",
- "subscription_credit_catalog_effective_date": "2026-05-07",
- "subscription_credit_usd": 0.0,
- "logical_subscription_credit_usd": 0.0,
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "exact_total_tokens_evidence": {
- "family": "usage.pricing_lane_exact_total_tokens",
- "fact_ref": "insight:provider-usage:physical-exact-total-tokens:total",
- "value_state": "known",
- "value": 388872,
- "measurement_authority": [
- "provider-reported",
- "structural"
- ],
- "weakest_measurement_authority": "structural",
- "evidence_refs": [
- "insight:session-model-usage:physical_session:priced",
- "insight:session-model-usage:physical_session:unknown"
- ],
- "definition_ref": "insight:usage-lane-exact-total-tokens:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical provider usage pricing lanes",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 2,
- "observed_count": 2,
- "supported_count": 2,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [
- "insight:session-model-usage:physical_session:priced:exact-total-tokens",
- "insight:session-model-usage:physical_session:unknown:exact-total-tokens"
- ],
- "observed_refs": [
- "insight:session-model-usage:physical_session:priced:exact-total-tokens",
- "insight:session-model-usage:physical_session:unknown:exact-total-tokens"
- ],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [
- {
- "fact_ref": "insight:session-model-usage:physical_session:priced:exact-total-tokens",
- "value_state": "known",
- "value": 388500,
- "measurement_authority": [
- "provider-reported"
- ],
- "evidence_refs": [
- "insight:session-model-usage:physical_session:priced"
- ],
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical_session session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- }
- },
- {
- "fact_ref": "insight:session-model-usage:physical_session:unknown:exact-total-tokens",
- "value_state": "known",
- "value": 372,
- "measurement_authority": [
- "structural"
- ],
- "evidence_refs": [
- "insight:session-model-usage:physical_session:unknown"
- ],
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical_session session_model_usage rows for 'unknown'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 5,
- "observed_count": 5,
- "supported_count": 5,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- }
- }
- ],
- "conflicts": []
- },
- "catalog_api_equivalent_evidence": {
- "family": "usage.pricing_lane_catalog_api_equivalent_cost",
- "fact_ref": "insight:provider-usage:physical-catalog-api-equivalent-cost:total",
- "value_state": "unknown",
- "value": null,
- "measurement_authority": [
- "catalog-derived"
- ],
- "weakest_measurement_authority": "catalog-derived",
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:physical_session:priced",
- "insight:session-model-usage:physical_session:unknown"
- ],
- "definition_ref": "insight:usage-lane-catalog-api-equivalent-cost:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical provider usage pricing lanes",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 2,
- "observed_count": 2,
- "supported_count": 1,
- "complete": false,
- "coverage_ratio": 1.0,
- "intended_refs": [
- "insight:session-model-usage:physical_session:priced:catalog-api-equivalent-cost",
- "insight:session-model-usage:physical_session:unknown:catalog-api-equivalent-cost"
- ],
- "observed_refs": [
- "insight:session-model-usage:physical_session:priced:catalog-api-equivalent-cost",
- "insight:session-model-usage:physical_session:unknown:catalog-api-equivalent-cost"
- ],
- "exclusions": [
- {
- "subject_ref": "insight:session-model-usage:physical_session:unknown",
- "reason": "unpriced-model-rows:2"
- },
- {
- "subject_ref": "insight:session-model-usage:physical_session:unknown:catalog-api-equivalent-cost",
- "reason": "contribution-coverage-incomplete"
- },
- {
- "subject_ref": "insight:session-model-usage:physical_session:unknown:catalog-api-equivalent-cost",
- "reason": "unsupported-contribution:unknown"
- }
- ]
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [
- {
- "fact_ref": "insight:session-model-usage:physical_session:priced:catalog-api-equivalent-cost",
- "value_state": "known",
- "value": 2.835,
- "measurement_authority": [
- "catalog-derived"
- ],
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:physical_session:priced"
- ],
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical_session session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- }
- },
- {
- "fact_ref": "insight:session-model-usage:physical_session:unknown:catalog-api-equivalent-cost",
- "value_state": "unknown",
- "value": null,
- "measurement_authority": [
- "catalog-derived"
- ],
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:physical_session:unknown"
- ],
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical_session session_model_usage rows for 'unknown'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 5,
- "observed_count": 5,
- "supported_count": 3,
- "complete": false,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": [
- {
- "subject_ref": "insight:session-model-usage:physical_session:unknown",
- "reason": "unpriced-model-rows:2"
- }
- ]
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- }
- }
- ],
- "conflicts": []
- },
- "logical_exact_total_tokens_evidence": {
- "family": "usage.pricing_lane_exact_total_tokens",
- "fact_ref": "insight:provider-usage:logical-exact-total-tokens:total",
- "value_state": "known",
- "value": 388872,
- "measurement_authority": [
- "provider-reported",
- "structural"
- ],
- "weakest_measurement_authority": "structural",
- "evidence_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced",
- "insight:session-model-usage:logical_session_model_high_water:unknown"
- ],
- "definition_ref": "insight:usage-lane-exact-total-tokens:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical provider usage pricing lanes",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 2,
- "observed_count": 2,
- "supported_count": 2,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced:exact-total-tokens",
- "insight:session-model-usage:logical_session_model_high_water:unknown:exact-total-tokens"
- ],
- "observed_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced:exact-total-tokens",
- "insight:session-model-usage:logical_session_model_high_water:unknown:exact-total-tokens"
- ],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [
- {
- "fact_ref": "insight:session-model-usage:logical_session_model_high_water:priced:exact-total-tokens",
- "value_state": "known",
- "value": 388500,
- "measurement_authority": [
- "provider-reported"
- ],
- "evidence_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced"
- ],
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical_session_model_high_water session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- }
- },
- {
- "fact_ref": "insight:session-model-usage:logical_session_model_high_water:unknown:exact-total-tokens",
- "value_state": "known",
- "value": 372,
- "measurement_authority": [
- "structural"
- ],
- "evidence_refs": [
- "insight:session-model-usage:logical_session_model_high_water:unknown"
- ],
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical_session_model_high_water session_model_usage rows for 'unknown'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 5,
- "observed_count": 5,
- "supported_count": 5,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- }
- }
- ],
- "conflicts": []
- },
- "logical_catalog_api_equivalent_evidence": {
- "family": "usage.pricing_lane_catalog_api_equivalent_cost",
- "fact_ref": "insight:provider-usage:logical-catalog-api-equivalent-cost:total",
- "value_state": "unknown",
- "value": null,
- "measurement_authority": [
- "catalog-derived"
- ],
- "weakest_measurement_authority": "catalog-derived",
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:logical_session_model_high_water:priced",
- "insight:session-model-usage:logical_session_model_high_water:unknown"
- ],
- "definition_ref": "insight:usage-lane-catalog-api-equivalent-cost:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical provider usage pricing lanes",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 2,
- "observed_count": 2,
- "supported_count": 1,
- "complete": false,
- "coverage_ratio": 1.0,
- "intended_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced:catalog-api-equivalent-cost",
- "insight:session-model-usage:logical_session_model_high_water:unknown:catalog-api-equivalent-cost"
- ],
- "observed_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced:catalog-api-equivalent-cost",
- "insight:session-model-usage:logical_session_model_high_water:unknown:catalog-api-equivalent-cost"
- ],
- "exclusions": [
- {
- "subject_ref": "insight:session-model-usage:logical_session_model_high_water:unknown",
- "reason": "unpriced-model-rows:2"
- },
- {
- "subject_ref": "insight:session-model-usage:logical_session_model_high_water:unknown:catalog-api-equivalent-cost",
- "reason": "contribution-coverage-incomplete"
- },
- {
- "subject_ref": "insight:session-model-usage:logical_session_model_high_water:unknown:catalog-api-equivalent-cost",
- "reason": "unsupported-contribution:unknown"
- }
- ]
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [
- {
- "fact_ref": "insight:session-model-usage:logical_session_model_high_water:priced:catalog-api-equivalent-cost",
- "value_state": "known",
- "value": 2.835,
- "measurement_authority": [
- "catalog-derived"
- ],
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:logical_session_model_high_water:priced"
- ],
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical_session_model_high_water session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- }
- },
- {
- "fact_ref": "insight:session-model-usage:logical_session_model_high_water:unknown:catalog-api-equivalent-cost",
- "value_state": "unknown",
- "value": null,
- "measurement_authority": [
- "catalog-derived"
- ],
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:logical_session_model_high_water:unknown"
- ],
- "temporal": {
- "observed_at": "2026-08-02T13:52:10.419644+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical_session_model_high_water session_model_usage rows for 'unknown'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 5,
- "observed_count": 5,
- "supported_count": 3,
- "complete": false,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": [
- {
- "subject_ref": "insight:session-model-usage:logical_session_model_high_water:unknown",
- "reason": "unpriced-model-rows:2"
- }
- ]
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:10.419644+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- }
- }
- ],
- "conflicts": []
- },
- "origins": [
- {
- "origin": "aistudio-drive",
- "detail_level": "headline",
- "provider": "gemini",
- "declared_coverage": "partial",
- "coverage_state": "headline_not_audited",
- "coverage_basis": "headline detail does not scan provider usage events or stale rollup diagnostics; model rollup totals are still computed from session_model_usage",
- "evidence_stream": "message_token_fields",
- "request_semantics": "AI Studio/Gemini exports may carry message-level tokenCount output counters on some records.",
- "cumulative_semantics": "No provider cumulative session usage window is available from Drive prompt exports.",
- "cache_semantics": "No cache read/write token lanes are available from Drive prompt exports.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 1,
- "message_count": 4,
- "transcript_word_count": 24,
- "raw_session_count": 1,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 0,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 0,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "provider usage telemetry is partial; request, cumulative, and cache semantics are incomplete"
- ]
- },
- {
- "origin": "antigravity-session",
- "detail_level": "headline",
- "provider": "antigravity",
- "declared_coverage": "unsupported",
- "coverage_state": "headline_not_audited",
- "coverage_basis": "headline detail does not scan provider usage events or stale rollup diagnostics; model rollup totals are still computed from session_model_usage",
- "evidence_stream": "transcript_text_only",
- "request_semantics": "No provider usage telemetry parser is implemented for this origin.",
- "cumulative_semantics": "No cumulative provider usage window is available.",
- "cache_semantics": "No cache read/write token lanes are available.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 1,
- "message_count": 2,
- "transcript_word_count": 29,
- "raw_session_count": 1,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 0,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 0,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "provider usage telemetry unsupported for this origin"
- ]
- },
- {
- "origin": "chatgpt-export",
- "detail_level": "headline",
- "provider": "chatgpt",
- "declared_coverage": "estimate_only",
- "coverage_state": "headline_not_audited",
- "coverage_basis": "headline detail does not scan provider usage events or stale rollup diagnostics; model rollup totals are still computed from session_model_usage",
- "evidence_stream": "transcript_text_estimate",
- "request_semantics": "ChatGPT exports do not carry reliable per-request token counters.",
- "cumulative_semantics": "Provider/account UI totals are external summaries and are not reconstructed from transcript text.",
- "cache_semantics": "No cache read/write token lanes are available in ChatGPT export rows.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 3,
- "message_count": 7,
- "transcript_word_count": 251,
- "raw_session_count": 5,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 2,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 0,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "exact provider telemetry unavailable; transcript text counts are estimate-only",
- "raw rows without parse errors are acquired but not materialized; usage coverage is incomplete until index.db is rebuilt"
- ]
- },
- {
- "origin": "claude-ai-export",
- "detail_level": "headline",
- "provider": "claude-ai",
- "declared_coverage": "estimate_only",
- "coverage_state": "headline_not_audited",
- "coverage_basis": "headline detail does not scan provider usage events or stale rollup diagnostics; model rollup totals are still computed from session_model_usage",
- "evidence_stream": "transcript_text_estimate",
- "request_semantics": "Claude.ai exports preserve transcript content, not provider usage counters.",
- "cumulative_semantics": "No cumulative provider usage window is present in the export shape.",
- "cache_semantics": "No cache read/write token lanes are available in Claude.ai export rows.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 1,
- "message_count": 2,
- "transcript_word_count": 17,
- "raw_session_count": 1,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 0,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 0,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "exact provider telemetry unavailable; transcript text counts are estimate-only"
- ]
- },
- {
- "origin": "claude-code-session",
- "detail_level": "headline",
- "provider": "claude-code",
- "declared_coverage": "exact",
- "coverage_state": "headline_not_audited",
- "coverage_basis": "headline detail does not scan provider usage events or stale rollup diagnostics; model rollup totals are still computed from session_model_usage",
- "evidence_stream": "provider_reported_usage",
- "request_semantics": "Claude Code message.usage rows are per message/request observations.",
- "cumulative_semantics": "Session rollups are derived by summing message usage rows; Claude Code does not supply a separate cumulative session high-water event.",
- "cache_semantics": "cache_read_input_tokens and cache_creation_input_tokens are preserved as cached_input and cache_write lanes and are not folded into generic input/output.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 4,
- "message_count": 19,
- "transcript_word_count": 398,
- "raw_session_count": 4,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 0,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 1,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 56000,
- "output_tokens": 10500,
- "cached_input_tokens": 280000,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388500
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 56000,
- "output_tokens": 10500,
- "cached_input_tokens": 280000,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388500
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "some sessions have no provider usage event rows; transcript words and model rollups cover different evidence"
- ]
- },
- {
- "origin": "codex-session",
- "detail_level": "headline",
- "provider": "codex",
- "declared_coverage": "exact",
- "coverage_state": "headline_not_audited",
- "coverage_basis": "headline detail does not scan provider usage events or stale rollup diagnostics; model rollup totals are still computed from session_model_usage",
- "evidence_stream": "provider_reported_usage",
- "request_semantics": "Codex last_token_usage is request/current-window telemetry and can be summed by request when present.",
- "cumulative_semantics": "Codex total_token_usage is cumulative and session-global; rollups take the latest total per session to avoid double-counting.",
- "cache_semantics": "cached_input_tokens and cache write/cache creation aliases are preserved as separate lanes and are not folded into generic input/output.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 7,
- "message_count": 30,
- "transcript_word_count": 229,
- "raw_session_count": 7,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 0,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 0,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "some sessions have no provider usage event rows; transcript words and model rollups cover different evidence"
- ]
- },
- {
- "origin": "gemini-cli-session",
- "detail_level": "headline",
- "provider": "gemini-cli",
- "declared_coverage": "partial",
- "coverage_state": "headline_not_audited",
- "coverage_basis": "headline detail does not scan provider usage events or stale rollup diagnostics; model rollup totals are still computed from session_model_usage",
- "evidence_stream": "message_token_fields",
- "request_semantics": "Local Gemini CLI documents may carry generic usage/tokens dictionaries per message.",
- "cumulative_semantics": "No provider cumulative session usage window is available.",
- "cache_semantics": "Generic cache_read/cache_write keys are preserved when present, but their provider semantics are not independently verified.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 1,
- "message_count": 2,
- "transcript_word_count": 33,
- "raw_session_count": 1,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 0,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 0,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 160,
- "output_tokens": 64,
- "cached_input_tokens": 20,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 244
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 160,
- "output_tokens": 64,
- "cached_input_tokens": 20,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 244
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "provider usage telemetry is partial; request, cumulative, and cache semantics are incomplete"
- ]
- },
- {
- "origin": "hermes-session",
- "detail_level": "headline",
- "provider": "hermes",
- "declared_coverage": "partial",
- "coverage_state": "headline_not_audited",
- "coverage_basis": "headline detail does not scan provider usage events or stale rollup diagnostics; model rollup totals are still computed from session_model_usage",
- "evidence_stream": "message_token_fields",
- "request_semantics": "Hermes local-agent documents may carry generic usage/tokens dictionaries per message.",
- "cumulative_semantics": "No provider cumulative session usage window is available.",
- "cache_semantics": "Generic cache_read/cache_write keys are preserved when present, but their provider semantics are not independently verified.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 1,
- "message_count": 5,
- "transcript_word_count": 39,
- "raw_session_count": 1,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 0,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 0,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 96,
- "output_tokens": 32,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 128
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 96,
- "output_tokens": 32,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 128
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "provider usage telemetry is partial; request, cumulative, and cache semantics are incomplete"
- ]
- }
- ],
- "caveats": [
- "provider usage events, transcript text volume, and model rollups are separate evidence streams",
- "this report does not query provider billing and is not a precise cost report",
- "headline detail computes session/source/model-rollup totals only; run with detail='full' for provider-event, cumulative, sample, and stale-rollup diagnostics",
- "catalog_api_equivalent_usd is unknown because at least one model row has no catalog price; catalog_priced_subtotal_usd preserves the known priced subset"
- ]
-}
diff --git a/.agent/demos/agent-forensics/current/usage-headline-claude-code.json b/.agent/demos/agent-forensics/current/usage-headline-claude-code.json
deleted file mode 100644
index 84e1a82465..0000000000
--- a/.agent/demos/agent-forensics/current/usage-headline-claude-code.json
+++ /dev/null
@@ -1,826 +0,0 @@
-{
- "archive_root": "/path/to/demo-archive",
- "detail_level": "headline",
- "coverage_matrix": [
- {
- "origin": "claude-code-session",
- "provider": "claude-code",
- "status": "exact",
- "evidence_stream": "provider_reported_usage",
- "event_types": [
- "message_usage"
- ],
- "request_semantics": "Claude Code message.usage rows are per message/request observations.",
- "cumulative_semantics": "Session rollups are derived by summing message usage rows; Claude Code does not supply a separate cumulative session high-water event.",
- "cache_semantics": "cache_read_input_tokens and cache_creation_input_tokens are preserved as cached_input and cache_write lanes and are not folded into generic input/output.",
- "notes": [
- "Exact token telemetry is available only where exported records include message.usage."
- ],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "codex-session",
- "provider": "codex",
- "status": "exact",
- "evidence_stream": "provider_reported_usage",
- "event_types": [
- "token_count"
- ],
- "request_semantics": "Codex last_token_usage is request/current-window telemetry and can be summed by request when present.",
- "cumulative_semantics": "Codex total_token_usage is cumulative and session-global; rollups take the latest total per session to avoid double-counting.",
- "cache_semantics": "cached_input_tokens and cache write/cache creation aliases are preserved as separate lanes and are not folded into generic input/output.",
- "notes": [
- "model_context_window is carried on token_count events when the provider supplies it."
- ],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "chatgpt-export",
- "provider": "chatgpt",
- "status": "estimate_only",
- "evidence_stream": "transcript_text_estimate",
- "event_types": [],
- "request_semantics": "ChatGPT exports do not carry reliable per-request token counters.",
- "cumulative_semantics": "Provider/account UI totals are external summaries and are not reconstructed from transcript text.",
- "cache_semantics": "No cache read/write token lanes are available in ChatGPT export rows.",
- "notes": [
- "Cost-looking metadata is not treated as exact token telemetry."
- ],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "claude-ai-export",
- "provider": "claude-ai",
- "status": "estimate_only",
- "evidence_stream": "transcript_text_estimate",
- "event_types": [],
- "request_semantics": "Claude.ai exports preserve transcript content, not provider usage counters.",
- "cumulative_semantics": "No cumulative provider usage window is present in the export shape.",
- "cache_semantics": "No cache read/write token lanes are available in Claude.ai export rows.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "aistudio-drive",
- "provider": "gemini",
- "status": "partial",
- "evidence_stream": "message_token_fields",
- "event_types": [],
- "request_semantics": "AI Studio/Gemini exports may carry message-level tokenCount output counters on some records.",
- "cumulative_semantics": "No provider cumulative session usage window is available from Drive prompt exports.",
- "cache_semantics": "No cache read/write token lanes are available from Drive prompt exports.",
- "notes": [
- "Input tokens and cache semantics are missing unless a future export shape supplies them explicitly."
- ],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "gemini-cli-session",
- "provider": "gemini-cli",
- "status": "partial",
- "evidence_stream": "message_token_fields",
- "event_types": [],
- "request_semantics": "Local Gemini CLI documents may carry generic usage/tokens dictionaries per message.",
- "cumulative_semantics": "No provider cumulative session usage window is available.",
- "cache_semantics": "Generic cache_read/cache_write keys are preserved when present, but their provider semantics are not independently verified.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "hermes-session",
- "provider": "hermes",
- "status": "partial",
- "evidence_stream": "message_token_fields",
- "event_types": [],
- "request_semantics": "Hermes local-agent documents may carry generic usage/tokens dictionaries per message.",
- "cumulative_semantics": "No provider cumulative session usage window is available.",
- "cache_semantics": "Generic cache_read/cache_write keys are preserved when present, but their provider semantics are not independently verified.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "antigravity-session",
- "provider": "antigravity",
- "status": "unsupported",
- "evidence_stream": "transcript_text_only",
- "event_types": [],
- "request_semantics": "No provider usage telemetry parser is implemented for this origin.",
- "cumulative_semantics": "No cumulative provider usage window is available.",
- "cache_semantics": "No cache read/write token lanes are available.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "unknown-export",
- "provider": "unknown",
- "status": "unsupported",
- "evidence_stream": "transcript_text_only",
- "event_types": [],
- "request_semantics": "Unknown exports are parsed for transcript content only.",
- "cumulative_semantics": "No cumulative provider usage window is available.",
- "cache_semantics": "No cache read/write token lanes are available.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- }
- ],
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 56000,
- "output_tokens": 10500,
- "cached_input_tokens": 280000,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388500
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 56000,
- "output_tokens": 10500,
- "cached_input_tokens": 280000,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388500
- },
- "pricing_catalog_provenance": "litellm-model-prices-vendored+polylogue-curated-overrides",
- "pricing_catalog_effective_date": "2026-06-27",
- "pricing_lanes": [
- {
- "provenance": "priced",
- "row_count": 1,
- "session_count": 1,
- "matched_model_row_count": 1,
- "unmatched_model_row_count": 0,
- "usage": {
- "input_tokens": 56000,
- "output_tokens": 10500,
- "cached_input_tokens": 280000,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388500
- },
- "stored_cost_usd": 2.835,
- "catalog_api_equivalent_usd": 2.835,
- "catalog_priced_subtotal_usd": 2.835,
- "subscription_credit_usd": 0.0,
- "grain": "physical_session",
- "observed_at": "2026-08-02T13:52:20.867273+00:00",
- "exact_total_tokens_evidence": {
- "family": "usage.pricing_lane_exact_total_tokens",
- "fact_ref": "insight:session-model-usage:physical_session:priced:exact-total-tokens",
- "value_state": "known",
- "value": 388500,
- "measurement_authority": [
- "provider-reported"
- ],
- "weakest_measurement_authority": "provider-reported",
- "evidence_refs": [
- "insight:session-model-usage:physical_session:priced"
- ],
- "definition_ref": "insight:usage-lane-exact-total-tokens:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:20.867273+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical_session session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:20.867273+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "catalog_api_equivalent_evidence": {
- "family": "usage.pricing_lane_catalog_api_equivalent_cost",
- "fact_ref": "insight:session-model-usage:physical_session:priced:catalog-api-equivalent-cost",
- "value_state": "known",
- "value": 2.835,
- "measurement_authority": [
- "catalog-derived"
- ],
- "weakest_measurement_authority": "catalog-derived",
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:physical_session:priced"
- ],
- "definition_ref": "insight:usage-lane-catalog-api-equivalent-cost:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:20.867273+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical_session session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:20.867273+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "caveats": []
- }
- ],
- "pricing_grain": "physical_session",
- "logical_pricing_lanes": [
- {
- "provenance": "priced",
- "row_count": 1,
- "session_count": 1,
- "matched_model_row_count": 1,
- "unmatched_model_row_count": 0,
- "usage": {
- "input_tokens": 56000,
- "output_tokens": 10500,
- "cached_input_tokens": 280000,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388500
- },
- "stored_cost_usd": 0.0,
- "catalog_api_equivalent_usd": 2.835,
- "catalog_priced_subtotal_usd": 2.835,
- "subscription_credit_usd": 0.0,
- "grain": "logical_session_model_high_water",
- "observed_at": "2026-08-02T13:52:20.867273+00:00",
- "exact_total_tokens_evidence": {
- "family": "usage.pricing_lane_exact_total_tokens",
- "fact_ref": "insight:session-model-usage:logical_session_model_high_water:priced:exact-total-tokens",
- "value_state": "known",
- "value": 388500,
- "measurement_authority": [
- "provider-reported"
- ],
- "weakest_measurement_authority": "provider-reported",
- "evidence_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced"
- ],
- "definition_ref": "insight:usage-lane-exact-total-tokens:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:20.867273+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical_session_model_high_water session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:20.867273+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "catalog_api_equivalent_evidence": {
- "family": "usage.pricing_lane_catalog_api_equivalent_cost",
- "fact_ref": "insight:session-model-usage:logical_session_model_high_water:priced:catalog-api-equivalent-cost",
- "value_state": "known",
- "value": 2.835,
- "measurement_authority": [
- "catalog-derived"
- ],
- "weakest_measurement_authority": "catalog-derived",
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:logical_session_model_high_water:priced"
- ],
- "definition_ref": "insight:usage-lane-catalog-api-equivalent-cost:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:20.867273+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical_session_model_high_water session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:20.867273+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "caveats": []
- }
- ],
- "logical_pricing_grain": "logical_session_model_high_water",
- "stored_provider_priced_usd": 2.835,
- "catalog_api_equivalent_usd": 2.835,
- "catalog_priced_subtotal_usd": 2.835,
- "logical_catalog_api_equivalent_usd": 2.835,
- "logical_catalog_priced_subtotal_usd": 2.835,
- "subscription_credit_catalog_provenance": "polylogue-curated-claude-code-subscription-v1",
- "subscription_credit_catalog_effective_date": "2026-05-07",
- "subscription_credit_usd": 0.0,
- "logical_subscription_credit_usd": 0.0,
- "observed_at": "2026-08-02T13:52:20.867273+00:00",
- "exact_total_tokens_evidence": {
- "family": "usage.pricing_lane_exact_total_tokens",
- "fact_ref": "insight:provider-usage:physical-exact-total-tokens:total",
- "value_state": "known",
- "value": 388500,
- "measurement_authority": [
- "provider-reported"
- ],
- "weakest_measurement_authority": "provider-reported",
- "evidence_refs": [
- "insight:session-model-usage:physical_session:priced"
- ],
- "definition_ref": "insight:usage-lane-exact-total-tokens:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:20.867273+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical provider usage pricing lanes",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [
- "insight:session-model-usage:physical_session:priced:exact-total-tokens"
- ],
- "observed_refs": [
- "insight:session-model-usage:physical_session:priced:exact-total-tokens"
- ],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:20.867273+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [
- {
- "fact_ref": "insight:session-model-usage:physical_session:priced:exact-total-tokens",
- "value_state": "known",
- "value": 388500,
- "measurement_authority": [
- "provider-reported"
- ],
- "evidence_refs": [
- "insight:session-model-usage:physical_session:priced"
- ],
- "temporal": {
- "observed_at": "2026-08-02T13:52:20.867273+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical_session session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:20.867273+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- }
- }
- ],
- "conflicts": []
- },
- "catalog_api_equivalent_evidence": {
- "family": "usage.pricing_lane_catalog_api_equivalent_cost",
- "fact_ref": "insight:provider-usage:physical-catalog-api-equivalent-cost:total",
- "value_state": "known",
- "value": 2.835,
- "measurement_authority": [
- "catalog-derived"
- ],
- "weakest_measurement_authority": "catalog-derived",
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:physical_session:priced"
- ],
- "definition_ref": "insight:usage-lane-catalog-api-equivalent-cost:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:20.867273+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical provider usage pricing lanes",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [
- "insight:session-model-usage:physical_session:priced:catalog-api-equivalent-cost"
- ],
- "observed_refs": [
- "insight:session-model-usage:physical_session:priced:catalog-api-equivalent-cost"
- ],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:20.867273+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [
- {
- "fact_ref": "insight:session-model-usage:physical_session:priced:catalog-api-equivalent-cost",
- "value_state": "known",
- "value": 2.835,
- "measurement_authority": [
- "catalog-derived"
- ],
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:physical_session:priced"
- ],
- "temporal": {
- "observed_at": "2026-08-02T13:52:20.867273+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical_session session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:20.867273+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- }
- }
- ],
- "conflicts": []
- },
- "logical_exact_total_tokens_evidence": {
- "family": "usage.pricing_lane_exact_total_tokens",
- "fact_ref": "insight:provider-usage:logical-exact-total-tokens:total",
- "value_state": "known",
- "value": 388500,
- "measurement_authority": [
- "provider-reported"
- ],
- "weakest_measurement_authority": "provider-reported",
- "evidence_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced"
- ],
- "definition_ref": "insight:usage-lane-exact-total-tokens:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:20.867273+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical provider usage pricing lanes",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced:exact-total-tokens"
- ],
- "observed_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced:exact-total-tokens"
- ],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:20.867273+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [
- {
- "fact_ref": "insight:session-model-usage:logical_session_model_high_water:priced:exact-total-tokens",
- "value_state": "known",
- "value": 388500,
- "measurement_authority": [
- "provider-reported"
- ],
- "evidence_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced"
- ],
- "temporal": {
- "observed_at": "2026-08-02T13:52:20.867273+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical_session_model_high_water session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:20.867273+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- }
- }
- ],
- "conflicts": []
- },
- "logical_catalog_api_equivalent_evidence": {
- "family": "usage.pricing_lane_catalog_api_equivalent_cost",
- "fact_ref": "insight:provider-usage:logical-catalog-api-equivalent-cost:total",
- "value_state": "known",
- "value": 2.835,
- "measurement_authority": [
- "catalog-derived"
- ],
- "weakest_measurement_authority": "catalog-derived",
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:logical_session_model_high_water:priced"
- ],
- "definition_ref": "insight:usage-lane-catalog-api-equivalent-cost:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:20.867273+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical provider usage pricing lanes",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced:catalog-api-equivalent-cost"
- ],
- "observed_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced:catalog-api-equivalent-cost"
- ],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:20.867273+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [
- {
- "fact_ref": "insight:session-model-usage:logical_session_model_high_water:priced:catalog-api-equivalent-cost",
- "value_state": "known",
- "value": 2.835,
- "measurement_authority": [
- "catalog-derived"
- ],
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:logical_session_model_high_water:priced"
- ],
- "temporal": {
- "observed_at": "2026-08-02T13:52:20.867273+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical_session_model_high_water session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-08-02T13:52:20.867273+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- }
- }
- ],
- "conflicts": []
- },
- "origins": [
- {
- "origin": "claude-code-session",
- "detail_level": "headline",
- "provider": "claude-code",
- "declared_coverage": "exact",
- "coverage_state": "headline_not_audited",
- "coverage_basis": "headline detail does not scan provider usage events or stale rollup diagnostics; model rollup totals are still computed from session_model_usage",
- "evidence_stream": "provider_reported_usage",
- "request_semantics": "Claude Code message.usage rows are per message/request observations.",
- "cumulative_semantics": "Session rollups are derived by summing message usage rows; Claude Code does not supply a separate cumulative session high-water event.",
- "cache_semantics": "cache_read_input_tokens and cache_creation_input_tokens are preserved as cached_input and cache_write lanes and are not folded into generic input/output.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 4,
- "message_count": 19,
- "transcript_word_count": 398,
- "raw_session_count": 4,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 0,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 1,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 56000,
- "output_tokens": 10500,
- "cached_input_tokens": 280000,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388500
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 56000,
- "output_tokens": 10500,
- "cached_input_tokens": 280000,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388500
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "some sessions have no provider usage event rows; transcript words and model rollups cover different evidence"
- ]
- }
- ],
- "caveats": [
- "provider usage events, transcript text volume, and model rollups are separate evidence streams",
- "this report does not query provider billing and is not a precise cost report",
- "headline detail computes session/source/model-rollup totals only; run with detail='full' for provider-event, cumulative, sample, and stale-rollup diagnostics"
- ]
-}
diff --git a/.agent/demos/agent-forensics/current/usage-headline-codex.json b/.agent/demos/agent-forensics/current/usage-headline-codex.json
deleted file mode 100644
index b1cebd6fae..0000000000
--- a/.agent/demos/agent-forensics/current/usage-headline-codex.json
+++ /dev/null
@@ -1,402 +0,0 @@
-{
- "archive_root": "/path/to/demo-archive",
- "detail_level": "headline",
- "coverage_matrix": [
- {
- "origin": "claude-code-session",
- "provider": "claude-code",
- "status": "exact",
- "evidence_stream": "provider_reported_usage",
- "event_types": [
- "message_usage"
- ],
- "request_semantics": "Claude Code message.usage rows are per message/request observations.",
- "cumulative_semantics": "Session rollups are derived by summing message usage rows; Claude Code does not supply a separate cumulative session high-water event.",
- "cache_semantics": "cache_read_input_tokens and cache_creation_input_tokens are preserved as cached_input and cache_write lanes and are not folded into generic input/output.",
- "notes": [
- "Exact token telemetry is available only where exported records include message.usage."
- ],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "codex-session",
- "provider": "codex",
- "status": "exact",
- "evidence_stream": "provider_reported_usage",
- "event_types": [
- "token_count"
- ],
- "request_semantics": "Codex last_token_usage is request/current-window telemetry and can be summed by request when present.",
- "cumulative_semantics": "Codex total_token_usage is cumulative and session-global; rollups take the latest total per session to avoid double-counting.",
- "cache_semantics": "cached_input_tokens and cache write/cache creation aliases are preserved as separate lanes and are not folded into generic input/output.",
- "notes": [
- "model_context_window is carried on token_count events when the provider supplies it."
- ],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "chatgpt-export",
- "provider": "chatgpt",
- "status": "estimate_only",
- "evidence_stream": "transcript_text_estimate",
- "event_types": [],
- "request_semantics": "ChatGPT exports do not carry reliable per-request token counters.",
- "cumulative_semantics": "Provider/account UI totals are external summaries and are not reconstructed from transcript text.",
- "cache_semantics": "No cache read/write token lanes are available in ChatGPT export rows.",
- "notes": [
- "Cost-looking metadata is not treated as exact token telemetry."
- ],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "claude-ai-export",
- "provider": "claude-ai",
- "status": "estimate_only",
- "evidence_stream": "transcript_text_estimate",
- "event_types": [],
- "request_semantics": "Claude.ai exports preserve transcript content, not provider usage counters.",
- "cumulative_semantics": "No cumulative provider usage window is present in the export shape.",
- "cache_semantics": "No cache read/write token lanes are available in Claude.ai export rows.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "aistudio-drive",
- "provider": "gemini",
- "status": "partial",
- "evidence_stream": "message_token_fields",
- "event_types": [],
- "request_semantics": "AI Studio/Gemini exports may carry message-level tokenCount output counters on some records.",
- "cumulative_semantics": "No provider cumulative session usage window is available from Drive prompt exports.",
- "cache_semantics": "No cache read/write token lanes are available from Drive prompt exports.",
- "notes": [
- "Input tokens and cache semantics are missing unless a future export shape supplies them explicitly."
- ],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "gemini-cli-session",
- "provider": "gemini-cli",
- "status": "partial",
- "evidence_stream": "message_token_fields",
- "event_types": [],
- "request_semantics": "Local Gemini CLI documents may carry generic usage/tokens dictionaries per message.",
- "cumulative_semantics": "No provider cumulative session usage window is available.",
- "cache_semantics": "Generic cache_read/cache_write keys are preserved when present, but their provider semantics are not independently verified.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "hermes-session",
- "provider": "hermes",
- "status": "partial",
- "evidence_stream": "message_token_fields",
- "event_types": [],
- "request_semantics": "Hermes local-agent documents may carry generic usage/tokens dictionaries per message.",
- "cumulative_semantics": "No provider cumulative session usage window is available.",
- "cache_semantics": "Generic cache_read/cache_write keys are preserved when present, but their provider semantics are not independently verified.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "antigravity-session",
- "provider": "antigravity",
- "status": "unsupported",
- "evidence_stream": "transcript_text_only",
- "event_types": [],
- "request_semantics": "No provider usage telemetry parser is implemented for this origin.",
- "cumulative_semantics": "No cumulative provider usage window is available.",
- "cache_semantics": "No cache read/write token lanes are available.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "unknown-export",
- "provider": "unknown",
- "status": "unsupported",
- "evidence_stream": "transcript_text_only",
- "event_types": [],
- "request_semantics": "Unknown exports are parsed for transcript content only.",
- "cumulative_semantics": "No cumulative provider usage window is available.",
- "cache_semantics": "No cache read/write token lanes are available.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- }
- ],
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "pricing_catalog_provenance": "litellm-model-prices-vendored+polylogue-curated-overrides",
- "pricing_catalog_effective_date": "2026-06-27",
- "pricing_lanes": [],
- "pricing_grain": "physical_session",
- "logical_pricing_lanes": [],
- "logical_pricing_grain": "logical_session_model_high_water",
- "stored_provider_priced_usd": 0,
- "catalog_api_equivalent_usd": null,
- "catalog_priced_subtotal_usd": 0,
- "logical_catalog_api_equivalent_usd": null,
- "logical_catalog_priced_subtotal_usd": 0,
- "subscription_credit_catalog_provenance": "polylogue-curated-claude-code-subscription-v1",
- "subscription_credit_catalog_effective_date": "2026-05-07",
- "subscription_credit_usd": 0,
- "logical_subscription_credit_usd": 0,
- "observed_at": "2026-08-02T13:52:31.038402+00:00",
- "exact_total_tokens_evidence": {
- "family": "usage.pricing_lane_exact_total_tokens",
- "fact_ref": "insight:provider-usage:physical-exact-total-tokens:total",
- "value_state": "unknown",
- "value": null,
- "measurement_authority": [],
- "weakest_measurement_authority": null,
- "evidence_refs": [],
- "definition_ref": "insight:usage-lane-exact-total-tokens:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:31.038402+00:00",
- "time_source": null,
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "inferred-partial",
- "coverage": {
- "intended_frame": "physical provider usage pricing lanes",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 0,
- "observed_count": 0,
- "supported_count": 0,
- "complete": false,
- "coverage_ratio": null,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "unavailable",
- "evaluated_at": "2026-08-02T13:52:31.038402+00:00",
- "cause": "no-freshness-evidence",
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "catalog_api_equivalent_evidence": {
- "family": "usage.pricing_lane_catalog_api_equivalent_cost",
- "fact_ref": "insight:provider-usage:physical-catalog-api-equivalent-cost:total",
- "value_state": "unknown",
- "value": null,
- "measurement_authority": [],
- "weakest_measurement_authority": null,
- "evidence_refs": [],
- "definition_ref": "insight:usage-lane-catalog-api-equivalent-cost:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:31.038402+00:00",
- "time_source": null,
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "inferred-partial",
- "coverage": {
- "intended_frame": "physical provider usage pricing lanes",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 0,
- "observed_count": 0,
- "supported_count": 0,
- "complete": false,
- "coverage_ratio": null,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "unavailable",
- "evaluated_at": "2026-08-02T13:52:31.038402+00:00",
- "cause": "no-freshness-evidence",
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "logical_exact_total_tokens_evidence": {
- "family": "usage.pricing_lane_exact_total_tokens",
- "fact_ref": "insight:provider-usage:logical-exact-total-tokens:total",
- "value_state": "unknown",
- "value": null,
- "measurement_authority": [],
- "weakest_measurement_authority": null,
- "evidence_refs": [],
- "definition_ref": "insight:usage-lane-exact-total-tokens:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:31.038402+00:00",
- "time_source": null,
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "inferred-partial",
- "coverage": {
- "intended_frame": "logical provider usage pricing lanes",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 0,
- "observed_count": 0,
- "supported_count": 0,
- "complete": false,
- "coverage_ratio": null,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "unavailable",
- "evaluated_at": "2026-08-02T13:52:31.038402+00:00",
- "cause": "no-freshness-evidence",
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "logical_catalog_api_equivalent_evidence": {
- "family": "usage.pricing_lane_catalog_api_equivalent_cost",
- "fact_ref": "insight:provider-usage:logical-catalog-api-equivalent-cost:total",
- "value_state": "unknown",
- "value": null,
- "measurement_authority": [],
- "weakest_measurement_authority": null,
- "evidence_refs": [],
- "definition_ref": "insight:usage-lane-catalog-api-equivalent-cost:v1",
- "temporal": {
- "observed_at": "2026-08-02T13:52:31.038402+00:00",
- "time_source": null,
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "inferred-partial",
- "coverage": {
- "intended_frame": "logical provider usage pricing lanes",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 0,
- "observed_count": 0,
- "supported_count": 0,
- "complete": false,
- "coverage_ratio": null,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "unavailable",
- "evaluated_at": "2026-08-02T13:52:31.038402+00:00",
- "cause": "no-freshness-evidence",
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "origins": [
- {
- "origin": "codex-session",
- "detail_level": "headline",
- "provider": "codex",
- "declared_coverage": "exact",
- "coverage_state": "headline_not_audited",
- "coverage_basis": "headline detail does not scan provider usage events or stale rollup diagnostics; model rollup totals are still computed from session_model_usage",
- "evidence_stream": "provider_reported_usage",
- "request_semantics": "Codex last_token_usage is request/current-window telemetry and can be summed by request when present.",
- "cumulative_semantics": "Codex total_token_usage is cumulative and session-global; rollups take the latest total per session to avoid double-counting.",
- "cache_semantics": "cached_input_tokens and cache write/cache creation aliases are preserved as separate lanes and are not folded into generic input/output.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 7,
- "message_count": 30,
- "transcript_word_count": 229,
- "raw_session_count": 7,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 0,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 0,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "some sessions have no provider usage event rows; transcript words and model rollups cover different evidence"
- ]
- }
- ],
- "caveats": [
- "provider usage events, transcript text volume, and model rollups are separate evidence streams",
- "this report does not query provider billing and is not a precise cost report",
- "headline detail computes session/source/model-rollup totals only; run with detail='full' for provider-event, cumulative, sample, and stale-rollup diagnostics"
- ]
-}
diff --git a/.agent/demos/agent-forensics/current/usage-timeline-month-origin-model.json b/.agent/demos/agent-forensics/current/usage-timeline-month-origin-model.json
deleted file mode 100644
index 99fa7e0c9f..0000000000
--- a/.agent/demos/agent-forensics/current/usage-timeline-month-origin-model.json
+++ /dev/null
@@ -1,178 +0,0 @@
-{
- "status": "ok",
- "result": {
- "total": 5,
- "usage_timeline": [
- {
- "contract_version": 10,
- "insight_kind": "usage_timeline",
- "semantic_tier": "evidence",
- "group_by": "month-origin-model",
- "bucket": "2024-02",
- "origin": "aistudio-drive",
- "model_name": "models/gemini-2.5-pro models/gemini",
- "normalized_model": "gemini-2.5-pro",
- "session_count": 1,
- "event_count": 0,
- "usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cache_read_tokens": 0,
- "cache_write_tokens": 0,
- "total_tokens": 0
- },
- "reasoning_output_tokens": 0,
- "stored_cost_usd": 0.0,
- "subscription_credits": 0.0,
- "cost_provenance_counts": {
- "unknown": 1
- },
- "provenance": {
- "materializer_version": 0,
- "materialized_at": "2026-08-02T13:52:52.183374+00:00",
- "source_updated_at": null,
- "source_sort_key": 1706934756990.0,
- "input_high_water_mark": null,
- "input_high_water_mark_source": null,
- "time_confidence": "unknown"
- }
- },
- {
- "contract_version": 10,
- "insight_kind": "usage_timeline",
- "semantic_tier": "evidence",
- "group_by": "month-origin-model",
- "bucket": "2024-11",
- "origin": "claude-code-session",
- "model_name": "claude-opus-4-8",
- "normalized_model": "claude-opus-4-8",
- "session_count": 1,
- "event_count": 0,
- "usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cache_read_tokens": 0,
- "cache_write_tokens": 0,
- "total_tokens": 0
- },
- "reasoning_output_tokens": 0,
- "stored_cost_usd": 2.835,
- "subscription_credits": 0.0,
- "cost_provenance_counts": {
- "priced": 1
- },
- "provenance": {
- "materializer_version": 0,
- "materialized_at": "2026-08-02T13:52:52.183374+00:00",
- "source_updated_at": null,
- "source_sort_key": 1730589655737.0,
- "input_high_water_mark": null,
- "input_high_water_mark_source": null,
- "time_confidence": "unknown"
- }
- },
- {
- "contract_version": 10,
- "insight_kind": "usage_timeline",
- "semantic_tier": "evidence",
- "group_by": "month-origin-model",
- "bucket": "2026-07",
- "origin": "chatgpt-export",
- "model_name": "gpt-5-demo",
- "normalized_model": "gpt-5",
- "session_count": 2,
- "event_count": 0,
- "usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cache_read_tokens": 0,
- "cache_write_tokens": 0,
- "total_tokens": 0
- },
- "reasoning_output_tokens": 0,
- "stored_cost_usd": 0.0,
- "subscription_credits": 0.0,
- "cost_provenance_counts": {
- "unknown": 2
- },
- "provenance": {
- "materializer_version": 0,
- "materialized_at": "2026-08-02T13:52:52.183374+00:00",
- "source_updated_at": null,
- "source_sort_key": 1783158903000.0,
- "input_high_water_mark": null,
- "input_high_water_mark_source": null,
- "time_confidence": "unknown"
- }
- },
- {
- "contract_version": 10,
- "insight_kind": "usage_timeline",
- "semantic_tier": "evidence",
- "group_by": "month-origin-model",
- "bucket": "2026-07",
- "origin": "gemini-cli-session",
- "model_name": "gemini-2.5-demo",
- "normalized_model": "gemini-2.5-demo",
- "session_count": 1,
- "event_count": 1,
- "usage": {
- "input_tokens": 160,
- "output_tokens": 64,
- "cache_read_tokens": 20,
- "cache_write_tokens": 0,
- "total_tokens": 0
- },
- "reasoning_output_tokens": 0,
- "stored_cost_usd": 0.0,
- "subscription_credits": 0.0,
- "cost_provenance_counts": {
- "unknown": 1
- },
- "provenance": {
- "materializer_version": 0,
- "materialized_at": "2026-08-02T13:52:52.183374+00:00",
- "source_updated_at": null,
- "source_sort_key": 1783159084000.0,
- "input_high_water_mark": null,
- "input_high_water_mark_source": null,
- "time_confidence": "unknown"
- }
- },
- {
- "contract_version": 10,
- "insight_kind": "usage_timeline",
- "semantic_tier": "evidence",
- "group_by": "month-origin-model",
- "bucket": "2026-07",
- "origin": "hermes-session",
- "model_name": "nous-hermes-demo",
- "normalized_model": "nous-hermes-demo",
- "session_count": 1,
- "event_count": 0,
- "usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cache_read_tokens": 0,
- "cache_write_tokens": 0,
- "total_tokens": 0
- },
- "reasoning_output_tokens": 0,
- "stored_cost_usd": 0.0,
- "subscription_credits": 0.0,
- "cost_provenance_counts": {
- "unknown": 1
- },
- "provenance": {
- "materializer_version": 0,
- "materialized_at": "2026-08-02T13:52:52.183374+00:00",
- "source_updated_at": null,
- "source_sort_key": 1783159204000.0,
- "input_high_water_mark": null,
- "input_high_water_mark_source": null,
- "time_confidence": "unknown"
- }
- }
- ]
- }
-}
diff --git a/.agent/demos/anti-demo-multi-source-reconstruction/NON-CLAIMS.md b/.agent/demos/anti-demo-multi-source-reconstruction/NON-CLAIMS.md
deleted file mode 100644
index 90c76d940d..0000000000
--- a/.agent/demos/anti-demo-multi-source-reconstruction/NON-CLAIMS.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# Non-claims
-
-- This refusal does not claim that cross-source reconstruction is impossible in a federated Sinex-backed architecture.
-- This packet does not measure production source coverage or the quality of any external activity system.
diff --git a/.agent/demos/anti-demo-multi-source-reconstruction/PROMPT.md b/.agent/demos/anti-demo-multi-source-reconstruction/PROMPT.md
deleted file mode 100644
index 61bab51810..0000000000
--- a/.agent/demos/anti-demo-multi-source-reconstruction/PROMPT.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# The Honesty Anti-Demo: Minute-by-Minute Multi-Source Reconstruction
-
-Predeclaration receipt: `artifact:anti-demo-multi-source-reconstruction-predeclaration`.
-
-This demo's success is refusal. Attempt the tempting claim below against the
-archive; the correct outcome is a `checks.json` with `verdict:
-"not_supported"`, naming every missing modality/ref and the bead that would
-supply it (or stating honestly that no such bead exists yet).
-
-## The tempting claim
-
-"Reconstruct exactly what the operator was doing, minute-by-minute, on a
-given day — correlating AI chat sessions with desktop window focus, shell
-commands typed outside any captured agent session, and browser tabs viewed —
-into one fused timeline."
-
-## Why this is tempting
-
-Polylogue already answers adjacent, real questions from the same archive:
-per-session git commit correlation (`session_commits`, confidence-scored),
-per-repo session grouping (`session_repos`), and within-session tool-call
-timing. It would be easy to imply these compose into a full desktop
-timeline. They do not, and the gap is structural, not a missing query.
-
-## What to check before claiming success
-
-1. Query `session_commits`/`session_repos` for the day in question — confirm
- what granularity they actually offer (session-to-repo/commit linkage,
- not minute-level desktop activity).
-2. Search the archive schema for any table holding desktop window-focus,
- raw shell history, or browser-tab telemetry — confirm none exists in
- Polylogue's own tiers (source/index/embeddings/user/ops).
-3. Do not substitute a different, easier claim and declare success; do not
- quietly narrow the claim's wording after failing to support it. Report
- the exact gap.
diff --git a/.agent/demos/anti-demo-multi-source-reconstruction/checks.json b/.agent/demos/anti-demo-multi-source-reconstruction/checks.json
deleted file mode 100644
index a2e455dac2..0000000000
--- a/.agent/demos/anti-demo-multi-source-reconstruction/checks.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "pass": true,
- "verdict": "not_supported",
- "unsupported_claims": [
- "minute-by-minute cross-source (chat + desktop window focus + shell history + browser tabs) reconstruction of operator activity for a given day"
- ],
- "coverage_notes": "pass=true means the refusal itself is correctly evidenced (schema-grep confirms no window-focus/shell-history/browser-tab table exists in any Polylogue tier), not that the analytical claim succeeded. No bead currently owns cross-system (Polylogue+Lynchpin) timeline fusion -- stated plainly rather than citing an invented or loosely-related bead ref."
-}
diff --git a/.agent/demos/anti-demo-multi-source-reconstruction/evidence.ndjson b/.agent/demos/anti-demo-multi-source-reconstruction/evidence.ndjson
deleted file mode 100644
index 7fea6f7ea5..0000000000
--- a/.agent/demos/anti-demo-multi-source-reconstruction/evidence.ndjson
+++ /dev/null
@@ -1,4 +0,0 @@
-{"ref": "artifact:anti-demo-multi-source-reconstruction-evidence", "cited_for": "Demo Packet v2 receipt root", "verified_via": "committed evidence.ndjson"}
-{"ref": "polylogue/storage/sqlite/archive_tiers/index.py:517", "cited_for": "session_commits table exists: session-grained git correlation, confidence-scored, not minute-level", "verified_via": "grep -n 'CREATE TABLE IF NOT EXISTS session_commits' -A 10 polylogue/storage/sqlite/archive_tiers/index.py"}
-{"ref": "polylogue/storage/sqlite/archive_tiers/index.py:506", "cited_for": "session_repos table exists: session-to-repo/branch linkage, not minute-level", "verified_via": "grep -n 'CREATE TABLE IF NOT EXISTS session_repos' polylogue/storage/sqlite/archive_tiers/index.py"}
-{"ref": "polylogue/storage/sqlite/archive_tiers/*.py", "cited_for": "no window-focus/shell-history/browser-tab telemetry table exists in any Polylogue tier", "verified_via": "grep -rln 'window_focus|shell_history|browser_tab|activitywatch' polylogue/storage/sqlite/archive_tiers/*.py (zero matches)"}
diff --git a/.agent/demos/anti-demo-multi-source-reconstruction/finding.yaml b/.agent/demos/anti-demo-multi-source-reconstruction/finding.yaml
deleted file mode 100644
index 11a59be224..0000000000
--- a/.agent/demos/anti-demo-multi-source-reconstruction/finding.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-archive_cursor: polylogue-demo-seed-fixture-world
-measure_version: demo-packet-v2
-commit_sha: e5a68ec51
-sample_frame_predicate: "polylogue archive schema (source/index/embeddings/user/ops tiers) plus the seeded demo corpus; the claim is refused on structural schema grounds, not corpus size"
-run_date: "2026-07-09"
-claim: "REFUSED: a minute-by-minute, cross-source (chat + desktop window focus + shell + browser) reconstruction of operator activity for a given day is not supported by the current archive"
-verdict: not_supported
diff --git a/.agent/demos/anti-demo-multi-source-reconstruction/packet.json b/.agent/demos/anti-demo-multi-source-reconstruction/packet.json
deleted file mode 100644
index e1e5570aee..0000000000
--- a/.agent/demos/anti-demo-multi-source-reconstruction/packet.json
+++ /dev/null
@@ -1,132 +0,0 @@
-{
- "baseline": {
- "method": "Use the recorded simpler comparison path rather than the structural product path.",
- "name": "plausible narrative completion",
- "receipts": [
- "artifact:anti-demo-multi-source-reconstruction-evidence"
- ],
- "result": "Infer missing ambient activity from nearby transcript text."
- },
- "claim": {
- "declared_before_execution": true,
- "receipts": [
- "artifact:anti-demo-multi-source-reconstruction-predeclaration"
- ],
- "scope": "the current Polylogue archive tiers at the recorded revision",
- "statement": "Minute-by-minute fusion of transcript, window-focus, shell-history, and browser-tab evidence is not supported by this Polylogue schema.",
- "status": "not_supported"
- },
- "controls": {
- "missing_evidence": [
- {
- "expected": "No matching ambient source table must produce a refusal, not an empty successful timeline.",
- "id": "absent-source-control",
- "observed": {
- "status": "not_supported"
- },
- "passed": true,
- "purpose": "Require missing evidence to remain explicit rather than converted into a positive claim.",
- "receipts": [
- "artifact:anti-demo-multi-source-reconstruction-evidence"
- ]
- }
- ],
- "negative": [
- {
- "expected": "Existing session-to-repository and session-to-commit rows must not be mislabeled as minute-level ambient evidence.",
- "id": "existing-git-correlation",
- "observed": {
- "ambient_timeline": false
- },
- "passed": true,
- "purpose": "Prevent an adjacent easier signal from being counted as the primary construct.",
- "receipts": [
- "artifact:anti-demo-multi-source-reconstruction-evidence"
- ]
- }
- ]
- },
- "falsifier": {
- "condition": "A current archive-tier table is found that stores minute-grained window-focus, independent shell-history, and browser-tab observations.",
- "evaluation_method": "Apply the stated condition to the committed evidence and run log.",
- "receipts": [
- "artifact:anti-demo-multi-source-reconstruction-evidence"
- ],
- "result": "pass",
- "triggered": false
- },
- "mode": "anti-demo",
- "non_claims": [
- "This refusal does not claim that cross-source reconstruction is impossible in a federated Sinex-backed architecture.",
- "This packet does not measure production source coverage or the quality of any external activity system."
- ],
- "oracle": {
- "description": "The archive DDL independently determines which source domains can exist in Polylogue.",
- "expected": {
- "ambient_sources_present": false
- },
- "independent": true,
- "method": "Inspect every archive-tier CREATE TABLE declaration for the required ambient source domains.",
- "receipts": [
- "artifact:anti-demo-multi-source-reconstruction-evidence"
- ]
- },
- "packet_id": "anti-demo-multi-source-reconstruction",
- "primary_construct": {
- "id": "evidence.refusal",
- "product_primitives": [
- "schema inspection",
- "evidence gap reporting"
- ],
- "statement": "The product refuses a cross-source reconstruction when required source domains are absent."
- },
- "provenance": {
- "archive_cursor": "polylogue-demo-seed-fixture-world",
- "commit_sha": "e5a68ec51",
- "measure_version": "demo-packet-v2",
- "run_date": "2026-07-10",
- "sample_frame_predicate": "all Polylogue archive-tier DDL files at the recorded revision"
- },
- "receipts": [
- {
- "artifact_path": "evidence.ndjson",
- "description": "Committed evidence rows and references for this packet.",
- "kind": "artifact",
- "ref": "artifact:anti-demo-multi-source-reconstruction-evidence",
- "resolved": true,
- "sha256": "4e71bc7bda5121b7e933faf014b025ef66ad659f53cd1e0a3adda3c8e9ef1108"
- },
- {
- "artifact_path": "PROMPT.md",
- "description": "The committed prompt that states the packet claim before execution.",
- "kind": "artifact",
- "ref": "artifact:anti-demo-multi-source-reconstruction-predeclaration",
- "resolved": true,
- "sha256": "ec64079d33664dad1fdfc4af633687b2dbadeff9f28463e6c24d1b773332c03f"
- }
- ],
- "reproduction": {
- "commands": [
- "python -m devtools.verify_demo_packet_registry"
- ],
- "deterministic": true,
- "fixture": "current archive-tier DDL and deterministic demo seed",
- "private_data": false
- },
- "results": {
- "measurements": [
- {
- "name": "required_ambient_source_tables",
- "receipts": [
- "artifact:anti-demo-multi-source-reconstruction-evidence"
- ],
- "unit": "tables",
- "value": 0
- }
- ],
- "status": "pass",
- "summary": "The claim is refused on structural schema grounds and the narrower existing correlations are named."
- },
- "schema_version": "2.0.0",
- "title": "Multi-source reconstruction refusal"
-}
diff --git a/.agent/demos/anti-demo-multi-source-reconstruction/queries.ndjson b/.agent/demos/anti-demo-multi-source-reconstruction/queries.ndjson
deleted file mode 100644
index d4b100043a..0000000000
--- a/.agent/demos/anti-demo-multi-source-reconstruction/queries.ndjson
+++ /dev/null
@@ -1,3 +0,0 @@
-{"text": "grep -n \"CREATE TABLE\" polylogue/storage/sqlite/archive_tiers/index.py | grep -iE \"session_commits|session_repos\"", "lowered_spec": {"kind": "schema-grep", "target": "session-to-external-activity correlation tables"}}
-{"text": "grep -n \"CREATE TABLE\" polylogue/storage/sqlite/archive_tiers/index.py | grep -iE \"window|focus|shell_history|browser_tab|activitywatch\"", "lowered_spec": {"kind": "schema-grep", "target": "desktop/shell/browser telemetry tables (expected: none)"}}
-{"text": "grep -rln \"window_focus|shell_history|browser_tab|activitywatch\" polylogue/storage/sqlite/archive_tiers/*.py", "lowered_spec": {"kind": "schema-grep", "target": "cross-tier confirmation (expected: none)"}}
diff --git a/.agent/demos/anti-demo-multi-source-reconstruction/report.md b/.agent/demos/anti-demo-multi-source-reconstruction/report.md
deleted file mode 100644
index a5b3cf6d35..0000000000
--- a/.agent/demos/anti-demo-multi-source-reconstruction/report.md
+++ /dev/null
@@ -1,90 +0,0 @@
-# The Honesty Anti-Demo: Minute-by-Minute Multi-Source Reconstruction
-
-## Claim
-
-REFUSED. "Reconstruct exactly what the operator was doing, minute-by-minute,
-on a given day — correlating AI chat sessions with desktop window focus,
-shell commands typed outside any captured agent session, and browser tabs
-viewed — into one fused timeline" is **not supported** by the current
-Polylogue archive.
-
-## Corpus
-
-Polylogue's own schema (`polylogue/storage/sqlite/archive_tiers/index.py`
-and sibling tier DDL files) plus the seeded demo corpus. This is a
-structural refusal, not a corpus-size limitation — the claim fails on
-schema grounds and would fail identically against the full live archive.
-
-## Method
-
-1. Identify what session-to-external-activity correlation actually exists
- in the schema.
-2. Search for any table carrying desktop window-focus, raw shell history,
- or browser-tab telemetry across every archive tier.
-3. Refuse the claim if neither exists at the required granularity, naming
- the specific gap rather than narrowing the claim quietly.
-
-## Findings
-
-**What exists**: `session_commits` (per-session git commit correlation,
-`detection_type` one of `time_window|file_overlap|explicit_ref|
-origin_reported`, confidence-scored `0..1`) and `session_repos`
-(session-to-repo/branch linkage). Both are real, and both are *session*-
-grained — they say "this session touched this repo/commit," never "this
-number of shell commands ran between 14:02 and 14:03."
-
-**What does not exist**: no table in any Polylogue tier (source.db,
-index.db, embeddings.db, user.db, ops.db) holds desktop window-focus
-events, raw shell command history independent of a captured agent session,
-or browser tab/navigation telemetry. Confirmed by direct schema grep across
-every `archive_tiers/*.py` DDL file (see `run.log`) — zero matches.
-
-**Where this data actually lives**: window-focus (ActivityWatch), shell
-history (Atuin), and browser history are captured by a *separate* system
-(sinity-lynchpin), not by Polylogue. Polylogue is scoped to AI session
-archives; cross-system correlation with Lynchpin's telemetry is a distinct,
-undecided product question, not a missing query on data Polylogue already
-holds.
-
-## Specimens
-
-See `evidence.ndjson` for the exact grep commands and their (zero-match)
-output.
-
-## Counterexamples
-
-None — the claim's negative result *is* the finding. There is no adjacent
-easier claim substituted here; the demo does not quietly narrow "minute-by-
-minute multi-source" down to "session-to-commit" and declare success.
-
-## Limits
-
-- This refusal is about Polylogue's own architecture as of this commit. If
- a future bead decides to ingest Lynchpin telemetry into Polylogue (or
- build a federated cross-system query layer), this verdict would need to
- be re-run and could change.
-- **No existing bead currently owns cross-system (Polylogue+Lynchpin)
- timeline fusion.** This is itself an honest finding: rather than invent a
- plausible-sounding bead reference, this report states plainly that the
- capability gap has no tracked owner yet. The closest adjacent, already-
- scoped primitives are `session_commits`/`session_repos` (session-grained
- git correlation, already shipped) and the general query-objects/result-set
- direction work (`polylogue-rxdo` family) that could eventually be a
- foundation for richer cross-source composition, but neither is a
- reference for "the bead that supplies minute-by-minute cross-system
- reconstruction" because no such bead exists.
-
-## Non-claims
-
-- This refusal does not claim that cross-source reconstruction is impossible in a federated Sinex-backed architecture.
-- This packet does not measure production source coverage or the quality of any external activity system.
-
-## Reproduce
-
-```bash
-grep -n "CREATE TABLE" polylogue/storage/sqlite/archive_tiers/index.py | grep -iE "session_commits|session_repos"
-grep -n "CREATE TABLE" polylogue/storage/sqlite/archive_tiers/index.py | grep -iE "window|focus|shell_history|browser_tab|activitywatch"
-grep -rln "window_focus|shell_history|browser_tab|activitywatch" polylogue/storage/sqlite/archive_tiers/*.py
-```
-
-See `run.log` for the exact recorded output.
diff --git a/.agent/demos/anti-demo-multi-source-reconstruction/run.log b/.agent/demos/anti-demo-multi-source-reconstruction/run.log
deleted file mode 100644
index a299b32c66..0000000000
--- a/.agent/demos/anti-demo-multi-source-reconstruction/run.log
+++ /dev/null
@@ -1,25 +0,0 @@
-=== Step 1: what session-to-external-activity correlation actually exists ===
-$ grep -n "CREATE TABLE" polylogue/storage/sqlite/archive_tiers/index.py | grep -iE "session_commits|session_repos"
-506:CREATE TABLE IF NOT EXISTS session_repos (
-517:CREATE TABLE IF NOT EXISTS session_commits (
-
-session_commits columns (per-session git correlation, confidence-scored, NOT minute-level):
-517:CREATE TABLE IF NOT EXISTS session_commits (
-518- session_id TEXT NOT NULL REFERENCES sessions(session_id) ON DELETE CASCADE,
-519- commit_sha TEXT NOT NULL,
-520- repo_id TEXT REFERENCES repos(repo_id) ON DELETE CASCADE,
-521- detection_type TEXT NOT NULL CHECK(detection_type IN ('time_window', 'file_overlap', 'explicit_ref', 'origin_reported')),
-522- method TEXT,
-523- confidence REAL NOT NULL CHECK(confidence BETWEEN 0 AND 1),
-524- evidence_json TEXT NOT NULL DEFAULT '{{}}',
-525- created_at_ms INTEGER NOT NULL,
-526- PRIMARY KEY(session_id, commit_sha)
-527-) STRICT;
-
-=== Step 2: search for any desktop/shell/browser telemetry table in Polylogue's own schema ===
-$ grep -n "CREATE TABLE" polylogue/storage/sqlite/archive_tiers/index.py | grep -iE "window|focus|shell_history|browser_tab|activitywatch"
-(no output above: no such table exists in polylogue/storage/sqlite/archive_tiers/index.py)
-
-=== Step 3: confirm no other tier (source/embeddings/user/ops) carries this either ===
-$ grep -rln "window_focus\|shell_history\|browser_tab\|activitywatch" polylogue/storage/sqlite/archive_tiers/*.py
-(no matches -- confirmed absent across all tiers)
diff --git a/.agent/demos/attachment-acquisition-census/census.json b/.agent/demos/attachment-acquisition-census/census.json
index 938ef7855f..da49a29adc 100644
--- a/.agent/demos/attachment-acquisition-census/census.json
+++ b/.agent/demos/attachment-acquisition-census/census.json
@@ -44,4 +44,4 @@
"declared_byte_sum": 53,
"missing_blob_ref_count": 0
}
-}
\ No newline at end of file
+}
diff --git a/.agent/demos/attachment-acquisition-census/regenerate.sh b/.agent/demos/attachment-acquisition-census/regenerate.sh
index 7dc12b7afa..3f82c04d3b 100755
--- a/.agent/demos/attachment-acquisition-census/regenerate.sh
+++ b/.agent/demos/attachment-acquisition-census/regenerate.sh
@@ -156,7 +156,7 @@ payload = {
},
}
-(demo_root / "census.json").write_text(json.dumps(payload, indent=2, sort_keys=True), encoding="utf-8")
+(demo_root / "census.json").write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n", encoding="utf-8")
lines = [
"# Attachment Acquisition Census",
diff --git a/.agent/demos/basic-usage/01-find-query.txt b/.agent/demos/basic-usage/01-find-query.txt
deleted file mode 100644
index da18f16a1e..0000000000
--- a/.agent/demos/basic-usage/01-find-query.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-$ polylogue --origin codex-session find "sessions where origin:codex-session" then select --format json
-[{"id":"codex-session:demo-receipts","origin":"codex-session","title":"Fix the clock-sensitive test and prove the suite passes.","date":"2026-07-04"},{"id":"codex-session:demo-anti-grep","origin":"codex-session","title":"Explain error budgets without running a command.","date":"2026-07-04"},{"id":"codex-session:demo-terminal-error","origin":"codex-session","title":"Run the command and stop if it fails.","date":"2026-07-04"},{"id":"codex-session:demo-lineage-subagent","origin":"codex-session","title":"demo-lineage-subagent","date":"2026-07-04"},{"id":"codex-session:demo-lineage-fork","origin":"codex-session","title":"Map the demo lineage base context.","date":"2026-07-04"},{"id":"codex-session:demo-lineage-parent","origin":"codex-session","title":"Map the demo lineage base context.","date":"2026-07-04"},{"id":"codex-session:demo-00","origin":"codex-session","title":"Could you review this code for potential issues?","date":"2024-01-23"}]
-
-$ polylogue find "actions where tool:bash | group by origin | count"
-session.origin=claude-code-session count=6
-session.origin=codex-session count=3
diff --git a/.agent/demos/basic-usage/02-read.txt b/.agent/demos/basic-usage/02-read.txt
deleted file mode 100644
index 2d7882e81c..0000000000
--- a/.agent/demos/basic-usage/02-read.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-$ polylogue find id:codex-session:demo-receipts then read --view transcript
-# Fix the clock-sensitive test and prove the suite passes.
-
-`codex-session:demo-receipts`
-
-## user
-Fix the clock-sensitive test and prove the suite passes.
-
-## assistant
-
-
-## tool
-{"metadata": {"exit_code": 1}, "output": "F tests/test_clock.py::test_uses_monotonic_clock\n1 failed in 0.18s"}
-
-## assistant
-All tests pass. The clock fix is complete.
-
-## user
-The receipt disagrees. Correct the fixture and verify again.
-
-## assistant
-
-
-## tool
-{"metadata": {"exit_code": 0}, "output": "Done!"}
-
-## assistant
-
-
-## tool
-{"metadata": {"exit_code": 0}, "output": ". 1 passed in 0.16s"}
-
-## assistant
-Verified after the correction: 1 passed in 0.16s.
diff --git a/.agent/demos/basic-usage/03-search.txt b/.agent/demos/basic-usage/03-search.txt
deleted file mode 100644
index dc6f645d3b..0000000000
--- a/.agent/demos/basic-usage/03-search.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-$ polylogue find "clock" then select --format json
-[{"id":"chatgpt-export:cross-material-duplicate-01","origin":"chatgpt-export","title":"Flaky clock test fix summary","date":"2026-07-04"},{"id":"chatgpt-export:cross-material-duplicate-02","origin":"chatgpt-export","title":"Flaky clock test fix summary","date":"2026-07-04"},{"id":"claude-code-session:demo-lineage-compaction-parent","origin":"claude-code-session","title":"Fix the flaky clock test before continuing the demo lineage audit.","date":"2026-07-04"},{"id":"codex-session:demo-receipts","origin":"codex-session","title":"Fix the clock-sensitive test and prove the suite passes.","date":"2026-07-04"}]
diff --git a/.agent/demos/basic-usage/04-resume.txt b/.agent/demos/basic-usage/04-resume.txt
deleted file mode 100644
index 89e92670ac..0000000000
--- a/.agent/demos/basic-usage/04-resume.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-$ polylogue find id:codex-session:demo-receipts then continue
-codex resume demo-receipts
diff --git a/.agent/demos/basic-usage/05-cost-usage.json b/.agent/demos/basic-usage/05-cost-usage.json
deleted file mode 100644
index e2474ecf41..0000000000
--- a/.agent/demos/basic-usage/05-cost-usage.json
+++ /dev/null
@@ -1,1380 +0,0 @@
-$ polylogue analyze usage --format json (excerpt: logical_pricing_lanes)
-
- "archive_root": "/realm/tmp/polylogue-demo-refresh-1784526507",
- "detail_level": "full",
- "coverage_matrix": [
- {
- "origin": "claude-code-session",
- "provider": "claude-code",
- "status": "exact",
- "evidence_stream": "provider_reported_usage",
- "event_types": [
- "message_usage"
- ],
- "request_semantics": "Claude Code message.usage rows are per message/request observations.",
- "cumulative_semantics": "Session rollups are derived by summing message usage rows; Claude Code does not supply a separate cumulative session high-water event.",
- "cache_semantics": "cache_read_input_tokens and cache_creation_input_tokens are preserved as cached_input and cache_write lanes and are not folded into generic input/output.",
- "notes": [
- "Exact token telemetry is available only where exported records include message.usage."
- ],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "codex-session",
- "provider": "codex",
- "status": "exact",
- "evidence_stream": "provider_reported_usage",
- "event_types": [
- "token_count"
- ],
- "request_semantics": "Codex last_token_usage is request/current-window telemetry and can be summed by request when present.",
- "cumulative_semantics": "Codex total_token_usage is cumulative and session-global; rollups take the latest total per session to avoid double-counting.",
- "cache_semantics": "cached_input_tokens and cache write/cache creation aliases are preserved as separate lanes and are not folded into generic input/output.",
- "notes": [
- "model_context_window is carried on token_count events when the provider supplies it."
- ],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "chatgpt-export",
- "provider": "chatgpt",
- "status": "estimate_only",
- "evidence_stream": "transcript_text_estimate",
- "event_types": [],
- "request_semantics": "ChatGPT exports do not carry reliable per-request token counters.",
- "cumulative_semantics": "Provider/account UI totals are external summaries and are not reconstructed from transcript text.",
- "cache_semantics": "No cache read/write token lanes are available in ChatGPT export rows.",
- "notes": [
- "Cost-looking metadata is not treated as exact token telemetry."
- ],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "claude-ai-export",
- "provider": "claude-ai",
- "status": "estimate_only",
- "evidence_stream": "transcript_text_estimate",
- "event_types": [],
- "request_semantics": "Claude.ai exports preserve transcript content, not provider usage counters.",
- "cumulative_semantics": "No cumulative provider usage window is present in the export shape.",
- "cache_semantics": "No cache read/write token lanes are available in Claude.ai export rows.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "aistudio-drive",
- "provider": "gemini",
- "status": "partial",
- "evidence_stream": "message_token_fields",
- "event_types": [],
- "request_semantics": "AI Studio/Gemini exports may carry message-level tokenCount output counters on some records.",
- "cumulative_semantics": "No provider cumulative session usage window is available from Drive prompt exports.",
- "cache_semantics": "No cache read/write token lanes are available from Drive prompt exports.",
- "notes": [
- "Input tokens and cache semantics are missing unless a future export shape supplies them explicitly."
- ],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "gemini-cli-session",
- "provider": "gemini-cli",
- "status": "partial",
- "evidence_stream": "message_token_fields",
- "event_types": [],
- "request_semantics": "Local Gemini CLI documents may carry generic usage/tokens dictionaries per message.",
- "cumulative_semantics": "No provider cumulative session usage window is available.",
- "cache_semantics": "Generic cache_read/cache_write keys are preserved when present, but their provider semantics are not independently verified.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "hermes-session",
- "provider": "hermes",
- "status": "partial",
- "evidence_stream": "message_token_fields",
- "event_types": [],
- "request_semantics": "Hermes local-agent documents may carry generic usage/tokens dictionaries per message.",
- "cumulative_semantics": "No provider cumulative session usage window is available.",
- "cache_semantics": "Generic cache_read/cache_write keys are preserved when present, but their provider semantics are not independently verified.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "antigravity-session",
- "provider": "antigravity",
- "status": "unsupported",
- "evidence_stream": "transcript_text_only",
- "event_types": [],
- "request_semantics": "No provider usage telemetry parser is implemented for this origin.",
- "cumulative_semantics": "No cumulative provider usage window is available.",
- "cache_semantics": "No cache read/write token lanes are available.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- },
- {
- "origin": "unknown-export",
- "provider": "unknown",
- "status": "unsupported",
- "evidence_stream": "transcript_text_only",
- "event_types": [],
- "request_semantics": "Unknown exports are parsed for transcript content only.",
- "cumulative_semantics": "No cumulative provider usage window is available.",
- "cache_semantics": "No cache read/write token lanes are available.",
- "notes": [],
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence"
- }
- ],
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 56256,
- "output_tokens": 10596,
- "cached_input_tokens": 280020,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388872
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 56256,
- "output_tokens": 10596,
- "cached_input_tokens": 280020,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388872
- },
- "pricing_catalog_provenance": "litellm-model-prices-vendored+polylogue-curated-overrides",
- "pricing_catalog_effective_date": "2026-06-27",
- "pricing_lanes": [
- {
- "provenance": "priced",
- "row_count": 6,
- "session_count": 6,
- "matched_model_row_count": 3,
- "unmatched_model_row_count": 3,
- "usage": {
- "input_tokens": 56256,
- "output_tokens": 10596,
- "cached_input_tokens": 280020,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388872
- },
- "stored_cost_usd": 2.835,
- "catalog_api_equivalent_usd": null,
- "catalog_priced_subtotal_usd": 2.835,
- "subscription_credit_usd": 0.0,
- "grain": "physical_session",
- "observed_at": "2026-07-20T05:56:19.734297+00:00",
- "exact_total_tokens_evidence": {
- "family": "usage.pricing_lane_exact_total_tokens",
- "fact_ref": "insight:session-model-usage:physical_session:priced:exact-total-tokens",
- "value_state": "known",
- "value": 388872,
- "measurement_authority": [
- "provider-reported"
- ],
- "weakest_measurement_authority": "provider-reported",
- "evidence_refs": [
- "insight:session-model-usage:physical_session:priced"
- ],
- "definition_ref": "insight:usage-lane-exact-total-tokens:v1",
- "temporal": {
- "observed_at": "2026-07-20T05:56:19.734297+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical_session session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 6,
- "observed_count": 6,
- "supported_count": 6,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-07-20T05:56:19.734297+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "catalog_api_equivalent_evidence": {
- "family": "usage.pricing_lane_catalog_api_equivalent_cost",
- "fact_ref": "insight:session-model-usage:physical_session:priced:catalog-api-equivalent-cost",
- "value_state": "unknown",
- "value": null,
- "measurement_authority": [
- "catalog-derived"
- ],
- "weakest_measurement_authority": "catalog-derived",
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:physical_session:priced"
- ],
- "definition_ref": "insight:usage-lane-catalog-api-equivalent-cost:v1",
- "temporal": {
- "observed_at": "2026-07-20T05:56:19.734297+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical_session session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 6,
- "observed_count": 6,
- "supported_count": 3,
- "complete": false,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": [
- {
- "subject_ref": "insight:session-model-usage:physical_session:priced",
- "reason": "unpriced-model-rows:3"
- }
- ]
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-07-20T05:56:19.734297+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "caveats": [
- "missing_price"
- ]
- }
- ],
- "pricing_grain": "physical_session",
- "logical_pricing_lanes": [
- {
- "provenance": "priced",
- "row_count": 6,
- "session_count": 6,
- "matched_model_row_count": 3,
- "unmatched_model_row_count": 3,
- "usage": {
- "input_tokens": 56256,
- "output_tokens": 10596,
- "cached_input_tokens": 280020,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388872
- },
- "stored_cost_usd": 0.0,
- "catalog_api_equivalent_usd": null,
- "catalog_priced_subtotal_usd": 2.835,
- "subscription_credit_usd": 0.0,
- "grain": "logical_session_model_high_water",
- "observed_at": "2026-07-20T05:56:19.734297+00:00",
- "exact_total_tokens_evidence": {
- "family": "usage.pricing_lane_exact_total_tokens",
- "fact_ref": "insight:session-model-usage:logical_session_model_high_water:priced:exact-total-tokens",
- "value_state": "known",
- "value": 388872,
- "measurement_authority": [
- "provider-reported"
- ],
- "weakest_measurement_authority": "provider-reported",
- "evidence_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced"
- ],
- "definition_ref": "insight:usage-lane-exact-total-tokens:v1",
- "temporal": {
- "observed_at": "2026-07-20T05:56:19.734297+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical_session_model_high_water session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 6,
- "observed_count": 6,
- "supported_count": 6,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-07-20T05:56:19.734297+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "catalog_api_equivalent_evidence": {
- "family": "usage.pricing_lane_catalog_api_equivalent_cost",
- "fact_ref": "insight:session-model-usage:logical_session_model_high_water:priced:catalog-api-equivalent-cost",
- "value_state": "unknown",
- "value": null,
- "measurement_authority": [
- "catalog-derived"
- ],
- "weakest_measurement_authority": "catalog-derived",
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:logical_session_model_high_water:priced"
- ],
- "definition_ref": "insight:usage-lane-catalog-api-equivalent-cost:v1",
- "temporal": {
- "observed_at": "2026-07-20T05:56:19.734297+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical_session_model_high_water session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 6,
- "observed_count": 6,
- "supported_count": 3,
- "complete": false,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": [
- {
- "subject_ref": "insight:session-model-usage:logical_session_model_high_water:priced",
- "reason": "unpriced-model-rows:3"
- }
- ]
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-07-20T05:56:19.734297+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [],
- "conflicts": []
- },
- "caveats": [
- "missing_price"
- ]
- }
- ],
- "logical_pricing_grain": "logical_session_model_high_water",
- "stored_provider_priced_usd": 2.835,
- "catalog_api_equivalent_usd": null,
- "catalog_priced_subtotal_usd": 2.835,
- "logical_catalog_api_equivalent_usd": null,
- "logical_catalog_priced_subtotal_usd": 2.835,
- "subscription_credit_catalog_provenance": "polylogue-curated-claude-code-subscription-v1",
- "subscription_credit_catalog_effective_date": "2026-05-07",
- "subscription_credit_usd": 0.0,
- "logical_subscription_credit_usd": 0.0,
- "observed_at": "2026-07-20T05:56:19.734297+00:00",
- "exact_total_tokens_evidence": {
- "family": "usage.pricing_lane_exact_total_tokens",
- "fact_ref": "insight:provider-usage:physical-exact-total-tokens:total",
- "value_state": "known",
- "value": 388872,
- "measurement_authority": [
- "provider-reported"
- ],
- "weakest_measurement_authority": "provider-reported",
- "evidence_refs": [
- "insight:session-model-usage:physical_session:priced"
- ],
- "definition_ref": "insight:usage-lane-exact-total-tokens:v1",
- "temporal": {
- "observed_at": "2026-07-20T05:56:19.734297+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical provider usage pricing lanes",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [
- "insight:session-model-usage:physical_session:priced:exact-total-tokens"
- ],
- "observed_refs": [
- "insight:session-model-usage:physical_session:priced:exact-total-tokens"
- ],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-07-20T05:56:19.734297+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [
- {
- "fact_ref": "insight:session-model-usage:physical_session:priced:exact-total-tokens",
- "value_state": "known",
- "value": 388872,
- "measurement_authority": [
- "provider-reported"
- ],
- "evidence_refs": [
- "insight:session-model-usage:physical_session:priced"
- ],
- "temporal": {
- "observed_at": "2026-07-20T05:56:19.734297+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical_session session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 6,
- "observed_count": 6,
- "supported_count": 6,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-07-20T05:56:19.734297+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- }
- }
- ],
- "conflicts": []
- },
- "catalog_api_equivalent_evidence": {
- "family": "usage.pricing_lane_catalog_api_equivalent_cost",
- "fact_ref": "insight:provider-usage:physical-catalog-api-equivalent-cost:total",
- "value_state": "unknown",
- "value": null,
- "measurement_authority": [
- "catalog-derived"
- ],
- "weakest_measurement_authority": "catalog-derived",
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:physical_session:priced"
- ],
- "definition_ref": "insight:usage-lane-catalog-api-equivalent-cost:v1",
- "temporal": {
- "observed_at": "2026-07-20T05:56:19.734297+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical provider usage pricing lanes",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 0,
- "complete": false,
- "coverage_ratio": 1.0,
- "intended_refs": [
- "insight:session-model-usage:physical_session:priced:catalog-api-equivalent-cost"
- ],
- "observed_refs": [
- "insight:session-model-usage:physical_session:priced:catalog-api-equivalent-cost"
- ],
- "exclusions": [
- {
- "subject_ref": "insight:session-model-usage:physical_session:priced",
- "reason": "unpriced-model-rows:3"
- },
- {
- "subject_ref": "insight:session-model-usage:physical_session:priced:catalog-api-equivalent-cost",
- "reason": "contribution-coverage-incomplete"
- },
- {
- "subject_ref": "insight:session-model-usage:physical_session:priced:catalog-api-equivalent-cost",
- "reason": "unsupported-contribution:unknown"
- }
- ]
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-07-20T05:56:19.734297+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [
- {
- "fact_ref": "insight:session-model-usage:physical_session:priced:catalog-api-equivalent-cost",
- "value_state": "unknown",
- "value": null,
- "measurement_authority": [
- "catalog-derived"
- ],
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:physical_session:priced"
- ],
- "temporal": {
- "observed_at": "2026-07-20T05:56:19.734297+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "physical_session session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 6,
- "observed_count": 6,
- "supported_count": 3,
- "complete": false,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": [
- {
- "subject_ref": "insight:session-model-usage:physical_session:priced",
- "reason": "unpriced-model-rows:3"
- }
- ]
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-07-20T05:56:19.734297+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- }
- }
- ],
- "conflicts": []
- },
- "logical_exact_total_tokens_evidence": {
- "family": "usage.pricing_lane_exact_total_tokens",
- "fact_ref": "insight:provider-usage:logical-exact-total-tokens:total",
- "value_state": "known",
- "value": 388872,
- "measurement_authority": [
- "provider-reported"
- ],
- "weakest_measurement_authority": "provider-reported",
- "evidence_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced"
- ],
- "definition_ref": "insight:usage-lane-exact-total-tokens:v1",
- "temporal": {
- "observed_at": "2026-07-20T05:56:19.734297+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical provider usage pricing lanes",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 1,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced:exact-total-tokens"
- ],
- "observed_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced:exact-total-tokens"
- ],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-07-20T05:56:19.734297+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [
- {
- "fact_ref": "insight:session-model-usage:logical_session_model_high_water:priced:exact-total-tokens",
- "value_state": "known",
- "value": 388872,
- "measurement_authority": [
- "provider-reported"
- ],
- "evidence_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced"
- ],
- "temporal": {
- "observed_at": "2026-07-20T05:56:19.734297+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical_session_model_high_water session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 6,
- "observed_count": 6,
- "supported_count": 6,
- "complete": true,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": []
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-07-20T05:56:19.734297+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- }
- }
- ],
- "conflicts": []
- },
- "logical_catalog_api_equivalent_evidence": {
- "family": "usage.pricing_lane_catalog_api_equivalent_cost",
- "fact_ref": "insight:provider-usage:logical-catalog-api-equivalent-cost:total",
- "value_state": "unknown",
- "value": null,
- "measurement_authority": [
- "catalog-derived"
- ],
- "weakest_measurement_authority": "catalog-derived",
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:logical_session_model_high_water:priced"
- ],
- "definition_ref": "insight:usage-lane-catalog-api-equivalent-cost:v1",
- "temporal": {
- "observed_at": "2026-07-20T05:56:19.734297+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical provider usage pricing lanes",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 1,
- "observed_count": 1,
- "supported_count": 0,
- "complete": false,
- "coverage_ratio": 1.0,
- "intended_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced:catalog-api-equivalent-cost"
- ],
- "observed_refs": [
- "insight:session-model-usage:logical_session_model_high_water:priced:catalog-api-equivalent-cost"
- ],
- "exclusions": [
- {
- "subject_ref": "insight:session-model-usage:logical_session_model_high_water:priced",
- "reason": "unpriced-model-rows:3"
- },
- {
- "subject_ref": "insight:session-model-usage:logical_session_model_high_water:priced:catalog-api-equivalent-cost",
- "reason": "contribution-coverage-incomplete"
- },
- {
- "subject_ref": "insight:session-model-usage:logical_session_model_high_water:priced:catalog-api-equivalent-cost",
- "reason": "unsupported-contribution:unknown"
- }
- ]
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-07-20T05:56:19.734297+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- },
- "calibrated_confidence": null,
- "contributions": [
- {
- "fact_ref": "insight:session-model-usage:logical_session_model_high_water:priced:catalog-api-equivalent-cost",
- "value_state": "unknown",
- "value": null,
- "measurement_authority": [
- "catalog-derived"
- ],
- "evidence_refs": [
- "insight:pricing-catalog:2026-06-27",
- "insight:session-model-usage:logical_session_model_high_water:priced"
- ],
- "temporal": {
- "observed_at": "2026-07-20T05:56:19.734297+00:00",
- "time_source": "materialization_ts",
- "time_confidence": "unknown",
- "frame_start": null,
- "frame_end": null
- },
- "enumeration": "census",
- "coverage": {
- "intended_frame": "logical_session_model_high_water session_model_usage rows for 'priced'",
- "grain": "pricing_lane",
- "denominator": "session_model_usage rows in the declared lane",
- "intended_count": 6,
- "observed_count": 6,
- "supported_count": 3,
- "complete": false,
- "coverage_ratio": 1.0,
- "intended_refs": [],
- "observed_refs": [],
- "exclusions": [
- {
- "subject_ref": "insight:session-model-usage:logical_session_model_high_water:priced",
- "reason": "unpriced-model-rows:3"
- }
- ]
- },
- "freshness": {
- "state": "fresh",
- "evaluated_at": "2026-07-20T05:56:19.734297+00:00",
- "cause": null,
- "last_good_at": null,
- "last_good_evidence_refs": []
- }
- }
- ],
- "conflicts": []
- },
- "origins": [
- {
- "origin": "aistudio-drive",
- "detail_level": "full",
- "provider": "gemini",
- "declared_coverage": "partial",
- "coverage_state": "partial_telemetry_unobserved",
- "coverage_basis": "this origin can carry partial message token fields, but none are materialized in model rollups",
- "evidence_stream": "message_token_fields",
- "request_semantics": "AI Studio/Gemini exports may carry message-level tokenCount output counters on some records.",
- "cumulative_semantics": "No provider cumulative session usage window is available from Drive prompt exports.",
- "cache_semantics": "No cache read/write token lanes are available from Drive prompt exports.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 1,
- "message_count": 4,
- "transcript_word_count": 25,
- "raw_session_count": 1,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 0,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 1,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "provider usage telemetry is partial; request, cumulative, and cache semantics are incomplete"
- ]
- },
- {
- "origin": "antigravity-session",
- "detail_level": "full",
- "provider": "antigravity",
- "declared_coverage": "unsupported",
- "coverage_state": "unsupported",
- "coverage_basis": "no reliable provider token telemetry is supported for this origin",
- "evidence_stream": "transcript_text_only",
- "request_semantics": "No provider usage telemetry parser is implemented for this origin.",
- "cumulative_semantics": "No cumulative provider usage window is available.",
- "cache_semantics": "No cache read/write token lanes are available.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 1,
- "message_count": 2,
- "transcript_word_count": 29,
- "raw_session_count": 1,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 0,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 0,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "provider usage telemetry unsupported for this origin"
- ]
- },
- {
- "origin": "chatgpt-export",
- "detail_level": "full",
- "provider": "chatgpt",
- "declared_coverage": "estimate_only",
- "coverage_state": "acquired_not_materialized",
- "coverage_basis": "source.db has raw rows without parse errors that are not represented in index.db sessions",
- "evidence_stream": "transcript_text_estimate",
- "request_semantics": "ChatGPT exports do not carry reliable per-request token counters.",
- "cumulative_semantics": "Provider/account UI totals are external summaries and are not reconstructed from transcript text.",
- "cache_semantics": "No cache read/write token lanes are available in ChatGPT export rows.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 3,
- "message_count": 7,
- "transcript_word_count": 222,
- "raw_session_count": 5,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 2,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 2,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [
- "e0dbd23201249caeabc286e0f8da7c152a9cb399ff2b693a8c63f3e1cc330588",
- "fb0151b0cb130e0634ef263bdf7f6a98bd54d24ab36b3409e99be3b997f1a91d"
- ],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "exact provider telemetry unavailable; transcript text counts are estimate-only",
- "raw rows without parse errors are acquired but not materialized; usage coverage is incomplete until index.db is rebuilt"
- ]
- },
- {
- "origin": "claude-ai-export",
- "detail_level": "full",
- "provider": "claude-ai",
- "declared_coverage": "estimate_only",
- "coverage_state": "estimate_only",
- "coverage_basis": "exact provider token telemetry is unavailable; transcript text counts remain estimate-only evidence",
- "evidence_stream": "transcript_text_estimate",
- "request_semantics": "Claude.ai exports preserve transcript content, not provider usage counters.",
- "cumulative_semantics": "No cumulative provider usage window is present in the export shape.",
- "cache_semantics": "No cache read/write token lanes are available in Claude.ai export rows.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 1,
- "message_count": 2,
- "transcript_word_count": 17,
- "raw_session_count": 1,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 0,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 0,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "exact provider telemetry unavailable; transcript text counts are estimate-only"
- ]
- },
- {
- "origin": "claude-code-session",
- "detail_level": "full",
- "provider": "claude-code",
- "declared_coverage": "exact",
- "coverage_state": "missing_provider_telemetry",
- "coverage_basis": "this origin supports exact provider telemetry, but no provider usage event rows are materialized",
- "evidence_stream": "provider_reported_usage",
- "request_semantics": "Claude Code message.usage rows are per message/request observations.",
- "cumulative_semantics": "Session rollups are derived by summing message usage rows; Claude Code does not supply a separate cumulative session high-water event.",
- "cache_semantics": "cache_read_input_tokens and cache_creation_input_tokens are preserved as cached_input and cache_write lanes and are not folded into generic input/output.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 4,
- "message_count": 19,
- "transcript_word_count": 398,
- "raw_session_count": 4,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 0,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 1,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 56000,
- "output_tokens": 10500,
- "cached_input_tokens": 280000,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388500
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 56000,
- "output_tokens": 10500,
- "cached_input_tokens": 280000,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388500
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "exact provider telemetry is supported for this origin but no usage events are materialized",
- "some sessions have no provider usage event rows; transcript words and model rollups cover different evidence"
- ]
- },
- {
- "origin": "codex-session",
- "detail_level": "full",
- "provider": "codex",
- "declared_coverage": "exact",
- "coverage_state": "missing_provider_telemetry",
- "coverage_basis": "this origin supports exact provider telemetry, but no provider usage event rows are materialized",
- "evidence_stream": "provider_reported_usage",
- "request_semantics": "Codex last_token_usage is request/current-window telemetry and can be summed by request when present.",
- "cumulative_semantics": "Codex total_token_usage is cumulative and session-global; rollups take the latest total per session to avoid double-counting.",
- "cache_semantics": "cached_input_tokens and cache write/cache creation aliases are preserved as separate lanes and are not folded into generic input/output.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 7,
- "message_count": 30,
- "transcript_word_count": 229,
- "raw_session_count": 7,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 0,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 0,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "exact provider telemetry is supported for this origin but no usage events are materialized",
- "some sessions have no provider usage event rows; transcript words and model rollups cover different evidence"
- ]
- },
- {
- "origin": "gemini-cli-session",
- "detail_level": "full",
- "provider": "gemini-cli",
- "declared_coverage": "partial",
- "coverage_state": "partial_provider_telemetry",
- "coverage_basis": "message-level token fields are materialized, but exact provider request/cumulative semantics are incomplete",
- "evidence_stream": "message_token_fields",
- "request_semantics": "Local Gemini CLI documents may carry generic usage/tokens dictionaries per message.",
- "cumulative_semantics": "No provider cumulative session usage window is available.",
- "cache_semantics": "Generic cache_read/cache_write keys are preserved when present, but their provider semantics are not independently verified.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 1,
- "message_count": 2,
- "transcript_word_count": 33,
- "raw_session_count": 1,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 0,
- "provider_event_session_count": 1,
- "provider_event_count": 1,
- "token_count_event_count": 0,
- "message_usage_event_count": 1,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 1,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 160,
- "output_tokens": 64,
- "cached_input_tokens": 20,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 160,
- "output_tokens": 64,
- "cached_input_tokens": 20,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 244
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 160,
- "output_tokens": 64,
- "cached_input_tokens": 20,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 244
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "provider usage telemetry is partial; request, cumulative, and cache semantics are incomplete"
- ]
- },
- {
- "origin": "hermes-session",
- "detail_level": "full",
- "provider": "hermes",
- "declared_coverage": "partial",
- "coverage_state": "partial_provider_telemetry",
- "coverage_basis": "message-level token fields are materialized, but exact provider request/cumulative semantics are incomplete",
- "evidence_stream": "message_token_fields",
- "request_semantics": "Hermes local-agent documents may carry generic usage/tokens dictionaries per message.",
- "cumulative_semantics": "No provider cumulative session usage window is available.",
- "cache_semantics": "Generic cache_read/cache_write keys are preserved when present, but their provider semantics are not independently verified.",
- "rebuild_guidance": "rebuild index.db from source.db/raw archives so usage events and rollups are materialized from source evidence",
- "session_count": 1,
- "message_count": 5,
- "transcript_word_count": 39,
- "raw_session_count": 1,
- "raw_parse_error_count": 0,
- "acquired_not_materialized_count": 0,
- "provider_event_session_count": 0,
- "provider_event_count": 0,
- "token_count_event_count": 0,
- "message_usage_event_count": 0,
- "zero_token_event_count": 0,
- "missing_model_event_count": 0,
- "multi_model_session_count": 0,
- "priced_model_row_count": 1,
- "origin_reported_model_row_count": 0,
- "estimated_model_row_count": 0,
- "stale_rollup_session_count": 0,
- "provider_request_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "provider_cumulative_usage": {
- "input_tokens": 0,
- "output_tokens": 0,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 0
- },
- "model_rollup_grain": "physical_session",
- "model_rollup_usage": {
- "input_tokens": 96,
- "output_tokens": 32,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 128
- },
- "logical_model_rollup_grain": "logical_session_model_high_water",
- "logical_model_rollup_usage": {
- "input_tokens": 96,
- "output_tokens": 32,
- "cached_input_tokens": 0,
- "cache_write_tokens": 0,
- "reasoning_output_tokens": 0,
- "total_tokens": 128
- },
- "sample_missing_model_sessions": [],
- "sample_zero_token_sessions": [],
- "sample_acquired_not_materialized_raw_ids": [],
- "sample_stale_rollup_sessions": [],
- "caveats": [
- "provider usage telemetry is partial; request, cumulative, and cache semantics are incomplete"
- ]
- }
- ],
- "caveats": [
- "provider usage events, transcript text volume, and model rollups are separate evidence streams",
- "this report does not query provider billing and is not a precise cost report",
- "catalog_api_equivalent_usd is unknown because at least one model row has no catalog price; catalog_priced_subtotal_usd preserves the known priced subset"
- ]
-}
diff --git a/.agent/demos/basic-usage/06-lineage.txt b/.agent/demos/basic-usage/06-lineage.txt
deleted file mode 100644
index 06c487330b..0000000000
--- a/.agent/demos/basic-usage/06-lineage.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-$ polylogue find id:codex-session:demo-lineage-fork then read --view transcript
-# Map the demo lineage base context.
-
-`codex-session:demo-lineage-fork`
-
-## user
-Map the demo lineage base context.
-
-## assistant
-I have the base context and can branch the analysis.
-
-## user
-Now take the forked branch and audit construct validity.
-
-## assistant
-The fork diverges into demo corpus construct checks.
-
-$ polylogue find id:codex-session:demo-lineage-parent then read --view transcript
-# Map the demo lineage base context.
-
-`codex-session:demo-lineage-parent`
-
-## user
-Map the demo lineage base context.
-
-## assistant
-I have the base context and can branch the analysis.
-
-## assistant
-Delegating a topology check to a focused subagent.
-Subagent completed. Session: codex-session:demo-lineage-subagent
diff --git a/.agent/demos/basic-usage/07-mcp-roundtrip.json b/.agent/demos/basic-usage/07-mcp-roundtrip.json
deleted file mode 100644
index 1d05b01bcd..0000000000
--- a/.agent/demos/basic-usage/07-mcp-roundtrip.json
+++ /dev/null
@@ -1,82 +0,0 @@
-{
- "query_call": {
- "tool": "query",
- "arguments": {
- "expression": "clock",
- "projection": "sessions",
- "limit": 3
- }
- },
- "query_first_hit_session_id": "chatgpt-export:cross-material-duplicate-01",
- "query_first_hit_snippet": "",
- "query_result_hit_count": 3,
- "read_call": {
- "tool": "read",
- "arguments": {
- "ref": "session:chatgpt-export:cross-material-duplicate-01"
- }
- },
- "read_result": {
- "mode": "ref-resolution",
- "ref": "session:chatgpt-export:cross-material-duplicate-01",
- "normalized_ref": "session:chatgpt-export:cross-material-duplicate-01",
- "kind": "session",
- "resolved": true,
- "payload_kind": "session-summary",
- "payload": {
- "id": "chatgpt-export:cross-material-duplicate-01",
- "origin": "chatgpt-export",
- "title": "Flaky clock test fix summary",
- "message_count": 2,
- "target_ref": {
- "target_type": "session",
- "target_id": "chatgpt-export:cross-material-duplicate-01",
- "session_id": "chatgpt-export:cross-material-duplicate-01",
- "message_id": null,
- "block_index": null,
- "identity_key": "session:chatgpt-export:cross-material-duplicate-01"
- },
- "anchor": "session-chatgpt-export-cross-material-duplicate-01",
- "actions": {
- "open": {
- "enabled": true,
- "state": "enabled",
- "disabled_reason": null,
- "repair_path": null,
- "inspect_path": null
- },
- "copy_link": {
- "enabled": true,
- "state": "enabled",
- "disabled_reason": null,
- "repair_path": null,
- "inspect_path": null
- },
- "annotate": {
- "enabled": true,
- "state": "enabled",
- "disabled_reason": null,
- "repair_path": null,
- "inspect_path": null
- }
- },
- "created_at": "2026-07-04T09:55:00Z",
- "updated_at": "2026-07-04T09:55:03Z"
- },
- "title": "Flaky clock test fix summary",
- "summary": "2 messages",
- "object_refs": [
- "session:chatgpt-export:cross-material-duplicate-01"
- ],
- "evidence_refs": [],
- "caveats": [],
- "actions": [
- {
- "label": "read",
- "command": "polylogue find id:chatgpt-export:cross-material-duplicate-01 then read --format json",
- "href": null,
- "enabled": true
- }
- ]
- }
-}
\ No newline at end of file
diff --git a/.agent/demos/basic-usage/08-status-health.debt.json b/.agent/demos/basic-usage/08-status-health.debt.json
deleted file mode 100644
index e494373ec3..0000000000
--- a/.agent/demos/basic-usage/08-status-health.debt.json
+++ /dev/null
@@ -1,245 +0,0 @@
-{
- "mode": "archive-debt-list",
- "generated_at": "2026-07-18T13:21:51.704665+00:00",
- "archive_root": "/tmp/polylogue-basic-usage-demo",
- "rows": [
- {
- "debt_ref": "debt:embedding:catchup:backlog",
- "kind": "embedding",
- "stage": "catchup",
- "subject_ref": "embedding:pending",
- "severity": "warning",
- "status": "actionable",
- "owner": "daemon",
- "summary": "14 session(s) pending embedding catch-up",
- "details": "Pending messages: 34; stale messages: 0.",
- "evidence_refs": [
- "archive-tier:/tmp/polylogue-basic-usage-demo/embeddings.db"
- ],
- "caveats": [],
- "actions": [
- {
- "label": "Run embedding backfill",
- "command": [
- "polylogue",
- "ops",
- "embed",
- "backfill"
- ]
- }
- ]
- },
- {
- "debt_ref": "debt:fts:messages_fts",
- "kind": "fts",
- "stage": "index-freshness",
- "subject_ref": "fts:messages_fts",
- "severity": "warning",
- "status": "actionable",
- "owner": "ops",
- "summary": "messages_fts is not query-ready",
- "details": "freshness not ready",
- "evidence_refs": [
- "archive-tier:/tmp/polylogue-basic-usage-demo/index.db"
- ],
- "caveats": [],
- "actions": [
- {
- "label": "Run daemon convergence",
- "command": [
- "polylogued",
- "run"
- ]
- }
- ]
- },
- {
- "debt_ref": "debt:assertion-candidate:assertion-finding:adb1c19ac49d5b835056e68eb12b9389656b83c6eb01d5f09eb7ad6dd5cf7edd",
- "kind": "assertion-candidate",
- "stage": "candidate-judgment",
- "subject_ref": "assertion:assertion-finding:adb1c19ac49d5b835056e68eb12b9389656b83c6eb01d5f09eb7ad6dd5cf7edd",
- "severity": "info",
- "status": "actionable",
- "owner": "user",
- "summary": "Candidate assertion awaits judgment for analysis:claim-vs-evidence-2026-07-04",
- "details": "The bounded origin-stratified sample inspected 3,752 Claude Code, 1,241 Codex, and seven Claude AI structured failures.",
- "observed_at": "2023-11-14T22:16:45+00:00",
- "evidence_refs": [
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#definition",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#totals",
- "file:.agent/demos/claim-vs-evidence/public-summary.json",
- "file:docs/findings/claim-vs-evidence.md",
- "assertion:assertion-finding:adb1c19ac49d5b835056e68eb12b9389656b83c6eb01d5f09eb7ad6dd5cf7edd"
- ],
- "caveats": [],
- "actions": [
- {
- "label": "Review candidate assertions",
- "command": [
- "polylogue",
- "mark",
- "candidates",
- "list",
- "--format",
- "json"
- ]
- }
- ]
- },
- {
- "debt_ref": "debt:assertion-candidate:assertion-finding:cbb4967fc2d33ce231978b76949205856a68d8306da46a610f478cb4244d2ad8",
- "kind": "assertion-candidate",
- "stage": "candidate-judgment",
- "subject_ref": "assertion:assertion-finding:cbb4967fc2d33ce231978b76949205856a68d8306da46a610f478cb4244d2ad8",
- "severity": "info",
- "status": "actionable",
- "owner": "user",
- "summary": "Candidate assertion awaits judgment for analysis:claim-vs-evidence-2026-07-04",
- "details": "The same sample's silent-continuation lower bounds were 22.3% for consequential handlers, 27.1% for benign-recovery handlers, and 53.9% for other handlers.",
- "observed_at": "2023-11-14T22:16:45+00:00",
- "evidence_refs": [
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#definition",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#totals",
- "file:.agent/demos/claim-vs-evidence/public-summary.json",
- "file:docs/findings/claim-vs-evidence.md",
- "assertion:assertion-finding:cbb4967fc2d33ce231978b76949205856a68d8306da46a610f478cb4244d2ad8"
- ],
- "caveats": [],
- "actions": [
- {
- "label": "Review candidate assertions",
- "command": [
- "polylogue",
- "mark",
- "candidates",
- "list",
- "--format",
- "json"
- ]
- }
- ]
- },
- {
- "debt_ref": "debt:assertion-candidate:assertion-finding:e5da9c88d1c236d15648fc52ad7898d8a6f7018277e84c624bdc9e7c7d037689",
- "kind": "assertion-candidate",
- "stage": "candidate-judgment",
- "subject_ref": "assertion:assertion-finding:e5da9c88d1c236d15648fc52ad7898d8a6f7018277e84c624bdc9e7c7d037689",
- "severity": "info",
- "status": "actionable",
- "owner": "user",
- "summary": "Candidate assertion awaits judgment for analysis:claim-vs-evidence-2026-07-04",
- "details": "In one bounded private-archive sample, 1,205 of 5,000 inspected structured failures were followed by silent continuation on the next assistant turn, a 24.1% lower bound.",
- "observed_at": "2023-11-14T22:16:45+00:00",
- "evidence_refs": [
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#definition",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#totals",
- "file:.agent/demos/claim-vs-evidence/public-summary.json",
- "file:docs/findings/claim-vs-evidence.md",
- "assertion:assertion-finding:e5da9c88d1c236d15648fc52ad7898d8a6f7018277e84c624bdc9e7c7d037689"
- ],
- "caveats": [],
- "actions": [
- {
- "label": "Review candidate assertions",
- "command": [
- "polylogue",
- "mark",
- "candidates",
- "list",
- "--format",
- "json"
- ]
- }
- ]
- },
- {
- "debt_ref": "debt:assertion-candidate:assertion-note:3be837fd2faa70afd6139351ee2868b033179a1aa6fbd01daed8711f7a5ea72c",
- "kind": "assertion-candidate",
- "stage": "candidate-judgment",
- "subject_ref": "assertion:assertion-note:3be837fd2faa70afd6139351ee2868b033179a1aa6fbd01daed8711f7a5ea72c",
- "severity": "info",
- "status": "actionable",
- "owner": "user",
- "summary": "Candidate assertion awaits judgment for session:claude-code-session:63705dcc-f3e5-4378-8118-8bc21e53bbb6",
- "details": "The demo pytest session is the approved fixture for search, read, and assertion overlays.",
- "observed_at": "2023-11-14T22:16:41+00:00",
- "evidence_refs": [
- "session:claude-code-session:63705dcc-f3e5-4378-8118-8bc21e53bbb6",
- "assertion:assertion-note:3be837fd2faa70afd6139351ee2868b033179a1aa6fbd01daed8711f7a5ea72c"
- ],
- "caveats": [],
- "actions": [
- {
- "label": "Review candidate assertions",
- "command": [
- "polylogue",
- "mark",
- "candidates",
- "list",
- "--format",
- "json"
- ]
- }
- ]
- },
- {
- "debt_ref": "debt:assertion-candidate:demo-assertion:decision:pytest-triage",
- "kind": "assertion-candidate",
- "stage": "candidate-judgment",
- "subject_ref": "assertion:demo-assertion:decision:pytest-triage",
- "severity": "info",
- "status": "actionable",
- "owner": "user",
- "summary": "Candidate assertion awaits judgment for session:claude-code-session:63705dcc-f3e5-4378-8118-8bc21e53bbb6",
- "details": "Use the Claude Code demo session as the stable pytest triage example.",
- "observed_at": "2023-11-14T22:16:44+00:00",
- "evidence_refs": [
- "session:claude-code-session:63705dcc-f3e5-4378-8118-8bc21e53bbb6",
- "assertion:demo-assertion:decision:pytest-triage"
- ],
- "caveats": [],
- "actions": [
- {
- "label": "Review candidate assertions",
- "command": [
- "polylogue",
- "mark",
- "candidates",
- "list",
- "--format",
- "json"
- ]
- }
- ]
- }
- ],
- "totals": {
- "total": 7,
- "critical": 0,
- "warning": 2,
- "info": 5,
- "actionable": 7,
- "blocked": 0,
- "classified": 0,
- "affected_total": 0,
- "affected_critical": 0,
- "affected_warning": 0,
- "affected_info": 0,
- "affected_actionable": 0,
- "affected_blocked": 0,
- "affected_open": 0,
- "affected_classified": 0
- },
- "caveats": [
- "Rows are composed from existing readiness projections; exact FTS reconciliation requires --exact-fts."
- ]
-}
diff --git a/.agent/demos/basic-usage/08-status-health.txt b/.agent/demos/basic-usage/08-status-health.txt
deleted file mode 100644
index 62f6b431ea..0000000000
--- a/.agent/demos/basic-usage/08-status-health.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-$ polylogue status --daemon-url http://127.0.0.1:1 # forces the direct-archive fallback path a reader without a running daemon would see
-
-Archive (daemon not running)
- Database: index.db
- Schema tiers: present=source, index, embeddings, user, ops
- Archive tier detail: source v13/13 ok, raw_sessions=21; index v42/42 ok, sessions=19; embeddings v4/4 ok, embedding_status=1; user v10/10 ok; ops v1/1 ok, ingest_attempts=0
- SQLite maintenance: WAL 0 KB, planner stats=source,index,embeddings,user
- Archive readiness: unchecked (direct_status_default_skips_exact_archive_readiness)
- Raw materialization: 2 debt row(s), 0 critical, 0 warning, 0 blocked
- Raw frontier: healthy
- Facade routes: 139/140 archive-ready, 0 unsupported
- CLI routes: 5/5 archive-ready, 0 unsupported
- Archive routing paths: ingest=archive -> source.db,index.db, rebuild_index=index_db; 0 blockers, tiers=source.db,index.db,embeddings.db,user.db,ops.db
- Archive route ownership: facade=index:87,none:1,source:5,user:47; cli=source:2,user:3
- Assertion candidate queue: stale-pending, 5 pending, oldest=978.3d
- Sessions: 19
- Messages: 71
- Raw records: 21
- FTS indexed: daemon status unavailable
- Embeddings: partial/partial, ready; 2 msgs, 1/19 convs (5.9%), 16 pending convs
-
- Run polylogued run to start the daemon.
diff --git a/.agent/demos/basic-usage/COLD_READER_GATE.md b/.agent/demos/basic-usage/COLD_READER_GATE.md
deleted file mode 100644
index 3adc50652b..0000000000
--- a/.agent/demos/basic-usage/COLD_READER_GATE.md
+++ /dev/null
@@ -1,50 +0,0 @@
-# Cold-Reader Gate
-
-Give a fresh reader only this directory and ask:
-
-```text
-Using only the files in this directory, list the eight Polylogue features
-this demo claims to prove work end-to-end, state which surface (CLI, MCP)
-each was exercised through, and identify the one walkthrough whose output
-was deliberately captured against a non-default daemon URL — and why.
-```
-
-## Expected Passing Answer
-
-- Names all eight walkthroughs: find (fielded query + pipeline aggregate),
- read (exact-ref transcript), search (FTS with provenance), resume
- (continuation command generation), cost (disjoint token/cost lanes),
- lineage (composed fork read), MCP (search → get_session_summary round-trip),
- status/health (archive readiness without a daemon).
-- States that seven walkthroughs use the `polylogue` CLI directly through the
- real subprocess test route and one (MCP) uses a real stdio JSON-RPC
- client/server exchange, not the CLI.
-- Identifies walkthrough 8 (status/health) as the one run with
- `--daemon-url http://127.0.0.1:1`, and explains this forces the
- direct-archive fallback path so the captured output reproduces
- identically for a reader with no daemon running at all.
-- Notices the demo runs against the deterministic seeded archive
- (`polylogue demo seed`), not the operator's live archive, and states why
- (public repository; the README's own "Why the demo archive" section).
-- Does not treat any of the eight numeric results (token counts, hit counts,
- session counts) as a claim about a real corpus — they are properties of
- the fixed deterministic demo archive.
-
-## Replacement Verification Mapping
-
-| Former check | Replacement | Production route exercised |
-| --- | --- | --- |
-| find query | `test_find_query_covers_fielded_filter_and_pipeline_aggregate` | Query-first CLI parser, SQL query plan, and select renderer |
-| read | `test_read_renders_the_seeded_transcript` | Query-first CLI read/transcript renderer |
-| search | `test_search_spans_multiple_origins` | CLI lexical search and result serialization |
-| resume | `test_continue_generates_a_resume_command` | CLI continuation action |
-| cost | `test_usage_reports_disjoint_token_lanes` | CLI usage insight and JSON renderer |
-| lineage | `test_lineage_read_composes_parent_prefix_and_child_tail` | CLI read path and lineage recomposition |
-| MCP round-trip | `test_mcp_query_and_get_round_trip` | Production stdio MCP query/get dispatcher |
-| status/health | `test_status_reports_direct_archive_fallback_when_daemon_is_unreachable` | CLI direct-archive status fallback |
-
-The replacement test seeds through `polylogue.demo.seed_demo_archive`, runs the
-CLI through `tests.infra.cli_subprocess.run_cli`, and invokes the production
-MCP stdio route. `polylogue demo verify --require-overlays` remains the
-structural demo contract check. The captured outputs remain private-data-free
-fixtures for cold reading; they are not a second QA command surface.
diff --git a/.agent/demos/basic-usage/README.md b/.agent/demos/basic-usage/README.md
deleted file mode 100644
index f2c586d80e..0000000000
--- a/.agent/demos/basic-usage/README.md
+++ /dev/null
@@ -1,241 +0,0 @@
-# Basic Usage — The Features Actually Work
-
-Generated: 2026-07-20
-Archive: Polylogue's deterministic demo archive (`polylogue demo seed`), index schema v42 at capture time.
-
-Eight short, real walkthroughs proving ordinary Polylogue features work
-end-to-end, not just in unit tests. Every command below was actually run; every
-output is the real result, copied verbatim (only line-wrapping added for
-readability). Each walkthrough states exactly what it proves and nothing more.
-
-**Why the demo archive, not the live one:** every command here is real and
-copy-pasteable, but it runs against the private-data-free deterministic demo
-archive rather than the operator's live archive, for two reasons: (1) this
-repository is public — the live archive is the operator's actual work
-history and its content must not appear here; (2) at the time this suite was
-built, the live archive's derived index was in a known, unrelated degraded
-state (see `docs/findings/claim-vs-evidence.md`) that would have made any
-live numbers non-representative anyway. The same commands work identically
-against a real archive — only the data differs.
-
-Reproduce the whole archive first:
-
-```bash
-export POLYLOGUE_ARCHIVE_ROOT=/tmp/polylogue-basic-usage-demo
-polylogue demo seed --root "$POLYLOGUE_ARCHIVE_ROOT" --force --with-overlays --format json
-polylogue demo verify --root "$POLYLOGUE_ARCHIVE_ROOT" --require-overlays --format json
-```
-
-Then every command below runs unmodified with that `POLYLOGUE_ARCHIVE_ROOT` exported.
-
-## 1. Find — fielded query + pipeline aggregate
-
-File: [`01-find-query.txt`](01-find-query.txt)
-
-```
-polylogue --origin codex-session find "sessions where origin:codex-session" then select --format json
-polylogue find "actions where tool:bash | group by origin | count"
-```
-
-The first command is a fielded DSL query (`origin:codex-session`) returning
-the matched session refs. The second is a pipeline query: it scopes to
-`actions` (not `sessions`), filters by tool name, groups by origin, and
-aggregates — the DSL's `sessions where … | s where … | group by … |
-count` grammar (`archive/query/expression.py`), not a bespoke script.
-
-**What this proves:** the query-first CLI's fielded predicates and multi-stage
-pipeline grammar both execute against a real archive and return real,
-distinct result shapes (a JSON row list vs. a grouped count table).
-
-## 2. Read — exact-ref transcript
-
-File: [`02-read.txt`](02-read.txt)
-
-```
-polylogue find id:codex-session:demo-receipts then read --view transcript
-```
-
-An exact-ref query (`id:`) piped into `read --view transcript`. The
-transcript itself is worth reading closely: the assistant claims "All tests
-pass" immediately after a tool result shows `exit_code: 1` and a failing
-test — a small, self-contained illustration of exactly the claim-vs-evidence
-gap this lane's Phase 0/1 work investigates, captured as normal archive
-content rather than manufactured for the point.
-
-**What this proves:** exact-ref resolution and the `transcript` render view
-work end-to-end, and the resulting text is faithful to the underlying
-structured tool-result evidence (not reconstructed from prose).
-
-## 3. Search — FTS hit with snippet and provenance
-
-File: [`03-search.txt`](03-search.txt)
-
-```
-polylogue find "clock" then select --format json
-```
-
-An unfielded, quoted free-text query runs through the same FTS5 index this
-CLI's `find` verb is backed by (`archive/query/expression.py`'s `near:`/bare
-free-text lowering). Every hit carries a stable session ref
-(`origin:native_id`), so a caller can always resolve a search hit back to its
-exact source. (The MCP `search` tool, demonstrated separately in section 7,
-additionally returns a highlighted snippet and message-level ref per hit —
-the CLI's `find` surface intentionally keeps this compact for terminal use.)
-
-**What this proves:** free-text search resolves across origins (a ChatGPT
-export, a Claude Code session, and a Codex session all matched "clock" from
-genuinely different underlying text) and every result is provenance-bearing,
-not a bag of disconnected snippets.
-
-## 4. Resume — continuation command generation
-
-File: [`04-resume.txt`](04-resume.txt)
-
-```
-polylogue find id:codex-session:demo-receipts then continue
-```
-
-**What this proves:** Polylogue can generate the exact runtime-native resume
-invocation (`codex resume `) for an archived session, not just read it —
-continuity, not just archaeology.
-
-## 5. Cost — disjoint token/cost accounting
-
-File: [`05-cost-usage.json`](05-cost-usage.json)
-
-```
-polylogue analyze usage --format json
-```
-
-The full output is long (it deliberately keeps provider-event rows, origin
-cumulative counters, and per-model rollups as separate evidence streams
-rather than collapsing them); the load-bearing excerpt is
-`logical_pricing_lanes`, which reports, per pricing provenance:
-
-```json
-{
- "provenance": "priced",
- "row_count": 4,
- "usage": {
- "input_tokens": 56000,
- "output_tokens": 10500,
- "cached_input_tokens": 280000,
- "cache_write_tokens": 42000,
- "reasoning_output_tokens": 0,
- "total_tokens": 388500
- },
- "catalog_priced_subtotal_usd": 2.835
-}
-```
-
-**What this proves:** cost/usage accounting keeps input, output, cached, and
-cache-write token lanes disjoint (never silently folded together, matching
-the documented Codex-inclusive-token/Claude-cache-token pitfalls) and
-reports pricing provenance (`priced` vs. `estimate_only`) per row rather than
-one blended number.
-
-## 6. Lineage — composed fork read
-
-File: [`06-lineage.txt`](06-lineage.txt)
-
-```
-polylogue find id:codex-session:demo-lineage-fork then read --view transcript
-polylogue find id:codex-session:demo-lineage-parent then read --view transcript
-```
-
-The fork session's transcript already contains the parent's two turns
-("Map the demo lineage base context." / "I have the base context and can
-branch the analysis.") composed ahead of its own divergent tail — reading
-the fork alone gives the full coherent conversation, not just the child's
-new turns. `demo-lineage-parent`'s own transcript is included for direct
-comparison: the fork's first two turns are byte-identical to the parent's,
-proving genuine prefix composition rather than duplicated storage that
-happens to render similarly.
-
-**What this proves:** forked sessions are read as parent-prefix + child-tail
-composition (the archive's `session_links` lineage model), not stored or
-displayed as disconnected fragments.
-
-## 7. MCP — search → get_session_summary round-trip
-
-File: [`07-mcp-roundtrip.json`](07-mcp-roundtrip.json)
-
-A real MCP client/server exchange over stdio JSON-RPC (the same protocol any
-MCP-speaking agent client uses), driven by
-`devtools/continuity_replay.py`'s `StdioMCPContinuityRoute` against the demo
-archive:
-
-```python
-async with StdioMCPContinuityRoute(archive_root) as route:
- search_result = await route.invoke("search", {"query": "clock", "limit": 3})
- # search_result["hits"][0]["session"]["id"] == "chatgpt-export:cross-material-duplicate-01"
- summary = await route.invoke("get_session_summary", {"id": "chatgpt-export:cross-material-duplicate-01"})
-```
-
-The MCP surface is mid-rewrite by a parallel lane (#3056 retired the
-`archive_list_sessions`/`archive_search_sessions` aliases the same week this
-suite was built), so this demo deliberately exercises the two canonical
-tools least likely to move — `search` and `get_session_summary` — rather
-than the full tool catalog. See `docs/mcp-reference.md` for the current
-complete tool list.
-
-**What this proves:** the MCP surface answers the identical question the CLI
-answers (search → resolve a session summary) through a real protocol
-round-trip, not a mocked handler — this is the continuity surface real agent
-clients (not humans at a terminal) actually use.
-
-## 8. Status/health — daemon and archive readiness
-
-Files: [`08-status-health.txt`](08-status-health.txt),
-[`08-status-health.debt.json`](08-status-health.debt.json)
-
-```
-polylogue status --daemon-url http://127.0.0.1:1
-polylogue ops debt list --format json
-```
-
-(`--daemon-url` points at an unreachable port so this demo reproduces
-identically for a reader with no daemon running at all — `polylogue status`
-normally talks to a live `polylogued` daemon's HTTP API first and only falls
-back to bounded local SQLite checks when the daemon is unreachable.)
-
-`ops debt list` names concrete, actionable freshness/convergence gaps rather
-than a pass/fail flag — in this demo archive: 14 sessions pending embedding
-catch-up, `messages_fts` not yet query-ready, and (because this suite seeds
-`--with-overlays`) a candidate finding assertion from the claim-vs-evidence
-demo overlay still awaiting operator judgment, each with its own evidence
-ref and a copy-pasteable remediation command.
-
-**What this proves:** archive health is queryable without a running daemon —
-per-tier schema versions, row counts, raw-materialization debt, and FTS/
-embedding backfill progress are all real, structural facts read directly
-from the five SQLite tiers, not decorative placeholder text — and debt is
-reported as named, actionable rows, not a single opaque health flag.
-
-## Regenerate everything
-
-```bash
-export POLYLOGUE_ARCHIVE_ROOT=/tmp/polylogue-basic-usage-demo
-polylogue demo seed --root "$POLYLOGUE_ARCHIVE_ROOT" --force --with-overlays --format json
-polylogue demo verify --root "$POLYLOGUE_ARCHIVE_ROOT" --require-overlays --format json
-devtools test tests/integration/test_basic_usage_cli.py
-```
-
-The integration tests re-run each CLI walkthrough against a fresh seed through
-the real subprocess entry point. `polylogue demo verify` checks the seeded
-archive's structural contract. See [`COLD_READER_GATE.md`](COLD_READER_GATE.md)
-for the replacement mapping and fresh-reader verification prompt.
-
-## Files
-
-- `01-find-query.txt`
-- `02-read.txt`
-- `03-search.txt`
-- `04-resume.txt`
-- `05-cost-usage.json`
-- `06-lineage.txt`
-- `07-mcp-roundtrip.json`
-- `08-status-health.txt`
-- `08-status-health.debt.json`
-- `COLD_READER_GATE.md`
-- `README.md` — this file.
diff --git a/.agent/demos/d1-receipts/NON-CLAIMS.md b/.agent/demos/d1-receipts/NON-CLAIMS.md
deleted file mode 100644
index e52d1257ce..0000000000
--- a/.agent/demos/d1-receipts/NON-CLAIMS.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Non-claims
-
-- This packet does not prove every sentence in PR #3282's body is independently verified -- only the four claims explicitly checked in report.md are scored; claim 4 is explicitly scored `not_supported`.
-- This packet does not establish that `session_refs` correctly resolves every PR reference archive-wide -- only that it resolves this one case with structural evidence.
-- This packet does not reproduce on the public seed corpus (seed 1843); it requires read-only access to the live archive and the `Sinity/polylogue` GitHub history.
diff --git a/.agent/demos/d1-receipts/PROMPT.md b/.agent/demos/d1-receipts/PROMPT.md
deleted file mode 100644
index 3e23fb53d6..0000000000
--- a/.agent/demos/d1-receipts/PROMPT.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# D1 "The Receipts": Claim-vs-Evidence on a Real Merged PR
-
-Predeclaration receipt: `artifact:d1-receipts-predeclaration`.
-
-Pick a real merged, agent-authored PR from this repository. Resolve it to
-its authoring/dispatch session **structurally** — via `session_refs`
-(kind=`pull_request`), not by regex-scanning message prose or a time-window
-heuristic. Then check specific sentences from the PR body against that
-session's own recorded tool_use/tool_result blocks: does the evidence
-actually support the claim, or is the claim resting on the PR body's own
-prose with nothing underneath it?
-
-Product primitives only: `session_refs` (the typed evidence table wired by
-PR #3425/#3431), `polylogue read --view correlation`, and structural SQL
-reads over `blocks`/`session_refs` for citation (mirroring the exact
-read-only query style PR #3392 and PR #3282 themselves used in their own
-Verification sections — this demo does not invent a new access pattern).
-
-## Steps
-
-1. Resolve PR → session structurally:
- ```sql
- SELECT session_id, repo, ref_number, url
- FROM session_refs
- WHERE kind = 'pull_request' AND repo = 'Sinity/polylogue' AND ref_number = 3282;
- ```
- Cross-check the same resolution through the CLI's own read surface:
- `polylogue find "id:" then read --view correlation --format json`
- (this is the surface PR #3425/#3431 wired `session_refs` into —
- `insights/session_commit.py:build_correlation_result` and
- `insights/correlation_view.py`).
-
-2. Fetch the PR body from GitHub (`gh pr view 3282 --json body`) and pull
- out individually falsifiable sentences — not the whole prose block, each
- claim on its own.
-
-3. For each claim, search the resolved session's own `blocks` rows
- (`tool_use`/`tool_result`, joined by `tool_id`) for structural evidence:
- an exact command, an exact exit code, an exact pytest summary line. A
- claim with no matching block is marked **not independently verified in
- this session** — never silently upgraded to "supported" because the PR
- body asserts it.
-
-4. Render the two columns: claimed sentence | observed block evidence
- (drillable via the cited `block:` ref), with an explicit status per row.
-
-## Note on this run
-
-This demo's session turned out to be a **merge-conductor** session: its own
-`blocks` are almost entirely `Bash` (53 of 56 tool_use blocks) plus 3 `Read`
-calls — zero `Edit`/`Write` tool_use. The actual file edits for PR #3282
-happened in separately dispatched worker sessions across multiple git
-worktrees (`/realm/worktrees/polylogue-membership-head*`); this session
-orchestrates `git`, `gh pr create`, and `devtools test`/`devtools verify`
-invocations across those worktrees and stitches the result into one PR.
-
-This is itself a real, useful finding, not a inconvenience to hide: the PR
-body's own Verification section names a 7-file `devtools test` invocation
-("`devtools test tests/unit/sources/test_live_batch_support.py ...` — all
-passing, **see individual commit messages for per-commit pass counts**") —
-its own parenthetical admits the aggregate command was never run as one
-shot. Searching this session's blocks confirms it: the 7-file string only
-appears inside the `gh pr create --body` tool_input (i.e. inside the PR body
-text itself), never as an actual invoked command. That specific claim is
-marked **not independently verified in this session** in `report.md` and
-`checks.json` — precisely the honesty discipline this packet exists to
-enforce, applied to itself.
diff --git a/.agent/demos/d1-receipts/checks.json b/.agent/demos/d1-receipts/checks.json
deleted file mode 100644
index 08d536a977..0000000000
--- a/.agent/demos/d1-receipts/checks.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "pass": true,
- "unsupported_claims": [
- "PR #3282 claim 4: the 7-file devtools test invocation named in the Verification section is not independently verified in the resolved session -- no matching tool_use block exists outside the gh-pr-create body text itself."
- ],
- "coverage_notes": "4 claims from PR #3282's body were checked structurally against the session_refs-resolved authoring/dispatch session's own blocks. 3 of 4 are supported by exact tool_use/tool_result evidence (gh pr create body/URL match, devtools verify --quick per-step exit codes, the rebuild_index.py test+commit pair). Claim 4 is explicitly and correctly scored not_supported rather than assumed true from the PR body's own prose -- this is the intended outcome of the packet's method, not a defect. The resolved session is also shown to be a merge-conductor (53 Bash + 3 Read tool_use blocks, 0 Edit/Write) rather than the direct file-editing session, which is documented as a real finding in report.md rather than hidden."
-}
diff --git a/.agent/demos/d1-receipts/evidence.ndjson b/.agent/demos/d1-receipts/evidence.ndjson
deleted file mode 100644
index 5035c3869b..0000000000
--- a/.agent/demos/d1-receipts/evidence.ndjson
+++ /dev/null
@@ -1,11 +0,0 @@
-{"ref": "artifact:d1-receipts-evidence", "cited_for": "Demo Packet v2 receipt root", "verified_via": "committed evidence.ndjson"}
-{"ref": "session:claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39", "cited_for": "session_refs kind=pull_request resolves this session to Sinity/polylogue#3282", "verified_via": "sqlite3 index.db: SELECT session_id,repo,ref_number,url FROM session_refs WHERE kind='pull_request' AND repo='Sinity/polylogue' AND ref_number=3282"}
-{"ref": "block:claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39:ae9a4788-4bf6-4b89-b01e-90f10e622981:0", "cited_for": "the gh pr create tool_use --body text is byte-identical to the PR body later fetched live via gh pr view 3282, including the exact bullet claims checked below", "verified_via": "diff of tool_input command against `gh pr view 3282 --repo Sinity/polylogue --json body`"}
-{"ref": "block:claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39:a98d94d0-831f-4cf6-946b-40bf99179283:0", "cited_for": "gh pr create tool_result: https://github.com/Sinity/polylogue/pull/3282 -- confirms this session actually opened PR #3282, not merely referenced it", "verified_via": "tool_result text (single URL line)"}
-{"ref": "block:claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39:bdacfb31-ecc7-4491-be2f-891f8bfb888b:0", "cited_for": "tool_use invoking `timeout 180 devtools verify --quick`, checking the PR claim 'devtools verify --quick -- pass'", "verified_via": "tool_input command text"}
-{"ref": "block:claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39:9786b513-9ad0-4e25-ad3e-e18a0f60220f:0", "cited_for": "tool_result: structured verify-run JSON, every step exit=0, total_duration_s=32.99, exit_code=0 -- SUPPORTS the claim via structure, not a trusted pass/fail word in prose", "verified_via": "tool_result JSON body (per-step name/duration_s/exit array)"}
-{"ref": "block:claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39:ebe785a2-de91-4de3-9b28-43bd1a8e9596:0", "cited_for": "tool_use invoking devtools test against tests/unit/maintenance/test_rebuild_index_bulk_build.py (+4 more files), checking the Solution-section claim 'rebuild_index bulk FTS materialization checkpoints progress'", "verified_via": "tool_input command text"}
-{"ref": "block:claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39:59a1be2d-7881-4d64-997d-d055dd61aa74:0", "cited_for": "tool_result: pytest summary '123 passed in 8.05s', ok (12.2s) -- SUPPORTS the rebuild_index claim", "verified_via": "tool_result text (pytest summary line)"}
-{"ref": "polylogue-6mvg", "cited_for": "the PR body's own tracking-item reference ('Ref polylogue-6mvg'), cited verbatim inside the gh pr create --body text", "verified_via": "block:...ae9a4788... tool_input"}
-{"ref": "action.tool_use.count=53,Bash", "cited_for": "56 total tool_use blocks in this session: 53 Bash, 3 Read, 0 Edit, 0 Write -- this is a merge-conductor/orchestration session, not the direct file-editing session", "verified_via": "sqlite3 index.db: SELECT tool_name, count(*) FROM blocks WHERE session_id=... AND block_type='tool_use' GROUP BY tool_name"}
-{"ref": "action.negative-control.missing-7-file-devtools-test-invocation", "cited_for": "counterexample: the PR body's exact 7-file `devtools test tests/unit/sources/test_live_batch_support.py ...` string appears ONLY inside the gh-pr-create --body text (i.e. inside the PR body itself), never as an actually-invoked command in this session's blocks -- 0 matching tool_use rows when the gh-pr-create block is excluded", "verified_via": "sqlite3 index.db: SELECT count(*) FROM blocks WHERE session_id=... AND block_type='tool_use' AND tool_input LIKE '%test_live_batch_support.py%' AND tool_input NOT LIKE '%gh pr create%' -- returns 0"}
diff --git a/.agent/demos/d1-receipts/finding.yaml b/.agent/demos/d1-receipts/finding.yaml
deleted file mode 100644
index c288a450ab..0000000000
--- a/.agent/demos/d1-receipts/finding.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-archive_cursor: "live-archive:/realm/db/polylogue (read-only, file:...?mode=ro)"
-measure_version: demo-packet-v2
-commit_sha: 59744a30bf461a587cc679ee62a432e8cd2cf82a
-sample_frame_predicate: "session_refs WHERE kind='pull_request' AND repo='Sinity/polylogue' AND ref_number=3282, resolving to claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39"
-run_date: "2026-07-31"
-claim: "session_refs typed pull_request evidence resolves a real merged PR to its authoring/dispatch session, and specific PR-body verification sentences can be checked against that session's own recorded blocks -- with unsupported claims marked as such, not silently believed"
diff --git a/.agent/demos/d1-receipts/packet.json b/.agent/demos/d1-receipts/packet.json
deleted file mode 100644
index fb5c35aebe..0000000000
--- a/.agent/demos/d1-receipts/packet.json
+++ /dev/null
@@ -1,135 +0,0 @@
-{
- "schema_version": "2.0.0",
- "packet_id": "d1-receipts",
- "title": "D1 receipts: claim-vs-evidence on a real merged PR",
- "mode": "private",
- "primary_construct": {
- "id": "correlation.session_refs.pr_link",
- "statement": "session_refs typed pull_request evidence (Claude Code's own pr-link sidecar record) resolves a real merged PR to its authoring/dispatch session with structural confidence, and that session's own tool_use/tool_result blocks let each PR-body verification claim be checked against real evidence instead of trusted prose.",
- "product_primitives": [
- "session_refs (storage table)",
- "polylogue read --view correlation",
- "insights/session_commit.py:build_correlation_result",
- "structural SQL reads over blocks/session_refs for citation"
- ]
- },
- "claim": {
- "statement": "session_refs resolves PR #3282 to claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39, and 3 of 4 checked PR-body claims are supported by that session's own recorded blocks; the fourth is correctly scored not_supported rather than assumed.",
- "declared_before_execution": true,
- "scope": "one real merged PR (Sinity/polylogue#3282) and its session_refs-resolved authoring/dispatch session, on the live archive at /realm/db/polylogue",
- "status": "supported",
- "receipts": ["artifact:d1-receipts-predeclaration", "artifact:d1-receipts-evidence"]
- },
- "oracle": {
- "description": "The SQL queries and gh CLI output cited are independent of the report prose and re-runnable against the same live archive and GitHub history.",
- "independent": true,
- "method": "Re-run the reproduce commands in report.md and compare cited block text / query results against evidence.ndjson.",
- "expected": {"queries_return_matching_rows": true, "negative_control_returns_zero": true},
- "receipts": ["artifact:d1-receipts-evidence"]
- },
- "baseline": {
- "name": "regex/time-window PR reference scan (the pre-#3425 default correlation path)",
- "method": "Scan message text for #NNN patterns within a time window around the session, with no structural resolution to a specific typed evidence row.",
- "result": "The same read --view correlation call surfaces a disagreements entry: the regex heuristic independently found 13 additional PR numbers in this session's message text that are NOT corroborated by typed session_refs evidence -- demonstrating why the typed path is authoritative and the heuristic path is demoted to a disagreement signal, not silently trusted.",
- "receipts": ["artifact:d1-receipts-evidence"]
- },
- "controls": {
- "negative": [
- {
- "id": "gh-pr-create-body-url-match-control",
- "purpose": "Prevent a stale or edited PR body from being treated as automatically representative of the session's own recorded claim text.",
- "expected": {"gh_pr_create_tool_result_url": "https://github.com/Sinity/polylogue/pull/3282"},
- "observed": {"gh_pr_create_tool_result_url": "https://github.com/Sinity/polylogue/pull/3282"},
- "passed": true,
- "receipts": ["artifact:d1-receipts-evidence"]
- }
- ],
- "missing_evidence": [
- {
- "id": "unverified-7-file-devtools-test-claim",
- "purpose": "Require a PR-body claim's supporting evidence to be structurally present in the resolved session, not assumed from the PR body's own prose.",
- "expected": {"status": "not_supported_when_no_matching_tool_use_block_exists"},
- "observed": {"status": "not_supported", "matching_tool_use_rows_excluding_gh_pr_create": 0},
- "passed": true,
- "receipts": ["artifact:d1-receipts-evidence"]
- }
- ]
- },
- "falsifier": {
- "condition": "The gh pr create tool_use body text does not byte-match the live-fetched PR #3282 body, or the devtools verify --quick tool_result JSON contains any step with exit != 0, or the negative-control count in evidence.ndjson is nonzero.",
- "evaluation_method": "Apply the stated condition to the committed evidence and re-run the queries in report.md's Reproduce section against the live archive.",
- "triggered": false,
- "result": "pass",
- "receipts": ["artifact:d1-receipts-evidence"]
- },
- "results": {
- "status": "pass",
- "summary": "3 of 4 checked PR-body claims are structurally supported by the session_refs-resolved session's own blocks; the 4th is correctly scored not_supported, and the session is shown to be a merge-conductor session (0 Edit/Write tool_use blocks) rather than the direct file-editing session -- both are real, documented findings, not hidden.",
- "measurements": [
- {
- "name": "claims_checked",
- "value": 4,
- "unit": "claims",
- "receipts": ["artifact:d1-receipts-evidence"]
- },
- {
- "name": "claims_supported",
- "value": 3,
- "unit": "claims",
- "receipts": ["artifact:d1-receipts-evidence"]
- },
- {
- "name": "claims_not_independently_verified",
- "value": 1,
- "unit": "claims",
- "receipts": ["artifact:d1-receipts-evidence"]
- },
- {
- "name": "tool_use_blocks_edit_or_write",
- "value": 0,
- "unit": "blocks",
- "receipts": ["artifact:d1-receipts-evidence"]
- }
- ]
- },
- "non_claims": [
- "This packet does not prove every sentence in PR #3282's body is independently verified -- only the four claims explicitly checked are scored.",
- "This packet does not establish that session_refs correctly resolves every PR reference archive-wide -- only that it resolves this one case with structural evidence.",
- "This packet does not reproduce on the public seed corpus (seed 1843); it requires read-only access to the live archive and the Sinity/polylogue GitHub history -- the public-corpus D1 variant is not built by this packet."
- ],
- "receipts": [
- {
- "ref": "artifact:d1-receipts-evidence",
- "kind": "artifact",
- "description": "Committed evidence rows and block/session citations for this packet.",
- "artifact_path": "evidence.ndjson",
- "resolved": true,
- "sha256": "1370ede81fa593585b216ed9d4f834093cf50cdd9a2e634467f4c267b3628fad"
- },
- {
- "ref": "artifact:d1-receipts-predeclaration",
- "kind": "artifact",
- "description": "The committed prompt that states the packet claim before execution.",
- "artifact_path": "PROMPT.md",
- "resolved": true,
- "sha256": "9860720832a1ed3460a8cb9196b1a0682f9223487821c569817e8f5da3098ecd"
- }
- ],
- "reproduction": {
- "fixture": "live archive /realm/db/polylogue (read-only) + Sinity/polylogue GitHub history",
- "deterministic": false,
- "private_data": true,
- "commands": [
- "sqlite3 \"file:/realm/db/polylogue/index.db?mode=ro\" \"SELECT session_id, repo, ref_number, url FROM session_refs WHERE kind='pull_request' AND repo='Sinity/polylogue' AND ref_number=3282\"",
- "polylogue find \"id:claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39\" then read --view correlation --format json",
- "gh pr view 3282 --repo Sinity/polylogue --json body"
- ]
- },
- "provenance": {
- "archive_cursor": "live-archive:/realm/db/polylogue (read-only, file:...?mode=ro)",
- "measure_version": "demo-packet-v2",
- "commit_sha": "59744a30bf461a587cc679ee62a432e8cd2cf82a",
- "sample_frame_predicate": "session_refs WHERE kind='pull_request' AND repo='Sinity/polylogue' AND ref_number=3282",
- "run_date": "2026-07-31"
- }
-}
diff --git a/.agent/demos/d1-receipts/queries.ndjson b/.agent/demos/d1-receipts/queries.ndjson
deleted file mode 100644
index a12b8a2619..0000000000
--- a/.agent/demos/d1-receipts/queries.ndjson
+++ /dev/null
@@ -1,5 +0,0 @@
-{"text": "SELECT session_id, repo, ref_number, url FROM session_refs WHERE kind='pull_request' AND repo='Sinity/polylogue' AND ref_number=3282", "lowered_spec": {"unit": "session_ref", "predicate_kind": "structural_equality", "table": "session_refs"}}
-{"text": "find \"id:claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39\" then read --view correlation --format json", "lowered_spec": {"unit": "session", "entry": "id", "view": "correlation"}}
-{"text": "SELECT tool_name, count(*) FROM blocks WHERE session_id='claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39' AND block_type='tool_use' GROUP BY tool_name ORDER BY 2 DESC", "lowered_spec": {"unit": "block", "pipeline_stages": ["group:tool_name", "count"]}}
-{"text": "SELECT tu.block_id, tr.text FROM blocks tu JOIN blocks tr ON tr.tool_id=tu.tool_id AND tr.block_type='tool_result' AND tr.session_id=tu.session_id WHERE tu.session_id='claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39' AND tu.tool_input LIKE '%devtools verify --quick%'", "lowered_spec": {"unit": "block", "predicate_kind": "join_tool_use_to_tool_result"}}
-{"text": "SELECT count(*) FROM blocks WHERE session_id='claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39' AND block_type='tool_use' AND tool_input LIKE '%test_live_batch_support.py%' AND tool_input NOT LIKE '%gh pr create%'", "lowered_spec": {"unit": "block", "predicate_kind": "negative_control_count", "expected_result": 0}}
diff --git a/.agent/demos/d1-receipts/report.md b/.agent/demos/d1-receipts/report.md
deleted file mode 100644
index a3de3d1bf0..0000000000
--- a/.agent/demos/d1-receipts/report.md
+++ /dev/null
@@ -1,153 +0,0 @@
-# D1 "The Receipts": Claim-vs-Evidence on a Real Merged PR
-
-This file is a Demo Finding Packet artifact (`devtools/demo_packet.py`
-`PACKET_FILENAMES` contract), not an agent session summary. It is consumed
-by `devtools lab policy demo-packet-registry` and read by future operators
-reproducing this demo -- it is checked-in repo content, not a report to the
-orchestrating agent.
-
-## Claim
-
-`session_refs` typed `pull_request` evidence resolves a real merged PR to
-its authoring/dispatch session, and specific sentences from that PR's body
-can be checked against the session's own recorded `blocks` -- with claims
-that have no matching evidence marked as such, not silently trusted.
-
-## Corpus
-
-The live archive (`/realm/db/polylogue`, read-only), scoped to one session:
-`claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39`, resolved via
-`session_refs WHERE kind='pull_request' AND repo='Sinity/polylogue' AND
-ref_number=3282`. This is the real, merged PR
-[Sinity/polylogue#3282](https://github.com/Sinity/polylogue/pull/3282)
-("perf(storage): defer FTS repair off the live-ingest write path").
-
-## Method
-
-1. Resolved PR #3282 to a session structurally through `session_refs` (the
- table PR #3425 populated and PR #3431 wired into
- `insights/session_commit.py:build_correlation_result` /
- `insights/correlation_view.py`'s `read --view correlation` surface --
- not a regex/time-window guess).
-2. Fetched the live PR body via `gh pr view 3282 --json body`.
-3. For each individually falsifiable claim in that body, searched the
- resolved session's `blocks` table (`tool_use`/`tool_result` joined by
- `tool_id`) for matching structural evidence.
-4. Recorded each claim's status: `supported` (matching block evidence
- found) or `not_supported` (no matching block, regardless of what the PR
- prose says).
-
-## Findings
-
-Claim-vs-evidence table (full block citations in `evidence.ndjson`):
-
-| # | PR #3282 claim | Evidence found in the session | Status |
-|---|---|---|---|
-| 1 | This session authored/opened the PR | `tool_use` block runs `gh pr create --title "perf(storage): defer FTS repair off the live-ingest write path" --body "..."` with body text byte-identical to the live-fetched PR body; `tool_result` returns `https://github.com/Sinity/polylogue/pull/3282` | **supported** |
-| 2 | "`devtools verify --quick` -- pass (ruff format/check, mypy, render all, topology/layering/...)" | `tool_use` runs `timeout 180 devtools verify --quick`; `tool_result` is a structured run-JSON with every step's `exit` field `0` (17 steps enumerated, `total_duration_s: 32.99`, top-level `exit_code: 0`) | **supported** (structural -- the exit codes, not a trusted "pass" word) |
-| 3 | "`rebuild_index` bulk FTS materialization checkpoints progress (base for #3281, rebased here after that merge)" | `tool_use` runs `devtools test tests/unit/maintenance/test_rebuild_index_bulk_build.py` (+4 more files) in `/realm/worktrees/polylogue-membership-head-provenance`; `tool_result` pytest summary: `123 passed in 8.05s`; a following `git commit` in the same worktree stages exactly `polylogue/maintenance/rebuild_index.py` -- the one file this line's claim is about, matching the PR's own file diff (`polylogue/maintenance/rebuild_index.py 1 1`) | **supported** |
-| 4 | "`devtools test tests/unit/sources/test_live_batch_support.py tests/unit/sources/test_live_catchup_planning.py tests/unit/storage/test_revision_replay.py tests/unit/storage/test_fts_identity_ledger.py tests/unit/storage/test_fts_repair_sql.py tests/unit/storage/test_bulk_fts_prefix_reextract.py tests/unit/daemon/test_daemon_cli.py -- all passing (see individual commit messages for per-commit pass counts)" | That exact 7-file string appears **only** inside the `gh pr create --body` tool_input (i.e. inside the PR body text itself) -- 0 rows when searching this session's `tool_use` blocks for the string with the `gh pr create` block excluded | **not independently verified in this session** |
-
-## Specimens
-
-See `evidence.ndjson` for the full block-id citations behind each row
-above, including the exact `tool_result` text for rows 2 and 3.
-
-## Counterexamples
-
-**Finding 4 is a real, structurally-confirmed gap, not an artifact of
-sloppy search.** The PR body's own parenthetical for that claim --
-"see individual commit messages for per-commit pass counts" -- already
-admits the aggregate 7-file invocation was never run as one shot; this
-session's block evidence confirms it structurally: the string is prose
-inside the PR body draft, never an executed command. This is the intended
-behavior of a claim-vs-evidence packet: a claim the PR body asserts in
-prose, with no matching structural evidence in the resolved session, must
-render as unsupported -- not silently upgraded because the surrounding
-claims (1-3) checked out.
-
-**This session is a merge-conductor, not the file-editing session.**
-`SELECT tool_name, count(*) ... GROUP BY tool_name` over this session's 56
-`tool_use` blocks returns `Bash=53, Read=3` -- zero `Edit`/`Write` blocks.
-The PR's actual code changes were authored in separately dispatched worker
-sessions across several git worktrees
-(`/realm/worktrees/polylogue-membership-head*`); this session orchestrates
-`git`/`gh`/`devtools` across them and opens the PR. `session_refs` correctly
-resolves PR #3282 to *this* session (the one that ran `gh pr create`), which
-is the right target for "which session can I ask about this PR's own
-claims" -- but it is not the right target for "which session edited file
-X", a different (currently unresolved by this packet) question.
-
-## Limits
-
-- This packet checks 4 claims from one PR's body, not every sentence. It is
- a method demonstration (structural claim-vs-evidence resolution through
- `session_refs`), not an audit of PR #3282's full body.
-- This is the **live-archive operator variant** only. The epic's own design
- (`polylogue-212`) calls for two variants per demo: a public seeded-corpus
- reproduction (seed 1843) and a live-archive operator variant. `session_refs`
- `pull_request` rows are a real, provider-native Claude Code capability
- (pr-link sidecar records) that the deterministic seed fixture does not
- currently populate, so the public variant is not built by this packet --
- named as remaining scope in the owning bead (`polylogue-xyel`) rather than
- claimed done here.
-- The multi-worktree merge-conductor pattern found in Finding 4/Counterexamples
- means `session_refs`'s PR-to-session resolution answers "which session
- opened this PR", not "which session wrote this specific line of this
- specific file" -- a real, useful distinction this packet surfaces but does
- not resolve further (that would need session-to-commit-to-worktree
- lineage, which `polylogue-cijx.1`'s notes document as a separate, still-
- open problem for the durable `session_commits` table, unrelated to the
- `session_refs` mechanism this packet exercises).
-
-## Non-claims
-
-- This packet does not prove every sentence in PR #3282's body is
- independently verified -- only the four claims explicitly checked above
- are scored; claim 4 is explicitly scored `not_supported`.
-- This packet does not establish that `session_refs` correctly resolves
- every PR reference archive-wide -- only that it resolves this one case
- with structural evidence.
-- This packet does not reproduce on the public seed corpus (seed 1843); it
- requires read-only access to the live archive and the `Sinity/polylogue`
- GitHub history.
-
-## Reproduce
-
-```bash
-# 1. resolve PR -> session
-sqlite3 "file:/realm/db/polylogue/index.db?mode=ro" \
- "SELECT session_id, repo, ref_number, url FROM session_refs \
- WHERE kind='pull_request' AND repo='Sinity/polylogue' AND ref_number=3282"
-
-# 2. cross-check through the CLI's own correlation surface
-POLYLOGUE_ARCHIVE_ROOT=/realm/db/polylogue POLYLOGUE_FORCE_PLAIN=1 \
- polylogue find "id:claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39" \
- then read --view correlation --format json
-
-# 3. fetch the live PR body
-gh pr view 3282 --repo Sinity/polylogue --json body
-
-# 4. tool_name distribution (merge-conductor finding)
-sqlite3 "file:/realm/db/polylogue/index.db?mode=ro" \
- "SELECT tool_name, count(*) FROM blocks \
- WHERE session_id='claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39' \
- AND block_type='tool_use' GROUP BY tool_name ORDER BY 2 DESC"
-
-# 5. the devtools verify --quick evidence (claim 2)
-sqlite3 "file:/realm/db/polylogue/index.db?mode=ro" \
- "SELECT tr.text FROM blocks tu JOIN blocks tr \
- ON tr.tool_id=tu.tool_id AND tr.block_type='tool_result' AND tr.session_id=tu.session_id \
- WHERE tu.session_id='claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39' \
- AND tu.tool_input LIKE '%devtools verify --quick%'"
-
-# 6. the negative-control count (claim 4 -- must return 0)
-sqlite3 "file:/realm/db/polylogue/index.db?mode=ro" \
- "SELECT count(*) FROM blocks \
- WHERE session_id='claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39' \
- AND block_type='tool_use' AND tool_input LIKE '%test_live_batch_support.py%' \
- AND tool_input NOT LIKE '%gh pr create%'"
-```
-
-See `evidence.ndjson` for every cited ref and `checks.json` for the
-pass/fail summary.
diff --git a/.agent/demos/d1-receipts/run.log b/.agent/demos/d1-receipts/run.log
deleted file mode 100644
index 15407a9ff6..0000000000
--- a/.agent/demos/d1-receipts/run.log
+++ /dev/null
@@ -1,113 +0,0 @@
-=== 1. resolve PR -> session (structural, session_refs) ===
-$ sqlite3 "file:/realm/db/polylogue/index.db?mode=ro" \
- "SELECT session_id, repo, ref_number, url FROM session_refs \
- WHERE kind='pull_request' AND repo='Sinity/polylogue' AND ref_number=3282"
-claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39|Sinity/polylogue|3282|https://github.com/Sinity/polylogue/pull/3282
-
-=== 2. cross-check through the CLI's own correlation surface (production read path) ===
-$ POLYLOGUE_ARCHIVE_ROOT=/realm/db/polylogue POLYLOGUE_FORCE_PLAIN=1 \
- polylogue find "id:claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39" \
- then read --view correlation --format json
-(pr_refs excerpt, one of six duplicate-window matches; source=typed_session_ref proves the
- typed session_refs evidence resolved this, not the regex heuristic)
-{
- "owner": "Sinity",
- "repo": "polylogue",
- "number": 3282,
- "kind": "pr",
- "url": "https://github.com/Sinity/polylogue/pull/3282",
- "raw_match": "https://github.com/Sinity/polylogue/pull/3282",
- "message_id": null,
- "source": "typed_session_ref",
- "object_ref": "github-pr:Sinity/polylogue#3282"
-}
-disagreements: 1 entry -- the regex heuristic path independently found PR numbers
-[3212, 3213, 3214, 3215, 3216, 3217, 3262, 3263, 3264, 3271, 3272, 3278, 3281] in message
-text that are NOT corroborated by typed session_refs evidence for this session -- surfaced
-as a disagreement rather than silently merged into the typed result.
-
-=== 3. fetch the live PR body ===
-$ gh pr view 3282 --repo Sinity/polylogue --json body
-(full body in evidence.ndjson citation for block ae9a4788-...; byte-identical to the
- gh pr create --body tool_input recorded in the session)
-
-=== 4. tool_name distribution over this session's tool_use blocks (merge-conductor finding) ===
-$ sqlite3 "file:/realm/db/polylogue/index.db?mode=ro" \
- "SELECT tool_name, count(*) FROM blocks \
- WHERE session_id='claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39' \
- AND block_type='tool_use' GROUP BY tool_name ORDER BY 2 DESC"
-Bash|53
-Read|3
-
-=== 5. devtools verify --quick evidence (claim 2) ===
-$ sqlite3 "file:/realm/db/polylogue/index.db?mode=ro" \
- "SELECT tr.text FROM blocks tu JOIN blocks tr \
- ON tr.tool_id=tu.tool_id AND tr.block_type='tool_result' AND tr.session_id=tu.session_id \
- WHERE tu.session_id='claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39' \
- AND tu.tool_input LIKE '%devtools verify --quick%'"
-(tail of the structured run-JSON result)
- {
- "name": "verify docs-coverage",
- "duration_s": 2.62,
- "exit": 0,
- "run_id": "20260726T185346Z-quick-611274-f5c7c756"
- },
- {
- "name": "verify test-infra-currency",
- "duration_s": 0.41,
- "exit": 0,
- "run_id": "20260726T185346Z-quick-611274-f5c7c756"
- },
- {
- "name": "verify test-clock-hygiene",
- "duration_s": 2.48,
- "exit": 0,
- "run_id": "20260726T185346Z-quick-611274-f5c7c756"
- },
- {
- "name": "verify pytest-timeout-overrides",
- "duration_s": 4.16,
- "exit": 0,
- "run_id": "20260726T185346Z-quick-611274-f5c7c756"
- },
- {
- "name": "verify degrade-loudly",
- "duration_s": 1.27,
- "exit": 0,
- "run_id": "20260726T185346Z-quick-611274-f5c7c756"
- }
- ],
- "total_duration_s": 32.99,
- "exit_code": 0
-}
-(every step in this run's full JSON has "exit": 0; 17 steps total)
-
-=== 6. rebuild_index test evidence (claim 3) ===
-$ sqlite3 "file:/realm/db/polylogue/index.db?mode=ro" \
- "SELECT tr.text FROM blocks tu JOIN blocks tr \
- ON tr.tool_id=tu.tool_id AND tr.block_type='tool_result' AND tr.session_id=tu.session_id \
- WHERE tu.session_id='claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39' \
- AND tu.tool_input LIKE '%test_rebuild_index_bulk_build.py tests/unit/storage/test_planner_statistics_seed.py tests/unit/storage/test_revision_replay.py%'"
-2 workers [123 items]
-........................................................................ [ 58%]
-................................................... [100%]
-============================= 123 passed in 8.05s ==============================
-ok (12.2s)
-
-=== 7. negative control: the 7-file devtools test invocation (claim 4) ===
-$ sqlite3 "file:/realm/db/polylogue/index.db?mode=ro" \
- "SELECT count(*) FROM blocks \
- WHERE session_id='claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39' \
- AND block_type='tool_use' AND tool_input LIKE '%test_live_batch_support.py%' \
- AND tool_input NOT LIKE '%gh pr create%'"
-0
--- the only match (without the exclusion) is the gh-pr-create block itself, i.e. the string
--- only exists as prose inside the PR body draft, never as an executed command.
-
-=== 8. gh pr create body/URL evidence (claim 1) ===
-$ sqlite3 "file:/realm/db/polylogue/index.db?mode=ro" \
- "SELECT tr.text FROM blocks tu JOIN blocks tr \
- ON tr.tool_id=tu.tool_id AND tr.block_type='tool_result' AND tr.session_id=tu.session_id \
- WHERE tu.session_id='claude-code-session:28407f0f-4f30-4508-b29b-1fd0bc301a39' \
- AND tu.tool_input LIKE '%gh pr create%'"
-https://github.com/Sinity/polylogue/pull/3282
diff --git a/.agent/demos/d4-behavioral-archaeology/NON-CLAIMS.md b/.agent/demos/d4-behavioral-archaeology/NON-CLAIMS.md
deleted file mode 100644
index dc3327fbaa..0000000000
--- a/.agent/demos/d4-behavioral-archaeology/NON-CLAIMS.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# Non-claims
-
-- The fixture counts do not estimate production prevalence, archive scale, or provider-wide behavior.
-- The packet does not prove that semantic search is complete when only 2 of 71 messages have synthetic embeddings.
-- The packet does not prove that a chat UI could never implement equivalent features.
-- The historical 2026-07-09 receipt is not evidence of the current 2026-08-09 run.
diff --git a/.agent/demos/d4-behavioral-archaeology/PROMPT.md b/.agent/demos/d4-behavioral-archaeology/PROMPT.md
deleted file mode 100644
index adc7575c63..0000000000
--- a/.agent/demos/d4-behavioral-archaeology/PROMPT.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# D4 "Behavioral Archaeology": Six DSL Queries, Rapid Fire
-
-Predeclaration receipt: `artifact:d4-behavioral-archaeology-predeclaration`.
-
-Run these six queries against a seeded demo archive (`polylogue demo seed`).
-Each answers a question an engineering lead would ask about their team's AI
-coding sessions — each impossible to answer from a chat UI transcript view.
-Product primitives only (`polylogue` CLI query DSL); no bespoke scripts.
-
-1. **SEQ thrash-loop hunt** — repeated shell-tool calls in a row:
- `polylogue find "sessions where seq(action:shell -> action:shell)" then select --format json`
-2. **Tool call volume** — which tools are actually used:
- `polylogue "actions where exit_code:>=0 | group by tool | count"`
-3. **Which tools break** — failure count by tool:
- `polylogue "actions where is_error:true | group by tool | count"`
-4. **Semantic probe across providers**:
- `polylogue find 'near:"flaky async test"'`
-5. **Time-scoped session population**:
- `polylogue find "since:2y"`
-6. **Pipe a query straight into `read`**:
- `polylogue find "origin:codex-session" then read --first --view messages`
-
-Then show `explain_query_expression` (CLI: `--explain`) once on query 1 to
-prove the query means what it says — the parsed AST, not just prose.
-
-## Note on this run
-
-While authoring query 1 for this specific seeded fixture, running the exact
-same predicate as a bare `find` (no `then` verb) vs `find ... then select`
-produced DIFFERENT results — the bare form silently ignored the filter. This
-is documented as a real finding in `report.md` (counterexamples) and filed
-as its own bug (polylogue-70qb), not hidden. This
-IS the point of the demo: a DSL query surfaces things a chat transcript
-never could — including, in this case, a defect in the query surface
-itself.
diff --git a/.agent/demos/d4-behavioral-archaeology/checks.json b/.agent/demos/d4-behavioral-archaeology/checks.json
deleted file mode 100644
index e6b95bcd4f..0000000000
--- a/.agent/demos/d4-behavioral-archaeology/checks.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "pass": true,
- "unsupported_claims": [],
- "coverage_notes": "All 6 queries and the required explain route executed through polylogue at d23f5dd27a0bda0a9c0a4306ef98c898d4d920ce against a private synthetic seeded demo corpus with 19 sessions and 71 messages. Query 4 returned one hit with only 2 of 71 messages embedded, so the packet does not claim semantic completeness. Query 5 is scoped as a time-filter demonstration, not abandonment classification. The bare-find predicate defect remains explicit and is retained as a historical finding."
-}
diff --git a/.agent/demos/d4-behavioral-archaeology/evidence.ndjson b/.agent/demos/d4-behavioral-archaeology/evidence.ndjson
deleted file mode 100644
index a9509ad3d4..0000000000
--- a/.agent/demos/d4-behavioral-archaeology/evidence.ndjson
+++ /dev/null
@@ -1,12 +0,0 @@
-{"ref": "artifact:d4-behavioral-archaeology-evidence", "cited_for": "Demo Packet v2 receipt root for the fresh run", "verified_via": "committed evidence.ndjson"}
-{"ref": "artifact:d4-behavioral-archaeology-current-run", "cited_for": "Fresh private-data-free six-query and explain receipt at commit d23f5dd27a0bda0a9c0a4306ef98c898d4d920ce", "verified_via": "run.log structured command sections and output digests"}
-{"ref": "codex-session:demo-receipts", "cited_for": "Q1 SEQ thrash-loop match and Q6 piped-read specimen", "verified_via": "current run q1 then select --format json and q6 then read"}
-{"ref": "claude-code-session:63705dcc-f3e5-4378-8118-8bc21e53bbb6", "cited_for": "Q1 SEQ thrash-loop match and Q4 semantic hit", "verified_via": "current run q1 and q4"}
-{"ref": "codex-session:demo-00", "cited_for": "Q1 SEQ thrash-loop match", "verified_via": "current run q1 then select --format json"}
-{"ref": "actions.group_by=tool", "cited_for": "Q2 tool call volume: Bash=9, Read=8, exec_command=3, and six singleton tools", "verified_via": "current run q2 actions where exit_code:>=0 | group by tool | count"}
-{"ref": "actions.group_by=tool.is_error", "cited_for": "Q3 tool failure count: Bash=4, exec_command=2, Edit=1", "verified_via": "current run q3 actions where is_error:true | group by tool | count"}
-{"ref": "embeddings.db:message_embeddings_meta", "cited_for": "Synthetic embedding coverage numerator: 2 messages embedded", "verified_via": "sqlite3 embeddings.db SELECT COUNT(*) FROM message_embeddings_meta"}
-{"ref": "index.db:messages", "cited_for": "Fresh seeded corpus denominator: 71 total messages, making coverage 2/71", "verified_via": "sqlite3 index.db SELECT COUNT(*) FROM messages"}
-{"ref": "since:2y", "cited_for": "Q5 time-scoped population: 13 of 19 sessions", "verified_via": "current run q5 find since:2y"}
-{"ref": "codex-session:demo-receipts", "cited_for": "Q6 piped-read specimen: failed clock test, conflicting claim, edit, and successful recovery", "verified_via": "current run q6 find origin:codex-session then read --first --view messages"}
-{"ref": "polylogue-70qb", "cited_for": "historical counterexample: bare find ignoring sessions-where predicates", "verified_via": "historical packet comparison; current receipt does not relabel it as a fresh command"}
diff --git a/.agent/demos/d4-behavioral-archaeology/finding.yaml b/.agent/demos/d4-behavioral-archaeology/finding.yaml
deleted file mode 100644
index e44f313c7f..0000000000
--- a/.agent/demos/d4-behavioral-archaeology/finding.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-archive_cursor: polylogue-demo-seed-fixture-world
-measure_version: demo-packet-v2
-commit_sha: d23f5dd27a0bda0a9c0a4306ef98c898d4d920ce
-sample_frame_predicate: "all 19 sessions in the private synthetic polylogue demo seed fixture"
-run_date: "2026-08-09"
-current_run_id: run:d4-behavioral-archaeology:20260809T061905Z
-current_run_timestamp: "2026-08-09T06:19:05Z"
-current_route: polylogue
-historical_commit_sha: fdd5ea848
-historical_run_date: "2026-07-09"
-historical_receipt_status: historical-only
-claim: "six DSL queries answer engineering-lead questions about AI coding sessions that no chat UI transcript view can answer, using only existing product primitives"
diff --git a/.agent/demos/d4-behavioral-archaeology/packet.json b/.agent/demos/d4-behavioral-archaeology/packet.json
deleted file mode 100644
index 8c04e72339..0000000000
--- a/.agent/demos/d4-behavioral-archaeology/packet.json
+++ /dev/null
@@ -1,284 +0,0 @@
-{
- "baseline": {
- "method": "Use the recorded simpler comparison path rather than the structural product path.",
- "name": "ordinary transcript browsing",
- "receipts": [
- "artifact:d4-behavioral-archaeology-evidence"
- ],
- "result": "Inspect sessions one by one without structural predicates or grouped action rows."
- },
- "claim": {
- "declared_before_execution": true,
- "receipts": [
- "artifact:d4-behavioral-archaeology-predeclaration"
- ],
- "scope": "the committed 19-session seed fixture and the fresh recorded commands",
- "statement": "The recorded six-query run exercises the documented query primitives against the deterministic demo archive.",
- "status": "supported"
- },
- "controls": {
- "missing_evidence": [
- {
- "expected": "A missing ambient-activity source must remain unsupported rather than inferred from transcript prose.",
- "id": "unsupported-cross-source-control",
- "observed": {
- "status": "not_supported"
- },
- "passed": true,
- "purpose": "Require missing evidence to remain explicit rather than converted into a positive claim.",
- "receipts": [
- "artifact:d4-behavioral-archaeology-evidence"
- ]
- }
- ],
- "negative": [
- {
- "expected": "Sparse embedding coverage must remain an explicit bounded result rather than a completeness claim.",
- "id": "sparse-semantic-control",
- "observed": {
- "semantic_hits": 1,
- "embedded_messages": 2,
- "total_messages": 71
- },
- "passed": true,
- "purpose": "Prevent an adjacent easier signal from being counted as the primary construct.",
- "receipts": [
- "artifact:d4-behavioral-archaeology-evidence"
- ]
- }
- ]
- },
- "falsifier": {
- "condition": "Any recorded query output cannot be reproduced from the deterministic archive or resolves to different cited rows.",
- "evaluation_method": "Apply the stated condition to the structured current-run receipt, committed evidence, and run log.",
- "receipts": [
- "artifact:d4-behavioral-archaeology-evidence"
- ],
- "result": "pass",
- "triggered": false
- },
- "mode": "public",
- "non_claims": [
- "The fixture counts do not estimate production prevalence, archive scale, or provider-wide behavior.",
- "The packet does not prove that semantic search is complete when embeddings are sparse.",
- "The packet does not prove that a chat UI could never implement equivalent features."
- ],
- "oracle": {
- "description": "The command log and cited deterministic rows are independent of the report prose.",
- "expected": {
- "commands_exit_zero": true,
- "query_count": 6,
- "explain_count": 1
- },
- "independent": true,
- "method": "Re-run the exact commands and compare selected refs and grouped counts with evidence.ndjson.",
- "receipts": [
- "artifact:d4-behavioral-archaeology-evidence"
- ]
- },
- "packet_id": "d4-behavioral-archaeology",
- "primary_construct": {
- "id": "query.dsl.composition",
- "product_primitives": [
- "polylogue find",
- "polylogue select",
- "polylogue read",
- "polylogue --explain"
- ],
- "statement": "The query DSL composes structural predicates, aggregations, reads, and explanations over the deterministic archive."
- },
- "provenance": {
- "archive_cursor": "polylogue-demo-seed-fixture-world",
- "commit_sha": "d23f5dd27a0bda0a9c0a4306ef98c898d4d920ce",
- "measure_version": "demo-packet-v2",
- "run_date": "2026-08-09",
- "sample_frame_predicate": "all 19 sessions in the private synthetic deterministic demo archive",
- "current_run": {
- "run_id": "run:d4-behavioral-archaeology:20260809T061905Z",
- "run_timestamp": "2026-08-09T06:19:05Z",
- "code_sha": "d23f5dd27a0bda0a9c0a4306ef98c898d4d920ce",
- "route": "polylogue",
- "archive_kind": "private synthetic seeded demo archive",
- "private_data": false,
- "run_log": "run.log",
- "commands": [
- {
- "id": "q1",
- "section": "Q1: SEQ thrash-loop hunt (repeated shell calls)",
- "command": "polylogue find \"sessions where seq(action:shell -> action:shell)\" then select --format json",
- "exit_code": 0,
- "output_sha256": "56a4b8a11a6be71ece8096b79be1bbc389d4235375a67fb841b30e5ee1df7ad4"
- },
- {
- "id": "q2",
- "section": "Q2: tool call volume by tool",
- "command": "polylogue \"actions where exit_code:>=0 | group by tool | count\"",
- "exit_code": 0,
- "output_sha256": "ec80035d0e7c46e434bb26f1efe857478a758dc6e37c3196c26064a1ed3f0c2f"
- },
- {
- "id": "q3",
- "section": "Q3: which tools break (failure count by tool)",
- "command": "polylogue \"actions where is_error:true | group by tool | count\"",
- "exit_code": 0,
- "output_sha256": "d74af1611854d6cd7f24f925b4de02b9d3388811b0c97390d8e6ab9fddd55e30"
- },
- {
- "id": "q4",
- "section": "Q4: near: semantic probe across providers",
- "command": "polylogue find 'near:\"flaky async test\"'",
- "exit_code": 0,
- "output_sha256": "86fbc77cdb0c9124a085a5db7339c63ed584d417c9b92d6e69c4d59dbf45b764"
- },
- {
- "id": "q5",
- "section": "Q5: time-scoped session population (last 2 years)",
- "command": "polylogue find \"since:2y\"",
- "exit_code": 0,
- "output_sha256": "c12d4efd26b669dee3ac46a41b9c2265a41dee4164b70c76449590d7eb85fc0a"
- },
- {
- "id": "q6",
- "section": "Q6: query piped into read",
- "command": "polylogue find \"origin:codex-session\" then read --first --view messages",
- "exit_code": 0,
- "output_sha256": "c6a11526af70310fbde28756bde722d635e4da2d7b61140c16ba8a0ac524f6d8"
- }
- ],
- "explain": {
- "section": "--explain demonstration (Q1)",
- "command": "polylogue --explain find \"sessions where seq(action:shell -> action:shell)\"",
- "exit_code": 0,
- "output_sha256": "9f2a3e107ff5c3dd34731d8606ced970379915b6adbd89d8f93da02486e98dc0"
- }
- },
- "historical_receipt": {
- "commit_sha": "fdd5ea848",
- "run_date": "2026-07-09",
- "status": "historical-only",
- "description": "Original D4 receipt retained only as historical context; it is not the current reproduction."
- }
- },
- "receipts": [
- {
- "artifact_path": "evidence.ndjson",
- "description": "Committed evidence rows and references for this packet.",
- "kind": "artifact",
- "ref": "artifact:d4-behavioral-archaeology-evidence",
- "resolved": true,
- "sha256": "799d7ea9914e7c59cca908a65612b0479322e737fb26766b2296eee08790b3a3"
- },
- {
- "artifact_path": "PROMPT.md",
- "description": "The committed prompt that states the packet claim before execution.",
- "kind": "artifact",
- "ref": "artifact:d4-behavioral-archaeology-predeclaration",
- "resolved": true,
- "sha256": "478e73d60135183895f680e0adbbd961527510d9f56b1a3795989776e5ca65d2"
- },
- {
- "artifact_path": "run.log",
- "description": "Fresh private seeded six-query and explain receipt at the current code SHA.",
- "kind": "artifact",
- "ref": "artifact:d4-behavioral-archaeology-current-run",
- "resolved": true,
- "sha256": "4234c64ea92e637f803bee6a455e08b048ca7a9e01078768585115c0a8bd42d4"
- }
- ],
- "reproduction": {
- "commands": [
- "polylogue demo seed --root /private/synthetic/demo-archive --force",
- "polylogue demo verify --root /private/synthetic/demo-archive --format json",
- "polylogue find \"sessions where seq(action:shell -> action:shell)\" then select --format json",
- "polylogue \"actions where exit_code:>=0 | group by tool | count\"",
- "polylogue \"actions where is_error:true | group by tool | count\"",
- "polylogue find 'near:\"flaky async test\"'",
- "polylogue find \"since:2y\"",
- "polylogue find \"origin:codex-session\" then read --first --view messages",
- "polylogue --explain find \"sessions where seq(action:shell -> action:shell)\""
- ],
- "deterministic": true,
- "fixture": "polylogue demo seed private synthetic fixture",
- "private_data": false
- },
- "results": {
- "measurements": [
- {
- "name": "recorded_query_commands",
- "receipts": [
- "artifact:d4-behavioral-archaeology-current-run"
- ],
- "unit": "commands",
- "value": 6
- },
- {
- "name": "seeded_sessions",
- "receipts": [
- "artifact:d4-behavioral-archaeology-current-run"
- ],
- "unit": "sessions",
- "value": 19
- },
- {
- "name": "seeded_messages",
- "receipts": [
- "artifact:d4-behavioral-archaeology-current-run"
- ],
- "unit": "messages",
- "value": 71
- },
- {
- "name": "q1_sequence_matches",
- "receipts": [
- "artifact:d4-behavioral-archaeology-current-run"
- ],
- "unit": "sessions",
- "value": 3
- },
- {
- "name": "q2_successful_actions",
- "receipts": [
- "artifact:d4-behavioral-archaeology-current-run"
- ],
- "unit": "actions",
- "value": 26
- },
- {
- "name": "q3_failed_actions",
- "receipts": [
- "artifact:d4-behavioral-archaeology-current-run"
- ],
- "unit": "actions",
- "value": 7
- },
- {
- "name": "q4_semantic_hits",
- "receipts": [
- "artifact:d4-behavioral-archaeology-current-run"
- ],
- "unit": "sessions",
- "value": 1
- },
- {
- "name": "q5_time_scoped_sessions",
- "receipts": [
- "artifact:d4-behavioral-archaeology-current-run"
- ],
- "unit": "sessions",
- "value": 13
- },
- {
- "name": "synthetic_embedding_messages",
- "receipts": [
- "artifact:d4-behavioral-archaeology-evidence"
- ],
- "unit": "messages",
- "value": 2
- }
- ],
- "status": "pass",
- "summary": "A fresh private seeded run at the exact current SHA exercised all six query surfaces and one explain route; observed counts and the bare-find defect remain explicit."
- },
- "schema_version": "2.0.0",
- "title": "Behavioral archaeology DSL packet"
-}
diff --git a/.agent/demos/d4-behavioral-archaeology/queries.ndjson b/.agent/demos/d4-behavioral-archaeology/queries.ndjson
deleted file mode 100644
index 35ba2d9c6d..0000000000
--- a/.agent/demos/d4-behavioral-archaeology/queries.ndjson
+++ /dev/null
@@ -1,6 +0,0 @@
-{"id": "q1", "text": "sessions where seq(action:shell -> action:shell)", "then": "select --format json", "historical_receipt": "then select --json (retired alias, historical only)", "current_run_id": "run:d4-behavioral-archaeology:20260809T061905Z", "lowered_spec": {"unit": "session", "entry": "boolean", "predicate_kind": "sequence"}}
-{"id": "q2", "text": "actions where exit_code:>=0 | group by tool | count", "current_run_id": "run:d4-behavioral-archaeology:20260809T061905Z", "lowered_spec": {"unit": "action", "pipeline_stages": ["group:tool", "count"]}}
-{"id": "q3", "text": "actions where is_error:true | group by tool | count", "current_run_id": "run:d4-behavioral-archaeology:20260809T061905Z", "lowered_spec": {"unit": "action", "pipeline_stages": ["group:tool", "count"]}}
-{"id": "q4", "text": "near:\"flaky async test\"", "current_run_id": "run:d4-behavioral-archaeology:20260809T061905Z", "lowered_spec": {"unit": "session", "entry": "compact", "retrieval_lane": "dialogue"}}
-{"id": "q5", "text": "since:2y", "current_run_id": "run:d4-behavioral-archaeology:20260809T061905Z", "lowered_spec": {"unit": "session", "entry": "compact"}}
-{"id": "q6", "text": "origin:codex-session", "then": "read --first --view messages", "current_run_id": "run:d4-behavioral-archaeology:20260809T061905Z", "lowered_spec": {"unit": "session", "entry": "compact"}}
diff --git a/.agent/demos/d4-behavioral-archaeology/report.md b/.agent/demos/d4-behavioral-archaeology/report.md
deleted file mode 100644
index 0b6e54b390..0000000000
--- a/.agent/demos/d4-behavioral-archaeology/report.md
+++ /dev/null
@@ -1,63 +0,0 @@
-# D4 "Behavioral Archaeology": Six DSL Queries, Rapid Fire
-
-## Claim
-
-Six DSL queries answer engineering-lead questions about AI coding sessions that no chat UI transcript view answers from a saved transcript alone, using only existing product primitives (`polylogue` CLI query DSL), with no bespoke scripts.
-
-## Corpus
-
-The fresh private-data-free run used the deterministic `polylogue demo seed` fixture at `run:d4-behavioral-archaeology:20260809T061905Z`. It contained 19 sessions, 71 messages, and 2 synthetic message embeddings. The command receipt was captured at commit `d23f5dd27a0bda0a9c0a4306ef98c898d4d920ce` on 2026-08-09.
-
-## Method
-
-The seed and verification steps ran against a throwaway private synthetic archive. Each of the six PROMPT.md commands then ran once through the `polylogue` CLI, followed by the required `polylogue --explain` route for Q1. `run.log` records each exact command, output, exit code, and output digest. The packet validator cross-checks those structured fields. The older 2026-07-09 receipt at `fdd5ea848` is retained only as historical context.
-
-## Findings
-
-1. **SEQ thrash-loop hunt**: `seq(action:shell -> action:shell)` finds 3 sessions with consecutive shell-tool calls: `codex-session:demo-receipts`, `claude-code-session:63705dcc-...`, and `codex-session:demo-00`. The current command uses `then select --format json`. The older `then select --json` spelling appears only in clearly labeled historical-receipt fields.
-2. **Tool call volume**: the current run reports 26 successful actions: Bash 9, Read 8, exec_command 3, and one each for Edit, Task, Write, apply_patch, read_file, and run_check.
-3. **Which tools break**: the current run reports 7 failed actions: Bash 4, exec_command 2, and Edit 1.
-4. **Semantic probe across providers**: `near:"flaky async test"` returns one result, a Claude Code session with the synthetic fixture message "I will inspect the generated fixture and adjust the next command." Only 2 of 71 messages have synthetic embeddings, so this result does not establish complete semantic coverage.
-5. **Time-scoped session population**: `since:2y` lists 13 of 19 sessions. This demonstrates time filtering only. It does not reproduce the severity or resumability scoring of `find_abandoned_sessions`.
-6. **Query piped into `read`**: `find 'origin:codex-session' then read --first --view messages` renders `codex-session:demo-receipts`, including a failed clock test command with exit code 1, a conflicting success claim, an `apply_patch`, and a later successful test result.
-
-## Specimens
-
-See `evidence.ndjson` for the cited session, action, embedding, and current-run references. The current command and output mapping is in `packet.json.provenance.current_run` and is independently bound to `run.log` by output digests.
-
-## Counterexamples
-
-The original D4 work also recorded a real defect: the bare command `polylogue find "sessions where seq(action:shell -> action:shell)"` ignored the explicit predicate and returned the full session set. That historical comparison remains documented as `polylogue-70qb`. It is not presented as a newly executed command in this receipt, and the retired `then select --json` alias is retained only as historical receipt text.
-
-## Limits
-
-- This is a deterministic seeded demo corpus, not the live archive. The 19-session and 71-message counts are illustrative and do not estimate production prevalence, archive scale, or provider-wide behavior.
-- The semantic result is bounded by 2 synthetic embeddings out of 71 messages. It does not prove semantic search completeness.
-- The time query demonstrates filtering only. It does not replicate `find_abandoned_sessions` severity or resumability scoring.
-- The packet records a current run and a historical receipt. The historical receipt is not evidence for the current code SHA.
-
-## Non-claims
-
-- The fixture counts do not estimate production prevalence, archive scale, or provider-wide behavior.
-- The packet does not prove that semantic search is complete when embeddings are sparse.
-- The packet does not prove that a chat UI could never implement equivalent features.
-
-## Reproduce
-
-```bash
-polylogue demo seed --root /path/to/private-synthetic-demo-archive --force
-export POLYLOGUE_ARCHIVE_ROOT=/path/to/private-synthetic-demo-archive
-export POLYLOGUE_FORCE_PLAIN=1
-
-polylogue find 'sessions where seq(action:shell -> action:shell)' then select --format json
-polylogue 'actions where exit_code:>=0 | group by tool | count'
-polylogue 'actions where is_error:true | group by tool | count'
-polylogue find 'near:"flaky async test"'
-polylogue find 'since:2y'
-polylogue find 'origin:codex-session' then read --first --view messages
-
-# --explain demonstration
-polylogue --explain find 'sessions where seq(action:shell -> action:shell)'
-```
-
-See `run.log` for the exact current output of every command above. The packet's current-run receipt identifies the exact code SHA, UTC timestamp, production route, private synthetic archive class, command mapping, and output hashes.
diff --git a/.agent/demos/d4-behavioral-archaeology/run.log b/.agent/demos/d4-behavioral-archaeology/run.log
deleted file mode 100644
index 2931d16826..0000000000
--- a/.agent/demos/d4-behavioral-archaeology/run.log
+++ /dev/null
@@ -1,236 +0,0 @@
-RUN_ID=run:d4-behavioral-archaeology:20260809T061905Z
-RUN_COMMANDS_STARTED_UTC=2026-08-09T06:19:05Z
-RUN_TIMESTAMP_UTC=2026-08-09T06:19:05Z
-HEAD_SHA=d23f5dd27a0bda0a9c0a4306ef98c898d4d920ce
-ROUTE=polylogue
-ARCHIVE_KIND=private synthetic seeded demo archive
-PRIVATE_DATA=false
-RECEIPT_REF=artifact:d4-behavioral-archaeology-current-run
-=== Q1: SEQ thrash-loop hunt (repeated shell calls) ===
-$ polylogue find "sessions where seq(action:shell -> action:shell)" then select --format json
-[{"id":"codex-session:demo-receipts","origin":"codex-session","title":"Fix the clock-sensitive test and prove the suite passes.","date":"2026-07-04"},{"id":"claude-code-session:63705dcc-f3e5-4378-8118-8bc21e53bbb6","origin":"claude-code-session","title":"synthetic-46324 syntheti","date":"2024-11-02"},{"id":"codex-session:demo-00","origin":"codex-session","title":"Could you review this code for potential issues?","date":"2024-01-23"}]
-Q1_EXIT_CODE=0
-=== Q2: tool call volume by tool ===
-$ polylogue "actions where exit_code:>=0 | group by tool | count"
-tool=Bash count=9
-tool=Read count=8
-tool=exec_command count=3
-tool=Edit count=1
-tool=Task count=1
-tool=Write count=1
-tool=apply_patch count=1
-tool=read_file count=1
-tool=run_check count=1
-Q2_EXIT_CODE=0
-=== Q3: which tools break (failure count by tool) ===
-$ polylogue "actions where is_error:true | group by tool | count"
-tool=Bash count=4
-tool=exec_command count=2
-tool=Edit count=1
-Q3_EXIT_CODE=0
-=== Q4: near: semantic probe across providers ===
-$ polylogue find 'near:"flaky async test"'
-1. claude-code-session synthetic-46324 syntheti I will inspect the generated fixture and adjust the next command.
-Q4_EXIT_CODE=0
-=== Q5: time-scoped session population (last 2 years) ===
-$ polylogue find "since:2y"
-codex-session:demo-recei 2026-07-04 codex-session Fix the clock-sensitive test and prove the suit... (10 msgs)
-codex-session:demo-anti- 2026-07-04 codex-session Explain error budgets without running a command. (2 msgs)
-codex-session:demo-termi 2026-07-04 codex-session Run the command and stop if it fails. (4 msgs)
-claude-code-session:demo 2026-07-04 claude-code-session Run a sidechain check for the deterministic dem... (2 msgs)
-claude-code-session:demo 2026-07-04 claude-code-session Fix the flaky clock test before continuing the... (4 msgs)
-hermes-session:demo-00 2026-07-04 hermes-session 5 msgs · 2026-07-04 (5 msgs)
-codex-session:demo-linea 2026-07-04 codex-session Map the demo lineage base context. (3 msgs)
-antigravity-session:demo 2026-07-04 antigravity-session Antigravity demo cascade (2 msgs)
-gemini-cli-session:demo- 2026-07-04 gemini-cli-session 1 file · 2 msgs · 2026-07-04 (2 msgs)
-chatgpt-export:cross-mat 2026-07-04 chatgpt-export Flaky clock test fix summary (2 msgs)
-chatgpt-export:cross-mat 2026-07-04 chatgpt-export Flaky clock test fix summary (2 msgs)
-claude-ai-export:demo-te 2026-07-04 claude-ai-export Temporary demo context check (2 msgs)
-claude-code-session:6370 2024-11-02 claude-code-session synthetic-46324 syntheti (12 msgs)
-Q5_EXIT_CODE=0
-=== Q6: query piped into read ===
-$ polylogue find "origin:codex-session" then read --first --view messages
-### Lineage boundary · unknown
-
-- session: `session:codex-session:demo-receipts`
-
-- authority: `session_row`
-
-- availability: `unavailable`
-
-- relation: `unknown`
-
-- composed transcript: `complete`
-
-- evidence: `session:codex-session:demo-receipts`, `provider:codex`, `origin:codex-session`
-
-> Caveat: root identity is unavailable from this bounded lineage authority
-
-> Caveat: the structural lineage relation is unknown
-
----
-
-**user · message** · `text` · `message:codex-session:demo-receipts:n:receipts-u0`, `provider:codex`, `origin:codex-session`, `material:human_authored`, `block:codex-session:demo-receipts:n:receipts-u0:0`, `occurred-at:2026-07-04T14:32:01+00:00`, `duration-ms:0`, `variant:0`, `active-path:true`, `active-leaf:false`
-
-Fix the clock-sensitive test and prove the suite passes.
-
----
-
-### Shell command · FAILED
-
-- tool: `exec_command`
-
-- semantic family: `shell`
-
-- classification: `persisted_semantic_type`
-
-- duration: `0 ms`
-
-- command: `pytest tests/test_clock.py -q`
-
-- evidence: `session:codex-session:demo-receipts`, `provider:codex`, `origin:codex-session`, `message:codex-session:demo-receipts:n:fc-receipts-test-fail`, `block:codex-session:demo-receipts:n:fc-receipts-test-fail:0`, `tool:exec_command`, `tool-id:call-receipts-test-fail`, `material:assistant_authored`, `duration-ms:0`, `parent-message:codex-session:demo-receipts:n:receipts-u0`, `variant:0`, `active-path:true`, `active-leaf:false`, `result-message:codex-session:demo-receipts:n:call-receipts-test-fail`, `result-block:codex-session:demo-receipts:n:call-receipts-test-fail:0`, `result-duration-ms:0`, `result-material:tool_result`
-
-- structural outcome: `failed`, `is_error=true`, `exit_code=1`
-
-**output**
-
-```text
-{"metadata": {"exit_code": 1}, "output": "F tests/test_clock.py::test_uses_monotonic_clock\n1 failed in 0.18s"}
-```
-
----
-
-**assistant · message** · `text` · `message:codex-session:demo-receipts:n:receipts-a-claim`, `provider:codex`, `origin:codex-session`, `material:assistant_authored`, `block:codex-session:demo-receipts:n:receipts-a-claim:0`, `occurred-at:2026-07-04T14:32:04+00:00`, `duration-ms:0`, `parent-message:codex-session:demo-receipts:n:call-receipts-test-fail`, `variant:0`, `active-path:true`, `active-leaf:false`
-
-All tests pass. The clock fix is complete.
-
----
-
-**user · message** · `text` · `message:codex-session:demo-receipts:n:receipts-u1`, `provider:codex`, `origin:codex-session`, `material:human_authored`, `block:codex-session:demo-receipts:n:receipts-u1:0`, `occurred-at:2026-07-04T14:32:05+00:00`, `duration-ms:0`, `parent-message:codex-session:demo-receipts:n:receipts-a-claim`, `variant:0`, `active-path:true`, `active-leaf:false`
-
-The receipt disagrees. Correct the fixture and verify again.
-
----
-
-### File edit · succeeded
-
-- tool: `apply_patch`
-
-- semantic family: `file_edit`
-
-- classification: `persisted_semantic_type`
-
-- duration: `0 ms`
-
-- evidence: `session:codex-session:demo-receipts`, `provider:codex`, `origin:codex-session`, `message:codex-session:demo-receipts:n:fc-receipts-edit`, `block:codex-session:demo-receipts:n:fc-receipts-edit:0`, `tool:apply_patch`, `tool-id:call-receipts-edit`, `material:assistant_authored`, `duration-ms:0`, `parent-message:codex-session:demo-receipts:n:receipts-u1`, `variant:0`, `active-path:true`, `active-leaf:false`, `result-message:codex-session:demo-receipts:n:call-receipts-edit`, `result-block:codex-session:demo-receipts:n:call-receipts-edit:0`, `result-duration-ms:0`, `result-material:tool_result`
-
-- structural outcome: `succeeded`, `is_error=false`, `exit_code=0`
-
-**diff**
-
-```diff
-*** Begin Patch
-*** Update File: tests/test_clock.py
-@@
-- shared_clock
-+ isolated_clock
-*** End Patch
-```
-
-**result**
-
-```text
-{"metadata": {"exit_code": 0}, "output": "Done!"}
-```
-
-> Caveat: no exact path field is present in tool input
-
----
-
-### Shell command · succeeded
-
-- tool: `exec_command`
-
-- semantic family: `shell`
-
-- classification: `persisted_semantic_type`
-
-- duration: `0 ms`
-
-- command: `pytest tests/test_clock.py -q`
-
-- evidence: `session:codex-session:demo-receipts`, `provider:codex`, `origin:codex-session`, `message:codex-session:demo-receipts:n:fc-receipts-test-pass`, `block:codex-session:demo-receipts:n:fc-receipts-test-pass:0`, `tool:exec_command`, `tool-id:call-receipts-test-pass`, `material:assistant_authored`, `duration-ms:0`, `parent-message:codex-session:demo-receipts:n:call-receipts-edit`, `variant:0`, `active-path:true`, `active-leaf:false`, `result-message:codex-session:demo-receipts:n:call-receipts-test-pass`, `result-block:codex-session:demo-receipts:n:call-receipts-test-pass:0`, `result-duration-ms:0`, `result-material:tool_result`
-
-- structural outcome: `succeeded`, `is_error=false`, `exit_code=0`
-
-**output**
-
-```text
-{"metadata": {"exit_code": 0}, "output": ". 1 passed in 0.16s"}
-```
-
----
-
-**assistant · message** · `text` · `message:codex-session:demo-receipts:n:receipts-a-verified`, `provider:codex`, `origin:codex-session`, `material:assistant_authored`, `block:codex-session:demo-receipts:n:receipts-a-verified:0`, `occurred-at:2026-07-04T14:32:10+00:00`, `duration-ms:0`, `parent-message:codex-session:demo-receipts:n:call-receipts-test-pass`, `variant:0`, `active-path:true`, `active-leaf:true`
-
-Verified after the correction: 1 passed in 0.16s.
-Q6_EXIT_CODE=0
-=== --explain demonstration (Q1) ===
-$ polylogue --explain find "sessions where seq(action:shell -> action:shell)"
-query: sessions where seq(action:shell -> action:shell)
-lowerer: lark-query-expression-to-session-query-spec
-units: action, session
-execution legs: sequence-action
-predicate:
-{
- "actions": [
- "shell",
- "shell"
- ],
- "kind": "sequence",
- "steps": [
- {
- "field": "action",
- "field_ref": {
- "name": "action",
- "scope": "unit",
- "source_name": "action",
- "unit": "action"
- },
- "kind": "field",
- "op": "=",
- "values": [
- "shell"
- ]
- },
- {
- "field": "action",
- "field_ref": {
- "name": "action",
- "scope": "unit",
- "source_name": "action",
- "unit": "action"
- },
- "kind": "field",
- "op": "=",
- "values": [
- "shell"
- ]
- }
- ],
- "unit": "action"
-}
-lowering plan:
-{
- "execution_legs": [
- "sequence-action"
- ],
- "lowerer": "lark-query-expression-to-session-query-spec",
- "plan_description": [],
- "selected_units": [
- "action",
- "session"
- ]
-}
-EXPLAIN_EXIT_CODE=0
-RUN_COMMANDS_FINISHED_UTC=2026-08-09T06:20:16Z
diff --git a/.agent/demos/registry.json b/.agent/demos/registry.json
deleted file mode 100644
index 367c242533..0000000000
--- a/.agent/demos/registry.json
+++ /dev/null
@@ -1,45 +0,0 @@
-[
- {
- "slug": "packet-contract-stub",
- "prompt_path": ".agent/demos/_packet-contract-stub/PROMPT.md",
- "packet_dir": ".agent/demos/_packet-contract-stub",
- "mode": "fixture",
- "required_primitives": [
- "polylogue demo seed",
- "polylogue find"
- ]
- },
- {
- "slug": "d4-behavioral-archaeology",
- "prompt_path": ".agent/demos/d4-behavioral-archaeology/PROMPT.md",
- "packet_dir": ".agent/demos/d4-behavioral-archaeology",
- "mode": "public",
- "required_primitives": [
- "polylogue demo seed",
- "polylogue find",
- "polylogue --explain",
- "polylogue read",
- "polylogue select"
- ]
- },
- {
- "slug": "d1-receipts",
- "prompt_path": ".agent/demos/d1-receipts/PROMPT.md",
- "packet_dir": ".agent/demos/d1-receipts",
- "mode": "private",
- "required_primitives": [
- "session_refs",
- "polylogue find",
- "polylogue read --view correlation"
- ]
- },
- {
- "slug": "anti-demo-multi-source-reconstruction",
- "prompt_path": ".agent/demos/anti-demo-multi-source-reconstruction/PROMPT.md",
- "packet_dir": ".agent/demos/anti-demo-multi-source-reconstruction",
- "mode": "anti-demo",
- "required_primitives": [
- "schema inspection (grep over archive_tiers DDL)"
- ]
- }
-]
diff --git a/.agent/demos/uplift-two-arm/README.md b/.agent/demos/uplift-two-arm/README.md
deleted file mode 100644
index a6ce2f49a6..0000000000
--- a/.agent/demos/uplift-two-arm/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Handoff-Pack Uplift Experiment
-
-This shelf is for current two-arm experiments that test whether bounded
-Polylogue handoff packets improve continuation reconstruction compared with a
-raw archive reference.
-
-The shelf is current, not append-only. Regenerate or replace `current/` when a
-better protocol or cleaner run exists.
-
-## Current run (2026-07-09, n=5 pilot)
-
-Successor to the n=1 `jxe`/`jxe.2` pilot (raw-ref 8/10 vs handoff-pack 5/10,
-diagnostic-negative, attributed to packet staleness). See `current/report.md`
-for the full write-up: n=5 pairs, handoff-pack wins 4/5, directional but
-explicitly **not** a publishable result (protocol calls for n>=12-20). One
-pair's blind was compromised and is documented rather than discarded; one
-pair is a genuine counterexample where the pack arm asserted a false fact
-with high confidence. Cold-reader gate: PASS.
diff --git a/.agent/demos/uplift-two-arm/current/arms/pair1-handoff-pack-output.md b/.agent/demos/uplift-two-arm/current/arms/pair1-handoff-pack-output.md
deleted file mode 100644
index 672f02d18f..0000000000
--- a/.agent/demos/uplift-two-arm/current/arms/pair1-handoff-pack-output.md
+++ /dev/null
@@ -1,59 +0,0 @@
-# Devloop Reconstruction Report — polylogue @ 91eb09549
-
-## (a) Current devloop state
-
-The devloop has been executing a long, disciplined merge train (11+ squash-merged PRs in the last few hours: #2588–#2604), alternating between real correctness fixes and investigation/bookkeeping. Verified via `git log --oneline -15`:
-
-- `91eb09549` close polylogue-4ts.6 (#2604)
-- `c06ca601c` feat(lineage): surface a completeness signal on composed reads (#2603)
-- `1d7d79ed2`/`6c12e9234` close polylogue-cpf.1 / timestamp-doctrine lint (#2601-2602)
-- `9f0e77116`/`7b5a5aa05` actions-view fan-out fix + close xnkf (#2597-2598)
-- `aa4a520b4` record 4ts.3 investigation findings, unclaim (#2596)
-- `ccd5cfdd5`/`086171701` close 4ts.4 / lineage read-transaction fix (#2594-2595)
-- `f7c997386` record 1vpm.1 investigation findings, unclaim (#2593)
-- `43d7fdf9b`/`64c079d6e` close 212.8 / honesty anti-demo (#2591-2592)
-
-This matches the pack's shipped-work list exactly and extends it one item further (`c06ca601c`, a lineage completeness signal, landed after the pack was generated).
-
-**Delivery gate board** (`.agent/tools/delivery-gate-status.py --fresh`), the authoritative frontier view:
-
-```
-A-trust-floor 23% closed 14 | ready 43 | blocked 3 <- frontier
-B-storage-rebuild-bytes 4% closed 1 | ready 19 | blocked 3
-F-lineage-compaction 17% closed 2 | ready 3 | blocked 7
-I-analytics-experiments 0% closed 0 | wip 1 (1vpm.1) | ready 9 | blocked 20
-L-external-legibility 13% closed 4 | ready 20 | blocked 6
-```
-
-A-trust-floor is the named frontier lane and is the biggest one still open (43 ready items), mostly the `polylogue-9e5.*` read-only audit family (coverage economics, dead-code sweeps, hash-boundary census, etc.) — this is exactly the "trust-floor P1s" the operator's `/goal` names.
-
-## (b) Open threads found
-
-1. **polylogue-1vpm.1 — live/committed state mismatch.** The last committed jsonl record (`f7c997386`, "record findings, unclaim") sets `status:"open"`. But `bd show polylogue-1vpm.1 --json` right now reports `status:"in_progress"`, `assignee:"Sinity"`, `updated_at: 2026-07-09T03:24:19Z` — a timestamp with **no corresponding commit** touching that bead in `.beads/issues.jsonl` history. This means the live embedded-dolt DB has state ahead of the last export/commit (some claim happened that hasn't been exported+committed yet). Not something I should "fix" here, but worth flagging before anyone else claims it — the committed bookkeeping record and the live DB disagree.
-2. **F-lineage-compaction ready set is exactly 3 items**: `polylogue-4ts` (epic), `polylogue-4ts.3` (investigated, fix location known), `polylogue-4ts.5` (fresh, "compaction boundary-range columns + effective-context derivation" — not yet investigated).
-3. **B-storage-rebuild-bytes ready set** includes `83u.2` (re-investigated/reframed to the "bytes reachable but not fetched" subset, per commit `6796ac1ed`) and `83u.3` ("preserve uploaded attachment bytes in live browser capture" — fresh, untouched).
-4. **212.x demo-unlock parallel set**: 212.1/212.3/212.5/212.6 remain open with no assignee; per the pack each has its own blocker (deep interpretive read / missing join primitive / live stagecraft / classifier bug); none looked trivially unblockable from what I can see in their notes (no blocker detail beyond the delivery-upgrade boilerplate), so I did not find a shortcut through any of them.
-5. **pj8** depends on `37t.4` (SessionStart preamble rollout) which is itself gated on real MCP-hook-wiring code, not just deployment — it's `open`, unclaimed, priority 3, and the pack says it's now "authorized" for the hook wiring step, but actually landing it still implies a SessionStart hook change that the pack says needs redeploy to prove — consistent with "postpone" guidance.
-6. **3tl** — confirmed still fully untouched (17 open children), and independently confirmed P4/docs-marketing in this pass (no evidence contradicting the pack).
-7. **cfk** — this very context-pack handoff is explicitly part of the live paired-arm uplift experiment it depends on; I was told not to read `.agent/demos/uplift-two-arm/`, so I can't and shouldn't try to advance or grade that experiment from inside it.
-
-## (c) Recommended next action
-
-**Claim and implement `polylogue-4ts.3`** — "Distinguish subagent auto-compaction from main-session acompact."
-
-Reasoning:
-- It is explicitly named as part of the "lineage epic" the operator's goal calls out, and is one of only 3 ready items left in F-lineage-compaction (the epic is 17% closed, actively being worked this session — `4ts.4`/`4ts.6` just shipped).
-- Unlike `1vpm.1` (comparable in size to `svfj`, a multi-surface feature — new query unit, new column, new registered `target_kind`) or `4ts.5` (still needs fresh investigation), `4ts.3` already has a completed, verified investigation on the bead itself, with an exact fix location I independently confirmed still exists at HEAD:
- - `polylogue/sources/dispatch.py:354` `_claude_code_grouped_record_specs`
- - `polylogue/sources/dispatch.py:441` `_claude_code_stream_sessions`
- - Both are called from the dispatch layer (lines 541, 831) and are the layer with visibility into sibling session-group content needed to distinguish subagent self-compaction from main-session `acompact`.
-- It requires no redeploy/MCP-reboot (unlike pj8/37t.4) and no live paired-arm experiment (unlike cfk).
-- It's a real correctness bug (misattributed parent session on ~39/187 affected files per the GH thread cited in the bead), not read-only analysis, so it continues today's demonstrated pattern of shipping concrete lineage-correctness fixes rather than accumulating more audit-lane findings on top of the already-large 43-item A-trust-floor backlog.
-
-Secondary/fallback candidates if `4ts.3` turns out blocked on something I couldn't see (e.g. a fixture gap): `polylogue-83u.3` (fresh, unclaimed, in the storage-rebuild-bytes lane) or one of the trust-floor `9e5.*` P1 audits (e.g. `polylogue-9e5.6`, hash-boundary census — the closest literal match to "storage identity" in the operator's phrasing).
-
-## (d) Confidence and evidence
-
-**Confidence: high** on devloop state and gate-board numbers (directly queried live `bd`/git, not inferred from the pack); **medium-high** on the `4ts.3` recommendation (its investigation note is detailed and the code anchors check out, but I have not read the full GH issue thread it references, nor written/run the fix itself); **medium** on the `1vpm.1` state-mismatch finding (clearly true from the data, but I don't know *why* — could be an uncommitted claim from a concurrent session, consistent with this repo's documented shared-checkout/multi-session risk).
-
-Evidence used: `git log --oneline` / `git log -p -- .beads/issues.jsonl` on the current worktree; `bd show`/`bd ready --json` for `polylogue-pj8`, `37t.4`, `3tl`, `cfk`, `212.9`, `1vpm.1`, `83u.2`, `4ts.3`, `4ts`, `9e5.6`, and the 212.1/212.2/212.3/212.5/212.6 family; `.agent/tools/delivery-gate-status.py --fresh` (whole-board and per-gate); direct `grep` confirmation of the `dispatch.py` fix anchors named in the `4ts.3` bead notes. No files under `.agent/demos/uplift-two-arm/` were read, per instruction.
diff --git a/.agent/demos/uplift-two-arm/current/arms/pair1-raw-ref-output.md b/.agent/demos/uplift-two-arm/current/arms/pair1-raw-ref-output.md
deleted file mode 100644
index 45d0677061..0000000000
--- a/.agent/demos/uplift-two-arm/current/arms/pair1-raw-ref-output.md
+++ /dev/null
@@ -1,63 +0,0 @@
-# Devloop State Reconstruction — polylogue @ commit 91eb09549
-
-## (a) Current devloop state
-
-The worktree HEAD (`91eb09549`) sits at the end of a dense, uninterrupted run of small merged PRs. Recent `git log --oneline -30` shows a tight cadence of `feat/fix` commits each immediately followed by a `chore(beads): close (#N)` commit — the devloop is running "ship → close bead → next" with no idle gaps:
-
-```
-91eb09549 chore(beads): close polylogue-4ts.6 (#2604)
-c06ca601c feat(lineage): surface a completeness signal on composed reads (#2603)
-1d7d79ed2 chore(beads): close polylogue-cpf.1 (#2602)
-6c12e9234 feat(devtools): timestamp-doctrine lint for durable-tier DDL (#2601)
-01592e5e9 chore(beads): close polylogue-jsy (#2600)
-b6b9fef2a fix(security): harden blob hash validation, drop misleading symlink check (#2599)
-...
-```
-
-The two most recent substantive shipped items:
-1. **`polylogue-cpf.1`** (PR #2601) — added `devtools/verify_timestamp_doctrine.py`, a lint rejecting `TEXT` timestamp columns in new durable-tier DDL. Wired into `devtools verify --lab`. This is doctrine-chain work under the `polylogue-cpf` epic ("Land the six doctrines").
-2. **`polylogue-4ts.6`** (PR #2603, just closed) — added `lineage_complete`/`lineage_truncation_reason` to `ArchiveSessionEnvelope` (both sync and async composition paths), wired it into the two MCP-facing payloads. CodeRabbit flagged on review that two more read surfaces (CLI reader payload, Python API `Session` model) and three async batch/paginated wrappers still silently drop the signal — this was **not silently ignored**: it was spun into a fresh follow-up bead, `polylogue-vv2b`, filed at close time with the exact same additive pattern already validated in #2603.
-
-`bd ready --json` currently returns **299 open, unblocked** beads — this is a long-horizon backlog, not near exhaustion. Beads are grouped into big epics (`9e5` audit lane, `cpf` doctrines, `t46`/`jnj`/`fnm` surface-algebra work, `20d`/`1xc` performance/scale, `bby` web workbench, `a7xr` substrate consolidation, etc.), most tagged with `delivery:` labels running a lettered sequence `A-trust-floor → ... → N-horizon`.
-
-Crucially, `.agent/tools/delivery-gate-status.py --fresh` (an ordinary repo script, not the forbidden demo dir) shows the priority field was **just reconciled to track this gate order** (commit `a2ee55ec4`, PR #2584, "Ref #8e1b" — mechanical sweep, 288 beads repriced). Gate state right now:
-
-```
-> A-trust-floor 23% closed(14) wip(0) ready(43) blocked(3) <- the active frontier
- B-storage-rebuild-bytes 4% ready(19)
- C-read-evidence-contract 2% ready(51)
- D-agent-context-coordination 0% ready(34)
- E-variants-preferences 0%
- F-lineage-compaction 17% closed(2) ready(3) blocked(7)
- ...through N-horizon
-```
-
-`A-trust-floor`'s exit criterion: "Full verification classified; security negative tests pass; missing bytes classified; numbers/time/prose-mined fields carry honest provenance; agent writes land as candidates." Priority-1 in `bd ready` == this gate by construction.
-
-## (b) Open threads found
-
-- **`polylogue-cpf` epic** (doctrine landing, gate A-trust-floor): `cpf.1` just closed. Siblings `cpf.2` (writer-class docstring + layering check) and `cpf.3` (injected-context deny-lexicon tripwire fixture) are both **open, wave:1, same epic, same "cheap lint" shape** as the just-shipped `cpf.1`. `cpf.4` (the broader "sweep silent soft-failure paths" class bead) explicitly names three concrete instances to verify against: `1xc.11` (closed 2026-07-05), `4ts.6` (**just closed**), and `tf0e` (still open, but in a different, lower-tier gate `K-interop-origin-export`). So 2 of 3 named instances are now resolved — `cpf.4` is closer to being closeable than it was an hour ago.
-- **`polylogue-vv2b`** (new, filed at `4ts.6` close time): wire the same `lineage_complete` signal into the CLI reader payload (`cli/archive_query.py:2198`), the Python API `Session` model (`api/archive.py:1162`), and the three async batch/paginated wrappers. Small, additive, pattern already proven in #2603. It carries no `delivery:*` gate label yet (falls into the 26-bead "unlabeled_open" bucket), so it sits outside the just-reconciled priority scheme — priority 3 is a leftover default, not a gate-derived value.
-- **Housekeeping loose end:** `polylogue-8e1b` ("Reconcile bead priority field with delivery-gate order") shipped its work in merged PR #2584 but the bead itself is still `status: in_progress` (assignee Sinity, no `closed_at`) — the work is done and merged; the bead just wasn't formally closed out.
-- Two investigation-only threads were recorded and unclaimed rather than completed: `4ts.3` ("record 4ts.3 investigation findings, unclaim") and `1vpm.1` (same pattern) — these remain open for someone to pick back up with the recorded findings as a starting point.
-- The `9e5` "Audit lane" epic has a large cluster of ready, priority-1/gate-A items (`9e5.1`, `9e5.3`–`9e5.27` minus closed ones) — read-only analysis work producing evidence artifacts, generally larger/more open-ended than the `cpf` doctrine lints.
-
-## (c) Recommended next action
-
-**Claim `polylogue-cpf.2`** ("Doctrine: writer-class docstring convention + layering check").
-
-Why this one specifically, over the many other ready candidates:
-- It is in **gate A-trust-floor**, the tool-confirmed active frontier (lowest completion %, and the gate the operator's own priority-reconciliation sweep just re-anchored as top priority).
-- It is the **direct sibling of the commit that just landed** (`cpf.1`, same epic, same `wave:1` label, same "small schema/layering lint wired into `devtools lab policy`" shape) — the agent that did `cpf.1` proved the exact pattern this bead needs (add a check, register it under `devtools lab policy`, wire into `devtools verify --lab`, unit-test with a fixture that should fail vs. one that should pass).
-- Its acceptance criteria are tight and mechanical: "A file declaring two writer classes fails the check; single-class files pass" — low risk, quick to verify, no architectural ambiguity.
-- No blocking dependencies (parent `cpf` is an open epic, but parent-child edges don't block readiness).
-
-Second-best alternative, if the goal is "clean up what's already in flight" rather than "advance the top-priority gate": **`polylogue-vv2b`** — it's the freshest, most concrete, most fully-specified bead in the tracker (filed minutes before HEAD, names exact file/line locations, reuses a pattern the same session just implemented twice), but it's gate `F-lineage-compaction` / unlabeled, i.e. formally lower priority under the current gate ordering than `cpf.2`/`cpf.3`/`cpf.4`.
-
-Also worth a two-minute detour regardless of which bead is claimed next: `bd close polylogue-8e1b` — its work already shipped in merged PR #2584 and it's just sitting `in_progress` unclosed.
-
-## (d) Confidence and evidence used
-
-High confidence on the state summary (git log + `bd show` on the exact beads referenced by the last four commits gave a coherent, cross-corroborating picture: commit messages, bead `close_reason` text, and the newly-filed `vv2b` bead's dependency edge to `4ts.6` all agree). Medium-high confidence on the "what's next" recommendation — it follows the repo's own explicitly documented policy (gate-ordered priority, `delivery-gate-status.py` as "the gate board") rather than my own guess, but there are 43 other A-trust-floor-ready beads I did not individually inspect, so a different reasonable pick from that same set is defensible.
-
-Evidence used: `git log --oneline -30` / `--all -10`; `bd ready --json --limit 500` (299 items); `bd show` on `polylogue-cpf`, `cpf.1`–`cpf.4`, `4ts.6`, `4ts`, `1xc.11`, `tf0e`, `vv2b`, `8e1b`; `bd list --status in_progress --json`; and one ordinary repo script read/run, `.agent/tools/delivery-gate-status.py --fresh` / `--gate A-trust-floor --json` (explicitly not under the forbidden `.agent/demos/uplift-two-arm/` path). No MCP/Polylogue archive tools were used (not required — the bd/git evidence was sufficient and directly conclusive).
diff --git a/.agent/demos/uplift-two-arm/current/arms/pair2-handoff-pack-output.md b/.agent/demos/uplift-two-arm/current/arms/pair2-handoff-pack-output.md
deleted file mode 100644
index f9112f29c2..0000000000
--- a/.agent/demos/uplift-two-arm/current/arms/pair2-handoff-pack-output.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# Devloop Reconstruction Report — commit 64c079d6e
-
-## (a) Current devloop state
-
-HEAD sits at 64c079d6e, the tail of a run of small, tightly-scoped merged PRs (9e5.29 -> 83u.4 -> 83u.6 -> svfj -> 212.7 -> 212.4 -> 212.8).
-
-The demo-unlock chain (9e5.29 -> svfj -> 212.7 -> {212.1-212.6,212.8 parallel} -> 1vpm.1 (+rxdo.7) -> 212.9) has its foundation fully cleared: 9e5.29, svfj, and 212.7 are all closed. Of the parallel demo set, 212.4 and 212.8 are closed -- 2 of the planned first-wave set are done.
-
-Gate-board snapshot: A-trust-floor 23% (frontier gate, 43 ready); B-storage-rebuild-bytes 4%; C-read-evidence-contract 2%; F-lineage-compaction 17%; L-external-legibility 13%.
-
-polylogue-1vpm.1 shows status=in_progress, assignee=Sinity, with no shipped commits yet on the checked-out history -- consistent with "not yet built."
-
-## (b) Open threads
-
-1. Demo portfolio (polylogue-212) -- 212.2 ("D1 'The receipts': claim-vs-evidence on a real PR") is the missing piece of the originally-planned first wave and is unblocked (all dependencies closed). 212.1 also implementation-ready. 212.3 blocked on a missing join primitive. 212.5/212.6 explicitly deferred. 212.9 depends on 1vpm.1 and optionally rxdo.7.
-2. Lineage epic (polylogue-4ts) -- untouched; only 4ts.3 and 4ts.5 ready, both priority 3.
-3. External legibility (polylogue-3tl) -- untouched as an epic, 6 children ready.
-4. polylogue-cfk (re-run two-arm uplift experiment) -- open, likely needing an operator-gated/infra-dependent step.
-5. polylogue-pj8 -- open, plausibly needs an MCP server reboot.
-6. polylogue-rxdo.7 -- needed for the demo chain's optional annotation-loop step.
-7. Large untouched P1 backlog under A-trust-floor (the 9e5.* family plus cpf.4).
-
-## (c) Recommended next action
-
-polylogue-212.2 -- "D1 'The receipts': claim-vs-evidence on a real PR." It is the one remaining piece of the demo epic's own first wave, fully unblocked, rated A-implementation-ready ("nearly free: all reads exist"), and keeps the demo-unlock chain moving. Lower-risk than picking an undifferentiated P1 trust-floor item, and doesn't require the redeploy/MCP-reboot precondition blocking cfk/pj8.
-
-Secondary candidate: polylogue-4ts.3 or 4ts.5 to start cracking open the lineage epic.
-
-## (d) Confidence
-
-High confidence on state reconstruction. Medium-high on the recommendation -- the ultimate call between continuing the demo thread versus the P1 trust-floor backlog is a judgment call the standing goal itself leaves open.
diff --git a/.agent/demos/uplift-two-arm/current/arms/pair2-raw-ref-output.md b/.agent/demos/uplift-two-arm/current/arms/pair2-raw-ref-output.md
deleted file mode 100644
index ebd3837340..0000000000
--- a/.agent/demos/uplift-two-arm/current/arms/pair2-raw-ref-output.md
+++ /dev/null
@@ -1,25 +0,0 @@
-## Current Devloop State
-
-The repository sits at commit 64c079d6e, the tip of a long, rapid-fire single-day devloop. The devloop is explicitly organized around a delivery-gate sequence (A-trust-floor -> B-storage-rebuild-bytes -> C-read-evidence-contract -> ... -> N-horizon), with bead priority fields recently reconciled (PR #2584, bead polylogue-8e1b, still technically in_progress even though its mechanical sweep already landed).
-
-The immediately preceding thread of work is the demo portfolio epic (polylogue-212): converting demos into a formal Demo Finding Packet contract (polylogue-212.7, closed) and producing a "first public mini-portfolio" of exactly three packets: D1 receipts (212.2, NOT implemented), D4 behavioral archaeology (212.4, closed), the honesty anti-demo (212.8, closed, HEAD commit). When 212.7 was closed, a follow-up bead polylogue-xyel was filed to implement the real D1-receipts packet.
-
-Also active: 9e5 audit-lane, f2qv (cost honesty), cpf (six doctrines), 83u (attachment/blob integrity, 83u.2 corrected-and-unclaimed), svfj's follow-up polylogue-xl25 (relocated_lineage/quarantined states). polylogue-1vpm.1 is genuinely in_progress right now.
-
-## Open Threads
-
-- D1 receipts demo incomplete (polylogue-xyel, ready, unblocked).
-- A real, freshly-discovered correctness bug: polylogue-70qb -- bare find "sessions where " silently ignores the boolean predicate. Discovered mid-authorship of 212.4, documented honestly as a counterexample. No delivery:* gate label yet.
-- polylogue-xl25 -- implement relocated_lineage/quarantined states for the block-content-hash citation resolver.
-- polylogue-8e1b -- still in_progress, unclosed despite mechanical sweep landing.
-- Large standing backlogs at every later delivery gate.
-
-## Recommended Next Action
-
-Claim polylogue-xyel (real D1-receipts demo). It is the single named, unblocked loose end from the work sequence that produced the last three commits; small, well-scoped.
-
-Close second: polylogue-70qb -- a genuine correctness defect in a core surface, numerically higher priority under the reconciled scheme, but not gate-labeled so it fell outside the reconciliation sweep.
-
-## Confidence
-
-High confidence on state reconstruction and xyel as the most contextually-continuous next claim. Moderate uncertainty on xyel-vs-70qb prioritization since they represent genuinely different, defensible notions of "next."
diff --git a/.agent/demos/uplift-two-arm/current/arms/pair3-handoff-pack-output.md b/.agent/demos/uplift-two-arm/current/arms/pair3-handoff-pack-output.md
deleted file mode 100644
index acee41dd45..0000000000
--- a/.agent/demos/uplift-two-arm/current/arms/pair3-handoff-pack-output.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# Devloop State Reconstruction — polylogue @ 01592e5e9
-
-## (a) Current devloop state
-
-The gate board (A-trust-floor -> N-horizon) shows: A-trust-floor 23% (frontier, 14 closed/43 ready/3 blocked); B-storage-rebuild-bytes 4%; C-read-evidence-contract 2%; D-agent-context-coordination 0%; F-lineage-compaction 17%; I-analytics-experiments 0% closed, 1 wip (1vpm.1); L-external-legibility 13% (demo portfolio + 3tl/cfk live here).
-
-Two intertwined recent threads: (1) demo-unlock chain 9e5.29 -> svfj -> 212.7 -> 212.4+212.8, all closed; (2) correctness-audit thread: 4ts.4, xnkf, jsy, all closed, jsy landing exactly at HEAD.
-
-polylogue-1vpm.1 is in_progress, assigned, with a detailed investigation note: the hard identity/extraction problem is already solved by build_run_projection/session_runs, so real remaining scope narrows to five gaps: (1) delegation_kind taxonomy, (2) link_status field, (3) delegations DSL query unit, (4) delegation-card read view, (5) target_kind=delegation for assertions. Left claimed-but-unimplemented "due to time."
-
-## (b) Open threads
-
-- Demo portfolio: 4 of 6 parallel demo beads still open -- 212.1, 212.2, 212.3, 212.5. 212.6 blocked by polylogue-tsk (a real classifier bug). 212.9 has a non-blocking related dependency on 1vpm.1 and rxdo.7.
-- rxdo.7 itself blocked by rxdo.1.
-- pj8 depends on parent s7ae and 37t.4 (itself blocked by 37t.12). Matches the "needs redeploy" postpone caveat.
-- cfk structurally unblocked but needs a live paired-arm experiment.
-- 3tl -- all 17 children open, uniformly P4 docs/marketing polish.
-- 4ts (lineage epic) only has a relates-to link to 38x, no P1/P2 children in flight.
-- Trust-floor "storage identity" P1 cluster: 9e5.4, 9e5.5, 9e5.6, 9e5.19 -- all P1, area:storage, all open/ready, none started. jsy and xnkf look like exactly what these audits are meant to produce systematically, discovered incidentally so far.
-- 37 P1 beads ready in A-trust-floor overall, dominated by the 9e5.* audit family.
-
-## (c) Recommended next action
-
-polylogue-1vpm.1 -- resume and finish the delegation derived-unit implementation. It is the only bead genuinely mid-flight with investigation already paid for and a concrete five-item implementation list recorded on the bead. Sits on the critical path to 212.9.
-
-Alternative if following the demo-parallel-then-1vpm.1 order strictly: 212.2 or 212.3. Third option if prioritizing trust-floor over demos: polylogue-9e5.6, sharing footprint/evidence base with the just-shipped jsy fix.
-
-## (d) Confidence and evidence
-
-High confidence on mechanical facts (bead statuses, dependency graphs, gate percentages). Moderate-to-high on the prioritization judgment.
diff --git a/.agent/demos/uplift-two-arm/current/arms/pair3-raw-ref-output.md b/.agent/demos/uplift-two-arm/current/arms/pair3-raw-ref-output.md
deleted file mode 100644
index 0536a016c2..0000000000
--- a/.agent/demos/uplift-two-arm/current/arms/pair3-raw-ref-output.md
+++ /dev/null
@@ -1,28 +0,0 @@
-## Devloop State Report — polylogue @ 01592e5e9
-
-### (a) Current state
-
-The devloop is deep in an extended "trust floor" hardening pass across security, storage-lineage, and evidence-integrity surfaces, with a parallel demo-authoring track validating the query/insights layer against real corpus behavior. The last ~30 commits show a tight, disciplined rhythm: land a fix/feature PR, then immediately land a companion chore(beads) commit that closes the bead with verified findings and files any follow-up debt discovered along the way.
-
-Most recently shipped: polylogue-jsy (blob hash validation hardening + symlink-check removal), the actions view pairing fix, holding one read transaction across lineage composition, the D4 behavioral archaeology demo, and a new Demo Finding Packet contract + registry lint.
-
-Two beads are in_progress: polylogue-8e1b (priority reconciliation sweep, work appears already executed, just needs closing) and polylogue-1vpm.1 (delegation-derived-unit materializer, mid-investigation).
-
-### (b) Open threads
-
-1. Attachment/blob integrity program (polylogue-83u) — 83u.2 still open and unclaimed.
-2. Security & privacy epic (polylogue-kwsb) — jsy just closed under it, epic remains open.
-3. Six-doctrines program (polylogue-cpf) — cpf.2/cpf.3/cpf.4 all still open/ready.
-4. Cost/usage honesty (polylogue-f2qv) — multiple children ready.
-5. Large read-only audit lane (polylogue-9e5) — ~20+ still-open children.
-6. A freshly-discovered, unfixed correctness bug filed at 2026-07-09T00:27:55Z.
-
-### (c) Recommended next bead: polylogue-70qb
-
-"Bare find sessions where ignores the boolean predicate, returns unfiltered list" — discovered during the just-merged 212.4 demo work. Reproduces identically for a plain field predicate and for a seq() predicate, so it isn't SEQ-specific — it's the bare-find/boolean-entry-form code path silently defaulting to an unfiltered listing.
-
-Reasons: real, exactly-reproduced, user-facing correctness bug; cheap to fix and verify (three one-line CLI repro commands already given); zero open blocking dependencies; directly protects trust in the CLI's primary query surface.
-
-### (d) Confidence
-
-High on state reconstruction. Moderate-high on the specific recommendation.
diff --git a/.agent/demos/uplift-two-arm/current/arms/pair4-handoff-pack-output.md b/.agent/demos/uplift-two-arm/current/arms/pair4-handoff-pack-output.md
deleted file mode 100644
index 4108da828a..0000000000
--- a/.agent/demos/uplift-two-arm/current/arms/pair4-handoff-pack-output.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# Devloop Reconstruction Report — polylogue @ a2ee55ec4
-
-## (a) Current devloop state
-
-At a2ee55ec4, the backlog is organized into 15 lettered delivery gates that must clear roughly in order. Gate A-trust-floor is the active frontier: 9 closed, 46 ready, 1 in-progress, 3 blocked (~15% complete). No later gate has meaningfully started.
-
-Two beads are literally in_progress at this exact commit: polylogue-9e5.29 (claimed by Sinity, priority 1, gate A-trust-floor) and polylogue-8e1b (the priority-reconciliation bead itself, not yet formally closed even though its PR landed).
-
-## (b) Open threads
-
-1. Demo-unlock chain: 9e5.29 is already claimed and in progress -- it's the live head of this chain, not a cold start. Of 212.7's dependencies, four already closed, three remain open: 9e5.29 (wip), svfj (open), 212.9 (open). Note: 212.7 genuinely depends on 212.9, which conflicts with the informal ordering placing 212.9 last -- this should be reconciled.
-2. Trust-floor P1 backlog large and only partly overlapping with the demo chain: 43 open/in-progress P1 beads gate-wide.
-3. Lineage epic (4ts): 4ts.1/4ts.2 already closed historically; remaining scope (4ts.3-4ts.7) all still open.
-4. 3tl epic: 5 children already closed historically; remaining ~10 children all priority 4.
-5. pj8: layers 1+2 already merged; explicit remaining blocker is a redeploy for the live MCP server to pick up new prompts.
-6. cfk and s7ae remain open with no children closed yet.
-7. 8e1b still in_progress despite its PR having merged as this very commit.
-
-## (c) Recommended next action
-
-Continue and close polylogue-9e5.29. Already claimed and in-progress; priority 1 in the active frontier gate; literal head-blocker of the demo-unlock chain. Concrete, anchored design (insights/rigor.py, RigorFieldContract). Checkable AC.
-
-Immediately after: close 8e1b (PR already merged). Then svfj as the next chain link, while separately flagging the 212.7<->212.9 ordering conflict.
-
-## (d) Confidence and evidence
-
-High confidence in the state reconstruction. The 212.7<->212.9 dependency-vs-narrative-order conflict is flagged as genuinely uncertain, a real graph inconsistency worth resolving rather than assuming the "212.9 last" framing is authoritative.
diff --git a/.agent/demos/uplift-two-arm/current/arms/pair4-raw-ref-output.md b/.agent/demos/uplift-two-arm/current/arms/pair4-raw-ref-output.md
deleted file mode 100644
index ba97a981e7..0000000000
--- a/.agent/demos/uplift-two-arm/current/arms/pair4-raw-ref-output.md
+++ /dev/null
@@ -1,26 +0,0 @@
-## Devloop reconstruction report — polylogue @ a2ee55ec4
-
-### (a) Current devloop state
-
-The backlog runs through a staged delivery-gate sequence A-trust-floor -> ... -> N-horizon. The tip commit (a2ee55ec4, "reconcile priority field with delivery-gate order") just finished a mechanical sweep reassigning every bead's priority to match this gate order -- 288 of 387 open/gate-labeled beads repointed. Pure bookkeeping, closing out #8e1b.
-
-Preceding it: temporal-provenance doctrine work (cpf.5/cpf.6, both closed); a wave of timeless-session correctness fixes across search/usage-timeline/CLI query-unit engine/work-events; security hardening (XSS fixes, browser-capture host-admission gate, bearer token requirement); devtools/verify robustness; the devloop scaffold retired in favor of Beads.
-
-Gate-board snapshot: A-trust-floor is the active frontier -- 23% closed (14/43/3). Every later gate essentially untouched.
-
-### (b) Open threads
-
-- A-trust-floor exit bar far from met -- most ready items are large audit/epic-shaped tasks (9e5.* audit family, f2qv.* cost-honesty chain, cpf.* doctrine chain).
-- Many ready A-trust-floor items are actually readiness=D-horizon-ready in their own notes -- only a subset are truly A-implementation-ready.
-- cpf epic: 3/6 children closed; remaining three (cpf.2/cpf.3/cpf.4) need more local inspection.
-- f2qv cost/usage-honesty chain fully open, each blocking the next.
-- polylogue-cuxz filed as a follow-on from the timeless-session fix wave.
-- Blocked items: polylogue-27m, polylogue-b0b/b0b.1, polylogue-9e5.16.
-
-### (c) Recommended next action
-
-Claim polylogue-jnj.5 -- "Route ops reset --session/--source through the mutation contract." A-implementation-ready, zero blocking dependencies, blocks nothing. A genuine, narrowly-scoped security bug: ops reset writes a tombstone before the dry-run/confirmation branch runs, so a typo could silently suppress data without --yes. Child of the kwsb security/privacy epic. Concrete testable AC.
-
-### (d) Confidence and evidence
-
-High confidence on state summary. Medium-high on the specific recommendation -- another equally valid choice could reasonably be argued.
diff --git a/.agent/demos/uplift-two-arm/current/arms/pair5-handoff-pack-output.md b/.agent/demos/uplift-two-arm/current/arms/pair5-handoff-pack-output.md
deleted file mode 100644
index 94816740f8..0000000000
--- a/.agent/demos/uplift-two-arm/current/arms/pair5-handoff-pack-output.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# Devloop State Reconstruction — polylogue (as of / since commit 697470661)
-
-## (a) Current devloop state
-
-The summary's endpoint was commit 697470661. The repository's actual tip has moved substantially further -- origin/master is now at 91eb09549, 19 commits ahead. Since the checkout, many closures have landed: svfj, 212.7, 212.4, 212.8, 4ts.4, 4ts.6, cpf.1, jsy, xnkf all closed; 4ts.3 investigated and unclaimed.
-
-The delivery-gate frontier is unchanged: A-trust-floor still leads at 23%.
-
-## (b) Open threads
-
-1. Demo-unlock chain well past where the summary left it. Only 212.4 and 212.8 done of 212.1-212.6/212.8; the rest remain open and parallelizable.
-2. polylogue-1vpm.1 is the live critical-path item and appears actively claimed right now. Sole dependency gating 212.9. Bead notes show a pre-implementation investigation narrowing scope to five concrete items. It was investigated-and-unclaimed once already, then re-claimed and set back to in_progress locally, uncommitted -- a worktree tracking master tip is present and not detached, consistent with an agent actively working this bead right now.
-3. polylogue-4ts epic has three open children left (4ts.3, 4ts.5, 4ts.7) plus the parent.
-4. polylogue-3tl, polylogue-cfk, polylogue-pj8 -- all still open at the epic level, essentially untouched.
-5. polylogue-83u.2 remains open, corrected findings but still unclaimed.
-6. polylogue-8e1b left in_progress even though its mechanical sweep already landed -- stale claim bookkeeping.
-
-## (c) Recommended next action
-
-Continue/finish polylogue-212.9's blocker, polylogue-1vpm.1 -- the standing goal's next unfinished chain link, already has a substantially narrowed, concrete implementation scope from its own investigation notes.
-
-Caveat: evidence strongly suggests this bead is already claimed by a concurrently running session (in_progress, uncommitted, recent timestamp, matching live non-detached worktree). A fresh agent should verify claim/lock status before starting. If actively held, pick up an independent demo item instead (212.1 or 212.2).
-
-## (d) Confidence and evidence
-
-High confidence on mechanical facts. Moderate confidence on the "concurrent agent is right now working 1vpm.1" inference -- reasonable but not certain.
diff --git a/.agent/demos/uplift-two-arm/current/arms/pair5-raw-ref-output.md b/.agent/demos/uplift-two-arm/current/arms/pair5-raw-ref-output.md
deleted file mode 100644
index 88c8584726..0000000000
--- a/.agent/demos/uplift-two-arm/current/arms/pair5-raw-ref-output.md
+++ /dev/null
@@ -1,25 +0,0 @@
-## Devloop Reconstruction Report — polylogue @ 697470661
-
-### (a) Current devloop state
-
-A long-running, multi-agent Beads-driven backlog burn against a 15-gate delivery sequence. Gate-board: A-trust-floor (active frontier) 23% complete -- 14 closed, 43 ready, 3 blocked. All later gates 0-17%.
-
-Total backlog: 533 beads. Priority mechanically re-derived from gate membership; 37 ready priority-1 beads, all labeled delivery:A-trust-floor.
-
-Immediately preceding commits were working polylogue-83u (attachment/blob evidence integrity, a B-gate epic): 83u.6 and 83u.4 shipped/closed; 83u.2 investigated in depth, found to require a real architecture decision with no confirmed live target, deliberately left open/unclaimed. HEAD is an unrelated shipped fix (content-hash citation anchors).
-
-### (b) Open threads
-
-1. 83u.2 stuck pending a design decision -- correctly left unclaimed.
-2. A-trust-floor gate (37 ready P1 beads) under-invested relative to the 83u work that just happened. Sub-clusters: f2qv cost/usage-honesty (f2qv.1 just closed, .2-.5 open); cpf doctrine/spine (cpf.5/.6 closed, .2/.3/.4 open); 9e5 large audit epic (~20 ready sub-beads); 38x reconciliation hub connecting several threads.
-3. Two beads in_progress: polylogue-8e1b (mechanical, already reflected in commit) and polylogue-1vpm.1 (delegation-derived-unit materializer) -- the latter shows a concurrent worktree session actively working it.
-
-### (c) Recommended next action
-
-Claim polylogue-f2qv.2 -- "Codex disjoint-lane normalizer." On-gate, picks up the exact cluster whose sibling f2qv.1 just closed. Fully specified, concrete AC with a named cross-check and a regression-guard test reproducing the historical 7.69x naive-sum bug. Closes out one leg of the still-open 38x reconciliation hub. No unresolved dependencies.
-
-Runner-up: polylogue-9e5.23.
-
-### (d) Confidence and evidence
-
-Moderate-high on "what happened". Moderate on "what to do next" -- a judgment call among ~37 equally-gated ready beads.
diff --git a/.agent/demos/uplift-two-arm/current/metrics/ground-truth-pair1.json b/.agent/demos/uplift-two-arm/current/metrics/ground-truth-pair1.json
deleted file mode 100644
index 4c99be68d2..0000000000
--- a/.agent/demos/uplift-two-arm/current/metrics/ground-truth-pair1.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "written_before_arms_ran": true,
- "written_at": "2026-07-09T03:20:00Z",
- "checkpoint": "immediately after PR #2601 (cpf.1 timestamp-doctrine lint) merged to master, before 4ts.6 work began",
- "checkpoint_commit": "6c12e9234",
- "ground_truth_next_action": "Claim and implement polylogue-4ts.6 (lineage composition silently truncates transcripts; surface a completeness signal) -- add lineage_complete/lineage_truncation_reason to ArchiveSessionEnvelope and a matching async LineageCompleteness return type, with regression tests for depth-limit and dangling-branch-point cases.",
- "ground_truth_open_threads": [
- "polylogue-4ts.3 (subagent auto-compaction misclassification) -- investigated, correctly scoped as needing dispatch-layer surgery (polylogue/sources/dispatch.py), left unclaimed",
- "polylogue-1vpm.1 (delegation derived unit) -- investigated, found existing session_runs/build_run_projection infrastructure covers most of the hard part, left unclaimed as still a real multi-file feature",
- "polylogue-83u.2 (attachment re-acquisition) -- investigated, found the static prework packet had wrong anchors, left unclaimed",
- "the standing /bead-loop goal explicitly lists: trust-floor/storage-identity P1s, lineage epic (4ts), pj8, 3tl, cfk, plus a demo-unlock chain (9e5.29 -> svfj -> 212.7 -> 212.1-212.6/212.8 -> 1vpm.1 -> 212.9)"
- ],
- "ground_truth_caveats": [
- "This is a live, still-running session -- the 'subject' and the ground-truth author are the same agent, which is a real construct-validity limit (matches jxe's own documented limit: 'hidden prior knowledge and tool availability are not fully controlled').",
- "Both arms are dispatched as isolated Agent-tool subagents from within the same session, not fully separate Claude Code processes like the original jxe pilot's agent_id-tracked arms -- a weaker isolation guarantee than the original protocol.",
- "n=1 pilot; cannot estimate general uplift, matching jxe.2's own caveat."
- ]
-}
diff --git a/.agent/demos/uplift-two-arm/current/metrics/ground-truth-pair2.json b/.agent/demos/uplift-two-arm/current/metrics/ground-truth-pair2.json
deleted file mode 100644
index b719363443..0000000000
--- a/.agent/demos/uplift-two-arm/current/metrics/ground-truth-pair2.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "written_before_arms_ran": true,
- "checkpoint": "immediately after PR #2592 (212.8 honesty anti-demo bead close) merged, before 1vpm.1/4ts.4 work began",
- "checkpoint_commit": "64c079d6e",
- "ground_truth_next_action": "Investigate polylogue-1vpm.1 (delegation derived unit) -- claimed, investigated, found existing session_runs/build_run_projection infrastructure covers most of the hard part, left unclaimed pending a fresh session's fuller implementation.",
- "ground_truth_open_threads": [
- "polylogue-4ts.4 (torn-transcript transaction race) -- not yet started at this checkpoint, becomes the very next shipped item",
- "polylogue-xnkf (actions view duplicate-tool_id fan-out) -- not yet started, ships several items later",
- "the standing /bead-loop goal's demo-unlock chain: 212.1-212.6 parallel set still has 4 unclaimed items after 212.4/212.8"
- ]
-}
diff --git a/.agent/demos/uplift-two-arm/current/metrics/ground-truth-pair3.json b/.agent/demos/uplift-two-arm/current/metrics/ground-truth-pair3.json
deleted file mode 100644
index 6a8ae6c1c1..0000000000
--- a/.agent/demos/uplift-two-arm/current/metrics/ground-truth-pair3.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "written_before_arms_ran": true,
- "checkpoint": "immediately after PR #2600 (jsy blob hash validation bead close) merged, before cpf.1 work began",
- "checkpoint_commit": "01592e5e9",
- "ground_truth_next_action": "Claim and implement polylogue-cpf.1 (doctrine lint: reject TEXT timestamps in new durable DDL) -- a new devtools lab policy check.",
- "ground_truth_open_threads": [
- "polylogue-jsy just shipped (blob hash hardening + symlink check removal)",
- "the cpf epic (doctrine landing) has several sibling lints not yet started: cpf.2 (writer-class docstring), cpf.3 (deny-lexicon tripwire)",
- "4ts.4/4ts.6/xnkf lineage and storage fixes have not yet happened at this checkpoint"
- ]
-}
diff --git a/.agent/demos/uplift-two-arm/current/metrics/ground-truth-pair4.json b/.agent/demos/uplift-two-arm/current/metrics/ground-truth-pair4.json
deleted file mode 100644
index 36b2721930..0000000000
--- a/.agent/demos/uplift-two-arm/current/metrics/ground-truth-pair4.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "checkpoint": "immediately after PR #2584 (bead priority/gate-order reconciliation) merged, before 9e5.29 work began",
- "checkpoint_commit": "a2ee55ec4",
- "ground_truth_next_action": "Claim and implement polylogue-9e5.29 (number-over-empty gates / RigorFieldContract mechanism).",
- "ground_truth_open_threads": [
- "the just-merged priority reconciliation repriced 288 beads to track the delivery-gate order",
- "83u.4/83u.6 attachment acquisition work not yet started at this checkpoint",
- "svfj/212.7/212.4/212.8/4ts.4/xnkf/jsy/cpf.1/4ts.6 all still fully in the future from this checkpoint"
- ]
-}
diff --git a/.agent/demos/uplift-two-arm/current/metrics/ground-truth-pair5.json b/.agent/demos/uplift-two-arm/current/metrics/ground-truth-pair5.json
deleted file mode 100644
index ac4cad9392..0000000000
--- a/.agent/demos/uplift-two-arm/current/metrics/ground-truth-pair5.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "checkpoint": "immediately after PR #2588 (svfj block content-hash citation anchors) merged, before its bead-close/212.7 work began",
- "checkpoint_commit": "697470661",
- "ground_truth_next_action": "Close polylogue-svfj bead (file relocated_lineage/quarantined follow-up), then claim and implement polylogue-212.7 (Demo Finding Packet contract + registry lint).",
- "ground_truth_open_threads": [
- "svfj just shipped: block content-hash citation anchors + typed resolver, index schema v24->v25",
- "the demo-unlock chain (9e5.29 -> svfj -> 212.7 -> 212.1-212.6/212.8 parallel -> 1vpm.1 -> 212.9) has 9e5.29 and svfj done, 212.7 is next",
- "83u.2 was just corrected/unclaimed with verified findings one commit prior"
- ]
-}
diff --git a/.agent/demos/uplift-two-arm/current/metrics/rubric.json b/.agent/demos/uplift-two-arm/current/metrics/rubric.json
deleted file mode 100644
index 2307ff67bf..0000000000
--- a/.agent/demos/uplift-two-arm/current/metrics/rubric.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "scoring": "0-10 per arm, integer",
- "criteria": [
- "answer_correctness_against_ground_truth: does the reconstructed state summary match what actually happened?",
- "open_thread_coverage: how many of the real open threads did it find?",
- "next_action_specificity: did it name a specific, defensible next bead, not a vague direction?",
- "caveat_honesty: did it flag its own confidence limits and evidence basis rather than overclaiming?"
- ],
- "note_to_judge": "Score each arm independently against the ground truth file. Do not assume either arm is the 'better' one by construction -- judge only on the merits of what's written. If both arms recommend a different but individually well-justified next action, note that explicitly rather than penalizing divergence from the ground truth's own next_action pick, since the ground truth's pick is one reasonable answer, not the only correct one."
-}
diff --git a/.agent/demos/uplift-two-arm/current/metrics/score.json b/.agent/demos/uplift-two-arm/current/metrics/score.json
deleted file mode 100644
index 2d9b6975bd..0000000000
--- a/.agent/demos/uplift-two-arm/current/metrics/score.json
+++ /dev/null
@@ -1,55 +0,0 @@
-{
- "pair_1": {
- "checkpoint_commit": "6c12e9234",
- "blinding_compromised": true,
- "blinding_compromise_reason": "Arm B (pack) self-referentially wrote 'This matches the pack's shipped-work list exactly', revealing its own identity to the judge",
- "judge_1": {
- "raw_ref_total": 29,
- "handoff_pack_total": 33,
- "winner": "handoff_pack",
- "primary_differentiator": "open_thread_coverage -- pack arm surfaced pj8/3tl/cfk/212.x chain explicitly named in ground truth; raw-ref arm did not"
- },
- "judge_2": {
- "raw_ref_total": 22,
- "handoff_pack_total": 35,
- "winner": "handoff_pack",
- "note": "explicitly checked for blinding leak, found none"
- }
- },
- "pair_2": {
- "checkpoint_commit": "64c079d6e",
- "note": "both arms converged on the same real next action (D1 receipts) under different bead-id labels (xyel vs 212.2)",
- "judge": {
- "raw_ref_total": 25,
- "handoff_pack_total": 31,
- "winner": "handoff_pack"
- }
- },
- "pair_3": {
- "checkpoint_commit": "01592e5e9",
- "judge": {
- "raw_ref_total": 31,
- "handoff_pack_total": 19,
- "winner": "raw_ref",
- "note": "pack arm confidently misstated 4ts.4/xnkf as already closed at this checkpoint (they were not yet), and missed the cpf epic entirely"
- }
- },
- "pair_5": {
- "checkpoint_commit": "697470661",
- "judge": {
- "raw_ref_total": 12,
- "handoff_pack_total": 36,
- "winner": "handoff_pack",
- "note": "raw-ref arm mischaracterized the checkpoint commit itself (svfj) as unrelated, missing the entire demo-unlock chain thread; pack arm correctly honest about reasoning past its own checkpoint"
- }
- },
- "pair_4": {
- "checkpoint_commit": "a2ee55ec4",
- "judge": {
- "raw_ref_total": 17,
- "handoff_pack_total": 32,
- "winner": "handoff_pack",
- "note": "ground truth verified via git log: 9e5.29 was indeed claimed/in-progress at this exact checkpoint and is the literal next thing worked; pack arm caught this exactly, raw-ref arm missed it entirely and recommended an unrelated bead"
- }
- }
-}
\ No newline at end of file
diff --git a/.agent/demos/uplift-two-arm/current/pairs.json b/.agent/demos/uplift-two-arm/current/pairs.json
deleted file mode 100644
index e0e92adba1..0000000000
--- a/.agent/demos/uplift-two-arm/current/pairs.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "n": 5,
- "protocol": "identical paired two-arm design per pair: raw-ref arm (session ref + live query access only, forbidden from any pre-built summary) vs handoff-pack arm (a bounded pre-built context summary + live query access), same task, same checkpoint commit, isolated worktree subagents. Ground truth for each pair written before either arm ran.",
- "pairs": [
- {"pair": 1, "checkpoint_commit": "6c12e9234", "raw_ref_score": 29, "handoff_pack_score": 33, "winner": "handoff_pack", "note": "blinding compromised (pack arm self-referenced 'the pack'); scored by 2 independent judges, both favored pack (33/29 and 35/22)"},
- {"pair": 2, "checkpoint_commit": "64c079d6e", "raw_ref_score": 25, "handoff_pack_score": 31, "winner": "handoff_pack", "note": "both arms converged on the same real next action under different bead-id labels"},
- {"pair": 3, "checkpoint_commit": "01592e5e9", "raw_ref_score": 31, "handoff_pack_score": 19, "winner": "raw_ref", "note": "pack arm confidently misstated two beads as already-closed when they were not yet at this checkpoint"},
- {"pair": 4, "checkpoint_commit": "a2ee55ec4", "raw_ref_score": 17, "handoff_pack_score": 32, "winner": "handoff_pack", "note": "ground truth verified via git log; pack arm correctly identified the literal in-progress bead, raw-ref missed it"},
- {"pair": 5, "checkpoint_commit": "697470661", "raw_ref_score": 12, "handoff_pack_score": 36, "winner": "handoff_pack", "note": "raw-ref arm mischaracterized the checkpoint commit itself as unrelated"}
- ],
- "aggregate": {
- "pairs_won_by_handoff_pack": 4,
- "pairs_won_by_raw_ref": 1,
- "sign_test": "4/5 -- directionally favors handoff_pack but NOT statistically significant at n=5 (binomial p~0.375 two-tailed under a null of no difference)",
- "mean_raw_ref": 22.8,
- "mean_handoff_pack": 30.2
- }
-}
diff --git a/.agent/demos/uplift-two-arm/current/report.md b/.agent/demos/uplift-two-arm/current/report.md
deleted file mode 100644
index 880160e6b7..0000000000
--- a/.agent/demos/uplift-two-arm/current/report.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# Handoff-Pack Uplift Re-Run (n=5 pilot)
-
-Successor to campaign `polylogue-jxe`, which closed diagnostic-negative (raw-ref 8/10 vs handoff-pack 5/10, n=1, attributed to packet staleness). This re-run tests whether a *fresh* pack (regenerated at continuation time) plus live query access beats raw-ref plus live query access, per the protocol decision recorded on `polylogue-cfk`.
-
-## Claim
-
-Directional evidence (4 of 5 pairs) that a fresh, bounded context summary given alongside live query access produces a better devloop-state reconstruction than live query access alone, at this sample size. **Not a publishable claim** — n=5 is a de-noising step per the original protocol's own staged design (n=1 pilot → n≥3 de-noise → n=12-20 publishable), not the final tier.
-
-**What this experiment actually measures.** Raw access is a strict superset of what's in the pack — nothing in the pack is exclusive information the raw-ref arm couldn't in principle derive itself, since the pack is a compressed derivative of the same underlying `bd`/`git` state. So this is not a test of whether information is *missing* from raw access; it's a test of whether front-loaded synthesis beats from-scratch synthesis *within the bounded effort of one task attempt*, and at what correctness cost. Read the 4 pack wins below as "raw-ref, given one shot, produced a shallower synthesis than an arm that started pre-digested" rather than "raw-ref was blind to something" — and read pair 3 (the one raw-ref win) as the sharpest evidence of the corresponding cost: a pack can encode a synthesis that has drifted from live truth, and an arm that trusts it uncritically can assert something false that an arm forced to re-derive from live state every time structurally cannot.
-
-## Method
-
-5 pairs, each at a distinct real checkpoint commit in this session's own devloop history. Each pair: two isolated Agent-tool subagents (worktree-isolated), one given only `bd`/`git`/repo-source access ("raw-ref"), one given the same access plus a hand-written bounded summary of recent shipped work and standing goals ("handoff-pack"). Both attempt the same task: reconstruct devloop state and recommend a specific next bead. A ground-truth file was written *before* dispatching each pair's arms, recording the checkpoint and (where knowable) what actually happened next. A separate, blinded judge subagent scored each pair against its ground truth without being told which arm was which.
-
-## Corpus
-
-This session's own live devloop (2026-07-09), five checkpoints: commits `6c12e9234`, `64c079d6e`, `01592e5e9`, `a2ee55ec4`, `697470661`.
-
-## Findings
-
-| Pair | Checkpoint | raw-ref | handoff-pack | Winner |
-|---|---|---|---|---|
-| 1 | 6c12e9234 | 29 (judge_1); 22 (judge_2) | 33 (judge_1); 35 (judge_2) | handoff-pack (both judges) |
-| 2 | 64c079d6e | 25 | 31 | handoff-pack |
-| 3 | 01592e5e9 | 31 | 19 | raw-ref |
-| 4 | a2ee55ec4 | 17 | 32 | handoff-pack |
-| 5 | 697470661 | 12 | 36 | handoff-pack |
-
-Handoff-pack wins 4 of 5 pairs. Mean scores: raw-ref 22.8/40, handoff-pack 30.2/40.
-
-**Where handoff-pack won**, the differentiator was consistently *open-thread coverage* and *avoiding a total miss on the checkpoint's own significance* — e.g. in pair 5, the raw-ref arm called the checkpoint commit itself "an unrelated shipped fix" when it was the load-bearing event; in pair 4, raw-ref never identified the literally-in-progress bead as in-progress. The pack arms consistently surfaced named epics/threads (pj8, 3tl, cfk, the 212.x chain, the lineage epic) that the raw-ref arms, working from `bd`/`git` alone, more often missed or under-weighted.
-
-**Where raw-ref won (pair 3)**, the pack arm made a confident, uncaveated factual error — asserting two beads (`4ts.4`, `xnkf`) were "already closed" at a checkpoint where they had not yet shipped. This is a genuine, real failure mode: a pack can encode information that's subtly ahead of (or stale relative to) the actual checkpoint, and an arm that trusts it uncritically can assert something false with high confidence. The raw-ref arm, forced to derive everything from the live state at that exact commit, could not make this specific class of error.
-
-## Specimens
-
-All 10 arm transcripts and 6 judge verdicts are in `arms/*.md` and recorded inline above; raw scores in `pairs.json`. `pairs.json`'s pair-1 row uses judge_1's scores (29/33) as the aggregate table's value with judge_2's (22/35) not separately averaged in, since both judges agreed on the winning direction and picking either alone doesn't change the sign-test outcome; a future revision could instead average the two.
-
-## Counterexamples
-
-Pair 3 is the explicit counterexample: a well-resourced arm can still fail when its input encodes inaccurate-for-this-checkpoint information and it doesn't verify against live state before asserting. This is exactly the "packet staleness" failure mode the original `jxe` campaign identified — not fully eliminated by giving the pack arm live query access, since it can simply not use that access to catch a factual error the pack primed it to assume.
-
-## Limits
-
-- **n=5 is not a publishable sample.** The protocol's own staged design calls for n≥12-20 for a publishable uplift claim. This result should be read as "worth continuing to n=12-20," not as a conclusion.
-- **Correlated subject and rater.** All 5 checkpoints come from the same session/devloop, authored, ground-truthed, and (for the initial pilot pair) partially scored within the same overall session that generated the subject matter. This is a real construct-validity limit shared with the original `jxe` pilot.
-- **Weaker isolation than the original protocol.** The original `jxe`/`jxe.2` pilot used fully separate Claude Code CLI invocations with distinct tracked `agent_id`s per arm. This re-run uses `Agent`-tool subagents in isolated git worktrees within the same orchestrating session — real process/context isolation, but not as strong a guarantee as fully independent CLI sessions.
-- **Pair 1's blind was compromised** (the pack arm's own text self-referenced "the pack"), discovered after dispatch. A second independent judge, explicitly told to check for and account for such a leak, still scored the same direction (35 vs 22), which is reassuring but doesn't retroactively fix the methodology for that pair — later pairs' arm prompts were corrected to forbid self-referential process commentary.
-- **This pilot did not test the "packet staleness" root cause directly** — i.e., it didn't measure whether `qt3`'s fast regeneration + `yps` freshness metadata actually keep a pack fresh under load; it assumed the packs handed to the pack arms were fresh (hand-written summaries, not regenerated via the production pack-generation pipeline). A full re-run per the original protocol would generate the pack through the actual pipeline at continuation time and verify freshness metadata, which this pilot did not do.
-
-## Reproduce
-
-The five ground-truth files (`metrics/ground-truth*.json`), the `pairs.json` aggregate, and every arm/judge transcript are committed under this directory. Re-running with the production pack-generation pipeline (rather than hand-written summaries) and extending to n≥12 pairs, drawn from genuinely independent subjects rather than one session's own consecutive checkpoints, is the next step toward a publishable result — tracked as a follow-up on `polylogue-cfk` rather than assumed complete by this pilot.
diff --git a/.circleci/config.yml b/.circleci/config.yml
index b824682990..b7f98e3694 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -3,12 +3,12 @@ version: 2.1
# CircleCI free-tier CI while GitHub Actions is billing-locked (and a cheap
# second opinion afterwards). Credit budget: ~30k credits/month on the free
# plan. Design keeps the per-push cost low and the heavy work nightly:
-# - quick-gate (PRs + master pushes): public claims + `devtools verify
-# --quick` itself (not a hand-picked subset of its steps -- see
+# - quick-gate (PRs + master pushes): `devtools verify --quick` itself (not a
+# hand-picked subset of its steps -- see
# polylogue-ze5i: this job used to reimplement ruff/mypy/render-all as
# separate `run` steps and silently diverged from what
# devtools/verify.py's `if not commit:` block actually gates, so
-# schema-versioning/classifier-fingerprints/demo-tour-freshness and
+# schema-versioning and
# every other check added to that block over time never ran in real CI
# even though `.github/workflows/ci.yml` referenced them -- that GHA
# workflow does not execute, only CircleCI does). No pytest; the test
@@ -17,10 +17,9 @@ version: 2.1
# only.
# - lab-policies (scheduled pipeline named "nightly"): the `lab policy *`
# checks that stay --lab-only because they scan the whole Beads/backlog
-# corpus rather than the current diff (backlog-hygiene, bead-graph) or
+# corpus rather than the current diff (bead-graph) or
# are otherwise not cheap/deterministic enough for every push
-# (timestamp-doctrine, insight-honesty, demo-packet-registry, docs-drift,
-# campaign-archive-boundaries). Runs nightly so a policy that fails
+# (timestamp-doctrine, insight-honesty). Runs nightly so a policy that fails
# continuously is at least visible somewhere, per polylogue-ze5i AC2,
# instead of only reachable via a human remembering `devtools verify
# --lab`.
@@ -68,9 +67,6 @@ jobs:
- mypy-v1-{{ .Branch }}
- mypy-v1-master
- mypy-v1-
- - run:
- name: Public claims gate
- command: ~/.local/bin/uv run devtools verify public-claims --json | tee /tmp/polylogue-public-claims.json
- run:
name: Structured PR scope carrier
command: |
@@ -95,10 +91,6 @@ jobs:
key: mypy-v1-{{ .Branch }}-{{ epoch }}
paths:
- .mypy_cache
- - store_artifacts:
- path: /tmp/polylogue-public-claims.json
- destination: diagnostics
- when: always
- store_artifacts:
path: /tmp/polylogue-pr-scope.log
destination: diagnostics
@@ -113,11 +105,9 @@ jobs:
- bootstrap
# Each currently-red check runs with `when: always` so one failure
# doesn't hide the pass/fail signal of the others in the same job --
- # backlog-hygiene and bead-graph are known-red until the pre-existing
- # backlog debt they report is triaged (tracked separately; see
- # polylogue-ze5i notes), and that must not mask a genuine regression
- # in timestamp-doctrine/insight-honesty/demo-packet-registry/
- # docs-drift/campaign-archive-boundaries going unnoticed.
+ # bead-graph reports repository-wide graph state rather than the current
+ # diff, and that must not mask a genuine regression
+ # in timestamp-doctrine/insight-honesty going unnoticed.
- run:
name: lab policy timestamp-doctrine
command: ~/.local/bin/uv run devtools lab policy timestamp-doctrine
@@ -127,24 +117,8 @@ jobs:
command: ~/.local/bin/uv run devtools lab policy insight-honesty
when: always
- run:
- name: lab policy demo-packet-registry
- command: ~/.local/bin/uv run devtools lab policy demo-packet-registry
- when: always
- - run:
- name: lab policy docs-drift
- command: ~/.local/bin/uv run devtools lab policy docs-drift
- when: always
- - run:
- name: lab policy campaign-archive-boundaries
- command: ~/.local/bin/uv run devtools lab policy campaign-archive-boundaries
- when: always
- - run:
- name: lab policy backlog-hygiene (known backlog debt, see polylogue-ze5i)
- command: ~/.local/bin/uv run devtools lab policy backlog-hygiene
- when: always
- - run:
- name: lab policy bead-graph (known backlog debt, see polylogue-ze5i)
- command: ~/.local/bin/uv run devtools lab policy bead-graph
+ name: lab policy bead-graph
+ command: ~/.local/bin/uv run devtools lab policy bead-graph --export .beads/issues.jsonl
when: always
full-suite:
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index ba3b626d42..5cbb22a5a4 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -20,6 +20,8 @@ _Exact commands run and any manual validation performed._
## Bead disposition matrix
+_Required for Bead-scoped PRs. Delete this section when the carrier uses `scope_kind=self_contained`._
+
| Assigned Bead | Whole-Bead disposition | Evidence refs | Named successor for residual work |
| --- | --- | --- | --- |
| `polylogue-...` | satisfied / partial / deferred / superseded | `test:...`, `command:...` | `polylogue-...` or n/a |
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4f53387317..1d80d4e141 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -30,7 +30,6 @@ jobs:
python-version: "3.14"
- run: uv sync --extra dev --frozen
- run: uv run devtools render all --check
- - run: uv run devtools verify public-claims --json
# An index schema bump merged without its lifecycle.py delta declaration
# downgrades every live generation to a full raw replay (polylogue-9rw0).
- run: uv run devtools lab policy schema-versioning
@@ -57,12 +56,8 @@ jobs:
POLYLOGUE_PYTEST_BASETEMP_ROOT: ${{ runner.temp }}/polylogue-pytest
test:
- # The full non-integration suite runs single-process under coverage
- # instrumentation across three Python versions; 45 min was on the edge and
- # legs were being cut mid-run (reported as "cancelled"), so the test gate
- # could never go green. 90 min gives headroom; passing runs cost their
- # actual ~45-50 min regardless of the ceiling.
- #
+ # The full suite runs under coverage instrumentation. Keep a generous job
+ # ceiling so pytest's per-test timeout can report the actual stalled node.
# This heavy gate is intentionally OFF the per-PR path (operator decision):
# the ~18 min wait on every PR was not worth it. It still runs post-merge on
# master (regression net) and on demand via workflow_dispatch, but no longer
diff --git a/.tokeignore b/.tokeignore
index 847d7a3f99..005105a5ea 100644
--- a/.tokeignore
+++ b/.tokeignore
@@ -28,9 +28,8 @@ webui/package-lock.json
webui/src/api/generated.ts
webui/src/generated/
-# Generated/rendered doc surfaces and demo artifacts.
+# Generated/rendered doc surfaces.
docs/cli-reference.md
-docs/examples/demo-tour/report.json
# Rendered byte-identical copy of polylogue/agent_integration/data/deep-reference.md;
# the source copy stays counted, this duplicate does not.
diff --git a/CLAUDE.md b/CLAUDE.md
index 7321576791..406af0f9ef 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -197,7 +197,7 @@ Two evolution regimes, enforced by `devtools lab policy schema-versioning`:
non-semantic delta upgrades an existing generation **in place** through
`index_fast_forward_plan()` on connect. Only a `SEMANTIC_REPARSE` delta — one
whose result depends on parser semantics — routes to
- `polylogue ops reset --index && polylogued run`. A bump without a declaration
+ `polylogue ops maintenance rebuild-index`. A bump without a declaration
is a policy violation, not a free rebuild: the lint fails and the archive
silently falls back to full raw replay.
@@ -293,7 +293,7 @@ scripts under any name. (Its evidence may still sit in a gitignored,
untracked `.agent/archive/devloop-2026-07/` in some working checkouts —
polylogue-ocby — it is not part of the repo and a fresh clone will not have
it.) Repo agent conventions: `.agent/CONVENTIONS.md`; run
-`devtools lab policy acceptance-contracts` and `devtools lab policy bead-graph` before shipping bead-state deltas. Run `bd prime` when task
+`devtools lab policy bead-graph --export .beads/issues.jsonl` before shipping bead-state deltas. Run `bd prime` when task
context, ready work, blockers, or project memory matter. Use `bd ready --json`,
`bd show --json`, `bd update --claim --json`,
`bd close --reason "…" --json`. Create linked Beads issues for discovered
@@ -354,8 +354,12 @@ Don't treat CI as the first verification pass — anticipate failures locally.
See [Schema regimes](#schema-regimes-durability-keyed). Durable tiers → numbered
additive migration + backup manifest; derived tiers → edit canonical DDL +
-rebuild plan (`polylogue ops reset --index && polylogued run`), never an upgrade
-helper (`devtools lab policy schema-versioning` rejects them).
+an explicitly declared lifecycle delta. Non-semantic deltas may use the
+clone-validated `index_fast_forward_plan()` route; semantic deltas require
+`polylogue ops maintenance rebuild-index`. Ad hoc open-path upgrade code is not
+an accepted third route. `devtools lab policy schema-versioning` validates the
+declarations, durable migration slots, and same-version benign-DDL shapes; it
+does not infer architecture from helper names.
### Multi-lane / merge-train tooling — use these, don't reinvent the discipline by hand
@@ -377,8 +381,10 @@ workflow, not optional conveniences — use them at the point named, every time:
- **Before claiming a batch of ready beads**: `devtools workspace bead-cluster`
— footprint/overlap/contention clustering so overlapping-file beads land on
one branch instead of colliding across parallel lanes.
-- **When dispatching a worktree-isolated lane**: `devtools workspace lane-brief
- --out ` for its dispatch prompt (footprint, prior art, hazards).
+- **When dispatching a worktree-isolated lane**: give the worker the current
+ Bead acceptance criteria, verified file ownership, relevant prior commits,
+ concrete non-goals, and exact verification commands directly. Do not insert
+ a generated Markdown packet between the current evidence and the worker.
- **Before opening a non-draft PR for a Bead lane**: render the versioned
carrier with `devtools workspace pr-scope render --input `, put
it in the PR body beside the human whole-Bead disposition matrix, then run
@@ -407,7 +413,7 @@ workflow, not optional conveniences — use them at the point named, every time:
then auto-records a receipt if none is fresh for the current head
sha (running `--command`, default `devtools verify`), BLOCKs the merge on
any `merge-gate check` failure (no fresh receipt, stale receipt, nonzero
- exit, a changed head-bound scope attestation, or an unacked review comment newer than the head commit), strips a
+ exit, a changed head-bound scope attestation, an unresolved GitHub review thread, or a changes-requested review), strips a
doubled `(#N) (#N)` squash-subject suffix, then runs the actual
`gh pr merge --squash`. `--dry-run` runs every check without merging;
`--with-verify` immediately runs and records the merge-train's terminal
@@ -420,9 +426,6 @@ workflow, not optional conveniences — use them at the point named, every time:
`devtools workspace merge-gate record/check` commands still exist for
ad hoc receipt inspection, but the merge action itself should go through
`workspace merge`.
-- Sizing/triage input: `devtools workspace backlog-calibration` for
- lead-time/discovery/staleness distributions before deciding batch size.
-
If you build a new tool in this family, add it here in the same sentence —
a tool without a line in this file is a tool the next session won't use.
@@ -561,7 +564,7 @@ Core loop:
[Verification](#verification--testmon-inner-loop-never-blanket-run).
- `devtools test ` — focused pytest through the managed harness.
- `devtools lab …` — executable schema/provider/pipeline/lane checks.
-- `devtools workspace …` — task history, frontier, worktree-gc, evidence.
+- `devtools workspace …` — task history, worktree-gc, evidence.
Adding a devtools command: add a `CommandSpec` to `devtools/command_catalog.py`,
implement in `devtools/.py`, run `devtools render devtools-reference`.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index cfb48e2ca3..87c535c270 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -117,8 +117,10 @@ changes require a copy-forward design and explicit operator consent; do not
hide them behind a routine migration.
Derived tiers (`index.db`, `embeddings.db`) are rebuildable products. They do
-not get in-place migration chains. A PR that bumps their schema edits the
-canonical DDL and provides a **rebuild/blue-green plan**:
+do not get ad hoc in-place migration chains. A PR that bumps their schema edits
+the canonical DDL, declares the delta in `storage/sqlite/lifecycle.py`, and
+provides either a clone-validated non-semantic fast-forward plan or a
+**rebuild/blue-green plan** for semantic changes:
- which user-visible archive operation triggers rebuild/re-acquisition from
source (e.g. `polylogue ops reset --index && polylogued run` for index-tier
@@ -136,8 +138,11 @@ index additions that can be grouped into one schema bump, and do not call a
full reingest necessary unless the changed semantics actually require replaying
source rows.
-The policy lint (`devtools lab policy schema-versioning`) rejects derived-tier
-upgrade helpers while allowing numbered durable-tier SQL migrations.
+The policy lint (`devtools lab policy schema-versioning`) validates derived-tier
+lifecycle declarations and clone-safe benign-DDL shapes while allowing numbered
+durable-tier SQL migrations. It does not attempt to classify Python helpers by
+their names; ad hoc open-path upgrades remain unsupported because the runtime
+routes derived changes only through declared fast-forward plans or rebuilds.
## Versioning and Releases
diff --git a/README.md b/README.md
index f072b63cc9..8182ffc453 100644
--- a/README.md
+++ b/README.md
@@ -9,15 +9,13 @@
-
Polylogue archives AI conversations and coding-agent runs from multiple tools in
one searchable local archive. It imports supported histories from ChatGPT,
Claude and Claude Code, Codex, Gemini, Hermes, and other sources, then exposes
sessions, messages, tool calls and results, branches, subagents, usage, and costs
through a CLI, Python API, local HTTP reader, and MCP server.
-By default, the archive stays on your machine. The author's archive contains
-more than **18,000 sessions and 4.7 million messages**.
+By default, the archive stays on your machine.
[Getting started](docs/getting-started.md) | [Live documentation](https://sinity.github.io/polylogue/) | [Demo](docs/demos.md) | [Architecture](docs/architecture.md) | [CLI reference](docs/cli-reference.md)
@@ -222,7 +220,6 @@ Start with the task-oriented guides below. The complete documentation map is in
| [Getting Started](docs/getting-started.md) | Install Polylogue, create an archive, and run a first query. |
| [Installation](docs/installation.md) | Package, source-checkout, Nix, and managed deployment options. |
| [Demos and Proofs](docs/demos.md) | Run the private-data-free tour and see what each demo establishes. |
-| [Proof Artifacts](docs/proof-artifacts.md) | Links between public claims and reproducible checks. |
| [Architecture](docs/architecture.md) | Storage, data flow, and component responsibilities. |
| [Code Navigation](docs/code-navigation.md) | Find the owning package, runtime path, and verification for a code change. |
| [Search & Query](docs/search.md) | Search syntax, filters, action queries, ranking, and output formats. |
diff --git a/TESTING.md b/TESTING.md
index 77eeee105a..3973786889 100644
--- a/TESTING.md
+++ b/TESTING.md
@@ -222,10 +222,9 @@ and `.cache/verify/current-pytest-output.log` to see the active/latest test node
selected/deselected node IDs, collection duration, slowest setup/call/teardown
phases, captured output, and termination reason if a focused run stalls.
-For optional lane, mutation-campaign, and benchmark inventories, see
-[docs/test-quality-workflows.md](docs/test-quality-workflows.md). Those registries are
-secondary navigation over executable checks; the source of truth for behavior is
-pytest plus the concrete `polylogue`/`devtools` commands they invoke.
+Optional lane, mutation-campaign, and benchmark commands remain discoverable
+through `devtools --help`; pytest and the concrete commands are the behavioral
+authority.
### Known limitation: collection-time-only imports are invisible to testmon
@@ -245,37 +244,12 @@ inherent to how testmon (and coverage-context-based selective testing in
general) works — it is **not** dependency-graph staleness, and running
`devtools verify --seed-testmon` does not fix it.
-Confirmed reproducible (2026-07-12, polylogue-csg7) with an isolated,
-freshly-seeded testmon run scoped to exactly one test file: after
-`TESTMON_DATAFILE= pytest --testmon --testmon-noselect
-tests/unit/devtools/test_verify_manifests.py`, `devtools/manifest_models.py`
-still has 0 `file_fp` rows even though a `--cov` run over the same test file
-reports 80% statement coverage on that module — all of it from Pydantic
-model/field declarations executed when `devtools.verify_manifests` is
-imported at module-collection time; every uncovered line is inside a
-`@field_validator`/`@model_validator` method body, which only runs when
-`validate_manifest()` is actually called (no test in that file calls it).
-
-Cross-referencing a full-suite `coverage.json` (`--cov=polylogue`) against
-`file_fp` filenames finds **95 files** under `polylogue/` with nonzero
-covered statements but zero testmon dependency rows — largely `*_models.py`,
-`types.py`, `protocols.py`, `enums.py`, and `api/contracts/*.py`, i.e. modules
-whose test-suite touch points are import-only. Query:
-
-```python
-import json, sqlite3
-
-cov = json.load(open(".cache/coverage/coverage.json"))["files"]
-tm = {r[0] for r in sqlite3.connect(".cache/testmon/testmondata").execute("SELECT DISTINCT filename FROM file_fp")}
-gaps = [(f, d["summary"]["covered_lines"]) for f, d in cov.items() if d["summary"]["covered_lines"] > 0 and f not in tm]
-```
-
**Blast radius:** the default `devtools verify` gate (`--testmon
--testmon-forceselect`) is the only local pre-merge signal for a change
scoped to one of these files — `devtools test ` forwards a literal
pytest selection and is not testmon-aware, so it does not share this gap
(point it at the file's *owning test module*, not the changed source file).
-A change confined to one of these 95 files can select zero tests locally and
+A change confined to one of these files can select zero tests locally and
still report a clean `devtools verify`. The heavy full-suite `devtools verify
coverage` CI job (`.github/workflows/ci.yml`) does not use testmon selection
and still catches such a regression, but only **post-merge** (it is
@@ -288,9 +262,7 @@ upstream tool behavior. When changing a file that is purely declarative
do not trust "0 tests selected" from the default `devtools verify` gate as
proof of safety; run the file's owning test module directly with `devtools
test `, and rely on `mypy --strict` (already in the default gate)
-to catch structural regressions in `TypedDict`/protocol shapes. See
-polylogue-csg7 for the investigation and a follow-up tracking item for making
-this gap machine-checkable.
+to catch structural regressions in `TypedDict`/protocol shapes.
## Test Suite Layout
@@ -450,15 +422,13 @@ checks HTTP/DOM/API contracts rather than screenshots.
```bash
devtools bench mutation list
devtools bench mutation run
-devtools bench mutation index
```
Policy:
- keep the committed mutmut configuration broad; narrow work happens through
focused campaigns
-- write local artifacts under `.local/mutation-campaigns/`
-- rebuild the mutation index after a campaign run
+- write per-run JSON artifacts under `.local/mutation-campaigns/`
## Protected Files
diff --git a/browser-extension/README.md b/browser-extension/README.md
index 226957d1ce..ae8504e98f 100644
--- a/browser-extension/README.md
+++ b/browser-extension/README.md
@@ -232,7 +232,7 @@ pages the badge shows grey and no data is sent.
|---------|-------|
| Badge is grey | Navigate to a supported page (chatgpt.com, claude.ai, or grok.com) |
| Badge is red | Receiver is not running — start `polylogued browser-capture serve` |
-| Captures not appearing in archive | Run `polylogue check` to verify the daemon is ingesting |
+| Captures not appearing in archive | Run `polylogue ops doctor --runtime --daemon` to verify the daemon is ingesting |
| Popup says `stale` | The receiver has a newer spool artifact than the indexed archive. Leave the daemon running and inspect the debug log request id if it does not converge. |
| Popup says `dom` / `dom_degraded` | Reload the provider page, wait for the conversation to load fully, then capture again so the native app payload can be observed. |
| A button click seems ineffective | The button status line should show Working/Done/Failed. Open **Debug log** and export JSON if the state does not change. |
diff --git a/devtools/acceptance_route_registry.py b/devtools/acceptance_route_registry.py
deleted file mode 100644
index 22f8bb18de..0000000000
--- a/devtools/acceptance_route_registry.py
+++ /dev/null
@@ -1,64 +0,0 @@
-"""Authoritative route registry for acceptance-contract dispatch."""
-
-from __future__ import annotations
-
-from collections.abc import Mapping
-from pathlib import Path
-from typing import Any
-
-from polylogue.core.json import JSONDecodeError
-from polylogue.core.json import loads as json_loads
-
-_REGISTRY_PATH = Path(__file__).parents[1] / "docs" / "plans" / "beads-acceptance-route-registry.json"
-
-
-class AcceptanceRouteRegistryError(ValueError):
- """Raised when the committed route registry is missing or malformed."""
-
-
-def load_registry(path: Path = _REGISTRY_PATH) -> dict[str, dict[str, Any]]:
- if not path.is_file():
- raise AcceptanceRouteRegistryError(f"{path}: acceptance route registry is missing")
- try:
- document = json_loads(path.read_text(encoding="utf-8"))
- except JSONDecodeError as exc:
- raise AcceptanceRouteRegistryError(f"{path}: invalid JSON: {exc}") from exc
- if not isinstance(document, Mapping) or document.get("schema_version") != 1:
- raise AcceptanceRouteRegistryError(f"{path}: unsupported acceptance route registry schema")
- entries = document.get("routes")
- if not isinstance(entries, list):
- raise AcceptanceRouteRegistryError(f"{path}: routes must be a list")
- registry: dict[str, dict[str, Any]] = {}
- for entry in entries:
- if not isinstance(entry, Mapping):
- raise AcceptanceRouteRegistryError(f"{path}: route entries must be objects")
- identifier = entry.get("identifier")
- if not isinstance(identifier, str) or not identifier:
- raise AcceptanceRouteRegistryError(f"{path}: route entry has no identifier")
- if identifier in registry:
- raise AcceptanceRouteRegistryError(f"{path}: duplicate route identifier {identifier!r}")
- registry[identifier] = dict(entry)
- return registry
-
-
-def resolve_route(
- identifier: object, *, registry: Mapping[str, Mapping[str, Any]] | None = None
-) -> Mapping[str, Any] | None:
- if not isinstance(identifier, str):
- return None
- routes = load_registry() if registry is None else registry
- return routes.get(identifier)
-
-
-def registry_digest(registry: Mapping[str, Mapping[str, Any]] | None = None) -> str:
- """Return the digest of the sorted route-entry payload."""
- import hashlib
-
- from polylogue.core.json import dumps as json_dumps
-
- routes = load_registry() if registry is None else registry
- payload = json_dumps(
- [routes[identifier] for identifier in sorted(routes)],
- sort_keys=True,
- )
- return hashlib.sha256(payload.encode("utf-8")).hexdigest()
diff --git a/devtools/action_contract_report.py b/devtools/action_contract_report.py
deleted file mode 100644
index 85b2a7d210..0000000000
--- a/devtools/action_contract_report.py
+++ /dev/null
@@ -1,96 +0,0 @@
-"""Render the public CLI action-contract report for generated docs."""
-
-from __future__ import annotations
-
-from collections.abc import Iterable
-
-from devtools.render_cli_output_schemas import SCHEMAS, CliOutputSchema
-from polylogue.operations.action_contracts import ACTION_CONTRACTS
-
-
-def _path_cell(path: tuple[str, ...]) -> str:
- return f"`polylogue {' '.join(path)}`"
-
-
-def _code_cell(value: str) -> str:
- return f"`{value}`"
-
-
-def _list_cell(values: Iterable[str]) -> str:
- rendered = tuple(_code_cell(value) for value in values)
- return ", ".join(rendered) if rendered else "-"
-
-
-def _format_set(values: frozenset[str]) -> tuple[str, ...]:
- order = {"human": 0, "json": 1, "ndjson": 2}
- return tuple(sorted(values, key=order.__getitem__))
-
-
-def _contract_rows() -> list[str]:
- rows = [
- "| Action | Effect | Target | Input | Cardinality | Safety | Formats | Destinations | Confirm | Select | Machine envelope | Guards | Next actions | Completion |",
- "| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |",
- ]
- for contract in ACTION_CONTRACTS:
- rows.append(
- " | ".join(
- (
- _path_cell(contract.path),
- _code_cell(contract.effect),
- _code_cell(contract.target),
- _code_cell(contract.input_unit),
- _code_cell(contract.cardinality),
- _code_cell(contract.safety_level),
- _list_cell(_format_set(contract.formats)),
- _list_cell(contract.destination_support),
- _code_cell(contract.confirmation_command) if contract.confirmation_command else "-",
- _code_cell(contract.selection_command) if contract.selection_command else "-",
- _code_cell(contract.machine_envelope),
- _list_cell(contract.guards),
- _list_cell(contract.next_actions),
- _code_cell(contract.completion_context) if contract.completion_context else "-",
- )
- ).join(("| ", " |"))
- )
- return rows
-
-
-def _schema_rows(schemas: tuple[CliOutputSchema, ...] = SCHEMAS) -> list[str]:
- rows = [
- "| Schema | Model | Surfaces |",
- "| --- | --- | --- |",
- ]
- for schema in schemas:
- rows.append(
- " | ".join(
- (
- f"`{schema.name}`",
- _code_cell(schema.model.__name__),
- " ".join(_code_cell(surface) for surface in schema.surfaces),
- )
- ).join(("| ", " |"))
- )
- return rows
-
-
-def render_action_contract_report() -> str:
- """Return the generated CLI action/output contract report."""
- lines = [
- "## Public Action Contracts",
- "",
- "This section is generated from `polylogue.operations.action_contracts.ACTION_CONTRACTS`.",
- "It records the public action floor, not every utility command in the Click tree.",
- "",
- *_contract_rows(),
- "",
- "## Published Machine Output Schemas",
- "",
- "This section is generated from `devtools.render_cli_output_schemas.SCHEMAS`.",
- "The schema files live under `docs/schemas/cli-output/`.",
- "",
- *_schema_rows(),
- ]
- return "\n".join(lines).rstrip()
-
-
-__all__ = ["render_action_contract_report"]
diff --git a/devtools/affordance_usage.py b/devtools/affordance_usage.py
index 97bd131128..28b21c0c7f 100644
--- a/devtools/affordance_usage.py
+++ b/devtools/affordance_usage.py
@@ -210,32 +210,15 @@ def _demo_summary(report: dict[str, Any]) -> dict[str, Any]:
"index_db": report["index_db"],
"snapshot_identity": report["snapshot_identity"],
"index_schema_version": report["index_schema_version"],
- "claim": (
- "Polylogue can compare agent affordance usage across normalized action evidence "
- "without summing unlike tool-name spellings or provider-specific call shapes."
- ),
- "non_claim": (
- "This is not a human-quality utility evaluation of any particular tool family. "
- "It measures captured usage evidence, failure signals, and coverage gaps; "
- "usefulness still requires qualitative review of session context and outcomes."
- ),
- "proof_report": {
- "report_version": report["report_version"],
- "action_scope": report["action_scope"],
- "recent_window_days": report["recent_window_days"],
- "patterns": report["patterns"],
- "detail_patterns": report["detail_patterns"],
- "top_families": summary["top_families"],
- "recent_top_families": summary["recent_top_families"],
- "surface_inventory_summary": surface_summary,
- },
- "caveats": [
- "Counts describe captured action evidence, not independent proof of user benefit.",
- "Failure rates are provider-reported tool-result signals where available; missing outcome structure is not success.",
- "Recent windows are adoption-sensitive and can legitimately differ from all-time counts.",
- "Zero captured agent use is not enough to remove operator-only surfaces; those rows carry an operator-only caveat.",
- ],
- "source_files": [
+ "report_version": report["report_version"],
+ "action_scope": report["action_scope"],
+ "recent_window_days": report["recent_window_days"],
+ "patterns": report["patterns"],
+ "detail_patterns": report["detail_patterns"],
+ "top_families": summary["top_families"],
+ "recent_top_families": summary["recent_top_families"],
+ "surface_inventory_summary": surface_summary,
+ "files": [
"affordance-usage.report.json",
"family-counts.csv",
"evidence-kind-counts.csv",
diff --git a/devtools/artifact_graph.py b/devtools/artifact_graph.py
index 250b56bc86..ded75732b1 100644
--- a/devtools/artifact_graph.py
+++ b/devtools/artifact_graph.py
@@ -6,17 +6,13 @@
import json
import sys
-from devtools.scenario_coverage import build_runtime_scenario_coverage
from polylogue.artifacts.graph import build_artifact_graph
def render_artifact_graph(*, as_json: bool) -> str:
graph = build_artifact_graph()
- coverage = build_runtime_scenario_coverage()
if as_json:
- payload = graph.to_dict()
- payload["scenario_coverage"] = coverage.to_dict()
- return json.dumps(payload, indent=2)
+ return json.dumps(graph.to_dict(), indent=2)
lines: list[str] = ["Artifact Paths:"]
for path in graph.paths:
@@ -48,60 +44,15 @@ def render_artifact_graph(*, as_json: bool) -> str:
lines.append(f"- {target.name} [{target.mode.value}/{target.category.value}]: {target.description}")
lines.append(f" - artifacts: {artifacts}")
lines.append(f" - operations: {operations}")
- lines.append("")
- lines.append("Runtime Path Coverage:")
- for path_name, path_coverage in sorted(coverage.paths.items()):
- status = "complete" if path_coverage.complete else "partial"
- rendered_refs = ", ".join(f"{ref.source}:{ref.name}" for ref in path_coverage.refs) or "—"
- lines.append(f"- {path_name} [{status}]: {rendered_refs}")
- if path_coverage.uncovered_artifacts:
- lines.append(f" - uncovered artifacts: {', '.join(path_coverage.uncovered_artifacts)}")
- if path_coverage.uncovered_operations:
- lines.append(f" - uncovered operations: {', '.join(path_coverage.uncovered_operations)}")
- lines.append("")
- lines.append("Runtime Scenario Coverage:")
- if not coverage.artifacts and not coverage.operations:
- lines.append("- none")
- return "\n".join(lines)
- for artifact_name, refs in sorted(coverage.artifacts.items()):
- rendered_refs = ", ".join(f"{ref.source}:{ref.name}" for ref in refs)
- lines.append(f"- artifact {artifact_name}: {rendered_refs}")
- for operation_name, refs in sorted(coverage.operations.items()):
- rendered_refs = ", ".join(f"{ref.source}:{ref.name}" for ref in refs)
- lines.append(f"- operation {operation_name}: {rendered_refs}")
- for target_name, refs in sorted(coverage.maintenance_targets.items()):
- rendered_refs = ", ".join(f"{ref.source}:{ref.name}" for ref in refs)
- lines.append(f"- maintenance {target_name}: {rendered_refs}")
- if coverage.uncovered_artifacts:
- lines.append("- uncovered artifacts: " + ", ".join(coverage.uncovered_artifacts))
- if coverage.uncovered_operations:
- lines.append("- uncovered operations: " + ", ".join(coverage.uncovered_operations))
- if coverage.uncovered_maintenance_targets:
- lines.append("- uncovered maintenance targets: " + ", ".join(coverage.uncovered_maintenance_targets))
return "\n".join(lines)
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--json", action="store_true", help="Emit the artifact graph as JSON.")
- parser.add_argument(
- "--strict",
- action="store_true",
- help="Fail with exit 1 if any runtime artifact, declared operation, maintenance target, or operation path is uncovered.",
- )
args = parser.parse_args(argv)
sys.stdout.write(render_artifact_graph(as_json=args.json))
sys.stdout.write("\n")
- if args.strict:
- coverage = build_runtime_scenario_coverage()
- if (
- coverage.uncovered_artifacts
- or coverage.uncovered_operations
- or coverage.uncovered_declared_operations
- or coverage.uncovered_maintenance_targets
- or any(not path.complete for path in coverage.paths.values())
- ):
- return 1
return 0
diff --git a/devtools/authored_scenario_catalog.py b/devtools/authored_scenario_catalog.py
deleted file mode 100644
index 6474976966..0000000000
--- a/devtools/authored_scenario_catalog.py
+++ /dev/null
@@ -1,92 +0,0 @@
-"""Central authored catalog for verification lanes and campaigns."""
-
-from __future__ import annotations
-
-from dataclasses import dataclass
-from functools import lru_cache
-
-from devtools.benchmark_catalog import (
- BenchmarkCampaignEntry,
- build_benchmark_entries,
- build_synthetic_benchmark_entries,
-)
-from devtools.lane_models import LaneEntry
-from devtools.mutation_catalog import MutationCampaignEntry, build_mutation_entries
-from devtools.validation_catalog import build_validation_lane_entries
-from polylogue.scenarios import (
- CorpusScenario,
- ScenarioProjectionEntry,
- ScenarioProjectionSource,
- compile_projection_entries,
-)
-from polylogue.schemas.operator.inference import list_inferred_corpus_scenarios
-
-
-@dataclass(frozen=True)
-class AuthoredScenarioCatalog:
- validation_lanes: tuple[LaneEntry, ...]
- mutation_campaigns: tuple[MutationCampaignEntry, ...]
- benchmark_campaigns: tuple[BenchmarkCampaignEntry, ...]
- synthetic_benchmark_campaigns: tuple[BenchmarkCampaignEntry, ...]
- inferred_corpus_scenarios: tuple[CorpusScenario, ...]
-
- @property
- def contract_lanes(self) -> tuple[LaneEntry, ...]:
- return tuple(entry for entry in self.validation_lanes if entry.category == "contract")
-
- @property
- def live_lanes(self) -> tuple[LaneEntry, ...]:
- return tuple(entry for entry in self.validation_lanes if entry.category == "live")
-
- @property
- def composite_lanes(self) -> tuple[LaneEntry, ...]:
- return tuple(entry for entry in self.validation_lanes if entry.category == "composite")
-
- def projection_sources(self) -> tuple[ScenarioProjectionSource, ...]:
- result: list[ScenarioProjectionSource] = []
- result.extend(self.validation_lanes) # type: ignore[arg-type]
- result.extend(self.mutation_campaigns)
- result.extend(self.benchmark_campaigns)
- result.extend(self.synthetic_benchmark_campaigns)
- result.extend(self.inferred_corpus_scenarios)
- return tuple(result)
-
- def validation_lane_index(self) -> dict[str, LaneEntry]:
- return {entry.name: entry for entry in self.validation_lanes}
-
- def mutation_campaign_index(self) -> dict[str, MutationCampaignEntry]:
- return {entry.name: entry for entry in self.mutation_campaigns}
-
- def benchmark_campaign_index(self) -> dict[str, BenchmarkCampaignEntry]:
- return {entry.name: entry for entry in self.benchmark_campaigns}
-
- def synthetic_benchmark_campaign_index(self) -> dict[str, BenchmarkCampaignEntry]:
- return {entry.name: entry for entry in self.synthetic_benchmark_campaigns}
-
- def compile_projection_entries(self) -> tuple[ScenarioProjectionEntry, ...]:
- return tuple(
- sorted(
- compile_projection_entries(self.projection_sources()),
- key=lambda item: (item.source_kind.value, item.name),
- )
- )
-
-
-@lru_cache(maxsize=1)
-def get_authored_scenario_catalog() -> AuthoredScenarioCatalog:
- # Repo-authored surfaces (rendered docs, verify gates) must be hermetic:
- # pin the schema registry to the in-repo SCHEMA_DIR so operator-local
- # inferred schemas under data_home()/schemas cannot leak into generated
- # docs or flip `render --check` per machine.
- from polylogue.schemas.registry import SCHEMA_DIR, SchemaRegistry
-
- return AuthoredScenarioCatalog(
- validation_lanes=build_validation_lane_entries(),
- mutation_campaigns=build_mutation_entries(),
- benchmark_campaigns=build_benchmark_entries(),
- synthetic_benchmark_campaigns=build_synthetic_benchmark_entries(),
- inferred_corpus_scenarios=list_inferred_corpus_scenarios(registry=SchemaRegistry(storage_root=SCHEMA_DIR)),
- )
-
-
-__all__ = ["AuthoredScenarioCatalog", "get_authored_scenario_catalog"]
diff --git a/devtools/backlog_calibration.py b/devtools/backlog_calibration.py
deleted file mode 100644
index 47b32f171d..0000000000
--- a/devtools/backlog_calibration.py
+++ /dev/null
@@ -1,444 +0,0 @@
-"""backlog-calibration: measured duration/discovery models over the bead corpus.
-
-Fits the numbers a backlog-execution plan needs from the actual bead history
-(and optionally the merged-PR history) instead of guessing them:
-
- - closed-bead lead-time percentiles, overall and split by priority, type,
- epic-child vs standalone, and dependency degree;
- - a right-censoring-honest survival view (fraction of a >=14d-old cohort
- closed within 1/3/7/14 days) -- closed-only medians are survivorship-
- biased and this section is the corrective;
- - close-reason classification (worked vs already-satisfied / obsolete /
- duplicate / misframed) with median age-at-closure per class -- the
- "verify before dispatching" economy;
- - discovery-vs-drain dynamics: created and closed per day, the
- created-per-close ratio, and net backlog growth;
- - optionally, PR open->merge latency by changed-file bucket from a
- `gh pr list --json` dump.
-
-Calibrated against 2026-07 history for the backlog-execution design
-(/realm/inbox/polylogue-audits-2026-07-31/backlog-execution-design.html);
-registered as a devtools command so the model can be re-fitted as the corpus
-grows instead of going stale like the guesses it replaced.
-
-Usage:
- # Fresh export (bd export -o under the hood):
- devtools workspace backlog-calibration
-
- # From an existing export / in tests:
- devtools workspace backlog-calibration --input beads.jsonl
-
- # Include PR merge-latency calibration:
- # gh pr list --state merged --limit 4000 \
- # --json number,createdAt,mergedAt,additions,deletions,changedFiles > prs.json
- devtools workspace backlog-calibration --prs prs.json
-
- # Machine-readable:
- devtools workspace backlog-calibration --json
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import subprocess
-import sys
-import tempfile
-from collections import Counter, defaultdict
-from collections.abc import Sequence
-from datetime import UTC, datetime
-from pathlib import Path
-from re import IGNORECASE
-from re import compile as re_compile
-from typing import Any
-
-BeadDict = dict[str, Any]
-
-_DAY_SECONDS = 86400.0
-_PERCENTILES = (10, 25, 50, 75, 90, 95)
-_SURVIVAL_WINDOWS_DAYS = (1, 3, 7, 14)
-_COHORT_MIN_AGE_DAYS = 14.0
-
-# Close-reason classes, checked in order; first match wins. "worked" is the
-# fall-through. Regexes over free text are advisory classification, not truth.
-_CLOSE_REASON_CLASSES: tuple[tuple[str, Any], ...] = (
- ("duplicate", re_compile(r"\bdup(?:e|licate)?\b", IGNORECASE)),
- (
- "already-satisfied",
- re_compile(r"\balready\b|\bsatisfied by\b|\bfixed by\b|\bfixed in\b", IGNORECASE),
- ),
- (
- "obsolete",
- re_compile(r"\bobsolete\b|\bsuperseded\b|\bno longer\b|\bstale\b|\bmoot\b", IGNORECASE),
- ),
- (
- "misframed",
- re_compile(r"\bmisframed\b|\binvalid\b|\bnot a bug\b|\bworking as\b", IGNORECASE),
- ),
-)
-NO_IMPLEMENTATION_CLASSES = frozenset(c for c, _ in _CLOSE_REASON_CLASSES)
-
-
-def _parse_ts(value: Any) -> datetime | None:
- if not isinstance(value, str) or not value:
- return None
- try:
- parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
- except ValueError:
- return None
- if parsed.tzinfo is None:
- parsed = parsed.replace(tzinfo=UTC)
- return parsed
-
-
-def _percentile(sorted_values: list[float], pct: float) -> float:
- if not sorted_values:
- raise ValueError("empty distribution")
- if len(sorted_values) == 1:
- return sorted_values[0]
- rank = (len(sorted_values) - 1) * pct / 100.0
- lower = int(rank)
- if lower >= len(sorted_values) - 1:
- return sorted_values[-1]
- frac = rank - lower
- return sorted_values[lower] + (sorted_values[lower + 1] - sorted_values[lower]) * frac
-
-
-def summarize_days(values: list[float]) -> dict[str, Any]:
- """Percentile summary of a list of durations expressed in days."""
- if not values:
- return {"n": 0}
- ordered = sorted(values)
- summary: dict[str, Any] = {"n": len(ordered)}
- for pct in _PERCENTILES:
- summary[f"p{pct}_days"] = round(_percentile(ordered, pct), 3)
- summary["max_days"] = round(ordered[-1], 3)
- return summary
-
-
-def classify_close_reason(reason: str | None) -> str:
- """Classify a free-text close reason; 'worked' is the fall-through."""
- text = reason or ""
- for name, pattern in _CLOSE_REASON_CLASSES:
- if pattern.search(text):
- return name
- return "worked"
-
-
-def _lead_days(bead: BeadDict) -> float | None:
- created = _parse_ts(bead.get("created_at"))
- closed = _parse_ts(bead.get("closed_at"))
- if created is None or closed is None or bead.get("status") != "closed":
- return None
- return (closed - created).total_seconds() / _DAY_SECONDS
-
-
-def _epic_child_ids(beads: list[BeadDict]) -> frozenset[str]:
- children: set[str] = set()
- for bead in beads:
- for dep in bead.get("dependencies") or []:
- if isinstance(dep, dict) and dep.get("type") == "parent-child":
- children.add(str(bead.get("id")))
- return frozenset(children)
-
-
-def _split_summaries(closed: list[tuple[BeadDict, float]], key: Any) -> dict[str, dict[str, Any]]:
- groups: dict[str, list[float]] = defaultdict(list)
- for bead, lead in closed:
- groups[str(key(bead))].append(lead)
- return {name: summarize_days(values) for name, values in sorted(groups.items())}
-
-
-def _survival(beads: list[BeadDict], as_of: datetime) -> dict[str, Any]:
- cohort = [
- bead
- for bead in beads
- if (created := _parse_ts(bead.get("created_at"))) is not None
- and (as_of - created).total_seconds() / _DAY_SECONDS >= _COHORT_MIN_AGE_DAYS
- ]
-
- def _fractions(members: list[BeadDict]) -> dict[str, Any]:
- row: dict[str, Any] = {"n": len(members)}
- for window in _SURVIVAL_WINDOWS_DAYS:
- closed_in = sum(1 for bead in members if (lead := _lead_days(bead)) is not None and lead <= window)
- row[f"closed_within_{window}d_pct"] = round(100.0 * closed_in / len(members), 1) if members else None
- return row
-
- by_priority = {
- f"P{priority}": _fractions([b for b in cohort if b.get("priority") == priority]) for priority in range(5)
- }
- return {
- "cohort_min_age_days": _COHORT_MIN_AGE_DAYS,
- "overall": _fractions(cohort),
- "by_priority": by_priority,
- }
-
-
-def _discovery(beads: list[BeadDict]) -> dict[str, Any]:
- created_per_day: Counter[str] = Counter()
- closed_per_day: Counter[str] = Counter()
- for bead in beads:
- created = _parse_ts(bead.get("created_at"))
- closed = _parse_ts(bead.get("closed_at"))
- if created is not None:
- created_per_day[created.date().isoformat()] += 1
- if closed is not None:
- closed_per_day[closed.date().isoformat()] += 1
- days = sorted(set(created_per_day) | set(closed_per_day))
- if not days:
- return {"days": [], "note": "no dated beads"}
- # The first day of a corpus is typically a bulk import, not discovery.
- import_day = days[0]
- series: list[dict[str, Any]] = [
- {
- "day": day,
- "created": created_per_day.get(day, 0),
- "closed": closed_per_day.get(day, 0),
- "net": created_per_day.get(day, 0) - closed_per_day.get(day, 0),
- }
- for day in days
- ]
- post = [row for row in series if row["day"] != import_day]
- created_total = sum(int(row["created"]) for row in post)
- closed_total = sum(int(row["closed"]) for row in post)
- nets: list[float] = sorted(float(row["net"]) for row in post)
- return {
- "import_day_excluded": import_day,
- "days": series,
- "post_import_created": created_total,
- "post_import_closed": closed_total,
- "created_per_close": (round(created_total / closed_total, 2) if closed_total else None),
- "median_net_per_day": (round(_percentile(nets, 50), 1) if nets else None),
- "net_negative_days": sum(1 for net in nets if net < 0),
- "post_import_day_count": len(post),
- }
-
-
-def _close_reasons(closed: list[tuple[BeadDict, float]]) -> dict[str, Any]:
- with_reason = [(bead, lead) for bead, lead in closed if bead.get("close_reason")]
- classes: dict[str, list[float]] = defaultdict(list)
- for bead, lead in with_reason:
- classes[classify_close_reason(bead.get("close_reason"))].append(lead)
- no_impl = sum(len(v) for name, v in classes.items() if name in NO_IMPLEMENTATION_CLASSES)
- return {
- "closed_with_reason": len(with_reason),
- "no_implementation_pct": (round(100.0 * no_impl / len(with_reason), 1) if with_reason else None),
- "classes": {name: summarize_days(values) for name, values in sorted(classes.items())},
- }
-
-
-_PR_FILE_BUCKETS: tuple[tuple[int, int, str], ...] = (
- (1, 3, "1-2"),
- (3, 6, "3-5"),
- (6, 11, "6-10"),
- (11, 31, "11-30"),
- (31, 10**9, "31+"),
-)
-
-
-def _pr_latency(prs: list[dict[str, Any]]) -> dict[str, Any]:
- rows: list[tuple[int, float]] = []
- for pr in prs:
- created = _parse_ts(pr.get("createdAt"))
- merged = _parse_ts(pr.get("mergedAt"))
- files = pr.get("changedFiles")
- if created is None or merged is None or not isinstance(files, int):
- continue
- rows.append((files, (merged - created).total_seconds() / 3600.0))
- buckets = {
- label: summarize_days([hours / 24.0 for files, hours in rows if lo <= files < hi])
- for lo, hi, label in _PR_FILE_BUCKETS
- }
- return {
- "n": len(rows),
- "overall_latency_hours": {
- k: (round(v * 24.0, 3) if isinstance(v, float) else v)
- for k, v in summarize_days([hours / 24.0 for _, hours in rows]).items()
- },
- "by_changed_files_days": buckets,
- "note": (
- "open->merge latency measures the merge train, not implementation: "
- "PRs in this repo open after the work is done"
- ),
- }
-
-
-def build_report(
- beads: list[BeadDict],
- *,
- as_of: datetime,
- prs: list[dict[str, Any]] | None = None,
-) -> dict[str, Any]:
- closed = [(bead, lead) for bead in beads if (lead := _lead_days(bead)) is not None]
- epic_children = _epic_child_ids(beads)
- corpus_age_days = None
- created_times = [t for bead in beads if (t := _parse_ts(bead.get("created_at")))]
- if created_times:
- corpus_age_days = round((as_of - min(created_times)).total_seconds() / _DAY_SECONDS, 1)
- report: dict[str, Any] = {
- "as_of": as_of.isoformat(),
- "population": {
- "total": len(beads),
- "by_status": dict(Counter(str(b.get("status")) for b in beads)),
- "corpus_age_days": corpus_age_days,
- "censoring_note": (
- "closed-only lead times are right-censored by corpus age and "
- "survivorship-biased by still-open beads; read the survival "
- "section for population-honest fractions"
- ),
- },
- "closed_lead_days": {
- "overall": summarize_days([lead for _, lead in closed]),
- "by_priority": _split_summaries(closed, lambda b: f"P{b.get('priority')}"),
- "by_type": _split_summaries(closed, lambda b: b.get("issue_type")),
- "by_epic_membership": _split_summaries(
- closed,
- lambda b: "epic-child" if str(b.get("id")) in epic_children else "standalone",
- ),
- "by_dependency_degree": _split_summaries(
- closed,
- lambda b: min(int(b.get("dependency_count") or 0), 2),
- ),
- },
- "survival": _survival(beads, as_of),
- "close_reasons": _close_reasons(closed),
- "discovery": _discovery(beads),
- }
- if prs is not None:
- report["pr_merge_latency"] = _pr_latency(prs)
- return report
-
-
-def _load_beads_jsonl(path: Path) -> list[BeadDict]:
- beads: list[BeadDict] = []
- for line_number, line in enumerate(path.read_text().splitlines(), start=1):
- if not line.strip():
- continue
- try:
- record = json.loads(line)
- except json.JSONDecodeError as exc:
- raise SystemExit(f"{path}:{line_number}: not valid JSON ({exc})") from exc
- if isinstance(record, dict):
- beads.append(record)
- return beads
-
-
-def _export_beads() -> list[BeadDict]:
- with tempfile.NamedTemporaryFile(suffix=".jsonl", prefix="backlog-calib-") as handle:
- result = subprocess.run(
- ["bd", "export", "-o", handle.name],
- capture_output=True,
- text=True,
- check=False,
- )
- if result.returncode != 0:
- raise SystemExit(f"bd export failed: {result.stderr.strip() or result.stdout.strip()}")
- return _load_beads_jsonl(Path(handle.name))
-
-
-def _fmt_days(value: Any) -> str:
- if not isinstance(value, (int, float)):
- return "-"
- return f"{value * 24:.1f}h" if value < 1 else f"{value:.1f}d"
-
-
-def _render_summary_line(name: str, summary: dict[str, Any]) -> str:
- if summary.get("n", 0) == 0:
- return f" {name:<16} n=0"
- return (
- f" {name:<16} n={summary['n']:<5} p50={_fmt_days(summary.get('p50_days')):<7} "
- f"p90={_fmt_days(summary.get('p90_days')):<7} max={_fmt_days(summary.get('max_days'))}"
- )
-
-
-def _render_human(report: dict[str, Any]) -> str:
- lines: list[str] = []
- population = report["population"]
- lines.append(
- f"backlog-calibration as of {report['as_of']} -- "
- f"{population['total']} beads ({population['by_status']}), "
- f"corpus age {population['corpus_age_days']}d"
- )
- lines.append(f"NOTE: {population['censoring_note']}")
- lead = report["closed_lead_days"]
- lines.append("\nclosed lead time (days):")
- lines.append(_render_summary_line("overall", lead["overall"]))
- for section in ("by_priority", "by_type", "by_epic_membership", "by_dependency_degree"):
- lines.append(f" {section}:")
- for name, summary in lead[section].items():
- lines.append(_render_summary_line(name, summary))
- survival = report["survival"]
- lines.append(
- f"\nsurvival (cohort created >={survival['cohort_min_age_days']:.0f}d ago, "
- f"n={survival['overall']['n']}): fraction closed within window"
- )
- for name, row in [("overall", survival["overall"]), *survival["by_priority"].items()]:
- if row["n"] == 0:
- continue
- windows = " ".join(f"{window}d={row[f'closed_within_{window}d_pct']}%" for window in _SURVIVAL_WINDOWS_DAYS)
- lines.append(f" {name:<8} n={row['n']:<5} {windows}")
- reasons = report["close_reasons"]
- lines.append(
- f"\nclose reasons (n={reasons['closed_with_reason']} with reason; "
- f"{reasons['no_implementation_pct']}% needed no implementation):"
- )
- for name, summary in reasons["classes"].items():
- lines.append(_render_summary_line(name, summary))
- discovery = report["discovery"]
- lines.append(
- f"\ndiscovery vs drain (excluding import day {discovery.get('import_day_excluded')}): "
- f"created={discovery.get('post_import_created')} "
- f"closed={discovery.get('post_import_closed')} "
- f"created-per-close={discovery.get('created_per_close')} "
- f"median-net/day={discovery.get('median_net_per_day')} "
- f"net-negative-days={discovery.get('net_negative_days')}"
- f"/{discovery.get('post_import_day_count')}"
- )
- if "pr_merge_latency" in report:
- pr = report["pr_merge_latency"]
- lines.append(f"\nPR open->merge latency (n={pr['n']}): {pr['note']}")
- for label, summary in pr["by_changed_files_days"].items():
- lines.append(_render_summary_line(f"{label} files", summary))
- return "\n".join(lines)
-
-
-def main(argv: Sequence[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- prog="devtools workspace backlog-calibration",
- description="Measured duration/discovery models over the bead corpus.",
- )
- parser.add_argument(
- "--input",
- "-i",
- metavar="FILE",
- help="Bead JSONL export (bd export -o FILE); default runs bd export itself",
- )
- parser.add_argument(
- "--prs",
- metavar="FILE",
- help=(
- "Optional gh dump: gh pr list --state merged --limit 4000 "
- "--json number,createdAt,mergedAt,additions,deletions,changedFiles"
- ),
- )
- parser.add_argument("--json", action="store_true", dest="json_out", help="JSON output")
- args = parser.parse_args(argv)
-
- beads = _load_beads_jsonl(Path(args.input)) if args.input else _export_beads()
- prs: list[dict[str, Any]] | None = None
- if args.prs:
- loaded = json.loads(Path(args.prs).read_text())
- if not isinstance(loaded, list):
- raise SystemExit(f"{args.prs}: expected a JSON array of PRs")
- prs = loaded
-
- report = build_report(beads, as_of=datetime.now(UTC), prs=prs)
- if args.json_out:
- print(json.dumps(report, indent=2))
- else:
- print(_render_human(report))
- return 0
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/bead_batch_show.py b/devtools/bead_batch_show.py
deleted file mode 100644
index 8ecd2ebf8c..0000000000
--- a/devtools/bead_batch_show.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"""Batch-show beads: id, status, prio, title, desc head, deps, notes tail.
-
-Usage: devtools workspace bead-batch-show [ ...]
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import subprocess
-import sys
-from typing import Any
-
-
-def _dep_str(dep: dict[str, Any]) -> str:
- target = dep.get("depends_on_id") or dep.get("to_id") or dep.get("id") or "?"
- return f"{target}({dep.get('type') or dep.get('dep_type') or '?'})"
-
-
-def _show_one(bead_id: str) -> None:
- result = subprocess.run(["bd", "show", bead_id, "--json"], capture_output=True, text=True)
- try:
- record = json.loads(result.stdout)[0]
- except Exception:
- print(f"== {bead_id} MISSING/ERROR: {result.stderr.strip()[:120]}")
- return
- print(f"== {record['id']} [{record['status']}] P{record['priority']} {record['issue_type']} | {record['title']}")
- desc = (record.get("description") or "").replace("\n", " ")[:280]
- print(f" DESC: {desc}")
- deps = record.get("dependencies") or []
- if deps:
- print(" DEPS:", ", ".join(_dep_str(d) if isinstance(d, dict) else str(d) for d in deps))
- notes = (record.get("notes") or "").replace("\n", " ")
- if notes:
- print(f" NOTES-tail: ...{notes[-240:]}")
- print()
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("bead_ids", nargs="+", help="Bead ids to show (e.g. polylogue-kapb)")
- args = parser.parse_args(argv)
- for bead_id in args.bead_ids:
- _show_one(bead_id)
- return 0
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/bead_cluster.py b/devtools/bead_cluster.py
index 6103192e8f..4ce76a130c 100644
--- a/devtools/bead_cluster.py
+++ b/devtools/bead_cluster.py
@@ -52,7 +52,7 @@
``frontier_clusters`` entries with ``len(beads) > 1`` rather than trusting a
frozen number. The plain any-overlap graph (``_build_overlap_graph`` /
``_connected_components``) is kept as a general-purpose utility (also used
-by ``devtools workspace lane-brief`` and other footprint tooling) but is no
+by footprint and overlap tooling) but is no
longer used to shape the FRONTIER-READY cluster output.
Usage:
diff --git a/devtools/beads_acceptance_applier.py b/devtools/beads_acceptance_applier.py
deleted file mode 100644
index 24c1406ca1..0000000000
--- a/devtools/beads_acceptance_applier.py
+++ /dev/null
@@ -1,75 +0,0 @@
-"""Apply an exact, already-reconciled acceptance wave to a file copy.
-
-This is a local file actuator for testing and coordinator dry runs. It never
-invokes ``bd`` and never writes a Beads database.
-"""
-
-from __future__ import annotations
-
-import argparse
-from pathlib import Path
-from typing import Any
-
-from devtools import beads_acceptance_reconciliation as reconciliation
-from polylogue.core.json import dumps as json_dumps
-
-
-def apply_guarded_wave(*, repository: Path, before: Path, wave: Path, report: Path, output: Path) -> dict[str, Any]:
- """Write the exact guarded result, or accept an identical prior result."""
- _, before_rows, wave_rows, report_value = reconciliation._validate_report_and_wave(
- repository=repository,
- before=before,
- wave=wave,
- report_path=report,
- )
- expected_rows = dict(before_rows)
- expected_rows.update(wave_rows)
- expected_order = list(before_rows)
- expected_digest = reconciliation.equality_digest(expected_rows)
- if output.exists():
- existing = reconciliation.load_jsonl(output)
- if list(existing) == expected_order and reconciliation.equality_digest(existing) == expected_digest:
- return {
- "ok": True,
- "idempotent": True,
- "output_population_digest": expected_digest,
- "report_digest": reconciliation.report_digest(report_value),
- "targeted_ids": report_value["targeted_ids"],
- }
- raise reconciliation.ReconciliationError("output already exists with a different guarded population")
- reconciliation._write_jsonl(output, (expected_rows[bead_id] for bead_id in expected_order))
- return {
- "ok": True,
- "idempotent": False,
- "output_population_digest": expected_digest,
- "report_digest": reconciliation.report_digest(report_value),
- "targeted_ids": report_value["targeted_ids"],
- }
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--repository", type=Path, required=True)
- parser.add_argument("--before", type=Path, required=True)
- parser.add_argument("--wave", type=Path, required=True)
- parser.add_argument("--report", type=Path, required=True)
- parser.add_argument("--output", type=Path, required=True)
- parser.add_argument("--json", action="store_true")
- args = parser.parse_args(argv)
- try:
- result = apply_guarded_wave(
- repository=args.repository,
- before=args.before,
- wave=args.wave,
- report=args.report,
- output=args.output,
- )
- except reconciliation.ReconciliationError as exc:
- print(str(exc))
- return 1
- print(json_dumps(result, indent=2, sort_keys=True))
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/beads_acceptance_contracts.py b/devtools/beads_acceptance_contracts.py
deleted file mode 100644
index fc8e72aa3a..0000000000
--- a/devtools/beads_acceptance_contracts.py
+++ /dev/null
@@ -1,655 +0,0 @@
-from __future__ import annotations
-
-import argparse
-import hashlib
-import re
-from collections.abc import Iterable, Mapping
-from pathlib import Path
-from typing import Any
-
-from devtools.acceptance_route_registry import (
- AcceptanceRouteRegistryError,
- load_registry,
- registry_digest,
- resolve_route,
-)
-from polylogue.core.json import JSONDecodeError
-from polylogue.core.json import dumps as json_dumps
-from polylogue.core.json import loads as json_loads
-
-_ALLOWED_TYPES = {
- "implementation",
- "live_operation",
- "audit",
- "decision",
- "epic",
- "test_harness",
- "process",
- "documentation",
-}
-_ALLOWED_RISKS = {"ordinary", "read-only", "durable-mutation", "semantic-integrity", "resource-concurrency"}
-_ALLOWED_CONFIDENCE = {"high", "medium", "planner-review"}
-_ALLOWED_CLOSURE_DISPOSITIONS = {"whole-or-explicit-partial"}
-_ALLOWED_ROUTE_MODES = {"named"}
-_ALLOWED_ROUTE_DISPATCH = {"production", "read-only", "decision", "documentation"}
-_ROUTE_IDENTIFIER = re.compile(r"^[a-z][a-z0-9]*(?:[._:/-][a-z0-9]+)*$")
-_ROUTE_DISPATCH_BY_TYPE = {
- "implementation": frozenset({"production"}),
- "live_operation": frozenset({"production"}),
- "audit": frozenset({"read-only"}),
- "decision": frozenset({"decision"}),
- "epic": frozenset({"production"}),
- "test_harness": frozenset({"production"}),
- "process": frozenset({"production"}),
- "documentation": frozenset({"documentation"}),
-}
-_ROUTE_CLASS_BY_TYPE = {
- "implementation": "ImplementationRoute",
- "live_operation": "LiveOperationRoute",
- "audit": "AuditRoute",
- "decision": "DecisionRoute",
- "epic": "EpicRoute",
- "test_harness": "TestHarnessRoute",
- "process": "ProcessRoute",
- "documentation": "DocumentationRoute",
-}
-_EVIDENCE_SPAN_FIELDS = frozenset({"source_field", "snapshot", "snapshot_digest", "range", "text_digest"})
-_EVIDENCE_RANGE_FIELDS = frozenset({"start", "end"})
-_ALLOWED_VERIFICATION_MANAGERS = {"devtools"}
-_ALLOWED_VERIFICATION_FOCUSED = {"devtools test"}
-_ALLOWED_VERIFICATION_DEFAULT = {"devtools verify"}
-_ALLOWED_RECEIPT_KINDS = {"live-operation"}
-_ALLOWED_RECEIPT_REQUIREMENTS = {"required"}
-_REQUIRED_RECEIPT_BINDINGS = frozenset(
- {"archive_identity", "operation", "target", "before_state", "after_state", "result_status"}
-)
-_PLACEHOLDER = re.compile(
- r"(?:<[^>]+>|\.{3}|\b(?:TBD|TODO|FIXME|as appropriate|figure out|choose an approach|add suitable tests)\b)",
- re.I,
-)
-_ROUTE_PLACEHOLDER = re.compile(r"\b(?:where applicable|as appropriate)\b", re.I)
-_SOURCE_FIELDS = ("id", "title", "description", "design", "notes", "priority", "issue_type")
-_SHA256 = re.compile(r"^[0-9a-f]{64}$")
-_MANIFEST_ID = re.compile(r"^polylogue-[a-z0-9]+(?:\.[a-z0-9]+)*$")
-_DEFAULT_MANIFEST = Path(__file__).parents[1] / "docs" / "plans" / "beads-acceptance-contracts-2026-08-07.txt"
-_EXPECTED_MANIFEST_COUNT = 218
-_EXPECTED_MANIFEST_DIGEST = "703df11c81dae8af6d7106bc4737502ca8baddc9013916bbb68922696d8206b5"
-
-
-class DependencyProjectionError(ValueError):
- """Raised when a structured dependency projection contains an invalid scalar."""
-
-
-def _dependency_projection(issue: Mapping[str, Any]) -> list[dict[str, str | None]]:
- """Return a stable, scope-bearing projection of Bead dependencies."""
- raw_dependencies = issue.get("dependencies")
- if raw_dependencies is None:
- return []
- if not isinstance(raw_dependencies, list):
- return [{"invalid_type": type(raw_dependencies).__name__}]
- dependencies: list[dict[str, str | None]] = []
- for index, dependency in enumerate(raw_dependencies):
- if isinstance(dependency, dict):
- depends_on_id = _dependency_scalar(dependency, index, ("depends_on_id", "to_id", "id"), "depends_on_id")
- dependency_type = _dependency_scalar(dependency, index, ("type", "dep_type"), "type")
- dependencies.append(
- {
- "depends_on_id": depends_on_id,
- "type": dependency_type,
- }
- )
- elif isinstance(dependency, str):
- dependencies.append({"depends_on_id": dependency, "type": None})
- else:
- dependencies.append({"invalid_type": type(dependency).__name__})
- return sorted(
- dependencies,
- key=lambda dependency: (
- dependency.get("depends_on_id") or "",
- dependency.get("type") or "",
- dependency.get("invalid_type") or "",
- ),
- )
-
-
-def _dependency_scalar(dependency: Mapping[str, Any], index: int, keys: tuple[str, ...], label: str) -> str | None:
- for key in keys:
- value = dependency.get(key)
- if value is None:
- continue
- if not isinstance(value, str):
- raise DependencyProjectionError(
- f"dependencies[{index}].{label} must be a string or null (got {type(value).__name__})"
- )
- return value
- return None
-
-
-def dependency_digest(issue: Mapping[str, Any]) -> str:
- """Return the digest for the canonical dependency projection."""
- return hashlib.sha256(json_dumps(_dependency_projection(issue), sort_keys=True).encode("utf-8")).hexdigest()
-
-
-def source_digest(issue: dict[str, Any]) -> str:
- """Return the digest bound to scope fields and the stable dependency projection."""
- payload = {key: issue.get(key) for key in _SOURCE_FIELDS}
- payload["dependencies"] = _dependency_projection(issue)
- return hashlib.sha256(json_dumps(payload, sort_keys=True).encode("utf-8")).hexdigest()
-
-
-def _decode_document(value: object) -> dict[str, Any] | None:
- if isinstance(value, dict):
- return value
- if not isinstance(value, str):
- return None
- try:
- parsed = json_loads(value)
- except JSONDecodeError:
- return None
- return parsed if isinstance(parsed, dict) else None
-
-
-def _require_string(errors: list[str], value: object, key: str) -> None:
- if not isinstance(value, str) or not value.strip():
- errors.append(f"{key} must be a non-empty string")
-
-
-def _require_string_list(errors: list[str], contract: dict[str, Any], key: str, *, optional: bool = False) -> bool:
- value = contract.get(key)
- if value == [] and optional:
- return True
- if not isinstance(value, list) or not value:
- if optional:
- errors.append(f"{key} must be a list of strings; use [] when empty")
- else:
- errors.append(f"{key} must be a non-empty list of strings")
- return False
- if any(not isinstance(item, str) or not item.strip() for item in value):
- errors.append(f"{key} must contain only non-empty strings")
- return False
- return True
-
-
-def _require_mapping(errors: list[str], value: object, key: str) -> Mapping[str, Any] | None:
- if not isinstance(value, Mapping):
- errors.append(f"{key} must be an object")
- return None
- return value
-
-
-def _validate_route_spec(errors: list[str], contract: dict[str, Any]) -> bool:
- route_spec = _require_mapping(errors, contract.get("route_spec"), "route_spec")
- if route_spec is None:
- return False
- valid = True
- if set(route_spec) != {"mode", "identifier", "class", "dispatch"}:
- errors.append("route_spec fields must be exactly mode, identifier, class, and dispatch")
- valid = False
- mode = route_spec.get("mode")
- if not isinstance(mode, str) or mode not in _ALLOWED_ROUTE_MODES:
- errors.append("route_spec.mode must be named")
- valid = False
- identifier = route_spec.get("identifier")
- if not isinstance(identifier, str) or not identifier.strip():
- errors.append("route_spec.identifier must be a non-empty named identifier")
- valid = False
- elif not _ROUTE_IDENTIFIER.fullmatch(identifier):
- errors.append("route_spec.identifier must be a structured named identifier")
- valid = False
- dispatch = route_spec.get("dispatch")
- if not isinstance(dispatch, str) or dispatch not in _ALLOWED_ROUTE_DISPATCH:
- errors.append("route_spec.dispatch is invalid")
- valid = False
- else:
- contract_type = contract.get("contract_type")
- allowed_dispatch = _ROUTE_DISPATCH_BY_TYPE.get(
- contract_type if isinstance(contract_type, str) else "", frozenset()
- )
- if dispatch not in allowed_dispatch:
- errors.append(
- f"route_spec.dispatch {dispatch!r} is incompatible with contract_type {contract.get('contract_type')!r}"
- )
- valid = False
- identifier = route_spec.get("identifier")
- try:
- registered = resolve_route(identifier)
- except AcceptanceRouteRegistryError as exc:
- errors.append(str(exc))
- return False
- if registered is None:
- errors.append(f"route_spec.identifier {identifier!r} is not registered")
- return False
- registered_bead_id = registered.get("bead_id")
- if not isinstance(registered_bead_id, str) or not registered_bead_id:
- errors.append("registered route authority must bind a non-empty Bead id")
- valid = False
- if not isinstance(contract.get("bead_id"), str) or registered_bead_id != contract.get("bead_id"):
- errors.append("route_spec.identifier is registered for a different Bead")
- valid = False
- registered_contract_type = registered.get("contract_type")
- if not isinstance(registered_contract_type, str) or registered_contract_type != contract.get("contract_type"):
- errors.append("route_spec.identifier is registered for a different contract_type")
- valid = False
- registered_dispatch = registered.get("dispatch")
- if not isinstance(registered_dispatch, str) or registered_dispatch != dispatch:
- errors.append("route_spec.dispatch does not match the registered route class")
- valid = False
- contract_type = contract.get("contract_type")
- expected_class = _ROUTE_CLASS_BY_TYPE.get(contract_type if isinstance(contract_type, str) else "")
- route_class = route_spec.get("class")
- if not isinstance(route_class, str) or route_class != expected_class:
- errors.append("route_spec.class does not match the contract_type")
- valid = False
- registered_class = registered.get("class")
- if not isinstance(registered_class, str) or registered_class != route_class:
- errors.append("route_spec.class does not match the registered route class")
- valid = False
- targets = registered.get("targets")
- if not isinstance(targets, list) or any(not isinstance(target, str) for target in targets):
- errors.append("registered route authority has no target list")
- valid = False
- elif targets != contract.get("routes"):
- errors.append("route_spec targets do not match the registered route authority")
- valid = False
- return valid
-
-
-def _validate_verification_route(errors: list[str], contract: dict[str, Any]) -> bool:
- route = _require_mapping(errors, contract.get("verification_route"), "verification_route")
- if route is None:
- return False
- valid = True
- manager = route.get("manager")
- if not isinstance(manager, str) or manager not in _ALLOWED_VERIFICATION_MANAGERS:
- errors.append("verification_route.manager must be devtools")
- valid = False
- focused = route.get("focused")
- if not isinstance(focused, str) or focused not in _ALLOWED_VERIFICATION_FOCUSED:
- errors.append("verification_route.focused must be devtools test")
- valid = False
- default = route.get("default")
- if not isinstance(default, str) or default not in _ALLOWED_VERIFICATION_DEFAULT:
- errors.append("verification_route.default must be devtools verify")
- valid = False
- return valid
-
-
-def _validate_receipt(errors: list[str], contract: dict[str, Any]) -> bool:
- receipt = _require_mapping(errors, contract.get("receipt"), "receipt")
- if receipt is None:
- return False
- valid = True
- kind = receipt.get("kind")
- if not isinstance(kind, str) or kind not in _ALLOWED_RECEIPT_KINDS:
- errors.append("receipt.kind must be live-operation")
- valid = False
- requirement = receipt.get("requirement")
- if not isinstance(requirement, str) or requirement not in _ALLOWED_RECEIPT_REQUIREMENTS:
- errors.append("receipt.requirement must be required")
- valid = False
- bindings = receipt.get("bindings")
- if not isinstance(bindings, list) or any(not isinstance(item, str) for item in bindings):
- errors.append("receipt.bindings must be a list of strings")
- return False
- if set(bindings) != _REQUIRED_RECEIPT_BINDINGS or len(bindings) != len(_REQUIRED_RECEIPT_BINDINGS):
- errors.append("receipt.bindings must include each required live-operation dimension exactly once")
- valid = False
- return valid
-
-
-def _validate_evidence_spans(errors: list[str], issue: dict[str, Any], contract: dict[str, Any]) -> None:
- """Validate evidence as byte ranges over the Bead's source fields."""
- evidence = contract.get("evidence")
- spans = contract.get("evidence_spans")
- if not isinstance(evidence, list) or not isinstance(spans, list):
- errors.append("evidence_spans must provide one typed span for every evidence item")
- return
- if len(spans) != len(evidence):
- errors.append("evidence_spans must contain exactly one span for every evidence item")
- return
- for index, (value, span) in enumerate(zip(evidence, spans, strict=True)):
- if not isinstance(span, Mapping):
- errors.append(f"evidence_spans[{index}] must be an object")
- continue
- if set(span) != _EVIDENCE_SPAN_FIELDS:
- errors.append(
- f"evidence_spans[{index}] fields must be exactly source_field, snapshot, snapshot_digest, range, and "
- "text_digest"
- )
- source_field = span.get("source_field")
- if not isinstance(source_field, str) or source_field not in {"title", "description", "design", "notes"}:
- errors.append(f"evidence_spans[{index}].source_field must name title, description, design, or notes")
- source_snapshot = issue.get(source_field) if isinstance(source_field, str) else None
- if not isinstance(source_snapshot, str) or not source_snapshot:
- errors.append(f"evidence_spans[{index}].source_field must reference a non-empty Bead source field")
- snapshot = span.get("snapshot")
- snapshot_bytes: bytes | None = None
- if not isinstance(snapshot, str):
- errors.append(f"evidence_spans[{index}].snapshot must be a UTF-8 snapshot string")
- else:
- snapshot_bytes = snapshot.encode("utf-8")
- if isinstance(source_snapshot, str) and snapshot != source_snapshot:
- errors.append(f"evidence_spans[{index}].snapshot does not match the Bead source field")
- snapshot_digest = span.get("snapshot_digest")
- if not isinstance(snapshot_digest, str) or not _SHA256.fullmatch(snapshot_digest):
- errors.append(f"evidence_spans[{index}].snapshot_digest must be a lowercase SHA-256 digest")
- elif snapshot_bytes is not None and snapshot_digest != hashlib.sha256(snapshot_bytes).hexdigest():
- errors.append(f"evidence_spans[{index}].snapshot_digest does not match the snapshot")
- evidence_range = span.get("range")
- if not isinstance(evidence_range, Mapping) or set(evidence_range) != _EVIDENCE_RANGE_FIELDS:
- errors.append(f"evidence_spans[{index}].range must contain exactly start and end")
- else:
- start = evidence_range.get("start")
- end = evidence_range.get("end")
- if (
- not isinstance(start, int)
- or isinstance(start, bool)
- or not isinstance(end, int)
- or isinstance(end, bool)
- or start < 0
- or end <= start
- ):
- errors.append(f"evidence_spans[{index}].range must be a non-empty half-open integer range")
- elif snapshot_bytes is not None and end > len(snapshot_bytes):
- errors.append(f"evidence_spans[{index}].range exceeds the snapshot byte length")
- text_digest = span.get("text_digest")
- if not isinstance(text_digest, str) or not _SHA256.fullmatch(text_digest):
- errors.append(f"evidence_spans[{index}].text_digest must be a lowercase SHA-256 digest")
- elif snapshot_bytes is not None and isinstance(evidence_range, Mapping):
- start = evidence_range.get("start")
- end = evidence_range.get("end")
- if (
- isinstance(start, int)
- and not isinstance(start, bool)
- and isinstance(end, int)
- and not isinstance(end, bool)
- and 0 <= start < end <= len(snapshot_bytes)
- ):
- span_bytes = snapshot_bytes[start:end]
- try:
- span_text = span_bytes.decode("utf-8")
- except UnicodeDecodeError:
- errors.append(f"evidence_spans[{index}].range must align to UTF-8 boundaries")
- else:
- expected_text_digest = hashlib.sha256(span_bytes).hexdigest()
- if text_digest != expected_text_digest:
- errors.append(f"evidence_spans[{index}].text_digest does not match the snapshot range")
- if value != span_text:
- errors.append(f"evidence_spans[{index}].range text does not match the evidence item")
-
-
-def load_manifest(path: Path) -> tuple[str, ...]:
- """Load and ratchet the committed required-contract inventory."""
- if not path.is_file():
- raise SystemExit(f"{path}: acceptance-contract manifest is missing")
- required_values = path.read_text(encoding="utf-8").split()
- if (
- len(required_values) != _EXPECTED_MANIFEST_COUNT
- or len(set(required_values)) != _EXPECTED_MANIFEST_COUNT
- or any(not _MANIFEST_ID.fullmatch(value) for value in required_values)
- ):
- raise SystemExit(f"{path}: acceptance-contract manifest inventory is invalid")
- manifest_digest = hashlib.sha256(("\n".join(sorted(required_values)) + "\n").encode("utf-8")).hexdigest()
- if manifest_digest != _EXPECTED_MANIFEST_DIGEST:
- raise SystemExit(f"{path}: acceptance-contract manifest inventory changed")
- return tuple(sorted(required_values))
-
-
-def _strings(value: Any) -> Iterable[str]:
- if isinstance(value, str):
- yield value
- elif isinstance(value, list):
- for item in value:
- yield from _strings(item)
- elif isinstance(value, dict):
- for item in value.values():
- yield from _strings(item)
-
-
-def render(contract: dict[str, Any]) -> str:
- rows: list[str] = []
- n = 1
-
- def add(label: str, value: str) -> None:
- nonlocal n
- rows.append(f"{n}. {label}: {value.strip()}")
- n += 1
-
- add("Outcome", contract["outcome"])
- if contract.get("confidence") == "planner-review":
- add("Dispatch gate", "Planner review is required before implementation dispatch.")
- route_spec = contract["route_spec"]
- add(
- "Route authority",
- f"{route_spec['mode']} {route_spec['identifier']} {route_spec['dispatch']} route coverage is required.",
- )
- for value in contract.get("retained_scope", []):
- add("Existing scope retained", value)
- for value in contract.get("routes", []):
- add("Production route", value)
- for value in contract.get("evidence", []):
- add("Evidence", value)
- for value in contract.get("verification", []):
- add("Verification", value)
- for value in contract.get("anti_vacuity", []):
- add("Anti-vacuity", value)
- for value in contract.get("safety", []):
- add("Safety", value)
- contract_type = contract.get("contract_type")
- if isinstance(contract_type, str) and contract_type in {"implementation", "test_harness"}:
- verification_route = contract["verification_route"]
- add(
- "Managed verification route",
- f"focused={verification_route['focused']}; default={verification_route['default']}",
- )
- if contract_type == "live_operation":
- receipt = contract["receipt"]
- add(
- "Receipt requirement",
- f"{receipt['kind']} result={receipt['requirement']} bindings={','.join(receipt['bindings'])}",
- )
- add("Closure disposition", contract["closure"]["disposition"])
- add(
- "Partial closure successor",
- "required when the closure disposition is whole-or-explicit-partial.",
- )
- add("Closure", contract["closure"]["rule"])
- return "\n".join(rows)
-
-
-def validate(issue: dict[str, Any]) -> list[str]:
- errors: list[str] = []
- metadata = _decode_document(issue.get("metadata"))
- if metadata is None:
- return ["metadata is not a JSON object"]
- contract = metadata.get("acceptance_contract_v1")
- if not isinstance(contract, dict):
- return ["missing metadata.acceptance_contract_v1"]
- if contract.get("schema_version") != 1:
- errors.append("schema_version must be 1")
- if contract.get("bead_id") != issue.get("id"):
- errors.append("bead_id does not match issue id")
- contract_type = contract.get("contract_type")
- if not isinstance(contract_type, str) or contract_type not in _ALLOWED_TYPES:
- errors.append("invalid contract_type")
- risk = contract.get("risk")
- if not isinstance(risk, str) or risk not in _ALLOWED_RISKS:
- errors.append("invalid risk")
- confidence = contract.get("confidence")
- if not isinstance(confidence, str) or confidence not in _ALLOWED_CONFIDENCE:
- errors.append("confidence must be high, medium, or planner-review")
- _require_string(errors, contract.get("bead_id"), "bead_id")
- _require_string(errors, contract.get("outcome"), "outcome")
- for key in ("routes", "evidence", "verification", "anti_vacuity"):
- _require_string_list(errors, contract, key)
- _require_string_list(errors, contract, "retained_scope", optional=True)
- _require_string_list(errors, contract, "safety", optional=True)
- _validate_route_spec(errors, contract)
- if isinstance(contract_type, str) and contract_type in {"implementation", "test_harness"}:
- _validate_verification_route(errors, contract)
- closure = contract.get("closure")
- if not isinstance(closure, Mapping):
- errors.append("closure must be an object")
- else:
- _require_string(errors, closure.get("rule"), "closure.rule")
- disposition = closure.get("disposition")
- if not isinstance(disposition, str) or disposition not in _ALLOWED_CLOSURE_DISPOSITIONS:
- errors.append("closure.disposition must be whole-or-explicit-partial")
- if not isinstance(closure.get("successor_required_for_partial"), bool):
- errors.append("closure.successor_required_for_partial must be boolean")
- elif disposition == "whole-or-explicit-partial" and not closure.get("successor_required_for_partial"):
- errors.append("whole-or-explicit-partial requires successor_required_for_partial=true")
- try:
- computed_source_digest = source_digest(issue)
- computed_dependency_digest = dependency_digest(issue)
- except DependencyProjectionError as exc:
- errors.append(str(exc))
- computed_source_digest = None
- computed_dependency_digest = None
- digest = contract.get("source_digest")
- if not isinstance(digest, str) or not _SHA256.fullmatch(digest):
- errors.append("source_digest must be a lowercase SHA-256 digest")
- elif computed_source_digest is not None and digest != computed_source_digest:
- errors.append("source_digest does not match the Bead source snapshot")
- dependency_digest_value = contract.get("dependency_digest")
- if not isinstance(dependency_digest_value, str) or not _SHA256.fullmatch(dependency_digest_value):
- errors.append("dependency_digest must be a lowercase SHA-256 digest")
- elif computed_dependency_digest is not None and dependency_digest_value != computed_dependency_digest:
- errors.append("dependency_digest does not match the Bead dependency projection")
- if issue.get("dependencies") is not None and not isinstance(issue.get("dependencies"), list):
- errors.append("dependencies must be a list")
- if contract_type == "live_operation" and not contract.get("safety"):
- errors.append("live_operation requires safety clauses")
- if contract_type == "live_operation":
- _validate_receipt(errors, contract)
- if risk == "durable-mutation" and not contract.get("safety"):
- errors.append("durable-mutation requires safety clauses")
- for value in contract.get("routes", []) if isinstance(contract.get("routes"), list) else []:
- if isinstance(value, str) and _ROUTE_PLACEHOLDER.search(value):
- errors.append("routes contains a generic placeholder; use named route fields")
- for key, value in contract.items():
- if key in {"evidence", "evidence_spans"}:
- continue
- for text in _strings(value):
- if _PLACEHOLDER.search(text):
- errors.append(f"placeholder in contract: {text[:80]}")
- _validate_evidence_spans(errors, issue, contract)
- if not errors:
- expected = render(contract)
- if issue.get("acceptance_criteria") != expected:
- errors.append("acceptance_criteria drifted from structured contract")
- return sorted(set(errors))
-
-
-def load(path: Path) -> list[dict[str, Any]]:
- rows: list[dict[str, Any]] = []
- for n, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
- if not line.strip():
- continue
- try:
- row = json_loads(line)
- except JSONDecodeError as exc:
- raise SystemExit(f"{path}:{n}: {exc}") from exc
- if not isinstance(row, dict):
- raise SystemExit(f"{path}:{n}: expected a JSON object, got {type(row).__name__}")
- rows.append(row)
- return rows
-
-
-def validate_route_registry(required_ids: Iterable[str]) -> list[str]:
- """Check that the committed route authority covers exactly the manifest IDs."""
- try:
- registry = load_registry()
- except AcceptanceRouteRegistryError as exc:
- return [str(exc)]
- required = set(required_ids)
- errors: list[str] = []
- entries = list(registry.items())
- if len(entries) != len(required):
- errors.append(f"route registry entry count mismatch: expected {len(required)}, found {len(entries)}")
- bound_ids: list[str] = []
- for identifier, entry in entries:
- bead_id = entry.get("bead_id")
- if not isinstance(bead_id, str) or not bead_id:
- errors.append(f"route registry entry {identifier!r} must bind one non-empty manifest Bead id")
- else:
- bound_ids.append(bead_id)
- if bead_id not in required:
- errors.append(f"route registry entry {identifier!r} binds unlisted Bead {bead_id!r}")
- for field in ("class", "contract_type", "dispatch"):
- value = entry.get(field)
- if not isinstance(value, str) or not value or value == "*":
- errors.append(f"route registry entry {identifier!r} has invalid {field} authority")
- targets = entry.get("targets")
- if (
- not isinstance(targets, list)
- or not targets
- or any(not isinstance(target, str) or not target for target in targets)
- ):
- errors.append(f"route registry entry {identifier!r} must have a non-empty string target list")
- if len(bound_ids) != len(set(bound_ids)):
- errors.append("route registry contains duplicate Bead bindings")
- if set(bound_ids) != required:
- errors.append(f"route registry Bead population mismatch: expected {len(required)}, found {len(set(bound_ids))}")
- return errors
-
-
-def route_registry_digest() -> str:
- return registry_digest()
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description="Validate structured Beads acceptance contracts without guessing from prose."
- )
- parser.add_argument("issues", type=Path, nargs="?", default=Path(".beads/issues.jsonl"))
- parser.add_argument(
- "--manifest",
- type=Path,
- default=_DEFAULT_MANIFEST,
- help="newline-separated Bead ids that must carry a valid contract",
- )
- parser.add_argument("--json", action="store_true")
- args = parser.parse_args(argv)
- required_values = load_manifest(args.manifest)
- registry_errors = validate_route_registry(required_values)
- failures: dict[str, list[str]] = {}
- required = set(required_values)
- seen = set()
- for issue in load(args.issues):
- bid = issue.get("id")
- if not isinstance(bid, str) or bid not in required:
- continue
- seen.add(bid)
- errors = validate(issue)
- if errors:
- failures[bid] = errors
- for missing in sorted(required - seen):
- failures[missing] = ["manifest id missing from issues or contract"]
- regeneration_required = [{"id": bead_id, "reasons": failures[bead_id]} for bead_id in sorted(failures)]
- report = {
- "ok": not failures and not registry_errors,
- "dispatch_blocked": bool(failures or registry_errors),
- "manifest": {
- "expected_count": _EXPECTED_MANIFEST_COUNT,
- "digest": _EXPECTED_MANIFEST_DIGEST,
- },
- "validated": len(seen),
- "route_registry_errors": registry_errors,
- "failures": failures,
- "regeneration_required": regeneration_required,
- }
- if args.json:
- print(json_dumps(report, indent=2, sort_keys=True))
- else:
- for error in registry_errors:
- print(f"route_registry: {error}")
- for bid, errors in sorted(failures.items()):
- for error in errors:
- print(f"{bid}: {error}")
- print(f"validated={len(seen)} failures={len(failures)} regeneration_required={len(regeneration_required)}")
- return 1 if failures or registry_errors else 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/beads_acceptance_reconciliation.py b/devtools/beads_acceptance_reconciliation.py
deleted file mode 100644
index d18f42a790..0000000000
--- a/devtools/beads_acceptance_reconciliation.py
+++ /dev/null
@@ -1,533 +0,0 @@
-"""Reconcile guarded acceptance contracts against a read-only Beads export.
-
-This module deliberately operates on JSONL files. It never invokes ``bd`` and
-never selects an authority for a changed record. The generated import wave is
-made from the live record, with only the two contract fields replaced, so
-``bd import --allow-stale`` cannot overwrite unrelated live work.
-"""
-
-from __future__ import annotations
-
-import argparse
-import copy
-import datetime as dt
-import hashlib
-import re
-import sys
-from collections.abc import Iterable, Mapping
-from decimal import Decimal
-from pathlib import Path
-from typing import Any
-
-from devtools import beads_acceptance_contracts as _contracts
-from polylogue.core.json import JSONDecodeError
-from polylogue.core.json import dumps as json_dumps
-from polylogue.core.json import loads as json_loads
-
-source_digest = _contracts.source_digest
-validate = _contracts.validate
-
-
-def render(contract: dict[str, Any]) -> str:
- """Expose the merged validator renderer for synthetic reconciliation fixtures."""
- return _contracts.render(contract)
-
-
-_CONTRACT_KEY = "acceptance_contract_v1"
-_CONTRACT_FIELDS = frozenset({"acceptance_criteria", "metadata"})
-_REPORT_CATEGORIES = (
- "master_only",
- "live_only",
- "master_newer",
- "live_newer",
- "same_timestamp_different",
- "contract_refused",
-)
-_BEADS_TIMESTAMP = re.compile(
- r"^(?P\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})"
- r"(?:\.(?P\d+))?(?PZ|[+-]\d{2}:\d{2})$"
-)
-_REPORT_VERSION = 2
-
-
-class ReconciliationError(ValueError):
- """Raised when a file-level reconciliation input is unsafe to consume."""
-
-
-def _metadata_object(value: object) -> dict[str, Any] | None:
- if value is None:
- return {}
- if isinstance(value, dict):
- return copy.deepcopy(value)
- if not isinstance(value, str):
- return None
- try:
- decoded = json_loads(value)
- except JSONDecodeError:
- return None
- return copy.deepcopy(decoded) if isinstance(decoded, dict) else None
-
-
-def _contract(issue: Mapping[str, Any]) -> dict[str, Any] | None:
- metadata = _metadata_object(issue.get("metadata"))
- if metadata is None:
- return None
- value = metadata.get(_CONTRACT_KEY)
- return copy.deepcopy(value) if isinstance(value, dict) else None
-
-
-def _source_digest_or_refuse(issue: Mapping[str, Any]) -> str:
- try:
- return source_digest(dict(issue))
- except _contracts.DependencyProjectionError as exc:
- raise ReconciliationError(f"{issue.get('id')}: {exc}") from exc
-
-
-def load_jsonl(path: Path) -> dict[str, dict[str, Any]]:
- """Load a Beads JSONL export, rejecting malformed or duplicate IDs."""
- rows: dict[str, dict[str, Any]] = {}
- for line_number, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
- if not line.strip():
- continue
- try:
- value = json_loads(line)
- except JSONDecodeError as exc:
- raise ReconciliationError(f"{path}:{line_number}: invalid JSON: {exc}") from exc
- if not isinstance(value, dict):
- raise ReconciliationError(f"{path}:{line_number}: expected a JSON object")
- bead_id = value.get("id")
- if not isinstance(bead_id, str) or not bead_id:
- raise ReconciliationError(f"{path}:{line_number}: missing string Bead id")
- if bead_id in rows:
- raise ReconciliationError(f"{path}:{line_number}: duplicate Bead id {bead_id}")
- rows[bead_id] = value
- return rows
-
-
-def _canonical_rows(rows: Mapping[str, Mapping[str, Any]], ids: Iterable[str]) -> str:
- return "\n".join(json_dumps(rows[bead_id], sort_keys=True) for bead_id in sorted(ids)) + "\n"
-
-
-def equality_digest(rows: Mapping[str, Mapping[str, Any]], ids: Iterable[str] | None = None) -> str:
- """Hash complete canonical rows, ordered by Bead ID."""
- selected = rows.keys() if ids is None else ids
- return hashlib.sha256(_canonical_rows(rows, selected).encode("utf-8")).hexdigest()
-
-
-def non_contract_equality_digest(rows: Mapping[str, Mapping[str, Any]], ids: Iterable[str]) -> str:
- """Hash rows after removing only the two contract fields."""
- scrubbed: dict[str, dict[str, Any]] = {}
- for bead_id in ids:
- row = dict(copy.deepcopy(rows[bead_id]))
- row.pop("acceptance_criteria", None)
- raw_metadata = row.get("metadata")
- metadata = _metadata_object(raw_metadata)
- if metadata is not None:
- metadata.pop(_CONTRACT_KEY, None)
- if not metadata:
- # The contract is the only allowed metadata mutation. Remove
- # the now-empty container from both sides of the projection;
- # all non-contract metadata keys remain visible and checked.
- row.pop("metadata", None)
- elif isinstance(raw_metadata, str):
- row["metadata"] = json_dumps(metadata)
- else:
- row["metadata"] = metadata
- scrubbed[bead_id] = row
- return equality_digest(scrubbed)
-
-
-def _parse_beads_timestamp(value: object) -> tuple[dt.datetime, Decimal]:
- if not isinstance(value, str):
- raise ValueError("updated_at must be a string on both repository and live records")
- match = _BEADS_TIMESTAMP.fullmatch(value)
- if match is None:
- raise ValueError("updated_at must be a valid canonical Beads timestamp")
- try:
- parsed = dt.datetime.fromisoformat(f"{match['second']}{match['timezone'].replace('Z', '+00:00')}")
- except ValueError as exc:
- raise ValueError("updated_at must be a valid canonical Beads timestamp") from exc
- if parsed.tzinfo is None:
- raise ValueError("updated_at must include a timezone")
- fraction = Decimal(f"0.{match['fraction'] or '0'}")
- return parsed.astimezone(dt.UTC).replace(microsecond=0), fraction
-
-
-def _classify_timestamp(master: Mapping[str, Any], live: Mapping[str, Any]) -> str:
- master_timestamp = _parse_beads_timestamp(master.get("updated_at"))
- live_timestamp = _parse_beads_timestamp(live.get("updated_at"))
- if master_timestamp == live_timestamp:
- return (
- "same_timestamp_same"
- if source_digest(dict(master)) == source_digest(dict(live))
- else "same_timestamp_different"
- )
- if master_timestamp > live_timestamp:
- return "master_newer"
- return "live_newer"
-
-
-def _guarded_row(
- *,
- master: Mapping[str, Any],
- live: Mapping[str, Any],
- contract: Mapping[str, Any],
-) -> dict[str, Any]:
- metadata = _metadata_object(live.get("metadata"))
- if metadata is None:
- raise ReconciliationError(f"{live.get('id')}: live metadata is not a JSON object")
- row = copy.deepcopy(dict(live))
- metadata[_CONTRACT_KEY] = copy.deepcopy(dict(contract))
- row["metadata"] = json_dumps(metadata) if isinstance(live.get("metadata"), str) else metadata
- row["acceptance_criteria"] = master.get("acceptance_criteria")
- changed = {key for key in set(row) | set(live) if key not in _CONTRACT_FIELDS and row.get(key) != live.get(key)}
- if changed:
- raise ReconciliationError(f"{live.get('id')}: guarded wave changed non-contract fields {sorted(changed)}")
- return row
-
-
-def _write_jsonl(path: Path, rows: Iterable[Mapping[str, Any]]) -> None:
- path.write_text(
- "".join(json_dumps(row, sort_keys=True) + "\n" for row in rows),
- encoding="utf-8",
- )
-
-
-def report_digest(report: Mapping[str, Any]) -> str:
- """Hash the exact reconciliation report payload."""
- return hashlib.sha256(json_dumps(dict(report), sort_keys=True).encode("utf-8")).hexdigest()
-
-
-def _load_report(path: Path) -> dict[str, Any]:
- try:
- value = json_loads(path.read_text(encoding="utf-8"))
- except (OSError, JSONDecodeError) as exc:
- raise ReconciliationError(f"{path}: invalid reconciliation report: {exc}") from exc
- if not isinstance(value, dict):
- raise ReconciliationError(f"{path}: reconciliation report must be an object")
- return value
-
-
-def _require_complete_report(actual: Mapping[str, Any], expected: Mapping[str, Any]) -> None:
- """Require every report field to equal a fresh recomputation from bound inputs."""
- if set(actual) != set(expected):
- raise ReconciliationError("reconciliation report fields do not match the canonical report shape")
- for field in sorted(expected):
- if actual[field] != expected[field]:
- raise ReconciliationError(f"reconciliation report field {field!r} does not match canonical recomputation")
-
-
-def _validate_report_and_wave(
- *,
- repository: Path,
- before: Path,
- wave: Path,
- report_path: Path,
-) -> tuple[dict[str, dict[str, Any]], dict[str, dict[str, Any]], dict[str, dict[str, Any]], dict[str, Any]]:
- master = load_jsonl(repository)
- before_rows = load_jsonl(before)
- wave_rows = load_jsonl(wave)
- report = _load_report(report_path)
- required_ids = _contracts.load_manifest(_contracts._DEFAULT_MANIFEST)
- registry_errors = _contracts.validate_route_registry(required_ids)
- if registry_errors:
- raise ReconciliationError("canonical route registry validation failed: " + "; ".join(registry_errors))
- if report.get("report_version") != _REPORT_VERSION:
- raise ReconciliationError("reconciliation report version is stale or unsupported")
- if report.get("manifest_digest") != _contracts._EXPECTED_MANIFEST_DIGEST:
- raise ReconciliationError("reconciliation report manifest digest does not match this exact head")
- if report.get("route_registry_digest") != _contracts.route_registry_digest():
- raise ReconciliationError("reconciliation report route registry digest is stale")
- if report.get("contract_denominator") != len(required_ids):
- raise ReconciliationError("reconciliation report contract denominator is stale")
- if report.get("repository_population_digest") != equality_digest(master):
- raise ReconciliationError("canonical repository population digest does not match the reconciliation report")
- if report.get("live_population_digest") != equality_digest(before_rows):
- raise ReconciliationError("before population digest does not match the reconciliation report")
- target_ids = report.get("targeted_ids")
- if (
- not isinstance(target_ids, list)
- or target_ids != sorted(set(target_ids))
- or any(not isinstance(i, str) for i in target_ids)
- ):
- raise ReconciliationError("reconciliation report targeted_ids must be sorted and unique")
- wave_ids = list(wave_rows)
- if wave_ids != target_ids:
- raise ReconciliationError("targeted wave order or population does not match the reconciliation report")
- if set(target_ids) - set(before_rows) or set(target_ids) - set(master):
- raise ReconciliationError("targeted wave contains records absent from the bound populations")
- expected_wave_digest = equality_digest(wave_rows, target_ids)
- if report.get("targeted_wave_equality_digest") != expected_wave_digest:
- raise ReconciliationError("targeted wave digest does not match the reconciliation report")
- row_digests = report.get("targeted_wave_row_digests")
- if not isinstance(row_digests, dict) or set(row_digests) != set(target_ids):
- raise ReconciliationError("reconciliation report does not carry every targeted wave row digest")
- for bead_id in target_ids:
- if row_digests.get(bead_id) != equality_digest({bead_id: wave_rows[bead_id]}, [bead_id]):
- raise ReconciliationError(f"targeted wave row digest mismatch for {bead_id}")
- canonical = master[bead_id]
- contract = _contract(canonical)
- if contract is None or validate(canonical):
- raise ReconciliationError(f"canonical contract revalidation failed for {bead_id}")
- if _source_digest_or_refuse(before_rows[bead_id]) != contract.get("source_digest"):
- raise ReconciliationError(f"stale source digest refuses targeted row {bead_id}")
- expected = _guarded_row(master=canonical, live=before_rows[bead_id], contract=contract)
- if wave_rows[bead_id] != expected:
- raise ReconciliationError(f"targeted wave row is not the canonical guarded row for {bead_id}")
- expected_report, expected_wave = reconcile(repository, before)
- expected_wave_rows = {row["id"]: row for row in expected_wave}
- if wave_rows != expected_wave_rows:
- raise ReconciliationError("targeted wave does not match the canonical reconciliation recomputation")
- _require_complete_report(report, expected_report)
- return master, before_rows, wave_rows, report
-
-
-def reconcile(
- repository: Path,
- live_export: Path,
- *,
- manifest: Path | None = None,
-) -> tuple[dict[str, Any], list[dict[str, Any]]]:
- """Return a report and a minimal guarded import wave.
-
- A contract is eligible only when the live source digest equals the digest
- carried by the canonical contract. Timestamp ordering is reported but is
- never used as an authority choice. A malformed live metadata document is
- an explicit contract refusal.
- """
- try:
- required_ids = _contracts.load_manifest(manifest or _contracts._DEFAULT_MANIFEST)
- except SystemExit as exc:
- raise ReconciliationError(str(exc)) from exc
- master = load_jsonl(repository)
- live = load_jsonl(live_export)
- missing_manifest_ids = sorted(set(required_ids) - set(master))
- if missing_manifest_ids:
- raise ReconciliationError(
- "canonical acceptance-contract manifest is incomplete: "
- f"missing {len(missing_manifest_ids)} IDs {missing_manifest_ids}"
- )
- master_contracts: dict[str, dict[str, Any]] = {}
- invalid_contracts: dict[str, list[str]] = {}
- for bead_id in required_ids:
- contract = _contract(master[bead_id])
- if contract is None:
- invalid_contracts[bead_id] = ["missing metadata.acceptance_contract_v1"]
- continue
- master_contracts[bead_id] = contract
- errors = validate(master[bead_id])
- if errors:
- invalid_contracts[bead_id] = errors
- if invalid_contracts:
- details = "; ".join(f"{bead_id}: {', '.join(errors)}" for bead_id, errors in sorted(invalid_contracts.items()))
- raise ReconciliationError(f"canonical contract validation failed: {details}")
-
- master_ids = set(master)
- live_ids = set(live)
- report: dict[str, Any] = {
- "report_version": _REPORT_VERSION,
- "repository": str(repository),
- "live_export": str(live_export),
- "counts": dict.fromkeys(_REPORT_CATEGORIES, 0),
- "ids": {category: [] for category in _REPORT_CATEGORIES},
- "contract_denominator": len(required_ids),
- "contract_present_denominator": len(set(required_ids) & live_ids),
- "contract_guarded_count": 0,
- "contract_refused_denominator": 0,
- "contract_refused_reasons": {},
- "contract_deferred_denominator": 0,
- "contract_deferred_reasons": {},
- "already_guarded_ids": [],
- "targeted_ids": [],
- }
- for report_category, ids in (
- ("master_only", master_ids - live_ids),
- ("live_only", live_ids - master_ids),
- ):
- report["ids"][report_category] = sorted(ids)
- report["counts"][report_category] = len(ids)
-
- wave: list[dict[str, Any]] = []
- refused_reasons: dict[str, list[str]] = {}
- for bead_id in sorted(master_ids & live_ids):
- master_row = master[bead_id]
- live_row = live[bead_id]
- timestamp_error: str | None = None
- try:
- timestamp_category = _classify_timestamp(master_row, live_row)
- except ValueError as exc:
- timestamp_category = None
- timestamp_error = str(exc)
- if timestamp_category in {"master_newer", "live_newer", "same_timestamp_different"}:
- report["ids"][timestamp_category].append(bead_id)
- report["counts"][timestamp_category] += 1
-
- contract = master_contracts.get(bead_id)
- if contract is None:
- continue
- report["contract_refused_denominator"] += 1
- reasons: list[str] = []
- expected_digest = contract["source_digest"]
- try:
- actual_digest = source_digest(live_row)
- except _contracts.DependencyProjectionError as exc:
- reasons.append(str(exc))
- else:
- if actual_digest != expected_digest:
- reasons.append(f"source digest mismatch: expected contract {expected_digest}, live {actual_digest}")
- if _metadata_object(live_row.get("metadata")) is None:
- reasons.append("live metadata is not a JSON object")
- if timestamp_error is not None and timestamp_error not in reasons:
- reasons.append(timestamp_error)
- if reasons:
- report["ids"]["contract_refused"].append(bead_id)
- report["counts"]["contract_refused"] += 1
- refused_reasons[bead_id] = reasons
- continue
- if timestamp_category == "live_newer":
- report["contract_deferred_denominator"] += 1
- report["contract_deferred_reasons"][bead_id] = (
- "live-newer record is excluded from the targeted wave; coordinator adjudication is required"
- )
- continue
- candidate = _guarded_row(master=master_row, live=live_row, contract=contract)
- current_contract = _contract(live_row)
- if (
- live_row.get("acceptance_criteria") == master_row.get("acceptance_criteria")
- and current_contract == contract
- ):
- report["already_guarded_ids"].append(bead_id)
- continue
- wave.append(candidate)
- report["targeted_ids"].append(bead_id)
-
- report["ids"]["contract_refused"] = sorted(report["ids"]["contract_refused"])
- report["contract_refused_reasons"] = {bead_id: refused_reasons[bead_id] for bead_id in sorted(refused_reasons)}
- report["contract_deferred_reasons"] = {
- bead_id: report["contract_deferred_reasons"][bead_id] for bead_id in sorted(report["contract_deferred_reasons"])
- }
- report["contract_guarded_count"] = len(report["targeted_ids"]) + len(report["already_guarded_ids"])
- report["manifest_digest"] = _contracts._EXPECTED_MANIFEST_DIGEST
- report["route_registry_digest"] = _contracts.route_registry_digest()
- report["repository_population_digest"] = equality_digest(master)
- report["live_equality_digest"] = equality_digest(live)
- report["live_population_digest"] = report["live_equality_digest"]
- report["targeted_non_contract_equality_digest"] = non_contract_equality_digest(live, report["targeted_ids"])
- report["targeted_wave_equality_digest"] = equality_digest({row["id"]: row for row in wave}, report["targeted_ids"])
- report["targeted_wave_non_contract_equality_digest"] = non_contract_equality_digest(
- {row["id"]: row for row in wave}, report["targeted_ids"]
- )
- report["targeted_wave_row_digests"] = {row["id"]: equality_digest({row["id"]: row}, [row["id"]]) for row in wave}
- return report, wave
-
-
-def verify_post_import(*, repository: Path, before: Path, after: Path, wave: Path, report: Path) -> dict[str, Any]:
- """Verify that a targeted import changed only the guarded contract fields."""
- _, before_rows, wave_rows, reconciliation = _validate_report_and_wave(
- repository=repository,
- before=before,
- wave=wave,
- report_path=report,
- )
- after_rows = load_jsonl(after)
- target_ids = set(wave_rows)
- if not target_ids <= set(before_rows):
- raise ReconciliationError("targeted wave contains records absent from the before export")
- if not target_ids <= set(after_rows):
- raise ReconciliationError("targeted wave contains records absent from the after export")
- unchanged_ids = set(before_rows) - target_ids
- added_ids = sorted(set(after_rows) - set(before_rows))
- removed_ids = sorted(set(before_rows) - set(after_rows))
- if added_ids or removed_ids:
- raise ReconciliationError(
- f"post-import export changed the record universe: added={added_ids}, removed={removed_ids}"
- )
- changed_outside_wave = sorted(
- bead_id for bead_id in unchanged_ids if before_rows[bead_id] != after_rows.get(bead_id)
- )
- if changed_outside_wave:
- raise ReconciliationError(f"post-import export changed records outside targeted wave: {changed_outside_wave}")
- before_non_contract = non_contract_equality_digest(before_rows, target_ids)
- after_non_contract = non_contract_equality_digest(after_rows, target_ids)
- expected_wave = equality_digest(wave_rows, reconciliation["targeted_ids"])
- actual_target = equality_digest(after_rows, target_ids)
- if before_non_contract != after_non_contract:
- raise ReconciliationError("post-import targeted records changed non-contract fields")
- if expected_wave != actual_target:
- raise ReconciliationError("post-import targeted records differ from the guarded wave")
- before_population_digest = equality_digest(before_rows)
- after_population_digest = equality_digest(after_rows)
- if reconciliation.get("live_population_digest") != before_population_digest:
- raise ReconciliationError("full before population digest changed after reconciliation")
- return {
- "ok": True,
- "report_digest": report_digest(reconciliation),
- "reconciliation_wave_digest": reconciliation["targeted_wave_equality_digest"],
- "before_population_digest": before_population_digest,
- "after_population_digest": after_population_digest,
- "targeted_ids": sorted(target_ids),
- "unchanged_outside_wave": len(unchanged_ids),
- "targeted_non_contract_equality_digest": after_non_contract,
- "targeted_wave_equality_digest": actual_target,
- }
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description="Reconcile repository acceptance contracts with a read-only live Beads export."
- )
- parser.add_argument("--repository", type=Path, help="canonical repository JSONL")
- parser.add_argument("--live", type=Path, help="read-only live Beads export")
- parser.add_argument(
- "--manifest", type=Path, default=_contracts._DEFAULT_MANIFEST, help="ratcheted contract ID manifest"
- )
- parser.add_argument("--wave", type=Path, help="write the guarded targeted import JSONL")
- parser.add_argument("--report", type=Path, help="write the reconciliation report JSON")
- parser.add_argument("--verify-before", type=Path, help="before export for post-import verification")
- parser.add_argument("--verify-after", type=Path, help="after export for post-import verification")
- parser.add_argument("--verify-wave", type=Path, help="guarded wave for post-import verification")
- parser.add_argument("--verify-repository", type=Path, help="canonical repository bound to the report")
- parser.add_argument("--verify-report", type=Path, help="exact reconciliation report bound to the wave")
- parser.add_argument("--json", action="store_true", help="emit the report or verification result as JSON")
- args = parser.parse_args(argv)
- try:
- if any(
- (
- args.verify_before,
- args.verify_after,
- args.verify_wave,
- args.verify_repository,
- args.verify_report,
- )
- ):
- if not all(
- (args.verify_before, args.verify_after, args.verify_wave, args.verify_repository, args.verify_report)
- ):
- raise ReconciliationError(
- "post-import verification requires --verify-repository, --verify-report, --verify-before, "
- "--verify-after, and --verify-wave"
- )
- result = verify_post_import(
- repository=args.verify_repository,
- before=args.verify_before,
- after=args.verify_after,
- wave=args.verify_wave,
- report=args.verify_report,
- )
- else:
- if not args.repository or not args.live:
- raise ReconciliationError("reconciliation requires --repository and --live")
- result, wave = reconcile(args.repository, args.live, manifest=args.manifest)
- if args.wave:
- _write_jsonl(args.wave, wave)
- if args.report:
- args.report.write_text(json_dumps(result, indent=2, sort_keys=True) + "\n", encoding="utf-8")
- except ReconciliationError as exc:
- print(str(exc), file=sys.stderr)
- return 1
- print(json_dumps(result, indent=2, sort_keys=True))
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/beads_state_report.py b/devtools/beads_state_report.py
deleted file mode 100644
index f2d5704268..0000000000
--- a/devtools/beads_state_report.py
+++ /dev/null
@@ -1,2542 +0,0 @@
-"""beads-state-report: a self-contained HTML state-of-the-backlog report.
-
-Reads ``.beads/issues.jsonl`` and emits one standalone HTML file covering the
-whole bead population -- open AND closed -- across eight views: pulse (now vs
-7/14 days ago, reconstructed from timestamps), shape (status x priority x
-type), structure (epic/program trees with per-epic trend sparklines), topology
-(the ``blocks`` dependency graph: ready / blocked / top blockers / cycles /
-densest cluster / the parallel frontier), time (creation, closure, burnup, age
-x priority heatmap), health (a review queue of graph defects), themes (where
-open work concentrates by subsystem), and the dated review passes (the
-hand-verified VERIFICATION(...) verdict subset and the 2026-07-31 P0
-reconciliation markers, rendered only when their markers exist in the data).
-
-Design rule: **interpretation is computed, never fossilized.** Every claim in
-the findings list is emitted by a conditional generator in ``compute_insights``
-that checks the condition against the live data and renders the variant that
-is actually true (or nothing). There is no hand-authored paragraph that can
-silently go false on regeneration. The only authored content is timeless
-framing (what a section shows, how to read the notation) and two named
-constants from dated review passes, kept as constants precisely so their
-dated provenance is explicit.
-
-Temporal reconstruction: every bead and every dependency edge in the export
-carries ``created_at`` (and beads a ``closed_at``), so the open/ready/blocked
-state of the graph at any past instant is recomputable. Caveats are inherent
-and stated in the report: deleted beads/edges are invisible, and a reopened
-bead's earlier closure is lost (``closed_at`` reflects only the latest close).
-That makes trend figures *derived*, not measured -- they are tagged as such.
-
-Usage: devtools workspace beads-state-report [--out PATH] [--fresh] [--json]
-``--fresh`` runs ``bd export -o .beads/issues.jsonl`` first, because ``bd``
-mutations do not immediately re-export and a stale file yields stale counts.
-"""
-
-from __future__ import annotations
-
-import argparse
-import datetime as dt
-import html
-import json
-import re
-import subprocess
-import sys
-from collections import Counter, defaultdict
-from collections.abc import Iterable, Sequence
-from dataclasses import dataclass, field
-from pathlib import Path
-from typing import Any
-
-from devtools import repo_root as _get_root
-
-IssueDict = dict[str, Any]
-# (src issue, depends-on issue, relation type, edge created_at ISO string)
-Edge = tuple[str, str, str, str]
-
-# --------------------------------------------------------------------------
-# Constants from dated review passes. These are the ONLY numbers in this
-# module that were not computed from the input file; each is an
-# operator-supplied figure from a specific, dated pass and is rendered with
-# that provenance attached.
-# --------------------------------------------------------------------------
-# 2026-07-31 landing-check lane: the operator's own count of the hand-verified
-# subset (strict regex extraction below finds fewer; the gap is reported).
-OPERATOR_VERIFIED_COUNT = 190
-# 2026-07-31 P0 reconciliation pass: the pass's own summary table covered this
-# many beads (marker extraction below finds fewer; the gap is reported).
-RECONCILIATION_EXPECTED = 24
-
-VERDICT_STRICT = re.compile(r"VERIFICATION\s*\(([^)]*)\)\s*:\s*(STALE|PARTIAL|LIVE)", re.IGNORECASE)
-VERDICT_LOOSE = re.compile(r"\b(STALE|PARTIAL|LIVE)\b")
-
-# The 2026-07-31 P0 reconciliation pass wrote one
-# `RECONCILIATION 2026-07-31[...]: ` marker per bead it touched.
-# Scoping the token search to a window *after* that literal anchor matters:
-# bare tokens like MISFRAMED are ordinary English words that also appear,
-# unrelated, in older notes on other beads.
-RECONCILIATION_ANCHOR = re.compile(r"RECONCILIATION 2026-07-31")
-RECONCILIATION_TOKENS: tuple[str, ...] = (
- "FIXED-AND-EFFECTIVE",
- "FIXED-PENDING-REBUILD",
- "FIXED-PENDING-DEPLOY",
- "MISFRAMED",
- "GENUINELY OPEN",
-)
-RECONCILIATION_TOKEN_RE = re.compile("|".join(re.escape(t) for t in RECONCILIATION_TOKENS))
-RECONCILIATION_WINDOW = 1200
-
-# Thresholds for computed insights. Named so the conditions are auditable.
-STALE_CLAIM_DAYS = 7 # in_progress untouched this long = zombie claim
-AGED_URGENT_DAYS = 14 # open P0/P1 older than this = urgency not being consumed
-VELOCITY_WINDOW_DAYS = 14 # trailing window vs the window before it
-
-SUBSYSTEMS: dict[str, tuple[str, ...]] = {
- # canonical subsystem -> area:* label suffixes folded into it
- "storage": ("storage", "substrate", "blob", "blobs", "schema", "schemas", "archive", "durability"),
- "sources": (
- "sources",
- "source",
- "ingest",
- "parsers",
- "parsing",
- "capture",
- "lineage",
- "attachments",
- "protocol",
- "identity",
- ),
- "daemon": ("daemon", "ops", "pipeline", "events", "perf", "performance", "reliability"),
- "insights": ("insights", "analytics", "cost", "usage", "temporal", "evidence", "analysis", "embeddings"),
- "cli": ("cli", "query", "query-dsl", "search", "surface", "api", "config"),
- "mcp": ("mcp", "context", "coordination", "orchestration", "agents", "delegation", "delegations"),
- "web/extension": ("web", "browser", "browser-capture", "extension", "rendering", "ux"),
- "tests": ("test", "testing", "tests", "test-harness", "verification", "coverage", "quality", "eval"),
- "devtools": (
- "devtools",
- "devloop",
- "ci",
- "release",
- "git",
- "beads",
- "beads-hygiene",
- "planning",
- "maintenance",
- "cleanup",
- "status",
- ),
- "docs/legibility": ("docs", "legibility", "demos", "demo", "architecture", "adoption", "audit"),
-}
-
-KEYWORDS: dict[str, tuple[str, ...]] = {
- "storage": ("storage", "sqlite", "index.db", "source.db", "user.db", "schema", "blob", "migration", "table"),
- "sources": ("parser", "parse", "ingest", "provider", "origin", "claude code", "codex", "chatgpt", "session"),
- "daemon": ("daemon", "polylogued", "converg", "watcher", "cursor", "acquire"),
- "insights": ("insight", "cost", "usage", "token", "profile", "timeline", "analytic"),
- "cli": ("cli", "command", "query", "click", "filter", "find ", "read --"),
- "mcp": ("mcp", "agent", "context", "assertion", "recall", "coordination"),
- "web/extension": ("web", "browser", "extension", "workbench", "http", "ui"),
- "tests": ("test", "pytest", "fixture", "coverage", "hypothesis", "regression"),
- "devtools": ("devtools", "render", "lint", "bead", "ci ", "workflow", "hook"),
- "docs/legibility": ("doc", "readme", "demo", "narrative", "legib", "explain"),
-}
-
-TYPE_GLYPH: dict[str, tuple[str, str]] = {
- "task": ("▪", "task"),
- "bug": ("✕", "bug"),
- "feature": ("✦", "feature"),
- "epic": ("▣", "epic"),
- "chore": ("⚙", "chore"),
- "decision": ("⚖", "decision"),
- "spike": ("⚡", "spike"),
-}
-STATUS_GLYPH: dict[str, tuple[str, str]] = {
- "open": ("○", "open"),
- "in_progress": ("◐", "in progress"),
- "deferred": ("◌", "deferred"),
- "closed": ("●", "closed"),
-}
-STATUS_ORDER: tuple[str, ...] = ("open", "in_progress", "deferred", "closed")
-
-# Mechanical graph-health checks: (badge class, label, Facts attribute, meaning).
-HEALTH_CHECKS: tuple[tuple[str, str, str, str], ...] = (
- ("bad", "dangling dependency references", "dangling", "edge points at an id that does not exist"),
- ("warn", "dotted id disagrees with parent edge", "id_mismatch", "id prefix names a different parent"),
- ("warn", "dotted id with no parent edge", "id_orphan", "looks nested, is structurally a root"),
- (
- "warn",
- "open parent, all children closed",
- "open_parent_all_closed",
- "review queue — adjudicate against the parent's own AC",
- ),
- (
- "warn",
- "closed parent with open children",
- "closed_parent_open_kids",
- "parent retired while decomposed work continues",
- ),
- (
- "warn",
- f"in-progress untouched >{STALE_CLAIM_DAYS} days",
- "stale_claims",
- "a claim nobody is working — release or finish it",
- ),
- ("warn", "duplicate titles", "dup_titles", "same work filed twice, independently"),
- ("info", "closed without a close reason", "closed_no_reason", "no durable record of why it ended"),
- ("info", "open without acceptance criteria", "no_ac_open", "no definition of done"),
-)
-
-
-# --------------------------------------------------------------------------
-# loading + primitives
-# --------------------------------------------------------------------------
-def load(path: Path) -> tuple[dict[str, IssueDict], list[Edge]]:
- """Parse the bd JSONL export into an id->issue map and a dependency edge list."""
- issues: dict[str, IssueDict] = {}
- edges: list[Edge] = []
- for line in path.read_text(encoding="utf-8").splitlines():
- line = line.strip()
- if not line:
- continue
- rec = json.loads(line)
- if rec.get("_type") == "issue":
- issues[rec["id"]] = rec
- for dep in rec.get("dependencies") or []:
- edges.append(
- (
- str(dep["issue_id"]),
- str(dep["depends_on_id"]),
- str(dep.get("type", "blocks")),
- str(dep.get("created_at") or ""),
- )
- )
- elif rec.get("_type") == "dependency":
- edges.append(
- (
- str(rec["issue_id"]),
- str(rec["depends_on_id"]),
- str(rec.get("type", "blocks")),
- str(rec.get("created_at") or ""),
- )
- )
- return issues, edges
-
-
-def _blob(rec: IssueDict) -> str:
- parts = [str(rec.get("notes") or "")]
- parts.extend(str(c.get("text") or "") for c in (rec.get("comments") or []))
- return "\n".join(parts)
-
-
-def _parse_ts(value: str) -> dt.datetime:
- parsed = dt.datetime.fromisoformat(value.replace("Z", "+00:00"))
- if parsed.tzinfo is None:
- parsed = parsed.replace(tzinfo=dt.UTC)
- return parsed
-
-
-def _median(values: Sequence[float]) -> float:
- if not values:
- return 0.0
- ordered = sorted(values)
- mid = len(ordered) // 2
- if len(ordered) % 2:
- return ordered[mid]
- return (ordered[mid - 1] + ordered[mid]) / 2
-
-
-def _git_show(root: Path, ref: str, rel_path: str) -> str | None:
- """Return a file's content at a git ref, or ``None`` if unavailable."""
- try:
- proc = subprocess.run(
- ["git", "show", f"{ref}:{rel_path}"],
- cwd=root,
- capture_output=True,
- text=True,
- timeout=15,
- )
- except (OSError, subprocess.SubprocessError):
- return None
- return proc.stdout if proc.returncode == 0 else None
-
-
-_LIFECYCLE_DECL_RE = re.compile(r"version=(\d+),.*?classes=\(([^)]*)\)", re.DOTALL)
-
-
-def schema_gap_facts(root: Path) -> dict[str, Any]:
- """The derived-index schema gap: origin/master's declared
- ``INDEX_SCHEMA_VERSION`` vs the live archive's actual ``PRAGMA
- user_version``, and which intervening versions are ``SEMANTIC_REPARSE``
- (block a SQL fast-forward -- a merged fix at one of those versions is
- real and inert until ``polylogue ops reset --index && polylogued run``).
-
- Two independent read paths, both best-effort and non-fatal on failure so
- a sandbox without network/git-remote access or a live archive still
- renders a report (just without this fact):
-
- - ``git show origin/master:...`` for the declared version and delta
- classes, so this is correct even on a branch behind master.
- - the operator's configured archive root
- (``~/.config/polylogue/polylogue.toml``), read-only ``PRAGMA``, for the
- live version. Deliberately does not use ``POLYLOGUE_ARCHIVE_ROOT`` --
- that env var is routinely overridden for sandboxed/test runs, and this
- fact is specifically about the real production archive.
- """
- result: dict[str, Any] = {
- "available": False,
- "declared": None,
- "live_version": None,
- "live_path": None,
- "blockers": [],
- "blocker_notes": {},
- }
-
- index_src = _git_show(root, "origin/master", "polylogue/storage/sqlite/archive_tiers/index.py")
- if index_src:
- m = re.search(r"^INDEX_SCHEMA_VERSION\s*=\s*(\d+)", index_src, re.MULTILINE)
- if m:
- result["declared"] = int(m.group(1))
-
- lifecycle_src = _git_show(root, "origin/master", "polylogue/storage/sqlite/lifecycle.py") or ""
- versions: dict[int, tuple[str, ...]] = {}
- for vm in _LIFECYCLE_DECL_RE.finditer(lifecycle_src):
- v = int(vm.group(1))
- classes = tuple(c.strip().removeprefix("DerivedDeltaClass.") for c in vm.group(2).split(",") if c.strip())
- versions[v] = classes
-
- live_path: Path | None = None
- try:
- import tomllib
-
- cfg_path = Path.home() / ".config/polylogue/polylogue.toml"
- if cfg_path.exists():
- cfg = tomllib.loads(cfg_path.read_text(encoding="utf-8"))
- root_str = cfg.get("archive", {}).get("root")
- if root_str:
- live_path = Path(root_str) / "index.db"
- except Exception:
- live_path = None
-
- if live_path and live_path.exists():
- result["live_path"] = str(live_path)
- try:
- proc = subprocess.run(
- ["sqlite3", "-readonly", str(live_path), "PRAGMA user_version;"],
- capture_output=True,
- text=True,
- timeout=15,
- check=True,
- )
- result["live_version"] = int(proc.stdout.strip())
- except Exception:
- pass
-
- if result["declared"] is not None and result["live_version"] is not None:
- result["available"] = True
- lo, hi = result["live_version"] + 1, result["declared"]
- result["blockers"] = [v for v in range(lo, hi + 1) if "SEMANTIC_REPARSE" in versions.get(v, ())]
- result["blocker_notes"] = {v: versions.get(v, ()) for v in range(lo, hi + 1)}
- return result
-
-
-# --------------------------------------------------------------------------
-# facts: every measured/derived quantity the report renders
-# --------------------------------------------------------------------------
-class Facts:
- """Every measured quantity the report renders. Nothing here is authored."""
-
- def __init__(self, issues: dict[str, IssueDict], edges: list[Edge], now: dt.datetime) -> None:
- self.issues = issues
- self.edges = edges
- self.now = now
- self._cluster_adj: dict[str, set[str]] = defaultdict(set)
- rows = list(issues.values())
- self.rows = rows
- self.total = len(rows)
-
- self.status = Counter(str(r["status"]) for r in rows)
- self.priority = Counter(int(r["priority"]) for r in rows)
- self.itype = Counter(str(r["issue_type"]) for r in rows)
- self.matrix: dict[tuple[str, int], int] = Counter((str(r["status"]), int(r["priority"])) for r in rows)
- self.open_ids = [str(r["id"]) for r in rows if r["status"] != "closed"]
- self.open_total = len(self.open_ids)
- self.statuses_present = [s for s in STATUS_ORDER if self.status.get(s)] + sorted(
- set(self.status) - set(STATUS_ORDER)
- )
-
- # ---- dependency graph -------------------------------------------
- self.dep_types = Counter(t for _, _, t, _ in edges)
-
- # relates-to/related vocabulary state. A repair that re-types every
- # existing `related` edge does not constrain the field, so a fresh
- # `related` edge can land minutes later -- that is a distinct state
- # from "never repaired" and from "clean".
- _relates, _related = self.dep_types["relates-to"], self.dep_types["related"]
- _assoc_total = _relates + _related
- if _related == 0:
- self.vocab_state = "clean"
- elif _assoc_total and _related <= max(3, 0.02 * _assoc_total):
- self.vocab_state = "recurring"
- else:
- self.vocab_state = "split"
-
- self.blockers: dict[str, set[str]] = defaultdict(set)
- self.blocking: dict[str, set[str]] = defaultdict(set)
- self.children: dict[str, list[str]] = defaultdict(list)
- self.parent: dict[str, str] = {}
- # blocks edges with their creation timestamp, for temporal replay
- self.block_edges_ts: list[tuple[str, str, str]] = []
- for src, dst, kind, created in edges:
- if kind == "blocks":
- self.blockers[src].add(dst)
- self.blocking[dst].add(src)
- self.block_edges_ts.append((src, dst, created))
- elif kind == "parent-child":
- self.children[dst].append(src)
- self.parent[src] = dst
- self.dangling = sorted({(a, b, t) for a, b, t, _ in edges if b not in issues or a not in issues})
-
- def is_open(bid: str) -> bool:
- rec = issues.get(bid)
- return rec is not None and rec["status"] != "closed"
-
- self.is_open = is_open
- self.blocked = [i for i in self.open_ids if any(is_open(b) for b in self.blockers[i])]
- self.ready = [i for i in self.open_ids if not any(is_open(b) for b in self.blockers[i])]
- self.top_blockers = sorted(
- ((sum(1 for x in self.blocking[i] if is_open(x)), i) for i in self.open_ids),
- reverse=True,
- )
- self.top_blockers = [(n, i) for n, i in self.top_blockers if n > 0]
- self.cycles = self._find_cycles()
-
- # ---- epics -------------------------------------------------------
- self.epics: list[dict[str, Any]] = []
- for pid, kids in self.children.items():
- if pid not in issues:
- continue
- self.epics.append(
- {
- "id": pid,
- "n": len(kids),
- "open": sum(1 for k in kids if is_open(k)),
- "kids": kids,
- "title": str(issues[pid]["title"]),
- "type": str(issues[pid]["issue_type"]),
- "status": str(issues[pid]["status"]),
- }
- )
- self.epics.sort(key=lambda e: (-int(e["n"]), str(e["id"])))
-
- # ---- id/edge hierarchy disagreement -------------------------------
- self.id_mismatch = sorted(
- (child, self.parent[child])
- for child in self.parent
- if "." in child and child.rsplit(".", 1)[0] != self.parent[child]
- )
- self.id_orphan = sorted(str(r["id"]) for r in rows if "." in str(r["id"]) and str(r["id"]) not in self.parent)
-
- # ---- health -------------------------------------------------------
- self.closed_parent_open_kids = sorted(
- (pid, [k for k in kids if is_open(k)])
- for pid, kids in self.children.items()
- if pid in issues and issues[pid]["status"] == "closed" and any(is_open(k) for k in kids)
- )
- self.open_parent_all_closed = sorted(
- pid
- for pid, kids in self.children.items()
- if pid in issues and is_open(pid) and kids and not any(is_open(k) for k in kids)
- )
- title_counts = Counter(str(r["title"]).strip().lower() for r in rows)
- self.dup_titles = sorted(
- (title, [str(r["id"]) for r in rows if str(r["title"]).strip().lower() == title])
- for title, n in title_counts.items()
- if n > 1
- )
- self.no_ac_open = [
- str(r["id"])
- for r in rows
- if r["status"] != "closed" and not str(r.get("acceptance_criteria") or "").strip()
- ]
- self.closed_no_reason = [
- str(r["id"]) for r in rows if r["status"] == "closed" and not str(r.get("close_reason") or "").strip()
- ]
- # in_progress rows whose updated_at is older than the staleness budget
- self.stale_claims: list[tuple[str, float]] = sorted(
- (
- (str(r["id"]), (now - _parse_ts(str(r["updated_at"]))).total_seconds() / 86400)
- for r in rows
- if r["status"] == "in_progress"
- and r.get("updated_at")
- and (now - _parse_ts(str(r["updated_at"]))).total_seconds() / 86400 > STALE_CLAIM_DAYS
- ),
- key=lambda t: -t[1],
- )
-
- # ---- time ----------------------------------------------------------
- self.created_day = Counter(str(r["created_at"])[:10] for r in rows)
- self.closed_day = Counter(str(r["closed_at"])[:10] for r in rows if r.get("closed_at"))
- self.days = sorted(set(self.created_day) | set(self.closed_day))
- self.first_created = min(str(r["created_at"]) for r in rows)[:10]
- self.last_created = max(str(r["created_at"]) for r in rows)[:10]
- self.span_days = (
- _parse_ts(self.last_created + "T00:00:00Z") - _parse_ts(self.first_created + "T00:00:00Z")
- ).days + 1
-
- self.lead_by_priority: dict[int, list[float]] = defaultdict(list)
- for r in rows:
- if r["status"] == "closed" and r.get("closed_at"):
- delta = (_parse_ts(str(r["closed_at"])) - _parse_ts(str(r["created_at"]))).total_seconds() / 86400
- self.lead_by_priority[int(r["priority"])].append(delta)
- self.age_open = [
- (now - _parse_ts(str(r["created_at"]))).total_seconds() / 86400 for r in rows if r["status"] != "closed"
- ]
- # age (weeks, capped at 3+) x priority heatmap of open work
- self.age_prio: Counter[tuple[int, int]] = Counter(
- (
- min(int((now - _parse_ts(str(r["created_at"]))).total_seconds() / 86400 // 7), 3),
- int(r["priority"]),
- )
- for r in rows
- if r["status"] != "closed"
- )
-
- # trailing velocity windows: [now-14d, now) vs [now-28d, now-14d)
- w1_start = now - dt.timedelta(days=VELOCITY_WINDOW_DAYS)
- w2_start = now - dt.timedelta(days=2 * VELOCITY_WINDOW_DAYS)
-
- def _window(day_counter: Counter[str], lo: dt.datetime, hi: dt.datetime) -> int:
- return sum(n for day, n in day_counter.items() if lo <= _parse_ts(day + "T00:00:00Z") < hi)
-
- self.win_recent = (_window(self.created_day, w1_start, now), _window(self.closed_day, w1_start, now))
- self.win_prior = (
- _window(self.created_day, w2_start, w1_start),
- _window(self.closed_day, w2_start, w1_start),
- )
-
- # open P0/P1 older than the aged-urgent budget
- self.aged_urgent = sorted(
- (
- str(r["id"])
- for r in rows
- if r["status"] != "closed"
- and int(r["priority"]) <= 1
- and (now - _parse_ts(str(r["created_at"]))).total_seconds() / 86400 > AGED_URGENT_DAYS
- ),
- )
-
- # close-reason coverage over time (first vs second half of closures)
- closed_rows = sorted(
- (r for r in rows if r["status"] == "closed" and r.get("closed_at")),
- key=lambda r: str(r["closed_at"]),
- )
- half = len(closed_rows) // 2
- self.reason_rate_halves: tuple[float, float] = (
- (sum(1 for r in closed_rows[:half] if str(r.get("close_reason") or "").strip()) / half if half else 0.0),
- (
- sum(1 for r in closed_rows[half:] if str(r.get("close_reason") or "").strip())
- / (len(closed_rows) - half)
- if len(closed_rows) - half
- else 0.0
- ),
- )
-
- # ---- labels / themes ------------------------------------------------
- self.labels = Counter(str(x) for r in rows for x in (r.get("labels") or []))
- self.area_labels = [x for x in self.labels if x.startswith("area:")]
- self.area_singletons = sum(1 for x in self.area_labels if self.labels[x] == 1)
- self.labelled = sum(1 for r in rows if any(str(x).startswith("area:") for x in (r.get("labels") or [])))
- # mechanical near-synonym detection: one area suffix a strict prefix of another
- suffixes = sorted(x.removeprefix("area:") for x in self.area_labels)
- self.label_synonym_pairs = sorted(
- (a, b) for a in suffixes for b in suffixes if a != b and b.startswith(a) and len(b) - len(a) <= 8
- )
-
- rev_area: dict[str, str] = {}
- for canon, folded_suffixes in SUBSYSTEMS.items():
- for suffix in folded_suffixes:
- rev_area[suffix] = canon
- self.by_label_theme: dict[str, Counter[str]] = defaultdict(Counter)
- for r in rows:
- seen: set[str] = set()
- for raw in r.get("labels") or []:
- text = str(raw)
- if not text.startswith("area:"):
- continue
- folded = rev_area.get(text.removeprefix("area:"))
- if folded and folded not in seen:
- seen.add(folded)
- self.by_label_theme[folded][str(r["status"])] += 1
- self.by_kw_theme: dict[str, Counter[str]] = defaultdict(Counter)
- for r in rows:
- text = (str(r["title"]) + " " + str(r.get("description") or "")).lower()
- best, score = "unclassified", 0
- for canon, words in KEYWORDS.items():
- hits = sum(text.count(w) for w in words)
- if hits > score:
- best, score = canon, hits
- self.by_kw_theme[best][str(r["status"])] += 1
-
- # ---- verdict subset --------------------------------------------------
- self.verdicts: list[tuple[str, str, str, str]] = []
- loose: Counter[str] = Counter()
- for r in rows:
- text = _blob(r)
- strict = VERDICT_STRICT.search(text)
- if strict:
- self.verdicts.append((str(r["id"]), strict.group(2).upper(), str(r["status"]), strict.group(1).strip()))
- found = VERDICT_LOOSE.findall(text)
- if found:
- loose[Counter(found).most_common(1)[0][0]] += 1
- self.verdict_counts = Counter(v for _, v, _, _ in self.verdicts)
- self.loose_counts = loose
-
- # A bulk relation re-type stamps every converted edge with the repair
- # date. Detect it as a same-day spike on the newest association edge.
- rel_days = Counter(created[:10] for _, _, kind, created in edges if kind == "relates-to" and created)
- self.retyped_spike = 0
- self.retyped_spike_day = ""
- if rel_days and self.vocab_state in ("clean", "recurring"):
- newest = max(rel_days)
- spike = rel_days[newest]
- if spike >= 0.2 * sum(rel_days.values()):
- self.retyped_spike = spike
- self.retyped_spike_day = newest
-
- # A `related` edge whose created_at is later than the newest
- # relates-to edge on the repair day proves the fork already started
- # recurring after the repair.
- self.related_recurrence: list[tuple[str, str, str]] = []
- if self.retyped_spike_day:
- newest_retype_ts = max(
- (
- created
- for _, _, kind, created in edges
- if kind == "relates-to" and created[:10] == self.retyped_spike_day
- ),
- default="",
- )
- for src, dst, kind, created in edges:
- if kind == "related" and created > newest_retype_ts:
- self.related_recurrence.append((src, dst, created))
-
- # ---- P0 reconciliation pass (2026-07-31) ---------------------------
- self.reconciliation: list[tuple[str, str, str]] = []
- self.reconciliation_anchored = 0
- for r in rows:
- text = _blob(r)
- anchor = RECONCILIATION_ANCHOR.search(text)
- if not anchor:
- continue
- self.reconciliation_anchored += 1
- window = text[anchor.end() : anchor.end() + RECONCILIATION_WINDOW]
- token = RECONCILIATION_TOKEN_RE.search(window)
- if token:
- cut = window.find(token.group()) + len(token.group())
- snippet = window[:cut].strip()
- self.reconciliation.append((str(r["id"]), token.group(), snippet))
- self.reconciliation_counts = Counter(v for _, v, _ in self.reconciliation)
-
- # ---- temporal reconstruction -----------------------------------------
- def open_at(self, rec: IssueDict, as_of: dt.datetime) -> bool:
- """Whether a bead existed and was not-closed at ``as_of``.
-
- Derived from ``created_at``/``closed_at``; a reopened bead's earlier
- closure is invisible (closed_at reflects only the latest close), and
- deleted beads are absent from the export entirely.
- """
- if _parse_ts(str(rec["created_at"])) > as_of:
- return False
- closed = rec.get("closed_at")
- return not (closed and _parse_ts(str(closed)) <= as_of)
-
- def snapshot(self, as_of: dt.datetime) -> dict[str, int]:
- """Key backlog metrics reconstructed as of a past instant."""
- exists = [r for r in self.rows if _parse_ts(str(r["created_at"])) <= as_of]
- open_rows = [r for r in exists if self.open_at(r, as_of)]
- open_set = {str(r["id"]) for r in open_rows}
- blocked_by_open: dict[str, bool] = defaultdict(bool)
- for src, dst, created in self.block_edges_ts:
- if created and _parse_ts(created) <= as_of and src in open_set and dst in open_set:
- blocked_by_open[src] = True
- blocked_n = sum(1 for bid in open_set if blocked_by_open[bid])
- return {
- "total": len(exists),
- "open": len(open_rows),
- "closed": len(exists) - len(open_rows),
- "p0_open": sum(1 for r in open_rows if int(r["priority"]) == 0),
- "blocked": blocked_n,
- "ready": len(open_set) - blocked_n,
- }
-
- def daily_series(self) -> list[tuple[str, int, int]]:
- """(day, open count, ready count) for every day of the backlog's life."""
- start = _parse_ts(self.first_created + "T00:00:00Z")
- out: list[tuple[str, int, int]] = []
- day = start
- while day <= self.now:
- eod = day + dt.timedelta(days=1)
- snap = self.snapshot(eod)
- out.append((day.strftime("%Y-%m-%d"), snap["open"], snap["ready"]))
- day = eod
- return out
-
- def epic_open_series(self, epic_id: str, days: Sequence[str]) -> list[int]:
- """Open-children count per day for one epic (membership as of today)."""
- kids = [self.issues[k] for k in self.children.get(epic_id, []) if k in self.issues]
- out: list[int] = []
- for day in days:
- eod = _parse_ts(day + "T00:00:00Z") + dt.timedelta(days=1)
- out.append(sum(1 for k in kids if self.open_at(k, eod)))
- return out
-
- # ---- graph structure --------------------------------------------------
- def _find_cycles(self) -> list[list[str]]:
- colour: dict[str, int] = {}
- cycles: list[list[str]] = []
-
- def visit(start: str) -> None:
- stack: list[tuple[str, Iterable[str]]] = [(start, iter(sorted(self.blockers[start])))]
- colour[start] = 1
- path = [start]
- while stack:
- node, it = stack[-1]
- advanced = False
- for nxt in it:
- if nxt not in self.issues:
- continue
- state = colour.get(nxt)
- if state == 1:
- cycles.append(path[path.index(nxt) :] + [nxt])
- elif state is None:
- colour[nxt] = 1
- path.append(nxt)
- stack.append((nxt, iter(sorted(self.blockers[nxt]))))
- advanced = True
- break
- if not advanced:
- colour[node] = 2
- stack.pop()
- path.pop()
-
- for bid in sorted(self.issues):
- if colour.get(bid) is None:
- visit(bid)
- return cycles
-
- def rate(self, priority: int) -> float:
- total = self.priority[priority]
- closed = self.matrix.get(("closed", priority), 0)
- return closed / total if total else 0.0
-
- def densest_cluster(self) -> list[str]:
- """Largest weakly-connected component of the open-only `blocks` graph."""
- adj: dict[str, set[str]] = defaultdict(set)
- open_set = set(self.open_ids)
- for src, dst, kind, _ in self.edges:
- if kind == "blocks" and src in open_set and dst in open_set:
- adj[src].add(dst)
- adj[dst].add(src)
- seen: set[str] = set()
- best: list[str] = []
- for node in sorted(adj):
- if node in seen:
- continue
- comp: list[str] = []
- queue = [node]
- seen.add(node)
- while queue:
- cur = queue.pop()
- comp.append(cur)
- for nxt in sorted(adj[cur]):
- if nxt not in seen:
- seen.add(nxt)
- queue.append(nxt)
- if len(comp) > len(best):
- best = comp
- self._cluster_adj = adj
- return sorted(best)
-
- def cluster_core(self, component: Sequence[str], min_degree: int = 3) -> list[str]:
- """The legible core of a component: nodes with >= min_degree neighbours in it."""
- adj = self._cluster_adj
- member = set(component)
- return sorted(n for n in component if len({x for x in adj[n] if x in member}) >= min_degree)
-
- def descendants(self, root: str, max_depth: int = 6) -> set[str]:
- """All parent-child descendants of a bead, cycle-safe."""
- out: set[str] = set()
- frontier = [root]
- for _ in range(max_depth):
- nxt: list[str] = []
- for node in frontier:
- for kid in self.children.get(node, []):
- if kid not in out:
- out.add(kid)
- nxt.append(kid)
- if not nxt:
- break
- frontier = nxt
- return out
-
- def parallel_frontier(self, top_n: int = 8) -> list[dict[str, Any]]:
- """The largest set of big open epics whose open subtrees share no
- ``blocks`` component -- work that can run in parallel with no ordering
- constraint between the programs. Greedy by open-descendant count.
- """
- # component id per open bead in the blocks graph
- self.densest_cluster() # populates _cluster_adj
- comp_of: dict[str, int] = {}
- cid = 0
- for node in sorted(self._cluster_adj):
- if node in comp_of:
- continue
- queue = [node]
- comp_of[node] = cid
- while queue:
- cur = queue.pop()
- for nxt in self._cluster_adj[cur]:
- if nxt not in comp_of:
- comp_of[nxt] = cid
- queue.append(nxt)
- cid += 1
-
- candidates: list[dict[str, Any]] = []
- for e in self.epics:
- desc = {d for d in self.descendants(str(e["id"])) if self.is_open(d)}
- if len(desc) < 3:
- continue
- comps = {comp_of[d] for d in desc if d in comp_of}
- candidates.append(
- {
- "id": str(e["id"]),
- "title": str(e["title"]),
- "open_desc": len(desc),
- "desc": desc,
- "comps": comps,
- "urgent": sum(1 for d in desc if int(self.issues[d]["priority"]) <= 2),
- }
- )
- candidates.sort(key=lambda c: (-int(c["open_desc"]), str(c["id"])))
-
- chosen: list[dict[str, Any]] = []
- used_comps: set[int] = set()
- used_beads: set[str] = set()
- for cand in candidates[:top_n]:
- if cand["comps"] & used_comps or cand["desc"] & used_beads:
- continue
- chosen.append(cand)
- used_comps |= set(cand["comps"])
- used_beads |= set(cand["desc"])
- return chosen
-
-
-# --------------------------------------------------------------------------
-# computed insights: the interpretation layer. Every entry is emitted by a
-# condition checked against the data; regeneration cannot leave a stale claim.
-# --------------------------------------------------------------------------
-@dataclass
-class Insight:
- sev: str # bad | warn | info | ok
- title: str # html
- body: str # html
- ev: str = "derived" # measured | derived
- chips: list[str] = field(default_factory=list) # bead ids to render as chips
-
-
-_SEV_ORDER = {"bad": 0, "warn": 1, "info": 2, "ok": 3}
-
-
-def compute_insights(facts: Facts, schema_gap: dict[str, Any], snaps: dict[str, dict[str, int]]) -> list[Insight]:
- out: list[Insight] = []
-
- # -- schema gap: merged fixes inert until rebuild -----------------------
- if schema_gap.get("available") and schema_gap.get("blockers"):
- pending = (
- facts.reconciliation_counts["FIXED-PENDING-REBUILD"] + facts.reconciliation_counts["FIXED-PENDING-DEPLOY"]
- )
- pending_note = (
- f" The dated reconciliation pass confirmed {pending} beads merged and inert behind it."
- if pending
- else ""
- )
- out.append(
- Insight(
- "bad",
- f"Live archive is {len(schema_gap['blockers'])} SEMANTIC_REPARSE version(s) behind origin/master "
- f"(v{schema_gap['live_version']} vs v{schema_gap['declared']})",
- "Merged fixes at those versions are real, reviewed, and completely inert until "
- "polylogue ops reset --index && polylogued run executes." + pending_note,
- ev="measured",
- )
- )
-
- # -- dangling refs ------------------------------------------------------
- if facts.dangling:
- targets = ", ".join(f"{esc(b)}" for _, b, _ in facts.dangling[:6])
- out.append(
- Insight(
- "bad",
- f"{len(facts.dangling)} dependency edge(s) point at ids that do not exist",
- f"Unresolvable targets: {targets}. The blocking intent behind each edge is silently absent "
- "from every query. Id references in dependency edges are not validated on write.",
- ev="measured",
- )
- )
-
- # -- cycles -------------------------------------------------------------
- if facts.cycles:
- first = " → ".join(esc(x) for x in facts.cycles[0])
- out.append(
- Insight(
- "bad",
- f"{len(facts.cycles)} cycle(s) in the blocks graph",
- f"A mutual-blocking loop can never become ready. First cycle: {first}.",
- ev="measured",
- )
- )
- else:
- out.append(
- Insight(
- "ok",
- "No cycles in the blocks graph",
- f"Verified by DFS colouring over all {facts.total:,} beads and "
- f"{facts.dep_types['blocks']:,} blocks edges. Stated explicitly rather than left as an "
- "absence: a graph grown this fast by many independent lanes is where mutual-blocking "
- "pairs appear by accident.",
- ev="measured",
- )
- )
-
- # -- velocity: trailing window vs the one before it --------------------
- (rc, rx), (pc, px) = facts.win_recent, facts.win_prior
- r_net, p_net = rc - rx, pc - px
- if r_net > 0 and p_net > 0:
- sev, verdict = "warn", "growing in both trailing windows — still in discovery, not burn-down"
- elif r_net < 0 <= p_net:
- sev, verdict = "ok", "tipped from growth to net drain in the most recent window"
- elif r_net < 0 and p_net < 0:
- sev, verdict = "ok", "draining in both trailing windows"
- elif r_net > 0 >= p_net:
- sev, verdict = "warn", "flipped back from drain to growth in the most recent window"
- else:
- sev, verdict = "info", "roughly flat"
- out.append(
- Insight(
- sev,
- f"Backlog is {verdict}",
- f"Last {VELOCITY_WINDOW_DAYS}d: {rc} created / {rx} closed (net {r_net:+d}). "
- f"Prior {VELOCITY_WINDOW_DAYS}d: {pc} created / {px} closed (net {p_net:+d}). "
- "Velocity-derived completion estimates are meaningful only once the trailing window "
- "is reliably net-negative.",
- )
- )
-
- # -- ready fraction -----------------------------------------------------
- if facts.open_total:
- frac = len(facts.ready) / facts.open_total
- if frac >= 0.6:
- out.append(
- Insight(
- "info",
- f"{frac:.0%} of open work is unblocked — throughput-bound, not dependency-bound",
- f"{len(facts.ready):,} of {facts.open_total:,} open beads have no open blocker. "
- "No amount of unblocking changes the picture; execution capacity is the constraint.",
- ev="measured",
- )
- )
- elif frac <= 0.35:
- out.append(
- Insight(
- "warn",
- f"Only {frac:.0%} of open work is unblocked — the graph is dependency-bound",
- f"{len(facts.blocked):,} of {facts.open_total:,} open beads wait on an open blocker. "
- "Unblocking the top blockers is the highest-leverage move; see Topology.",
- ev="measured",
- )
- )
-
- # -- priority ladder ----------------------------------------------------
- rates = [facts.rate(p) for p in range(5)]
- leads = [_median(facts.lead_by_priority[p]) for p in range(5)]
- rate_inversions = [p for p in range(3) if facts.priority[p + 1] and rates[p] < rates[p + 1]]
- lead_inversions = [p for p in range(3) if leads[p + 1] and leads[p] > leads[p + 1]]
- lead_str = " / ".join(f"{v:.1f}" for v in leads)
- rate_str = " / ".join(f"{v:.0%}" for v in rates)
- if not rate_inversions and not lead_inversions:
- out.append(
- Insight(
- "info",
- "The priority scale is load-bearing — do not renumber it",
- f"Median lead time rises monotonically P0→P3 ({lead_str} days for P0–P4) and "
- f"closure rate falls monotonically P0→P3 ({rate_str}). An inflated priority label "
- "would show a flat curve; this one sorts work at every rung.",
- )
- )
- else:
- inv = ", ".join(f"P{p}→P{p + 1}" for p in sorted(set(rate_inversions + lead_inversions)))
- out.append(
- Insight(
- "warn",
- f"Priority ladder inverts at {inv}",
- f"Median lead days P0–P4: {lead_str}. Closure rates: {rate_str}. "
- "Where a lower-urgency rung closes faster or more often than the rung above it, the "
- "label is not carrying the information a scheduler needs.",
- )
- )
-
- # -- aged urgency -------------------------------------------------------
- if facts.aged_urgent:
- out.append(
- Insight(
- "warn",
- f"{len(facts.aged_urgent)} open P0/P1 bead(s) older than {AGED_URGENT_DAYS} days",
- "Urgency that sits is urgency mislabelled or capacity missing — either way it is "
- "the first shelf to triage. Oldest listed below.",
- chips=facts.aged_urgent[:8],
- )
- )
-
- # -- stale in-progress claims ------------------------------------------
- if facts.stale_claims:
- out.append(
- Insight(
- "warn",
- f"{len(facts.stale_claims)} in-progress claim(s) untouched for over {STALE_CLAIM_DAYS} days",
- "A claim without activity blocks other agents from picking the bead up. "
- "Release the claim or finish the work.",
- ev="measured",
- chips=[bid for bid, _ in facts.stale_claims[:8]],
- )
- )
-
- # -- parallel frontier --------------------------------------------------
- frontier = facts.parallel_frontier()
- if len(frontier) >= 2:
- total_open_desc = sum(int(c["open_desc"]) for c in frontier)
- share = total_open_desc / facts.open_total if facts.open_total else 0.0
- names = ", ".join(f"{esc(str(c['id']))}" for c in frontier)
- out.append(
- Insight(
- "info",
- f"{len(frontier)} large programs share no blocking path — they can run in parallel",
- f"{names} hold {total_open_desc} open descendants between them ({share:.0%} of all open "
- "work) and their open subtrees occupy disjoint components of the blocks "
- "graph: no ordering constraint exists between the programs. Detail in Topology.",
- )
- )
-
- # -- relation vocabulary fork ------------------------------------------
- relates, related = facts.dep_types["relates-to"], facts.dep_types["related"]
- if facts.vocab_state == "split":
- out.append(
- Insight(
- "bad",
- "Split relation vocabulary: relates-to vs related",
- f"{relates} + {related} edges are one relation under two names. Any association query "
- "silently returns a partial subset. Pick one spelling, rewrite the other, constrain the field.",
- ev="measured",
- )
- )
- elif facts.vocab_state == "recurring":
- out.append(
- Insight(
- "warn",
- "Relation vocabulary was unified, then forked again",
- f"A bulk re-type unified the association relation, but wrote no constraint, and "
- f"{related} fresh related edge(s) landed after the repair window. "
- "The data was cleaned; the write path is still open.",
- ev="measured",
- )
- )
-
- # -- label vocabulary ---------------------------------------------------
- if facts.label_synonym_pairs:
- pairs = ", ".join(f"{esc(a)}/{esc(b)}" for a, b in facts.label_synonym_pairs[:6])
- out.append(
- Insight(
- "warn",
- f"{len(facts.area_labels)} distinct area:* labels, "
- f"{facts.area_singletons} used once, {len(facts.label_synonym_pairs)} near-synonym pair(s)",
- f"Prefix-detected synonym pairs: {pairs}. A free-text label field with no controlled "
- "vocabulary degrades into per-author spelling; grouping by raw label undercounts every "
- "affected subsystem. The Themes section folds them through an explicit map.",
- ev="measured",
- )
- )
-
- # -- review queue -------------------------------------------------------
- if facts.open_parent_all_closed:
- out.append(
- Insight(
- "warn",
- f"{len(facts.open_parent_all_closed)} open parent(s) with every child closed — "
- "review, not auto-close",
- "Children closing is evidence a parent is ready for adjudication against its own "
- "acceptance criteria, never evidence that it is done. Queue in Health.",
- )
- )
-
- # -- duplicate titles ---------------------------------------------------
- if facts.dup_titles:
- out.append(
- Insight(
- "info",
- f"{len(facts.dup_titles)} duplicate title pair(s)",
- "Independently filed beads describing the same work; listed in Health with both ids.",
- ev="measured",
- )
- )
-
- # -- close-reason discipline -------------------------------------------
- r1, r2 = facts.reason_rate_halves
- if facts.status["closed"] >= 20:
- direction = "improving" if r2 > r1 + 0.02 else ("degrading" if r2 < r1 - 0.02 else "steady")
- sev = "info" if r2 >= 0.9 else "warn"
- out.append(
- Insight(
- sev,
- f"Close-reason coverage is {r2:.0%} in the newer half of closures ({direction})",
- f"Earlier half {r1:.0%}, newer half {r2:.0%}; "
- f"{len(facts.closed_no_reason)} closed bead(s) in total carry no reason. A close without "
- "a reason leaves no durable record of why the work ended.",
- )
- )
-
- # -- open-count trend vs 7d --------------------------------------------
- now_open = snaps["now"]["open"]
- week_open = snaps["7d"]["open"]
- if week_open:
- delta = now_open - week_open
- if abs(delta) >= max(5, 0.03 * week_open):
- direction = "grew" if delta > 0 else "shrank"
- out.append(
- Insight(
- "info",
- f"Open backlog {direction} {abs(delta)} bead(s) in the last 7 days ({week_open} → {now_open})",
- "Reconstructed from created/closed timestamps; deleted beads and reopen history "
- "are invisible to the reconstruction.",
- )
- )
-
- out.sort(key=lambda i: _SEV_ORDER.get(i.sev, 9))
- return out
-
-
-# --------------------------------------------------------------------------
-# rendering helpers
-# --------------------------------------------------------------------------
-def esc(text: str) -> str:
- return html.escape(str(text), quote=True)
-
-
-def chip(facts: Facts, bid: str, *, title: bool = False) -> str:
- """The compact bead notation used everywhere in the report."""
- rec = facts.issues.get(bid)
- if rec is None:
- return f'{esc(bid)} ? '
- prio = int(rec["priority"])
- status = str(rec["status"])
- sglyph, sname = STATUS_GLYPH.get(status, ("?", status))
- tglyph, tname = TYPE_GLYPH.get(str(rec["issue_type"]), ("?", str(rec["issue_type"])))
- inn = sum(1 for b in facts.blockers[bid] if facts.is_open(b))
- out = sum(1 for b in facts.blocking[bid] if facts.is_open(b))
- deg = ""
- if inn or out:
- deg = f'{"↑" + str(inn) if inn else ""}{"↓" + str(out) if out else ""} '
- tip = f"P{prio} · {sname} · {tname} · {inn} open blocker(s) · blocks {out} open"
- text = f' {esc(str(rec["title"])[:64])} ' if title else ""
- return (
- f''
- f'P{prio} '
- f'{sglyph} '
- f'{esc(bid)} '
- f'{tglyph} {deg}{text} '
- )
-
-
-def delta_chip(now_v: int, then_v: int, *, up_is_bad: bool = False) -> str:
- """A signed 7-day delta rendered next to a stat tile value."""
- d = now_v - then_v
- if d == 0:
- return '±0 '
- arrow = "▲" if d > 0 else "▼"
- bad = (d > 0) == up_is_bad
- cls = "worse" if bad else "better"
- return f'{arrow}{abs(d)} '
-
-
-def sparkline_svg(values: Sequence[int], *, label: str = "") -> str:
- """A tiny inline trend line; viewBox only, currentColor stroke."""
- if len(values) < 2:
- return ""
- lo, hi = min(values), max(values)
- span = (hi - lo) or 1
- w = (len(values) - 1) * 3
- pts = " ".join(f"{i * 3},{18 - 15 * (v - lo) / span:.1f}" for i, v in enumerate(values))
- title = f"{esc(label)} {values[0]} → {values[-1]} " if label else ""
- return (
- f'{title}'
- f' '
- )
-
-
-def burnup_svg(series: Sequence[tuple[str, int, int]]) -> str:
- """Open + ready count over the backlog's whole life, one small chart."""
- if len(series) < 2:
- return ""
- peak = max(v for _, v, _ in series) or 1
- n = len(series)
- w, h = (n - 1) * 10, 60
-
- def path(values: Sequence[int]) -> str:
- return " ".join(f"{i * 10},{h - 4 - (h - 12) * (v / peak):.1f}" for i, v in enumerate(values))
-
- open_pts = path([row[1] for row in series])
- ready_pts = path([row[2] for row in series])
- parts = [
- f'',
- f' ',
- f' ',
- ]
- for i, (day, open_n, ready_n) in enumerate(series):
- parts.append(
- f''
- f"{esc(day)}: {open_n} open, {ready_n} ready "
- )
- parts.append(" ")
- return "".join(parts)
-
-
-def histogram_svg(days: Sequence[str], series: Sequence[tuple[str, Counter[str], str]]) -> str:
- """Grouped per-day bar chart, pure SVG, viewBox only."""
- if not days:
- return ""
- step = 10.0
- width = len(days) * step
- height = 46.0
- peak = max((c[day] for _, c, _ in series for day in days), default=1) or 1
- parts = [
- f''
- ]
- bw = step / (len(series) + 1)
- for si, (_, counts, cls) in enumerate(series):
- for di, day in enumerate(days):
- value = counts[day]
- if not value:
- continue
- bh = (value / peak) * (height - 8)
- x = di * step + si * bw
- parts.append(
- f'{esc(day)}: {value} '
- )
- parts.append(" ")
- return "".join(parts)
-
-
-def cluster_svg(facts: Facts, nodes: Sequence[str]) -> str:
- """Layered DAG of one connected `blocks` component. Layer = longest path from a root."""
- node_set = set(nodes)
- layer: dict[str, int] = {}
-
- def depth(bid: str, seen: frozenset[str]) -> int:
- if bid in layer:
- return layer[bid]
- ups = [b for b in facts.blockers[bid] if b in node_set and b not in seen]
- value = 0 if not ups else 1 + max(depth(u, seen | {bid}) for u in ups)
- layer[bid] = value
- return value
-
- for bid in nodes:
- depth(bid, frozenset())
- rows: dict[int, list[str]] = defaultdict(list)
- for bid in sorted(nodes):
- rows[layer[bid]].append(bid)
- pos: dict[str, tuple[float, float]] = {}
- col_w, row_h = 210.0, 34.0
- for lv, members in rows.items():
- for i, bid in enumerate(sorted(members)):
- pos[bid] = (18 + lv * col_w, 22 + i * row_h)
- width = 36 + (max(rows) + 1) * col_w
- height = 30 + max(len(v) for v in rows.values()) * row_h
- parts = [
- f'',
- ' ',
- ]
- for src in nodes:
- for dst in facts.blockers[src]:
- if dst not in node_set:
- continue
- x1, y1 = pos[dst]
- x2, y2 = pos[src]
- parts.append(
- f' '
- )
- for bid, (x, y) in pos.items():
- rec = facts.issues[bid]
- prio = int(rec["priority"])
- parts.append(
- f' '
- f'P{prio} {esc(bid)} '
- f"{esc(str(rec['title'])[:110])} "
- )
- parts.append(" ")
- return "".join(parts)
-
-
-def tree_html(facts: Facts, root: str, depth: int = 0) -> str:
- kids = sorted(facts.children.get(root, []))
- if not kids or depth > 1:
- return ""
- items = []
- for kid in kids:
- if kid not in facts.issues:
- continue
- sub = tree_html(facts, kid, depth + 1)
- title = esc(str(facts.issues[kid]["title"])[:78])
- items.append(f'{chip(facts, kid)} {title} {sub} ')
- return f''
-
-
-def fill_bar(open_n: int, total: int) -> str:
- done = total - open_n
- pct = 100 * done / total if total else 0
- return (
- f''
- f' '
- f'{done}/{total} '
- )
-
-
-def heatmap_html(facts: Facts) -> str:
- """Age (weeks) x priority heatmap of open work; sequential single-hue fill."""
- age_labels = ["0–6d", "7–13d", "14–20d", "21d+"]
- peak = max(facts.age_prio.values()) if facts.age_prio else 1
- parts = ['age \\ priority ']
- for p in range(5):
- parts.append(f'P{p} ')
- parts.append('row ')
- for w, label in enumerate(age_labels):
- row_total = sum(facts.age_prio.get((w, p), 0) for p in range(5))
- parts.append(f"{label} ")
- for p in range(5):
- n = facts.age_prio.get((w, p), 0)
- pct = 58 * n / peak if peak else 0
- parts.append(
- f'{n or ""} '
- )
- parts.append(f'{row_total} ')
- parts.append("
")
- return "".join(parts)
-
-
-def qa(command: str, label: str) -> str:
- """Attach the exact invocation that produced a figure."""
- return (
- ''
- f"{esc(label)} {esc(command)} "
- )
-
-
-CSS = """
-:root{
- --bg:#f6f7f9; --panel:#ffffff; --ink:#1a2129; --muted:#5b6773;
- --line:#dde3e9; --accent:#2563eb; --accent-ink:#ffffff;
- --ok:#0f7b46; --ok-bg:#e2f5eb; --warn:#8a5a00; --warn-bg:#fdf0d3;
- --bad:#a01c1c; --bad-bg:#fbe4e4; --info:#1d4ed8; --info-bg:#e3ebfd;
- --todo:#6b21a8; --todo-bg:#f1e6fb; --code-bg:#eef1f4;
- --p0:#a01c1c; --p1:#b45309; --p2:#1d4ed8; --p3:#0f7b46; --p4:#5b6773;
-}
-@media (prefers-color-scheme: dark){:root{
- --bg:#12161b; --panel:#1a2027; --ink:#e6ebf0; --muted:#94a1ad;
- --line:#2b333c; --accent:#5b8def; --accent-ink:#0d1117;
- --ok:#4cc98a; --ok-bg:#12301f; --warn:#e2b93b; --warn-bg:#33290e;
- --bad:#ef7070; --bad-bg:#391717; --info:#7ea6f4; --info-bg:#16223b;
- --todo:#c793ef; --todo-bg:#2a1738; --code-bg:#232a32;
- --p0:#ef7070; --p1:#e2b93b; --p2:#7ea6f4; --p3:#4cc98a; --p4:#94a1ad;
-}}
-:root[data-theme="light"]{color-scheme:light}
-:root[data-theme="dark"]{color-scheme:dark}
-:root[data-theme="dark"]{
- --bg:#12161b; --panel:#1a2027; --ink:#e6ebf0; --muted:#94a1ad;
- --line:#2b333c; --accent:#5b8def; --accent-ink:#0d1117;
- --ok:#4cc98a; --ok-bg:#12301f; --warn:#e2b93b; --warn-bg:#33290e;
- --bad:#ef7070; --bad-bg:#391717; --info:#7ea6f4; --info-bg:#16223b;
- --todo:#c793ef; --todo-bg:#2a1738; --code-bg:#232a32;
- --p0:#ef7070; --p1:#e2b93b; --p2:#7ea6f4; --p3:#4cc98a; --p4:#94a1ad;
-}
-:root[data-theme="light"]{
- --bg:#f6f7f9; --panel:#ffffff; --ink:#1a2129; --muted:#5b6773;
- --line:#dde3e9; --accent:#2563eb; --accent-ink:#ffffff;
- --ok:#0f7b46; --ok-bg:#e2f5eb; --warn:#8a5a00; --warn-bg:#fdf0d3;
- --bad:#a01c1c; --bad-bg:#fbe4e4; --info:#1d4ed8; --info-bg:#e3ebfd;
- --todo:#6b21a8; --todo-bg:#f1e6fb; --code-bg:#eef1f4;
- --p0:#a01c1c; --p1:#b45309; --p2:#1d4ed8; --p3:#0f7b46; --p4:#5b6773;
-}
-:root{--fs:17px}
-*{box-sizing:border-box}
-html{font-size:var(--fs)}
-body{margin:0;background:var(--bg);color:var(--ink);
- font:1rem/1.62 system-ui,-apple-system,"Segoe UI",sans-serif}
-header.page{position:sticky;top:0;z-index:5;background:var(--panel);
- border-bottom:1px solid var(--line);padding:.7rem 1.2rem;
- display:flex;flex-wrap:wrap;align-items:baseline;gap:.6rem}
-header.page h1{font-size:1.3rem;margin:0}
-header.page .spacer{flex:1}
-.chip{display:inline-block;padding:.12rem .6rem;border:1px solid var(--line);
- border-radius:99px;font-size:.85rem;color:var(--muted);background:var(--bg)}
-button.theme,button.fs{border:1px solid var(--line);background:var(--bg);color:var(--ink);
- border-radius:.4rem;padding:.2rem .6rem;cursor:pointer;font-size:.85rem}
-.layout{display:grid;grid-template-columns:16rem minmax(0,1fr);
- max-width:80rem;margin:0 auto;gap:1.2rem;padding:1.2rem}
-@media(max-width:62rem){.layout{grid-template-columns:minmax(0,1fr)}nav#toc{display:none}}
-nav#toc{position:sticky;top:3.8rem;align-self:start;font-size:.92rem;
- border-right:1px solid var(--line);padding-right:.8rem;max-height:85vh;overflow:auto}
-nav#toc a{display:block;color:var(--muted);text-decoration:none;padding:.16rem 0}
-nav#toc a.h3{padding-left:.9rem;font-size:.87rem}
-nav#toc a:hover{color:var(--accent)}
-main{min-width:0}
-section{background:var(--panel);border:1px solid var(--line);border-radius:.6rem;
- padding:1.1rem 1.3rem;margin-bottom:1.1rem}
-h2{font-size:1.28rem;margin:.1rem 0 .7rem;line-height:1.3}
-h3{font-size:1.07rem;margin:1.1rem 0 .45rem;line-height:1.35}
-p{margin:.5rem 0;max-width:76ch}
-a{color:var(--accent)}
-code,kbd{background:var(--code-bg);border-radius:.3rem;padding:.08rem .35rem;
- font:.9em ui-monospace,SFMono-Regular,Menlo,monospace}
-pre{background:var(--code-bg);padding:.75rem .9rem;border-radius:.5rem;
- overflow-x:auto;font-size:.92rem;line-height:1.5}
-pre code{background:none;padding:0;font-size:1em}
-.tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(10.5rem,1fr));
- gap:.7rem;margin:.4rem 0 .9rem}
-.tile{border:1px solid var(--line);border-radius:.55rem;padding:.6rem .85rem;background:var(--bg)}
-.tile .n{font-size:1.6rem;font-weight:650;display:block;line-height:1.2}
-.tile .l{font-size:.85rem;color:var(--muted)}
-.tile.qa{position:relative;cursor:help}
-.tile.qa::after{content:"\\2315";position:absolute;top:.35rem;right:.45rem;opacity:.35;font-size:.8rem}
-.dl{font-size:.8rem;font-weight:700;margin-left:.35rem;vertical-align:.25em}
-.dl.worse{color:var(--bad)} .dl.better{color:var(--ok)} .dl.flat{color:var(--muted)}
-.badge{display:inline-block;font-size:.8rem;font-weight:600;letter-spacing:.02em;
- padding:.1rem .55rem;border-radius:99px;white-space:nowrap}
-.ok{color:var(--ok);background:var(--ok-bg)} .warn{color:var(--warn);background:var(--warn-bg)}
-.bad{color:var(--bad);background:var(--bad-bg)} .info{color:var(--info);background:var(--info-bg)}
-.todo{color:var(--todo);background:var(--todo-bg)}
-.tablewrap{overflow-x:auto}
-table{border-collapse:collapse;width:100%;font-size:.95rem}
-th,td{border-bottom:1px solid var(--line);text-align:left;padding:.42rem .6rem;vertical-align:top}
-th{color:var(--muted);font-size:.85rem;text-transform:uppercase;letter-spacing:.04em;
- cursor:pointer;user-select:none;white-space:nowrap}
-th.nosort{cursor:default}
-tr:hover td{background:color-mix(in srgb, var(--accent) 6%, transparent)}
-td.num{text-align:right;font-variant-numeric:tabular-nums}
-details{border:1px solid var(--line);border-radius:.5rem;padding:.5rem .85rem;margin:.5rem 0;background:var(--bg)}
-summary{cursor:pointer;font-weight:600;font-size:1rem}
-details[open]{padding-bottom:.6rem}
-input.filter{width:100%;max-width:26rem;margin:.2rem 0 .55rem;padding:.35rem .65rem;
- border:1px solid var(--line);border-radius:.4rem;background:var(--bg);color:var(--ink);font-size:.95rem}
-footer{color:var(--muted);font-size:.88rem;text-align:center;padding:1rem}
-.meta{display:grid;grid-template-columns:auto 1fr;gap:.2rem .9rem;font-size:.9rem;
- border-left:3px solid var(--line);padding:.1rem 0 .1rem .9rem;margin:.2rem 0 .9rem}
-.meta dt{color:var(--muted)}
-.meta dd{margin:0}
-.ev{display:inline-block;font-size:.72rem;font-weight:700;letter-spacing:.03em;
- padding:0 .35rem;border-radius:.25rem;vertical-align:.1em;text-transform:uppercase}
-.ev-measured{color:var(--ok);background:var(--ok-bg)}
-.ev-derived{color:var(--info);background:var(--info-bg)}
-.ev-inferred{color:var(--warn);background:var(--warn-bg)}
-.ev-assumed{color:var(--bad);background:var(--bad-bg)}
-time.age{color:var(--muted);font-size:.85em;font-variant-numeric:tabular-nums}
-time.age.stale{color:var(--warn);font-weight:600}
-time.age.stale::after{content:" \\26A0"}
-a.path{font:.9em ui-monospace,SFMono-Regular,Menlo,monospace;background:var(--code-bg);
- border-radius:.3rem;padding:.08rem .35rem;text-decoration:none;border-bottom:1px dotted var(--accent)}
-.pop{position:fixed;z-index:50;max-width:min(46rem,92vw);max-height:70vh;overflow:auto;
- background:var(--panel);border:1px solid var(--line);border-radius:.5rem;
- box-shadow:0 .6rem 2rem rgba(0,0,0,.28);padding:.7rem .9rem;font-size:.92rem}
-.pop h4{margin:0 0 .35rem;font-size:.92rem;font-family:ui-monospace,monospace;color:var(--muted)}
-.pop pre{margin:0;max-height:52vh;font-size:.86rem}
-.pop .pin{float:right;border:none;background:none;color:var(--muted);cursor:pointer}
-blockquote.q{position:relative;margin:.55rem 0 .4rem;padding:.6rem 1.1rem .6rem 2.3rem;
- background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--todo);
- border-radius:0 .45rem .45rem 0;
- font:italic 1rem/1.55 Georgia,"Iowan Old Style","Noto Serif",ui-serif,serif}
-blockquote.q::before{content:"\\201C";position:absolute;left:.45rem;top:.15rem;
- font:italic 2.2rem/1 Georgia,ui-serif,serif;color:var(--todo);opacity:.5}
-blockquote.q cite{display:block;margin-top:.4rem;font:600 .72rem/1 system-ui,sans-serif;
- text-transform:uppercase;letter-spacing:.05em;color:var(--muted);font-style:normal}
-
-/* ---- BEAD NOTATION -------------------------------------------------- */
-.bd{display:inline-flex;align-items:center;gap:.28rem;border:1px solid var(--line);
- border-radius:.35rem;padding:.02rem .34rem .02rem .05rem;background:var(--bg);
- font:.82rem/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;white-space:nowrap;
- border-left:3px solid var(--pc,var(--muted))}
-.bd.p0{--pc:var(--p0)} .bd.p1{--pc:var(--p1)} .bd.p2{--pc:var(--p2)}
-.bd.p3{--pc:var(--p3)} .bd.p4{--pc:var(--p4)}
-.bd .bp{font-weight:700;color:var(--pc);font-size:.78rem;padding-left:.3rem}
-.bd .bs{font-size:.82rem;opacity:.85}
-.bd.st-closed{opacity:.62}
-.bd.st-closed .bi{text-decoration:line-through;text-decoration-thickness:1px}
-.bd.st-in_progress{box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--accent) 45%,transparent)}
-.bd.st-deferred{opacity:.75;border-style:dashed}
-.bd .bi{color:var(--ink)}
-.bd .by{opacity:.75}
-.bd .bg{color:var(--accent);font-size:.75rem;font-weight:700}
-.bd.missing{border-left-color:var(--bad);background:var(--bad-bg)}
-.bd .bl{font:.8rem/1.5 system-ui,sans-serif;color:var(--muted);max-width:26rem;
- overflow:hidden;text-overflow:ellipsis}
-.legend{display:grid;grid-template-columns:repeat(auto-fit,minmax(13rem,1fr));gap:.5rem 1.2rem;
- font-size:.9rem;margin:.6rem 0}
-.legend div{display:flex;gap:.45rem;align-items:baseline}
-.legend b{font:.85rem ui-monospace,monospace;color:var(--accent);min-width:2.2rem}
-
-/* ---- distribution bars ---- */
-.dist{position:relative;text-align:right;white-space:nowrap}
-.dist span{position:absolute;left:0;top:.25rem;bottom:.25rem;width:var(--w);
- background:var(--accent);opacity:.18;border-radius:.2rem}
-.dist b{position:relative;font-variant-numeric:tabular-nums}
-
-/* ---- epic fill bars ---- */
-.fill{display:inline-block;width:9rem;height:.62rem;border-radius:99px;background:var(--code-bg);
- overflow:hidden;vertical-align:middle;border:1px solid var(--line)}
-.fill>span{display:block;height:100%;background:var(--ok)}
-.filln{font:.78rem ui-monospace,monospace;color:var(--muted);margin-left:.4rem;
- font-variant-numeric:tabular-nums}
-
-/* ---- matrix / heatmap ---- */
-table.mx td.c{text-align:right;font-variant-numeric:tabular-nums;position:relative}
-table.mx td.c i{position:absolute;left:.2rem;top:.25rem;bottom:.25rem;border-radius:.2rem;
- background:var(--accent);opacity:.16;font-style:normal}
-table.mx td.c b{position:relative}
-table.hm td.c{text-align:center;font-variant-numeric:tabular-nums;min-width:3.2rem}
-table.hm td,table.hm th{border:1px solid var(--line)}
-
-/* ---- charts ---- */
-.chart svg{width:100%;height:auto;max-height:7rem}
-.bar{fill:var(--accent);opacity:.75}
-.bar.closed{fill:var(--ok);opacity:.8}
-.ln{stroke-width:2;vector-effect:non-scaling-stroke}
-.ln.open{stroke:var(--accent)}
-.ln.ready{stroke:var(--ok)}
-.hit{fill:transparent}
-.spark{width:6.5rem;height:1.1rem;color:var(--accent);vertical-align:middle}
-.dag{height:auto;color:var(--muted);min-width:44rem;width:100%}
-.dag .dn rect{fill:var(--bg);stroke:var(--pc,var(--muted));stroke-width:1.4}
-.dag .dn.p0{--pc:var(--p0)} .dag .dn.p1{--pc:var(--p1)} .dag .dn.p2{--pc:var(--p2)}
-.dag .dn.p3{--pc:var(--p3)} .dag .dn.p4{--pc:var(--p4)}
-.dag .dn text{fill:var(--ink);font-family:ui-monospace,monospace}
-.dagwrap{overflow-x:auto;border:1px solid var(--line);border-radius:.5rem;padding:.4rem;background:var(--bg)}
-
-/* ---- trees / findings ---- */
-.tree,.tree ul{list-style:none;margin:0;padding-left:1.1rem}
-.tree li{position:relative;padding:.1rem 0 .1rem .8rem}
-.tree li::before{content:"";position:absolute;left:0;top:0;bottom:0;border-left:1px solid var(--line)}
-.tree li::after{content:"";position:absolute;left:0;top:.85rem;width:.65rem;border-top:1px solid var(--line)}
-.tree>li:last-child::before{bottom:auto;height:.85rem}
-.tree .meta{font-size:.82rem;opacity:.7;margin-left:.4rem}
-ul.findings{list-style:none;padding:0;margin:.5rem 0}
-ul.findings li{border-left:3px solid var(--line);padding:.4rem 0 .4rem .8rem;margin:.5rem 0;max-width:80ch}
-ul.findings li.sev-bad{border-left-color:var(--bad)}
-ul.findings li.sev-warn{border-left-color:var(--warn)}
-ul.findings li.sev-info{border-left-color:var(--info)}
-ul.findings li.sev-ok{border-left-color:var(--ok)}
-ul.findings b{display:block;margin-bottom:.15rem}
-.digest{display:flex;flex-wrap:wrap;gap:.45rem;margin:.4rem 0 .2rem}
-@media print{header.page,nav#toc,button,input.filter,.pop{display:none}
- .layout{grid-template-columns:1fr;max-width:none}
- section{break-inside:avoid;border:none;padding:0}
- details{border:none}details:not([open])>*:not(summary){display:revert}}
-"""
-
-JS = """
-function tgl(){const r=document.documentElement,
- d=(r.dataset.theme||(matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'))==='dark';
- r.dataset.theme=d?'light':'dark';try{localStorage.htmlreport_theme=r.dataset.theme}catch(e){}}
-function fs(d){const r=document.documentElement,
- cur=parseFloat(getComputedStyle(r).getPropertyValue('--fs'))||17,
- next=Math.min(24,Math.max(13,cur+d));
- r.style.setProperty('--fs',next+'px');try{localStorage.htmlreport_fs=next}catch(e){}}
-try{if(localStorage.htmlreport_fs)document.documentElement.style.setProperty('--fs',localStorage.htmlreport_fs+'px');
- if(localStorage.htmlreport_theme)document.documentElement.dataset.theme=localStorage.htmlreport_theme}catch(e){}
-(()=>{const t=document.getElementById('toc');if(!t)return;
-document.querySelectorAll('main h2, main h3').forEach(h=>{
- const s=h.closest('section')||h;if(!h.id)h.id=(h.textContent||'').trim().toLowerCase()
- .replace(/[^a-z0-9]+/g,'-').replace(/^-|-$/g,'');
- const a=document.createElement('a');a.href='#'+(h.tagName==='H2'&&s.id?s.id:h.id);
- a.textContent=h.textContent;if(h.tagName==='H3')a.className='h3';t.appendChild(a)})})();
-document.querySelectorAll('table').forEach(tb=>{
- tb.querySelectorAll('th:not(.nosort)').forEach((th,i)=>th.addEventListener('click',()=>{
- const dir=th.dataset.d=th.dataset.d==='a'?'d':'a';
- const val=td=>td&&td.dataset.v!==undefined?+td.dataset.v:(td?td.textContent.trim():'');
- [...tb.tBodies[0].rows].sort((r1,r2)=>{const a=val(r1.cells[i]),b=val(r2.cells[i]);
- const c=(typeof a=='number'&&typeof b=='number')?a-b:String(a).localeCompare(String(b));
- return dir==='a'?c:-c}).forEach(r=>tb.tBodies[0].appendChild(r))}))});
-function flt(inp,id){const q=inp.value.toLowerCase();
- document.querySelectorAll('#'+id+' tbody tr').forEach(r=>
- r.style.display=r.textContent.toLowerCase().includes(q)?'':'none')}
-(()=>{const U=[[31536e6,'y'],[2592e6,'mo'],[6048e5,'w'],[864e5,'d'],[36e5,'h'],[6e4,'m']];
-document.querySelectorAll('time.age').forEach(t=>{
- const d=new Date(t.dateTime);if(isNaN(d))return;const ms=Date.now()-d;
- let s='just now';for(const[u,n]of U){if(Math.abs(ms)>=u){s=Math.floor(Math.abs(ms)/u)+n+(ms<0?' ahead':' ago');break}}
- const pad=n=>String(n).padStart(2,'0');
- const iso=d.getFullYear()+'-'+pad(d.getMonth()+1)+'-'+pad(d.getDate())+' '+pad(d.getHours())+':'+pad(d.getMinutes());
- if(!t.textContent.trim())t.textContent=iso+' ('+s+')';else t.textContent+=' ('+s+')';
- t.title=d.toString();
- const budget=+(t.dataset.staleDays||0);
- if(budget&&ms>budget*864e5)t.classList.add('stale')})})();
-(()=>{let cur=null,pinned=false,timer=null;
-const kill=()=>{if(cur&&!pinned){cur.remove();cur=null}};
-const show=(host,html,title)=>{
- if(cur)cur.remove();
- const p=document.createElement('div');p.className='pop';
- p.innerHTML='\\u{1F4CC} '+(title?''+title+' ':'')+html;
- document.body.appendChild(p);
- const r=host.getBoundingClientRect(),pr=p.getBoundingClientRect();
- let top=r.bottom+8; if(top+pr.height>innerHeight-8)top=Math.max(8,r.top-pr.height-8);
- let left=Math.min(r.left,innerWidth-pr.width-8);
- p.style.top=top+'px';p.style.left=Math.max(8,left)+'px';
- p.querySelector('.pin').onclick=()=>{pinned=false;kill()};
- p.onmouseenter=()=>clearTimeout(timer);
- p.onmouseleave=()=>{timer=setTimeout(kill,220)};
- cur=p};
-const src=el=>{
- const t=el.querySelector(':scope > template.pop');
- if(t)return[t.innerHTML,el.dataset.popTitle||''];
- return null};
-document.querySelectorAll(':has(> template.pop)').forEach(el=>{
- const s=src(el);if(!s)return;
- if(el.tabIndex<0)el.tabIndex=0;
- const open=()=>{clearTimeout(timer);pinned=false;show(el,s[0],s[1])};
- el.addEventListener('mouseenter',()=>{clearTimeout(timer);timer=setTimeout(open,180)});
- el.addEventListener('mouseleave',()=>{clearTimeout(timer);timer=setTimeout(kill,220)});
- el.addEventListener('focus',open);
- el.addEventListener('click',e=>{
- if(el.tagName==='A'&&(e.metaKey||e.ctrlKey))return;
- e.preventDefault();if(!cur)open();pinned=!pinned});
-});
-addEventListener('keydown',e=>{if(e.key==='Escape'){pinned=false;kill()}});})();
-"""
-
-
-# --------------------------------------------------------------------------
-# render
-# --------------------------------------------------------------------------
-def render(facts: Facts, source: Path, generated: dt.datetime, schema_gap: dict[str, Any] | None = None) -> str:
- schema_gap = schema_gap or {}
- snaps = {
- "now": facts.snapshot(generated),
- "7d": facts.snapshot(generated - dt.timedelta(days=7)),
- "14d": facts.snapshot(generated - dt.timedelta(days=14)),
- }
- series = facts.daily_series()
- days_axis = [d for d, _, _ in series]
- insights = compute_insights(facts, schema_gap, snaps)
- sev_counts = Counter(i.sev for i in insights)
- out: list[str] = []
- add = out.append
- src = str(source)
-
- add('\n\n\n ')
- add(' ')
- add(f"Beads backlog — state of the graph — {generated:%Y-%m-%d} ")
- add("")
- add("\n")
- add('Beads backlog — state of the graph ')
- add(f'polylogue {facts.total:,} beads ')
- add(f'{generated:%Y-%m-%d} ')
- add('A− ')
- add('A+ ')
- add('◐ theme ')
- add('')
-
- # ---------------- summary ----------------
- add('Summary ')
- add('')
- add(f'generated ')
- add(
- f'data as of — a live backlog; re-run to refresh '
- )
- add(
- 'basis measured every count, matrix, '
- 'tree, and histogram · derived every trend '
- "(reconstructed from timestamps; deletions and reopen history are invisible) and every "
- "finding (each emitted by a condition checked against this data) "
- )
- add(f'source {esc(src)} ')
- add("regenerate devtools workspace beads-state-report --fresh --out <path> ")
- add(" ")
-
- tiles = [
- (
- f"{facts.total:,}",
- delta_chip(snaps["now"]["total"], snaps["7d"]["total"]),
- "beads, all time",
- "wc -l .beads/issues.jsonl",
- ),
- (
- f"{facts.open_total:,}",
- delta_chip(snaps["now"]["open"], snaps["7d"]["open"], up_is_bad=True),
- "open + in progress",
- "jq -r 'select(._type==\"issue\")|.status' .beads/issues.jsonl | grep -vc closed",
- ),
- (
- f"{facts.status['closed']:,}",
- delta_chip(snaps["now"]["closed"], snaps["7d"]["closed"]),
- "closed",
- "jq -r 'select(._type==\"issue\")|.status' .beads/issues.jsonl | grep -c closed",
- ),
- (
- f"{len(facts.ready):,}",
- delta_chip(snaps["now"]["ready"], snaps["7d"]["ready"]),
- "ready (no open blocker)",
- "bd ready --limit 5000 --json | jq length",
- ),
- (
- str(snaps["now"]["p0_open"]),
- delta_chip(snaps["now"]["p0_open"], snaps["7d"]["p0_open"], up_is_bad=True),
- "open P0",
- "jq -r 'select(._type==\"issue\")|select(.status!=\"closed\")|.priority' .beads/issues.jsonl | grep -c '^0$'",
- ),
- (
- f"{len(facts.epics)}",
- "",
- "beads with children",
- "jq -r '.dependencies[]?|select(.type==\"parent-child\")|.depends_on_id' "
- ".beads/issues.jsonl | sort -u | wc -l",
- ),
- ]
- add('')
- for value, delta, label, cmd in tiles:
- add(
- f'
{value}{delta} '
- f'{label} Δ7d '
- f"{qa(cmd, 'measured ' + generated.strftime('%Y-%m-%d'))}
"
- )
- add("
")
- add(
- f"The whole bead population, open and closed, as one artifact: {facts.total:,} beads "
- f"created over {facts.span_days} days ({facts.first_created} → {facts.last_created}), "
- f"{facts.status['closed']:,} already closed. Deltas on the tiles are against the state "
- "reconstructed 7 days ago. The findings below are the report's judgement layer — "
- "every one is emitted by a condition this generator checked against this file, so a claim "
- "that stops being true stops being printed.
"
- )
- add('")
- add(" ")
-
- # ---------------- pulse ----------------
- add('Pulse ')
- add(
- "Backlog state over its whole life, reconstructed per day from "
- "created_at/closed_at and edge timestamps "
- 'derived . '
- '■ open '
- '■ ready . '
- "The gap between the lines is the blocked share; the lines converging means the "
- "graph is getting less dependency-bound.
"
- )
- add('' + burnup_svg(series) + " ")
- add('metric ')
- add('14d ago 7d ago now ')
- add('Δ7d ')
- for key, label, up_bad in (
- ("open", "open beads", True),
- ("ready", "ready (no open blocker)", False),
- ("blocked", "blocked by an open bead", True),
- ("p0_open", "open P0", True),
- ):
- d = delta_chip(snaps["now"][key], snaps["7d"][key], up_is_bad=up_bad)
- add(
- f"{label} {snaps['14d'][key]} "
- f"{snaps['7d'][key]} {snaps['now'][key]} "
- f"{d} "
- )
- add("
")
- add(
- "Reconstruction caveats, stated once: a deleted bead or edge leaves no trace in the "
- "export, and a reopened bead's earlier closure is overwritten by its latest one. Both are "
- "rare enough here that the curve's shape is trustworthy; individual day values are "
- "±a few.
"
- )
- add(" ")
-
- # ---------------- notation ----------------
- add('Bead notation ')
- add(
- "One bead renders as one chip, everywhere in this report. Left bar and "
- "leading number are priority; then status, id, type glyph, and dependency "
- "degree. Hover any chip for the expanded reading.
"
- )
- samples = [str(facts.rows[0]["id"])]
- for wanted in ("epic", "bug", "feature"):
- for r in facts.rows:
- if r["issue_type"] == wanted and str(r["id"]) not in samples:
- samples.append(str(r["id"]))
- break
- add("" + " ".join(chip(facts, s) for s in samples[:4]) + "
")
- add('')
- add("
P0–P4 priority; also the left bar colour
")
- for glyph, name in STATUS_GLYPH.values():
- add(f"
{glyph} {name}
")
- for glyph, name in TYPE_GLYPH.values():
- add(f"
{glyph} {name}
")
- add("
↑n n open beads block this one
")
- add("
↓n this one blocks n open beads
")
- add("
struck id closed
")
- add("
blue outline in progress
")
- add("
dashed border deferred
")
- add("
")
- add(
- 'reading it A chip with a red left bar, a hollow '
- "circle, and ↓9 is an open P0 that nine other open beads are "
- "waiting on — the highest-leverage shape in the graph.
"
- )
- add(" ")
-
- # ---------------- shape ----------------
- add('Shape ')
- add(
- "The status × priority matrix, plus per-tier closure rate and median lead "
- "time — the fastest read on whether the priority scale is load-bearing. The "
- "computed verdict is in Findings .
"
- )
- add("Status × priority ")
- add('')
- status_cols = facts.statuses_present
- head = "".join(f"{esc(STATUS_GLYPH.get(s, ('?', s))[1])} " for s in status_cols)
- add(
- f"priority {head}total closed % median lead (days) "
- )
- peak = max(facts.matrix.values()) or 1
- for p in range(5):
- row = [f'P{p} ']
- for st in status_cols:
- n = facts.matrix.get((st, p), 0)
- row.append(f'{n:,} ')
- total_p = facts.priority[p]
- med = _median(facts.lead_by_priority[p])
- row.append(f'{total_p:,} ')
- row.append(f'{facts.rate(p):.0%} ')
- row.append(f'{med:.2f} ')
- add("".join(row) + " ")
- add("
")
-
- add("Type ")
- add('type beads ')
- add("share closed % ")
- peak_t = max(facts.itype.values()) or 1
- for tname, n in facts.itype.most_common():
- closed = sum(1 for r in facts.rows if r["issue_type"] == tname and r["status"] == "closed")
- glyph = TYPE_GLYPH.get(tname, ("?", tname))[0]
- add(
- f"{glyph} {esc(tname)} "
- f' '
- f"{n:,} "
- f'{100 * n / facts.total:.1f}% '
- f'{closed / n:.0%} '
- )
- add("
")
- add(" ")
-
- # ---------------- structure ----------------
- add('Structure ')
- add(
- "Parents ranked by child count, from parent-child edges (the dotted "
- "id is not the parent link — the two disagree for "
- f"{len(facts.id_mismatch)} beads and {len(facts.id_orphan)} dotted beads have no edge "
- "at all; both are counted in Health). The trend column is each epic's open-children "
- 'count over the backlog\'s life derived — '
- "a falling line is a draining program, a flat high line is a parked one, a rising "
- "line is a program still being decomposed.
"
- )
- add('parent title ')
- add('progress trend children open ')
- for e in facts.epics[:24]:
- eid = str(e["id"])
- spark = sparkline_svg(facts.epic_open_series(eid, days_axis), label=f"{eid} open children")
- add(
- f"{chip(facts, eid)} "
- f"{esc(str(e['title'])[:74])} "
- f''
- f"{fill_bar(int(e['open']), int(e['n']))} "
- f"{spark} "
- f'{e["n"]} '
- f'{e["open"]} '
- )
- add("
")
-
- # the two computed extremes: most-finished and least-started large parents
- big = [e for e in facts.epics if int(e["n"]) >= 8]
- if big:
- most_done = min(big, key=lambda e: int(e["open"]) / int(e["n"]))
- least_started = max(big, key=lambda e: int(e["open"]) / int(e["n"]))
- add("Trees: the two extremes ")
- add(
- f"Computed from the table above: the most-finished large parent "
- f"({chip(facts, str(most_done['id']))}, {int(most_done['n']) - int(most_done['open'])} of "
- f"{most_done['n']} children closed) against the least-started "
- f"({chip(facts, str(least_started['id']))}, {least_started['open']} of "
- f"{least_started['n']} still open). A flat backlog list renders those identically; "
- "the fill bars are why this section exists.
"
- )
- for e in (most_done, least_started):
- eid = str(e["id"])
- if eid not in facts.issues:
- continue
- rec = facts.issues[eid]
- add(
- f"{chip(facts, eid)} {esc(str(rec['title'])[:80])} "
- + tree_html(facts, eid)
- + " "
- )
- add("All other parents with 8+ children ")
- skip = {str(most_done["id"]), str(least_started["id"])}
- for e in big:
- if str(e["id"]) in skip:
- continue
- add(
- f"{chip(facts, str(e['id']))} {esc(str(e['title'])[:80])} "
- f" {fill_bar(int(e['open']), int(e['n']))} "
- + tree_html(facts, str(e["id"]))
- + " "
- )
- add(" ")
- add(" ")
-
- # ---------------- topology ----------------
- add('Topology ')
- ready_pct = f"{len(facts.ready) / facts.open_total:.0%}" if facts.open_total else "n/a"
- add(
- f"The blocks graph: {facts.dep_types['blocks']:,} edges over "
- f"{facts.open_total:,} open beads, of which {len(facts.ready):,} are ready "
- f"({ready_pct}) and {len(facts.blocked)} wait on an open blocker.
"
- )
- add('')
- for value, label, cmd in [
- (
- f"{facts.dep_types['blocks']:,}",
- "blocks edges",
- "jq -r '.dependencies[]?|.type' .beads/issues.jsonl | sort | uniq -c",
- ),
- (f"{len(facts.ready):,}", "ready", "bd ready --limit 5000 --json | jq length"),
- (f"{len(facts.blocked)}", "blocked by an open bead", "bd blocked --json | jq length"),
- (f"{len(facts.cycles)}", "cycles in blocks", "DFS colouring over the blocks graph (this generator)"),
- ]:
- add(
- f'
{value} {label} '
- f"{qa(cmd, 'measured')}
"
- )
- add("
")
-
- frontier = facts.parallel_frontier()
- if len(frontier) >= 2:
- add("The parallel frontier ")
- add(
- "Computed: the largest programs whose open subtrees occupy disjoint "
- "components of the blocks graph — no dependency path of any "
- "length connects them, so they can run as parallel lanes with zero coordination "
- "on ordering. Greedy by open-descendant count.
"
- )
- add('program title ')
- add("open descendants open P0–P2 ")
- for c in frontier:
- add(
- f"{chip(facts, str(c['id']))} {esc(str(c['title'])[:70])} "
- f'{c["open_desc"]} '
- f'{c["urgent"]} '
- )
- add("
")
-
- add("Relation vocabulary ")
- add('relation edges ')
- add("first written last written ")
- first_last: dict[str, tuple[str, str]] = {}
- for _, _, kind, created in facts.edges:
- when = created[:10]
- if not when:
- continue
- lo, hi = first_last.get(kind, (when, when))
- first_last[kind] = (min(lo, when), max(hi, when))
- peak_r = max(facts.dep_types.values()) or 1
- for kind, n in facts.dep_types.most_common():
- lo, hi = first_last.get(kind, ("", ""))
- flag = ""
- if kind in ("relates-to", "related"):
- flag = {
- "split": ' split vocab ',
- "recurring": ' unified, then recurred ',
- "clean": ' unified ',
- }[facts.vocab_state]
- add(
- f"{esc(kind)}{flag} "
- f'{n:,} '
- f"{esc(lo)} {esc(hi)} "
- )
- add("
")
- if facts.retyped_spike:
- add(
- f"A bulk re-type is visible in the timestamps: {facts.retyped_spike:,} "
- f"relates-to edges carry {esc(facts.retyped_spike_day)} as "
- "their created_at — converted edges lose their original assertion "
- "dates, so any “when were associations asserted?” analysis must treat that "
- 'date as an artifact spike, not a real burst derived .
'
- )
- if facts.related_recurrence:
- add(
- "Post-repair recurrence, exactly: the edge(s) below were written after "
- "the newest re-typed edge, proving the write path is still unconstrained.
"
- )
- add('from relates to ')
- add("created_at ")
- for src_id, dst_id, ts in facts.related_recurrence:
- add(f"{chip(facts, src_id)} {chip(facts, dst_id)} {esc(ts)} ")
- add("
")
-
- add("Highest-leverage blockers ")
- add(
- "Each row releases a fan-out no other bead does; if the graph is "
- "dependency-bound these are the lever, and if it is throughput-bound they are "
- "merely the tidiest finish-first candidates.
"
- )
- add('bead title ')
- add("blocks (open) ")
- for n, bid in facts.top_blockers[:20]:
- add(
- f"{chip(facts, bid)} {esc(str(facts.issues[bid]['title'])[:80])} "
- f'{n} '
- )
- add("
")
-
- cluster = facts.densest_cluster()
- core = facts.cluster_core(cluster)
- if core:
- add("Densest blocking cluster ")
- add(
- f"Rendering all {facts.total:,} beads as a graph produces a hairball, so this is "
- f"a slice: the largest connected component of the open-only blocks graph "
- f"holds {len(cluster)} beads, and this is its {len(core)} -node core "
- "(members with ≥3 neighbours inside it; the dropped nodes are single-edge leaves). "
- "Arrows point blocker → blocked; columns are longest-path depth, so leftmost is "
- "furthest upstream. Hover a node for its title.
"
- )
- add('' + cluster_svg(facts, core) + "
")
- add(" ")
-
- # ---------------- time ----------------
- add('Time ')
- peak_day, peak_n = max(facts.created_day.items(), key=lambda kv: kv[1])
- add(
- f"Filing is spiky ({peak_n} beads on {esc(peak_day)}, the busiest day, against a "
- f"median of {_median(list(facts.created_day.values())):.0f}/day) — the signature "
- "of audit-lane batch filing rather than continuous discovery. Closure runs at a median "
- f"of {_median(list(facts.closed_day.values())):.0f}/day.
"
- )
- add('')
- add(
- histogram_svg(
- facts.days,
- [("created", facts.created_day, "created"), ("closed", facts.closed_day, "closed")],
- )
- )
- add(
- f"beads per day, {facts.first_created} → {facts.last_created} "
- f'· ■ created '
- f'■ closed · '
- f'measured '
- )
- add(" ")
-
- (rc, rx), (pc, px) = facts.win_recent, facts.win_prior
- add('window ')
- add('created closed net ')
- for name, created_n, closed_n in (
- (f"prior {VELOCITY_WINDOW_DAYS}d", pc, px),
- (f"last {VELOCITY_WINDOW_DAYS}d", rc, rx),
- ):
- cls = "bad" if created_n - closed_n > 0 else "ok"
- add(
- f'{name} {created_n} {closed_n} '
- f'{created_n - closed_n:+d} '
- )
- add("
")
-
- add("Age × priority of open work ")
- add(
- "Where open work sits in the age-urgency plane. Mass in the bottom-left "
- "(old, urgent) is the shelf to triage first; mass in the bottom-right (old, P3/P4) "
- "is parking, which is fine as long as it was chosen.
"
- )
- add(heatmap_html(facts))
- add(
- f"Median open bead is {_median(facts.age_open):.0f} days old; the oldest is "
- f"{max(facts.age_open):.0f} days — against a tracker that is itself only "
- f"{facts.span_days} days old.
"
- )
- add(" ")
-
- # ---------------- health ----------------
- add('Health ')
- add(
- f"{len(HEALTH_CHECKS)} mechanical checks over the graph. These are a "
- "review queue , not a batch-fix list — especially the "
- "“open parent, all children closed” row, where children closing means the "
- "parent is ready for adjudication against its own acceptance criteria, never that it "
- "is done.
"
- )
- add('check count ')
- add("meaning ")
- for cls, name, attr, meaning in HEALTH_CHECKS:
- n = len(getattr(facts, attr))
- badge = f'{n} '
- add(f"{name} {badge} {meaning} ")
- add("
")
-
- if facts.dangling:
- add("Dangling references ")
- add(
- "A genuine data bug, not a judgement call: these edges point at ids that "
- "resolve to nothing, so the blocking intent behind them is silently absent from "
- "every query.
"
- )
- add('from points at ')
- add("relation ")
- for a, b, kind in facts.dangling:
- add(
- f"{chip(facts, a)} "
- f'{esc(b)} '
- f'✘ {esc(kind)} '
- )
- add("
")
-
- if facts.stale_claims:
- add("Stale in-progress claims ")
- add('bead title ')
- add("days since update ")
- for bid, days_stale in facts.stale_claims:
- add(
- f"{chip(facts, bid)} {esc(str(facts.issues[bid]['title'])[:76])} "
- f'{days_stale:.0f} '
- )
- add("
")
-
- add("Review queue: open parents whose children are all closed ")
- add('parent title ')
- add('children has own AC ')
- for pid in facts.open_parent_all_closed:
- rec = facts.issues[pid]
- has_ac = bool(str(rec.get("acceptance_criteria") or "").strip())
- flag = 'yes — read it ' if has_ac else 'no '
- add(
- f"{chip(facts, pid)} {esc(str(rec['title'])[:76])} "
- f'{len(facts.children[pid])} '
- f"{flag} "
- )
- add("
")
-
- if facts.dup_titles:
- add("Duplicate titles ")
- add('title ')
- add('beads ')
- for title, ids in facts.dup_titles:
- add(f"{esc(title[:86])} " + " ".join(chip(facts, i) for i in ids) + " ")
- add("
")
-
- # schema gap: a live archive/code divergence fact, rendered when measurable
- if schema_gap.get("available"):
- add("Archive/code schema gap ")
- add(
- f"The live archive is at index-schema v{schema_gap['live_version']} ; "
- f"origin/master declares v{schema_gap['declared']} . "
- f"{len(schema_gap['blockers'])} intervening version(s) are "
- "SEMANTIC_REPARSE — no clone-safe SQL fast-forward exists, so every "
- "merged fix at those versions is inert until "
- "polylogue ops reset --index && polylogued run. A closed bead "
- "here can still describe a live bug against the data an operator queries right now.
"
- )
- add('')
- for value, label, cmd in [
- (
- f"v{schema_gap['live_version']}",
- "live archive schema",
- f"sqlite3 -readonly {schema_gap.get('live_path', '
/index.db')} 'PRAGMA user_version;'",
- ),
- (
- f"v{schema_gap['declared']}",
- "origin/master declares",
- "git show origin/master:polylogue/storage/sqlite/archive_tiers/index.py | grep INDEX_SCHEMA_VERSION",
- ),
- (
- str(len(schema_gap["blockers"])),
- "SEMANTIC_REPARSE versions blocking fast-forward",
- "git show origin/master:polylogue/storage/sqlite/lifecycle.py",
- ),
- ]:
- add(
- f'{esc(value)} {esc(label)} '
- f"{qa(cmd, 'measured ' + generated.strftime('%Y-%m-%d'))}
"
- )
- add(" ")
- if schema_gap["blockers"]:
- add('version ')
- add('delta class(es) ')
- for v in range(schema_gap["live_version"] + 1, schema_gap["declared"] + 1):
- classes = schema_gap["blocker_notes"].get(v, ())
- cls_badges = (
- " ".join(
- f'{esc(c)} '
- for c in classes
- )
- or 'undeclared '
- )
- add(f"v{v} {cls_badges} ")
- add("
")
- else:
- add(
- 'schema gap not measured Needs both '
- "git show origin/master:… and a readable live archive at the "
- "operator's configured archive root; at least one was unavailable, so the tiles are "
- "omitted rather than guessed.
"
- )
- add(" ")
-
- # ---------------- themes ----------------
- add('Themes ')
- add(
- f"Two independent readings of where open work concentrates, because neither alone is "
- f"trustworthy: the label view folds the repository's own area:* labels "
- f"through an explicit synonym map (covers {facts.labelled:,} of {facts.total:,} beads and "
- f"says nothing about the rest), and the keyword view classifies every bead from title and "
- "description (full coverage, will misfile loose titles). Where the two agree, the "
- "concentration is real.
"
- )
- add('subsystem ')
- add(
- "open (labels) closed (labels) open (keywords) "
- "closed (keywords) "
- )
- names = sorted(set(facts.by_label_theme) | set(facts.by_kw_theme))
- peak_o = (
- max(
- (facts.by_label_theme[n]["open"] + facts.by_label_theme[n]["in_progress"] for n in names),
- default=1,
- )
- or 1
- )
- for name in names:
- lab = facts.by_label_theme.get(name, Counter())
- kw = facts.by_kw_theme.get(name, Counter())
- lab_open = lab["open"] + lab["in_progress"]
- kw_open = kw["open"] + kw["in_progress"]
- add(
- f"{esc(name)} "
- f'{lab_open} '
- f'{lab["closed"]} '
- f'{kw_open} '
- f'{kw["closed"]} '
- )
- add("
")
- add("The synonym map used to fold area:* labels ")
- add('subsystem ')
- add('folded area labels ')
- for canon, suffixes in SUBSYSTEMS.items():
- add(f"{esc(canon)} " + " ".join(f"area:{esc(s)}" for s in suffixes) + " ")
- add("
")
- add(
- "This map is a proposal written by hand, not something the repository declares. "
- "Disagreeing with a row changes the table above it.
"
- )
- add(" ")
- add("Raw area:* labels, top 30 ")
- add('label beads ')
- add("")
- area_counts = [(x, facts.labels[x]) for x in facts.area_labels]
- area_counts.sort(key=lambda kv: (-kv[1], kv[0]))
- peak_l = area_counts[0][1] if area_counts else 1
- for name, n in area_counts[:30]:
- add(
- f"{esc(name)} "
- f'{n} '
- )
- add("
")
- add(" ")
-
- # ---------------- dated review passes ----------------
- strict_total = sum(facts.verdict_counts.values())
- loose_total = sum(facts.loose_counts.values())
- if strict_total or facts.reconciliation:
- add('Dated review passes ')
- add(
- "Two hand-verification passes left machine-parseable markers in bead notes; this "
- "generator extracts them mechanically. They are dated evidence — "
- "ground truth as of the day each pass ran, ageing at the speed the code moves, not "
- "recomputed facts.
"
- )
- if strict_total:
- add('The verified subset pass of 2026-07-31 ')
- add(
- f"{strict_total} beads carry a machine-parseable "
- "VERIFICATION (…): STALE|PARTIAL|LIVE verdict written by a human "
- f"reviewer — {facts.verdict_counts['LIVE']} LIVE / "
- f"{facts.verdict_counts['PARTIAL']} PARTIAL / {facts.verdict_counts['STALE']} STALE. "
- "It is the only subset of this backlog where “is this claim still true?” "
- "was answered by inspection rather than assumed. Preserve it as a labelled "
- "evaluation set.
"
- )
- add(
- f"Extraction gap, stated rather than papered over: the operator's own count of "
- f"the pass is {OPERATOR_VERIFIED_COUNT} beads; the strict pattern finds "
- f"{strict_total}, and relaxing to any bare verdict token finds {loose_total} "
- f"({facts.loose_counts['LIVE']}/{facts.loose_counts['PARTIAL']}/"
- f"{facts.loose_counts['STALE']}), which brackets the figure but includes incidental "
- "prose. The difference is verdicts phrased outside the parseable form — a "
- "review this valuable should write its verdict one way, every time.
"
- )
- add(' ')
- add('bead verdict ')
- add("sweep title ")
- badge_of = {"LIVE": "ok", "PARTIAL": "warn", "STALE": "bad"}
- for bid, verdict, _status, sweep in sorted(facts.verdicts, key=lambda v: (v[1], v[0])):
- add(
- f"{chip(facts, bid)} "
- f'{verdict} '
- f"{esc(sweep[:34])} "
- f"{esc(str(facts.issues[bid]['title'])[:70])} "
- )
- add("
")
-
- if facts.reconciliation:
- add('P0 reconciliation pass of 2026-07-31 ')
- add(
- f"A hand-verified pass over the P0 shelf, read against origin/master "
- "and the live archive. Its sharpest product is a split a flat status field cannot "
- "express: “open” work with no code fix yet versus work that is "
- "done and merged but inert behind the archive/code schema gap (see Health). "
- f"Marker coverage: {facts.reconciliation_anchored} beads carry the anchor; the "
- f"pass's own summary covered {RECONCILIATION_EXPECTED}.
"
- )
- add('')
- for value, label in [
- (str(facts.reconciliation_counts["FIXED-AND-EFFECTIVE"]), "FIXED-AND-EFFECTIVE — closed"),
- (str(facts.reconciliation_counts["FIXED-PENDING-REBUILD"]), "FIXED-PENDING-REBUILD"),
- (str(facts.reconciliation_counts["FIXED-PENDING-DEPLOY"]), "FIXED-PENDING-DEPLOY"),
- (str(facts.reconciliation_counts["MISFRAMED"]), "MISFRAMED — demoted"),
- (str(facts.reconciliation_counts["GENUINELY OPEN"]), "GENUINELY OPEN"),
- ]:
- add(f'
{value} {label}
')
- add("
")
- rebuild_rows = [
- (bid, verdict, snippet)
- for bid, verdict, snippet in facts.reconciliation
- if verdict in ("FIXED-PENDING-REBUILD", "FIXED-PENDING-DEPLOY")
- ]
- if rebuild_rows:
- add(
- "The rebuild-blocked set: merged, confirmed inert by direct query, needing no "
- "further engineering — the honest measure of how much apparent open work is "
- "actually done.
"
- )
- add('bead title ')
- add('verdict evidence ')
- for bid, verdict, snippet in sorted(rebuild_rows, key=lambda t: (t[1], t[0])):
- title = esc(str(facts.issues[bid]["title"])[:70]) if bid in facts.issues else ""
- add(
- f"{chip(facts, bid)} {title} "
- f'{esc(verdict)} '
- f"{esc(snippet[-220:])} "
- )
- add("
")
- add("Full reconciliation table ")
- add(' ')
- add('bead title ')
- add("verdict ")
- rc_badge = {
- "FIXED-AND-EFFECTIVE": "ok",
- "FIXED-PENDING-REBUILD": "warn",
- "FIXED-PENDING-DEPLOY": "warn",
- "MISFRAMED": "info",
- "GENUINELY OPEN": "bad",
- }
- for bid, verdict, _snippet in sorted(facts.reconciliation, key=lambda t: (t[1], t[0])):
- title = esc(str(facts.issues[bid]["title"])[:74]) if bid in facts.issues else ""
- add(
- f"{chip(facts, bid)} {title} "
- f'{esc(verdict)} '
- )
- add("
")
- if strict_total or facts.reconciliation:
- add(" ")
-
- # ---------------- findings ----------------
- add('Findings ')
- add(
- "The judgement layer, ordered by severity. Every entry was emitted by a condition "
- "this generator checked against the input file at render time — there is no "
- "hand-authored claim here that can silently outlive its evidence. "
- 'measured marks direct counts; '
- 'derived marks reconstructions and computed '
- "verdicts.
"
- )
- add('')
- for ins in insights:
- chips = (" " + " ".join(chip(facts, c) for c in ins.chips)) if ins.chips else ""
- add(
- f'{ins.sev} '
- f'{ins.title} {ins.ev} {ins.body}{chips} '
- )
- add(" ")
- add(" ")
-
- # ---------------- method ----------------
- add('Method & regeneration ')
- add(
- "Everything numeric on this page is computed by the generator named below from a "
- "single input file; nothing was transcribed. Interpretation is computed too: findings "
- "are conditional generators, not prose — if a number here disagrees with "
- "bd, the export is stale, not the arithmetic; regenerate with "
- "--fresh.
"
- )
- add("Provenance ")
- add('part of the report ')
- add('origin ')
- for part, origin in [
- ("every count, percentage, matrix cell, median, heatmap cell", "measured from the JSONL"),
- ("epic trees, fill bars, dependency degree on each chip", "measured (parent-child + blocks edges)"),
- ("per-day histogram, velocity windows", "measured"),
- (
- "pulse snapshots, burnup, epic sparklines, 7d deltas",
- "derived (timestamp reconstruction; deletions invisible)",
- ),
- (
- "ready / blocked / cycles / densest cluster / parallel frontier",
- "measured (graph traversal in the generator)",
- ),
- ("health checks and review queues", "measured"),
- ("keyword theme classification", "measured, using a hand-written keyword list"),
- ("area-label folding", "measured, using a hand-written synonym map"),
- ("verdict + reconciliation marker extraction", "measured by regex over notes and comments"),
- ("schema gap (live vs origin/master)", "measured: git show + read-only PRAGMA"),
- ("findings", "derived: conditional generators over all of the above"),
- ("section framing sentences and the notation legend", "authored, deliberately data-free"),
- (
- f"two constants from dated passes ({OPERATOR_VERIFIED_COUNT}, {RECONCILIATION_EXPECTED})",
- "operator-supplied, provenance attached where used",
- ),
- ]:
- cls = "todo" if origin.startswith(("authored", "operator")) else "info"
- add(f'{esc(part)} {esc(origin)} ')
- add("
")
- add("Regenerate ")
- add(
- "cd /realm/project/polylogue\n"
- "devtools workspace beads-state-report --fresh \\\n"
- f" --out {esc(str(source.parent))}/beads-state.html "
- )
- add(
- "--fresh re-runs bd export -o .beads/issues.jsonl "
- "first. Without it the report describes whatever the file last held, which after "
- "any uncommitted bd mutation is not the live state. The exported "
- "file is contended across sessions and should not be committed as part of "
- "generating a report.
"
- )
- add(" ")
-
- add(" ")
- add(
- f"generated by devtools workspace beads-state-report on "
- f"{generated:%Y-%m-%d %H:%M} from {esc(src)} · {facts.total:,} beads, "
- f"{len(facts.edges):,} dependency edges "
- )
- add("")
- add("\n")
- return "\n".join(out)
-
-
-# --------------------------------------------------------------------------
-# entry point
-# --------------------------------------------------------------------------
-def json_payload(facts: Facts, schema_gap: dict[str, Any], generated: dt.datetime) -> dict[str, Any]:
- snaps = {
- "now": facts.snapshot(generated),
- "7d": facts.snapshot(generated - dt.timedelta(days=7)),
- "14d": facts.snapshot(generated - dt.timedelta(days=14)),
- }
- insights = compute_insights(facts, schema_gap, snaps)
- return {
- "generated": generated.isoformat(),
- "total": facts.total,
- "status": dict(facts.status),
- "priority": {str(k): v for k, v in facts.priority.items()},
- "open_total": facts.open_total,
- "ready": len(facts.ready),
- "blocked": len(facts.blocked),
- "cycles": facts.cycles,
- "dangling": [list(d) for d in facts.dangling],
- "open_parent_all_closed": facts.open_parent_all_closed,
- "stale_claims": [[bid, round(days, 2)] for bid, days in facts.stale_claims],
- "aged_urgent": facts.aged_urgent,
- "dup_titles": [[t, ids] for t, ids in facts.dup_titles],
- "snapshots": snaps,
- "velocity": {
- "recent": {"created": facts.win_recent[0], "closed": facts.win_recent[1]},
- "prior": {"created": facts.win_prior[0], "closed": facts.win_prior[1]},
- "window_days": VELOCITY_WINDOW_DAYS,
- },
- "parallel_frontier": [
- {"id": c["id"], "open_desc": c["open_desc"], "urgent": c["urgent"]} for c in facts.parallel_frontier()
- ],
- "verdicts": {"strict": dict(facts.verdict_counts), "loose": dict(facts.loose_counts)},
- "reconciliation": facts.reconciliation,
- "vocab_state": facts.vocab_state,
- "schema_gap": schema_gap,
- "insights": [{"sev": i.sev, "title": i.title, "body": i.body, "ev": i.ev} for i in insights],
- }
-
-
-def main(argv: list[str] | None = None) -> int:
- root = _get_root()
- parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
- parser.add_argument("path", nargs="?", default=None, help="issues.jsonl (default: .beads/issues.jsonl)")
- parser.add_argument("--out", default=None, help="write HTML here (default: .local/beads-state.html)")
- parser.add_argument("--fresh", action="store_true", help="run `bd export` before reading")
- parser.add_argument("--json", action="store_true", help="print the computed facts as JSON instead of HTML")
- args = parser.parse_args(argv)
-
- path = Path(args.path) if args.path else root / ".beads/issues.jsonl"
- if args.fresh:
- subprocess.run(["bd", "export", "-o", str(path)], check=True, capture_output=True)
- if not path.exists():
- print(f"no such file: {path}", file=sys.stderr)
- return 1
-
- issues, edges = load(path)
- if not issues:
- print(f"no issues parsed from {path}", file=sys.stderr)
- return 1
- now = dt.datetime.now(dt.UTC)
- facts = Facts(issues, edges, now)
- schema_gap = schema_gap_facts(root)
-
- if args.json:
- print(json.dumps(json_payload(facts, schema_gap, now), indent=2, sort_keys=True))
- return 0
-
- out = Path(args.out) if args.out else root / ".local/beads-state.html"
- out.parent.mkdir(parents=True, exist_ok=True)
- out.write_text(render(facts, path, now, schema_gap), encoding="utf-8")
- print(f"wrote {out} ({out.stat().st_size:,} bytes) from {facts.total:,} beads")
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/benchmark_campaign.py b/devtools/benchmark_campaign.py
deleted file mode 100644
index 9fbd2ec4d0..0000000000
--- a/devtools/benchmark_campaign.py
+++ /dev/null
@@ -1,415 +0,0 @@
-"""Run and compare benchmark campaigns with durable artifacts."""
-
-from __future__ import annotations
-
-import argparse
-import json
-import subprocess
-import tempfile
-import time
-from collections.abc import Iterable, Mapping
-from dataclasses import asdict, dataclass, field
-from datetime import UTC, datetime
-from pathlib import Path
-from typing import TypedDict
-
-from devtools import repo_root as _get_root
-from polylogue.core.json import JSONDocument, json_document
-from polylogue.scenarios import ExecutionKind, ScenarioMetadata, pytest_execution, run_execution
-
-from .authored_scenario_catalog import get_authored_scenario_catalog
-from .benchmark_catalog import BenchmarkCampaignEntry
-from .benchmark_results import (
- BenchmarkStat,
- BenchmarkStatRecord,
- benchmark_stat_record,
- parse_pytest_benchmark_stats,
-)
-
-ROOT = _get_root()
-ARTIFACT_DIR = Path(".local/benchmark-campaigns")
-STATUS_IGNORE_PREFIXES = (f"{ARTIFACT_DIR.as_posix()}/",)
-DEFAULT_WARN_PCT = 10.0
-DEFAULT_FAIL_PCT = 20.0
-CAMPAIGNS = get_authored_scenario_catalog().benchmark_campaign_index()
-
-
-class RegressionRecord(TypedDict):
- fullname: str
- baseline_mean: float
- current_mean: float
- delta_pct: float
-
-
-@dataclass(frozen=True)
-class Regression:
- fullname: str
- baseline_mean: float
- current_mean: float
- delta_pct: float
-
-
-@dataclass(frozen=True)
-class CampaignResult:
- campaign: str
- description: str
- commit: str
- worktree_dirty: bool
- created_at: str
- workspace: str
- command: list[str]
- tests: list[str]
- notes: list[str]
- benchmark_count: int
- runtime_seconds: float
- exit_code: int
- machine_info: JSONDocument
- benchmarks: list[BenchmarkStatRecord]
- slowest: list[BenchmarkStatRecord]
- compare_to: str | None
- warn_pct: float
- fail_pct: float
- regressions: list[RegressionRecord]
- worst_regression_pct: float | None
- origin: str = "authored"
- path_targets: list[str] = field(default_factory=list)
- artifact_targets: list[str] = field(default_factory=list)
- operation_targets: list[str] = field(default_factory=list)
- maintenance_targets: list[str] = field(default_factory=list)
- tags: list[str] = field(default_factory=list)
-
-
-def _git_output(*args: str) -> str:
- return subprocess.check_output(["git", *args], cwd=ROOT, text=True).strip()
-
-
-def _worktree_dirty() -> bool:
- status = subprocess.check_output(["git", "status", "--short"], cwd=ROOT, text=True)
- for line in status.splitlines():
- path = line[3:]
- if any(path.startswith(prefix) for prefix in STATUS_IGNORE_PREFIXES):
- continue
- if path:
- return True
- return False
-
-
-def _default_artifact_path(campaign: str, suffix: str) -> Path:
- date = datetime.now(UTC).strftime("%Y-%m-%d")
- return ROOT / ARTIFACT_DIR / f"{date}-{campaign}.{suffix}"
-
-
-def _number_value(value: object, *, field: str) -> str | int | float:
- if isinstance(value, bool) or not isinstance(value, (str, int, float)):
- raise ValueError(f"Benchmark payload field {field!r} is not numeric: {value!r}")
- return value
-
-
-def _regression_record(regression: Regression) -> RegressionRecord:
- return {
- "fullname": regression.fullname,
- "baseline_mean": regression.baseline_mean,
- "current_mean": regression.current_mean,
- "delta_pct": regression.delta_pct,
- }
-
-
-def _load_campaign_result(path: Path) -> CampaignResult:
- return CampaignResult(**json.loads(path.read_text()))
-
-
-def _compare_results(current: list[BenchmarkStat], baseline: Iterable[Mapping[str, object]]) -> list[Regression]:
- baseline_map = {str(item["fullname"]): item for item in baseline}
- regressions: list[Regression] = []
- for bench in current:
- previous = baseline_map.get(bench.fullname)
- if previous is None:
- continue
- baseline_mean = float(_number_value(previous["mean"], field="mean"))
- if baseline_mean <= 0:
- continue
- delta_pct = ((bench.mean - baseline_mean) / baseline_mean) * 100.0
- regressions.append(
- Regression(
- fullname=bench.fullname,
- baseline_mean=baseline_mean,
- current_mean=bench.mean,
- delta_pct=delta_pct,
- )
- )
- regressions.sort(key=lambda item: item.delta_pct, reverse=True)
- return regressions
-
-
-def _render_markdown(result: CampaignResult) -> str:
- lines = [
- f"# Benchmark Campaign: {result.campaign}",
- "",
- f"- Description: {result.description}",
- f"- Commit: `{result.commit}`",
- f"- Worktree dirty: {'yes' if result.worktree_dirty else 'no'}",
- f"- Created: `{result.created_at}`",
- f"- Runtime: `{result.runtime_seconds:.2f}s`",
- f"- Command: `{' '.join(result.command)}`",
- f"- Tests: `{', '.join(result.tests)}`",
- f"- Benchmarks: `{result.benchmark_count}`",
- f"- Warn threshold: `{result.warn_pct:.1f}%`",
- f"- Fail threshold: `{result.fail_pct:.1f}%`",
- "",
- ]
- if (
- result.path_targets
- or result.artifact_targets
- or result.operation_targets
- or result.maintenance_targets
- or result.tags
- ):
- lines.extend(["## Scenario Metadata", ""])
- lines.append(f"- Origin: `{result.origin}`")
- if result.path_targets:
- lines.append(f"- Path targets: `{', '.join(result.path_targets)}`")
- if result.artifact_targets:
- lines.append(f"- Artifact targets: `{', '.join(result.artifact_targets)}`")
- if result.operation_targets:
- lines.append(f"- Operation targets: `{', '.join(result.operation_targets)}`")
- if result.maintenance_targets:
- lines.append(f"- Maintenance targets: `{', '.join(result.maintenance_targets)}`")
- if result.tags:
- lines.append(f"- Tags: `{', '.join(result.tags)}`")
- lines.append("")
- lines.extend(
- [
- "## Slowest Benchmarks",
- "",
- "| Benchmark | Mean (s) | Median (s) | Ops/s | Rounds |",
- "| --- | ---: | ---: | ---: | ---: |",
- ]
- )
- for bench in result.slowest:
- ops = "-" if bench["ops"] is None else f"{bench['ops']:.2f}"
- lines.append(
- f"| `{bench['fullname']}` | {bench['mean']:.6f} | {bench['median']:.6f} | {ops} | {bench['rounds']} |"
- )
- if result.regressions:
- lines.extend(
- [
- "",
- "## Largest Regressions vs Baseline",
- "",
- "| Benchmark | Delta % | Baseline Mean (s) | Current Mean (s) |",
- "| --- | ---: | ---: | ---: |",
- ]
- )
- for regression in result.regressions[:10]:
- lines.append(
- f"| `{regression['fullname']}` | {regression['delta_pct']:.2f}% | {regression['baseline_mean']:.6f} | {regression['current_mean']:.6f} |"
- )
- if result.notes:
- lines.extend(["", "## Notes", ""])
- lines.extend([f"- {note}" for note in result.notes])
- return "\n".join(lines) + "\n"
-
-
-def run_campaign(
- campaign: BenchmarkCampaignEntry,
- *,
- json_out: Path | None,
- markdown_out: Path | None,
- compare_to: Path | None,
- warn_pct: float | None,
- fail_pct: float | None,
-) -> CampaignResult:
- if campaign.execution is None or campaign.execution.kind is not ExecutionKind.PYTEST:
- raise ValueError(f"Benchmark campaign {campaign.name!r} must use pytest execution")
-
- artifact_json = json_out or _default_artifact_path(campaign.name, "json")
- artifact_md = markdown_out or _default_artifact_path(campaign.name, "md")
- artifact_json.parent.mkdir(parents=True, exist_ok=True)
- artifact_md.parent.mkdir(parents=True, exist_ok=True)
-
- with tempfile.TemporaryDirectory(prefix=f"benchmark-{campaign.name}-") as tmpdir:
- raw_json = Path(tmpdir) / "pytest-benchmark.json"
- benchmark_execution = pytest_execution(
- "-q",
- "--override-ini=addopts=-ra",
- "-n",
- "0",
- "-p",
- "no:randomly",
- "--benchmark-enable",
- f"--benchmark-json={raw_json}",
- *campaign.execution.pytest_targets,
- )
- start = time.monotonic()
- completed = run_execution(benchmark_execution, cwd=ROOT)
- runtime_seconds = time.monotonic() - start
- command = list(completed.command)
- if completed.exit_code != 0 and (not raw_json.exists() or raw_json.stat().st_size == 0):
- raise SystemExit(completed.exit_code)
- if not raw_json.exists():
- raise SystemExit(f"Benchmark run for {campaign.name} produced no JSON artifact")
- payload = json.loads(raw_json.read_text())
-
- payload_document = json_document(payload)
- benchmarks = parse_pytest_benchmark_stats(payload_document)
- benchmarks.sort(key=lambda item: item.mean, reverse=True)
- baseline_result = _load_campaign_result(compare_to) if compare_to else None
- regressions = _compare_results(benchmarks, baseline_result.benchmarks) if baseline_result else []
- warn_threshold = campaign.warn_pct if warn_pct is None else warn_pct
- fail_threshold = campaign.fail_pct if fail_pct is None else fail_pct
- worst_regression = regressions[0].delta_pct if regressions else None
-
- metadata = ScenarioMetadata.from_object(campaign)
- result = CampaignResult(
- campaign=campaign.name,
- description=campaign.description,
- commit=_git_output("rev-parse", "HEAD"),
- worktree_dirty=_worktree_dirty(),
- created_at=datetime.now(UTC).isoformat(),
- workspace=str(ROOT),
- command=command,
- tests=list(campaign.tests),
- notes=list(campaign.notes),
- benchmark_count=len(benchmarks),
- runtime_seconds=runtime_seconds,
- exit_code=completed.exit_code,
- machine_info=json_document(payload_document.get("machine_info")),
- benchmarks=[benchmark_stat_record(bench) for bench in benchmarks],
- slowest=[benchmark_stat_record(bench) for bench in benchmarks[:10]],
- compare_to=str(compare_to) if compare_to else None,
- warn_pct=warn_threshold,
- fail_pct=fail_threshold,
- regressions=[_regression_record(item) for item in regressions],
- worst_regression_pct=worst_regression,
- origin=metadata.origin,
- path_targets=list(metadata.path_targets),
- artifact_targets=list(metadata.artifact_targets),
- operation_targets=list(metadata.operation_targets),
- maintenance_targets=list(metadata.maintenance_targets),
- tags=list(metadata.tags),
- )
-
- artifact_json.write_text(json.dumps(asdict(result), indent=2, sort_keys=True) + "\n")
- artifact_md.write_text(_render_markdown(result))
-
- if completed.exit_code != 0:
- raise SystemExit(completed.exit_code)
- if worst_regression is not None and worst_regression > fail_threshold:
- raise SystemExit(
- f"Benchmark regression exceeded fail threshold: {worst_regression:.2f}% > {fail_threshold:.2f}%"
- )
- return result
-
-
-def render_index() -> str:
- artifact_dir = ROOT / ARTIFACT_DIR
- rows: list[tuple[str, str, str, str, str, str, str]] = []
- for json_path in sorted(artifact_dir.glob("*.json")):
- result = _load_campaign_result(json_path)
- md_path = json_path.with_suffix(".md")
- worst = "-" if result.worst_regression_pct is None else f"{result.worst_regression_pct:.2f}%"
- rows.append(
- (
- result.created_at[:10],
- result.campaign,
- result.commit[:12],
- str(result.benchmark_count),
- f"{result.runtime_seconds:.2f}s",
- worst,
- md_path.name if md_path.exists() else "-",
- )
- )
- lines = [
- "# Benchmark Campaign Artifacts",
- "",
- "Use `devtools bench campaign list` to see campaign definitions.",
- "Use `devtools bench campaign run ` to record a fresh artifact.",
- "Use `devtools bench campaign compare ` to compare two artifacts.",
- "",
- "| Date | Campaign | Commit | Benchmarks | Runtime | Worst Regression | Markdown |",
- "| --- | --- | --- | ---: | ---: | ---: | --- |",
- ]
- for row in rows:
- date, campaign, commit, count, runtime, worst, markdown = row
- md_link = f"[{markdown}](./{markdown})" if markdown != "-" else "-"
- lines.append(f"| {date} | `{campaign}` | `{commit}` | {count} | {runtime} | {worst} | {md_link} |")
- return "\n".join(lines) + "\n"
-
-
-def compare_artifacts(baseline: Path, candidate: Path, fail_pct: float) -> int:
- baseline_result = _load_campaign_result(baseline)
- candidate_result = _load_campaign_result(candidate)
- regressions = _compare_results(
- [BenchmarkStat(**entry) for entry in candidate_result.benchmarks],
- baseline_result.benchmarks,
- )
- if not regressions:
- print("No overlapping benchmarks to compare.")
- return 0
- print(f"Comparing {candidate.name} against {baseline.name}:")
- for regression in regressions[:10]:
- print(
- f" {regression.fullname}: {regression.delta_pct:.2f}% "
- f"({regression.baseline_mean:.6f}s -> {regression.current_mean:.6f}s)"
- )
- worst = regressions[0].delta_pct
- if worst > fail_pct:
- print(f"FAIL: worst regression {worst:.2f}% exceeds {fail_pct:.2f}%")
- return 1
- return 0
-
-
-def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
- parser = argparse.ArgumentParser(description=__doc__)
- subparsers = parser.add_subparsers(dest="command", required=True)
-
- subparsers.add_parser("list", help="List benchmark campaigns")
- subparsers.add_parser("index", help="Regenerate benchmark artifact index markdown")
-
- run_parser = subparsers.add_parser("run", help="Run a benchmark campaign and write durable artifacts")
- run_parser.add_argument("campaign", choices=sorted(CAMPAIGNS))
- run_parser.add_argument("--json-out", type=Path)
- run_parser.add_argument("--markdown-out", type=Path)
- run_parser.add_argument("--compare-to", type=Path)
- run_parser.add_argument("--warn-pct", type=float)
- run_parser.add_argument("--fail-pct", type=float)
-
- compare_parser = subparsers.add_parser("compare", help="Compare two existing benchmark artifacts")
- compare_parser.add_argument("baseline", type=Path)
- compare_parser.add_argument("candidate", type=Path)
- compare_parser.add_argument("--fail-pct", type=float, default=DEFAULT_FAIL_PCT)
-
- return parser.parse_args(argv)
-
-
-def main(argv: list[str] | None = None) -> int:
- args = parse_args(argv)
- if args.command == "list":
- for campaign in CAMPAIGNS.values():
- print(f"{campaign.name}: {campaign.description}")
- for test in campaign.tests:
- print(f" - {test}")
- return 0
- if args.command == "index":
- path = ROOT / ARTIFACT_DIR / "README.md"
- path.parent.mkdir(parents=True, exist_ok=True)
- path.write_text(render_index())
- print(path)
- return 0
- if args.command == "run":
- run_campaign(
- CAMPAIGNS[args.campaign],
- json_out=args.json_out,
- markdown_out=args.markdown_out,
- compare_to=args.compare_to,
- warn_pct=args.warn_pct,
- fail_pct=args.fail_pct,
- )
- return 0
- if args.command == "compare":
- return compare_artifacts(args.baseline, args.candidate, args.fail_pct)
- raise AssertionError(f"Unhandled command: {args.command}")
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/benchmark_campaigns.py b/devtools/benchmark_campaigns.py
deleted file mode 100644
index f7b9df24ff..0000000000
--- a/devtools/benchmark_campaigns.py
+++ /dev/null
@@ -1,113 +0,0 @@
-"""Long-haul benchmark campaign runner.
-
-Executes reproducible benchmark campaigns against synthetic archives
-and produces durable JSON + Markdown reports under .local/benchmark-campaigns/.
-"""
-
-from __future__ import annotations
-
-from pathlib import Path
-
-from polylogue.scenarios import CorpusSourceKind, RunnerInvocation, dispatch_runner_execution
-
-from .authored_scenario_catalog import get_authored_scenario_catalog
-from .benchmark_catalog import BenchmarkCampaignEntry
-from .campaign_archive_location import CampaignArchiveLocation
-from .synthetic_benchmark_runtime import CampaignResult, resolve_synthetic_benchmark_runner
-
-SYNTHETIC_CAMPAIGNS: dict[str, BenchmarkCampaignEntry] = (
- get_authored_scenario_catalog().synthetic_benchmark_campaign_index()
-)
-
-
-async def run_synthetic_benchmark_campaign(name: str, db_path: Path) -> CampaignResult:
- """Dispatch one synthetic benchmark campaign by authored scenario id."""
-
- campaign = SYNTHETIC_CAMPAIGNS[name]
- if campaign.execution is None:
- raise ValueError(f"Synthetic benchmark campaign {campaign.name!r} has no execution")
- result = await dispatch_runner_execution(
- campaign.execution,
- runner_resolver=resolve_synthetic_benchmark_runner,
- invocation=RunnerInvocation(args=(db_path,)),
- )
- result.origin = campaign.origin
- result.path_targets = list(campaign.path_targets)
- result.artifact_targets = list(campaign.artifact_targets)
- result.operation_targets = list(campaign.operation_targets)
- result.tags = list(campaign.tags)
- return result
-
-
-async def run_full_campaign(
- scale_level: str,
- output_dir: Path,
- *,
- corpus_source: CorpusSourceKind | str = CorpusSourceKind.DEFAULT,
-) -> list[CampaignResult]:
- """Run all benchmark campaigns at a given scale level.
-
- Generates a synthetic archive at the specified scale, then runs
- each campaign against the resulting database.
-
- Args:
- scale_level: One of "small", "medium", "large", "stretch".
- output_dir: Directory for archive and report output.
-
- Returns:
- List of CampaignResult for all campaigns.
- """
- from devtools.large_archive_generator import (
- ScaleLevel,
- generate_archive,
- get_default_spec,
- )
-
- level = ScaleLevel(scale_level)
- spec = get_default_spec(level)
-
- archive_dir = output_dir / f"archive-{scale_level}"
- source_kind = CorpusSourceKind(corpus_source)
-
- # Acquired once and held for the entire campaign run: generation and
- # ownership must stay stable from archive generation through every
- # subsequent benchmark reopen below (polylogue-ovme.3). A wrong/unowned
- # archive_dir fails here, before any archive generation or measurement
- # work starts.
- with CampaignArchiveLocation.acquire(archive_dir) as location:
- print(
- f"Generating {scale_level} archive from {source_kind.value} corpus source "
- f"({spec.sessions} sessions, ~{spec.message_count} messages)..."
- )
- archive_metrics = await generate_archive(spec, archive_dir, corpus_source=source_kind, location=location)
- print(
- f"Archive generated in {archive_metrics.wall_time_s:.1f}s "
- f"({archive_metrics.session_count} convs, "
- f"{archive_metrics.message_count} msgs, "
- f"{archive_metrics.db_size_bytes / 1024 / 1024:.1f} MB)"
- )
-
- results: list[CampaignResult] = []
-
- for campaign in SYNTHETIC_CAMPAIGNS.values():
- if campaign.scale_targets and scale_level not in campaign.scale_targets:
- continue
- print(f"Running {campaign.name} campaign...")
- # Re-fetched on every reopen (not cached from generation above)
- # so a stale/foreign generation is caught before this campaign
- # opens a connection against it.
- result = await run_synthetic_benchmark_campaign(campaign.name, location.active_index_path)
- result.scale_level = scale_level
- results.append(result)
- metric_value = result.metrics.get(campaign.summary_metric, 0)
- print(f" -> {metric_value:.4f}{campaign.summary_label}")
-
- return results
-
-
-__all__ = [
- "CampaignResult",
- "SYNTHETIC_CAMPAIGNS",
- "run_full_campaign",
- "run_synthetic_benchmark_campaign",
-]
diff --git a/devtools/benchmark_catalog.py b/devtools/benchmark_catalog.py
deleted file mode 100644
index 9db3352615..0000000000
--- a/devtools/benchmark_catalog.py
+++ /dev/null
@@ -1,22 +0,0 @@
-"""Typed benchmark campaign catalog shared across control-plane surfaces."""
-
-from __future__ import annotations
-
-from .benchmark_models import BenchmarkCampaignEntry
-from .benchmark_scenario_catalog import BENCHMARK_SCENARIOS
-from .synthetic_benchmark_catalog import SYNTHETIC_BENCHMARK_SCENARIOS
-
-
-def build_benchmark_entries() -> tuple[BenchmarkCampaignEntry, ...]:
- return tuple(sorted(BENCHMARK_SCENARIOS, key=lambda item: item.name))
-
-
-def build_synthetic_benchmark_entries() -> tuple[BenchmarkCampaignEntry, ...]:
- return tuple(sorted(SYNTHETIC_BENCHMARK_SCENARIOS, key=lambda item: item.name))
-
-
-__all__ = [
- "BenchmarkCampaignEntry",
- "build_benchmark_entries",
- "build_synthetic_benchmark_entries",
-]
diff --git a/devtools/benchmark_models.py b/devtools/benchmark_models.py
deleted file mode 100644
index aa2115c57d..0000000000
--- a/devtools/benchmark_models.py
+++ /dev/null
@@ -1,40 +0,0 @@
-"""Shared benchmark campaign metadata for control-plane catalogs."""
-
-from __future__ import annotations
-
-from dataclasses import dataclass
-
-from polylogue.scenarios import ExecutableScenario, ScenarioProjectionSourceKind
-
-
-@dataclass(frozen=True, kw_only=True)
-class BenchmarkCampaignEntry(ExecutableScenario):
- notes: tuple[str, ...] = ()
- summary_metric: str = ""
- summary_label: str = ""
- scale_targets: tuple[str, ...] = ()
- projection_kind: ScenarioProjectionSourceKind = ScenarioProjectionSourceKind.BENCHMARK_CAMPAIGN
-
- @property
- def projection_source_kind(self) -> ScenarioProjectionSourceKind:
- return self.projection_kind
-
- @property
- def warn_pct(self) -> float:
- return self.assertion.resolved_benchmark_warn_pct()
-
- @property
- def fail_pct(self) -> float:
- return self.assertion.resolved_benchmark_fail_pct()
-
-
-def compile_benchmark_campaigns(
- campaigns: tuple[BenchmarkCampaignEntry, ...],
-) -> dict[str, BenchmarkCampaignEntry]:
- return {campaign.name: campaign for campaign in campaigns}
-
-
-__all__ = [
- "BenchmarkCampaignEntry",
- "compile_benchmark_campaigns",
-]
diff --git a/devtools/benchmark_scenario_catalog.py b/devtools/benchmark_scenario_catalog.py
deleted file mode 100644
index 8ada96f334..0000000000
--- a/devtools/benchmark_scenario_catalog.py
+++ /dev/null
@@ -1,115 +0,0 @@
-"""Authored durable benchmark campaigns shared across control-plane surfaces."""
-
-from __future__ import annotations
-
-from devtools.benchmark_models import BenchmarkCampaignEntry, compile_benchmark_campaigns
-from polylogue.scenarios import pytest_execution
-
-BENCHMARK_SCENARIOS: tuple[BenchmarkCampaignEntry, ...] = (
- BenchmarkCampaignEntry(
- name="search-filters",
- description="FTS and SessionFilter benchmark domain",
- execution=pytest_execution("tests/benchmarks/test_search_filters.py"),
- notes=(
- "Canonical search/filter latency domain.",
- "Keep on session-seeded DB fixtures for comparability.",
- ),
- origin="authored.benchmark-domain",
- artifact_targets=("session_query_results", "message_fts"),
- operation_targets=("query-sessions", "benchmark.query.search-filters"),
- tags=("benchmark", "search", "filters"),
- ),
- BenchmarkCampaignEntry(
- name="storage",
- description="Repository/backend list/get-many/save benchmark domain",
- execution=pytest_execution("tests/benchmarks/test_storage.py"),
- notes=("Canonical storage CRUD and batch-write latency domain.",),
- origin="authored.benchmark-domain",
- conceptual_artifact_targets=("session_rows", "message_rows", "raw_rows"),
- operation_targets=("benchmark.storage.crud",),
- tags=("benchmark", "storage"),
- ),
- BenchmarkCampaignEntry(
- name="pipeline",
- description="Index rebuild/update plus hashing and semantic helper benchmark domain",
- execution=pytest_execution("tests/benchmarks/test_pipeline.py"),
- notes=("Covers indexing and hot helper throughput.",),
- origin="authored.benchmark-domain",
- conceptual_artifact_targets=("index_state", "pipeline_helpers"),
- operation_targets=("benchmark.pipeline.index-and-helpers",),
- tags=("benchmark", "pipeline"),
- ),
- BenchmarkCampaignEntry(
- name="reader-api",
- description="Reader HTTP API list/get/facets/context-image/cost-rollup benchmark domain",
- execution=pytest_execution("tests/benchmarks/test_reader_api.py"),
- notes=(
- "Covers reader read-path latency for list, get, facets, and context operations.",
- "SLO catalog gates are defined in docs/plans/slo-catalog.yaml.",
- ),
- origin="authored.benchmark-domain",
- conceptual_artifact_targets=("reader_list_results", "reader_facets"),
- operation_targets=("benchmark.reader.api",),
- tags=("benchmark", "reader", "api"),
- ),
- BenchmarkCampaignEntry(
- name="session-digest",
- description="Deterministic session digest transform/render benchmark domain",
- execution=pytest_execution("tests/benchmarks/test_session_digest.py"),
- notes=(
- "Covers session digest transform compilation and report rendering over tool-heavy sessions.",
- "Keeps #1880 session digest artifact shape in the generated benchmark inventory.",
- ),
- origin="authored.benchmark-domain",
- path_targets=("session-digest-transform-loop",),
- artifact_targets=("session_digest", "forensic_index", "resume_bundle", "session_report_markdown"),
- operation_targets=(
- "compile-session-digest",
- "render-session-report",
- "benchmark.transform.session-digest",
- "benchmark.transform.session-report",
- ),
- tags=("benchmark", "transform", "session-analysis"),
- ),
- BenchmarkCampaignEntry(
- name="daemon-convergence",
- description="Daemon ingest convergence at synthetic scale tiers — single-file and multi-session",
- execution=pytest_execution("tests/benchmarks/test_daemon_convergence.py"),
- notes=(
- "Measures convergence stage timing at small/medium/large synthetic tiers.",
- "Run with --benchmark-enable -p no:xdist -o 'addopts='",
- ),
- origin="authored.benchmark-domain",
- conceptual_artifact_targets=("daemon_convergence_timing",),
- operation_targets=("benchmark.daemon.convergence",),
- tags=("benchmark", "daemon", "convergence"),
- ),
- BenchmarkCampaignEntry(
- name="archive-maintenance",
- description="Archive backup planning, blob-GC dry-run, and space-report benchmark domain",
- execution=pytest_execution("tests/benchmarks/test_archive_maintenance.py"),
- notes=(
- "Covers read-only archive maintenance performance artifacts.",
- "Backup runtime copy/restore semantics are intentionally out of scope.",
- ),
- origin="authored.benchmark-domain",
- artifact_targets=("archive_readiness",),
- operation_targets=(
- "benchmark.archive.backup-plan",
- "benchmark.archive.blob-gc-dry-run",
- "benchmark.archive.space-report",
- ),
- maintenance_targets=("orphaned_blobs",),
- tags=("benchmark", "archive", "maintenance", "backup", "gc"),
- ),
-)
-
-BENCHMARK_SCENARIO_INDEX: dict[str, BenchmarkCampaignEntry] = compile_benchmark_campaigns(BENCHMARK_SCENARIOS)
-
-
-__all__ = [
- "BENCHMARK_SCENARIO_INDEX",
- "BENCHMARK_SCENARIOS",
- "BenchmarkCampaignEntry",
- "compile_benchmark_campaigns",
-]
diff --git a/devtools/campaign_report.py b/devtools/campaign_report.py
deleted file mode 100644
index 2a025e3bbb..0000000000
--- a/devtools/campaign_report.py
+++ /dev/null
@@ -1,182 +0,0 @@
-"""Generate Markdown and JSON reports from campaign results."""
-
-from __future__ import annotations
-
-import json
-from dataclasses import asdict
-from datetime import UTC, datetime
-from pathlib import Path
-
-from devtools.synthetic_benchmark_runtime import CampaignResult
-
-
-def generate_campaign_markdown(results: list[CampaignResult]) -> str:
- """Produce a Markdown report from a list of campaign results.
-
- The report includes scale level, per-campaign timing, DB size,
- row counts, and a comparison table for easy diffing.
- """
- if not results:
- return "# Benchmark Campaign Report\n\nNo results.\n"
-
- scale_level = results[0].scale_level or "unknown"
- timestamp = results[0].timestamp
-
- lines = [
- "# Benchmark Campaign Report",
- "",
- f"- **Scale level**: {scale_level}",
- f"- **Generated**: {timestamp}",
- "",
- "## Summary",
- "",
- "| Campaign | Key Metric | Value |",
- "| --- | --- | ---: |",
- ]
-
- for result in results:
- key_metric, value = _pick_key_metric(result)
- lines.append(f"| {result.campaign_name} | {key_metric} | {value} |")
-
- lines.extend(["", "## Detailed Results", ""])
-
- for result in results:
- lines.extend(_render_campaign_section(result))
-
- # DB stats comparison table
- lines.extend(["", "## Database Statistics", ""])
- lines.extend(_render_db_stats_table(results))
-
- lines.append("")
- return "\n".join(lines)
-
-
-def _pick_key_metric(result: CampaignResult) -> tuple[str, str]:
- """Pick the single most important metric from a campaign result."""
- m = result.metrics
- match result.campaign_name:
- case "fts-rebuild":
- return "rebuild_wall_s", f"{m.get('rebuild_wall_s', 0):.3f}s"
- case "incremental-index":
- return "total_wall_s", f"{m.get('total_wall_s', 0):.3f}s"
- case "filter-scan":
- return "list_50_wall_s", f"{m.get('list_50_wall_s', 0):.4f}s"
- case "startup-readiness":
- return "total_readiness_s", f"{m.get('total_readiness_s', 0):.4f}s"
- case _:
- if m:
- key = next(iter(m))
- return key, f"{m[key]}"
- return "n/a", "n/a"
-
-
-def _render_campaign_section(result: CampaignResult) -> list[str]:
- """Render a single campaign's detailed section."""
- lines = [
- f"### {result.campaign_name}",
- "",
- ]
- if result.path_targets or result.artifact_targets or result.operation_targets or result.tags:
- lines.extend(
- [
- "| Scenario metadata | Value |",
- "| --- | --- |",
- f"| origin | `{result.origin}` |",
- ]
- )
- if result.path_targets:
- lines.append(f"| path targets | `{', '.join(result.path_targets)}` |")
- if result.artifact_targets:
- lines.append(f"| artifact targets | `{', '.join(result.artifact_targets)}` |")
- if result.operation_targets:
- lines.append(f"| operation targets | `{', '.join(result.operation_targets)}` |")
- if result.tags:
- lines.append(f"| tags | `{', '.join(result.tags)}` |")
- lines.append("")
-
- if result.metrics:
- lines.extend(
- [
- "| Metric | Value |",
- "| --- | ---: |",
- ]
- )
- for key, value in sorted(result.metrics.items()):
- if isinstance(value, float):
- lines.append(f"| {key} | {value:.4f} |")
- else:
- lines.append(f"| {key} | {value} |")
- lines.append("")
-
- return lines
-
-
-def _render_db_stats_table(results: list[CampaignResult]) -> list[str]:
- """Render a DB statistics comparison table."""
- # Collect all unique stat keys
- all_keys: list[str] = []
- seen: set[str] = set()
- for result in results:
- for key in result.db_stats:
- if key not in seen:
- all_keys.append(key)
- seen.add(key)
-
- if not all_keys:
- return ["_No database statistics collected._"]
-
- # Header
- campaign_names = [r.campaign_name for r in results]
- header = "| Stat | " + " | ".join(campaign_names) + " |"
- separator = "| --- | " + " | ".join("---:" for _ in campaign_names) + " |"
- lines = [header, separator]
-
- for key in all_keys:
- values = []
- for result in results:
- val = result.db_stats.get(key, "")
- if isinstance(val, int) and key.endswith("_bytes"):
- values.append(f"{val / 1024 / 1024:.1f} MB")
- else:
- values.append(str(val))
- lines.append(f"| {key} | " + " | ".join(values) + " |")
-
- return lines
-
-
-def generate_campaign_json(results: list[CampaignResult]) -> str:
- """Produce a JSON report from a list of campaign results."""
- payload = {
- "generated_at": datetime.now(UTC).isoformat(),
- "scale_level": results[0].scale_level if results else "unknown",
- "campaigns": [asdict(r) for r in results],
- }
- return json.dumps(payload, indent=2, sort_keys=True) + "\n"
-
-
-def save_campaign_reports(results: list[CampaignResult], output_dir: Path) -> list[Path]:
- """Save both Markdown and JSON reports to the output directory.
-
- Returns:
- List of paths to saved report files.
- """
- output_dir.mkdir(parents=True, exist_ok=True)
-
- scale = results[0].scale_level if results else "unknown"
- date = datetime.now(UTC).strftime("%Y-%m-%d")
- stem = f"{date}-{scale}"
-
- md_path = output_dir / f"{stem}.md"
- json_path = output_dir / f"{stem}.json"
-
- md_path.write_text(generate_campaign_markdown(results), encoding="utf-8")
- json_path.write_text(generate_campaign_json(results), encoding="utf-8")
-
- return [md_path, json_path]
-
-
-__all__ = [
- "generate_campaign_json",
- "generate_campaign_markdown",
- "save_campaign_reports",
-]
diff --git a/devtools/chatgpt_lifecycle_anchor_audit.py b/devtools/chatgpt_lifecycle_anchor_audit.py
deleted file mode 100644
index afdae3e6ab..0000000000
--- a/devtools/chatgpt_lifecycle_anchor_audit.py
+++ /dev/null
@@ -1,375 +0,0 @@
-"""Read-only ChatGPT lifecycle-anchor census through the production parser route.
-
-This command audits whether quarantined ChatGPT revisions currently exhibit
-the historical mapping-order failure: two exports with equal transcript and
-lifecycle content but a different generation-lifecycle anchor. It does not
-change archive state. The only optional write is a caller-selected,
-sanitized JSON receipt outside the archive.
-"""
-
-from __future__ import annotations
-
-import argparse
-import hashlib
-import json
-import os
-import sqlite3
-import subprocess
-from collections import Counter, defaultdict
-from collections.abc import Iterable
-from dataclasses import dataclass
-from pathlib import Path
-from typing import Literal, TextIO
-
-from polylogue.archive.session_revision_membership import MembershipRevision, _relation, classify_membership_revisions
-from polylogue.core.enums import Provider
-from polylogue.core.hashing import hash_payload
-from polylogue.pipeline.ids import _event_content_payload, session_revision_projection
-from polylogue.sources.parsers.base import ParsedSession, ParsedSessionEvent
-from polylogue.sources.revision_backfill import _parse_one
-from polylogue.storage.blob_store import BlobStore
-
-_Relation = Literal["equal", "a_contains_b", "b_contains_a", "conflict"]
-
-SCHEMA = "polylogue.chatgpt-lifecycle-anchor-audit.v2"
-TARGET_PREDICATE = (
- "A pair in one persisted logical_source_key cohort where each parsed session has exactly one "
- "generation_lifecycle event (other session events are allowed), their source_message_provider_id "
- "anchors differ, message_contents, attachment_identities, and attachment_contents are equal, "
- "generation_lifecycle event "
- "content hashes after removing source_message_provider_id are equal, all normalized event content "
- "is equal after that same lifecycle-only exception, and the production _relation is conflict."
-)
-SELECTION_SQL = """
-SELECT r.raw_id, r.source_path, lower(hex(r.blob_hash)) AS blob_hash,
- m.logical_source_key, m.provider_session_id
-FROM raw_sessions AS r
-JOIN raw_session_memberships AS m ON m.raw_id = r.raw_id
-WHERE r.origin = 'chatgpt-export' AND r.revision_authority = 'quarantined'
-ORDER BY m.logical_source_key, r.raw_id
-""".strip()
-POPULATION_SQL = """
-SELECT raw_id
-FROM raw_sessions
-WHERE origin = 'chatgpt-export' AND revision_authority = 'quarantined'
-ORDER BY raw_id
-""".strip()
-
-
-@dataclass(frozen=True, slots=True)
-class _RawMember:
- raw_id: str
- source_path: str
- blob_hash: str
- logical_source_key: str
- provider_session_id: str
-
-
-@dataclass(frozen=True, slots=True)
-class _ParsedMember:
- revision: MembershipRevision
- session: ParsedSession
-
-
-def _connect_read_only(path: Path) -> sqlite3.Connection:
- return sqlite3.connect(f"file:{path}?mode=ro", uri=True)
-
-
-def _database_provenance(conn: sqlite3.Connection, path: Path) -> dict[str, int]:
- stat = path.stat()
- return {
- "size_bytes": stat.st_size,
- "mtime_ns": stat.st_mtime_ns,
- "sqlite_schema_version": int(conn.execute("PRAGMA schema_version").fetchone()[0]),
- "sqlite_user_version": int(conn.execute("PRAGMA user_version").fetchone()[0]),
- }
-
-
-def _git_provenance() -> dict[str, object]:
- repo_root = Path(__file__).resolve().parents[1]
- try:
- revision = subprocess.check_output(
- ["git", "-C", os.fspath(repo_root), "rev-parse", "--verify", "HEAD"],
- text=True,
- stderr=subprocess.DEVNULL,
- timeout=5,
- ).strip()
- status = subprocess.run(
- ["git", "-C", os.fspath(repo_root), "status", "--porcelain=v1", "--untracked-files=all"],
- capture_output=True,
- check=True,
- text=True,
- timeout=5,
- ).stdout
- except (OSError, subprocess.CalledProcessError, subprocess.TimeoutExpired) as error:
- raise RuntimeError("ChatGPT lifecycle-anchor audit requires a readable git producer checkout") from error
- return {
- "git_revision": revision,
- "working_tree_clean": not bool(status),
- "working_tree_status_sha256": hashlib.sha256(status.encode("utf-8")).hexdigest(),
- }
-
-
-def _generation_events(session: ParsedSession) -> list[ParsedSessionEvent]:
- return [event for event in session.session_events if event.event_type == "generation_lifecycle"]
-
-
-def _anchor_independent_event_content(event: ParsedSessionEvent) -> bytes:
- """Hash one lifecycle event without its provider-message anchor."""
- payload = _event_content_payload(event)
- payload.pop("source_message_provider_id", None)
- return bytes.fromhex(hash_payload(payload))
-
-
-def _event_content_signature(event: ParsedSessionEvent) -> bytes:
- """Hash normalized event content, retaining anchors except for lifecycle events."""
- if event.event_type == "generation_lifecycle":
- return _anchor_independent_event_content(event)
- return bytes.fromhex(hash_payload(_event_content_payload(event)))
-
-
-def _session_event_content_signatures(session: ParsedSession) -> Counter[bytes]:
- """Return normalized event content as a multiset, independent of array order."""
- return Counter(_event_content_signature(event) for event in session.session_events)
-
-
-def _blob_store_snapshot(blob_store: BlobStore) -> dict[str, object]:
- """Capture a deterministic, read-only identity and integrity scan of blobs."""
- snapshot_digest = hashlib.sha256()
- integrity_digest = hashlib.sha256()
- canonical_blob_count = 0
- canonical_blob_bytes = 0
- verified_blob_count = 0
- hash_mismatch_count = 0
- invalid_namespace_entry_count = 0
-
- for entry in blob_store.iter_namespace():
- if entry.hash_hex is None:
- invalid_namespace_entry_count += 1
- record = {
- "kind": entry.kind.value,
- "issue": entry.issue.value if entry.issue is not None else None,
- "relative_path": entry.relative_path,
- }
- encoded = json.dumps(record, sort_keys=True, separators=(",", ":")).encode("utf-8")
- snapshot_digest.update(encoded)
- snapshot_digest.update(b"\n")
- integrity_digest.update(encoded)
- integrity_digest.update(b"\n")
- continue
-
- size_bytes = entry.path.stat().st_size
- actual_digest = hashlib.sha256()
- with entry.path.open("rb") as blob:
- while chunk := blob.read(1024 * 1024):
- actual_digest.update(chunk)
- verified = actual_digest.hexdigest() == entry.hash_hex
- canonical_blob_count += 1
- canonical_blob_bytes += size_bytes
- verified_blob_count += int(verified)
- hash_mismatch_count += int(not verified)
- snapshot_record = {"hash": entry.hash_hex, "size_bytes": size_bytes}
- integrity_record = {
- **snapshot_record,
- "verified": verified,
- "observed_sha256": actual_digest.hexdigest(),
- }
- snapshot_encoded = json.dumps(snapshot_record, sort_keys=True, separators=(",", ":")).encode("utf-8")
- integrity_encoded = json.dumps(integrity_record, sort_keys=True, separators=(",", ":")).encode("utf-8")
- snapshot_digest.update(snapshot_encoded)
- snapshot_digest.update(b"\n")
- integrity_digest.update(integrity_encoded)
- integrity_digest.update(b"\n")
-
- return {
- "snapshot_sha256": snapshot_digest.hexdigest(),
- "canonical_blob_count": canonical_blob_count,
- "canonical_blob_bytes": canonical_blob_bytes,
- "integrity": {
- "scan": "full_read_only_namespace_and_content_hash",
- "verified_blob_count": verified_blob_count,
- "hash_mismatch_count": hash_mismatch_count,
- "invalid_namespace_entry_count": invalid_namespace_entry_count,
- "integrity_sha256": integrity_digest.hexdigest(),
- },
- }
-
-
-def _matches_target(left: _ParsedMember, right: _ParsedMember, relation: _Relation) -> bool:
- left_generation_events = _generation_events(left.session)
- right_generation_events = _generation_events(right.session)
- if len(left_generation_events) != 1 or len(right_generation_events) != 1:
- return False
- left_event, right_event = left_generation_events[0], right_generation_events[0]
- left_projection = left.revision.projection
- right_projection = right.revision.projection
- return (
- left_event.source_message_provider_id != right_event.source_message_provider_id
- and left_projection.message_contents == right_projection.message_contents
- and left_projection.attachment_identities == right_projection.attachment_identities
- and left_projection.attachment_contents == right_projection.attachment_contents
- and _session_event_content_signatures(left.session) == _session_event_content_signatures(right.session)
- and _anchor_independent_event_content(left_event) == _anchor_independent_event_content(right_event)
- and relation == "conflict"
- )
-
-
-def _load_existing_heads(index_conn: sqlite3.Connection) -> dict[str, str]:
- return {
- str(row[0]): str(row[1])
- for row in index_conn.execute("SELECT logical_source_key, accepted_raw_id FROM raw_revision_heads")
- }
-
-
-def _parse_member(member: _RawMember, blob_store: BlobStore, archive_root: Path) -> _ParsedMember:
- sessions = _parse_one(
- Provider.CHATGPT,
- blob_store.read_all(member.blob_hash),
- member.source_path,
- archive_root=archive_root,
- fallback_id_override=member.provider_session_id,
- )
- matches = [session for session in sessions if session.provider_session_id == member.provider_session_id]
- if len(matches) != 1:
- raise RuntimeError(
- "ChatGPT lifecycle-anchor audit expected one parsed session for a persisted membership row, "
- f"got {len(matches)}"
- )
- session = matches[0]
- return _ParsedMember(MembershipRevision(member.raw_id, session_revision_projection(session)), session)
-
-
-def _cohorts(rows: Iterable[_RawMember]) -> dict[str, list[_RawMember]]:
- grouped: dict[str, list[_RawMember]] = defaultdict(list)
- for row in rows:
- grouped[row.logical_source_key].append(row)
- return dict(grouped)
-
-
-def run_audit(archive_root: Path) -> dict[str, object]:
- """Run the full current-corpus census without opening an archive writer."""
- producer = _git_provenance()
- source_db = archive_root / "source.db"
- index_db = archive_root / "index.db"
- blob_store = BlobStore(archive_root / "blob")
- source_conn = _connect_read_only(source_db)
- index_conn = _connect_read_only(index_db)
- try:
- population_raw_ids = {str(row[0]) for row in source_conn.execute(POPULATION_SQL)}
- rows = [_RawMember(*map(str, row)) for row in source_conn.execute(SELECTION_SQL)]
- rows_by_raw_id: dict[str, list[_RawMember]] = defaultdict(list)
- for row in rows:
- rows_by_raw_id[row.raw_id].append(row)
- duplicated_membership_raw_count = sum(1 for members in rows_by_raw_id.values() if len(members) != 1)
- if duplicated_membership_raw_count:
- raise RuntimeError("ChatGPT lifecycle-anchor audit requires exactly one membership row per selected raw")
- cohorts = _cohorts(rows)
- relation_counts: Counter[str] = Counter()
- classifier_counts: Counter[str] = Counter()
- target_pair_count = 0
- parsed_raw_count = 0
- heads = _load_existing_heads(index_conn)
- blob_snapshot = _blob_store_snapshot(blob_store)
- for logical_source_key in sorted(cohorts):
- revisions = [
- _parse_member(member, blob_store, archive_root)
- for member in sorted(cohorts[logical_source_key], key=lambda member: member.raw_id)
- ]
- parsed_raw_count += len(revisions)
- for index, left in enumerate(revisions):
- for right in revisions[index + 1 :]:
- relation = _relation(left.revision.projection, right.revision.projection)
- relation_counts[relation] += 1
- if _matches_target(left, right, relation):
- target_pair_count += 1
- classification = classify_membership_revisions(
- [revision.revision for revision in revisions], existing_accepted_raw_id=heads.get(logical_source_key)
- )
- classifier_counts["cohorts_with_accepted_raw"] += bool(classification.accepted_raw_ids)
- classifier_counts["cohorts_with_equivalent_raw"] += bool(classification.equivalent_raw_ids)
- classifier_counts["cohorts_with_ambiguous_raw"] += bool(classification.ambiguous_raw_ids)
- cohort_sizes = Counter(len(members) for members in cohorts.values())
- return {
- "schema": SCHEMA,
- "provenance": {
- "archive_access": "SQLite source.db and index.db opened mode=ro; blob files read only; no archive writer created.",
- "producer_git_revision": producer["git_revision"],
- "producer_working_tree_clean": producer["working_tree_clean"],
- "producer_working_tree_status_sha256": producer["working_tree_status_sha256"],
- "production_route": [
- "polylogue.sources.revision_backfill._parse_one",
- "polylogue.pipeline.ids.session_revision_projection",
- "polylogue.archive.session_revision_membership._relation",
- "polylogue.archive.session_revision_membership.classify_membership_revisions",
- ],
- "source_db": _database_provenance(source_conn, source_db),
- "index_db": _database_provenance(index_conn, index_db),
- "blob_store": blob_snapshot,
- },
- "selection": {"sql": SELECTION_SQL, "population_sql": POPULATION_SQL},
- "target_predicate": TARGET_PREDICATE,
- "denominators": {
- "selected_quarantined_chatgpt_raw_count": len(population_raw_ids),
- "selected_membership_row_count": len(rows),
- "membershipless_selected_raw_count": len(population_raw_ids - set(rows_by_raw_id)),
- "logical_source_key_count": len(cohorts),
- "singleton_cohort_count": cohort_sizes[1],
- "multi_candidate_cohort_count": sum(count for size, count in cohort_sizes.items() if size > 1),
- "raws_in_multi_candidate_cohorts": sum(
- size * count for size, count in cohort_sizes.items() if size > 1
- ),
- "parsed_and_projected_raw_count": parsed_raw_count,
- },
- "outcomes": {
- "pair_relation_counts": {
- name: relation_counts[name] for name in ("equal", "a_contains_b", "b_contains_a", "conflict")
- },
- "target_pair_count": target_pair_count,
- "classifier_cohort_counts": dict(sorted(classifier_counts.items())),
- },
- "scope": {
- "sanitized": "No raw ids, native ids, source paths, blob hashes, titles, or payload content are emitted.",
- "conclusion_limit": (
- "A zero target_pair_count describes only this current parser-and-corpus snapshot. It does not establish "
- "the historical pre-fix replay required to reclassify or remove any graph gate."
- ),
- },
- }
- finally:
- index_conn.close()
- source_conn.close()
-
-
-def _write_receipt(path: Path, receipt: dict[str, object]) -> None:
- path.parent.mkdir(parents=True, exist_ok=True)
- path.write_text(json.dumps(receipt, indent=2, sort_keys=True) + "\n")
-
-
-def main(argv: list[str] | None = None, *, stdout: TextIO | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--archive-root", type=Path, required=True, help="Archive root to inspect without mutation.")
- parser.add_argument("--receipt", type=Path, help="Optional worktree-local path for the sanitized JSON receipt.")
- parser.add_argument(
- "--json",
- action="store_true",
- help="Emit the machine-readable JSON audit report (the default output format).",
- )
- args = parser.parse_args(argv)
- archive_root = args.archive_root.resolve()
- if args.receipt is not None:
- receipt_path = args.receipt.resolve()
- try:
- receipt_path.relative_to(archive_root)
- except ValueError:
- pass
- else:
- parser.error("--receipt must resolve outside --archive-root")
- receipt = run_audit(archive_root)
- if args.receipt is not None:
- _write_receipt(args.receipt.resolve(), receipt)
- print(json.dumps(receipt, indent=2, sort_keys=True), file=stdout)
- return 0
-
-
-if __name__ == "__main__": # pragma: no cover
- raise SystemExit(main())
diff --git a/devtools/claim_vs_evidence.py b/devtools/claim_vs_evidence.py
index 06342c8dfb..6a2beca24a 100644
--- a/devtools/claim_vs_evidence.py
+++ b/devtools/claim_vs_evidence.py
@@ -15,7 +15,8 @@
from typing import Any
from polylogue.archive.actions.followup import classify_failed_followup_evidence
-from polylogue.config import Config, get_config
+from polylogue.config import Config, active_archive_root, get_config
+from polylogue.storage.index_generation import RebuildLease
from polylogue.storage.sqlite.connection_profile import open_readonly_connection
_WORDLESS_CONTINUATION_TEXT_CHAR_LIMIT = 40
@@ -110,7 +111,8 @@ def _parser() -> argparse.ArgumentParser:
help=(
"Register this run's structured-failure selection, matched rows, and headline numbers "
"as durable query/result-set/finding evidence in the archive's user tier (polylogue-rxdo.13). "
- "Off by default; report generation stays read-only unless explicitly requested."
+ "Off by default; report generation stays read-only unless explicitly requested, and the "
+ "materializing form requires exclusive offline writer ownership."
),
)
parser.add_argument("--json", action="store_true", help="Emit JSON report to stdout.")
@@ -131,6 +133,11 @@ def _config_with_archive_root(config: Config, archive_root: Path | None) -> Conf
)
+def _report_config(args: argparse.Namespace) -> Config:
+ """Resolve one file-set authority for both report reads and optional writes."""
+ return _config_with_archive_root(get_config(), args.archive_root)
+
+
def _user_version(conn: Connection) -> int:
row = conn.execute("PRAGMA user_version").fetchone()
return int(row[0]) if row else 0
@@ -449,6 +456,7 @@ def _failure_outcome_rows(conn: Connection, *, limit: int, origin: str | None) -
SELECT
r.session_id,
r.message_id AS tool_result_message_id,
+ r.block_id AS tool_result_block_id,
r.tool_id AS tool_result_tool_id,
s.origin,
r.tool_result_is_error AS is_error,
@@ -463,6 +471,7 @@ def _failure_outcome_rows(conn: Connection, *, limit: int, origin: str | None) -
SELECT
r.session_id,
r.message_id AS tool_result_message_id,
+ r.block_id AS tool_result_block_id,
r.tool_id AS tool_result_tool_id,
s.origin,
r.tool_result_is_error AS is_error,
@@ -479,6 +488,7 @@ def _failure_outcome_rows(conn: Connection, *, limit: int, origin: str | None) -
SELECT
r.session_id,
r.message_id AS tool_result_message_id,
+ r.block_id AS tool_result_block_id,
r.tool_id AS tool_result_tool_id,
s.origin,
r.tool_result_is_error AS is_error,
@@ -494,7 +504,7 @@ def _failure_outcome_rows(conn: Connection, *, limit: int, origin: str | None) -
)
SELECT *
FROM failed
- ORDER BY session_id, tool_result_tool_id, order_message_id
+ ORDER BY session_id, tool_result_tool_id, order_message_id, tool_result_block_id
LIMIT ?
""",
params,
@@ -510,7 +520,7 @@ def _paired_failure_rows(
paired_rows: list[dict[str, object]] = []
for start in range(0, len(failure_rows), chunk_size):
chunk = failure_rows[start : start + chunk_size]
- placeholders = ",".join("(?, ?, ?, ?, ?, ?, ?, ?)" for _ in chunk)
+ placeholders = ",".join("(?, ?, ?, ?, ?, ?, ?, ?, ?)" for _ in chunk)
params: list[object] = []
for offset, row in enumerate(chunk, start=start):
params.extend(
@@ -518,6 +528,7 @@ def _paired_failure_rows(
offset,
row["session_id"],
row["tool_result_message_id"],
+ row["tool_result_block_id"],
row["tool_result_tool_id"],
row["origin"],
row["is_error"],
@@ -533,6 +544,7 @@ def _paired_failure_rows(
sort_index,
session_id,
tool_result_message_id,
+ tool_result_block_id,
tool_result_tool_id,
origin,
is_error,
@@ -545,11 +557,12 @@ def _paired_failure_rows(
SELECT
w.sort_index,
w.session_id,
- u.message_id,
+ a.message_id,
w.tool_result_message_id,
+ w.tool_result_block_id,
w.tool_result_tool_id,
- u.tool_name,
- u.tool_command,
+ a.tool_name,
+ a.tool_command,
w.origin,
w.is_error,
w.exit_code,
@@ -559,23 +572,33 @@ def _paired_failure_rows(
SELECT nm.message_id
FROM messages AS nm
WHERE nm.session_id = w.session_id
- AND nm.role = 'assistant'
+ AND nm.material_origin = 'assistant_authored'
AND nm.position > rm.position
- ORDER BY nm.position
+ AND nm.position < COALESCE(
+ (
+ SELECT MIN(next_human.position)
+ FROM messages AS next_human
+ WHERE next_human.session_id = w.session_id
+ AND next_human.material_origin = 'human_authored'
+ AND next_human.position > rm.position
+ ),
+ 9223372036854775807
+ )
+ ORDER BY nm.position, nm.variant_index, nm.message_id
LIMIT 1
) AS next_message_id
FROM wanted AS w
- JOIN blocks AS u INDEXED BY idx_blocks_tool_id
- ON u.tool_id = w.tool_result_tool_id
- AND u.session_id = w.session_id
- AND u.block_type = 'tool_use'
- JOIN messages AS m ON m.message_id = u.message_id
+ JOIN actions AS a
+ ON a.session_id = w.session_id
+ AND a.tool_result_block_id = w.tool_result_block_id
+ JOIN messages AS m ON m.message_id = a.message_id
JOIN messages AS rm ON rm.message_id = w.tool_result_message_id
)
SELECT
p.session_id,
p.message_id,
p.tool_result_message_id,
+ p.tool_result_block_id,
p.tool_result_tool_id,
p.tool_name,
p.tool_command,
@@ -622,7 +645,7 @@ def _assistant_window_details(
SELECT MIN(next_user.position)
FROM messages AS next_user
WHERE next_user.session_id = w.session_id
- AND next_user.role = 'user'
+ AND next_user.material_origin = 'human_authored'
AND next_user.position > w.result_position
) AS next_user_position
FROM wanted AS w
@@ -632,14 +655,15 @@ def _assistant_window_details(
b.sort_index,
m.message_id,
m.position,
- ROW_NUMBER() OVER (
+ m.variant_index,
+ DENSE_RANK() OVER (
PARTITION BY b.sort_index
ORDER BY m.position
) AS assistant_rank
FROM bounded AS b
JOIN messages AS m
ON m.session_id = b.session_id
- AND m.role = 'assistant'
+ AND m.material_origin = 'assistant_authored'
AND m.position > b.result_position
AND (
b.next_user_position IS NULL
@@ -660,7 +684,7 @@ def _assistant_window_details(
COALESCE(b.text, '') AS text
FROM top_window AS w
LEFT JOIN blocks AS b ON b.message_id = w.message_id
- ORDER BY w.sort_index, w.assistant_rank, b.position
+ ORDER BY w.sort_index, w.assistant_rank, w.variant_index, w.message_id, b.position
""",
[*params, window_size],
)
@@ -946,7 +970,7 @@ def _calibration_labels_path(args: argparse.Namespace) -> Path | None:
return candidate if candidate.exists() else None
-def build_report(args: argparse.Namespace) -> dict[str, Any]:
+def build_report(args: argparse.Namespace, *, config: Config | None = None) -> dict[str, Any]:
if args.limit < 1:
raise ValueError("--limit must be positive")
if args.sample_limit < 1:
@@ -955,7 +979,8 @@ def build_report(args: argparse.Namespace) -> dict[str, Any]:
raise ValueError("--n-min must be positive")
if args.calibration_size < 0:
raise ValueError("--calibration-size must be non-negative")
- config = _config_with_archive_root(get_config(), args.archive_root)
+ config = config or _report_config(args)
+ file_set_root = active_archive_root(config)
index_db = config.db_path
conn = open_readonly_connection(index_db)
try:
@@ -1015,6 +1040,7 @@ def build_report(args: argparse.Namespace) -> dict[str, Any]:
"session_ref": f"session:{row['session_id']}",
"tool_message_ref": f"message:{row['message_id']}",
"tool_result_message_ref": f"message:{row['tool_result_message_id']}",
+ "tool_result_block_ref": f"block:{row['tool_result_block_id']}",
"tool_result_tool_id": row["tool_result_tool_id"],
"next_message_ref": f"message:{row['next_message_id']}" if row["next_message_id"] else None,
"tool_name": tool,
@@ -1115,7 +1141,7 @@ def build_report(args: argparse.Namespace) -> dict[str, Any]:
"report_version": 1,
"captured_at": datetime.now(UTC).isoformat(),
"command": "devtools workspace claim-vs-evidence",
- "archive_root": str(config.archive_root),
+ "archive_root": str(file_set_root),
"index_db": str(index_db),
"index_schema_version": schema_version,
"limit": args.limit,
@@ -1131,7 +1157,7 @@ def build_report(args: argparse.Namespace) -> dict[str, Any]:
"then proportional fill by origin failure count; each origin candidate frame is bounded "
"before pairing to tool-use rows"
),
- "selection_order": "origin, session_id, tool_id, tool_result_message_id",
+ "selection_order": "origin, session_id, tool_id, tool_result_message_id, tool_result_block_id",
"failure_predicate": "tool_result_is_error = 1 OR tool_result_exit_code != 0",
"classification_scope": "immediately following assistant message only",
"sensitivity_scope": "next 3 assistant messages after the failed result, stopping before the next user message",
@@ -1184,7 +1210,7 @@ def build_report(args: argparse.Namespace) -> dict[str, Any]:
"other": "Any tool name outside the explicit benign/consequential methodology sets.",
},
"evidence": {
- "member_refs": sorted({f"message:{row['tool_result_message_id']}" for row in rows}),
+ "member_refs": sorted(f"block:{row['tool_result_block_id']}" for row in rows),
},
"calibration": calibration,
"calibration_sample": [
@@ -1659,9 +1685,8 @@ def _write_readme(path: Path, report: dict[str, Any]) -> None:
"```bash",
"devtools workspace claim-vs-evidence \\",
" --limit 5000 \\",
- " --out-dir .agent/demos/claim-vs-evidence \\",
+ " --out-dir .local/evidence/claim-vs-evidence \\",
" --json",
- "devtools workspace demo-shelf",
"```",
"",
"## Files",
@@ -1672,7 +1697,7 @@ def _write_readme(path: Path, report: dict[str, Any]) -> None:
f"- `{_COLD_READER_GATE_FILE}` — cold-reader prompt and passing-answer checklist.",
f"- `{_CALIBRATION_SAMPLE_FILE}` — deterministic sample for marker calibration.",
f"- `{_CALIBRATION_LABELS_FILE}` — optional human labels consumed on regeneration.",
- "- `summary.json` — current demo-shelf claim/non-claim/proof/caveat summary.",
+ "- `summary.json` — local claim/non-claim/proof/caveat summary.",
"- `README.md` — this human-readable packet.",
"",
]
@@ -1681,19 +1706,27 @@ def _write_readme(path: Path, report: dict[str, Any]) -> None:
def main(argv: list[str] | None = None) -> int:
parsed = _parser().parse_args(argv)
+ config = _report_config(parsed)
+ evidence: object | None = None
try:
- report = build_report(parsed)
+ if parsed.materialize_evidence:
+ from devtools.claim_vs_evidence_evidence import materialize_claim_vs_evidence_evidence_under_lease
+
+ file_set_root = active_archive_root(config)
+ with RebuildLease(file_set_root):
+ report = build_report(parsed, config=config)
+ evidence = materialize_claim_vs_evidence_evidence_under_lease(
+ report,
+ archive_root=file_set_root,
+ now_ms=int(datetime.now(UTC).timestamp() * 1000),
+ )
+ else:
+ report = build_report(parsed, config=config)
except ValueError as exc:
print(f"claim-vs-evidence: {exc}", file=sys.stderr)
return 2
if parsed.materialize_evidence:
- from devtools.claim_vs_evidence_evidence import materialize_claim_vs_evidence_evidence
-
- evidence = materialize_claim_vs_evidence_evidence(
- report,
- archive_root=Path(report["archive_root"]),
- now_ms=int(datetime.now(UTC).timestamp() * 1000),
- )
+ assert evidence is not None
print(f"materialized evidence: {json.dumps(evidence, indent=2, sort_keys=True)}", file=sys.stderr)
if parsed.json:
sys.stdout.write(json.dumps(report, indent=2, sort_keys=True) + "\n")
diff --git a/devtools/claim_vs_evidence_evidence.py b/devtools/claim_vs_evidence_evidence.py
index 475aee44bd..af03d64e44 100644
--- a/devtools/claim_vs_evidence_evidence.py
+++ b/devtools/claim_vs_evidence_evidence.py
@@ -12,8 +12,9 @@
It writes through the same production primitives the daemon's own
standing-query convergence stage uses
-(``polylogue/daemon/convergence_standing_queries.py``) via
-``open_daemon_connection`` -- not a new generic finding registry, not a
+(``polylogue/daemon/convergence_standing_queries.py``), but only after taking
+the archive's exclusive offline-writer lease -- not through a second live
+SQLite writer, not a new generic finding registry, not a
metric/pattern/cohort/experiment definition system, and not a scheduler. A
finding is written with ``public_claim=None`` (no ``PublicClaimDeclaration``)
unless the run's own construct-validity gates (``n_min``, non-zero classified
@@ -36,6 +37,8 @@
from polylogue.core.query_identity import JsonValue
from polylogue.core.query_identity import query_ref as _query_object_ref
from polylogue.core.query_identity import result_set_ref as _result_set_object_ref
+from polylogue.storage.archive_identity import archive_file_set_root
+from polylogue.storage.index_generation import RebuildLease
from polylogue.storage.sqlite.archive_tiers.user_write import (
ArchiveAssertionEnvelope,
FindingAssertion,
@@ -61,7 +64,7 @@
ANALYSIS_TARGET_REF = "analysis:claim-vs-evidence"
_QUERY_GRAIN = "structured-failure-followup"
_QUERY_LANE = "analysis"
-_QUERY_RANK_POLICY = "origin,session_id,tool_id,tool_result_message_id"
+_QUERY_RANK_POLICY = "origin,session_id,tool_id,tool_result_message_id,tool_result_block_id"
class MaterializedEvidence(TypedDict):
@@ -100,7 +103,7 @@ def build_query_definition(report: dict[str, Any]) -> dict[str, JsonValue]:
def build_result_set_members(report: dict[str, Any]) -> tuple[str, ...]:
- """Return the sorted ``message:`` refs the run actually classified."""
+ """Return one sorted ``block:`` ref per failed outcome classified."""
return tuple(report["evidence"]["member_refs"])
@@ -222,18 +225,13 @@ def build_findings(
]
-def materialize_claim_vs_evidence_evidence(
+def materialize_claim_vs_evidence_evidence_under_lease(
report: dict[str, Any],
*,
archive_root: Path,
now_ms: int,
) -> MaterializedEvidence:
- """Register one report run's query, result set, receipt, and findings.
-
- Writes through ``open_daemon_connection`` (the same connection helper the
- daemon's own standing-query convergence stage uses), so this coexists
- with the running daemon's single-writer discipline instead of bypassing
- it with a bare ``sqlite3.connect``.
+ """Register one report while the caller holds ``RebuildLease``.
The AnalysisDefinition (query) and its matched-row ResultSetManifest are
content-addressed: identical selection logic and identical matched rows
@@ -245,7 +243,16 @@ def materialize_claim_vs_evidence_evidence(
should carry that a re-verification happened under a later tier state --
not silently collapse repeated regenerations into one row.
"""
- index_db = Path(report["index_db"])
+ archive_root = archive_root.resolve()
+ report_root = Path(report["archive_root"]).resolve()
+ index_db = Path(report["index_db"]).resolve()
+ if report_root != archive_root:
+ raise ValueError(f"report archive root {report_root} does not match materialization root {archive_root}")
+ index_file_set_root = archive_file_set_root(archive_root=archive_root, db_path=index_db).resolve()
+ if index_file_set_root != archive_root:
+ raise ValueError(
+ f"report index {index_db} belongs to {index_file_set_root}, not materialization root {archive_root}"
+ )
query_definition = build_query_definition(report)
member_refs = build_result_set_members(report)
conn = open_daemon_connection(archive_root / "user.db", timeout=30.0)
@@ -259,7 +266,19 @@ def materialize_claim_vs_evidence_evidence(
created_at_ms=now_ms,
)
query_reference = _query_object_ref(query.query_hash).format()
- result_set_id = f"finding-{membership_merkle_root(member_refs)}"
+ corpus_epoch = _index_epoch(index_db)
+ result_set_digest = hash_payload(
+ (
+ query.query_hash,
+ _QUERY_GRAIN,
+ corpus_epoch,
+ membership_merkle_root(member_refs),
+ hash_payload(list(member_refs)),
+ "capped",
+ "finding",
+ )
+ )
+ result_set_id = f"finding-{result_set_digest}"
result_set: ResultSetManifest | None = get_result_set(conn, result_set_id)
if result_set is None:
result_set = put_result_set(
@@ -267,7 +286,7 @@ def materialize_claim_vs_evidence_evidence(
result_set_id=result_set_id,
query_hash=query.query_hash,
grain=_QUERY_GRAIN,
- corpus_epoch=_index_epoch(index_db),
+ corpus_epoch=corpus_epoch,
member_refs=member_refs,
exactness="capped",
persistence_class="finding",
@@ -305,3 +324,25 @@ def materialize_claim_vs_evidence_evidence(
"finding_assertion_ids": [envelope.assertion_id for envelope in envelopes],
"public_claim_written": any(finding.public_claim is not None for finding in findings),
}
+
+
+def materialize_claim_vs_evidence_evidence(
+ report: dict[str, Any],
+ *,
+ archive_root: Path,
+ now_ms: int,
+) -> MaterializedEvidence:
+ """Materialize an already-collected report under exclusive writer ownership.
+
+ The CLI acquires this lease before report collection and calls the internal
+ under-lease function directly. This public helper remains safe for callers
+ that already hold a report: it excludes every live writer before opening
+ ``user.db`` and validates that the report's index and durable tiers belong
+ to the same archive file set.
+ """
+ with RebuildLease(archive_root):
+ return materialize_claim_vs_evidence_evidence_under_lease(
+ report,
+ archive_root=archive_root,
+ now_ms=now_ms,
+ )
diff --git a/devtools/cli_surface_audit.py b/devtools/cli_surface_audit.py
deleted file mode 100644
index 148a08f253..0000000000
--- a/devtools/cli_surface_audit.py
+++ /dev/null
@@ -1,379 +0,0 @@
-"""Capture a current-curated CLI surface audit demo."""
-
-from __future__ import annotations
-
-import argparse
-import json
-import shutil
-import sqlite3
-import subprocess
-import sys
-import time
-from dataclasses import dataclass
-from datetime import datetime
-from pathlib import Path
-from typing import TypedDict
-
-
-@dataclass(frozen=True, slots=True)
-class AuditCommand:
- name: str
- argv: tuple[str, ...]
- notes: str
-
-
-class ArchiveCounts(TypedDict):
- schema_version: int | None
- sessions: int | None
- messages: int | None
-
-
-class CommandRecord(TypedDict):
- name: str
- argv: list[str]
- exit_code: int
- duration_ms: float
- stdout_bytes: int
- stderr_bytes: int
- stdout_lines: int
- stderr_lines: int
- json_top_level_bytes: dict[str, int] | None
- notes: str
-
-
-class AuditPayload(TypedDict):
- generated_at: str
- archive_root: str
- archive: ArchiveCounts
- include_unbounded_dialogue: bool
- commands: list[CommandRecord]
-
-
-DEFAULT_COMMANDS: tuple[AuditCommand, ...] = (
- AuditCommand("root_help", ("polylogue", "--help"), "Dense but coherent root help."),
- AuditCommand("find_help", ("polylogue", "find", "--help"), "Short query workflow help."),
- AuditCommand("read_help", ("polylogue", "read", "--help"), "Projection, delivery, and read-view options."),
- AuditCommand(
- "read_views_json",
- ("polylogue", "read", "--views", "--format", "json"),
- "Machine-discoverable read-view registry.",
- ),
- AuditCommand("status_plain", ("polylogue", "--plain", "status"), "Compact archive/daemon status."),
- AuditCommand(
- "ops_status_json",
- ("polylogue", "--plain", "ops", "status", "--json"),
- "Machine status payload.",
- ),
- AuditCommand(
- "find_explain_read_json",
- (
- "polylogue",
- "--plain",
- "--format",
- "json",
- "--explain",
- "find",
- "repo:polylogue",
- "then",
- "read",
- "--view",
- "messages",
- "--limit",
- "1",
- ),
- "Query explain JSON for a messages read.",
- ),
- AuditCommand(
- "find_select_json",
- (
- "polylogue",
- "--plain",
- "--format",
- "json",
- "find",
- "repo:polylogue",
- "then",
- "select",
- "--limit",
- "3",
- ),
- "Bounded candidate identity selection.",
- ),
- AuditCommand(
- "read_dialogue_bounded_json",
- (
- "polylogue",
- "--plain",
- "find",
- "repo:polylogue",
- "then",
- "read",
- "--view",
- "dialogue",
- "--format",
- "json",
- "--limit",
- "1",
- "--max-tokens",
- "120",
- ),
- "Projection-bounded dialogue payload with omission accounting.",
- ),
- AuditCommand(
- "read_temporal_spec_json",
- (
- "polylogue",
- "--plain",
- "find",
- "repo:polylogue",
- "then",
- "read",
- "--view",
- "temporal,chronicle",
- "--render",
- "layout:context-image,timestamps:omit,format:json,destination:stdout",
- "--projection",
- "max-tokens:240,redact-paths:true,include-assertions:false",
- "--spec",
- "--limit",
- "1",
- ),
- "Projection/render spec path with compact projection and render expressions.",
- ),
- AuditCommand(
- "facets_json",
- ("polylogue", "--plain", "facets", "--query", "repo:polylogue", "--format", "json"),
- "Archive-backed facets payload.",
- ),
-)
-
-UNBOUNDED_DIALOGUE_COMMAND = AuditCommand(
- "read_dialogue_unbounded_json",
- (
- "polylogue",
- "--plain",
- "find",
- "repo:polylogue",
- "then",
- "read",
- "--view",
- "dialogue",
- "--format",
- "json",
- "--limit",
- "1",
- ),
- "Opt-in diagnostic for the large unbounded dialogue payload.",
-)
-
-
-def _parser() -> argparse.ArgumentParser:
- parser = argparse.ArgumentParser(
- prog="devtools workspace cli-surface-audit",
- description="Capture a current-curated CLI surface audit demo.",
- )
- parser.add_argument("--out-dir", type=Path, default=Path(".agent/demos/cli-surface-audit/current"))
- parser.add_argument("--archive-root", type=Path, default=Path.home() / ".local/share/polylogue")
- parser.add_argument("--include-unbounded-dialogue", action="store_true")
- parser.add_argument("--timeout", type=int, default=60)
- parser.add_argument("--json", action="store_true")
- return parser
-
-
-def _archive_counts(archive_root: Path) -> ArchiveCounts:
- index_db = archive_root / "index.db"
- if not index_db.exists():
- return {"schema_version": None, "sessions": None, "messages": None}
- with sqlite3.connect(index_db) as conn:
- version = int(conn.execute("PRAGMA user_version").fetchone()[0])
- sessions = int(conn.execute("SELECT COUNT(*) FROM sessions").fetchone()[0])
- messages = int(conn.execute("SELECT COUNT(*) FROM messages").fetchone()[0])
- return {"schema_version": version, "sessions": sessions, "messages": messages}
-
-
-def _commands(include_unbounded_dialogue: bool) -> tuple[AuditCommand, ...]:
- if include_unbounded_dialogue:
- return (*DEFAULT_COMMANDS, UNBOUNDED_DIALOGUE_COMMAND)
- return DEFAULT_COMMANDS
-
-
-def _line_count(text: str) -> int:
- return text.count("\n") + (1 if text and not text.endswith("\n") else 0)
-
-
-def _json_top_level_bytes(text: str) -> dict[str, int] | None:
- try:
- payload = json.loads(text)
- except json.JSONDecodeError:
- return None
- if isinstance(payload, list):
- return {
- "$array_bytes": len(json.dumps(payload, sort_keys=True, separators=(",", ":")).encode()),
- "$array_items": len(payload),
- }
- if not isinstance(payload, dict):
- return {"$scalar_bytes": len(json.dumps(payload, sort_keys=True, separators=(",", ":")).encode())}
- return {
- key: len(json.dumps(value, sort_keys=True, separators=(",", ":")).encode())
- for key, value in sorted(payload.items())
- }
-
-
-def _run_commands(commands: tuple[AuditCommand, ...], *, outdir: Path, timeout: int) -> list[CommandRecord]:
- summary: list[CommandRecord] = []
- for command in commands:
- started = time.perf_counter()
- proc = subprocess.run(command.argv, text=True, capture_output=True, timeout=timeout)
- duration_ms = round((time.perf_counter() - started) * 1000, 3)
- (outdir / f"{command.name}.stdout").write_text(proc.stdout, encoding="utf-8")
- (outdir / f"{command.name}.stderr").write_text(proc.stderr, encoding="utf-8")
- summary.append(
- {
- "name": command.name,
- "argv": list(command.argv),
- "exit_code": proc.returncode,
- "duration_ms": duration_ms,
- "stdout_bytes": len(proc.stdout.encode()),
- "stderr_bytes": len(proc.stderr.encode()),
- "stdout_lines": _line_count(proc.stdout),
- "stderr_lines": _line_count(proc.stderr),
- "json_top_level_bytes": _json_top_level_bytes(proc.stdout),
- "notes": command.notes,
- }
- )
- return summary
-
-
-def _json_breakdown_section(commands: list[CommandRecord]) -> str:
- large_json_commands = [
- command for command in commands if command["json_top_level_bytes"] and command["stdout_bytes"] >= 8192
- ]
- if not large_json_commands:
- return ""
- sections = ["## Large JSON Payloads", ""]
- for command in large_json_commands:
- top_level_bytes = command["json_top_level_bytes"]
- if top_level_bytes is None:
- continue
- top = sorted(
- top_level_bytes.items(),
- key=lambda item: item[1],
- reverse=True,
- )[:8]
- sections.append(f"### `{command['name']}`")
- sections.append("")
- sections.append(f"- stdout: {command['stdout_bytes']} bytes")
- sections.append("- top-level sections:")
- for name, size in top:
- sections.append(f" - `{name}`: {size} bytes")
- sections.append("")
- return "\n".join(sections)
-
-
-def _readme(*, generated_at: str, archive_root: Path, archive: ArchiveCounts, commands: list[CommandRecord]) -> str:
- rows = [
- "| Command | Exit | Duration | Size | Notes |",
- "| --- | ---: | ---: | ---: | --- |",
- ]
- for command in commands:
- rows.append(
- "| `{}` | {} | {:.0f} ms | {} bytes | {} |".format(
- " ".join(str(part) for part in command["argv"]),
- command["exit_code"],
- command["duration_ms"],
- command["stdout_bytes"],
- command["notes"],
- )
- )
- matrix = "\n".join(rows)
- json_breakdown = _json_breakdown_section(commands)
- return f"""# CLI Surface Audit
-
-Generated: {generated_at}
-Archive root: `{archive_root}`
-Archive state: index schema v{archive["schema_version"]}, {archive["sessions"]} sessions, {archive["messages"]} messages
-
-## What This Proves
-
-This artifact is a live command audit over representative Polylogue CLI
-surfaces: help, read-view discovery, daemon/archive status, query explain,
-select, bounded dialogue read, temporal spec, and facets. It is not a complete
-CLI certification; it is a dogfood slice that turns real command behavior into
-concrete product work.
-
-Raw command outputs are in `outputs/`. Timings, byte counts, exit codes, and
-command notes are in `command-matrix.json`.
-
-## Command Matrix
-
-{matrix}
-
-{json_breakdown}
-
-## Current Curation Policy
-
-The default audit intentionally excludes the unbounded dialogue JSON export.
-That diagnostic remains available with `--include-unbounded-dialogue`, but the
-current demo shelf should prefer bounded dialogue output because it demonstrates
-the product path an operator should actually use for large devloop sessions.
-
-## Regeneration
-
-```bash
-devtools workspace cli-surface-audit --out-dir .agent/demos/cli-surface-audit/current
-```
-"""
-
-
-def run_audit(
- *,
- out_dir: Path,
- archive_root: Path,
- include_unbounded_dialogue: bool,
- timeout: int,
-) -> AuditPayload:
- out_dir = out_dir.expanduser()
- outputs = out_dir / "outputs"
- if outputs.exists():
- shutil.rmtree(outputs)
- outputs.mkdir(parents=True, exist_ok=True)
- generated_at = datetime.now().astimezone().strftime("%Y-%m-%d %H:%M:%S %Z")
- archive = _archive_counts(archive_root)
- commands = _run_commands(_commands(include_unbounded_dialogue), outdir=outputs, timeout=timeout)
- payload: AuditPayload = {
- "generated_at": generated_at,
- "archive_root": str(archive_root),
- "archive": archive,
- "include_unbounded_dialogue": include_unbounded_dialogue,
- "commands": commands,
- }
- out_dir.mkdir(parents=True, exist_ok=True)
- (out_dir / "command-matrix.json").write_text(json.dumps(payload, indent=2, sort_keys=True), encoding="utf-8")
- (out_dir / "README.md").write_text(
- _readme(generated_at=generated_at, archive_root=archive_root, archive=archive, commands=commands),
- encoding="utf-8",
- )
- return payload
-
-
-def main(argv: list[str] | None = None) -> int:
- args = _parser().parse_args(argv)
- try:
- payload = run_audit(
- out_dir=args.out_dir,
- archive_root=args.archive_root,
- include_unbounded_dialogue=args.include_unbounded_dialogue,
- timeout=args.timeout,
- )
- except (OSError, sqlite3.Error, subprocess.SubprocessError) as exc:
- print(f"cli-surface-audit: {exc}", file=sys.stderr)
- return 2
- if args.json:
- print(json.dumps(payload, indent=2, sort_keys=True))
- else:
- print(f"captured {len(payload['commands'])} CLI command(s) under {args.out_dir}")
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/click_dispatch.py b/devtools/click_dispatch.py
index 371b0d5d48..5d469378c6 100644
--- a/devtools/click_dispatch.py
+++ b/devtools/click_dispatch.py
@@ -179,10 +179,8 @@ def callback(args: tuple[str, ...], json_flag: bool = False, inner_help: bool =
callback=callback,
params=params,
)
- # Subcommands that use argparse internally need unknown options forwarded
- # as-is rather than rejected by Click's option parser. This allows
- # modules like devtools/task_history.py with their own sub-subcommands and
- # --flags to work transparently.
+ # Subcommands use argparse internally, so unknown options must be forwarded
+ # as-is rather than rejected by Click's option parser.
cmd.allow_extra_args = True
cmd.ignore_unknown_options = True
return cmd
@@ -270,18 +268,7 @@ def _dispatch(argv: list[str]) -> int:
def main(argv: list[str] | None = None) -> int:
- """Entry point for programmatic use of the Click-based devtools CLI.
-
- Converts argv to Click invocation and returns the exit code. Every
- invocation appends a JSONL record to ``.agent/task-history/tasks.jsonl`` so
- agent task history is self-populating (see ``devtools workspace tasks``). Set
- ``POLYLOGUE_TASK_HISTORY_DISABLE=1`` to opt out (also suppressed during a
- ``devtools workspace tasks replay`` to avoid double-logging the outer wrapper).
- """
- import os
- import time
-
- from devtools import task_history as task_history_mod
+ """Entry point for programmatic use of the Click-based devtools CLI."""
try:
assert_polylogue_matches_checkout(_REPO_ROOT, context="devtools")
@@ -289,34 +276,4 @@ def main(argv: list[str] | None = None) -> int:
sys.stderr.write(f"{exc}\n")
return 125
- args_list = list(argv or [])
- if not args_list or args_list[0].startswith("-"):
- # Bare invocation or root option only — skip auto-log.
- return _dispatch(args_list)
-
- command_name = args_list[0]
- inner_args = args_list[1:]
- for spec in sorted(COMMAND_SPECS, key=lambda item: len(item.command_path), reverse=True):
- path = spec.command_path
- if tuple(args_list[: len(path)]) == path:
- command_name = " ".join(path)
- inner_args = args_list[len(path) :]
- break
-
- if task_history_mod.auto_log_disabled():
- return _dispatch(args_list)
-
- started = time.perf_counter()
- exit_code = 0
- try:
- exit_code = _dispatch(args_list)
- return exit_code
- finally:
- duration_ms = (time.perf_counter() - started) * 1000.0
- task_history_mod.record_invocation(
- command=command_name,
- args=inner_args,
- duration_ms=duration_ms,
- exit_code=exit_code,
- cwd=os.getcwd(),
- )
+ return _dispatch(list(argv or []))
diff --git a/devtools/command_catalog.py b/devtools/command_catalog.py
index f6d46cf21e..a6c690501b 100644
--- a/devtools/command_catalog.py
+++ b/devtools/command_catalog.py
@@ -9,43 +9,6 @@
CommandMain = Callable[[list[str] | None], int]
CONTROL_PLANE = "devtools"
-VERIFICATION_LAB_COMMAND_NAMES: tuple[str, ...] = (
- "lab graph",
- "lab lanes",
- "lab policy backlog-hygiene",
- "lab policy bead-graph",
- "lab policy acceptance-contracts",
- "lab policy acceptance-contract-reconcile",
- "lab policy campaign-archive-boundaries",
- "lab policy demo-packet-registry",
- "lab policy demo-tour-freshness",
- "lab policy docs-drift",
- "lab policy insight-honesty",
- "lab policy schema-versioning",
- "lab policy timestamp-doctrine",
- "lab provider completeness",
- "lab probe capture-regression",
- "lab probe cost-reconciliation",
- "lab probe pipeline",
- "lab probe turso",
- "lab projections",
- "lab run",
- "lab smoke",
- "lab schema audit",
- "lab schema commit",
- "lab schema compare",
- "lab schema explain",
- "lab schema generate",
- "lab schema list",
- "lab schema parser-diff",
- "lab schema promote",
- "lab schema roundtrip",
- "lab seed-receipt-compare",
- "lab snapshot read-surface",
- "lab test-economics",
- "lab testmon-blind-spots",
- "lab testmon-proof",
-)
CATEGORY_ORDER: tuple[str, ...] = (
"core",
@@ -102,26 +65,6 @@ def to_dict(self) -> dict[str, object]:
return data
-@dataclass(frozen=True, slots=True)
-class WorkspaceCommandDisposition:
- name: str
- disposition: str
- evidence: str
- replacement: str
- replacement_command: str | None = None
-
-
-@dataclass(frozen=True, slots=True)
-class CatalogBypassSite:
- path: str
- marker: str
- command_name: str | None
- disposition: str
- reason: str
- occurrence_line: int | None = None
- expected_occurrences: int = 0
-
-
COMMAND_SPECS: tuple[CommandSpec, ...] = (
CommandSpec(
"status",
@@ -217,29 +160,12 @@ class CatalogBypassSite:
"Render the command catalog inside docs/devtools.md.",
"devtools.render_devtools_reference",
),
- CommandSpec(
- "render demo-corpus-datasheet",
- "generated surfaces",
- "Render docs/plans/demo-corpus-construct-audit.md from the demo family registry and a measured seed archive.",
- "devtools.render_demo_corpus_datasheet",
- use_when="Refresh or verify the deterministic demo corpus construct datasheet after changing demo families, constructs, or seed semantics.",
- examples=(
- "devtools render demo-corpus-datasheet",
- "devtools render demo-corpus-datasheet --check",
- ),
- ),
CommandSpec(
"render docs-surface",
"generated surfaces",
"Render docs/README.md and the README documentation table.",
"devtools.render_docs_surface",
),
- CommandSpec(
- "render quality-reference",
- "generated surfaces",
- "Render docs/test-quality-workflows.md from executable lane, mutation, and benchmark registries.",
- "devtools.render_quality_reference",
- ),
CommandSpec(
"render query-discovery",
"generated surfaces",
@@ -251,69 +177,6 @@ class CatalogBypassSite:
),
examples=("devtools render query-discovery", "devtools render query-discovery --check"),
),
- CommandSpec(
- "render api-operation-parity",
- "generated surfaces",
- "Render the committed semantic-operation parity matrix and Python facade reference.",
- "devtools.render_api_operation_parity",
- use_when=(
- "Refresh or verify stable Python API operation IDs, cross-surface bindings, intentional exclusions, "
- "and the signature-aware generated section in docs/library-api.md."
- ),
- examples=("devtools render api-operation-parity", "devtools render api-operation-parity --check"),
- ),
- CommandSpec(
- "render mcp-equivalence",
- "generated surfaces",
- "Render docs/generated/mcp-equivalence.json from executable MCP declarations.",
- "devtools.render_mcp_equivalence",
- use_when=(
- "Refresh or verify MCP discovery names, input/output contracts, role gates, operation owners, "
- "Python parity expectations, and disjoint migration ownership after changing the compatibility surface."
- ),
- examples=("devtools render mcp-equivalence", "devtools render mcp-equivalence --check"),
- ),
- CommandSpec(
- "render mcp-tool-index",
- "generated surfaces",
- "Render the generated exhaustive tool-name appendix into docs/mcp-reference.md.",
- "devtools.render_mcp_tool_index",
- use_when=(
- "Keep every registered MCP tool name individually reachable from the docs tree "
- "(tests/infra/mcp.py:EXPECTED_TOOL_NAMES) after adding or removing a tool, so "
- "`devtools verify docs-coverage` stays clean without hand-duplicating the list."
- ),
- examples=("devtools render mcp-tool-index", "devtools render mcp-tool-index --check"),
- ),
- CommandSpec(
- "render product-workflows",
- "generated surfaces",
- "Render docs/product/workflows.md from executable query-action workflow registries.",
- "devtools.render_product_workflows",
- use_when=(
- "Refresh or verify the product query-action workflow contract after changing action contracts, "
- "read-view surfaces, completion behavior, or workflow golden paths (#2305)."
- ),
- examples=(
- "devtools render product-workflows",
- "devtools render product-workflows --check",
- ),
- ),
- CommandSpec(
- "render public-claims",
- "generated surfaces",
- "Render README, launch, findings-page, and verified-export claim views from FINDING assertions.",
- "devtools.render_public_claims",
- use_when=(
- "Refresh public claim Markdown/JSON and the generated YAML compatibility view after changing "
- "FINDING seeds, judgments, capability declarations, or 37t.14 verdict receipts."
- ),
- examples=(
- "devtools render public-claims",
- "devtools render public-claims --check",
- "devtools render public-claims --archive-root /path/to/archive --verdicts /path/to/verdicts.json",
- ),
- ),
CommandSpec(
"render pages",
"generated surfaces",
@@ -331,7 +194,6 @@ class CatalogBypassSite:
examples=(
"devtools render visual-tapes",
"devtools render visual-tapes --capture",
- "devtools render visual-tapes --check",
),
),
CommandSpec(
@@ -344,18 +206,20 @@ class CatalogBypassSite:
featured=True,
),
CommandSpec(
- "verify public-claims",
+ "verify ci-commands",
"verification",
- "Verify generated public-claim views, preset parity, sanitized refs, coverage markers, and retired copy.",
- "devtools.public_claims",
- use_when=(
- "Check externally visible claims after changing README, demos, findings, FINDING assertions, "
- "capability declarations, or evidence-integrity receipts."
- ),
- examples=(
- "devtools verify public-claims",
- "devtools verify public-claims --json",
- ),
+ "Validate devtools invocations in structured CI run fields.",
+ "devtools.verify_ci_commands",
+ use_when="Catch CI scripts that reference a removed or misspelled devtools command.",
+ examples=("devtools verify ci-commands", "devtools verify ci-commands --json"),
+ ),
+ CommandSpec(
+ "verify doc-commands",
+ "verification",
+ "Validate executable documentation examples against live command inventories.",
+ "devtools.verify_doc_commands",
+ use_when="Catch README and documentation examples that reference an unknown command path or flag.",
+ examples=("devtools verify doc-commands", "devtools verify doc-commands --json"),
),
CommandSpec(
"verify corpus-fidelity",
@@ -387,21 +251,6 @@ class CatalogBypassSite:
"--ground-truth-root codex-session=/path/to/codex --receipt /path/to/schema-inference-gate-receipt.json --json",
),
),
- CommandSpec(
- "release readiness",
- "release",
- "Validate the externally-presentable release gate definition.",
- "devtools.release_readiness",
- use_when=(
- "Check that the release-readiness gate document, required local commands, "
- "and release PR evidence template are still coherent before touching a release PR."
- ),
- examples=(
- "devtools release readiness",
- "devtools release readiness --json",
- "devtools release readiness --release-body-file /tmp/release-pr-body.md",
- ),
- ),
CommandSpec(
"lab provider completeness",
"verification lab",
@@ -431,17 +280,6 @@ class CatalogBypassSite:
),
featured=True,
),
- CommandSpec(
- "reindex-canary",
- "verification",
- "Run the product's representative inactive-generation reindex canary.",
- "devtools.reindex_canary",
- use_when="Exercise the bounded semantic reindex canary before paying for a full rebuild.",
- examples=(
- "devtools reindex-canary --archive-root /path/to/isolated-archive --input /path/to/index.db --schema-inference-receipt /path/to/schema-inference-gate-receipt.json --sample 100 --report /path/to/canary.json --no-promote",
- "devtools reindex-canary --archive-root /path/to/isolated-archive --schema-inference-receipt /path/to/schema-inference-gate-receipt.json --pathology-session-id codex-session:whale --report /path/to/canary.json --no-promote",
- ),
- ),
CommandSpec(
"verify coverage",
"verification",
@@ -457,7 +295,7 @@ class CatalogBypassSite:
CommandSpec(
"verify mutation-freshness",
"verification",
- "Verify fresh mutation campaigns meet their declared kill-rate thresholds.",
+ "Verify executable mutation campaigns meet the selected freshness and kill-rate thresholds.",
"devtools.verify_mutation_freshness",
use_when=(
"Enforce mutation campaign freshness and kill-rate thresholds after a rotating CI campaign "
@@ -465,47 +303,18 @@ class CatalogBypassSite:
),
examples=(
"devtools verify mutation-freshness --enforce-kill-rate",
- "devtools verify mutation-freshness --yaml .local/mutation-campaigns/index.yaml --strict",
- ),
- ),
- CommandSpec(
- "lab lanes",
- "verification lab",
- "Run named validation lanes.",
- "devtools.run_validation_lanes",
- use_when="List, dry-run, or execute authored validation lanes from the executable lane registry.",
- examples=(
- "devtools lab lanes --list",
- "devtools lab lanes --lane frontier-local",
- "devtools lab lanes --lane live-archive-smoke --dry-run",
+ "devtools verify mutation-freshness --strict --default-freshness-days 30",
),
),
CommandSpec(
"lab graph",
"verification lab",
- "Render the runtime artifact, operation, and scenario-coverage map.",
+ "Render the runtime artifact and operation graph.",
"devtools.artifact_graph",
- use_when="Inspect the authored runtime graph and see which scenarios currently cover declared artifacts and operations.",
+ use_when="Inspect declared runtime artifacts, operations, paths, and maintenance targets.",
examples=(
"devtools lab graph",
"devtools lab graph --json",
- "devtools lab graph --strict",
- ),
- ),
- CommandSpec(
- "lab test-economics",
- "verification lab",
- "Report per-package coverage/fix-density/test-cost economics (polylogue-9e5.11).",
- "devtools.test_economics_report",
- use_when=(
- "Decide where test-writing effort or test-suite pruning actually pays off, by "
- "cross-referencing coverage percent, historical fix-commit density, testmon "
- "wall-time cost exposure, and testmon selection fan-out per top-level package."
- ),
- examples=(
- "devtools lab test-economics",
- "devtools lab test-economics --json",
- "devtools lab test-economics --write docs/test-economics.md",
),
),
CommandSpec(
@@ -520,53 +329,6 @@ class CatalogBypassSite:
),
examples=("devtools lab testmon-proof", "devtools lab testmon-proof --json"),
),
- CommandSpec(
- "lab testmon-blind-spots",
- "verification lab",
- "Audit coverage-known files that are absent from the testmon fingerprint graph.",
- "devtools.testmon_blind_spot_audit",
- use_when=(
- "Inspect an existing coverage JSON report against an existing pytest-testmon database. "
- "Declaration-only modules are reported separately from executable validator risk; this command "
- "does not run pytest or regenerate coverage."
- ),
- examples=(
- "devtools lab testmon-blind-spots",
- "devtools lab testmon-blind-spots --json",
- "devtools lab testmon-blind-spots --coverage-json path/to/coverage.json --testmon-db path/to/testmondata",
- ),
- ),
- CommandSpec(
- "lab pytest-witness-repetitions",
- "verification lab",
- "Repeat the exact optimize, WAL, and embedding seed-hang witnesses with durable receipts.",
- "devtools.pytest_witness_repetitions",
- use_when=(
- "Establish that the historical periodic optimize, WAL checkpoint, and embedding backlog "
- "lifecycle witnesses survive consecutive isolated and xdist runs. Each attempt uses the ordinary "
- "managed pytest/supervisor path; failures and timeouts are retained rather than retried."
- ),
- examples=(
- "devtools lab pytest-witness-repetitions",
- "devtools lab pytest-witness-repetitions --attempts 2 --xdist-workers 3 --json",
- ),
- ),
- CommandSpec(
- "lab seed-receipt-compare",
- "verification lab",
- "Compare two workload receipts for a clean, like-for-like seed/incident proof (polylogue-b054.1.1.3).",
- "devtools.seed_receipt_compare",
- use_when=(
- "Judge a seed-testmon or focused pytest run's resource receipt against a named baseline "
- "receipt (e.g. a prior incident) — confirms both runs share workload identity and terminated "
- "cleanly, then scores wall-time speedup and peak-PSS ceiling targets, naming a blocker and "
- "linked follow-up for any unmet target instead of silently dropping it."
- ),
- examples=(
- "devtools lab seed-receipt-compare --baseline incident.json --candidate current.json",
- "devtools lab seed-receipt-compare --baseline incident.json --candidate current.json --json",
- ),
- ),
CommandSpec(
"bench ingest-amplification",
"benchmarking",
@@ -603,13 +365,6 @@ class CatalogBypassSite:
"devtools bench ingest-throughput --batches 20 --seed 2391",
),
),
- CommandSpec(
- "bench coordination-latency",
- "benchmarking",
- "Measure compact coordination status p50/p95 with raw stage samples.",
- "devtools.coordination_latency_probe",
- examples=("devtools bench coordination-latency --samples 21 --out .local/coordination-latency.json",),
- ),
CommandSpec(
"lab snapshot read-surface",
"verification lab",
@@ -657,40 +412,6 @@ class CatalogBypassSite:
"devtools workspace worktree-gc --apply --force",
),
),
- CommandSpec(
- "workspace backlog-calibration",
- "workspace",
- "Measured lead-time/discovery/staleness distributions over the bead corpus.",
- "devtools.backlog_calibration",
- use_when=(
- "Re-fit the numbers a backlog-execution plan rests on instead of guessing them: "
- "closed-bead lead-time percentiles split by priority/type/epic-membership/dependency "
- "degree, a censoring-honest survival view (closed-only medians are survivorship-"
- "biased), close-reason classification measuring how much of the backlog closes with "
- "no implementation (already-satisfied/obsolete/duplicate), and created-vs-closed "
- "discovery dynamics (does the backlog drain?). Optionally calibrates PR open->merge "
- "latency by size from a gh dump. Answers a different question than "
- "`workspace beads-state-report` (population shape and graph hygiene, point-in-time) "
- "and `workspace bead-cluster` (what to batch next): this is duration *models* over "
- "history, meant to be re-run as the corpus grows so plans stop quoting stale guesses."
- ),
- examples=(
- "devtools workspace backlog-calibration",
- "devtools workspace backlog-calibration --input beads.jsonl --json",
- "devtools workspace backlog-calibration --prs prs.json",
- ),
- ),
- CommandSpec(
- "workspace bead-batch-show",
- "workspace",
- "Batch-show beads: id, status, prio, title, desc head, deps, notes tail.",
- "devtools.bead_batch_show",
- use_when=(
- "Skim several beads at once (e.g. a fanout cluster or a discovered-follow-up batch) "
- "without a separate `bd show` round-trip per id."
- ),
- examples=("devtools workspace bead-batch-show polylogue-kapb polylogue-2yax",),
- ),
CommandSpec(
"workspace bead-cluster",
"workspace",
@@ -701,10 +422,7 @@ class CatalogBypassSite:
"footprint (cluster into one branch/PR sweep) vs. which are genuinely disjoint "
"(safe to run as parallel worktree lanes), and flag contention -- beads that touch "
"the same durable migration slot or the same generated surface even without an "
- "exact file-path overlap. Answers a different question than "
- "`workspace delivery-gate-status` (gate-progress board): this is footprint/overlap "
- "clustering over the same live bead data, not gate percentage. Footprints are "
- "advisory -- verify on claim."
+ "exact file-path overlap. Footprints are advisory, so verify them when claiming work."
),
examples=(
"devtools workspace bead-cluster",
@@ -714,25 +432,6 @@ class CatalogBypassSite:
"devtools workspace bead-cluster --input ready.json --validate-roster",
),
),
- CommandSpec(
- "workspace lane-brief",
- "workspace",
- "Generate a dispatch brief for a bead lane with live footprint/prior-art evidence.",
- "devtools.lane_brief",
- use_when=(
- "Before dispatching a batch of bead ids as one lane/branch to a subagent, produce a "
- "markdown brief carrying the full bead records plus LIVE evidence: every file path "
- "mentioned in the bead text is checked against the working tree (exists? line count? "
- "last 3 commits?) so a dispatcher does not hand a subagent stale bead prose, and closed "
- "beads mentioning the same paths are surfaced as prior art. Sections the tool cannot "
- "fill (measured baseline, non-goals) are emitted as explicit placeholders, never "
- "silently dropped."
- ),
- examples=(
- "devtools workspace lane-brief polylogue-abc polylogue-def",
- "devtools workspace lane-brief polylogue-ei94 --out .agent/scratch/lane-ei94.md",
- ),
- ),
CommandSpec(
"workspace lane-init",
"workspace",
@@ -793,7 +492,7 @@ class CatalogBypassSite:
CommandSpec(
"workspace merge-gate",
"workspace",
- "Structural pre-merge safety check: fresh local-verification receipt + no late review comments.",
+ "Structural pre-merge safety check: fresh local verification + resolved review threads.",
"devtools.merge_gate",
use_when=(
"Immediately before squash-merging any PR in a merge train, replacing coordinator memory "
@@ -801,17 +500,17 @@ class CatalogBypassSite:
'per-PR) with a check that fails closed. `record --command "..."` requires the current '
"checkout to already be the PR's exact head commit with a clean tree (it refuses otherwise), "
"first validates the same versioned PR-scope carrier CircleCI checks, then runs a local verification "
- "command, and persists a receipt flagging commands that look like they skip tests (e.g. "
- "`verify --quick`). `check ` polls review comments across a real grace window (default "
- "3x20s, covering CodeRabbit's 30-60s late-arrival window) and BLOCKs unless a receipt exists "
- "for the CURRENT head sha within a freshness window with exit_code 0, and no review comment's "
- "created_at is newer than the head commit's timestamp unless explicitly `ack`'d for that exact "
- "head sha. The receipt binds the carrier digest plus a fresh head- and Bead-bound scope attestation, so a changed scope or Bead state requires re-recording. Motivated by two 2026-08-01 incidents: PR #3502 merged before CodeRabbit's findings "
+ "command and persists its typed verification scope. `check ` polls structured GitHub "
+ "review-thread state across a real grace window (default 3x20s, covering CodeRabbit's "
+ "30-60s late-arrival window) and BLOCKs unless a receipt exists for the CURRENT head sha "
+ "within a freshness window with exit_code 0, every review thread is resolved, and GitHub's "
+ "review decision is not CHANGES_REQUESTED. The receipt binds the carrier digest plus a fresh "
+ "head- and Bead-bound scope attestation, so a changed scope or Bead state requires re-recording. "
+ "Motivated by two 2026-08-01 incidents: PR #3502 merged before CodeRabbit's findings "
"posted, and PR #3517 nearly merged with a 43-test regression no CI check or review comment "
"ever flagged -- plus review findings on this tool itself (recording from an unrelated "
- "checkout, a --quick example that would have missed its own motivating regression, a single "
- "comment snapshot instead of a grace-period poll, and no way to triage a false-positive late "
- "comment without an empty commit). `check --post-status` (polylogue-1cbeh) posts the "
+ "checkout, a --quick example that would have missed its own motivating regression, and a single "
+ "review snapshot instead of a grace-period poll). `check --post-status` (polylogue-1cbeh) posts the "
"verdict as a GitHub commit status (`context=merge-gate`, success/failure) on the PR's "
"current head sha via `gh api repos/{owner}/{repo}/statuses/{sha}` -- this is what lets "
"branch protection or `gh pr merge --auto` gate on the same verdict instead of a "
@@ -822,7 +521,6 @@ class CatalogBypassSite:
"devtools workspace merge-gate check 3517",
"devtools workspace merge-gate check 3517 --json --max-age-s 7200 --poll-rounds 1",
"devtools workspace merge-gate check 3517 --post-status",
- 'devtools workspace merge-gate ack 3517 123456789 --reason "already fixed upstream, false positive"',
),
),
CommandSpec(
@@ -854,26 +552,6 @@ class CatalogBypassSite:
'devtools workspace merge record-full-verify --command "devtools verify --all"',
),
),
- CommandSpec(
- "workspace merge-conductor",
- "workspace",
- "Mechanical-conflict triage for the PR merge train (dry-run by default).",
- "devtools.merge_conductor",
- use_when=(
- "Before or during a merge train, classify each roster PR's conflicting/modified files "
- "into AUTO-RESOLVABLE mechanical classes (.beads/issues.jsonl take-master, regenerable "
- "surfaces) vs ESCALATE classes (schema migrations, hooks config, anything else) and "
- "detect cross-PR contention (two PRs claiming the same migration slot or generated-"
- "surface family). Implements the mechanical slice of the polylogue-ei94 merge-conductor "
- "design. --execute only touches AUTO-RESOLVABLE PRs, in a scratch worktree, and aborts "
- "back to ESCALATE on any deviation; escalate-class PRs are never touched under --execute."
- ),
- examples=(
- "devtools workspace merge-conductor --pr 3301 --pr 3302",
- "devtools workspace merge-conductor --pr 3301 --json",
- "devtools workspace merge-conductor --pr 3301 --execute",
- ),
- ),
CommandSpec(
"workspace bead-reimport-guard",
"workspace",
@@ -894,24 +572,6 @@ class CatalogBypassSite:
"devtools workspace bead-reimport-guard export /tmp/issues-snapshot.jsonl",
),
),
- CommandSpec(
- "workspace delivery-gate-status",
- "workspace",
- "Per-release-gate progress board over .beads/issues.jsonl (delivery: / lane: overlay).",
- "devtools.delivery_gate_status",
- use_when=(
- "Check overall delivery-gate progress (R0-normalize through N-horizon) -- percent "
- "complete, ready/blocked/in-progress counts, and the active frontier gate's exit "
- "criterion. --fresh re-exports .beads/issues.jsonl first since bd updates do not "
- "immediately re-export."
- ),
- examples=(
- "devtools workspace delivery-gate-status",
- "devtools workspace delivery-gate-status --fresh",
- "devtools workspace delivery-gate-status --json",
- "devtools workspace delivery-gate-status --gate delivery:A-trust-floor",
- ),
- ),
CommandSpec(
"demo real-slice-screen",
"workspace",
@@ -957,22 +617,6 @@ class CatalogBypassSite:
"devtools workspace dev-loop --inspect-run .cache/dev-loop/ --json",
),
),
- CommandSpec(
- "workspace frontier",
- "workspace",
- "Derive a complete, non-mutating execution focus from live Beads state.",
- "devtools.frontier_report",
- use_when=(
- "During Direction, Velocity, or wait-ahead windows, distinguish the full ambition, admitted "
- "active set, current claims, dependency-ready work, and resource-permitted execution focus before "
- "claiming or dispatching work."
- ),
- examples=(
- "devtools workspace frontier",
- "devtools workspace frontier --json",
- "devtools workspace frontier --out .agent/task-history/frontier-latest.md",
- ),
- ),
CommandSpec(
"workspace deployment-smoke",
"workspace",
@@ -1072,20 +716,6 @@ class CatalogBypassSite:
"devtools workspace raw-live-source-reconciliation --limit 500 --sample-limit 20",
),
),
- CommandSpec(
- "workspace chatgpt-lifecycle-anchor-audit",
- "workspace",
- "Census the current quarantined ChatGPT corpus for lifecycle-anchor conflicts.",
- "devtools.chatgpt_lifecycle_anchor_audit",
- use_when=(
- "Run the read-only parser-to-classifier census behind the historical ChatGPT mapping-order defect. "
- "It emits only aggregate, sanitized evidence and never reclassifies source rows or graph gates."
- ),
- examples=(
- "devtools workspace chatgpt-lifecycle-anchor-audit --archive-root /path/to/archive",
- "devtools workspace chatgpt-lifecycle-anchor-audit --archive-root /path/to/archive --receipt docs/audits/receipt.json",
- ),
- ),
CommandSpec(
"workspace raw-live-source-reconciliation-apply",
"workspace",
@@ -1496,21 +1126,6 @@ class CatalogBypassSite:
"devtools workspace temporal-read-profile --query 'repo:polylogue devloop' --limit 3 --out .local/temporal-profile.json",
),
),
- CommandSpec(
- "workspace temporal-devloop",
- "workspace",
- "Compose git and operating-log events into a temporal evidence window.",
- "devtools.devloop_temporal",
- use_when=(
- "Dogfood temporal analysis on the current devloop without inventing a bespoke report shape: "
- "git commits and OPERATING-LOG headings are normalized as event families and projected through "
- "the shared TemporalEvidenceWindow."
- ),
- examples=(
- "devtools workspace temporal-devloop --since 2026-06-30T00:00:00+02:00 --json",
- "devtools workspace temporal-devloop --out .agent/demos/14-devloop-temporal-dogfood/devloop-events.json",
- ),
- ),
CommandSpec(
"workspace temporal-archive-aggregates",
"workspace",
@@ -1523,7 +1138,7 @@ class CatalogBypassSite:
),
examples=(
"devtools workspace temporal-archive-aggregates --json",
- "devtools workspace temporal-archive-aggregates --out-dir .agent/demos/01-real-archive-temporal-devloops",
+ "devtools workspace temporal-archive-aggregates --out-dir .local/temporal-archive-aggregates",
),
),
CommandSpec(
@@ -1539,7 +1154,7 @@ class CatalogBypassSite:
examples=(
"devtools workspace lineage-validation --json",
"devtools workspace lineage-validation --sample-prefix-sharing 100 --json",
- "devtools workspace lineage-validation --out-dir .agent/demos/lineage-validation/current",
+ "devtools workspace lineage-validation --out-dir .local/evidence/lineage-validation/current",
),
),
CommandSpec(
@@ -1554,24 +1169,22 @@ class CatalogBypassSite:
examples=(
"devtools workspace affordance-usage --days 7 --json",
"devtools workspace affordance-usage --detail-pattern codebase-memory --detail-pattern search_code --days 30",
- "devtools workspace affordance-usage --out-dir .agent/demos/agent-affordance-usage",
+ "devtools workspace affordance-usage --out-dir .local/evidence/agent-affordance-usage",
),
),
CommandSpec(
- "workspace demo-shelf",
+ "workspace claim-vs-evidence",
"workspace",
- "Refresh or verify current demo shelf indexes.",
- "devtools.demo_shelf",
+ "Analyze structured failures and the assistant behavior that followed.",
+ "devtools.claim_vs_evidence",
use_when=(
- "After curating .agent/demos or another explicit current demo shelf, regenerate "
- "MANIFEST.readable.json and SUMMARY_INDEX.json from one deterministic helper. "
- "Declarative read packages own portable readable bundles; the shelf is the best current set, "
- "not an append-only archive."
+ "Measure bounded, origin-stratified follow-up behavior from structural tool-result failures; "
+ "the report preserves ambiguous outcomes, calibration, sensitivity windows, and separate "
+ "usage/cost lanes instead of treating prose as the failure oracle."
),
examples=(
- "devtools workspace demo-shelf",
- "devtools workspace demo-shelf --check",
- "devtools workspace demo-shelf --root /realm/project/sinex/.agent/demos --json",
+ "devtools workspace claim-vs-evidence --json",
+ "devtools workspace claim-vs-evidence --limit 5000 --out-dir .local/evidence/claim-vs-evidence",
),
),
CommandSpec(
@@ -1586,37 +1199,7 @@ class CatalogBypassSite:
),
examples=(
"devtools workspace degraded-archive-proof --json",
- "devtools workspace degraded-archive-proof --out-dir .agent/demos/degraded-archive-proof/current --json",
- ),
- ),
- CommandSpec(
- "workspace cli-surface-audit",
- "workspace",
- "Capture a current-curated CLI surface audit demo.",
- "devtools.cli_surface_audit",
- use_when=(
- "Refresh the CLI surface audit shelf through one reusable command that captures representative "
- "help, status, query, read, and facets outputs while keeping large unbounded diagnostics opt-in."
- ),
- examples=(
- "devtools workspace cli-surface-audit",
- "devtools workspace cli-surface-audit --out-dir .agent/demos/cli-surface-audit/current --json",
- "devtools workspace cli-surface-audit --include-unbounded-dialogue",
- ),
- ),
- CommandSpec(
- "workspace claim-vs-evidence",
- "workspace",
- "Build a structured failure follow-up claim-vs-evidence demo.",
- "devtools.claim_vs_evidence",
- use_when=(
- "Produce a fast, bounded report over structured tool failures and the immediately following "
- "assistant turn, using tool_result is_error/exit_code as the evidence anchor instead of "
- "prose-mined outcome claims."
- ),
- examples=(
- "devtools workspace claim-vs-evidence --json",
- "devtools workspace claim-vs-evidence --limit 5000 --out-dir .agent/demos/claim-vs-evidence",
+ "devtools workspace degraded-archive-proof --out-dir .local/evidence/degraded-archive-proof/current --json",
),
),
CommandSpec(
@@ -1634,18 +1217,6 @@ class CatalogBypassSite:
"devtools workspace read-package --spec package.yaml --session-id 019f... --out-dir product-read --dry-run --json",
),
),
- CommandSpec(
- "lab projections",
- "verification lab",
- "Render the authored scenario-bearing verification projections.",
- "devtools.scenario_projections",
- use_when="Inspect the unified projection inventory that feeds runtime coverage, generated docs, and control-plane maps.",
- examples=(
- "devtools lab projections",
- "devtools lab projections --source-kind validation-lane --artifact-target session_insight_rows",
- "devtools lab projections --json",
- ),
- ),
CommandSpec(
"verify agent-integration",
"verification",
@@ -1658,17 +1229,6 @@ class CatalogBypassSite:
"devtools verify agent-integration --require-live",
),
),
- CommandSpec(
- "verify closure-matrix",
- "verification",
- "Verify docs/plans/test-closure-matrix.yaml stays grounded in the realized tree.",
- "devtools.verify_closure_matrix",
- use_when=(
- "Keep the per-domain test-closure matrix honest — fails when a declared target file or "
- "representative test path is missing, or when a row violates the gate schema."
- ),
- examples=("devtools verify closure-matrix", "devtools verify closure-matrix --json"),
- ),
CommandSpec(
"bench slo",
"benchmarking",
@@ -1703,79 +1263,6 @@ class CatalogBypassSite:
"devtools bench help-latency --repeats 5 --out .local/help-latency.json",
),
),
- CommandSpec(
- "verify manifests",
- "verification",
- "Verify internal consistency across all docs/plans/*.yaml manifest files.",
- "devtools.verify_manifests",
- use_when=(
- "Catch malformed manifests, duplicate rule IDs, missing required fields, "
- "and cross-manifest reference inconsistencies."
- ),
- examples=("devtools verify manifests",),
- ),
- CommandSpec(
- "verify doc-commands",
- "verification",
- "Verify README/docs command examples resolve to live polylogue, polylogued, and devtools commands.",
- "devtools.verify_doc_commands",
- use_when=(
- "Catch doc drift away from the daemon-first command surface. "
- "Fails when README.md or any docs/**/*.md references a subcommand "
- "that is not registered, or a stale invocation like "
- "'polylogued run --enable-api' / 'polylogue run --source'."
- ),
- examples=("devtools verify doc-commands", "devtools verify doc-commands --json"),
- ),
- CommandSpec(
- "verify docs-coverage",
- "verification",
- "Verify every public CLI command, MCP tool, config key, and stable daemon route is named in the docs tree.",
- "devtools.verify_docs_coverage",
- use_when=(
- "Catch doc drift in the other direction from doc-commands: a real public surface "
- "(CLI command, MCP tool, config key, stable daemon route) shipped with zero doc-tree "
- "mention. Fails naming the exact missing entry (polylogue-3tl.9). Pre-existing gaps "
- "are tracked in docs/plans/docs-coverage-baseline.yaml as a ratchet, not an allowlist "
- "to extend."
- ),
- examples=("devtools verify docs-coverage", "devtools verify docs-coverage --json"),
- ),
- CommandSpec(
- "verify ci-workflows",
- "verification",
- "Verify CI workflow files reference locally-known devtools commands and existing paths.",
- "devtools.verify_ci_workflows",
- use_when=(
- "Catch CI workflow files that reference unregistered devtools commands or "
- "non-existent paths. Checks only locally verifiable facts — not remote CI state."
- ),
- examples=("devtools verify ci-workflows", "devtools verify ci-workflows --json"),
- ),
- CommandSpec(
- "verify catalog-bypasses",
- "verification",
- "Reject direct devtools module or script execution outside sanctioned adapters.",
- "devtools.verify_catalog_bypasses",
- use_when=(
- "Check workflow run blocks, repository hooks, and devtools process-launch sites for direct "
- "python -m devtools.X or python devtools/X.py execution that bypasses the command catalog."
- ),
- examples=("devtools verify catalog-bypasses", "devtools verify catalog-bypasses --json"),
- ),
- CommandSpec(
- "verify test-infra-currency",
- "verification",
- "Verify tests/infra/ helpers reference only tables that exist in the current SCHEMA_VERSION.",
- "devtools.verify_test_infra_currency",
- use_when=(
- "Catch helpers that target renamed or removed tables (#1208). "
- "When SCHEMA_VERSION bumps, helper SQL drifting away from the live "
- "schema is invisible to testmon-selected runs until an unrelated change "
- "invalidates the affected tests."
- ),
- examples=("devtools verify test-infra-currency", "devtools verify test-infra-currency --json"),
- ),
CommandSpec(
"lab policy schema-versioning",
"verification lab",
@@ -1789,235 +1276,21 @@ class CatalogBypassSite:
),
examples=("devtools lab policy schema-versioning", "devtools lab policy schema-versioning --json"),
),
- CommandSpec(
- "lab policy classifier-fingerprints",
- "verification lab",
- "Verify parser/classifier decision-boundary changes are declared as reparse-requiring or acknowledged.",
- "devtools.verify_classifier_fingerprints",
- use_when=(
- "Catch the gap `lab policy schema-versioning` cannot see (polylogue-gucv): a parser/classifier "
- "under polylogue/sources/ or polylogue/archive/artifact_taxonomy/ (looks_like*/classify_artifact* "
- "functions) changes what it accepts for identical input bytes without any INDEX_SCHEMA_VERSION "
- "bump at all, so already-indexed rows go silently stale with no signal a reparse was needed "
- "(PR #3428 shipped exactly this, green, against the version-keyed gate)."
- ),
- examples=(
- "devtools lab policy classifier-fingerprints",
- "devtools lab policy classifier-fingerprints --json",
- "devtools lab policy classifier-fingerprints --ack polylogue/sources/parsers/foo.py:looks_like_x "
- "--reason 'only tightens a shape that never validly matched' --ref polylogue-abcd",
- ),
- ),
- CommandSpec(
- "lab policy raw-payload-hash-purity",
- "verification lab",
- "Verify no raw-capture write path splices a synthesized literal onto captured bytes before hashing.",
- "devtools.verify_raw_payload_hash_purity",
- use_when=(
- "Prevent a regression of polylogue-u19l's confirmed bug: sources/live/batch.py used to prepend a "
- "synthetic session_meta header onto every Codex append capture before hashing/storing it, so the "
- "stored blob was never a literal byte-slice of the live file, permanently defeating live-source "
- "byte-identity verification for ~59GB of raw rows. Statically forbids concatenating a synthesized "
- "literal (bytes/str constant, f-string, json.dumps()/.encode() result) onto captured bytes anywhere "
- "in the raw-capture write-path modules (WRITE_PATH_MODULES)."
- ),
- examples=("devtools lab policy raw-payload-hash-purity", "devtools lab policy raw-payload-hash-purity --json"),
- ),
- CommandSpec(
- "lab policy table-exists-duplication",
- "verification lab",
- "Verify no module outside storage/introspection.py redefines table_exists/column_exists/index_exists.",
- "devtools.verify_table_exists_duplication",
- use_when=(
- "Keep polylogue-48h's consolidation from silently regrowing: ~25 independently maintained "
- "_table_exists/_column_exists/_index_exists copies (each trivially small and subtly different) "
- "were merged into polylogue.storage.introspection. A grep-based tripwire forbidding a new "
- "top-level def with one of the retired names outside that module."
- ),
- examples=(
- "devtools lab policy table-exists-duplication",
- "devtools lab policy table-exists-duplication --json",
- ),
- ),
- CommandSpec(
- "lab policy position-derived-identity",
- "verification lab",
- "Verify no parser mints cross-revision comparison identity from positional/index data.",
- "devtools.verify_position_derived_identity",
- use_when=(
- "Prevent a regression of polylogue-hith/qkuq's already-fixed attachment-id bug (a synthetic id "
- "seeded partly by array index was unstable across export vintages that reorder/insert entries, "
- "manufacturing false divergence in revision-authority membership comparison) and catch new "
- "occurrences of the same shape (polylogue-gysk3 found the identical hazard still live for "
- "provider_message_id, the sole input to message_identity_hash). Statically scans "
- "polylogue/sources/parsers/ for an identity-bearing field constructed from an f-string/format/"
- "concatenation referencing a loop index/position variable, either inline or via a local variable."
- ),
- examples=(
- "devtools lab policy position-derived-identity",
- "devtools lab policy position-derived-identity --json",
- "devtools lab policy position-derived-identity --ack "
- "'polylogue/sources/parsers/foo.py:parse:provider_message_id' "
- "--reason 'tracked in polylogue-xxxx, not fixed inline' --ref polylogue-xxxx",
- ),
- ),
- CommandSpec(
- "lab policy raw-authority-frontier-executability",
- "verification lab",
- "Verify every raw-authority frontier state has a reachable actuator.",
- "devtools.verify_raw_authority_frontier_executability",
- use_when=(
- "polylogue-w32w / polylogue-lb39z (Phase 1, item 4): "
- "RawAuthorityFrontierItem.__post_init__ raises if a CONSTRUCTED item pairs a "
- "dispatched actuator (_APPLY_DISPATCHED_ACTUATORS) with a non-executable state "
- "(_EXECUTABLE_STATES) -- but that only fires when a test or live classification "
- "actually builds one; a new frontier state or re-paired actuator can ship an "
- "unexercised branch that stays silent until it accumulates against real archive "
- "data (the original defect: 4,174 blockers demanding an unreachable actuator, "
- "undetected for weeks). This lint statically enumerates every literal "
- "(state, actuator) construction site in polylogue/storage/raw_reconciler.py "
- "(_item(...) and _StrategyOverride(...) calls) and re-checks the same invariant "
- "at review time, independent of test coverage."
- ),
- examples=(
- "devtools lab policy raw-authority-frontier-executability",
- "devtools lab policy raw-authority-frontier-executability --json",
- ),
- ),
- CommandSpec(
- "lab policy acceptance-contracts",
- "verification lab",
- "Validate structured Beads acceptance contracts and the committed contract manifest.",
- "devtools.beads_acceptance_contracts",
- use_when=(
- "Run the source-digest-bound acceptance-contract gate before shipping Beads state. "
- "It validates typed contract fields, rendered criteria equality, planner-review "
- "dispatch markers, safety and receipt clauses, and the committed 218-Bead manifest."
- ),
- examples=(
- "devtools lab policy acceptance-contracts",
- "devtools lab policy acceptance-contracts --json",
- ),
- ),
- CommandSpec(
- "lab policy acceptance-contract-reconcile",
- "verification lab",
- "Reconcile canonical acceptance contracts with a read-only live Beads export.",
- "devtools.beads_acceptance_reconciliation",
- use_when=(
- "Run this file-level dry run before a coordinator applies acceptance contracts. "
- "It reports authority differences, refuses source-digest mismatches, and emits "
- "a targeted wave made from live rows with only acceptance_criteria and "
- "metadata.acceptance_contract_v1 changed. It never invokes bd or mutates Dolt."
- ),
- examples=(
- "devtools lab policy acceptance-contract-reconcile --repository .beads/issues.jsonl "
- "--live /path/live.jsonl --wave /path/targeted.jsonl --report /path/report.json",
- "devtools lab policy acceptance-contract-reconcile --verify-repository .beads/issues.jsonl "
- "--verify-report /path/report.json --verify-before /path/before.jsonl "
- "--verify-after /path/after.jsonl --verify-wave /path/targeted.jsonl --json",
- ),
- ),
- CommandSpec(
- "lab policy acceptance-contract-apply",
- "verification lab",
- "Apply an exact acceptance wave to a guarded JSONL file copy.",
- "devtools.beads_acceptance_applier",
- use_when=(
- "Exercise the local guarded applier against an exact reconciliation report and wave. "
- "This route never invokes bd or mutates the Beads database and accepts an identical "
- "prior output idempotently."
- ),
- examples=(
- "devtools lab policy acceptance-contract-apply --repository .beads/issues.jsonl "
- "--before RUN/live-before.jsonl --wave RUN/targeted.jsonl --report RUN/reconciliation.json "
- "--output RUN/applied.jsonl --json",
- ),
- ),
- CommandSpec(
- "lab policy backlog-hygiene",
- "verification lab",
- "Verify Beads backlog structure invariants (.beads/issues.jsonl).",
- "devtools.verify_backlog_hygiene",
- use_when=(
- "Enforce the standing backlog-hygiene invariant lint (polylogue-8jg9.1): 20 checks "
- "over the Beads export catching dangling dependency refs, blocks-cycles, missing "
- "horizon/AC/design content on tech-tree beads, P0/P1 beads without acceptance "
- "criteria, unlabeled non-epic beads, epics with no members or description, stale "
- "'adopted' decisions left open, duplicate titles, bead ids named but never "
- "created, an unclean/corrupt bd JSONL sync receipt (S1, consuming "
- "polylogue-gxjh.1's monotonic sync contract), an active leaf that is itself an "
- "epic (F1), an active leaf with a missing/dangling/mismatched program ref (F2), a "
- "stale in_progress claim with no recent activity (F3, configurable window), and a "
- "frontier_program=active program with no admitted active leaves (F4) -- catches "
- "backlog structure drift before it needs an archaeology sweep to recover, instead "
- "of only a manually-invoked script. Also reports a non-blocking active-set size "
- "diagnostic (soft target/warn bands, never a hard cap or failure)."
- ),
- examples=(
- "devtools lab policy backlog-hygiene",
- "devtools lab policy backlog-hygiene --json",
- "devtools lab policy backlog-hygiene --fresh",
- "devtools lab policy backlog-hygiene --stale-claim-days 10",
- ),
- ),
CommandSpec(
"lab policy bead-graph",
"verification lab",
- "Bead-graph invariant lint and complete missing-AC census over live `bd` state.",
+ "Validate typed dependency endpoints, uniqueness, parent cardinality, and cycles in the Beads graph.",
"devtools.verify_bead_graph",
use_when=(
- "Run right before shipping a bead-state delta (matches the sinex bead-graph-lint "
- "convention). Checks LIVE `bd dep cycles` / `bd list --all --json` output rather than "
- "the exported .beads/issues.jsonl snapshot, so it catches drift not yet re-exported. It fails "
- "closed for real missing acceptance criteria and validates zero-or-one structured parent-child "
- "parents. `--json` emits the complete deterministic missing-AC census, never a display page. "
- "INTENTIONAL DIVERGENCE from sinex: only duplicate `wave:` labels are flagged "
- "(polylogue's `lane:`/`delivery:`/`horizon:` taxonomy is local and not enforced here)."
+ "Run before shipping a bead-state delta. With no source option it checks live `bd` state; "
+ "`--export .beads/issues.jsonl` validates the branch snapshot without importing it into the "
+ "shared database. The gate reads dependency records only and does not make prose, labels, or "
+ "campaign-specific edge lists machine authority."
),
- examples=("devtools lab policy bead-graph", "devtools lab policy bead-graph --json"),
- ),
- CommandSpec(
- "lab policy demo-packet-registry",
- "verification lab",
- "Verify every registered 212 demo has a conforming Demo Finding Packet.",
- "devtools.verify_demo_packet_registry",
- use_when=(
- "Enforce the 212 portfolio contract (polylogue-212.7): every demo prompt in "
- ".agent/demos/registry.json must have a packet directory carrying PROMPT.md, "
- "finding.yaml (five-part provenance stanza), report.md (fixed section order), "
- "evidence.ndjson, queries.ndjson, checks.json, and run.log. Catches a missing "
- "or malformed packet before it silently drops out of the demo shelf."
- ),
- examples=("devtools lab policy demo-packet-registry", "devtools lab policy demo-packet-registry --json"),
- ),
- CommandSpec(
- "lab policy demo-tour-freshness",
- "verification lab",
- "Verify a freshly-run demo tour matches the committed docs/examples/demo-tour/ evidence artifacts.",
- "devtools.verify_demo_tour_freshness",
- use_when=(
- "Catch drift between what `polylogue demo tour` actually emits at runtime (transcript, "
- "report, per-step command output, recording tape) and the committed copies under "
- "docs/examples/demo-tour/, modulo an explicit wall-clock-duration mask (polylogue-3tl.17). "
- "Runs the real tour (~10s), so it lives in the lab tier rather than --quick."
- ),
- examples=("devtools lab policy demo-tour-freshness",),
- ),
- CommandSpec(
- "lab policy docs-drift",
- "verification lab",
- "Verify checkable factual claims in the Reference-docs table against current source.",
- "devtools.verify_docs_drift",
- use_when=(
- "Catch doc-vs-code drift in the hand-maintained Reference-docs table "
- "(CLAUDE.md): a backtick-quoted file path that no longer exists, a "
- "' schema version N' claim ahead of the tier's current constant, or "
- "a watchlisted table name renamed to a different current name (e.g. "
- "`artifact_observations` renamed to `raw_artifacts`) still asserted as "
- "current (polylogue-9e5.13)."
+ examples=(
+ "devtools lab policy bead-graph",
+ "devtools lab policy bead-graph --export .beads/issues.jsonl --json",
),
- examples=("devtools lab policy docs-drift", "devtools lab policy docs-drift --json"),
),
CommandSpec(
"lab policy timestamp-doctrine",
@@ -2047,49 +1320,6 @@ class CatalogBypassSite:
),
examples=("devtools lab policy insight-honesty", "devtools lab policy insight-honesty --json"),
),
- CommandSpec(
- "lab policy campaign-archive-boundaries",
- "verification lab",
- "Verify devtools synthetic benchmark/scale campaigns route through ArchiveLocation.",
- "devtools.verify_campaign_archive_boundaries",
- use_when=(
- "Catch a regression of the phantom-benchmark.db bug (polylogue-ovme.3): a campaign "
- "reintroducing a 'benchmark.db' sentinel, an ad hoc tier-path sibling derivation, or "
- "an entry point (generate_archive/run_full_campaign/run_campaign._run) that no longer "
- "routes through CampaignArchiveLocation. Scoped to the devtools campaign boundary only "
- "-- the broader storage/diagnostics/daemon/maintenance/transitions boundary audit is "
- "polylogue-ovme.2's migration surface."
- ),
- examples=(
- "devtools lab policy campaign-archive-boundaries",
- "devtools lab policy campaign-archive-boundaries --json",
- ),
- ),
- CommandSpec(
- "verify pytest-timeout-overrides",
- "verification",
- "Verify explicit pytest timeout overrides are positive, bounded, and justified.",
- "devtools.verify_pytest_timeout_overrides",
- use_when=(
- "Check AST-parsed @pytest.mark.timeout decorators and managed pytest command literals. "
- "Values above the pyproject default require an exact manifest rationale."
- ),
- examples=("devtools verify pytest-timeout-overrides", "devtools verify pytest-timeout-overrides --json"),
- ),
- CommandSpec(
- "verify degrade-loudly",
- "verification",
- "Verify broad except-handlers in daemon/storage/insights/coordination log or signal on failure.",
- "devtools.verify_degrade_loudly",
- use_when=(
- "Enforce the degrade-loudly doctrine (polylogue-cpf.4): a broad except-handler "
- "(Exception/BaseException/*.Error) in derived-read, status, or probe code that "
- "swallows the exception with no log call and no re-raise is indistinguishable from "
- "'no data' to a reader. New silent sites must add a log call, or add a typed signal "
- "plus a rationale entry in docs/plans/degrade-loudly-allowlist.yaml."
- ),
- examples=("devtools verify degrade-loudly", "devtools verify degrade-loudly --json"),
- ),
CommandSpec(
"release verify-distribution",
"release",
@@ -2291,20 +1521,6 @@ class CatalogBypassSite:
),
examples=("devtools verify layering", "devtools verify layering --json"),
),
- CommandSpec(
- "verify evidence",
- "verification",
- "Render the pytest-first evidence dashboard.",
- "devtools.evidence_dashboard",
- use_when=(
- "Inspect pytest health, contract-evidence inventory, coverage, SLO "
- "catalog, static-gate status, and campaign freshness."
- ),
- examples=(
- "devtools verify evidence --json",
- "devtools verify evidence --markdown",
- ),
- ),
CommandSpec(
"release build-package",
"release",
@@ -2316,25 +1532,12 @@ class CatalogBypassSite:
CommandSpec(
"bench mutation",
"benchmarking",
- "Run focused mutation campaigns and maintain their local index.",
+ "Run focused mutation campaigns with isolated execution and JSON artifacts.",
"devtools.mutmut_campaign",
use_when="Run or inspect focused mutation-testing work without shrinking the committed mutmut scope.",
examples=("devtools bench mutation list", "devtools bench mutation run filters"),
featured=True,
),
- CommandSpec(
- "bench campaign",
- "benchmarking",
- "Run or compare benchmark campaigns.",
- "devtools.benchmark_campaign",
- use_when="Record durable benchmark artifacts or compare a candidate run against a baseline artifact.",
- examples=(
- "devtools bench campaign list",
- "devtools bench campaign run search-filters",
- "devtools bench campaign compare baseline.json candidate.json",
- ),
- featured=True,
- ),
CommandSpec(
"bench nightly-compare",
"benchmarking",
@@ -2357,21 +1560,6 @@ class CatalogBypassSite:
"devtools bench synthetic --scale medium --campaign search-filters",
),
),
- CommandSpec(
- "workspace tasks",
- "workspace",
- "Record and query local agent task execution history.",
- "devtools.task_history",
- use_when="Log, view recent, or summarize agent task execution history during development sessions.",
- examples=(
- "devtools workspace tasks log --command 'devtools render all' --duration-ms 3200 --exit-code 0",
- "devtools workspace tasks recent",
- "devtools workspace tasks recent --count 20",
- "devtools workspace tasks stats",
- "devtools workspace tasks stats --json",
- "devtools workspace tasks stats --resources",
- ),
- ),
CommandSpec(
"workspace failure-context",
"workspace",
@@ -2388,50 +1576,20 @@ class CatalogBypassSite:
),
),
CommandSpec(
- "workspace mandate-continuity-replay",
+ "workspace continuity-evidence",
"workspace",
- "Wire t8t continuity scenarios + work-evidence effects + discovery into one mandate artifact.",
- "devtools.mandate_continuity_replay",
+ "Replay continuity scenarios and verify their query routes are discoverable.",
+ "devtools.continuity_evidence",
use_when=(
- "Run the polylogue-z9gh.7 terminal mandate gate: replay the polylogue-t8t continuity scenario "
- "catalog over real MCP stdio JSON-RPC, reconcile this repository's own real git+Beads history "
- "through the polylogue-1vpm.6.2 effect adapters, cross-check every query-tool route step against "
- "the polylogue-z9gh.3 query-discovery catalog, and emit one JSON artifact with a mandate "
- "acceptance-criteria matrix. Defaults to a fresh, privacy-safe synthetic archive; pass "
- "--archive-root for an authorized live-scale replay."
+ "Replay the continuity scenario catalog over MCP stdio JSON-RPC and cross-check "
+ "its query routes against discovery. The default seeds the packaged synthetic corpus. "
+ "A supplied --archive-root must be paired with the exact --catalog that describes it; "
+ "the runner rejects an unrelated live archive rather than applying synthetic oracles."
),
examples=(
- "devtools workspace mandate-continuity-replay",
- "devtools workspace mandate-continuity-replay --output .cache/mandate-continuity-replay.json",
- "devtools workspace mandate-continuity-replay --archive-root /path/to/authorized/archive --keep-archive",
- ),
- ),
- CommandSpec(
- "workspace beads-state-report",
- "workspace",
- "Self-contained HTML state-of-the-backlog report over the whole bead population.",
- "devtools.beads_state_report",
- use_when=(
- "Answer 'what shape is the backlog in?' across the whole bead population -- open "
- "AND closed -- rather than the ready frontier. Computes status x priority x type, "
- "epic/program trees with fill bars and per-epic trend sparklines, the blocks-graph "
- "topology (ready/blocked/top blockers/cycles/densest cluster/parallel frontier), a "
- "Pulse section reconstructing open/ready/blocked at now vs 7/14 days ago from "
- "timestamps, creation/closure velocity over trailing windows, an age x priority "
- "heatmap, graph-health review queues (dangling refs, id-vs-edge hierarchy "
- "disagreement, open parents whose children all closed, stale in-progress claims, "
- "duplicate titles), subsystem concentration by both area label and keyword, and the "
- "dated hand-verified VERIFICATION(...) / RECONCILIATION marker subsets. Its findings "
- "list is generated by conditional checks over the data, so regeneration cannot leave "
- "stale claims. Answers a different question than `workspace bead-cluster` "
- "(execution-frontier footprint clustering) and `workspace delivery-gate-status` "
- "(per-gate progress): this is population shape and graph hygiene, not the next batch "
- "to dispatch. Use --fresh, since bd mutations do not immediately re-export."
- ),
- examples=(
- "devtools workspace beads-state-report --fresh",
- "devtools workspace beads-state-report --out /tmp/beads-state.html",
- "devtools workspace beads-state-report --json",
+ "devtools workspace continuity-evidence",
+ "devtools workspace continuity-evidence --output .cache/continuity-evidence.json",
+ "devtools workspace continuity-evidence --archive-root /path/to/archive --catalog /path/to/catalog.json",
),
),
)
@@ -2439,121 +1597,6 @@ class CatalogBypassSite:
COMMANDS: dict[str, CommandSpec] = {spec.name: spec for spec in COMMAND_SPECS}
-WORKSPACE_COMMAND_DISPOSITIONS: tuple[WorkspaceCommandDisposition, ...] = (
- WorkspaceCommandDisposition(
- "workspace index-fast-forward",
- "retain",
- "Recent production commits plus focused devtools/storage tests; emits a reusable proof receipt.",
- "Keep the registered command as the index-tier actuator.",
- ),
- WorkspaceCommandDisposition(
- "workspace archive-schema-fast-forward",
- "remove",
- "No current CommandSpec, implementation module, focused test, or history entry exists for this name.",
- "Use workspace index-fast-forward for declared derived-index fast-forwards.",
- "workspace index-fast-forward",
- ),
- WorkspaceCommandDisposition(
- "workspace degraded-archive-proof",
- "retain",
- "Focused tests and deterministic self-healing proof artifacts cover the command.",
- "Keep the registered command for archive repair evidence.",
- ),
- WorkspaceCommandDisposition(
- "workspace frontier",
- "retain",
- "Operator-facing frontier report with documented workflow use and structured report output.",
- "Keep the registered command for frontier batching and wait-ahead decisions.",
- ),
- WorkspaceCommandDisposition(
- "workspace temporal-read-profile",
- "retain",
- "Focused tests cover the report and JSON timing output is reusable for read tuning.",
- "Keep the registered command as the temporal read profiling entrypoint.",
- ),
- WorkspaceCommandDisposition(
- "workspace temporal-devloop",
- "retain",
- "Focused tests cover structured and Markdown event sources; output is a reusable evidence window.",
- "Keep the registered command as the devloop temporal evidence entrypoint.",
- ),
- WorkspaceCommandDisposition(
- "workspace temporal-archive-aggregates",
- "retain",
- "Focused tests cover aggregate report construction and reusable archive artifacts.",
- "Keep the registered command as the run-projection aggregate entrypoint.",
- ),
- WorkspaceCommandDisposition(
- "workspace lineage-validation",
- "retain",
- "Focused tests cover lineage evidence and the command emits reusable count and composition proof.",
- "Keep the registered command before publishing archive cardinality claims.",
- ),
- WorkspaceCommandDisposition(
- "workspace cli-surface-audit",
- "retain",
- "Focused tests cover bounded output and stale-artifact pruning; the audit shelf is reusable.",
- "Keep the registered command as the current CLI surface audit entrypoint.",
- ),
- WorkspaceCommandDisposition(
- "demo real-slice-screen",
- "retain",
- "Focused privacy-screening tests cover redaction, PII review, and report generation.",
- "Keep the registered command as the read-only real-archive screening entrypoint.",
- ),
-)
-
-
-CATALOG_BYPASS_SITES: tuple[CatalogBypassSite, ...] = (
- CatalogBypassSite(
- ".github/workflows/mutation-testing.yml",
- "uv run devtools verify mutation-freshness",
- "verify mutation-freshness",
- "registered",
- "CI invokes the catalog command so inventory and workflow validation see the freshness gate.",
- ),
- CatalogBypassSite(
- ".github/workflows/nightly-scale.yml",
- "uv run devtools bench nightly-compare",
- "bench nightly-compare",
- "registered",
- "CI invokes the catalog command so the nightly comparison is discoverable and checked.",
- ),
- CatalogBypassSite(
- "devtools/pre_push_gate.py",
- 'control_plane_argv("lab policy backlog-hygiene")',
- "lab policy backlog-hygiene",
- "registered",
- "The intentional Beads-only route remains narrow while using the registered policy command.",
- ),
- CatalogBypassSite(
- "docs/test-economics.md",
- "python -m devtools.test_economics_report",
- "lab test-economics",
- "sanctioned-bypass",
- "The generated provenance header preserves the module that emitted the document; operators use the catalog command.",
- ),
- CatalogBypassSite(
- ".githooks/pre-push",
- "python -m devtools.pre_push_gate",
- None,
- "sanctioned-bypass",
- "The hook adapter must receive Git's staged stdin update stream before dispatching its catalog-aware gate.",
- occurrence_line=21,
- expected_occurrences=1,
- ),
- CatalogBypassSite(
- ".beads-hooks/pre-push",
- "python -m devtools.pre_push_gate",
- None,
- "sanctioned-bypass",
- "The Beads-augmented hook retains the same stdin adapter before its managed Beads section runs.",
- occurrence_line=21,
- expected_occurrences=1,
- ),
-)
-
-
def command_name_from_tokens(tokens: Iterable[str], commands: Iterable[CommandSpec] = COMMAND_SPECS) -> str | None:
"""Resolve leading argv tokens to a registered command name."""
token_tuple = tuple(tokens)
@@ -2586,8 +1629,7 @@ def featured_command_specs(commands: Iterable[CommandSpec] = COMMAND_SPECS) -> t
def verification_lab_command_specs(commands: Iterable[CommandSpec] = COMMAND_SPECS) -> tuple[CommandSpec, ...]:
- by_name = {spec.name: spec for spec in commands}
- return tuple(by_name[name] for name in VERIFICATION_LAB_COMMAND_NAMES)
+ return tuple(spec for spec in commands if spec.category == "verification lab")
def grouped_command_specs(commands: Iterable[CommandSpec] = COMMAND_SPECS) -> OrderedDict[str, list[CommandSpec]]:
@@ -2604,17 +1646,13 @@ def grouped_command_specs(commands: Iterable[CommandSpec] = COMMAND_SPECS) -> Or
"CATEGORY_ORDER",
"COMMANDS",
"COMMAND_SPECS",
- "CATALOG_BYPASS_SITES",
"CONTROL_PLANE",
"CommandMain",
"CommandSpec",
- "WorkspaceCommandDisposition",
"command_name_from_tokens",
"control_plane_argv",
"control_plane_command",
"featured_command_specs",
"grouped_command_specs",
- "VERIFICATION_LAB_COMMAND_NAMES",
- "WORKSPACE_COMMAND_DISPOSITIONS",
"verification_lab_command_specs",
]
diff --git a/devtools/continuity_evidence.py b/devtools/continuity_evidence.py
new file mode 100644
index 0000000000..3b058d10a6
--- /dev/null
+++ b/devtools/continuity_evidence.py
@@ -0,0 +1,272 @@
+"""Replay continuity and query-discovery behavior together.
+
+The continuity scenario suite exercises seven workflows plus the
+parallel-agent incident variant against a deterministic synthetic archive.
+The executable query-discovery catalog describes the plans a cold client can
+formulate. This module runs those two existing capabilities together without
+reimplementing them.
+
+This module is that wiring, not a fourth reimplementation:
+
+- :func:`check_discovery_coverage` reuses the real
+ :data:`polylogue.archive.query.discovery.QUERY_DISCOVERY_EXAMPLES` catalog
+ to prove every ``query``-tool route step any continuity scenario executes
+ has a declared positive example of the same unit-source/route shape --
+ i.e. a cold model relying on discovery alone could have found that plan
+ family, not just executed it once the runner already knew it.
+- :func:`run_continuity_evidence` calls
+ :func:`devtools.continuity_replay.replay_archive` unmodified against either
+ a supplied archive paired with its explicit corpus/oracle catalog or a
+ freshly seeded synthetic corpus (the default, privacy-safe CI lane), then
+ combines both executable lanes into one JSON artifact. :func:`redact_report`
+ strips raw evidence prose from that
+ artifact (keeping refs/hashes/counts) for the live-archive lane; the
+ synthetic lane never touches private content so redaction there is a no-op
+ proof of the same mechanism, not a load-bearing privacy boundary.
+
+The report states whether it used a supplied live archive. It does not copy a
+tracker item's acceptance prose into product output or infer tracker closure
+from the three lane statuses.
+"""
+
+from __future__ import annotations
+
+import argparse
+import asyncio
+import hashlib
+import json
+import sys
+import time
+from collections.abc import Sequence
+from dataclasses import asdict, dataclass
+from pathlib import Path
+from tempfile import TemporaryDirectory
+from typing import Literal, TextIO, cast
+
+if __package__ in {None, ""}: # pragma: no cover - exercised by the script entry point
+ sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
+
+from devtools.continuity_replay import replay_archive
+from polylogue.archive.query.discovery import QUERY_DISCOVERY_EXAMPLES
+from polylogue.core.json import JSONDocument, JSONValue, require_json_document
+from polylogue.product.continuity_scenarios import CONTINUITY_SCENARIOS, ContinuityScenarioSpec, continuity_scenario
+from tests.infra.continuity import load_continuity_catalog, seed_continuity_archive
+
+# ── Discovery-coverage lane ───────────────────────────────────────────
+
+
+@dataclass(frozen=True, slots=True)
+class DiscoveryCoverageGap:
+ """One continuity route step whose plan family has no discovery example."""
+
+ scenario_id: str
+ step_id: str
+ plan_atom: str
+ reason: str
+
+ def to_dict(self) -> dict[str, str]:
+ return asdict(self)
+
+
+@dataclass(frozen=True, slots=True)
+class DiscoveryCoverageReport:
+ """Whether every continuity-scenario query plan is independently discoverable."""
+
+ checked_steps: int
+ covered_steps: int
+ gaps: tuple[DiscoveryCoverageGap, ...]
+
+ @property
+ def status(self) -> Literal["pass", "fail"]:
+ return "pass" if not self.gaps else "fail"
+
+ def to_dict(self) -> dict[str, object]:
+ return {
+ "status": self.status,
+ "checked_steps": self.checked_steps,
+ "covered_steps": self.covered_steps,
+ "gaps": [gap.to_dict() for gap in self.gaps],
+ }
+
+
+def check_discovery_coverage(
+ scenarios: Sequence[ContinuityScenarioSpec],
+) -> DiscoveryCoverageReport:
+ """Prove every ``query``-tool continuity route step is independently discoverable.
+
+ A continuity scenario's route steps prove the runner *can execute* a
+ plan; they say nothing about whether a cold model, given only the
+ published query-discovery catalog (``archive/query/discovery.py``), could
+ have *formulated* that same plan family without hidden knowledge. This
+ cross-checks each ``query``-tool step's unit-source against
+ ``QUERY_DISCOVERY_EXAMPLES`` -- the same catalog z9gh.3 generates MCP
+ schemas/completions from -- so a shipped scenario whose plan family the
+ discovery catalog does not teach shows up as a named gap rather than a
+ silent success.
+ """
+
+ catalog_atoms = {f"query:{example.unit_source}" for example in QUERY_DISCOVERY_EXAMPLES if example.route == "query"}
+ gaps: list[DiscoveryCoverageGap] = []
+ checked = 0
+ for scenario in scenarios:
+ for step in scenario.route_steps:
+ if step.tool != "query":
+ continue
+ checked += 1
+ atom = step.plan_atom
+ if atom not in catalog_atoms:
+ gaps.append(
+ DiscoveryCoverageGap(
+ scenario_id=scenario.scenario_id,
+ step_id=step.step_id,
+ plan_atom=atom,
+ reason=f"no declared query-discovery example teaches {atom!r}",
+ )
+ )
+ return DiscoveryCoverageReport(checked_steps=checked, covered_steps=checked - len(gaps), gaps=tuple(gaps))
+
+
+# ── Redaction ─────────────────────────────────────────────────────────
+
+_REDACTABLE_KEYS = frozenset({"label", "claim_text", "reason", "response_sha256"})
+
+
+def _redact_value(key: str, value: JSONValue) -> JSONValue:
+ if key in _REDACTABLE_KEYS and isinstance(value, str) and value:
+ return f"redacted:sha256:{hashlib.sha256(value.encode('utf-8')).hexdigest()}"
+ return value
+
+
+def redact_report(document: JSONValue) -> JSONValue:
+ """Strip raw evidence prose from a mandate report, keeping refs/counts/hashes.
+
+ Recursively walks the report replacing any string value stored under a
+ label/claim-text/reason-shaped key with a stable hash of itself. Refs,
+ ids, statuses, and counts (everything the mandate AC actually needs
+ cited) pass through unchanged -- only free-text prose that could carry
+ private archive content is hashed.
+ """
+
+ if isinstance(document, dict):
+ return {key: _redact_value(key, redact_report(value)) for key, value in document.items()}
+ if isinstance(document, list):
+ return [redact_report(item) for item in document]
+ return document
+
+
+# ── Orchestration ──────────────────────────────────────────────────────
+
+
+async def run_continuity_evidence(
+ *,
+ archive_root: Path | None = None,
+ catalog_path: Path | None = None,
+ scenario_names: Sequence[str] | None = None,
+ redact: bool = True,
+ keep_archive: bool = False,
+) -> JSONDocument:
+ """Run the continuity and discovery lanes as one artifact.
+
+ When ``archive_root`` is ``None`` (the default), a fresh, privacy-safe
+ synthetic continuity corpus is seeded and torn down automatically -- the
+ CI/deterministic lane. A supplied archive must also name the independent
+ corpus/oracle catalog that describes that archive. Reusing the planted
+ synthetic catalog against unrelated live data would test fixture identity,
+ not continuity behavior, so that ambiguous mode is rejected.
+ """
+
+ started_ns = time.perf_counter_ns()
+ live_archive = archive_root is not None
+ if live_archive and catalog_path is None:
+ raise ValueError("--archive-root requires --catalog for the selected archive")
+ catalog = load_continuity_catalog(catalog_path)
+ workdir: TemporaryDirectory[str] | None = None
+
+ resolved_root: Path
+ if archive_root is None:
+ workdir = TemporaryDirectory(prefix="polylogue-continuity-evidence-")
+ resolved_root = Path(workdir.name) / "archive"
+ seed_continuity_archive(resolved_root, catalog=catalog)
+ else:
+ resolved_root = archive_root
+
+ try:
+ continuity_report = await replay_archive(resolved_root, catalog, scenario_names=scenario_names)
+ finally:
+ if workdir is not None and not keep_archive:
+ workdir.cleanup()
+
+ scenarios = (
+ CONTINUITY_SCENARIOS if scenario_names is None else tuple(continuity_scenario(name) for name in scenario_names)
+ )
+ discovery_report = check_discovery_coverage(scenarios)
+ overall_status: Literal["pass", "fail"] = (
+ "pass" if continuity_report.get("status") == "pass" and discovery_report.status == "pass" else "fail"
+ )
+ report: dict[str, object] = {
+ "schema_version": 3,
+ "live_archive": live_archive,
+ "catalog_sha256": hashlib.sha256(
+ json.dumps(catalog, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode("utf-8")
+ ).hexdigest(),
+ "archive_root": str(resolved_root.resolve()) if keep_archive or live_archive else None,
+ "elapsed_ms": round((time.perf_counter_ns() - started_ns) / 1_000_000, 3),
+ "status": overall_status,
+ "continuity": continuity_report,
+ "discovery_coverage": discovery_report.to_dict(),
+ }
+ document = require_json_document(report, context="continuity evidence report")
+ return cast(JSONDocument, redact_report(document)) if redact else document
+
+
+def _scenario_names(value: str) -> tuple[str, ...] | None:
+ if value == "all":
+ return None
+ return tuple(part.strip() for part in value.split(",") if part.strip())
+
+
+def main(argv: list[str] | None = None, *, stdout: TextIO | None = None) -> int:
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument(
+ "--archive-root",
+ type=Path,
+ default=None,
+ help="Archive to replay; requires an exact matching --catalog.",
+ )
+ parser.add_argument("--catalog", type=Path, help="Corpus/oracle catalog describing --archive-root")
+ parser.add_argument("--scenario", default="all", help="all or a comma-separated scenario id list")
+ parser.add_argument("--no-redact", action="store_true", help="Disable evidence redaction (CI/synthetic lane only)")
+ parser.add_argument("--keep-archive", action="store_true")
+ parser.add_argument("--output", type=Path)
+ args = parser.parse_args(argv)
+
+ report = asyncio.run(
+ run_continuity_evidence(
+ archive_root=args.archive_root,
+ catalog_path=args.catalog,
+ scenario_names=_scenario_names(args.scenario),
+ redact=not args.no_redact,
+ keep_archive=args.keep_archive,
+ )
+ )
+ rendered = json.dumps(report, indent=2, sort_keys=True)
+ out = stdout or sys.stdout
+ if args.output is not None:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(rendered + "\n", encoding="utf-8")
+ print(rendered, file=out)
+ return 0 if report["status"] == "pass" else 1
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
+
+
+__all__ = [
+ "DiscoveryCoverageGap",
+ "DiscoveryCoverageReport",
+ "check_discovery_coverage",
+ "main",
+ "redact_report",
+ "run_continuity_evidence",
+]
diff --git a/devtools/continuity_replay.py b/devtools/continuity_replay.py
index 1a27c02762..0ecf66817c 100644
--- a/devtools/continuity_replay.py
+++ b/devtools/continuity_replay.py
@@ -13,21 +13,21 @@
import hashlib
import inspect
import json
-import os
import re
import sys
+import threading
import time
from collections.abc import Callable, Mapping, Sequence
from contextlib import AsyncExitStack, suppress
from dataclasses import dataclass, field
from datetime import timedelta
from pathlib import Path
+from tempfile import TemporaryDirectory
from typing import TYPE_CHECKING, Literal, Protocol, TypeAlias, TypeGuard, cast
if __package__ in {None, ""}: # pragma: no cover - exercised by the script entry point
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
-from polylogue.archive.query.execution_control import DEFAULT_CAPACITY
from polylogue.core.json import JSONDocument, JSONValue, require_json_document, require_json_value
from polylogue.product.continuity_scenarios import (
CONTINUITY_SCENARIOS,
@@ -51,13 +51,8 @@
ArgumentMutator: TypeAlias = Callable[[str, RouteArguments, int], RouteArguments]
ResponseMutator: TypeAlias = Callable[[str, RouteArguments, int, str], str]
DiscoveryMutator: TypeAlias = Callable[[JSONDocument], JSONDocument]
-#: Concurrent copies of one real route step issued by the cancellation
-#: exercise (see StdioMCPContinuityRoute.exercise_cancellation). Comfortably
-#: above the production admission controller's default per-process capacity
-#: so at least one copy is provably still queued (never touched SQLite) when
-#: the cancellation notifications are sent, making the exercise deterministic
-#: rather than a race against how fast any one query happens to run.
-_CANCELLATION_PROBE_CONCURRENCY = DEFAULT_CAPACITY + 4
+_CONTINUITY_DAEMON_SINK_URL = "http://127.0.0.1:1"
+_CONTINUITY_API_TOKEN_SENTINEL = "continuity-replay-call-log-disabled"
_TEMPLATE_RE = re.compile(r"\{fixture:([A-Za-z0-9_.-]+)\}")
_ATTEMPT_TOKEN_RE = re.compile(r"(?P[a-z_]+):(?P[A-Za-z0-9_-]+)")
_ATTEMPT_GRADES: frozenset[str] = frozenset(
@@ -72,6 +67,86 @@
)
+def _hermetic_stdio_environment(*, runtime_root: Path, archive_root: Path) -> dict[str, str]:
+ """Build the complete environment for an offline continuity subprocess.
+
+ The route deliberately does not inherit the operator's environment. In
+ particular, daemon URLs/tokens, MCP capabilities, config locations, and
+ user data roots must not escape into an archive replay. The fixed daemon
+ sink and inert token make call-log isolation testable without granting any
+ real daemon authority.
+ """
+
+ roots = {
+ "HOME": runtime_root / "home",
+ "XDG_CONFIG_HOME": runtime_root / "config",
+ "XDG_DATA_HOME": runtime_root / "data",
+ "XDG_STATE_HOME": runtime_root / "state",
+ "XDG_CACHE_HOME": runtime_root / "cache",
+ "XDG_RUNTIME_DIR": runtime_root / "runtime",
+ "TMPDIR": runtime_root / "tmp",
+ }
+ for name, path in roots.items():
+ path.mkdir(mode=0o700, parents=True, exist_ok=True)
+ if name == "XDG_RUNTIME_DIR":
+ path.chmod(0o700)
+ return {
+ **{name: str(path) for name, path in roots.items()},
+ "POLYLOGUE_ARCHIVE_ROOT": str(archive_root),
+ "POLYLOGUE_CONFIG": str(runtime_root / "config" / "absent-polylogue.toml"),
+ "POLYLOGUE_SITE_CONFIG": "",
+ "POLYLOGUE_DAEMON": "off",
+ "POLYLOGUE_NO_DAEMON": "1",
+ "POLYLOGUE_DAEMON_URL": _CONTINUITY_DAEMON_SINK_URL,
+ "POLYLOGUE_API_AUTH_TOKEN": _CONTINUITY_API_TOKEN_SENTINEL,
+ "POLYLOGUE_MCP_WRITE_ENABLED": "0",
+ "POLYLOGUE_MCP_JUDGE_ENABLED": "0",
+ "POLYLOGUE_MCP_MAINTENANCE_ENABLED": "0",
+ "POLYLOGUE_FORCE_PLAIN": "1",
+ "PYTHONNOUSERSITE": "1",
+ "PYTHONUNBUFFERED": "1",
+ }
+
+
+def _serve_saturated_cancellation_probe() -> None:
+ """Run the real MCP server with one production admission slot held.
+
+ Fast fixture reads can finish before a cancellation notification reaches
+ the server. Guessing a sleep or cancelling a swarm of predicted request
+ ids races the MCP SDK's responder cleanup. This disposable subprocess
+ instead creates the ordinary production admission controller with one
+ slot, occupies that slot through its real ``admit_blocking`` path, and
+ then starts the unmodified Polylogue MCP server. The probe request is
+ therefore deterministically queued until its real MCP task is cancelled.
+ """
+
+ from polylogue.archive.query import execution_control
+ from polylogue.mcp.cli import main
+
+ controller = execution_control.QueryAdmissionController(capacity=1, reserved_interactive=0)
+ holder = execution_control.QueryExecutionContext.create(
+ query_text="continuity-cancellation-holder",
+ timeout_s=None,
+ )
+ held = threading.Event()
+ release = threading.Event()
+
+ def hold_admission_slot() -> None:
+ with controller.admit_blocking(holder):
+ held.set()
+ release.wait()
+
+ thread = threading.Thread(target=hold_admission_slot, daemon=True)
+ thread.start()
+ if not held.wait(timeout=5):
+ raise RuntimeError("continuity cancellation holder did not acquire admission")
+ with execution_control._default_controller_lock:
+ if execution_control._default_controller is not None:
+ raise RuntimeError("continuity cancellation server initialized admission too early")
+ execution_control._default_controller = controller
+ main()
+
+
CancellationOutcome: TypeAlias = Literal[
"cancelled_confirmed",
"completed_before_cancel",
@@ -300,16 +375,20 @@ def __init__(
response_mutator: ResponseMutator | None = None,
discovery_mutator: DiscoveryMutator | None = None,
read_timeout_seconds: float = 60.0,
+ saturated_cancellation_probe: bool = False,
) -> None:
self.archive_root = archive_root.resolve()
self.argument_mutator = argument_mutator
self.response_mutator = response_mutator
self.discovery_mutator = discovery_mutator
self.read_timeout_seconds = read_timeout_seconds
+ self.saturated_cancellation_probe = saturated_cancellation_probe
self._stack: AsyncExitStack | None = None
self._session: ClientSession | None = None
+ self._runtime_workdir: TemporaryDirectory[str] | None = None
self._discovery: JSONDocument = {}
self._invocation_count = 0
+ self._cancellation_receipts: dict[str, CancellationExerciseReceipt] = {}
@property
def transport_name(self) -> str:
@@ -323,19 +402,18 @@ async def __aenter__(self) -> StdioMCPContinuityRoute:
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
- runtime_root = self.archive_root / ".continuity-runtime"
- environment = dict(os.environ)
- environment.update(
- {
- "POLYLOGUE_ARCHIVE_ROOT": str(self.archive_root),
- "XDG_CONFIG_HOME": str(runtime_root / "config"),
- "XDG_STATE_HOME": str(runtime_root / "state"),
- "XDG_CACHE_HOME": str(runtime_root / "cache"),
- }
+ runtime_workdir = TemporaryDirectory(prefix="polylogue-continuity-runtime-")
+ runtime_root = Path(runtime_workdir.name)
+ environment = _hermetic_stdio_environment(runtime_root=runtime_root, archive_root=self.archive_root)
+ server_expression = (
+ "from devtools.continuity_replay import _serve_saturated_cancellation_probe; "
+ "_serve_saturated_cancellation_probe()"
+ if self.saturated_cancellation_probe
+ else "from polylogue.mcp.cli import main; main()"
)
parameters = StdioServerParameters(
command=sys.executable,
- args=["-c", "from polylogue.mcp.cli import main; main()"],
+ args=["-c", server_expression],
env=environment,
cwd=str(Path.cwd()),
)
@@ -360,6 +438,7 @@ async def __aenter__(self) -> StdioMCPContinuityRoute:
break
except Exception as exc:
await stack.aclose()
+ runtime_workdir.cleanup()
raise ContinuityReplayError(
f"failed to initialize MCP stdio route: {exc}",
kind="stdio_initialization_failed",
@@ -368,6 +447,7 @@ async def __aenter__(self) -> StdioMCPContinuityRoute:
self._stack = stack
self._session = session
+ self._runtime_workdir = runtime_workdir
self._discovery = _stdio_discovery(initialize, tools, self.transport_name)
if self.discovery_mutator is not None:
self._discovery = require_json_document(
@@ -378,10 +458,16 @@ async def __aenter__(self) -> StdioMCPContinuityRoute:
async def __aexit__(self, exc_type: object, exc: object, traceback: object) -> None:
stack = self._stack
+ runtime_workdir = self._runtime_workdir
self._stack = None
self._session = None
- if stack is not None:
- await stack.aclose()
+ self._runtime_workdir = None
+ try:
+ if stack is not None:
+ await stack.aclose()
+ finally:
+ if runtime_workdir is not None:
+ runtime_workdir.cleanup()
async def invoke(self, tool: str, arguments: Mapping[str, object]) -> str:
session = self._session
@@ -411,6 +497,35 @@ async def invoke(self, tool: str, arguments: Mapping[str, object]) -> str:
async def exercise_cancellation(
self, tool: str, arguments: Mapping[str, object], *, grace_ms: int
+ ) -> CancellationExerciseReceipt:
+ """Exercise cancellation once per interruptible production tool.
+
+ Cancellation deliberately stresses request lifecycle and transport
+ teardown. A failed or partially supported cancellation must not
+ poison the session used for the graded continuity query that follows.
+ Keep the probe on the same production server route and archive, but
+ isolate its connection authority from the measured scenario. The
+ cancellation boundary is the registered tool route, not scenario
+ wording, so scenarios sharing one tool reuse its exact receipt instead
+ of launching equivalent MCP subprocesses.
+ """
+ if cached := self._cancellation_receipts.get(tool):
+ return cached
+ async with StdioMCPContinuityRoute(
+ self.archive_root,
+ read_timeout_seconds=self.read_timeout_seconds,
+ saturated_cancellation_probe=True,
+ ) as probe:
+ receipt = await probe._exercise_cancellation_on_open_session(
+ tool,
+ arguments,
+ grace_ms=grace_ms,
+ )
+ self._cancellation_receipts[tool] = receipt
+ return receipt
+
+ async def _exercise_cancellation_on_open_session(
+ self, tool: str, arguments: Mapping[str, object], *, grace_ms: int
) -> CancellationExerciseReceipt:
"""Drive real MCP ``notifications/cancelled`` messages through the
live stdio session and observe whether the production
@@ -419,35 +534,11 @@ async def exercise_cancellation(
admission queue's own cancellation check while a call is still
waiting for a free slot) actually aborted an in-flight read.
- This does not race a single call's wall-clock duration against a
- settle delay: direct probing showed that approach is genuinely
- flaky -- some scenarios' own real queries (a marker lookup with
- ``limit=2``) complete in well under a millisecond end to end, so no
- fixed settle window reliably wins, while heavier queries reliably
- do; picking one or the other per scenario is not honest. Instead
- this issues ``_CANCELLATION_PROBE_CONCURRENCY`` concurrent copies of
- the SAME real (tool, arguments) call -- comfortably more than the
- production admission controller's default capacity
- (``DEFAULT_CAPACITY``, currently 4) -- and sends a cancellation
- notification for every one of them. Regardless of how fast any
- individual copy's own SQL work would complete, the ones that exceed
- the shared admission ceiling are provably still queued (not yet
- admitted, not yet touching SQLite) when the notifications are sent,
- and the admission wait loop checks ``ctx.should_abort()`` on its own
- short poll cadence -- making at least one confirmed cancellation
- deterministic, not a race. Direct probing confirmed 100% success
- (40/40 across 5 rounds) against the checked-in continuity fixture,
- including under the same logging load that made the single-call
- approach flake.
-
- This does not reuse :meth:`invoke`: it issues its own calls directly
- against the session so the exercise never consumes a mutation
- invocation slot or perturbs ``_BudgetState`` call/byte accounting --
- it is a probe, not a graded plan step. Request ids are predicted from
- the session's own sequential counter read once before any of the
- concurrent tasks are created; this is only valid because the SDK
- assigns ids in task-creation order and the replay harness does not
- interleave unrelated requests on this session while the probe runs.
+ The disposable server has its sole production admission slot occupied
+ before MCP startup, so this single real route call cannot complete
+ before cancellation. That removes both timing sleeps and request-id
+ swarms while still exercising FastMCP, the registered Polylogue tool,
+ QueryExecutionContext, and QueryAdmissionController.
"""
session = self._session
if session is None:
@@ -463,70 +554,69 @@ async def exercise_cancellation(
call_arguments = dict(arguments)
started = time.perf_counter()
- base_request_id = session._request_id
- probe_tasks: list[asyncio.Task[object]] = [
- asyncio.ensure_future(session.call_tool(tool, arguments=call_arguments))
- for _ in range(_CANCELLATION_PROBE_CONCURRENCY)
- ]
- await asyncio.sleep(0) # let every probe task reach its own request write
- for offset in range(_CANCELLATION_PROBE_CONCURRENCY):
- await session.send_notification(
- ClientNotification(
- CancelledNotification(
- params=CancelledNotificationParams(
- requestId=base_request_id + offset,
- reason="continuity-replay-cancellation-exercise",
- )
+ request_id = session._request_id
+ probe_task = asyncio.create_task(session.call_tool(tool, arguments=call_arguments))
+ for _ in range(3):
+ await asyncio.sleep(0)
+ if session._request_id == request_id + 1:
+ break
+ else:
+ raise ContinuityReplayError(
+ "MCP cancellation probe did not reserve its expected request id",
+ kind="cancellation_request_ids_unavailable",
+ failure_class="execution",
+ )
+ await session.send_notification(
+ ClientNotification(
+ CancelledNotification(
+ params=CancelledNotificationParams(
+ requestId=request_id,
+ reason="continuity-replay-cancellation-exercise",
)
)
)
+ )
- confirmed_count = 0
- completed_count = 0
- failure_details: list[str] = []
- for probe_task in probe_tasks:
- try:
- await asyncio.wait_for(probe_task, timeout=max(1.0, grace_ms / 1000))
- except McpError as exc:
- message = exc.error.message or ""
- if exc.error.code == 0 and "cancel" in message.lower():
- confirmed_count += 1
- else:
- failure_details.append(message or f"McpError code={exc.error.code}")
- except TimeoutError:
- probe_task.cancel()
- with suppress(BaseException):
- await probe_task
- failure_details.append("probe call did not resolve within the grace budget")
+ confirmed = False
+ outcome: CancellationOutcome = "call_failed"
+ detail: str | None = None
+ try:
+ await asyncio.wait_for(probe_task, timeout=max(1.0, grace_ms / 1000))
+ except McpError as exc:
+ message = exc.error.message or ""
+ if exc.error.code == 0 and "cancel" in message.lower():
+ confirmed = True
+ outcome = "cancelled_confirmed"
+ detail = "queued production MCP read returned the SDK cancellation response"
else:
- completed_count += 1
+ detail = message or f"McpError code={exc.error.code}"
+ except TimeoutError:
+ probe_task.cancel()
+ with suppress(BaseException):
+ await probe_task
+ outcome = "not_confirmed_within_grace"
+ detail = "queued production MCP read did not resolve within the cancellation grace budget"
+ else:
+ outcome = "completed_before_cancel"
+ detail = "saturated production admission unexpectedly allowed the probe to complete"
+
+ # A cancellation response proves the handler stopped, but it does not
+ # prove the stdio server has consumed every preceding cancellation
+ # notification. Closing the disposable transport at that point can
+ # race the SDK's stdin reader: it reads one last notification after
+ # the server-side memory stream has closed and exits with
+ # BrokenResourceError. A protocol ping is an ordered transport
+ # barrier. Its response proves the server consumed all prior input
+ # and remains healthy before teardown; a broken session therefore
+ # remains an honest call failure instead of being hidden as a
+ # confirmed cancellation.
+ await session.send_ping()
+
elapsed_ms = (time.perf_counter() - started) * 1000
- detail = (
- f"{confirmed_count}/{_CANCELLATION_PROBE_CONCURRENCY} concurrent probe calls confirmed cancelled, "
- f"{completed_count} completed normally"
- )
- if failure_details:
- detail += f"; {len(failure_details)} unexpected outcome(s): {failure_details[:3]}"
- if confirmed_count > 0:
- return CancellationExerciseReceipt(
- attempted=True,
- confirmed=True,
- outcome="cancelled_confirmed",
- elapsed_ms=elapsed_ms,
- detail=detail,
- )
- if completed_count == _CANCELLATION_PROBE_CONCURRENCY:
- return CancellationExerciseReceipt(
- attempted=True,
- confirmed=False,
- outcome="completed_before_cancel",
- elapsed_ms=elapsed_ms,
- detail=detail,
- )
return CancellationExerciseReceipt(
attempted=True,
- confirmed=False,
- outcome="call_failed",
+ confirmed=confirmed,
+ outcome=outcome,
elapsed_ms=elapsed_ms,
detail=detail,
)
diff --git a/devtools/coordination_latency_probe.py b/devtools/coordination_latency_probe.py
deleted file mode 100644
index 40ce01039e..0000000000
--- a/devtools/coordination_latency_probe.py
+++ /dev/null
@@ -1,94 +0,0 @@
-"""Measure compact coordination-envelope latency with stage attribution.
-
-Use ``devtools bench coordination-latency --samples 21 --out PATH`` to write a
-portable raw artifact. Samples are intentionally taken through the production
-envelope builder; each carries the complete per-stage timing map and the report
-adds p50/p95 rather than hiding tail latency behind a single average.
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-from datetime import UTC, datetime
-from pathlib import Path
-from time import perf_counter
-from typing import Any
-
-
-def _percentile(values: list[float], percentile: float) -> float:
- ordered = sorted(values)
- rank = max(1, min(len(ordered), round(percentile / 100 * len(ordered))))
- return ordered[rank - 1]
-
-
-def measure(*, samples: int, cwd: Path | None = None) -> dict[str, Any]:
- """Return raw compact samples and an honest distribution summary."""
-
- from polylogue.coordination.envelope import build_coordination_envelope
- from polylogue.paths import archive_root
-
- root = (cwd or Path.cwd()).resolve()
- raw: list[dict[str, object]] = []
- latencies: list[float] = []
- for number in range(samples):
- stages: dict[str, float] = {}
- started = perf_counter()
- payload = build_coordination_envelope(cwd=root, stage_timings_ms=stages)
- latency_ms = round((perf_counter() - started) * 1_000, 3)
- latencies.append(latency_ms)
- raw.append(
- {
- "sample": number,
- "latency_ms": latency_ms,
- "stages_ms": stages,
- "serialized_bytes": payload.projection.serialized_bytes,
- }
- )
- return {
- "version": 1,
- "generated_at": datetime.now(UTC).isoformat(),
- "git_head": _git_head(root),
- "cwd": str(root),
- "archive_state": _archive_state(archive_root()),
- "mode": "warm-in-process-core",
- "samples": raw,
- "distribution_ms": {"p50": _percentile(latencies, 50), "p95": _percentile(latencies, 95)},
- }
-
-
-def _archive_state(root: Path) -> dict[str, object]:
- """Record non-content archive facts needed to compare local samples."""
-
- index = root / "index.db"
- try:
- index_bytes: int | None = index.stat().st_size
- except OSError:
- index_bytes = None
- return {"root": str(root), "index_exists": index.exists(), "index_bytes": index_bytes}
-
-
-def _git_head(cwd: Path) -> str | None:
- import subprocess
-
- completed = subprocess.run(["git", "rev-parse", "HEAD"], cwd=cwd, text=True, capture_output=True, check=False)
- return completed.stdout.strip() or None
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--samples", type=int, default=21)
- parser.add_argument("--cwd", type=Path, default=None)
- parser.add_argument("--out", type=Path, default=None, help="Write the full raw JSON artifact to this path.")
- args = parser.parse_args(argv)
- report = measure(samples=max(1, args.samples), cwd=args.cwd)
- encoded = json.dumps(report, indent=2, sort_keys=True)
- if args.out is not None:
- args.out.parent.mkdir(parents=True, exist_ok=True)
- args.out.write_text(encoded + "\n", encoding="utf-8")
- print(encoded)
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/daemon_workload_probe.py b/devtools/daemon_workload_probe.py
index c10680f6ff..cc322abd06 100644
--- a/devtools/daemon_workload_probe.py
+++ b/devtools/daemon_workload_probe.py
@@ -21,7 +21,6 @@
from pathlib import Path
from typing import Any
-from devtools.preflight_ledger import build_preflight_ledger
from polylogue.config import Config
from polylogue.paths import archive_root
from polylogue.storage.archive_identity import resolve_active_index_path
@@ -33,7 +32,7 @@
# Bumped when the JSON shape gains new top-level keys or changes a field type.
# The compare path uses this to refuse incompatible inputs loudly.
-REPORT_VERSION = 20 # v20 adds the opt-in read-only preflight ledger.
+REPORT_VERSION = 19
UNKNOWN_TABLE_COUNT = -2
_EXPECTED_FTS_TRIGGERS: tuple[str, ...] = ("messages_fts_ai", "messages_fts_ad", "messages_fts_au")
@@ -2356,7 +2355,6 @@ def probe(
exact_derived_counts: bool = False,
exact_table_counts: bool = False,
blob_reference_debt: bool = False,
- preflight: bool = False,
) -> dict[str, Any]:
ops_db = db.with_name("ops.db")
index_db = db.with_name("index.db")
@@ -2420,11 +2418,6 @@ def probe(
"convergence_debt": convergence_debt,
"cursor_lag_baselines": _cursor_lag_baselines(conn, ops_db=ops_db),
"query_plans": _query_plans(conn, db=db),
- "preflight_ledger": (
- build_preflight_ledger(db.parent, limit=limit)
- if preflight
- else {"requested": False, "read_only": True, "state": "not_requested", "mutation_operations": []}
- ),
}
finally:
conn.close()
@@ -2988,11 +2981,6 @@ def _parser() -> argparse.ArgumentParser:
action="store_true",
help="Count missing referenced blob files exactly (can stat many blob paths on large archives)",
)
- parser.add_argument(
- "--preflight",
- action="store_true",
- help="Add the strict read-only deployed-status preflight ledger (exact source/FTS/frontier reads)",
- )
parser.add_argument(
"--compare",
nargs=2,
@@ -3028,7 +3016,6 @@ def main(argv: list[str] | None = None) -> int:
exact_derived_counts=args.exact_derived_counts,
exact_table_counts=args.exact_table_counts,
blob_reference_debt=args.blob_reference_debt,
- preflight=args.preflight,
)
if args.json:
print(json.dumps(payload, indent=2, sort_keys=True))
@@ -3039,32 +3026,6 @@ def main(argv: list[str] | None = None) -> int:
if not payload.get("ok"):
print(f" error: {payload.get('error')}")
return 1
- preflight = payload.get("preflight_ledger") or {}
- if preflight.get("requested") is not False:
- print(
- " preflight: "
- f"{preflight.get('state')} "
- f"(blocking={len(preflight.get('blocking_checks') or [])}, "
- f"warnings={len(preflight.get('warning_checks') or [])})"
- )
- source = (preflight.get("checks") or {}).get("source") or {}
- totals = source.get("totals") or {}
- if totals:
- print(
- " source raw: "
- f"{totals.get('raw_count', 0)} total, "
- f"{totals.get('quarantined_count', 0)} quarantined, "
- f"{totals.get('missing_census_count', 0)} missing census"
- )
- for item in source.get("by_origin") or []:
- quarantine = item.get("quarantine") or {}
- census = item.get("census_coverage") or {}
- print(
- f" {item.get('origin')}: quarantine={quarantine.get('count', 0)} "
- f"({(quarantine.get('size') or {}).get('display', '0.0GiB')}), "
- f"census={census.get('missing_count', 0)} missing "
- f"({(census.get('missing_size') or {}).get('display', '0.0GiB')})"
- )
counts = payload["attempt_counts"]
print(f" attempts: {counts['total']} total, {counts['running']} running, {counts['failed']} failed")
print(f" stale cursor writes: {counts.get('stale_cursor_writes', 0)}")
diff --git a/devtools/data/bead-lint-allow.txt b/devtools/data/bead-lint-allow.txt
deleted file mode 100644
index 62814851c3..0000000000
--- a/devtools/data/bead-lint-allow.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# Backlog-hygiene allowlist for devtools.verify_backlog_hygiene.
-# Format: CHECKBEAD_ID (one finding per line; keep the reason as a comment above it)
-#
-# D1 dangling-dep false positives: bd export emits an orphaned raw dependency
-# row (depends_on_id without the "polylogue-" prefix) alongside the correct,
-# re-added edge. bd's own query tools (bd show, bd dep list) already report
-# only the single correct edge -- this is an export-layer artifact, not a
-# real dangling reference. bd dep remove does not clear the underlying row
-# (Dolt-backed store), so hand-editing the JSONL gets clobbered by the next
-# pre-commit bd export. Revisit if bd's export/remove behavior changes.
-D1 polylogue-jtwu
-D1 polylogue-fko9
diff --git a/devtools/data/tracker-authority.json b/devtools/data/tracker-authority.json
deleted file mode 100644
index a6920ad55b..0000000000
--- a/devtools/data/tracker-authority.json
+++ /dev/null
@@ -1,132 +0,0 @@
-{
- "version": 1,
- "generated_at": "2026-07-26T19:05:00Z",
- "relations": {
- "gh_mirror": "The Bead and GitHub issue express the same outcome; scope and state must reconcile.",
- "gh_public_parent": "GitHub owns the public outcome; this Bead owns the internal program or aggregate authority.",
- "gh_implements": "This Bead is an executable child or proof slice under the named public GitHub outcome.",
- "gh_supersedes_scope": "The Bead is the current implementation authority and deliberately replaces stale solution wording in the GitHub issue.",
- "internal_only": "No public GitHub projection is required."
- },
- "bindings": [
- {
- "bead_id": "polylogue-fnm.4",
- "github_issue": 1844,
- "relation": "gh_mirror",
- "external_ref": "gh-1844",
- "note": "GitHub #1844 is the public and near-equivalent outcome for grammar-derived completion, fuzzy selection, and query-builder discovery."
- },
- {
- "bead_id": "polylogue-s8q",
- "github_issue": 2308,
- "relation": "gh_implements",
- "external_ref": "gh-2308",
- "note": "This Bead is the deployed-version/schema/origin attestation slice under the broader live archive closure gate in GitHub #2308; it is not a mirror of the whole issue."
- },
- {
- "bead_id": "polylogue-lkrc",
- "github_issue": 2308,
- "relation": "gh_implements",
- "note": "Canonical raw-authority reconciler implementation under GitHub #2308."
- },
- {
- "bead_id": "polylogue-hjpx",
- "github_issue": 2308,
- "relation": "gh_implements",
- "note": "Fixed-point replay-plan execution slice under GitHub #2308."
- },
- {
- "bead_id": "polylogue-yla8",
- "github_issue": 2308,
- "relation": "gh_implements",
- "note": "Operator-authorized live replay and closure proof under GitHub #2308."
- },
- {
- "bead_id": "polylogue-jnj.9",
- "github_issue": 2309,
- "relation": "gh_implements",
- "external_ref": "gh-2309",
- "note": "This Bead owns effective-config inventory and provenance. GitHub #2309 remains open for residual governance, unsafe-combination rejection, and ownership simplification."
- },
- {
- "bead_id": "polylogue-5hf",
- "github_issue": 2316,
- "relation": "gh_mirror",
- "external_ref": "gh-2316",
- "note": "GitHub #2316 and this Bead jointly own honest provider usage, billing semantics, coverage, and reconciliation."
- },
- {
- "bead_id": "polylogue-rii",
- "github_issue": 2384,
- "relation": "gh_public_parent",
- "external_ref": "gh-2384",
- "note": "Public closure now requires a real emit -> query -> evidence-backed context consumption loop, not merely additional substrate architecture."
- },
- {
- "bead_id": "polylogue-rii.1",
- "github_issue": 2384,
- "relation": "gh_implements",
- "external_ref": "gh-2384",
- "note": "Internal live work-event write-leg owner. Former separate public issue #2459 was closed as duplicate scope; this Bead remains open until its acceptance criteria are satisfied."
- },
- {
- "bead_id": "polylogue-rii.2",
- "github_issue": 2384,
- "relation": "gh_implements",
- "external_ref": "gh-2384",
- "note": "Internal hook/OTLP evidence-projection owner. Former separate public issue #2461 was closed as duplicate scope; recognized hook raw materialization has advanced, while full projection/coverage and OTLP durability remain to prove."
- },
- {
- "bead_id": "polylogue-20d.6",
- "github_issue": 2391,
- "relation": "gh_mirror",
- "external_ref": "gh-2391",
- "note": "Remeasure current-head full-corpus ingest/catch-up performance before changing code; historical June timings are evidence, not current truth."
- },
- {
- "bead_id": "polylogue-fs1",
- "github_issue": 2460,
- "relation": "gh_supersedes_scope",
- "external_ref": "gh-2460",
- "title": "Bridge Hermes runtime evidence into queryable work graphs and forensic reports",
- "description": "Ingest the strongest available Hermes runtime/state, observer/span, transcript, and repository evidence into a deterministic queryable work graph, then generate a citable run-forensics artifact with explicit coverage gaps. Parser-only snapshot enrichment is optional input work, not the authority model. Polylogue records evidence and projections; Hermes retains mutable runtime task authority.",
- "acceptance_criteria": "At least one real Hermes corpus covers delegation, task lifecycle, retry/reroute or failure, skill/tool use, and continuation where available. Evidence from state/runtime/transcript sources is admitted with stable identity, timestamps, source provenance, and explicit caveats. Parent/child and continuation structure and task/tool/skill/run events are queryable without manufactured edges. Reingestion is deterministic and idempotent. A generated run-forensics artifact links every material claim to evidence refs and lets a fresh reviewer identify the main branch, failed or wasted branches, current state, and next justified action. Missing sources degrade visibly rather than producing a complete-looking graph.",
- "note": "This Bead deliberately supersedes the original parse_hermes-only solution in GitHub #2460; the public issue was rewritten to match this broader authority model."
- },
- {
- "bead_id": "polylogue-4ts.5",
- "github_issue": 2478,
- "relation": "gh_mirror",
- "external_ref": "gh-2478",
- "note": "GitHub #2478 and this Bead jointly own precise compaction boundary ranges and effective-context derivation."
- },
- {
- "bead_id": "polylogue-z9gh.9",
- "github_issue": 3283,
- "relation": "gh_public_parent",
- "external_ref": "gh-3283",
- "note": "GitHub #3283 is the public outcome for bounded, cancellable, resumable archive reads across every transport."
- },
- {
- "bead_id": "polylogue-z9gh.9.1",
- "github_issue": 3283,
- "relation": "gh_implements",
- "external_ref": "gh-3283",
- "note": "Delivery owner for landing the shared query transaction across CLI, MCP, Python, daemon HTTP, and web."
- },
- {
- "bead_id": "polylogue-z9gh.1",
- "github_issue": 3283,
- "relation": "gh_implements",
- "external_ref": "gh-3283",
- "note": "Interruptibility, deadlines, cancellation, and resource-bounding repair slice under GitHub #3283."
- },
- {
- "bead_id": "polylogue-z9gh.2",
- "github_issue": 3283,
- "relation": "gh_implements",
- "external_ref": "gh-3283",
- "note": "Archive-wide action/delegation materialization repair slice under GitHub #3283."
- }
- ]
-}
diff --git a/devtools/delivery_gate_status.py b/devtools/delivery_gate_status.py
deleted file mode 100644
index 391f26e47f..0000000000
--- a/devtools/delivery_gate_status.py
+++ /dev/null
@@ -1,231 +0,0 @@
-"""delivery-gate-status: per-release-gate progress board over .beads/issues.jsonl.
-
-The delivery overlay (2026-07-07, corpus escrowed at
-.agent/scratch/corpus-gpt-pro-2026-07-07/) labels every active bead with a
-delivery: gate and lane:. This computes, per gate: open /
-in_progress / closed / blocked / ready counts, percent complete, and the
-gate's exit criterion (embedded below — the corpus copy is ephemeral).
-
-Gate ORDER is the implementation sequence: a gate is "up next" when every
-earlier gate is complete or explicitly waived. Exit criteria are prose —
-they need human/agent judgment, so the board prints them as reminders, not
-as computed booleans.
-
-Usage: devtools workspace delivery-gate-status [--json] [--fresh]
- [--gate delivery:A-trust-floor] [path-to-issues.jsonl]
---fresh runs `bd export -o .beads/issues.jsonl` first (bd updates do NOT
-immediately re-export; a stale file yields stale counts).
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import subprocess
-import sys
-from collections import defaultdict
-from pathlib import Path
-from typing import Any
-
-from devtools import repo_root as _get_root
-
-IssueDict = dict[str, Any]
-
-# (gate-id, short name, exit criterion) in implementation order.
-# Source: delivery overlay release_gates (adjudicated 2026-07-07); durable copy.
-GATES: list[tuple[str, str, str]] = [
- (
- "R0-normalize",
- "Backlog normalization",
- "Every active bead has a delivery release, lane, readiness grade, proof lane, and either acceptance criteria or a deliberate horizon/spec status.",
- ),
- (
- "A-trust-floor",
- "Trust floor",
- "Full verification classified; security negative tests pass; missing bytes classified; numbers/time/prose-mined fields carry honest provenance; agent writes land as candidates.",
- ),
- (
- "B-storage-rebuild-bytes",
- "Storage/rebuild/bytes",
- "Blue-green derived rebuilds cannot show partial archives as ready; restore drill passes; blob refs resolve or carry classified missing state.",
- ),
- (
- "C-read-evidence-contract",
- "Read + evidence contract",
- "CLI, daemon, MCP, Python API, web, reports, and docs read through the same contract; content-hash citations expose drift states.",
- ),
- (
- "D-agent-context-coordination",
- "Agent context/coordination",
- "Hooks install; MCP roles/prompts discoverable; context scheduler emits ledgers; two-agent worktree proof exists.",
- ),
- (
- "E-variants-preferences",
- "Variants + preferences",
- "Variant refs/nodes/alignment/storage exist; reader/query/projection can show source, variant, and side-by-side views honestly.",
- ),
- (
- "F-lineage-compaction",
- "Lineage + compaction",
- "Shared content is stored/counted once, compaction loss is queryable, and regrounding packs pass through the context scheduler.",
- ),
- (
- "G-live-performance",
- "Live performance",
- "Named SLOs and regression gates exist; daemon push/live cache paths work; capture reliability is visible and tested.",
- ),
- (
- "H-web-cockpit",
- "Web evidence cockpit",
- "Evidence basket to citable export works; web UI shows stale/partial/degraded states instead of pretending readiness.",
- ),
- (
- "I-analytics-experiments",
- "Analytics + experiments",
- "Measures are registered, experiments are first-class, analytics render caveats and evidence tiers.",
- ),
- (
- "J-embeddings-retrieval",
- "Embeddings + retrieval",
- "FTS/vector/hybrid quality evals exist; local/cloud providers share one interface; large sessions bound vector work.",
- ),
- (
- "K-interop-origin-export",
- "Interop + origin + export",
- "Each origin has detector/parser/fixtures/fidelity docs; Polylogue export/import is content-hash idempotent; outbound citations preserve provenance.",
- ),
- (
- "L-external-legibility",
- "External legibility",
- "README first screen is clear; one-command demo passes; public claims ledger covers launch claims; cold-reader proof passes.",
- ),
- (
- "M-substrate-consolidation",
- "Substrate consolidation",
- "Storage twins collapse behind a clear boundary; public models are frozen; dead abstractions are deleted or adopted.",
- ),
- (
- "N-horizon",
- "Horizon",
- "Each item either has an implementation-grade spec or remains parked with a decision record.",
- ),
-]
-GATE_IDS = [g[0] for g in GATES]
-
-
-def load(path: Path) -> tuple[dict[str, IssueDict], list[tuple[str, str, str]]]:
- issues: dict[str, IssueDict] = {}
- deps: list[tuple[str, str, str]] = []
- for line in path.read_text().splitlines():
- if not line.strip():
- continue
- d = json.loads(line)
- if d.get("_type") == "issue":
- issues[d["id"]] = d
- for dep in d.get("dependencies") or []:
- deps.append((d["id"], dep.get("depends_on_id"), dep.get("type", "blocks")))
- elif d.get("_type") == "dependency":
- deps.append((d.get("issue_id"), d.get("depends_on_id"), d.get("type", "blocks")))
- return issues, deps
-
-
-def main(argv: list[str] | None = None) -> int:
- root = _get_root()
- parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
- parser.add_argument("path", nargs="?", default=None, help="path to issues.jsonl (default: .beads/issues.jsonl)")
- parser.add_argument("--json", action="store_true")
- parser.add_argument("--fresh", action="store_true", help="bd export first")
- parser.add_argument("--gate", help="only this gate (accepts 'A-trust-floor' or 'delivery:A-trust-floor')")
- args = parser.parse_args(argv)
-
- path = Path(args.path) if args.path else root / ".beads/issues.jsonl"
-
- if args.fresh:
- subprocess.run(["bd", "export", "-o", str(path)], check=True, capture_output=True)
-
- issues, deps = load(path)
- blockers: dict[str, list[str]] = defaultdict(list)
- for src, dst, kind in deps:
- if kind == "blocks" and dst in issues:
- blockers[src].append(dst)
-
- def gate_of(d: IssueDict) -> str | None:
- for lab in d.get("labels") or []:
- lab_str = str(lab)
- # delivery:ac-patched is an overlay marker, not a gate assignment
- if lab_str.startswith("delivery:") and lab_str != "delivery:ac-patched":
- return lab_str.removeprefix("delivery:")
- return None
-
- by_gate: dict[str, list[IssueDict]] = defaultdict(list)
- unlabeled_open = 0
- for d in issues.values():
- g = gate_of(d)
- if g is None:
- if d.get("status") in ("open", "in_progress"):
- unlabeled_open += 1
- continue
- by_gate[g].append(d)
-
- want = args.gate.removeprefix("delivery:") if args.gate else None
- rows: list[dict[str, Any]] = []
- for gid, name, exit_crit in GATES:
- if want and gid != want:
- continue
- beads = by_gate.get(gid, [])
- closed = [b for b in beads if b["status"] == "closed"]
- in_prog = [b for b in beads if b["status"] == "in_progress"]
- open_ = [b for b in beads if b["status"] == "open"]
- blocked = [b for b in open_ if any(issues[x]["status"] != "closed" for x in blockers.get(b["id"], []))]
- ready = [b for b in open_ if b not in blocked]
- rows.append(
- {
- "gate": gid,
- "name": name,
- "total": len(beads),
- "closed": len(closed),
- "in_progress": len(in_prog),
- "ready": len(ready),
- "blocked": len(blocked),
- "pct": round(100 * len(closed) / len(beads)) if beads else None,
- "exit": exit_crit,
- "ready_ids": sorted(b["id"] for b in ready)[:12],
- "in_progress_ids": sorted(b["id"] for b in in_prog),
- }
- )
-
- unknown_gates = sorted(set(by_gate) - set(GATE_IDS))
-
- if args.json:
- print(json.dumps({"gates": rows, "unlabeled_open": unlabeled_open, "unknown_gates": unknown_gates}, indent=2))
- return 0
-
- frontier_shown = False
- for r in rows:
- if r["total"] == 0:
- bar = "(no beads)"
- else:
- done = int(round((r["pct"] or 0) / 10))
- bar = "#" * done + "." * (10 - done) + f" {r['pct']:>3}%"
- marker = " "
- if not frontier_shown and r["total"] and r["closed"] < r["total"]:
- marker = ">" # first incomplete gate = active frontier
- frontier_shown = True
- print(
- f"{marker} {r['gate']:<32} {bar} closed {r['closed']:>3} | wip {r['in_progress']:>2} | ready {r['ready']:>3} | blocked {r['blocked']:>3}"
- )
- if marker == ">" or (want and rows):
- print(f" exit: {r['exit']}")
- if r["in_progress_ids"]:
- print(f" wip: {', '.join(r['in_progress_ids'])}")
- if r["ready_ids"]:
- print(f" ready: {', '.join(r['ready_ids'])}")
- if unlabeled_open:
- print(f"\n {unlabeled_open} open/in_progress beads carry no delivery:* label")
- if unknown_gates:
- print(f" labels outside the gate registry: {', '.join(unknown_gates)}")
- return 0
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/demo_packet.py b/devtools/demo_packet.py
deleted file mode 100644
index 5a33e41040..0000000000
--- a/devtools/demo_packet.py
+++ /dev/null
@@ -1,656 +0,0 @@
-"""Demo Packet v2 validation and registry policy (polylogue-212.12).
-
-The original Demo Finding Packet established a uniform directory shape. V2
-adds an epistemic contract: a demo is not conforming unless it predeclares one
-primary construct and a receipt-backed claim, provides an independently
-checkable oracle, baseline, negative and missing-evidence controls, explicit
-falsifier, content-bound receipts, and bounded non-claims.
-
-The normative schema lives at ``docs/schemas/demo-packet-v2.schema.json``.
-This module intentionally keeps the existing human packet files too: JSON is
-the gate, Markdown/NDJSON are the inspectable publication surface.
-"""
-
-from __future__ import annotations
-
-import hashlib
-import json
-from collections.abc import Iterable, Mapping
-from dataclasses import dataclass, field
-from pathlib import Path, PurePosixPath
-
-PROVENANCE_STANZA_FIELDS: tuple[str, ...] = (
- "archive_cursor",
- "measure_version",
- "commit_sha",
- "sample_frame_predicate",
- "run_date",
-)
-
-REPORT_SECTION_ORDER: tuple[str, ...] = (
- "claim",
- "corpus",
- "method",
- "findings",
- "specimens",
- "counterexamples",
- "limits",
- "non-claims",
- "reproduce",
-)
-
-PACKET_FILENAMES: tuple[str, ...] = (
- "PROMPT.md",
- "packet.json",
- "finding.yaml",
- "report.md",
- "evidence.ndjson",
- "queries.ndjson",
- "checks.json",
- "NON-CLAIMS.md",
- "run.log",
-)
-#: Optional -- present only when an external-agent annotation loop ran.
-OPTIONAL_PACKET_FILENAMES: tuple[str, ...] = ("annotations.ndjson",)
-DEFAULT_SCHEMA_PATH = Path(__file__).resolve().parents[1] / "docs" / "schemas" / "demo-packet-v2.schema.json"
-DEFAULT_DEMO_ROOT = Path(".agent/demos")
-
-
-class DemoPacketValidationError(ValueError):
- """Raised when a packet directory or registry entry fails the contract."""
-
-
-@dataclass(frozen=True)
-class PacketValidationResult:
- """Outcome of validating one packet directory."""
-
- packet_dir: Path
- ok: bool
- missing_files: tuple[str, ...] = ()
- missing_stanza_fields: tuple[str, ...] = ()
- malformed_sections: tuple[str, ...] = ()
- schema_errors: tuple[str, ...] = ()
- receipt_errors: tuple[str, ...] = ()
- errors: tuple[str, ...] = field(default_factory=tuple)
-
- def to_dict(self) -> dict[str, object]:
- return {
- "packet_dir": str(self.packet_dir),
- "ok": self.ok,
- "missing_files": list(self.missing_files),
- "missing_stanza_fields": list(self.missing_stanza_fields),
- "malformed_sections": list(self.malformed_sections),
- "schema_errors": list(self.schema_errors),
- "receipt_errors": list(self.receipt_errors),
- "errors": list(self.errors),
- }
-
-
-def _parse_minimal_yaml_mapping(text: str) -> dict[str, str]:
- """Parse the packet's flat provenance stanza without a full YAML loader."""
-
- result: dict[str, str] = {}
- for raw_line in text.splitlines():
- line = raw_line.split("#", 1)[0].strip()
- if not line or ":" not in line:
- continue
- key, _, value = line.partition(":")
- result[key.strip()] = value.strip().strip("\"'")
- return result
-
-
-def _validate_ndjson(path: Path) -> str | None:
- """Return an error string if *path* is not valid line-delimited JSON."""
-
- for line_no, line in enumerate(path.read_text(encoding="utf-8").splitlines(), start=1):
- if not line.strip():
- continue
- try:
- json.loads(line)
- except json.JSONDecodeError as exc:
- return f"{path.name}:{line_no}: invalid JSON ({exc})"
- return None
-
-
-def _json_pointer(error: object) -> str:
- absolute_path = getattr(error, "absolute_path", ())
- parts = [str(part).replace("~", "~0").replace("/", "~1") for part in absolute_path]
- return "/" + "/".join(parts) if parts else "/"
-
-
-def _validate_schema(payload: object, *, schema_path: Path) -> tuple[str, ...]:
- try:
- schema = json.loads(schema_path.read_text(encoding="utf-8"))
- except (OSError, json.JSONDecodeError) as exc:
- return (f"schema unavailable at {schema_path}: {exc}",)
-
- try:
- from jsonschema import Draft202012Validator, FormatChecker
- except ImportError:
- return ("jsonschema is required for the Demo Packet v2 policy gate",)
-
- validator = Draft202012Validator(schema, format_checker=FormatChecker())
- errors = sorted(validator.iter_errors(payload), key=lambda item: (list(item.absolute_path), item.message))
- return tuple(f"packet.json{_json_pointer(error)}: {error.message}" for error in errors)
-
-
-def _receipt_artifact_path(packet_dir: Path, raw_path: object) -> tuple[Path | None, str | None]:
- if not isinstance(raw_path, str) or not raw_path.strip():
- return None, "receipt artifact_path must be a non-empty string"
- posix = PurePosixPath(raw_path)
- if posix.is_absolute() or ".." in posix.parts:
- return None, f"receipt artifact_path escapes packet directory: {raw_path!r}"
- candidate = (packet_dir / Path(*posix.parts)).resolve()
- packet_root = packet_dir.resolve()
- if not candidate.is_relative_to(packet_root):
- return None, f"receipt artifact_path escapes packet directory: {raw_path!r}"
- return candidate, None
-
-
-def _iter_referenced_receipts(value: object, *, at_root: bool = True) -> Iterable[str]:
- """Yield every receipt ref used by an epistemic field in *value*.
-
- The top-level ``receipts`` member declares the resolver table and is not a
- use site. Nested members named ``receipts`` are citations and must resolve
- to that table. The recursive form keeps future packet sections honest
- without requiring a second list of allowed citation locations.
- """
-
- if isinstance(value, Mapping):
- for key, child in value.items():
- if key == "receipts" and not at_root and isinstance(child, list):
- yield from (ref for ref in child if isinstance(ref, str))
- continue
- yield from _iter_referenced_receipts(child, at_root=False)
- elif isinstance(value, list):
- for child in value:
- yield from _iter_referenced_receipts(child, at_root=False)
-
-
-def _validate_receipts(packet_dir: Path, payload: object) -> tuple[str, ...]:
- if not isinstance(payload, Mapping):
- return ()
- raw_receipts = payload.get("receipts")
- if not isinstance(raw_receipts, list):
- return () # The schema reports this more precisely.
-
- errors: list[str] = []
- seen_refs: set[str] = set()
- for index, raw_receipt in enumerate(raw_receipts):
- if not isinstance(raw_receipt, Mapping):
- continue
- ref = raw_receipt.get("ref")
- if isinstance(ref, str):
- if ref in seen_refs:
- errors.append(f"receipt[{index}] duplicates ref {ref!r}")
- seen_refs.add(ref)
- kind = raw_receipt.get("kind")
- expected_kind = ref.partition(":")[0]
- if isinstance(kind, str) and kind != expected_kind:
- errors.append(f"receipt[{index}] kind {kind!r} does not match ref prefix {expected_kind!r}")
- artifact, artifact_error = _receipt_artifact_path(packet_dir, raw_receipt.get("artifact_path"))
- if artifact_error is not None:
- errors.append(f"receipt[{index}]: {artifact_error}")
- continue
- assert artifact is not None
- if not artifact.is_file():
- errors.append(f"receipt[{index}] artifact missing: {artifact.relative_to(packet_dir.resolve())}")
- continue
- try:
- artifact_bytes = artifact.read_bytes()
- content = artifact_bytes.decode("utf-8")
- except (OSError, UnicodeDecodeError) as exc:
- errors.append(f"receipt[{index}] artifact unreadable: {exc}")
- continue
- if isinstance(ref, str) and ref not in content:
- errors.append(
- f"receipt[{index}] ref {ref!r} is not present in {artifact.relative_to(packet_dir.resolve())}"
- )
- expected_sha = raw_receipt.get("sha256")
- if isinstance(expected_sha, str):
- actual_sha = hashlib.sha256(artifact_bytes).hexdigest()
- if actual_sha != expected_sha:
- errors.append(
- f"receipt[{index}] sha256 mismatch for {artifact.name}: expected {expected_sha}, got {actual_sha}"
- )
-
- undeclared = sorted(set(_iter_referenced_receipts(payload)) - seen_refs)
- errors.extend(f"referenced receipt is not declared in packet.receipts: {ref!r}" for ref in undeclared)
- return tuple(errors)
-
-
-def _canonical_report_heading(section: str) -> str:
- return f"## {section[0].upper()}{section[1:]}"
-
-
-def _report_headings(report_text: str) -> tuple[str, ...]:
- """Return Markdown headings outside fenced code, preserving exact bytes."""
-
- headings: list[str] = []
- fence: str | None = None
- for line in report_text.splitlines():
- stripped = line.lstrip()
- marker = stripped[:3]
- if marker in {"```", "~~~"}:
- if fence is None:
- fence = marker
- elif fence == marker:
- fence = None
- continue
- if fence is None and line.startswith("#"):
- headings.append(line)
- return tuple(headings)
-
-
-def _validate_report_sections(report_text: str) -> tuple[str, ...]:
- """Require each canonical level-two heading exactly once and in order."""
-
- headings = _report_headings(report_text)
- malformed: list[str] = []
- positions: list[int] = []
- for section in REPORT_SECTION_ORDER:
- canonical = _canonical_report_heading(section)
- matches = [index for index, heading in enumerate(headings) if heading == canonical]
- if len(matches) != 1:
- malformed.append(section)
- else:
- positions.append(matches[0])
- if len(positions) == len(REPORT_SECTION_ORDER) and positions != sorted(positions):
- malformed.append("section-order")
- return tuple(malformed)
-
-
-def _duplicate_strings(values: Iterable[object]) -> tuple[str, ...]:
- seen: set[str] = set()
- duplicates: set[str] = set()
- for value in values:
- if not isinstance(value, str):
- continue
- if value in seen:
- duplicates.add(value)
- seen.add(value)
- return tuple(sorted(duplicates))
-
-
-def _validate_semantic_consistency(payload: object) -> tuple[str, ...]:
- """Check cross-field invariants that JSON Schema cannot state clearly."""
-
- if not isinstance(payload, Mapping):
- return ()
- errors: list[str] = []
-
- falsifier = payload.get("falsifier")
- if isinstance(falsifier, Mapping):
- triggered = falsifier.get("triggered")
- result = falsifier.get("result")
- if triggered is True and result != "fail":
- errors.append("falsifier.triggered=true requires falsifier.result='fail'")
- if result == "fail" and triggered is not True:
- errors.append("falsifier.result='fail' requires falsifier.triggered=true")
- if result == "pass" and triggered is not False:
- errors.append("falsifier.result='pass' requires falsifier.triggered=false")
-
- controls = payload.get("controls")
- if isinstance(controls, Mapping):
- control_ids: list[object] = []
- for lane in ("negative", "missing_evidence"):
- raw_controls = controls.get(lane)
- if isinstance(raw_controls, list):
- control_ids.extend(control.get("id") for control in raw_controls if isinstance(control, Mapping))
- for duplicate in _duplicate_strings(control_ids):
- errors.append(f"control id is duplicated across packet controls: {duplicate!r}")
-
- results = payload.get("results")
- if isinstance(results, Mapping):
- measurements = results.get("measurements")
- if isinstance(measurements, list):
- names = [measurement.get("name") for measurement in measurements if isinstance(measurement, Mapping)]
- for duplicate in _duplicate_strings(names):
- errors.append(f"measurement name is duplicated: {duplicate!r}")
-
- return tuple(errors)
-
-
-def _logged_output(
- log_text: str,
- *,
- section: str,
- command: str,
- exit_marker: str,
-) -> tuple[str, int] | str:
- """Read one structurally delimited command result from a packet log."""
-
- lines = log_text.splitlines(keepends=True)
- heading = f"=== {section} ==="
- heading_indexes = [index for index, line in enumerate(lines) if line.rstrip("\r\n") == heading]
- if len(heading_indexes) != 1:
- return f"run.log must contain exactly one section heading {heading!r}"
- command_index = heading_indexes[0] + 1
- expected_command = f"$ {command}"
- if command_index >= len(lines) or lines[command_index].rstrip("\r\n") != expected_command:
- return f"run.log section {section!r} does not record command {command!r}"
- output_start = command_index + 1
- exit_indexes = [index for index in range(output_start, len(lines)) if lines[index].startswith(f"{exit_marker}=")]
- if len(exit_indexes) != 1:
- return f"run.log section {section!r} must contain exactly one {exit_marker} marker"
- exit_index = exit_indexes[0]
- raw_exit = lines[exit_index].rstrip("\r\n").partition("=")[2]
- try:
- exit_code = int(raw_exit)
- except ValueError:
- return f"run.log marker {exit_marker!r} has a non-integer exit code"
- return "".join(lines[output_start:exit_index]), exit_code
-
-
-def _validate_current_run(packet_dir: Path, payload: object) -> tuple[str, ...]:
- """Bind an opt-in current run receipt to its structured log evidence.
-
- Older packets intentionally have only historical provenance. A packet that
- claims a full current SHA must opt into this receipt so the claim cannot be
- satisfied by editing a command transcript alone.
- """
-
- if not isinstance(payload, Mapping):
- return ()
- provenance = payload.get("provenance")
- if not isinstance(provenance, Mapping):
- return ()
- commit_sha = provenance.get("commit_sha")
- current_run = provenance.get("current_run")
- if current_run is None:
- if payload.get("packet_id") == "d4-behavioral-archaeology":
- return ("provenance.current_run is required for the D4 current receipt",)
- return ()
- if not isinstance(current_run, Mapping):
- return ("provenance.current_run must be an object",)
-
- errors: list[str] = []
- if current_run.get("code_sha") != commit_sha:
- errors.append("provenance.current_run.code_sha must equal provenance.commit_sha")
- if current_run.get("route") != "polylogue":
- errors.append("provenance.current_run.route must be 'polylogue'")
- if current_run.get("private_data") is not False:
- errors.append("provenance.current_run.private_data must be false")
-
- run_log = current_run.get("run_log")
- log_path, path_error = _receipt_artifact_path(packet_dir, run_log)
- if path_error is not None:
- errors.append(f"provenance.current_run: {path_error}")
- return tuple(errors)
- assert log_path is not None
- if not log_path.is_file():
- return (f"provenance.current_run log missing: {run_log}",)
- try:
- log_text = log_path.read_text(encoding="utf-8")
- except OSError as exc:
- return (f"provenance.current_run log unreadable: {exc}",)
-
- raw_commands = current_run.get("commands")
- if not isinstance(raw_commands, list):
- return tuple(errors)
- command_ids = [item.get("id") for item in raw_commands if isinstance(item, Mapping)]
- if command_ids != ["q1", "q2", "q3", "q4", "q5", "q6"]:
- errors.append("provenance.current_run.commands must be ordered q1 through q6")
- for item in raw_commands:
- if not isinstance(item, Mapping):
- continue
- result = _logged_output(
- log_text,
- section=str(item.get("section", "")),
- command=str(item.get("command", "")),
- exit_marker=f"{str(item.get('id', '')).upper()}_EXIT_CODE",
- )
- if isinstance(result, str):
- errors.append(result)
- continue
- output, exit_code = result
- if exit_code != item.get("exit_code"):
- errors.append(f"run.log exit code does not match current_run command {item.get('id')!r}")
- actual_sha = hashlib.sha256(output.encode("utf-8")).hexdigest()
- if actual_sha != item.get("output_sha256"):
- errors.append(f"run.log output digest does not match current_run command {item.get('id')!r}")
-
- explain = current_run.get("explain")
- if isinstance(explain, Mapping):
- result = _logged_output(
- log_text,
- section=str(explain.get("section", "")),
- command=str(explain.get("command", "")),
- exit_marker="EXPLAIN_EXIT_CODE",
- )
- if isinstance(result, str):
- errors.append(result)
- else:
- output, exit_code = result
- if exit_code != explain.get("exit_code"):
- errors.append("run.log explain exit code does not match provenance")
- actual_sha = hashlib.sha256(output.encode("utf-8")).hexdigest()
- if actual_sha != explain.get("output_sha256"):
- errors.append("run.log explain output digest does not match provenance")
- return tuple(errors)
-
-
-def validate_packet(packet_dir: Path, *, schema_path: Path = DEFAULT_SCHEMA_PATH) -> PacketValidationResult:
- """Validate *packet_dir* against both the human and v2 machine contracts.
-
- The function is read-only. Receipt resolution is intentionally bounded to
- committed artifacts inside the packet directory; generation-time code may
- additionally resolve the same refs against a live deterministic archive.
- """
-
- missing_files = tuple(name for name in PACKET_FILENAMES if not (packet_dir / name).exists())
- errors: list[str] = []
- missing_stanza_fields: tuple[str, ...] = ()
- malformed_sections: list[str] = []
- schema_errors: tuple[str, ...] = ()
- receipt_errors: tuple[str, ...] = ()
- packet_payload: object = None
-
- packet_path = packet_dir / "packet.json"
- if packet_path.exists():
- try:
- packet_payload = json.loads(packet_path.read_text(encoding="utf-8"))
- except json.JSONDecodeError as exc:
- errors.append(f"packet.json is not valid JSON: {exc}")
- else:
- schema_errors = _validate_schema(packet_payload, schema_path=schema_path)
- receipt_errors = _validate_receipts(packet_dir, packet_payload)
- errors.extend(_validate_semantic_consistency(packet_payload))
- errors.extend(_validate_current_run(packet_dir, packet_payload))
-
- finding_path = packet_dir / "finding.yaml"
- if finding_path.exists():
- stanza = _parse_minimal_yaml_mapping(finding_path.read_text(encoding="utf-8"))
- missing_stanza_fields = tuple(name for name in PROVENANCE_STANZA_FIELDS if not stanza.get(name))
- if isinstance(packet_payload, Mapping):
- provenance = packet_payload.get("provenance")
- current_run = provenance.get("current_run") if isinstance(provenance, Mapping) else None
- historical = provenance.get("historical_receipt") if isinstance(provenance, Mapping) else None
- if isinstance(current_run, Mapping):
- expected_finding_fields = {
- "commit_sha": provenance.get("commit_sha") if isinstance(provenance, Mapping) else None,
- "run_date": provenance.get("run_date") if isinstance(provenance, Mapping) else None,
- "current_run_id": current_run.get("run_id"),
- "current_run_timestamp": current_run.get("run_timestamp"),
- "current_route": current_run.get("route"),
- "historical_commit_sha": historical.get("commit_sha") if isinstance(historical, Mapping) else None,
- "historical_run_date": historical.get("run_date") if isinstance(historical, Mapping) else None,
- "historical_receipt_status": historical.get("status") if isinstance(historical, Mapping) else None,
- }
- for key, expected in expected_finding_fields.items():
- if stanza.get(key) != str(expected):
- errors.append(f"finding.yaml {key} does not match packet provenance")
-
- report_path = packet_dir / "report.md"
- if report_path.exists():
- report_text = report_path.read_text(encoding="utf-8")
- malformed_sections.extend(_validate_report_sections(report_text))
-
- nonclaims_path = packet_dir / "NON-CLAIMS.md"
- if nonclaims_path.exists() and not nonclaims_path.read_text(encoding="utf-8").strip():
- errors.append("NON-CLAIMS.md must not be empty")
-
- checks_path = packet_dir / "checks.json"
- if checks_path.exists():
- try:
- checks_payload = json.loads(checks_path.read_text(encoding="utf-8"))
- except json.JSONDecodeError as exc:
- errors.append(f"checks.json is not valid JSON: {exc}")
- else:
- for required_key in ("pass", "unsupported_claims", "coverage_notes"):
- if required_key not in checks_payload:
- errors.append(f"checks.json missing required key: {required_key}")
-
- for ndjson_name in ("evidence.ndjson", "queries.ndjson"):
- ndjson_path = packet_dir / ndjson_name
- if ndjson_path.exists():
- error = _validate_ndjson(ndjson_path)
- if error is not None:
- errors.append(error)
-
- ok = not (missing_files or missing_stanza_fields or malformed_sections or schema_errors or receipt_errors or errors)
- return PacketValidationResult(
- packet_dir=packet_dir,
- ok=ok,
- missing_files=missing_files,
- missing_stanza_fields=missing_stanza_fields,
- malformed_sections=tuple(malformed_sections),
- schema_errors=schema_errors,
- receipt_errors=receipt_errors,
- errors=tuple(errors),
- )
-
-
-@dataclass(frozen=True)
-class DemoRegistryEntry:
- """One row in the demo registry manifest."""
-
- slug: str
- prompt_path: str
- packet_dir: str
- mode: str # public | private | fixture | anti-demo
- required_primitives: tuple[str, ...] = ()
-
- @staticmethod
- def from_dict(payload: dict[str, object]) -> DemoRegistryEntry:
- try:
- raw_primitives = payload.get("required_primitives", ())
- primitives = raw_primitives if isinstance(raw_primitives, list | tuple) else ()
- return DemoRegistryEntry(
- slug=str(payload["slug"]),
- prompt_path=str(payload["prompt_path"]),
- packet_dir=str(payload["packet_dir"]),
- mode=str(payload["mode"]),
- required_primitives=tuple(str(item) for item in primitives),
- )
- except KeyError as exc:
- raise DemoPacketValidationError(f"registry entry missing required key: {exc}") from None
-
-
-def load_demo_registry(registry_path: Path) -> tuple[DemoRegistryEntry, ...]:
- payload = json.loads(registry_path.read_text(encoding="utf-8"))
- if not isinstance(payload, list):
- raise DemoPacketValidationError(f"{registry_path}: expected a JSON array of registry entries")
- return tuple(DemoRegistryEntry.from_dict(entry) for entry in payload)
-
-
-@dataclass(frozen=True)
-class RegistryLintResult:
- """Outcome of linting every entry in a demo registry manifest."""
-
- registry_path: Path
- ok: bool
- entry_results: tuple[tuple[str, PacketValidationResult | None], ...]
- registry_errors: tuple[str, ...] = ()
- unregistered_packet_dirs: tuple[str, ...] = ()
-
- def to_dict(self) -> dict[str, object]:
- return {
- "registry_path": str(self.registry_path),
- "ok": self.ok,
- "registry_errors": list(self.registry_errors),
- "unregistered_packet_dirs": list(self.unregistered_packet_dirs),
- "entries": [
- {
- "slug": slug,
- "packet_missing": result is None,
- **({"validation": result.to_dict()} if result is not None else {}),
- }
- for slug, result in self.entry_results
- ],
- }
-
-
-def _registered_packet_paths(entries: Iterable[DemoRegistryEntry], *, repo_root: Path) -> set[Path]:
- return {(repo_root / entry.packet_dir).resolve() for entry in entries}
-
-
-def _discover_v2_packet_dirs(*, repo_root: Path) -> set[Path]:
- demo_root = repo_root / DEFAULT_DEMO_ROOT
- if not demo_root.is_dir():
- return set()
- return {path.parent.resolve() for path in demo_root.rglob("packet.json") if path.is_file()}
-
-
-def lint_demo_registry(
- registry_path: Path,
- *,
- repo_root: Path,
- schema_path: Path = DEFAULT_SCHEMA_PATH,
-) -> RegistryLintResult:
- """Validate every registered packet and reject unregistered v2 packets."""
-
- entries = load_demo_registry(registry_path)
- results: list[tuple[str, PacketValidationResult | None]] = []
- registry_errors: list[str] = []
- slugs: set[str] = set()
- packet_paths: set[Path] = set()
-
- for entry in entries:
- if entry.slug in slugs:
- registry_errors.append(f"duplicate registry slug: {entry.slug}")
- slugs.add(entry.slug)
- packet_dir = (repo_root / entry.packet_dir).resolve()
- if packet_dir in packet_paths:
- registry_errors.append(f"duplicate registry packet_dir: {entry.packet_dir}")
- packet_paths.add(packet_dir)
- prompt_path = (repo_root / entry.prompt_path).resolve()
- if not prompt_path.is_file():
- registry_errors.append(f"{entry.slug}: prompt missing at {entry.prompt_path}")
- if not packet_dir.is_dir():
- results.append((entry.slug, None))
- continue
- results.append((entry.slug, validate_packet(packet_dir, schema_path=schema_path)))
-
- discovered = _discover_v2_packet_dirs(repo_root=repo_root)
- registered = _registered_packet_paths(entries, repo_root=repo_root)
- unregistered = tuple(sorted(str(path.relative_to(repo_root.resolve())) for path in discovered - registered))
- ok = not registry_errors and not unregistered and all(result is not None and result.ok for _, result in results)
- return RegistryLintResult(
- registry_path=registry_path,
- ok=ok,
- entry_results=tuple(results),
- registry_errors=tuple(registry_errors),
- unregistered_packet_dirs=unregistered,
- )
-
-
-def iter_registry_slugs(entries: Iterable[DemoRegistryEntry]) -> tuple[str, ...]:
- return tuple(entry.slug for entry in entries)
-
-
-__all__ = [
- "DEFAULT_SCHEMA_PATH",
- "OPTIONAL_PACKET_FILENAMES",
- "PACKET_FILENAMES",
- "PROVENANCE_STANZA_FIELDS",
- "REPORT_SECTION_ORDER",
- "DemoPacketValidationError",
- "DemoRegistryEntry",
- "PacketValidationResult",
- "RegistryLintResult",
- "iter_registry_slugs",
- "lint_demo_registry",
- "load_demo_registry",
- "validate_packet",
-]
diff --git a/devtools/demo_shelf.py b/devtools/demo_shelf.py
deleted file mode 100644
index 38dd2a79c1..0000000000
--- a/devtools/demo_shelf.py
+++ /dev/null
@@ -1,588 +0,0 @@
-"""Refresh or verify a curated current demo shelf."""
-
-from __future__ import annotations
-
-import argparse
-import json
-import re
-import subprocess
-import sys
-from dataclasses import dataclass
-from pathlib import Path
-from typing import Any
-
-DEFAULT_ROOT = Path(".agent/demos")
-DEFAULT_MANIFEST = "MANIFEST.readable.json"
-DEFAULT_SUMMARY_INDEX = "SUMMARY_INDEX.json"
-DEFAULT_README = "README.md"
-DEFAULT_CATALOG = "CURATED_CATALOG.md"
-DEMO_SET_CONTRACT = "current-curated-demo-set"
-READABLE_SUFFIXES = frozenset({".md", ".json", ".jsonl", ".csv", ".txt", ".yaml", ".yml"})
-SUMMARY_COVERAGE_FIELDS = frozenset({"claim", "non_claim", "proof_fields", "caveat_fields"})
-MAX_EXCLUSION_SAMPLES = 20
-
-
-@dataclass(frozen=True, slots=True)
-class ShelfRender:
- manifest_path: Path
- summary_index_path: Path
- readme_path: Path
- catalog_path: Path
- manifest_text: str
- summary_index_text: str
- readme_text: str
- catalog_text: str
- file_count: int
- readable_count: int
- summary_count: int
- summary_coverage: dict[str, list[str]]
- unsummarized_demos: list[str]
- input_closure_mode: str
- display_root: str
- excluded_input_count: int
- exclusion_reason_counts: dict[str, int]
- exclusion_samples: list[dict[str, str]]
-
-
-def _is_readable_artifact(path: Path) -> bool:
- return path.suffix.lower() in READABLE_SUFFIXES
-
-
-def _first_heading(path: Path) -> str:
- try:
- for line in path.read_text(encoding="utf-8", errors="replace").splitlines():
- match = re.match(r"^#\s+(.+)$", line)
- if match:
- return match.group(1).strip()
- except OSError:
- return ""
- return ""
-
-
-def _nonempty_string(value: object) -> bool:
- return isinstance(value, str) and bool(value.strip())
-
-
-def _summary_timestamp(payload: dict[str, Any]) -> object:
- for key in ("updated_at", "generated_at", "created_at"):
- value = payload.get(key)
- if value is not None:
- return value
- return None
-
-
-def _summary_record(root: Path, path: Path) -> dict[str, Any]:
- rel = path.relative_to(root).as_posix()
- demo = path.parent.relative_to(root).as_posix()
- try:
- payload = json.loads(path.read_text())
- except (OSError, json.JSONDecodeError) as exc:
- return {
- "demo": demo,
- "summary_path": rel,
- "parse_error": str(exc),
- "coverage": {
- "claim": False,
- "non_claim": False,
- "proof_fields": False,
- "caveat_fields": False,
- },
- }
- if not isinstance(payload, dict):
- return {
- "demo": demo,
- "summary_path": rel,
- "parse_error": "summary root is not a JSON object",
- "coverage": {
- "claim": False,
- "non_claim": False,
- "proof_fields": False,
- "caveat_fields": False,
- },
- }
-
- proof_fields = sorted(key for key in payload if "proof" in key.lower())
- caveat_fields = sorted(key for key in payload if "caveat" in key.lower())
- claim = payload.get("claim")
- non_claim = payload.get("non_claim")
- record: dict[str, Any] = {
- "demo": demo,
- "summary_path": rel,
- "artifact": payload.get("artifact", demo),
- "claim": claim if _nonempty_string(claim) else None,
- "non_claim": non_claim if _nonempty_string(non_claim) else None,
- "proof_fields": proof_fields,
- "caveat_fields": caveat_fields,
- "archive_root": payload.get("archive_root"),
- "index_schema_version": payload.get("index_schema_version", payload.get("index_schema")),
- "timestamp": _summary_timestamp(payload),
- "coverage": {
- "claim": _nonempty_string(claim),
- "non_claim": _nonempty_string(non_claim),
- "proof_fields": bool(proof_fields),
- "caveat_fields": bool(caveat_fields),
- },
- }
- return record
-
-
-def _summary_records(root: Path, included_paths: set[Path]) -> list[dict[str, Any]]:
- records: list[dict[str, Any]] = []
- for path in sorted(included_paths):
- if path.name.endswith("summary.json"):
- records.append(_summary_record(root, path))
- return records
-
-
-def _summary_coverage(records: list[dict[str, Any]]) -> dict[str, list[str]]:
- return {
- "without_claim": [record["summary_path"] for record in records if not record["coverage"]["claim"]],
- "without_non_claim": [record["summary_path"] for record in records if not record["coverage"]["non_claim"]],
- "without_proof_fields": [
- record["summary_path"] for record in records if not record["coverage"]["proof_fields"]
- ],
- "without_caveat_fields": [
- record["summary_path"] for record in records if not record["coverage"]["caveat_fields"]
- ],
- }
-
-
-def _schema_version_mismatches(records: list[dict[str, Any]], required: int | None) -> list[dict[str, Any]]:
- if required is None:
- return []
- mismatches: list[dict[str, Any]] = []
- for record in records:
- observed = record.get("index_schema_version")
- if observed is None:
- continue
- try:
- observed_int = int(observed)
- except (TypeError, ValueError):
- observed_int = None
- if observed_int != required:
- mismatches.append(
- {
- "summary_path": record["summary_path"],
- "observed": observed,
- "required": required,
- }
- )
- return mismatches
-
-
-def _unsummarized_demos(demo_records: list[dict[str, object]], summary_records: list[dict[str, Any]]) -> list[str]:
- summarized_top_level = {str(record["demo"]).split("/", maxsplit=1)[0] for record in summary_records}
- return [str(record["id"]) for record in demo_records if str(record["id"]) not in summarized_top_level]
-
-
-def _build_summary_index(
- root: Path,
- summary_records: list[dict[str, Any]],
- unsummarized_demos: list[str],
-) -> tuple[str, int, dict[str, list[str]]]:
- coverage = _summary_coverage(summary_records)
- coverage = {
- **coverage,
- "unsummarized_demos": unsummarized_demos,
- }
- summary_index = {
- "root": str(root),
- "summary_count": len(summary_records),
- "coverage": coverage,
- "records": summary_records,
- }
- return json.dumps(summary_index, indent=2) + "\n", len(summary_records), coverage
-
-
-def _demo_records(
- root: Path,
- files: list[dict[str, object]],
- included_paths: set[Path],
-) -> list[dict[str, object]]:
- records: list[dict[str, object]] = []
- demo_ids = sorted(
- {
- str(record["path"]).split("/", maxsplit=1)[0]
- for record in files
- if "/" in str(record["path"]) and not str(record["path"]).startswith(".")
- }
- )
- for demo_id in demo_ids:
- entry = root / demo_id
- readme_candidates = (entry / "README.md", entry / "current" / "README.md")
- analysis_candidates = (entry / "ANALYSIS.md", entry / "current" / "ANALYSIS.md")
- readme = next((path for path in readme_candidates if path.resolve() in included_paths), None)
- analysis = next((path for path in analysis_candidates if path.resolve() in included_paths), None)
- title = (
- (_first_heading(readme) if readme is not None else "")
- or (_first_heading(analysis) if analysis is not None else "")
- or demo_id.replace("-", " ").title()
- )
- entry_files = [record for record in files if str(record["path"]).startswith(f"{demo_id}/")]
- readable_count = sum(1 for record in entry_files if record["readable"])
- records.append(
- {
- "id": demo_id,
- "title": title,
- "readme": readme.relative_to(root).as_posix() if readme is not None else None,
- "analysis": analysis.relative_to(root).as_posix() if analysis is not None else None,
- "file_count": len(entry_files),
- "readable_count": readable_count,
- }
- )
- return records
-
-
-def _build_readme(records: list[dict[str, object]]) -> str:
- lines = [
- "# Polylogue Current Demo Shelf",
- "",
- "Generated by `devtools workspace demo-shelf`.",
- "",
- "This shelf contains the best current Polylogue demos for the active devloop.",
- "It is not append-only. Replace, consolidate, or move stale demos out when a",
- "better demo supersedes them.",
- "",
- "## Current Entries",
- "",
- ]
- if records:
- for record in records:
- lines.append(f"- `{record['id']}` — {record['title']}")
- if record["readme"]:
- lines.append(f" - readme: `{record['readme']}`")
- if record["analysis"]:
- lines.append(f" - analysis: `{record['analysis']}`")
- lines.append(f" - files: {record['file_count']} ({record['readable_count']} readable)")
- else:
- lines.append("No demo entries found.")
- lines.extend(["", "Retired demo material belongs under `.agent/archive/retired-demos/`, not here.", ""])
- return "\n".join(lines)
-
-
-def _build_catalog(records: list[dict[str, object]]) -> str:
- lines = [
- "# Polylogue Demo Catalog",
- "",
- "Generated by `devtools workspace demo-shelf`.",
- "",
- ]
- if records:
- for record in records:
- lines.append(f"## {record['title']}")
- lines.append("")
- lines.append(f"- id: `{record['id']}`")
- if record["readme"]:
- lines.append(f"- readme: `{record['readme']}`")
- if record["analysis"]:
- lines.append(f"- analysis: `{record['analysis']}`")
- lines.append(f"- files: {record['file_count']} ({record['readable_count']} readable)")
- lines.append("")
- else:
- lines.append("No demo entries found.")
- lines.append("")
- return "\n".join(lines)
-
-
-def _parse_required_summary_coverage(value: str) -> set[str]:
- if not value:
- return set()
- fields = {item.strip() for item in value.split(",") if item.strip()}
- unknown = fields - SUMMARY_COVERAGE_FIELDS
- if unknown:
- expected = ", ".join(sorted(SUMMARY_COVERAGE_FIELDS))
- raise argparse.ArgumentTypeError(
- f"unknown coverage field(s): {', '.join(sorted(unknown))}; expected {expected}"
- )
- return fields
-
-
-def _coverage_failures(summary_coverage: dict[str, list[str]], required: set[str]) -> dict[str, list[str]]:
- return {
- field: summary_coverage.get(f"without_{field}", [])
- for field in sorted(required)
- if summary_coverage.get(f"without_{field}", [])
- }
-
-
-def _repository_context(root: Path) -> tuple[Path, str] | None:
- result = subprocess.run(
- ["git", "-C", str(root), "rev-parse", "--show-toplevel"],
- check=False,
- capture_output=True,
- text=True,
- )
- if result.returncode != 0:
- return None
- repository_root = Path(result.stdout.strip()).resolve()
- try:
- relative_root = root.relative_to(repository_root).as_posix()
- except ValueError:
- return None
- return repository_root, relative_root or "."
-
-
-def _select_input_files(
- root: Path,
- *,
- generated: set[Path],
- output_root: Path,
- private_projection: bool,
-) -> tuple[str, str, list[Path], list[dict[str, str]]]:
- repository_context = _repository_context(root)
- relative_root = repository_context[1] if repository_context is not None else None
- display_root = relative_root if relative_root is not None else str(root)
- all_files = [
- path.resolve()
- for path in sorted(root.rglob("*"))
- if path.is_file()
- and path.resolve() not in generated
- and (output_root == root or not path.resolve().is_relative_to(output_root))
- ]
- if private_projection or repository_context is None:
- mode = "filesystem-private" if private_projection else "filesystem"
- return mode, display_root, all_files, []
-
- repository_root, relative_root = repository_context
- result = subprocess.run(
- ["git", "-C", str(repository_root), "ls-files", "-z", "--", relative_root],
- check=True,
- capture_output=True,
- )
- tracked = {
- (repository_root / raw.decode("utf-8", errors="surrogateescape")).resolve()
- for raw in result.stdout.split(b"\0")
- if raw
- }
- included = [path for path in all_files if path in tracked]
- excluded = [
- {"path": path.relative_to(root).as_posix(), "reason": "not_git_tracked"}
- for path in all_files
- if path not in tracked
- ]
- return "git-tracked", display_root, included, excluded
-
-
-def render_demo_shelf(
- root: Path,
- *,
- manifest_name: str = DEFAULT_MANIFEST,
- summary_index_name: str = DEFAULT_SUMMARY_INDEX,
- readme_name: str = DEFAULT_README,
- catalog_name: str = DEFAULT_CATALOG,
- private_output: Path | None = None,
-) -> ShelfRender:
- """Build deterministic indexes from tracked inputs or an explicit private projection."""
- root = root.expanduser().resolve()
- output_root = private_output.expanduser().resolve() if private_output is not None else root
- if private_output is not None and output_root.is_relative_to(root):
- raise ValueError("private output must be outside the committed shelf root")
- manifest_path = output_root / manifest_name
- summary_index_path = output_root / summary_index_name
- readme_path = output_root / readme_name
- catalog_path = output_root / catalog_name
- generated = {
- path.resolve()
- for path in (
- manifest_path,
- summary_index_path,
- readme_path,
- catalog_path,
- root / manifest_name,
- root / summary_index_name,
- root / readme_name,
- root / catalog_name,
- )
- }
- mode, display_root, input_files, excluded_inputs = _select_input_files(
- root,
- generated=generated,
- output_root=output_root,
- private_projection=private_output is not None,
- )
- reason_counts: dict[str, int] = {}
- for excluded in excluded_inputs:
- reason = excluded["reason"]
- reason_counts[reason] = reason_counts.get(reason, 0) + 1
- files = [
- {
- "path": path.relative_to(root).as_posix(),
- "bytes": path.stat().st_size,
- "readable": _is_readable_artifact(path),
- }
- for path in input_files
- ]
- manifest = {
- "contract": DEMO_SET_CONTRACT,
- "root": display_root,
- "input_closure": {
- "mode": mode,
- "included_count": len(files),
- "excluded_count": len(excluded_inputs),
- "exclusion_reason_counts": dict(sorted(reason_counts.items())),
- "exclusion_samples": "bounded samples are emitted in the command JSON payload",
- },
- "packaging": (
- "Use devtools workspace read-package for portable readable bundles; this helper only writes indexes."
- ),
- "curation_policy": (
- "This is not append-only. Keep the best current demos here; replace, consolidate, or move stale demos out."
- ),
- "file_count": len(files),
- "readable_count": sum(1 for item in files if item["readable"]),
- "files": files,
- }
- manifest_text = json.dumps(manifest, indent=2) + "\n"
- included_paths = set(input_files)
- summary_records = _summary_records(root, included_paths)
- records = _demo_records(root, files, included_paths)
- unsummarized_demos = _unsummarized_demos(records, summary_records)
- summary_index_text, summary_count, summary_coverage = _build_summary_index(
- Path(display_root),
- summary_records,
- unsummarized_demos,
- )
- readme_text = _build_readme(records)
- catalog_text = _build_catalog(records)
- return ShelfRender(
- manifest_path=manifest_path,
- summary_index_path=summary_index_path,
- readme_path=readme_path,
- catalog_path=catalog_path,
- manifest_text=manifest_text,
- summary_index_text=summary_index_text,
- readme_text=readme_text,
- catalog_text=catalog_text,
- file_count=len(files),
- readable_count=sum(1 for item in files if item["readable"]),
- summary_count=summary_count,
- summary_coverage=summary_coverage,
- unsummarized_demos=unsummarized_demos,
- input_closure_mode=mode,
- display_root=display_root,
- excluded_input_count=len(excluded_inputs),
- exclusion_reason_counts=dict(sorted(reason_counts.items())),
- exclusion_samples=excluded_inputs[:MAX_EXCLUSION_SAMPLES],
- )
-
-
-def _changed(path: Path, expected: str) -> bool:
- try:
- return path.read_text() != expected
- except FileNotFoundError:
- return True
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- prog="devtools workspace demo-shelf",
- description="Refresh or verify curated current demo shelf indexes.",
- )
- parser.add_argument("--root", type=Path, default=DEFAULT_ROOT, help=f"Demo shelf root (default: {DEFAULT_ROOT})")
- parser.add_argument("--manifest", default=DEFAULT_MANIFEST, help=f"Manifest filename (default: {DEFAULT_MANIFEST})")
- parser.add_argument(
- "--summary-index",
- default=DEFAULT_SUMMARY_INDEX,
- help=f"Summary index filename (default: {DEFAULT_SUMMARY_INDEX})",
- )
- parser.add_argument(
- "--require-summary-coverage",
- type=_parse_required_summary_coverage,
- default=set(),
- metavar="FIELDS",
- help="In check mode, fail when summaries lack comma-separated fields: claim, non_claim, proof_fields, caveat_fields.",
- )
- parser.add_argument(
- "--require-index-schema-version",
- type=int,
- default=None,
- metavar="VERSION",
- help="In check mode, fail when a summary declares a different index_schema_version.",
- )
- parser.add_argument(
- "--private-output",
- type=Path,
- default=None,
- help="Write a full-filesystem private projection to this separate, untracked directory.",
- )
- parser.add_argument("--check", action="store_true", help="Verify files are current without writing.")
- parser.add_argument("--json", action="store_true", help="Emit machine-readable JSON.")
- args = parser.parse_args(argv)
- rendered = render_demo_shelf(
- args.root,
- manifest_name=args.manifest,
- summary_index_name=args.summary_index,
- private_output=args.private_output,
- )
- changed = {
- "manifest": _changed(rendered.manifest_path, rendered.manifest_text),
- "summary_index": _changed(rendered.summary_index_path, rendered.summary_index_text),
- "readme": _changed(rendered.readme_path, rendered.readme_text),
- "catalog": _changed(rendered.catalog_path, rendered.catalog_text),
- }
- coverage_failures = _coverage_failures(rendered.summary_coverage, args.require_summary_coverage)
- summary_index_payload = json.loads(rendered.summary_index_text)
- schema_mismatches = _schema_version_mismatches(
- summary_index_payload["records"],
- args.require_index_schema_version,
- )
- undeclared_inputs = rendered.input_closure_mode == "git-tracked" and rendered.excluded_input_count > 0
- ok = not any(changed.values()) and not coverage_failures and not schema_mismatches and not undeclared_inputs
- if not args.check and not undeclared_inputs:
- rendered.manifest_path.parent.mkdir(parents=True, exist_ok=True)
- rendered.manifest_path.write_text(rendered.manifest_text)
- rendered.summary_index_path.write_text(rendered.summary_index_text)
- rendered.readme_path.write_text(rendered.readme_text)
- rendered.catalog_path.write_text(rendered.catalog_text)
- ok = True
- changed = {"manifest": False, "summary_index": False, "readme": False, "catalog": False}
- coverage_failures = {}
- schema_mismatches = []
-
- payload = {
- "ok": ok,
- "root": str(args.root.expanduser().resolve()),
- "manifest": str(rendered.manifest_path),
- "summary_index": str(rendered.summary_index_path),
- "file_count": rendered.file_count,
- "readable_count": rendered.readable_count,
- "summary_count": rendered.summary_count,
- "unsummarized_demos": rendered.unsummarized_demos,
- "required_summary_coverage": sorted(args.require_summary_coverage),
- "summary_coverage_failures": coverage_failures,
- "required_index_schema_version": args.require_index_schema_version,
- "summary_schema_mismatches": schema_mismatches,
- "input_closure": {
- "mode": rendered.input_closure_mode,
- "included_count": rendered.file_count,
- "excluded_count": rendered.excluded_input_count,
- "exclusion_reason_counts": rendered.exclusion_reason_counts,
- },
- "undeclared_inputs": undeclared_inputs,
- "exclusion_samples": rendered.exclusion_samples,
- "changed": changed,
- "mode": "check" if args.check else "write",
- }
- if args.json:
- json.dump(payload, sys.stdout, indent=2)
- sys.stdout.write("\n")
- elif ok:
- print(
- f"demo shelf {'current' if args.check else 'refreshed'}: "
- f"{rendered.file_count} files, {rendered.readable_count} readable, "
- f"{rendered.summary_count} summaries, "
- f"{len(rendered.unsummarized_demos)} unsummarized; portable bundles: read-package"
- )
- else:
- reasons = [name for name, value in changed.items() if value]
- reasons.extend(f"summary coverage {field}" for field in coverage_failures)
- if schema_mismatches:
- reasons.append("summary schema version")
- if undeclared_inputs:
- reasons.append("undeclared shelf inputs (use --private-output for a private projection)")
- print("demo shelf drift:", ", ".join(reasons), file=sys.stderr)
- return 0 if ok else 1
-
-
-if __name__ == "__main__": # pragma: no cover
- raise SystemExit(main())
diff --git a/devtools/devloop_temporal.py b/devtools/devloop_temporal.py
deleted file mode 100644
index 626c8e6033..0000000000
--- a/devtools/devloop_temporal.py
+++ /dev/null
@@ -1,255 +0,0 @@
-"""Compose devloop-local event sources into a TemporalEvidenceWindow."""
-
-from __future__ import annotations
-
-import argparse
-import json
-import re
-import subprocess
-import sys
-from datetime import datetime
-from pathlib import Path
-from zoneinfo import ZoneInfo
-
-from polylogue.surfaces.temporal_evidence import TemporalEvidenceEvent, build_temporal_evidence_window
-
-ROOT = Path(__file__).resolve().parents[1]
-DEFAULT_CONDUCTOR_ROOT = ROOT / ".agent/conductor-devloop"
-DEFAULT_OPERATING_LOG = DEFAULT_CONDUCTOR_ROOT / "OPERATING-LOG.md"
-DEFAULT_EVENT_LOG = DEFAULT_CONDUCTOR_ROOT / "EVENTS.jsonl"
-WARSAW = ZoneInfo("Europe/Warsaw")
-LOG_HEADING_RE = re.compile(
- r"^## (?P\d{4}-\d{2}-\d{2}) (?P\d{2}:\d{2}(?::\d{2})?) CEST [—-] (?P.+)$"
-)
-
-
-def _parser() -> argparse.ArgumentParser:
- parser = argparse.ArgumentParser(
- prog="devtools workspace temporal-devloop",
- description="Compose git and operating-log events into the shared temporal evidence window.",
- )
- parser.add_argument("--repo", type=Path, default=ROOT, help="Git repository to read commits from.")
- parser.add_argument("--log", type=Path, default=DEFAULT_OPERATING_LOG, help="Conductor OPERATING-LOG.md path.")
- parser.add_argument(
- "--event-log", type=Path, default=DEFAULT_EVENT_LOG, help="Structured devloop EVENTS.jsonl path."
- )
- parser.add_argument("--since", default=None, help="Inclusive ISO datetime lower bound.")
- parser.add_argument("--until", default=None, help="Inclusive ISO datetime upper bound.")
- parser.add_argument("--max-commits", type=int, default=100, help="Maximum git commits to include.")
- parser.add_argument("--max-log-events", type=int, default=200, help="Maximum operating-log headings to include.")
- parser.add_argument("--out", type=Path, default=None, help="Write JSON report to this path.")
- parser.add_argument("--json", action="store_true", help="Emit JSON to stdout. Accepted for devtools parity.")
- return parser
-
-
-def _parse_bound(value: str | None) -> datetime | None:
- if value is None:
- return None
- parsed = datetime.fromisoformat(value)
- if parsed.tzinfo is None:
- parsed = parsed.replace(tzinfo=WARSAW)
- return parsed
-
-
-def _parse_log_datetime(date_text: str, time_text: str) -> datetime:
- if time_text.count(":") == 1:
- time_text = f"{time_text}:00"
- return datetime.fromisoformat(f"{date_text}T{time_text}").replace(tzinfo=WARSAW)
-
-
-def operating_log_events(path: Path, *, limit: int) -> tuple[list[TemporalEvidenceEvent], tuple[str, ...]]:
- """Parse timestamped operating-log headings into temporal events."""
-
- if not path.exists():
- return [], ("operating_log_missing",)
- events: list[TemporalEvidenceEvent] = []
- skipped = 0
- for line_no, line in enumerate(path.read_text(encoding="utf-8").splitlines(), start=1):
- if not line.startswith("## "):
- continue
- match = LOG_HEADING_RE.match(line)
- if match is None:
- skipped += 1
- continue
- if len(events) >= limit:
- break
- occurred_at = _parse_log_datetime(match.group("date"), match.group("time"))
- title = match.group("title").strip()
- phase = None
- if title.startswith("focus: ") and " -> " in title:
- phase = title.rsplit(" -> ", maxsplit=1)[-1].strip()
- events.append(
- TemporalEvidenceEvent(
- event_id=f"operating-log:{line_no}",
- occurred_at=occurred_at,
- family="devloop-log",
- kind="focus" if phase else "checkpoint",
- label=title,
- source_ref=f"{path}:{line_no}",
- evidence_refs=(f"file:{path}:{line_no}",),
- phase=phase,
- )
- )
- caveats: list[str] = []
- if skipped:
- caveats.append("operating_log_unparsed_headings")
- if len(events) >= limit:
- caveats.append("operating_log_events_capped")
- return events, tuple(caveats)
-
-
-def structured_devloop_events(path: Path, *, limit: int) -> tuple[list[TemporalEvidenceEvent], tuple[str, ...]]:
- """Read structured devloop JSONL records into temporal events."""
-
- if not path.exists():
- return [], ("devloop_event_log_missing",)
- events: list[TemporalEvidenceEvent] = []
- malformed = 0
- unsupported = 0
- for line_no, line in enumerate(path.read_text(encoding="utf-8").splitlines(), start=1):
- if not line.strip():
- continue
- if len(events) >= limit:
- break
- try:
- record = json.loads(line)
- except json.JSONDecodeError:
- malformed += 1
- continue
- if record.get("schema_version") != 1:
- unsupported += 1
- continue
- occurred_raw = record.get("occurred_at")
- title_raw = record.get("title")
- if not isinstance(occurred_raw, str) or not isinstance(title_raw, str):
- malformed += 1
- continue
- occurred_at: datetime | None
- if occurred_raw.endswith(" CEST"):
- occurred_text = occurred_raw.removesuffix(" CEST")
- try:
- occurred_at = datetime.strptime(occurred_text, "%Y-%m-%d %H:%M:%S").replace(tzinfo=WARSAW)
- except ValueError:
- malformed += 1
- continue
- else:
- try:
- occurred_at = _parse_bound(occurred_raw)
- except ValueError:
- malformed += 1
- continue
- if occurred_at is None:
- malformed += 1
- continue
- title = title_raw.strip()
- phase = None
- if title.startswith("focus: ") and " -> " in title:
- phase = title.rsplit(" -> ", maxsplit=1)[-1].strip()
- events.append(
- TemporalEvidenceEvent(
- event_id=f"devloop-event:{line_no}",
- occurred_at=occurred_at,
- family="devloop-log",
- kind="focus" if phase else "checkpoint",
- label=title,
- source_ref=f"{path}:{line_no}",
- evidence_refs=(f"file:{path}:{line_no}",),
- phase=phase,
- )
- )
- caveats: list[str] = []
- if malformed:
- caveats.append("devloop_event_log_malformed_rows")
- if unsupported:
- caveats.append("devloop_event_log_unsupported_rows")
- if len(events) >= limit:
- caveats.append("devloop_event_log_events_capped")
- return events, tuple(caveats)
-
-
-def git_commit_events(
- repo: Path, *, limit: int, since: datetime | None
-) -> tuple[list[TemporalEvidenceEvent], tuple[str, ...]]:
- """Read local git commit events as temporal events."""
-
- command = [
- "git",
- "log",
- f"--max-count={max(limit, 0)}",
- "--date=iso-strict",
- "--format=%cI%x09%h%x09%s",
- ]
- if since is not None:
- command.insert(2, f"--since={since.isoformat()}")
- try:
- completed = subprocess.run(command, cwd=repo, text=True, capture_output=True, check=False, timeout=10)
- except (OSError, subprocess.TimeoutExpired):
- return [], ("git_log_failed",)
- if completed.returncode != 0:
- return [], ("git_log_failed",)
- events: list[TemporalEvidenceEvent] = []
- for line in completed.stdout.splitlines():
- parts = line.split("\t", maxsplit=2)
- if len(parts) != 3:
- continue
- occurred_at = datetime.fromisoformat(parts[0])
- short_sha = parts[1]
- subject = parts[2]
- events.append(
- TemporalEvidenceEvent(
- event_id=f"git-commit:{short_sha}",
- occurred_at=occurred_at,
- family="git",
- kind="commit",
- label=subject,
- source_ref=f"commit:{short_sha}",
- evidence_refs=(f"commit:{short_sha}",),
- )
- )
- caveats = ("git_commits_capped",) if len(events) >= limit else ()
- return events, caveats
-
-
-def build_report(args: argparse.Namespace) -> dict[str, object]:
- since = _parse_bound(args.since)
- until = _parse_bound(args.until)
- log_source = "structured_jsonl"
- log_events, log_caveats = structured_devloop_events(args.event_log, limit=args.max_log_events)
- if not log_events:
- log_source = "markdown_fallback"
- log_events, log_caveats = operating_log_events(args.log, limit=args.max_log_events)
- commit_events, commit_caveats = git_commit_events(args.repo, limit=args.max_commits, since=since)
- window = build_temporal_evidence_window(
- [*log_events, *commit_events],
- since=since,
- until=until,
- caveats=(*log_caveats, *commit_caveats),
- )
- return {
- "report_version": 1,
- "command": "devtools workspace temporal-devloop",
- "repo": str(args.repo),
- "operating_log": str(args.log),
- "event_log": str(args.event_log),
- "devloop_event_source": log_source,
- "source_counts": {
- "devloop_log_events": len(log_events),
- "git_commit_events": len(commit_events),
- },
- "temporal_window": window.model_dump(mode="json"),
- }
-
-
-def main(argv: list[str] | None = None) -> int:
- args = _parser().parse_args(argv)
- report = build_report(args)
- rendered = json.dumps(report, indent=2, sort_keys=True) + "\n"
- if args.out is not None:
- args.out.parent.mkdir(parents=True, exist_ok=True)
- args.out.write_text(rendered, encoding="utf-8")
- sys.stdout.write(rendered)
- return 0
-
-
-if __name__ == "__main__": # pragma: no cover
- raise SystemExit(main())
diff --git a/devtools/docs_surface.py b/devtools/docs_surface.py
index 5c44186a09..788961e5f4 100644
--- a/devtools/docs_surface.py
+++ b/devtools/docs_surface.py
@@ -104,7 +104,7 @@ def _entry(title: str, path: str, description: str, tier: DocsTier) -> DocsEntry
_entry("Codex Provider", "providers/openai-codex.md", "Codex session detection and parser notes.", "guide"),
# Reference
_entry("CLI Reference", "cli-reference.md", "Generated command reference from live help output.", "reference"),
- _entry("MCP Reference", "mcp-reference.md", "Generated MCP tool and contract reference.", "reference"),
+ _entry("MCP Reference", "mcp-reference.md", "MCP tools, capability opt-ins, and client setup.", "reference"),
_entry("Library API", "library-api.md", "Async archive API, filters, and query patterns.", "reference"),
_entry("MCP Integration", "mcp-integration.md", "Model Context Protocol server setup and usage.", "reference"),
_entry(
@@ -206,13 +206,6 @@ def _entry(title: str, path: str, description: str, tier: DocsTier) -> DocsEntry
"Daemon, web-shell, browser-capture, and extension debugging workflow.",
"operations",
),
- _entry("Test Economics", "test-economics.md", "Test-selection and verification cost model.", "operations"),
- _entry(
- "Test Quality Workflows",
- "test-quality-workflows.md",
- "Executable mutation-campaign and benchmark registries.",
- "operations",
- ),
_entry(
"Visual Evidence",
"visual-evidence.md",
@@ -222,24 +215,6 @@ def _entry(title: str, path: str, description: str, tier: DocsTier) -> DocsEntry
_entry(
"Release Checklist", "release.md", "Cut-time packaging, installed-artifact, and publish checks.", "operations"
),
- _entry(
- "Tracker Authority",
- "tracker-authority.md",
- "GitHub and Beads authority split, and the reconciliation script that checks it.",
- "operations",
- ),
- _entry(
- "Acceptance Contract Wave",
- "plans/beads-acceptance-contracts-2026-08-07.md",
- "Guarded structured acceptance contracts for the current Beads execution wave.",
- "operations",
- ),
- _entry(
- "Acceptance Contract Reconciliation",
- "plans/beads-acceptance-reconciliation.md",
- "Read-only authority reconciliation and guarded targeted import protocol for the acceptance-contract wave.",
- "operations",
- ),
# Evidence and product
_entry(
"Demos and Proofs",
@@ -247,58 +222,10 @@ def _entry(title: str, path: str, description: str, tier: DocsTier) -> DocsEntry
"Reproducible proofs, construct-valid demo doctrine, and flagship demonstrations.",
"evidence",
),
- _entry(
- "Cursor Authority Census, 2026-08-04",
- "evidence/polylogue-xeck9-cursor-authority-census-2026-08-04.md",
- "Privacy-safe read-only census of cursor and accepted-head readiness evidence.",
- "evidence",
- ),
- _entry(
- "Topology Live-Proof Residue, 2026-08-06",
- "evidence/polylogue-topology-live-proof-2026-08-06.md",
- "Candidate topology census, production-route cycle evidence, and unexercised live-archive residue.",
- "evidence",
- ),
- _entry(
- "Reindex Canary Differ Implementation, 2026-08-09",
- "evidence/polylogue-0x7nh-reindex-canary-differ-implementation-2026-08-09.md",
- "Implementation packet, supersession proof, anti-vacuity evidence, and the remaining first-production-report gate.",
- "evidence",
- ),
- _entry(
- "Proof Artifacts",
- "proof-artifacts.md",
- "Claim-to-proof map for public-facing demo and evidence claims.",
- "evidence",
- ),
- _entry(
- "README Public-Claims View",
- "generated/public-claims/readme.md",
- "Generated compact status view for claims used in README-facing copy.",
- "evidence",
- ),
- _entry(
- "Launch Public-Claims View",
- "generated/public-claims/launch.md",
- "Generated launch-copy claim status with evidence blockers and remediation refs.",
- "evidence",
- ),
- _entry(
- "Findings-Page Public-Claims View",
- "generated/public-claims/findings-page.md",
- "Generated finding status with judgment, privacy, evidence, epoch, and frame qualifiers.",
- "evidence",
- ),
- _entry(
- "Verified Public-Claims Export",
- "generated/public-claims/verified-export.md",
- "Generated full public-claim projection corresponding to the machine-readable export.",
- "evidence",
- ),
_entry(
"Structured Failure Follow-Up",
"findings/claim-vs-evidence.md",
- "Bounded field finding with oracle, sample frame, calibration, and caveats.",
+ "Bounded finding with a structural oracle, sample frame, calibration, and caveats.",
"evidence",
),
_entry(
@@ -316,34 +243,7 @@ def _entry(title: str, path: str, description: str, tier: DocsTier) -> DocsEntry
_entry(
"Query-Action Workflows",
"product/workflows.md",
- "Executable product contract for workflows, affordances, completions, and golden paths.",
- "evidence",
- ),
- _entry(
- "Demo Corpus Construct Audit",
- "plans/demo-corpus-construct-audit.md",
- "Generated construct-coverage audit for the demo fixture world.",
- "evidence",
- ),
- _entry(
- "Release Readiness Gate",
- "plans/release-readiness-gate.md",
- "Externally presentable release gate and required proof contract.",
- "evidence",
- ),
- _entry(
- "Demo Packet v2", "examples/demo-packet-v2/README.md", "Worked private-data-free evidence packet.", "evidence"
- ),
- _entry(
- "Demo Tour Report",
- "examples/demo-tour/report.md",
- "Recorded output and receipts from the demo tour.",
- "evidence",
- ),
- _entry(
- "UVX Installation Proof",
- "examples/demo-tour/uvx-proof.md",
- "Recorded installation proof for the uvx distribution path.",
+ "Selection rules, common paths, and executable demo-archive evidence.",
"evidence",
),
_entry(
@@ -390,25 +290,7 @@ def _entry(title: str, path: str, description: str, tier: DocsTier) -> DocsEntry
"Browser-capture redesign rationale and verification artifacts.",
"design",
),
- _entry(
- "Incident 14:32 Proof World",
- "design/incident-1432-proof-world.md",
- "Deterministic demo corpus and anti-circularity rules.",
- "design",
- ),
_entry("Project Memory", "design/project-memory.md", "Long-term memory model and product intent.", "design"),
- _entry(
- "Storage Twins Divergences",
- "plans/STORAGE_TWINS_DIVERGENCES.md",
- "Documented sync/async storage backend divergences, tracked for the twins regression test.",
- "design",
- ),
- _entry(
- "Query-Action Workflows Design",
- "design/query-action-workflows.md",
- "Historical design pointer for the workflow contract.",
- "design",
- ),
_entry(
"Query Set Algebra", "design/query-set-algebra.md", "Set-composition semantics over query results.", "design"
),
@@ -424,12 +306,6 @@ def _entry(title: str, path: str, description: str, tier: DocsTier) -> DocsEntry
"Implementation architecture for content hashing, event storage, lineage, origins, and raw byte authority.",
"design",
),
- _entry(
- "Bead Readiness Audit",
- "plans/bead-readiness-audit-implementation-cluster.md",
- "Execution-readiness audit for the implementation-cluster Beads and their verification boundaries.",
- "design",
- ),
_entry(
"Analysis Rigor",
"design/analysis-rigor.md",
@@ -452,59 +328,7 @@ def _entry(title: str, path: str, description: str, tier: DocsTier) -> DocsEntry
_entry("Time Machine", "design/time-machine.md", "Vision note for reconstructing work over time.", "design"),
_entry("Whole Product", "design/whole-product.md", "Product vision and system relationships.", "design"),
# Historical and generated material
- _entry(
- "Closed-Issue Workload Audit",
- "audits/2026-05-19-closed-issue-workload-audit.md",
- "Historical audit of closed-issue workload.",
- "archive",
- ),
- _entry(
- "Cross-Surface Coherence Audit",
- "audits/2026-05-20-cross-surface-coherence-audit.md",
- "Historical cross-surface coherence audit.",
- "archive",
- ),
- _entry("API Bypass Audit", "audits/2026-05-25-api-bypass-audit.md", "Historical audit of API bypasses.", "archive"),
- _entry(
- "Daemon Loop Lock-Starvation Map",
- "audits/2026-07-09-daemon-loop-lock-starvation-map.md",
- "Lock-starvation investigation record.",
- "archive",
- ),
- _entry(
- "Hash Boundary Census",
- "audits/2026-07-09-hash-boundary-census.md",
- "Hash-boundary investigation record.",
- "archive",
- ),
- _entry(
- "Race Window Audit", "audits/2026-07-09-race-window-audit.md", "Race-window investigation record.", "archive"
- ),
- _entry(
- "Reindex Forcing-Class Audit",
- "audits/2026-08-04-reindex-forcing-class-audit.md",
- "Forcing-class and reindex-gate evidence audit.",
- "archive",
- ),
- _entry(
- "Blob-Reference Liveness Closure Audit",
- "audits/2026-08-04-blob-ref-liveness-closure.md",
- "I3 live evidence, source-tier reconciliation safeguards, and the direct-reindex gate.",
- "archive",
- ),
- _entry(
- "Raw-Failure Preflight",
- "audits/2026-08-04-raw-failure-preflight.md",
- "Read-only raw-failure census before lifecycle evidence deployment.",
- "archive",
- ),
- _entry(
- "ChatGPT Lifecycle-Anchor Evidence Packet",
- "audits/2026-08-04-polylogue-uqwd-chatgpt-lifecycle-anchor.md",
- "Current-corpus evidence for ChatGPT generation lifecycle-anchor drift.",
- "archive",
- ),
- _entry("Audit Record Index", "audits/README.md", "Index of dated investigation records.", "archive"),
+ _entry("Audit Record Index", "audits/README.md", "Index of retained investigation records.", "archive"),
_entry(
"1498 Cascade Retrospective",
"retro/2026-05-24-1498-cascade.md",
@@ -512,24 +336,6 @@ def _entry(title: str, path: str, description: str, tier: DocsTier) -> DocsEntry
"archive",
),
_entry("Retrospective Index", "retro/README.md", "Index of historical incident retrospectives.", "archive"),
- _entry(
- "Query Pipeline Substrate Plan",
- "plans/query-pipeline-substrate.md",
- "Historical/active query pipeline design plan.",
- "archive",
- ),
- _entry(
- "Nine-Bead Decision Adjudication",
- "plans/decision-adjudication-kea7p-avna-cijx-uh6c-rxdo9-ze5-dx1-fie-ca4.md",
- "Implementation decisions and dependency graph for nine architecture Beads.",
- "archive",
- ),
- _entry(
- "Semantic Card Tool Map",
- "generated/semantic-card-tool-map.md",
- "Generated map from semantic cards to tools.",
- "archive",
- ),
)
REPO_GUIDE_ENTRIES: tuple[DocsEntry, ...] = (
@@ -555,7 +361,6 @@ def _entry(title: str, path: str, description: str, tier: DocsTier) -> DocsEntry
"Getting Started",
"Installation",
"Demos and Proofs",
- "Proof Artifacts",
"Architecture",
"Code Navigation",
"Search & Query",
diff --git a/devtools/evidence_dashboard.py b/devtools/evidence_dashboard.py
deleted file mode 100644
index 2f167bb49b..0000000000
--- a/devtools/evidence_dashboard.py
+++ /dev/null
@@ -1,562 +0,0 @@
-"""Evidence dashboard and changed-path traceability.
-
-Reads real artifacts emitted by the verification pipeline and presents them
-as a single dashboard for operators and PR consumers. Unlike
-``devtools evidence-report`` (which focuses on verify-history + suppressions),
-this command aggregates the full pytest-first evidence surface introduced by
-PRs #1083/#1086/#1087/#1088:
-
-- pytest health from ``.cache/verify/last-pytest.json``;
-- coverage from ``.coverage`` / ``coverage.xml`` when present;
-- benchmark/SLO catalog rows and their required-artifact coverage;
-- static gate status from the shared XDG verify history;
-- witness lifecycle counts;
-- mutation/benchmark campaign freshness.
-
-All sections are backed by real artifacts. Sections with no underlying file
-are reported as ``"available": false`` with the reason — no aspirational rows.
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import sys
-import xml.etree.ElementTree as ET
-from datetime import datetime, timezone
-from pathlib import Path
-from typing import Any
-
-from devtools import repo_root as _get_root
-from devtools.verify_runs import VERIFY_HISTORY_PATH, git_dirty, git_head
-from devtools.verify_runs import worktree_fingerprint as _worktree_fingerprint
-
-ROOT = _get_root()
-
-# Artifact paths (relative to repo root).
-PYTEST_REPORT_REL = Path(".cache/verify/last-pytest.json")
-LAST_VERIFY_RESULT_REL = Path(".cache/last-verify-result.json")
-COVERAGE_DATA_REL = Path(".coverage")
-COVERAGE_XML_REL = Path("coverage.xml")
-WITNESSES_COMMITTED_REL = Path("tests/witnesses")
-WITNESSES_LOCAL_REL = Path(".local/witnesses")
-BENCHMARK_CAMPAIGNS_REL = Path(".local/benchmark-campaigns")
-MUTATION_CAMPAIGNS_REL = Path(".local/mutation-campaigns")
-SLO_CATALOG_REL = Path("docs/plans/slo-catalog.yaml")
-
-DEFAULT_STALE_DAYS = 7
-
-
-# ──────────────────────────────────────────────────────────────────────
-# Section: pytest health
-# ──────────────────────────────────────────────────────────────────────
-
-
-def _pytest_health(root: Path, *, now: datetime) -> dict[str, Any]:
- report_path = root / PYTEST_REPORT_REL
- if not report_path.exists():
- return {
- "available": False,
- "reason": f"missing {PYTEST_REPORT_REL} — run devtools verify",
- "path": str(PYTEST_REPORT_REL),
- }
- try:
- raw = json.loads(report_path.read_text())
- except (OSError, json.JSONDecodeError) as exc:
- return {
- "available": False,
- "reason": f"unreadable {PYTEST_REPORT_REL}: {exc}",
- "path": str(PYTEST_REPORT_REL),
- }
- if not isinstance(raw, dict):
- return {
- "available": False,
- "reason": f"{PYTEST_REPORT_REL} not a JSON object",
- "path": str(PYTEST_REPORT_REL),
- }
- raw_summary = raw.get("summary")
- summary: dict[str, Any] = raw_summary if isinstance(raw_summary, dict) else {}
- mtime = datetime.fromtimestamp(report_path.stat().st_mtime, tz=timezone.utc)
- age_days = (now - mtime).days
- counts: dict[str, int] = {}
- for key in ("passed", "failed", "error", "skipped", "xfailed", "xpassed", "total"):
- value = summary.get(key)
- if isinstance(value, int):
- counts[key] = value
- failed = counts.get("failed", 0) + counts.get("error", 0)
- status = "ok" if failed == 0 else "fail"
- return {
- "available": True,
- "path": str(PYTEST_REPORT_REL),
- "status": status,
- "counts": counts,
- "duration_s": (round(float(raw["duration"]), 2) if isinstance(raw.get("duration"), (int, float)) else None),
- "last_run": mtime.isoformat(),
- "age_days": age_days,
- "stale": age_days > DEFAULT_STALE_DAYS,
- }
-
-
-# ──────────────────────────────────────────────────────────────────────
-# Section: coverage
-# ──────────────────────────────────────────────────────────────────────
-
-
-def _coverage(root: Path) -> dict[str, Any]:
- xml_path = root / COVERAGE_XML_REL
- data_path = root / COVERAGE_DATA_REL
- if xml_path.exists():
- try:
- tree = ET.parse(xml_path)
- attrib = tree.getroot().attrib
- line_rate = float(attrib.get("line-rate", "0"))
- return {
- "available": True,
- "path": str(COVERAGE_XML_REL),
- "line_rate": round(line_rate, 4),
- "percent": round(line_rate * 100, 2),
- "lines_covered": int(attrib["lines-covered"]) if "lines-covered" in attrib else None,
- "lines_valid": int(attrib["lines-valid"]) if "lines-valid" in attrib else None,
- }
- except (OSError, ET.ParseError, ValueError) as exc:
- return {
- "available": False,
- "reason": f"unreadable {COVERAGE_XML_REL}: {exc}",
- "path": str(COVERAGE_XML_REL),
- }
- if data_path.exists():
- mtime = datetime.fromtimestamp(data_path.stat().st_mtime, tz=timezone.utc)
- return {
- "available": True,
- "path": str(COVERAGE_DATA_REL),
- "note": "binary .coverage present — run coverage report/xml for percent",
- "mtime": mtime.isoformat(),
- }
- return {
- "available": False,
- "reason": "no coverage.xml or .coverage found — run devtools verify coverage",
- "path": str(COVERAGE_XML_REL),
- }
-
-
-# ──────────────────────────────────────────────────────────────────────
-# Section: benchmark / SLO catalog
-# ──────────────────────────────────────────────────────────────────────
-
-
-def _benchmark_slo(root: Path, *, now: datetime) -> dict[str, Any]:
- out: dict[str, Any] = {}
- campaigns_dir = root / BENCHMARK_CAMPAIGNS_REL
- if campaigns_dir.exists():
- runs: list[dict[str, Any]] = []
- for json_file in sorted(campaigns_dir.glob("**/*.json")):
- mtime = datetime.fromtimestamp(json_file.stat().st_mtime, tz=timezone.utc)
- runs.append(
- {
- "name": json_file.stem,
- "path": str(json_file.relative_to(root)),
- "mtime": mtime.isoformat(),
- "age_days": (now - mtime).days,
- }
- )
- out["benchmark_campaigns"] = {
- "available": True,
- "path": str(BENCHMARK_CAMPAIGNS_REL),
- "total_runs": len(runs),
- "runs": runs,
- }
- else:
- out["benchmark_campaigns"] = {
- "available": False,
- "reason": f"missing {BENCHMARK_CAMPAIGNS_REL} — run devtools bench campaign run ",
- "path": str(BENCHMARK_CAMPAIGNS_REL),
- }
- slo_path = root / SLO_CATALOG_REL
- if slo_path.exists():
- try:
- from devtools.verify_slos import _parse_slo_catalog
-
- surfaces = _parse_slo_catalog(slo_path.read_text())
- required = [
- name
- for name, cfg in surfaces.items()
- if isinstance(cfg.get("gate"), str) and cfg.get("gate") == "required"
- ]
- informational = [
- name
- for name, cfg in surfaces.items()
- if isinstance(cfg.get("gate"), str) and cfg.get("gate") == "informational"
- ]
- out["slo_catalog"] = {
- "available": True,
- "path": str(SLO_CATALOG_REL),
- "total_surfaces": len(surfaces),
- "required_surfaces": sorted(required),
- "informational_surfaces": sorted(informational),
- }
- except (OSError, ValueError) as exc:
- out["slo_catalog"] = {
- "available": False,
- "reason": f"unreadable {SLO_CATALOG_REL}: {exc}",
- "path": str(SLO_CATALOG_REL),
- }
- else:
- out["slo_catalog"] = {
- "available": False,
- "reason": f"missing {SLO_CATALOG_REL}",
- "path": str(SLO_CATALOG_REL),
- }
- return out
-
-
-# ──────────────────────────────────────────────────────────────────────
-# Section: static gates (from verify history)
-# ──────────────────────────────────────────────────────────────────────
-
-
-_STATIC_GATE_NAMES: tuple[str, ...] = (
- "ruff format",
- "ruff check",
- "mypy",
- "render all",
- "verify layering",
- "lab schema roundtrip",
- "verify manifests",
-)
-
-
-def _static_evidence_is_bound(
- entry: dict[str, Any],
- *,
- checkout_root: str,
- checkout_head: str | None,
- worktree_fingerprint: str,
-) -> bool:
- """Accept only evidence tied to the exact checkout contents being viewed."""
- steps = entry.get("steps")
- stability_failed = isinstance(steps, list) and any(
- isinstance(step, dict) and step.get("name") == "checkout stability" and step.get("exit") != 0 for step in steps
- )
- return (
- not stability_failed
- and entry.get("diagnosis") not in {"checkout_changed_during_verification", "checkout_fingerprint_unavailable"}
- and entry.get("checkout_root") == checkout_root
- and entry.get("git_head") == checkout_head
- and entry.get("worktree_fingerprint") == worktree_fingerprint
- and entry.get("final_worktree_fingerprint") == worktree_fingerprint
- )
-
-
-def _static_gates(root: Path, *, now: datetime) -> dict[str, Any]:
- history_path = VERIFY_HISTORY_PATH
- last_result_path = root / LAST_VERIFY_RESULT_REL
- checkout_root = str(root.resolve())
- checkout_head = git_head(root)
- checkout_dirty = git_dirty(root)
- fingerprint = None if checkout_dirty or checkout_head is None else _worktree_fingerprint(root)
- worktree_fingerprint = None if fingerprint == "unavailable" else fingerprint
- identity_available = checkout_head is not None and worktree_fingerprint is not None
-
- # Prefer last-verify-result.json (the most recent run) then walk back through
- # history to find the last status for each gate.
- last_steps: dict[str, dict[str, Any]] = {}
- last_result_mtime: str | None = None
- if last_result_path.exists():
- try:
- data = json.loads(last_result_path.read_text())
- result = data.get("result") if isinstance(data, dict) else None
- if (
- isinstance(result, dict)
- and worktree_fingerprint is not None
- and _static_evidence_is_bound(
- result,
- checkout_root=checkout_root,
- checkout_head=checkout_head,
- worktree_fingerprint=worktree_fingerprint,
- )
- ):
- for step in result.get("steps", []):
- if isinstance(step, dict) and isinstance(step.get("name"), str):
- last_steps[step["name"]] = step
- last_result_mtime = result.get("timestamp")
- except (OSError, json.JSONDecodeError):
- pass
-
- history_entries: list[dict[str, Any]] = []
- if history_path.exists():
- try:
- with history_path.open() as fh:
- for line in fh:
- line = line.strip()
- if not line:
- continue
- try:
- history_entries.append(json.loads(line))
- except json.JSONDecodeError:
- continue
- except OSError:
- pass
-
- # Fill in any gates missing from last-verify-result with the most recent
- # appearance in history.
- if history_entries:
- for entry in reversed(history_entries):
- if worktree_fingerprint is None or not _static_evidence_is_bound(
- entry,
- checkout_root=checkout_root,
- checkout_head=checkout_head,
- worktree_fingerprint=worktree_fingerprint,
- ):
- continue
- steps = entry.get("steps", [])
- for step in steps:
- if not isinstance(step, dict):
- continue
- name = step.get("name")
- if isinstance(name, str) and name not in last_steps:
- last_steps[name] = {**step, "_source": "history", "_run_timestamp": entry.get("timestamp")}
-
- gates: list[dict[str, Any]] = []
- for gate_name in _STATIC_GATE_NAMES:
- step = last_steps.get(gate_name)
- if step is None:
- reason = (
- "checkout has uncommitted changes"
- if checkout_dirty
- else "checkout Git identity is unavailable"
- if not identity_available
- else "no bound run observed in cached history"
- )
- gates.append({"name": gate_name, "available": False, "reason": reason})
- continue
- exit_code = step.get("exit", -1)
- gates.append(
- {
- "name": gate_name,
- "available": True,
- "status": "ok" if exit_code == 0 else "fail",
- "exit_code": exit_code,
- "duration_s": step.get("duration_s"),
- "last_run": step.get("_run_timestamp", last_result_mtime),
- }
- )
- failing = [g for g in gates if g.get("status") == "fail"]
- return {
- "available": bool(last_steps) and not checkout_dirty and identity_available,
- "history_path": str(history_path),
- "last_result_path": str(LAST_VERIFY_RESULT_REL),
- "total_gates_tracked": len(_STATIC_GATE_NAMES),
- "gates_with_status": sum(1 for g in gates if g.get("available")),
- "failing": [g["name"] for g in failing],
- "gates": gates,
- "history_runs": len(history_entries),
- }
-
-
-# ──────────────────────────────────────────────────────────────────────
-# Section: witnesses
-# ──────────────────────────────────────────────────────────────────────
-
-
-def _witnesses(root: Path) -> dict[str, Any]:
- committed = root / WITNESSES_COMMITTED_REL
- local = root / WITNESSES_LOCAL_REL
- committed_files = sorted(committed.glob("*.witness.json")) if committed.exists() else []
- local_files = sorted(local.glob("**/*.witness.json")) if local.exists() else []
- return {
- "committed": {
- "available": committed.exists(),
- "path": str(WITNESSES_COMMITTED_REL),
- "count": len(committed_files),
- },
- "local": {
- "available": local.exists(),
- "path": str(WITNESSES_LOCAL_REL),
- "count": len(local_files),
- },
- }
-
-
-# ──────────────────────────────────────────────────────────────────────
-# Section: mutation campaigns
-# ──────────────────────────────────────────────────────────────────────
-
-
-def _mutation_campaigns(root: Path, *, now: datetime) -> dict[str, Any]:
- mut_dir = root / MUTATION_CAMPAIGNS_REL
- if not mut_dir.exists():
- return {
- "available": False,
- "reason": f"missing {MUTATION_CAMPAIGNS_REL} — run devtools bench mutation run ",
- "path": str(MUTATION_CAMPAIGNS_REL),
- }
- campaigns: dict[str, dict[str, Any]] = {}
- for child in sorted(mut_dir.iterdir()):
- if not child.is_dir():
- continue
- latest_mtime: float | None = None
- files = 0
- for f in child.rglob("*"):
- if f.is_file():
- files += 1
- m = f.stat().st_mtime
- if latest_mtime is None or m > latest_mtime:
- latest_mtime = m
- entry: dict[str, Any] = {"files": files}
- if latest_mtime is not None:
- mtime = datetime.fromtimestamp(latest_mtime, tz=timezone.utc)
- entry["latest_mtime"] = mtime.isoformat()
- entry["age_days"] = (now - mtime).days
- campaigns[child.name] = entry
- return {
- "available": True,
- "path": str(MUTATION_CAMPAIGNS_REL),
- "total_campaigns": len(campaigns),
- "campaigns": campaigns,
- }
-
-
-# ──────────────────────────────────────────────────────────────────────
-# Dashboard assembly
-# ──────────────────────────────────────────────────────────────────────
-
-
-def build_dashboard(root: Path, *, now: datetime | None = None) -> dict[str, Any]:
- """Build the complete verify evidence payload from real artifacts."""
- when = now or datetime.now(timezone.utc)
- benchmark_section = _benchmark_slo(root, now=when)
- return {
- "schema_version": 1,
- "generated_at": when.isoformat(),
- "root": str(root),
- "pytest": _pytest_health(root, now=when),
- "coverage": _coverage(root),
- "benchmark_campaigns": benchmark_section["benchmark_campaigns"],
- "slo_catalog": benchmark_section["slo_catalog"],
- "static_gates": _static_gates(root, now=when),
- "witnesses": _witnesses(root),
- "mutation_campaigns": _mutation_campaigns(root, now=when),
- }
-
-
-# ──────────────────────────────────────────────────────────────────────
-# Markdown rendering
-# ──────────────────────────────────────────────────────────────────────
-
-
-def _availability_marker(available: bool) -> str:
- return "yes" if available else "no"
-
-
-def render_markdown(dashboard: dict[str, Any]) -> str:
- lines: list[str] = []
- lines.append(f"# Evidence Dashboard ({dashboard.get('generated_at', 'unknown')})")
- lines.append("")
-
- pytest_data = dashboard["pytest"]
- lines.append("## Pytest health")
- if pytest_data.get("available"):
- counts = pytest_data.get("counts", {})
- stale = " (stale)" if pytest_data.get("stale") else ""
- lines.append(
- f"- status: **{pytest_data.get('status')}** — passed={counts.get('passed', 0)}, "
- f"failed={counts.get('failed', 0)}, xfailed={counts.get('xfailed', 0)}, "
- f"skipped={counts.get('skipped', 0)}"
- )
- lines.append(
- f"- duration: {pytest_data.get('duration_s', '?')}s, last_run: {pytest_data.get('last_run')}{stale}"
- )
- else:
- lines.append(f"- unavailable: {pytest_data.get('reason')}")
- lines.append("")
-
- coverage = dashboard["coverage"]
- lines.append("## Coverage")
- if coverage.get("available"):
- if "percent" in coverage:
- lines.append(f"- line coverage: {coverage['percent']}% (from {coverage['path']})")
- else:
- lines.append(f"- {coverage.get('note', 'present')} ({coverage['path']})")
- else:
- lines.append(f"- unavailable: {coverage.get('reason')}")
- lines.append("")
-
- bench = dashboard["benchmark_campaigns"]
- lines.append("## Benchmark campaigns")
- if bench.get("available"):
- lines.append(f"- total_runs: {bench.get('total_runs')}")
- else:
- lines.append(f"- unavailable: {bench.get('reason')}")
- lines.append("")
-
- slo = dashboard["slo_catalog"]
- lines.append("## SLO catalog")
- if slo.get("available"):
- lines.append(
- f"- surfaces: {slo.get('total_surfaces')} "
- f"(required={len(slo.get('required_surfaces', []))}, "
- f"informational={len(slo.get('informational_surfaces', []))})"
- )
- else:
- lines.append(f"- unavailable: {slo.get('reason')}")
- lines.append("")
-
- gates = dashboard["static_gates"]
- lines.append("## Static gates")
- if gates.get("available"):
- lines.append(
- f"- gates with cached status: {gates['gates_with_status']}/{gates['total_gates_tracked']}, "
- f"failing: {len(gates['failing'])}"
- )
- if gates["failing"]:
- lines.append(f" - failing: {', '.join(gates['failing'])}")
- else:
- lines.append("- unavailable: no verify history found")
- lines.append("")
-
- witnesses = dashboard["witnesses"]
- lines.append("## Witnesses")
- lines.append(
- f"- committed: {witnesses['committed']['count']} ({_availability_marker(witnesses['committed']['available'])}), "
- f"local: {witnesses['local']['count']} ({_availability_marker(witnesses['local']['available'])})"
- )
- lines.append("")
-
- mut = dashboard["mutation_campaigns"]
- lines.append("## Mutation campaigns")
- if mut.get("available"):
- lines.append(f"- total_campaigns: {mut.get('total_campaigns')}")
- else:
- lines.append(f"- unavailable: {mut.get('reason')}")
- lines.append("")
-
- return "\n".join(lines)
-
-
-# ──────────────────────────────────────────────────────────────────────
-# CLI
-# ──────────────────────────────────────────────────────────────────────
-
-
-def _emit_dashboard(args: argparse.Namespace) -> int:
- dashboard = build_dashboard(ROOT)
- if args.json or not args.markdown:
- json.dump(dashboard, sys.stdout, indent=2, sort_keys=True)
- sys.stdout.write("\n")
- if args.markdown:
- sys.stdout.write(render_markdown(dashboard))
- sys.stdout.write("\n")
- return 0
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--json", action="store_true", help="Emit JSON output (default).")
- parser.add_argument("--markdown", action="store_true", help="Emit Markdown output (combinable with --json).")
-
- args = parser.parse_args(argv)
- return _emit_dashboard(args)
-
-
-if __name__ == "__main__":
- sys.exit(main(sys.argv[1:]))
diff --git a/devtools/frontier_report.py b/devtools/frontier_report.py
deleted file mode 100644
index 07affbedde..0000000000
--- a/devtools/frontier_report.py
+++ /dev/null
@@ -1,536 +0,0 @@
-"""Derive the execution focus from the complete Beads frontier.
-
-The report keeps three deliberately separate sets:
-
-* full ambition: every open or in-progress Bead;
-* active set: Beads explicitly admitted through structured frontier metadata;
-* execution focus: ready, unclaimed admitted active leaves selected after
- declared resource and footprint-conflict constraints.
-
-It only reports those derivations. It never claims, releases, truncates, or
-otherwise mutates Beads admission state.
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import subprocess
-import sys
-from collections import defaultdict
-from datetime import datetime, timezone
-from pathlib import Path
-from typing import Any
-
-from devtools import bead_cluster
-
-ROOT = Path(__file__).resolve().parents[1]
-
-# This is a focus-selection policy, not an active-set cap. It is visible in
-# every JSON report, so a coordinator can see exactly why a ready Bead waits.
-RESOURCE_POLICY: dict[str, dict[str, Any]] = {
- "schema-lane": {"max_parallel": 1, "reason": "schema changes serialize through the active schema owner"},
- "live-state": {"max_parallel": 1, "reason": "live-state work requires one operator-controlled lane"},
- "ordinary": {"max_parallel": None, "reason": "no shared resource limit declared"},
-}
-
-_MAX_FRONTIER_RECORDS = 100_000
-_SCHEMA_TEXT_MARKERS = (
- "index_schema_version",
- "source_schema_version",
- "user_schema_version",
- "canonical ddl",
- "schema migration",
- "schema change",
-)
-_CANONICAL_TIER_DDL_SUFFIXES = (
- "storage/sqlite/archive_tiers/index.py",
- "storage/sqlite/archive_tiers/source.py",
- "storage/sqlite/archive_tiers/user.py",
-)
-_STALE_CLAIM_DAYS = 7
-
-
-def _parser() -> argparse.ArgumentParser:
- parser = argparse.ArgumentParser(
- prog="devtools workspace frontier",
- description="Derive a complete, non-mutating execution focus from live Beads state.",
- )
- parser.add_argument("--repo", type=Path, default=ROOT, help="Repository root containing the Beads workspace.")
- parser.add_argument("--json", action="store_true", help="Emit machine-readable JSON.")
- parser.add_argument("--out", type=Path, default=None, help="Write the report to this path.")
- return parser
-
-
-def _run_bd(repo: Path, args: list[str]) -> list[Any]:
- command = [
- "bd",
- "--readonly",
- *args,
- "--limit",
- str(_MAX_FRONTIER_RECORDS + 1),
- "--max-rows",
- str(_MAX_FRONTIER_RECORDS + 1),
- "--json",
- ]
- try:
- completed = subprocess.run(command, cwd=repo, text=True, capture_output=True, timeout=20, check=False)
- except (OSError, subprocess.TimeoutExpired) as exc:
- raise RuntimeError(f"failed to run {' '.join(command)}: {exc}") from exc
- if completed.returncode != 0:
- detail = completed.stderr.strip() or completed.stdout.strip()
- raise RuntimeError(f"{' '.join(command)} failed: {detail}")
- try:
- payload = json.loads(completed.stdout)
- except json.JSONDecodeError as exc:
- raise RuntimeError(f"{' '.join(command)} returned non-JSON output") from exc
- if isinstance(payload, list):
- if len(payload) > _MAX_FRONTIER_RECORDS:
- raise RuntimeError(
- f"{' '.join(command)} exceeded the {_MAX_FRONTIER_RECORDS:,}-record complete-report bound"
- )
- return payload
- raise RuntimeError(f"{' '.join(command)} returned {type(payload).__name__}, expected list")
-
-
-def _normalize_issues(records: list[Any], *, source: str) -> list[dict[str, Any]]:
- """Validate the live Beads records once before report derivation."""
- normalized: list[dict[str, Any]] = []
- seen_ids: set[str] = set()
- for index, record in enumerate(records):
- if not isinstance(record, dict):
- raise RuntimeError(f"{source} record {index} is {type(record).__name__}, expected object with string id")
- bead_id = record.get("id")
- if not isinstance(bead_id, str) or not bead_id:
- raise RuntimeError(f"{source} record {index} has no non-empty string id")
- if bead_id in seen_ids:
- raise RuntimeError(f"{source} record {index} duplicates id {bead_id!r}")
- seen_ids.add(bead_id)
- normalized.append(record)
- return normalized
-
-
-def _labels(issue: dict[str, Any]) -> set[str]:
- labels = issue.get("labels")
- return {label for label in labels if isinstance(label, str)} if isinstance(labels, list) else set()
-
-
-def _metadata(issue: dict[str, Any]) -> dict[str, Any]:
- metadata = issue.get("metadata")
- return metadata if isinstance(metadata, dict) else {}
-
-
-def _is_active_program(issue: dict[str, Any]) -> bool:
- return _metadata(issue).get("frontier_program") == "active"
-
-
-def _priority(issue: dict[str, Any]) -> int:
- try:
- return int(issue.get("priority", 2))
- except (TypeError, ValueError):
- return 2
-
-
-def _is_open(issue: dict[str, Any]) -> bool:
- return issue.get("status") in {"open", "in_progress"}
-
-
-def _is_executable_leaf(issue: dict[str, Any]) -> bool:
- """Whether a record represents work that can occupy an execution lane."""
- return issue.get("issue_type") not in {"epic", "program"}
-
-
-def _parse_timestamp(value: object) -> datetime | None:
- if not isinstance(value, str) or not value.strip():
- return None
- try:
- return datetime.fromisoformat(value.replace("Z", "+00:00"))
- except ValueError:
- return None
-
-
-def _claim_is_live(issue: dict[str, Any], *, now: datetime, stale_claim_days: int) -> bool:
- updated = _parse_timestamp(issue.get("updated_at"))
- if updated is None:
- # Keep legacy records schedulable until the backlog hygiene check can
- # supply a structured activity timestamp. A known stale timestamp is
- # enough to reject ownership; an absent timestamp is not evidence of
- # staleness by itself.
- return True
- if updated.tzinfo is None:
- updated = updated.replace(tzinfo=timezone.utc)
- return (now - updated).total_seconds() <= stale_claim_days * 86400
-
-
-def _valid_active_leaf_ids(issues: list[dict[str, Any]]) -> set[str]:
- by_id = {str(issue["id"]): issue for issue in issues}
- valid: set[str] = set()
- for issue in issues:
- if not (_is_open(issue) and _is_executable_leaf(issue) and _metadata(issue).get("frontier") == "active"):
- continue
- program_ref = _metadata(issue).get("frontier_program_ref")
- if isinstance(program_ref, str) and program_ref and _is_active_program(by_id.get(program_ref, {})):
- valid.add(str(issue["id"]))
- return valid
-
-
-def _resource_classes(issue: dict[str, Any], footprint: bead_cluster.Footprint) -> tuple[str, ...]:
- labels = _labels(issue)
- text = " ".join(str(issue.get(field, "")) for field in ("design", "acceptance_criteria", "description")).lower()
- resources: list[str] = []
- if (
- footprint.migration_slots
- or "area:schema" in labels
- or any(marker in text for marker in _SCHEMA_TEXT_MARKERS)
- or any("schema" in path.lower() and "storage" in path.lower() for path in footprint.files)
- or any(path.lower().endswith(suffix) for path in footprint.files for suffix in _CANONICAL_TIER_DDL_SUFFIXES)
- ):
- resources.append("schema-lane")
- if "resource:live-state" in labels or "risk:live-state" in labels:
- resources.append("live-state")
- return tuple(resources) or ("ordinary",)
-
-
-def _active_set(issues: list[dict[str, Any]]) -> list[str]:
- return sorted(
- str(issue["id"])
- for issue in issues
- if _is_open(issue) and _is_executable_leaf(issue) and _metadata(issue).get("frontier") == "active"
- )
-
-
-def _active_set_rows(issues: list[dict[str, Any]], ready_ids: set[str]) -> list[dict[str, Any]]:
- """Expose readiness, blockers, and program grouping for admitted leaves."""
- active_ids = set(_active_set(issues))
- by_id = {str(issue["id"]): issue for issue in issues}
- rows: list[dict[str, Any]] = []
- for issue_id in sorted(active_ids):
- issue = by_id[issue_id]
- blockers = sorted(
- (
- str(dependency["depends_on_id"])
- if str(dependency.get("depends_on_id", "")) in by_id
- else f"{str(dependency.get('depends_on_id', '')) or ''} (missing)"
- )
- for dependency in issue.get("dependencies", [])
- if isinstance(dependency, dict)
- and dependency.get("type") == "blocks"
- and (
- str(dependency.get("depends_on_id", "")) not in by_id
- or by_id[str(dependency["depends_on_id"])].get("status") != "closed"
- )
- )
- rows.append(
- {
- "id": issue_id,
- "title": str(issue.get("title", "")),
- "status": str(issue.get("status", "unknown")),
- "priority": _priority(issue),
- "dependency_ready": issue_id in ready_ids,
- "blocked_by": blockers,
- "frontier_program_ref": _metadata(issue).get("frontier_program_ref"),
- }
- )
- return rows
-
-
-def _full_ambition(issues: list[dict[str, Any]]) -> list[dict[str, Any]]:
- """Return every open Bead with the fields needed to audit its admission."""
- rows: list[dict[str, Any]] = []
- for issue in issues:
- if not _is_open(issue):
- continue
- metadata = _metadata(issue)
- rows.append(
- {
- "id": str(issue["id"]),
- "title": str(issue.get("title", "")),
- "status": str(issue.get("status", "unknown")),
- "priority": _priority(issue),
- "issue_type": str(issue.get("issue_type", "unknown")),
- "frontier": metadata.get("frontier"),
- "frontier_program_ref": metadata.get("frontier_program_ref"),
- "horizons": sorted(label for label in _labels(issue) if label.startswith("horizon:")),
- }
- )
- return sorted(rows, key=lambda row: str(row["id"]))
-
-
-def _critical_path_leverage(issues: list[dict[str, Any]]) -> dict[str, int]:
- """Count downstream work unblocked through exclusively single-blocker paths."""
- blocked_by: dict[str, set[str]] = defaultdict(set)
- known = {issue["id"]: issue for issue in issues}
- for child_id, issue in known.items():
- if not _is_open(issue):
- continue
- dependencies = issue.get("dependencies")
- remaining_blockers: set[str] = set()
- for dependency in dependencies if isinstance(dependencies, list) else []:
- if not isinstance(dependency, dict) or dependency.get("type") != "blocks":
- continue
- target = dependency.get("depends_on_id")
- if not isinstance(target, str) or not target:
- continue
- blocker = known.get(target)
- if blocker is None or blocker.get("status") != "closed":
- remaining_blockers.add(target)
- if len(remaining_blockers) == 1:
- blocked_by[next(iter(remaining_blockers))].add(child_id)
- leverage: dict[str, int] = {}
- for blocker_id in blocked_by:
- reachable: set[str] = set()
- pending = list(blocked_by[blocker_id])
- while pending:
- child = pending.pop()
- if child in reachable:
- continue
- reachable.add(child)
- pending.extend(blocked_by.get(child, ()))
- leverage[blocker_id] = len(reachable)
- return leverage
-
-
-def _footprint_conflicts(issue_id: str, occupied_ids: list[str], footprint_keys: dict[str, set[str]]) -> list[str]:
- keys = footprint_keys[issue_id]
- return sorted(other_id for other_id in occupied_ids if keys & footprint_keys[other_id])
-
-
-def _candidate_row(
- issue: dict[str, Any],
- *,
- footprint: bead_cluster.Footprint,
- footprint_keys: dict[str, set[str]],
- leverage: int,
- occupied_ids: list[str],
- ready_ids: set[str],
-) -> dict[str, Any]:
- issue_id = issue["id"]
- resource_classes = _resource_classes(issue, footprint)
- return {
- "id": issue_id,
- "title": str(issue.get("title", "")),
- "status": str(issue.get("status", "unknown")),
- "priority": _priority(issue),
- "dependency_ready": issue_id in ready_ids,
- "critical_path_leverage": leverage,
- "resource_class": resource_classes[0],
- "resource_classes": list(resource_classes),
- "conflicts_with_claims": _footprint_conflicts(issue_id, occupied_ids, footprint_keys),
- "frontier_program_ref": _metadata(issue).get("frontier_program_ref"),
- }
-
-
-def derive_execution_focus(issues: list[dict[str, Any]], ready_ids: set[str]) -> dict[str, Any]:
- """Select every executable candidate permitted by the declared policy.
-
- Claims occupy resource classes and footprint keys. Candidates remain in
- the report whether selected or deferred, making this a transparent focus
- derivation rather than a hidden admission or count-pruning mechanism.
- """
- open_issues = [issue for issue in issues if _is_open(issue)]
- footprints = {issue["id"]: bead_cluster.extract_footprint(issue) for issue in open_issues}
- footprint_keys = {
- issue_id: footprint.overlap_keys() | footprint.contention_keys() for issue_id, footprint in footprints.items()
- }
- now = datetime.now(timezone.utc)
- claims = sorted(
- (
- issue
- for issue in open_issues
- if issue.get("status") == "in_progress"
- and _is_executable_leaf(issue)
- and _claim_is_live(issue, now=now, stale_claim_days=_STALE_CLAIM_DAYS)
- ),
- key=lambda item: item["id"],
- )
- claim_ids = [issue["id"] for issue in claims]
- ambiguous_claim_ids = sorted(issue_id for issue_id in claim_ids if not footprint_keys[issue_id])
- leverage = _critical_path_leverage(issues)
- active_ids = _valid_active_leaf_ids(issues)
- candidates = [
- _candidate_row(
- issue,
- footprint=footprints[issue["id"]],
- footprint_keys=footprint_keys,
- leverage=leverage.get(issue["id"], 0),
- occupied_ids=claim_ids,
- ready_ids=ready_ids,
- )
- for issue in open_issues
- if issue.get("status") == "open" and issue["id"] in ready_ids and issue["id"] in active_ids
- ]
- candidates.sort(key=lambda row: (row["priority"], -row["critical_path_leverage"], row["id"]))
-
- occupied_by_resource: dict[str, list[str]] = defaultdict(list)
- for claim in claims:
- for resource_class in _resource_classes(claim, footprints[claim["id"]]):
- occupied_by_resource[resource_class].append(claim["id"])
- selected: list[dict[str, Any]] = []
- deferred: list[dict[str, Any]] = []
- selected_by_resource: dict[str, list[str]] = defaultdict(list)
- for candidate in candidates:
- resource_classes = [str(value) for value in candidate["resource_classes"]]
- conflicts = list(candidate["conflicts_with_claims"])
- selected_conflicts = _footprint_conflicts(candidate["id"], selected_by_resource["all"], footprint_keys)
- saturated_resources = [
- required_resource
- for required_resource in resource_classes
- if (
- (max_parallel := RESOURCE_POLICY[required_resource]["max_parallel"]) is not None
- and (
- len(occupied_by_resource[required_resource]) + len(selected_by_resource[required_resource])
- >= max_parallel
- )
- )
- ]
- if not footprint_keys[candidate["id"]]:
- candidate["focus_state"] = "deferred"
- candidate["reason"] = "footprint is ambiguous; confirm ownership before parallel focus"
- deferred.append(candidate)
- elif ambiguous_claim_ids:
- candidate["focus_state"] = "deferred"
- candidate["reason"] = (
- "active claim footprint is ambiguous; confirm ownership before parallel focus: "
- + ", ".join(ambiguous_claim_ids)
- )
- deferred.append(candidate)
- elif conflicts:
- candidate["focus_state"] = "deferred"
- candidate["reason"] = f"footprint conflict with active claim(s): {', '.join(conflicts)}"
- deferred.append(candidate)
- elif selected_conflicts:
- candidate["focus_state"] = "deferred"
- candidate["reason"] = f"footprint conflict with selected focus: {', '.join(selected_conflicts)}"
- deferred.append(candidate)
- elif saturated_resources:
- saturated_resource = saturated_resources[0]
- saturated_occupied_ids = sorted(occupied_by_resource[saturated_resource])
- candidate["focus_state"] = "deferred"
- if saturated_occupied_ids:
- candidate["reason"] = f"{saturated_resource} occupied by claim(s): {', '.join(saturated_occupied_ids)}"
- else:
- candidate["reason"] = (
- f"{saturated_resource} occupied by selected focus: "
- f"{', '.join(selected_by_resource[saturated_resource])}"
- )
- deferred.append(candidate)
- else:
- candidate["focus_state"] = "focus"
- candidate["reason"] = "ready, unclaimed, and permitted by declared resource policy"
- selected.append(candidate)
- for required_resource in resource_classes:
- selected_by_resource[required_resource].append(candidate["id"])
- selected_by_resource["all"].append(candidate["id"])
- return {
- "resource_policy": RESOURCE_POLICY,
- "occupied_claims": claim_ids,
- "candidates": candidates,
- "focus": selected,
- "deferred": deferred,
- }
-
-
-def build_report(issues: list[Any], ready: list[Any], *, repo: Path) -> dict[str, Any]:
- issues = _normalize_issues(issues, source="bd list")
- ready = _normalize_issues(ready, source="bd ready")
- ready_ids = {issue["id"] for issue in ready}
- issue_ids = {issue["id"] for issue in issues}
- missing_ready_ids = sorted(ready_ids - issue_ids)
- if missing_ready_ids:
- raise RuntimeError(
- "bd ready snapshot contains IDs absent from bd list snapshot: " + ", ".join(missing_ready_ids)
- )
- execution_focus = derive_execution_focus(issues, ready_ids)
- ambition = _full_ambition(issues)
- claims = [
- issue
- for issue in issues
- if _is_open(issue)
- and issue.get("status") == "in_progress"
- and _is_executable_leaf(issue)
- and _claim_is_live(issue, now=datetime.now(timezone.utc), stale_claim_days=_STALE_CLAIM_DAYS)
- ]
- return {
- "report_version": 3,
- "command": "devtools workspace frontier",
- "repo": str(repo),
- "counts": {
- "ambition": len(ambition),
- "active_set": len(_active_set(issues)),
- "claims": len(claims),
- "dependency_ready": len(ready_ids),
- "execution_focus": len(execution_focus["focus"]),
- "deferred": len(execution_focus["deferred"]),
- },
- "ambition": ambition,
- "active_set": _active_set(issues),
- "active_set_rows": _active_set_rows(issues, ready_ids),
- "execution_focus": execution_focus,
- }
-
-
-def _render_markdown(report: dict[str, Any]) -> str:
- counts = report["counts"]
- lines = [
- "# Execution Focus",
- "",
- f"repo: `{report['repo']}`",
- (
- "counts: "
- f"ambition={counts['ambition']} active_set={counts['active_set']} claims={counts['claims']} "
- f"dependency_ready={counts['dependency_ready']} execution_focus={counts['execution_focus']} "
- f"deferred={counts['deferred']}"
- ),
- "",
- "## Active Set",
- "",
- ]
- for item in report.get("active_set_rows", []):
- blockers = ", ".join(item["blocked_by"]) or "none"
- program = item["frontier_program_ref"] or "no program"
- lines.append(
- f"- `{item['id']}` P{item['priority']} ready={item['dependency_ready']} "
- f"blocked_by={blockers} program={program} {item['title']}"
- )
- lines.extend(
- [
- "",
- "## Focus",
- "",
- ]
- )
- for item in report["execution_focus"]["focus"]:
- lines.append(f"- `{item['id']}` P{item['priority']} leverage={item['critical_path_leverage']} {item['title']}")
- lines.extend(["", "## Deferred", ""])
- for item in report["execution_focus"]["deferred"]:
- lines.append(f"- `{item['id']}` P{item['priority']} {item['reason']}")
- lines.extend(["", "## Full Ambition", ""])
- for item in report["ambition"]:
- horizons = ", ".join(item["horizons"]) or "no horizon"
- program = item["frontier_program_ref"] or "no program"
- lines.append(
- f"- `{item['id']}` P{item['priority']} {item['status']} {item['issue_type']} "
- f"program={program} horizons={horizons} {item['title']}"
- )
- return "\n".join(lines)
-
-
-def main(argv: list[str] | None = None) -> int:
- args = _parser().parse_args(argv)
- try:
- issues = _run_bd(args.repo, ["list", "--all"])
- ready = _run_bd(args.repo, ["ready"])
- report = build_report(issues, ready, repo=args.repo)
- except RuntimeError as exc:
- print(f"frontier report failed: {exc}", file=sys.stderr)
- return 1
- output = json.dumps(report, indent=2, sort_keys=True) + "\n" if args.json else _render_markdown(report) + "\n"
- if args.out is not None:
- args.out.parent.mkdir(parents=True, exist_ok=True)
- args.out.write_text(output, encoding="utf-8")
- print(output, end="")
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/generated_surfaces.py b/devtools/generated_surfaces.py
index ae11d6bc4d..58bfb16a39 100644
--- a/devtools/generated_surfaces.py
+++ b/devtools/generated_surfaces.py
@@ -7,19 +7,12 @@
from devtools import (
render_agent_manual,
- render_api_operation_parity,
render_cli_output_schemas,
render_cli_reference,
- render_demo_corpus_datasheet,
render_devtools_reference,
render_docs_surface,
- render_mcp_equivalence,
- render_mcp_tool_index,
render_openapi,
render_pages,
- render_product_workflows,
- render_public_claims,
- render_quality_reference,
render_query_discovery,
render_visual_tapes,
render_webui_client,
@@ -41,23 +34,6 @@ class GeneratedSurface:
GENERATED_SURFACES: tuple[GeneratedSurface, ...] = (
- GeneratedSurface(
- name="api-operation-parity",
- label="Python API operation parity",
- description="Render the semantic-operation matrix and generated Python facade reference.",
- command=control_plane_argv("render api-operation-parity"),
- main=render_api_operation_parity.main,
- inputs=(
- "polylogue/api/__init__.py",
- "polylogue/api/archive.py",
- "polylogue/api/embeddings.py",
- "polylogue/api/ingest.py",
- "polylogue/api/insights.py",
- "polylogue/api/operation_parity.py",
- "devtools/render_api_operation_parity.py",
- "docs/library-api.md",
- ),
- ),
GeneratedSurface(
name="agent-manual",
label="Agent manual",
@@ -75,7 +51,7 @@ class GeneratedSurface:
GeneratedSurface(
name="cli-reference",
label="CLI docs",
- description="Render docs/cli-reference.md from live CLI help and action-contract metadata.",
+ description="Render docs/cli-reference.md from live CLI help.",
command=control_plane_argv("render cli-reference"),
main=render_cli_reference.main,
inputs=(
@@ -94,7 +70,6 @@ class GeneratedSurface:
"polylogue/surfaces/payloads.py",
"polylogue/sources/provider_completeness.py",
"devtools/render_cli_reference.py",
- "devtools/action_contract_report.py",
"devtools/render_cli_output_schemas.py",
"devtools/provider_completeness.py",
),
@@ -177,53 +152,6 @@ class GeneratedSurface:
"devtools/render_devtools_reference.py",
),
),
- GeneratedSurface(
- name="demo-corpus-datasheet",
- label="Demo corpus datasheet",
- description="Render docs/plans/demo-corpus-construct-audit.md from declared demo families and measured seed rows.",
- command=control_plane_argv("render demo-corpus-datasheet"),
- main=render_demo_corpus_datasheet.main,
- inputs=(
- "devtools/render_demo_corpus_datasheet.py",
- "polylogue/demo/",
- "polylogue/scenarios/",
- ),
- ),
- GeneratedSurface(
- name="quality-reference",
- label="Quality docs",
- description="Render docs/test-quality-workflows.md from quality registries.",
- command=control_plane_argv("render quality-reference"),
- main=render_quality_reference.main,
- inputs=(
- "devtools/render_quality_reference.py",
- "devtools/benchmark_catalog.py",
- "devtools/mutation_catalog.py",
- "devtools/quality_registry.py",
- "devtools/run_validation_lanes.py",
- "devtools/scenario_coverage.py",
- "devtools/scenario_projection_catalog.py",
- "devtools/validation_lane_catalog_contracts.py",
- "devtools/validation_lane_catalog_live.py",
- "polylogue/operations/specs.py",
- "polylogue/scenarios/",
- "pyproject.toml",
- ),
- ),
- GeneratedSurface(
- name="product-workflows",
- label="Product workflows",
- description="Render docs/product/workflows.md from query-action workflow registries (#2305).",
- command=control_plane_argv("render product-workflows"),
- main=render_product_workflows.main,
- inputs=(
- "devtools/render_product_workflows.py",
- "polylogue/product/workflows.py",
- "polylogue/operations/action_contracts.py",
- "polylogue/surfaces/action_affordances.py",
- "polylogue/archive/viewport/profiles.py",
- ),
- ),
GeneratedSurface(
name="query-discovery",
label="Query discovery",
@@ -239,24 +167,6 @@ class GeneratedSurface:
"docs/search.md",
),
),
- GeneratedSurface(
- name="public-claims",
- label="Public claims",
- description="Render all public-claim presets and the generated YAML compatibility view.",
- command=control_plane_argv("render public-claims"),
- main=render_public_claims.main,
- inputs=(
- "devtools/render_public_claims.py",
- "devtools/public_claims.py",
- "polylogue/insights/measurement/public_claims.py",
- "polylogue/scenarios/corpus.py",
- "polylogue/storage/sqlite/archive_tiers/user_write.py",
- "polylogue/storage/sqlite/finding_provenance.py",
- "README.md",
- "docs/demos.md",
- "docs/findings/claim-vs-evidence.md",
- ),
- ),
GeneratedSurface(
name="docs-surface",
label="Docs surface",
@@ -276,26 +186,6 @@ class GeneratedSurface:
"README.md",
),
),
- GeneratedSurface(
- name="mcp-equivalence",
- label="MCP algebra equivalence map",
- description="Render the executable MCP contract and migration map as generated JSON.",
- command=control_plane_argv("render mcp-equivalence"),
- main=render_mcp_equivalence.main,
- inputs=(
- "devtools/render_mcp_equivalence.py",
- "polylogue/declarations/",
- "polylogue/mcp/declarations/",
- ),
- ),
- GeneratedSurface(
- name="mcp-tool-index",
- label="MCP tool index",
- description="Render the exhaustive generated tool-name appendix into docs/mcp-reference.md.",
- command=control_plane_argv("render mcp-tool-index"),
- main=render_mcp_tool_index.main,
- inputs=("devtools/render_mcp_tool_index.py", "polylogue/mcp/declarations/registry.py"),
- ),
GeneratedSurface(
name="pages",
label="GitHub Pages",
@@ -320,31 +210,15 @@ class GeneratedSurface:
description="Render (or verify) the committed VHS tape files for the default visual evidence specs.",
command=control_plane_argv("render visual-tapes"),
main=render_visual_tapes.generated_surface_main,
- inputs=(
- "devtools/visual_vhs.py",
- "devtools/render_visual_tapes.py",
- ),
+ inputs=("devtools/visual_vhs.py", "devtools/render_visual_tapes.py"),
),
)
GENERATED_SURFACE_BY_NAME = {surface.name: surface for surface in GENERATED_SURFACES}
-# Commands in `devtools/command_catalog.py`'s "generated surfaces" category
-# that are intentionally NOT registered above, because their check semantics
-# genuinely don't fit the hash-stamp render/--check contract every
-# GeneratedSurface.main follows. Each entry names the bespoke gate that covers
-# it instead, so the exemption is auditable rather than a silent gap --
-# `tests/unit/devtools/test_generated_surfaces.py` fails closed if a new
-# "generated surfaces" command shows up here without either a GENERATED_SURFACES
-# entry or a line in this dict (polylogue-bfc7a). "render all" itself is the
-# orchestrator over this registry, not a member of it, and needs no entry.
-GENERATED_SURFACES_CATALOG_EXEMPTIONS: dict[str, str] = {}
-
-
__all__ = [
"GENERATED_SURFACES",
- "GENERATED_SURFACES_CATALOG_EXEMPTIONS",
"GENERATED_SURFACE_BY_NAME",
"GeneratedSurface",
]
diff --git a/devtools/incident_coverage_ledger.py b/devtools/incident_coverage_ledger.py
deleted file mode 100644
index 8addf4e848..0000000000
--- a/devtools/incident_coverage_ledger.py
+++ /dev/null
@@ -1,795 +0,0 @@
-"""Resolve the structured incident coverage contract for the 818fy campaign."""
-
-from __future__ import annotations
-
-import argparse
-import hashlib
-import importlib
-import json
-import subprocess
-import sys
-from collections.abc import Mapping
-from dataclasses import dataclass
-from pathlib import Path
-from typing import NoReturn, cast
-
-from jsonschema import Draft202012Validator
-
-from devtools import repo_root
-
-ROOT = repo_root()
-LEDGER_PATH = ROOT / "docs" / "plans" / "reindex-incident-coverage.json"
-SCHEMA_PATH = ROOT / "docs" / "plans" / "reindex-incident-coverage.schema.json"
-CAMPAIGN_GRAPH_PATH = ROOT / "tests" / "fixtures" / "reindex_incident_coverage" / "campaign_graph.json"
-BEADS_PATH = ROOT / ".beads" / "issues.jsonl"
-
-JsonObject = dict[str, object]
-DEPENDENCY_KINDS = frozenset({"blocks", "discovered-from", "parent-child", "relates-to", "supersedes"})
-GRAPH_KINDS = frozenset({"decision", "design", "implementation", "operation", "verification"})
-ROUTE_KINDS = frozenset({"campaign", "canary", "decision", "operation", "registry"})
-
-
-class IncidentCoverageLedgerError(ValueError):
- """Raised when the ledger or its campaign graph is incomplete."""
-
- def __init__(self, message: str, *, diagnostic: JsonObject | None = None) -> None:
- super().__init__(message)
- self.diagnostic = diagnostic or {"error": "incident_coverage_ledger", "message": message}
-
-
-@dataclass(frozen=True, slots=True)
-class CoverageResolution:
- """The useful summary of a successfully resolved coverage ledger."""
-
- target_bead_id: str
- forcing_dependency_ids: tuple[str, ...]
- ledger_row_count: int
- closed_implementation_ids: tuple[str, ...]
- successor_backed_ids: tuple[str, ...]
-
-
-def _fail(code: str, message: str, **fields: object) -> NoReturn:
- raise IncidentCoverageLedgerError(message, diagnostic={"error": code, **fields})
-
-
-def _load_json(path: Path) -> JsonObject:
- try:
- value = json.loads(path.read_text(encoding="utf-8"))
- except (OSError, json.JSONDecodeError) as exc:
- _fail("artifact_load_failed", f"cannot load structured artifact {path}: {exc}", path=str(path))
- if not isinstance(value, dict):
- _fail("artifact_shape_invalid", f"structured artifact {path} must contain an object", path=str(path))
- return cast(JsonObject, value)
-
-
-def load_ledger(
- path: Path = LEDGER_PATH,
- *,
- schema_path: Path = SCHEMA_PATH,
-) -> JsonObject:
- """Load and JSON-Schema-validate the versioned ledger document."""
-
- ledger = _load_json(path)
- schema = _load_json(schema_path)
- validator = Draft202012Validator(schema)
- errors = sorted(validator.iter_errors(ledger), key=lambda error: list(error.path))
- if errors:
- first = errors[0]
- location = ".".join(str(part) for part in first.path) or "$"
- _fail("ledger_schema_invalid", f"ledger schema error at {location}: {first.message}", location=location)
- return ledger
-
-
-def load_campaign_graph(path: Path = CAMPAIGN_GRAPH_PATH) -> JsonObject:
- """Load the committed normalized snapshot of the 818fy forcing graph."""
-
- return _load_json(path)
-
-
-def _parse_beads_jsonl(lines: list[str]) -> dict[str, JsonObject]:
- """Parse only structured Beads records and dependency fields.
-
- Descriptions, notes, close reasons, comments, and PR text are deliberately
- never inspected here. The JSONL is the committed source of dependency
- membership and status.
- """
-
- records: dict[str, JsonObject] = {}
- for line_number, line in enumerate(lines, start=1):
- if not line.strip():
- continue
- try:
- value = json.loads(line)
- except json.JSONDecodeError as exc:
- _fail("beads_json_invalid", f"invalid Beads JSONL at line {line_number}: {exc}", line=line_number)
- if not isinstance(value, dict):
- _fail("beads_record_invalid", f"Beads record at line {line_number} must be an object", line=line_number)
- record = cast(JsonObject, value)
- bead_id = _string(record.get("id"), context=f"Beads record {line_number}.id")
- if bead_id in records:
- _fail("duplicate_bead_id", f"duplicate Bead record {bead_id}", bead_id=bead_id)
- dependencies = record.get("dependencies", [])
- if not isinstance(dependencies, list):
- _fail("bead_dependencies_invalid", f"Bead {bead_id}.dependencies must be a list", bead_id=bead_id)
- for index, raw_dependency in enumerate(dependencies):
- dependency = _object(raw_dependency, context=f"Bead {bead_id}.dependencies[{index}]")
- dependency_kind = _string(dependency.get("type"), context=f"Bead {bead_id}.dependencies[{index}].type")
- if dependency_kind not in DEPENDENCY_KINDS:
- _fail(
- "unknown_dependency_kind",
- f"unknown dependency kind {dependency_kind!r} on {bead_id}",
- bead_id=bead_id,
- dependency_kind=dependency_kind,
- allowed_dependency_kinds=sorted(DEPENDENCY_KINDS),
- )
- records[bead_id] = record
- return records
-
-
-def load_beads_jsonl(path: Path = BEADS_PATH) -> dict[str, JsonObject]:
- """Load a supplied committed Beads export without invoking ``bd``."""
-
- try:
- lines = path.read_text(encoding="utf-8").splitlines()
- except OSError as exc:
- _fail("beads_load_failed", f"cannot load structured Beads JSONL {path}: {exc}", path=str(path))
- return _parse_beads_jsonl(lines)
-
-
-def _object(value: object, *, context: str) -> JsonObject:
- if not isinstance(value, dict):
- _fail("object_required", f"{context} must be an object", context=context)
- return cast(JsonObject, value)
-
-
-def _string(value: object, *, context: str) -> str:
- if not isinstance(value, str) or not value:
- _fail("string_required", f"{context} must be a non-empty string", context=context)
- return value
-
-
-def _load_registered_value(source: str, registry: str, *, context: str) -> object:
- if not source.endswith(".py"):
- _fail("registry_source_invalid", f"{context} source must be a Python module path", source=source)
- module_name = source[:-3].replace("/", ".")
- try:
- module = importlib.import_module(module_name)
- except (ImportError, ModuleNotFoundError) as exc:
- _fail("registry_import_failed", f"cannot import {context} registry {source}: {exc}", source=source)
- value: object = module
- for component in registry.split("."):
- if isinstance(value, Mapping):
- if component not in value:
- _fail(
- "registry_entry_missing",
- f"{context} registry {registry} is absent from {source}",
- source=source,
- registry=registry,
- )
- value = value[component]
- continue
- if not hasattr(value, component):
- _fail(
- "registry_entry_missing",
- f"{context} registry {registry} is absent from {source}",
- source=source,
- registry=registry,
- )
- value = getattr(value, component)
- return value
-
-
-def _strings(value: object, *, context: str) -> tuple[str, ...]:
- if not isinstance(value, list) or not all(isinstance(item, str) and item for item in value):
- _fail("strings_required", f"{context} must be a list of non-empty strings", context=context)
- return tuple(cast(str, item) for item in value)
-
-
-def _catalog(ledger: JsonObject, name: str) -> dict[str, JsonObject]:
- value = ledger.get(name)
- if not isinstance(value, dict):
- _fail("catalog_invalid", f"ledger catalog {name!r} must be an object", catalog=name)
- return {str(key): _object(item, context=f"ledger catalog {name}.{key}") for key, item in value.items()}
-
-
-def _derive_forcing_dependencies(records: dict[str, JsonObject], target: str) -> tuple[JsonObject, ...]:
- target_record = records.get(target)
- if target_record is None:
- _fail("target_bead_missing", f"Beads JSONL has no target bead {target}", target_bead_id=target)
- raw_dependencies = target_record.get("dependencies", [])
- if not isinstance(raw_dependencies, list):
- _fail("bead_dependencies_invalid", f"Bead {target}.dependencies must be a list", bead_id=target)
- dependencies: list[JsonObject] = []
- seen: set[str] = set()
- queued: list[tuple[str, int]] = []
- for index, raw_dependency in enumerate(raw_dependencies):
- dependency = _object(raw_dependency, context=f"Bead {target}.dependencies[{index}]")
- issue_id = _string(dependency.get("issue_id"), context=f"Bead {target}.dependencies[{index}].issue_id")
- if issue_id != target:
- _fail(
- "dependency_owner_mismatch",
- f"dependency record {index} on {target} names issue {issue_id}",
- target_bead_id=target,
- dependency_index=index,
- issue_id=issue_id,
- )
- dependency_kind = _string(dependency.get("type"), context=f"Bead {target}.dependencies[{index}].type")
- if dependency_kind == "blocks":
- queued.append(
- (
- _string(
- dependency.get("depends_on_id"), context=f"Bead {target}.dependencies[{index}].depends_on_id"
- ),
- 1,
- )
- )
- while queued:
- bead_id, depth = queued.pop(0)
- if bead_id in seen:
- continue
- seen.add(bead_id)
- record = records.get(bead_id)
- if record is None:
- _fail("forcing_bead_missing", f"forcing dependency {bead_id} has no Beads record", bead_id=bead_id)
- status = _string(record.get("status"), context=f"Beads record {bead_id}.status")
- children = record.get("dependencies", [])
- if not isinstance(children, list):
- _fail("bead_dependencies_invalid", f"Bead {bead_id}.dependencies must be a list", bead_id=bead_id)
- child_ids: list[str] = []
- for index, raw_child in enumerate(children):
- child = _object(raw_child, context=f"Bead {bead_id}.dependencies[{index}]")
- if _string(child.get("issue_id"), context=f"Bead {bead_id}.dependencies[{index}].issue_id") != bead_id:
- _fail(
- "dependency_owner_mismatch",
- f"dependency record {index} on {bead_id} names another issue",
- bead_id=bead_id,
- dependency_index=index,
- )
- if _string(child.get("type"), context=f"Bead {bead_id}.dependencies[{index}].type") == "blocks":
- child_id = _string(
- child.get("depends_on_id"), context=f"Bead {bead_id}.dependencies[{index}].depends_on_id"
- )
- child_ids.append(child_id)
- queued.append(
- (
- child_id,
- depth + 1,
- )
- )
- dependencies.append(
- {
- "bead_id": bead_id,
- "status": status,
- "dependency_kind": "blocks",
- "depth": depth,
- "child_bead_ids": child_ids,
- "priority": record.get("priority"),
- "issue_type": record.get("issue_type"),
- }
- )
- return tuple(dependencies)
-
-
-def _graph_dependencies(graph: JsonObject, *, bead_records: dict[str, JsonObject]) -> tuple[JsonObject, ...]:
- target = _string(graph.get("target_bead_id"), context="campaign graph target_bead_id")
- if target != "polylogue-818fy":
- _fail("target_mismatch", f"campaign graph target {target!r} is not polylogue-818fy", target_bead_id=target)
- raw_dependencies = graph.get("forcing_dependencies")
- if not isinstance(raw_dependencies, list):
- _fail("graph_dependencies_invalid", "campaign graph forcing_dependencies must be a list")
- known_children = _strings(graph.get("known_child_bead_ids"), context="campaign graph known_child_bead_ids")
- unknown_known_children = sorted(set(known_children) - set(bead_records))
- if unknown_known_children:
- _fail(
- "unknown_successor_id",
- f"campaign graph names unknown child beads {unknown_known_children}",
- unknown_ids=unknown_known_children,
- )
- dependencies: list[JsonObject] = []
- seen: set[str] = set()
- for index, raw_dependency in enumerate(raw_dependencies):
- dependency = _object(raw_dependency, context=f"campaign graph dependency {index}")
- bead_id = _string(dependency.get("bead_id"), context=f"campaign graph dependency {index}.bead_id")
- if bead_id in seen:
- _fail("duplicate_graph_dependency", f"duplicate forcing dependency {bead_id}", duplicate_ids=[bead_id])
- seen.add(bead_id)
- status = _string(dependency.get("status"), context=f"campaign graph dependency {bead_id}.status")
- graph_kind = _string(dependency.get("kind"), context=f"campaign graph dependency {bead_id}.kind")
- if graph_kind not in GRAPH_KINDS:
- _fail(
- "unknown_graph_kind",
- f"unknown campaign graph kind {graph_kind!r} for {bead_id}",
- bead_id=bead_id,
- dependency_kind=graph_kind,
- allowed_dependency_kinds=sorted(GRAPH_KINDS),
- )
- dependency_kind = _string(
- dependency.get("dependency_kind"),
- context=f"campaign graph dependency {bead_id}.dependency_kind",
- )
- if dependency_kind not in DEPENDENCY_KINDS:
- _fail(
- "unknown_dependency_kind",
- f"unknown dependency kind {dependency_kind!r} for {bead_id}",
- bead_id=bead_id,
- dependency_kind=dependency_kind,
- allowed_dependency_kinds=sorted(DEPENDENCY_KINDS),
- )
- child_ids = _strings(
- dependency.get("child_bead_ids"),
- context=f"campaign graph dependency {bead_id}.child_bead_ids",
- )
- unknown_children = sorted(set(child_ids) - set(bead_records))
- if unknown_children:
- _fail(
- "unknown_successor_id",
- f"campaign graph dependency {bead_id} names unknown child beads {unknown_children}",
- bead_id=bead_id,
- unknown_ids=unknown_children,
- )
- dependencies.append(
- {
- **dependency,
- "status": status,
- "dependency_kind": dependency_kind,
- }
- )
- return tuple(dependencies)
-
-
-def _set_diagnostic(
- *,
- expected_ids: tuple[str, ...],
- actual_ids: tuple[str, ...],
- stale_ids: list[str] | None = None,
- duplicate_ids: list[str] | None = None,
-) -> JsonObject:
- expected = set(expected_ids)
- actual = set(actual_ids)
- return {
- "missing_ids": sorted(expected - actual),
- "extra_ids": sorted(actual - expected),
- "stale_ids": sorted(stale_ids or []),
- "duplicate_ids": sorted(duplicate_ids or []),
- "expected_count": len(expected_ids),
- "actual_count": len(actual_ids),
- }
-
-
-def _assert_same_forcing_graph(derived: tuple[JsonObject, ...], fixture: tuple[JsonObject, ...]) -> None:
- expected_ids = tuple(_string(item.get("bead_id"), context="derived forcing dependency bead_id") for item in derived)
- fixture_ids = tuple(_string(item.get("bead_id"), context="campaign graph dependency bead_id") for item in fixture)
- duplicate_ids = sorted({bead_id for bead_id in fixture_ids if fixture_ids.count(bead_id) > 1})
- expected_by_id = {str(item["bead_id"]): item for item in derived}
- fixture_by_id = {str(item["bead_id"]): item for item in fixture}
- stale_ids = sorted(
- bead_id
- for bead_id in set(expected_by_id) & set(fixture_by_id)
- if expected_by_id[bead_id].get("status") != fixture_by_id[bead_id].get("status")
- or fixture_by_id[bead_id].get("dependency_kind", "blocks") != "blocks"
- or expected_by_id[bead_id].get("child_bead_ids", []) != fixture_by_id[bead_id].get("child_bead_ids", [])
- )
- diagnostic = _set_diagnostic(
- expected_ids=expected_ids,
- actual_ids=fixture_ids,
- stale_ids=stale_ids,
- duplicate_ids=duplicate_ids,
- )
- if any(diagnostic[key] for key in ("missing_ids", "extra_ids", "stale_ids", "duplicate_ids")):
- _fail(
- "campaign_graph_mismatch",
- "campaign graph does not match current Beads forcing dependencies",
- **diagnostic,
- )
-
-
-def _committed_paths() -> set[str]:
- try:
- completed = subprocess.run(
- ["git", "ls-files", "-z"],
- cwd=ROOT,
- check=True,
- capture_output=True,
- timeout=10,
- )
- except (OSError, subprocess.SubprocessError) as exc:
- _fail("git_files_unavailable", f"cannot inspect committed source files: {exc}")
- return {raw.decode("utf-8") for raw in completed.stdout.split(b"\0") if raw}
-
-
-def _validate_graph_provenance(graph: JsonObject, *, beads_path: Path) -> None:
- source_path = _string(graph.get("source_path"), context="campaign graph source_path")
- if source_path != ".beads/issues.jsonl":
- _fail("graph_source_path_invalid", f"campaign graph source path must be .beads/issues.jsonl, got {source_path}")
- snapshot_digest = graph.get("source_snapshot_sha256")
- if isinstance(snapshot_digest, str) and snapshot_digest:
- actual_digest = hashlib.sha256(beads_path.read_bytes()).hexdigest()
- if actual_digest != snapshot_digest:
- _fail(
- "graph_source_snapshot_mismatch",
- "campaign graph source snapshot digest does not match current Beads export",
- source_path=source_path,
- expected_digest=snapshot_digest,
- actual_digest=actual_digest,
- )
- return
- source_commit = _string(graph.get("source_commit"), context="campaign graph source_commit")
- try:
- subprocess.run(
- ["git", "cat-file", "-e", f"{source_commit}^{{commit}}"],
- cwd=ROOT,
- check=True,
- capture_output=True,
- timeout=10,
- )
- source_bytes = subprocess.run(
- ["git", "show", f"{source_commit}:{source_path}"], cwd=ROOT, check=True, capture_output=True, timeout=10
- ).stdout
- except (OSError, subprocess.SubprocessError) as exc:
- _fail(
- "graph_source_commit_missing",
- f"campaign graph source commit cannot be read: {exc}",
- source_commit=source_commit,
- )
- actual_bytes = beads_path.read_bytes()
- if hashlib.sha256(source_bytes).hexdigest() != hashlib.sha256(actual_bytes).hexdigest():
- _fail(
- "graph_source_snapshot_mismatch",
- "campaign graph source commit does not contain the current Beads snapshot",
- source_commit=source_commit,
- source_path=source_path,
- )
-
-
-def _validate_sources(
- catalogs: dict[str, dict[str, JsonObject]],
- *,
- bead_records: dict[str, JsonObject],
-) -> None:
- committed = _committed_paths()
- for catalog_name, catalog in catalogs.items():
- for item_id, entry in catalog.items():
- source = _string(entry.get("source"), context=f"ledger catalog {catalog_name}.{item_id}.source")
- if source in committed:
- continue
- if source in bead_records:
- continue
- _fail(
- "unresolved_source_reference",
- f"{catalog_name}.{item_id} source {source!r} is not a committed file or current Bead",
- catalog=catalog_name,
- item_id=item_id,
- source=source,
- )
-
-
-def resolve_incident_coverage(
- ledger: JsonObject,
- graph: JsonObject,
- *,
- beads_path: Path | None = None,
-) -> CoverageResolution:
- """Resolve row completeness and all structured references for one campaign graph."""
-
- target = _string(ledger.get("target_bead_id"), context="ledger target_bead_id")
- if target != "polylogue-818fy":
- _fail("target_mismatch", f"ledger target {target!r} is not polylogue-818fy", target_bead_id=target)
- if target != _string(graph.get("target_bead_id"), context="campaign graph target_bead_id"):
- _fail("target_mismatch", "ledger and campaign graph target beads differ")
-
- declared_dependency_kinds = _strings(ledger.get("dependency_kinds"), context="ledger dependency_kinds")
- if set(declared_dependency_kinds) != DEPENDENCY_KINDS:
- _fail(
- "dependency_kind_vocabulary_mismatch",
- "ledger dependency kind vocabulary must equal the closed validator vocabulary",
- declared_dependency_kinds=sorted(declared_dependency_kinds),
- allowed_dependency_kinds=sorted(DEPENDENCY_KINDS),
- )
-
- bead_records = load_beads_jsonl(beads_path or BEADS_PATH)
- if beads_path is None or beads_path == BEADS_PATH:
- _validate_graph_provenance(graph, beads_path=beads_path or BEADS_PATH)
- derived_dependencies = _derive_forcing_dependencies(bead_records, target)
- graph_dependencies = _graph_dependencies(graph, bead_records=bead_records)
- _assert_same_forcing_graph(derived_dependencies, graph_dependencies)
-
- catalogs = {
- name: _catalog(ledger, name) for name in ("fixtures", "checks", "snapshots", "receipts", "successors", "routes")
- }
- known_successors = set(_strings(graph.get("known_child_bead_ids"), context="campaign graph known_child_bead_ids"))
- missing_successors = sorted(known_successors - set(catalogs["successors"]))
- if missing_successors:
- _fail("unknown_successor", f"unknown successors {missing_successors}", unknown_ids=missing_successors)
- receipts = catalogs["receipts"]
- for receipt_id, receipt in receipts.items():
- owner = _string(receipt.get("owner_bead_id"), context=f"ledger receipt {receipt_id}.owner_bead_id")
- if owner not in bead_records:
- _fail("receipt_owner_missing", f"receipt {receipt_id} names unknown owner {owner}", receipt_id=receipt_id)
- registry_source = _string(
- receipt.get("registry_source"), context=f"ledger receipt {receipt_id}.registry_source"
- )
- registry_name = _string(receipt.get("registry"), context=f"ledger receipt {receipt_id}.registry")
- producer_registry = _object(
- _load_registered_value(registry_source, registry_name, context=f"ledger receipt {receipt_id}"),
- context=f"ledger receipt {receipt_id}.registry",
- )
- if producer_registry.get(receipt_id) != owner:
- _fail(
- "receipt_registry_mismatch",
- f"receipt {receipt_id} is not bound to owner {owner}",
- receipt_id=receipt_id,
- owner_bead_id=owner,
- )
- source = _string(receipt.get("registry_source"), context=f"ledger receipt {receipt_id}.registry_source")
- registry = _string(receipt.get("registry"), context=f"ledger receipt {receipt_id}.registry")
- registered = _object(
- _load_registered_value(source, registry, context=f"ledger receipt {receipt_id}"),
- context=f"ledger receipt {receipt_id}.registry",
- )
- if registered.get(receipt_id) != owner:
- _fail(
- "receipt_registry_mismatch",
- f"receipt {receipt_id} is not bound to owner {owner}",
- receipt_id=receipt_id,
- owner_bead_id=owner,
- )
- _validate_sources(catalogs, bead_records=bead_records)
-
- raw_rows = ledger.get("rows")
- if not isinstance(raw_rows, list):
- _fail("rows_invalid", "ledger rows must be a list")
- rows = tuple(_object(row, context=f"ledger row {index}") for index, row in enumerate(raw_rows))
- row_ids = tuple(_string(row.get("bead_id"), context="ledger row bead_id") for row in rows)
- duplicate_ids = sorted({bead_id for bead_id in row_ids if row_ids.count(bead_id) > 1})
- dependency_ids = tuple(
- _string(dep.get("bead_id"), context="forcing dependency bead_id") for dep in derived_dependencies
- )
- diagnostic = _set_diagnostic(
- expected_ids=dependency_ids,
- actual_ids=row_ids,
- duplicate_ids=duplicate_ids,
- )
- if duplicate_ids:
- _fail(
- "duplicate_ledger_row",
- f"ledger has duplicate rows for {duplicate_ids}",
- **diagnostic,
- )
- if any(diagnostic[key] for key in ("missing_ids", "extra_ids", "duplicate_ids")) or len(rows) != len(
- derived_dependencies
- ):
- _fail(
- "forcing_set_mismatch",
- f"ledger rows do not match forcing dependencies: missing={diagnostic['missing_ids']}, "
- f"extra={diagnostic['extra_ids']}, expected={len(derived_dependencies)}, actual={len(rows)}",
- **diagnostic,
- )
-
- graph_by_id = {str(dep["bead_id"]): dep for dep in graph_dependencies}
- derived_by_id = {str(dep["bead_id"]): dep for dep in derived_dependencies}
- closed_implementation_ids: list[str] = []
- successor_backed_ids: list[str] = []
- orders: list[int] = []
- for row in rows:
- bead_id = _string(row.get("bead_id"), context="ledger row bead_id")
- graph_entry = graph_by_id[bead_id]
- derived_entry = derived_by_id[bead_id]
- if row.get("bead_status") != derived_entry.get("status") or row.get("bead_status") != graph_entry.get("status"):
- _fail("stale_row", f"ledger status disagrees with current Beads for {bead_id}", stale_ids=[bead_id])
- if row.get("dependency_kind", "blocks") != derived_entry.get("dependency_kind"):
- _fail("stale_row", f"ledger dependency kind disagrees for {bead_id}", stale_ids=[bead_id])
-
- incident = _object(row.get("incident"), context=f"ledger row {bead_id}.incident")
- if _string(incident.get("bead_id"), context=f"ledger row {bead_id}.incident.bead_id") != bead_id:
- _fail("row_reference_mismatch", f"incident bead reference disagrees for {bead_id}")
-
- route = _object(row.get("route"), context=f"ledger row {bead_id}.route")
- route_kind = _string(route.get("kind"), context=f"ledger row {bead_id}.route.kind")
- if route_kind not in ROUTE_KINDS:
- _fail("unknown_route_kind", f"unknown route kind {route_kind!r} for {bead_id}", bead_id=bead_id)
- entrypoint = _string(route.get("entrypoint"), context=f"ledger row {bead_id}.route.entrypoint")
- if entrypoint not in catalogs["routes"]:
- _fail(
- "unknown_route_entrypoint",
- f"route entrypoint {entrypoint} is not registered for {bead_id}",
- bead_id=bead_id,
- entrypoint=entrypoint,
- )
- route_catalog = catalogs["routes"][entrypoint]
- route_source = _string(route_catalog.get("source"), context=f"ledger route {entrypoint}.source")
- route_registry = _string(route_catalog.get("registry"), context=f"ledger route {entrypoint}.registry")
- registered_routes = _object(
- _load_registered_value(route_source, route_registry, context=f"ledger route {entrypoint}"),
- context=f"ledger route {entrypoint}.registry",
- )
- if entrypoint not in registered_routes:
- _fail(
- "route_registry_mismatch",
- f"route {entrypoint} is absent from its executable registry",
- bead_id=bead_id,
- entrypoint=entrypoint,
- )
-
- schedule = _object(row.get("schedule"), context=f"ledger row {bead_id}.schedule")
- order = schedule.get("order")
- if not isinstance(order, int) or isinstance(order, bool) or order < 1:
- _fail("schedule_invalid", f"schedule order is invalid for {bead_id}")
- orders.append(order)
-
- expected_snapshot = _object(row.get("expected_snapshot"), context=f"ledger row {bead_id}.expected_snapshot")
- snapshot_id = _string(
- expected_snapshot.get("snapshot_id"), context=f"ledger row {bead_id}.expected_snapshot.snapshot_id"
- )
- if snapshot_id not in catalogs["snapshots"]:
- _fail("unknown_snapshot", f"unknown snapshot {snapshot_id} for {bead_id}")
-
- red_mutation = _object(row.get("red_mutation"), context=f"ledger row {bead_id}.red_mutation")
- fixture_id = _string(red_mutation.get("fixture_id"), context=f"ledger row {bead_id}.red_mutation.fixture_id")
- if fixture_id not in catalogs["fixtures"]:
- _fail("unknown_fixture", f"unknown fixture {fixture_id} for {bead_id}")
- mutation_id = _string(red_mutation.get("mutation_id"), context=f"ledger row {bead_id}.red_mutation.mutation_id")
- mutation_ids = _strings(
- catalogs["fixtures"][fixture_id].get("mutation_ids"), context=f"ledger fixture {fixture_id}.mutation_ids"
- )
- if mutation_id not in mutation_ids:
- _fail(
- "unknown_mutation",
- f"mutation {mutation_id} is not declared by fixture {fixture_id}",
- bead_id=bead_id,
- fixture_id=fixture_id,
- mutation_id=mutation_id,
- )
- fixture_catalog = catalogs["fixtures"][fixture_id]
- mutation_source = _string(
- fixture_catalog.get("mutation_source"), context=f"ledger fixture {fixture_id}.mutation_source"
- )
- mutation_registry = _string(
- fixture_catalog.get("mutation_registry"), context=f"ledger fixture {fixture_id}.mutation_registry"
- )
- registered_mutations = _object(
- _load_registered_value(mutation_source, mutation_registry, context=f"ledger fixture {fixture_id}"),
- context=f"ledger fixture {fixture_id}.mutation_registry",
- )
- if mutation_id not in registered_mutations:
- _fail(
- "mutation_registry_mismatch",
- f"mutation {mutation_id} is absent from its fixture registry",
- bead_id=bead_id,
- fixture_id=fixture_id,
- mutation_id=mutation_id,
- )
- fixture_source = _string(fixture_catalog.get("source"), context=f"ledger fixture {fixture_id}.source")
- if fixture_source.endswith(".json"):
- fixture_payload = _load_json(ROOT / fixture_source)
- source_mutations = _strings(
- fixture_payload.get("mutation_ids"), context=f"fixture source {fixture_source}.mutation_ids"
- )
- if mutation_id not in source_mutations:
- _fail(
- "fixture_mutation_missing",
- f"mutation {mutation_id} is absent from fixture source {fixture_source}",
- bead_id=bead_id,
- fixture_id=fixture_id,
- mutation_id=mutation_id,
- )
-
- check_ids = _strings(row.get("registry_checks"), context=f"ledger row {bead_id}.registry_checks")
- unknown_checks = sorted(set(check_ids) - set(catalogs["checks"]))
- if unknown_checks:
- _fail("unknown_checks", f"unknown checks {unknown_checks} for {bead_id}", unknown_ids=unknown_checks)
-
- receipt_ids = _strings(row.get("receipts"), context=f"ledger row {bead_id}.receipts")
- unknown_receipts = sorted(set(receipt_ids) - set(receipts))
- if unknown_receipts:
- _fail(
- "unknown_receipts", f"unknown receipts {unknown_receipts} for {bead_id}", unknown_ids=unknown_receipts
- )
- for receipt_id in receipt_ids:
- owner = _string(
- receipts[receipt_id].get("owner_bead_id"), context=f"ledger receipt {receipt_id}.owner_bead_id"
- )
- if owner != bead_id:
- _fail(
- "receipt_owner_mismatch",
- f"receipt {receipt_id} is owned by {owner}, not {bead_id}",
- receipt_id=receipt_id,
- expected_owner=bead_id,
- actual_owner=owner,
- )
-
- successor = row.get("residual_successor")
- successor_id: str | None = None
- if successor is not None:
- successor_object = _object(successor, context=f"ledger row {bead_id}.residual_successor")
- successor_id = _string(
- successor_object.get("bead_id"), context=f"ledger row {bead_id}.residual_successor.bead_id"
- )
- if successor_id not in catalogs["successors"]:
- _fail("unknown_successor", f"unknown successor {successor_id} for {bead_id}")
- child_ids = _strings(
- graph_entry.get("child_bead_ids"), context=f"campaign graph dependency {bead_id}.child_bead_ids"
- )
- if successor_id not in child_ids:
- _fail("successor_parent_mismatch", f"successor {successor_id} is not a named child of {bead_id}")
- successor_backed_ids.append(bead_id)
-
- if graph_entry.get("status") == "closed" and graph_entry.get("kind") == "implementation":
- closed_implementation_ids.append(bead_id)
- implementation_proof = any(
- receipts[receipt_id].get("kind") in {"live-proof", "implementation-proof"} for receipt_id in receipt_ids
- )
- if not implementation_proof and successor_id is None:
- _fail(
- "closed_implementation_unproven",
- f"closed implementation bead {bead_id} has no live proof or named child successor",
- )
-
- if len(set(orders)) != len(orders) or set(orders) != set(range(1, len(rows) + 1)):
- _fail("schedule_invalid", "ledger schedule orders must be a permutation of 1..row_count")
-
- return CoverageResolution(
- target_bead_id=target,
- forcing_dependency_ids=dependency_ids,
- ledger_row_count=len(rows),
- closed_implementation_ids=tuple(closed_implementation_ids),
- successor_backed_ids=tuple(successor_backed_ids),
- )
-
-
-def resolve_default_incident_coverage(*, beads_path: Path = BEADS_PATH) -> CoverageResolution:
- """Load and resolve the ledger against the supplied current Beads export."""
-
- return resolve_incident_coverage(load_ledger(), load_campaign_graph(), beads_path=beads_path)
-
-
-def main(argv: list[str] | None = None) -> int:
- """Run the unconditional static verification entrypoint."""
-
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--beads-export", type=Path, default=BEADS_PATH)
- args = parser.parse_args(argv)
-
- try:
- result = resolve_default_incident_coverage(beads_path=args.beads_export)
- except IncidentCoverageLedgerError as exc:
- print(json.dumps(exc.diagnostic, sort_keys=True))
- return 1
- print(
- json.dumps(
- {
- "status": "ok",
- "target_bead_id": result.target_bead_id,
- "forcing_dependency_count": len(result.forcing_dependency_ids),
- "ledger_row_count": result.ledger_row_count,
- },
- sort_keys=True,
- )
- )
- return 0
-
-
-ROUTE_REGISTRY: dict[str, object] = {
- "reindex-campaign": resolve_default_incident_coverage,
- "reindex-final-proof": main,
-}
-
-
-__all__ = [
- "BEADS_PATH",
- "CAMPAIGN_GRAPH_PATH",
- "CoverageResolution",
- "DEPENDENCY_KINDS",
- "IncidentCoverageLedgerError",
- "LEDGER_PATH",
- "ROUTE_KINDS",
- "SCHEMA_PATH",
- "load_beads_jsonl",
- "load_campaign_graph",
- "load_ledger",
- "resolve_default_incident_coverage",
- "resolve_incident_coverage",
-]
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/inject_semantic_annotations.py b/devtools/inject_semantic_annotations.py
deleted file mode 100644
index adf7504ac0..0000000000
--- a/devtools/inject_semantic_annotations.py
+++ /dev/null
@@ -1,299 +0,0 @@
-"""Inject x-polylogue-semantic-role annotations into baseline provider schemas.
-
-One-shot script. Run once to annotate, commit the updated schemas, then
-this script can remain as a re-annotation utility.
-
-Usage: devtools inject-semantic-annotations [--dry-run]
-"""
-
-from __future__ import annotations
-
-import gzip
-import json
-import sys
-
-from devtools import repo_root as _get_root
-from polylogue.core.json import JSONDocument, is_json_document, json_document
-from polylogue.schemas.registry import SchemaRegistry
-
-SCHEMAS_DIR = _get_root() / "polylogue" / "schemas" / "providers"
-
-# ---------------------------------------------------------------------------
-# Annotation map: provider → list of (json_path_segments, semantic_role)
-#
-# Paths use a mini-DSL:
-# "properties.X" → schema["properties"]["X"]
-# "items" → schema["items"]
-# "additionalProperties" → schema["additionalProperties"]
-# "anyOf:props" → find the anyOf variant that has "properties"
-# "anyOf:array" → find the anyOf variant with type="array"
-# ---------------------------------------------------------------------------
-
-ANNOTATION_MAP: dict[str, list[tuple[list[str], str]]] = {
- "chatgpt": [
- (["properties.title"], "session_title"),
- (["properties.create_time"], "message_timestamp"),
- (["properties.mapping"], "message_container"),
- # mapping.*.message(anyOf→props).author.role → message_role
- (
- [
- "properties.mapping",
- "additionalProperties",
- "properties.message",
- "anyOf:props",
- "properties.author",
- "properties.role",
- ],
- "message_role",
- ),
- # mapping.*.message(anyOf→props).content.parts → message_body (on items)
- (
- [
- "properties.mapping",
- "additionalProperties",
- "properties.message",
- "anyOf:props",
- "properties.content",
- "properties.parts",
- "items",
- ],
- "message_body",
- ),
- ],
- "claude-ai": [
- (["properties.name"], "session_title"),
- (["properties.created_at"], "message_timestamp"),
- (["properties.chat_messages"], "message_container"),
- (["properties.chat_messages", "items", "properties.sender"], "message_role"),
- (["properties.chat_messages", "items", "properties.text"], "message_body"),
- ],
- "claude-code": [
- (["properties.type"], "message_role"),
- (
- # ``message.role`` mirrors the top-level ``type`` discriminator
- # in real Claude Code records but was never itself annotated, so
- # generation filled it with an opaque placeholder even before
- # the c53ad94e0 promotion -- this is a distinct gap from the
- # promotion's own annotation loss, not a duplicate of it
- # (polylogue-c66i: without this entry,
- # ``tests/infra/strategies/providers.py:repair_role_discriminators``'s
- # ``message.role`` branch stays load-bearing after the
- # promotion-loss annotations are restored).
- ["properties.message", "properties.role"],
- "message_role",
- ),
- (
- # The role discriminator lives on the top-level record
- # (``type``), not inside ``message`` -- but ``message`` is still
- # the object that wraps the message's own identity/content, the
- # same structural role ``payload`` plays for codex. Without this
- # entry ``test_schema_has_expected_semantic_roles[claude-code]``
- # is missing ``message_container`` from its expected 5-role set
- # (polylogue-c66i: the injector's ANNOTATION_MAP simply never
- # had this entry, not a path-resolution gap against the promoted
- # schema).
- ["properties.message"],
- "message_container",
- ),
- (
- # The 2026-07-29 structural-merge promotion (c53ad94e0) flattened
- # this field's shape from an anyOf union of type variants to a
- # plain `"type": ["array", "string"]` with `items` present
- # directly -- there is no `anyOf` to select a variant from
- # anymore (polylogue-c66i).
- [
- "properties.message",
- "properties.content",
- "items",
- "properties.text",
- ],
- "message_body",
- ),
- (["properties.timestamp"], "message_timestamp"),
- (["properties.gitBranch"], "session_title"),
- ],
- "codex": [
- (["properties.timestamp"], "message_timestamp"),
- (["properties.payload"], "message_container"),
- (["properties.payload", "properties.role"], "message_role"),
- (
- # The 2026-07-29 structural-merge promotion (c53ad94e0) unioned
- # in a second, legitimate codex record shape: a flat
- # ``{"type": "message", "role": ..., ...}`` record with no
- # ``payload`` wrapper (the real parser accepts this too --
- # ``sources/parsers/codex.py`` treats ``record_type == "message"
- # or isinstance(role, str)`` as a message record). Without this
- # entry, generation that happens to produce the flat shape (no
- # ``payload`` filled) leaves this record's role as an
- # unannotated placeholder (polylogue-c66i).
- ["properties.role"],
- "message_role",
- ),
- (
- # Same post-promotion shape flattening as claude-code above:
- # `summary` is now `"type": ["array", "string"]` with `items`
- # present directly, no `anyOf` variant to select (polylogue-c66i).
- [
- "properties.payload",
- "properties.summary",
- "items",
- "properties.text",
- ],
- "message_body",
- ),
- (["properties.payload", "properties.name"], "session_title"),
- ],
- "gemini": [
- (
- [
- "properties.chunkedPrompt",
- "properties.chunks",
- ],
- "message_container",
- ),
- (
- [
- "properties.chunkedPrompt",
- "properties.chunks",
- "items",
- "properties.role",
- ],
- "message_role",
- ),
- (
- [
- "properties.chunkedPrompt",
- "properties.chunks",
- "items",
- "properties.text",
- ],
- "message_body",
- ),
- (
- [
- "properties.chunkedPrompt",
- "properties.chunks",
- "items",
- "properties.createTime",
- ],
- "message_timestamp",
- ),
- (["properties.runSettings", "properties.thinkingLevel"], "session_title"),
- ],
-}
-
-
-def _navigate(schema: JSONDocument, path_segments: list[str]) -> JSONDocument | None:
- """Navigate a schema using path segments, returning the target node."""
- node: object = schema
- for segment in path_segments:
- if not is_json_document(node):
- return None
-
- mapping = node
-
- if segment.startswith("properties."):
- key = segment[len("properties.") :]
- properties = mapping.get("properties")
- if not is_json_document(properties):
- return None
- node = properties.get(key)
- elif segment == "items":
- node = mapping.get("items")
- elif segment == "additionalProperties":
- node = mapping.get("additionalProperties")
- elif segment == "anyOf:props":
- # Find the anyOf variant that has "properties"
- variants = mapping.get("anyOf", [])
- found = None
- if not isinstance(variants, list):
- return None
- for variant in variants:
- if is_json_document(variant) and "properties" in variant:
- found = variant
- break
- node = found
- elif segment == "anyOf:array":
- # Find the anyOf variant with type="array"
- variants = mapping.get("anyOf", [])
- found = None
- if not isinstance(variants, list):
- return None
- for variant in variants:
- if is_json_document(variant) and variant.get("type") == "array":
- found = variant
- break
- node = found
- else:
- node = mapping.get(segment)
-
- if node is None:
- return None
-
- return node if is_json_document(node) else None
-
-
-def inject_annotations(provider: str, schema: JSONDocument, *, dry_run: bool = False) -> int:
- """Inject semantic role annotations into a schema. Returns count of annotations added."""
- annotations = ANNOTATION_MAP.get(provider, [])
- count = 0
-
- for path_segments, role in annotations:
- target = _navigate(schema, path_segments)
- if target is None:
- print(f" WARNING: path not found for {provider}: {' → '.join(path_segments)}")
- continue
-
- if target.get("x-polylogue-semantic-role") == role:
- print(f" SKIP (already set): {provider}.{' → '.join(path_segments)} = {role}")
- continue
-
- if not dry_run:
- target["x-polylogue-semantic-role"] = role
- print(f" {'DRY-RUN: ' if dry_run else ''}SET: {provider}.{' → '.join(path_segments)} = {role}")
- count += 1
-
- return count
-
-
-def main(argv: list[str] | None = None) -> int:
- import argparse
-
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--dry-run", action="store_true", help="Show what would be changed without modifying files")
- args = parser.parse_args(argv)
-
- registry = SchemaRegistry(storage_root=SCHEMAS_DIR)
- total = 0
- for provider in ANNOTATION_MAP:
- package = registry.get_package(provider, version="default")
- if package is None:
- print(f"SKIP: no bundled schema package found for {provider}")
- continue
- element = package.element(package.default_element_kind)
- if element is None or element.schema_file is None:
- print(f"SKIP: no default element schema found for {provider}")
- continue
- schema_path = SCHEMAS_DIR / provider / "versions" / package.version / "elements" / element.schema_file
- if not schema_path.exists():
- print(f"SKIP: {schema_path} not found")
- continue
-
- print(f"\n--- {provider} ---")
- with gzip.open(schema_path, "rt") as f:
- schema = json_document(json.load(f))
-
- count = inject_annotations(provider, schema, dry_run=args.dry_run)
- total += count
-
- if count > 0 and not args.dry_run:
- with gzip.open(schema_path, "wt") as f:
- json.dump(schema, f, indent=2, ensure_ascii=False)
- print(f" Written {count} annotations to {schema_path.name}")
-
- print(f"\nTotal annotations {'would be ' if args.dry_run else ''}injected: {total}")
- return 0
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/lab_scenario.py b/devtools/lab_scenario.py
index 1c5e711a58..2c127f06ff 100644
--- a/devtools/lab_scenario.py
+++ b/devtools/lab_scenario.py
@@ -4,6 +4,8 @@
import argparse
import json
+import os
+import shutil
import subprocess
import sys
import time
@@ -26,10 +28,6 @@
run_storage_correctness,
storage_correctness_scenario_entry,
)
-from devtools.visual_artifacts import (
- READER_VISUAL_SMOKE_PYTEST_COMMAND,
- reader_visual_artifact_payloads,
-)
from polylogue.core.outcomes import OutcomeStatus
from polylogue.scenarios import AssertionSpec, ExecutionSpec, polylogue_execution
@@ -40,6 +38,7 @@
REBUILD_SAFETY_SCENARIO_NAME,
)
_ARCHIVE_SMOKE_TIER = 0
+_READER_VISUAL_SMOKE_PYTEST_ARGS: tuple[str, ...] = ("-m", "pytest", "-q", "tests/visual")
class _ScenarioResult(Protocol):
@@ -251,8 +250,7 @@ def list_scenarios(*, as_json: bool) -> int:
{
"name": "reader-visual-smoke",
"kind": "reader-visual",
- "command": " ".join((sys.executable, *READER_VISUAL_SMOKE_PYTEST_COMMAND[1:])),
- "artifact_count": len(reader_visual_artifact_payloads()),
+ "command": " ".join((sys.executable, *_READER_VISUAL_SMOKE_PYTEST_ARGS)),
},
storage_correctness_scenario_entry(),
{
@@ -282,14 +280,27 @@ def list_scenarios(*, as_json: bool) -> int:
def run_reader_visual_smoke(*, report_dir: Path | None, as_json: bool) -> int:
"""Run the daemon reader visual/DOM smoke lane."""
- command = [sys.executable, *READER_VISUAL_SMOKE_PYTEST_COMMAND[1:]]
+ command = [sys.executable, *_READER_VISUAL_SMOKE_PYTEST_ARGS]
+ artifact_dir = report_dir / "reader-visual-artifacts" if report_dir is not None else None
+ env = os.environ.copy()
+ if artifact_dir is not None:
+ if artifact_dir.exists():
+ shutil.rmtree(artifact_dir)
+ artifact_dir.mkdir(parents=True)
+ env["POLYLOGUE_VISUAL_EVIDENCE_DIR"] = str(artifact_dir)
result = subprocess.run(
command,
cwd=_get_root(),
+ env=env,
text=True,
capture_output=True,
check=False,
)
+ artifact_inventory = (
+ [json.loads(path.read_text(encoding="utf-8")) for path in sorted(artifact_dir.glob("*.json"))]
+ if artifact_dir is not None
+ else []
+ )
artifact_report = report_dir / "reader-visual-smoke.json" if report_dir is not None else None
payload: dict[str, object] = {
"scenario": "reader-visual-smoke",
@@ -297,7 +308,7 @@ def run_reader_visual_smoke(*, report_dir: Path | None, as_json: bool) -> int:
"exit_code": result.returncode,
"stdout": result.stdout,
"stderr": result.stderr,
- "artifact_inventory": reader_visual_artifact_payloads(),
+ "artifact_inventory": artifact_inventory,
"artifact_report": str(artifact_report) if artifact_report is not None else None,
}
if report_dir is not None and artifact_report is not None:
diff --git a/devtools/lane_brief.py b/devtools/lane_brief.py
deleted file mode 100644
index f1f3d4ec0a..0000000000
--- a/devtools/lane_brief.py
+++ /dev/null
@@ -1,600 +0,0 @@
-"""lane-brief: generate a dispatch brief for a bead lane with live evidence.
-
-Bead prose alone produces bad lanes -- descriptions/design fields drift from
-the current tree (files get renamed or deleted, migrations land, generated
-surfaces regenerate) and a dispatcher copying bead text into a subagent
-prompt has no way to tell current fact from stale claim without a manual
-`bd show` + `git log` + `find` round-trip per bead.
-
-This command does that round-trip once, for a whole lane (a batch of bead
-ids meant to land on one branch), and emits a markdown brief:
-
- 1. Full bead records (id/priority/type/title/description/design/AC/
- notes tail/dependencies) via `bd show --json`.
- 2. Footprint extraction (reusing devtools.bead_cluster's regex/helpers)
- over the combined bead text, then LIVE verification of each extracted
- path: does it exist right now, how many lines, what are its last 3
- commits. A path that no longer exists is flagged loudly -- it means
- the bead prose is stale and must not be trusted uncritically.
- 3. Prior art: closed beads (from a fresh `bd export`) whose text mentions
- any of the same file paths, so the dispatcher can see what was already
- tried/decided here.
-
-Sections the tool cannot fill (measured baseline, non-goals) are emitted as
-explicit `` placeholders rather than silently
-omitted -- a missing section is a worse failure mode than a visible gap,
-because a silently-dropped section reads as "not needed" instead of
-"not yet filled in".
-
-Usage:
- devtools workspace lane-brief polylogue-abc polylogue-def
- devtools workspace lane-brief polylogue-abc --out .agent/scratch/lane-abc.md
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import subprocess
-import sys
-from collections.abc import Sequence
-from dataclasses import dataclass, field
-from pathlib import Path
-from typing import Any
-
-import devtools.beads_acceptance_contracts as acceptance_contracts
-from polylogue.core.json import JSONDecodeError
-from polylogue.core.json import loads as strict_json_loads
-
-try:
- from devtools.bead_cluster import _FILE_PAT as _LANE_FILE_PAT
-except ImportError: # pragma: no cover -- defensive: keep working if bead_cluster moves/breaks
- import re
-
- _LANE_FILE_PAT = re.compile(
- r"(?:polylogue|tests|\.agent|docs|storage|pipeline|daemon|cli|mcp"
- r"|browser[_-]extension|browser_capture|coordination|archive|insights"
- r"|context|core|hooks|maintenance|artifacts)"
- r"/[\w./\-]+\.(?:py|ts|js|yaml|yml|md|json|sql|html)",
- re.IGNORECASE,
- )
-
-BeadDict = dict[str, Any]
-
-_ANTI_VACUITY_CONTRACT = (
- "Name the production caller that exercises every new surface this lane adds. "
- "A test-local reimplementation, self-authorized registry, or write-only table is "
- "a FAILED lane even if green. State the implementation mutation that would make "
- "your test fail."
-)
-_MISSING_CONTRACT_ERROR = "missing metadata.acceptance_contract_v1"
-
-_HAZARDS = (
- "commit every logical chunk (worktree auto-clean destroys uncommitted work)",
- "never cd to the main checkout",
- "run EVERY command synchronously in your own foreground turn -- never launch a "
- "background job and idle-wait on it across turns (2026-08-01: three lanes stalled for "
- "multiple turns each waiting on backgrounded devtools test runs)",
- "`bd` reimports .beads/issues.jsonl on every invocation -- run "
- "`bd export -o .beads/issues.jsonl` after every bead write, do not commit that file in this lane",
- "a worktree's .beads/issues.jsonl is frozen at its branch point: once the worktree ages, "
- "ANY bd invocation or git-checkout hook inside it can reimport the stale file and revert "
- "live bead state (polylogue-2ara; 2026-08-01 incident reverted 5+ coordinator writes twice) "
- "-- prefer no bd writes from lane worktrees at all; report bead-state changes to the coordinator",
- "no `git stash` (refs/stash is shared across worktrees)",
- "TMPDIR=/realm/tmp (system /tmp is a 6GiB tmpfs)",
- "run `python -m devtools ...` from the worktree root so the worktree's code wins over the shared-venv .pth",
-)
-
-_VERIFICATION_TIER = (
- "Inner loop: `devtools test ` / testmon-affected selection.\n"
- "Pre-PR: `devtools verify`.\n"
- "Do NOT run whole-directory pytest.\n"
- "Per-PR CI skips the heavy test suite, so green checks alone are not test evidence -- "
- "verify locally."
-)
-
-_PR_SCOPE_CARRIER = (
- "Before opening a non-draft PR, render stable v2 intent from assigned and mutated Bead IDs, "
- "whole-Bead dispositions, typed evidence refs, and open successors for residual work: "
- "`devtools workspace pr-scope render --input .agent/pr-scope.json`. Embed the rendered comment "
- "in the PR body and validate the published PR with `devtools workspace pr-scope check --pr `. "
- "Use `devtools workspace pr-scope sync --pr ` to inspect the current head-bound attestation without "
- "rewriting the body after each commit. "
- "Do not infer acceptance from Bead prose or invent missing Bead IDs."
-)
-
-
-@dataclass
-class BeadRecord:
- id: str
- found: bool
- priority: int | None = None
- issue_type: str | None = None
- title: str = ""
- description: str = ""
- design: str = ""
- acceptance_criteria: str = ""
- notes_tail: str = ""
- dependencies: list[str] = field(default_factory=list)
- contract_confidence: str | None = None
- contract_errors: list[str] = field(default_factory=list)
- contract_source_digest: str | None = None
- computed_source_digest: str | None = None
- contract_dependency_digest: str | None = None
- computed_dependency_digest: str | None = None
- error: str = ""
-
-
-@dataclass
-class FootprintEvidence:
- path: str
- exists: bool
- line_count: int | None = None
- recent_commits: list[str] = field(default_factory=list)
-
-
-@dataclass
-class PriorArtHit:
- id: str
- title: str
- close_reason_head: str
-
-
-def _dep_labels(record: BeadDict) -> list[str]:
- labels: list[str] = []
- for dep in record.get("dependencies") or []:
- if isinstance(dep, dict):
- target = dep.get("depends_on_id") or dep.get("to_id") or dep.get("id") or "?"
- dep_type = dep.get("type") or dep.get("dep_type") or "?"
- labels.append(f"{target}({dep_type})")
- else:
- labels.append(str(dep))
- return labels
-
-
-def _fetch_bead(bead_id: str) -> BeadRecord:
- result = subprocess.run(["bd", "show", bead_id, "--json"], capture_output=True, text=True)
- if result.returncode != 0:
- return BeadRecord(id=bead_id, found=False, error=result.stderr.strip()[:200] or "bd show failed")
- try:
- payload = strict_json_loads(result.stdout)
- except (JSONDecodeError, TypeError) as exc:
- return BeadRecord(id=bead_id, found=False, error=f"unparseable bd show output: {exc}")
- if isinstance(payload, list):
- if len(payload) != 1:
- return BeadRecord(
- id=bead_id,
- found=False,
- error=f"bd show returned {len(payload)} records; expected exactly one for {bead_id}",
- )
- record = payload[0]
- else:
- record = payload
- if not isinstance(record, dict):
- return BeadRecord(
- id=bead_id, found=False, error=f"unparseable bd show output: expected object, got {type(record).__name__}"
- )
- record_id = record.get("id")
- if not isinstance(record_id, str) or not record_id:
- return BeadRecord(id=bead_id, found=False, error="bd show response is missing a non-empty id")
- if record_id != bead_id:
- return BeadRecord(
- id=bead_id,
- found=False,
- error=f"bd show response id {record_id!r} does not match requested id {bead_id!r}",
- )
-
- notes_value = record.get("notes")
- notes = notes_value if isinstance(notes_value, str) else ""
- metadata = record.get("metadata")
- if isinstance(metadata, str):
- try:
- metadata = strict_json_loads(metadata)
- except JSONDecodeError:
- metadata = {}
- contract = metadata.get("acceptance_contract_v1") if isinstance(metadata, dict) else None
- confidence = contract.get("confidence") if isinstance(contract, dict) else None
- contract_errors = acceptance_contracts.validate(record) if isinstance(contract, dict) else [_MISSING_CONTRACT_ERROR]
- try:
- computed_source_digest = acceptance_contracts.source_digest(record)
- computed_dependency_digest = acceptance_contracts.dependency_digest(record)
- except acceptance_contracts.DependencyProjectionError as exc:
- contract_errors = sorted({*contract_errors, str(exc)})
- computed_source_digest = None
- computed_dependency_digest = None
- contract_source_digest = contract.get("source_digest") if isinstance(contract, dict) else None
- contract_dependency_digest = contract.get("dependency_digest") if isinstance(contract, dict) else None
- priority = record.get("priority")
- issue_type = record.get("issue_type")
- title = record.get("title")
- description = record.get("description")
- design = record.get("design")
- acceptance_criteria = record.get("acceptance_criteria")
- return BeadRecord(
- id=bead_id,
- found=True,
- priority=priority if isinstance(priority, int) and not isinstance(priority, bool) else None,
- issue_type=issue_type if isinstance(issue_type, str) else None,
- title=title if isinstance(title, str) else "",
- description=description if isinstance(description, str) else "",
- design=design if isinstance(design, str) else "",
- acceptance_criteria=acceptance_criteria if isinstance(acceptance_criteria, str) else "",
- notes_tail=notes[-500:],
- dependencies=_dep_labels(record),
- contract_confidence=confidence if isinstance(confidence, str) else None,
- contract_errors=contract_errors,
- contract_source_digest=contract_source_digest if isinstance(contract_source_digest, str) else None,
- computed_source_digest=computed_source_digest,
- contract_dependency_digest=contract_dependency_digest if isinstance(contract_dependency_digest, str) else None,
- computed_dependency_digest=computed_dependency_digest,
- )
-
-
-def _combined_text(records: Sequence[BeadRecord]) -> str:
- parts: list[str] = []
- for r in records:
- parts.extend([r.description, r.design, r.acceptance_criteria, r.notes_tail])
- return " ".join(p for p in parts if p)
-
-
-def _extract_paths(text: str) -> list[str]:
- return list(dict.fromkeys(_LANE_FILE_PAT.findall(text)))
-
-
-def _git_log_recent(repo_root: Path, path: str, limit: int = 3) -> list[str]:
- result = subprocess.run(
- ["git", "log", "--oneline", f"-{limit}", "--", path],
- capture_output=True,
- text=True,
- cwd=repo_root,
- )
- if result.returncode != 0:
- return []
- return [line for line in result.stdout.splitlines() if line]
-
-
-def _verify_footprint(repo_root: Path, paths: list[str]) -> list[FootprintEvidence]:
- evidence: list[FootprintEvidence] = []
- for path in paths:
- full = repo_root / path
- if full.is_file():
- try:
- line_count = sum(1 for _ in full.open("r", errors="replace"))
- except OSError:
- line_count = None
- evidence.append(
- FootprintEvidence(
- path=path,
- exists=True,
- line_count=line_count,
- recent_commits=_git_log_recent(repo_root, path),
- )
- )
- else:
- evidence.append(FootprintEvidence(path=path, exists=False))
- return evidence
-
-
-def _load_bd_export(repo_root: Path, tmpdir: Path) -> list[BeadDict]:
- """Export the full bd backlog and parse it for closed-bead prior art.
-
- Degrades quietly to an empty list on any subprocess/parse failure --
- prior-art is advisory, and a brief that omits it is still useful.
- """
- export_path = tmpdir / "lane-brief-export.jsonl"
- try:
- result = subprocess.run(
- ["bd", "export", "-o", str(export_path)],
- capture_output=True,
- text=True,
- cwd=repo_root,
- timeout=60,
- )
- except (OSError, subprocess.SubprocessError):
- return []
- if result.returncode != 0 or not export_path.exists():
- return []
-
- records: list[BeadDict] = []
- try:
- with export_path.open("r") as f:
- for line in f:
- line = line.strip()
- if not line:
- continue
- try:
- records.append(json.loads(line))
- except json.JSONDecodeError:
- continue
- except OSError:
- return []
- return records
-
-
-def _find_prior_art(
- export_records: list[BeadDict],
- paths: list[str],
- exclude_ids: set[str],
- limit: int = 5,
-) -> list[PriorArtHit]:
- if not paths:
- return []
- hits: list[PriorArtHit] = []
- for rec in export_records:
- if rec.get("_type", "issue") != "issue":
- continue
- if rec.get("status") != "closed":
- continue
- bead_id = rec.get("id", "")
- if bead_id in exclude_ids:
- continue
- text = " ".join(
- filter(
- None,
- [rec.get("description", ""), rec.get("design", ""), rec.get("notes", "")],
- )
- )
- if any(p in text for p in paths):
- close_reason = (rec.get("close_reason") or rec.get("notes") or "").strip().replace("\n", " ")
- hits.append(
- PriorArtHit(
- id=bead_id,
- title=rec.get("title", ""),
- close_reason_head=close_reason[:160],
- )
- )
- if len(hits) >= limit:
- break
- return hits
-
-
-def _recent_master_commits(repo_root: Path, paths: list[str], days: int = 7, limit: int = 15) -> list[str]:
- """Commits on the default-branch tip touching any footprint path in the last N days.
-
- This is the prior-satisfaction signal the per-path footprint listing buries:
- on 2026-08-01 a dispatched lane (polylogue-2cuv) burned most of its budget
- re-investigating a bead whose core ask had already been merged earlier the
- same session. Aggregating recent-master churn across the whole footprint in
- one loud list makes "is this already done?" the first question, not a
- late discovery.
- """
- if not paths:
- return []
- ref = "origin/master"
- if (
- subprocess.run(["git", "rev-parse", "--verify", ref], capture_output=True, text=True, cwd=repo_root).returncode
- != 0
- ):
- ref = "HEAD"
- result = subprocess.run(
- ["git", "log", f"--since={days} days ago", "--format=%h %ad %s", "--date=short", ref, "--", *paths],
- capture_output=True,
- text=True,
- cwd=repo_root,
- )
- if result.returncode != 0:
- return []
- lines = [line for line in result.stdout.splitlines() if line.strip()]
- return lines[:limit]
-
-
-def _render_markdown(
- lane_ids: list[str],
- records: list[BeadRecord],
- footprint: list[FootprintEvidence],
- prior_art: list[PriorArtHit],
- recent_commits: list[str] | None = None,
- recent_days: int = 7,
-) -> str:
- lines: list[str] = []
- lines.append(f"# Lane brief: {', '.join(lane_ids)}")
- lines.append("")
-
- lines.append("## Scope")
- lines.append("")
- for r in records:
- if not r.found:
- lines.append(f"### {r.id} -- NOT FOUND")
- lines.append(f"`bd show {r.id}` failed: {r.error}")
- lines.append("")
- continue
- lines.append(f"### {r.id} -- P{r.priority} {r.issue_type} -- {r.title}")
- lines.append("")
- if r.contract_errors:
- lines.append("**DISPATCH BLOCKED:** the current acceptance contract is invalid or stale.")
- lines.append("")
- for error in r.contract_errors:
- lines.append(f"- {error}")
- lines.append("")
- elif r.contract_confidence == "planner-review":
- lines.append(
- "**DISPATCH BLOCKED:** this acceptance contract requires planner review before implementation dispatch."
- )
- lines.append("")
- if r.contract_source_digest or r.computed_source_digest:
- lines.append(
- f"**Source digest:** contract={r.contract_source_digest or '(missing)'}; "
- f"current={r.computed_source_digest or '(unavailable)'}"
- )
- lines.append("")
- if r.contract_dependency_digest or r.computed_dependency_digest:
- lines.append(
- f"**Dependency digest:** contract={r.contract_dependency_digest or '(missing)'}; "
- f"current={r.computed_dependency_digest or '(unavailable)'}"
- )
- lines.append("")
- lines.append("**Description:**")
- lines.append("")
- lines.append(r.description or "(empty)")
- lines.append("")
- lines.append("**Design:**")
- lines.append("")
- lines.append(r.design or "(empty)")
- lines.append("")
- lines.append("**Acceptance criteria:**")
- lines.append("")
- lines.append(r.acceptance_criteria or "(empty)")
- lines.append("")
- if r.notes_tail:
- lines.append("**Notes (last 500 chars):**")
- lines.append("")
- lines.append(r.notes_tail)
- lines.append("")
- if r.dependencies:
- lines.append(f"**Dependencies:** {', '.join(r.dependencies)}")
- lines.append("")
- lines.append("")
-
- lines.append("## Footprint (verified)")
- lines.append("")
- if not footprint:
- lines.append("No file paths were extracted from the combined bead text.")
- else:
- for ev in footprint:
- if ev.exists:
- lines.append(f"- `{ev.path}` -- exists, {ev.line_count} lines")
- for commit in ev.recent_commits:
- lines.append(f" - {commit}")
- if not ev.recent_commits:
- lines.append(" - (no commit history found for this path)")
- else:
- lines.append(f"- `{ev.path}` -- **PATH NOT FOUND** -- bead prose may be stale, verify before trusting")
- lines.append("")
-
- lines.append("## Prior art")
- lines.append("")
- if prior_art:
- for hit in prior_art:
- lines.append(f"- **{hit.id}** -- {hit.title}")
- if hit.close_reason_head:
- lines.append(f" - close reason: {hit.close_reason_head}")
- else:
- lines.append("No closed beads found mentioning the same file paths.")
- lines.append("")
-
- lines.append(f"## Recently merged on master (footprint overlap, last {recent_days} days)")
- lines.append("")
- if recent_commits:
- lines.append(
- f"**PRIOR-SATISFACTION CHECK:** {len(recent_commits)} recent master commit(s) touched "
- "this lane's footprint. Read them BEFORE implementing -- the bead's core ask may "
- "already be satisfied by one of these merges. If it is, report that honestly and "
- "stop; do not re-implement."
- )
- lines.append("")
- for commit in recent_commits:
- lines.append(f"- {commit}")
- else:
- lines.append("No master commits touched the extracted footprint paths in this window.")
- lines.append("")
-
- lines.append("## Measured baseline")
- lines.append("")
- lines.append("")
- lines.append(
- "Paste the actual command output that motivates this lane (a failing test, a "
- "measured metric, a reproduction). Bead prose alone is not evidence."
- )
- lines.append("")
-
- lines.append("## Non-goals")
- lines.append("")
- lines.append("")
- lines.append("State explicitly what this lane will NOT change, to bound scope creep.")
- lines.append("")
-
- lines.append("## Anti-vacuity contract")
- lines.append("")
- lines.append(_ANTI_VACUITY_CONTRACT)
- lines.append("")
-
- lines.append("## Hazards (standing)")
- lines.append("")
- for hazard in _HAZARDS:
- lines.append(f"- {hazard}")
- lines.append("")
-
- lines.append("## Verification tier")
- lines.append("")
- lines.append(_VERIFICATION_TIER)
- lines.append("")
- lines.append("## PR scope carrier")
- lines.append("")
- lines.append(_PR_SCOPE_CARRIER)
- lines.append("")
-
- return "\n".join(lines)
-
-
-def _repo_root() -> Path:
- result = subprocess.run(["git", "rev-parse", "--show-toplevel"], capture_output=True, text=True)
- if result.returncode == 0 and result.stdout.strip():
- return Path(result.stdout.strip())
- return Path.cwd()
-
-
-def main(argv: Sequence[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
- parser.add_argument("bead_ids", nargs="+", help="Bead ids in this lane (e.g. polylogue-abc polylogue-def)")
- parser.add_argument("--out", metavar="FILE", help="Write the brief to this path instead of stdout")
- parser.add_argument(
- "--tmpdir",
- metavar="DIR",
- default="/realm/tmp",
- help="Scratch dir for the bd export used for prior-art scanning (default: /realm/tmp)",
- )
- parser.add_argument(
- "--recent-days",
- type=int,
- default=7,
- metavar="N",
- help="Window for the recently-merged footprint-overlap section (default: 7)",
- )
- args = parser.parse_args(argv)
-
- repo_root = _repo_root()
- try:
- acceptance_contracts.load_manifest(acceptance_contracts._DEFAULT_MANIFEST)
- except SystemExit as exc:
- print(f"DISPATCH BLOCKED: {exc}", file=sys.stderr)
- return 2
- required_ids = set(acceptance_contracts.load_manifest(acceptance_contracts._DEFAULT_MANIFEST))
- records = [_fetch_bead(bead_id) for bead_id in args.bead_ids]
- for record in records:
- if record.id not in required_ids:
- record.contract_errors = [error for error in record.contract_errors if error != _MISSING_CONTRACT_ERROR]
-
- combined_text = _combined_text(records)
- paths = _extract_paths(combined_text)
- footprint = _verify_footprint(repo_root, paths)
-
- tmpdir = Path(args.tmpdir)
- tmpdir.mkdir(parents=True, exist_ok=True)
- export_records = _load_bd_export(repo_root, tmpdir)
- exclude_ids = {r.id for r in records}
- prior_art = _find_prior_art(export_records, paths, exclude_ids)
- recent_commits = _recent_master_commits(repo_root, paths, days=args.recent_days)
-
- brief = _render_markdown(
- list(args.bead_ids),
- records,
- footprint,
- prior_art,
- recent_commits=recent_commits,
- recent_days=args.recent_days,
- )
-
- if args.out:
- Path(args.out).write_text(brief)
- print(f"Wrote lane brief to {args.out}")
- else:
- print(brief)
-
- return (
- 2 if any(not r.found or r.contract_errors or r.contract_confidence == "planner-review" for r in records) else 0
- )
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/lane_models.py b/devtools/lane_models.py
deleted file mode 100644
index 488b3d4639..0000000000
--- a/devtools/lane_models.py
+++ /dev/null
@@ -1,109 +0,0 @@
-"""Shared control-plane lane metadata."""
-
-from __future__ import annotations
-
-import logging
-from dataclasses import dataclass, field
-
-from polylogue.scenarios.assertions import AssertionSpec
-from polylogue.scenarios.execution import ExecutionSpec
-from polylogue.scenarios.metadata import ScenarioMetadata
-from polylogue.scenarios.projections import ScenarioProjectionEntry, ScenarioProjectionSourceKind
-
-logger = logging.getLogger(__name__)
-
-
-@dataclass(frozen=True, kw_only=True)
-class LaneEntry:
- """One named control-plane lane."""
-
- name: str
- description: str
- timeout_s: int
- category: str
- execution: ExecutionSpec | None = None
- assertion: AssertionSpec = field(default_factory=AssertionSpec)
- family: str | None = None
-
- # Metadata fields kept as direct attributes for ScenarioMetadata.from_object
- # compatibility and for _build_lane_entry merge logic.
- origin: str = "authored.validation-lane"
- path_targets: tuple[str, ...] = ()
- artifact_targets: tuple[str, ...] = ()
- conceptual_path_targets: tuple[str, ...] = ()
- conceptual_artifact_targets: tuple[str, ...] = ()
- operation_targets: tuple[str, ...] = ()
- maintenance_targets: tuple[str, ...] = ()
- tags: tuple[str, ...] = ()
-
- def __post_init__(self) -> None:
- """Validate assertion/lane consistency after construction."""
- if self.execution and self.execution.members:
- # Composite lanes delegate to sub-lanes; skip validation.
- return
- warnings = self.assertion.validate()
- for w in warnings:
- logger.warning("validation lane %s: %s", self.name, w)
-
- @property
- def is_composite(self) -> bool:
- return self.execution is not None and self.execution.is_composite
-
- @property
- def sub_lanes(self) -> tuple[str, ...]:
- if self.execution is None:
- return ()
- return self.execution.members
-
- # ------------------------------------------------------------------
- # Projection protocol (replaces ExecutableScenario/NamedScenarioSource inheritance)
- # ------------------------------------------------------------------
-
- @property
- def projection_source_kind(self) -> ScenarioProjectionSourceKind:
- return ScenarioProjectionSourceKind.VALIDATION_LANE
-
- @property
- def projection_name(self) -> str:
- return self.name
-
- @property
- def projection_description(self) -> str:
- return self.description
-
- def projection_source_payload(self) -> dict[str, object]:
- payload: dict[str, object] = {
- "timeout_s": self.timeout_s,
- "category": self.category,
- }
- if self.family is not None:
- payload["family"] = self.family
- return payload
-
- def to_projection_entry(self) -> ScenarioProjectionEntry:
- metadata = ScenarioMetadata.from_object(self)
- return ScenarioProjectionEntry(
- source_kind=self.projection_source_kind,
- name=self.name,
- description=self.description,
- origin=metadata.origin,
- path_targets=metadata.path_targets,
- artifact_targets=metadata.artifact_targets,
- conceptual_path_targets=metadata.conceptual_path_targets,
- conceptual_artifact_targets=metadata.conceptual_artifact_targets,
- operation_targets=metadata.operation_targets,
- maintenance_targets=metadata.maintenance_targets,
- tags=metadata.tags,
- docs_role=metadata.docs_role,
- caption=metadata.caption,
- narrative_order=metadata.narrative_order,
- audience=metadata.audience,
- demonstrates=metadata.demonstrates,
- privacy_level=metadata.privacy_level,
- media=metadata.media,
- visual_style=metadata.visual_style,
- source_payload=dict(self.projection_source_payload()),
- )
-
-
-__all__ = ["LaneEntry"]
diff --git a/devtools/lineage_validation.py b/devtools/lineage_validation.py
index 2c797eedfc..0f3b22dcb9 100644
--- a/devtools/lineage_validation.py
+++ b/devtools/lineage_validation.py
@@ -706,31 +706,17 @@ def _demo_summary(report: dict[str, Any]) -> dict[str, Any]:
"index_db": report["index_db"],
"snapshot_identity": report["snapshot_identity"],
"index_schema_version": report["index_schema_version"],
- "claim": (
- "Polylogue can emit a read-only lineage validation artifact that separates physical stored "
- "archive counts from logical session counts before those numbers are cited externally."
- ),
- "non_claim": (
- "This artifact does not prove every composed transcript is byte-identical to the pre-lineage "
- "archive; it samples composed reads and flags residual integrity gaps for follow-up."
- ),
- "proof_report": {
- "external_counts_citable": verdict["external_counts_citable"],
- "physical_sessions": counts["physical_sessions"],
- "logical_sessions": counts["logical_sessions"],
- "stored_messages": counts["stored_messages"],
- "profile_coverage": counts["profile_coverage"],
- "link_counts": report["lineage"]["counts"],
- "integrity": report["lineage"]["integrity"],
- "sample": report["lineage"]["prefix_sharing_read_sample"],
- "topology": report["lineage"]["topology"],
- },
- "caveats": verdict["reasons"]
- or [
- "Prefix-sharing read composition is sampled, not exhaustively compared against historical pre-dedup transcripts.",
- "The archive may still have non-lineage convergence caveats outside this gate.",
- ],
- "source_files": [
+ "external_counts_citable": verdict["external_counts_citable"],
+ "reasons": verdict["reasons"],
+ "physical_sessions": counts["physical_sessions"],
+ "logical_sessions": counts["logical_sessions"],
+ "stored_messages": counts["stored_messages"],
+ "profile_coverage": counts["profile_coverage"],
+ "link_counts": report["lineage"]["counts"],
+ "integrity": report["lineage"]["integrity"],
+ "sample": report["lineage"]["prefix_sharing_read_sample"],
+ "topology": report["lineage"]["topology"],
+ "files": [
"lineage-validation.report.json",
"summary.json",
"README.md",
@@ -773,7 +759,6 @@ def _write_readme(path: Path, report: dict[str, Any]) -> None:
"## Files",
"",
"- `lineage-validation.report.json` — full machine-readable evidence.",
- "- `summary.json` — demo-shelf claim/non-claim/proof/caveat summary.",
"",
]
if verdict["reasons"]:
diff --git a/devtools/mandate_continuity_replay.py b/devtools/mandate_continuity_replay.py
deleted file mode 100644
index 098dfcf448..0000000000
--- a/devtools/mandate_continuity_replay.py
+++ /dev/null
@@ -1,599 +0,0 @@
-"""z9gh.7-owned mandate replay: wire t8t scenarios + the work-evidence effect
-graph + query discovery into one privacy-safe artifact.
-
-``polylogue-t8t`` declares and proves the seven continuity scenarios (plus the
-parallel-Claude incident variant) against a deterministic synthetic archive.
-``polylogue-1vpm.6.2`` supplies production repository-effect adapters
-(``polylogue.insights.work_effects``) that reconcile work-evidence claims
-against independently observed git/GitHub/Beads effects. ``polylogue-z9gh.3``
-supplies the executable query-discovery catalog a cold model would use to
-formulate the same query plans t8t's scenarios execute. None of the three is
-wired to the other two, and no artifact reports them as one terminal gate --
-that is z9gh.7's own named residual scope (2026-07-20 "CONCRETE BAR" item 3).
-
-This module is that wiring, not a fourth reimplementation:
-
-- :func:`check_discovery_coverage` reuses the real
- :data:`polylogue.archive.query.discovery.QUERY_DISCOVERY_EXAMPLES` catalog
- to prove every ``query``-tool route step any continuity scenario executes
- has a declared positive example of the same unit-source/route shape --
- i.e. a cold model relying on discovery alone could have found that plan
- family, not just executed it once the runner already knew it.
-- :func:`build_repository_claim_graph` and :func:`run_work_evidence_effect_proof`
- reuse the real, production :mod:`polylogue.insights.work_effects` adapters
- (``GitCommitEffectAdapter``, ``BeadsIssueEffectAdapter``,
- ``GitHubPullRequestEffectAdapter``) against *this repository's own* git
- history and committed ``.beads/interactions.jsonl`` ledger -- real,
- full-scale, and privacy-safe because both are already public/committed
- project artifacts, not private chat archive content. Claims are built
- independently from the same ledger's "issue closed" transitions, so the
- effect adapters are proving something over real evidence, not reconciling
- a graph against its own construction.
-- :func:`run_mandate_continuity_replay` calls
- :func:`devtools.continuity_replay.replay_archive` unmodified against either
- a supplied archive root (an authorized live-scale replay) or a freshly
- seeded synthetic corpus (the default, privacy-safe CI lane), then combines
- all three lanes plus a mandate acceptance-criteria matrix into one JSON
- artifact. :func:`redact_report` strips raw evidence prose from that
- artifact (keeping refs/hashes/counts) for the live-archive lane; the
- synthetic lane never touches private content so redaction there is a no-op
- proof of the same mechanism, not a load-bearing privacy boundary.
-
-Two acceptance-criteria items this module explicitly does NOT claim to
-close, stated up front rather than discovered by a reviewer:
-
-- AC2's specific 2026-07-15 incident replay (finding the real coordinator
- ``cf0c6474-...`` and run ``wf_54d4fb2e-841`` in a live private archive)
- requires an authorized live archive this sandbox does not have. The
- synthetic lane proves the identical mechanism against t8t's corrected
- 91/38/129/4 census; a live run is `--archive-root` away once one is
- authorized, deferred honestly in the AC matrix rather than faked.
-- AC6 (mutation checks) is already t8t's own proven scope
- (``tests/infra/continuity_mutations.py``); this module cites that
- suite rather than duplicating it.
-"""
-
-from __future__ import annotations
-
-import argparse
-import asyncio
-import hashlib
-import json
-import re
-import sys
-import time
-from collections import Counter
-from collections.abc import Sequence
-from dataclasses import asdict, dataclass
-from pathlib import Path
-from tempfile import TemporaryDirectory
-from typing import Literal, TextIO, cast
-
-if __package__ in {None, ""}: # pragma: no cover - exercised by the script entry point
- sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
-
-from devtools.continuity_replay import replay_archive
-from polylogue.archive.artifact_taxonomy.support import looks_like_beads_interaction
-from polylogue.archive.query.discovery import QUERY_DISCOVERY_EXAMPLES
-from polylogue.core.json import JSONDocument, JSONValue, require_json_document
-from polylogue.core.refs import ObjectRef
-from polylogue.insights.work_effects import (
- DEFAULT_WORK_ITEM_ID_PATTERN,
- BeadsIssueEffectAdapter,
- GitCommitEffectAdapter,
- GitHubPullRequestEffectAdapter,
- RepositoryEffectAdapter,
- collect_repository_effects,
- derive_direct_identifier_judgments,
-)
-from polylogue.insights.work_evidence import WorkEvidenceGraph, WorkEvidenceNode
-from polylogue.insights.work_reconciliation import reconcile_work_effects
-from polylogue.product.continuity_scenarios import CONTINUITY_SCENARIOS, ContinuityScenarioSpec, continuity_scenario
-from tests.infra.continuity import load_continuity_catalog, seed_continuity_archive
-
-#: Repo root -- this file lives at ``devtools/mandate_continuity_replay.py``.
-DEFAULT_REPO_PATH = Path(__file__).resolve().parents[1]
-DEFAULT_BEADS_LEDGER_RELATIVE = Path(".beads") / "interactions.jsonl"
-_GITHUB_REPO_SLUG = "Sinity/polylogue"
-
-MandateLaneStatus = Literal["pass", "fail", "deferred"]
-
-#: z9gh.7's own acceptance criteria, verbatim (see ``bd show polylogue-z9gh.7``).
-#: Numbering matches the bead's numbering so the artifact's ac_matrix can be
-#: diffed against the bead text directly.
-_MANDATE_AC_TEXT: tuple[str, ...] = (
- "The seven polylogue-t8t flows pass as real MCP walks.",
- "The 2026-07-15 incident replay starts from repo, approximate time, and "
- "parallel-agent wording; it finds coordinator "
- "cf0c6474-da22-44be-af3e-666037aa5ea4 and run wf_54d4fb2e-841, distinguishes "
- "four Workflow invocations from one resumed run, reconstructs 50 call keys, "
- "91 attempt transcripts, 65 result records over 49 completed keys, one "
- "unresolved key, and the final structured result, and excludes the "
- "coordinator's other 38 child sessions from Workflow membership.",
- "The replay distinguishes model, material, call, attempt, and effect scopes "
- "and cites git, PR, and Beads effects with uncertainty.",
- "Payload paging is lossless, cancellation stops work, and measured latency/memory stay within declared SLOs.",
- "A cold model succeeds using MCP schemas/errors/catalog evidence alone.",
- "Mutation checks prove the replay fails if continuation state, selective "
- "SQL, orchestration links, source coverage, or provenance classification "
- "is removed.",
- "The artifact records each mandate bead as satisfied, deferred to a named successor, or still blocking.",
-)
-
-
-# ── Discovery-coverage lane ───────────────────────────────────────────
-
-
-@dataclass(frozen=True, slots=True)
-class DiscoveryCoverageGap:
- """One continuity route step whose plan family has no discovery example."""
-
- scenario_id: str
- step_id: str
- plan_atom: str
- reason: str
-
- def to_dict(self) -> dict[str, str]:
- return asdict(self)
-
-
-@dataclass(frozen=True, slots=True)
-class DiscoveryCoverageReport:
- """Whether every continuity-scenario query plan is independently discoverable."""
-
- checked_steps: int
- covered_steps: int
- gaps: tuple[DiscoveryCoverageGap, ...]
-
- @property
- def status(self) -> Literal["pass", "fail"]:
- return "pass" if not self.gaps else "fail"
-
- def to_dict(self) -> dict[str, object]:
- return {
- "status": self.status,
- "checked_steps": self.checked_steps,
- "covered_steps": self.covered_steps,
- "gaps": [gap.to_dict() for gap in self.gaps],
- }
-
-
-def check_discovery_coverage(
- scenarios: Sequence[ContinuityScenarioSpec],
-) -> DiscoveryCoverageReport:
- """Prove every ``query``-tool continuity route step is independently discoverable.
-
- A continuity scenario's route steps prove the runner *can execute* a
- plan; they say nothing about whether a cold model, given only the
- published query-discovery catalog (``archive/query/discovery.py``), could
- have *formulated* that same plan family without hidden knowledge. This
- cross-checks each ``query``-tool step's unit-source against
- ``QUERY_DISCOVERY_EXAMPLES`` -- the same catalog z9gh.3 generates MCP
- schemas/completions from -- so a shipped scenario whose plan family the
- discovery catalog does not teach shows up as a named gap rather than a
- silent success.
- """
-
- catalog_atoms = {f"query:{example.unit_source}" for example in QUERY_DISCOVERY_EXAMPLES if example.route == "query"}
- gaps: list[DiscoveryCoverageGap] = []
- checked = 0
- for scenario in scenarios:
- for step in scenario.route_steps:
- if step.tool != "query":
- continue
- checked += 1
- atom = step.plan_atom
- if atom not in catalog_atoms:
- gaps.append(
- DiscoveryCoverageGap(
- scenario_id=scenario.scenario_id,
- step_id=step.step_id,
- plan_atom=atom,
- reason=f"no declared query-discovery example teaches {atom!r}",
- )
- )
- return DiscoveryCoverageReport(checked_steps=checked, covered_steps=checked - len(gaps), gaps=tuple(gaps))
-
-
-# ── Work-evidence effect-reconciliation lane (this repo's own git+Beads) ──
-
-
-def _file_identity(path: Path) -> str:
- return hashlib.sha256(str(Path(path).resolve()).encode("utf-8")).hexdigest()[:16]
-
-
-def build_repository_claim_graph(
- jsonl_path: Path,
- *,
- graph_id: str = "mandate-repository-claims",
- id_pattern: re.Pattern[str] = DEFAULT_WORK_ITEM_ID_PATTERN,
-) -> WorkEvidenceGraph:
- """Build one claim node per Beads issue independently observed as closed.
-
- Reads the *same* interaction ledger :class:`BeadsIssueEffectAdapter` reads
- as an effect source, but here as an independent claim source: "issue X
- was closed" is a claim about work completion, distinct from whether
- observed git/PR/Beads evidence actually supports it. Every claim's own
- identity is the issue id; the reconciliation lane below never treats this
- ledger's row as its own confirming effect for the same interaction --
- corroboration must come from an independently matched effect (typically a
- git commit citing the same issue id, or a distinct Beads interaction).
- """
-
- if not jsonl_path.is_file():
- raise FileNotFoundError(f"Beads interaction ledger not found: {jsonl_path}")
- snapshot_ref = ObjectRef(kind="context-snapshot", object_id=f"beads-claims:{_file_identity(jsonl_path)}")
- nodes: dict[str, WorkEvidenceNode] = {}
- for line in jsonl_path.read_text(encoding="utf-8").splitlines():
- line = line.strip()
- if not line:
- continue
- try:
- record = json.loads(line)
- except json.JSONDecodeError:
- continue
- if not looks_like_beads_interaction(record):
- continue
- if str(record.get("kind")) != "field_change":
- continue
- extra = record.get("extra")
- if not isinstance(extra, dict) or extra.get("field") != "status" or extra.get("new_value") != "closed":
- continue
- issue_id = str(record["issue_id"])
- if not id_pattern.fullmatch(issue_id):
- continue
- ref = ObjectRef(kind="work-claim", object_id=f"claimed-closed:{issue_id}")
- if ref.format() in nodes:
- continue
- nodes[ref.format()] = WorkEvidenceNode(
- ref=ref,
- kind="claim",
- label=f"{issue_id} claimed closed",
- claim_text=f"Beads issue {issue_id} was recorded as closed.",
- evidence_refs=(ObjectRef(kind="artifact", object_id=f"beads-interaction:{issue_id}:{record['id']}"),),
- corpus_snapshot_ref=snapshot_ref,
- authority="operator",
- confidence=1.0,
- )
- return WorkEvidenceGraph(graph_id=graph_id, corpus_snapshot_ref=snapshot_ref, nodes=tuple(nodes.values()), edges=())
-
-
-@dataclass(frozen=True, slots=True)
-class WorkEvidenceEffectProof:
- """Quantified result of reconciling repository claims against real effects."""
-
- graph_id: str
- claims_total: int
- claims_evaluated: int
- claims_unevaluated: int
- effect_count_by_authority: dict[str, int]
- judgment_count_by_evaluation: dict[str, int]
- adapter_failures: tuple[dict[str, str], ...]
-
- @property
- def status(self) -> Literal["pass", "fail"]:
- # A live-scale proof over a real, non-empty ledger must actually
- # evaluate at least one claim through a real effect adapter, or the
- # wiring has silently stopped matching anything.
- return "pass" if self.claims_total > 0 and self.claims_evaluated > 0 else "fail"
-
- def to_dict(self) -> dict[str, object]:
- return {
- "graph_id": self.graph_id,
- "claims_total": self.claims_total,
- "claims_evaluated": self.claims_evaluated,
- "claims_unevaluated": self.claims_unevaluated,
- "effect_count_by_authority": dict(self.effect_count_by_authority),
- "judgment_count_by_evaluation": dict(self.judgment_count_by_evaluation),
- "adapter_failures": [dict(failure) for failure in self.adapter_failures],
- "status": self.status,
- }
-
-
-def run_work_evidence_effect_proof(
- *,
- repo_path: Path,
- beads_ledger_path: Path,
- since_ms: int | None = None,
- until_ms: int | None = None,
- adapters: Sequence[RepositoryEffectAdapter] | None = None,
-) -> WorkEvidenceEffectProof:
- """Reconcile real repository claims against real git/GitHub/Beads effects.
-
- Runs the production adapters from ``polylogue.insights.work_effects``
- against this checkout's own git history and Beads ledger -- real,
- full-repository scale, and privacy-safe because both are already public,
- committed project artifacts. The GitHub adapter is included and is
- expected to fail explicitly (no ``gh``/network assumption here): that
- failure is itself the honest "cites ... with uncertainty" PR-evidence
- citation the mandate AC asks for, not an omission.
- """
-
- graph = build_repository_claim_graph(beads_ledger_path)
- resolved_adapters: Sequence[RepositoryEffectAdapter] = adapters or (
- GitCommitEffectAdapter(repo_path=repo_path),
- BeadsIssueEffectAdapter(jsonl_path=beads_ledger_path),
- GitHubPullRequestEffectAdapter(repo=_GITHUB_REPO_SLUG),
- )
- collection = collect_repository_effects(resolved_adapters, since_ms=since_ms, until_ms=until_ms)
- judgments = derive_direct_identifier_judgments(graph, collection.effects)
- reconciled = reconcile_work_effects(graph, effects=collection.effects, judgments=judgments)
-
- claim_refs = {node.ref.format() for node in graph.nodes if node.kind == "claim"}
- evaluated_claim_refs = {edge.source_ref.format() for edge in reconciled.edges if edge.kind == "claimed"}
- evaluated = claim_refs & evaluated_claim_refs
-
- return WorkEvidenceEffectProof(
- graph_id=graph.graph_id,
- claims_total=len(claim_refs),
- claims_evaluated=len(evaluated),
- claims_unevaluated=len(claim_refs - evaluated),
- effect_count_by_authority=dict(sorted(Counter(effect.authority for effect in collection.effects).items())),
- judgment_count_by_evaluation=dict(sorted(Counter(judgment.evaluation for judgment in judgments).items())),
- adapter_failures=tuple(
- {"authority": failure.authority, "reason": failure.reason} for failure in collection.unavailable
- ),
- )
-
-
-# ── Redaction ─────────────────────────────────────────────────────────
-
-_REDACTABLE_KEYS = frozenset({"label", "claim_text", "reason", "response_sha256"})
-
-
-def _redact_value(key: str, value: JSONValue) -> JSONValue:
- if key in _REDACTABLE_KEYS and isinstance(value, str) and value:
- return f"redacted:sha256:{hashlib.sha256(value.encode('utf-8')).hexdigest()}"
- return value
-
-
-def redact_report(document: JSONValue) -> JSONValue:
- """Strip raw evidence prose from a mandate report, keeping refs/counts/hashes.
-
- Recursively walks the report replacing any string value stored under a
- label/claim-text/reason-shaped key with a stable hash of itself. Refs,
- ids, statuses, and counts (everything the mandate AC actually needs
- cited) pass through unchanged -- only free-text prose that could carry
- private archive content is hashed.
- """
-
- if isinstance(document, dict):
- return {key: _redact_value(key, redact_report(value)) for key, value in document.items()}
- if isinstance(document, list):
- return [redact_report(item) for item in document]
- return document
-
-
-# ── Mandate acceptance-criteria matrix ────────────────────────────────
-
-
-@dataclass(frozen=True, slots=True)
-class MandateAcceptanceCriterion:
- index: int
- text: str
- status: Literal["satisfied", "deferred", "blocking"]
- note: str
-
- def to_dict(self) -> dict[str, object]:
- return {"index": self.index, "text": self.text, "status": self.status, "note": self.note}
-
-
-def build_ac_matrix(
- *,
- continuity_report: JSONDocument,
- discovery_report: DiscoveryCoverageReport,
- effect_proof: WorkEvidenceEffectProof,
- live_archive: bool,
-) -> tuple[MandateAcceptanceCriterion, ...]:
- """Map this artifact's lane results onto z9gh.7's own seven AC items."""
-
- continuity_status = str(continuity_report.get("status"))
- ac1 = MandateAcceptanceCriterion(
- index=1,
- text=_MANDATE_AC_TEXT[0],
- status="satisfied" if continuity_status == "pass" else "blocking",
- note=(
- f"devtools.continuity_replay.replay_archive ran {continuity_report.get('scenario_count')} t8t "
- f"scenarios over real MCP stdio JSON-RPC: {continuity_report.get('passed')} passed, "
- f"{continuity_report.get('failed')} failed."
- ),
- )
- ac2 = MandateAcceptanceCriterion(
- index=2,
- text=_MANDATE_AC_TEXT[1],
- status="satisfied" if live_archive and continuity_status == "pass" else "deferred",
- note=(
- "Ran against an authorized live archive root."
- if live_archive
- else "No authorized live archive was supplied to this run; proved the identical mechanism "
- "against t8t's corrected synthetic 91/38/129/4 parallel-incident census instead. Re-run this "
- "same artifact with --archive-root pointed at the promoted live archive to satisfy this item "
- "for real; deferred, not fabricated."
- ),
- )
- effect_status = effect_proof.status
- ac3 = MandateAcceptanceCriterion(
- index=3,
- text=_MANDATE_AC_TEXT[2],
- status="satisfied" if effect_status == "pass" else "blocking",
- note=(
- f"reconcile_repository_effects over this repo's real git+Beads history: "
- f"{effect_proof.claims_evaluated}/{effect_proof.claims_total} claims evaluated "
- f"({effect_proof.judgment_count_by_evaluation}); GitHub PR effects explicitly unavailable "
- f"({[failure['authority'] for failure in effect_proof.adapter_failures]}), cited as uncertainty "
- "rather than silently omitted."
- ),
- )
- ac4 = MandateAcceptanceCriterion(
- index=4,
- text=_MANDATE_AC_TEXT[3],
- status="satisfied" if continuity_status == "pass" else "blocking",
- note="Paging/cancellation/SLO budgets are t8t's own proven scope (PR #3185); this artifact cites "
- "its pass/fail rather than re-deriving it.",
- )
- ac5 = MandateAcceptanceCriterion(
- index=5,
- text=_MANDATE_AC_TEXT[4],
- status="satisfied" if discovery_report.status == "pass" else "blocking",
- note=(
- f"{discovery_report.covered_steps}/{discovery_report.checked_steps} query-tool route steps have "
- f"a declared query-discovery example of the same unit-source/route shape."
- ),
- )
- ac6 = MandateAcceptanceCriterion(
- index=6,
- text=_MANDATE_AC_TEXT[5],
- status="deferred",
- note="t8t's own mutation curriculum (tests/infra/continuity_mutations.py, six named families) "
- "already proves this; this artifact cites that suite rather than duplicating it.",
- )
- ac7 = MandateAcceptanceCriterion(
- index=7,
- text=_MANDATE_AC_TEXT[6],
- status="satisfied",
- note="This ac_matrix is that record: 7 items, each explicitly satisfied/deferred/blocking with a cited reason.",
- )
- return (ac1, ac2, ac3, ac4, ac5, ac6, ac7)
-
-
-# ── Orchestration ──────────────────────────────────────────────────────
-
-
-async def run_mandate_continuity_replay(
- *,
- archive_root: Path | None = None,
- repo_path: Path = DEFAULT_REPO_PATH,
- beads_ledger_path: Path | None = None,
- scenario_names: Sequence[str] | None = None,
- since_ms: int | None = None,
- until_ms: int | None = None,
- redact: bool = True,
- keep_archive: bool = False,
-) -> JSONDocument:
- """Run the continuity, discovery, and work-evidence lanes as one artifact.
-
- When ``archive_root`` is ``None`` (the default), a fresh, privacy-safe
- synthetic continuity corpus is seeded and torn down automatically -- the
- CI/deterministic lane. Passing an authorized live archive root runs the
- identical mechanism against it (the live-scale lane); pair that with
- ``redact=True`` (the default) so evidence prose never leaves this
- process's stdout/artifact file.
- """
-
- beads_ledger_path = beads_ledger_path or (repo_path / DEFAULT_BEADS_LEDGER_RELATIVE)
- started_ns = time.perf_counter_ns()
- catalog = load_continuity_catalog()
- live_archive = archive_root is not None
- workdir: TemporaryDirectory[str] | None = None
-
- resolved_root: Path
- if archive_root is None:
- workdir = TemporaryDirectory(prefix="mandate-continuity-replay-")
- resolved_root = Path(workdir.name) / "archive"
- seed_continuity_archive(resolved_root, catalog=catalog)
- else:
- resolved_root = archive_root
-
- try:
- continuity_report = await replay_archive(resolved_root, catalog, scenario_names=scenario_names)
- finally:
- if workdir is not None and not keep_archive:
- workdir.cleanup()
-
- scenarios = (
- CONTINUITY_SCENARIOS if scenario_names is None else tuple(continuity_scenario(name) for name in scenario_names)
- )
- discovery_report = check_discovery_coverage(scenarios)
- effect_proof = run_work_evidence_effect_proof(
- repo_path=repo_path,
- beads_ledger_path=beads_ledger_path,
- since_ms=since_ms,
- until_ms=until_ms,
- )
- ac_matrix = build_ac_matrix(
- continuity_report=continuity_report,
- discovery_report=discovery_report,
- effect_proof=effect_proof,
- live_archive=live_archive,
- )
- overall_status: Literal["pass", "fail"] = "pass" if all(item.status != "blocking" for item in ac_matrix) else "fail"
- report: dict[str, object] = {
- "schema_version": 1,
- "mandate_bead": "polylogue-z9gh.7",
- "live_archive": live_archive,
- "archive_root": str(resolved_root.resolve()) if keep_archive or live_archive else None,
- "elapsed_ms": round((time.perf_counter_ns() - started_ns) / 1_000_000, 3),
- "status": overall_status,
- "continuity": continuity_report,
- "discovery_coverage": discovery_report.to_dict(),
- "work_evidence_effect_proof": effect_proof.to_dict(),
- "ac_matrix": [item.to_dict() for item in ac_matrix],
- }
- document = require_json_document(report, context="mandate continuity replay report")
- return cast(JSONDocument, redact_report(document)) if redact else document
-
-
-def _scenario_names(value: str) -> tuple[str, ...] | None:
- if value == "all":
- return None
- return tuple(part.strip() for part in value.split(",") if part.strip())
-
-
-def main(argv: list[str] | None = None, *, stdout: TextIO | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument(
- "--archive-root",
- type=Path,
- default=None,
- help="Authorized live archive to replay against; omit for the default synthetic CI lane.",
- )
- parser.add_argument("--repo-path", type=Path, default=DEFAULT_REPO_PATH)
- parser.add_argument("--beads-ledger", type=Path, default=None)
- parser.add_argument("--scenario", default="all", help="all or a comma-separated scenario id list")
- parser.add_argument("--since-ms", type=int, default=None)
- parser.add_argument("--until-ms", type=int, default=None)
- parser.add_argument("--no-redact", action="store_true", help="Disable evidence redaction (CI/synthetic lane only)")
- parser.add_argument("--keep-archive", action="store_true")
- parser.add_argument("--output", type=Path)
- args = parser.parse_args(argv)
-
- report = asyncio.run(
- run_mandate_continuity_replay(
- archive_root=args.archive_root,
- repo_path=args.repo_path,
- beads_ledger_path=args.beads_ledger,
- scenario_names=_scenario_names(args.scenario),
- since_ms=args.since_ms,
- until_ms=args.until_ms,
- redact=not args.no_redact,
- keep_archive=args.keep_archive,
- )
- )
- rendered = json.dumps(report, indent=2, sort_keys=True)
- out = stdout or sys.stdout
- if args.output is not None:
- args.output.parent.mkdir(parents=True, exist_ok=True)
- args.output.write_text(rendered + "\n", encoding="utf-8")
- print(rendered, file=out)
- return 0 if report["status"] == "pass" else 1
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
-
-
-__all__ = [
- "DEFAULT_BEADS_LEDGER_RELATIVE",
- "DEFAULT_REPO_PATH",
- "DiscoveryCoverageGap",
- "DiscoveryCoverageReport",
- "MandateAcceptanceCriterion",
- "WorkEvidenceEffectProof",
- "build_ac_matrix",
- "build_repository_claim_graph",
- "check_discovery_coverage",
- "main",
- "redact_report",
- "run_mandate_continuity_replay",
- "run_work_evidence_effect_proof",
-]
diff --git a/devtools/manifest_models.py b/devtools/manifest_models.py
index 5926c8de58..d29e3dd500 100644
--- a/devtools/manifest_models.py
+++ b/devtools/manifest_models.py
@@ -8,184 +8,9 @@
from __future__ import annotations
-from datetime import date
from typing import ClassVar, Literal
-from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
-
-# ──────────────────────────────────────────────────────────────────────
-# Coverage Gap (shared fragment in many *coverage*.yaml manifests)
-# ──────────────────────────────────────────────────────────────────────
-
-
-class CoverageGap(BaseModel):
- """A known coverage gap record."""
-
- model_config = ConfigDict(extra="forbid")
- id: str
- gap: str
- owner: str
- severity: str
- declared_at: str # ISO-8601 date
- review_after: str # ISO-8601 date
- issue: int | str | None = None
- suppression: str | None = None
- bead: str | None = None
- next_evidence: str | None = None
- subject: str | None = None
- dimension: str | None = None
- axis: str | None = None
- area: str | None = None
- artifact: str | None = None
- platform: str | None = None
- concern: str | None = None
- domain: str | None = None
-
- VALID_SEVERITIES: ClassVar[frozenset[str]] = frozenset({"info", "minor", "major", "serious"})
-
- @field_validator("severity")
- @classmethod
- def _check_severity(cls, v: str) -> str:
- if v not in cls.VALID_SEVERITIES:
- raise ValueError(f"severity must be one of {sorted(cls.VALID_SEVERITIES)}, got {v!r}")
- return v
-
- @field_validator("declared_at", "review_after")
- @classmethod
- def _check_date(cls, v: str) -> str:
- try:
- date.fromisoformat(v)
- except (ValueError, TypeError) as err:
- raise ValueError(f"not a valid ISO date: {v!r}") from err
- return v
-
-
-# ──────────────────────────────────────────────────────────────────────
-# Generic coverage manifest (*coverage*.yaml)
-# ──────────────────────────────────────────────────────────────────────
-
-
-class CoverageManifest(BaseModel):
- """Generic root for *coverage*.yaml files that carry a coverage_gaps list."""
-
- model_config = ConfigDict(extra="forbid")
- description: str | None = None
- coverage_gaps: list[CoverageGap] = Field(default_factory=list)
-
-
-# ──────────────────────────────────────────────────────────────────────
-# Scenario-coverage manifest (scenario-coverage.yaml)
-# ──────────────────────────────────────────────────────────────────────
-
-
-class ScenarioFamily(BaseModel):
- """A single scenario family."""
-
- model_config = ConfigDict(extra="forbid")
- name: str
- description: str
- subject: str
- scenario_count: int | str # int literal or "dynamic"
- location: str
- bead: str | None = None
- notes: str | None = None
-
-
-class ScenarioCoverageManifest(BaseModel):
- """Root of scenario-coverage.yaml."""
-
- model_config = ConfigDict(extra="forbid")
- description: str | None = None
- families: list[ScenarioFamily]
- coverage_gaps: list[CoverageGap] = Field(default_factory=list)
-
-
-# ──────────────────────────────────────────────────────────────────────
-# Campaign-coverage manifest (campaign-coverage.yaml)
-# ──────────────────────────────────────────────────────────────────────
-
-
-class MutationCampaignEntry(BaseModel):
- """A single mutation-campaign record."""
-
- model_config = ConfigDict(extra="forbid")
- name: str
- description: str
- paths_to_mutate: list[str]
- tests: list[str]
- status: str = "active"
- freshness_days: int | None = None
- artifact_glob: str | None = None
- min_kill_rate: float | None = None
-
- VALID_STATUSES: ClassVar[frozenset[str]] = frozenset({"active", "inactive", "draft", "archived"})
-
- @field_validator("status")
- @classmethod
- def _check_status(cls, v: str) -> str:
- if v not in cls.VALID_STATUSES:
- raise ValueError(f"status must be one of {sorted(cls.VALID_STATUSES)}, got {v!r}")
- return v
-
- @field_validator("freshness_days")
- @classmethod
- def _check_freshness(cls, v: int | None) -> int | None:
- if v is not None and v <= 0:
- raise ValueError(f"freshness_days must be positive, got {v!r}")
- return v
-
- @field_validator("min_kill_rate")
- @classmethod
- def _check_min_kill_rate(cls, v: float | None) -> float | None:
- if v is not None and not (0.0 <= v <= 1.0):
- raise ValueError(f"min_kill_rate must be within [0, 1], got {v!r}")
- return v
-
-
-class BenchmarkCampaignEntry(BaseModel):
- """A single benchmark-campaign record."""
-
- model_config = ConfigDict(extra="forbid")
- name: str
- description: str
- tests: list[str]
- status: str = "active"
- freshness_days: int | None = None
- artifact_glob: str | None = None
-
- VALID_STATUSES: ClassVar[frozenset[str]] = frozenset({"active", "inactive", "draft", "archived"})
-
- @field_validator("status")
- @classmethod
- def _check_status(cls, v: str) -> str:
- if v not in cls.VALID_STATUSES:
- raise ValueError(f"status must be one of {sorted(cls.VALID_STATUSES)}, got {v!r}")
- return v
-
- @field_validator("freshness_days")
- @classmethod
- def _check_freshness(cls, v: int | None) -> int | None:
- if v is not None and v <= 0:
- raise ValueError(f"freshness_days must be positive, got {v!r}")
- return v
-
-
-class CampaignCoverageManifest(BaseModel):
- """Root of campaign-coverage.yaml."""
-
- model_config = ConfigDict(extra="forbid")
- description: str | None = None
- default_min_kill_rate: float | None = None
- mutation_campaigns: list[MutationCampaignEntry] = Field(default_factory=list)
- benchmark_campaigns: list[BenchmarkCampaignEntry] = Field(default_factory=list)
-
- @field_validator("default_min_kill_rate")
- @classmethod
- def _check_default_min_kill_rate(cls, v: float | None) -> float | None:
- if v is not None and not (0.0 <= v <= 1.0):
- raise ValueError(f"default_min_kill_rate must be within [0, 1], got {v!r}")
- return v
-
+from pydantic import BaseModel, ConfigDict, Field, model_validator
# ──────────────────────────────────────────────────────────────────────
# Layering manifest (layering.yaml)
@@ -277,249 +102,18 @@ class LayeringManifest(BaseModel):
rules: list[LayeringRule]
-# ──────────────────────────────────────────────────────────────────────
-# ──────────────────────────────────────────────────────────────────────
-# Security-privacy-coverage manifest (security-privacy-coverage.yaml)
-# ──────────────────────────────────────────────────────────────────────
-
-
-class TestCoverage(BaseModel):
- """Test-coverage metadata for a security area."""
-
- model_config = ConfigDict(extra="forbid")
- location: str | None = None
- hypothesis: bool = False
-
-
-class SecurityControl(BaseModel):
- """A single security control entry."""
-
- model_config = ConfigDict(extra="forbid")
- description: str
- implemented: bool = False
- controls: list[dict[str, str]] | dict[str, str] = Field(default_factory=dict)
- test_coverage: TestCoverage = Field(default_factory=TestCoverage)
- notes: str | None = None
-
-
-class SecurityPrivacyManifest(BaseModel):
- """Root of security-privacy-coverage.yaml."""
-
- model_config = ConfigDict(extra="forbid")
- description: str | None = None
- areas: dict[str, SecurityControl] = Field(default_factory=dict)
- coverage_gaps: list[CoverageGap] = Field(default_factory=list)
-
-
-# ──────────────────────────────────────────────────────────────────────
-# Distribution-coverage manifest (distribution-coverage.yaml)
-# ──────────────────────────────────────────────────────────────────────
-
-
-class DistributionArtifact(BaseModel):
- """A single distribution artifact entry.
-
- Only fields consumed by an executable check are retained
- (#1064 Pack C). ``ci_build`` / ``ci_test`` / ``ci_present`` drive
- ``verify_manifests.check_distribution_ci_claims`` against committed
- workflow YAML; ``build_command`` / ``verification_command`` /
- ``config_location`` resolve through ``check_coverage_references``.
- The previous ``freshness_days`` field was removed because no check
- consumed it.
- """
-
- model_config = ConfigDict(extra="forbid")
- description: str | None = None
- build_system: str | None = None
- config_location: str | None = None
- build_command: str | None = None
- install_command: str | None = None
- verification_command: str | None = None
- ci_build: bool = False
- ci_test: bool = False
- notes: str | None = None
- ci_present: bool = False
-
-
-class PlatformCoverage(BaseModel):
- """Platform coverage entry."""
-
- model_config = ConfigDict(extra="forbid")
- linux: str | bool = False
- macos: bool = False
- windows: bool = False
- notes: str | None = None
-
-
-class PipDependencies(BaseModel):
- """Pip dependencies metadata stored inside the artifacts dict."""
-
- model_config = ConfigDict(extra="forbid")
- count: int | None = None
- resolved_by: str | None = None
-
-
-class DistributionCoverageManifest(BaseModel):
- """Root of distribution-coverage.yaml."""
-
- model_config = ConfigDict(extra="forbid")
- description: str | None = None
- artifacts: dict[str, DistributionArtifact | PipDependencies | PlatformCoverage] = Field(default_factory=dict)
- coverage_gaps: list[CoverageGap] = Field(default_factory=list)
-
-
-# ──────────────────────────────────────────────────────────────────────
-# Docs-media-coverage manifest (docs-media-coverage.yaml)
-# ──────────────────────────────────────────────────────────────────────
-
-
-class DocMediaSurface(BaseModel):
- """A single documentation surface entry.
-
- Only fields consumed by an executable check are retained
- (#1064 Pack C). ``path`` is verified against the filesystem and
- ``generated_by`` / ``verified_by`` resolve against the devtools
- command catalog via ``check_coverage_references``. The previous
- ``related_paths``, ``sections``, ``freshness_days``, ``count``,
- and ``providers`` fields were removed because no check consumed
- them.
- """
-
- model_config = ConfigDict(extra="forbid")
- path: str | None = None
- generated_by: str | None = None
- verified_by: str | None = None
- notes: str | None = None
-
-
-class DocsMediaCoverageManifest(BaseModel):
- """Root of docs-media-coverage.yaml."""
-
- model_config = ConfigDict(extra="forbid")
- description: str | None = None
- surfaces: dict[str, DocMediaSurface] = Field(default_factory=dict)
- coverage_gaps: list[CoverageGap] = Field(default_factory=list)
-
-
-# ──────────────────────────────────────────────────────────────────────
-# Test-quality-coverage manifest (test-quality-coverage.yaml)
-# ──────────────────────────────────────────────────────────────────────
-
-
-class FuzzTool(BaseModel):
- """Fuzz-tool entry."""
-
- model_config = ConfigDict(extra="forbid")
- name: str
- locations: list[str] = Field(default_factory=list)
- strategies_location: str | None = None
- schema_driven_strategies: bool = False
- notes: str | None = None
-
-
-class FlakyTest(BaseModel):
- """Known flaky test entry."""
-
- model_config = ConfigDict(extra="forbid")
- name: str | None = None
- location: str | None = None
- intermittent_on: str | None = None
- behavior: str | None = None
- workaround: str | None = None
-
-
-class TestQualityDimension(BaseModel):
- """A single test-quality dimension."""
-
- model_config = ConfigDict(extra="forbid")
- description: str | None = None
- measured: bool = False
- value_percent: int | None = None
- fail_under_percent: int | None = None
- tool: str | None = None
- config_location: str | None = None
- ci_gate: bool = False
- last_verified: str | None = None
- notes: str | None = None
- known_flaky: list[FlakyTest] = Field(default_factory=list)
- ci_retry: bool = False
- flakiness_dashboard: bool = False
- tools: list[FuzzTool] = Field(default_factory=list)
- policy: str | None = None
-
-
-class TestLocations(BaseModel):
- """Test-location groups."""
-
- model_config = ConfigDict(extra="forbid")
- unit_core: list[str] = Field(default_factory=list)
- unit_sources: list[str] = Field(default_factory=list)
- unit_storage: list[str] = Field(default_factory=list)
- unit_pipeline: list[str] = Field(default_factory=list)
- unit_cli: list[str] = Field(default_factory=list)
- unit_mcp: list[str] = Field(default_factory=list)
- unit_security: list[str] = Field(default_factory=list)
- unit_rendering: list[str] = Field(default_factory=list)
- integration: list[str] = Field(default_factory=list)
- fuzz: list[str] = Field(default_factory=list)
-
-
-class TestCount(BaseModel):
- """Test-count record."""
-
- model_config = ConfigDict(extra="forbid")
- total: int | None = None
- unit: str | None = None
- property: str | None = None
- integration: str | None = None
- snapshot: str | int | None = None
- last_measured: str | None = None
-
-
-class TestQualityCoverageManifest(BaseModel):
- """Root of test-quality-coverage.yaml."""
-
- model_config = ConfigDict(extra="forbid")
- description: str | None = None
- dimensions: dict[str, TestQualityDimension | TestCount | TestLocations] = Field(default_factory=dict)
- coverage_gaps: list[CoverageGap] = Field(default_factory=list)
-
-
-# ──────────────────────────────────────────────────────────────────────
-# Manifest-type dispatch table
-# ──────────────────────────────────────────────────────────────────────
-
-# Maps YAML filename → Pydantic model class for structural validation.
-MANIFEST_MODELS: dict[str, type[BaseModel]] = {
- "scenario-coverage.yaml": ScenarioCoverageManifest,
- "campaign-coverage.yaml": CampaignCoverageManifest,
- "layering.yaml": LayeringManifest,
- "security-privacy-coverage.yaml": SecurityPrivacyManifest,
- "distribution-coverage.yaml": DistributionCoverageManifest,
- "docs-media-coverage.yaml": DocsMediaCoverageManifest,
- "test-quality-coverage.yaml": TestQualityCoverageManifest,
-}
-
-
-def validate_manifest(manifest_path: str, data: dict[str, object]) -> list[str]:
- """Validate a single parsed YAML manifest against its Pydantic model.
+def validate_layering_manifest(data: dict[str, object], *, path: str) -> list[str]:
+ """Validate the layering policy before its owning gate consumes it.
Returns a list of human-readable error strings (empty == valid).
Each error includes the manifest file name and the field path so
that operators can locate the problem without opening the file
in an editor.
"""
- import os
-
- filename = os.path.basename(manifest_path)
- model_cls = MANIFEST_MODELS.get(filename)
- if model_cls is None:
- return [] # unknown manifest skipped (not an error)
-
try:
- model_cls.model_validate(data)
+ LayeringManifest.model_validate(data)
except Exception as exc:
- errors = _format_pydantic_errors(manifest_path, exc)
+ errors = _format_pydantic_errors(path, exc)
return errors
return []
@@ -546,33 +140,11 @@ def _format_pydantic_errors(path: str, exc: Exception) -> list[str]:
__all__ = [
- "BenchmarkCampaignEntry",
- "CampaignCoverageManifest",
- "CoverageGap",
- "CoverageManifest",
- "DistributionArtifact",
- "DistributionCoverageManifest",
- "DocMediaSurface",
- "DocsMediaCoverageManifest",
- "FlakyTest",
- "FuzzTool",
"LayeringManifest",
"LayeringRule",
"TwinWriteContract",
"WriterModuleEntry",
"WriterModulePolicy",
"WriterModuleSurface",
- "MANIFEST_MODELS",
- "MutationCampaignEntry",
- "PlatformCoverage",
- "ScenarioCoverageManifest",
- "ScenarioFamily",
- "SecurityControl",
- "SecurityPrivacyManifest",
- "TestCount",
- "TestCoverage",
- "TestLocations",
- "TestQualityCoverageManifest",
- "TestQualityDimension",
- "validate_manifest",
+ "validate_layering_manifest",
]
diff --git a/devtools/merge_boundary.py b/devtools/merge_boundary.py
index b7f4f90b6d..656b4bc46d 100644
--- a/devtools/merge_boundary.py
+++ b/devtools/merge_boundary.py
@@ -443,6 +443,8 @@ def _receipt_is_fresh_for_scope(
valid_scopes = {scope.value for scope in VerificationScope}
if verification_scope not in valid_scopes:
return False
+ if verification_scope not in merge_gate._MERGE_AUTHORIZING_VERIFICATION_SCOPES:
+ return False
release_allowed = receipt.get("release_baseline_allowed")
if not isinstance(release_allowed, bool):
return False
@@ -898,6 +900,10 @@ def cmd_record_full_verify(
def main(argv: list[str] | None = None) -> int:
+ raw_argv = list(sys.argv[1:] if argv is None else argv)
+ if raw_argv and raw_argv[0].isdigit():
+ raw_argv.insert(0, "merge")
+
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
sub = parser.add_subparsers(dest="action", required=True)
@@ -927,7 +933,7 @@ def main(argv: list[str] | None = None) -> int:
)
record_p.add_argument("--command", default="devtools verify --all")
- args = parser.parse_args(argv)
+ args = parser.parse_args(raw_argv)
if args.action == "merge":
return cmd_merge(
diff --git a/devtools/merge_conductor.py b/devtools/merge_conductor.py
deleted file mode 100644
index d9944dae59..0000000000
--- a/devtools/merge_conductor.py
+++ /dev/null
@@ -1,453 +0,0 @@
-"""merge-conductor: mechanical-conflict triage for the PR merge train.
-
-Implements the MECHANICAL slice of the polylogue-ei94 merge-conductor design
-(state machine, admission vectors, review/gate triage). This command is
-deliberately narrower: given a roster of PR numbers, it classifies each PR's
-modified/conflicting files into conflict classes and reports a verdict --
-AUTO-RESOLVABLE, ESCALATE, or CLEAN. It does NOT triage code review findings,
-run the full admission state machine, or serialize Beads writes; those stay
-polylogue-ei94's scope.
-
-Conflict classes:
-
- - ``beads-jsonl`` -- .beads/issues.jsonl. Resolution: take master's
- side; bead state syncs separately. AUTO.
- - ``generated-surface`` -- known regenerable doc/plan artifacts (topology
- projection, CLI/MCP/devtools reference docs,
- OpenAPI, ...). Resolution: regenerate via
- `python -m devtools render ...`. AUTO.
- - ``schema-migration`` -- polylogue/storage/sqlite/migrations/** or
- polylogue/storage/sqlite/lifecycle.py. NEVER
- auto-resolved -- two PRs claiming the same
- durable-tier migration slot or lifecycle delta
- class nearly dropped a declaration on
- 2026-07-30. ESCALATE, always.
- - ``hooks-config`` -- .claude/ or .git*-prefixed hook/config paths.
- ESCALATE, always.
- - ``other`` -- everything else. ESCALATE by default: this
- tool's whole safety case is a short allowlist
- of provably-mechanical classes, not a guess
- about arbitrary code conflicts.
-
-Default is DRY-RUN: this command only classifies and reports. --execute is
-required to touch anything, and even then it only ever acts on PRs whose
-verdict is AUTO-RESOLVABLE -- ESCALATE-class PRs are never touched under
---execute, full stop. Every --execute step is wrapped so that ANY deviation
-(rebase conflict, render diff outside the expected surfaces, a failing
-`devtools verify --quick`) aborts that PR's automation, cleans up its scratch
-worktree, and marks it ESCALATE in the receipt instead of forcing a push.
-
-This tool must degrade to report-only on any subprocess failure (missing
-`gh`, network failure, auth failure, unexpected `gh` JSON shape) -- a broken
-signal should never be silently treated as "no conflict".
-
-Usage:
- devtools workspace merge-conductor --pr 3301 --pr 3302
- devtools workspace merge-conductor --pr 3301 --json
- devtools workspace merge-conductor --pr 3301 --execute
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import subprocess
-import sys
-from collections import defaultdict
-from collections.abc import Sequence
-from dataclasses import dataclass, field
-from pathlib import Path
-from typing import Any
-
-# ---------------------------------------------------------------------------
-# Conflict classification
-# ---------------------------------------------------------------------------
-
-BEADS_JSONL_PATH = ".beads/issues.jsonl"
-
-# Known regenerable doc/plan artifacts. Kept as an explicit allowlist rather
-# than a broad "anything under docs/" match -- most of docs/ is hand-authored
-# prose, and treating hand-authored docs as auto-resolvable would silently
-# discard a human's conflicting edit.
-_GENERATED_SURFACE_FILES: frozenset[str] = frozenset(
- {
- "docs/topology-status.md",
- "docs/cli-reference.md",
- "docs/devtools.md",
- "docs/mcp-reference.md",
- "docs/search.md",
- "docs/product/workflows.md",
- "docs/test-quality-workflows.md",
- "docs/README.md",
- "docs/openapi/search.yaml",
- "docs/generated/mcp-equivalence.json",
- "docs/plans/demo-corpus-construct-audit.md",
- }
-)
-_GENERATED_SURFACE_PREFIXES: tuple[str, ...] = (
- "docs/schemas/cli-output/",
- "docs/generated/",
-)
-
-_SCHEMA_MIGRATION_PREFIX = "polylogue/storage/sqlite/migrations/"
-_SCHEMA_LIFECYCLE_FILE = "polylogue/storage/sqlite/lifecycle.py"
-
-_HOOKS_CONFIG_PREFIXES: tuple[str, ...] = (".claude/", ".git")
-
-CONFLICT_CLASSES = (
- "beads-jsonl",
- "generated-surface",
- "schema-migration",
- "hooks-config",
- "other",
-)
-AUTO_RESOLVABLE_CLASSES = frozenset({"beads-jsonl", "generated-surface"})
-
-
-def classify_file(path: str) -> str:
- """Classify a single modified/conflicting file path into a conflict class."""
- if path == BEADS_JSONL_PATH:
- return "beads-jsonl"
- if path in _GENERATED_SURFACE_FILES or any(path.startswith(p) for p in _GENERATED_SURFACE_PREFIXES):
- return "generated-surface"
- if path.startswith(_SCHEMA_MIGRATION_PREFIX) or path == _SCHEMA_LIFECYCLE_FILE:
- return "schema-migration"
- if any(path.startswith(p) for p in _HOOKS_CONFIG_PREFIXES):
- return "hooks-config"
- return "other"
-
-
-# Classes that identify a *contention slot* worth naming across PRs even
-# though they're both ESCALATE individually -- a migration file touched by
-# two PRs in the same roster is the exact 2026-07-30 near-miss.
-_CONTENTION_CLASSES = frozenset({"schema-migration", "generated-surface"})
-
-
-# ---------------------------------------------------------------------------
-# PR data + classification
-# ---------------------------------------------------------------------------
-
-
-@dataclass
-class PRReport:
- number: int
- ok: bool
- error: str = ""
- title: str = ""
- head_ref: str = ""
- mergeable: str = ""
- merge_state_status: str = ""
- checks_summary: str = ""
- files: list[str] = field(default_factory=list)
- files_by_class: dict[str, list[str]] = field(default_factory=dict)
- verdict: str = "ESCALATE"
- escalation_files: list[str] = field(default_factory=list)
- execute_result: str = ""
-
-
-def _gh_json(args: list[str]) -> Any:
- result = subprocess.run(["gh", *args], capture_output=True, text=True, timeout=60)
- if result.returncode != 0:
- raise RuntimeError(result.stderr.strip()[:300] or f"gh {' '.join(args)} failed")
- return json.loads(result.stdout)
-
-
-def _fetch_pr_report(pr_number: int) -> PRReport:
- try:
- info = _gh_json(
- [
- "pr",
- "view",
- str(pr_number),
- "--json",
- "number,title,headRefName,mergeable,mergeStateStatus,statusCheckRollup",
- ]
- )
- except (RuntimeError, json.JSONDecodeError, OSError, subprocess.SubprocessError) as exc:
- return PRReport(number=pr_number, ok=False, error=f"gh pr view failed: {exc}")
-
- diff_result = subprocess.run(
- ["gh", "pr", "diff", str(pr_number), "--name-only"],
- capture_output=True,
- text=True,
- timeout=60,
- )
- if diff_result.returncode != 0:
- return PRReport(
- number=pr_number,
- ok=False,
- error=f"gh pr diff failed: {diff_result.stderr.strip()[:300]}",
- )
- files = [line for line in diff_result.stdout.splitlines() if line.strip()]
-
- checks = info.get("statusCheckRollup") or []
- check_states: dict[str, int] = defaultdict(int)
- for check in checks:
- state = check.get("state") or check.get("conclusion") or check.get("status") or "UNKNOWN"
- check_states[str(state).upper()] += 1
- checks_summary = ", ".join(f"{count} {state.lower()}" for state, count in sorted(check_states.items()))
- if not checks_summary:
- checks_summary = "no checks reported"
-
- files_by_class: dict[str, list[str]] = defaultdict(list)
- for f in files:
- files_by_class[classify_file(f)].append(f)
-
- escalation_files: list[str] = []
- for cls in CONFLICT_CLASSES:
- if cls not in AUTO_RESOLVABLE_CLASSES:
- escalation_files.extend(files_by_class.get(cls, []))
-
- if escalation_files:
- verdict = "ESCALATE"
- elif info.get("mergeable") == "CONFLICTING":
- verdict = "AUTO-RESOLVABLE"
- else:
- verdict = "CLEAN"
-
- return PRReport(
- number=pr_number,
- ok=True,
- title=info.get("title", ""),
- head_ref=info.get("headRefName", ""),
- mergeable=info.get("mergeable", "UNKNOWN"),
- merge_state_status=info.get("mergeStateStatus", "UNKNOWN"),
- checks_summary=checks_summary,
- files=files,
- files_by_class=dict(files_by_class),
- verdict=verdict,
- escalation_files=escalation_files,
- )
-
-
-def _find_contention(reports: list[PRReport]) -> list[dict[str, Any]]:
- """Cross-PR contention: two roster PRs touching the same contention-class file."""
- file_to_prs: dict[str, list[int]] = defaultdict(list)
- for r in reports:
- if not r.ok:
- continue
- for cls in _CONTENTION_CLASSES:
- for f in r.files_by_class.get(cls, []):
- file_to_prs[f].append(r.number)
- events: list[dict[str, Any]] = []
- for f, prs in file_to_prs.items():
- if len(prs) > 1:
- events.append(
- {
- "file": f,
- "class": classify_file(f),
- "prs": sorted(set(prs)),
- "recommendation": "serialize these PRs -- do not admit both concurrently",
- }
- )
- return events
-
-
-# ---------------------------------------------------------------------------
-# --execute: conservative scratch-worktree automation for AUTO-RESOLVABLE only
-# ---------------------------------------------------------------------------
-
-WORKTREE_ROOT = Path("/realm/worktrees")
-
-
-def _run(cmd: list[str], cwd: Path | None = None, timeout: int = 300) -> subprocess.CompletedProcess[str]:
- return subprocess.run(cmd, cwd=cwd, capture_output=True, text=True, timeout=timeout)
-
-
-def _execute_auto_resolve(report: PRReport, repo_root: Path) -> str:
- """Attempt the declared safe automation for one AUTO-RESOLVABLE PR.
-
- Returns a short outcome string. Any deviation aborts and cleans up --
- this function must never leave a dirty scratch worktree behind and must
- never push unless every declared step succeeded.
- """
- assert report.verdict == "AUTO-RESOLVABLE"
- scratch = WORKTREE_ROOT / f"merge-conductor-{report.number}"
- branch = f"merge-conductor-pr-{report.number}"
-
- def _abort(reason: str) -> str:
- report.verdict = "ESCALATE"
- report.escalation_files = list(report.files)
- if scratch.exists():
- _run(["git", "worktree", "remove", "--force", str(scratch)], cwd=repo_root)
- return f"ABORTED (auto-resolve deviated): {reason}"
-
- if scratch.exists():
- return _abort(f"scratch worktree {scratch} already exists -- refusing to reuse it")
-
- fetch = _run(["git", "fetch", "origin", report.head_ref, "master"], cwd=repo_root)
- if fetch.returncode != 0:
- return _abort(f"git fetch failed: {fetch.stderr.strip()[:200]}")
-
- add = _run(
- ["git", "worktree", "add", "-b", branch, str(scratch), f"origin/{report.head_ref}"],
- cwd=repo_root,
- )
- if add.returncode != 0:
- return _abort(f"git worktree add failed: {add.stderr.strip()[:200]}")
-
- rebase = _run(["git", "rebase", "origin/master"], cwd=scratch)
- if rebase.returncode != 0:
- _run(["git", "rebase", "--abort"], cwd=scratch)
- return _abort(f"rebase onto origin/master conflicted: {rebase.stderr.strip()[:200]}")
-
- # Resolve beads-jsonl by taking master's side, unconditionally.
- if "beads-jsonl" in report.files_by_class:
- show = _run(["git", "show", f"origin/master:{BEADS_JSONL_PATH}"], cwd=scratch)
- if show.returncode != 0:
- return _abort(f"could not read master's {BEADS_JSONL_PATH}: {show.stderr.strip()[:200]}")
- (scratch / BEADS_JSONL_PATH).write_text(show.stdout)
- add_beads = _run(["git", "add", BEADS_JSONL_PATH], cwd=scratch)
- if add_beads.returncode != 0:
- return _abort(f"git add {BEADS_JSONL_PATH} failed: {add_beads.stderr.strip()[:200]}")
-
- # Regenerate generated surfaces if any were in this PR's conflict set.
- if "generated-surface" in report.files_by_class:
- render = _run(["python", "-m", "devtools", "render", "all"], cwd=scratch, timeout=600)
- if render.returncode != 0:
- return _abort(f"devtools render all failed: {render.stderr.strip()[:200]}")
- add_gen = _run(["git", "add", *report.files_by_class["generated-surface"]], cwd=scratch)
- if add_gen.returncode != 0:
- return _abort(f"git add generated surfaces failed: {add_gen.stderr.strip()[:200]}")
-
- status = _run(["git", "status", "--porcelain"], cwd=scratch)
- if status.stdout.strip():
- commit = _run(["git", "commit", "-m", "chore(merge-conductor): auto-resolve mechanical conflicts"], cwd=scratch)
- if commit.returncode != 0:
- return _abort(f"commit of resolved files failed: {commit.stderr.strip()[:200]}")
-
- continue_rebase = _run(["git", "rebase", "--continue"], cwd=scratch)
- if continue_rebase.returncode != 0:
- _run(["git", "rebase", "--abort"], cwd=scratch)
- return _abort(f"rebase --continue failed: {continue_rebase.stderr.strip()[:200]}")
-
- verify = _run(["python", "-m", "devtools", "verify", "--quick"], cwd=scratch, timeout=900)
- if verify.returncode != 0:
- return _abort(f"devtools verify --quick failed: {verify.stdout[-300:]} {verify.stderr[-300:]}")
-
- push = _run(
- ["git", "push", "--force-with-lease", "origin", f"HEAD:{report.head_ref}"],
- cwd=scratch,
- timeout=120,
- )
- if push.returncode != 0:
- return _abort(f"push --force-with-lease failed: {push.stderr.strip()[:200]}")
-
- _run(["git", "worktree", "remove", "--force", str(scratch)], cwd=repo_root)
- return "RESOLVED and pushed"
-
-
-# ---------------------------------------------------------------------------
-# Output rendering
-# ---------------------------------------------------------------------------
-
-
-def _render_human(reports: list[PRReport], contention: list[dict[str, Any]], executed: bool) -> None:
- print("=" * 78)
- print("MERGE CONDUCTOR -- mechanical conflict triage" + (" (EXECUTED)" if executed else " (DRY RUN)"))
- print("=" * 78)
- print()
- header = f"{'PR':>6} {'mergeable':<12} {'verdict':<16} {'classes':<28} checks"
- print(header)
- print("-" * len(header))
- for r in reports:
- if not r.ok:
- print(f"{r.number:>6} ERROR: {r.error}")
- continue
- classes = ",".join(sorted(r.files_by_class)) or "(no files)"
- print(f"{r.number:>6} {r.mergeable:<12} {r.verdict:<16} {classes:<28} {r.checks_summary}")
- if r.execute_result:
- print(f" -> {r.execute_result}")
- if r.verdict == "ESCALATE" and r.escalation_files:
- for f in r.escalation_files:
- print(f" ESCALATE file: {f} [{classify_file(f)}]")
- print()
- if contention:
- print(f"-- CROSS-PR CONTENTION ({len(contention)}) --------------------------------------")
- for ev in contention:
- print(f" {ev['file']} [{ev['class']}] PRs: {ev['prs']}")
- print(f" -> {ev['recommendation']}")
- print()
- print(
- "Advisory: classification is mechanical only. schema-migration and hooks-config "
- "conflicts are NEVER auto-resolved."
- )
-
-
-def _report_to_dict(r: PRReport) -> dict[str, Any]:
- return {
- "number": r.number,
- "ok": r.ok,
- "error": r.error,
- "title": r.title,
- "head_ref": r.head_ref,
- "mergeable": r.mergeable,
- "merge_state_status": r.merge_state_status,
- "checks_summary": r.checks_summary,
- "files": r.files,
- "files_by_class": r.files_by_class,
- "verdict": r.verdict,
- "escalation_files": r.escalation_files,
- "execute_result": r.execute_result,
- }
-
-
-def _render_json(reports: list[PRReport], contention: list[dict[str, Any]]) -> None:
- out = {
- "prs": [_report_to_dict(r) for r in reports],
- "contention": contention,
- }
- json.dump(out, sys.stdout, indent=2)
- print()
-
-
-# ---------------------------------------------------------------------------
-# Main
-# ---------------------------------------------------------------------------
-
-
-def _repo_root() -> Path:
- result = subprocess.run(["git", "rev-parse", "--show-toplevel"], capture_output=True, text=True)
- if result.returncode == 0 and result.stdout.strip():
- return Path(result.stdout.strip())
- return Path.cwd()
-
-
-def main(argv: Sequence[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
- parser.add_argument("--pr", type=int, action="append", required=True, dest="prs", help="PR number (repeatable)")
- parser.add_argument("--json", action="store_true", dest="json_out", help="Machine-readable JSON output")
- parser.add_argument(
- "--execute",
- action="store_true",
- help=(
- "Actually resolve AUTO-RESOLVABLE PRs in a scratch worktree and push. "
- "ESCALATE-class PRs are never touched. Default is dry-run/report-only."
- ),
- )
- args = parser.parse_args(argv)
-
- reports = [_fetch_pr_report(pr) for pr in args.prs]
- contention = _find_contention(reports)
-
- if args.execute:
- repo_root = _repo_root()
- for r in reports:
- if r.ok and r.verdict == "AUTO-RESOLVABLE":
- try:
- r.execute_result = _execute_auto_resolve(r, repo_root)
- except (OSError, subprocess.SubprocessError, RuntimeError) as exc:
- r.verdict = "ESCALATE"
- r.escalation_files = list(r.files)
- r.execute_result = f"ABORTED (unexpected error): {exc}"
-
- if args.json_out:
- _render_json(reports, contention)
- else:
- _render_human(reports, contention, executed=args.execute)
-
- return 0
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/merge_gate.py b/devtools/merge_gate.py
index 427038007b..06870e491a 100644
--- a/devtools/merge_gate.py
+++ b/devtools/merge_gate.py
@@ -25,25 +25,18 @@
never actually tested (review-caught gap: recording from an unrelated
checkout, e.g. master or a stale worktree, previously produced a receipt
that ``check`` would accept).
- - ``check``: polls PR review comments across a real grace window (default
- 3 rounds x 20s, covering the 30-60s late-arrival window from incident 1)
+ - ``check``: polls GitHub's structured review-thread state across a real
+ grace window (default 3 rounds x 20s, covering the 30-60s late-arrival
+ window from incident 1)
before deciding. BLOCKs unless a receipt exists for the PR's *current*
head sha (not a stale one from an earlier push), was recorded within a
- freshness window, had exit code 0, and its command actually looks like it
- ran tests (a bare ``--quick`` profile is flagged, not silently accepted --
- review-caught gap: the documented example used exactly the profile that
- would have missed the PR #3517 regression). No review comment's
- ``created_at`` may be newer than the head commit's ``committedDate``
- unless it has been explicitly acknowledged via ``ack`` for this exact
- head sha (review-caught gap: without ``ack``, a stale-forever comparison
- made even a reviewed false positive permanently unmergeable without an
- empty commit).
-
-This does not replace judgment about *what* a late comment means -- ``ack``
-still requires a human/agent to have actually read it and decided it's not
-actionable. It makes the presence of an unverified late signal impossible to
-merge past silently, and impossible to permanently paper over without an
-explicit, current-head-scoped decision.
+ freshness window, had exit code 0, and emitted a typed verification scope
+ and release-baseline decision (command wording grants no authority). Every
+ review thread must be
+ resolved in GitHub and ``reviewDecision`` must not be
+ ``CHANGES_REQUESTED``. Review requests, review summaries,
+ acknowledgements, and ordinary PR conversation are not findings and do
+ not need a second local acknowledgement registry.
``check --post-status`` closes the remaining gap (2026-08-03,
polylogue-1cbeh): the verdict above is a purely local CLI result, so nothing
@@ -63,7 +56,6 @@
devtools workspace merge-gate check 3517
devtools workspace merge-gate check 3517 --json --max-age-s 7200 --poll-rounds 1
devtools workspace merge-gate check 3517 --post-status
- devtools workspace merge-gate ack 3517 --reason "false positive, already fixed upstream"
"""
from __future__ import annotations
@@ -91,13 +83,13 @@
_DEFAULT_MAX_AGE_S = 3600
_DEFAULT_POLL_ROUNDS = 3
_DEFAULT_POLL_INTERVAL_S = 20
-# Heuristic: profiles that explicitly skip tests (see CLAUDE.md -- `devtools
-# verify --quick` is format+lint+mypy+render, no pytest). Not exhaustive; a
-# command containing neither this nor an obvious test-runner name still gets
-# flagged as an advisory, since the whole point is not trusting a plausible-
-# looking command string without comment.
-_TEST_SKIPPING_MARKERS: tuple[str, ...] = ("verify --quick", "verify --lab")
-_LOOKS_LIKE_TESTS_MARKERS: tuple[str, ...] = ("test", "pytest", "verify --all", "devtools verify")
+_MERGE_AUTHORIZING_VERIFICATION_SCOPES = frozenset(
+ {
+ VerificationScope.AFFECTED.value,
+ VerificationScope.NARROW_TERMINAL.value,
+ VerificationScope.RELEASE_BASELINE.value,
+ }
+)
def _gh_json(args: list[str]) -> Any:
@@ -107,25 +99,6 @@ def _gh_json(args: list[str]) -> Any:
return json.loads(result.stdout)
-def _gh_json_paginated(args: list[str]) -> list[Any]:
- """Like ``_gh_json`` but follows pagination -- the GitHub REST list
- endpoints cap at 30-100 items per page, and a PR with more review comments
- than that would otherwise silently hide later (possibly late-arriving)
- ones from the late-comment check. ``--slurp`` wraps every page's own JSON
- array into one outer array, which this then flattens."""
- result = subprocess.run(["gh", *args, "--paginate", "--slurp"], capture_output=True, text=True, timeout=120)
- if result.returncode != 0:
- raise RuntimeError(result.stderr.strip()[:300] or f"gh {' '.join(args)} --paginate failed")
- pages = json.loads(result.stdout)
- items: list[Any] = []
- for page in pages:
- if isinstance(page, list):
- items.extend(page)
- else:
- items.append(page)
- return items
-
-
# GitHub commit-status `description` is truncated to 140 chars by the API
# itself; trim ourselves so the reported description matches what actually
# gets stored rather than being silently cut mid-word server-side.
@@ -134,7 +107,7 @@ def _gh_json_paginated(args: list[str]) -> list[Any]:
def _status_description(verdict: GateVerdict) -> str:
if verdict.ok:
- return "merge-gate OK: verification receipt fresh, no unacked late comments"
+ return "merge-gate OK: verification fresh, no unresolved review threads"
joined = "; ".join(verdict.reasons) or "merge-gate BLOCK"
if len(joined) > _STATUS_DESCRIPTION_MAX:
joined = joined[: _STATUS_DESCRIPTION_MAX - 1] + "…"
@@ -217,7 +190,7 @@ class GateVerdict:
reasons: list[str] = field(default_factory=list)
head_sha: str = ""
receipt: dict[str, Any] | None = None
- late_comments: list[dict[str, Any]] = field(default_factory=list)
+ unresolved_review_threads: list[dict[str, Any]] = field(default_factory=list)
status_post: dict[str, Any] | None = None
pr_scope: dict[str, Any] | None = None
@@ -226,17 +199,6 @@ def _receipt_path(pr: int) -> Path:
return _repository_root() / _RECEIPT_DIR / f"pr-{pr}.json"
-def _ack_path(pr: int) -> Path:
- return _repository_root() / _RECEIPT_DIR / f"pr-{pr}-acks.json"
-
-
-def _command_skips_tests(command: str) -> bool:
- lowered = command.lower()
- if any(marker in lowered for marker in _TEST_SKIPPING_MARKERS):
- return True
- return not any(marker in lowered for marker in _LOOKS_LIKE_TESTS_MARKERS)
-
-
def _invocation_receipt(
*,
path: Path,
@@ -246,7 +208,6 @@ def _invocation_receipt(
checkout_root: Path,
) -> dict[str, Any] | None:
"""Load the exact run artifact bound to the launched verifier process."""
-
try:
payload = json.loads(path.read_text(encoding="utf-8"))
except (OSError, UnicodeDecodeError, json.JSONDecodeError):
@@ -407,7 +368,6 @@ def cmd_record(pr: int, command: str) -> int:
)["attestation_digest"],
"branch": info["headRefName"],
"command": command,
- "skips_tests": _command_skips_tests(command),
"verification_scope": _verification_scope(verification_receipt),
"release_baseline_allowed": _release_baseline_permission(verification_receipt),
"terminal_authorization": _terminal_authorization(verification_receipt),
@@ -422,98 +382,112 @@ def cmd_record(pr: int, command: str) -> int:
receipt_path.write_text(json.dumps(receipt, indent=2))
print(f"recorded receipt for PR #{pr} @ {head_sha[:8]}: exit={result.returncode} ({duration_s}s)")
- if receipt["skips_tests"]:
- print(
- f" advisory: command {command!r} does not look like it ran tests -- `check` will flag this",
- file=sys.stderr,
- )
if result.returncode != 0:
print(result.stdout[-2000:])
print(result.stderr[-2000:], file=sys.stderr)
return result.returncode
-def cmd_ack(pr: int, comment_id: int, *, reason: str) -> int:
- info = _gh_json(["pr", "view", str(pr), "--json", "headRefOid"])
- head_sha = info["headRefOid"]
+_REVIEW_STATE_QUERY = """
+query($owner:String!,$repo:String!,$number:Int!,$endCursor:String) {
+ repository(owner:$owner,name:$repo) {
+ pullRequest(number:$number) {
+ reviewDecision
+ reviewThreads(first:100,after:$endCursor) {
+ nodes {
+ id
+ isResolved
+ isOutdated
+ comments(first:100) {
+ nodes { databaseId createdAt path line body }
+ }
+ }
+ pageInfo { hasNextPage endCursor }
+ }
+ }
+ }
+}
+"""
- ack_path = _ack_path(pr)
- if ack_path.exists():
- acks = _read_json_object(ack_path)
- if acks is None:
- print(
- f"REFUSING to ack: {ack_path} exists but is unreadable/corrupt -- fix or remove it by hand "
- "first, rather than silently losing prior acknowledgements.",
- file=sys.stderr,
- )
- return 2
- else:
- acks = {}
- acks[str(comment_id)] = {"head_sha": head_sha, "reason": reason, "acked_at": time.time()}
- ack_path.parent.mkdir(parents=True, exist_ok=True)
- ack_path.write_text(json.dumps(acks, indent=2))
- print(f"acknowledged comment {comment_id} on PR #{pr} @ {head_sha[:8]}: {reason}")
- return 0
-
-
-def _fetch_review_comments(pr: int) -> list[dict[str, Any]] | None:
- """Combine every top-level review signal the late-comment check should
- see: inline diff comments, issue-level PR comments, and review bodies
- (a review's own summary text is a separate object from its line
- comments -- see GitHub's REST API docs). All three are normalized to a
- common shape (id, created_at, path, line, body) and empty-bodied entries
- (e.g. an APPROVE review with no summary text) are dropped -- they carry
- no signal for triage."""
- normalized: list[dict[str, Any]] = []
+
+def _fetch_review_state(pr: int) -> dict[str, Any] | None:
+ """Return GitHub's typed review decision and every unresolved thread.
+
+ Conversation bodies are deliberately not classified. A finding is a
+ review thread; its disposition is GitHub's ``isResolved`` field. This
+ avoids treating review requests, bot summaries, and repair replies as new
+ findings merely because they are prose posted after a commit.
+ """
+ result = subprocess.run(
+ [
+ "gh",
+ "api",
+ "graphql",
+ "--paginate",
+ "--slurp",
+ "-F",
+ "owner={owner}",
+ "-F",
+ "repo={repo}",
+ "-F",
+ f"number={pr}",
+ "-f",
+ f"query={_REVIEW_STATE_QUERY}",
+ ],
+ capture_output=True,
+ text=True,
+ timeout=120,
+ )
+ if result.returncode != 0:
+ return None
try:
- inline = _gh_json_paginated(["api", f"repos/{{owner}}/{{repo}}/pulls/{pr}/comments"])
- for item in inline:
- normalized.append(
- {
- "id": item.get("id"),
- "created_at": item.get("created_at", ""),
- "path": item.get("path"),
- "line": item.get("line"),
- "body": item.get("body") or "",
- }
- )
- issue_comments = _gh_json_paginated(["api", f"repos/{{owner}}/{{repo}}/issues/{pr}/comments"])
- for item in issue_comments:
- normalized.append(
- {
- "id": item.get("id"),
- "created_at": item.get("created_at", ""),
- "path": None,
- "line": None,
- "body": item.get("body") or "",
- }
- )
- reviews = _gh_json_paginated(["api", f"repos/{{owner}}/{{repo}}/pulls/{pr}/reviews"])
- for item in reviews:
- normalized.append(
- {
- "id": item.get("id"),
- "created_at": item.get("submitted_at", ""),
- "path": None,
- "line": None,
- "body": item.get("body") or "",
- }
- )
- except (RuntimeError, json.JSONDecodeError, OSError, subprocess.SubprocessError):
+ pages = json.loads(result.stdout)
+ except json.JSONDecodeError:
+ return None
+ if not isinstance(pages, list) or not pages:
return None
- return [comment for comment in normalized if comment["body"].strip()]
-
-def _poll_stable_comments(pr: int, *, rounds: int, interval_s: int) -> list[dict[str, Any]] | None:
- """Poll review comments repeatedly so a comment posted 30-60s after CI
- goes green (the PR #3502 incident) is observed rather than missed by a
- single snapshot taken too early."""
- last: list[dict[str, Any]] | None = None
+ decision: str | None = None
+ unresolved: dict[str, dict[str, Any]] = {}
+ for page in pages:
+ try:
+ pull_request = page["data"]["repository"]["pullRequest"]
+ page_decision = pull_request.get("reviewDecision")
+ threads = pull_request["reviewThreads"]["nodes"]
+ except (KeyError, TypeError):
+ return None
+ if isinstance(page_decision, str):
+ decision = page_decision
+ if not isinstance(threads, list):
+ return None
+ for thread in threads:
+ if not isinstance(thread, dict) or thread.get("isResolved") is not False:
+ continue
+ thread_id = thread.get("id")
+ comments = thread.get("comments", {}).get("nodes", [])
+ if not isinstance(thread_id, str) or not isinstance(comments, list):
+ return None
+ last = comments[-1] if comments and isinstance(comments[-1], dict) else {}
+ unresolved[thread_id] = {
+ "thread_id": thread_id,
+ "is_outdated": bool(thread.get("isOutdated")),
+ "comment_id": last.get("databaseId"),
+ "path": last.get("path"),
+ "line": last.get("line"),
+ "created_at": last.get("createdAt"),
+ "body_head": str(last.get("body") or "")[:200],
+ }
+ return {"review_decision": decision, "unresolved_threads": list(unresolved.values())}
+
+
+def _poll_stable_review_state(pr: int, *, rounds: int, interval_s: int) -> dict[str, Any] | None:
+ """Poll typed review state so findings arriving after CI are observed."""
+ last: dict[str, Any] | None = None
for round_index in range(max(1, rounds)):
- comments = _fetch_review_comments(pr)
- if comments is None:
+ review_state = _fetch_review_state(pr)
+ if review_state is None:
return None
- last = comments
+ last = review_state
if round_index < rounds - 1:
time.sleep(interval_s)
return last
@@ -537,7 +511,7 @@ def cmd_check(
"view",
str(pr),
"--json",
- "headRefOid,baseRefOid,mergeStateStatus,state,commits,body,isDraft,author,files",
+ "headRefOid,baseRefOid,mergeStateStatus,state,body,isDraft,author,files",
]
)
except (RuntimeError, json.JSONDecodeError, OSError, subprocess.SubprocessError) as exc:
@@ -584,10 +558,6 @@ def cmd_check(
verdict.ok = False
verdict.reasons.append(f"mergeStateStatus is {mss!r} (expected CLEAN/UNSTABLE/UNKNOWN)")
- commits = info.get("commits") or []
- head_commit = next((commit for commit in commits if commit.get("oid") == head_sha), None)
- head_committed_at = head_commit.get("committedDate") if head_commit else None
-
receipt_path = _receipt_path(pr)
receipt = _read_json_object(receipt_path)
if receipt is None:
@@ -648,6 +618,9 @@ def cmd_check(
verdict.reasons.append(
"verification receipt lacks a valid typed verification_scope; command text cannot grant authority"
)
+ elif verification_scope not in _MERGE_AUTHORIZING_VERIFICATION_SCOPES:
+ verdict.ok = False
+ verdict.reasons.append("verification receipt contains no test execution and cannot authorize a merge")
release_allowed = receipt.get("release_baseline_allowed")
if not isinstance(release_allowed, bool):
verdict.ok = False
@@ -657,50 +630,22 @@ def cmd_check(
verdict.reasons.append(
"release-baseline verification receipt does not grant release_baseline_allowed=true"
)
- if receipt.get("skips_tests"):
- verdict.reasons.append(
- f"advisory: receipt command {receipt.get('command')!r} does not look like it ran tests "
- "-- confirm this PR genuinely needs no test coverage before merging"
- )
- review_comments = _poll_stable_comments(pr, rounds=poll_rounds, interval_s=poll_interval_s)
- if review_comments is None:
+ review_state = _poll_stable_review_state(pr, rounds=poll_rounds, interval_s=poll_interval_s)
+ if review_state is None:
verdict.ok = False
- verdict.reasons.append("could not fetch review comments after polling")
- review_comments = []
-
- acks = _read_json_object(_ack_path(pr)) or {}
-
- if head_committed_at:
- for comment in review_comments:
- created_at = comment.get("created_at", "")
- if created_at <= head_committed_at:
- continue
- comment_id = comment.get("id")
- ack = acks.get(str(comment_id))
- if ack is not None and ack.get("head_sha") == head_sha:
- continue # explicitly triaged for this exact head sha
- verdict.late_comments.append(
- {
- "id": comment_id,
- "path": comment.get("path"),
- "line": comment.get("line"),
- "created_at": created_at,
- "body_head": (comment.get("body") or "")[:200],
- }
- )
- if verdict.late_comments:
+ verdict.reasons.append("could not fetch structured review-thread state after polling")
+ else:
+ verdict.unresolved_review_threads = review_state["unresolved_threads"]
+ if verdict.unresolved_review_threads:
verdict.ok = False
verdict.reasons.append(
- f"{len(verdict.late_comments)} unacknowledged review comment(s) posted after the head commit "
- f"({head_committed_at}) -- read and `ack` (if not actionable) or fix before merging"
+ f"{len(verdict.unresolved_review_threads)} unresolved GitHub review thread(s) -- "
+ "fix or explicitly resolve each thread before merging"
)
- else:
- verdict.ok = False
- verdict.reasons.append(
- "could not determine the head commit timestamp, so the late-comment check cannot run -- "
- "refusing to report OK"
- )
+ if review_state["review_decision"] == "CHANGES_REQUESTED":
+ verdict.ok = False
+ verdict.reasons.append("GitHub reviewDecision is CHANGES_REQUESTED")
if post_status:
verdict.status_post = _post_commit_status(
@@ -720,9 +665,10 @@ def _emit(verdict: GateVerdict, as_json: bool) -> None:
print(f"PR #{verdict.pr} @ {verdict.head_sha[:8] if verdict.head_sha else '?'}: {'OK' if verdict.ok else 'BLOCK'}")
for reason in verdict.reasons:
print(f" - {reason}")
- for late in verdict.late_comments:
+ for thread in verdict.unresolved_review_threads:
print(
- f" late comment id={late['id']} [{late['path']}:{late['line']}] {late['created_at']}: {late['body_head']}"
+ f" unresolved thread {thread['thread_id']} [{thread['path']}:{thread['line']}] "
+ f"{thread['created_at']}: {thread['body_head']}"
)
if verdict.status_post is not None:
if verdict.status_post.get("posted"):
@@ -759,17 +705,10 @@ def main(argv: list[str] | None = None) -> int:
),
)
- ack_p = sub.add_parser("ack", help="Acknowledge a specific review comment as triaged for the current head sha")
- ack_p.add_argument("pr", type=int)
- ack_p.add_argument("comment_id", type=int)
- ack_p.add_argument("--reason", required=True, help="Why this comment does not block merging")
-
args = parser.parse_args(argv)
if args.action == "record":
return cmd_record(args.pr, args.command)
- if args.action == "ack":
- return cmd_ack(args.pr, args.comment_id, reason=args.reason)
return cmd_check(
args.pr,
max_age_s=args.max_age_s,
diff --git a/devtools/mutation_catalog.py b/devtools/mutation_catalog.py
deleted file mode 100644
index 6d25b55eb6..0000000000
--- a/devtools/mutation_catalog.py
+++ /dev/null
@@ -1,17 +0,0 @@
-"""Mutation-campaign catalog shared across control-plane surfaces."""
-
-from __future__ import annotations
-
-from .mutation_scenario_catalog import MUTATION_CAMPAIGNS, MutationCampaign
-
-MutationCampaignEntry = MutationCampaign
-
-
-def build_mutation_entries() -> tuple[MutationCampaignEntry, ...]:
- return tuple(sorted(MUTATION_CAMPAIGNS.values(), key=lambda item: item.name))
-
-
-__all__ = [
- "MutationCampaignEntry",
- "build_mutation_entries",
-]
diff --git a/devtools/mutation_scenario_catalog.py b/devtools/mutation_scenario_catalog.py
index 2b6f718e8d..9a0017ebc8 100644
--- a/devtools/mutation_scenario_catalog.py
+++ b/devtools/mutation_scenario_catalog.py
@@ -128,7 +128,6 @@ def projection_source_kind(self) -> ScenarioProjectionSourceKind:
paths_to_mutate=(
"polylogue/cli/query.py",
"polylogue/archive/query/plan.py",
- "polylogue/cli/query_actions.py",
"polylogue/cli/query_output.py",
),
tests=(
diff --git a/devtools/mutmut_campaign.py b/devtools/mutmut_campaign.py
index b7d7b8e327..39b178106c 100644
--- a/devtools/mutmut_campaign.py
+++ b/devtools/mutmut_campaign.py
@@ -27,33 +27,24 @@
from devtools import repo_root as _get_root
-from .authored_scenario_catalog import get_authored_scenario_catalog
-from .mutation_catalog import MutationCampaignEntry
-from .verify_mutation_freshness import (
- MANIFEST as _FRESHNESS_MANIFEST,
-)
+from .mutation_scenario_catalog import MUTATION_CAMPAIGNS, MutationCampaign
from .verify_mutation_freshness import (
assess_campaign as _freshness_assess,
)
-from .verify_mutation_freshness import (
- load_manifest as _freshness_load_manifest,
-)
ROOT = _get_root()
CAMPAIGN_ARTIFACT_DIR = Path(".local/mutation-campaigns")
-def default_artifact_paths(campaign_name: str, created_at: datetime) -> tuple[Path, Path]:
- """Default JSON/Markdown artifact paths for a campaign run.
+def default_artifact_path(campaign_name: str, created_at: datetime) -> Path:
+ """Return the default JSON artifact path for a campaign run.
- Layout: ``.local/mutation-campaigns//.{json,md}``.
- Used by ``mutmut-campaign run`` when ``--json-out`` / ``--markdown-out``
- are not supplied, and consumed by ``verify-mutation-freshness`` and
- ``mutmut-campaign status`` to locate the per-campaign artifact history.
+ Layout: ``.local/mutation-campaigns//.json``. It is
+ consumed by ``verify-mutation-freshness`` and ``mutmut-campaign status``.
"""
stamp = created_at.strftime("%Y%m%dT%H%M%SZ")
base = CAMPAIGN_ARTIFACT_DIR / campaign_name / stamp
- return base.with_suffix(".json"), base.with_suffix(".md")
+ return base.with_suffix(".json")
STATUS_IGNORE_PREFIXES = (f"{CAMPAIGN_ARTIFACT_DIR.as_posix()}/",)
@@ -67,7 +58,7 @@ def default_artifact_paths(campaign_name: str, created_at: datetime) -> tuple[Pa
"__pycache__",
".claude",
)
-CAMPAIGNS = get_authored_scenario_catalog().mutation_campaign_index()
+CAMPAIGNS = MUTATION_CAMPAIGNS
@dataclass(frozen=True)
@@ -278,210 +269,17 @@ def summarize_mutmut_results(
)
-def format_markdown(result: CampaignResult) -> str:
- def render_table(rows: list[tuple[str, int]]) -> str:
- if not rows:
- return "| Function | Count |\n| --- | ---: |\n| _none_ | 0 |"
- body = "\n".join(f"| `{name}` | {count} |" for name, count in rows)
- return f"| Function | Count |\n| --- | ---: |\n{body}"
-
- lines = [
- f"# Mutmut Campaign: `{result.campaign}`",
- "",
- f"- Recorded on `{result.created_at}`",
- f"- Commit: `{result.commit}`",
- f"- Worktree dirty: `{'yes' if result.worktree_dirty else 'no'}`",
- f"- Description: {result.description}",
- f"- Workspace: `{result.workspace}`",
- f"- Command: `{' '.join(result.command)}`",
- "",
- "## Scope",
- "",
- f"- Mutated paths: {', '.join(f'`{path}`' for path in result.paths_to_mutate)}",
- f"- Selected tests: {', '.join(f'`{path}`' for path in result.tests)}",
- ]
- if result.path_targets or result.artifact_targets or result.operation_targets or result.tags:
- lines.extend(["", "## Scenario Metadata", ""])
- lines.append(f"- Origin: `{result.origin}`")
- if result.path_targets:
- lines.append(f"- Path targets: `{', '.join(result.path_targets)}`")
- if result.artifact_targets:
- lines.append(f"- Artifact targets: `{', '.join(result.artifact_targets)}`")
- if result.operation_targets:
- lines.append(f"- Operation targets: `{', '.join(result.operation_targets)}`")
- if result.tags:
- lines.append(f"- Tags: `{', '.join(result.tags)}`")
- lines.extend(
- [
- "",
- "## Counts",
- "",
- "| Status | Count |",
- "| --- | ---: |",
- f"| Killed | {result.counts.get('killed', 0)} |",
- f"| Survived | {result.counts.get('survived', 0)} |",
- f"| Timeout | {result.counts.get('timeout', 0)} |",
- f"| Not checked | {result.counts.get('not_checked', 0)} |",
- f"| Suspicious | {result.counts.get('suspicious', 0)} |",
- f"| Skipped | {result.counts.get('skipped', 0)} |",
- "",
- f"- Runtime: `{result.runtime_seconds:.2f}s`",
- f"- Exit code: `{result.exit_code}`",
- "",
- "## Dominant Survivors",
- "",
- render_table(result.dominant_survivors),
- "",
- "## Dominant Timeouts",
- "",
- render_table(result.dominant_timeouts),
- "",
- "## Dominant Not-Checked Clusters",
- "",
- render_table(result.dominant_not_checked),
- ]
- )
- if result.survivor_keys:
- lines.extend(
- [
- "",
- "## Survivor Keys",
- "",
- ]
- )
- lines.extend(f"- `{key}`" for key in result.survivor_keys[:25])
- if len(result.survivor_keys) > 25:
- lines.append(f"- ... {len(result.survivor_keys) - 25} more")
- if result.timeout_keys:
- lines.extend(
- [
- "",
- "## Timeout Keys",
- "",
- ]
- )
- lines.extend(f"- `{key}`" for key in result.timeout_keys[:25])
- if len(result.timeout_keys) > 25:
- lines.append(f"- ... {len(result.timeout_keys) - 25} more")
- if result.not_checked_keys:
- lines.extend(
- [
- "",
- "## Not-Checked Keys",
- "",
- ]
- )
- lines.extend(f"- `{key}`" for key in result.not_checked_keys[:25])
- if len(result.not_checked_keys) > 25:
- lines.append(f"- ... {len(result.not_checked_keys) - 25} more")
- if result.status_summary:
- lines.extend(["", "## Source Worktree Status", ""])
- lines.extend(f"- `{line}`" for line in result.status_summary[:50])
- if len(result.status_summary) > 50:
- lines.append(f"- ... {len(result.status_summary) - 50} more")
- if result.notes:
- lines.extend(["", "## Notes", ""])
- lines.extend(f"- {note}" for note in result.notes)
- lines.append("")
- return "\n".join(lines)
-
-
-def load_results(campaign_dir: Path) -> list[CampaignResult]:
- results: list[CampaignResult] = []
- for path in sorted(campaign_dir.glob("*.json")):
- payload = json.loads(path.read_text())
- result = CampaignResult(
- campaign=payload["campaign"],
- description=payload["description"],
- commit=payload["commit"],
- worktree_dirty=bool(payload.get("worktree_dirty", False)),
- status_summary=list(payload.get("status_summary", [])),
- created_at=payload["created_at"],
- workspace=payload["workspace"],
- command=list(payload["command"]),
- paths_to_mutate=list(payload["paths_to_mutate"]),
- tests=list(payload["tests"]),
- counts=dict(payload["counts"]),
- dominant_survivors=[tuple(item) for item in payload["dominant_survivors"]],
- dominant_timeouts=[tuple(item) for item in payload["dominant_timeouts"]],
- dominant_not_checked=[tuple(item) for item in payload["dominant_not_checked"]],
- survivor_keys=list(payload.get("survivor_keys", [])),
- timeout_keys=list(payload.get("timeout_keys", [])),
- not_checked_keys=list(payload.get("not_checked_keys", [])),
- runtime_seconds=float(payload["runtime_seconds"]),
- exit_code=int(payload["exit_code"]),
- notes=list(payload.get("notes", [])),
- origin=str(payload.get("origin", "authored")),
- path_targets=list(payload.get("path_targets", [])),
- artifact_targets=list(payload.get("artifact_targets", [])),
- operation_targets=list(payload.get("operation_targets", [])),
- tags=list(payload.get("tags", [])),
- )
- results.append(result)
- return results
-
-
-def latest_results_by_campaign(results: list[CampaignResult]) -> list[CampaignResult]:
- latest: dict[str, CampaignResult] = {}
- for result in results:
- existing = latest.get(result.campaign)
- if existing is None or result.created_at > existing.created_at:
- latest[result.campaign] = result
- return sorted(latest.values(), key=lambda result: result.campaign)
-
-
-def format_index(results: list[CampaignResult]) -> str:
- latest = latest_results_by_campaign(results)
- lines = [
- "# Mutation Campaign Index",
- "",
- "Latest recorded artifact per campaign.",
- "",
- "| Campaign | Recorded | Commit | Killed | Survived | Timeout | Not checked | Dirty | Runtime |",
- "| --- | --- | --- | ---: | ---: | ---: | ---: | --- | ---: |",
- ]
- for result in latest:
- lines.append(
- "| "
- f"`{result.campaign}` | "
- f"`{result.created_at}` | "
- f"`{result.commit[:12]}` | "
- f"{result.counts.get('killed', 0)} | "
- f"{result.counts.get('survived', 0)} | "
- f"{result.counts.get('timeout', 0)} | "
- f"{result.counts.get('not_checked', 0)} | "
- f"{'yes' if result.worktree_dirty else 'no'} | "
- f"{result.runtime_seconds:.2f}s |"
- )
- lines.extend(
- [
- "",
- "## Notes",
- "",
- "- Artifacts live in this directory as per-campaign JSON and Markdown files.",
- "- `Dirty` reflects non-artifact worktree changes in the source repository at campaign start.",
- "- Use `devtools bench mutation list` to inspect available campaign scopes.",
- ]
- )
- lines.append("")
- return "\n".join(lines)
-
-
-def write_artifacts(result: CampaignResult, *, json_out: Path | None, markdown_out: Path | None) -> None:
+def write_json_artifact(result: CampaignResult, *, json_out: Path | None) -> None:
if json_out is not None:
json_out.parent.mkdir(parents=True, exist_ok=True)
json_out.write_text(json.dumps(asdict(result), indent=2) + "\n")
- if markdown_out is not None:
- markdown_out.parent.mkdir(parents=True, exist_ok=True)
- markdown_out.write_text(format_markdown(result))
def run_campaign(
- campaign: MutationCampaignEntry,
+ campaign: MutationCampaign,
*,
repo_root: Path,
json_out: Path | None,
- markdown_out: Path | None,
keep_workspace: bool,
) -> CampaignResult:
commit = git_commit_sha(repo_root)
@@ -558,7 +356,7 @@ def run_campaign(
operation_targets=list(campaign.operation_targets),
tags=list(campaign.tags or ("mutation",)),
)
- write_artifacts(result, json_out=json_out, markdown_out=markdown_out)
+ write_json_artifact(result, json_out=json_out)
return result
finally:
if temp_dir_obj is not None:
@@ -575,36 +373,22 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
run_parser = subparsers.add_parser("run", help="Run one isolated mutation campaign")
run_parser.add_argument("campaign", choices=sorted(CAMPAIGNS))
run_parser.add_argument("--json-out", type=Path)
- run_parser.add_argument("--markdown-out", type=Path)
run_parser.add_argument("--keep-workspace", action="store_true")
run_parser.set_defaults(command_fn=cmd_run)
status_parser = subparsers.add_parser(
"status",
- help="Show per-campaign last-run, kill rate, and freshness against docs/plans/campaign-coverage.yaml.",
+ help="Show per-campaign last-run, kill rate, and freshness from the executable catalog.",
)
status_parser.add_argument("--json", action="store_true")
status_parser.add_argument(
"--default-freshness-days",
type=int,
default=60,
- help="Freshness budget for manifest entries without freshness_days (default 60).",
+ help="Freshness budget for campaign artifacts (default 60).",
)
status_parser.set_defaults(command_fn=cmd_status)
- index_parser = subparsers.add_parser("index", help="Build an index over recorded campaign artifacts")
- index_parser.add_argument(
- "--campaign-dir",
- type=Path,
- default=ROOT / CAMPAIGN_ARTIFACT_DIR,
- )
- index_parser.add_argument(
- "--out",
- type=Path,
- default=ROOT / CAMPAIGN_ARTIFACT_DIR / "README.md",
- )
- index_parser.set_defaults(command_fn=cmd_index)
-
return parser.parse_args(argv)
@@ -621,49 +405,32 @@ def cmd_list(_args: argparse.Namespace) -> int:
def cmd_run(args: argparse.Namespace) -> int:
campaign = CAMPAIGNS[args.campaign]
- json_out: Path | None
- markdown_out: Path | None
- if args.json_out is None and args.markdown_out is None:
+ if args.json_out is None:
# Default per-campaign artifact layout so freshness lint and status
- # readouts always have something to discover. Operators can still
- # override with explicit --json-out / --markdown-out.
- default_json, default_md = default_artifact_paths(campaign.name, datetime.now(UTC))
- json_out = ROOT / default_json
- markdown_out = ROOT / default_md
+ # readouts always have something to discover.
+ json_out = ROOT / default_artifact_path(campaign.name, datetime.now(UTC))
else:
- json_out = (
- None if args.json_out is None else (args.json_out if args.json_out.is_absolute() else ROOT / args.json_out)
- )
- markdown_out = (
- None
- if args.markdown_out is None
- else (args.markdown_out if args.markdown_out.is_absolute() else ROOT / args.markdown_out)
- )
+ json_out = args.json_out if args.json_out.is_absolute() else ROOT / args.json_out
result = run_campaign(
campaign,
repo_root=ROOT,
json_out=json_out,
- markdown_out=markdown_out,
keep_workspace=args.keep_workspace,
)
- print(format_markdown(result))
+ print(json.dumps(asdict(result), indent=2))
return result.exit_code
def cmd_status(args: argparse.Namespace) -> int:
- manifest = _freshness_load_manifest(_FRESHNESS_MANIFEST)
- raw_entries = manifest.get("mutation_campaigns") or []
- entries: list[object] = list(raw_entries) if isinstance(raw_entries, list) else []
now = datetime.now(UTC)
assessments = [
_freshness_assess(
- entry,
+ campaign.name,
repo_root=ROOT,
now=now,
- default_freshness_days=args.default_freshness_days,
+ freshness_days=args.default_freshness_days,
)
- for entry in entries
- if isinstance(entry, dict) and "name" in entry
+ for campaign in CAMPAIGNS.values()
]
if args.json:
json.dump(
@@ -684,17 +451,6 @@ def cmd_status(args: argparse.Namespace) -> int:
return 0
-def cmd_index(args: argparse.Namespace) -> int:
- campaign_dir = args.campaign_dir if args.campaign_dir.is_absolute() else ROOT / args.campaign_dir
- out = args.out if args.out.is_absolute() else ROOT / args.out
- results = load_results(campaign_dir)
- rendered = format_index(results)
- out.parent.mkdir(parents=True, exist_ok=True)
- out.write_text(rendered)
- print(rendered)
- return 0
-
-
def main(argv: list[str] | None = None) -> int:
args = parse_args(argv)
return int(args.command_fn(args))
diff --git a/devtools/pr_scope.py b/devtools/pr_scope.py
index e1a5654a0a..721ffeec5a 100644
--- a/devtools/pr_scope.py
+++ b/devtools/pr_scope.py
@@ -131,6 +131,15 @@ def load_bead_records(path: Path = _BEADS_PATH) -> dict[str, dict[str, Any]]:
return _parse_bead_records(path.read_text(encoding="utf-8").splitlines(), line_label="line")
+def load_committed_bead_records() -> dict[str, dict[str, Any]]:
+ """Load the exact HEAD Bead snapshot without invoking ``bd``.
+
+ Callers whose authorization depends on tracker state need Git's committed
+ object rather than a mutable worktree file or Beads' shared Dolt state.
+ """
+ return _bead_records_at(_git_head_sha())
+
+
def canonical_beads_digest(
records: dict[str, dict[str, Any]], bead_ids: list[str], *, carrier_version: int = _V1
) -> str:
diff --git a/devtools/pre_push_gate.py b/devtools/pre_push_gate.py
index 8139eb5f0a..6489b0ed99 100644
--- a/devtools/pre_push_gate.py
+++ b/devtools/pre_push_gate.py
@@ -96,16 +96,9 @@ def _run(command: list[str], *, cwd: Path) -> None:
def run_gate(updates: list[PushUpdate], *, cwd: Path) -> str:
paths = changed_paths(updates, cwd=cwd)
if is_beads_only(paths):
- print("pre-push: Beads-only diff; checking JSONL and dependency graph.", file=sys.stderr)
+ print("pre-push: Beads-only diff; checking the structured dependency graph.", file=sys.stderr)
_run(
- [
- sys.executable,
- "-m",
- *control_plane_argv("lab policy backlog-hygiene"),
- "--checks",
- "D1,D2",
- ".beads/issues.jsonl",
- ],
+ [sys.executable, "-m", *control_plane_argv("lab policy bead-graph", "--export", ".beads/issues.jsonl")],
cwd=cwd,
)
return "beads"
diff --git a/devtools/preflight_ledger.py b/devtools/preflight_ledger.py
deleted file mode 100644
index 67dc5ac0bc..0000000000
--- a/devtools/preflight_ledger.py
+++ /dev/null
@@ -1,569 +0,0 @@
-"""Read-only live-archive preflight ledger.
-
-This module is deliberately a projection, not a repair command. It reads the
-durable relations used by deployed status and keeps terminal census verdicts,
-actionable parser failures, and absent census coverage distinct.
-"""
-
-from __future__ import annotations
-
-import sqlite3
-from datetime import UTC, datetime
-from pathlib import Path
-
-from polylogue.config import Config
-from polylogue.storage.archive_readiness import probe_archive_tier, raw_materialization_readiness_snapshot
-from polylogue.storage.fts.fts_lifecycle import fts_invariant_snapshot_sync
-from polylogue.storage.raw_failure_lifecycle import read_raw_failure_lifecycle
-from polylogue.storage.raw_retention import raw_frontier_integrity_projection
-from polylogue.storage.repair import raw_materialization_replay_backlog
-from polylogue.storage.sqlite.archive_tiers.types import ArchiveTier
-from polylogue.storage.sqlite.connection_profile import open_readonly_connection
-
-PREFLIGHT_REPORT_VERSION = 1
-_REQUIRED_RAW_COLUMNS = frozenset(
- {"raw_id", "origin", "blob_size", "parse_error", "validation_status", "revision_authority"}
-)
-_REQUIRED_CENSUS_COLUMNS = frozenset({"raw_id", "status", "member_count"})
-_REQUIRED_CURSOR_COLUMNS = frozenset(
- {"source_path", "origin", "stat_size", "byte_offset", "failure_count", "next_retry_at", "excluded"}
-)
-_VALID_DEBT_STATUSES = frozenset({"failed", "deferred"})
-
-
-def _gib(size_bytes: int) -> float:
- return round(size_bytes / (1024**3), 3)
-
-
-def _count(value: object) -> int:
- return 0 if value is None else int(str(value))
-
-
-def _size_evidence(size_bytes: int) -> dict[str, object]:
- gib = _gib(size_bytes)
- return {"bytes": size_bytes, "gib": gib, "display": f"{gib:.1f}GiB"}
-
-
-def _status(*, state: str, reason: str | None = None, **evidence: object) -> dict[str, object]:
- payload: dict[str, object] = {"state": state}
- if reason is not None:
- payload["reason"] = reason
- payload.update(evidence)
- return payload
-
-
-def _table_columns(conn: sqlite3.Connection, table: str) -> frozenset[str]:
- rows = conn.execute("SELECT name FROM pragma_table_info(?)", (table,)).fetchall()
- return frozenset(str(row[0]) for row in rows)
-
-
-def _relation_error(relation: str, exc: Exception) -> dict[str, object]:
- return _status(state="unknown", reason=f"{relation} unavailable: {exc}", available=False)
-
-
-def _schema_preflight(root: Path) -> dict[str, object]:
- tiers: dict[str, object] = {}
- blocking: list[str] = []
- for tier in ArchiveTier:
- probe = probe_archive_tier(tier, root / f"{tier.value}.db")
- tiers[tier.value] = {
- "exists": probe.exists,
- "user_version": probe.user_version,
- "expected_user_version": probe.expected_user_version,
- "version_status": probe.version_status,
- }
- if not probe.exists or probe.version_status != "ok":
- blocking.append(tier.value)
- return _status(
- state="pass" if not blocking else "fail",
- reason=None if not blocking else "archive tier schema is missing or mismatched",
- available=True,
- schema_mismatches=blocking,
- tiers=tiers,
- )
-
-
-def _source_distribution(root: Path) -> dict[str, object]:
- source_db = root / "source.db"
- if not source_db.exists():
- return _relation_error("source.db", FileNotFoundError(source_db))
- try:
- conn = open_readonly_connection(source_db)
- try:
- raw_columns = _table_columns(conn, "raw_sessions")
- census_columns = _table_columns(conn, "raw_membership_census")
- missing_raw = sorted(_REQUIRED_RAW_COLUMNS - raw_columns)
- missing_census_columns = sorted(_REQUIRED_CENSUS_COLUMNS - census_columns)
- if missing_raw or missing_census_columns:
- missing = ", ".join(
- [
- *(f"raw_sessions.{column}" for column in missing_raw),
- *(f"raw_membership_census.{column}" for column in missing_census_columns),
- ]
- )
- return _status(
- state="unknown",
- reason=f"required source relation columns missing: {missing}",
- available=False,
- )
- rows = conn.execute(
- """
- WITH classified AS (
- SELECT r.origin, r.blob_size, r.revision_authority, r.parse_error,
- LOWER(COALESCE(r.validation_status, '')) AS validation_status,
- c.status AS census_status,
- CASE WHEN c.raw_id IS NULL THEN 1 ELSE 0 END AS coverage_unknown,
- CASE WHEN c.status IN ('failed', 'non_session') THEN 1 ELSE 0 END AS terminal,
- CASE WHEN r.parse_error IS NOT NULL
- OR LOWER(COALESCE(r.validation_status, '')) = 'failed'
- THEN 1 ELSE 0 END AS failure,
- CASE WHEN c.status = 'complete' AND c.member_count > 0 THEN 1 ELSE 0 END AS census_eligible
- FROM raw_sessions AS r
- LEFT JOIN raw_membership_census AS c ON c.raw_id = r.raw_id
- )
- SELECT origin, COUNT(*), COALESCE(SUM(blob_size), 0),
- COALESCE(SUM(parse_error IS NOT NULL), 0),
- COALESCE(SUM(validation_status = 'failed'), 0),
- COALESCE(SUM(revision_authority = 'quarantined'), 0),
- COALESCE(SUM(CASE WHEN revision_authority = 'quarantined' THEN blob_size ELSE 0 END), 0),
- COALESCE(SUM(coverage_unknown), 0),
- COALESCE(SUM(CASE WHEN coverage_unknown = 1 THEN blob_size ELSE 0 END), 0),
- COALESCE(SUM(CASE WHEN coverage_unknown = 0 AND terminal = 1 THEN 1 ELSE 0 END), 0),
- COALESCE(SUM(CASE WHEN coverage_unknown = 0 AND terminal = 1 THEN blob_size ELSE 0 END), 0),
- COALESCE(SUM(CASE WHEN coverage_unknown = 0 AND terminal = 0 AND failure = 1 THEN 1 ELSE 0 END), 0),
- COALESCE(SUM(CASE WHEN coverage_unknown = 0 AND terminal = 0 AND failure = 1 THEN blob_size ELSE 0 END), 0),
- COALESCE(SUM(CASE WHEN coverage_unknown = 0 AND terminal = 0 AND failure = 0
- AND revision_authority = 'quarantined' THEN 1 ELSE 0 END), 0),
- COALESCE(SUM(CASE WHEN coverage_unknown = 0 AND terminal = 0 AND failure = 0
- AND revision_authority = 'quarantined' THEN blob_size ELSE 0 END), 0),
- COALESCE(SUM(CASE WHEN coverage_unknown = 0 AND terminal = 0 AND failure = 0
- AND revision_authority != 'quarantined' AND census_eligible = 1 THEN 1 ELSE 0 END), 0),
- COALESCE(SUM(CASE WHEN coverage_unknown = 0 AND terminal = 0 AND failure = 0
- AND revision_authority != 'quarantined' AND census_eligible = 1
- THEN blob_size ELSE 0 END), 0)
- FROM classified
- GROUP BY origin
- ORDER BY COUNT(*) DESC, origin
- """
- ).fetchall()
- totals = conn.execute(
- """
- SELECT COUNT(*), COALESCE(SUM(blob_size), 0),
- COALESCE(SUM(parse_error IS NOT NULL), 0),
- COALESCE(SUM(LOWER(COALESCE(validation_status, '')) = 'failed'), 0),
- COALESCE(SUM(revision_authority = 'quarantined'), 0),
- COALESCE(SUM(CASE WHEN revision_authority = 'quarantined' THEN blob_size ELSE 0 END), 0),
- COALESCE(SUM(CASE WHEN c.raw_id IS NULL THEN 1 ELSE 0 END), 0),
- COALESCE(SUM(CASE WHEN c.raw_id IS NULL THEN r.blob_size ELSE 0 END), 0)
- FROM raw_sessions AS r
- LEFT JOIN raw_membership_census AS c ON c.raw_id = r.raw_id
- """
- ).fetchone()
- finally:
- conn.close()
- except Exception as exc:
- return _relation_error("source raw/census relations", exc)
-
- distribution: list[dict[str, object]] = []
- for row in rows:
- distribution.append(
- {
- "origin": str(row[0]),
- "raw_count": int(row[1] or 0),
- "blob": _size_evidence(int(row[2] or 0)),
- "parse_failures": int(row[3] or 0),
- "validation_failures": int(row[4] or 0),
- "quarantine": {"count": int(row[5] or 0), "size": _size_evidence(int(row[6] or 0))},
- "census_coverage": {
- "status": "missing" if int(row[7] or 0) else "present",
- "missing_count": int(row[7] or 0),
- "missing_size": _size_evidence(int(row[8] or 0)),
- },
- "eligibility": {
- "terminal_count": int(row[9] or 0),
- "terminal_size": _size_evidence(int(row[10] or 0)),
- "actionable_count": int(row[11] or 0),
- "actionable_size": _size_evidence(int(row[12] or 0)),
- "authority_pending_count": int(row[13] or 0),
- "authority_pending_size": _size_evidence(int(row[14] or 0)),
- "eligible_count": int(row[15] or 0),
- "eligible_size": _size_evidence(int(row[16] or 0)),
- },
- }
- )
- (
- raw_count,
- raw_bytes,
- parse_failures,
- validation_failures,
- quarantined,
- quarantined_bytes,
- missing_census,
- missing_census_bytes,
- ) = tuple(_count(value) for value in totals)
- eligibility_rows = [item["eligibility"] for item in distribution]
- actionable = sum(int(item["actionable_count"]) for item in eligibility_rows if isinstance(item, dict))
- terminal = sum(int(item["terminal_count"]) for item in eligibility_rows if isinstance(item, dict))
- authority_pending = sum(int(item["authority_pending_count"]) for item in eligibility_rows if isinstance(item, dict))
- state = (
- "fail" if actionable else "unknown" if missing_census else "warn" if terminal or authority_pending else "pass"
- )
- return _status(
- state=state,
- reason=(
- "source coverage is incomplete"
- if missing_census
- else "actionable parse/validation failures remain"
- if actionable
- else "known terminal or authority-pending raw evidence"
- if terminal or authority_pending
- else None
- ),
- available=True,
- totals={
- "raw_count": raw_count,
- "raw_size": _size_evidence(raw_bytes),
- "parse_failures": parse_failures,
- "validation_failures": validation_failures,
- "quarantined_count": quarantined,
- "quarantined_size": _size_evidence(quarantined_bytes),
- "missing_census_count": missing_census,
- "missing_census_size": _size_evidence(missing_census_bytes),
- "terminal_count": terminal,
- "actionable_count": actionable,
- "authority_pending_count": authority_pending,
- },
- by_origin=distribution,
- semantics={
- "quarantine": "authority_pending, not automatically bad",
- "missing_census": "coverage_unknown, never terminal or actionable without a census verdict",
- "terminal": "census status failed or non_session",
- "actionable": "parse/validation failure with present non-terminal census evidence",
- },
- )
-
-
-def _index_profiles(root: Path) -> dict[str, object]:
- index_db = root / "index.db"
- if not index_db.exists():
- return _relation_error("index.db", FileNotFoundError(index_db))
- try:
- conn = open_readonly_connection(index_db)
- try:
- required = {"sessions", "session_profiles"}
- missing = sorted(
- table
- for table in required
- if not conn.execute("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?", (table,)).fetchone()
- )
- if missing:
- return _status(
- state="unknown", reason=f"required index relation(s) missing: {', '.join(missing)}", available=False
- )
- sessions = int(conn.execute("SELECT COUNT(*) FROM sessions").fetchone()[0] or 0)
- missing_profiles = int(
- conn.execute(
- "SELECT COUNT(*) FROM sessions AS s WHERE NOT EXISTS (SELECT 1 FROM session_profiles AS p WHERE p.session_id = s.session_id)"
- ).fetchone()[0]
- or 0
- )
- finally:
- conn.close()
- except Exception as exc:
- return _relation_error("index sessions/profile relations", exc)
- return _status(
- state="fail" if missing_profiles else "pass",
- reason="session profile rows are missing" if missing_profiles else None,
- available=True,
- sessions_count=sessions,
- missing_profile_count=missing_profiles,
- )
-
-
-def _fts_preflight(root: Path) -> dict[str, object]:
- index_db = root / "index.db"
- if not index_db.exists():
- return _relation_error("index.db FTS relations", FileNotFoundError(index_db))
- try:
- conn = open_readonly_connection(index_db)
- try:
- snapshot = fts_invariant_snapshot_sync(conn)
- finally:
- conn.close()
- except Exception as exc:
- return _relation_error("FTS readiness", exc)
- surfaces = {
- surface.name: {
- "source_exists": surface.source_exists,
- "exists": surface.exists,
- "source_rows": surface.source_rows,
- "indexed_rows": surface.indexed_rows,
- "triggers_present": surface.triggers_present,
- "missing_rows": surface.missing_rows,
- "excess_rows": surface.excess_rows,
- "duplicate_rows": surface.duplicate_rows,
- "identity_mismatch_rows": surface.identity_mismatch_rows,
- "ready": surface.ready,
- }
- for surface in snapshot.surfaces
- }
- debt = 0
- for surface in surfaces.values():
- debt += sum(
- int(surface.get(key) or 0)
- for key in ("missing_rows", "excess_rows", "duplicate_rows", "identity_mismatch_rows")
- )
- ready = snapshot.ready
- return _status(
- state="pass" if ready and debt == 0 else "fail",
- reason=None if ready and debt == 0 else "FTS debt or invariant failure is present",
- available=True,
- debt_count=debt,
- coverage_pct=(
- round(snapshot.messages.indexed_rows / snapshot.messages.source_rows * 100, 1)
- if snapshot.messages.source_rows
- else None
- ),
- coverage_exact=True,
- surfaces=surfaces,
- )
-
-
-def _frontier_preflight(root: Path) -> dict[str, object]:
- try:
- readiness = raw_materialization_readiness_snapshot(root, classify_gaps=True)
- projection = raw_frontier_integrity_projection(root, readiness)
- payload = projection.to_dict()
- except Exception as exc:
- return _relation_error("raw frontier relations", exc)
- overall = str(payload.get("overall_status") or "unknown")
- state = "pass" if overall == "healthy" else "fail" if overall == "violated" else "unknown"
- return _status(
- state=state,
- reason=None
- if state == "pass"
- else str(payload.get("missing_source_raw_reason") or "raw frontier is not healthy"),
- available=bool(payload.get("available")),
- evidence=payload,
- )
-
-
-def _replay_preflight(root: Path, *, limit: int) -> dict[str, object]:
- try:
- payload = raw_materialization_replay_backlog(
- Config(archive_root=root, render_root=root / "render", sources=[], db_path=root / "index.db"),
- limit=limit,
- )
- except Exception as exc:
- return _relation_error("raw replay relations", exc)
- if payload.get("available") is not True:
- return _status(
- state="unknown",
- reason=str(payload.get("reason") or "raw replay backlog unavailable"),
- available=False,
- evidence=payload,
- )
- candidate_count = _count(payload.get("candidate_count"))
- blocked_count = _count(payload.get("blocked_candidate_count"))
- executable_component_count = _count(payload.get("executable_authority_component_count"))
- # ``candidate_count`` counts raw rows, while ``blocked_candidate_count``
- # includes authority/resource debt. The backlog already computes the
- # executable authority-component population, so use that typed relation
- # to distinguish executable work from blocked-only work.
- state = (
- "fail" if executable_component_count else "warn" if blocked_count else "unknown" if candidate_count else "pass"
- )
- return _status(
- state=state,
- reason=(
- "executable raw replay candidates remain"
- if state == "fail"
- else "raw replay candidates are authority/resource blocked"
- if state == "warn"
- else "raw replay candidates lack executable or blocked classification"
- if state == "unknown"
- else None
- ),
- available=True,
- candidate_count=candidate_count,
- blocked_candidate_count=blocked_count,
- executable_authority_component_count=executable_component_count,
- authority_quarantined_count=_count(payload.get("authority_quarantined_count")),
- evidence=payload,
- )
-
-
-def _cursor_preflight(root: Path, *, now: datetime | None = None, limit: int) -> dict[str, object]:
- ops_db = root / "ops.db"
- if not ops_db.exists():
- return _relation_error("ops.db cursor relation", FileNotFoundError(ops_db))
- try:
- conn = open_readonly_connection(ops_db)
- try:
- columns = _table_columns(conn, "ingest_cursor")
- missing = sorted(_REQUIRED_CURSOR_COLUMNS - columns)
- if missing:
- return _status(
- state="unknown", reason=f"ingest_cursor columns missing: {', '.join(missing)}", available=False
- )
- rows = conn.execute(
- "SELECT source_path, origin, failure_count, next_retry_at, excluded FROM ingest_cursor ORDER BY source_path"
- ).fetchall()
- totals = conn.execute(
- """
- SELECT COUNT(*), COALESCE(SUM(failure_count > 0), 0),
- COALESCE(SUM(excluded = 1), 0),
- COALESCE(SUM(failure_count > 0 AND excluded = 0), 0)
- FROM ingest_cursor
- """
- ).fetchone()
- finally:
- conn.close()
- except Exception as exc:
- return _relation_error("ops.db ingest_cursor", exc)
- resolved_now = now or datetime.now(UTC)
- failed = int(totals[1] or 0)
- excluded = int(totals[2] or 0)
- retry_due = 0
- for row in rows:
- if int(row[2] or 0) <= 0 or bool(row[4]):
- continue
- retry_at = row[3]
- if retry_at is None:
- retry_due += 1
- continue
- try:
- if datetime.fromisoformat(str(retry_at)) <= resolved_now:
- retry_due += 1
- except ValueError:
- return _status(
- state="unknown", reason=f"ingest_cursor has malformed retry timestamp: {retry_at!r}", available=False
- )
- state = "fail" if failed else "warn" if excluded else "pass"
- return _status(
- state=state,
- reason="cursor failures remain"
- if failed
- else "excluded cursors are parked until source identity changes"
- if excluded
- else None,
- available=True,
- tracked_count=int(totals[0] or 0),
- failed_count=failed,
- excluded_count=excluded,
- retry_due_count=retry_due,
- sample=[
- {"source_path": str(row[0]), "origin": row[1], "failure_count": int(row[2] or 0), "excluded": bool(row[4])}
- for row in rows[:limit]
- ],
- )
-
-
-def _convergence_preflight(root: Path) -> dict[str, object]:
- ops_db = root / "ops.db"
- if not ops_db.exists():
- return _relation_error("ops.db convergence_debt relation", FileNotFoundError(ops_db))
- try:
- conn = open_readonly_connection(ops_db)
- try:
- columns = _table_columns(conn, "convergence_debt")
- missing = sorted({"stage", "status", "target_type", "target_id", "updated_at_ms"} - columns)
- if missing:
- return _status(
- state="unknown", reason=f"convergence_debt columns missing: {', '.join(missing)}", available=False
- )
- rows = conn.execute(
- "SELECT stage, status, target_type, target_id FROM convergence_debt ORDER BY updated_at_ms DESC LIMIT 16"
- ).fetchall()
- counts = conn.execute("SELECT status, COUNT(*) FROM convergence_debt GROUP BY status").fetchall()
- finally:
- conn.close()
- except Exception as exc:
- return _relation_error("ops.db convergence_debt", exc)
- unknown = sorted(str(row[0]) for row in counts if str(row[0]) not in _VALID_DEBT_STATUSES)
- if unknown:
- return _status(
- state="unknown",
- reason=f"convergence_debt has unknown status value(s): {', '.join(unknown)}",
- available=False,
- )
- failed = sum(int(row[1] or 0) for row in counts if str(row[0]) == "failed")
- deferred = sum(int(row[1] or 0) for row in counts if str(row[0]) == "deferred")
- return _status(
- state="fail" if failed else "warn" if deferred else "pass",
- reason="failed convergence debt rows remain"
- if failed
- else "deferred convergence debt remains"
- if deferred
- else None,
- available=True,
- failed_count=failed,
- deferred_count=deferred,
- row_count=failed + deferred,
- sample=[
- {"stage": str(row[0]), "status": str(row[1]), "target_type": str(row[2]), "target_id": str(row[3])}
- for row in rows
- ],
- )
-
-
-def _raw_failure_preflight(root: Path, *, limit: int) -> dict[str, object]:
- """Project typed lifecycle evidence into the stopped-daemon ledger."""
- snapshot = read_raw_failure_lifecycle(root / "source.db", sample_limit=limit)
- if not snapshot.available:
- return _status(
- state="unknown",
- reason=snapshot.reason or "raw failure lifecycle unavailable",
- available=False,
- evidence=snapshot.to_dict(),
- )
- state = "fail" if snapshot.unexplained else "warn" if snapshot.deferred or snapshot.terminal else "pass"
- return _status(
- state=state,
- reason=(
- "raw failures lack typed lifecycle evidence"
- if snapshot.unexplained
- else "raw failures are classified as deferred or terminal"
- if snapshot.deferred or snapshot.terminal
- else None
- ),
- available=True,
- evidence=snapshot.to_dict(),
- )
-
-
-def build_preflight_ledger(root: Path, *, limit: int = 10, now: datetime | None = None) -> dict[str, object]:
- """Build a read-only preflight ledger from the deployed archive relations."""
- checks = {
- "schema": _schema_preflight(root),
- "source": _source_distribution(root),
- "index_profiles": _index_profiles(root),
- "fts": _fts_preflight(root),
- "source_frontier": _frontier_preflight(root),
- "replay_backlog": _replay_preflight(root, limit=limit),
- "cursor_failures": _cursor_preflight(root, now=now, limit=limit),
- "raw_failure_lifecycle": _raw_failure_preflight(root, limit=limit),
- "convergence_debt": _convergence_preflight(root),
- }
- states = [str(value.get("state")) for value in checks.values()]
- blocking = [name for name, value in checks.items() if value.get("state") in {"fail", "unknown"}]
- warnings = [name for name, value in checks.items() if value.get("state") == "warn"]
- gate = "blocked" if blocking else "ready_with_warnings" if warnings else "ready"
- return {
- "report_version": PREFLIGHT_REPORT_VERSION,
- "read_only": True,
- "mutation_operations": [],
- "state": gate,
- "ok": not blocking,
- "blocking_checks": blocking,
- "warning_checks": warnings,
- "checks": checks,
- "evidence": {
- "source": "deployed archive status relations",
- "states_observed": states,
- "denominator_policy": "counts and bytes are exact SQL aggregates; cursor samples are bounded",
- },
- }
-
-
-__all__ = ["PREFLIGHT_REPORT_VERSION", "build_preflight_ledger"]
diff --git a/devtools/public_claims.py b/devtools/public_claims.py
deleted file mode 100644
index a6095f5848..0000000000
--- a/devtools/public_claims.py
+++ /dev/null
@@ -1,389 +0,0 @@
-"""Verify the generated public-claims projection and its coverage markers."""
-
-from __future__ import annotations
-
-import argparse
-import json
-import re
-import sqlite3
-import tempfile
-from collections import Counter, defaultdict
-from collections.abc import Mapping, Sequence
-from dataclasses import dataclass
-from pathlib import Path, PurePosixPath, PureWindowsPath
-from typing import Any
-
-import yaml
-
-from devtools.command_catalog import control_plane_command
-from polylogue.insights.measurement.public_claims import (
- CapabilityClaimInput,
- EvidenceIntegrityStatus,
- EvidenceIntegrityVerdict,
- MappingEvidenceIntegrityProvider,
- PublicClaimPresetName,
- PublicClaimProjection,
- build_public_claims_payload,
- project_public_claims,
- render_public_claims_json,
- render_public_claims_markdown,
-)
-from polylogue.scenarios.corpus import claim_vs_evidence_findings
-from polylogue.storage.sqlite.archive_tiers.bootstrap import initialize_archive_database
-from polylogue.storage.sqlite.archive_tiers.types import ArchiveTier
-from polylogue.storage.sqlite.archive_tiers.user_write import upsert_findings_as_assertions
-from polylogue.storage.sqlite.finding_provenance import list_public_finding_inputs
-
-ROOT = Path(__file__).resolve().parents[1]
-DEFAULT_OUTPUT_DIR = ROOT / "docs" / "generated" / "public-claims"
-DEFAULT_COMPATIBILITY_PATH = ROOT / "docs" / "public-claims.yaml"
-COMPATIBILITY_SCHEMA = "polylogue.public-claims-compatibility-view.v1"
-VERDICT_EXPORT_SCHEMA = "polylogue.evidence-integrity-verdicts.v1"
-PUBLIC_SURFACES = (
- Path("README.md"),
- Path("docs/demos.md"),
- Path("docs/findings/claim-vs-evidence.md"),
-)
-RETIRED_PHRASES = ("your AI memory",)
-_MARKER_RE = re.compile(r"")
-_FORBIDDEN_PUBLIC_PATH_RE = re.compile(r"(?:^|[\s`'\"])(?:/home/|/realm/|[A-Za-z]:\\)", re.MULTILINE)
-
-
-@dataclass(frozen=True, slots=True)
-class ClaimProblem:
- """One bounded verification problem."""
-
- claim_id: str | None
- message: str
-
- def to_payload(self) -> dict[str, str | None]:
- return {"claim_id": self.claim_id, "message": self.message}
-
-
-REPOSITORY_CAPABILITY_CLAIMS: tuple[CapabilityClaimInput, ...] = (
- CapabilityClaimInput(
- claim_key="category.local-evidence-system",
- publication="Polylogue archives your AI conversations - all of them, in one place, on your machine.",
- scope="The current local archive, query, evidence, judgment, and context surfaces.",
- caveat="This is a product-category capability statement, not a measured performance or prevalence claim.",
- public_evidence_refs=(
- "file:README.md",
- "file:docs/architecture.md",
- "file:docs/proof-artifacts.md",
- ),
- presets=tuple(PublicClaimPresetName),
- ),
-)
-
-
-def load_integrity_verdicts(path: Path | None) -> MappingEvidenceIntegrityProvider:
- """Load a bounded 37t.14 receipt export; absence means uncomputed/unresolved."""
-
- if path is None:
- return MappingEvidenceIntegrityProvider({})
- document = json.loads(path.read_text(encoding="utf-8"))
- if not isinstance(document, dict) or document.get("schema") != VERDICT_EXPORT_SCHEMA:
- raise ValueError(f"integrity verdict export must use schema {VERDICT_EXPORT_SCHEMA!r}")
- raw_verdicts = document.get("verdicts")
- if not isinstance(raw_verdicts, list):
- raise ValueError("integrity verdict export verdicts must be a list")
-
- verdicts: dict[str, EvidenceIntegrityVerdict] = {}
- for raw in raw_verdicts:
- if not isinstance(raw, dict):
- raise ValueError("every integrity verdict must be a mapping")
- finding_ref = _required_string(raw.get("finding_ref"), field="finding_ref")
- if finding_ref in verdicts:
- raise ValueError(f"duplicate integrity verdict for {finding_ref!r}")
- try:
- status = EvidenceIntegrityStatus(_required_string(raw.get("status"), field="status"))
- except ValueError as exc:
- raise ValueError(f"unknown integrity status for {finding_ref!r}") from exc
- verdicts[finding_ref] = EvidenceIntegrityVerdict(
- finding_ref=finding_ref,
- status=status,
- public_evidence_refs=_string_tuple(raw.get("public_evidence_refs")),
- reason_codes=_string_tuple(raw.get("reason_codes")),
- blind_spot_codes=_string_tuple(raw.get("blind_spot_codes")),
- as_of_epoch=_optional_string(raw.get("as_of_epoch")),
- frame_ref=_optional_string(raw.get("frame_ref")),
- definition_ref=_optional_string(raw.get("definition_ref")),
- public_remediation_refs=_string_tuple(raw.get("public_remediation_refs")),
- )
- return MappingEvidenceIntegrityProvider(verdicts)
-
-
-def build_repository_projection(
- *,
- archive_root: Path | None = None,
- verdicts_path: Path | None = None,
-) -> tuple[PublicClaimProjection, ...]:
- """Build one projection from a live user.db or the deterministic seed population."""
-
- integrity = load_integrity_verdicts(verdicts_path)
- if archive_root is not None:
- user_db_path = archive_root / "user.db"
- if not user_db_path.exists():
- raise ValueError(f"archive user tier does not exist: {user_db_path}")
- conn = sqlite3.connect(user_db_path)
- conn.row_factory = sqlite3.Row
- try:
- findings = list_public_finding_inputs(conn)
- finally:
- conn.close()
- else:
- with tempfile.TemporaryDirectory(prefix="polylogue-public-claims-") as temp_dir:
- user_db_path = Path(temp_dir) / "user.db"
- initialize_archive_database(user_db_path, ArchiveTier.USER)
- conn = sqlite3.connect(user_db_path)
- conn.row_factory = sqlite3.Row
- try:
- upsert_findings_as_assertions(conn, claim_vs_evidence_findings(), now_ms=1_720_080_953_667)
- conn.commit()
- findings = list_public_finding_inputs(conn)
- finally:
- conn.close()
-
- return project_public_claims(
- findings,
- REPOSITORY_CAPABILITY_CLAIMS,
- integrity=integrity,
- )
-
-
-def rendered_artifacts(
- claims: Sequence[PublicClaimProjection],
- *,
- output_dir: Path = DEFAULT_OUTPUT_DIR,
- compatibility_path: Path = DEFAULT_COMPATIBILITY_PATH,
-) -> dict[Path, str]:
- """Return every Markdown/JSON preset plus the generated YAML compatibility view."""
-
- generated_note = (
- f"\n\n"
- )
- artifacts: dict[Path, str] = {}
- for preset in PublicClaimPresetName:
- artifacts[output_dir / f"{preset.value}.md"] = generated_note + render_public_claims_markdown(claims, preset)
- artifacts[output_dir / f"{preset.value}.json"] = render_public_claims_json(claims, preset)
-
- compatibility = build_public_claims_payload(claims, PublicClaimPresetName.VERIFIED_EXPORT)
- compatibility_document = {
- "schema": COMPATIBILITY_SCHEMA,
- "generated_by": control_plane_command("render public-claims"),
- "authority": compatibility["authority"],
- "preset": compatibility["preset"],
- "claim_count": compatibility["claim_count"],
- "publishable_claim_keys": compatibility["publishable_claim_keys"],
- "claims": compatibility["claims"],
- }
- artifacts[compatibility_path] = yaml.safe_dump(
- compatibility_document,
- sort_keys=False,
- allow_unicode=True,
- width=120,
- )
- return artifacts
-
-
-def build_report(
- *,
- root: Path = ROOT,
- claims: Sequence[PublicClaimProjection] | None = None,
- output_dir: Path | None = None,
- compatibility_path: Path | None = None,
-) -> dict[str, Any]:
- """Return a machine-readable generated-view, parity, and coverage report."""
-
- problems: list[ClaimProblem] = []
- resolved_claims = tuple(claims) if claims is not None else build_repository_projection()
- resolved_output_dir = output_dir or root / "docs" / "generated" / "public-claims"
- resolved_compatibility_path = compatibility_path or root / "docs" / "public-claims.yaml"
- expected = rendered_artifacts(
- resolved_claims,
- output_dir=resolved_output_dir,
- compatibility_path=resolved_compatibility_path,
- )
-
- for path, rendered in expected.items():
- current = path.read_text(encoding="utf-8") if path.exists() else ""
- if current != rendered:
- problems.append(
- ClaimProblem(None, f"generated public-claims artifact is out of sync: {_display_path(path, root)}")
- )
- if _FORBIDDEN_PUBLIC_PATH_RE.search(current):
- problems.append(
- ClaimProblem(
- None,
- f"checked-in generated artifact contains an absolute private path: {_display_path(path, root)}",
- )
- )
- if _FORBIDDEN_PUBLIC_PATH_RE.search(rendered):
- problems.append(
- ClaimProblem(None, f"generated artifact contains an absolute private path: {_display_path(path, root)}")
- )
-
- problems.extend(_preset_parity_problems(resolved_claims))
- problems.extend(_coverage_problems(root, resolved_claims))
- problems.extend(_retired_phrase_problems(root))
- problems.extend(_public_ref_problems(resolved_claims))
-
- status_counts = Counter(claim.status.value for claim in resolved_claims)
- integrity_counts = Counter(
- claim.integrity_status.value for claim in resolved_claims if claim.integrity_status is not None
- )
- return {
- "ok": not problems,
- "schema": COMPATIBILITY_SCHEMA,
- "claim_count": len(resolved_claims),
- "status_counts": dict(sorted(status_counts.items())),
- "integrity_status_counts": dict(sorted(integrity_counts.items())),
- "artifact_count": len(expected),
- "surface_count": len(PUBLIC_SURFACES),
- "public_surfaces": [path.as_posix() for path in PUBLIC_SURFACES],
- "claim_keys": [claim.claim_key for claim in resolved_claims],
- "problems": [problem.to_payload() for problem in problems],
- }
-
-
-def _preset_parity_problems(claims: Sequence[PublicClaimProjection]) -> list[ClaimProblem]:
- statuses_by_key: dict[str, set[str]] = defaultdict(set)
- for preset in PublicClaimPresetName:
- payload = build_public_claims_payload(claims, preset)
- raw_claims = payload.get("claims")
- if not isinstance(raw_claims, list):
- return [ClaimProblem(None, f"preset {preset.value!r} did not render a claims list")]
- for raw in raw_claims:
- if isinstance(raw, dict) and isinstance(raw.get("claim_key"), str) and isinstance(raw.get("status"), str):
- statuses_by_key[raw["claim_key"]].add(raw["status"])
- return [
- ClaimProblem(claim_key, f"status differs across presets: {sorted(statuses)!r}")
- for claim_key, statuses in sorted(statuses_by_key.items())
- if len(statuses) != 1
- ]
-
-
-def _coverage_problems(root: Path, claims: Sequence[PublicClaimProjection]) -> list[ClaimProblem]:
- known = {claim.claim_key for claim in claims}
- covered: set[str] = set()
- problems: list[ClaimProblem] = []
- for relative_path in PUBLIC_SURFACES:
- path = root / relative_path
- if not path.exists():
- problems.append(ClaimProblem(None, f"public surface does not exist: {relative_path.as_posix()}"))
- continue
- text = path.read_text(encoding="utf-8")
- for marker in _MARKER_RE.findall(text):
- if marker not in known:
- problems.append(
- ClaimProblem(marker, f"public surface marker has no projected claim: {relative_path.as_posix()}")
- )
- else:
- covered.add(marker)
- for claim_key in sorted(known - covered):
- problems.append(ClaimProblem(claim_key, "projected claim is not covered by a public-surface marker"))
- return problems
-
-
-def _retired_phrase_problems(root: Path) -> list[ClaimProblem]:
- problems: list[ClaimProblem] = []
- for relative_path in PUBLIC_SURFACES:
- path = root / relative_path
- if not path.exists():
- continue
- text = path.read_text(encoding="utf-8").casefold()
- for phrase in RETIRED_PHRASES:
- if phrase.casefold() in text:
- problems.append(ClaimProblem(None, f"retired phrase {phrase!r} appears in {relative_path.as_posix()}"))
- return problems
-
-
-def _public_ref_problems(claims: Sequence[PublicClaimProjection]) -> list[ClaimProblem]:
- problems: list[ClaimProblem] = []
- for claim in claims:
- if not claim.public_evidence_refs and claim.privacy_review != "held_private":
- problems.append(ClaimProblem(claim.claim_key, "claim publishes no evidence refs"))
- for ref in (*claim.public_evidence_refs, *claim.public_remediation_refs):
- if _public_ref_is_unsafe(ref):
- problems.append(ClaimProblem(claim.claim_key, f"unsafe public ref: {ref}"))
- return problems
-
-
-def _public_ref_is_unsafe(ref: str) -> bool:
- _kind, separator, object_id = ref.partition(":")
- if not separator or not object_id:
- return True
- path_text = object_id.split("#", maxsplit=1)[0]
- if ref.startswith("file:"):
- return (
- path_text.startswith("~")
- or PurePosixPath(path_text).is_absolute()
- or PureWindowsPath(path_text).is_absolute()
- or ".." in PurePosixPath(path_text).parts
- or ".." in PureWindowsPath(path_text).parts
- )
- return False
-
-
-def _display_path(path: Path, root: Path) -> str:
- try:
- return path.relative_to(root).as_posix()
- except ValueError:
- return str(path)
-
-
-def _required_string(value: object, *, field: str) -> str:
- if not isinstance(value, str) or not value.strip():
- raise ValueError(f"{field} must be a non-empty string")
- return value.strip()
-
-
-def _optional_string(value: object) -> str | None:
- if value is None:
- return None
- return _required_string(value, field="optional verdict field")
-
-
-def _string_tuple(value: object) -> tuple[str, ...]:
- if value is None:
- return ()
- if not isinstance(value, list) or not all(isinstance(item, str) and item.strip() for item in value):
- raise ValueError("verdict list fields must contain strings")
- return tuple(dict.fromkeys(item.strip() for item in value))
-
-
-def _print_human(report: Mapping[str, Any]) -> None:
- print(f"public claims: {'ok' if report['ok'] else 'FAIL'}")
- print(f"claims: {report['claim_count']}")
- print(f"generated artifacts: {report['artifact_count']}")
- print(f"public surfaces: {report['surface_count']}")
- for problem in report["problems"]:
- prefix = f"{problem['claim_id']}: " if problem["claim_id"] else ""
- print(f" - {prefix}{problem['message']}")
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--json", action="store_true")
- args = parser.parse_args(argv)
-
- try:
- report = build_report()
- except (OSError, ValueError, json.JSONDecodeError, sqlite3.Error) as exc:
- report = {
- "ok": False,
- "claim_count": 0,
- "artifact_count": 0,
- "surface_count": len(PUBLIC_SURFACES),
- "problems": [ClaimProblem(None, str(exc)).to_payload()],
- }
- if args.json:
- print(json.dumps(report, indent=2, sort_keys=True))
- else:
- _print_human(report)
- return 0 if report["ok"] else 1
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/pytest_timeout_overrides.toml b/devtools/pytest_timeout_overrides.toml
deleted file mode 100644
index 0c59f1ee26..0000000000
--- a/devtools/pytest_timeout_overrides.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-# Exceptions to pytest's repository-wide 120-second timeout default
-# (tool.pytest.ini_options.timeout in pyproject.toml). Every path/value pair
-# must correspond to a live literal command override; `devtools verify
-# pytest-timeout-overrides` rejects stale entries.
-
-[[exception]]
-path = "devtools/coverage_gate.py"
-value = 600
-rationale = "The single-process coverage gate needs a bounded diagnostic budget for the full non-benchmark suite."
-
-[[exception]]
-path = "tests/unit/scenarios/test_codex_804_live_proof.py"
-value = 900
-rationale = "The sanitized 804-revision proof generates and acquires the outlier corpus, runs source remediation, then exercises pre-checkpoint failure, interrupted replay, fresh-process resume, and promotion under one bounded incident-scale budget."
diff --git a/devtools/pytest_witness_repetitions.py b/devtools/pytest_witness_repetitions.py
deleted file mode 100644
index 72dafdf74b..0000000000
--- a/devtools/pytest_witness_repetitions.py
+++ /dev/null
@@ -1,413 +0,0 @@
-"""Bounded, receipt-bearing repetitions for the seed-hang witnesses.
-
-The July seed failures were not ordinary unit-test failures: their defining
-property was intermittent lifecycle loss under an xdist controller. A single
-green invocation cannot establish that those paths are repaired. This module
-therefore invokes the *ordinary* ``devtools test`` route once per witness and
-mode, retaining every managed-run receipt even when an attempt times out or
-fails. It deliberately has no retry path.
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import os
-import re
-import subprocess
-import sys
-import time
-from collections.abc import Callable, Sequence
-from dataclasses import asdict, dataclass
-from datetime import UTC, datetime
-from pathlib import Path
-from typing import Any
-
-from devtools import repo_root
-
-_CACHE_ROOT = Path(".cache") / "pytest-witness-repetitions"
-_WORKER_RE = re.compile(r"\[(gw\d+)\]")
-_OWNER_SHUTDOWN_GRACE_S = 5.0
-
-
-@dataclass(frozen=True, slots=True)
-class Witness:
- """One exact lifecycle witness and the event its real-route test awaits."""
-
- name: str
- nodeid: str
- awaited_lifecycle: str
-
-
-WITNESSES: tuple[Witness, ...] = (
- Witness(
- name="periodic-wal-checkpoint",
- nodeid="tests/unit/daemon/test_daemon_cli.py::test_periodic_wal_checkpoint_targets_archive_root_tiers",
- awaited_lifecycle="daemon write coordinator invokes maintenance.wal_checkpoint then cancellation propagates",
- ),
- Witness(
- name="periodic-db-optimize",
- nodeid="tests/unit/daemon/test_daemon_cli.py::test_periodic_db_optimize_targets_archive_root_tiers",
- awaited_lifecycle="daemon write coordinator invokes maintenance.db_optimize then cancellation propagates",
- ),
- Witness(
- name="periodic-embedding-backlog",
- nodeid="tests/unit/daemon/test_embedding_convergence_progress.py::test_periodic_embedding_backlog_waits_for_catch_up_complete",
- awaited_lifecycle="catch_up_complete event gates the first maintenance.embedding_backlog drain",
- ),
-)
-
-
-@dataclass(frozen=True, slots=True)
-class AttemptReceipt:
- """Durable result of one invocation; failures remain first-class evidence."""
-
- witness: str
- nodeid: str
- mode: str
- ordinal: int
- workers: int
- command: tuple[str, ...]
- started_at: str
- finished_at: str
- status: str
- exit_code: int | None
- duration_s: float | None
- node_duration_s: float | None
- worker_id: str | None
- archive_root_scope: str | None
- archive_root_cleaned: bool | None
- containment_receipt: str | None
- process_group_cleaned: bool | None
- awaited_lifecycle: str
- failure: str | None
-
-
-@dataclass(frozen=True, slots=True)
-class RepetitionReceipt:
- """One complete proof batch, including every passed and failed attempt."""
-
- format: str
- source_root: str
- git_head: str | None
- attempts_per_mode: int
- xdist_workers: int
- timeout_s: float
- started_at: str
- finished_at: str
- attempts: tuple[AttemptReceipt, ...]
- ok: bool
-
- def to_dict(self) -> dict[str, object]:
- return asdict(self)
-
-
-Runner = Callable[[Sequence[str], Path, dict[str, str], float], subprocess.CompletedProcess[str]]
-
-
-def _utc_now() -> str:
- return datetime.now(UTC).isoformat()
-
-
-def _git_head(root: Path) -> str | None:
- try:
- result = subprocess.run(
- ["git", "rev-parse", "HEAD"], cwd=root, text=True, capture_output=True, timeout=5, check=False
- )
- except (OSError, subprocess.TimeoutExpired):
- return None
- return result.stdout.strip() if result.returncode == 0 and result.stdout.strip() else None
-
-
-def _run_direct(
- command: Sequence[str], root: Path, env: dict[str, str], timeout_s: float
-) -> subprocess.CompletedProcess[str]:
- return subprocess.run(
- list(command), cwd=root, env=env, text=True, capture_output=True, timeout=timeout_s, check=False
- )
-
-
-def _run_directories(root: Path) -> set[Path]:
- runs = root / ".cache" / "verify" / "runs"
- return {path.parent for path in runs.glob("*/run.json")}
-
-
-def _single_new_run(root: Path, before: set[Path]) -> Path | None:
- new = _run_directories(root) - before
- if len(new) != 1:
- return None
- return next(iter(new))
-
-
-def _read_json(path: Path) -> dict[str, Any] | None:
- try:
- payload = json.loads(path.read_text(encoding="utf-8"))
- except (OSError, json.JSONDecodeError):
- return None
- return payload if isinstance(payload, dict) else None
-
-
-def _node_metadata(report: dict[str, Any] | None, nodeid: str) -> tuple[float | None, str | None]:
- if report is None:
- return None, None
- tests = report.get("tests")
- if not isinstance(tests, list):
- return None, None
- for test in tests:
- if not isinstance(test, dict) or test.get("nodeid") != nodeid:
- continue
- duration = 0.0
- seen_duration = False
- worker_id: str | None = None
- for phase in ("setup", "call", "teardown"):
- value = test.get(phase)
- if not isinstance(value, dict):
- continue
- phase_duration = value.get("duration")
- if isinstance(phase_duration, (int, float)):
- duration += float(phase_duration)
- seen_duration = True
- longrepr = value.get("longrepr")
- if isinstance(longrepr, str):
- match = _WORKER_RE.search(longrepr)
- if match:
- worker_id = match.group(1)
- return (duration if seen_duration else None), worker_id
- return None, None
-
-
-def _receipt_from_run(
- run_dir: Path | None, *, root: Path, nodeid: str
-) -> tuple[float | None, float | None, str | None, str | None, bool | None, str | None, bool | None]:
- if run_dir is None:
- return None, None, None, None, None, None, None
- run = _read_json(run_dir / "run.json")
- if run is None:
- return None, None, None, None, None, None, None
- steps = run.get("steps")
- step = steps[0] if isinstance(steps, list) and steps and isinstance(steps[0], dict) else {}
- report_path = step.get("report_path")
- report = _read_json(root / report_path) if isinstance(report_path, str) else None
- node_duration, worker_id = _node_metadata(report, nodeid)
- containment_path = run_dir / "steps" / "01-pytest-focused" / "containment.json"
- containment = _read_json(containment_path)
- if containment is None:
- current_path = step.get("containment_path")
- containment = _read_json(root / current_path) if isinstance(current_path, str) else None
- archive_root_scope = containment.get("tmpfs_cleanup_path") if containment else None
- if not isinstance(archive_root_scope, str):
- archive_root_scope = None
- archive_root_cleaned = not Path(archive_root_scope).exists() if archive_root_scope else None
- process_group_cleaned = containment.get("controller_group_alive") is False if containment else None
- return (
- float(step["duration_s"]) if isinstance(step.get("duration_s"), (int, float)) else None,
- node_duration,
- worker_id,
- archive_root_scope,
- archive_root_cleaned,
- str(containment_path),
- process_group_cleaned,
- )
-
-
-def _await_timeout_cleanup(
- *, root: Path, before: set[Path], nodeid: str
-) -> tuple[
- float | None,
- float | None,
- str | None,
- str | None,
- bool | None,
- str | None,
- bool | None,
-]:
- """Wait briefly for the externally-owned supervisor to publish teardown.
-
- A subprocess timeout terminates the devtools owner, while the independent
- supervisor still needs a bounded interval to notice that death, kill the
- pytest group, clean its tmpfs root, and write the final receipt. Reading
- before that transition would report a completed cleanup as a leak.
- """
- details = _receipt_from_run(None, root=root, nodeid=nodeid)
- for _ in range(100):
- run_dir = _single_new_run(root, before)
- details = _receipt_from_run(run_dir, root=root, nodeid=nodeid)
- if details[4] is True and details[6] is True:
- return details
- time.sleep(0.05)
- return details
-
-
-def _command(*, nodeid: str, workers: int) -> list[str]:
- return [sys.executable, "-m", "devtools", "test", nodeid, "-n", str(workers)]
-
-
-def _attempt(
- *,
- witness: Witness,
- mode: str,
- ordinal: int,
- workers: int,
- root: Path,
- timeout_s: float,
- runner: Runner,
-) -> AttemptReceipt:
- command = _command(nodeid=witness.nodeid, workers=workers)
- before = _run_directories(root)
- started_at = _utc_now()
- env = os.environ.copy()
- env["POLYLOGUE_PYTEST_WORKERS"] = str(workers)
- try:
- completed = runner(command, root, env, timeout_s + _OWNER_SHUTDOWN_GRACE_S)
- completed_run_dir = _single_new_run(root, before)
- duration_s, node_duration_s, worker_id, archive_scope, archive_cleaned, containment, group_cleaned = (
- _receipt_from_run(completed_run_dir, root=root, nodeid=witness.nodeid)
- )
- failed = completed.returncode != 0
- failure = (completed.stderr or completed.stdout).strip()[-4000:] if failed else None
- return AttemptReceipt(
- witness=witness.name,
- nodeid=witness.nodeid,
- mode=mode,
- ordinal=ordinal,
- workers=workers,
- command=tuple(command),
- started_at=started_at,
- finished_at=_utc_now(),
- status="failed" if failed else "passed",
- exit_code=completed.returncode,
- duration_s=duration_s,
- node_duration_s=node_duration_s,
- worker_id=worker_id,
- archive_root_scope=archive_scope,
- archive_root_cleaned=archive_cleaned,
- containment_receipt=containment,
- process_group_cleaned=group_cleaned,
- awaited_lifecycle=witness.awaited_lifecycle,
- failure=failure,
- )
- except subprocess.TimeoutExpired as exc:
- # ``subprocess.run`` kills the devtools owner on timeout. Its external
- # supervisor then owns the process-tree teardown; wait only for that
- # receipt to become observable and retain whatever it says. Never run
- # the failed attempt again.
- duration_s, node_duration_s, worker_id, archive_scope, archive_cleaned, containment, group_cleaned = (
- _await_timeout_cleanup(root=root, before=before, nodeid=witness.nodeid)
- )
- return AttemptReceipt(
- witness=witness.name,
- nodeid=witness.nodeid,
- mode=mode,
- ordinal=ordinal,
- workers=workers,
- command=tuple(command),
- started_at=started_at,
- finished_at=_utc_now(),
- status="timed_out",
- exit_code=None,
- duration_s=duration_s,
- node_duration_s=node_duration_s,
- worker_id=worker_id,
- archive_root_scope=archive_scope,
- archive_root_cleaned=archive_cleaned,
- containment_receipt=containment,
- process_group_cleaned=group_cleaned,
- awaited_lifecycle=witness.awaited_lifecycle,
- failure=(
- f"managed invocation did not finish within {timeout_s + _OWNER_SHUTDOWN_GRACE_S:g}s "
- f"(including {timeout_s:g}s evidence bound): {exc}"
- ),
- )
-
-
-def run_repetitions(
- *,
- source_root: Path | None = None,
- attempts_per_mode: int = 10,
- xdist_workers: int = 3,
- timeout_s: float = 10.0,
- runner: Runner = _run_direct,
-) -> RepetitionReceipt:
- """Run every current witness in isolated and xdist mode without retries."""
- if attempts_per_mode < 1:
- raise ValueError("attempts_per_mode must be positive")
- if xdist_workers < 1:
- raise ValueError("xdist_workers must be positive")
- if timeout_s <= 0:
- raise ValueError("timeout_s must be positive")
- root = (source_root or repo_root()).resolve()
- started_at = _utc_now()
- attempts: list[AttemptReceipt] = []
- for witness in WITNESSES:
- for mode, workers in (("isolated", 0), ("xdist", xdist_workers)):
- for ordinal in range(1, attempts_per_mode + 1):
- attempts.append(
- _attempt(
- witness=witness,
- mode=mode,
- ordinal=ordinal,
- workers=workers,
- root=root,
- timeout_s=timeout_s,
- runner=runner,
- )
- )
- ok = all(
- attempt.status == "passed"
- and attempt.duration_s is not None
- and attempt.duration_s < timeout_s
- and attempt.node_duration_s is not None
- and attempt.node_duration_s < timeout_s
- and attempt.archive_root_cleaned is True
- and attempt.process_group_cleaned is True
- for attempt in attempts
- )
- return RepetitionReceipt(
- format="pytest-witness-repetitions-v1",
- source_root=str(root),
- git_head=_git_head(root),
- attempts_per_mode=attempts_per_mode,
- xdist_workers=xdist_workers,
- timeout_s=timeout_s,
- started_at=started_at,
- finished_at=_utc_now(),
- attempts=tuple(attempts),
- ok=ok,
- )
-
-
-def _default_output(root: Path) -> Path:
- stamp = datetime.now(UTC).strftime("%Y%m%dT%H%M%SZ")
- return root / _CACHE_ROOT / f"{stamp}-receipt.json"
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description="Repeat exact seed-hang witnesses through managed pytest.")
- parser.add_argument("--attempts", type=int, default=10, help="Consecutive attempts per witness and mode.")
- parser.add_argument("--xdist-workers", type=int, default=3, help="Workers for each xdist attempt.")
- parser.add_argument("--timeout-s", type=float, default=10.0, help="Per-invocation and per-node bound.")
- parser.add_argument("--output", type=Path, help="Durable JSON receipt destination.")
- parser.add_argument("--json", action="store_true", help="Print the complete receipt as JSON.")
- args = parser.parse_args(argv)
- root = repo_root().resolve()
- receipt = run_repetitions(
- source_root=root,
- attempts_per_mode=args.attempts,
- xdist_workers=args.xdist_workers,
- timeout_s=args.timeout_s,
- )
- output = (args.output or _default_output(root)).resolve()
- output.parent.mkdir(parents=True, exist_ok=True)
- output.write_text(json.dumps(receipt.to_dict(), indent=2) + "\n", encoding="utf-8")
- if args.json:
- print(json.dumps(receipt.to_dict(), indent=2))
- else:
- print(f"pytest witness repetitions {'passed' if receipt.ok else 'failed'}: {output}")
- return 0 if receipt.ok else 1
-
-
-__all__ = ["AttemptReceipt", "RepetitionReceipt", "WITNESSES", "Witness", "main", "run_repetitions"]
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/quality_registry.py b/devtools/quality_registry.py
deleted file mode 100644
index 16b2af86af..0000000000
--- a/devtools/quality_registry.py
+++ /dev/null
@@ -1,60 +0,0 @@
-"""Shared registry for validation lanes and durable quality campaigns."""
-
-from __future__ import annotations
-
-from dataclasses import dataclass
-
-from devtools.authored_scenario_catalog import AuthoredScenarioCatalog, get_authored_scenario_catalog
-from devtools.benchmark_catalog import BenchmarkCampaignEntry
-from devtools.lane_models import LaneEntry
-from devtools.mutation_catalog import MutationCampaignEntry
-from devtools.scenario_projection_catalog import build_scenario_projection_entries
-from polylogue.scenarios import CorpusScenario, ScenarioProjectionEntry
-
-
-@dataclass(frozen=True)
-class QualityRegistry:
- catalog: AuthoredScenarioCatalog
- scenario_projections: tuple[ScenarioProjectionEntry, ...]
-
- @property
- def contract_lanes(self) -> tuple[LaneEntry, ...]:
- return self.catalog.contract_lanes
-
- @property
- def live_lanes(self) -> tuple[LaneEntry, ...]:
- return self.catalog.live_lanes
-
- @property
- def composite_lanes(self) -> tuple[LaneEntry, ...]:
- return self.catalog.composite_lanes
-
- @property
- def mutation_campaigns(self) -> tuple[MutationCampaignEntry, ...]:
- return self.catalog.mutation_campaigns
-
- @property
- def benchmark_campaigns(self) -> tuple[BenchmarkCampaignEntry, ...]:
- return self.catalog.benchmark_campaigns
-
- @property
- def synthetic_benchmark_campaigns(self) -> tuple[BenchmarkCampaignEntry, ...]:
- return self.catalog.synthetic_benchmark_campaigns
-
- @property
- def inferred_corpus_scenarios(self) -> tuple[CorpusScenario, ...]:
- return self.catalog.inferred_corpus_scenarios
-
-
-def build_quality_registry() -> QualityRegistry:
- catalog = get_authored_scenario_catalog()
- return QualityRegistry(
- catalog=catalog,
- scenario_projections=build_scenario_projection_entries(catalog=catalog),
- )
-
-
-__all__ = [
- "QualityRegistry",
- "build_quality_registry",
-]
diff --git a/devtools/raw_authority_restart_proof.py b/devtools/raw_authority_restart_proof.py
index d9e9125d06..afafb4895b 100644
--- a/devtools/raw_authority_restart_proof.py
+++ b/devtools/raw_authority_restart_proof.py
@@ -25,7 +25,7 @@
from polylogue.core.enums import Provider
from polylogue.core.json import require_json_document
from polylogue.storage import raw_authority, repair
-from polylogue.storage.raw_authority import RawReplayPlan, RawReplayPlanStatus
+from polylogue.storage.raw_authority import RawReplayPlan, RawReplayPlanOutcome, RawReplayPlanStatus
from polylogue.storage.sqlite.archive_tiers.archive import ArchiveStore
from polylogue.storage.sqlite.archive_tiers.bootstrap import initialize_active_archive_root
@@ -113,7 +113,7 @@ def _require_not_none(value: _T | None, detail: str) -> _T:
def _config(root: Path) -> Config:
- return Config(archive_root=root, render_root=root / "render", sources=[], db_path=root / "archive.db")
+ return Config(archive_root=root, render_root=root / "render", sources=[])
def _conversation(session_id: str, *, text: str, update_time: int) -> dict[str, object]:
@@ -585,6 +585,13 @@ def _result_summary(result: repair.RepairResult) -> dict[str, object]:
}
+def _outcome_has_application_decision(outcome: RawReplayPlanOutcome, expected: str) -> bool:
+ if outcome.application_receipt is None:
+ return False
+ rows = outcome.application_receipt.get("application_rows")
+ return isinstance(rows, list) and any(isinstance(row, dict) and row.get("decision") == expected for row in rows)
+
+
def _resume_and_drain(topology: PreparedTopology) -> tuple[dict[str, object], ...]:
results: list[dict[str, object]] = []
config = _config(topology.archive_root)
@@ -604,7 +611,46 @@ def _resume_and_drain(topology: PreparedTopology) -> tuple[dict[str, object], ..
).fetchone()[0]
)
if not candidates.raw_ids and planned == 0:
- _require(result.success, f"production repair drained candidates but reported failure: {result.detail}")
+ if not result.success:
+ # The scenario deliberately injects these two non-success
+ # outcomes. Accept only their typed application evidence;
+ # production continues to report the archive unhealthy.
+ expected = {
+ topology.plan_ids_by_role["membership-terminal"]: (
+ RawReplayPlanStatus.TERMINAL,
+ "ambiguous",
+ ),
+ topology.plan_ids_by_role["membership-deferred"]: (
+ RawReplayPlanStatus.DEFERRED,
+ "deferred",
+ ),
+ }
+ exceptional = tuple(
+ outcome
+ for outcome in result.plan_outcomes
+ if outcome.status not in {RawReplayPlanStatus.EXECUTED, RawReplayPlanStatus.CARRIED_FORWARD}
+ )
+ expected_failure = {outcome.plan_id for outcome in exceptional} == set(expected)
+ for outcome in exceptional:
+ expected_outcome = expected.get(outcome.plan_id)
+ expected_failure = (
+ expected_failure
+ and expected_outcome is not None
+ and outcome.status is expected_outcome[0]
+ and _outcome_has_application_decision(outcome, expected_outcome[1])
+ )
+ blocker_metrics = (
+ result.metrics.get("raw_materialization_plan_conservation_error_count", 0),
+ result.metrics.get("raw_materialization_unresolved_blocker_count", 0),
+ result.metrics.get("raw_materialization_missing_blob_count", 0),
+ result.metrics.get("raw_materialization_resource_blocked_count", 0),
+ result.metrics.get("raw_materialization_no_progress_count", 0),
+ result.metrics.get("raw_materialization_remaining_byte_authority_pending_count", 0),
+ )
+ _require(
+ expected_failure and not any(blocker_metrics),
+ f"production repair drained candidates but reported unexplained failure: {result.detail}",
+ )
return tuple(results)
raise RawAuthorityRestartProofError("production repair did not drain the compact topology after restart")
diff --git a/devtools/raw_authority_scale_proof.py b/devtools/raw_authority_scale_proof.py
index 5185fc384b..53918386b6 100644
--- a/devtools/raw_authority_scale_proof.py
+++ b/devtools/raw_authority_scale_proof.py
@@ -21,7 +21,7 @@
import threading
import time
from collections import Counter
-from collections.abc import Callable
+from collections.abc import Callable, Mapping
from dataclasses import asdict, dataclass
from pathlib import Path
from typing import TextIO, cast
@@ -37,7 +37,7 @@
)
from polylogue.schemas.workload_tiers import WorkloadScaleTier
from polylogue.storage import repair
-from polylogue.storage.raw_authority import RawReplayPlanStatus
+from polylogue.storage.raw_authority import RawReplayPlanOutcome, RawReplayPlanStatus
from polylogue.storage.sqlite.archive_tiers.archive import ArchiveStore
from polylogue.storage.sqlite.archive_tiers.bootstrap import initialize_active_archive_root
from polylogue.storage.sqlite.archive_tiers.source_write import write_source_raw_session_blob_ref
@@ -58,6 +58,7 @@ class RawAuthorityScalePass:
executable_component_count: int
fixed_point: bool
plan_status_counts: dict[str, int]
+ production_success: bool
wall_ms: int
peak_rss_bytes: int
peak_pss_bytes: int | None
@@ -67,6 +68,13 @@ class RawAuthorityScalePass:
write_io_bytes: int | None
+@dataclass(frozen=True, slots=True)
+class _ExpectedExceptionalComponent:
+ status: RawReplayPlanStatus
+ application_decision: str
+ exceptional_raw_ids: frozenset[str]
+
+
@dataclass(frozen=True, slots=True)
class ProcessSample:
"""Boundary sample for the runner process, using kernel-owned counters."""
@@ -243,6 +251,24 @@ def count(field: str) -> int:
)
+def _outcome_matches_expected_exception(
+ outcome: RawReplayPlanOutcome,
+ expected: _ExpectedExceptionalComponent,
+) -> bool:
+ """Bind a typed exceptional outcome to the exact seeded raw identities."""
+ if outcome.status is not expected.status or outcome.application_receipt is None:
+ return False
+ rows = outcome.application_receipt.get("application_rows")
+ if not isinstance(rows, list):
+ return False
+ decided_raw_ids = {
+ str(row.get("raw_id"))
+ for row in rows
+ if isinstance(row, dict) and row.get("decision") == expected.application_decision
+ }
+ return decided_raw_ids == expected.exceptional_raw_ids
+
+
def _payload_header(native_id: str, revision: int, *, first: bool) -> bytes:
"""Build the leading JSONL record(s) for one raw payload write.
@@ -651,6 +677,8 @@ def _record_repair_pass(
pass_limit: int,
max_payload_bytes: int,
check_admission: Callable[[], None],
+ expected_exception_components: Mapping[frozenset[str], _ExpectedExceptionalComponent] | None = None,
+ observed_exception_components: set[frozenset[str]] | None = None,
) -> tuple[RawAuthorityScalePass, str]:
"""Run one real repair/census pass and reject incomplete evidence."""
check_admission()
@@ -666,7 +694,7 @@ def _record_repair_pass(
before, after = sampler.samples[0], sampler.samples[-1]
check_admission()
metrics = result.metrics
- if not result.success:
+ if not result.success and not metrics:
raise RuntimeError(f"raw-authority scale proof repair pass failed: {result.detail}")
candidate_value = metrics.get("raw_materialization_candidate_count")
executable_candidate_value = metrics.get("raw_materialization_executable_candidate_count", candidate_value)
@@ -693,6 +721,56 @@ def _record_repair_pass(
expected_modes = {"apply", "census"} if mode == "apply" else {"dry_run"}
if receipt.mode not in expected_modes:
raise RuntimeError(f"raw-authority scale proof expected {mode} census evidence, received {receipt.mode}")
+ plan_status_counts = {
+ status.value: sum(outcome.status is status for outcome in result.plan_outcomes)
+ for status in RawReplayPlanStatus
+ }
+ exceptional_outcomes = tuple(
+ outcome
+ for outcome in result.plan_outcomes
+ if outcome.status not in {RawReplayPlanStatus.EXECUTED, RawReplayPlanStatus.CARRIED_FORWARD}
+ )
+ expected_outcomes = not exceptional_outcomes
+ if exceptional_outcomes:
+ expected_outcomes = expected_exception_components is not None
+ pass_components: set[frozenset[str]] = set()
+ for outcome in exceptional_outcomes:
+ component_id = frozenset(outcome.input_raw_ids)
+ expected = expected_exception_components.get(component_id) if expected_exception_components else None
+ if (
+ expected is None
+ or not _outcome_matches_expected_exception(outcome, expected)
+ or component_id in pass_components
+ or (observed_exception_components is not None and component_id in observed_exception_components)
+ ):
+ expected_outcomes = False
+ continue
+ pass_components.add(component_id)
+ if not expected_outcomes:
+ raise RuntimeError(
+ "raw-authority scale proof repair pass failed: observed an unbound exceptional repair outcome"
+ )
+ if observed_exception_components is not None:
+ observed_exception_components.update(pass_components)
+ if not result.success:
+ # RepairResult.success is archive health. This fault/scale proof may
+ # deliberately create typed terminal debt, but it must never mistake
+ # an unrelated failed pass for successful proof execution.
+ blockers = (
+ metrics.get("raw_materialization_plan_conservation_error_count", 0),
+ metrics.get("raw_materialization_unresolved_blocker_count", 0),
+ metrics.get("raw_materialization_missing_blob_count", 0),
+ metrics.get("raw_materialization_resource_blocked_count", 0),
+ metrics.get("raw_materialization_no_progress_count", 0),
+ metrics.get("raw_materialization_remaining_byte_authority_pending_count", 0),
+ )
+ remaining = metrics.get("raw_materialization_remaining_candidate_count", 0)
+ bounded_progress = mode == "apply" and result.repaired_count > 0 and remaining > 0 and not exceptional_outcomes
+ expected_terminal_classification = (
+ mode == "apply" and result.repaired_count > 0 and bool(exceptional_outcomes) and expected_outcomes
+ )
+ if any(blockers) or not (bounded_progress or expected_terminal_classification):
+ raise RuntimeError(f"raw-authority scale proof repair pass failed: {result.detail}")
return (
RawAuthorityScalePass(
number=number,
@@ -702,10 +780,8 @@ def _record_repair_pass(
repaired_count=result.repaired_count,
executable_component_count=int(metrics.get("raw_materialization_selected_executable_component_count", 0)),
fixed_point=receipt.fixed_point,
- plan_status_counts={
- status.value: sum(outcome.status is status for outcome in result.plan_outcomes)
- for status in RawReplayPlanStatus
- },
+ plan_status_counts=plan_status_counts,
+ production_success=result.success,
wall_ms=wall_ms,
peak_rss_bytes=int(sampler.peak("rss_bytes") or 0),
peak_pss_bytes=sampler.peak("pss_bytes"),
@@ -790,6 +866,12 @@ def check_replay_pressure() -> None:
shutil.rmtree(root)
initialize_active_archive_root(root)
component_shape = _component_authority_shape(scenario)
+ expected_application_decision = "ambiguous" if scenario.terminal_sibling_outcome == "terminal" else "deferred"
+ expected_exception_status = (
+ RawReplayPlanStatus.TERMINAL
+ if scenario.terminal_sibling_outcome == "terminal"
+ else RawReplayPlanStatus.DEFERRED
+ )
component_sizes = _row_sizes(
scenario,
[direct_count + sibling_count for direct_count, sibling_count in component_shape],
@@ -801,6 +883,8 @@ def check_replay_pressure() -> None:
raise RuntimeError("raw-authority scale proof requires a writable blob publisher")
source_conn = archive._ensure_source_conn()
generated_archive_id = _GeneratedArchiveId()
+ component_raw_ids = [set[str]() for _ in range(scenario.components)]
+ exceptional_raw_ids = [set[str]() for _ in range(scenario.components)]
pending_rows: list[tuple[str, str, str, int, bool, int]] = []
generated_payload_bytes = 0
acquired_at_ms = 0
@@ -865,7 +949,9 @@ def check_replay_pressure() -> None:
blob_publication_receipt_id=publisher.receipt_id(row_hash),
manage_transaction=False,
)
+ component_raw_ids[row_component].add(raw_id)
if terminalized:
+ exceptional_raw_ids[row_component].add(raw_id)
with sqlite3.connect(root / "index.db") as index_conn:
index_conn.execute(
"""
@@ -919,7 +1005,9 @@ def check_replay_pressure() -> None:
blob_publication_receipt_id=publisher.receipt_id(row_hash),
manage_transaction=False,
)
+ component_raw_ids[row_component].add(raw_id)
if terminalized:
+ exceptional_raw_ids[row_component].add(raw_id)
with sqlite3.connect(root / "index.db") as index_conn:
index_conn.execute(
"""
@@ -941,6 +1029,17 @@ def check_replay_pressure() -> None:
acquired_at_ms += 1
check_generation_pressure()
staging.rmdir()
+ expected_exception_components = {
+ frozenset(component_raw_ids[index]): _ExpectedExceptionalComponent(
+ status=expected_exception_status,
+ application_decision=expected_application_decision,
+ exceptional_raw_ids=frozenset(exceptional_raw_ids[index]),
+ )
+ for index in range(scenario.components)
+ if exceptional_raw_ids[index]
+ }
+ if any(not component for component in component_raw_ids):
+ raise RuntimeError("raw-authority scale proof generated an empty authority component")
archive_id = generated_archive_id.value()
config = Config(archive_root=root, render_root=root, sources=[], db_path=root / "index.db")
check_replay_pressure()
@@ -976,6 +1075,7 @@ def check_replay_pressure() -> None:
maximum_passes=(scenario.components * 3) + 4,
)
pass_receipts: list[RawAuthorityScalePass] = []
+ observed_exception_components: set[frozenset[str]] = set()
for number in range(1, (scenario.components * 3) + 4):
pass_receipt, _digest = _record_repair_pass(
number=number,
@@ -984,6 +1084,8 @@ def check_replay_pressure() -> None:
pass_limit=pass_limit,
max_payload_bytes=max_payload_bytes,
check_admission=check_replay_pressure,
+ expected_exception_components=expected_exception_components,
+ observed_exception_components=observed_exception_components,
)
pass_receipts.append(pass_receipt)
if pass_receipt.candidate_count == 0:
@@ -992,6 +1094,19 @@ def check_replay_pressure() -> None:
raise RuntimeError("raw-authority scale proof left unexecuted candidate work after bounded replay")
else:
raise RuntimeError("raw-authority scale proof did not drain bounded apply passes")
+ if observed_exception_components != set(expected_exception_components):
+ missing = sorted(
+ (sorted(component) for component in set(expected_exception_components) - observed_exception_components),
+ key=str,
+ )
+ unexpected = sorted(
+ (sorted(component) for component in observed_exception_components - set(expected_exception_components)),
+ key=str,
+ )
+ raise RuntimeError(
+ "raw-authority scale proof did not receipt every exact exceptional authority component: "
+ f"missing={missing}, unexpected={unexpected}"
+ )
fixed_point_digests: list[str] = []
for _ in range(2):
pass_receipt, digest = _record_repair_pass(
@@ -1001,6 +1116,8 @@ def check_replay_pressure() -> None:
pass_limit=pass_limit,
max_payload_bytes=max_payload_bytes,
check_admission=check_replay_pressure,
+ expected_exception_components=expected_exception_components,
+ observed_exception_components=observed_exception_components,
)
if pass_receipt.candidate_count != 0:
raise RuntimeError("raw-authority scale proof lost quiescence during fixed-point confirmation")
@@ -1008,6 +1125,22 @@ def check_replay_pressure() -> None:
fixed_point_digests.append(digest)
if fixed_point_digests[0] != fixed_point_digests[1] or not pass_receipts[-1].fixed_point:
raise RuntimeError("raw-authority scale proof did not reach two matching quiescent fixed-point censuses")
+ expected_exception_count = sum(sibling_count > 0 for _direct_count, sibling_count in component_shape)
+ observed_exception_count = sum(item.plan_status_counts[expected_exception_status.value] for item in pass_receipts)
+ other_exception_status = (
+ RawReplayPlanStatus.DEFERRED
+ if expected_exception_status is RawReplayPlanStatus.TERMINAL
+ else RawReplayPlanStatus.TERMINAL
+ )
+ unexpected_exception_count = sum(
+ item.plan_status_counts[other_exception_status.value]
+ + item.plan_status_counts[RawReplayPlanStatus.REJECTED_STALE.value]
+ for item in pass_receipts
+ )
+ if observed_exception_count != expected_exception_count or unexpected_exception_count:
+ raise RuntimeError(
+ "raw-authority scale proof terminal classification disagrees with the requested synthetic topology"
+ )
profile_id = (
f"workload-profile:synthetic-raw-authority:{scenario.components}:"
f"{scenario.direct_candidates}:{scenario.expanded_candidates}"
diff --git a/devtools/reconcile_tracker_authority.py b/devtools/reconcile_tracker_authority.py
deleted file mode 100644
index a348be09cf..0000000000
--- a/devtools/reconcile_tracker_authority.py
+++ /dev/null
@@ -1,244 +0,0 @@
-"""Apply the declared GitHub/Beads authority map to the live Beads database.
-
-The GitHub issue mutations are performed through GitHub itself. This command updates the
-repo-local Beads authority from ``devtools/data/tracker-authority.json`` without trusting the
-possibly stale checked-in JSONL snapshot:
-
-1. export the current live Dolt-backed Beads state;
-2. mutate only named rows;
-3. give changed rows a fresh ``updated_at`` revision;
-4. apply them through ``bd_reimport_guard.py reconcile`` so downgrades and incomparable rows
- are refused and a receipt is written;
-5. let the guard re-export ``.beads/issues.jsonl`` from the resulting live state.
-
-Default mode is a dry run. Pass ``--apply`` to mutate Beads.
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import subprocess
-import sys
-import tempfile
-from datetime import UTC, datetime
-from pathlib import Path
-from typing import Any
-
-ROOT = Path(__file__).resolve().parent.parent
-MANIFEST_PATH = ROOT / "devtools" / "data" / "tracker-authority.json"
-GUARD_PATH = ROOT / "devtools" / "bd_reimport_guard.py"
-
-_MARKER_START = ""
-_MARKER_END = ""
-_RELATION_LABELS = {
- "gh_mirror": "tracker:gh-mirror",
- "gh_public_parent": "tracker:gh-public-parent",
- "gh_implements": "tracker:gh-implements",
- "gh_supersedes_scope": "tracker:gh-supersedes-scope",
- "internal_only": "tracker:internal-only",
-}
-
-
-def _run(command: list[str]) -> subprocess.CompletedProcess[str]:
- return subprocess.run(command, cwd=ROOT, check=True, capture_output=True, text=True)
-
-
-def _export_live_rows() -> dict[str, dict[str, Any]]:
- with tempfile.NamedTemporaryFile(suffix=".jsonl", delete=False) as handle:
- export_path = Path(handle.name)
- try:
- _run([sys.executable, str(GUARD_PATH), "export", str(export_path)])
- rows: dict[str, dict[str, Any]] = {}
- for line_number, line in enumerate(export_path.read_text().splitlines(), start=1):
- if not line.strip():
- continue
- row = json.loads(line)
- issue_id = row.get("id")
- if not isinstance(issue_id, str) or not issue_id:
- raise ValueError(f"export line {line_number} has no issue id")
- rows[issue_id] = row
- return rows
- finally:
- export_path.unlink(missing_ok=True)
-
-
-def _load_manifest(path: Path) -> dict[str, Any]:
- payload = json.loads(path.read_text())
- if not isinstance(payload, dict):
- raise ValueError(f"tracker authority manifest is not a JSON object: {type(payload).__name__}")
- if payload.get("version") != 1:
- raise ValueError(f"unsupported manifest version: {payload.get('version')!r}")
- bindings = payload.get("bindings")
- if not isinstance(bindings, list) or not bindings:
- raise ValueError("tracker authority manifest has no bindings")
- return payload
-
-
-def _normalise_labels(value: Any) -> list[str]:
- if value is None:
- return []
- if isinstance(value, str):
- return [part.strip() for part in value.split(",") if part.strip()]
- if not isinstance(value, list):
- raise ValueError(f"unsupported labels shape: {type(value).__name__}")
- labels: list[str] = []
- for item in value:
- if isinstance(item, str):
- labels.append(item)
- elif isinstance(item, dict) and isinstance(item.get("name"), str):
- labels.append(item["name"])
- else:
- raise ValueError(f"unsupported label entry: {item!r}")
- return labels
-
-
-def _replace_authority_note(existing: Any, block: str) -> str:
- text = existing if isinstance(existing, str) else ""
- while _MARKER_START in text:
- start = text.index(_MARKER_START)
- end = text.find(_MARKER_END, start)
- if end < 0:
- text = text[:start].rstrip()
- break
- text = (text[:start] + text[end + len(_MARKER_END) :]).strip()
- if text:
- return f"{text.rstrip()}\n\n{block}\n"
- return f"{block}\n"
-
-
-def _authority_block(binding: dict[str, Any]) -> str:
- issue = binding.get("github_issue")
- relation = binding["relation"]
- note = binding.get("note", "")
- lines = [
- _MARKER_START,
- f"Tracker relation: {relation}; public GitHub outcome: #{issue}.",
- ]
- if note:
- lines.append(str(note))
- lines.append(_MARKER_END)
- return "\n".join(lines)
-
-
-def _apply_binding(row: dict[str, Any], binding: dict[str, Any], *, timestamp: str) -> list[str]:
- changes: list[str] = []
- relation = binding.get("relation")
- if relation not in _RELATION_LABELS:
- raise ValueError(f"unknown tracker relation {relation!r} for {binding.get('bead_id')}")
-
- labels = _normalise_labels(row.get("labels"))
- relation_labels = set(_RELATION_LABELS.values())
- desired_label = _RELATION_LABELS[relation]
- new_labels = [label for label in labels if label not in relation_labels]
- if desired_label not in new_labels:
- new_labels.append(desired_label)
- new_labels = sorted(dict.fromkeys(new_labels))
- if new_labels != labels:
- row["labels"] = new_labels
- changes.append(f"labels -> add {desired_label}")
-
- for field in ("external_ref", "title", "description", "acceptance_criteria"):
- if field not in binding:
- continue
- desired = binding[field]
- if row.get(field) != desired:
- row[field] = desired
- changes.append(f"{field} updated")
-
- block = _authority_block(binding)
- notes = _replace_authority_note(row.get("notes"), block)
- if notes != row.get("notes"):
- row["notes"] = notes
- changes.append("tracker authority note updated")
-
- if changes:
- row["updated_at"] = timestamp
- return changes
-
-
-def _write_candidate(rows: dict[str, dict[str, Any]]) -> Path:
- with tempfile.NamedTemporaryFile(mode="w", suffix=".jsonl", delete=False) as handle:
- path = Path(handle.name)
- for issue_id in sorted(rows):
- handle.write(json.dumps(rows[issue_id], sort_keys=True) + "\n")
- return path
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument(
- "--apply",
- action="store_true",
- help="apply the candidate through the monotonic Beads guard",
- )
- parser.add_argument(
- "--manifest",
- type=Path,
- default=MANIFEST_PATH,
- help="authority manifest path",
- )
- args = parser.parse_args(argv)
-
- manifest = _load_manifest(args.manifest.resolve())
- live_rows = _export_live_rows()
- timestamp = datetime.now(UTC).isoformat().replace("+00:00", "Z")
-
- changed: dict[str, dict[str, Any]] = {}
- missing: list[str] = []
- report: list[tuple[str, list[str]]] = []
- for raw_binding in manifest["bindings"]:
- binding = dict(raw_binding)
- bead_id = binding.get("bead_id")
- if not isinstance(bead_id, str) or not bead_id:
- raise ValueError(f"invalid binding without bead_id: {binding!r}")
- original = live_rows.get(bead_id)
- if original is None:
- missing.append(bead_id)
- continue
- candidate = json.loads(json.dumps(original))
- changes = _apply_binding(candidate, binding, timestamp=timestamp)
- report.append((bead_id, changes))
- if changes:
- changed[bead_id] = candidate
-
- coherent_count = len(report) - len(changed)
- print(f"tracker authority: {len(changed)} changed, {coherent_count} already coherent")
- for bead_id, changes in report:
- if changes:
- print(f" {bead_id}: " + "; ".join(changes))
- if missing:
- print("missing target beads: " + ", ".join(sorted(missing)), file=sys.stderr)
- return 2
-
- if not changed:
- return 0
- if not args.apply:
- print("dry run only; rerun with --apply to mutate live Beads")
- return 0
-
- candidate_path = _write_candidate(changed)
- try:
- result = subprocess.run(
- [
- sys.executable,
- str(GUARD_PATH),
- "reconcile",
- str(candidate_path),
- "--source",
- "tracker-authority-v1",
- ],
- cwd=ROOT,
- text=True,
- )
- if result.returncode != 0:
- return result.returncode
- finally:
- candidate_path.unlink(missing_ok=True)
-
- print("tracker authority applied; .beads/issues.jsonl re-exported by the guard")
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/regenerate_acceptance_contracts.py b/devtools/regenerate_acceptance_contracts.py
deleted file mode 100644
index a33efebd0d..0000000000
--- a/devtools/regenerate_acceptance_contracts.py
+++ /dev/null
@@ -1,138 +0,0 @@
-"""Regenerate the exact typed acceptance-contract snapshot without invoking bd."""
-
-from __future__ import annotations
-
-import argparse
-import hashlib
-from collections.abc import Iterable
-from pathlib import Path
-from typing import Any
-
-from devtools import beads_acceptance_contracts as contracts
-from devtools.acceptance_route_registry import registry_digest
-from polylogue.core.json import dumps as json_dumps
-
-_EVIDENCE_SOURCE_FIELDS = ("title", "description", "design", "notes")
-
-
-def _span(source_field: str, snapshot: str, evidence: str) -> dict[str, Any]:
- start_character = snapshot.find(evidence)
- if start_character < 0:
- raise ValueError(f"evidence is not a substring of Bead {source_field} source field")
- start = len(snapshot[:start_character].encode("utf-8"))
- encoded = snapshot.encode("utf-8")
- evidence_bytes = evidence.encode("utf-8")
- snapshot_digest = hashlib.sha256(encoded).hexdigest()
- return {
- "source_field": source_field,
- "snapshot": snapshot,
- "snapshot_digest": snapshot_digest,
- "range": {"start": start, "end": start + len(evidence_bytes)},
- "text_digest": hashlib.sha256(evidence_bytes).hexdigest(),
- }
-
-
-def _evidence_span(issue: dict[str, Any], evidence: str) -> dict[str, Any]:
- for source_field in _EVIDENCE_SOURCE_FIELDS:
- snapshot = issue.get(source_field)
- if isinstance(snapshot, str) and evidence in snapshot:
- return _span(source_field, snapshot, evidence)
- raise ValueError(f"{issue.get('id')}: evidence is not present in a title, description, design, or notes field")
-
-
-def _route_entry(issue: dict[str, Any], contract: dict[str, Any]) -> dict[str, Any]:
- contract_type = contract["contract_type"]
- dispatch = next(iter(contracts._ROUTE_DISPATCH_BY_TYPE[contract_type]))
- identifier = f"acceptance/{issue['id']}"
- return {
- "identifier": identifier,
- "bead_id": issue["id"],
- "contract_type": contract_type,
- "class": contracts._ROUTE_CLASS_BY_TYPE[contract_type],
- "dispatch": dispatch,
- "targets": list(contract["routes"]),
- }
-
-
-def regenerate(
- rows: list[dict[str, Any]], required_ids: Iterable[str]
-) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
- required = set(required_ids)
- routes: list[dict[str, Any]] = []
- output: list[dict[str, Any]] = []
- for issue in rows:
- if issue.get("id") not in required:
- output.append(issue)
- continue
- metadata = issue.get("metadata")
- if not isinstance(metadata, dict) or not isinstance(metadata.get("acceptance_contract_v1"), dict):
- raise ValueError(f"{issue.get('id')}: missing acceptance_contract_v1")
- contract = metadata["acceptance_contract_v1"]
- route = _route_entry(issue, contract)
- contract["route_spec"] = {
- "mode": "named",
- "identifier": route["identifier"],
- "class": route["class"],
- "dispatch": route["dispatch"],
- }
- if contract.get("contract_type") in {"implementation", "test_harness"}:
- contract["verification_route"] = {
- "manager": "devtools",
- "focused": "devtools test",
- "default": "devtools verify",
- }
- contract["evidence_spans"] = [_evidence_span(issue, value) for value in contract.get("evidence", [])]
- if contract.get("contract_type") == "live_operation":
- contract["receipt"] = {
- "kind": "live-operation",
- "requirement": "required",
- "bindings": sorted(contracts._REQUIRED_RECEIPT_BINDINGS),
- }
- contract["source_digest"] = contracts.source_digest(issue)
- contract["dependency_digest"] = contracts.dependency_digest(issue)
- issue["acceptance_criteria"] = contracts.render(contract)
- routes.append(route)
- output.append(issue)
- if {issue.get("id") for issue in output if issue.get("id") in required} != required:
- raise ValueError("canonical snapshot does not contain every manifest id")
- return output, routes
-
-
-def _write_jsonl(path: Path, rows: Iterable[dict[str, Any]]) -> None:
- path.write_text("".join(json_dumps(row, sort_keys=True) + "\n" for row in rows), encoding="utf-8")
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--issues", type=Path, default=Path(".beads/issues.jsonl"))
- parser.add_argument("--manifest", type=Path, default=contracts._DEFAULT_MANIFEST)
- parser.add_argument("--registry", type=Path, default=Path("docs/plans/beads-acceptance-route-registry.json"))
- args = parser.parse_args(argv)
- rows = contracts.load(args.issues)
- required = contracts.load_manifest(args.manifest)
- regenerated, routes = regenerate(rows, required)
- registry_document = {
- "schema_version": 1,
- "manifest_count": len(required),
- "manifest_digest": contracts._EXPECTED_MANIFEST_DIGEST,
- "routes": sorted(routes, key=lambda route: route["identifier"]),
- }
- args.registry.parent.mkdir(parents=True, exist_ok=True)
- args.registry.write_text(json_dumps(registry_document, indent=2, sort_keys=True) + "\n", encoding="utf-8")
- _write_jsonl(args.issues, regenerated)
- print(
- json_dumps(
- {
- "ok": True,
- "records": len(required),
- "registry_routes": len(routes),
- "registry_digest": registry_digest({route["identifier"]: route for route in routes}),
- },
- sort_keys=True,
- )
- )
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/reindex_canary.py b/devtools/reindex_canary.py
deleted file mode 100644
index fd796062eb..0000000000
--- a/devtools/reindex_canary.py
+++ /dev/null
@@ -1,28 +0,0 @@
-"""Developer-tool adapter for the product reindex canary command."""
-
-from __future__ import annotations
-
-import sys
-
-from devtools.cli_boundary import invoke_polylogue_cli
-from polylogue.scenarios import polylogue_execution
-
-
-def main(argv: list[str] | None = None) -> int:
- """Delegate to the real product CLI without reimplementing rebuild logic."""
-
- forwarded = list(argv or ())
- if "--json" in forwarded:
- forwarded.remove("--json")
- if "--output-format" not in forwarded:
- forwarded.extend(("--output-format", "json"))
- result = invoke_polylogue_cli(
- polylogue_execution("ops", "maintenance", "reindex-canary", *forwarded),
- )
- sys.stdout.write(result.stdout)
- sys.stderr.write(result.stderr)
- return result.exit_code
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/release_readiness.py b/devtools/release_readiness.py
deleted file mode 100644
index 88ab2d660d..0000000000
--- a/devtools/release_readiness.py
+++ /dev/null
@@ -1,275 +0,0 @@
-"""Validate the externally-presentable release gate definition (#1827)."""
-
-from __future__ import annotations
-
-import argparse
-import json
-import re
-from dataclasses import dataclass
-from pathlib import Path
-from typing import Any
-
-ROOT = Path(__file__).resolve().parents[1]
-GATE_DOC = ROOT / "docs" / "plans" / "release-readiness-gate.md"
-
-
-@dataclass(frozen=True, slots=True)
-class GateCommand:
- argv: tuple[str, ...]
- required: bool
- reason: str
-
- def to_dict(self) -> dict[str, Any]:
- return {"argv": list(self.argv), "required": self.required, "reason": self.reason}
-
-
-REQUIRED_COMMANDS: tuple[GateCommand, ...] = (
- GateCommand(("devtools", "release", "readiness"), True, "release gate definition"),
- GateCommand(("devtools", "verify", "--quick"), True, "static/generated baseline"),
- GateCommand(("devtools", "verify", "public-claims"), True, "generated public-claims projection"),
- GateCommand(("devtools", "verify", "--lab"), True, "lab baseline"),
- GateCommand(("devtools", "release", "build-package"), True, "wheel/sdist/Nix package smoke"),
- GateCommand(("devtools", "render", "pages"), True, "documentation site build"),
- GateCommand(("devtools", "verify doc-commands"), True, "README/docs command examples"),
-)
-
-FOCUSED_COMMANDS: tuple[GateCommand, ...] = (
- GateCommand(
- ("devtools", "test", "tests/unit/cli/test_query_verbs_runtime.py"),
- False,
- "command/read surface changed",
- ),
- GateCommand(
- ("devtools", "test", "tests/unit/storage/test_blackboard_facade.py"),
- False,
- "user assertion/KV surface changed",
- ),
- GateCommand(
- (
- "devtools",
- "test",
- "tests/unit/cli/test_demo_command.py",
- "tests/unit/demo/test_demo_seed_verify.py",
- "tests/visual",
- ),
- False,
- "demo or reader visual surfaces changed",
- ),
- GateCommand(("nix", "flake", "check"), False, "packaging, Nix, or dependency metadata changed"),
-)
-
-REQUIRED_DOC_HEADINGS: tuple[str, ...] = (
- "## Gate Rule",
- "## Required Local Commands",
- "## Automated Gate Matrix",
- "## Manual Release Review",
- "## Current Status",
- "## Release PR Body Requirements",
-)
-
-REQUIRED_RELEASE_BODY_HEADINGS: tuple[str, ...] = ("Release gate:", "Verification:")
-
-REQUIRED_RELEASE_BODY_FIELDS: tuple[str, ...] = (
- "- Command floor:",
- "- Machine output:",
- "- README/demo:",
- "- Import/demo fixture:",
- "- Session digest/context:",
- "- Web/API scope:",
- "- Packaging:",
- "- Known caveats scoped out:",
-)
-
-STATUS_SATISFIED_HEADING = "Satisfied:"
-STATUS_BLOCKING_HEADING = "Still blocking external release claims:"
-RETIRED_ISSUE_REFS = ("#1839",)
-_STATUS_CAVEAT_RE = re.compile(
- r"\b(do not advertise|scoped out|unless|if the release claims|if claimed|caveat)\b", re.I
-)
-_ISSUE_REF_RE = re.compile(r"#\d+")
-
-
-def _status_list(text: str, *, heading: str) -> list[str]:
- """Extract top-level bullet lines under a release-status heading."""
-
- if heading not in text:
- return []
- after_heading = text.split(heading, 1)[1]
- bullets: list[str] = []
- for line in after_heading.splitlines():
- if line.startswith("## ") or (line in {STATUS_SATISFIED_HEADING, STATUS_BLOCKING_HEADING} and line != heading):
- break
- if line.startswith("- "):
- bullets.append(line[2:].strip())
- elif bullets and line.startswith(" "):
- bullets[-1] = f"{bullets[-1]} {line.strip()}"
- return bullets
-
-
-def _issue_refs(lines: list[str]) -> set[str]:
- refs: set[str] = set()
- for line in lines:
- refs.update(_ISSUE_REF_RE.findall(line))
- return refs
-
-
-def _catalog_command_name(argv: tuple[str, ...], commands: set[str]) -> str:
- """Return the devtools command path before command-local arguments."""
-
- command_parts: list[str] = []
- for part in argv[1:]:
- if part.startswith("-"):
- break
- command_parts.append(part)
- for end in range(len(command_parts), 0, -1):
- candidate = " ".join(command_parts[:end])
- if candidate in commands:
- return candidate
- return " ".join(command_parts)
-
-
-def _read_text_file(path: Path, *, label: str, errors: list[str]) -> str | None:
- try:
- return path.read_text(encoding="utf-8")
- except OSError as exc:
- errors.append(f"could not read {label}: {path}: {exc}")
- return None
-
-
-def _validate_release_body(text: str, *, errors: list[str]) -> dict[str, Any]:
- missing_headings = [heading for heading in REQUIRED_RELEASE_BODY_HEADINGS if heading not in text]
- missing_fields = [field for field in REQUIRED_RELEASE_BODY_FIELDS if field not in text]
- for heading in missing_headings:
- errors.append(f"release PR body missing heading: {heading}")
- for field in missing_fields:
- errors.append(f"release PR body missing field: {field}")
- return {
- "checked": True,
- "missing_headings": missing_headings,
- "missing_fields": missing_fields,
- }
-
-
-def build_report(
- *,
- gate_doc: Path = GATE_DOC,
- release_body_file: Path | None = None,
- release_body_text: str | None = None,
-) -> dict[str, Any]:
- """Return a JSON-serializable release-gate definition report."""
- from devtools.command_catalog import COMMANDS
-
- errors: list[str] = []
- text = gate_doc.read_text(encoding="utf-8") if gate_doc.exists() else ""
- satisfied = _status_list(text, heading=STATUS_SATISFIED_HEADING)
- blocking = _status_list(text, heading=STATUS_BLOCKING_HEADING)
- if not text:
- errors.append(f"missing gate document: {gate_doc}")
-
- for heading in REQUIRED_DOC_HEADINGS:
- if heading not in text:
- errors.append(f"gate document missing heading: {heading}")
- for heading in REQUIRED_RELEASE_BODY_HEADINGS:
- if heading not in text:
- errors.append(f"release PR template missing heading: {heading}")
- for field in REQUIRED_RELEASE_BODY_FIELDS:
- if field not in text:
- errors.append(f"release PR template missing field: {field}")
-
- for command in (*REQUIRED_COMMANDS, *FOCUSED_COMMANDS):
- command_text = " ".join(command.argv)
- if command.required and command_text not in text:
- errors.append(f"required command missing from gate document: {command_text}")
- if command.argv[0] == "devtools" and _catalog_command_name(command.argv, set(COMMANDS)) not in COMMANDS:
- errors.append(f"unknown devtools command in release gate: {command_text}")
-
- if STATUS_SATISFIED_HEADING not in text:
- errors.append("gate document missing satisfied release-status list")
- if STATUS_BLOCKING_HEADING not in text:
- errors.append("gate document missing blocking release-status list")
- for retired_ref in RETIRED_ISSUE_REFS:
- if retired_ref in text:
- errors.append(f"release gate references retired issue: {retired_ref}")
-
- satisfied_refs = _issue_refs(satisfied)
- for line in blocking:
- overlapping_refs = sorted(satisfied_refs.intersection(_ISSUE_REF_RE.findall(line)))
- if overlapping_refs and _STATUS_CAVEAT_RE.search(line) is None:
- errors.append(
- "blocking release-status line also cites satisfied issue(s) "
- f"{', '.join(overlapping_refs)} without scoped-out/caveat wording"
- )
-
- release_body_report: dict[str, Any] = {"checked": False}
- if release_body_text is not None and release_body_file is not None:
- errors.append("pass either release_body_text or release_body_file, not both")
- elif release_body_text is not None:
- release_body_report = _validate_release_body(release_body_text, errors=errors)
- elif release_body_file is not None:
- body_text = _read_text_file(release_body_file, label="release PR body", errors=errors)
- if body_text is not None:
- release_body_report = _validate_release_body(body_text, errors=errors)
- release_body_report["path"] = str(release_body_file)
-
- return {
- "ok": not errors,
- "gate_doc": str(gate_doc.relative_to(ROOT) if gate_doc.is_relative_to(ROOT) else gate_doc),
- "required_commands": [command.to_dict() for command in REQUIRED_COMMANDS],
- "focused_commands": [command.to_dict() for command in FOCUSED_COMMANDS],
- "required_release_body_headings": list(REQUIRED_RELEASE_BODY_HEADINGS),
- "required_release_body_fields": list(REQUIRED_RELEASE_BODY_FIELDS),
- "release_body": release_body_report,
- "release_status": {
- "satisfied": satisfied,
- "blocking_external_claims": blocking,
- },
- "errors": errors,
- }
-
-
-def _print_human(report: dict[str, Any]) -> None:
- status = "ok" if report["ok"] else "FAIL"
- print(f"release readiness: {status}")
- print(f"gate doc: {report['gate_doc']}")
- print("required commands:")
- for command in report["required_commands"]:
- print(f" {' '.join(command['argv'])} # {command['reason']}")
- print("focused commands:")
- for command in report["focused_commands"]:
- print(f" {' '.join(command['argv'])} # {command['reason']}")
- print("release status:")
- print(f" satisfied: {len(report['release_status']['satisfied'])}")
- print(f" blocking external claims: {len(report['release_status']['blocking_external_claims'])}")
- body = report.get("release_body")
- if isinstance(body, dict) and body.get("checked"):
- print("release PR body: checked")
- if body.get("missing_headings"):
- print(f" missing headings: {len(body['missing_headings'])}")
- if body.get("missing_fields"):
- print(f" missing fields: {len(body['missing_fields'])}")
- if report["errors"]:
- print("errors:")
- for error in report["errors"]:
- print(f" - {error}")
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--json", action="store_true", help="Emit the gate-definition report as JSON.")
- parser.add_argument(
- "--release-body-file",
- type=Path,
- help="Validate an actual release PR body against the gate evidence template.",
- )
- args = parser.parse_args(argv)
-
- report = build_report(release_body_file=args.release_body_file)
- if args.json:
- print(json.dumps(report, indent=2, sort_keys=True))
- else:
- _print_human(report)
- return 0 if report["ok"] else 1
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/render_agent_manual.py b/devtools/render_agent_manual.py
index 45f659627b..31007232da 100644
--- a/devtools/render_agent_manual.py
+++ b/devtools/render_agent_manual.py
@@ -385,12 +385,12 @@ def render_deep_reference() -> str:
)
for resource in TARGET_RESOURCES:
lines.append(
- f"- `{resource.uri_template}` — objects {', '.join(resource.object_kinds)}; required capability `{resource.required_capability or 'read'}`; owner `{resource.migration_owner}`; {resource.authority}."
+ f"- `{resource.uri_template}` — objects {', '.join(resource.object_kinds)}; required capability `{resource.required_capability or 'read'}`; {resource.authority}."
)
lines.extend(["", "### Workflow prompts", ""])
for prompt in TARGET_PROMPTS:
lines.append(
- f"- `{prompt.name}` — workflow `{prompt.workflow}`; required capability `{prompt.required_capability or 'read'}`; mutation authority `{prompt.mutation_authority}`; owner `{prompt.migration_owner}`."
+ f"- `{prompt.name}` — workflow `{prompt.workflow}`; required capability `{prompt.required_capability or 'read'}`; mutation authority `{prompt.mutation_authority}`."
)
lines.extend(["", "## Source origins", ""])
for origin in ORIGIN_MEANINGS:
diff --git a/devtools/render_api_operation_parity.py b/devtools/render_api_operation_parity.py
deleted file mode 100644
index 6482101ce9..0000000000
--- a/devtools/render_api_operation_parity.py
+++ /dev/null
@@ -1,191 +0,0 @@
-"""Render and verify the semantic-operation parity map for the Python API."""
-
-from __future__ import annotations
-
-import argparse
-import json
-import sys
-from collections import defaultdict
-from dataclasses import asdict
-from pathlib import Path
-
-from devtools.command_catalog import control_plane_command
-from devtools.render_support import write_if_changed
-from polylogue.api.operation_parity import (
- API_EXCLUSIONS,
- API_OPERATIONS,
- API_PARITY_AUTHORITY,
- ApiOperation,
- SurfaceBinding,
- facade_callable_records,
- validate_live_facade,
-)
-
-DEFAULT_OUTPUT_PATH = Path("docs/generated/api-operation-parity.json")
-DEFAULT_LIBRARY_API_PATH = Path("docs/library-api.md")
-SCHEMA_VERSION = 1
-BEGIN_MARKER = ""
-END_MARKER = ""
-
-
-def _binding_payload(binding: SurfaceBinding) -> dict[str, object]:
- names = binding.names
- absence = binding.intentional_absence_authority
- return {"names": list(names), "intentional_absence_authority": absence}
-
-
-def build_parity_payload() -> dict[str, object]:
- """Build the committed machine-readable operation matrix."""
-
- validate_live_facade()
- records = {
- binding: {"signature": signature, "async": is_async}
- for binding, signature, is_async in facade_callable_records()
- }
- operations: list[dict[str, object]] = []
- for operation in API_OPERATIONS:
- operations.append(
- {
- "operation_id": operation.operation_id,
- "section": operation.section,
- "summary": operation.summary,
- "route_class": operation.route_class,
- "python": [{"binding": binding, **records.get(binding, {})} for binding in operation.python_bindings],
- "cli": _binding_payload(operation.cli),
- "mcp": _binding_payload(operation.mcp),
- }
- )
- return {
- "schema_version": SCHEMA_VERSION,
- "generated_by": control_plane_command("render api-operation-parity"),
- "authority": {
- "operation_declarations": "polylogue/api/operation_parity.py",
- "drift_owner": API_PARITY_AUTHORITY,
- "facade": "polylogue.api.Polylogue",
- "documentation": "docs/library-api.md",
- },
- "operation_count": len(operations),
- "operations": operations,
- "exclusions": [asdict(exclusion) for exclusion in API_EXCLUSIONS],
- }
-
-
-def render_parity_output() -> str:
- return json.dumps(build_parity_payload(), indent=2, sort_keys=True, ensure_ascii=False) + "\n"
-
-
-def _display_binding(binding: SurfaceBinding) -> str:
- names = binding.names
- absence = binding.intentional_absence_authority
- return ", ".join(f"`{name}`" for name in names) if names else f"Intentional absence: `{absence}`"
-
-
-def render_library_api_section() -> str:
- """Render the signature- and asyncness-aware section in library-api.md."""
-
- validate_live_facade()
- records = {binding: (signature, is_async) for binding, signature, is_async in facade_callable_records()}
- by_section: defaultdict[str, list[ApiOperation]] = defaultdict(list)
- for operation in API_OPERATIONS:
- by_section[operation.section].append(operation)
-
- lines = [
- BEGIN_MARKER,
- "",
- "## Generated facade operation index",
- "",
- "This reference is generated from `polylogue/api/operation_parity.py`. Each live public facade callable is bound to a stable semantic operation ID; exported data models and adapter helpers are listed as intentional exclusions in the committed [machine-readable matrix](generated/api-operation-parity.json).",
- "",
- ]
- for section, operations in by_section.items():
- lines.extend([f"### {section}", ""])
- for operation in operations:
- lines.extend(
- [
- f"#### `{operation.operation_id}`",
- "",
- operation.summary,
- "",
- f"Route/tier class: `{operation.route_class}`. CLI: {_display_binding(operation.cli)}. MCP: {_display_binding(operation.mcp)}.",
- "",
- ]
- )
- lines.extend(["| Python callable | Signature |", "|---|---|"])
- for binding in operation.python_bindings:
- if binding not in records:
- lines.append(f"| `{binding}` | Constructed facade builder |")
- continue
- signature, is_async = records[binding]
- prefix = "async " if is_async else ""
- lines.append(f"| `{binding}` | `{prefix}{signature}` |")
- lines.append("")
- lines.extend(["### Intentional exclusions", "", "| Export | Reason | Authority |", "|---|---|---|"])
- for exclusion in API_EXCLUSIONS:
- lines.append(f"| `{exclusion.binding}` | {exclusion.reason} | `{exclusion.authority}` |")
- lines.extend(["", END_MARKER])
- return "\n".join(lines)
-
-
-def replace_library_api_section(current: str, section: str) -> str:
- """Replace only the generated block, rejecting an unmarked duplicate surface."""
-
- if current.count(BEGIN_MARKER) != 1 or current.count(END_MARKER) != 1:
- raise ValueError("docs/library-api.md must contain exactly one API parity marker pair")
- start = current.index(BEGIN_MARKER)
- end = current.index(END_MARKER, start) + len(END_MARKER)
- return current[:start] + section + current[end:]
-
-
-def render_library_api_output(path: Path) -> str:
- return replace_library_api_section(path.read_text(encoding="utf-8"), render_library_api_section())
-
-
-def validate_library_api_section(contents: str) -> None:
- """Reject a missing, mis-sectioned, stale-signature API reference."""
-
- if contents.count(BEGIN_MARKER) != 1 or contents.count(END_MARKER) != 1:
- raise ValueError("docs/library-api.md must contain exactly one API parity marker pair")
- start = contents.index(BEGIN_MARKER)
- end = contents.index(END_MARKER, start) + len(END_MARKER)
- if contents[start:end] != render_library_api_section():
- raise ValueError("docs/library-api.md generated API parity section does not match live facade signatures")
-
-
-def _check(path: Path, expected: str, label: str) -> bool:
- actual = path.read_text(encoding="utf-8") if path.exists() else ""
- if actual == expected:
- print(f"render api-operation-parity: sync OK: {label}")
- return True
- print(f"render api-operation-parity: out of sync: {label}", file=sys.stderr)
- return False
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description="Render the semantic-operation parity matrix for the Python API.")
- parser.add_argument("--output-path", type=Path, default=DEFAULT_OUTPUT_PATH)
- parser.add_argument("--library-api-path", type=Path, default=DEFAULT_LIBRARY_API_PATH)
- parser.add_argument(
- "--check", action="store_true", help="Exit non-zero when the artifact or API reference is out of sync."
- )
- args = parser.parse_args(argv)
- try:
- parity = render_parity_output()
- library_api = render_library_api_output(args.library_api_path)
- validate_library_api_section(library_api)
- except (ValueError, OSError) as exc:
- print(f"render api-operation-parity: {exc}", file=sys.stderr)
- return 1
- if args.check:
- return (
- 0
- if _check(args.output_path, parity, str(args.output_path))
- and _check(args.library_api_path, library_api, str(args.library_api_path))
- else 1
- )
- write_if_changed(args.output_path, parity)
- write_if_changed(args.library_api_path, library_api)
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/render_cli_output_schemas.py b/devtools/render_cli_output_schemas.py
index f5d23acc09..875852facd 100644
--- a/devtools/render_cli_output_schemas.py
+++ b/devtools/render_cli_output_schemas.py
@@ -84,7 +84,7 @@ class CliOutputSchema:
model=SessionSummaryPayload,
surfaces=(
"polylogue analyze --format json (rows)",
- "polylogue --format json (hits[].session)",
+ "polylogue --format json find (hits[].session)",
),
),
CliOutputSchema(
@@ -118,8 +118,8 @@ class CliOutputSchema:
),
model=SessionSearchHitPayload,
surfaces=(
- "polylogue --format json ",
- "polylogue --format ndjson ",
+ "polylogue --format json find ",
+ "polylogue --format ndjson find ",
),
),
CliOutputSchema(
@@ -134,7 +134,7 @@ class CliOutputSchema:
),
model=SearchEnvelope,
surfaces=(
- "polylogue --format json ",
+ "polylogue --format json find ",
"GET /api/sessions?query=...",
),
),
@@ -165,7 +165,7 @@ class CliOutputSchema:
),
model=QueryUnitAggregateEnvelope,
surfaces=(
- "polylogue --format json messages where ... | group by role | count",
+ 'polylogue --format json find "messages where ... | group by role | count"',
"Polylogue.query_units(...)",
"MCP query_units",
"GET /api/query-units?expression=...",
@@ -274,23 +274,19 @@ class CliOutputSchema:
name="machine-error",
title="Machine Error Envelope",
description=(
- "Standard CLI machine-readable error envelope. Emitted by any "
- "command that ran with `--machine` or otherwise opts into a "
- "JSON error surface."
+ "Standard CLI machine-readable error envelope. Emitted when an invocation requests JSON output and fails."
),
model=MachineErrorPayload,
- surfaces=("polylogue * --machine (error path)",),
+ surfaces=("polylogue --format json find (error path)",),
),
CliOutputSchema(
name="machine-success",
title="Machine Success Envelope",
description=(
- "Standard CLI machine-readable success envelope. Emitted by "
- "commands that ran with `--machine` and produced structured "
- "output."
+ "Standard CLI machine-readable success envelope. Emitted by commands that produce structured JSON output."
),
model=MachineSuccessPayload,
- surfaces=("polylogue * --machine (success path)",),
+ surfaces=("polylogue analyze --format json (success path)",),
),
CliOutputSchema(
name="query-error",
diff --git a/devtools/render_cli_reference.py b/devtools/render_cli_reference.py
index e4118d652e..bf2e2887a0 100644
--- a/devtools/render_cli_reference.py
+++ b/devtools/render_cli_reference.py
@@ -66,8 +66,6 @@ def render_help(command: tuple[str, ...]) -> str:
def build_document(sections: list[tuple[str, str]]) -> str:
- from devtools.action_contract_report import render_action_contract_report
-
parts = [
"[← Back to README](../README.md)",
"",
@@ -80,7 +78,6 @@ def build_document(sections: list[tuple[str, str]]) -> str:
]
for title, body in sections:
parts.extend([f"## {title}", "", "```text", body, "```", ""])
- parts.append(render_action_contract_report())
return "\n".join(parts).rstrip() + "\n"
diff --git a/devtools/render_demo_corpus_datasheet.py b/devtools/render_demo_corpus_datasheet.py
deleted file mode 100644
index 492e122bf9..0000000000
--- a/devtools/render_demo_corpus_datasheet.py
+++ /dev/null
@@ -1,248 +0,0 @@
-"""Render the deterministic demo corpus construct datasheet."""
-
-from __future__ import annotations
-
-import argparse
-import asyncio
-import shutil
-import sys
-from dataclasses import dataclass
-from pathlib import Path
-
-from devtools.command_catalog import control_plane_command
-from devtools.render_support import write_if_changed
-from polylogue.demo import DemoSeedResult, DemoVerifyResult, seed_demo_archive, verify_demo_archive
-from polylogue.scenarios import DEMO_CORPUS_FAMILIES
-from polylogue.storage.sqlite.connection_profile import open_readonly_connection
-from polylogue.storage.sqlite.run_projection_relations import (
- context_snapshot_relation_sql,
- observed_event_relation_sql,
- run_relation_sql,
-)
-
-GENERATED_NOTE = (
- f""
-)
-
-
-@dataclass(frozen=True, slots=True)
-class DemoCorpusMeasurement:
- """SQLite row counts that make the datasheet concrete."""
-
- blocks: int
- origins: tuple[str, ...]
- run_rows: int
- observed_event_rows: int
- context_snapshot_rows: int
-
-
-RESIDUAL_GAPS: tuple[tuple[str, str, str], ...] = (
- ("None", "Every declared construct currently has non-empty seeded coverage.", "—"),
-)
-
-
-def _code_list(items: tuple[str, ...]) -> str:
- if not items:
- return "—"
- return " ".join(f"`{item}`" for item in items)
-
-
-def _measure_archive(archive_root: Path) -> DemoCorpusMeasurement:
- with open_readonly_connection(archive_root / "index.db") as conn:
- origins = tuple(
- str(row[0]) for row in conn.execute("SELECT DISTINCT origin FROM sessions ORDER BY origin").fetchall()
- )
- return DemoCorpusMeasurement(
- blocks=int(conn.execute("SELECT COUNT(*) FROM blocks").fetchone()[0]),
- origins=origins,
- run_rows=int(conn.execute(f"{run_relation_sql()}\nSELECT COUNT(*) FROM runs").fetchone()[0]),
- observed_event_rows=int(
- conn.execute(
- f"{observed_event_relation_sql(source_where='1')}\nSELECT COUNT(*) FROM observed_events"
- ).fetchone()[0]
- ),
- context_snapshot_rows=int(
- conn.execute(f"{context_snapshot_relation_sql()}\nSELECT COUNT(*) FROM context_snapshots").fetchone()[0]
- ),
- )
-
-
-async def seed_datasheet_archive(work_root: Path) -> tuple[DemoSeedResult, DemoVerifyResult, DemoCorpusMeasurement]:
- """Build the deterministic demo archive used to render this datasheet."""
-
- archive_root = work_root / "archive"
- if archive_root.exists():
- shutil.rmtree(archive_root)
- seed = await seed_demo_archive(archive_root, force=True, with_overlays=True)
- verify = verify_demo_archive(archive_root, require_overlays=True)
- measurement = _measure_archive(archive_root)
- return seed, verify, measurement
-
-
-def _render_family_table() -> list[str]:
- lines = [
- "| Family | Provider | Source paths | Construct IDs | Synthetic |",
- "| --- | --- | --- | --- | --- |",
- ]
- for family in DEMO_CORPUS_FAMILIES:
- lines.append(
- f"| `{family.family_id}` | `{family.provider}` | {_code_list(family.source_paths)} | "
- f"{_code_list(family.construct_ids)} | `{str(family.synthetic).lower()}` |"
- )
- return lines
-
-
-def _render_construct_table(seed: DemoSeedResult) -> list[str]:
- lines = [
- "| Construct | Required coverage | Status |",
- "| --- | ---: | --- |",
- ]
- for row in seed.construct_coverage:
- status = "ok" if row.ok else "missing"
- lines.append(f"| {row.label} (`{row.construct_id}`) | >= {row.minimum} | `{status}` |")
- return lines
-
-
-def _render_residual_table() -> list[str]:
- lines = [
- "| Gap | Current evidence | Driver beads |",
- "| --- | --- | --- |",
- ]
- for gap, evidence, beads in RESIDUAL_GAPS:
- lines.append(f"| {gap} | {evidence} | {beads} |")
- return lines
-
-
-def build_document(
- seed: DemoSeedResult,
- verify: DemoVerifyResult,
- measurement: DemoCorpusMeasurement,
-) -> str:
- """Render the datasheet from declared families plus measured archive rows."""
-
- parts = [
- "# Demo Corpus Construct Audit",
- "",
- GENERATED_NOTE,
- "",
- "This datasheet is generated from the deterministic demo family registry, "
- "the declared construct registry, and a fresh no-daemon seed/verify run. "
- "It exists to keep demo claims construct-valid instead of relying on a "
- "hand-maintained table.",
- "",
- "## Evidence Snapshot",
- "",
- f"- Seed command: `{control_plane_command('render demo-corpus-datasheet')}` "
- "seeds a throwaway archive under `.cache/demo-corpus-datasheet/archive` "
- "with overlays enabled.",
- "- Verifier: `polylogue demo verify --require-overlays` semantics via `verify_demo_archive`.",
- f"- Verifier result: `{'ok' if verify.ok else 'failed'}`.",
- f"- Problems: {'—' if not verify.problems else '; '.join(verify.problems)}",
- "",
- "## Current Demo Archive Coverage",
- "",
- "| Fact | Current |",
- "| --- | ---: |",
- f"| Sessions | {seed.session_count} |",
- f"| Messages | {seed.message_count} indexed |",
- f"| Blocks | {measurement.blocks} |",
- f"| Session profiles | {next((row.observed for row in seed.construct_coverage if row.construct_id == 'session_profiles'), 0)} |",
- f"| Origins | {', '.join(measurement.origins)} |",
- f"| Run rows | {measurement.run_rows} |",
- f"| Observed-event rows | {measurement.observed_event_rows} |",
- f"| Context-snapshot rows | {measurement.context_snapshot_rows} |",
- "",
- "## Declared Source Families",
- "",
- *_render_family_table(),
- "",
- "## Declared Construct Coverage",
- "",
- *_render_construct_table(seed),
- "",
- "## Interpretation Notes",
- "",
- "- Families go through normal parser/storage paths; the demo does not patch rows directly into the index tier.",
- "- Codex `forked_from_id` is measured as a generic `branch` link with "
- "`prefix-sharing` inheritance because source evidence proves parentage "
- "and shared prefix, not fork-vs-resume.",
- "- Claude Code `agent-acompact-*` measures a continuation link and "
- "compaction event; the sidechain source measures typed sidechain session "
- "state.",
- "- Browser-capture convergence is measured across `source.db` and "
- "`index.db`: three raw observations for the same ChatGPT native id remain "
- "durable while the canonical indexed session stays singular and raw-linked.",
- "- Resume/abandonment demo coverage is grounded in structural "
- "`session_profiles.terminal_state` values (`question_left`, `tool_left`, "
- "`error_left`). The demo intentionally does not invent a source-declared "
- "`abandoned` or `censored` flag.",
- "- Parent-side subagent runs use distinct `run_ref` values from the child "
- "session's own main run, so both execution views can coexist.",
- "- Embedding coverage uses deterministic synthetic vectors over authored "
- "demo prose; it proves non-empty embedding-tier/status surfaces without "
- "contacting an external provider.",
- "",
- "## Residual Gaps",
- "",
- *_render_residual_table(),
- "",
- ]
- return "\n".join(parts)
-
-
-def render_datasheet(*, work_root: Path) -> str:
- seed, verify, measurement = asyncio.run(seed_datasheet_archive(work_root.resolve()))
- rendered = build_document(seed, verify, measurement)
- if not rendered.endswith("\n"):
- rendered += "\n"
- return rendered
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description="Render the deterministic demo corpus construct datasheet.")
- parser.add_argument(
- "--output",
- default="docs/plans/demo-corpus-construct-audit.md",
- help="Output file path or '-' for stdout (default: docs/plans/demo-corpus-construct-audit.md)",
- )
- parser.add_argument(
- "--work-root",
- default=".cache/demo-corpus-datasheet",
- help="Scratch root for the throwaway measured demo archive.",
- )
- parser.add_argument("--check", action="store_true", help="Exit non-zero when the output is out of sync.")
- args = parser.parse_args(argv)
-
- rendered = render_datasheet(work_root=Path(args.work_root))
-
- if args.output == "-":
- if args.check:
- print("render demo-corpus-datasheet: --check does not support --output -", file=sys.stderr)
- return 2
- sys.stdout.write(rendered)
- return 0
-
- output_path = Path(args.output).expanduser().resolve()
- if args.check:
- try:
- current = output_path.read_text(encoding="utf-8")
- except FileNotFoundError:
- current = ""
- if current != rendered:
- print(f"render demo-corpus-datasheet: out of sync: {output_path}", file=sys.stderr)
- print(
- f"render demo-corpus-datasheet: run: {control_plane_command('render demo-corpus-datasheet')}",
- file=sys.stderr,
- )
- return 1
- print("render demo-corpus-datasheet: sync OK")
- return 0
-
- write_if_changed(output_path, rendered)
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/render_devtools_reference.py b/devtools/render_devtools_reference.py
index 3eba7321e9..b8a496d8a7 100644
--- a/devtools/render_devtools_reference.py
+++ b/devtools/render_devtools_reference.py
@@ -7,8 +7,6 @@
from pathlib import Path
from devtools.command_catalog import (
- CATALOG_BYPASS_SITES,
- WORKSPACE_COMMAND_DISPOSITIONS,
CommandSpec,
control_plane_command,
featured_command_specs,
@@ -67,40 +65,6 @@ def _render_verification_lab_surface(commands: tuple[CommandSpec, ...]) -> list[
return lines
-def _render_workspace_dispositions() -> list[str]:
- lines = [
- "## Workspace disposition audit",
- "",
- "The utf.1 triage retains workspace commands with operator history, reusable output, or focused tests. "
- "The stale archive-schema-fast-forward name is removed in favor of the registered index fast-forward command.",
- "",
- "| Named entry | Disposition | Evidence | Replacement |",
- "| --- | --- | --- | --- |",
- ]
- for item in WORKSPACE_COMMAND_DISPOSITIONS:
- display_name = item.name if item.disposition == "remove" else control_plane_command(item.name)
- lines.append(f"| `{display_name}` | `{item.disposition}` | {item.evidence} | {item.replacement} |")
- lines.extend(
- [
- "",
- "Catalog bypass audit sites are machine-checked across workflow runs, CI-owned npm scripts, hooks, and devtools process launches. Direct hook adapters require declared sanctioned exceptions with an exact occurrence and cardinality.",
- "",
- "| Site | Status | Registered command | Occurrence | Reason |",
- "| --- | --- | --- | --- | --- |",
- ]
- )
- for site in CATALOG_BYPASS_SITES:
- command = control_plane_command(site.command_name) if site.command_name is not None else "hook adapter"
- occurrence = (
- f"line {site.occurrence_line} ({site.expected_occurrences} expected)"
- if site.occurrence_line is not None
- else "not applicable"
- )
- lines.append(f"| `{site.path}` | `{site.disposition}` | `{command}` | {occurrence} | {site.reason} |")
- lines.append("")
- return lines
-
-
def build_command_catalog() -> str:
groups = grouped_command_specs()
featured = featured_command_specs()
@@ -123,7 +87,6 @@ def build_command_catalog() -> str:
lines.extend(_render_verification_lab_surface(verification_lab))
if featured:
lines.extend(_render_featured_commands(featured))
- lines.extend(_render_workspace_dispositions())
for category, commands in groups.items():
lines.extend(_render_table(category, commands))
lines.append("")
diff --git a/devtools/render_docs_surface.py b/devtools/render_docs_surface.py
index c340354c1b..fc0b58fb4d 100644
--- a/devtools/render_docs_surface.py
+++ b/devtools/render_docs_surface.py
@@ -6,7 +6,11 @@
import os
import sys
from collections import Counter, defaultdict
+from collections.abc import Iterable
from pathlib import Path
+from urllib.parse import unquote, urlsplit
+
+from markdown_it import MarkdownIt
from devtools.command_catalog import control_plane_command
from devtools.docs_surface import (
@@ -27,7 +31,6 @@
"Getting Started": "Install Polylogue, create an archive, and run a first query.",
"Installation": "Package, source-checkout, Nix, and managed deployment options.",
"Demos and Proofs": "Run the private-data-free tour and see what each demo establishes.",
- "Proof Artifacts": "Links between public claims and reproducible checks.",
"Architecture": "Storage, data flow, and component responsibilities.",
"Code Navigation": "Find the owning package, runtime path, and verification for a code change.",
"Search & Query": "Search syntax, filters, action queries, ranking, and output formats.",
@@ -68,10 +71,45 @@ def _select_entries(entries: tuple[DocsEntry, ...], titles: tuple[str, ...]) ->
return tuple(by_title[title] for title in titles)
+def _markdown_links(path: Path) -> Iterable[str]:
+ """Yield local Markdown link destinations from one documentation page."""
+
+ parser = MarkdownIt("commonmark", {"html": False, "linkify": False})
+ for token in parser.parse(path.read_text(encoding="utf-8")):
+ for candidate in (token, *(token.children or ())):
+ if candidate.type != "link_open":
+ continue
+ href = candidate.attrGet("href")
+ if isinstance(href, str):
+ yield href
+
+
+def _reachable_documentation_paths(docs_entries: tuple[DocsEntry, ...], *, docs_root: Path) -> set[str]:
+ """Return registered docs and local Markdown pages reachable from them."""
+
+ resolved_docs_root = docs_root.resolve()
+ repo_root = resolved_docs_root.parent
+ queued = [repo_root / entry.path for entry in docs_entries if (repo_root / entry.path).is_file()]
+ reached: set[Path] = set()
+ while queued:
+ page = queued.pop().resolve()
+ if page in reached:
+ continue
+ reached.add(page)
+ for href in _markdown_links(page):
+ parts = urlsplit(href)
+ if parts.scheme or parts.netloc or not unquote(parts.path).lower().endswith(".md"):
+ continue
+ target = (page.parent / unquote(parts.path)).resolve()
+ if target.is_relative_to(resolved_docs_root) and target.is_file() and target not in reached:
+ queued.append(target)
+ return {path.relative_to(repo_root).as_posix() for path in reached}
+
+
def undocumented_paths(docs_entries: tuple[DocsEntry, ...], *, docs_root: Path) -> set[str]:
- """Return Markdown files that have no deliberate place in the docs map."""
+ """Return Markdown files unreachable from the deliberate docs map."""
expected = {f"docs/{path.relative_to(docs_root).as_posix()}" for path in docs_root.rglob("*.md")}
- documented = {entry.path for entry in docs_entries}
+ documented = _reachable_documentation_paths(docs_entries, docs_root=docs_root)
return expected - documented - GENERATED_DOC_PATHS
diff --git a/devtools/render_mcp_equivalence.py b/devtools/render_mcp_equivalence.py
deleted file mode 100644
index 3482b06b7c..0000000000
--- a/devtools/render_mcp_equivalence.py
+++ /dev/null
@@ -1,136 +0,0 @@
-"""Render the executable MCP algebra inventory and compatibility map."""
-
-from __future__ import annotations
-
-import argparse
-import json
-import sys
-from collections import Counter
-from dataclasses import asdict
-from pathlib import Path
-
-from devtools.command_catalog import control_plane_command
-from devtools.render_support import write_if_changed
-from polylogue.mcp.declarations.models import MCPTransactionDeclaration
-from polylogue.mcp.declarations.registry import (
- MCP_TOOL_DECLARATIONS,
- PRIVILEGED_ALGEBRA,
- TARGET_DEFAULT_READ_ALGEBRA,
- TARGET_PROMPTS,
- TARGET_RESOURCES,
-)
-
-DEFAULT_OUTPUT_PATH = Path("docs/generated/mcp-equivalence.json")
-SCHEMA_VERSION = 1
-
-
-def _transaction_payload(item: MCPTransactionDeclaration) -> dict[str, object]:
- return {
- "name": item.name,
- "verb": item.verb.value,
- "required_capability": item.required_capability or "read",
- "object_kinds": list(item.object_kinds),
- "result_semantics": [value.value for value in item.result_semantics],
- "purpose": item.purpose,
- "migration_owner": item.migration_owner,
- }
-
-
-def build_equivalence_payload() -> dict[str, object]:
- """Return the stable generated map consumed by drift checks and operators."""
-
- capability_counts: Counter[str] = Counter(
- declaration.required_capability or "read" for declaration in MCP_TOOL_DECLARATIONS
- )
- read_retirements = sorted(
- declaration.name for declaration in MCP_TOOL_DECLARATIONS if declaration.retirement_owner == "polylogue-t46.8.2"
- )
- privileged_retirements = sorted(
- declaration.name for declaration in MCP_TOOL_DECLARATIONS if declaration.retirement_owner == "polylogue-t46.8.3"
- )
- bound_python = sorted(
- declaration.name for declaration in MCP_TOOL_DECLARATIONS if declaration.python_parity.binding is not None
- )
- governed_absences = sorted(
- declaration.name for declaration in MCP_TOOL_DECLARATIONS if declaration.python_parity.binding is None
- )
-
- capability_order: tuple[str, ...] = ("read", "write", "judge", "maintenance")
-
- return {
- "schema_version": SCHEMA_VERSION,
- "generated_by": control_plane_command("render mcp-equivalence"),
- "authority": {
- "declarations": "polylogue/mcp/declarations/registry.py",
- "live_registration": "polylogue/mcp/declarations/adapter.py",
- "independent_name_baseline": "tests/infra/mcp.py::MCP_TOOL_NAME_BASELINE",
- "independent_output_baseline": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT",
- "migration_authority": {
- "read": "polylogue-t46.8.2",
- "privileged": "polylogue-t46.8.3",
- "python_parity": "polylogue-s1kr",
- },
- },
- "compatibility_surface": {
- "tool_count": len(MCP_TOOL_DECLARATIONS),
- "required_capability_counts": {
- capability: capability_counts.get(capability, 0) for capability in capability_order
- },
- "python_binding_count": len(bound_python),
- "governed_python_absence_count": len(governed_absences),
- "tool_names": [declaration.name for declaration in MCP_TOOL_DECLARATIONS],
- },
- "target_algebra": {
- "default_read_transaction_count": len(TARGET_DEFAULT_READ_ALGEBRA),
- "default_read_transactions": [_transaction_payload(item) for item in TARGET_DEFAULT_READ_ALGEBRA],
- "privileged_transactions": [_transaction_payload(item) for item in PRIVILEGED_ALGEBRA],
- "resources": [asdict(item) for item in TARGET_RESOURCES],
- "prompts": [asdict(item) for item in TARGET_PROMPTS],
- },
- "migration_groups": {
- "polylogue-t46.8.2": read_retirements,
- "polylogue-t46.8.3": privileged_retirements,
- },
- "python_parity": {
- "bound_tools": bound_python,
- "governed_absences": governed_absences,
- },
- "tools": [declaration.to_dict() for declaration in MCP_TOOL_DECLARATIONS],
- }
-
-
-def render_output() -> str:
- return json.dumps(build_equivalence_payload(), indent=2, sort_keys=True, ensure_ascii=False) + "\n"
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description="Render the generated MCP algebra equivalence map.")
- parser.add_argument(
- "--output-path",
- default=str(DEFAULT_OUTPUT_PATH),
- help=f"target JSON artifact (default: {DEFAULT_OUTPUT_PATH})",
- )
- parser.add_argument("--check", action="store_true", help="Exit non-zero when the artifact is out of sync.")
- args = parser.parse_args(argv)
- output_path = Path(args.output_path)
- rendered = render_output()
-
- if args.check:
- current = output_path.read_text(encoding="utf-8") if output_path.exists() else ""
- if current != rendered:
- print("render mcp-equivalence: out of sync:", file=sys.stderr)
- print(f" - {output_path}", file=sys.stderr)
- print(
- f"render mcp-equivalence: run: {control_plane_command('render mcp-equivalence')}",
- file=sys.stderr,
- )
- return 1
- print("render mcp-equivalence: sync OK")
- return 0
-
- write_if_changed(output_path, rendered)
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/render_mcp_tool_index.py b/devtools/render_mcp_tool_index.py
deleted file mode 100644
index 21f4a3ac38..0000000000
--- a/devtools/render_mcp_tool_index.py
+++ /dev/null
@@ -1,90 +0,0 @@
-"""Render the exhaustive MCP tool-name index into docs/mcp-reference.md.
-
-``docs/mcp-reference.md`` hand-curates a representative sample of tools by
-category; that stays. This adds a generated appendix enumerating every
-declared tool name (``polylogue.mcp.declarations.registry``), so each
-tool is individually reachable from the docs tree (polylogue-3tl.9's
-docs-coverage lint checks exactly this) without hand-duplicating the list.
-"""
-
-from __future__ import annotations
-
-import argparse
-import sys
-from pathlib import Path
-
-from devtools.command_catalog import control_plane_command
-from devtools.render_support import write_if_changed
-
-MARKER = "mcp-tool-index"
-DEFAULT_DOC_PATH = Path("docs/mcp-reference.md")
-
-
-def _tool_names() -> tuple[str, ...]:
- from polylogue.mcp.declarations.models import MCPCapabilities
- from polylogue.mcp.declarations.registry import declared_tool_names
-
- return tuple(sorted(declared_tool_names(MCPCapabilities(write=True, judge=True, maintenance=True))))
-
-
-def build_tool_index_section(tool_names: tuple[str, ...] | None = None) -> str:
- names = tool_names if tool_names is not None else _tool_names()
- generated_note = f""
- lines = [
- f"",
- "## All Registered Tools",
- "",
- generated_note,
- "",
- f"Every currently-registered MCP tool name ({len(names)} total), for lookup and doc-coverage "
- "purposes. See the category breakdown above for what each group is for.",
- "",
- ]
- lines.extend(f"- `{name}`" for name in names)
- lines.append("")
- lines.append(f"")
- return "\n".join(lines)
-
-
-def replace_marked_section(text: str, *, replacement: str) -> str:
- begin, end = f"", f""
- start = text.find(begin)
- if start == -1:
- # No existing block: append at end of file (after a trailing blank line).
- return text.rstrip("\n") + "\n\n" + replacement + "\n"
- finish = text.find(end, start)
- if finish == -1:
- raise ValueError(f"marker block malformed: {MARKER}")
- return text[:start] + replacement + text[finish + len(end) :]
-
-
-def render_output(doc_path: Path) -> str:
- current = doc_path.read_text(encoding="utf-8") if doc_path.exists() else ""
- return replace_marked_section(current, replacement=build_tool_index_section())
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description="Render the generated MCP tool-name index appendix.")
- parser.add_argument("--doc-path", default=str(DEFAULT_DOC_PATH), help=f"target doc (default: {DEFAULT_DOC_PATH})")
- parser.add_argument("--check", action="store_true", help="Exit non-zero when the doc target is out of sync.")
- args = parser.parse_args(argv)
- doc_path = Path(args.doc_path)
-
- rendered = render_output(doc_path)
-
- if args.check:
- current = doc_path.read_text(encoding="utf-8") if doc_path.exists() else ""
- if current != rendered:
- print("render mcp-tool-index: out of sync:", file=sys.stderr)
- print(f" - {doc_path}", file=sys.stderr)
- print(f"render mcp-tool-index: run: {control_plane_command('render mcp-tool-index')}", file=sys.stderr)
- return 1
- print("render mcp-tool-index: sync OK")
- return 0
-
- write_if_changed(doc_path, rendered)
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/render_pages.py b/devtools/render_pages.py
index 60558b769d..9a3df97288 100644
--- a/devtools/render_pages.py
+++ b/devtools/render_pages.py
@@ -71,14 +71,12 @@ def _run_render_commands(verbose: bool = False) -> None:
render_cli_reference,
render_devtools_reference,
render_docs_surface,
- render_quality_reference,
)
renderers = [
("render cli-reference", render_cli_reference.main),
("render devtools-reference", render_devtools_reference.main),
("render docs-surface", render_docs_surface.main),
- ("render quality-reference", render_quality_reference.main),
]
for name, render in renderers:
if verbose:
diff --git a/devtools/render_product_workflows.py b/devtools/render_product_workflows.py
deleted file mode 100644
index c676f5bf31..0000000000
--- a/devtools/render_product_workflows.py
+++ /dev/null
@@ -1,330 +0,0 @@
-"""Render executable product query-action workflows from the live registry (#2305)."""
-
-from __future__ import annotations
-
-import argparse
-import sys
-from collections.abc import Iterable
-from pathlib import Path
-
-from devtools.command_catalog import control_plane_command
-from devtools.render_support import write_if_changed
-from polylogue.operations.action_contracts import ACTION_CONTRACTS, CliActionContract
-from polylogue.product.workflows import (
- ACTION_UNIT_EVIDENCE,
- EXECUTABLE_WORKFLOW_GOLDEN_PATHS,
- PRODUCT_VERB_MATRIX_EXTRA_ROWS,
- QUERY_ACTION_WORKFLOWS,
- ActionUnitEvidence,
- ExecutableWorkflowGoldenPath,
- ProductVerbMatrixRow,
- QueryActionWorkflow,
-)
-from polylogue.surfaces.action_affordances import ActionAffordancePayload
-
-GENERATED_NOTE = (
- f""
-)
-
-
-def _escape_table(value: object) -> str:
- return str(value).replace("|", "\\|").replace("\n", " ")
-
-
-def _code(value: str) -> str:
- return f"`{value}`"
-
-
-def _code_list(items: Iterable[str]) -> str:
- values = tuple(items)
- if not values:
- return "—"
- return " ".join(_code(item) for item in values)
-
-
-def _command(value: str) -> str:
- return "`" + value.replace("`", "\\`") + "`"
-
-
-def _path_label(path: tuple[str, ...]) -> str:
- return " ".join(path)
-
-
-def _action_index() -> dict[str, CliActionContract]:
- return {contract.action_id: contract for contract in ACTION_CONTRACTS}
-
-
-def _render_workflow_table(workflows: tuple[QueryActionWorkflow, ...]) -> list[str]:
- lines = [
- "| Workflow | Query/action shape | Selector + cardinality | Output + evidence | Surfaces |",
- "| --- | --- | --- | --- | --- |",
- ]
- for workflow in workflows:
- selector = f"{workflow.selector_policy} {workflow.cardinality_policy}"
- output = f"{workflow.output_policy} {workflow.evidence_policy}"
- lines.append(
- "| "
- + _escape_table(f"{workflow.title} (`{workflow.id}`)")
- + " | "
- + _escape_table(_command(workflow.query_shape))
- + " | "
- + _escape_table(selector)
- + " | "
- + _escape_table(output)
- + " | "
- + _code_list(workflow.surfaces)
- + " |"
- )
- return lines
-
-
-def _render_product_verb_matrix_row(row: ProductVerbMatrixRow) -> str:
- return (
- f"| `{row.action_id}` | {_escape_table(row.target_input)} | `{row.cardinality}` | "
- f"`{row.safety}` | {_code_list(row.formats)} | {_code_list(row.destinations)} | "
- f"{_escape_table(row.selection_confirmation)} | {_code_list(row.next_actions)} |"
- )
-
-
-def _render_action_matrix(
- contracts: tuple[CliActionContract, ...],
- extra_rows: tuple[ProductVerbMatrixRow, ...] = PRODUCT_VERB_MATRIX_EXTRA_ROWS,
-) -> list[str]:
- lines = [
- "| Action | Target / input | Cardinality | Safety | Formats | Destinations | Selection / confirmation | Next actions |",
- "| --- | --- | --- | --- | --- | --- | --- | --- |",
- ]
- for contract in contracts:
- selection = contract.selection_command or "—"
- if contract.confirmation_command:
- selection = f"{selection} confirm: `{contract.confirmation_command}`"
- if contract.disabled_reason:
- selection = f"{selection} disabled: {contract.disabled_reason}"
- lines.append(
- f"| `{contract.action_id}` | `{contract.target}` / `{contract.input_unit}` | `{contract.cardinality}` | "
- f"`{contract.safety_level}` | {_code_list(sorted(contract.formats))} | "
- f"{_code_list(contract.destination_support)} | {_escape_table(selection)} | "
- f"{_code_list(contract.next_actions)} |"
- )
- lines.extend(_render_product_verb_matrix_row(row) for row in extra_rows)
- return lines
-
-
-def _render_action_unit_table(rows: tuple[ActionUnitEvidence, ...]) -> list[str]:
- lines = [
- "| Action unit | Evidence unit | Evidence surface | Negative guard |",
- "| --- | --- | --- | --- |",
- ]
- for row in rows:
- lines.append(
- f"| `{row.action_id}` | {_escape_table(row.evidence_unit)} | "
- f"{_escape_table(row.evidence_surface)} | {_escape_table(row.negative_guard)} |"
- )
- return lines
-
-
-def _render_golden_path_table(goldens: tuple[ExecutableWorkflowGoldenPath, ...]) -> list[str]:
- lines = [
- "| Golden path | Workflow | Command | Output | Structural assertions | Human/string checks |",
- "| --- | --- | --- | --- | --- | --- |",
- ]
- for golden in goldens:
- json_assertions = "—"
- if golden.json_expectations:
- json_assertions = " ".join(
- _code(".".join(str(part) for part in expectation.path) or "$") + f" is {expectation.kind}"
- for expectation in golden.json_expectations
- )
- human_checks = _code_list(golden.stdout_contains)
- lines.append(
- f"| `{golden.id}` | `{golden.workflow_id}` | {_command(golden.command_text)} | "
- f"`{golden.output_kind}` | {json_assertions} | {human_checks} |"
- )
- return lines
-
-
-def _render_affordance_fields() -> list[str]:
- fields = tuple(ActionAffordancePayload.model_fields)
- return [
- "The shared action affordance DTO is the finite envelope consumed by CLI, daemon/API, MCP, docs, and browser rails.",
- "It must keep these operator-visible fields:",
- "",
- _code_list(fields),
- "",
- "Load-bearing fields for workflow execution are `target`, `input.unit`, `execution.cardinality_state`, "
- "`execution.guards`, `execution.requires_daemon`, output metadata (`output.destination_support`, "
- "`output.format_support`, `output.default_format`, `output.machine_envelope`), and safety/availability "
- "metadata (`safety.safety_level`, `safety.confirmation_command`, `safety.selection_command`, "
- "`availability.disabled_reason`, `availability.estimated_cost`, `availability.next_actions`).",
- "",
- ]
-
-
-def _render_repeatable_template() -> list[str]:
- return [
- "## Repeatable Workflow Template",
- "",
- "1. **Select intentionally.** Start with `polylogue find QUERY`. `find` declares query intent; command words after "
- "`then` are actions. A bare `read` at the start remains a read command, not hidden query text.",
- "2. **Preserve exact refs.** `id:...`, `session:...`, message refs, assertion refs, and operation refs are identity "
- "filters. If an exact ref misses, the workflow returns no target or an unresolved ref instead of falling back to FTS; "
- "an exact ref plus extra text remains a scoped search within that target.",
- "3. **Apply cardinality before execution.** Singleton actions select one target; explicit multi actions need `--all`, "
- "`--first`, a bounded export mode, or an action-specific multi contract. Multi-match `then read` must be explicit, "
- "while aggregate actions such as `analyze --facets` accept zero, one, or many sessions without selecting a target.",
- "4. **Expose the output contract.** Human output is default where available; JSON/NDJSON only exist when the action/read-view "
- "declares that format. Unsupported syntax or formats fail loudly.",
- "5. **Surface safety and availability.** Mutating/destructive actions carry `safety.safety_level`, "
- "`execution.guards`, and a `safety.confirmation_command` or `safety.selection_command`. Disabled or "
- "daemon-required actions report that posture in `availability`/`execution`.",
- "6. **Return next action affordances.** A workflow result should tell the operator what can happen next, rather than requiring "
- "the UI to invent a second truth ledger.",
- "",
- ]
-
-
-def build_document(
- workflows: tuple[QueryActionWorkflow, ...] = QUERY_ACTION_WORKFLOWS,
- contracts: tuple[CliActionContract, ...] = ACTION_CONTRACTS,
- goldens: tuple[ExecutableWorkflowGoldenPath, ...] = EXECUTABLE_WORKFLOW_GOLDEN_PATHS,
-) -> str:
- action_by_id = _action_index()
- missing_actions = sorted(
- {
- _path_label(path)
- for workflow in workflows
- for path in workflow.action_paths
- if _path_label(path) not in action_by_id
- }
- - {"find"}
- )
- if missing_actions:
- raise ValueError(f"workflow registry references actions with no contract: {missing_actions}")
-
- lines: list[str] = [
- "[← Back to README](../README.md)",
- "",
- GENERATED_NOTE,
- "",
- "# Executable Query-Action Workflows",
- "",
- "This product contract is generated from the live workflow registry and CLI action contracts. The registry drives the "
- "table below and the demo-archive golden-path tests, so the workflow map cannot drift into decorative metadata.",
- "",
- *_render_repeatable_template(),
- "## Workflow Registry",
- "",
- *_render_workflow_table(workflows),
- "",
- "## Verb Matrix",
- "",
- "The matrix is rendered from `ACTION_CONTRACTS`, the same source used by `polylogue config action-affordances`, "
- "`GET /api/action-affordances`, MCP affordance exposure, and completion descriptions.",
- "",
- *_render_action_matrix(contracts),
- "",
- "## Action-Unit Evidence",
- "",
- "Action units are the evidence grain for query-action execution. They define the target evidence, proof surface, and negative "
- "guard that keeps a workflow honest.",
- "",
- *_render_action_unit_table(ACTION_UNIT_EVIDENCE),
- "",
- "## Shared Affordance DTO",
- "",
- *_render_affordance_fields(),
- "## Exact-Ref and Multi-Match Rules",
- "",
- "Exact refs are identity coordinates, not search suggestions. `id:` and `session:` filters route through the compiled query "
- "spec and must not broaden to FTS when absent. Text query matches are candidate result sets; downstream actions then apply "
- "the action cardinality. In particular, `find QUERY then read` reads one selected session unless the operator chooses "
- "`--all` or an explicit bounded export/read mode.",
- "",
- "Cardinality semantics are explicit: zero matches return no selected target or empty scoped buckets; one exact match is "
- "the selected session/read payload; many ranked matches remain candidate rows for singleton actions and aggregate buckets "
- "for `analyze --facets`.",
- "",
- "## Facet Family Contract",
- "",
- "`analyze --facets` names families rather than leaking raw bucket internals. Cheap default families are `total_counts`, "
- "`origins`, and `tags`. Deferred detail families are `repos`, `role_counts`, `material_origins`, `message_types`, "
- "`action_types`, and `has_flags`; JSON reports each family in `family_status` with `label`, `source`, "
- "`canonicalization`, `expensive`, freshness/degraded fields, and `deferred_families` when omitted by default.",
- "",
- "The family meanings stay separate: provider `origins` describe archive/source provider; `role_counts` are provider-reported "
- "message roles and not authoredness; `material_origins` describe human/assistant/runtime provenance; `message_types` "
- "describe normalized content kind; `tags` are user/session labels; `repos` are canonical product repository labels. "
- "Incidental archive paths and noisy repo/path tokens are reported under omitted/noisy counts instead of being presented as "
- "authoritative repositories. Terminal facet output shows a bounded top set per family and points users to "
- "`--format json` for complete buckets and IDF values.",
- "",
- "## Completion Contract",
- "",
- "Shell completions are part of the workflow contract. They must cover `find QUERY then ACTION`, the action verbs "
- "(`select`, `read`, `continue`, `analyze`, `mark`, `delete`), read views, destinations and view-scoped formats, "
- "mutating/destructive guards (`mark --all|--first`, `delete --dry-run|--yes|--all`), root `judge` options, "
- "and `continue --candidates` options. Unsupported query syntax must fail loudly and must not be completed as broad FTS.",
- "",
- "## Daemon and Browser Workbench Contract",
- "",
- "`GET /api/sessions` returns the same `action_affordances` list as the CLI action-affordance payload for query-result "
- "actions, while `GET /api/action-affordances` returns the complete action floor. The browser workbench renders those "
- "affordances as operator-visible action rails; it may disable actions by availability, but it must not invent hidden "
- "redaction or silently remove safe actions.",
- "",
- "## Demo-Archive Golden Paths",
- "",
- "The following commands are parametrized tests over `polylogue demo seed --with-overlays`. They verify at least one JSON "
- "shape and one human-rendered surface from the same registry that generates this document.",
- "",
- *_render_golden_path_table(goldens),
- "",
- "## Regeneration and Verification",
- "",
- "```bash",
- control_plane_command("render product-workflows"),
- control_plane_command("render product-workflows", "--check"),
- control_plane_command("test", "tests/unit/product/test_query_action_workflows.py"),
- control_plane_command("test", "tests/unit/cli/test_completion_matrix.py", "-k", "query_action"),
- "```",
- "",
- ]
- return "\n".join(lines)
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description="Render docs/product/workflows.md from executable query-action registries."
- )
- parser.add_argument("--output", default="docs/product/workflows.md", help="Output path.")
- parser.add_argument("--check", action="store_true", help="Exit non-zero when the output is out of sync.")
- args = parser.parse_args(argv)
-
- output_path = Path(args.output)
- try:
- content = build_document()
- except ValueError as exc:
- print(f"render product-workflows: {exc}", file=sys.stderr)
- return 1
-
- if args.check:
- try:
- current = output_path.read_text(encoding="utf-8")
- except FileNotFoundError:
- current = ""
- if current != content:
- print(f"render product-workflows: out of sync: {output_path}", file=sys.stderr)
- print(
- f"render product-workflows: run: {control_plane_command('render product-workflows')}", file=sys.stderr
- )
- return 1
- print("render product-workflows: sync OK")
- return 0
-
- write_if_changed(output_path, content)
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/render_public_claims.py b/devtools/render_public_claims.py
deleted file mode 100644
index c16f17b0b8..0000000000
--- a/devtools/render_public_claims.py
+++ /dev/null
@@ -1,106 +0,0 @@
-"""Render public-claims presets from FINDING assertions and 37t.14 verdict receipts."""
-
-from __future__ import annotations
-
-import argparse
-import json
-import sqlite3
-import sys
-from pathlib import Path
-
-from devtools.command_catalog import control_plane_command
-from devtools.public_claims import (
- DEFAULT_COMPATIBILITY_PATH,
- DEFAULT_OUTPUT_DIR,
- build_repository_projection,
- rendered_artifacts,
-)
-from devtools.render_support import write_if_changed
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument(
- "--output-dir",
- type=Path,
- default=DEFAULT_OUTPUT_DIR,
- help=f"Markdown/JSON preset directory (default: {DEFAULT_OUTPUT_DIR})",
- )
- parser.add_argument(
- "--compatibility-path",
- type=Path,
- default=DEFAULT_COMPATIBILITY_PATH,
- help=f"generated YAML compatibility view (default: {DEFAULT_COMPATIBILITY_PATH})",
- )
- parser.add_argument("--archive-root", type=Path, help="read public FINDING rows from this archive's user.db")
- parser.add_argument("--verdicts", type=Path, help="37t.14 JSON verdict receipt export")
- parser.add_argument("--check", action="store_true", help="exit non-zero when any generated artifact is out of sync")
- parser.add_argument("--json", action="store_true", help="emit a machine-readable render report")
- args = parser.parse_args(argv)
-
- try:
- claims = build_repository_projection(archive_root=args.archive_root, verdicts_path=args.verdicts)
- artifacts = rendered_artifacts(
- claims,
- output_dir=args.output_dir,
- compatibility_path=args.compatibility_path,
- )
- except (OSError, ValueError, json.JSONDecodeError, sqlite3.Error) as exc:
- if args.json:
- print(json.dumps({"ok": False, "error": str(exc)}, indent=2, sort_keys=True))
- else:
- print(f"render public-claims: {exc}", file=sys.stderr)
- return 2
-
- changed = [
- path
- for path, rendered in artifacts.items()
- if (path.read_text(encoding="utf-8") if path.exists() else "") != rendered
- ]
- if args.check:
- ok = not changed
- if args.json:
- print(
- json.dumps(
- {
- "ok": ok,
- "claim_count": len(claims),
- "artifact_count": len(artifacts),
- "out_of_sync": [str(path) for path in changed],
- },
- indent=2,
- sort_keys=True,
- )
- )
- elif ok:
- print("render public-claims: sync OK")
- else:
- print("render public-claims: out of sync:", file=sys.stderr)
- for path in changed:
- print(f" - {path}", file=sys.stderr)
- print(
- f"render public-claims: run: {control_plane_command('render public-claims')}",
- file=sys.stderr,
- )
- return 0 if ok else 1
-
- for path, rendered in artifacts.items():
- write_if_changed(path, rendered)
- if args.json:
- print(
- json.dumps(
- {
- "ok": True,
- "claim_count": len(claims),
- "artifact_count": len(artifacts),
- "written": [str(path) for path in changed],
- },
- indent=2,
- sort_keys=True,
- )
- )
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/render_quality_reference.py b/devtools/render_quality_reference.py
deleted file mode 100644
index 7bab4f3b7d..0000000000
--- a/devtools/render_quality_reference.py
+++ /dev/null
@@ -1,492 +0,0 @@
-"""Render the quality workflow reference from live registries."""
-
-from __future__ import annotations
-
-import argparse
-import sys
-from pathlib import Path
-
-from devtools.benchmark_catalog import BenchmarkCampaignEntry
-from devtools.command_catalog import control_plane_command
-from devtools.lane_models import LaneEntry
-from devtools.mutation_catalog import MutationCampaignEntry
-from devtools.quality_registry import QualityRegistry, build_quality_registry
-from devtools.render_support import write_if_changed
-from devtools.scenario_coverage import RuntimeScenarioCoverage, build_runtime_scenario_coverage
-from polylogue.scenarios import CorpusScenario, ScenarioProjectionEntry
-
-
-def _format_code_list(items: tuple[str, ...]) -> str:
- if not items:
- return "—"
- return " ".join(f"`{item}`" for item in items)
-
-
-def _render_lane_table(entries: tuple[LaneEntry, ...]) -> list[str]:
- lines = [
- "| Lane | Timeout (s) | Description |",
- "| --- | ---: | --- |",
- ]
- for entry in entries:
- lines.append(f"| `{entry.name}` | {entry.timeout_s} | {entry.description} |")
- return lines
-
-
-def _render_composite_lane_table(entries: tuple[LaneEntry, ...]) -> list[str]:
- lines = [
- "| Lane | Timeout (s) | Includes | Description |",
- "| --- | ---: | --- | --- |",
- ]
- for entry in entries:
- includes = _format_code_list(entry.sub_lanes)
- lines.append(f"| `{entry.name}` | {entry.timeout_s} | {includes} | {entry.description} |")
- return lines
-
-
-def _render_mutation_table(entries: tuple[MutationCampaignEntry, ...]) -> list[str]:
- lines = [
- "| Campaign | Mutates | Tests | Description |",
- "| --- | --- | --- | --- |",
- ]
- for entry in entries:
- lines.append(
- f"| `{entry.name}` | {_format_code_list(entry.paths_to_mutate)} | "
- f"{_format_code_list(entry.tests)} | {entry.description} |"
- )
- return lines
-
-
-def _render_benchmark_table(entries: tuple[BenchmarkCampaignEntry, ...]) -> list[str]:
- lines = [
- "| Campaign | Tests | Warn | Fail | Description |",
- "| --- | --- | ---: | ---: | --- |",
- ]
- for entry in entries:
- lines.append(
- f"| `{entry.name}` | {_format_code_list(entry.tests)} | "
- f"{entry.warn_pct:.1f}% | {entry.fail_pct:.1f}% | {entry.description} |"
- )
- return lines
-
-
-def _render_inferred_corpus_table(entries: tuple[CorpusScenario, ...]) -> list[str]:
- lines = [
- "| Provider | Package | Variants | Targets | Tags |",
- "| --- | --- | ---: | --- | --- |",
- ]
- for entry in entries:
- lines.append(
- f"| `{entry.provider}` | `{entry.package_version}` | `{len(entry.corpus_specs)}` | "
- f"{_format_code_list(entry.target_labels)} | "
- f"{_format_code_list(entry.tags)} |"
- )
- return lines
-
-
-def _render_scenario_projection_table(entries: tuple[ScenarioProjectionEntry, ...]) -> list[str]:
- lines = [
- "| Source | Projection | Runtime Path Targets | Runtime Artifact Targets | Conceptual Path Targets | Conceptual Artifact Targets | Operation Targets | Maintenance Targets | Tags | Description |",
- "| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |",
- ]
- for entry in entries:
- lines.append(
- f"| `{entry.source_kind.value}` | `{entry.name}` | "
- f"{_format_code_list(entry.runtime_path_targets())} | "
- f"{_format_code_list(entry.artifact_targets)} | "
- f"{_format_code_list(entry.conceptual_path_targets)} | "
- f"{_format_code_list(entry.conceptual_artifact_targets)} | "
- f"{_format_code_list(entry.operation_targets)} | "
- f"{_format_code_list(entry.maintenance_targets)} | "
- f"{_format_code_list(entry.tags)} | {entry.description} |"
- )
- return lines
-
-
-def _render_runtime_coverage_section(coverage: RuntimeScenarioCoverage) -> list[str]:
- uncovered_paths = tuple(sorted(name for name, path in coverage.paths.items() if not path.complete))
- return [
- "## Runtime Coverage",
- "",
- f"- covered runtime paths: `{sum(1 for path in coverage.paths.values() if path.complete)}`",
- f"- covered runtime artifacts: `{len(coverage.artifacts)}`",
- f"- covered runtime operations: `{len(coverage.operations)}`",
- f"- covered maintenance targets: `{len(coverage.maintenance_targets)}`",
- f"- covered declared operation targets: `{len(coverage.declared_operations)}`",
- "- uncovered runtime paths: "
- + ("—" if not uncovered_paths else ", ".join(f"`{name}`" for name in uncovered_paths)),
- "- uncovered runtime artifacts: "
- + (
- "—" if not coverage.uncovered_artifacts else ", ".join(f"`{name}`" for name in coverage.uncovered_artifacts)
- ),
- "- uncovered runtime operations: "
- + (
- "—"
- if not coverage.uncovered_operations
- else ", ".join(f"`{name}`" for name in coverage.uncovered_operations)
- ),
- "- uncovered maintenance targets: "
- + (
- "—"
- if not coverage.uncovered_maintenance_targets
- else ", ".join(f"`{name}`" for name in coverage.uncovered_maintenance_targets)
- ),
- "- uncovered declared operation targets: "
- + (
- "—"
- if not coverage.uncovered_declared_operations
- else ", ".join(f"`{name}`" for name in coverage.uncovered_declared_operations)
- ),
- "",
- "Inspect the full authored map with:",
- "",
- "```bash",
- control_plane_command("lab graph"),
- control_plane_command("lab graph", "--json"),
- "```",
- "",
- ]
-
-
-def _render_test_infrastructure_section() -> list[str]:
- return [
- "## Test Infrastructure Contracts",
- "",
- "Shared helpers under `tests/infra/` are verification substrate. Prefer these contracts over",
- "per-suite JSON parsing, surface invocation, archive seeding, or cross-surface oracle helpers.",
- "",
- "| Helper | Contract | Primary consumers |",
- "| --- | --- | --- |",
- "| `tests/infra/json_contracts.py` | Typed JSON object/envelope/result narrowing for machine surfaces | CLI, MCP, insight, and devtools JSON tests |",
- "| `tests/infra/mcp.py` | MCP surface registration, invocation, and mock archive seams | MCP server and tool-contract tests |",
- "| `tests/infra/storage_records.py` | Durable archive row builders and DB factories | Storage, CLI, insight, and health tests |",
- "| `tests/infra/surfaces.py` | Cross-surface archive adapters over SQLite, repository, and facade projections | Scenario/oracle tests |",
- "",
- ]
-
-
-def _render_scenario_projection_snapshot(registry: QualityRegistry) -> list[str]:
- projection_counts: dict[str, int] = {}
- for entry in registry.scenario_projections:
- source_kind = entry.source_kind.value
- projection_counts[source_kind] = projection_counts.get(source_kind, 0) + 1
- return [
- f"- scenario projections: `{len(registry.scenario_projections)}`",
- f"- inferred corpus scenarios: `{len(registry.inferred_corpus_scenarios)}`",
- *(f" - {source_kind}: `{count}`" for source_kind, count in sorted(projection_counts.items())),
- ]
-
-
-def build_document(registry: QualityRegistry, *, runtime_coverage: RuntimeScenarioCoverage | None = None) -> str:
- coverage = runtime_coverage or build_runtime_scenario_coverage(projections=registry.scenario_projections)
- parts = [
- "[← Back to README](../README.md)",
- "",
- f"",
- "",
- "# Test Quality Workflows",
- "",
- "This reference is generated from the executable validation-lane, mutation-campaign, and benchmark-campaign registries. It is navigation over concrete commands, not a separate proof ledger.",
- "",
- "Current registry snapshot:",
- "",
- f"- contract lanes: `{len(registry.contract_lanes)}`",
- f"- live lanes: `{len(registry.live_lanes)}`",
- f"- composite lanes: `{len(registry.composite_lanes)}`",
- f"- mutation campaigns: `{len(registry.mutation_campaigns)}`",
- f"- benchmark campaigns: `{len(registry.benchmark_campaigns)}`",
- f"- synthetic benchmark campaigns: `{len(registry.synthetic_benchmark_campaigns)}`",
- *_render_scenario_projection_snapshot(registry),
- "",
- *_render_runtime_coverage_section(coverage),
- "## Common Commands",
- "",
- "Commands below assume the project devshell is already active. If not, prefix them with `nix develop -c`.",
- "",
- "### Full correctness run",
- "",
- "```bash",
- "pytest -q -n 0",
- "```",
- "",
- "### Fast local run",
- "",
- "Use this when iterating locally and skipping slow checks and benchmarks.",
- "",
- "```bash",
- 'pytest -q -n 0 -m "not slow and not benchmark"',
- "```",
- "",
- *_render_test_infrastructure_section(),
- "### Validation lanes",
- "",
- "Validation lanes are optional wrappers over executable checks. Prefer the focused pytest or `devtools test` command for a narrow edit; use a lane when you need the composed command set it declares.",
- "",
- "```bash",
- control_plane_command("lab lanes", "--list"),
- control_plane_command("lab lanes", "--lane", "frontier-local"),
- control_plane_command("lab lanes", "--lane", "live-archive-smoke", "--dry-run"),
- "```",
- "",
- "### Schema evolution policy lane",
- "",
- "Polylogue uses two schema-evolution regimes (see",
- "[Schema Versioning Model](internals.md#schema-versioning-model)):",
- "durable tiers use explicit additive migrations with a backup gate, while",
- "derived tiers rebuild or blue-green replace from source evidence, except for",
- "declared, clone-validated SQL fast-forwards for non-semantic deltas; they",
- "prove structural clone equivalence, not parser-content equivalence.",
- f"`{control_plane_command('lab policy schema-versioning')}` enforces that policy boundary:",
- "",
- "- It scans derived-tier storage modules for upgrade-shaped helpers",
- " (`build_vN_to_vM`, `_apply_version_upgrade_plan`, `upgrade_vN_to_vM`,",
- " `migrate_vN_*`, `ensure_schema_upgrades_vN`).",
- "- It requires every index schema bump since the supported compatibility floor",
- " to declare its delta class before it can ship.",
- "- It allows numbered SQL resources only under durable migration roots:",
- " `polylogue/storage/sqlite/migrations/{source,user}/`.",
- "- If a derived upgrade helper, undeclared index delta, or invalid migration resource is found,",
- " the lint fails.",
- "",
- "The lint runs as part of `devtools verify --lab`, not the fast default path:",
- "the policy boundary is an architectural concern, not a per-edit gate.",
- "",
- "```bash",
- control_plane_command("lab policy schema-versioning"),
- control_plane_command("lab policy schema-versioning", "--json"),
- "```",
- "",
- "### Mutation campaigns",
- "",
- "```bash",
- control_plane_command("bench mutation", "list"),
- control_plane_command("bench mutation", "run", ""),
- control_plane_command("bench mutation", "index"),
- "```",
- "",
- "### Benchmark campaigns",
- "",
- "```bash",
- control_plane_command("bench campaign", "list"),
- control_plane_command("bench campaign", "run", ""),
- control_plane_command("bench campaign", "compare") + " \\",
- " .local/benchmark-campaigns/.json \\",
- " .local/benchmark-campaigns/.json",
- control_plane_command("bench campaign", "index"),
- control_plane_command("bench synthetic", "--list"),
- control_plane_command("bench synthetic", "--scale", "medium", "--campaign", ""),
- "```",
- "",
- "### Fast pipeline probes",
- "",
- "```bash",
- control_plane_command(
- "lab probe pipeline",
- "--provider",
- "chatgpt",
- "--count",
- "5",
- "--stage",
- "parse",
- "--workdir",
- "/tmp/polylogue-probe",
- ),
- control_plane_command(
- "lab probe pipeline",
- "--input-mode",
- "archive-subset",
- "--source-db",
- '"$XDG_DATA_HOME/polylogue/source.db"',
- "--sample-per-provider",
- "50",
- "--stage",
- "parse",
- "--workdir",
- "/tmp/polylogue-probe-real",
- "--manifest-out",
- "/tmp/polylogue-probe-real.json",
- ),
- control_plane_command(
- "lab probe pipeline",
- "--input-mode",
- "archive-subset",
- "--manifest-in",
- "/tmp/polylogue-probe-real.json",
- "--stage",
- "parse",
- "--workdir",
- "/tmp/polylogue-probe-replay",
- ),
- "```",
- "",
- "### Demo and visual behavior checks",
- "",
- "```bash",
- "devtools test tests/unit/cli/test_demo_command.py tests/unit/demo/test_demo_seed_verify.py tests/visual",
- "```",
- "",
- "## Validation Lane Catalog",
- "",
- "Use the named lanes through the runner.",
- "",
- "### Contract Lanes",
- "",
- *_render_lane_table(registry.contract_lanes),
- "",
- "### Live Lanes",
- "",
- *_render_lane_table(registry.live_lanes),
- "",
- "### Composite Lanes",
- "",
- *_render_composite_lane_table(registry.composite_lanes),
- "",
- "## Mutation Campaign Catalog",
- "",
- "Durable mutation ledgers live under `.local/mutation-campaigns/`; workflow policy lives in [../TESTING.md](../TESTING.md).",
- "",
- *_render_mutation_table(registry.mutation_campaigns),
- "",
- "## Benchmark Campaign Catalog",
- "",
- "Benchmark comparisons are manual.",
- "",
- *_render_benchmark_table(registry.benchmark_campaigns),
- "",
- "## Synthetic Benchmark Campaign Catalog",
- "",
- "These campaigns generate synthetic archives and run long-haul benchmark workloads through `devtools bench synthetic`.",
- "",
- *_render_benchmark_table(registry.synthetic_benchmark_campaigns),
- "",
- "## Inferred Corpus Catalog",
- "",
- "These inferred corpus specs come from the live schema registry and participate in the shared scenario projection map.",
- "",
- *_render_inferred_corpus_table(registry.inferred_corpus_scenarios),
- "",
- "## Scenario Projection Catalog",
- "",
- "These projections explain which executable lanes, inferred fixture scenarios, or benchmark campaigns feed runtime coverage maps.",
- "",
- *_render_scenario_projection_table(registry.scenario_projections),
- "",
- "## Artifact Locations",
- "",
- "- mutation campaigns: `.local/mutation-campaigns/`",
- "- benchmark campaigns: `.local/benchmark-campaigns/`",
- "- pipeline probe manifests and replay bundles: user-selected paths outside the repo by default",
- "",
- "## Scale Tier Model",
- "",
- "Scale-sensitive tests opt into one of three tiers (issue #1183). The tier",
- "determines which verification gate runs the test and what corpus size the",
- "fixture seeds.",
- "",
- "| Tier | Marker | Approx. size | Gate |",
- "| --- | --- | --- | --- |",
- "| small | `@pytest.mark.scale_small` | ~100 convs / ~1k msgs | default `devtools verify` |",
- "| medium | `@pytest.mark.scale_medium` | ~1k convs / ~10k msgs | `devtools verify --lab` |",
- "| large | `@pytest.mark.scale_large` | ~10k convs / ~100k msgs | nightly CI (`.github/workflows/nightly-scale.yml`) or explicit `devtools bench campaign` |",
- "",
- "Fixtures live in `tests/infra/scale_fixtures.py` as `tier_small_db`,",
- "`tier_medium_db`, and `tier_large_db`. They are session-scoped and seed",
- "a SQLite archive via the same realistic-distribution helpers used by",
- "`tests/benchmarks/conftest.py`.",
- "",
- "Adding a new scale benchmark:",
- "",
- "1. Decide the smallest tier that exposes the regression you want to catch.",
- " Prefer `scale_small` so the test runs in the default gate.",
- "2. Mark the test with the matching `@pytest.mark.scale_*` marker and",
- " request the corresponding `tier_*_db` fixture.",
- "3. Use ratio-based assertions across tiers (large/medium, medium/small)",
- " instead of absolute milliseconds — the latter bake in host-machine",
- " assumptions and break portability.",
- "4. If the test needs measured timings, also add `@pytest.mark.benchmark`",
- " and surface it through a benchmark campaign.",
- "",
- "## Slow-Test Policy",
- "",
- "- keep the default correctness lane representative of real archive/storage invariants",
- "- mark a test `slow` only when it is an optional heavy check, not a core correctness contract",
- "- review `pytest --durations` output when a new heavy test appears",
- "",
- "## Closure Matrix",
- "",
- "The per-domain closure matrix at `docs/plans/test-closure-matrix.yaml` maps each",
- "production domain to its representative tests, the verification gate that runs them,",
- "and any known gaps. `devtools verify closure-matrix` (wired into `devtools verify`)",
- "fails when a declared target or representative test path disappears, when an",
- "`absent` row is missing a `known_gaps` bullet, or when a `required`/`optional`",
- "row has no representative tests.",
- "",
- "When adding a new domain, parser, or surface, add or update its row in the matrix",
- "alongside the test that exercises it.",
- "",
- "## Workflow Guidance",
- "",
- "When changing code in a narrow domain:",
- "",
- "1. run the targeted `pytest -q -n 0` slice for that domain",
- "2. run the corresponding mutation campaign if that domain has one",
- "3. run the corresponding benchmark campaign only if the change touches a hot path already represented in `tests/benchmarks`",
- "4. rerun the full correctness lane before closing the work",
- "5. update `docs/plans/test-closure-matrix.yaml` if the domain's representative tests change",
- "",
- "When a new validation lane, mutation campaign, or benchmark campaign is added, make sure it dispatches concrete commands and regenerate this document.",
- "",
- ]
- return "\n".join(parts)
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description="Render docs/test-quality-workflows.md from live quality registries.")
- parser.add_argument(
- "--output",
- default="docs/test-quality-workflows.md",
- help="Output file path or '-' for stdout (default: docs/test-quality-workflows.md)",
- )
- parser.add_argument(
- "--check",
- action="store_true",
- help="Exit non-zero when the output file is out of sync with the rendered content.",
- )
- args = parser.parse_args(argv)
-
- output_path = None if args.output == "-" else Path(args.output).expanduser()
- rendered = build_document(build_quality_registry())
- if not rendered.endswith("\n"):
- rendered += "\n"
-
- if args.output == "-":
- if args.check:
- print("render quality-reference: --check does not support --output -", file=sys.stderr)
- return 2
- sys.stdout.write(rendered)
- return 0
-
- assert output_path is not None
- if args.check:
- try:
- current = output_path.read_text(encoding="utf-8")
- except FileNotFoundError:
- current = ""
- if current != rendered:
- print(f"render quality-reference: out of sync: {output_path}", file=sys.stderr)
- print(
- f"render quality-reference: run: {control_plane_command('render quality-reference', '--output', str(output_path))}",
- file=sys.stderr,
- )
- return 1
- print(f"render quality-reference: sync OK: {output_path}")
- return 0
-
- write_if_changed(output_path, rendered)
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
-
-
-__all__ = ["build_document", "main", "write_if_changed"]
diff --git a/devtools/render_semantic_card_registry.py b/devtools/render_semantic_card_registry.py
deleted file mode 100644
index a25047245d..0000000000
--- a/devtools/render_semantic_card_registry.py
+++ /dev/null
@@ -1,178 +0,0 @@
-"""Render the reviewable provider/tool → semantic-card registry surface."""
-
-from __future__ import annotations
-
-import argparse
-import json
-import sys
-from collections import Counter, defaultdict
-from pathlib import Path
-
-from polylogue.rendering.semantic_card_models import CARD_SCHEMA_VERSION, SemanticCardKind
-from polylogue.rendering.semantic_card_registry import (
- ToolMapping,
- provider_namespace_documents,
- semantic_type_policy_documents,
- tool_mapping_rows,
-)
-
-DEFAULT_JSON = Path("docs/generated/semantic-card-tool-map.json")
-DEFAULT_MARKDOWN = Path("docs/generated/semantic-card-tool-map.md")
-MAP_SCHEMA_VERSION = "semantic-card-tool-map.v1"
-
-
-def build_json_document() -> dict[str, object]:
- rows = tool_mapping_rows()
- counts = Counter(row.rendering_status for row in rows)
- policies = provider_namespace_documents()
- providers = sorted({str(policy["provider_family"]) for policy in policies})
- return {
- "schema_version": MAP_SCHEMA_VERSION,
- "card_schema_version": CARD_SCHEMA_VERSION,
- "classification_policy": {
- "precedence": [
- "structural_mcp_tool_identity",
- "persisted_semantic_type",
- "exact_provider_tool_alias",
- "fallback",
- ],
- "unknown_tool": "fallback_raw_evidence",
- "outcome_policy": "structural_fields_only",
- "null_outcome": "unknown",
- },
- "provider_families": providers,
- "card_kinds": [item.value for item in SemanticCardKind],
- "status_counts": dict(sorted(counts.items())),
- "provider_namespace_policies": policies,
- "semantic_type_policies": semantic_type_policy_documents(),
- "provider_semantic_coverage": [
- {
- "provider_family": provider,
- "semantic_types": sorted({row.semantic_type for row in rows if row.provider_family == provider}),
- "exact_alias_count": sum(1 for row in rows if row.provider_family == provider),
- }
- for provider in providers
- ],
- "rows": [row.to_document() for row in rows],
- }
-
-
-def build_markdown() -> str:
- grouped: dict[str, list[ToolMapping]] = defaultdict(list)
- for row in tool_mapping_rows():
- grouped[row.provider_family].append(row)
- lines = [
- "",
- "",
- "# Semantic card tool map",
- "",
- "This is the review surface for the provider-neutral `semantic-card.v1` registry. ",
- "Structural MCP identity wins, then persisted semantic type, then a repository-grounded ",
- "exact provider/tool alias. Provider namespaces are open: an unlisted tool always becomes a raw fallback card, ",
- "and names or prose are never fuzzily classified.",
- "",
- "`launch` means the shared CLI/API/web renderer has a specialized card. `model_only` means ",
- "the shared card is intentionally generic at the presentation leaf. `fallback` is intentional ",
- "raw evidence, not a missing hidden heuristic.",
- "",
- ]
- lines.extend(
- [
- "## Persisted semantic-family policy",
- "",
- "This table is exhaustive over `SemanticBlockType`. It is the provider-neutral path used ",
- "when a parser has already persisted a trusted family, including provider-private names ",
- "that cannot be enumerated in the exact-alias tables.",
- "",
- "| Persisted semantic type | Card kind | Status |",
- "|---|---|---|",
- ]
- )
- for policy in semantic_type_policy_documents():
- lines.append(f"| `{policy['semantic_type']}` | `{policy['card_kind']}` | `{policy['rendering_status']}` |")
- lines.extend(
- [
- "",
- "## Executable-origin policy",
- "",
- "Every `Origin` value has an explicit provider family and open-world fallback policy.",
- "",
- "| Origin | Provider family | Namespace | Grounded exact aliases | Unlisted behavior |",
- "|---|---|---|---:|---|",
- ]
- )
- for policy in provider_namespace_documents():
- lines.append(
- f"| `{policy['origin']}` | `{policy['provider_family']}` | `{policy['namespace']}` | "
- f"{policy['grounded_exact_aliases']} | `{policy['unlisted_behavior']}` |"
- )
- lines.extend(["", "## Provider exact-alias census", ""])
-
- for provider in sorted(grouped):
- lines.extend(
- [
- f"## {provider}",
- "",
- "| Exact tool name | Semantic type | Card kind | Status | Basis | Evidence |",
- "|---|---|---|---|---|---|",
- ]
- )
- for row in sorted(grouped[provider], key=lambda item: item.tool_name.casefold()):
- lines.append(
- f"| `{row.tool_name}` | `{row.semantic_type}` | `{row.card_kind.value}` | "
- f"`{row.rendering_status}` | `{row.evidence_kind}` | `{row.evidence}` |"
- )
- lines.append("")
- lines.extend(
- [
- "## Gap-reading rules",
- "",
- "- Every executable origin has an explicit open namespace; the exact-alias table is evidence-backed rather than aspirational.",
- "- A structural `mcp__server__tool` identity is classified before provider aliases and exposes both server and tool coordinates.",
- "- A provider can emit tool names not listed here. Those cards preserve exact raw input and result evidence.",
- "- A persisted `semantic_type` can safely specialize a provider-private name because classification already happened upstream.",
- "- `NULL` structural result fields remain `unknown`; a success-like sentence is not a success signal.",
- "- Cross-page pairing is orchestrated from a whole-session projection; a bounded storage-level pairing index remains a performance follow-on.",
- "",
- ]
- )
- return "\n".join(line.rstrip() for line in lines)
-
-
-def _write_or_check(path: Path, content: str, *, check: bool) -> bool:
- current = path.read_text(encoding="utf-8") if path.exists() else None
- if check:
- return current == content
- path.parent.mkdir(parents=True, exist_ok=True)
- path.write_text(content, encoding="utf-8")
- return True
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__)
- mode = parser.add_mutually_exclusive_group(required=True)
- mode.add_argument("--check", action="store_true")
- mode.add_argument("--write", action="store_true")
- parser.add_argument("--json", type=Path, default=DEFAULT_JSON)
- parser.add_argument("--markdown", type=Path, default=DEFAULT_MARKDOWN)
- args = parser.parse_args(argv)
-
- json_text = json.dumps(build_json_document(), indent=2, ensure_ascii=False) + "\n"
- markdown_text = build_markdown()
- results = {
- args.json: _write_or_check(args.json, json_text, check=args.check),
- args.markdown: _write_or_check(args.markdown, markdown_text, check=args.check),
- }
- stale = [path for path, ok in results.items() if not ok]
- if stale:
- print("semantic-card registry: generated surfaces are stale", file=sys.stderr)
- for path in stale:
- print(f" - {path}", file=sys.stderr)
- return 1
- action = "verified" if args.check else "wrote"
- print(f"semantic-card registry: {action} {len(results)} surface(s)")
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/render_visual_tapes.py b/devtools/render_visual_tapes.py
index ca86e3b94b..05634b0b1b 100644
--- a/devtools/render_visual_tapes.py
+++ b/devtools/render_visual_tapes.py
@@ -9,13 +9,9 @@
command that regenerates the demo screencast media, so the first-contact GIF
stays reproducible instead of being a committed binary that bitrots.
-``--check`` does two things (polylogue-3tl.17): it confirms every default spec
-still generates cleanly (structural check), and it byte-compares each
-generated tape against its committed counterpart under
-``docs/examples/visual-tapes/`` (drift check). The kit shipped a stale
-``demo-tour.tape`` twice in 2026-07 with every prior gate green -- the specs
-generated cleanly, nothing compared the output against what was actually
-committed.
+``--check`` confirms every default spec still generates cleanly and
+byte-compares each generated tape against its committed counterpart under
+``docs/examples/visual-tapes/``.
"""
from __future__ import annotations
@@ -40,13 +36,7 @@
def committed_tape_drift(
tapes: dict[str, str], *, committed_dir: Path = COMMITTED_TAPES_DIR
) -> dict[str, tuple[str | None, str]]:
- """Return ``{spec_name: (committed_text_or_None, generated_text)}`` for every
- spec whose generated content differs from (or has no) committed tape.
-
- A spec with no committed tape at all is reported too (``committed`` is
- ``None``) rather than silently skipped -- a new default spec ships with a
- committed tape from day one, not a bare generator entry.
- """
+ """Return generated tapes that differ from the committed visual surface."""
drift: dict[str, tuple[str | None, str]] = {}
for name, generated in tapes.items():
committed_path = committed_dir / f"{name}.tape"
@@ -92,10 +82,7 @@ def main(argv: list[str] | None = None) -> int:
parser.add_argument(
"--check",
action="store_true",
- help=(
- "verify the tape specs generate cleanly and match the committed "
- f"tapes under {COMMITTED_TAPES_DIR}, without writing any files"
- ),
+ help="verify generated tapes match the committed visual surface without writing files",
)
args = parser.parse_args(argv)
@@ -103,16 +90,10 @@ def main(argv: list[str] | None = None) -> int:
if args.check:
tapes = generate_all_tapes(specs)
- print(f"visual-tapes: {len(tapes)} tape specs generate cleanly")
drift = committed_tape_drift(tapes)
if drift:
- print(f"visual-tapes: {len(drift)} committed tape(s) out of sync with their spec:", file=sys.stderr)
- _print_drift(drift, committed_dir=COMMITTED_TAPES_DIR)
- print(
- "visual-tapes: run 'devtools render visual-tapes --output-dir "
- f"{COMMITTED_TAPES_DIR}' and commit the result to fix",
- file=sys.stderr,
- )
+ print(f"visual-tapes: {len(drift)} committed tape(s) out of sync", file=sys.stderr)
+ _print_drift(drift)
return 1
print(f"visual-tapes: {len(tapes)} committed tape(s) match their generated spec output")
return 0
@@ -149,17 +130,7 @@ def main(argv: list[str] | None = None) -> int:
def generated_surface_main(argv: list[str] | None = None) -> int:
- """Entry point wired into ``devtools.generated_surfaces.GENERATED_SURFACES``.
-
- ``--check`` behaves exactly like the public CLI: it drift-compares the
- generated tapes against the committed ``docs/examples/visual-tapes/``
- directory without writing anything. Render mode, however, writes directly
- into that committed directory (rather than the public CLI's
- ``.local/visual-tapes`` staging default) so a plain ``devtools render
- all`` fixes drift in place, matching every other generated surface. The
- public ``devtools render visual-tapes`` command keeps its staging default
- for manual iteration and ``--capture`` GIF runs.
- """
+ """Render/check the committed tape files as a generated repository surface."""
args = list(argv or [])
if "--check" in args:
return main(args)
diff --git a/devtools/run_campaign.py b/devtools/run_campaign.py
index f9fa79a237..885f97fdc1 100644
--- a/devtools/run_campaign.py
+++ b/devtools/run_campaign.py
@@ -10,6 +10,8 @@
import argparse
import asyncio
+import inspect
+import json
import shutil
import sys
from pathlib import Path
@@ -39,7 +41,7 @@ def _parse_args(argv: list[str] | None = None) -> argparse.Namespace:
"--output",
type=Path,
default=ROOT / ".local" / "benchmark-campaigns",
- help="Output directory for reports (default: .local/benchmark-campaigns/)",
+ help="Output directory for generated archives (default: .local/benchmark-campaigns/)",
)
parser.add_argument(
"--list",
@@ -63,37 +65,55 @@ def _parse_args(argv: list[str] | None = None) -> argparse.Namespace:
async def _run(args: argparse.Namespace) -> int:
- from devtools.benchmark_campaigns import (
- SYNTHETIC_CAMPAIGNS,
- run_full_campaign,
- run_synthetic_benchmark_campaign,
- )
from devtools.campaign_archive_location import CampaignArchiveLocation
- from devtools.campaign_report import save_campaign_reports
from devtools.large_archive_generator import (
ScaleLevel,
generate_archive,
get_default_spec,
)
+ from devtools.synthetic_benchmark_runtime import SYNTHETIC_BENCHMARK_RUNNERS, CampaignResult
+
+ async def run_synthetic_benchmark(name: str, db_path: Path) -> CampaignResult:
+ try:
+ runner = SYNTHETIC_BENCHMARK_RUNNERS[name]
+ except KeyError as exc:
+ raise ValueError(f"Unknown synthetic benchmark runner {name!r}") from exc
+ result = runner(db_path)
+ if inspect.isawaitable(result):
+ return await result
+ return result
if args.list_campaigns:
- print("Available campaigns:")
- for campaign in SYNTHETIC_CAMPAIGNS.values():
- print(f" {campaign.name}: {campaign.description}")
+ print("Available synthetic benchmark runners:")
+ for name in SYNTHETIC_BENCHMARK_RUNNERS:
+ print(f" {name}")
print("\nScale levels: small, medium, large, stretch")
return 0
if args.campaign == "all":
- results = await run_full_campaign(
- args.scale,
- args.output,
- corpus_source=CorpusSourceKind(args.corpus_source),
- )
+ level = ScaleLevel(args.scale)
+ spec = get_default_spec(level)
+ archive_dir = args.output / f"archive-{args.scale}"
+ archive_dir.mkdir(parents=True, exist_ok=True)
+ with CampaignArchiveLocation.acquire(archive_dir) as location:
+ print(f"Generating {args.scale} archive from {args.corpus_source} corpus source...")
+ await generate_archive(
+ spec,
+ archive_dir,
+ corpus_source=CorpusSourceKind(args.corpus_source),
+ location=location,
+ )
+ results: list[CampaignResult] = []
+ for name in SYNTHETIC_BENCHMARK_RUNNERS:
+ print(f"Running {name}...")
+ result = await run_synthetic_benchmark(name, location.active_index_path)
+ result.scale_level = args.scale
+ results.append(result)
else:
# Generate archive first
- if args.campaign not in SYNTHETIC_CAMPAIGNS:
+ if args.campaign not in SYNTHETIC_BENCHMARK_RUNNERS:
print(f"Unknown campaign: {args.campaign}")
- print(f"Available: {', '.join(SYNTHETIC_CAMPAIGNS)}")
+ print(f"Available: {', '.join(SYNTHETIC_BENCHMARK_RUNNERS)}")
return 1
archive_dir = args.output / f"archive-{args.scale}"
@@ -109,7 +129,7 @@ async def _run(args: argparse.Namespace) -> int:
archive_dir.mkdir(parents=True, exist_ok=True)
with CampaignArchiveLocation.acquire(archive_dir) as location:
- result = await run_synthetic_benchmark_campaign(args.campaign, location.active_index_path)
+ result = await run_synthetic_benchmark(args.campaign, location.active_index_path)
else:
level = ScaleLevel(args.scale)
spec = get_default_spec(level)
@@ -122,6 +142,7 @@ async def _run(args: argparse.Namespace) -> int:
print(f"Generating {args.scale} archive from {args.corpus_source} corpus source...")
+ archive_dir.mkdir(parents=True, exist_ok=True)
with CampaignArchiveLocation.acquire(archive_dir) as location:
await generate_archive(
spec,
@@ -129,16 +150,13 @@ async def _run(args: argparse.Namespace) -> int:
corpus_source=CorpusSourceKind(args.corpus_source),
location=location,
)
- result = await run_synthetic_benchmark_campaign(args.campaign, location.active_index_path)
+ result = await run_synthetic_benchmark(args.campaign, location.active_index_path)
result.scale_level = args.scale
results = [result]
- # Save reports
- saved = save_campaign_reports(results, args.output)
- print("\nReports saved:")
- for path in saved:
- print(f" {path}")
+ for result in results:
+ print(f"{result.campaign_name}: {json.dumps(result.metrics, sort_keys=True)}")
return 0
diff --git a/devtools/run_validation_lanes.py b/devtools/run_validation_lanes.py
deleted file mode 100644
index 3cabe942d8..0000000000
--- a/devtools/run_validation_lanes.py
+++ /dev/null
@@ -1,80 +0,0 @@
-"""Run named validation lanes for the remaining operator frontier.
-
-Usage:
- devtools lab lanes --list
- devtools lab lanes --lane machine-contract
- devtools lab lanes --lane frontier-local --dry-run
- devtools lab lanes --lane archive-intelligence --dry-run
-"""
-
-from __future__ import annotations
-
-import sys
-
-from devtools.lane_models import LaneEntry
-from devtools.validation_lane_runtime import (
- LANES,
- VALID_LANES,
- build_lane_command,
- parse_lane,
- print_lane,
- run_lane,
-)
-
-
-def main(argv: list[str] | None = None) -> int:
- """Main entry point."""
- import argparse
-
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- )
- parser.add_argument(
- "--lane",
- choices=sorted(VALID_LANES),
- help="Validation lane to run",
- )
- parser.add_argument(
- "--list",
- action="store_true",
- dest="list_lanes",
- help="List available lanes and exit",
- )
- parser.add_argument(
- "--dry-run",
- action="store_true",
- help="Print the selected lane command(s) without running them",
- )
- args = parser.parse_args(argv)
-
- if args.list_lanes:
- print("Available validation lanes:")
- for lane_name in sorted(VALID_LANES):
- lane = parse_lane(lane_name)
- print(f" {lane.name}: {lane.description}")
- return 0
-
- if not args.lane:
- parser.error("--lane is required unless --list is used")
-
- lane = parse_lane(args.lane)
- if args.dry_run:
- print_lane(lane)
- return 0
-
- return run_lane(lane)
-
-
-__all__ = [
- "LANES",
- "VALID_LANES",
- "LaneEntry",
- "build_lane_command",
- "main",
- "parse_lane",
-]
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/scenario_coverage.py b/devtools/scenario_coverage.py
deleted file mode 100644
index 01f9acaf3c..0000000000
--- a/devtools/scenario_coverage.py
+++ /dev/null
@@ -1,178 +0,0 @@
-"""Shared runtime scenario-coverage computation for control-plane surfaces."""
-
-from __future__ import annotations
-
-from dataclasses import dataclass
-
-from devtools.scenario_projection_catalog import build_scenario_projection_entries
-from polylogue.artifacts.graph import build_artifact_graph
-from polylogue.core.json import JSONDocument, json_document
-from polylogue.scenarios import ScenarioProjectionEntry, declared_operation_target_names
-
-
-@dataclass(frozen=True, slots=True)
-class ScenarioCoverageRef:
- source: str
- name: str
- origin: str
-
- def to_dict(self) -> dict[str, str]:
- return {
- "source": self.source,
- "name": self.name,
- "origin": self.origin,
- }
-
-
-@dataclass(frozen=True, slots=True)
-class RuntimePathCoverage:
- name: str
- refs: tuple[ScenarioCoverageRef, ...]
- uncovered_artifacts: tuple[str, ...]
- uncovered_operations: tuple[str, ...]
- uncovered_route_operations: tuple[str, ...] = ()
- missing_route_declaration: bool = False
-
- @property
- def complete(self) -> bool:
- return (
- not self.uncovered_artifacts
- and not self.uncovered_operations
- and not self.uncovered_route_operations
- and not self.missing_route_declaration
- )
-
- def to_dict(self) -> JSONDocument:
- return json_document(
- {
- "refs": [ref.to_dict() for ref in self.refs],
- "uncovered_artifacts": list(self.uncovered_artifacts),
- "uncovered_operations": list(self.uncovered_operations),
- "uncovered_route_operations": list(self.uncovered_route_operations),
- "missing_route_declaration": self.missing_route_declaration,
- "complete": self.complete,
- }
- )
-
-
-@dataclass(frozen=True, slots=True)
-class RuntimeScenarioCoverage:
- artifacts: dict[str, tuple[ScenarioCoverageRef, ...]]
- operations: dict[str, tuple[ScenarioCoverageRef, ...]]
- maintenance_targets: dict[str, tuple[ScenarioCoverageRef, ...]]
- declared_operations: dict[str, tuple[ScenarioCoverageRef, ...]]
- paths: dict[str, RuntimePathCoverage]
- uncovered_artifacts: tuple[str, ...]
- uncovered_operations: tuple[str, ...]
- uncovered_maintenance_targets: tuple[str, ...]
- uncovered_declared_operations: tuple[str, ...]
-
- def to_dict(self) -> JSONDocument:
- return json_document(
- {
- "artifacts": {name: [ref.to_dict() for ref in refs] for name, refs in self.artifacts.items()},
- "operations": {name: [ref.to_dict() for ref in refs] for name, refs in self.operations.items()},
- "maintenance_targets": {
- name: [ref.to_dict() for ref in refs] for name, refs in self.maintenance_targets.items()
- },
- "declared_operations": {
- name: [ref.to_dict() for ref in refs] for name, refs in self.declared_operations.items()
- },
- "paths": {name: path.to_dict() for name, path in self.paths.items()},
- "uncovered_artifacts": list(self.uncovered_artifacts),
- "uncovered_operations": list(self.uncovered_operations),
- "uncovered_maintenance_targets": list(self.uncovered_maintenance_targets),
- "uncovered_declared_operations": list(self.uncovered_declared_operations),
- }
- )
-
-
-def build_runtime_scenario_coverage(
- *,
- projections: tuple[ScenarioProjectionEntry, ...] | None = None,
-) -> RuntimeScenarioCoverage:
- scenario_projections = projections or build_scenario_projection_entries()
- graph = build_artifact_graph()
- artifact_refs: dict[str, list[ScenarioCoverageRef]] = {name: [] for name in graph.by_name()}
- operation_refs: dict[str, list[ScenarioCoverageRef]] = {operation.name: [] for operation in graph.operations}
- maintenance_target_refs: dict[str, list[ScenarioCoverageRef]] = {
- target.name: [] for target in graph.maintenance_targets
- }
- declared_operation_refs: dict[str, list[ScenarioCoverageRef]] = {
- name: [] for name in declared_operation_target_names()
- }
- path_refs: dict[str, list[ScenarioCoverageRef]] = {path.name: [] for path in graph.paths}
- path_operation_refs: dict[str, dict[str, list[ScenarioCoverageRef]]] = {
- path.name: {operation.name: [] for operation in graph.operations_for_path(path)} for path in graph.paths
- }
-
- for projection in scenario_projections:
- ref = ScenarioCoverageRef(source=projection.source_kind.value, name=projection.name, origin=projection.origin)
- runtime_paths = projection.resolve_runtime_paths()
- runtime_operations = projection.resolve_runtime_operations()
- for path in runtime_paths:
- path_refs[path.name].append(ref)
- for operation in runtime_operations:
- if operation.name in path_operation_refs[path.name]:
- path_operation_refs[path.name][operation.name].append(ref)
- for artifact in projection.resolve_runtime_artifacts():
- artifact_refs[artifact.name].append(ref)
- for operation in runtime_operations:
- operation_refs[operation.name].append(ref)
- maintenance_targets = {
- *projection.resolve_runtime_maintenance_targets(),
- *graph.maintenance_targets_for_operation_names(projection.runtime_operation_targets()),
- }
- for target in maintenance_targets:
- maintenance_target_refs[target.name].append(ref)
- for operation_name in projection.declared_operation_targets():
- declared_operation_refs[operation_name].append(ref)
-
- covered_artifacts = {name: tuple(refs) for name, refs in artifact_refs.items() if refs}
- covered_operations = {name: tuple(refs) for name, refs in operation_refs.items() if refs}
- covered_maintenance_targets = {name: tuple(refs) for name, refs in maintenance_target_refs.items() if refs}
- covered_declared_operations = {name: tuple(refs) for name, refs in declared_operation_refs.items() if refs}
- path_coverage: dict[str, RuntimePathCoverage] = {}
- for path in graph.paths:
- relevant_operations = tuple(operation.name for operation in graph.operations_for_path(path))
- refs = {
- *path_refs[path.name],
- *(ref for node_name in path.nodes for ref in artifact_refs[node_name]),
- *(ref for operation_name in relevant_operations for ref in operation_refs[operation_name]),
- }
- path_coverage[path.name] = RuntimePathCoverage(
- name=path.name,
- refs=tuple(sorted(refs, key=lambda ref: (ref.source, ref.name, ref.origin))),
- uncovered_artifacts=tuple(sorted(node_name for node_name in path.nodes if not artifact_refs[node_name])),
- uncovered_operations=tuple(
- sorted(operation_name for operation_name in relevant_operations if not operation_refs[operation_name])
- ),
- uncovered_route_operations=tuple(
- sorted(
- operation_name
- for operation_name in relevant_operations
- if not path_operation_refs[path.name][operation_name]
- )
- ),
- missing_route_declaration=bool(relevant_operations) and not path_refs[path.name],
- )
-
- return RuntimeScenarioCoverage(
- artifacts=covered_artifacts,
- operations=covered_operations,
- maintenance_targets=covered_maintenance_targets,
- declared_operations=covered_declared_operations,
- paths=path_coverage,
- uncovered_artifacts=tuple(sorted(name for name, refs in artifact_refs.items() if not refs)),
- uncovered_operations=tuple(sorted(name for name, refs in operation_refs.items() if not refs)),
- uncovered_maintenance_targets=tuple(sorted(name for name, refs in maintenance_target_refs.items() if not refs)),
- uncovered_declared_operations=tuple(sorted(name for name, refs in declared_operation_refs.items() if not refs)),
- )
-
-
-__all__ = [
- "RuntimeScenarioCoverage",
- "RuntimePathCoverage",
- "ScenarioCoverageRef",
- "build_runtime_scenario_coverage",
-]
diff --git a/devtools/scenario_projection_catalog.py b/devtools/scenario_projection_catalog.py
deleted file mode 100644
index f3f96198e6..0000000000
--- a/devtools/scenario_projection_catalog.py
+++ /dev/null
@@ -1,17 +0,0 @@
-"""Live catalog of authored scenario-bearing verification projections."""
-
-from __future__ import annotations
-
-from devtools.authored_scenario_catalog import AuthoredScenarioCatalog, get_authored_scenario_catalog
-from polylogue.scenarios import ScenarioProjectionEntry
-
-
-def build_scenario_projection_entries(
- *,
- catalog: AuthoredScenarioCatalog | None = None,
-) -> tuple[ScenarioProjectionEntry, ...]:
- authored_catalog = catalog or get_authored_scenario_catalog()
- return authored_catalog.compile_projection_entries()
-
-
-__all__ = ["build_scenario_projection_entries"]
diff --git a/devtools/scenario_projections.py b/devtools/scenario_projections.py
deleted file mode 100644
index dda111902d..0000000000
--- a/devtools/scenario_projections.py
+++ /dev/null
@@ -1,124 +0,0 @@
-"""Render authored scenario-bearing verification projections."""
-
-from __future__ import annotations
-
-import argparse
-import json
-import sys
-from collections.abc import Iterable
-
-from devtools.scenario_projection_catalog import build_scenario_projection_entries
-from polylogue.scenarios import ScenarioProjectionEntry
-
-
-def _select_projections(
- projections: Iterable[ScenarioProjectionEntry],
- *,
- source_kinds: tuple[str, ...],
- path_target: str | None,
- artifact_target: str | None,
- operation_target: str | None,
- tag: str | None,
-) -> tuple[ScenarioProjectionEntry, ...]:
- selected: list[ScenarioProjectionEntry] = []
- for entry in projections:
- if source_kinds and entry.source_kind.value not in source_kinds:
- continue
- if path_target and path_target not in entry.runtime_path_targets():
- continue
- if artifact_target and artifact_target not in entry.artifact_targets:
- continue
- if operation_target and operation_target not in entry.operation_targets:
- continue
- if tag and tag not in entry.tags:
- continue
- selected.append(entry)
- return tuple(selected)
-
-
-def render_scenario_projections(
- *,
- as_json: bool,
- source_kinds: tuple[str, ...] = (),
- path_target: str | None = None,
- artifact_target: str | None = None,
- operation_target: str | None = None,
- tag: str | None = None,
-) -> str:
- projections = _select_projections(
- build_scenario_projection_entries(),
- source_kinds=source_kinds,
- path_target=path_target,
- artifact_target=artifact_target,
- operation_target=operation_target,
- tag=tag,
- )
- if as_json:
- return json.dumps([entry.to_dict() for entry in projections], indent=2)
-
- lines = [f"Scenario Projections ({len(projections)}):"]
- if not projections:
- lines.append("- none")
- return "\n".join(lines)
- for entry in projections:
- lines.append(f"- {entry.source_kind.value}:{entry.name} [{entry.origin}]")
- lines.append(f" - description: {entry.description}")
- lines.append(
- f" - path targets: {', '.join(entry.runtime_path_targets()) if entry.runtime_path_targets() else '—'}"
- )
- lines.append(f" - artifact targets: {', '.join(entry.artifact_targets) if entry.artifact_targets else '—'}")
- lines.append(
- " - conceptual path targets: "
- f"{', '.join(entry.conceptual_path_targets) if entry.conceptual_path_targets else '—'}"
- )
- lines.append(
- " - conceptual artifact targets: "
- f"{', '.join(entry.conceptual_artifact_targets) if entry.conceptual_artifact_targets else '—'}"
- )
- lines.append(f" - operation targets: {', '.join(entry.operation_targets) if entry.operation_targets else '—'}")
- lines.append(f" - tags: {', '.join(entry.tags) if entry.tags else '—'}")
- if entry.docs_role or entry.caption or entry.demonstrates:
- lines.append(f" - docs role: {entry.docs_role or '—'}")
- lines.append(f" - caption: {entry.caption or '—'}")
- lines.append(f" - demonstrates: {', '.join(entry.demonstrates) if entry.demonstrates else '—'}")
- return "\n".join(lines)
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--json", action="store_true", help="Emit scenario projections as JSON.")
- parser.add_argument(
- "--source-kind",
- dest="source_kinds",
- action="append",
- default=[],
- help="Restrict to a specific projection source kind (repeatable).",
- )
- parser.add_argument(
- "--path-target", default=None, help="Restrict to projections covering this runtime path target."
- )
- parser.add_argument(
- "--artifact-target", default=None, help="Restrict to projections covering this artifact target."
- )
- parser.add_argument(
- "--operation-target",
- default=None,
- help="Restrict to projections covering this operation target.",
- )
- parser.add_argument("--tag", default=None, help="Restrict to projections carrying this tag.")
- args = parser.parse_args(argv)
- sys.stdout.write(
- render_scenario_projections(
- as_json=args.json,
- source_kinds=tuple(args.source_kinds),
- path_target=args.path_target,
- artifact_target=args.artifact_target,
- operation_target=args.operation_target,
- tag=args.tag,
- )
- )
- sys.stdout.write("\n")
- return 0
-
-
-__all__ = ["main", "render_scenario_projections"]
diff --git a/devtools/seed_receipt_compare.py b/devtools/seed_receipt_compare.py
deleted file mode 100644
index 090f1857e6..0000000000
--- a/devtools/seed_receipt_compare.py
+++ /dev/null
@@ -1,362 +0,0 @@
-"""Like-for-like comparison of two workload receipts (polylogue-b054.1.1.3).
-
-``devtools verify`` and ``devtools test`` already emit a real ``WorkloadReceipt``
-(``polylogue/scenarios/workload.py``) for every managed pytest step, embedded
-under ``metadata["workload_receipt"]`` and persisted to each step's
-``postmortem.json``. PR #2934/#2980 extended that receipt with per-process-tree
-and cgroup RSS/PSS/swap/read/write accounting, but nothing yet *used* two such
-receipts together to answer the question the resource accounting exists to
-answer: "is this run clean, comparable to a named baseline, and within its
-declared physical envelope?"
-
-This module closes that gap. It does not invent a new sampling mechanism —
-it reads the receipts PR #2934/#2980 already produce and:
-
-1. Confirms the two runs are actually comparable ("like-for-like"): the same
- declared workload/family/input identity, and both terminated
- ``succeeded`` — a partial, failed, or cancelled run cannot anchor or be
- judged against a physical-envelope target.
-2. Evaluates a small set of declared comparison targets (wall-time speedup
- relative to the baseline, an absolute peak-PSS ceiling) against the
- observed ``execute``-phase measures, using the same
- :class:`~polylogue.scenarios.workload.BudgetVerdict` vocabulary the rest of
- the workload-receipt system already uses — ``pass``, ``exceeded``, or
- ``measurement-unavailable`` (never a fabricated pass when a measure was not
- captured).
-3. Names an explicit blocker and a linked follow-up reference for every
- unmet target, so an unmet 2x/peak-memory target is durable evidence
- instead of a silently-dropped aspiration (polylogue-b054.1.1 AC5/AC8).
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import sys
-from collections.abc import Mapping, Sequence
-from dataclasses import dataclass
-from enum import Enum
-from pathlib import Path
-from typing import Any
-
-from polylogue.scenarios.workload import BudgetMeasure, BudgetVerdict
-
-#: The follow-up that owns closing the still-outstanding memory-amplification
-#: gap identified while proving polylogue-b054.1.1's own 2x/<3GiB target
-#: (see that bead's notes, 2026-07-16).
-DEFAULT_FOLLOW_UP_REF = "polylogue-b054.1.1.2"
-
-_GIB = 1024**3
-
-
-class ComparisonTargetKind(str, Enum):
- """How a target's ``limit`` relates the candidate to the baseline."""
-
- #: candidate <= baseline * limit (e.g. limit=0.5 asserts a 2x speedup).
- MAX_RATIO_OF_BASELINE = "max-ratio-of-baseline"
- #: candidate <= limit, independent of the baseline's own value.
- MAX_ABSOLUTE = "max-absolute"
-
-
-@dataclass(frozen=True, slots=True)
-class ReceiptComparisonTarget:
- """One declared comparison budget over a workload receipt's phase measure."""
-
- measure: BudgetMeasure
- kind: ComparisonTargetKind
- limit: float
- phase: str = "execute"
- follow_up_ref: str | None = None
-
- def to_payload(self) -> dict[str, Any]:
- return {
- "measure": self.measure.value,
- "kind": self.kind.value,
- "limit": self.limit,
- "phase": self.phase,
- "follow_up_ref": self.follow_up_ref,
- }
-
-
-@dataclass(frozen=True, slots=True)
-class ReceiptComparisonResult:
- """Verdict for one declared target after comparing baseline vs candidate."""
-
- measure: BudgetMeasure
- kind: ComparisonTargetKind
- phase: str
- limit: float
- baseline_value: float | None
- candidate_value: float | None
- ratio: float | None
- verdict: BudgetVerdict
- blocker: str | None
- follow_up_ref: str | None
-
- def to_payload(self) -> dict[str, Any]:
- return {
- "measure": self.measure.value,
- "kind": self.kind.value,
- "phase": self.phase,
- "limit": self.limit,
- "baseline_value": self.baseline_value,
- "candidate_value": self.candidate_value,
- "ratio": self.ratio,
- "verdict": self.verdict.value,
- "blocker": self.blocker,
- "follow_up_ref": self.follow_up_ref,
- }
-
-
-def default_seed_comparison_targets(
- *,
- follow_up_ref: str = DEFAULT_FOLLOW_UP_REF,
- speedup_ratio: float = 0.5,
- peak_pss_ceiling_bytes: float = 3 * _GIB,
-) -> tuple[ReceiptComparisonTarget, ...]:
- """Return the polylogue-b054.1.1 seed-comparison targets (2x wall, <3GiB peak PSS).
-
- ``speedup_ratio=0.5`` means the candidate's wall time must be at most half
- the baseline's — i.e. at least a 2x speedup, matching the target recorded
- in polylogue-b054.1.1's own acceptance criteria.
- """
- return (
- ReceiptComparisonTarget(
- measure=BudgetMeasure.WALL_MS,
- kind=ComparisonTargetKind.MAX_RATIO_OF_BASELINE,
- limit=speedup_ratio,
- phase="execute",
- follow_up_ref=follow_up_ref,
- ),
- ReceiptComparisonTarget(
- measure=BudgetMeasure.PEAK_PSS_BYTES,
- kind=ComparisonTargetKind.MAX_ABSOLUTE,
- limit=peak_pss_ceiling_bytes,
- phase="execute",
- follow_up_ref=follow_up_ref,
- ),
- )
-
-
-def _phase(receipt: Mapping[str, Any], phase: str) -> Mapping[str, Any] | None:
- phases = receipt.get("phases")
- if not isinstance(phases, list):
- return None
- for candidate_phase in phases:
- if isinstance(candidate_phase, dict) and candidate_phase.get("name") == phase:
- return candidate_phase
- return None
-
-
-def _measure_value(receipt: Mapping[str, Any], *, phase: str, measure: BudgetMeasure) -> float | None:
- observed_phase = _phase(receipt, phase)
- if observed_phase is None:
- return None
- value = observed_phase.get(measure.value)
- if isinstance(value, bool) or not isinstance(value, (int, float)):
- return None
- return float(value)
-
-
-def identity_mismatches(baseline: Mapping[str, Any], candidate: Mapping[str, Any]) -> tuple[str, ...]:
- """Return every field that keeps two receipts from being like-for-like.
-
- Comparable receipts must declare the identical workload/family identity
- and the identical input digest (``spec.inputs[*].input_id`` is a content
- hash of the workload's command/selection) — otherwise a ratio between the
- two measures nothing.
- """
- raw_baseline_spec = baseline.get("spec")
- raw_candidate_spec = candidate.get("spec")
- baseline_spec: dict[str, Any] = raw_baseline_spec if isinstance(raw_baseline_spec, dict) else {}
- candidate_spec: dict[str, Any] = raw_candidate_spec if isinstance(raw_candidate_spec, dict) else {}
- mismatches: list[str] = []
- for field in ("workload_id", "family_id", "measurement_scope"):
- baseline_value = baseline_spec.get(field)
- candidate_value = candidate_spec.get(field)
- if baseline_value != candidate_value:
- mismatches.append(f"{field}: baseline={baseline_value!r} candidate={candidate_value!r}")
- baseline_inputs = tuple(item.get("input_id") for item in baseline_spec.get("inputs", []) if isinstance(item, dict))
- candidate_inputs = tuple(
- item.get("input_id") for item in candidate_spec.get("inputs", []) if isinstance(item, dict)
- )
- if baseline_inputs != candidate_inputs:
- mismatches.append(f"inputs: baseline={baseline_inputs!r} candidate={candidate_inputs!r}")
- return tuple(mismatches)
-
-
-def evaluate_target(
- baseline: Mapping[str, Any],
- candidate: Mapping[str, Any],
- target: ReceiptComparisonTarget,
-) -> ReceiptComparisonResult:
- """Score one declared target without inventing a verdict for missing data."""
- baseline_value = _measure_value(baseline, phase=target.phase, measure=target.measure)
- candidate_value = _measure_value(candidate, phase=target.phase, measure=target.measure)
-
- ratio = None
- if baseline_value is not None and candidate_value is not None and baseline_value != 0:
- ratio = candidate_value / baseline_value
-
- if baseline_value is None or candidate_value is None:
- verdict = BudgetVerdict.MEASUREMENT_UNAVAILABLE
- elif target.kind is ComparisonTargetKind.MAX_RATIO_OF_BASELINE:
- effective_limit = baseline_value * target.limit
- verdict = BudgetVerdict.PASS if candidate_value <= effective_limit else BudgetVerdict.EXCEEDED
- else:
- verdict = BudgetVerdict.PASS if candidate_value <= target.limit else BudgetVerdict.EXCEEDED
-
- blocker: str | None = None
- if verdict is BudgetVerdict.EXCEEDED:
- if target.kind is ComparisonTargetKind.MAX_RATIO_OF_BASELINE:
- blocker = (
- f"{target.measure.value} on phase {target.phase!r}: candidate={candidate_value!r} "
- f"baseline={baseline_value!r} ratio={ratio!r} exceeds the declared "
- f"max-ratio-of-baseline target {target.limit!r}"
- )
- else:
- blocker = (
- f"{target.measure.value} on phase {target.phase!r}: candidate={candidate_value!r} "
- f"exceeds the declared absolute ceiling {target.limit!r}"
- )
-
- return ReceiptComparisonResult(
- measure=target.measure,
- kind=target.kind,
- phase=target.phase,
- limit=target.limit,
- baseline_value=baseline_value,
- candidate_value=candidate_value,
- ratio=ratio,
- verdict=verdict,
- blocker=blocker,
- follow_up_ref=target.follow_up_ref if verdict is BudgetVerdict.EXCEEDED else None,
- )
-
-
-def compare_receipts(
- baseline: Mapping[str, Any],
- candidate: Mapping[str, Any],
- targets: Sequence[ReceiptComparisonTarget] | None = None,
-) -> dict[str, Any]:
- """Compare two workload receipts and score every declared target.
-
- Returns a JSON-serializable dict; ``like_for_like`` is ``False`` whenever
- the two receipts do not share workload identity or either run did not
- terminate ``succeeded`` — a dirty or mismatched pair cannot license any
- budget verdict below, regardless of what the individual measures say.
- """
- resolved_targets = tuple(targets) if targets is not None else default_seed_comparison_targets()
- mismatches = identity_mismatches(baseline, candidate)
- baseline_status = baseline.get("status")
- candidate_status = candidate.get("status")
- clean = baseline_status == "succeeded" and candidate_status == "succeeded"
- like_for_like = not mismatches and clean
-
- results = tuple(evaluate_target(baseline, candidate, target) for target in resolved_targets)
- exceeded = tuple(result for result in results if result.verdict is BudgetVerdict.EXCEEDED)
-
- return {
- "like_for_like": like_for_like,
- "identity_mismatches": list(mismatches),
- "baseline_status": baseline_status,
- "candidate_status": candidate_status,
- "targets_met": like_for_like and not exceeded,
- "results": [result.to_payload() for result in results],
- }
-
-
-def _unwrap_receipt(payload: Mapping[str, Any]) -> Mapping[str, Any]:
- """Accept either a bare workload receipt or a wrapping postmortem.json."""
- workload_receipt = payload.get("workload_receipt")
- if isinstance(workload_receipt, dict):
- return workload_receipt
- return payload
-
-
-def load_receipt(path: Path) -> Mapping[str, Any]:
- payload = json.loads(path.read_text(encoding="utf-8"))
- if not isinstance(payload, dict):
- raise ValueError(f"{path}: expected a JSON object, got {type(payload).__name__}")
- return _unwrap_receipt(payload)
-
-
-def _render_text(comparison: Mapping[str, Any]) -> str:
- lines: list[str] = []
- if comparison["like_for_like"]:
- lines.append("like-for-like: yes")
- else:
- lines.append("like-for-like: NO")
- for mismatch in comparison["identity_mismatches"]:
- lines.append(f" identity mismatch: {mismatch}")
- if comparison["baseline_status"] != "succeeded":
- lines.append(f" baseline run did not succeed: status={comparison['baseline_status']!r}")
- if comparison["candidate_status"] != "succeeded":
- lines.append(f" candidate run did not succeed: status={comparison['candidate_status']!r}")
- for result in comparison["results"]:
- marker = {"pass": "PASS", "exceeded": "EXCEEDED", "measurement-unavailable": "N/A"}[result["verdict"]]
- lines.append(
- f"[{marker}] {result['measure']} ({result['phase']}): "
- f"baseline={result['baseline_value']!r} candidate={result['candidate_value']!r} "
- f"ratio={result['ratio']!r} limit={result['limit']!r} kind={result['kind']}"
- )
- if result["blocker"]:
- lines.append(f" blocker: {result['blocker']}")
- lines.append(f" follow-up: {result['follow_up_ref']}")
- lines.append(f"targets_met: {comparison['targets_met']}")
- return "\n".join(lines)
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description=(
- "Compare a baseline and candidate workload receipt (devtools verify/test "
- "postmortem.json or a bare workload_receipt payload) for a clean, "
- "like-for-like seed/incident comparison (polylogue-b054.1.1.3)."
- )
- )
- parser.add_argument("--baseline", required=True, type=Path, help="Path to the baseline receipt JSON.")
- parser.add_argument("--candidate", required=True, type=Path, help="Path to the candidate receipt JSON.")
- parser.add_argument(
- "--follow-up-ref",
- default=DEFAULT_FOLLOW_UP_REF,
- help="Tracking-item reference cited on any unmet target (default: %(default)s).",
- )
- parser.add_argument(
- "--speedup-ratio",
- type=float,
- default=0.5,
- help="Maximum candidate/baseline wall-time ratio to pass (default 0.5 = 2x speedup).",
- )
- parser.add_argument(
- "--peak-pss-ceiling-mb",
- type=float,
- default=3 * 1024.0,
- help="Absolute peak-PSS ceiling in MiB (default 3072 MiB = 3 GiB).",
- )
- parser.add_argument("--json", action="store_true", help="Emit the complete comparison as JSON.")
- args = parser.parse_args(argv)
-
- baseline = load_receipt(args.baseline)
- candidate = load_receipt(args.candidate)
- targets = default_seed_comparison_targets(
- follow_up_ref=args.follow_up_ref,
- speedup_ratio=args.speedup_ratio,
- peak_pss_ceiling_bytes=args.peak_pss_ceiling_mb * 1024 * 1024,
- )
- comparison = compare_receipts(baseline, candidate, targets)
-
- if args.json:
- print(json.dumps(comparison, indent=2))
- else:
- print(_render_text(comparison))
-
- if not comparison["like_for_like"]:
- return 2
- if not comparison["targets_met"]:
- return 1
- return 0
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/synthetic_benchmark_catalog.py b/devtools/synthetic_benchmark_catalog.py
deleted file mode 100644
index 0b9ed18b0c..0000000000
--- a/devtools/synthetic_benchmark_catalog.py
+++ /dev/null
@@ -1,119 +0,0 @@
-"""Authored synthetic benchmark scenarios shared across control-plane surfaces."""
-
-from __future__ import annotations
-
-from devtools.benchmark_models import BenchmarkCampaignEntry, compile_benchmark_campaigns
-from polylogue.scenarios import ScenarioProjectionSourceKind, runner_execution
-
-SYNTHETIC_BENCHMARK_SCENARIOS: tuple[BenchmarkCampaignEntry, ...] = (
- BenchmarkCampaignEntry(
- name="fts-rebuild",
- description="Benchmark full FTS5 index rebuild",
- execution=runner_execution("fts-rebuild"),
- summary_metric="rebuild_wall_s",
- summary_label="s",
- scale_targets=("small", "medium", "large", "stretch"),
- origin="authored.synthetic-benchmark",
- artifact_targets=("message_source_rows", "message_fts"),
- operation_targets=("index-message-fts", "index.message-fts-rebuild"),
- tags=("benchmark", "synthetic", "fts"),
- projection_kind=ScenarioProjectionSourceKind.SYNTHETIC_BENCHMARK,
- ),
- BenchmarkCampaignEntry(
- name="incremental-index",
- description="Benchmark incremental FTS index updates",
- execution=runner_execution("incremental-index"),
- summary_metric="total_wall_s",
- summary_label="s",
- scale_targets=("small", "medium", "large", "stretch"),
- origin="authored.synthetic-benchmark",
- artifact_targets=("message_source_rows", "message_fts"),
- operation_targets=("index-message-fts", "index.message-fts-incremental"),
- tags=("benchmark", "synthetic", "fts"),
- projection_kind=ScenarioProjectionSourceKind.SYNTHETIC_BENCHMARK,
- ),
- BenchmarkCampaignEntry(
- name="filter-scan",
- description="Benchmark common filter query patterns",
- execution=runner_execution("filter-scan"),
- summary_metric="list_50_wall_s",
- summary_label="s",
- scale_targets=("small", "medium", "large", "stretch"),
- origin="authored.synthetic-benchmark",
- artifact_targets=("message_fts", "session_query_results"),
- operation_targets=("query-sessions", "query.filters.synthetic-scan"),
- tags=("benchmark", "synthetic", "filters"),
- projection_kind=ScenarioProjectionSourceKind.SYNTHETIC_BENCHMARK,
- ),
- BenchmarkCampaignEntry(
- name="startup-readiness",
- description="Benchmark check --runtime startup speed",
- execution=runner_execution("startup-readiness"),
- summary_metric="total_readiness_s",
- summary_label="s",
- scale_targets=("small", "medium", "large", "stretch"),
- origin="authored.synthetic-benchmark",
- artifact_targets=("message_fts", "archive_readiness"),
- operation_targets=("project-archive-readiness", "readiness.startup.synthetic"),
- tags=("benchmark", "synthetic", "readiness"),
- projection_kind=ScenarioProjectionSourceKind.SYNTHETIC_BENCHMARK,
- ),
- BenchmarkCampaignEntry(
- name="session-insight-materialization",
- description="Benchmark durable session-insight rebuild over synthetic archive sessions",
- execution=runner_execution("session-insight-materialization"),
- summary_metric="rebuild_wall_s",
- summary_label="s",
- scale_targets=("small", "medium", "large", "stretch"),
- origin="authored.synthetic-benchmark",
- artifact_targets=(
- "session_insight_source_sessions",
- "session_profile_rows",
- "session_work_event_rows",
- "session_work_event_fts",
- "session_phase_rows",
- "thread_rows",
- "thread_fts",
- "session_tag_rollup_rows",
- "session_insight_rows",
- "session_insight_fts",
- ),
- operation_targets=("materialize-session-insights",),
- tags=("benchmark", "synthetic", "session-insights"),
- projection_kind=ScenarioProjectionSourceKind.SYNTHETIC_BENCHMARK,
- ),
- BenchmarkCampaignEntry(
- name="daemon-live-convergence",
- description="Benchmark daemon live batch convergence over generated JSONL source workloads",
- execution=runner_execution("daemon-live-convergence"),
- summary_metric="total_wall_s",
- summary_label="s",
- scale_targets=("small", "medium", "large", "stretch"),
- origin="authored.synthetic-benchmark",
- artifact_targets=(
- "configured_sources",
- "source_payload_stream",
- "archive_session_rows",
- "message_source_rows",
- "message_fts",
- ),
- operation_targets=(
- "ingest-archive-runtime",
- "index-message-fts",
- "materialize-session-insights",
- ),
- tags=("benchmark", "synthetic", "daemon", "live", "convergence"),
- projection_kind=ScenarioProjectionSourceKind.SYNTHETIC_BENCHMARK,
- ),
-)
-
-SYNTHETIC_BENCHMARK_REGISTRY: dict[str, BenchmarkCampaignEntry] = compile_benchmark_campaigns(
- SYNTHETIC_BENCHMARK_SCENARIOS
-)
-
-
-__all__ = [
- "SYNTHETIC_BENCHMARK_REGISTRY",
- "SYNTHETIC_BENCHMARK_SCENARIOS",
- "BenchmarkCampaignEntry",
-]
diff --git a/devtools/task_history.py b/devtools/task_history.py
deleted file mode 100644
index 77a205a360..0000000000
--- a/devtools/task_history.py
+++ /dev/null
@@ -1,718 +0,0 @@
-"""Agent-visible task execution history.
-
-Maintains an append-only JSONL log of task executions under
-``.agent/task-history/tasks.jsonl`` for use by agents and operators.
-
-Subcommands:
-
-- ``log`` — Append a structured task record.
-- ``recent`` — Show the N most recent tasks.
-- ``stats`` — Aggregate summary over all recorded tasks.
-- ``replay`` — Re-run a previously logged ``devtools`` invocation.
-- ``budget`` — Enforce per-class p95 latency budgets.
-- ``prune`` — Bound the on-disk JSONL log size.
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import os
-import subprocess
-import sys
-from datetime import datetime, timezone
-from pathlib import Path
-from typing import Any
-
-from devtools import repo_root as _get_root
-from devtools.verify_runs import CURRENT_RUN_PATH
-from polylogue.core.json import JSONDocument
-
-TaskRecord = JSONDocument
-
-
-# ---------------------------------------------------------------------------
-# Storage helpers (path-injectable for tests)
-# ---------------------------------------------------------------------------
-
-
-def task_history_file_path() -> Path:
- """Return the active task-history JSONL path.
-
- Honors ``POLYLOGUE_TASK_HISTORY_FILE`` (used by tests and one-off overrides);
- otherwise defaults to ``/.agent/task-history/tasks.jsonl``.
- """
- override = os.environ.get("POLYLOGUE_TASK_HISTORY_FILE")
- if override:
- return Path(override)
- return _get_root() / ".agent" / "task-history" / "tasks.jsonl"
-
-
-def _ensure_file(path: Path) -> None:
- path.parent.mkdir(parents=True, exist_ok=True)
- if not path.exists():
- path.write_text("", encoding="utf-8")
-
-
-def _read_tasks(path: Path | None = None) -> list[TaskRecord]:
- target = path or task_history_file_path()
- _ensure_file(target)
- tasks: list[TaskRecord] = []
- for line in target.read_text(encoding="utf-8").splitlines():
- line = line.strip()
- if not line:
- continue
- try:
- tasks.append(json.loads(line))
- except json.JSONDecodeError:
- continue # skip malformed lines
- return tasks
-
-
-def _append_task(task: TaskRecord, path: Path | None = None) -> None:
- target = path or task_history_file_path()
- _ensure_file(target)
- with target.open("a", encoding="utf-8") as fh:
- fh.write(json.dumps(task, sort_keys=True) + "\n")
-
-
-def _latest_verify_run_metadata(command: str) -> dict[str, Any]:
- if command not in {"verify", "test"}:
- return {}
- path = _get_root() / CURRENT_RUN_PATH
- try:
- payload = json.loads(path.read_text(encoding="utf-8"))
- except (OSError, json.JSONDecodeError):
- return {}
- if not isinstance(payload, dict):
- return {}
- latest_pytest = next(
- (
- step
- for step in reversed(payload.get("steps", []))
- if isinstance(step, dict) and str(step.get("name", "")).startswith("pytest")
- ),
- {},
- )
- metadata: dict[str, Any] = {
- "verify_run_id": payload.get("run_id"),
- "verify_artifact_dir": payload.get("artifact_dir"),
- "verify_status": payload.get("status"),
- "verify_diagnosis": payload.get("diagnosis"),
- }
- if isinstance(latest_pytest, dict):
- for key in (
- "diagnosis",
- "selected_count",
- "deselected_count",
- "count",
- "peak_tree_rss_mb",
- "peak_tree_pss_mb",
- "peak_process_count",
- "resource_sample_count",
- ):
- if key in latest_pytest:
- metadata[f"pytest_{key}"] = latest_pytest[key]
- return {key: value for key, value in metadata.items() if value is not None}
-
-
-# ---------------------------------------------------------------------------
-# Command-class taxonomy
-# ---------------------------------------------------------------------------
-
-
-_CLASS_PREFIXES: tuple[tuple[str, str], ...] = (
- ("verify", "verify"),
- ("render", "render"),
- ("release build-package", "render"),
- ("lab", "lab"),
- ("witness", "witness"),
- ("lab lanes", "verify"),
- ("bench mutation", "campaign"),
- ("bench campaign", "campaign"),
- ("bench synthetic", "campaign"),
- ("schema", "verify"),
- ("evidence", "query"),
- ("lab graph", "query"),
- ("lab probe pipeline", "query"),
- ("bench memory", "query"),
- ("lab probe capture-regression", "query"),
- ("lab projections", "query"),
- ("verify coverage", "verify"),
- ("workspace tasks", "query"),
- ("workspace failure-context", "query"),
- ("workspace worktree-gc", "query"),
- ("workspace dev-loop", "query"),
- ("status", "query"),
-)
-
-
-def classify_command(command_name: str) -> str:
- """Classify a devtools command name into a coarse class bucket.
-
- Classes: ``verify``, ``render``, ``lab``, ``witness``, ``campaign``,
- ``query``, ``other``.
- """
- if not command_name:
- return "other"
- for prefix, klass in _CLASS_PREFIXES:
- if command_name == prefix or command_name.startswith(f"{prefix} "):
- return klass
- head = command_name.split()[0]
- if head == prefix or head.startswith(f"{prefix}-") or head.startswith(f"{prefix}_"):
- return klass
- return "other"
-
-
-# ---------------------------------------------------------------------------
-# Auto-log entrypoint (called from click_dispatch.main)
-# ---------------------------------------------------------------------------
-
-
-def record_invocation(
- *,
- command: str,
- args: list[str],
- duration_ms: float,
- exit_code: int,
- cwd: str | None = None,
- path: Path | None = None,
-) -> None:
- """Append a single invocation record; never raise.
-
- Intended for the ``devtools`` harness wrapper. Failures are swallowed
- so a broken task history path does not prevent commands from returning.
- """
- try:
- task: dict[str, Any] = {
- "timestamp": datetime.now(timezone.utc).isoformat(),
- "command": command,
- "args": list(args),
- "duration_ms": round(float(duration_ms), 3),
- "exit_code": int(exit_code),
- "cwd": cwd if cwd is not None else os.getcwd(),
- "class": classify_command(command),
- }
- task.update(_latest_verify_run_metadata(command))
- _append_task(task, path=path)
- except Exception:
- # Auto-log must never crash the wrapped command.
- return
-
-
-def auto_log_disabled() -> bool:
- """Return True when auto-logging is suppressed via env."""
- return os.environ.get("POLYLOGUE_TASK_HISTORY_DISABLE", "") not in ("", "0", "false", "False")
-
-
-# ---------------------------------------------------------------------------
-# Subcommand: log
-# ---------------------------------------------------------------------------
-
-
-def _cmd_log(args: argparse.Namespace) -> int:
- task: dict[str, Any] = {
- "timestamp": datetime.now(timezone.utc).isoformat(),
- "command": args.command or "",
- }
- if args.duration_ms is not None:
- task["duration_ms"] = args.duration_ms
- if args.exit_code is not None:
- task["exit_code"] = args.exit_code
- if args.tags:
- task["tags"] = args.tags
- if args.cwd is not None:
- task["cwd"] = str(args.cwd)
- if args.note is not None:
- task["note"] = args.note
- if args.command:
- task["class"] = classify_command(args.command)
-
- _append_task(task)
- if args.json:
- print(json.dumps(task, indent=2, sort_keys=True))
- return 0
-
-
-# ---------------------------------------------------------------------------
-# Subcommand: recent
-# ---------------------------------------------------------------------------
-
-
-def _cmd_recent(args: argparse.Namespace) -> int:
- tasks = _read_tasks()
- recent = tasks[-args.count :] if args.count else tasks
- if args.json:
- print(json.dumps(recent, indent=2, sort_keys=True))
- return 0
- if not recent:
- print("no tasks recorded")
- return 0
- for idx, task in enumerate(reversed(recent), start=1):
- ts: str = task.get("timestamp", "?") # type: ignore[assignment]
- cmd: str = task.get("command", "?") # type: ignore[assignment]
- code = task.get("exit_code")
- dur = task.get("duration_ms")
- parts: list[str] = [f"#{idx}", ts, cmd]
- if code is not None:
- parts.append(f"exit={code}")
- if dur is not None:
- parts.append(f"{dur}ms")
- if task.get("verify_run_id"):
- parts.append(f"run={task['verify_run_id']}")
- if task.get("verify_diagnosis") or task.get("pytest_diagnosis"):
- parts.append(f"diagnosis={task.get('verify_diagnosis') or task.get('pytest_diagnosis')}")
- if task.get("pytest_peak_tree_rss_mb") is not None:
- parts.append(f"rss_peak={task['pytest_peak_tree_rss_mb']}MiB")
- print(" ".join(parts))
- return 0
-
-
-# ---------------------------------------------------------------------------
-# Subcommand: stats
-# ---------------------------------------------------------------------------
-
-
-def _percentile(values: list[float], pct: float) -> float:
- """Return the linear-interpolated percentile of a numeric list."""
- if not values:
- return 0.0
- if len(values) == 1:
- return float(values[0])
- ordered = sorted(values)
- k = (len(ordered) - 1) * (pct / 100.0)
- lo = int(k)
- hi = min(lo + 1, len(ordered) - 1)
- if lo == hi:
- return float(ordered[lo])
- frac = k - lo
- return float(ordered[lo] + (ordered[hi] - ordered[lo]) * frac)
-
-
-def _class_distributions(tasks: list[TaskRecord]) -> dict[str, dict[str, float]]:
- buckets: dict[str, list[float]] = {}
- for task in tasks:
- dur = task.get("duration_ms")
- if dur is None:
- continue
- klass = task.get("class") or classify_command(str(task.get("command", "")))
- buckets.setdefault(str(klass), []).append(float(dur)) # type: ignore[arg-type]
- return {
- klass: {
- "count": float(len(durations)),
- "median_ms": _percentile(durations, 50),
- "p95_ms": _percentile(durations, 95),
- "max_ms": float(max(durations)),
- "sum_ms": float(sum(durations)),
- }
- for klass, durations in buckets.items()
- }
-
-
-def _phase_duration(value: object) -> float:
- if not isinstance(value, dict):
- return 0.0
- duration = value.get("duration")
- return float(duration) if isinstance(duration, (int, float)) else 0.0
-
-
-def _slow_test_rows_from_report(report_path: Path) -> list[dict[str, Any]]:
- try:
- payload = json.loads(report_path.read_text(encoding="utf-8"))
- except (OSError, json.JSONDecodeError):
- return []
- tests = payload.get("tests")
- if not isinstance(tests, list):
- return []
-
- rows: list[dict[str, Any]] = []
- for item in tests:
- if not isinstance(item, dict):
- continue
- nodeid = item.get("nodeid")
- if not isinstance(nodeid, str):
- continue
- setup_s = _phase_duration(item.get("setup"))
- call_s = _phase_duration(item.get("call"))
- teardown_s = _phase_duration(item.get("teardown"))
- total_s = setup_s + call_s + teardown_s
- if total_s <= 0:
- continue
- rows.append(
- {
- "nodeid": nodeid,
- "total_s": round(total_s, 4),
- "setup_s": round(setup_s, 4),
- "call_s": round(call_s, 4),
- "teardown_s": round(teardown_s, 4),
- "outcome": item.get("outcome"),
- "report": report_path.name,
- }
- )
- return rows
-
-
-def _latest_pytest_slow_tests(limit: int) -> list[dict[str, Any]]:
- if limit <= 0:
- return []
- rows: list[dict[str, Any]] = []
- verify_dir = _get_root() / ".cache" / "verify"
- for name in ("last-pytest.json", "last-pytest-isolated.json"):
- rows.extend(_slow_test_rows_from_report(verify_dir / name))
- rows.sort(key=lambda row: float(row["total_s"]), reverse=True)
- return rows[:limit]
-
-
-def _cmd_stats(args: argparse.Namespace) -> int:
- tasks = _read_tasks()
- if not tasks:
- if args.json:
- print(json.dumps({"total": 0, "by_command": {}, "by_exit_code": {}}, indent=2))
- else:
- print("no tasks recorded")
- return 0
-
- total = len(tasks)
- by_command: dict[str, int] = {}
- by_exit_code: dict[str, int] = {}
- total_duration_ms: float = 0.0
- duration_count = 0
-
- for task in tasks:
- cmd: str = task.get("command", "(unknown)") # type: ignore[assignment]
- by_command[cmd] = by_command.get(cmd, 0) + 1
- code = task.get("exit_code")
- code_key: str = str(code) if code is not None else "(none)"
- by_exit_code[code_key] = by_exit_code.get(code_key, 0) + 1
- dur = task.get("duration_ms")
- if dur is not None:
- total_duration_ms += float(dur) # type: ignore[arg-type]
- duration_count += 1
-
- stats: dict[str, Any] = {
- "total": total,
- "by_command": by_command,
- "by_exit_code": by_exit_code,
- }
- if duration_count > 0:
- stats["total_duration_ms"] = total_duration_ms
- stats["avg_duration_ms"] = total_duration_ms / duration_count
-
- if args.by_class:
- stats["by_class"] = _class_distributions(tasks)
-
- peaks: list[float] = []
- for task in tasks:
- value = task.get("pytest_peak_tree_rss_mb")
- if isinstance(value, (int, float)):
- peaks.append(float(value))
- if args.resources and peaks:
- stats["resources"] = {
- "count": len(peaks),
- "peak_rss_mb_max": max(peaks),
- "peak_rss_mb_p95": _percentile(peaks, 95),
- }
- slow_tests = _latest_pytest_slow_tests(args.slow_tests)
- if slow_tests:
- stats["slow_tests"] = slow_tests
-
- slowest: list[TaskRecord] = []
- if args.slowest and args.slowest > 0:
- timed = [t for t in tasks if t.get("duration_ms") is not None]
- timed.sort(key=lambda t: float(t.get("duration_ms", 0)), reverse=True) # type: ignore[arg-type]
- slowest = timed[: args.slowest]
- stats["slowest"] = slowest
-
- if args.json:
- print(json.dumps(stats, indent=2, sort_keys=True))
- return 0
-
- print(f"total tasks: {total}")
- print(f"by command ({len(by_command)}):")
- for cmd, count in sorted(by_command.items(), key=lambda x: -x[1]):
- print(f" {count:>4}x {cmd}")
- print(f"by exit code ({len(by_exit_code)}):")
- for code_key, count in sorted(by_exit_code.items(), key=lambda x: -x[1]):
- print(f" {count:>4}x {code_key}")
- if duration_count > 0:
- print(f"total duration: {total_duration_ms:.0f}ms")
- print(f"avg duration: {stats['avg_duration_ms']:.0f}ms")
- if args.by_class:
- print(f"by class ({len(stats['by_class'])}):")
- for klass, dist in sorted(stats["by_class"].items()):
- print(
- f" {klass:<10} n={int(dist['count']):>4} "
- f"median={dist['median_ms']:.0f}ms p95={dist['p95_ms']:.0f}ms "
- f"max={dist['max_ms']:.0f}ms"
- )
- if args.resources and "resources" in stats:
- res = stats["resources"]
- print(
- f"resources: n={res['count']} "
- f"peak_rss_max={res['peak_rss_mb_max']:.1f}MiB "
- f"peak_rss_p95={res['peak_rss_mb_p95']:.1f}MiB"
- )
- if slow_tests:
- print(f"slow tests from latest pytest report ({len(slow_tests)}):")
- for test in slow_tests:
- print(
- f" {test['total_s']:.2f}s "
- f"setup={test['setup_s']:.2f}s "
- f"call={test['call_s']:.2f}s "
- f"teardown={test['teardown_s']:.2f}s "
- f"report={test['report']} "
- f"{test['nodeid']}"
- )
- if slowest:
- print(f"slowest {len(slowest)}:")
- for task in slowest:
- cmd_str: str = task.get("command", "?") # type: ignore[assignment]
- dur = task.get("duration_ms")
- ts: str = task.get("timestamp", "?") # type: ignore[assignment]
- print(f" {dur}ms {cmd_str} {ts}")
- return 0
-
-
-# ---------------------------------------------------------------------------
-# Subcommand: replay
-# ---------------------------------------------------------------------------
-
-
-def _cmd_replay(args: argparse.Namespace) -> int:
- tasks = _read_tasks()
- if not tasks:
- print("no tasks recorded", file=sys.stderr)
- return 1
- # ``index`` is 1-based from the most recent task (replay 1 = last task).
- index = max(1, args.index)
- if index > len(tasks):
- print(
- f"replay index {index} exceeds {len(tasks)} recorded tasks",
- file=sys.stderr,
- )
- return 1
- task = tasks[-index]
-
- command_name: str = str(task.get("command", "")).strip()
- raw_args = task.get("args", [])
- invocation_args: list[str] = [str(item) for item in raw_args] if isinstance(raw_args, list) else []
-
- if not command_name:
- print("task has no recorded command name", file=sys.stderr)
- return 1
-
- argv = [command_name, *invocation_args]
- if args.dry_run or args.json:
- payload = {
- "index": index,
- "timestamp": task.get("timestamp"),
- "command": command_name,
- "args": invocation_args,
- "argv": argv,
- "cwd": task.get("cwd"),
- "previous_exit_code": task.get("exit_code"),
- "previous_duration_ms": task.get("duration_ms"),
- }
- if args.json:
- print(json.dumps(payload, indent=2, sort_keys=True))
- else:
- print(json.dumps(payload, indent=2, sort_keys=True))
- if args.dry_run:
- return 0
-
- # Re-run via the devtools entrypoint as a subprocess so the inner run
- # gets its own auto-log record without recursing inside this process.
- env = os.environ.copy()
- cwd = task.get("cwd") if isinstance(task.get("cwd"), str) else None
- if cwd is not None and not Path(cwd).exists():
- cwd = None
- cmd = [sys.executable, "-m", "devtools", *argv]
- try:
- completed = subprocess.run(cmd, cwd=cwd, env=env, check=False)
- except FileNotFoundError as exc: # python missing — surface clearly
- print(f"replay failed: {exc}", file=sys.stderr)
- return 1
- return int(completed.returncode)
-
-
-# ---------------------------------------------------------------------------
-# Subcommand: budget
-# ---------------------------------------------------------------------------
-
-
-def _cmd_budget(args: argparse.Namespace) -> int:
- tasks = _read_tasks()
- distributions = _class_distributions(tasks)
- target_class = args.class_name
- dist = distributions.get(target_class)
- if dist is None or dist["count"] == 0:
- payload = {
- "class": target_class,
- "count": 0,
- "max_ms": args.max_ms,
- "status": "no-data",
- }
- if args.json:
- print(json.dumps(payload, indent=2, sort_keys=True))
- else:
- print(f"no data for class {target_class}")
- return 0 if args.allow_empty else 1
-
- p95 = dist["p95_ms"]
- within = p95 <= float(args.max_ms)
- payload = {
- "class": target_class,
- "count": int(dist["count"]),
- "median_ms": dist["median_ms"],
- "p95_ms": p95,
- "max_ms_observed": dist["max_ms"],
- "budget_ms": float(args.max_ms),
- "within_budget": within,
- "status": "ok" if within else "over-budget",
- }
- if args.json:
- print(json.dumps(payload, indent=2, sort_keys=True))
- else:
- symbol = "OK" if within else "OVER"
- print(
- f"[{symbol}] class={target_class} n={int(dist['count'])} "
- f"p95={p95:.0f}ms budget={args.max_ms:.0f}ms "
- f"median={dist['median_ms']:.0f}ms max={dist['max_ms']:.0f}ms"
- )
- return 0 if within else 2
-
-
-# ---------------------------------------------------------------------------
-# Subcommand: prune
-# ---------------------------------------------------------------------------
-
-
-def _cmd_prune(args: argparse.Namespace) -> int:
- tasks = _read_tasks()
- if args.keep < 0:
- print("--keep must be >= 0", file=sys.stderr)
- return 2
- before = len(tasks)
- if args.keep >= before:
- payload = {"before": before, "after": before, "removed": 0, "keep": args.keep}
- if args.json:
- print(json.dumps(payload, indent=2, sort_keys=True))
- else:
- print(f"nothing to prune (have {before}, keep {args.keep})")
- return 0
- keep_tasks = tasks[-args.keep :] if args.keep > 0 else []
- path = task_history_file_path()
- _ensure_file(path)
- # Atomic-ish rewrite: write to a sibling temp file then replace.
- tmp = path.with_suffix(path.suffix + ".tmp")
- with tmp.open("w", encoding="utf-8") as fh:
- for task in keep_tasks:
- fh.write(json.dumps(task, sort_keys=True) + "\n")
- tmp.replace(path)
- removed = before - len(keep_tasks)
- payload = {"before": before, "after": len(keep_tasks), "removed": removed, "keep": args.keep}
- if args.json:
- print(json.dumps(payload, indent=2, sort_keys=True))
- else:
- print(f"pruned {removed} records (kept {len(keep_tasks)} of {before})")
- return 0
-
-
-# ---------------------------------------------------------------------------
-# Main entry point
-# ---------------------------------------------------------------------------
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(prog="devtools workspace tasks", description="Task execution history.")
- subparsers = parser.add_subparsers(dest="subcommand", required=True)
-
- log_parser = subparsers.add_parser("log", help="Append a task record.")
- log_parser.add_argument("--command", "-c", default=None, help="Command that was run.")
- log_parser.add_argument("--duration-ms", type=float, default=None, help="Duration in milliseconds.")
- log_parser.add_argument("--exit-code", type=int, default=None, help="Exit code.")
- log_parser.add_argument("--tags", action="append", default=None, help="Tags for the task.")
- log_parser.add_argument("--cwd", default=None, help="Working directory.")
- log_parser.add_argument("--note", default=None, help="Free-text note.")
- log_parser.add_argument("--json", action="store_true", help="Emit machine-readable JSON.")
-
- recent_parser = subparsers.add_parser("recent", help="Show recent tasks.")
- recent_parser.add_argument("--count", "-n", type=int, default=10, help="Number of recent tasks (default: 10).")
- recent_parser.add_argument("--json", action="store_true", help="Emit machine-readable JSON.")
-
- stats_parser = subparsers.add_parser("stats", help="Task statistics.")
- stats_parser.add_argument("--json", action="store_true", help="Emit machine-readable JSON.")
- stats_parser.add_argument(
- "--by-class",
- action="store_true",
- help="Add per-class duration distributions (median/p95/max).",
- )
- stats_parser.add_argument(
- "--slowest",
- type=int,
- default=0,
- metavar="N",
- help="Include the N slowest invocations by duration_ms.",
- )
- stats_parser.add_argument(
- "--resources",
- action="store_true",
- help="Add pytest resource distributions when verify/test records carry them.",
- )
- stats_parser.add_argument(
- "--slow-tests",
- type=int,
- default=0,
- metavar="N",
- help="Include the N slowest tests from the latest pytest JSON reports.",
- )
-
- replay_parser = subparsers.add_parser("replay", help="Re-run the Nth most recent task (default 1).")
- replay_parser.add_argument(
- "index", type=int, nargs="?", default=1, help="1-based offset from most recent (default 1)."
- )
- replay_parser.add_argument(
- "--dry-run", action="store_true", help="Print the resolved invocation without executing."
- )
- replay_parser.add_argument(
- "--json", action="store_true", help="Emit the resolved invocation as JSON before running."
- )
-
- budget_parser = subparsers.add_parser("budget", help="Enforce a p95 latency budget for a command class.")
- budget_parser.add_argument(
- "--class",
- dest="class_name",
- required=True,
- help="Command class to evaluate (verify, render, lab, witness, campaign, query, other).",
- )
- budget_parser.add_argument("--max-ms", type=float, required=True, help="Budget ceiling in milliseconds (p95).")
- budget_parser.add_argument(
- "--allow-empty",
- action="store_true",
- help="Treat missing data for the class as a pass rather than a failure.",
- )
- budget_parser.add_argument("--json", action="store_true", help="Emit machine-readable JSON.")
-
- prune_parser = subparsers.add_parser("prune", help="Bound the JSONL log size.")
- prune_parser.add_argument("--keep", type=int, required=True, help="Number of most recent records to retain.")
- prune_parser.add_argument("--json", action="store_true", help="Emit machine-readable JSON.")
-
- parsed = parser.parse_args(argv)
-
- if parsed.subcommand == "log":
- return _cmd_log(parsed)
- elif parsed.subcommand == "recent":
- return _cmd_recent(parsed)
- elif parsed.subcommand == "stats":
- return _cmd_stats(parsed)
- elif parsed.subcommand == "replay":
- return _cmd_replay(parsed)
- elif parsed.subcommand == "budget":
- return _cmd_budget(parsed)
- elif parsed.subcommand == "prune":
- return _cmd_prune(parsed)
- return 1
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/test_economics_report.py b/devtools/test_economics_report.py
deleted file mode 100644
index c28ba9fa81..0000000000
--- a/devtools/test_economics_report.py
+++ /dev/null
@@ -1,485 +0,0 @@
-"""Per-package test-suite economics: coverage vs fix-density vs test cost (polylogue-9e5.11).
-
-Background
-----------
-
-The repo has ~248k test lines against ~229k product lines by raw line count,
-yet a real production defect (embedding staleness) shipped untested despite
-that volume. That is a symptom, not a diagnosis: test *volume* says nothing
-about whether tests concentrate on risk-bearing substrate or on
-mechanically-easy-to-cover surface. This report builds the map that lets a
-human or agent tell those apart, per top-level ``polylogue/`` package:
-
-1. **Coverage percent** -- from a ``coverage.py`` JSON report (statement
- coverage; the repo's own ratchet in ``pyproject.toml`` is line-based).
-2. **Historical fix-density** -- count of ``fix:``/``fix(scope):``
- conventional-commit subjects (this repo's own convention, see CLAUDE.md's
- Git Protocol) whose commit touched a path under the package. A proxy for
- "how often did this module actually break in a way that needed a fix",
- not a synthetic bug-injection score.
-3. **Test wall-time cost exposure** -- from ``testmon``'s own dependency
- database (``.cache/testmon/testmondata``): for every test whose recorded
- dependency fingerprint set includes at least one file under the package,
- sum that test's last-recorded duration. A test touching N packages
- contributes its full duration to each -- this is deliberately a *cost
- exposure* metric ("how much wall-time is on the hook if this package
- changes"), not a time partition, so package totals do not sum to the
- suite total. See the module docstring note below on why an exact,
- double-counting-free wall-time partition is not reconstructable from
- data already on disk.
-4. **testmon selection fan-out** -- median, across files with a recorded
- fingerprint in the package, of "how many distinct tests depend on this
- file". Median (not sum/max) because a small number of hub files
- (``polylogue/storage/sqlite/connection.py``,
- ``polylogue/mcp/server_support.py``,
- ``polylogue/schemas/validator_resolution.py``,
- ``polylogue/daemon/status_snapshot.py`` at last measurement) are
- transitively imported by essentially every test and would otherwise
- swamp the per-package number to ~100% for four packages and hide the
- more informative "typical file in this package" fan-out.
-
-Honesty note on wall-time provenance
--------------------------------------
-
-``.cache/verify/runs/*/steps/*/summary.json`` (3,800+ historical verify runs)
-only retains the **top 20 slowest** test reports per run
-(``devtools/pytest_progress_plugin.py:_SLOW_REPORT_LIMIT``), not a full
-per-test duration list -- that full list only ever exists transiently in
-``.cache/verify/last-pytest.json`` for the *most recent* invocation, and is
-overwritten on the next run. There is therefore no comprehensive historical
-per-test wall-time record on disk. ``testmon``'s own database, however,
-already tracks one row per currently-known test with its last-recorded
-duration plus the full file-dependency graph testmon uses to select tests --
-that is what this report uses instead of re-running a fresh full-suite
-timing pass (which a full ``devtools verify --all`` would otherwise require).
-
-Coverage still requires an actual instrumented run: this report does not
-invoke pytest itself. Point it at a ``coverage json`` report (see
-``--coverage-json``); generate one with:
-
- coverage json --data-file=.cache/coverage/.coverage -o .cache/coverage/coverage.json
-
-after any full/near-full pytest run with ``--cov=polylogue``.
-
-Usage
------
-
- python -m devtools.test_economics_report
- python -m devtools.test_economics_report --json
- python -m devtools.test_economics_report --write docs/test-economics.md
-
-Wired into ``devtools lab test-economics`` (see ``command_catalog.py``).
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import statistics
-import subprocess
-import sys
-from collections import defaultdict
-from collections.abc import Iterable
-from dataclasses import dataclass, field
-from pathlib import Path
-from typing import Any
-
-from polylogue.storage.sqlite.connection_profile import open_readonly_connection
-
-_REPO_ROOT = Path(__file__).resolve().parents[1]
-_POLYLOGUE_ROOT = _REPO_ROOT / "polylogue"
-_DEFAULT_TESTMON_DB = _REPO_ROOT / ".cache" / "testmon" / "testmondata"
-_DEFAULT_COVERAGE_JSON = _REPO_ROOT / ".cache" / "coverage" / "coverage.json"
-_ROOT_BUCKET = "_root"
-
-# Fix-commit subject match: this repo's conventional-commit convention
-# (CLAUDE.md Git Protocol) is `fix:` or `fix(scope):` at the start of the
-# subject line. Matches git's own -E (extended regex) grep.
-_FIX_GREP_PATTERN = r"^fix(\(|:)"
-
-
-def discover_packages(polylogue_root: Path = _POLYLOGUE_ROOT) -> list[str]:
- """Every top-level polylogue/ subpackage, plus `_root` for stray top-level .py files."""
- packages = sorted(
- p.name
- for p in polylogue_root.iterdir()
- if p.is_dir() and not p.name.startswith("_") and not p.name.startswith(".")
- )
- has_root_files = any(p.is_file() and p.suffix == ".py" for p in polylogue_root.iterdir())
- if has_root_files:
- packages.append(_ROOT_BUCKET)
- return packages
-
-
-def _package_for_relpath(relpath: str, packages: Iterable[str]) -> str | None:
- """Map a 'polylogue//...' or 'polylogue/.py' path to its package bucket."""
- if not relpath.startswith("polylogue/"):
- return None
- parts = relpath.split("/")
- if len(parts) < 2:
- return None
- head = parts[1]
- if head.endswith(".py") and len(parts) == 2:
- return _ROOT_BUCKET if _ROOT_BUCKET in packages else None
- return head if head in packages else None
-
-
-@dataclass
-class PackageMetrics:
- package: str
- coverage_percent: float | None = None
- coverage_statements: int = 0
- coverage_covered: int = 0
- fix_commits: int = 0
- test_wall_time_exposure_s: float = 0.0
- tests_touching_package: int = 0
- selection_fanout_median: float | None = None
- selection_fanout_max: int = 0
- files_with_fingerprint: int = 0
- quadrant: str = "unclassified"
- notes: list[str] = field(default_factory=list)
-
- def to_dict(self) -> dict[str, Any]:
- return {
- "package": self.package,
- "coverage_percent": self.coverage_percent,
- "coverage_statements": self.coverage_statements,
- "coverage_covered": self.coverage_covered,
- "fix_commits": self.fix_commits,
- "test_wall_time_exposure_s": round(self.test_wall_time_exposure_s, 2),
- "tests_touching_package": self.tests_touching_package,
- "selection_fanout_median": self.selection_fanout_median,
- "selection_fanout_max": self.selection_fanout_max,
- "files_with_fingerprint": self.files_with_fingerprint,
- "quadrant": self.quadrant,
- "notes": self.notes,
- }
-
-
-def compute_fix_density(
- packages: list[str], *, repo_root: Path = _REPO_ROOT, polylogue_root: Path = _POLYLOGUE_ROOT
-) -> dict[str, int]:
- """Count fix:-prefixed commits touching each package's path, via one `git log` per package.
-
- One process per package (≈29 invocations) rather than one global log parsed in
- Python, because git's own `-- ` restriction is the simplest correct way to
- ask "did this commit touch this subtree" across renames within the tree.
-
- The `_root` bucket passes each top-level polylogue/*.py file as an explicit,
- non-glob pathspec -- a glob pathspec like `polylogue/*.py` is NOT anchored to
- one path segment in git's default (non-literal) pathspec matching, so `*`
- silently crosses `/` and matches every file in every subpackage too.
- """
- counts: dict[str, int] = {}
- for pkg in packages:
- if pkg == _ROOT_BUCKET:
- pathspec = [f"polylogue/{p.name}" for p in polylogue_root.iterdir() if p.is_file() and p.suffix == ".py"]
- else:
- pathspec = [f"polylogue/{pkg}"]
- cmd = [
- "git",
- "log",
- "--oneline",
- "-E",
- f"--grep={_FIX_GREP_PATTERN}",
- "--",
- *pathspec,
- ]
- result = subprocess.run(cmd, cwd=repo_root, capture_output=True, text=True, check=True)
- lines = [line for line in result.stdout.splitlines() if line.strip()]
- counts[pkg] = len(lines)
- return counts
-
-
-def compute_coverage(packages: list[str], coverage_json_path: Path) -> tuple[dict[str, tuple[int, int]], str | None]:
- """Return {package: (covered_statements, total_statements)} from a coverage.py JSON report.
-
- Returns (empty dict, warning) if the report is missing.
- """
- if not coverage_json_path.exists():
- return {}, f"no coverage report found at {coverage_json_path}; coverage_percent left null"
- data = json.loads(coverage_json_path.read_text(encoding="utf-8"))
- totals: dict[str, list[int]] = defaultdict(lambda: [0, 0])
- files = data.get("files", {})
- for filename, filedata in files.items():
- norm = filename.replace("\\", "/")
- if not norm.startswith("polylogue/"):
- continue
- pkg = _package_for_relpath(norm, packages)
- if pkg is None:
- continue
- summary = filedata.get("summary", {})
- totals[pkg][0] += int(summary.get("covered_lines", 0))
- totals[pkg][1] += int(summary.get("num_statements", 0))
- return {pkg: (v[0], v[1]) for pkg, v in totals.items()}, None
-
-
-def compute_test_economics(
- packages: list[str], testmon_db_path: Path
-) -> tuple[dict[str, tuple[float, int]], dict[str, tuple[float | None, int, int]], str | None]:
- """Query testmon's dependency graph for wall-time exposure and selection fan-out.
-
- Returns:
- wall_time[pkg] = (summed duration of distinct tests touching the package, test count)
- fanout[pkg] = (median per-file selected-test count, max per-file count, files counted)
- warning if the db is missing.
- """
- if not testmon_db_path.exists():
- return {}, {}, f"no testmon database found at {testmon_db_path}; wall-time/fan-out left null"
-
- con = open_readonly_connection(testmon_db_path)
- try:
- cur = con.cursor()
- cur.execute(
- """
- SELECT te.test_name, te.duration, ff.filename
- FROM test_execution te
- JOIN test_execution_file_fp tefp ON tefp.test_execution_id = te.id
- JOIN file_fp ff ON ff.id = tefp.fingerprint_id
- WHERE ff.filename LIKE 'polylogue/%'
- """
- )
- rows = cur.fetchall()
-
- # wall-time exposure: distinct (test, package) touched
- pkg_tests: dict[str, set[str]] = defaultdict(set)
- test_dur: dict[str, float] = {}
- # per-file distinct test counts, for fan-out
- file_test_counts: dict[str, set[str]] = defaultdict(set)
-
- for name, dur, filename in rows:
- test_dur[name] = dur
- pkg = _package_for_relpath(filename, packages)
- if pkg is not None:
- pkg_tests[pkg].add(name)
- file_test_counts[filename].add(name)
-
- wall_time: dict[str, tuple[float, int]] = {}
- for pkg, tests in pkg_tests.items():
- total = sum(test_dur[t] for t in tests)
- wall_time[pkg] = (total, len(tests))
-
- pkg_file_counts: dict[str, list[int]] = defaultdict(list)
- for filename, testset in file_test_counts.items():
- pkg = _package_for_relpath(filename, packages)
- if pkg is not None:
- pkg_file_counts[pkg].append(len(testset))
-
- fanout: dict[str, tuple[float | None, int, int]] = {}
- for pkg, counts in pkg_file_counts.items():
- median = statistics.median(counts) if counts else None
- fanout[pkg] = (median, max(counts) if counts else 0, len(counts))
-
- return wall_time, fanout, None
- finally:
- con.close()
-
-
-def classify_quadrants(metrics: dict[str, PackageMetrics]) -> None:
- """Assign a quadrant label using median-split thresholds within this package set.
-
- high fix-density + low coverage -> under-tested substrate
- low fix-density + (high wall-time OR high fan-out) -> over-tested mechanical surface
- everything else -> mixed / does not fit cleanly
-
- A package with no coverage number is classified "coverage unknown" (optionally
- qualified by fix-density) rather than silently defaulting to well-covered --
- absence of a measurement must never read as a clean bill of health.
- """
- fix_values = [m.fix_commits for m in metrics.values()]
- cov_values = [m.coverage_percent for m in metrics.values() if m.coverage_percent is not None]
- wall_values = [m.test_wall_time_exposure_s for m in metrics.values()]
- fanout_values = [m.selection_fanout_median for m in metrics.values() if m.selection_fanout_median is not None]
-
- if not fix_values:
- return
- fix_median = statistics.median(fix_values)
- cov_median = statistics.median(cov_values) if cov_values else None
- wall_median = statistics.median(wall_values) if wall_values else 0.0
- fanout_median_all = statistics.median(fanout_values) if fanout_values else 0.0
-
- for m in metrics.values():
- high_fix = m.fix_commits > fix_median
- high_wall = m.test_wall_time_exposure_s > wall_median
- high_fanout = m.selection_fanout_median is not None and m.selection_fanout_median > fanout_median_all
-
- if m.coverage_percent is None:
- m.quadrant = "high-fix, coverage unknown" if high_fix else "coverage unknown"
- continue
-
- assert cov_median is not None # cov_values is non-empty whenever coverage_percent is set
- low_cov = m.coverage_percent < cov_median
-
- if high_fix and low_cov:
- m.quadrant = "under-tested substrate"
- elif (not high_fix) and (high_wall or high_fanout):
- m.quadrant = "over-tested mechanical surface"
- elif high_fix and not low_cov:
- m.quadrant = "well-covered risk area"
- elif (not high_fix) and (not high_wall) and (not high_fanout):
- m.quadrant = "low-risk, low-cost (fine as-is)"
- else:
- m.quadrant = "mixed / no clean fit"
-
-
-def build_report(
- *,
- testmon_db_path: Path = _DEFAULT_TESTMON_DB,
- coverage_json_path: Path = _DEFAULT_COVERAGE_JSON,
- repo_root: Path = _REPO_ROOT,
-) -> tuple[dict[str, PackageMetrics], list[str]]:
- warnings: list[str] = []
- packages = discover_packages(repo_root / "polylogue")
- metrics = {pkg: PackageMetrics(package=pkg) for pkg in packages}
-
- fix_counts = compute_fix_density(packages, repo_root=repo_root, polylogue_root=repo_root / "polylogue")
- for pkg, count in fix_counts.items():
- metrics[pkg].fix_commits = count
-
- coverage_totals, cov_warning = compute_coverage(packages, coverage_json_path)
- if cov_warning:
- warnings.append(cov_warning)
- for pkg, (covered, total) in coverage_totals.items():
- metrics[pkg].coverage_covered = covered
- metrics[pkg].coverage_statements = total
- metrics[pkg].coverage_percent = round(100.0 * covered / total, 1) if total else None
-
- wall_time, fanout, tm_warning = compute_test_economics(packages, testmon_db_path)
- if tm_warning:
- warnings.append(tm_warning)
- for pkg, (wall_time_s, touching_count) in wall_time.items():
- metrics[pkg].test_wall_time_exposure_s = wall_time_s
- metrics[pkg].tests_touching_package = touching_count
- for pkg, (median, mx, nfiles) in fanout.items():
- metrics[pkg].selection_fanout_median = median
- metrics[pkg].selection_fanout_max = mx
- metrics[pkg].files_with_fingerprint = nfiles
-
- classify_quadrants(metrics)
- return metrics, warnings
-
-
-def render_markdown(metrics: dict[str, PackageMetrics], warnings: list[str]) -> str:
- ordered = sorted(metrics.values(), key=lambda m: (-m.fix_commits, m.package))
- lines: list[str] = []
- lines.append("")
- lines.append("")
- lines.append("")
- lines.append("# Test-suite economics: coverage vs fix-density map")
- lines.append("")
- lines.append(
- "Per-package view of where tests earn their runtime (polylogue-9e5.11). See "
- "`devtools/test_economics_report.py` module docstring for exact metric "
- "definitions and honesty notes on data provenance."
- )
- lines.append("")
- if warnings:
- lines.append("**Warnings from this run:**")
- for w in warnings:
- lines.append(f"- {w}")
- lines.append("")
- lines.append(
- "| Package | Coverage % | Fix commits | Wall-time exposure (s) | Tests touching | "
- "Fan-out median/max | Quadrant |"
- )
- lines.append("| --- | --- | --- | --- | --- | --- | --- |")
- for m in ordered:
- cov = f"{m.coverage_percent:.1f}" if m.coverage_percent is not None else "n/a"
- fanout = (
- f"{m.selection_fanout_median:.0f}/{m.selection_fanout_max}"
- if m.selection_fanout_median is not None
- else "n/a"
- )
- lines.append(
- f"| `{m.package}` | {cov} | {m.fix_commits} | {m.test_wall_time_exposure_s:.1f} | "
- f"{m.tests_touching_package} | {fanout} | {m.quadrant} |"
- )
- lines.append("")
- lines.append(
- "Wall-time exposure double-counts tests that touch multiple packages by design "
- "(cost-exposure, not a partition); fan-out is median/max distinct-test count "
- "per file with a recorded fingerprint in the package, not a package-level sum "
- "(a handful of hub files are imported by ~every test and would otherwise swamp "
- "the package number to ~100%)."
- )
- lines.append("")
-
- zero_coverage = sorted(
- m.package for m in metrics.values() if m.coverage_percent == 0.0 and m.coverage_statements > 0
- )
- if zero_coverage:
- lines.append(
- "**Zero-coverage packages (real statements, none executed by the suite):** "
- + ", ".join(f"`{pkg}`" for pkg in zero_coverage)
- + ". Confirm these are genuinely unused (candidates for removal, per "
- "the repo's 'reference-count is not legitimacy' doctrine) rather than an "
- "unwired feature, before writing tests for them."
- )
- lines.append("")
-
- lines.append(
- "**Findings from the polylogue-9e5.11 baseline run (2026-07-09), not "
- "necessarily still true on a later regeneration:**"
- )
- lines.append(
- "- Four files are testmon dependency hubs touched by ~every test -- "
- "`polylogue/storage/sqlite/connection.py`, `polylogue/mcp/server_support.py`, "
- "`polylogue/schemas/validator_resolution.py`, `polylogue/daemon/status_snapshot.py` "
- "-- each carries a docstring note now; see polylogue-9e5.11."
- )
- lines.append(
- "- `verification` shows 0 tests touching it in testmon's graph but 84.6% real "
- "coverage from a fresh instrumented run -- a testmon fingerprint-graph staleness "
- "gap, not an actual coverage hole. Tracked as polylogue-csg7."
- )
- lines.append(
- "- `paths` classifies as 'over-tested mechanical surface' (low fix-density, high "
- "fan-out) but is foundational, stable plumbing at 98.2% coverage -- a case the "
- "bead explicitly asks to flag as not fitting cleanly rather than a real pruning "
- "target."
- )
- lines.append(
- "- Five follow-up actions filed from this run: polylogue-znwj (daemon/cli.py + "
- "status.py coverage), polylogue-c52g (cli/query_verbs.py + commands/status.py "
- "coverage), polylogue-csg7 (testmon staleness), polylogue-ixqt (surfaces "
- "mechanical-overcoverage review), polylogue-w9wt (pre-existing test-failure "
- "triage discovered while generating this report)."
- )
- lines.append("")
- return "\n".join(lines) + "\n"
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__.splitlines()[0] if __doc__ else "")
- parser.add_argument("--testmon-db", type=Path, default=_DEFAULT_TESTMON_DB)
- parser.add_argument("--coverage-json", type=Path, default=_DEFAULT_COVERAGE_JSON)
- parser.add_argument("--json", action="store_true", help="Emit machine-readable JSON instead of markdown.")
- parser.add_argument("--write", type=Path, default=None, help="Write the markdown table to this path.")
- args = parser.parse_args(argv)
-
- metrics, warnings = build_report(
- testmon_db_path=args.testmon_db,
- coverage_json_path=args.coverage_json,
- )
-
- if args.json:
- payload = {
- "packages": {pkg: m.to_dict() for pkg, m in sorted(metrics.items())},
- "warnings": warnings,
- }
- print(json.dumps(payload, indent=2, sort_keys=True))
- else:
- markdown = render_markdown(metrics, warnings)
- if args.write:
- args.write.write_text(markdown, encoding="utf-8")
- sys.stderr.write(f"wrote {args.write}\n")
- else:
- print(markdown)
-
- for w in warnings:
- sys.stderr.write(f"warning: {w}\n")
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/testmon_blind_spot_audit.py b/devtools/testmon_blind_spot_audit.py
deleted file mode 100644
index 46f7497a74..0000000000
--- a/devtools/testmon_blind_spot_audit.py
+++ /dev/null
@@ -1,280 +0,0 @@
-"""Audit coverage metadata against the pytest-testmon dependency graph.
-
-This is an on-demand audit. It consumes an existing coverage.py JSON report
-and an existing pytest-testmon SQLite database; it never runs pytest and never
-creates or refreshes coverage data.
-
-Coverage metadata can know about a file that testmon does not fingerprint.
-That absence is harmless for a declaration-only module, but it is a blind spot
-for executable code. The distinction is made from the source AST rather than
-from the coverage statement count or the file name, so a stale or edited
-fixture cannot turn executable validation code into a safe result.
-"""
-
-from __future__ import annotations
-
-import argparse
-import ast
-import json
-from dataclasses import asdict, dataclass
-from pathlib import Path, PurePosixPath
-from typing import Literal
-
-from polylogue.storage.sqlite.connection_profile import open_readonly_connection
-
-ASTClassification = Literal["declaration-only", "executable", "source-unreadable"]
-FindingStatus = Literal[
- "fingerprinted",
- "declaration-only-unfingerprinted",
- "executable-validator-unfingerprinted",
- "source-unreadable",
-]
-
-
-@dataclass(frozen=True, slots=True)
-class CoverageFile:
- path: str
- statements: int
- covered_lines: int
-
-
-@dataclass(frozen=True, slots=True)
-class BlindSpotFinding:
- path: str
- statements: int
- covered_lines: int
- ast_classification: ASTClassification
- testmon_fingerprinted: bool
- status: FindingStatus
- safe: bool
-
- def to_dict(self) -> dict[str, object]:
- return asdict(self)
-
-
-@dataclass(frozen=True, slots=True)
-class BlindSpotReport:
- findings: tuple[BlindSpotFinding, ...]
- coverage_file_count: int
- testmon_fingerprint_count: int
-
- @property
- def risks(self) -> tuple[BlindSpotFinding, ...]:
- return tuple(finding for finding in self.findings if not finding.safe)
-
- def to_dict(self) -> dict[str, object]:
- return {
- "findings": [finding.to_dict() for finding in self.findings],
- "coverage_file_count": self.coverage_file_count,
- "testmon_fingerprint_count": self.testmon_fingerprint_count,
- "risk_count": len(self.risks),
- "safe": not self.risks,
- }
-
-
-def _relative_path(filename: str, *, source_root: Path) -> str | None:
- root = source_root.resolve()
- candidate = Path(filename)
- if candidate.is_absolute():
- try:
- candidate = candidate.resolve().relative_to(root)
- except ValueError:
- return None
- normalized = PurePosixPath(str(candidate).replace("\\", "/"))
- if normalized.is_absolute() or ".." in normalized.parts:
- return None
- return str(normalized)
-
-
-def read_coverage_files(coverage_json_path: Path, *, source_root: Path) -> tuple[CoverageFile, ...]:
- """Read source-file metadata from an existing coverage.py JSON report."""
- payload = json.loads(coverage_json_path.read_text(encoding="utf-8"))
- raw_files = payload.get("files", {})
- if not isinstance(raw_files, dict):
- raise ValueError("coverage JSON has no files object")
-
- files: list[CoverageFile] = []
- for raw_filename, raw_filedata in raw_files.items():
- if not isinstance(raw_filename, str) or not isinstance(raw_filedata, dict):
- continue
- relative = _relative_path(raw_filename, source_root=source_root)
- if relative is None or not relative.endswith(".py"):
- continue
- summary = raw_filedata.get("summary", {})
- if not isinstance(summary, dict):
- summary = {}
- files.append(
- CoverageFile(
- path=relative,
- statements=int(summary.get("num_statements", 0)),
- covered_lines=int(summary.get("covered_lines", 0)),
- )
- )
- return tuple(sorted(files, key=lambda item: item.path))
-
-
-def read_testmon_fingerprints(testmon_db_path: Path, *, source_root: Path) -> frozenset[str]:
- """Read the file paths currently represented in testmon's dependency graph."""
- connection = open_readonly_connection(testmon_db_path)
- try:
- columns = {str(row[1]) for row in connection.execute("PRAGMA table_info(file_fp)").fetchall()}
- path_column = "filename" if "filename" in columns else "path" if "path" in columns else None
- if path_column is None:
- raise ValueError("testmon database file_fp table has no filename/path column")
- rows = connection.execute(f"SELECT {path_column} FROM file_fp").fetchall()
- finally:
- connection.close()
-
- return frozenset(
- relative
- for row in rows
- if row and isinstance(row[0], str)
- if (relative := _relative_path(row[0], source_root=source_root)) is not None
- )
-
-
-def _is_docstring(node: ast.stmt, *, first: bool) -> bool:
- return (
- first
- and isinstance(node, ast.Expr)
- and isinstance(node.value, ast.Constant)
- and isinstance(node.value.value, str)
- )
-
-
-def _statement_is_executable(node: ast.stmt) -> bool:
- """Return whether a statement can carry runtime validation behavior."""
- if isinstance(node, (ast.Pass, ast.Import, ast.ImportFrom)):
- return False
- if (
- isinstance(node, ast.Expr)
- and isinstance(node.value, ast.Constant)
- and (isinstance(node.value.value, str) or node.value.value is Ellipsis)
- ):
- return False
- if isinstance(node, ast.AnnAssign) and node.value is None:
- return False
- if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
- if node.decorator_list:
- return True
- if node.args.defaults or any(default is not None for default in node.args.kw_defaults):
- return True
- return _body_is_executable(node.body)
- if isinstance(node, ast.ClassDef):
- if node.decorator_list:
- return True
- if node.bases or node.keywords:
- return True
- return _body_is_executable(node.body)
- if isinstance(node, ast.Assign):
- return _expression_is_runtime(node.value)
- if isinstance(node, ast.AnnAssign):
- return node.value is not None and _expression_is_runtime(node.value)
- return True
-
-
-def _expression_is_runtime(node: ast.expr) -> bool:
- """Conservatively identify assignment expressions with runtime effects."""
- if isinstance(node, (ast.Constant, ast.Name, ast.Attribute)):
- return False
- if isinstance(node, (ast.Tuple, ast.List, ast.Set)):
- return any(_expression_is_runtime(element) for element in node.elts)
- if isinstance(node, ast.Dict):
- return any(
- (key is not None and _expression_is_runtime(key)) or _expression_is_runtime(value)
- for key, value in zip(node.keys, node.values, strict=True)
- )
- return True
-
-
-def _body_is_executable(body: list[ast.stmt]) -> bool:
- for index, node in enumerate(body):
- if _is_docstring(node, first=index == 0):
- continue
- if _statement_is_executable(node):
- return True
- return False
-
-
-def classify_source_ast(source_path: Path) -> ASTClassification:
- """Classify source by executable AST content, with read and parse failures as risk."""
- try:
- tree = ast.parse(source_path.read_text(encoding="utf-8"), filename=str(source_path))
- except OSError:
- return "source-unreadable"
- except (SyntaxError, UnicodeDecodeError):
- return "executable"
- return "executable" if _body_is_executable(tree.body) else "declaration-only"
-
-
-def audit_blind_spots(
- *,
- coverage_json_path: Path,
- testmon_db_path: Path,
- source_root: Path,
-) -> BlindSpotReport:
- """Compare coverage-known files with testmon fingerprints without mutation."""
- coverage_files = read_coverage_files(coverage_json_path, source_root=source_root)
- fingerprints = read_testmon_fingerprints(testmon_db_path, source_root=source_root)
- findings: list[BlindSpotFinding] = []
- for coverage_file in coverage_files:
- source_path = source_root / coverage_file.path
- readable = source_path.is_file()
- classification = classify_source_ast(source_path)
- fingerprinted = coverage_file.path in fingerprints
- if not readable or classification == "source-unreadable":
- status: FindingStatus = "source-unreadable"
- safe = False
- elif fingerprinted:
- status = "fingerprinted"
- safe = True
- elif classification == "declaration-only":
- status = "declaration-only-unfingerprinted"
- safe = True
- else:
- status = "executable-validator-unfingerprinted"
- safe = False
- findings.append(
- BlindSpotFinding(
- path=coverage_file.path,
- statements=coverage_file.statements,
- covered_lines=coverage_file.covered_lines,
- ast_classification=classification,
- testmon_fingerprinted=fingerprinted,
- status=status,
- safe=safe,
- )
- )
- return BlindSpotReport(
- findings=tuple(findings),
- coverage_file_count=len(coverage_files),
- testmon_fingerprint_count=len(fingerprints),
- )
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description="Audit existing coverage metadata against pytest-testmon fingerprints without running tests."
- )
- parser.add_argument("--coverage-json", type=Path, default=Path(".cache/coverage/coverage.json"))
- parser.add_argument("--testmon-db", type=Path, default=Path(".cache/testmon/testmondata"))
- parser.add_argument("--source-root", type=Path, default=Path("."))
- parser.add_argument("--json", action="store_true", help="Emit the complete audit report as JSON.")
- args = parser.parse_args(argv)
- report = audit_blind_spots(
- coverage_json_path=args.coverage_json,
- testmon_db_path=args.testmon_db,
- source_root=args.source_root,
- )
- if args.json:
- print(json.dumps(report.to_dict(), indent=2))
- else:
- for finding in report.findings:
- print(f"{finding.status:>38} {finding.path}")
- print(f"coverage files: {report.coverage_file_count}; testmon fingerprints: {report.testmon_fingerprint_count}")
- print(f"risk findings: {len(report.risks)}")
- return 1 if report.risks else 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/validation_catalog.py b/devtools/validation_catalog.py
deleted file mode 100644
index e4bf002053..0000000000
--- a/devtools/validation_catalog.py
+++ /dev/null
@@ -1,115 +0,0 @@
-"""Typed validation-lane catalog shared across control-plane surfaces."""
-
-from __future__ import annotations
-
-from dataclasses import replace
-
-from .lane_models import LaneEntry
-from .validation_lane_catalog_contracts import COMPOSITE_LANES, CONTRACT_LANES
-from .validation_lane_catalog_live import LIVE_LANES
-
-ALL_VALIDATION_LANES: dict[str, LaneEntry] = {
- **CONTRACT_LANES,
- **LIVE_LANES,
- **COMPOSITE_LANES,
-}
-
-
-def _merge_unique(*groups: tuple[str, ...]) -> tuple[str, ...]:
- seen: set[str] = set()
- merged: list[str] = []
- for group in groups:
- for item in group:
- if item not in seen:
- seen.add(item)
- merged.append(item)
- return tuple(merged)
-
-
-def _build_lane_entry(
- lane_name: str,
- *,
- cache: dict[str, LaneEntry],
- visiting: set[str],
-) -> LaneEntry:
- if lane_name in cache:
- return cache[lane_name]
- if lane_name in visiting:
- raise ValueError(f"Cyclic validation lane metadata dependency: {lane_name}")
-
- visiting.add(lane_name)
- lane = ALL_VALIDATION_LANES[lane_name]
- child_entries = tuple(_build_lane_entry(child, cache=cache, visiting=visiting) for child in lane.sub_lanes)
- exec_meta = lane.execution.metadata if lane.execution is not None else None
- entry = replace(
- lane,
- path_targets=_merge_unique(
- lane.path_targets,
- exec_meta.path_targets if exec_meta is not None else (),
- *(child.path_targets for child in child_entries),
- ),
- artifact_targets=_merge_unique(
- lane.artifact_targets,
- exec_meta.artifact_targets if exec_meta is not None else (),
- *(child.artifact_targets for child in child_entries),
- ),
- conceptual_path_targets=_merge_unique(
- lane.conceptual_path_targets,
- exec_meta.conceptual_path_targets if exec_meta is not None else (),
- *(child.conceptual_path_targets for child in child_entries),
- ),
- conceptual_artifact_targets=_merge_unique(
- lane.conceptual_artifact_targets,
- exec_meta.conceptual_artifact_targets if exec_meta is not None else (),
- *(child.conceptual_artifact_targets for child in child_entries),
- ),
- operation_targets=_merge_unique(
- lane.operation_targets,
- exec_meta.operation_targets if exec_meta is not None else (),
- *(child.operation_targets for child in child_entries),
- ),
- maintenance_targets=_merge_unique(
- lane.maintenance_targets,
- exec_meta.maintenance_targets if exec_meta is not None else (),
- *(child.maintenance_targets for child in child_entries),
- ),
- tags=_merge_unique(lane.tags, *(child.tags for child in child_entries)),
- )
- visiting.remove(lane_name)
- cache[lane_name] = entry
- return entry
-
-
-def build_validation_lane_entries() -> tuple[LaneEntry, ...]:
- cache: dict[str, LaneEntry] = {}
- return tuple(
- sorted(
- (_build_lane_entry(name, cache=cache, visiting=set()) for name in ALL_VALIDATION_LANES),
- key=lambda item: item.name,
- )
- )
-
-
-def _category_entries(category: str) -> tuple[LaneEntry, ...]:
- return tuple(entry for entry in build_validation_lane_entries() if entry.category == category)
-
-
-def build_contract_lane_entries() -> tuple[LaneEntry, ...]:
- return _category_entries("contract")
-
-
-def build_live_lane_entries() -> tuple[LaneEntry, ...]:
- return _category_entries("live")
-
-
-def build_composite_lane_entries() -> tuple[LaneEntry, ...]:
- return _category_entries("composite")
-
-
-__all__ = [
- "build_validation_lane_entries",
- "LaneEntry",
- "build_composite_lane_entries",
- "build_contract_lane_entries",
- "build_live_lane_entries",
-]
diff --git a/devtools/validation_lane_catalog_contracts.py b/devtools/validation_lane_catalog_contracts.py
deleted file mode 100644
index 4ee6223395..0000000000
--- a/devtools/validation_lane_catalog_contracts.py
+++ /dev/null
@@ -1,863 +0,0 @@
-"""Local/test-focused validation lane declarations plus composite lanes."""
-
-from __future__ import annotations
-
-from devtools.lane_models import LaneEntry
-from polylogue.scenarios import (
- CorpusRequest,
- PipelineProbeRequest,
- ScenarioMetadata,
- composite_execution,
- devtools_execution,
- pipeline_probe_execution,
- pytest_execution,
-)
-from polylogue.scenarios.assertions import AssertionClass, AssertionSpec
-
-# ---------------------------------------------------------------------------
-# Contract lanes
-# ---------------------------------------------------------------------------
-
-CONTRACT_LANES: dict[str, LaneEntry] = {
- "machine-contract": LaneEntry(
- name="machine-contract",
- description="Root CLI JSON success/failure envelopes and runtime-health machine surfaces",
- timeout_s=180,
- category="contract",
- execution=pytest_execution("-q", "-n", "0", "-m", "machine_contract"),
- operation_targets=("cli.json-contract",),
- tags=("contract", "json", "cli"),
- ),
- "verification-substrate-contracts": LaneEntry(
- name="verification-substrate-contracts",
- description="Shared test fixture contracts for JSON metadata, scenario content blocks, and semantic facts",
- timeout_s=180,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/infra/test_storage_records.py",
- "tests/infra/test_archive_scenarios.py",
- "tests/infra/test_json_contracts.py",
- ),
- conceptual_path_targets=("verification-fixture-substrate",),
- conceptual_artifact_targets=("archive_scenario_fixtures", "storage_record_fixtures", "json_contract_helpers"),
- operation_targets=("seed-archive-scenarios", "build-storage-record-fixtures"),
- tags=("contract", "fixtures", "semantic-precision"),
- ),
- "query-routing": LaneEntry(
- name="query-routing",
- description="Query-first CLI route planning, integration, and streamed read checks",
- timeout_s=240,
- category="contract",
- execution=pytest_execution("-q", "-n", "0", "-m", "query_routing"),
- ),
- "demo-visual": LaneEntry(
- name="demo-visual",
- description="Deterministic demo seed/verify commands plus reader visual DOM evidence",
- timeout_s=300,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/cli/test_demo_command.py",
- "tests/unit/demo/test_demo_seed_verify.py",
- "tests/visual",
- ),
- operation_targets=("cli.help", "seed-demo-archive", "verify-demo-archive", "reader-visual-dom"),
- tags=("contract", "demo", "visual"),
- ),
- "pipeline-probe-chatgpt": LaneEntry(
- name="pipeline-probe-chatgpt",
- description="Synthetic ChatGPT parse-stage pipeline probe under explicit runtime and RSS budgets",
- timeout_s=180,
- category="contract",
- execution=pipeline_probe_execution(
- PipelineProbeRequest(
- stage="parse",
- corpus_request=CorpusRequest(providers=("chatgpt",), count=5, messages_min=4, messages_max=12, seed=42),
- max_total_ms=10000,
- max_peak_rss_mb=512,
- )
- ),
- assertion=AssertionSpec(
- stdout_min_lines=3,
- classification_override=AssertionClass.SMOKE_PROCESS,
- ),
- ),
- "storage-correctness": LaneEntry(
- name="storage-correctness",
- description="Archive-backed storage correctness for idempotency, FTS drift, blob GC, and lineage composition",
- timeout_s=180,
- category="contract",
- execution=devtools_execution(
- "lab smoke",
- "run",
- "storage-correctness",
- "--json",
- metadata=ScenarioMetadata(
- path_targets=(
- "raw-archive-ingest-loop",
- "message-fts-readiness-loop",
- "session-query-loop",
- ),
- artifact_targets=(
- "archive_session_rows",
- "message_source_rows",
- "message_fts",
- "session_query_results",
- ),
- operation_targets=(
- "ingest-archive-runtime",
- "index-message-fts",
- "query-sessions",
- ),
- ),
- ),
- assertion=AssertionSpec(
- stdout_is_valid_json=True,
- stdout_contains=('"scenario": "storage-correctness"', '"ok": true'),
- classification_override=AssertionClass.SMOKE_PROCESS,
- ),
- family="storage-correctness",
- tags=("contract", "storage", "scenario", "fts", "gc", "lineage"),
- ),
- "semantic-stack": LaneEntry(
- name="semantic-stack",
- description="Unified harmonization, semantic facts/profile convergence, and contract inventory coverage",
- timeout_s=360,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/core/test_semantic_facts.py",
- "tests/unit/core/test_schema_semantic_inference.py",
- "tests/unit/cli/test_check.py",
- "tests/unit/core/test_session_semantics.py",
- ),
- ),
- "schema-list-contract": LaneEntry(
- name="schema-list-contract",
- description="Devtools schema package catalog list surface and runtime projection coverage",
- timeout_s=120,
- category="contract",
- execution=devtools_execution("lab schema list", "--json"),
- tags=("contract", "schema", "devtools"),
- ),
- "schema-explain-contract": LaneEntry(
- name="schema-explain-contract",
- description="Devtools schema package explanation surface and runtime projection coverage",
- timeout_s=120,
- category="contract",
- execution=devtools_execution("lab schema explain", "--provider", "chatgpt", "--json"),
- tags=("contract", "schema", "devtools"),
- ),
- "source-provider-fidelity": LaneEntry(
- name="source-provider-fidelity",
- description="Source traversal, Drive/runtime source boundaries, parser decoding, and provider-ingest fidelity",
- timeout_s=420,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/sources/test_drive_ops.py",
- "tests/unit/sources/test_source_laws.py",
- "tests/unit/sources/test_acquisition_encoding.py",
- "tests/unit/storage/test_parse_tracking.py",
- "tests/unit/pipeline/test_ingestion_chaos.py",
- "tests/integration/test_security.py",
- ),
- path_targets=("source-acquisition-loop",),
- artifact_targets=(
- "configured_sources",
- "source_payload_stream",
- "raw_validation_state",
- "artifact_observation_rows",
- ),
- operation_targets=("acquire-raw-sessions",),
- tags=("contract", "sources", "acquisition"),
- ),
- "maintenance-workflows": LaneEntry(
- name="maintenance-workflows",
- description="Health, maintenance selection, cache/live provenance, and machine output",
- timeout_s=480,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/core/test_health_core.py",
- "tests/unit/storage/test_fts5.py",
- "tests/unit/cli/test_check.py",
- "tests/unit/cli/test_source_selection_helpers.py",
- "tests/unit/cli/test_deterministic_output.py",
- "tests/integration/test_health.py",
- ),
- tags=("contract", "maintenance"),
- ),
- "mutation-routes": LaneEntry(
- name="mutation-routes",
- description="Executor-routed mutation actuators and transaction receipts over their declared runtime closures",
- timeout_s=480,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/operations/test_mutations.py",
- "tests/unit/operations/test_mutation_actuators.py",
- "tests/unit/operations/test_operation_bindings.py",
- "tests/unit/maintenance/test_raw_authority_reset.py",
- "tests/unit/annotations/test_importer.py::test_import_roundtrip_keeps_failures_candidates_and_independent_batches",
- "tests/unit/cli/test_excise.py::TestExciseStandalone::test_yes_applies_excision",
- ),
- path_targets=(
- "tag-mutation-loop",
- "metadata-mutation-loop",
- "mark-mutation-loop",
- "annotation-mutation-loop",
- "blackboard-post-loop",
- "assertion-candidate-capture-loop",
- "raw-authority-blocker-resolution-loop",
- "raw-authority-recovery-loop",
- "saved-view-mutation-loop",
- "recall-pack-mutation-loop",
- "workspace-mutation-loop",
- "correction-mutation-loop",
- "session-delete-loop",
- "session-excision-loop",
- "identity-reset-loop",
- "message-fts-readiness-loop",
- "session-insight-repair-loop",
- ),
- artifact_targets=(
- "sessions",
- "assertions",
- "archive_deleted_session",
- "raw_sessions",
- "blob_refs",
- "excision_receipt",
- "suppression_rows",
- "raw_authority_plans",
- "raw_authority_blockers",
- "raw_authority_blocker_resolution",
- "raw_authority_census_ledger",
- "raw_authority_census_recovery_receipt",
- "raw_revision_heads",
- "raw_revision_applications",
- "raw_authority_index_seed_recovery_receipt",
- ),
- operation_targets=(
- "mutate-add-tag",
- "mutate-remove-tag",
- "mutate-bulk-tag-sessions",
- "mutate-set-metadata",
- "mutate-delete-metadata",
- "mutate-add-mark",
- "mutate-remove-mark",
- "mutate-save-annotation",
- "mutate-delete-annotation",
- "mutate-blackboard-post",
- "mutate-capture-assertion-candidate",
- "mutate-import-annotation-batch",
- "mutate-rebuild-index",
- "mutate-update-index",
- "mutate-rebuild-insights",
- "mutate-resolve-raw-authority-blocker",
- "mutate-reset-raw-authority-census",
- "mutate-prune-orphaned-index-revision-seeds",
- "mutate-save-saved-view",
- "mutate-delete-saved-view",
- "mutate-save-recall-pack",
- "mutate-delete-recall-pack",
- "mutate-save-workspace",
- "mutate-delete-workspace",
- "mutate-record-correction",
- "mutate-delete-correction",
- "mutate-clear-corrections",
- "mutate-delete-session",
- "mutate-session-excision",
- "mutate-session-lifecycle-request",
- "mutate-identity-reset",
- ),
- tags=("contract", "mutation", "operation-executor"),
- ),
- "insight-query-routes": LaneEntry(
- name="insight-query-routes",
- description="CLI insight routes for thread and tool-usage projections over seeded archive data",
- timeout_s=300,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/cli/test_insights.py::test_insights_threads_json",
- "tests/unit/cli/test_diagnostics.py::test_tools_renders_against_real_archive_backed_store",
- ),
- path_targets=("thread-query-loop", "tool-usage-query-loop"),
- artifact_targets=("thread_rows", "thread_fts", "thread_results", "archive_session_rows", "tool_usage_results"),
- operation_targets=("query-threads", "query-tool-usage"),
- tags=("contract", "insights", "query"),
- ),
- "maintenance-target-routes": LaneEntry(
- name="maintenance-target-routes",
- description="Doctor and preview routes for required cleanup and derived-repair maintenance targets",
- timeout_s=300,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/cli/test_check.py",
- "tests/unit/maintenance/test_preview.py",
- "tests/unit/maintenance/test_targets.py",
- ),
- maintenance_targets=("empty_sessions", "message_type_backfill", "superseded_raw_snapshots"),
- tags=("contract", "maintenance", "doctor"),
- ),
- "archive-data-insights": LaneEntry(
- name="archive-data-insights",
- description="Archive insights, consumer contracts, grouped stats, and readiness/debt surfaces",
- timeout_s=600,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/cli/test_insights.py",
- "tests/unit/core/test_facade_api.py",
- "tests/unit/cli/test_query_verbs_runtime.py",
- "tests/unit/cli/test_check.py",
- "tests/unit/cli/test_click_app.py",
- "tests/unit/core/test_health_core.py",
- "tests/integration/test_health.py",
- ),
- ),
- "semantic-insight-normalization": LaneEntry(
- name="semantic-insight-normalization",
- description="Semantic/session insight normalization, operator/toolchain narrowing, schema contracts, and provider parser cleanup",
- timeout_s=900,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/core/test_repo_identity.py",
- "tests/unit/cli/test_insights.py",
- "tests/unit/core/test_facade_api.py",
- "tests/unit/cli/test_check.py",
- "tests/unit/core/test_schema_registry.py",
- "tests/unit/core/test_schema_generation.py",
- "tests/unit/core/test_operator_models.py",
- "tests/integration/test_schema_operator_workflow.py",
- "tests/unit/storage/test_search_misc.py",
- "tests/unit/sources/test_parsers_base.py",
- "tests/unit/sources/test_parsers_drive.py",
- "tests/unit/devtools/test_validation_lanes.py",
- ),
- assertion=AssertionSpec(
- classification_override=AssertionClass.SMOKE_PROCESS,
- ),
- ),
- "retrieval-checks": LaneEntry(
- name="retrieval-checks",
- description="Action-aware query truth, grouped retrieval stats, and archive readiness",
- timeout_s=480,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/cli/test_query_verbs_runtime.py",
- "tests/unit/cli/test_query_exec_laws.py",
- "tests/unit/storage/test_store_ops.py",
- "tests/unit/core/test_filters_props.py",
- "tests/unit/core/test_health_core.py",
- "tests/unit/cli/test_source_selection_helpers.py",
- ),
- path_targets=("session-query-loop", "message-fts-readiness-loop"),
- artifact_targets=("message_fts", "session_query_results", "archive_readiness"),
- operation_targets=("query-sessions", "project-archive-readiness"),
- tags=("contract", "retrieval", "readiness"),
- ),
- "embeddings-coverage": LaneEntry(
- name="embeddings-coverage",
- description="Embedding coverage/readiness stats, readiness exposure, and embed command contracts",
- timeout_s=300,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/cli/test_embed.py",
- "tests/unit/storage/test_embedding_stats.py",
- "tests/unit/core/test_health_core.py",
- "tests/unit/cli/test_source_selection_helpers.py",
- ),
- path_targets=("embedding-materialization-loop", "embedding-status-query-loop", "retrieval-band-readiness-loop"),
- artifact_targets=(
- "archive_session_rows",
- "embedding_metadata_rows",
- "embedding_status_rows",
- "message_embedding_vectors",
- "retrieval_band_readiness",
- "embedding_status_results",
- ),
- operation_targets=(
- "materialize-transcript-embeddings",
- "project-retrieval-band-readiness",
- "query-embedding-status",
- ),
- tags=("contract", "embeddings", "retrieval"),
- ),
- "evidence-tier-contracts": LaneEntry(
- name="evidence-tier-contracts",
- description="Explicit evidence-tier insight contracts, chronology fields, and evidence payload/query surfaces",
- timeout_s=420,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/cli/test_insights.py",
- "tests/unit/core/test_facade_api.py",
- "tests/unit/storage/test_store_ops.py",
- "tests/unit/pipeline/test_prepare_semantic.py",
- ),
- ),
- "inference-tier-contracts": LaneEntry(
- name="inference-tier-contracts",
- description="Inference-tier work-event/phase/profile contracts with confidence/provenance-bearing semantic payloads",
- timeout_s=420,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/cli/test_insights.py",
- "tests/unit/core/test_facade_api.py",
- "tests/unit/pipeline/test_prepare_semantic.py",
- ),
- ),
- "mixed-consumer-contracts": LaneEntry(
- name="mixed-consumer-contracts",
- description="CLI, facade, and readiness surfaces consuming the same evidence/inference insight model",
- timeout_s=480,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/cli/test_insights.py",
- "tests/unit/core/test_facade_api.py",
- "tests/unit/cli/test_check.py",
- "tests/integration/test_health.py",
- ),
- ),
- "retrieval-band-readiness": LaneEntry(
- name="retrieval-band-readiness",
- description="Transcript/evidence/inference retrieval-band readiness, embedding stats, and readiness exposure",
- timeout_s=420,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/cli/test_embed.py",
- "tests/unit/storage/test_embedding_stats.py",
- "tests/unit/core/test_health_core.py",
- "tests/unit/cli/test_check.py",
- ),
- path_targets=("embedding-status-query-loop", "retrieval-band-readiness-loop", "message-fts-readiness-loop"),
- artifact_targets=(
- "embedding_metadata_rows",
- "embedding_status_rows",
- "message_embedding_vectors",
- "retrieval_band_readiness",
- "embedding_status_results",
- "archive_readiness",
- ),
- operation_targets=("project-retrieval-band-readiness", "query-embedding-status", "project-archive-readiness"),
- tags=("contract", "retrieval", "embeddings", "readiness"),
- ),
- "heuristic-inference-contracts": LaneEntry(
- name="heuristic-inference-contracts",
- description="Heuristic session/work/phase contract hardening with explicit supporting metadata and consumer parity",
- timeout_s=600,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/cli/test_insights.py",
- "tests/unit/core/test_facade_api.py",
- "tests/unit/core/test_semantic_facts.py",
- "tests/unit/pipeline/test_prepare_semantic.py",
- "tests/unit/core/test_health_core.py",
- ),
- ),
- "probabilistic-enrichment-contracts": LaneEntry(
- name="probabilistic-enrichment-contracts",
- description="Session-enrichment contracts across CLI, facade, storage, and retrieval-band status",
- timeout_s=720,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/cli/test_insights.py",
- "tests/unit/core/test_facade_api.py",
- "tests/unit/storage/test_embedding_stats.py",
- "tests/unit/storage/test_store_ops.py",
- "tests/unit/core/test_health_core.py",
- ),
- ),
- "cleanup-contracts": LaneEntry(
- name="cleanup-contracts",
- description="Cleanup lineage, readiness/debt views, and maintenance workflow coverage",
- timeout_s=900,
- category="contract",
- execution=pytest_execution(
- "-q",
- "-n",
- "0",
- "tests/unit/cli/test_insights.py",
- "tests/unit/cli/test_check.py",
- "tests/unit/core/test_health_core.py",
- "tests/integration/test_health.py",
- ),
- ),
- "tui": LaneEntry(
- name="tui",
- description="Textual dashboard screens and interaction-state coverage",
- timeout_s=240,
- category="contract",
- execution=pytest_execution("-q", "-n", "0", "-m", "tui"),
- ),
- "chaos": LaneEntry(
- name="chaos",
- description="Hostility, interruption, and chronology integration coverage",
- timeout_s=900,
- category="contract",
- execution=pytest_execution("-q", "-n", "0", "-m", "chaos"),
- ),
- "scale-fast": LaneEntry(
- name="scale-fast",
- description="Fast storage scale budgets",
- timeout_s=120,
- category="contract",
- execution=pytest_execution("-v", "tests/unit/storage/test_scale.py", "-x", "--timeout=30"),
- ),
- "scale-regression": LaneEntry(
- name="scale-regression",
- description="Seeded large-archive-shaped regression probe for real-scale archive bugs",
- timeout_s=240,
- category="contract",
- execution=devtools_execution("workspace scale-regression", "--json"),
- assertion=AssertionSpec(
- stdout_is_valid_json=True,
- classification_override=AssertionClass.SMOKE_PROCESS,
- ),
- conceptual_path_targets=("session-insight-materialization-loop", "raw-materialization-loop"),
- # polylogue-dab/itvd: "session_runs" renamed to "run_projection" --
- # run/observed-event/context-snapshot rows are source-derived CTE
- # relations (run_projection_relations.py), not a materialized table.
- artifact_targets=("raw_sessions",),
- conceptual_artifact_targets=(
- "session_profile",
- "run_projection",
- "archive_tiers",
- ),
- operation_targets=(
- "materialize-session-insights",
- "materialize-run-projection",
- "project-archive-readiness",
- ),
- tags=("contract", "scale", "storage", "regression"),
- ),
- "scale-slow": LaneEntry(
- name="scale-slow",
- description="Slow local storage scale budgets",
- timeout_s=360,
- category="contract",
- execution=pytest_execution("-v", "-m", "slow", "tests/unit/storage/", "--timeout=120"),
- ),
- "long-haul-small": LaneEntry(
- name="long-haul-small",
- description="Small reproducible benchmark/long-haul campaign",
- timeout_s=1800,
- category="contract",
- execution=devtools_execution("bench synthetic", "--scale", "small"),
- ),
-}
-
-# ---------------------------------------------------------------------------
-# Composite lanes (flattened from former validation_family_models DSL +
-# standalone composite declarations)
-# ---------------------------------------------------------------------------
-
-_COMPOSITE_ORIGIN = "authored.validation-lane.composite"
-
-COMPOSITE_LANES: dict[str, LaneEntry] = {
- # --- Family-generated composites ---
- "domain-read-model-contracts": LaneEntry(
- name="domain-read-model-contracts",
- description="Local domain read-model lane for analytics/insights, consumer contracts, and debt views",
- timeout_s=2400,
- category="composite",
- family="domain-read-model",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution("archive-data-insights", "maintenance-workflows"),
- ),
- "domain-read-model-live": LaneEntry(
- name="domain-read-model-live",
- description="Bounded live archive lane for insights, analytics/debt views, and maintenance checks",
- timeout_s=1800,
- category="composite",
- family="domain-read-model",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution(
- "live-insights-small", "live-insights-coverage-provider", "live-insights-debt", "live-maintenance-small"
- ),
- ),
- "domain-read-model-hardening": LaneEntry(
- name="domain-read-model-hardening",
- description="Full domain read-model lane with local contracts and bounded live checks",
- timeout_s=3600,
- category="composite",
- family="domain-read-model",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution("domain-read-model-contracts", "domain-read-model-live"),
- ),
- "runtime-substrate-contracts": LaneEntry(
- name="runtime-substrate-contracts",
- description="Local runtime-substrate lane across query, semantic checks, archive insights, and maintenance workflows",
- timeout_s=2400,
- category="composite",
- family="runtime-substrate",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution(
- "query-routing", "semantic-stack", "maintenance-workflows", "archive-data-insights"
- ),
- ),
- "runtime-substrate-live": LaneEntry(
- name="runtime-substrate-live",
- description="Bounded live archive lane for runtime-substrate checks, maintenance checks, and memory budgets",
- timeout_s=1800,
- category="composite",
- family="runtime-substrate",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution("live-archive-small", "live-maintenance-small", "memory-budget"),
- ),
- "runtime-substrate-hardening": LaneEntry(
- name="runtime-substrate-hardening",
- description="Full runtime-substrate validation lane covering local contracts plus bounded live archive checks",
- timeout_s=3600,
- category="composite",
- family="runtime-substrate",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution("runtime-substrate-contracts", "runtime-substrate-live"),
- ),
- "evidence-contracts": LaneEntry(
- name="evidence-contracts",
- description="Evidence/inference contract lane across explicit evidence, inferred semantics, consumer parity, and retrieval readiness",
- timeout_s=2400,
- category="composite",
- family="evidence",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution(
- "evidence-tier-contracts",
- "inference-tier-contracts",
- "mixed-consumer-contracts",
- "retrieval-band-readiness",
- ),
- ),
- "evidence-live": LaneEntry(
- name="evidence-live",
- description="Bounded live archive lane for tiered insight views, live repair, health, and retrieval-band budgets",
- timeout_s=2400,
- category="composite",
- family="evidence",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution(
- "live-session-insight-repair",
- "live-insights-status",
- "live-insights-profiles-evidence",
- "live-insights-profiles-inference",
- "live-insights-work-events",
- "live-insights-phases",
- "live-embed-stats",
- "live-readiness-json",
- "maintenance-memory-budget",
- ),
- ),
- "evidence-hardening": LaneEntry(
- name="evidence-hardening",
- description="Full evidence lane with contracts and bounded live checks",
- timeout_s=4800,
- category="composite",
- family="evidence",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution("evidence-contracts", "evidence-live"),
- ),
- "semantic-insight-live": LaneEntry(
- name="semantic-insight-live",
- description="Bounded live archive lane for normalized insights, maintenance preview, and memory budgets",
- timeout_s=1800,
- category="composite",
- family="semantic-insight",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution(
- "live-insights-status",
- "live-insights-tags",
- "live-insights-coverage-day",
- "live-insights-debt",
- "live-maintenance-small",
- ),
- ),
- "semantic-insight-hardening": LaneEntry(
- name="semantic-insight-hardening",
- description="Full semantic-insight normalization and toolchain convergence lane",
- timeout_s=3600,
- category="composite",
- family="semantic-insight",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution("semantic-insight-normalization", "semantic-insight-live"),
- ),
- "probabilistic-enrichment-live": LaneEntry(
- name="probabilistic-enrichment-live",
- description="Bounded live archive lane for enrichment insights, retrieval bands, and readiness surfaces",
- timeout_s=2400,
- category="composite",
- family="probabilistic-enrichment",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution(
- "live-session-insight-repair",
- "live-insights-status",
- "live-insights-profiles-inference",
- "live-embed-stats",
- "live-readiness-json",
- "memory-budget",
- ),
- ),
- "probabilistic-enrichment-cleanup-live": LaneEntry(
- name="probabilistic-enrichment-cleanup-live",
- description="Bounded live archive lane for cleanup/debt preview and maintenance budgets",
- timeout_s=2400,
- category="composite",
- family="probabilistic-enrichment",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution("live-insights-debt", "live-maintenance-preview", "maintenance-memory-budget"),
- ),
- "probabilistic-enrichment-hardening": LaneEntry(
- name="probabilistic-enrichment-hardening",
- description="Full probabilistic-enrichment and cleanup lane",
- timeout_s=5400,
- category="composite",
- family="probabilistic-enrichment",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution(
- "heuristic-inference-contracts",
- "probabilistic-enrichment-contracts",
- "cleanup-contracts",
- "probabilistic-enrichment-live",
- "probabilistic-enrichment-cleanup-live",
- ),
- ),
- # --- Standalone composites ---
- "source-runtime-alignment": LaneEntry(
- name="source-runtime-alignment",
- description="Local source/provider fidelity plus runtime maintenance alignment",
- timeout_s=1800,
- category="composite",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution("source-provider-fidelity", "maintenance-workflows"),
- ),
- "live-archive-small": LaneEntry(
- name="live-archive-small",
- description="Bounded live archive retrieval/readiness/health dogfood lane",
- timeout_s=480,
- category="composite",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution(
- "live-embed-stats", "live-retrieval-checks", "live-insights-status", "live-readiness-json"
- ),
- ),
- "live-insights-small": LaneEntry(
- name="live-insights-small",
- description="Bounded live archive insight and grouped-stats lane",
- timeout_s=480,
- category="composite",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution("live-insights-status", "live-insights-tags", "live-project-stats"),
- ),
- "live-archive-slow": LaneEntry(
- name="live-archive-slow",
- description="Broader live archive dogfood lane including retrieval/readiness and live scenario checks",
- timeout_s=2400,
- category="composite",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution("live-archive-small", "live-archive-smoke"),
- ),
- "archive-intelligence": LaneEntry(
- name="archive-intelligence",
- description="Local archive-intelligence closure lane for retrieval and embedding readiness",
- timeout_s=1800,
- category="composite",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution("retrieval-checks", "embeddings-coverage"),
- ),
- "archive-data-insights-live": LaneEntry(
- name="archive-data-insights-live",
- description="Local insight-contract lane plus bounded live archive insight checks",
- timeout_s=1800,
- category="composite",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution("archive-data-insights", "live-insights-small"),
- ),
- "live-maintenance-small": LaneEntry(
- name="live-maintenance-small",
- description="Bounded live archive lane for health, maintenance preview, and maintenance memory budget",
- timeout_s=720,
- category="composite",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution("live-readiness-json", "live-maintenance-preview", "maintenance-memory-budget"),
- ),
- "scale-stretch": LaneEntry(
- name="scale-stretch",
- description="Combined fast and slow storage scale budgets",
- timeout_s=600,
- category="composite",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution("scale-fast", "scale-slow"),
- ),
- "frontier-local": LaneEntry(
- name="frontier-local",
- description="Non-live local closure lane for machine/query/semantic/TUI/chaos validation",
- timeout_s=1500,
- category="composite",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution(
- "machine-contract",
- "query-routing",
- "demo-visual",
- "semantic-stack",
- "tui",
- "chaos",
- ),
- ),
- "frontier-extended": LaneEntry(
- name="frontier-extended",
- description="Local closure lane plus fast scale and small long-haul campaign",
- timeout_s=3600,
- category="composite",
- origin=_COMPOSITE_ORIGIN,
- execution=composite_execution("frontier-local", "pipeline-probe-chatgpt", "scale-fast", "long-haul-small"),
- ),
-}
-
-__all__ = ["COMPOSITE_LANES", "CONTRACT_LANES"]
diff --git a/devtools/validation_lane_catalog_live.py b/devtools/validation_lane_catalog_live.py
deleted file mode 100644
index 067c70f1d5..0000000000
--- a/devtools/validation_lane_catalog_live.py
+++ /dev/null
@@ -1,93 +0,0 @@
-"""Live/archive-oriented validation lane declarations."""
-
-from __future__ import annotations
-
-from devtools.lane_models import LaneEntry
-from polylogue.scenarios import (
- PipelineProbeInputMode,
- PipelineProbeRequest,
- build_live_insight_surface_lanes,
- build_live_operational_surface_lanes,
- build_memory_budget_operational_surface_lanes,
- devtools_execution,
- memory_budget_execution,
- pipeline_probe_execution,
- polylogue_execution,
-)
-
-
-def _live_insight_lanes() -> dict[str, LaneEntry]:
- return {
- spec.name: LaneEntry(
- name=spec.name,
- description=spec.description,
- timeout_s=spec.timeout_s,
- category="live",
- execution=polylogue_execution(*spec.args),
- tags=spec.tags,
- )
- for spec in build_live_insight_surface_lanes()
- }
-
-
-def _live_operational_lanes() -> dict[str, LaneEntry]:
- return {
- spec.name: LaneEntry(
- name=spec.name,
- description=spec.description,
- timeout_s=spec.timeout_s,
- category="live",
- execution=polylogue_execution(*spec.args),
- tags=spec.tags,
- )
- for spec in build_live_operational_surface_lanes()
- }
-
-
-def _memory_budget_operational_lanes() -> dict[str, LaneEntry]:
- return {
- spec.name: LaneEntry(
- name=spec.name,
- description=spec.description,
- timeout_s=spec.timeout_s,
- category="live",
- execution=memory_budget_execution(
- spec.max_rss_mb or 1024,
- polylogue_execution(*spec.args),
- ),
- tags=spec.tags,
- )
- for spec in build_memory_budget_operational_surface_lanes()
- }
-
-
-LIVE_LANES: dict[str, LaneEntry] = {
- "live-archive-subset-parse-probe": LaneEntry(
- name="live-archive-subset-parse-probe",
- description="Live archive medium archive-subset parse probe with persisted manifest/workdir artifacts",
- timeout_s=1800,
- category="live",
- execution=pipeline_probe_execution(
- PipelineProbeRequest(
- input_mode=PipelineProbeInputMode.ARCHIVE_SUBSET,
- stage="parse",
- sample_per_provider=50,
- workdir="/tmp/polylogue-live-archive-subset-parse-probe",
- json_out="/tmp/polylogue-live-archive-subset-parse-probe.json",
- )
- ),
- tags=("live", "probe", "parse"),
- ),
- "live-archive-smoke": LaneEntry(
- name="live-archive-smoke",
- description="Manual lab archive-smoke lane",
- timeout_s=1800,
- category="live",
- execution=devtools_execution("lab smoke", "run", "archive-smoke", "--live", "--tier", "0", "--json"),
- ),
- **_live_operational_lanes(),
- **_live_insight_lanes(),
- **_memory_budget_operational_lanes(),
-}
-
-__all__ = ["LIVE_LANES"]
diff --git a/devtools/validation_lane_runtime.py b/devtools/validation_lane_runtime.py
deleted file mode 100644
index 0b2a890573..0000000000
--- a/devtools/validation_lane_runtime.py
+++ /dev/null
@@ -1,79 +0,0 @@
-"""Validation lane registry and execution helpers."""
-
-from __future__ import annotations
-
-import subprocess
-
-from devtools.authored_scenario_catalog import get_authored_scenario_catalog
-from devtools.lane_models import LaneEntry
-from polylogue.scenarios import resolve_execution_command, run_execution
-
-LANES: dict[str, LaneEntry] = get_authored_scenario_catalog().validation_lane_index()
-VALID_LANES = frozenset(LANES)
-
-
-def parse_lane(lane_name: str) -> LaneEntry:
- if lane_name not in LANES:
- raise ValueError(f"Invalid lane: {lane_name!r}. Valid lanes: {', '.join(sorted(VALID_LANES))}")
- return LANES[lane_name]
-
-
-def build_lane_command(lane: LaneEntry) -> list[str]:
- if lane.execution is None:
- raise ValueError(f"Lane {lane.name!r} is composite and has no direct command")
- return list(resolve_execution_command(lane.execution))
-
-
-def print_lane(lane: LaneEntry, *, indent: str = "") -> None:
- print(f"{indent}{lane.name}: {lane.description}")
- if lane.is_composite:
- for child_name in lane.sub_lanes:
- print_lane(parse_lane(child_name), indent=indent + " ")
- else:
- print(f"{indent} command: {' '.join(build_lane_command(lane))}")
- print(f"{indent} timeout: {lane.timeout_s}s")
- print(f"{indent} assertion: {lane.assertion.classification.value}")
-
-
-def run_lane(lane: LaneEntry) -> int:
- if lane.is_composite:
- print(f"Validation lane: {lane.name} — {lane.description}")
- for child_name in lane.sub_lanes:
- exit_code = run_lane(parse_lane(child_name))
- if exit_code != 0:
- return exit_code
- return 0
-
- cmd = build_lane_command(lane)
- print(f"Validation lane: {lane.name} — {lane.description}")
- print(f"Command: {' '.join(cmd)}")
- print(f"Timeout: {lane.timeout_s}s")
- print()
-
- try:
- execution = lane.execution
- if execution is None:
- raise ValueError(f"Lane {lane.name!r} is missing execution metadata")
- result = run_execution(execution, timeout=lane.timeout_s, capture_output=True)
- if result.stdout:
- print(result.stdout, end="" if result.stdout.endswith("\n") else "\n")
- if result.stderr:
- print(result.stderr, end="" if result.stderr.endswith("\n") else "\n")
- error = lane.assertion.validate_process(result.stdout, result.exit_code)
- if error is not None:
- print(f"\nLane {lane.name!r} failed assertion: {error}")
- return result.exit_code if result.exit_code != 0 else 1
- return result.exit_code
- except subprocess.TimeoutExpired:
- print(f"\nLane {lane.name!r} timed out after {lane.timeout_s}s")
- return 2
-
-
-__all__ = [
- "LANES",
- "VALID_LANES",
- "build_lane_command",
- "parse_lane",
- "print_lane",
- "run_lane",
-]
diff --git a/devtools/verify.py b/devtools/verify.py
index f08979c1d3..b7c4171d2d 100644
--- a/devtools/verify.py
+++ b/devtools/verify.py
@@ -2084,17 +2084,9 @@ def build_verify_steps(
[
("render all", _devtools_cmd("render all", "--check")),
("verify layering", _devtools_cmd("verify layering")),
- ("lab graph strict", _devtools_cmd("lab graph", "--strict")),
- ("verify closure-matrix", _devtools_cmd("verify closure-matrix")),
- ("lab schema roundtrip", _devtools_cmd("lab schema roundtrip", "--all")),
- ("verify manifests", _devtools_cmd("verify manifests")),
- ("verify ci-workflows", _devtools_cmd("verify ci-workflows")),
- ("verify catalog-bypasses", _devtools_cmd("verify catalog-bypasses")),
+ ("verify ci-commands", _devtools_cmd("verify ci-commands")),
("verify doc-commands", _devtools_cmd("verify doc-commands")),
- ("verify docs-coverage", _devtools_cmd("verify docs-coverage")),
- ("verify test-infra-currency", _devtools_cmd("verify test-infra-currency")),
- ("verify pytest-timeout-overrides", _devtools_cmd("verify pytest-timeout-overrides")),
- ("verify degrade-loudly", _devtools_cmd("verify degrade-loudly")),
+ ("lab schema roundtrip", _devtools_cmd("lab schema roundtrip", "--all")),
# Static, archive-independent, sub-second: an index bump that
# lands without its lifecycle.py delta declaration silently
# downgrades every existing generation to a full raw replay
@@ -2102,60 +2094,6 @@ def build_verify_steps(
# failure surfaces as an unqueryable live archive rather than
# as a test failure.
("lab policy schema-versioning", _devtools_cmd("lab policy schema-versioning")),
- # Static, archive-independent, sub-second: catches the gap the
- # schema-versioning gate above cannot see -- a parser/classifier
- # changing what it accepts for identical input bytes with no
- # version bump at all (polylogue-gucv; PR #3428 is the
- # concrete case that shipped green against the version-keyed
- # gate above).
- ("lab policy classifier-fingerprints", _devtools_cmd("lab policy classifier-fingerprints")),
- # ~15-30s, fully deterministic (wall-clock timing is masked
- # before comparison, see devtools/verify_demo_tour_freshness.py).
- # Unlike backlog-hygiene/bead-graph below, this check's failure
- # count does not scale with total backlog/bead-corpus size --
- # it is a fixed-cost diff against one committed fixture that
- # only drifts when demo/insight code actually changes shape
- # (polylogue-ze5i: moved out of --lab after the committed
- # fixture was regenerated to match a `healed_tiers` field the
- # demo receipts code had already grown).
- ("lab policy demo-tour-freshness", _devtools_cmd("lab policy demo-tour-freshness")),
- # Static, archive-independent, sub-second: forbids the exact
- # byte-mutation-before-hashing pattern that produced
- # polylogue-u19l's Codex append-header bug (a synthesized
- # literal spliced onto captured bytes before they reached the
- # content hasher, permanently defeating live-source
- # byte-identity verification for ~59GB of raw rows).
- ("lab policy raw-payload-hash-purity", _devtools_cmd("lab policy raw-payload-hash-purity")),
- # Static, archive-independent, sub-second: forbids a NEW
- # occurrence of polylogue-hith/qkuq's already-fixed
- # attachment-id bug shape (comparison identity minted from
- # positional/index data, unstable across export vintages
- # that reorder entries) -- polylogue-gysk3 found the same
- # hazard still live for provider_message_id.
- ("lab policy position-derived-identity", _devtools_cmd("lab policy position-derived-identity")),
- # Static, archive-independent, sub-second: forbids a NEW
- # unreachable (frontier state, dispatched actuator) pairing in
- # polylogue/storage/raw_reconciler.py -- polylogue-w32w found
- # UNRESOLVED_PROVENANCE paired with the dispatched
- # REFINE_QUARANTINE actuator, an actuator no path could ever
- # select, and 4,174 blockers accumulated behind it for weeks
- # before anyone noticed. The runtime constructor guard
- # (RawAuthorityFrontierItem.__post_init__) only fires when
- # something actually constructs the bad combination; this
- # lint re-checks every literal pairing at review time.
- (
- "lab policy raw-authority-frontier-executability",
- _devtools_cmd("lab policy raw-authority-frontier-executability"),
- ),
- # Static, archive-independent, sub-second: forbids a NEW
- # top-level def named table_exists/column_exists/index_exists
- # (or a _-prefixed/_sync/_async variant) outside
- # polylogue/storage/introspection.py -- the ~25-copy
- # duplication polylogue-48h consolidated into that module.
- (
- "lab policy table-exists-duplication",
- _devtools_cmd("lab policy table-exists-duplication"),
- ),
# Publication gate. Committed provider schema packages are
# public artifacts; this blocks local provenance
# (bundle_scopes/representative_paths) and scans for secrets.
@@ -2172,20 +2110,6 @@ def build_verify_steps(
str(PYTEST_REPORT_DIR / "schema-promotion-audit.json"),
],
),
- # Static, archive-independent: the committed incident ledger
- # must agree with the structured Beads dependency graph and
- # every receipt/reference must resolve before quick verify is
- # allowed to report green.
- (
- "incident coverage ledger",
- [
- sys.executable,
- "-m",
- "devtools.incident_coverage_ledger",
- "--beads-export",
- str(ROOT / ".beads" / "issues.jsonl"),
- ],
- ),
]
)
@@ -2196,8 +2120,7 @@ def build_verify_steps(
# Scale-tier policy (issue #1183): default verify includes
# ``scale_small`` but excludes ``scale_medium`` / ``scale_large``.
# ``--lab`` lets the medium tier in; the large tier is reserved
- # for nightly CI and explicit ``devtools bench campaign``
- # invocations.
+ # for nightly CI's direct pytest-benchmark execution.
scale_marker_expr = "not scale_large" if lab else "not scale_medium and not scale_large"
pytest_cmd = [
sys.executable,
@@ -2274,36 +2197,6 @@ def _isolated_report_arg(arg: str) -> str:
steps.append(("bench slo", _devtools_cmd("bench slo", "--include-lab")))
steps.append(("lab policy timestamp-doctrine", _devtools_cmd("lab policy timestamp-doctrine")))
steps.append(("lab policy insight-honesty", _devtools_cmd("lab policy insight-honesty")))
- steps.append(("lab policy demo-packet-registry", _devtools_cmd("lab policy demo-packet-registry")))
- steps.append(("lab policy docs-drift", _devtools_cmd("lab policy docs-drift")))
- steps.append(
- ("lab policy campaign-archive-boundaries", _devtools_cmd("lab policy campaign-archive-boundaries"))
- )
- steps.append(("lab policy acceptance-contracts", _devtools_cmd("lab policy acceptance-contracts")))
- steps.append(
- (
- "lab policy acceptance-contract-reconcile",
- _devtools_cmd("lab policy acceptance-contract-reconcile"),
- )
- )
- steps.append(
- (
- "lab policy acceptance-contract-apply",
- _devtools_cmd("lab policy acceptance-contract-apply"),
- )
- )
- # backlog-hygiene and bead-graph are corpus-wide backlog-debt scans
- # (findings scale with the total count of open Beads issues, not
- # with this change's diff) -- they stay --lab-only/scheduled rather
- # than default- or CI-gated. Gating either on a merge would block
- # every PR in the repo until the entire pre-existing backlog is
- # cleaned up (485 backlog-hygiene findings / 225 missing-AC beads
- # measured 2026-08-02), which is periodic hygiene debt, not a
- # per-change regression signal. Wired into the CircleCI nightly
- # schedule instead (polylogue-ze5i) so continuous failure is at
- # least visible, and the backlog itself is tracked by follow-up
- # beads rather than left to rot silently.
- steps.append(("lab policy backlog-hygiene", _devtools_cmd("lab policy backlog-hygiene")))
steps.append(("lab policy bead-graph", _devtools_cmd("lab policy bead-graph")))
return steps
diff --git a/devtools/verify_agent_integration.py b/devtools/verify_agent_integration.py
index bf490027e2..6de72f7354 100644
--- a/devtools/verify_agent_integration.py
+++ b/devtools/verify_agent_integration.py
@@ -246,18 +246,6 @@ def _manual_compilation_lane() -> LaneResult:
missing_reference = set(ALL_TARGET_TOOLS) - reference_tool_names
if missing_reference:
problems.append(f"deep reference omits target invocation(s): {sorted(missing_reference)}")
- required_phrases = (
- "same tool with **only** the returned opaque token",
- "Never cite a continuation token",
- "preview-bound confirmation",
- "strict command floor",
- "find` keyword",
- "quoted expression",
- "field syntax",
- )
- for phrase in required_phrases:
- if phrase not in manual:
- problems.append(f"standing manual omits required teaching: {phrase}")
origin_tokens = tuple(item.token for item in ORIGIN_MEANINGS)
if origin_tokens != tuple(item.value for item in Origin):
problems.append("source coverage does not match the authoritative Origin enum")
diff --git a/devtools/verify_backlog_hygiene.py b/devtools/verify_backlog_hygiene.py
deleted file mode 100644
index e9e28e5b98..0000000000
--- a/devtools/verify_backlog_hygiene.py
+++ /dev/null
@@ -1,694 +0,0 @@
-"""Verify Beads backlog structure invariants (`.beads/issues.jsonl`).
-
-Background
-----------
-
-Backlog structure trails filing unless an invariant lint enforces it: the
-2026-07-06 session needed a 41-agent sweep to recover from accumulated drift
-(missing acceptance criteria, dangling dependency refs, unlabeled beads,
-stale "adopted" decisions left open). This is the backlog equivalent of
-`devtools lab policy schema-versioning` / `docs-drift` / `timestamp-doctrine`:
-a mechanical check that fails a gate instead of drift silently accumulating
-until an archaeology session (polylogue-8jg9.1).
-
-Checks over `.beads/issues.jsonl`:
-
- D1 no dangling dependency refs
- D2 no dependency cycles among blocks-edges
- H1 open tech-tree bead has a horizon label (frontier/mid/vision)
- H2 horizon:vision => priority P3/P4 (keeps `bd ready` clean)
- H3 open horizon:frontier bead has acceptance criteria (field or notes sidecar)
- H4 open horizon:frontier bead has design content (field, notes, or description with file paths)
- P1 open P0/P1 bead has acceptance criteria
- E1 epic has members: id-prefix children, dep edges, or bead ids named in its text
- E2 epic has a non-empty description (WHY + member map)
- T1 no ephemeral-path ground truth: /realm/inbox/ or /tmp/ cited outside provenance context
- X1 duplicate open titles (exact, case-folded)
- X2 bead id named in an open bead's text does not exist
- R1 READY bead (open, all blocks-deps closed) at P1/P2 lacking AC — the fast-execution gap
- A1 open non-epic bead has at least one area:* label
- B1 open decision-type bead whose text declares Status: adopted/decided should be closed
- S1 the most recent bd JSONL sync receipt (``.cache/bd-sync-receipts/``,
- written by ``devtools/bd_reimport_guard.py``) is missing required
- fields, fails to parse, or reports a conflicted/unauthorized-downgrade
- row — the portfolio gate's consumption of polylogue-gxjh.1's monotonic
- sync receipts (polylogue-8jg9.1). No receipt on disk is not a
- violation (nothing has synced through the guard yet in this
- checkout); a *present but unclean* receipt is.
- F1 an open bead carrying ``metadata.frontier == "active"`` (an admitted
- active leaf) is itself an epic — epics are not work; the epic should
- instead carry ``metadata.frontier_program == "active"`` and its
- member leaves should be the ones admitted.
- F2 an open active leaf (non-epic; F1 already covers epics) has no
- ``frontier_program_ref``, or the ref is dangling, or the referenced
- bead does not itself carry ``metadata.frontier_program == "active"``
- — the leaf cannot be grouped into a valid program.
- F3 an ``in_progress`` bead has had no recorded activity
- (``updated_at``) within the configurable stale-claim window (default
- 7 days, ``--stale-claim-days``) — a likely abandoned/session-killed
- claim that should be re-verified or released.
- F4 an open bead marked ``metadata.frontier_program == "active"`` has
- zero open active leaves whose ``frontier_program_ref`` points back
- at it — a program admitted with no admitted members ("program
- grouping derives frontier_program=active from its member leaves",
- polylogue-8jg9.1 AC3).
-
-Three-view policy (polylogue-8jg9.1 AC1): *full ambition* is every open bead
-in the export regardless of admission (unaffected by this module — nothing
-here demotes or hides a bead); the *active set* is every open non-epic leaf
-carrying ``metadata.frontier == "active"`` (F1/F2/F4 police its structural
-validity, ``compute_active_set_summary()`` reports its size); *execution
-focus* is the smaller ``status=in_progress`` claim-backed subset (F3 polices
-claim liveness). Active-set *size* is soft operating guidance, never a hard
-cap: ``compute_active_set_summary()`` compares the current active-leaf count
-to a configurable target (default 30) and warn threshold (default 50) and
-returns informational diagnostics only — it is not part of ``Finding``/
-``collect_findings()`` and can never fail the gate, truncate the set, or
-hide a bead. Only F1/F2/F3/F4 structural violations are hard findings.
-
-(8jg9.1's design names five conceptual classes: (a) P0/P1 missing AC = P1;
-(b) decision-type bead stuck past adopted/decided = B1; (c) no area:* label =
-A1; (d) orphan beads with no epic parent — covered by the native `bd orphans`
-command, not duplicated here; (e) a blocks-edge pointing at a closed bead —
-not representable, since bd computes "blocked" live from dependency status
-rather than persisting a blocked flag that could go stale.)
-
-This module supersedes the standalone `.agent/tools/bead-lint.py` script
-(same algorithm, ported so the check runs through the standing `devtools
-verify --lab` gate instead of requiring a manual invocation). The allowlist
-lives at `devtools/data/bead-lint-allow.txt` (format:
-`CHECKbead-idreason` per line; moved from
-`.agent/tools/bead-lint-allow.txt` by polylogue-kapb).
-
-S1 is this module's named consumption of `devtools/bd_reimport_guard.py`'s
-`SyncReceipt` (polylogue-gxjh.1): the sync layer classifies every merged row
-as new/updated/equal/skipped_downgrade/conflicted/recovered_downgrade and
-writes a receipt to `.cache/bd-sync-receipts/`; this gate reads the most
-recent one and refuses to treat a corrupt, incomplete, conflicted, or
-silently-downgraded synchronization as clean, instead of trusting bare `bd`
-command exit status. Per 8jg9.1's division of labor, this module does not
-reimplement merge/conflict resolution — it only consumes the receipt gxjh.1
-already writes.
-
-Wired into ``devtools verify --lab`` alongside the other policy checks, since
-this is a repo-hygiene boundary check rather than a per-edit gate.
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import re
-import subprocess
-import sys
-from collections import defaultdict
-from collections.abc import Callable
-from dataclasses import dataclass
-from datetime import datetime, timezone
-from pathlib import Path
-
-from devtools import repo_root as _get_root
-
-_HORIZONS = {"horizon:frontier", "horizon:mid", "horizon:vision"}
-_EPHEMERAL_RE = re.compile(r"(/realm/inbox/|(? tuple[dict[str, dict[str, object]], list[tuple[str, str, str]]]:
- """Parse the exported jsonl snapshot into an in-memory issue/dep index.
-
- Bounded-enumeration note (polylogue-8jg9.1 remaining scope item 2): this
- reads one already-exported, finite local file (``.beads/issues.jsonl``,
- ~1,100 rows / ~5 MB at present backlog scale) with a single
- ``read_text().splitlines()`` pass, never a live, potentially-unbounded
- `bd list`/`bd ready` query. That distinction matters — the 2026-07-15
- incident recorded on this bead was a read-only `bd list --status open
- --limit 500` process reaching 7.88 GB RSS + 20.3 GB swap against the live
- Dolt-backed `bd` server, not against this exported-file path. Every
- check in this module (including the new F1-F4 active-set/execution-focus
- checks below) is derived from this same bounded, already-materialized
- dict — none of them shell out to `bd` per-issue or re-query a live
- unbounded source. If the exported jsonl itself grows to a size where a
- single-pass in-memory dict is no longer bounded for realistic backlog
- scale, that is the trigger to switch this loader to a streaming/paged
- parse; at ~5 MB for ~1,100 issues it is not currently warranted.
- """
- issues: dict[str, dict[str, object]] = {}
- deps: list[tuple[str, str, str]] = []
- for line in path.read_text().splitlines():
- if not line.strip():
- continue
- d = json.loads(line)
- if d.get("_type") == "issue":
- issues[d["id"]] = d
- for dep in d.get("dependencies") or []:
- deps.append((d["id"], dep.get("depends_on_id"), dep.get("type", "blocks")))
- elif d.get("_type") == "dependency":
- deps.append((d.get("issue_id"), d.get("depends_on_id"), d.get("type", "blocks")))
- return issues, deps
-
-
-def _text_of(d: dict[str, object]) -> str:
- return " ".join(str(d.get(k) or "") for k in ("description", "design", "acceptance_criteria", "notes"))
-
-
-def _has_ac(d: dict[str, object]) -> bool:
- if str(d.get("acceptance_criteria") or "").strip():
- return True
- notes = str(d.get("notes") or "").lower()
- return "acceptance" in notes or "verify:" in notes or "ac:" in notes
-
-
-def _has_design(d: dict[str, object]) -> bool:
- if str(d.get("design") or "").strip():
- return True
- blob = str(d.get("description") or "") + str(d.get("notes") or "")
- # A description that names concrete code surfaces counts as design-bearing.
- return bool(re.search(r"\w+\.py|\w+/\w+\.|::|polylogue/", blob))
-
-
-def _labels_of(d: dict[str, object]) -> set[str]:
- raw = d.get("labels") or []
- return {str(lab) for lab in raw} if isinstance(raw, list) else set()
-
-
-def _priority_of(d: dict[str, object]) -> int:
- prio = d.get("priority", 2)
- return int(prio) if isinstance(prio, int | float | str) and str(prio).lstrip("-").isdigit() else 2
-
-
-def _metadata_of(d: dict[str, object]) -> dict[str, object]:
- raw = d.get("metadata")
- return raw if isinstance(raw, dict) else {}
-
-
-def _is_active_leaf(d: dict[str, object]) -> bool:
- return _metadata_of(d).get("frontier") == "active"
-
-
-def _is_active_program(d: dict[str, object]) -> bool:
- return _metadata_of(d).get("frontier_program") == "active"
-
-
-def _parse_timestamp(value: object) -> datetime | None:
- if not isinstance(value, str) or not value.strip():
- return None
- try:
- return datetime.fromisoformat(value.replace("Z", "+00:00"))
- except ValueError:
- return None
-
-
-def _load_allowlist(allow_path: Path) -> set[tuple[str, str]]:
- allow: set[tuple[str, str]] = set()
- if allow_path.exists():
- for line in allow_path.read_text().splitlines():
- if line.startswith("#"):
- continue
- parts = line.split("\t")
- if len(parts) >= 2:
- allow.add((parts[0], parts[1]))
- return allow
-
-
-def _latest_receipt_path(receipts_dir: Path) -> Path | None:
- if not receipts_dir.is_dir():
- return None
- # Receipt filenames are `<-source>.json` with the
- # created_at token stripped of `:`/`-`, so lexicographic sort of
- # basenames is chronological (see bd_reimport_guard.write_receipt).
- candidates = sorted(p for p in receipts_dir.glob("*.json") if p.is_file())
- return candidates[-1] if candidates else None
-
-
-def _check_sync_receipt(receipts_dir: Path, add: Callable[[str, str, str], None]) -> None:
- """S1: the most recent bd sync receipt, if any, must be clean.
-
- No receipt on disk is not a finding — `.cache/` is disposable local
- state and nothing may have synced through the guard yet in this
- checkout. A *present* receipt that fails to parse, is missing required
- fields, or reports a conflicted/unauthorized-downgrade row is a hard
- finding: it means the last JSONL synchronization was not proven clean,
- and bare command exit status cannot be trusted instead (polylogue-8jg9.1
- consuming polylogue-gxjh.1's SyncReceipt contract).
- """
- latest = _latest_receipt_path(receipts_dir)
- if latest is None:
- return
-
- try:
- payload = json.loads(latest.read_text())
- except (OSError, json.JSONDecodeError) as exc:
- add("S1", "", f"corrupt sync receipt {latest.name}: {exc}")
- return
-
- if not isinstance(payload, dict) or "is_clean" not in payload or "outcomes" not in payload:
- add("S1", "", f"incomplete sync receipt {latest.name}: missing is_clean/outcomes")
- return
-
- outcomes = payload.get("outcomes")
- if not isinstance(outcomes, list):
- add("S1", "", f"incomplete sync receipt {latest.name}: outcomes is not a list")
- return
-
- if payload.get("is_clean") is True:
- return
-
- unclean_rows = [o for o in outcomes if isinstance(o, dict) and o.get("outcome") in _UNCLEAN_OUTCOMES]
- if not unclean_rows:
- # is_clean is False but no row explains why (schema drift on gxjh.1's
- # side, or a payload we don't fully understand) -- still a finding,
- # since a receipt claiming uncleanliness must be actionable, not silent.
- add("S1", "", f"sync receipt {latest.name} reports is_clean=false with no explanatory rows")
- return
-
- for row in unclean_rows:
- bead_id = str(row.get("id") or "")
- kind = row.get("outcome")
- current_rev = row.get("current_revision")
- candidate_rev = row.get("candidate_revision")
- if kind == "conflicted":
- add(
- "S1",
- bead_id,
- f"sync receipt {latest.name}: incomparable/conflicted row "
- f"(current={current_rev!r}, candidate={candidate_rev!r})",
- )
- else: # skipped_downgrade
- add(
- "S1",
- bead_id,
- f"sync receipt {latest.name}: unauthorized downgrade skipped "
- f"(current={current_rev!r}, candidate={candidate_rev!r}) -- "
- "recover explicitly via `bd_reimport_guard.py reconcile --allow-downgrade` "
- "with an actor/reason if this candidate should win",
- )
-
-
-def collect_findings(
- path: Path | None = None,
- allow_path: Path | None = None,
- checks: set[str] | None = None,
- receipts_path: Path | None = None,
- stale_claim_days: int = _DEFAULT_STALE_CLAIM_DAYS,
- now: datetime | None = None,
-) -> list[Finding]:
- """Run all 20 backlog-hygiene checks against a Beads jsonl export.
-
- ``path`` defaults to ``.beads/issues.jsonl`` under the repo root;
- ``allow_path`` defaults to ``devtools/data/bead-lint-allow.txt``;
- ``receipts_path`` (S1) defaults to ``.cache/bd-sync-receipts/`` under the
- repo root. ``stale_claim_days`` (F3) defaults to
- ``_DEFAULT_STALE_CLAIM_DAYS``; ``now`` (F3) defaults to the current UTC
- time and exists so tests can pin a fixed clock instead of the host wall
- clock.
- """
- if now is None:
- now = datetime.now(timezone.utc)
- root = _get_root()
- if path is None:
- path = root / _DEFAULT_ISSUES_RELPATH
- if allow_path is None:
- allow_path = root / _DEFAULT_ALLOWLIST_RELPATH
- if receipts_path is None:
- receipts_path = root / _DEFAULT_RECEIPTS_RELPATH
- allow = _load_allowlist(allow_path)
-
- issues, deps = _load(path)
- open_ids = {i for i, d in issues.items() if d.get("status") in ("open", "in_progress")}
- findings: list[Finding] = []
-
- def add(check: str, bid: str, msg: str) -> None:
- if (checks is None or check in checks) and (check, bid) not in allow:
- findings.append(Finding(check, bid, msg))
-
- _check_sync_receipt(receipts_path, add)
-
- # D1 dangling deps
- for src, dst, typ in deps:
- if dst not in issues:
- add("D1", src, f"dangling dep -> {dst} ({typ})")
-
- # D2 cycles among blocks deps (open issues only)
- graph: dict[str, set[str]] = defaultdict(set)
- for src, dst, typ in deps:
- if typ == "blocks" and src in open_ids and dst in open_ids:
- graph[src].add(dst)
- white, gray, black = 0, 1, 2
- color: dict[str, int] = defaultdict(int)
-
- def dfs(n: str, stack: list[str]) -> None:
- color[n] = gray
- for m in graph[n]:
- if color[m] == gray:
- cyc = stack[stack.index(m) :] + [m] if m in stack else [n, m]
- add("D2", n, "blocks-cycle: " + " -> ".join(cyc))
- elif color[m] == white:
- dfs(m, stack + [m])
- color[n] = black
-
- for n in list(graph):
- if color[n] == white:
- dfs(n, [n])
-
- # F1/F2/F4: active-set (frontier=active) and program-grouping structure.
- # active_leaf_ids are open beads admitted into the active set; epics among
- # them are F1 violations (epics are not work) rather than valid leaves.
- active_leaf_ids = [i for i in open_ids if _is_active_leaf(issues[i])]
- # Reverse index: program id -> admitted non-epic leaves referencing it,
- # used by F4 to check a program's frontier_program=active claim is backed
- # by at least one member (polylogue-8jg9.1 AC3: program grouping is
- # derived from member leaves, not asserted independently of them).
- program_leaves: dict[str, list[str]] = defaultdict(list)
- for i in active_leaf_ids:
- d = issues[i]
- if d.get("issue_type") == "epic":
- add(
- "F1",
- i,
- "epic carries frontier=active as a leaf (epics are not work; mark the epic "
- "frontier_program=active instead and admit its member leaves)",
- )
- continue
- ref = _metadata_of(d).get("frontier_program_ref")
- if not isinstance(ref, str) or not ref:
- add("F2", i, "active leaf has no frontier_program_ref (cannot be grouped into a program)")
- elif ref not in issues:
- add("F2", i, f"active leaf's frontier_program_ref -> {ref} does not exist")
- elif not _is_active_program(issues[ref]):
- add("F2", i, f"active leaf's frontier_program_ref -> {ref} is not itself frontier_program=active")
- else:
- program_leaves[ref].append(i)
-
- for i in open_ids:
- d = issues[i]
- if _is_active_program(d) and not program_leaves.get(i):
- add(
- "F4",
- i,
- "frontier_program=active with no open active leaf referencing it via "
- "frontier_program_ref (stale program admission -- derive frontier_program=active "
- "from member leaves, not the reverse)",
- )
-
- # F3: stale in_progress claims (no recorded updated_at activity within
- # the configured window). Defined purely from bd's own updated_at field
- # -- bd does not persist a separate "last activity" timestamp, and
- # updated_at already advances on every field/status/note mutation.
- for i, d in issues.items():
- if d.get("status") != "in_progress":
- continue
- updated = _parse_timestamp(d.get("updated_at"))
- if updated is None:
- continue
- age_days = (now - updated).total_seconds() / 86400
- if age_days > stale_claim_days:
- add(
- "F3",
- i,
- f"in_progress with no recorded activity for {age_days:.1f}d "
- f"(> {stale_claim_days}d stale-claim threshold) -- re-verify claim liveness or release it",
- )
-
- # Per-issue checks.
- titles: dict[str, list[str]] = defaultdict(list)
- children: dict[str, int] = defaultdict(int)
- for i in issues:
- if "." in i.removeprefix("polylogue-"):
- children[i.rsplit(".", 1)[0]] += 1
- dep_touch: dict[str, int] = defaultdict(int) # epics may group members via dep edges instead of id-prefix
- for src, dst, _typ in deps:
- dep_touch[src] += 1
- dep_touch[dst] += 1
-
- for i, d in issues.items():
- if d.get("status") not in ("open", "in_progress"):
- continue
- labels = _labels_of(d)
- prio = _priority_of(d)
- horizon = labels & _HORIZONS
- titles[str(d.get("title", "")).strip().casefold()].append(i)
-
- if "tech-tree" in labels and not horizon:
- add("H1", i, "tech-tree bead without horizon label")
- if "horizon:vision" in labels and prio < 3:
- add("H2", i, f"vision bead at P{prio} (should be P3/P4)")
- if "horizon:frontier" in labels and not _has_ac(d):
- add("H3", i, "frontier bead without acceptance criteria")
- if "horizon:frontier" in labels and not _has_design(d):
- add("H4", i, "frontier bead without design content")
- if prio <= 1 and d.get("issue_type") != "epic" and not _has_ac(d):
- add("P1", i, f"P{prio} bead without acceptance criteria")
- if d.get("issue_type") != "epic" and not any(lab.startswith("area:") for lab in labels):
- add("A1", i, "open non-epic bead without an area:* label")
- if d.get("issue_type") == "decision" and re.search(r"status:\s*(adopted|decided)", _text_of(d), re.IGNORECASE):
- add("B1", i, "decision bead declares adopted/decided but is still open")
- if d.get("issue_type") == "epic":
- named_members = [r for r in _BEAD_REF_RE.findall(_text_of(d)) if r != i and r in issues]
- if children[i] == 0 and dep_touch[i] == 0 and not named_members:
- add("E1", i, "epic with no members (no children, no dep edges, no named bead ids)")
- if not str(d.get("description") or "").strip():
- add("E2", i, "epic without description")
- blob = _text_of(d)
- for ref in set(_BEAD_REF_RE.findall(blob)):
- token = ref.removeprefix("polylogue-").split(".", 1)[0]
- # id-shaped tokens only: pure-alpha words >=4 chars are English compounds
- # ("polylogue-substrate intake"); pure-numeric are #N-style refs.
- if token.isalpha() and len(token) >= 4:
- continue
- if token.isdigit():
- continue
- # Tolerate .N suffix references to a future child of an existing bead.
- if ref not in issues and ref.rsplit(".", 1)[0] not in issues:
- add("X2", i, f"names nonexistent bead {ref}")
- if _EPHEMERAL_RE.search(blob):
- low = blob.lower()
- if not any(h in low for h in _PROVENANCE_HINTS):
- add("T1", i, "ephemeral path (/realm/inbox or /tmp) cited without provenance framing")
-
- for _t, ids in titles.items():
- if _t and len(ids) > 1:
- for i in ids:
- add("X1", i, f"duplicate open title with {[x for x in ids if x != i]}")
-
- # R1 ready-queue executable check.
- blocked: set[str] = set()
- for src, dst, typ in deps:
- if typ == "blocks" and src in open_ids and dst in open_ids:
- blocked.add(src)
- for i in sorted(open_ids - blocked):
- d = issues[i]
- if _priority_of(d) <= 2 and d.get("issue_type") not in ("epic",) and not _has_ac(d):
- add("R1", i, f"READY P{_priority_of(d)} bead without AC (cold agent cannot execute fast)")
-
- return findings
-
-
-@dataclass(frozen=True, slots=True)
-class ActiveSetSummary:
- """Soft-band size report over the active set (polylogue-8jg9.1 AC1).
-
- Never a `Finding`: exceeding ``target``/``warn`` is informational
- guidance, not a structural violation, a truncation, or a gate failure.
- """
-
- active_leaf_count: int
- target: int
- warn: int
- band: str
- programs: dict[str, int]
- diagnostics: list[str]
-
- def to_dict(self) -> dict[str, object]:
- return {
- "active_leaf_count": self.active_leaf_count,
- "target": self.target,
- "warn": self.warn,
- "band": self.band,
- "programs": self.programs,
- "diagnostics": self.diagnostics,
- }
-
-
-def compute_active_set_summary(
- path: Path | None = None,
- *,
- target: int = _DEFAULT_ACTIVE_TARGET,
- warn: int = _DEFAULT_ACTIVE_WARN,
-) -> ActiveSetSummary:
- """Report active-set size against soft target/warn bands.
-
- Reads the same bounded, already-exported jsonl as `collect_findings`
- (see `_load`'s bounded-enumeration note) -- no additional `bd` query.
- Non-epic open leaves only (epics-as-leaves are F1 findings, not counted
- here as legitimate active work).
- """
- root = _get_root()
- if path is None:
- path = root / _DEFAULT_ISSUES_RELPATH
- issues, _deps = _load(path)
- open_ids = {i for i, d in issues.items() if d.get("status") in ("open", "in_progress")}
- active_leaf_ids = [i for i in open_ids if _is_active_leaf(issues[i]) and issues[i].get("issue_type") != "epic"]
-
- programs: dict[str, int] = defaultdict(int)
- for i in active_leaf_ids:
- ref = _metadata_of(issues[i]).get("frontier_program_ref")
- programs[str(ref)] += 1
-
- count = len(active_leaf_ids)
- diagnostics: list[str] = []
- if count > warn:
- band = "above-warn"
- diagnostics.append(
- f"{count} active leaves exceeds the soft warn threshold of {warn}. This is a diagnostic, "
- "not a failure -- review whether the growth is explained (a new program admitted, a "
- "reconciliation sweep) or is unexplained backlog drift worth pruning."
- )
- elif count > target:
- band = "above-target"
- diagnostics.append(
- f"{count} active leaves exceeds the soft target of {target}. Informational only; no action "
- f"required unless growth continues unexplained toward the warn threshold of {warn}."
- )
- else:
- band = "within-target"
- return ActiveSetSummary(
- active_leaf_count=count, target=target, warn=warn, band=band, programs=dict(programs), diagnostics=diagnostics
- )
-
-
-def _format_report(findings: list[Finding], *, issues_scanned: int) -> str:
- if not findings:
- return f"backlog hygiene: zero unhandled findings across {issues_scanned} issues scanned."
- by: dict[str, list[Finding]] = defaultdict(list)
- for f in findings:
- by[f.check].append(f)
- lines: list[str] = []
- for check in sorted(by):
- lines.append(f"[{check}] {len(by[check])} finding(s)")
- for f in by[check]:
- lines.append(f" {f.bead_id}: {f.message}")
- lines.append(f"\n{len(findings)} finding(s) across {len(by)} check(s); {issues_scanned} issues scanned.")
- return "\n".join(lines)
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- )
- parser.add_argument("--json", action="store_true", help="emit machine-readable JSON")
- parser.add_argument(
- "--checks",
- type=lambda value: {item.strip() for item in value.split(",") if item.strip()},
- default=None,
- help="run only the named comma-separated checks (for example D1,D2)",
- )
- parser.add_argument(
- "--fresh",
- action="store_true",
- help="run `bd export -o ` first (bd updates do not immediately re-export the jsonl)",
- )
- parser.add_argument(
- "--stale-claim-days",
- type=int,
- default=_DEFAULT_STALE_CLAIM_DAYS,
- help=f"F3 stale-claim window in days (default {_DEFAULT_STALE_CLAIM_DAYS})",
- )
- parser.add_argument(
- "--active-target",
- type=int,
- default=_DEFAULT_ACTIVE_TARGET,
- help=f"active-set soft target leaf count, informational only (default {_DEFAULT_ACTIVE_TARGET})",
- )
- parser.add_argument(
- "--active-warn",
- type=int,
- default=_DEFAULT_ACTIVE_WARN,
- help=f"active-set soft warn leaf count, informational only (default {_DEFAULT_ACTIVE_WARN})",
- )
- parser.add_argument(
- "path",
- nargs="?",
- default=None,
- help="path to issues.jsonl (default: .beads/issues.jsonl under the repo root)",
- )
- args = parser.parse_args(argv)
-
- root = _get_root()
- path = Path(args.path) if args.path else root / _DEFAULT_ISSUES_RELPATH
-
- if args.fresh:
- subprocess.run(["bd", "export", "-o", str(path)], check=True, capture_output=True)
-
- if not path.exists():
- message = f"backlog hygiene: {path} does not exist (no Beads workspace to check)."
- if args.json:
- print(json.dumps({"ok": True, "findings": [], "issues_scanned": 0, "skipped": message}, indent=2))
- else:
- print(message)
- return 0
-
- findings = collect_findings(
- path=path,
- allow_path=root / _DEFAULT_ALLOWLIST_RELPATH,
- checks=args.checks,
- stale_claim_days=args.stale_claim_days,
- )
- issues_scanned = len(_load(path)[0])
- active_set = compute_active_set_summary(path=path, target=args.active_target, warn=args.active_warn)
-
- if args.json:
- payload = {
- "ok": not findings,
- "issues_scanned": issues_scanned,
- "findings": [{"check": f.check, "id": f.bead_id, "msg": f.message} for f in findings],
- "active_set": active_set.to_dict(),
- }
- print(json.dumps(payload, indent=2))
- else:
- print(_format_report(findings, issues_scanned=issues_scanned))
- print(
- f"\nactive set: {active_set.active_leaf_count} leaf/leaves "
- f"(target~{active_set.target}, warn~{active_set.warn}, band={active_set.band}) "
- f"across {len(active_set.programs)} program(s)"
- )
- for diag in active_set.diagnostics:
- print(f" note: {diag}")
-
- return 1 if findings else 0
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/verify_bead_graph.py b/devtools/verify_bead_graph.py
index 6c949ceccc..db2db577d2 100644
--- a/devtools/verify_bead_graph.py
+++ b/devtools/verify_bead_graph.py
@@ -1,14 +1,9 @@
-"""Bead-graph invariant lint and full missing-AC census.
+"""Validate structural integrity of the Beads dependency graph.
-Run before shipping Beads state. The command reads live structured ``bd``
-state through ``bd dep cycles`` and unbounded ``bd list --all --json``. It
-never treats prose fields, titles, or labels as acceptance criteria.
-
-Besides dependency-cycle and wave checks, the report validates that each
-Bead has zero or one canonical parent derived solely from ``parent-child``
-dependency records. The JSON output is deliberately complete and stable so
-the coordinator can batch the real missing-AC population without weakening
-the fail-closed lint.
+The gate inspects typed dependency records: endpoint existence, duplicate
+edges, parent cardinality, and cycles. It deliberately does not interpret
+titles, labels, descriptions, acceptance prose, campaign snapshots, or a
+hard-coded list of project-specific edges.
"""
from __future__ import annotations
@@ -22,11 +17,6 @@
from pathlib import Path
from typing import Any
-from devtools import beads_acceptance_contracts
-from devtools.beads_acceptance_contracts import validate as validate_acceptance_contract
-
-_CONTRACT_MANIFEST = Path(__file__).parents[1] / "docs" / "plans" / "beads-acceptance-contracts-2026-08-07.txt"
-
@dataclass(frozen=True, slots=True)
class Finding:
@@ -35,50 +25,22 @@ class Finding:
detail: str
-@dataclass(frozen=True, slots=True)
-class RequiredBlockingEdge:
- """One non-negotiable ``blocks`` relation in the reindex proof graph."""
-
- dependent_id: str
- blocker_id: str
-
-
-# These are the twelve live-proof records whose implementation/acceptance
-# blockers must remain explicit in the current graph. Keep this as structured
-# policy rather than deriving ordering from issue text or close reasons.
-REINDEX_REQUIRED_LIVE_PROOF_BLOCKING_EDGES: tuple[RequiredBlockingEdge, ...] = (
- RequiredBlockingEdge("polylogue-active-leaf-live-proof", "polylogue-2hwl"),
- RequiredBlockingEdge("polylogue-hook-authority-conflict-proof", "polylogue-foee"),
- RequiredBlockingEdge("polylogue-chatgpt-content-live-proof", "polylogue-xofj"),
- RequiredBlockingEdge("polylogue-excluded-cursor-live-proof", "polylogue-ix5r"),
- RequiredBlockingEdge("polylogue-byte-supersession-live-proof", "polylogue-6753s"),
- RequiredBlockingEdge("polylogue-hook-reconciliation-apply-proof", "polylogue-nhbvf"),
- RequiredBlockingEdge("polylogue-raw-dedupe-apply-proof", "polylogue-zm4w8"),
- RequiredBlockingEdge("polylogue-claude-streaming-live-proof", "polylogue-4987i"),
- RequiredBlockingEdge("polylogue-claude-vintage-live-proof", "polylogue-0qfy"),
- RequiredBlockingEdge("polylogue-codex-804-live-proof", "polylogue-27522"),
- RequiredBlockingEdge("polylogue-topology-live-proof", "polylogue-4ts.10"),
- RequiredBlockingEdge("polylogue-stalled-cursor-live-proof", "polylogue-2qrx"),
-)
-
-# The edge guard is consumed by both phase boundaries. This binds the static
-# policy to the actual readiness graph without turning it into a live receipt.
-REINDEX_PROOF_EDGE_GUARD_PHASE_BINDINGS: tuple[RequiredBlockingEdge, ...] = (
- RequiredBlockingEdge("polylogue-reindex-preflight-authorization", "polylogue-eqq02"),
- RequiredBlockingEdge("polylogue-reindex-final-proof", "polylogue-eqq02"),
-)
-
-
-def _wave(issue: dict[str, Any]) -> tuple[int | None, Finding | None]:
- """Parse the issue's ``wave:`` label."""
- for label in issue.get("labels") or []:
- if isinstance(label, str) and label.startswith("wave:"):
- raw = label[len("wave:") :]
- try:
- return int(raw), None
- except ValueError:
- return None, Finding("malformed-wave", str(issue["id"]), f"non-numeric wave label: {label!r}")
- return None, None
+def _validated_issues(payload: object, *, source: str) -> list[dict[str, Any]]:
+ if not isinstance(payload, list):
+ raise RuntimeError(f"{source} returned {type(payload).__name__}, expected list")
+ issues: list[dict[str, Any]] = []
+ seen: set[str] = set()
+ for index, issue in enumerate(payload):
+ if not isinstance(issue, dict):
+ raise RuntimeError(f"{source} record {index} is {type(issue).__name__}, expected object")
+ bead_id = issue.get("id")
+ if not isinstance(bead_id, str) or not bead_id:
+ raise RuntimeError(f"{source} record {index} has no non-empty string id")
+ if bead_id in seen:
+ raise RuntimeError(f"{source} contains duplicate issue id {bead_id!r}")
+ seen.add(bead_id)
+ issues.append(issue)
+ return issues
def _run_bd_dep_cycles() -> tuple[bool, str]:
@@ -88,413 +50,179 @@ def _run_bd_dep_cycles() -> tuple[bool, str]:
def _run_bd_list_all() -> list[dict[str, Any]]:
- """Load the complete live population; ``-n 0`` is never a display page."""
result = subprocess.run(
["bd", "list", "--all", "-n", "0", "--json"],
capture_output=True,
text=True,
check=True,
)
- payload = json.loads(result.stdout)
- if not isinstance(payload, list):
- raise RuntimeError(f"bd list returned {type(payload).__name__}, expected list")
- issues: list[dict[str, Any]] = []
- for index, issue in enumerate(payload):
- if not isinstance(issue, dict):
- raise RuntimeError(
- f"bd list record {index} is {type(issue).__name__}, expected object with non-empty string id"
- )
- bead_id = issue.get("id")
- if not isinstance(bead_id, str) or not bead_id:
- raise RuntimeError(f"bd list record {index} has no non-empty string id")
- issues.append(issue)
- return issues
+ return _validated_issues(json.loads(result.stdout), source="bd list")
-def _metadata(issue: dict[str, Any]) -> dict[str, Any]:
- value = issue.get("metadata")
- if isinstance(value, dict):
- return value
- if isinstance(value, str):
+def _load_export(path: Path) -> list[dict[str, Any]]:
+ records: list[object] = []
+ for line_number, line in enumerate(path.read_text(encoding="utf-8").splitlines(), start=1):
+ if not line.strip():
+ continue
try:
- decoded = json.loads(value)
- except json.JSONDecodeError:
- return {}
- return decoded if isinstance(decoded, dict) else {}
- return {}
+ records.append(json.loads(line))
+ except json.JSONDecodeError as exc:
+ raise RuntimeError(f"{path}:{line_number}: invalid JSON: {exc.msg}") from exc
+ return _validated_issues(records, source=str(path))
-def _labels(issue: dict[str, Any]) -> list[str]:
- value = issue.get("labels")
- return sorted(label for label in value if isinstance(label, str)) if isinstance(value, list) else []
-
-
-def _priority(issue: dict[str, Any]) -> int:
- value = issue.get("priority", 2)
- try:
- return int(value)
- except (TypeError, ValueError):
- return 2
+def _dependency_records(issue: dict[str, Any]) -> list[dict[str, Any]]:
+ dependencies = issue.get("dependencies")
+ return (
+ [dependency for dependency in dependencies if isinstance(dependency, dict)]
+ if isinstance(dependencies, list)
+ else []
+ )
def _parent_targets(issue: dict[str, Any]) -> list[str]:
- targets: list[str] = []
- dependencies = issue.get("dependencies")
- if not isinstance(dependencies, list):
- return targets
- for dependency in dependencies:
- if not isinstance(dependency, dict) or dependency.get("type") != "parent-child":
- continue
- target = dependency.get("depends_on_id")
- if isinstance(target, str) and target:
- targets.append(target)
- return targets
+ return [
+ target
+ for dependency in _dependency_records(issue)
+ if dependency.get("type") == "parent-child"
+ and isinstance((target := dependency.get("depends_on_id")), str)
+ and target
+ ]
def canonical_parent_map(issues: list[dict[str, Any]]) -> dict[str, str | None]:
- """Return the structured canonical parent for every known issue.
-
- A zero-parent issue maps to ``None``. Multiple parent-child targets are
- intentionally represented as ``None`` because there is no canonical
- choice until the graph validator reports and an operator repairs it.
- """
parents: dict[str, str | None] = {}
for issue in issues:
- bead_id = str(issue.get("id", ""))
targets = _parent_targets(issue)
- parents[bead_id] = targets[0] if len(targets) == 1 else None
+ parents[str(issue["id"])] = targets[0] if len(targets) == 1 else None
return parents
-def _parent_findings(issues: list[dict[str, Any]]) -> list[Finding]:
- """Validate structured parent-child edges, independent of Bead prose."""
- by_id = {str(issue["id"]): issue for issue in issues if isinstance(issue.get("id"), str)}
+def _cycle_findings(edges: dict[str, set[str]], *, kind: str, label: str) -> list[Finding]:
findings: list[Finding] = []
- canonical: dict[str, str] = {}
- for bead_id, issue in sorted(by_id.items()):
- for dependency in issue.get("dependencies", []) if isinstance(issue.get("dependencies"), list) else []:
- if not isinstance(dependency, dict) or dependency.get("type") != "parent-child":
- continue
- target = dependency.get("depends_on_id")
- if not isinstance(target, str) or not target:
- findings.append(Finding("malformed-parent", bead_id, f"invalid parent-child target: {target!r}"))
- targets = _parent_targets(issue)
- if len(targets) > 1:
- findings.append(Finding("multiple-parents", bead_id, f"parent-child targets={sorted(targets)}"))
- continue
- if not targets:
- continue
- parent_id = next(iter(targets))
- if parent_id not in by_id:
- findings.append(Finding("missing-parent", bead_id, f"parent-child target {parent_id!r} does not exist"))
- continue
- if parent_id == bead_id:
- findings.append(Finding("parent-self-cycle", bead_id, "parent-child target is the child itself"))
- continue
- canonical[bead_id] = parent_id
-
- visited: set[str] = set()
- for start in sorted(canonical):
- if start in visited:
- continue
- path: list[str] = []
- index: dict[str, int] = {}
- node = start
- while node in canonical and node not in visited:
- if node in index:
- cycle = path[index[node] :] + [node]
- findings.append(Finding("parent-cycle", node, "parent-child cycle: " + " -> ".join(cycle)))
- break
- index[node] = len(path)
- path.append(node)
- node = canonical[node]
- visited.update(path)
+ state: dict[str, int] = {}
+ path: list[str] = []
+ positions: dict[str, int] = {}
+ reported: set[frozenset[str]] = set()
+
+ def visit(node: str) -> None:
+ state[node] = 1
+ positions[node] = len(path)
+ path.append(node)
+ for target in sorted(edges.get(node, set())):
+ if state.get(target, 0) == 0:
+ visit(target)
+ elif state.get(target) == 1:
+ cycle = path[positions[target] :] + [target]
+ identity = frozenset(cycle)
+ if identity not in reported:
+ findings.append(Finding(kind, target, f"{label}: " + " -> ".join(cycle)))
+ reported.add(identity)
+ path.pop()
+ positions.pop(node)
+ state[node] = 2
+
+ for start in sorted(edges):
+ if state.get(start, 0) == 0:
+ visit(start)
return findings
-def _blocks_targets(issue: dict[str, Any]) -> set[str]:
- """Return the structured blockers declared by one Bead record."""
- dependencies = issue.get("dependencies")
- if not isinstance(dependencies, list):
- return set()
- return {
- target
- for dependency in dependencies
- if isinstance(dependency, dict)
- and dependency.get("type") == "blocks"
- and isinstance((target := dependency.get("depends_on_id")), str)
- and target
- }
-
-
-def _required_blocking_edge_findings(
- issues: list[dict[str, Any]],
- *,
- required_edges: tuple[RequiredBlockingEdge, ...],
- kind: str,
-) -> list[Finding]:
- """Report missing structured edges without accepting another edge kind."""
- by_id = {str(issue["id"]): issue for issue in issues if isinstance(issue.get("id"), str)}
+def collect_findings(issues: list[dict[str, Any]]) -> list[Finding]:
+ by_id = {str(issue["id"]): issue for issue in issues}
findings: list[Finding] = []
- for edge in required_edges:
- dependent = by_id.get(edge.dependent_id)
- blocker = by_id.get(edge.blocker_id)
- detail = f"required blocks dependency: {edge.dependent_id} -> {edge.blocker_id}"
- if dependent is None and blocker is None:
- findings.append(Finding(kind, edge.dependent_id, f"missing dependent and blocker; {detail}"))
- elif dependent is None:
- findings.append(Finding(kind, edge.dependent_id, f"missing dependent; {detail}"))
- elif blocker is None:
- findings.append(Finding(kind, edge.blocker_id, f"missing blocker; {detail}"))
- elif edge.blocker_id not in _blocks_targets(dependent):
- findings.append(Finding(kind, edge.dependent_id, f"missing {detail}"))
- return findings
-
-
-def reindex_proof_edge_findings(issues: list[dict[str, Any]]) -> list[Finding]:
- """Validate required reindex live-proof ownership and phase bindings."""
- return [
- *_required_blocking_edge_findings(
- issues,
- required_edges=REINDEX_REQUIRED_LIVE_PROOF_BLOCKING_EDGES,
- kind="missing-required-reindex-proof-edge",
- ),
- *_required_blocking_edge_findings(
- issues,
- required_edges=REINDEX_PROOF_EDGE_GUARD_PHASE_BINDINGS,
- kind="missing-reindex-proof-edge-guard-binding",
- ),
- ]
-
-
-def collect_findings(
- issues: list[dict[str, Any]],
- *,
- required_contract_ids: frozenset[str] | None = None,
- enforce_reindex: bool = False,
-) -> list[Finding]:
- by_id = {str(issue["id"]): issue for issue in issues if isinstance(issue.get("id"), str)}
- findings: list[Finding] = [*_parent_findings(issues)]
- if enforce_reindex:
- findings.extend(reindex_proof_edge_findings(issues))
-
- for issue_id in sorted(required_contract_ids or ()):
- issue = by_id.get(issue_id)
- if issue is None:
- findings.append(Finding("missing-required-acceptance-contract", issue_id, "manifest Bead is absent"))
- elif "acceptance_contract_v1" not in _metadata(issue):
- findings.append(
- Finding("missing-required-acceptance-contract", issue_id, "manifest Bead has no structured contract")
- )
-
- for issue_id, issue in sorted(by_id.items()):
- if "acceptance_contract_v1" not in _metadata(issue):
- continue
- for error in validate_acceptance_contract(issue):
- findings.append(Finding("invalid-acceptance-contract", issue_id, error))
-
- waves: dict[str, int | None] = {}
- for issue_id, issue in sorted(by_id.items()):
- if issue.get("status") == "closed":
- continue
- wave_value, malformed = _wave(issue)
- waves[issue_id] = wave_value
- if malformed is not None:
- findings.append(malformed)
+ parent_edges: dict[str, set[str]] = {}
+ block_edges: dict[str, set[str]] = defaultdict(set)
- for issue_id, issue in sorted(by_id.items()):
- if issue.get("status") == "closed":
+ for bead_id, issue in sorted(by_id.items()):
+ raw_dependencies = issue.get("dependencies")
+ if raw_dependencies is not None and not isinstance(raw_dependencies, list):
+ findings.append(Finding("malformed-dependencies", bead_id, "dependencies must be a list"))
continue
- wave_labels = [label for label in _labels(issue) if label.startswith("wave:")]
- if len(wave_labels) > 1:
- findings.append(Finding("duplicate-wave", issue_id, f"labels={wave_labels}"))
- acceptance_criteria = issue.get("acceptance_criteria")
- if not isinstance(acceptance_criteria, str) or not acceptance_criteria.strip():
- detail = (
- str(issue.get("title", ""))[:60]
- if isinstance(acceptance_criteria, str)
- else "acceptance_criteria must be a non-empty string"
- )
- findings.append(Finding("missing-ac", issue_id, detail))
- wave_value = waves.get(issue_id)
- dependencies = issue.get("dependencies")
- for dependency in dependencies if isinstance(dependencies, list) else []:
- if not isinstance(dependency, dict) or dependency.get("type") != "blocks":
+ seen_edges: set[tuple[str, str]] = set()
+ parents: list[str] = []
+ for index, dependency in enumerate(raw_dependencies or []):
+ if not isinstance(dependency, dict):
+ findings.append(Finding("malformed-dependency", bead_id, f"dependency {index} is not an object"))
continue
- blocker_id = dependency.get("depends_on_id")
- blocker = by_id.get(str(blocker_id))
- if blocker is None or blocker.get("status") == "closed":
+ dep_type = dependency.get("type")
+ target = dependency.get("depends_on_id")
+ if not isinstance(dep_type, str) or not dep_type or not isinstance(target, str) or not target:
+ findings.append(Finding("malformed-dependency", bead_id, f"dependency {index} lacks type or target"))
continue
- blocker_wave = waves.get(str(blocker_id))
- if wave_value is not None and blocker_wave is not None and blocker_wave > wave_value:
+ edge = (dep_type, target)
+ if edge in seen_edges:
+ findings.append(Finding("duplicate-dependency", bead_id, f"duplicate {dep_type} edge to {target}"))
+ seen_edges.add(edge)
+ if target not in by_id:
findings.append(
- Finding("wave-inversion", issue_id, f"(wave:{wave_value}) <- {blocker_id} (wave:{blocker_wave})")
+ Finding("missing-dependency-target", bead_id, f"{dep_type} target {target!r} does not exist")
)
+ if target == bead_id:
+ findings.append(Finding("self-dependency", bead_id, f"{dep_type} edge targets itself"))
+ if dep_type == "parent-child":
+ parents.append(target)
+ elif dep_type == "blocks":
+ block_edges[bead_id].add(target)
+ if len(parents) > 1:
+ findings.append(Finding("multiple-parents", bead_id, f"parent-child targets={sorted(parents)}"))
+ elif parents:
+ parent_edges[bead_id] = {parents[0]}
+
+ findings.extend(_cycle_findings(parent_edges, kind="parent-cycle", label="parent-child cycle"))
+ findings.extend(_cycle_findings(block_edges, kind="blocks-cycle", label="blocks cycle"))
return sorted(findings, key=lambda finding: (finding.kind, finding.bead_id, finding.detail))
-def _campaigns(issue: dict[str, Any]) -> list[str]:
- """Read campaign declarations from structured metadata or labels only."""
- values: set[str] = set()
- metadata_campaign = _metadata(issue).get("campaign")
- if isinstance(metadata_campaign, str) and metadata_campaign:
- values.add(metadata_campaign)
- elif isinstance(metadata_campaign, list):
- values.update(value for value in metadata_campaign if isinstance(value, str) and value)
- values.update(label.removeprefix("campaign:") for label in _labels(issue) if label.startswith("campaign:"))
- if "campaign" in _labels(issue):
- values.add(str(issue.get("id", "")))
- return sorted(values)
-
-
-def _partition(items: list[dict[str, Any]], key: str) -> dict[str, dict[str, Any]]:
- groups: dict[str, list[str]] = defaultdict(list)
- for item in items:
- groups[str(item[key])].append(str(item["id"]))
- return {name: {"count": len(ids), "ids": sorted(ids)} for name, ids in sorted(groups.items())}
-
-
-def missing_ac_census(
- issues: list[dict[str, Any]], *, required_contract_ids: frozenset[str] | None = None
-) -> dict[str, Any]:
- """Produce a complete, deterministic census of fail-closed missing ACs."""
- parents = canonical_parent_map(issues)
- missing_ids = {
- finding.bead_id
- for finding in collect_findings(issues, required_contract_ids=required_contract_ids)
- if finding.kind == "missing-ac"
- }
- rows: list[dict[str, Any]] = []
- for issue in issues:
- bead_id = str(issue.get("id", ""))
- if bead_id not in missing_ids:
- continue
- program = _metadata(issue).get("frontier_program_ref")
- program_or_parent = (
- str(program) if isinstance(program, str) and program else parents.get(bead_id) or "unparented"
- )
- campaigns = _campaigns(issue)
- rows.append(
- {
- "id": bead_id,
- "status": str(issue.get("status", "unknown")),
- "priority": _priority(issue),
- "program_or_parent": program_or_parent,
- "campaign_relevance": "declared" if campaigns else "none",
- "campaigns": campaigns,
- }
- )
- rows.sort(key=lambda row: (row["status"], row["priority"], row["program_or_parent"], row["id"]))
- return {
- "report_version": 1,
- "total": len(rows),
- "by_status": _partition(rows, "status"),
- "by_priority": _partition(rows, "priority"),
- "by_program_or_parent": _partition(rows, "program_or_parent"),
- "by_campaign_relevance": _partition(rows, "campaign_relevance"),
- "items": rows,
- }
-
-
-def build_report(
- issues: list[dict[str, Any]],
- *,
- cycles_ok: bool,
- cycles_output: str,
- required_contract_ids: frozenset[str] | None = None,
- enforce_reindex: bool = False,
-) -> dict[str, Any]:
- findings = collect_findings(
- issues,
- required_contract_ids=required_contract_ids,
- enforce_reindex=enforce_reindex,
- )
- by_kind: dict[str, int] = defaultdict(int)
+def build_report(issues: list[dict[str, Any]], *, cycles_ok: bool, cycles_output: str) -> dict[str, Any]:
+ findings = collect_findings(issues)
+ structured_cycles_ok = not any(finding.kind in {"parent-cycle", "blocks-cycle"} for finding in findings)
+ counts: dict[str, int] = defaultdict(int)
for finding in findings:
- by_kind[finding.kind] += 1
+ counts[finding.kind] += 1
return {
- "report_version": 1,
- "cycles": {"ok": cycles_ok, "output": cycles_output},
+ "report_version": 2,
+ "cycles": {"ok": cycles_ok and structured_cycles_ok, "output": cycles_output},
"issues_scanned": len(issues),
- "contract_manifest": {
- "expected_count": beads_acceptance_contracts._EXPECTED_MANIFEST_COUNT,
- "digest": beads_acceptance_contracts._EXPECTED_MANIFEST_DIGEST,
- },
"findings": [{"kind": f.kind, "id": f.bead_id, "detail": f.detail} for f in findings],
- "counts": dict(sorted(by_kind.items())),
- "missing_ac_census": missing_ac_census(issues, required_contract_ids=required_contract_ids),
+ "counts": dict(sorted(counts.items())),
}
def _format_report(report: dict[str, Any]) -> str:
- lines: list[str] = []
- cycle_output = report["cycles"]["output"]
- if cycle_output:
- lines.append(str(cycle_output))
- for finding in report["findings"]:
- lines.append(f"{finding['kind']}: {finding['id']} {finding['detail']}")
- counts = report["counts"]
- lines.append(
- "violations: "
- f"dup_labels={counts.get('duplicate-wave', 0)} "
- f"inversions={counts.get('wave-inversion', 0)} "
- f"missing_ac={counts.get('missing-ac', 0)} "
- f"invalid_contracts={counts.get('invalid-acceptance-contract', 0)} "
- f"missing_required_contracts={counts.get('missing-required-acceptance-contract', 0)} "
- f"malformed_wave={counts.get('malformed-wave', 0)} "
- f"parent_integrity={sum(value for key, value in counts.items() if key.startswith('parent-') or key in {'multiple-parents', 'missing-parent'})}"
- )
+ lines = [str(report["cycles"]["output"])] if report["cycles"]["output"] else []
+ lines.extend(f"{item['kind']}: {item['id']} {item['detail']}" for item in report["findings"])
+ lines.append(f"bead-graph: {report['issues_scanned']} issues, {len(report['findings'])} structural violations")
return "\n".join(lines)
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--json", action="store_true", help="emit the complete machine-readable graph report")
+ parser.add_argument("--json", action="store_true", help="emit a machine-readable structural report")
+ parser.add_argument(
+ "--export", type=Path, help="validate a JSONL export without touching the shared live Beads database"
+ )
args = parser.parse_args(argv)
try:
- required_contract_ids = frozenset(beads_acceptance_contracts.load_manifest(_CONTRACT_MANIFEST))
- cycles_ok, cycles_output = _run_bd_dep_cycles()
- if not cycles_ok:
- if args.json:
- print(
- json.dumps(
- {
- "report_version": 1,
- "error": "dependency cycle check failed",
- "cycles_output": cycles_output,
- },
- indent=2,
- sort_keys=True,
- )
- )
- else:
- print(f"bead-graph: dependency cycle check failed: {cycles_output}", file=sys.stderr)
- return 1
- issues = _run_bd_list_all()
- except SystemExit as exc:
- if args.json:
- print(json.dumps({"report_version": 1, "error": str(exc)}, indent=2, sort_keys=True))
+ if args.export is not None:
+ issues = _load_export(args.export)
+ cycles_ok, cycles_output = True, ""
else:
- print(f"bead-graph: {exc}", file=sys.stderr)
- return 1
+ cycles_ok, cycles_output = _run_bd_dep_cycles()
+ if not cycles_ok:
+ raise RuntimeError(f"dependency cycle check failed: {cycles_output}")
+ issues = _run_bd_list_all()
+ report = build_report(issues, cycles_ok=cycles_ok, cycles_output=cycles_output)
except (OSError, subprocess.CalledProcessError, RuntimeError, json.JSONDecodeError) as exc:
+ payload = {"report_version": 2, "error": str(exc)}
if args.json:
- print(json.dumps({"report_version": 1, "error": str(exc)}, indent=2, sort_keys=True))
+ print(json.dumps(payload, indent=2, sort_keys=True))
else:
- print(f"bead-graph: failed to load live Beads state: {exc}", file=sys.stderr)
+ print(f"bead-graph: {exc}", file=sys.stderr)
return 1
- report = build_report(
- issues,
- cycles_ok=cycles_ok,
- cycles_output=cycles_output,
- required_contract_ids=required_contract_ids,
- enforce_reindex=True,
- )
- if args.json:
- print(json.dumps(report, indent=2, sort_keys=True))
- else:
- print(_format_report(report))
+
+ print(json.dumps(report, indent=2, sort_keys=True) if args.json else _format_report(report))
return 0 if not report["findings"] else 1
diff --git a/devtools/verify_campaign_archive_boundaries.py b/devtools/verify_campaign_archive_boundaries.py
deleted file mode 100644
index 9219c65d66..0000000000
--- a/devtools/verify_campaign_archive_boundaries.py
+++ /dev/null
@@ -1,247 +0,0 @@
-"""Verify devtools synthetic benchmark/scale campaigns route through ArchiveLocation.
-
-Background
-----------
-
-The canonical "phantom benchmark.db" regression (polylogue-ovme,
-polylogue-ovme.3): campaign constructors generated a real synthetic
-archive under an output directory, then handed a root-shaped or
-filename-shaped sentinel path (``archive_dir / "benchmark.db"``) to
-benchmark runners instead of the archive's real, ArchiveLocation-resolved
-active ``index.db``. Some consumers (``SQLiteBackend``) canonicalize a
-non-``index.db`` filename before opening it; others
-(``polylogue.storage.sqlite.connection.open_connection``) do not -- so the
-same sentinel silently produced two divergent SQLite files, and some
-benchmark runners quietly measured the empty phantom instead of the real
-generated archive.
-
-This lint is a narrow, devtools-campaign-scoped completeness check that
-catches a regression of that exact shape recurring in the campaign entry
-points this bead fixed. It is intentionally **not** a repo-wide boundary
-audit over storage/diagnostics/daemon/maintenance/transitions -- that
-broader sweep is polylogue-ovme.2's migration surface (storage, status,
-maintenance, b5l transitions) and building it here, before that migration
-lands, would either produce false positives against not-yet-migrated
-production code or require editing files ovme.2 owns concurrently. See
-``docs/internals.md`` / the ovme epic notes for the full boundary-audit
-scope; this lint covers only the devtools campaign slice of it.
-
-What this lint checks
-----------------------
-
-1. None of the campaign entry-point modules may contain the literal
- ``"benchmark.db"`` sentinel string anywhere in source (the concrete
- filename of the historical bug). Reintroducing it in these files is
- almost certainly the same regression recurring.
-2. None of the campaign entry-point modules may construct a sibling tier
- path via ad hoc ``Path`` arithmetic (`` / "index.db"``,
- `` / "source.db"``, etc.) -- tier-path derivation belongs solely
- to :class:`polylogue.storage.archive_identity.ArchiveLocation`'s
- resolver; a campaign module deriving one directly is the same class of
- ambiguous-path bug with a different filename.
-3. The known campaign entry points (``generate_archive``,
- ``run_full_campaign``, ``devtools.run_campaign._run``) must each
- reference ``CampaignArchiveLocation`` somewhere in their module -- a
- purely negative "no bad string" scan can be defeated by simply deleting
- the ownership plumbing while leaving no forbidden string behind, so this
- positive check is required too.
-
-Wired into ``devtools verify --lab`` (a lab/architectural policy concern,
-not a per-edit gate).
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import re
-import sys
-from dataclasses import dataclass
-from pathlib import Path
-
-from devtools import repo_root as _get_root
-
-ROOT = _get_root()
-
-# Campaign entry-point modules this lint owns. Intentionally narrow --
-# see the module docstring for why this does not cover storage/diagnostics/
-# daemon/maintenance/transitions (polylogue-ovme.2's surface).
-CAMPAIGN_MODULES: tuple[Path, ...] = (
- ROOT / "devtools" / "large_archive_generator.py",
- ROOT / "devtools" / "benchmark_campaigns.py",
- ROOT / "devtools" / "run_campaign.py",
- ROOT / "devtools" / "synthetic_benchmark_runtime.py",
-)
-
-# Modules exempted from the sibling-derivation/sentinel scan because they
-# themselves ARE the sanctioned resolver, or are the ownership wrapper that
-# legitimately names "index.db" once in its own docstrings/property.
-RESOLVER_MODULES: frozenset[str] = frozenset({"archive_identity.py", "campaign_archive_location.py"})
-
-_FORBIDDEN_SENTINEL_PATTERN = re.compile(r'"benchmark\.db"')
-
-# Ad hoc sibling tier-path derivation: ` / "index.db"` (or any other
-# known tier filename), constructed directly rather than obtained from
-# ArchiveLocation/CampaignArchiveLocation. A bare string search is
-# deliberately used (not just AST) so it also catches f-string/format
-# variants of the same shape.
-_TIER_FILENAMES: tuple[str, ...] = ("source.db", "index.db", "embeddings.db", "user.db", "ops.db")
-_SIBLING_DERIVATION_PATTERN = re.compile(
- r'/\s*["\'](' + "|".join(re.escape(name) for name in _TIER_FILENAMES) + r')["\']'
-)
-
-# Entry points that must positively reference CampaignArchiveLocation
-# (module path, symbol name) -- a purely negative scan can be defeated by
-# deleting the ownership plumbing while leaving no forbidden string behind.
-_REQUIRED_OWNERSHIP_REFERENCE: tuple[tuple[Path, str], ...] = (
- (ROOT / "devtools" / "large_archive_generator.py", "generate_archive"),
- (ROOT / "devtools" / "benchmark_campaigns.py", "run_full_campaign"),
- (ROOT / "devtools" / "run_campaign.py", "_run"),
-)
-
-
-@dataclass(frozen=True, slots=True)
-class SentinelHit:
- path: Path
- lineno: int
- line: str
-
-
-@dataclass(frozen=True, slots=True)
-class SiblingDerivationHit:
- path: Path
- lineno: int
- line: str
- tier_filename: str
-
-
-@dataclass(frozen=True, slots=True)
-class MissingOwnershipReference:
- path: Path
- symbol: str
-
-
-def _scan_modules(modules: tuple[Path, ...]) -> tuple[list[SentinelHit], list[SiblingDerivationHit]]:
- sentinel_hits: list[SentinelHit] = []
- sibling_hits: list[SiblingDerivationHit] = []
- for path in modules:
- if not path.exists() or path.name in RESOLVER_MODULES:
- continue
- for lineno, line in enumerate(path.read_text(encoding="utf-8").splitlines(), start=1):
- if _FORBIDDEN_SENTINEL_PATTERN.search(line):
- sentinel_hits.append(SentinelHit(path=path, lineno=lineno, line=line.strip()))
- match = _SIBLING_DERIVATION_PATTERN.search(line)
- if match:
- sibling_hits.append(
- SiblingDerivationHit(path=path, lineno=lineno, line=line.strip(), tier_filename=match.group(1))
- )
- return sentinel_hits, sibling_hits
-
-
-def _missing_ownership_references(
- entries: tuple[tuple[Path, str], ...] = _REQUIRED_OWNERSHIP_REFERENCE,
-) -> list[MissingOwnershipReference]:
- missing: list[MissingOwnershipReference] = []
- for path, symbol in entries:
- if not path.exists():
- missing.append(MissingOwnershipReference(path=path, symbol=symbol))
- continue
- source = path.read_text(encoding="utf-8")
- if f"def {symbol}" not in source:
- missing.append(MissingOwnershipReference(path=path, symbol=symbol))
- continue
- if "CampaignArchiveLocation" not in source:
- missing.append(MissingOwnershipReference(path=path, symbol=symbol))
- return missing
-
-
-def _format_report(
- *,
- sentinel_hits: list[SentinelHit],
- sibling_hits: list[SiblingDerivationHit],
- missing_refs: list[MissingOwnershipReference],
-) -> str:
- lines = [
- f"forbidden benchmark.db sentinel references found: {len(sentinel_hits)}",
- f"ad hoc tier-path sibling derivations found: {len(sibling_hits)}",
- f"campaign entry points missing CampaignArchiveLocation reference: {len(missing_refs)}",
- ]
- if sentinel_hits:
- lines.append("")
- lines.append("Forbidden benchmark.db sentinel references:")
- for sentinel in sentinel_hits:
- lines.append(f" {sentinel.path.relative_to(ROOT)}:{sentinel.lineno}: {sentinel.line}")
- lines.append("")
- lines.append(
- "Policy violation: campaigns must resolve the real active index via "
- "CampaignArchiveLocation, never invent a 'benchmark.db' sentinel."
- )
- if sibling_hits:
- lines.append("")
- lines.append("Ad hoc tier-path sibling derivations:")
- for sibling in sibling_hits:
- lines.append(f" {sibling.path.relative_to(ROOT)}:{sibling.lineno}: {sibling.line}")
- lines.append("")
- lines.append(
- "Policy violation: tier-path derivation belongs to ArchiveLocation's resolver alone; "
- "a campaign module deriving a sibling path directly reintroduces ambiguous archive typing."
- )
- if missing_refs:
- lines.append("")
- lines.append("Campaign entry points missing ownership plumbing:")
- for ref in missing_refs:
- lines.append(f" {ref.path.relative_to(ROOT) if ref.path.exists() else ref.path}: {ref.symbol}")
- lines.append("")
- lines.append(
- "Policy violation: campaign, ownership, generation, and target tier must stay stable "
- "through every reopen -- each entry point must route through CampaignArchiveLocation."
- )
- if not sentinel_hits and not sibling_hits and not missing_refs:
- lines.append("")
- lines.append("Campaign archive-location boundary intact.")
- return "\n".join(lines)
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- )
- parser.add_argument("--json", action="store_true", help="emit machine-readable JSON")
- args = parser.parse_args(argv)
-
- sentinel_hits, sibling_hits = _scan_modules(CAMPAIGN_MODULES)
- missing_refs = _missing_ownership_references()
-
- ok = not sentinel_hits and not sibling_hits and not missing_refs
-
- if args.json:
- payload = {
- "sentinel_hits": [
- {"path": str(sentinel.path.relative_to(ROOT)), "line": sentinel.lineno, "text": sentinel.line}
- for sentinel in sentinel_hits
- ],
- "sibling_derivation_hits": [
- {
- "path": str(sibling.path.relative_to(ROOT)),
- "line": sibling.lineno,
- "text": sibling.line,
- "tier_filename": sibling.tier_filename,
- }
- for sibling in sibling_hits
- ],
- "missing_ownership_references": [
- {"path": str(ref.path.relative_to(ROOT) if ref.path.exists() else ref.path), "symbol": ref.symbol}
- for ref in missing_refs
- ],
- "ok": ok,
- }
- print(json.dumps(payload, indent=2))
- else:
- print(_format_report(sentinel_hits=sentinel_hits, sibling_hits=sibling_hits, missing_refs=missing_refs))
-
- return 0 if ok else 1
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/verify_catalog_bypasses.py b/devtools/verify_catalog_bypasses.py
deleted file mode 100644
index 26fee09389..0000000000
--- a/devtools/verify_catalog_bypasses.py
+++ /dev/null
@@ -1,305 +0,0 @@
-"""Reject unregistered direct devtools command execution in control surfaces.
-
-The CommandSpec catalog is the public execution registry. Workflow ``run:``
-blocks, repository hooks, CI-owned npm scripts, and devtools process-launch
-calls must invoke it as ``devtools ...``. This checker catches literal direct forms such as
-``python -m devtools.some_module``, ``python -mdevtools.some_module``, and
-``python devtools/some_module.py``.
-
-Scope is deliberately execution-only:
-
-* workflow ``run:`` blocks, hook shell scripts, and the declared top-level
- JavaScript workspace npm scripts are scanned as structured command text;
-* ``devtools/**/*.py`` is parsed with ``ast`` and only command-runner call
- arguments are inspected, including literal ``args=`` keyword vectors and
- CPython's compact ``-mdevtools.module`` form.
-
-Generated provenance headers, argparse ``prog`` values, comments, and
-docstrings are outside the scope because they do not launch a process. A real
-hook adapter can remain only through a structured ``sanctioned-bypass`` entry
-in ``CATALOG_BYPASS_SITES`` with a reason, exact line, and expected occurrence
-count. Dynamic values remain untrusted, but literal executable, module, and
-script segments are inspected without scanning comments or prose.
-"""
-
-from __future__ import annotations
-
-import argparse
-import ast
-import json
-import re
-import sys
-from collections.abc import Iterable
-from dataclasses import asdict, dataclass
-from pathlib import Path
-
-import yaml
-
-from devtools import repo_root as _get_root
-from devtools.command_catalog import CATALOG_BYPASS_SITES, CatalogBypassSite
-
-ROOT = _get_root()
-_COMMAND_RUNNERS = {
- "run",
- "call",
- "check_call",
- "check_output",
- "Popen",
- "system",
- "_run",
- "run_command",
- "_run_command",
-}
-_PYTHON = r"python(?:3(?:\.\d+)?)?"
-_MODULE_INVOCATION = re.compile(
- rf"(? str:
- try:
- return path.relative_to(root).as_posix()
- except ValueError:
- return path.as_posix()
-
-
-def _shell_invocations(source: str, *, path: str, line_offset: int = 0) -> list[DirectDevtoolsInvocation]:
- findings: list[DirectDevtoolsInvocation] = []
- for pattern, prefix in ((_MODULE_INVOCATION, "python -m"), (_SCRIPT_INVOCATION, "python")):
- for match in pattern.finditer(source):
- findings.append(
- DirectDevtoolsInvocation(
- path=path,
- lineno=line_offset + source.count("\n", 0, match.start()) + 1,
- invocation=f"{prefix} {match.group(1)}",
- )
- )
- return findings
-
-
-def _is_command_runner(call: ast.Call) -> bool:
- func = call.func
- if isinstance(func, ast.Name):
- return func.id in _COMMAND_RUNNERS
- return isinstance(func, ast.Attribute) and func.attr in _COMMAND_RUNNERS
-
-
-def _is_python_expression(node: ast.expr) -> bool:
- if isinstance(node, ast.Constant) and isinstance(node.value, str):
- return re.fullmatch(_PYTHON, node.value) is not None
- return (
- isinstance(node, ast.Attribute)
- and isinstance(node.value, ast.Name)
- and node.value.id == "sys"
- and node.attr == "executable"
- )
-
-
-def _literal_command_parts(node: ast.expr) -> list[ast.expr] | None:
- if isinstance(node, ast.Constant) and isinstance(node.value, str):
- return [node]
- if isinstance(node, ast.List | ast.Tuple):
- return list(node.elts)
- return None
-
-
-def _literal_string(node: ast.expr) -> str | None:
- return node.value if isinstance(node, ast.Constant) and isinstance(node.value, str) else None
-
-
-def _invocations_from_command_expression(node: ast.expr, *, path: str, lineno: int) -> list[DirectDevtoolsInvocation]:
- parts = _literal_command_parts(node)
- if parts is None:
- return []
- if len(parts) == 1:
- shell = _literal_string(parts[0])
- return _shell_invocations(shell, path=path) if shell is not None else []
-
- findings: list[DirectDevtoolsInvocation] = []
- for index, part in enumerate(parts):
- if not _is_python_expression(part) or index + 1 >= len(parts):
- continue
- next_part = _literal_string(parts[index + 1])
- module: str | None = None
- if next_part == "-m" and index + 2 < len(parts):
- module = _literal_string(parts[index + 2])
- elif next_part is not None:
- compact = re.fullmatch(r"-m(devtools\.[A-Za-z_][A-Za-z0-9_]*)", next_part)
- module = compact.group(1) if compact is not None else None
- if module is not None and re.fullmatch(r"devtools\.[A-Za-z_][A-Za-z0-9_]*", module):
- findings.append(DirectDevtoolsInvocation(path=path, lineno=lineno, invocation=f"python -m {module}"))
- elif next_part is not None and re.fullmatch(r"(?:\./)?devtools/[A-Za-z_][A-Za-z0-9_]*\.py", next_part):
- findings.append(
- DirectDevtoolsInvocation(path=path, lineno=lineno, invocation=f"python {next_part.removeprefix('./')}")
- )
- return findings
-
-
-def _python_invocations(source: str, *, path: str) -> list[DirectDevtoolsInvocation]:
- try:
- tree = ast.parse(source, filename=path)
- except SyntaxError:
- return []
- findings: list[DirectDevtoolsInvocation] = []
- for node in ast.walk(tree):
- if not isinstance(node, ast.Call) or not _is_command_runner(node):
- continue
- command = (
- node.args[0]
- if node.args
- else next((keyword.value for keyword in node.keywords if keyword.arg == "args"), None)
- )
- if command is not None:
- findings.extend(_invocations_from_command_expression(command, path=path, lineno=node.lineno))
- return findings
-
-
-def _workflow_run_blocks(path: Path) -> Iterable[str]:
- try:
- data = yaml.safe_load(path.read_text(encoding="utf-8"))
- except yaml.YAMLError:
- return ()
-
- def _walk(value: object) -> Iterable[str]:
- if isinstance(value, dict):
- for key, nested in value.items():
- if key == "run" and isinstance(nested, str):
- yield nested
- yield from _walk(nested)
- elif isinstance(value, list):
- for nested in value:
- yield from _walk(nested)
-
- return tuple(_walk(data))
-
-
-def _npm_script_invocations(path: Path, *, relative: str) -> list[DirectDevtoolsInvocation]:
- try:
- manifest = json.loads(path.read_text(encoding="utf-8"))
- except json.JSONDecodeError:
- return []
- scripts = manifest.get("scripts")
- if not isinstance(scripts, dict):
- return []
- source = path.read_text(encoding="utf-8")
- findings: list[DirectDevtoolsInvocation] = []
- for name, command in scripts.items():
- if not isinstance(name, str) or not isinstance(command, str):
- continue
- match = re.search(rf'^\s*"{re.escape(name)}"\s*:', source, flags=re.MULTILINE)
- line_offset = source.count("\n", 0, match.start()) if match is not None else 0
- findings.extend(_shell_invocations(command, path=relative, line_offset=line_offset))
- return findings
-
-
-def control_surface_paths(root: Path = ROOT) -> tuple[Path, ...]:
- paths: list[Path] = []
- workflows = root / ".github" / "workflows"
- if workflows.exists():
- paths.extend(sorted((*workflows.glob("*.yml"), *workflows.glob("*.yaml"))))
- for hook_dir in (root / ".githooks", root / ".beads-hooks"):
- if hook_dir.exists():
- paths.extend(sorted(path for path in hook_dir.iterdir() if path.is_file()))
- devtools = root / "devtools"
- if devtools.exists():
- paths.extend(sorted(devtools.rglob("*.py")))
- paths.extend(root / manifest for manifest in _NPM_SCRIPT_MANIFESTS if (root / manifest).is_file())
- return tuple(paths)
-
-
-def scan_control_surfaces(root: Path = ROOT, *, paths: Iterable[Path] | None = None) -> list[DirectDevtoolsInvocation]:
- findings: list[DirectDevtoolsInvocation] = []
- for candidate in paths if paths is not None else control_surface_paths(root):
- path = candidate if candidate.is_absolute() else root / candidate
- if not path.is_file():
- continue
- relative = _relative_path(path, root)
- source = path.read_text(encoding="utf-8")
- if path.suffix in {".yml", ".yaml"}:
- for run in _workflow_run_blocks(path):
- findings.extend(_shell_invocations(run, path=relative))
- elif path.name == "package.json":
- findings.extend(_npm_script_invocations(path, relative=relative))
- elif path.suffix == ".py":
- findings.extend(_python_invocations(source, path=relative))
- else:
- findings.extend(_shell_invocations(source, path=relative))
- return findings
-
-
-def _sanctioned_sites() -> tuple[CatalogBypassSite, ...]:
- return tuple(
- site
- for site in CATALOG_BYPASS_SITES
- if site.disposition == "sanctioned-bypass" and site.occurrence_line is not None
- )
-
-
-def collect_violations(root: Path = ROOT, *, paths: Iterable[Path] | None = None) -> list[BypassViolation]:
- selected = tuple(paths) if paths is not None else control_surface_paths(root)
- findings = scan_control_surfaces(root, paths=selected)
- sanctioned = _sanctioned_sites()
- selected_paths = {
- _relative_path(candidate if candidate.is_absolute() else root / candidate, root) for candidate in selected
- }
- allowed = {(site.path, site.occurrence_line, site.marker) for site in sanctioned}
- violations = [
- BypassViolation(item.path, item.lineno, item.invocation, "undeclared-direct-invocation")
- for item in findings
- if (item.path, item.lineno, item.invocation) not in allowed
- ]
- for site in sanctioned:
- occurrence_line = site.occurrence_line
- assert occurrence_line is not None
- if site.path not in selected_paths:
- continue
- count = sum(item.path == site.path and item.invocation == site.marker for item in findings)
- if count != site.expected_occurrences:
- violations.append(
- BypassViolation(
- site.path,
- occurrence_line,
- site.marker,
- f"sanctioned-occurrence-count:{count}!={site.expected_occurrences}",
- )
- )
- return violations
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--json", action="store_true", help="emit machine-readable output")
- args = parser.parse_args(argv)
- violations = collect_violations(ROOT)
- if args.json:
- print(json.dumps({"ok": not violations, "violations": [asdict(item) for item in violations]}, indent=2))
- elif violations:
- print("Catalog bypass violations:", file=sys.stderr)
- for item in violations:
- print(f" {item.path}:{item.lineno}: {item.invocation} ({item.reason})", file=sys.stderr)
- else:
- print("Catalog bypass scan OK: no undeclared direct devtools execution sites.")
- return 1 if violations else 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/verify_ci_commands.py b/devtools/verify_ci_commands.py
new file mode 100644
index 0000000000..c8b99655a5
--- /dev/null
+++ b/devtools/verify_ci_commands.py
@@ -0,0 +1,114 @@
+"""Validate catalogued devtools commands in structured CI run fields."""
+
+from __future__ import annotations
+
+import argparse
+import json
+import shlex
+from collections.abc import Iterator, Mapping, Sequence
+from pathlib import Path
+from typing import Any
+
+import yaml
+
+from devtools import repo_root
+from devtools.command_catalog import COMMAND_SPECS, command_name_from_tokens
+
+
+def _run_scripts(value: object) -> Iterator[str]:
+ """Yield executable scripts from YAML ``run`` fields, never prose fields."""
+ if isinstance(value, Mapping):
+ for key, child in value.items():
+ if key == "run":
+ if isinstance(child, str):
+ yield child
+ elif isinstance(child, Mapping) and isinstance(child.get("command"), str):
+ yield child["command"]
+ yield from _run_scripts(child)
+ elif isinstance(value, list):
+ for child in value:
+ yield from _run_scripts(child)
+
+
+def _shell_tokens(script: str) -> tuple[str, ...]:
+ lexer = shlex.shlex(script, posix=True, punctuation_chars=";&|()")
+ lexer.whitespace_split = True
+ lexer.commenters = "#"
+ try:
+ return tuple(lexer)
+ except ValueError:
+ return ()
+
+
+def _invocations(script: str) -> Iterator[tuple[str, ...]]:
+ """Yield argv tails following exact ``devtools`` executable tokens."""
+ tokens = _shell_tokens(script.replace("\\\n", " "))
+ separators = {";", "&", "&&", "|", "||", "(", ")"}
+ for index, token in enumerate(tokens):
+ if Path(token).name != "devtools":
+ continue
+ tail: list[str] = []
+ for candidate in tokens[index + 1 :]:
+ if candidate in separators:
+ break
+ tail.append(candidate)
+ yield tuple(tail)
+
+
+def _unknown_command(argv: Sequence[str]) -> str | None:
+ if not argv or argv[0].startswith("-"):
+ return None
+ matched = command_name_from_tokens(argv)
+ if matched is None:
+ return argv[0]
+ matched_path = next(spec.command_path for spec in COMMAND_SPECS if spec.name == matched)
+ remaining = argv[len(matched_path) :]
+ has_subcommands = any(
+ len(spec.command_path) > len(matched_path) and spec.command_path[: len(matched_path)] == matched_path
+ for spec in COMMAND_SPECS
+ )
+ if has_subcommands and remaining and not remaining[0].startswith("-"):
+ return " ".join((*matched_path, remaining[0]))
+ return None
+
+
+def validate_ci_commands(root: Path) -> tuple[str, ...]:
+ """Return parse and command errors from GitHub Actions and CircleCI YAML."""
+ paths = sorted((root / ".github" / "workflows").glob("*.yml"))
+ circle = root / ".circleci" / "config.yml"
+ if circle.exists():
+ paths.append(circle)
+ errors: list[str] = []
+ for path in paths:
+ relative = path.relative_to(root)
+ try:
+ document: Any = yaml.safe_load(path.read_text(encoding="utf-8"))
+ except (OSError, yaml.YAMLError) as exc:
+ errors.append(f"{relative}: invalid YAML: {exc}")
+ continue
+ for script in _run_scripts(document):
+ for argv in _invocations(script):
+ unknown = _unknown_command(argv)
+ if unknown is not None:
+ errors.append(f"{relative}: unknown devtools command {unknown!r}")
+ return tuple(errors)
+
+
+def main(argv: list[str] | None = None) -> int:
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument("--json", action="store_true")
+ args = parser.parse_args(argv)
+ root = repo_root()
+ errors = validate_ci_commands(root)
+ if args.json:
+ print(json.dumps({"blocking": bool(errors), "errors": list(errors)}, indent=2))
+ elif errors:
+ for error in errors:
+ print(f"[BLOCK] {error}")
+ else:
+ print("CI devtools commands match the live command catalog")
+ return 1 if errors else 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/devtools/verify_ci_workflows.py b/devtools/verify_ci_workflows.py
deleted file mode 100644
index 0318d8f39f..0000000000
--- a/devtools/verify_ci_workflows.py
+++ /dev/null
@@ -1,334 +0,0 @@
-"""Verify CI workflow files reference locally-known commands and paths.
-
-Checks each .github/workflows/*.yml file for:
-- devtools commands: must be registered in the devtools catalog
-- polylogue CLI commands: must match the installed CLI surface
-- file/dir paths passed to ruff/mypy/pytest: must exist in the repo
-
-Also exposes an inventory of workflow facts that other manifest checks
-consume to cross-reference declared CI state against actual workflow YAML:
-
-- workflow_names: the ``name:`` of each workflow
-- job_names: the keys under ``jobs:`` for each workflow
-- run_commands: every ``run:`` script string concatenated across all steps
-- artifact_uploads: artifact ``name`` values uploaded via
- ``actions/upload-artifact``
-- triggers: top-level ``on:`` keys (workflow_dispatch, pull_request, push, ...)
-
-Does NOT check remote CI state, GitHub secrets, or external service calls.
-Remote facts (branch protection, required checks, success rate, runner
-availability) are deliberately not invented here.
-"""
-
-from __future__ import annotations
-
-import argparse
-import re
-import shlex
-import sys
-from dataclasses import dataclass, field
-from pathlib import Path
-
-import yaml
-
-from devtools import repo_root as _get_root
-from devtools.command_catalog import COMMANDS, command_name_from_tokens
-
-ROOT = _get_root()
-WORKFLOWS_DIR = ROOT / ".github" / "workflows"
-
-_DEVTOOLS_RE = re.compile(r"(? frozenset[str]:
- return frozenset(COMMANDS.keys())
-
-
-def _devtools_command_from_rest(rest: str) -> str | None:
- for stop in ("&&", "||", "|", ";", "#", "$("):
- idx = rest.find(stop)
- if idx >= 0:
- rest = rest[:idx]
- try:
- parts = shlex.split(rest)
- except ValueError:
- parts = rest.split()
- tokens = tuple(part for part in parts if part and not part.startswith("-"))
- if not tokens:
- return None
- known = command_name_from_tokens(tokens)
- if known is not None:
- return known
- max_len = max((len(spec.command_path) for spec in COMMANDS.values()), default=1)
- return " ".join(tokens[: min(len(tokens), max_len)])
-
-
-def _extract_run_steps(workflow: dict[str, object]) -> list[tuple[str, str, str]]:
- """Return (job_name, step_name, run_script) for all run steps."""
- results: list[tuple[str, str, str]] = []
- jobs = workflow.get("jobs")
- if not isinstance(jobs, dict):
- return results
- for job_name, job in jobs.items():
- if not isinstance(job, dict):
- continue
- for step in job.get("steps", []):
- if not isinstance(step, dict):
- continue
- run = step.get("run")
- if isinstance(run, str) and run.strip():
- step_name = str(step.get("name", ""))
- results.append((str(job_name), step_name, run))
- return results
-
-
-def _check_devtools_commands(
- run: str,
- known: frozenset[str],
- job: str,
- step: str,
- workflow: str,
-) -> list[str]:
- errors: list[str] = []
- for match in _DEVTOOLS_RE.finditer(run):
- cmd = _devtools_command_from_rest(match.group(1))
- if cmd is None:
- continue
- if cmd not in known:
- errors.append(f"{workflow}:{job}/{step!r}: unknown devtools command {cmd!r}")
- return errors
-
-
-def _check_paths(
- run: str,
- root: Path,
- job: str,
- step: str,
- workflow: str,
-) -> list[str]:
- warnings: list[str] = []
- for pattern, label in [
- (_RUFF_PATH_RE, "ruff"),
- (_MYPY_PATH_RE, "mypy"),
- (_PYTEST_PATH_RE, "pytest"),
- ]:
- for match in pattern.finditer(run):
- raw = match.group(1).strip()
- # Skip flags and variable expansions. Multiline shell scripts can
- # leave trailing backslash continuations inside the captured
- # fragment; shlex rejects them with ``No escaped character``.
- # Treat any tokenization failure as "fragment isn't a clean path
- # list" and skip it — best-effort, not strict shell parsing.
- try:
- parts = shlex.split(raw) if raw else []
- except ValueError:
- continue
- for part in parts:
- # Skip flags, shell expansions, and non-path tokens
- if part.startswith("-") or "$" in part or "{" in part:
- continue
- # Accept only plausible repo-relative paths (word chars, slashes, dots, hyphens)
- if not re.match(r"^[\w./\-]+$", part):
- continue
- path = root / part
- if not path.exists():
- warnings.append(f"{workflow}:{job}/{step!r}: {label} references non-existent path {part!r}")
- return warnings
-
-
-@dataclass(frozen=True)
-class WorkflowFacts:
- """Locally-knowable facts extracted from a single workflow YAML."""
-
- path: Path
- workflow_name: str
- job_names: tuple[str, ...]
- run_commands: tuple[str, ...]
- artifact_uploads: tuple[str, ...]
- triggers: tuple[str, ...]
-
-
-@dataclass(frozen=True)
-class WorkflowInventory:
- """Aggregate facts across every workflow under .github/workflows/."""
-
- workflows: tuple[WorkflowFacts, ...] = field(default_factory=tuple)
-
- @property
- def workflow_names(self) -> tuple[str, ...]:
- return tuple(w.workflow_name for w in self.workflows if w.workflow_name)
-
- @property
- def all_job_names(self) -> tuple[str, ...]:
- return tuple(name for w in self.workflows for name in w.job_names)
-
- @property
- def all_run_commands(self) -> tuple[str, ...]:
- return tuple(run for w in self.workflows for run in w.run_commands)
-
- @property
- def all_artifact_uploads(self) -> tuple[str, ...]:
- return tuple(name for w in self.workflows for name in w.artifact_uploads)
-
-
-def _extract_workflow_facts(path: Path, workflow: dict[str, object]) -> WorkflowFacts:
- """Pull job names, run commands, artifact names, and triggers from one YAML."""
- workflow_name = workflow.get("name") if isinstance(workflow.get("name"), str) else ""
- triggers: list[str] = []
- # PyYAML parses the bare key ``on`` as the boolean ``True`` (YAML 1.1
- # norway-style problem), so the actual triggers section can live under
- # either ``"on"`` or ``True``. We accept both.
- # Cast workflow to a dynamic-key dict for the boolean-key lookup since the
- # declared type only models string keys.
- raw_workflow: dict[object, object] = dict(workflow.items())
- on = raw_workflow.get("on") if "on" in raw_workflow else raw_workflow.get(True)
- if isinstance(on, dict | list):
- triggers.extend(str(k) for k in on)
- elif isinstance(on, str):
- triggers.append(on)
-
- job_names: list[str] = []
- run_commands: list[str] = []
- artifact_uploads: list[str] = []
- jobs = workflow.get("jobs")
- if isinstance(jobs, dict):
- for job_name, job in jobs.items():
- job_names.append(str(job_name))
- if not isinstance(job, dict):
- continue
- for step in job.get("steps", []):
- if not isinstance(step, dict):
- continue
- run = step.get("run")
- if isinstance(run, str) and run.strip():
- run_commands.append(run)
- uses = step.get("uses")
- if isinstance(uses, str) and uses.startswith("actions/upload-artifact"):
- with_block = step.get("with")
- if isinstance(with_block, dict):
- artifact_name = with_block.get("name")
- if isinstance(artifact_name, str) and artifact_name.strip():
- artifact_uploads.append(artifact_name)
-
- return WorkflowFacts(
- path=path,
- workflow_name=str(workflow_name) if workflow_name else "",
- job_names=tuple(job_names),
- run_commands=tuple(run_commands),
- artifact_uploads=tuple(artifact_uploads),
- triggers=tuple(triggers),
- )
-
-
-def inventory_workflows(workflows_dir: Path | None = None) -> WorkflowInventory:
- """Parse every ``.yml`` workflow under ``workflows_dir`` into facts.
-
- Used by manifest checks that need to cross-reference declared CI
- state (job names, command presence, artifact uploads, triggers)
- against committed workflow YAML.
- """
- target = workflows_dir if workflows_dir is not None else WORKFLOWS_DIR
- if not target.exists():
- return WorkflowInventory()
- facts: list[WorkflowFacts] = []
- for path in sorted(target.glob("*.yml")):
- try:
- with open(path, encoding="utf-8") as f:
- data = yaml.safe_load(f)
- except Exception:
- continue
- if not isinstance(data, dict):
- continue
- facts.append(_extract_workflow_facts(path, data))
- return WorkflowInventory(workflows=tuple(facts))
-
-
-def check_workflow(path: Path, root: Path, known_commands: frozenset[str]) -> tuple[list[str], list[str]]:
- """Return (errors, warnings) for a workflow file."""
- errors: list[str] = []
- warnings: list[str] = []
- rel = path.relative_to(root).as_posix()
-
- try:
- with open(path, encoding="utf-8") as f:
- workflow = yaml.safe_load(f)
- except Exception as exc:
- return [f"{rel}: failed to parse YAML: {exc}"], []
-
- if not isinstance(workflow, dict):
- return [f"{rel}: expected mapping at top level"], []
-
- for job, step, run in _extract_run_steps(workflow):
- errors.extend(_check_devtools_commands(run, known_commands, job, step, rel))
- warnings.extend(_check_paths(run, root, job, step, rel))
-
- return errors, warnings
-
-
-def main(argv: list[str] | None = None) -> int:
- p = argparse.ArgumentParser(description=__doc__)
- p.add_argument("--json", action="store_true")
- p.add_argument("--warn-paths", action="store_true", help="Treat missing paths as errors, not warnings.")
- args = p.parse_args(argv)
-
- if not WORKFLOWS_DIR.exists():
- if args.json:
- import json
-
- json.dump({"blocking": False, "errors": [], "warnings": [], "files_checked": 0}, sys.stdout, indent=2)
- sys.stdout.write("\n")
- else:
- print("no .github/workflows/ directory found — skipping")
- return 0
-
- known = _devtools_command_names()
- all_errors: list[str] = []
- all_warnings: list[str] = []
- files_checked = 0
-
- for path in sorted(WORKFLOWS_DIR.glob("*.yml")):
- errors, warnings = check_workflow(path, ROOT, known)
- all_errors.extend(errors)
- all_warnings.extend(warnings)
- files_checked += 1
-
- if args.warn_paths:
- all_errors.extend(all_warnings)
- all_warnings = []
-
- blocking = bool(all_errors)
-
- if args.json:
- import json
-
- json.dump(
- {
- "blocking": blocking,
- "errors": all_errors,
- "warnings": all_warnings,
- "files_checked": files_checked,
- },
- sys.stdout,
- indent=2,
- )
- sys.stdout.write("\n")
- else:
- if all_errors:
- for e in all_errors:
- print(f"[BLOCK] {e}")
- else:
- print(f"verify ci-workflows: {files_checked} workflow files checked, no errors")
- for w in all_warnings:
- print(f"[warn] {w}")
- print()
- print(f"blocking={blocking}")
-
- return 1 if blocking else 0
-
-
-if __name__ == "__main__":
- sys.exit(main(sys.argv[1:]))
diff --git a/devtools/verify_classifier_fingerprints.py b/devtools/verify_classifier_fingerprints.py
deleted file mode 100644
index bab763e9c7..0000000000
--- a/devtools/verify_classifier_fingerprints.py
+++ /dev/null
@@ -1,507 +0,0 @@
-"""Verify classifier/parser decision-boundary drift is declared.
-
-Background
-----------
-
-``devtools lab policy schema-versioning`` (``verify_schema_upgrade_lane.py``)
-enforces the durable-vs-derived schema-evolution policy boundary, but it is
-keyed entirely to ``INDEX_SCHEMA_VERSION``: a version integer. It has no
-visibility into ``polylogue/sources/**`` or
-``polylogue/archive/artifact_taxonomy/**``, where the actual acceptance
-decision for "is this raw payload a session?" is made.
-
-A parser/classifier can change what it accepts for *identical input bytes*
-without touching the index schema version at all. PR #3428 (``ab8a92c1a``,
-"require positive conversation evidence before session classification")
-is the concrete case this lint exists to catch retroactively: it tightened
-``looks_like_record_entry`` and ``looks_like_code`` so that a payload the
-classifier used to admit is now refused (or vice versa), while
-``INDEX_SCHEMA_VERSION`` stayed unchanged and ``lifecycle.py`` gained no new
-declaration. ``devtools lab policy schema-versioning`` ran green on that PR --
-correctly, per its own narrow contract, and uselessly for this defect. Rows
-already indexed under the old classification stayed silently stale with no
-signal that a reparse was ever needed (see ``polylogue-gucv``, ``-9ykn``,
-``-zqph``).
-
-A classification decision does not have to live in a function body at all.
-``polylogue/sources/origin_specs.py``'s ``OriginSpec.artifact_rules`` is a
-declarative table -- each ``OriginArtifactRule`` names a ``parse_policy``
-(``"session"`` / ``"fact"`` / ``"raw-only"``) for a native path family. PR
-#3088 changed ``parse_as_session`` for four Claude Workflow artifact kinds by
-editing this table, not a function, with no ``INDEX_SCHEMA_VERSION`` bump
-(retroactively declared by polylogue-lzh8 as the missing v48 delta). A lint
-that only fingerprints function ASTs is structurally blind to this table, so
-it is fingerprinted too (polylogue-qs4b).
-
-What this lint checks
-----------------------
-
-1. Discover every module-level function under ``polylogue/sources/`` or
- ``polylogue/archive/artifact_taxonomy/`` whose name matches
- ``looks_like*`` or ``classify_artifact*`` -- the naming convention this
- codebase already uses for a payload-shape/acceptance decision (grepped
- directly; see the functions this module's own tests pin) -- **and** every
- ``OriginArtifactRule`` entry in ``polylogue.sources.origin_specs.ORIGIN_SPECS``,
- keyed by ``origin:kind``.
-
-2. Fingerprint each one:
-
- * A function gets a SHA-256 hash of its AST (leading docstring excluded,
- line/column attributes excluded by construction), so reformatting,
- comment edits, and docstring rewrites do not trip the gate, but any
- change to the function's actual logic does.
- * An ``OriginArtifactRule`` gets a SHA-256 hash of its classification-
- relevant fields (``path_pattern``, ``parse_policy``, ``parser_path``,
- ``coverage_role``, ``path_suffixes``) as canonical JSON. ``fidelity_note``
- is prose documentation, excluded the same way a docstring is.
-
-3. Compare against the committed manifest
- (``docs/plans/classifier-fingerprints.json``). A function whose current
- fingerprint does not match its manifest entry is *undeclared drift*: the
- classification boundary moved and nothing says whether that was safe.
- Undeclared drift fails the gate. It resolves one of two ways, both
- recorded as manifest metadata:
-
- * ``semantic_reparse_version`` -- the change ships alongside an
- ``INDEX_SCHEMA_VERSION`` bump whose ``lifecycle.py`` declaration
- includes ``DerivedDeltaClass.SEMANTIC_REPARSE`` for that version. The
- manifest entry names the version; this lint cross-checks it is really
- declared that way.
- * ``acknowledged_safe`` -- an explicit, reviewed statement (a reason plus
- a bead/issue reference) that the change is safe without a reparse, e.g.
- because it only *tightens* acceptance for a shape that was never validly
- admitted in the first place. This is the escape hatch the parent bead's
- acceptance criteria call for when a reparse is judged unnecessary --
- it must still be an explicit, attributable decision, not silence.
-
-4. A function or artifact rule that disappears from source without its
- manifest entry being removed (an orphaned entry), or a newly added one with
- no manifest entry at all, both fail -- the manifest must track exactly the
- live set of classification-relevant surfaces.
-
-Scope and false-positive discipline
-------------------------------------
-
-In scope: functions matching the ``looks_like*`` / ``classify_artifact*``
-naming convention under the two classification directories, and every
-``OriginArtifactRule`` reachable from ``ORIGIN_SPECS``. An unrelated refactor
-elsewhere in ``polylogue/sources/`` (a parser's message mapping, cost
-accounting, attachment handling, ...) never touches either surface, so it
-never fires. Renaming, reformatting, or re-documenting a classifier function
-without changing its AST shape also does not fire (docstrings are stripped
-before hashing; ``ast.dump`` already omits source positions); editing an
-artifact rule's ``fidelity_note`` alone does not fire for the same reason.
-Adding a brand-new ``OriginSpec`` (a new origin, no rules yet) does not fire
-either -- an empty ``artifact_rules`` tuple contributes nothing to fingerprint.
-The known residual false-positive sources are a behaviour-preserving *local*
-refactor inside a classifier function itself (e.g. renaming a local variable),
-and reordering an artifact rule's ``path_suffixes`` tuple (JSON-serialized as
-a list, so order is part of the hash) -- both accepted deliberately, because
-the cost of one extra ``--ack``/``--semantic-reparse`` run is far lower than
-another silent phantom-classification incident.
-
-Wired into ``devtools verify`` directly (like the schema-versioning lane) --
-static, archive-independent, sub-second.
-"""
-
-from __future__ import annotations
-
-import argparse
-import ast
-import hashlib
-import json
-import re
-import sys
-from dataclasses import dataclass
-from pathlib import Path
-from typing import Literal, TypedDict
-
-from devtools import repo_root as _get_root
-from polylogue.sources.origin_specs import ORIGIN_SPECS, OriginArtifactRule, OriginSpec
-from polylogue.storage.sqlite.lifecycle import INDEX_DELTA_DECLARATIONS, DerivedDeltaClass
-
-ROOT = _get_root()
-CLASSIFICATION_ROOTS: tuple[Path, ...] = (
- ROOT / "polylogue" / "sources",
- ROOT / "polylogue" / "archive" / "artifact_taxonomy",
-)
-ORIGIN_SPECS_PATH = ROOT / "polylogue" / "sources" / "origin_specs.py"
-MANIFEST_PATH = ROOT / "docs" / "plans" / "classifier-fingerprints.json"
-
-_NAME_PATTERN = re.compile(r"^(looks_like\w*|classify_artifact\w*)$")
-_REF_PATTERN = re.compile(r"^(polylogue-[a-z0-9][a-z0-9.]*|#\d+)$")
-_MIN_REASON_LEN = 20
-
-
-@dataclass(frozen=True, slots=True)
-class ClassifierFunction:
- qualname: str
- path: Path
- lineno: int
- fingerprint: str
-
-
-def _fingerprint_function(node: ast.FunctionDef | ast.AsyncFunctionDef) -> str:
- """Hash the AST of a function, excluding its leading docstring."""
- body = list(node.body)
- if (
- body
- and isinstance(body[0], ast.Expr)
- and isinstance(body[0].value, ast.Constant)
- and isinstance(body[0].value.value, str)
- ):
- body = body[1:]
- replacement_cls = ast.FunctionDef if isinstance(node, ast.FunctionDef) else ast.AsyncFunctionDef
- replacement = replacement_cls(
- name="_",
- args=node.args,
- body=body or [ast.Pass()],
- decorator_list=node.decorator_list,
- returns=None,
- )
- dump = ast.dump(replacement, annotate_fields=True, include_attributes=False)
- return hashlib.sha256(dump.encode("utf-8")).hexdigest()
-
-
-def collect_classifier_functions(roots: tuple[Path, ...] = CLASSIFICATION_ROOTS) -> dict[str, ClassifierFunction]:
- """Return every in-scope classification function, keyed by qualname."""
- found: dict[str, ClassifierFunction] = {}
- for root in roots:
- if not root.exists():
- continue
- for path in sorted(root.rglob("*.py")):
- try:
- tree = ast.parse(path.read_text(encoding="utf-8"))
- except (SyntaxError, UnicodeDecodeError):
- continue
- for node in tree.body:
- if isinstance(node, ast.FunctionDef | ast.AsyncFunctionDef) and _NAME_PATTERN.match(node.name):
- rel = path.relative_to(ROOT).as_posix()
- qualname = f"{rel}:{node.name}"
- found[qualname] = ClassifierFunction(
- qualname=qualname,
- path=path,
- lineno=node.lineno,
- fingerprint=_fingerprint_function(node),
- )
- return found
-
-
-def _fingerprint_artifact_rule(rule: OriginArtifactRule) -> str:
- """Hash an ``OriginArtifactRule``'s classification-relevant fields.
-
- ``fidelity_note`` is prose documentation and is excluded, mirroring
- docstring exclusion for functions. Everything else here decides how a
- native artifact path is admitted and dispatched: changing any of it for
- an identical path is the same class of undeclared drift a function
- fingerprint catches.
- """
- payload = {
- "path_pattern": rule.path_pattern,
- "parse_policy": rule.parse_policy,
- "parser_path": rule.parser_path,
- "coverage_role": rule.coverage_role,
- "path_suffixes": list(rule.path_suffixes),
- }
- dump = json.dumps(payload, sort_keys=True)
- return hashlib.sha256(dump.encode("utf-8")).hexdigest()
-
-
-def collect_origin_artifact_rules(
- specs: tuple[OriginSpec, ...] = ORIGIN_SPECS,
-) -> dict[str, ClassifierFunction]:
- """Return every declared ``OriginArtifactRule``, keyed by ``origin:kind``."""
- found: dict[str, ClassifierFunction] = {}
- rel = ORIGIN_SPECS_PATH.relative_to(ROOT).as_posix()
- for spec in specs:
- for rule in spec.artifact_rules:
- qualname = f"{rel}:artifact_rule:{spec.origin.value}:{rule.kind}"
- found[qualname] = ClassifierFunction(
- qualname=qualname,
- path=ORIGIN_SPECS_PATH,
- lineno=0,
- fingerprint=_fingerprint_artifact_rule(rule),
- )
- return found
-
-
-def collect_all_classification_surfaces(
- roots: tuple[Path, ...] = CLASSIFICATION_ROOTS,
- specs: tuple[OriginSpec, ...] = ORIGIN_SPECS,
-) -> dict[str, ClassifierFunction]:
- """Every fingerprinted classification surface: functions plus artifact rules."""
- return {**collect_classifier_functions(roots), **collect_origin_artifact_rules(specs)}
-
-
-CoveredByKind = Literal["semantic_reparse_version", "acknowledged_safe"]
-
-
-@dataclass(frozen=True, slots=True)
-class CoveredBy:
- kind: CoveredByKind
- reason: str
- ref: str
- version: int | None = None
-
-
-@dataclass(frozen=True, slots=True)
-class ManifestEntry:
- fingerprint: str
- covered_by: CoveredBy
-
-
-class ManifestJSON(TypedDict):
- functions: dict[str, dict[str, object]]
-
-
-def _covered_by_from_dict(data: dict[str, object]) -> CoveredBy:
- kind_raw = data["kind"]
- if kind_raw not in ("semantic_reparse_version", "acknowledged_safe"):
- raise ValueError(f"unknown covered_by kind in manifest: {kind_raw!r}")
- kind: CoveredByKind = kind_raw
- version_raw = data.get("version")
- return CoveredBy(
- kind=kind,
- reason=str(data["reason"]),
- ref=str(data["ref"]),
- version=int(version_raw) if isinstance(version_raw, int) else None,
- )
-
-
-def load_manifest(path: Path = MANIFEST_PATH) -> dict[str, ManifestEntry]:
- if not path.exists():
- return {}
- raw: ManifestJSON = json.loads(path.read_text(encoding="utf-8"))
- entries: dict[str, ManifestEntry] = {}
- for qualname, data in raw.get("functions", {}).items():
- covered_by_raw = data["covered_by"]
- assert isinstance(covered_by_raw, dict)
- entries[qualname] = ManifestEntry(
- fingerprint=str(data["fingerprint"]),
- covered_by=_covered_by_from_dict(covered_by_raw),
- )
- return entries
-
-
-def save_manifest(entries: dict[str, ManifestEntry], path: Path = MANIFEST_PATH) -> None:
- payload: ManifestJSON = {
- "functions": {
- qualname: {
- "fingerprint": entry.fingerprint,
- "covered_by": {
- "kind": entry.covered_by.kind,
- "reason": entry.covered_by.reason,
- "ref": entry.covered_by.ref,
- **({"version": entry.covered_by.version} if entry.covered_by.version is not None else {}),
- },
- }
- for qualname, entry in sorted(entries.items())
- }
- }
- path.parent.mkdir(parents=True, exist_ok=True)
- path.write_text(json.dumps(payload, indent=2, sort_keys=False) + "\n", encoding="utf-8")
-
-
-@dataclass(frozen=True, slots=True)
-class DriftReport:
- missing: tuple[str, ...]
- orphaned: tuple[str, ...]
- drifted: tuple[str, ...]
- invalid_covered_by: tuple[tuple[str, str], ...]
-
- @property
- def ok(self) -> bool:
- return not self.missing and not self.orphaned and not self.drifted and not self.invalid_covered_by
-
-
-def _valid_semantic_reparse_version(version: int) -> bool:
- for declaration in INDEX_DELTA_DECLARATIONS:
- if declaration.version == version:
- return DerivedDeltaClass.SEMANTIC_REPARSE in declaration.classes
- return False
-
-
-def _validate_covered_by(covered_by: CoveredBy) -> str | None:
- if len(covered_by.reason.strip()) < _MIN_REASON_LEN:
- return f"reason too short (must explain why no reparse is required, >= {_MIN_REASON_LEN} chars)"
- if not _REF_PATTERN.match(covered_by.ref):
- return "ref must be a bead id (polylogue-xxxx) or issue number (#N)"
- if covered_by.kind == "semantic_reparse_version":
- if covered_by.version is None:
- return "semantic_reparse_version covered_by requires a version"
- if not _valid_semantic_reparse_version(covered_by.version):
- return (
- f"version {covered_by.version} has no SEMANTIC_REPARSE declaration in "
- "polylogue/storage/sqlite/lifecycle.py INDEX_DELTA_DECLARATIONS"
- )
- elif covered_by.kind == "acknowledged_safe":
- pass
- else:
- return f"unknown covered_by kind: {covered_by.kind!r}"
- return None
-
-
-def compute_drift_report(
- current: dict[str, ClassifierFunction] | None = None,
- manifest: dict[str, ManifestEntry] | None = None,
-) -> DriftReport:
- if current is None:
- current = collect_all_classification_surfaces()
- if manifest is None:
- manifest = load_manifest()
-
- missing = tuple(sorted(qualname for qualname in current if qualname not in manifest))
- orphaned = tuple(sorted(qualname for qualname in manifest if qualname not in current))
- drifted = tuple(
- sorted(
- qualname
- for qualname in current
- if qualname in manifest and manifest[qualname].fingerprint != current[qualname].fingerprint
- )
- )
- invalid_covered_by: list[tuple[str, str]] = []
- for qualname, entry in sorted(manifest.items()):
- if qualname in orphaned or qualname in drifted:
- # An orphaned/drifted entry's covered_by is stale by construction;
- # report the structural problem once, not a redundant validation.
- continue
- problem = _validate_covered_by(entry.covered_by)
- if problem is not None:
- invalid_covered_by.append((qualname, problem))
-
- return DriftReport(
- missing=missing,
- orphaned=orphaned,
- drifted=drifted,
- invalid_covered_by=tuple(invalid_covered_by),
- )
-
-
-def _format_report(report: DriftReport) -> str:
- lines = [
- f"classification surfaces missing a manifest entry: {len(report.missing)}",
- f"stale manifest entries (surface no longer exists): {len(report.orphaned)}",
- f"classification surfaces with undeclared fingerprint drift: {len(report.drifted)}",
- f"manifest entries with an invalid covered_by declaration: {len(report.invalid_covered_by)}",
- ]
- if report.missing:
- lines.append("")
- lines.append("New classification surfaces (function or artifact rule) with no manifest entry:")
- for qualname in report.missing:
- lines.append(f" {qualname}")
- lines.append(
- " Fix: devtools lab policy classifier-fingerprints --ack --reason '...' --ref "
- )
- if report.orphaned:
- lines.append("")
- lines.append("Manifest entries whose surface no longer exists (remove them):")
- for qualname in report.orphaned:
- lines.append(f" {qualname}")
- lines.append(f" Fix: edit {MANIFEST_PATH.relative_to(ROOT)} and delete the stale entry.")
- if report.drifted:
- lines.append("")
- lines.append(
- "Classification surfaces whose logic changed without a declared reparse "
- "or acknowledgment (a parser/classifier decision boundary moved for identical "
- "input bytes -- see devtools/verify_classifier_fingerprints.py's module docstring):"
- )
- for qualname in report.drifted:
- lines.append(f" {qualname}")
- lines.append(
- " Fix: either bump INDEX_SCHEMA_VERSION with a declared SEMANTIC_REPARSE delta "
- "and run `devtools lab policy classifier-fingerprints --ack "
- "--semantic-reparse --reason '...' --ref `, or record an explicit "
- "safety acknowledgment with `devtools lab policy classifier-fingerprints --ack "
- "--reason '...' --ref `."
- )
- if report.invalid_covered_by:
- lines.append("")
- lines.append("Manifest entries with an invalid covered_by declaration:")
- for qualname, problem in report.invalid_covered_by:
- lines.append(f" {qualname}: {problem}")
- if report.ok:
- lines.append("")
- lines.append("Classifier fingerprint policy intact.")
- return "\n".join(lines)
-
-
-def _cmd_ack(qualname: str, *, reason: str, ref: str, semantic_reparse_version: int | None) -> int:
- current = collect_all_classification_surfaces()
- if qualname not in current:
- print(f"error: {qualname!r} is not a currently discovered classification surface", file=sys.stderr)
- return 2
- manifest = load_manifest()
- covered_by = CoveredBy(
- kind="semantic_reparse_version" if semantic_reparse_version is not None else "acknowledged_safe",
- reason=reason,
- ref=ref,
- version=semantic_reparse_version,
- )
- problem = _validate_covered_by(covered_by)
- if problem is not None:
- print(f"error: {problem}", file=sys.stderr)
- return 2
- manifest[qualname] = ManifestEntry(fingerprint=current[qualname].fingerprint, covered_by=covered_by)
- save_manifest(manifest)
- print(f"recorded {qualname} ({covered_by.kind})")
- return 0
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- )
- parser.add_argument("--json", action="store_true", help="emit machine-readable JSON")
- parser.add_argument(
- "--ack",
- metavar="QUALNAME",
- help="record an acknowledged_safe (or, with --semantic-reparse, semantic_reparse_version) "
- "manifest entry for a classification function at its current fingerprint",
- )
- parser.add_argument("--reason", help="justification text for --ack (required with --ack)")
- parser.add_argument("--ref", help="bead id (polylogue-xxxx) or issue number (#N) for --ack (required with --ack)")
- parser.add_argument(
- "--semantic-reparse",
- dest="semantic_reparse_version",
- type=int,
- metavar="VERSION",
- help="with --ack: record semantic_reparse_version covered_by instead of acknowledged_safe",
- )
- args = parser.parse_args(argv)
-
- if args.ack:
- if not args.reason or not args.ref:
- parser.error("--ack requires --reason and --ref")
- return _cmd_ack(
- args.ack,
- reason=args.reason,
- ref=args.ref,
- semantic_reparse_version=args.semantic_reparse_version,
- )
-
- report = compute_drift_report()
-
- if args.json:
- print(
- json.dumps(
- {
- "missing": list(report.missing),
- "orphaned": list(report.orphaned),
- "drifted": list(report.drifted),
- "invalid_covered_by": [
- {"qualname": qualname, "problem": problem} for qualname, problem in report.invalid_covered_by
- ],
- "ok": report.ok,
- },
- indent=2,
- )
- )
- else:
- print(_format_report(report))
-
- return 0 if report.ok else 1
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/verify_closure_matrix.py b/devtools/verify_closure_matrix.py
deleted file mode 100644
index ed314388e9..0000000000
--- a/devtools/verify_closure_matrix.py
+++ /dev/null
@@ -1,170 +0,0 @@
-"""Verify docs/plans/test-closure-matrix.yaml stays grounded in the realized tree.
-
-For every row in the closure matrix, this lint checks:
-
-* each ``target_files`` path exists (file or directory),
-* each ``representative_tests`` entry exists (file path or the file portion of
- a ``path::Class::test`` nodeid),
-* every ``gate: absent`` row carries at least one ``known_gaps`` bullet,
-* every ``gate: required`` / ``gate: optional`` row lists at least one
- representative test,
-* ``gate`` is one of ``required | optional | absent``,
-* ``domain`` values are unique.
-
-Wired into ``devtools verify`` so that closure-matrix drift fails locally
-before a PR is opened. Backstops the per-domain coverage callouts in issue
-#997.
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import sys
-from pathlib import Path
-from typing import Any
-
-import yaml
-
-from devtools import repo_root as _get_root
-
-ROOT = _get_root()
-MANIFEST = ROOT / "docs" / "plans" / "test-closure-matrix.yaml"
-
-_VALID_GATES = frozenset({"required", "optional", "absent"})
-
-
-def _load(path: Path) -> dict[str, Any]:
- with path.open(encoding="utf-8") as handle:
- data = yaml.safe_load(handle)
- if not isinstance(data, dict):
- raise ValueError(f"{path}: expected mapping at top level, got {type(data).__name__}")
- return data
-
-
-def _split_nodeid(entry: str) -> str:
- """Return the file portion of a ``path::Class::test`` nodeid."""
- return entry.split("::", 1)[0]
-
-
-def _path_exists(rel: str) -> bool:
- """Accepts a file or a directory (trailing / optional)."""
- candidate = ROOT / rel.rstrip("/")
- return candidate.exists()
-
-
-def _validate_row(row: dict[str, Any], index: int) -> list[str]:
- errors: list[str] = []
- prefix = f"row[{index}]"
-
- domain = row.get("domain")
- if not isinstance(domain, str) or not domain.strip():
- errors.append(f"{prefix}: 'domain' must be a non-empty string")
- domain = f""
- prefix = f"row[{index}] domain={domain!r}"
-
- gate = row.get("gate")
- if gate not in _VALID_GATES:
- errors.append(f"{prefix}: 'gate' must be one of {sorted(_VALID_GATES)}, got {gate!r}")
-
- target_files = row.get("target_files") or []
- if not isinstance(target_files, list) or not target_files:
- errors.append(f"{prefix}: 'target_files' must be a non-empty list")
- target_files = []
- for entry in target_files:
- if not isinstance(entry, str):
- errors.append(f"{prefix}: target_files entry not a string: {entry!r}")
- continue
- if not _path_exists(entry):
- errors.append(f"{prefix}: target_files path missing: {entry}")
-
- representative_tests = row.get("representative_tests") or []
- if not isinstance(representative_tests, list):
- errors.append(f"{prefix}: 'representative_tests' must be a list")
- representative_tests = []
- for entry in representative_tests:
- if not isinstance(entry, str):
- errors.append(f"{prefix}: representative_tests entry not a string: {entry!r}")
- continue
- file_part = _split_nodeid(entry)
- if not _path_exists(file_part):
- errors.append(f"{prefix}: representative_tests path missing: {entry}")
-
- known_gaps = row.get("known_gaps") or []
- if not isinstance(known_gaps, list):
- errors.append(f"{prefix}: 'known_gaps' must be a list when present")
- known_gaps = []
-
- if gate == "absent":
- if not known_gaps:
- errors.append(f"{prefix}: gate='absent' rows must list at least one 'known_gaps' bullet")
- elif gate in ("required", "optional") and not representative_tests:
- errors.append(f"{prefix}: gate={gate!r} rows must list at least one representative test")
-
- return errors
-
-
-def _validate(matrix: dict[str, Any]) -> list[str]:
- errors: list[str] = []
-
- rows = matrix.get("rows")
- if not isinstance(rows, list) or not rows:
- return [f"{MANIFEST.name}: 'rows' must be a non-empty list"]
-
- seen: set[str] = set()
- for index, row in enumerate(rows):
- if not isinstance(row, dict):
- errors.append(f"row[{index}]: must be a mapping")
- continue
- errors.extend(_validate_row(row, index))
- domain = row.get("domain")
- if isinstance(domain, str):
- if domain in seen:
- errors.append(f"duplicate domain: {domain!r}")
- seen.add(domain)
-
- return errors
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--yaml", type=Path, default=MANIFEST)
- parser.add_argument("--json", action="store_true")
- args = parser.parse_args(argv)
-
- try:
- matrix = _load(args.yaml)
- except (OSError, ValueError, yaml.YAMLError) as exc:
- if args.json:
- json.dump({"blocking": True, "errors": [str(exc)]}, sys.stdout, indent=2)
- sys.stdout.write("\n")
- else:
- print(f"[BLOCK] failed to load {args.yaml}: {exc}")
- return 1
-
- errors = _validate(matrix)
- blocking = bool(errors)
- row_count = len(matrix.get("rows") or [])
-
- if args.json:
- json.dump(
- {"blocking": blocking, "errors": errors, "rows": row_count},
- sys.stdout,
- indent=2,
- )
- sys.stdout.write("\n")
- else:
- if errors:
- print(f"[BLOCK] closure-matrix errors: {len(errors)}")
- for line in errors:
- print(f" {line}")
- else:
- print(f"closure-matrix: clean ({row_count} domains)")
- print()
- print(f"blocking={blocking}")
-
- return 1 if blocking else 0
-
-
-if __name__ == "__main__":
- sys.exit(main(sys.argv[1:]))
diff --git a/devtools/verify_degrade_loudly.py b/devtools/verify_degrade_loudly.py
deleted file mode 100644
index e921fa3bde..0000000000
--- a/devtools/verify_degrade_loudly.py
+++ /dev/null
@@ -1,328 +0,0 @@
-"""Lint: broad except-handlers in derived-read/status/probe code must signal.
-
-Background (polylogue-cpf.4, the "degrade loudly" doctrine under
-``polylogue-cpf``): a deep read (2026-07-05) found the daemon/storage/
-insights/coordination packages systematically degrade *silently* on
-derived-read, fallback, and freshness-probe paths — a caught exception is
-swallowed and a plain default (``None``/``0``/``[]``/``False``) is returned,
-which is indistinguishable from the query genuinely finding nothing. For a
-system-of-record that is a construct-validity hole: a reader cannot tell
-"no data" from "the probe/query failed".
-
-This lint scans ``polylogue/daemon``, ``polylogue/storage``,
-``polylogue/insights``, and ``polylogue/coordination`` (excluding tests) for
-``except`` handlers that catch a broad exception type (``Exception``,
-``BaseException``, or any ``*.Error`` such as ``sqlite3.Error``) whose body:
-
-1. Never calls anything with "log" in its name (covers ``logger.warning``,
- ``self._logger.exception``, etc.) — the doctrine's "log loudly" minimum, and
-2. Never re-raises.
-
-Narrower excepts (``ValueError``, ``TypeError``, ``JSONDecodeError``, ...) are
-not flagged: in this codebase they are overwhelmingly routine defensive value
-coercion on a single optionally-malformed field (a documented fallback for
-*one field*, not a derived-read health/readiness signal), not the
-system-of-record degradation the doctrine targets.
-
-A violation is not automatically a bug: many broad excepts already return a
-typed signal instead of logging (``HealthAlert(severity=ERROR, message=f"...:
-{exc}")`` in ``daemon/health.py``, ``{"available": False, "error": str(exc)}``
-dicts, ``_repair_result(..., success=False, detail=f"...: {exc}")``). This
-lint cannot see through a return value to tell whether it structurally
-encodes the failure, so those sites are pre-approved in the allowlist at
-``docs/plans/degrade-loudly-allowlist.yaml`` with a one-line rationale.
-
-New broad excepts must either add a log call (cheapest fix), return a typed
-signal *and* add an allowlist entry explaining what the signal is, or
-genuinely re-raise. The allowlist is keyed by (path, enclosing function
-qualname, sorted exception names, occurrence index within that function) —
-not line number — so it survives unrelated line-shift churn elsewhere in the
-file; only an edit to the flagged function's except-handler shape invalidates
-an entry. Stale allowlist entries (no longer matching any current violation)
-are also rejected, so the allowlist can't quietly grow unbounded.
-"""
-
-from __future__ import annotations
-
-import argparse
-import ast
-import json
-import sys
-from dataclasses import dataclass
-from pathlib import Path
-
-try:
- import yaml
-except ImportError: # pragma: no cover - yaml is a hard repo dep
- yaml = None # type: ignore[assignment]
-
-from devtools import repo_root as _get_root
-
-ROOT = _get_root()
-TARGET_DIRS = (
- "polylogue/daemon",
- "polylogue/storage",
- "polylogue/insights",
- "polylogue/coordination",
-)
-ALLOWLIST_PATH = ROOT / "docs" / "plans" / "degrade-loudly-allowlist.yaml"
-
-_BROAD_NAMES = {"Exception", "BaseException", "Error"}
-_LOG_HINT = "log"
-
-
-@dataclass(frozen=True, slots=True)
-class Site:
- path: str
- function: str
- exceptions: tuple[str, ...]
- occurrence: int
- lineno: int
-
- @property
- def key(self) -> tuple[str, str, tuple[str, ...], int]:
- return (self.path, self.function, self.exceptions, self.occurrence)
-
-
-def _exception_names(handler: ast.ExceptHandler) -> tuple[str, ...]:
- node = handler.type
- if node is None:
- return ("",)
- names: list[str] = []
- elts = node.elts if isinstance(node, ast.Tuple) else [node]
- for elt in elts:
- if isinstance(elt, ast.Name):
- names.append(elt.id)
- elif isinstance(elt, ast.Attribute):
- names.append(elt.attr)
- return tuple(sorted(names))
-
-
-def _body_logs_or_raises(body: list[ast.stmt]) -> bool:
- holder = ast.Module(body=body, type_ignores=[])
- for node in ast.walk(holder):
- if isinstance(node, ast.Raise):
- return True
- if isinstance(node, ast.Call):
- func = node.func
- if (
- isinstance(func, ast.Attribute)
- and isinstance(func.value, ast.Name)
- and _LOG_HINT in func.value.id.lower()
- ):
- return True
- if isinstance(func, ast.Name) and _LOG_HINT in func.id.lower():
- return True
- return False
-
-
-class _FunctionScopeVisitor(ast.NodeVisitor):
- """Walk a module tracking enclosing function qualnames and per-function
- occurrence counters for broad, unsignalled except-handlers."""
-
- def __init__(self, relpath: str) -> None:
- self.relpath = relpath
- self._stack: list[str] = [""]
- self._occurrence: dict[str, int] = {}
- self.sites: list[Site] = []
-
- def _qualname(self) -> str:
- return ".".join(self._stack)
-
- def _visit_function(self, node: ast.FunctionDef | ast.AsyncFunctionDef) -> None:
- self._stack.append(node.name)
- self.generic_visit(node)
- self._stack.pop()
-
- def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
- self._visit_function(node)
-
- def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None:
- self._visit_function(node)
-
- def visit_ExceptHandler(self, node: ast.ExceptHandler) -> None:
- names = _exception_names(node)
- if set(names) & _BROAD_NAMES and not _body_logs_or_raises(node.body):
- qualname = self._qualname()
- occ_key = f"{qualname}::{names}"
- occurrence = self._occurrence.get(occ_key, 0)
- self._occurrence[occ_key] = occurrence + 1
- self.sites.append(
- Site(
- path=self.relpath,
- function=qualname,
- exceptions=names,
- occurrence=occurrence,
- lineno=node.lineno,
- )
- )
- self.generic_visit(node)
-
-
-def _scan_file(path: Path, *, root: Path) -> list[Site]:
- try:
- tree = ast.parse(path.read_text(encoding="utf-8"))
- except (SyntaxError, UnicodeDecodeError):
- return []
- relpath = str(path.relative_to(root))
- visitor = _FunctionScopeVisitor(relpath)
- visitor.visit(tree)
- return visitor.sites
-
-
-def _scan_repo(*, root: Path) -> list[Site]:
- sites: list[Site] = []
- for target in TARGET_DIRS:
- base = root / target
- if not base.exists():
- continue
- for path in sorted(base.rglob("*.py")):
- if "test" in path.parts:
- continue
- sites.extend(_scan_file(path, root=root))
- return sites
-
-
-@dataclass(frozen=True, slots=True)
-class AllowlistEntry:
- path: str
- function: str
- exceptions: tuple[str, ...]
- occurrence: int
- reason: str
-
- @property
- def key(self) -> tuple[str, str, tuple[str, ...], int]:
- return (self.path, self.function, self.exceptions, self.occurrence)
-
-
-def _load_allowlist(allowlist_path: Path) -> list[AllowlistEntry]:
- if not allowlist_path.exists():
- return []
- if yaml is None:
- raise RuntimeError("PyYAML is required to read the degrade-loudly allowlist")
- data = yaml.safe_load(allowlist_path.read_text(encoding="utf-8")) or {}
- entries = data.get("entries", []) or []
- out: list[AllowlistEntry] = []
- for entry in entries:
- if not isinstance(entry, dict):
- continue
- exceptions = entry.get("exceptions", [])
- out.append(
- AllowlistEntry(
- path=str(entry.get("path", "")),
- function=str(entry.get("function", "")),
- exceptions=tuple(sorted(str(e) for e in exceptions)),
- occurrence=int(entry.get("occurrence", 0)),
- reason=str(entry.get("reason", "")),
- )
- )
- return out
-
-
-def _format_report(
- *,
- sites: list[Site],
- allowlist: list[AllowlistEntry],
- unallowlisted: list[Site],
- stale: list[AllowlistEntry],
- root: Path,
- allowlist_path: Path,
-) -> str:
- lines = [
- f"broad except-handlers scanned across {len(TARGET_DIRS)} package(s): {len(sites)}",
- f"allowlisted: {len(allowlist)}",
- f"unallowlisted (new silent soft-fails): {len(unallowlisted)}",
- f"stale allowlist entries: {len(stale)}",
- ]
- if unallowlisted:
- lines.append("")
- lines.append("Broad except-handlers with no log call and no re-raise, outside the allowlist:")
- for site in sorted(unallowlisted, key=lambda s: (s.path, s.lineno)):
- lines.append(
- f" {site.path}:{site.lineno} in {site.function}() except {list(site.exceptions)} "
- "— add a log call (or re-raise), or add an allowlist entry at "
- f"{allowlist_path.relative_to(root) if allowlist_path.is_relative_to(root) else allowlist_path} "
- "explaining the existing signal (polylogue-cpf.4)."
- )
- if stale:
- lines.append("")
- lines.append("Allowlist entries that no longer match a current violation (remove them):")
- for entry in sorted(stale, key=lambda e: (e.path, e.function)):
- lines.append(
- f" {entry.path} :: {entry.function}() except {list(entry.exceptions)} [occurrence {entry.occurrence}]"
- )
- return "\n".join(lines)
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- )
- parser.add_argument("--json", action="store_true", help="emit machine-readable JSON")
- parser.add_argument("--root", type=Path, default=ROOT, help="Repository root to scan.")
- parser.add_argument(
- "--allowlist",
- type=Path,
- default=None,
- help="Allowlist YAML path (defaults to /docs/plans/degrade-loudly-allowlist.yaml).",
- )
- args = parser.parse_args(argv)
-
- root: Path = args.root.resolve()
- default_allowlist = root / "docs" / "plans" / "degrade-loudly-allowlist.yaml"
- allowlist_path: Path = (args.allowlist or default_allowlist).resolve()
-
- sites = _scan_repo(root=root)
- allowlist = _load_allowlist(allowlist_path)
- allowed_keys = {entry.key for entry in allowlist}
- site_keys = {site.key for site in sites}
-
- unallowlisted = [site for site in sites if site.key not in allowed_keys]
- stale = [entry for entry in allowlist if entry.key not in site_keys]
-
- ok = not unallowlisted and not stale
-
- if args.json:
- payload = {
- "sites_scanned": len(sites),
- "allowlisted": len(allowlist),
- "violations": [
- {
- "path": site.path,
- "line": site.lineno,
- "function": site.function,
- "exceptions": list(site.exceptions),
- }
- for site in sorted(unallowlisted, key=lambda s: (s.path, s.lineno))
- ],
- "stale_allowlist_entries": [
- {
- "path": entry.path,
- "function": entry.function,
- "exceptions": list(entry.exceptions),
- "occurrence": entry.occurrence,
- }
- for entry in sorted(stale, key=lambda e: (e.path, e.function))
- ],
- "ok": ok,
- }
- print(json.dumps(payload, indent=2))
- else:
- print(
- _format_report(
- sites=sites,
- allowlist=allowlist,
- unallowlisted=unallowlisted,
- stale=stale,
- root=root,
- allowlist_path=allowlist_path,
- )
- )
-
- return 0 if ok else 1
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/verify_demo_packet_registry.py b/devtools/verify_demo_packet_registry.py
deleted file mode 100644
index 88c54440a1..0000000000
--- a/devtools/verify_demo_packet_registry.py
+++ /dev/null
@@ -1,83 +0,0 @@
-"""Verify every registered demo has a conforming Demo Packet v2 (polylogue-212.12).
-
-Background
-----------
-
-The 212 demo portfolio manifest (``.agent/demos/registry.json``) lists every
-demo prompt and its expected packet directory. This lint enumerates the
-manifest and validates each entry against the Demo Packet v2 epistemic
-contract (``devtools.demo_packet``) -- catching a demo whose packet is
-missing entirely, distinct from one whose packet exists but is malformed.
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-from pathlib import Path
-
-from devtools.demo_packet import lint_demo_registry
-
-DEFAULT_REGISTRY_PATH = Path(".agent/demos/registry.json")
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- )
- parser.add_argument(
- "--registry",
- type=Path,
- default=DEFAULT_REGISTRY_PATH,
- help=f"path to the demo registry manifest (default: {DEFAULT_REGISTRY_PATH})",
- )
- parser.add_argument("--json", action="store_true", help="emit machine-readable JSON")
- args = parser.parse_args(argv)
-
- if not args.registry.exists():
- message = f"demo packet registry: manifest not found at {args.registry}"
- if args.json:
- print(json.dumps({"ok": False, "error": message}, indent=2))
- else:
- print(message)
- return 1
-
- result = lint_demo_registry(args.registry, repo_root=Path.cwd())
-
- if args.json:
- print(json.dumps(result.to_dict(), indent=2))
- return 0 if result.ok else 1
-
- if result.ok:
- print(f"demo packet registry: all {len(result.entry_results)} entries conform")
- return 0
-
- print("demo packet registry: violations found")
- for error in result.registry_errors:
- print(f" registry: {error}")
- for packet_dir in result.unregistered_packet_dirs:
- print(f" unregistered v2 packet: {packet_dir}")
- for slug, validation in result.entry_results:
- if validation is None:
- print(f" {slug}: packet directory missing")
- continue
- if not validation.ok:
- print(f" {slug}: {validation.packet_dir}")
- for name in validation.missing_files:
- print(f" missing file: {name}")
- for name in validation.missing_stanza_fields:
- print(f" missing provenance stanza field: {name}")
- for name in validation.malformed_sections:
- print(f" missing report.md section: {name}")
- for error in validation.schema_errors:
- print(f" schema: {error}")
- for error in validation.receipt_errors:
- print(f" receipt: {error}")
- for error in validation.errors:
- print(f" {error}")
- return 1
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/verify_demo_tour_freshness.py b/devtools/verify_demo_tour_freshness.py
deleted file mode 100644
index 827ba71272..0000000000
--- a/devtools/verify_demo_tour_freshness.py
+++ /dev/null
@@ -1,187 +0,0 @@
-"""Verify a freshly-run ``polylogue demo tour`` matches the committed
-``docs/examples/demo-tour/`` evidence artifacts, modulo an explicit
-volatile-field mask (polylogue-3tl.17).
-
-Background
-----------
-
-``devtools render visual-tapes --check`` (polylogue-3tl.17) catches drift
-between the tape *specs* and the committed ``.tape`` recipe files. It does
-not catch drift between what ``polylogue demo tour`` actually *emits* at
-runtime (transcript, report, per-step command output, recording tape) and
-the committed copies of those emitted artifacts under
-``docs/examples/demo-tour/`` -- the kit shipped a stale recorded tour twice
-in 2026-07 (cwd-relative paths regressed once), caught only by a manual diff.
-
-Volatile-field mask
---------------------
-
-The tour is deterministic in every respect except wall-clock timing. In the
-prose/Markdown artifacts (transcript, report.md, recording tape, per-step
-command output) that timing renders as ``.s`` text, masked by
-a plain regex. ``report.json`` -- "the complete fixture and verification
-audit" per the tour's own summary -- carries the same timing as *numeric*
-JSON fields (``first_result_s``, ``total_duration_s``, each step's
-``duration_s``) with no trailing ``s``, so the text regex would not mask
-them; it is compared via a JSON-aware mask that zeroes exactly those three
-known-volatile keys and re-serializes with the same ``indent=2,
-sort_keys=True`` the tour itself uses, so every other field -- including
-nested structure, construct-coverage counts, and claim/oracle/falsifier
-text -- must match exactly. That is the ONLY masking this gate performs --
-claim text, exit codes, refs, anti-grep counts, command strings, and the
-out-dir basename referenced inside the recording tape must match exactly. A
-full-file skip would recreate the vacuity this gate exists to kill.
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import re
-import sys
-import tempfile
-from pathlib import Path
-from typing import Any
-
-from devtools import repo_root as _get_root
-
-ROOT = _get_root()
-COMMITTED_DIR = ROOT / "docs" / "examples" / "demo-tour"
-
-# Matches the committed fixture's own out-dir basename so freshly-run output
-# references the same path the recording tape's commands were authored
-# against (`cat polylogue-demo-tour/transcript.txt`, etc.).
-_COMMITTED_OUT_DIR_BASENAME = "polylogue-demo-tour"
-
-_DURATION_PATTERN = re.compile(r"\d+\.\d+s")
-
-# The only wall-clock-timing keys `polylogue/demo/tour.py` writes into
-# report.json (DemoTourResult.to_public_dict / DemoTourStep.to_public_dict).
-# Keep in sync with polylogue/demo/models.py -- any other numeric field in
-# report.json is a real construct-coverage/exit-code count and must match
-# exactly, not be masked.
-_JSON_DURATION_KEYS = {"duration_s", "first_result_s", "total_duration_s"}
-
-
-def mask_volatile(text: str) -> str:
- """Replace every wall-clock duration with a stable placeholder."""
- return _DURATION_PATTERN.sub("", text)
-
-
-def _mask_json_durations(obj: Any) -> Any:
- if isinstance(obj, dict):
- return {
- key: (
- ""
- if key in _JSON_DURATION_KEYS and isinstance(value, (int, float))
- else _mask_json_durations(value)
- )
- for key, value in obj.items()
- }
- if isinstance(obj, list):
- return [_mask_json_durations(item) for item in obj]
- return obj
-
-
-def mask_volatile_json(text: str) -> str:
- """JSON-aware mask for report.json.
-
- Parses the document, replaces exactly the known duration fields
- (:data:`_JSON_DURATION_KEYS`) with a stable placeholder, and
- re-serializes with the same formatting `polylogue/demo/tour.py` uses
- (``indent=2, sort_keys=True``) so the comparison is exact on every other
- field -- structured claim/oracle/falsifier text, construct-coverage
- counts, exit codes -- not just a prose summary of them.
- """
- masked = _mask_json_durations(json.loads(text))
- return mask_volatile(json.dumps(masked, indent=2, sort_keys=True))
-
-
-def _iter_comparable_relpaths(root: Path) -> list[str]:
- relpaths = ["transcript.txt", "report.md", "report.json", "recording.tape"]
- command_output_dir = root / "command-output"
- if command_output_dir.is_dir():
- relpaths.extend(f"command-output/{p.name}" for p in sorted(command_output_dir.glob("*.txt")))
- return relpaths
-
-
-def _iter_comparable_relpaths_union(committed_root: Path, fresh_root: Path) -> list[str]:
- """Union of comparable relpaths from both sides, so a file the fresh tour
- emits that the committed fixture never had (or vice versa) is reported as
- a mismatch instead of silently skipped."""
- seen: dict[str, None] = {}
- for relpath in _iter_comparable_relpaths(committed_root) + _iter_comparable_relpaths(fresh_root):
- seen.setdefault(relpath, None)
- return list(seen)
-
-
-def tour_freshness_diff(*, out_dir: Path) -> dict[str, tuple[str, str]]:
- """Run the demo tour into ``out_dir`` and return mismatches.
-
- ``out_dir``'s basename should be :data:`_COMMITTED_OUT_DIR_BASENAME` so
- the fresh recording tape's commands are directly comparable to the
- committed one.
-
- Returns ``{relpath: (committed_masked, fresh_masked)}`` for every file
- whose masked content differs, or whose fresh counterpart is missing
- entirely (fresh content reported as ``""``).
- """
- from polylogue.demo.tour import run_demo_tour
-
- run_demo_tour(output_dir=out_dir)
-
- def _mask_for(relpath: str, text: str) -> str:
- return mask_volatile_json(text) if relpath == "report.json" else mask_volatile(text)
-
- mismatches: dict[str, tuple[str, str]] = {}
- for relpath in _iter_comparable_relpaths_union(COMMITTED_DIR, out_dir):
- committed_path = COMMITTED_DIR / relpath
- fresh_path = out_dir / relpath
- committed_masked = (
- _mask_for(relpath, committed_path.read_text(encoding="utf-8")) if committed_path.exists() else ""
- )
- fresh_masked = (
- _mask_for(relpath, fresh_path.read_text(encoding="utf-8")) if fresh_path.exists() else ""
- )
- if committed_masked != fresh_masked:
- mismatches[relpath] = (committed_masked, fresh_masked)
- return mismatches
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
- parser.parse_args(argv)
-
- with tempfile.TemporaryDirectory() as tmp:
- out_dir = Path(tmp) / _COMMITTED_OUT_DIR_BASENAME
- mismatches = tour_freshness_diff(out_dir=out_dir)
-
- if not mismatches:
- print("demo-tour-freshness: fresh tour output matches committed docs/examples/demo-tour/ (masked)")
- return 0
-
- print(f"demo-tour-freshness: {len(mismatches)} file(s) differ from the committed tour evidence:", file=sys.stderr)
- import difflib
-
- for relpath, (committed_masked, fresh_masked) in sorted(mismatches.items()):
- print(f" {relpath}", file=sys.stderr)
- diff = difflib.unified_diff(
- committed_masked.splitlines(),
- fresh_masked.splitlines(),
- fromfile=f"committed/{relpath}",
- tofile=f"fresh/{relpath}",
- lineterm="",
- )
- for line in diff:
- print(line, file=sys.stderr)
- print(
- "demo-tour-freshness: run 'polylogue demo tour --out-dir "
- f"{_COMMITTED_OUT_DIR_BASENAME} --force' and copy the regenerated files into "
- f"{COMMITTED_DIR.relative_to(ROOT)}/ to fix",
- file=sys.stderr,
- )
- return 1
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/verify_doc_commands.py b/devtools/verify_doc_commands.py
index 562f4da3e4..59a77ddecb 100644
--- a/devtools/verify_doc_commands.py
+++ b/devtools/verify_doc_commands.py
@@ -10,24 +10,19 @@
For ``polylogued`` and ``devtools`` the lint extracts the first non-flag
token after the surface name and verifies it is a real subcommand.
-The ``polylogue`` CLI is query-first — any bare token after ``polylogue``
-is normally a valid FTS query, not a typo — so it is validated *by command
-recognition* (#2438): a documented invocation is only checked when its
-leading token resolves to a known command path or a removed command name.
-A recognized command path then has its long-flags validated against the
-union of root and full-path options (lazy subcommands are materialized via
-``get_params`` so ``analyze insights profiles --tier`` resolves correctly),
-while a leading token that resolves to neither a known nor a removed command
-is left alone so ``polylogue rate limiting retries`` stays legal.
+The ``polylogue`` CLI is query-first but requires explicit query intent. Its
+examples are parsed through the live root parser, so ``find``, shell-quoted
+free text, and field syntax remain valid while an unknown bare root is rejected.
+Recognized command paths also have their long flags checked against the live
+Click tree.
The lint only reads tokens that appear inside Markdown code surfaces
(inline ``` `code` ``` spans and fenced ``` ```bash/sh/shell/console``` `` blocks);
plain prose is ignored to avoid false positives from sentences such as
"polylogue and devtools share a workflow".
-It exists to keep #1262 / #869 / #2438 closed: doc drift away from the
-live command surface should fail a CI gate, not survive in master until a
-user files a bug.
+The validator derives authority from the current command implementations. It
+does not grep for historical spellings or require prose to preserve old names.
"""
from __future__ import annotations
@@ -35,6 +30,7 @@
import argparse
import json
import re
+import shlex
import sys
from collections.abc import Iterable
from dataclasses import dataclass
@@ -96,8 +92,8 @@ def _polylogue_root_value_flags(root: click.Command) -> frozenset[str]:
return frozenset(out)
-def _polylogue_path_flags(root: click.Command) -> dict[tuple[str, ...], frozenset[str]]:
- """Long-flags declared on every command path in the ``polylogue`` tree.
+def _click_path_flags(root: click.Command) -> dict[tuple[str, ...], frozenset[str]]:
+ """Long flags declared on every command path in a Click tree.
``iter_command_paths`` descends the full tree, so leaf subcommands such as
``analyze insights profiles`` expose their real options here even though the
@@ -106,23 +102,12 @@ def _polylogue_path_flags(root: click.Command) -> dict[tuple[str, ...], frozense
return {cp.path: _long_opts(cp.command) for cp in iter_command_paths(root, include_root=False) if cp.path}
-# ``polylogue`` subcommands that were removed/renamed. The root command is
-# query-first — any bare token after ``polylogue`` is normally a valid FTS
-# query, not a typo — so a removed command name (``polylogue list``) is
-# indistinguishable from a search ("find sessions matching 'list'") without
-# remembering it once *was* a command. This intentionally small, documented set
-# replaces the previous hand-maintained per-flag denylist for the cases where
-# command recognition alone cannot fire.
-REMOVED_POLYLOGUE_COMMANDS: dict[str, str] = {
- "list": "polylogue: the 'list' verb was removed; use 'read --all' (optionally with --format).",
- "show": "polylogue: the 'show' verb was removed; use 'read --view transcript' for one session.",
-}
-
-
# Dated point-in-time records under these trees assert the command surface *as
# of their date*, not the current one. Holding them to live-command accuracy
# would force rewriting history, so they are excluded from the drift lint.
-_EXCLUDED_DOC_DIRS: tuple[str, ...] = ("docs/audits",)
+# Audits record past state and designs may describe proposed interfaces. Neither
+# is a contract for the currently installed command tree.
+_EXCLUDED_DOC_DIRS: tuple[str, ...] = ("docs/audits", "docs/design")
def _doc_files(root: Path) -> list[Path]:
@@ -141,44 +126,9 @@ def _doc_files(root: Path) -> list[Path]:
# neighbours such as ``polylogued.service`` (systemd unit) or
# ``polylogue-mcp`` (sibling executable). The preceding ``(? tuple[str, ...]:
def _invocation_tokens(rest: str) -> list[str]:
- """Ordered raw tokens (flags kept) up to a shell/pipeline boundary."""
+ """Shell tokens (flags kept) up to a shell/pipeline boundary."""
stripped = rest.lstrip()
- for stop in ("&&", "||", "|", ";", "#", "$(", "`"):
- idx = stripped.find(stop)
- if idx >= 0:
- stripped = stripped[:idx]
+ if stripped.endswith("\\"):
+ stripped = stripped[:-1].rstrip()
+ lexer = shlex.shlex(stripped, posix=True, punctuation_chars="|;&")
+ lexer.whitespace_split = True
+ lexer.commenters = "#"
tokens: list[str] = []
- for part in stripped.split():
- cleaned = part.strip(".,:;\"'`()[]<>")
+ for part in lexer:
+ if part in {"&&", "||", "|", ";"} or part.startswith(("$(", "`")):
+ break
+ cleaned = part.strip(".,:;`()[]<>")
if cleaned:
tokens.append(cleaned)
return tokens
-def _polylogue_invocation_errors(
+def _polylogue_query_intent_errors(
+ rel: str,
+ line: int,
+ tokens: list[str],
+ *,
+ ctx: _ClickContext,
+) -> list[str]:
+ """Apply the product CLI's strict query-intent floor without executing it."""
+
+ from polylogue.cli.query_group import _split_query_mode_args, has_signalled_query_intent
+
+ if not isinstance(ctx.root, click.Group):
+ return []
+ try:
+ _, query_terms, has_subcommand, explicit_query = _split_query_mode_args(ctx.root, list(tokens))
+ except click.ClickException as exc:
+ return [f"{rel}:{line}: invalid 'polylogue' invocation: {exc.format_message()}"]
+
+ if has_subcommand:
+ return []
+ if has_signalled_query_intent(query_terms, explicit_query=explicit_query):
+ return []
+ invocation = " ".join(("polylogue", *tokens))
+ return [
+ f"{rel}:{line}: '{invocation}' does not signal query intent; "
+ "use `polylogue find ...`, quote the free-text expression, or use field syntax"
+ ]
+
+
+def _click_invocation_errors(
rel: str,
line: int,
rest: str,
*,
- ctx: _PolylogueContext,
+ surface: str,
+ ctx: _ClickContext,
) -> list[str]:
- """Validate a single ``polylogue ...`` invocation.
+ """Validate flags for a command path derived from the live Click tree.
- Opt-in by command recognition: a removed command name fails; a recognized
- command path has its long-flags validated against ``root ∪ path ∪ direct``
- options; a leading token that resolves to neither is left alone so
- query-first FTS examples (``polylogue rate limiting retries``) stay legal.
+ Validation opts in only after command recognition. This preserves
+ query-first free text for ``polylogue`` while still checking strict daemon
+ invocations after their command has been identified.
"""
- tokens = _invocation_tokens(rest)
+ try:
+ tokens = _invocation_tokens(rest)
+ except ValueError as exc:
+ return [f"{rel}:{line}: invalid shell quoting after '{surface}': {exc}"]
if not tokens:
return []
- # 1. Command detection: the first bare token that is a known/removed command.
+ errors = _polylogue_query_intent_errors(rel, line, tokens, ctx=ctx) if surface == "polylogue" else []
+
+ # Command detection: the first bare token that is a known command.
# A token consumed as the value of a root value-flag (``--add-tag export``)
# is skipped so a flag value is never read as a subcommand.
start: int | None = None
@@ -279,8 +266,6 @@ def _polylogue_invocation_errors(
if "=" not in tok and tok in ctx.value_flags:
skip_next = True
continue
- if tok in REMOVED_POLYLOGUE_COMMANDS:
- return [f"{rel}:{line}: '{tok}' — {REMOVED_POLYLOGUE_COMMANDS[tok]}"]
if (tok,) in ctx.path_flags:
start, verb = idx, tok
break
@@ -289,7 +274,7 @@ def _polylogue_invocation_errors(
if verb is None or start is None or "then" in tokens:
# Unrecognized leading token (query-first) or a ``then`` chain whose
# flags attribute to different verbs — leave it alone.
- return []
+ return errors
# 2. Resolve the full command path by descending on consecutive bare tokens
# that are children of the current path. Flags are skipped; the first bare
@@ -310,8 +295,7 @@ def _polylogue_invocation_errors(
for depth in range(1, len(path) + 1):
valid |= ctx.path_flags.get(path[:depth], frozenset())
- errors: list[str] = []
- label = "polylogue " + " ".join(path)
+ label = surface + " " + " ".join(path)
for tok in tokens:
if tok == "--": # end-of-options; remainder is positional
break
@@ -379,40 +363,36 @@ def _code_segments(text: str) -> list[tuple[int, str]]:
@dataclass(frozen=True)
-class _PolylogueContext:
+class _ClickContext:
+ root: click.Command
root_flags: frozenset[str]
value_flags: frozenset[str]
path_flags: dict[tuple[str, ...], frozenset[str]]
-def _build_polylogue_context() -> _PolylogueContext:
- cli = _polylogue_cli()
- return _PolylogueContext(
- root_flags=_long_opts(cli),
- value_flags=_polylogue_root_value_flags(cli),
- path_flags=_polylogue_path_flags(cli),
+def _build_click_context(root: click.Command) -> _ClickContext:
+ return _ClickContext(
+ root=root,
+ root_flags=_long_opts(root),
+ value_flags=_polylogue_root_value_flags(root),
+ path_flags=_click_path_flags(root),
)
def _scan_file(
- path: Path, root: Path, polylogue_ctx: _PolylogueContext | None = None
+ path: Path,
+ root: Path,
+ polylogue_ctx: _ClickContext | None = None,
+ polylogued_ctx: _ClickContext | None = None,
) -> tuple[list[DocCommandRef], list[str]]:
rel = path.relative_to(root).as_posix()
refs: list[DocCommandRef] = []
- stale_hits: list[str] = []
+ command_errors: list[str] = []
try:
text = path.read_text(encoding="utf-8")
except OSError as exc:
return refs, [f"{rel}: read error: {exc}"]
- # Stale-substring check runs against full lines so it catches the
- # token sequence regardless of code-fence wrapping.
- for line_no, line in enumerate(text.splitlines(), start=1):
- sanitized = re.sub(r"\]\([^)]+\)", "]()", line)
- for needle, hint in STALE_INVOCATIONS:
- if needle in sanitized:
- stale_hits.append(f"{rel}:{line_no}: stale invocation '{needle.rstrip()}' — {hint}")
-
# Subcommand validity is checked only inside code segments, and only
# when the surface name appears in a command-start position. Prose
# inside ``# comment`` lines of a fenced bash block is skipped so a
@@ -440,13 +420,17 @@ def _scan_file(
rest = match.group(2)
if surface == "polylogue":
if polylogue_ctx is not None:
- stale_hits.extend(_polylogue_invocation_errors(rel, line_no, rest, ctx=polylogue_ctx))
+ command_errors.extend(
+ _click_invocation_errors(rel, line_no, rest, surface=surface, ctx=polylogue_ctx)
+ )
continue
+ if surface == "polylogued" and polylogued_ctx is not None:
+ command_errors.extend(_click_invocation_errors(rel, line_no, rest, surface=surface, ctx=polylogued_ctx))
token = _surface_subcommand(surface, rest)
if token is None:
continue
refs.append(DocCommandRef(surface=surface, subcommand=token, file=path, line=line_no))
- return refs, stale_hits
+ return refs, command_errors
def check_docs(root: Path | None = None) -> tuple[list[str], int]:
@@ -457,12 +441,13 @@ def check_docs(root: Path | None = None) -> tuple[list[str], int]:
"polylogued": _polylogued_subcommands(),
"devtools": _devtools_subcommands(),
}
- polylogue_ctx = _build_polylogue_context()
+ polylogue_ctx = _build_click_context(_polylogue_cli())
+ polylogued_ctx = _build_click_context(polylogued_root)
errors: list[str] = []
for path in files:
- refs, stale = _scan_file(path, target_root, polylogue_ctx)
- errors.extend(stale)
+ refs, command_errors = _scan_file(path, target_root, polylogue_ctx, polylogued_ctx)
+ errors.extend(command_errors)
rel = path.relative_to(target_root).as_posix()
for ref in refs:
known = surface_names[ref.surface]
diff --git a/devtools/verify_docs_coverage.py b/devtools/verify_docs_coverage.py
deleted file mode 100644
index 1f860ddd08..0000000000
--- a/devtools/verify_docs_coverage.py
+++ /dev/null
@@ -1,225 +0,0 @@
-"""Verify every public CLI command, MCP tool, config key, and stable daemon
-route is reachable (named) from the docs tree.
-
-This is the reverse direction of ``devtools verify doc-commands`` (which
-checks that every command *mentioned* in the docs resolves to a real
-command). This lint checks that every real public surface is *mentioned*
-somewhere in the docs tree, so a new command/tool/config-key/route shipped
-without a matching doc update fails a gate instead of silently rotting into
-an undocumented surface (polylogue-3tl.9).
-
-Four typed inventories, each already maintained for a different purpose and
-reused here rather than re-derived:
-
-- CLI commands: ``polylogue.cli.command_inventory.iter_command_paths`` over
- the live Click tree.
-- MCP tools: ``tests.infra.mcp.EXPECTED_TOOL_NAMES``.
-- Config keys: ``polylogue.config.config_inventory_by_key``.
-- Daemon routes: ``polylogue.daemon.route_contracts.ROUTE_CONTRACTS``,
- restricted to ``stable``/``shell_supported`` routes (``operational`` and
- ``private`` routes are internal-only by design and are not expected to
- have reader-facing docs).
-
-"Reachable from the docs tree" is a coarse but honest check: the surface's
-identifying token (command display name, tool name, config key, or route
-pattern) appears verbatim somewhere in ``README.md`` or ``docs/**/*.md``.
-This will not catch a doc that mentions a command name in an unrelated
-sentence, but it does catch the failure mode this bead exists for: a surface
-added with zero doc footprint.
-
-Baseline
---------
-
-The repo already carries pre-existing undocumented surfaces (discovered by
-running this lint against HEAD when it was introduced). Those are recorded
-in ``docs/plans/docs-coverage-baseline.yaml`` as tracked debt so introducing
-the gate does not require writing ~100 doc entries in the same change. The
-baseline is a ratchet, not a target: it must never grow, and CI should trend
-it toward empty. A baseline entry whose surface has since been documented is
-reported as "stale" (should be removed) but does not fail the lane.
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import sys
-from dataclasses import dataclass
-
-try:
- import yaml
-except ImportError: # pragma: no cover - yaml is a hard repo dep
- yaml = None # type: ignore[assignment]
-
-from devtools import repo_root as _get_root
-
-ROOT = _get_root()
-DOCS_ROOT = ROOT / "docs"
-BASELINE_PATH = ROOT / "docs" / "plans" / "docs-coverage-baseline.yaml"
-
-Surface = str # "cli" | "mcp" | "config" | "route"
-
-
-@dataclass(frozen=True, slots=True)
-class CoverageGap:
- surface: Surface
- name: str
-
-
-def _docs_corpus_text() -> str:
- """Concatenated text of every reader-facing Markdown page."""
- parts = [(ROOT / "README.md").read_text(encoding="utf-8")]
- for path in sorted(DOCS_ROOT.rglob("*.md")):
- parts.append(path.read_text(encoding="utf-8", errors="ignore"))
- return "\n".join(parts)
-
-
-def _cli_inventory() -> tuple[str, ...]:
- from polylogue.cli.click_app import cli
- from polylogue.cli.command_inventory import iter_command_paths
-
- return tuple(sorted({path.display_name for path in iter_command_paths(cli)}))
-
-
-def _mcp_inventory() -> tuple[str, ...]:
- from tests.infra.mcp import EXPECTED_TOOL_NAMES
-
- return tuple(sorted(EXPECTED_TOOL_NAMES))
-
-
-def _config_inventory() -> tuple[str, ...]:
- from polylogue.config import config_inventory_by_key
-
- return tuple(sorted(config_inventory_by_key()))
-
-
-def _route_inventory() -> tuple[str, ...]:
- from polylogue.daemon.route_contracts import ROUTE_CONTRACTS
-
- return tuple(
- sorted({route.pattern for route in ROUTE_CONTRACTS if route.stability in ("stable", "shell_supported")})
- )
-
-
-def _all_inventories() -> dict[Surface, tuple[str, ...]]:
- return {
- "cli": _cli_inventory(),
- "mcp": _mcp_inventory(),
- "config": _config_inventory(),
- "route": _route_inventory(),
- }
-
-
-def _load_baseline() -> dict[Surface, dict[str, str]]:
- """Return ``{surface: {name: reason}}`` from the baseline YAML."""
- if not BASELINE_PATH.exists():
- return {}
- if yaml is None:
- raise RuntimeError("PyYAML is required to read the docs coverage baseline")
- data = yaml.safe_load(BASELINE_PATH.read_text(encoding="utf-8")) or {}
- out: dict[Surface, dict[str, str]] = {}
- for surface, entries in (data.get("gaps") or {}).items():
- surface_map: dict[str, str] = {}
- for entry in entries or ():
- if isinstance(entry, str):
- surface_map[entry] = ""
- elif isinstance(entry, dict):
- name = entry.get("name")
- if isinstance(name, str):
- surface_map[name] = str(entry.get("reason", ""))
- out[surface] = surface_map
- return out
-
-
-@dataclass(frozen=True, slots=True)
-class CoverageReport:
- gaps: tuple[CoverageGap, ...]
- stale_baseline: tuple[CoverageGap, ...]
- inventory_sizes: dict[Surface, int]
-
- @property
- def ok(self) -> bool:
- return not self.gaps
-
-
-def collect_coverage(*, docs_text: str | None = None) -> CoverageReport:
- text = docs_text if docs_text is not None else _docs_corpus_text()
- baseline = _load_baseline()
- inventories = _all_inventories()
-
- gaps: list[CoverageGap] = []
- stale: list[CoverageGap] = []
- for surface, names in inventories.items():
- surface_baseline = baseline.get(surface, {})
- for name in names:
- documented = name in text
- baselined = name in surface_baseline
- if not documented and not baselined:
- gaps.append(CoverageGap(surface=surface, name=name))
- elif documented and baselined:
- stale.append(CoverageGap(surface=surface, name=name))
-
- return CoverageReport(
- gaps=tuple(gaps),
- stale_baseline=tuple(stale),
- inventory_sizes={surface: len(names) for surface, names in inventories.items()},
- )
-
-
-def _format_report(report: CoverageReport) -> str:
- if report.ok:
- lines = ["docs-coverage: every public CLI command, MCP tool, config key, and stable route is reachable"]
- if report.stale_baseline:
- lines.append("")
- lines.append(f"Stale baseline entries (now documented, remove from {BASELINE_PATH.name}):")
- for gap in report.stale_baseline:
- lines.append(f" {gap.surface}: {gap.name}")
- return "\n".join(lines)
-
- lines = [f"docs-coverage: {len(report.gaps)} undocumented public surface(s), not in the tracked baseline:"]
- by_surface: dict[str, list[str]] = {}
- for gap in report.gaps:
- by_surface.setdefault(gap.surface, []).append(gap.name)
- for surface, names in sorted(by_surface.items()):
- lines.append(f" {surface} ({len(names)}):")
- for name in sorted(names):
- lines.append(f" - {name}")
- lines.append("")
- lines.append(
- f"Fix: document the surface (README.md or docs/**/*.md), or, for pre-existing debt only, "
- f"add it to {BASELINE_PATH.relative_to(ROOT)} with a reason."
- )
- if report.stale_baseline:
- lines.append("")
- lines.append(f"Stale baseline entries (now documented, remove from {BASELINE_PATH.name}):")
- for gap in report.stale_baseline:
- lines.append(f" {gap.surface}: {gap.name}")
- return "\n".join(lines)
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- )
- parser.add_argument("--json", action="store_true", help="emit machine-readable JSON")
- args = parser.parse_args(argv)
-
- report = collect_coverage()
-
- if args.json:
- payload = {
- "ok": report.ok,
- "gaps": [{"surface": g.surface, "name": g.name} for g in report.gaps],
- "stale_baseline": [{"surface": g.surface, "name": g.name} for g in report.stale_baseline],
- "inventory_sizes": report.inventory_sizes,
- }
- print(json.dumps(payload, indent=2))
- else:
- print(_format_report(report))
-
- return 0 if report.ok else 1
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/verify_docs_drift.py b/devtools/verify_docs_drift.py
deleted file mode 100644
index b3ea844c75..0000000000
--- a/devtools/verify_docs_drift.py
+++ /dev/null
@@ -1,318 +0,0 @@
-"""Verify checkable factual claims in the Reference-docs table against current source.
-
-Background
-----------
-
-``CLAUDE.md``'s "Reference docs" table points readers at fifteen hand-written
-markdown files (architecture, internals, testing, CLI/MCP reference, ...).
-Unlike the generated surfaces (``docs/cli-reference.md``'s body, the topology
-projection, the devtools catalog), these docs are free text: nothing forces
-them to track a renamed table, a moved file, or a bumped schema version. Drift
-accumulates silently until an agent or operator hits a stale path/table/flag
-mid-task (polylogue-9e5.13).
-
-This lint does not attempt full natural-language fact-checking. It mechanically
-checks three narrow, high-confidence claim shapes:
-
-1. **File paths** — every backtick-quoted, extension-bearing path referenced in
- a doc must exist on disk (tried as-is, then under ``polylogue/`` for paths
- given relative to the package root).
-2. **Schema versions** — every " schema version N" mention must not
- exceed the tier's current ``*_SCHEMA_VERSION`` constant. (A doc whose
- history stops below the current constant is an incomplete-but-not-false
- history; this lint does not flag that — only a claim of a version that does
- not exist yet.)
-3. **Watchlist table names** — a short, explicit list of table names known to
- have been renamed or removed (e.g. ``artifact_observations`` -> the DDL now
- defines ``raw_artifacts``) must not appear in doc prose describing the
- *current* schema. New renames get added to ``_RENAMED_TABLE_WATCHLIST`` as
- they're discovered rather than the lint attempting a fully generic
- table/column sweep (which would false-positive heavily on code identifiers,
- config keys, and CLI flags that happen to be backtick-quoted snake_case).
-
-Wired into ``devtools verify --lab`` alongside the other policy checks, since
-this is a repo-hygiene boundary check rather than a per-edit gate.
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import re
-import sys
-from dataclasses import dataclass
-from pathlib import Path
-
-_REPO_ROOT = Path(__file__).resolve().parents[1]
-
-# The doc set from CLAUDE.md's "Reference docs" table (paths relative to repo root).
-REFERENCE_DOCS: tuple[str, ...] = (
- "docs/architecture.md",
- "docs/internals.md",
- "docs/architecture-spine.md",
- "CONTRIBUTING.md",
- "TESTING.md",
- "docs/devtools.md",
- "docs/cloud-agents.md",
- "docs/provider-origin-identity.md",
- "docs/search.md",
- "docs/data-model.md",
- "docs/daemon.md",
- "docs/daemon-threat-model.md",
- "docs/cost-model.md",
- "docs/cli-reference.md",
- "docs/mcp-reference.md",
-)
-
-# Renamed/removed table names known from source-history archaeology. Each
-# watchlist entry fires only when the OLD name appears; it does not require
-# the doc to use the new name verbatim (a doc may legitimately say "there is
-# no separate X table; the name is a historical alias for Y").
-_RENAMED_TABLE_WATCHLIST: dict[str, str] = {
- "artifact_observations": "renamed to `raw_artifacts` (see polylogue/storage/sqlite/archive_tiers/source.py)",
-}
-
-# Backtick spans that look like a checkable repo-relative file path: contains
-# a "/" and ends with a common source/doc extension. Deliberately excludes
-# bare module dotted-names, SQL fragments, and shell snippets.
-_PATH_CANDIDATE = re.compile(
- r"`([A-Za-z0-9_./{}\-]+/[A-Za-z0-9_.\-]+\.(?:py|md|sql|json|ya?ml|toml|sh|txt|cfg|ini))"
- r"(?::[A-Za-z_][A-Za-z0-9_]*\(\))?`"
-)
-
-# " schema version N" claims, tier names matching the *_SCHEMA_VERSION constants.
-_SCHEMA_VERSION_CLAIM = re.compile(
- r"\b(Source|Index|Embeddings|User|Ops)\s+schema\s+version\s+(\d+)\b",
- re.IGNORECASE,
-)
-
-
-@dataclass(frozen=True, slots=True)
-class MissingPath:
- doc: str
- line: int
- quoted: str
- tried: tuple[str, ...]
-
-
-@dataclass(frozen=True, slots=True)
-class SchemaVersionOverclaim:
- doc: str
- line: int
- tier: str
- claimed: int
- current: int
-
-
-@dataclass(frozen=True, slots=True)
-class WatchlistHit:
- doc: str
- line: int
- term: str
- note: str
-
-
-@dataclass(frozen=True, slots=True)
-class DriftReport:
- missing_paths: tuple[MissingPath, ...]
- schema_overclaims: tuple[SchemaVersionOverclaim, ...]
- watchlist_hits: tuple[WatchlistHit, ...]
-
- @property
- def ok(self) -> bool:
- return not (self.missing_paths or self.schema_overclaims or self.watchlist_hits)
-
-
-def _current_schema_versions() -> dict[str, int]:
- from polylogue.storage.sqlite.archive_tiers.embeddings import EMBEDDINGS_SCHEMA_VERSION
- from polylogue.storage.sqlite.archive_tiers.index import INDEX_SCHEMA_VERSION
- from polylogue.storage.sqlite.archive_tiers.ops import OPS_SCHEMA_VERSION
- from polylogue.storage.sqlite.archive_tiers.source import SOURCE_SCHEMA_VERSION
- from polylogue.storage.sqlite.archive_tiers.user import USER_SCHEMA_VERSION
-
- return {
- "source": SOURCE_SCHEMA_VERSION,
- "index": INDEX_SCHEMA_VERSION,
- "embeddings": EMBEDDINGS_SCHEMA_VERSION,
- "user": USER_SCHEMA_VERSION,
- "ops": OPS_SCHEMA_VERSION,
- }
-
-
-def _resolve_path(candidate: str) -> tuple[bool, tuple[str, ...]]:
- """Return (found, tried) for a doc-referenced path candidate.
-
- Tried as-is relative to the repo root, then with a ``polylogue/`` prefix
- (many internals.md snippets give paths relative to the package root
- without the leading ``polylogue/`` segment).
- """
- # Expand a single brace-group like "{source,user}" into each alternative;
- # docs use this shorthand for the migrations directory family.
- brace_match = re.search(r"\{([a-z_]+(?:,[a-z_]+)+)\}", candidate)
- variants = (
- [candidate.replace(brace_match.group(0), alt) for alt in brace_match.group(1).split(",")]
- if brace_match
- else [candidate]
- )
-
- tried: list[str] = []
- for variant in variants:
- for prefix in ("", "polylogue/", "tests/"):
- tried_path = f"{prefix}{variant}"
- tried.append(tried_path)
- if (_REPO_ROOT / tried_path).exists():
- return True, tuple(tried)
- return False, tuple(tried)
-
-
-# Phrases that mark a path as a deliberate historical reference (a doc
-# explaining that something used to exist and was retired/removed/superseded),
-# not a live claim that the path exists today.
-_HISTORICAL_MARKERS = ("retired", "superseded", "no longer exists", "was removed", "has been removed")
-
-
-def _check_paths(doc: str, text: str) -> list[MissingPath]:
- missing: list[MissingPath] = []
- lines = text.splitlines()
- # Markdown hard-wraps prose across lines, so a "was retired" clause about a
- # path mentioned earlier in the same paragraph can land a few lines below
- # it. Check each paragraph (blank-line-delimited block) as a whole rather
- # than line-by-line for the historical-reference exemption.
- paragraph_start = 0
- for idx, line in enumerate(lines):
- is_blank = line.strip() == ""
- if is_blank or idx == len(lines) - 1:
- end = idx if is_blank else idx + 1
- paragraph = lines[paragraph_start:end]
- paragraph_text = "\n".join(paragraph).lower()
- is_historical = any(marker in paragraph_text for marker in _HISTORICAL_MARKERS)
- if not is_historical:
- for offset, para_line in enumerate(paragraph):
- lineno = paragraph_start + offset + 1
- for match in _PATH_CANDIDATE.finditer(para_line):
- candidate = match.group(1)
- # Runtime/generated output (gitignored under .cache/, .local/)
- # only exists after a command has run; not a stale doc claim.
- if candidate.startswith((".cache/", ".local/")):
- continue
- found, tried = _resolve_path(candidate)
- if not found:
- missing.append(MissingPath(doc=doc, line=lineno, quoted=candidate, tried=tried))
- paragraph_start = idx + 1
- return missing
-
-
-def _check_schema_versions(doc: str, text: str, current: dict[str, int]) -> list[SchemaVersionOverclaim]:
- overclaims: list[SchemaVersionOverclaim] = []
- for lineno, line in enumerate(text.splitlines(), start=1):
- for match in _SCHEMA_VERSION_CLAIM.finditer(line):
- tier = match.group(1).lower()
- claimed = int(match.group(2))
- current_version = current.get(tier)
- if current_version is not None and claimed > current_version:
- overclaims.append(
- SchemaVersionOverclaim(doc=doc, line=lineno, tier=tier, claimed=claimed, current=current_version)
- )
- return overclaims
-
-
-def _check_watchlist(doc: str, text: str) -> list[WatchlistHit]:
- hits: list[WatchlistHit] = []
- for lineno, line in enumerate(text.splitlines(), start=1):
- for term, note in _RENAMED_TABLE_WATCHLIST.items():
- if term in line:
- # A line explicitly explaining the alias/rename (contains "renamed"
- # or "historical alias") is documenting the fact, not asserting it.
- if "historical alias" in line or "renamed" in line:
- continue
- hits.append(WatchlistHit(doc=doc, line=lineno, term=term, note=note))
- return hits
-
-
-def collect_drift(docs: tuple[str, ...] | None = None) -> DriftReport:
- # Resolved at call time (not bound as a default-argument value) so a test
- # or caller that monkeypatches the module-level REFERENCE_DOCS/_REPO_ROOT
- # observes the change.
- if docs is None:
- docs = REFERENCE_DOCS
- current = _current_schema_versions()
- missing_paths: list[MissingPath] = []
- schema_overclaims: list[SchemaVersionOverclaim] = []
- watchlist_hits: list[WatchlistHit] = []
-
- for doc in docs:
- doc_path = _REPO_ROOT / doc
- if not doc_path.exists():
- missing_paths.append(MissingPath(doc=doc, line=0, quoted=doc, tried=(doc,)))
- continue
- text = doc_path.read_text(encoding="utf-8")
- missing_paths.extend(_check_paths(doc, text))
- schema_overclaims.extend(_check_schema_versions(doc, text, current))
- watchlist_hits.extend(_check_watchlist(doc, text))
-
- return DriftReport(
- missing_paths=tuple(missing_paths),
- schema_overclaims=tuple(schema_overclaims),
- watchlist_hits=tuple(watchlist_hits),
- )
-
-
-def _format_report(report: DriftReport) -> str:
- if report.ok:
- return "docs drift: zero unhandled drift across the reference-docs sweep."
-
- lines: list[str] = []
- if report.missing_paths:
- lines.append(f"Missing referenced paths: {len(report.missing_paths)}")
- for missing in report.missing_paths:
- lines.append(f" {missing.doc}:{missing.line}: `{missing.quoted}` (tried: {', '.join(missing.tried)})")
- lines.append("")
- if report.schema_overclaims:
- lines.append(f"Schema version overclaims: {len(report.schema_overclaims)}")
- for overclaim in report.schema_overclaims:
- lines.append(
- f" {overclaim.doc}:{overclaim.line}: {overclaim.tier} schema version {overclaim.claimed} "
- f"claimed, current constant is {overclaim.current}"
- )
- lines.append("")
- if report.watchlist_hits:
- lines.append(f"Renamed/removed table names still referenced: {len(report.watchlist_hits)}")
- for hit in report.watchlist_hits:
- lines.append(f" {hit.doc}:{hit.line}: `{hit.term}` -- {hit.note}")
- lines.append("")
- return "\n".join(lines)
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- )
- parser.add_argument("--json", action="store_true", help="emit machine-readable JSON")
- args = parser.parse_args(argv)
-
- report = collect_drift()
-
- if args.json:
- payload = {
- "missing_paths": [
- {"doc": m.doc, "line": m.line, "quoted": m.quoted, "tried": list(m.tried)} for m in report.missing_paths
- ],
- "schema_overclaims": [
- {"doc": s.doc, "line": s.line, "tier": s.tier, "claimed": s.claimed, "current": s.current}
- for s in report.schema_overclaims
- ],
- "watchlist_hits": [
- {"doc": w.doc, "line": w.line, "term": w.term, "note": w.note} for w in report.watchlist_hits
- ],
- "ok": report.ok,
- }
- print(json.dumps(payload, indent=2))
- else:
- print(_format_report(report))
-
- return 0 if report.ok else 1
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/verify_layering.py b/devtools/verify_layering.py
index c42243a544..8b8d344753 100644
--- a/devtools/verify_layering.py
+++ b/devtools/verify_layering.py
@@ -25,6 +25,7 @@
from pathlib import Path
from devtools import repo_root as _get_root
+from devtools.manifest_models import validate_layering_manifest
from polylogue.core.json import dumps
from polylogue.storage.sqlite.archive_tiers import ARCHIVE_DDL_BY_TIER
@@ -745,6 +746,14 @@ def main(argv: list[str] | None = None) -> int:
return 1
manifest = _load_manifest(rules_path)
+ schema_errors = validate_layering_manifest(manifest, path=str(rules_path))
+ if schema_errors:
+ if args.json:
+ print(dumps({"ok": False, "schema_errors": schema_errors}, indent=2))
+ else:
+ for error in schema_errors:
+ print(f" ✗ {error}", file=sys.stderr)
+ return 1
rules = _load_rules(rules_path)
violations: list[dict[str, object]] = []
baselined: list[dict[str, object]] = []
diff --git a/devtools/verify_manifests.py b/devtools/verify_manifests.py
deleted file mode 100644
index ed1679915c..0000000000
--- a/devtools/verify_manifests.py
+++ /dev/null
@@ -1,720 +0,0 @@
-"""Verify internal consistency across all docs/plans/*.yaml manifests.
-
-Ensures manifest files are valid YAML, their cross-references are
-consistent, and their structure matches the declared Pydantic models.
-Runs as part of devtools verify.
-"""
-
-from __future__ import annotations
-
-import re
-import shlex
-import sys
-from datetime import UTC, date, datetime, timedelta
-from pathlib import Path
-from typing import Any
-
-import yaml
-
-from devtools import repo_root as _get_root
-from devtools.authored_scenario_catalog import get_authored_scenario_catalog
-from devtools.command_catalog import COMMANDS, command_name_from_tokens
-from devtools.manifest_models import validate_manifest
-from devtools.verify_ci_workflows import WorkflowInventory, inventory_workflows
-
-_COVERAGE_AXIS_KEYS = ("domain", "subject", "area", "dimension", "artifact", "platform", "concern")
-_COVERAGE_GAP_SEVERITIES = {"info", "minor", "major", "serious"}
-_EVIDENCE_COMMANDS = {
- "pytest",
- "ruff",
- "mypy",
- "nix",
- "polylogue",
- "polylogued",
- "polylogue-mcp",
- # Browser-extension build pipeline (browser-extension/scripts/*.mjs).
- "npm",
- "node",
-}
-_COVERAGE_COMMAND_FIELDS = {"generated_by", "verified_by", "verification_command"}
-_COVERAGE_PATH_FIELDS = {"config_location", "location", "path", "strategies_location"}
-_COVERAGE_PATH_LIST_FIELDS = {"locations", "paths_to_mutate", "tests"}
-
-
-def load_manifest(path: Path) -> dict[str, object]:
- """Load a YAML manifest and return its parsed contents."""
- try:
- with open(path, encoding="utf-8") as f:
- data = yaml.safe_load(f)
- if not isinstance(data, dict):
- raise ValueError(f"expected mapping, got {type(data).__name__}")
- return data
- except Exception as exc:
- raise ValueError(f"failed to load {path}: {exc}") from exc
-
-
-def check_coverage_gaps(plans_dir: Path) -> list[str]:
- """Validate that passive coverage gaps are tracked as actionable records."""
- errors: list[str] = []
- gap_ids: set[str] = set()
- gap_subject_leaves: set[str] = set()
- for path in sorted(plans_dir.glob("*coverage*.yaml")):
- try:
- data = load_manifest(path)
- except ValueError as exc:
- errors.append(str(exc))
- continue
- gaps = data.get("coverage_gaps")
- if gaps is None:
- continue
- if not isinstance(gaps, list):
- errors.append(f"{path}: 'coverage_gaps' must be a list")
- continue
- for index, gap in enumerate(gaps):
- if not isinstance(gap, dict):
- errors.append(f"{path}: coverage_gaps[{index}] must be a mapping")
- continue
- label = _coverage_gap_label(path, index, gap)
- gap_id = gap.get("id")
- if not isinstance(gap_id, str) or not gap_id.strip():
- errors.append(f"{label} missing id")
- elif gap_id in gap_ids:
- errors.append(f"{label} duplicate id {gap_id!r}")
- else:
- gap_ids.add(gap_id)
- gap_subject_leaf = _coverage_gap_slug(gap_id)
- if gap_subject_leaf in gap_subject_leaves:
- errors.append(f"{label} duplicate coverage subject slug {gap_subject_leaf!r}")
- else:
- gap_subject_leaves.add(gap_subject_leaf)
- if not any(isinstance(gap.get(key), str) and gap.get(key, "").strip() for key in _COVERAGE_AXIS_KEYS):
- errors.append(f"{path}: coverage_gaps[{index}] missing coverage axis")
- if not isinstance(gap.get("gap"), str) or not gap.get("gap", "").strip():
- errors.append(f"{label} missing gap text")
- if not isinstance(gap.get("owner"), str) or not gap.get("owner", "").strip():
- errors.append(f"{label} missing owner")
- severity = gap.get("severity")
- if severity not in _COVERAGE_GAP_SEVERITIES:
- errors.append(f"{label} missing or invalid severity")
- for field in ("declared_at", "review_after"):
- if not _valid_iso_date(gap.get(field)):
- errors.append(f"{label} missing or invalid {field}")
- issue = gap.get("issue")
- suppression = gap.get("suppression")
- bead = gap.get("bead")
- if not _valid_issue_ref(issue) and not _valid_suppression_ref(suppression) and not _valid_bead_ref(bead):
- errors.append(f"{label} missing issue, bead, or suppression")
- next_evidence = gap.get("next_evidence")
- if not isinstance(next_evidence, str) or not next_evidence.strip():
- errors.append(f"{label} missing next_evidence")
- elif not _resolvable_next_evidence(next_evidence):
- errors.append(f"{label} next_evidence does not resolve to a known command")
- return errors
-
-
-def check_coverage_references(plans_dir: Path) -> list[str]:
- """Validate locally checkable command and path references in coverage manifests."""
- errors: list[str] = []
- repo_root = _repo_root_for_plans(plans_dir)
- for path in sorted(plans_dir.glob("*coverage*.yaml")):
- try:
- data = load_manifest(path)
- except ValueError as exc:
- errors.append(str(exc))
- continue
- for ref_path, key, value in _iter_manifest_fields(data):
- label = f"{path}: {'.'.join(ref_path)}"
- if (
- key in _COVERAGE_COMMAND_FIELDS
- and isinstance(value, str)
- and value.strip()
- and not _resolvable_command(value)
- ):
- errors.append(f"{label} command does not resolve: {value!r}")
- if key in _COVERAGE_PATH_FIELDS and isinstance(value, str) and value.strip():
- candidate = _manifest_path_token(value)
- if candidate and not _manifest_path_exists(repo_root, candidate):
- errors.append(f"{label} path does not exist: {candidate!r}")
- if key in _COVERAGE_PATH_LIST_FIELDS and isinstance(value, list):
- for item_index, item in enumerate(value):
- if not isinstance(item, str) or not item.strip():
- continue
- candidate = _manifest_path_token(item)
- if candidate and not _manifest_path_exists(repo_root, candidate):
- errors.append(f"{label}[{item_index}] path does not exist: {candidate!r}")
- return errors
-
-
-def check_coverage_status_claims(plans_dir: Path) -> list[str]:
- """Validate internally contradictory coverage status claims."""
- errors: list[str] = []
- for path in sorted(plans_dir.glob("*coverage*.yaml")):
- try:
- data = load_manifest(path)
- except ValueError as exc:
- errors.append(str(exc))
- continue
- for ref_path, payload in _iter_manifest_mappings(data):
- label = f"{path}: {'.'.join(ref_path)}"
- implemented = payload.get("implemented")
- if implemented is True:
- if not _non_empty_list(payload.get("controls")):
- errors.append(f"{label} implemented=true but controls are missing or empty")
- if not _has_test_coverage_location(payload.get("test_coverage")):
- errors.append(f"{label} implemented=true but test_coverage.location is missing")
- elif implemented is False:
- if _non_empty_list(payload.get("controls")):
- errors.append(f"{label} implemented=false but controls are declared")
- if _has_test_coverage_location(payload.get("test_coverage")):
- errors.append(f"{label} implemented=false but test_coverage.location is declared")
- return errors
-
-
-def check_campaign_coverage_catalog(plans_dir: Path) -> list[str]:
- """Validate campaign-coverage.yaml against the authored campaign catalog."""
- errors: list[str] = []
- path = plans_dir / "campaign-coverage.yaml"
- if not path.exists():
- return errors
- try:
- data = load_manifest(path)
- except ValueError as exc:
- return [str(exc)]
-
- catalog = get_authored_scenario_catalog()
- errors.extend(
- _compare_campaign_section(
- path=path,
- section="mutation_campaigns",
- actual=data.get("mutation_campaigns"),
- expected={
- entry.name: {
- "paths_to_mutate": tuple(entry.paths_to_mutate),
- "tests": tuple(entry.tests),
- "status": "active",
- }
- for entry in catalog.mutation_campaigns
- },
- )
- )
- errors.extend(
- _compare_campaign_section(
- path=path,
- section="benchmark_campaigns",
- actual=data.get("benchmark_campaigns"),
- expected={
- entry.name: {
- "tests": tuple(entry.tests),
- "status": "active",
- }
- for entry in catalog.benchmark_campaigns
- },
- )
- )
- errors.extend(_check_campaign_test_paths(path, data, plans_dir))
- return errors
-
-
-def _check_campaign_test_paths(
- path: Path,
- data: dict[str, object],
- plans_dir: Path,
-) -> list[str]:
- """Verify every active campaign declares non-empty tests/paths that exist on disk.
-
- This closes the manifest-only loophole where a row can carry a name and a
- description but route nowhere executable.
- """
- repo_root = _repo_root_for_plans(plans_dir)
- errors: list[str] = []
- for section in ("mutation_campaigns", "benchmark_campaigns"):
- value = data.get(section)
- if not isinstance(value, list):
- continue
- for index, item in enumerate(value):
- if not isinstance(item, dict):
- continue
- name = item.get("name")
- label_name = f"{name!r}" if isinstance(name, str) and name.strip() else f"index {index}"
- status = item.get("status", "active")
- if status != "active":
- continue
- tests = item.get("tests")
- if not isinstance(tests, list) or not tests:
- errors.append(
- f"{path}: {section} campaign {label_name} declares no tests; "
- "active campaigns must point at executable test paths"
- )
- else:
- for test_index, test_path in enumerate(tests):
- if not isinstance(test_path, str) or not test_path.strip():
- errors.append(
- f"{path}: {section} campaign {label_name} tests[{test_index}] must be a non-empty string"
- )
- continue
- candidate = _manifest_path_token(test_path)
- if candidate and not _manifest_path_exists(repo_root, candidate):
- errors.append(
- f"{path}: {section} campaign {label_name} tests[{test_index}] "
- f"path does not exist: {candidate!r}"
- )
- if section == "mutation_campaigns":
- paths_to_mutate = item.get("paths_to_mutate")
- if not isinstance(paths_to_mutate, list) or not paths_to_mutate:
- errors.append(
- f"{path}: {section} campaign {label_name} declares no paths_to_mutate; "
- "active mutation campaigns must target executable source paths"
- )
- errors.extend(_check_campaign_freshness(path, section, label_name, item, repo_root))
- return errors
-
-
-def _check_campaign_freshness(
- path: Path,
- section: str,
- label_name: str,
- item: dict[object, object],
- repo_root: Path,
-) -> list[str]:
- """Enforce ``freshness_days`` / ``artifact_glob`` when declared.
-
- Absent fields stay silent so rows opt in gradually. When declared, the most
- recent matching artifact must exist, be non-empty, and (if
- ``freshness_days`` is set) be newer than the declared window. Without an
- explicit ``artifact_glob``, benchmark campaigns default to
- ``.local/benchmark-campaigns/*-.json`` — the path written by
- ``devtools bench campaign run``.
- """
- errors: list[str] = []
- freshness_days = item.get("freshness_days")
- artifact_glob = item.get("artifact_glob")
- name = item.get("name")
- if not isinstance(name, str) or not name.strip():
- return errors
-
- fresh_declared = isinstance(freshness_days, int) and freshness_days > 0
- glob_declared = isinstance(artifact_glob, str) and bool(artifact_glob.strip())
- if not fresh_declared and not glob_declared:
- return errors
-
- if glob_declared:
- assert isinstance(artifact_glob, str)
- glob = artifact_glob.strip()
- elif section == "benchmark_campaigns":
- glob = f".local/benchmark-campaigns/*-{name}.json"
- elif section == "mutation_campaigns":
- # Default mutation-campaign artifact layout (#1304). Matches
- # devtools.mutmut_campaign.default_artifact_paths.
- glob = f".local/mutation-campaigns/{name}/*.json"
- else:
- errors.append(
- f"{path}: {section} campaign {label_name} declares freshness_days without "
- "an artifact_glob; only mutation_campaigns and benchmark_campaigns have a default location"
- )
- return errors
-
- matches = sorted(repo_root.glob(glob))
- if not matches:
- errors.append(
- f"{path}: {section} campaign {label_name} declares artifact glob {glob!r} but no matching artifacts exist"
- )
- return errors
-
- newest = max(matches, key=lambda p: p.stat().st_mtime)
- if newest.stat().st_size == 0:
- errors.append(f"{path}: {section} campaign {label_name} newest artifact {newest.name!r} is empty")
-
- if fresh_declared:
- assert isinstance(freshness_days, int)
- age = datetime.now(UTC) - datetime.fromtimestamp(newest.stat().st_mtime, tz=UTC)
- if age > timedelta(days=freshness_days):
- errors.append(
- f"{path}: {section} campaign {label_name} newest artifact {newest.name!r} is "
- f"{age.days}d old, exceeding freshness_days={freshness_days}"
- )
-
- return errors
-
-
-def _compare_campaign_section(
- *,
- path: Path,
- section: str,
- actual: object,
- expected: dict[str, dict[str, Any]],
-) -> list[str]:
- errors: list[str] = []
- actual_by_name = _manifest_named_entries(path, section, actual, errors)
- if actual_by_name is None:
- return errors
-
- actual_names = set(actual_by_name)
- expected_names = set(expected)
- for name in sorted(expected_names - actual_names):
- errors.append(f"{path}: {section} missing catalog campaign {name!r}")
- for name in sorted(actual_names - expected_names):
- errors.append(f"{path}: {section} declares unknown campaign {name!r}")
-
- for name in sorted(actual_names & expected_names):
- payload = actual_by_name[name]
- for field, expected_value in expected[name].items():
- actual_value: object
- if isinstance(expected_value, tuple):
- actual_value = _string_tuple(payload.get(field))
- else:
- actual_value = payload.get(field)
- if actual_value != expected_value:
- errors.append(
- f"{path}: {section}[{name!r}] {field} does not match authored catalog "
- f"(expected {expected_value!r}, got {actual_value!r})"
- )
- return errors
-
-
-def _manifest_named_entries(
- path: Path,
- section: str,
- value: object,
- errors: list[str],
-) -> dict[str, dict[object, object]] | None:
- if value is None:
- return {}
- if not isinstance(value, list):
- errors.append(f"{path}: {section!r} must be a list")
- return None
- entries: dict[str, dict[object, object]] = {}
- for index, item in enumerate(value):
- if not isinstance(item, dict):
- errors.append(f"{path}: {section}[{index}] must be a mapping")
- continue
- name = item.get("name")
- if not isinstance(name, str) or not name.strip():
- errors.append(f"{path}: {section}[{index}] missing name")
- continue
- if name in entries:
- errors.append(f"{path}: {section}[{index}] duplicate campaign name {name!r}")
- continue
- entries[name] = item
- return entries
-
-
-def _string_tuple(value: object) -> tuple[str, ...]:
- if not isinstance(value, list):
- return ()
- return tuple(item for item in value if isinstance(item, str))
-
-
-def _iter_manifest_mappings(
- value: object, prefix: tuple[str, ...] = ()
-) -> list[tuple[tuple[str, ...], dict[object, object]]]:
- mappings: list[tuple[tuple[str, ...], dict[object, object]]] = []
- if isinstance(value, dict):
- mappings.append((prefix, value))
- for raw_key, child in value.items():
- mappings.extend(_iter_manifest_mappings(child, (*prefix, str(raw_key))))
- elif isinstance(value, list):
- for index, child in enumerate(value):
- mappings.extend(_iter_manifest_mappings(child, (*prefix, str(index))))
- return mappings
-
-
-def _non_empty_list(value: object) -> bool:
- return isinstance(value, list) and bool(value)
-
-
-def _has_test_coverage_location(value: object) -> bool:
- if not isinstance(value, dict):
- return False
- location = value.get("location")
- return isinstance(location, str) and bool(_manifest_path_token(location))
-
-
-def _iter_manifest_fields(value: object, prefix: tuple[str, ...] = ()) -> list[tuple[tuple[str, ...], str, object]]:
- fields: list[tuple[tuple[str, ...], str, object]] = []
- if isinstance(value, dict):
- for raw_key, child in value.items():
- key = str(raw_key)
- child_path = (*prefix, key)
- fields.append((child_path, key, child))
- fields.extend(_iter_manifest_fields(child, child_path))
- elif isinstance(value, list):
- for index, child in enumerate(value):
- fields.extend(_iter_manifest_fields(child, (*prefix, str(index))))
- return fields
-
-
-def _repo_root_for_plans(plans_dir: Path) -> Path:
- if plans_dir.name == "plans" and plans_dir.parent.name == "docs":
- return plans_dir.parent.parent
- return plans_dir
-
-
-def _manifest_path_token(value: str) -> str:
- token = value.strip().split(maxsplit=1)[0].strip()
- return "" if token in {"", "null", "dynamic", "unknown"} else token
-
-
-def _manifest_path_exists(repo_root: Path, token: str) -> bool:
- path = Path(token)
- if path.is_absolute():
- return path.exists()
- return (repo_root / path).exists()
-
-
-def _coverage_gap_label(path: Path, index: int, gap: dict[object, object]) -> str:
- gap_id = gap.get("id")
- if isinstance(gap_id, str) and gap_id.strip():
- return f"{path}: coverage_gaps[{index}] {gap_id!r}"
- return f"{path}: coverage_gaps[{index}]"
-
-
-def _valid_iso_date(value: object) -> bool:
- if not isinstance(value, str) or not value.strip():
- return False
- try:
- date.fromisoformat(value)
- except ValueError:
- return False
- return True
-
-
-def _valid_issue_ref(value: object) -> bool:
- if isinstance(value, int):
- return value > 0
- if not isinstance(value, str):
- return False
- stripped = value.strip()
- if stripped.startswith("#"):
- stripped = stripped[1:]
- return stripped.isdecimal() and int(stripped) > 0
-
-
-def _valid_suppression_ref(value: object) -> bool:
- return isinstance(value, str) and bool(value.strip())
-
-
-_BEAD_REF_PATTERN = re.compile(r"^polylogue-[a-z0-9]+(\.[0-9]+)?$")
-
-
-def _valid_bead_ref(value: object) -> bool:
- return isinstance(value, str) and bool(_BEAD_REF_PATTERN.match(value.strip()))
-
-
-def _resolvable_next_evidence(value: str) -> bool:
- return _resolvable_command(value)
-
-
-def _resolvable_command(value: str) -> bool:
- try:
- tokens = shlex.split(value)
- except ValueError:
- return False
- if not tokens:
- return False
- command = tokens[0]
- if command == "devtools":
- return command_name_from_tokens(tokens[1:]) in COMMANDS
- return command in _EVIDENCE_COMMANDS
-
-
-def _coverage_gap_slug(value: str) -> str:
- return "".join(char if char.isalnum() else "-" for char in value.lower()).strip("-") or "unnamed"
-
-
-def _command_present_in_workflows(command: str, inventory: WorkflowInventory) -> bool:
- """Return True if ``command`` (or its leading token) appears in any ``run:``.
-
- Substring match is sufficient — manifests declare canonical CLI commands
- such as ``devtools verify coverage`` or ``uv build --wheel .`` and workflows
- invoke them either directly or via ``uv run`` wrappers. We strip the
- optional ``uv run`` prefix so the substring still resolves.
- """
- if not command or not command.strip():
- return False
- needle = command.strip()
- for run in inventory.all_run_commands:
- if needle in run:
- return True
- # Fall back to the registered command path, e.g. "devtools render all".
- try:
- tokens = shlex.split(needle)
- except ValueError:
- return False
- if len(tokens) >= 2 and tokens[0] == "devtools":
- command_name = command_name_from_tokens(tokens[1:])
- if command_name is None:
- return False
- prefix = f"devtools {command_name}"
- for run in inventory.all_run_commands:
- if prefix in run:
- return True
- elif len(tokens) >= 2:
- bigram = f"{tokens[0]} {tokens[1]}"
- for run in inventory.all_run_commands:
- if bigram in run:
- return True
- return False
-
-
-def check_distribution_ci_claims(
- plans_dir: Path,
- inventory: WorkflowInventory | None = None,
-) -> list[str]:
- """Verify ``ci_build``/``ci_test``/``ci_present`` claims against workflows.
-
- ``distribution-coverage.yaml`` declares whether each artifact's build,
- test, and presence is wired into CI. These are locally verifiable: the
- declared ``build_command``/``verification_command`` must appear in some
- workflow ``run:`` step, otherwise the manifest is lying about CI state.
- """
- errors: list[str] = []
- path = plans_dir / "distribution-coverage.yaml"
- if not path.exists():
- return errors
- try:
- data = load_manifest(path)
- except ValueError as exc:
- return [str(exc)]
-
- wf = inventory if inventory is not None else inventory_workflows(plans_dir.parent.parent / ".github" / "workflows")
-
- artifacts = data.get("artifacts")
- if not isinstance(artifacts, dict):
- return errors
-
- for artifact_name, artifact in artifacts.items():
- if not isinstance(artifact, dict):
- continue
- label = f"{path}: artifacts.{artifact_name}"
-
- if artifact.get("ci_build") is True:
- build_command = artifact.get("build_command")
- if not isinstance(build_command, str) or not build_command.strip():
- errors.append(f"{label} ci_build=true but build_command is missing")
- elif not _command_present_in_workflows(build_command, wf):
- errors.append(
- f"{label} ci_build=true but build_command {build_command!r} "
- "does not appear in any workflow run step"
- )
-
- if artifact.get("ci_test") is True:
- verification_command = artifact.get("verification_command")
- if isinstance(verification_command, str) and verification_command.strip():
- if not _command_present_in_workflows(verification_command, wf):
- errors.append(
- f"{label} ci_test=true but verification_command "
- f"{verification_command!r} does not appear in any workflow run step"
- )
- else:
- # ci_test without a verification_command must at least show the
- # build_command in CI (nix flake check counts as the verification).
- build_command = artifact.get("build_command")
- if (
- isinstance(build_command, str)
- and build_command.strip()
- and not _command_present_in_workflows(build_command, wf)
- ):
- errors.append(
- f"{label} ci_test=true but neither verification_command nor "
- f"build_command {build_command!r} appears in any workflow run step"
- )
-
- return errors
-
-
-def check_test_quality_ci_claims(
- plans_dir: Path,
- inventory: WorkflowInventory | None = None,
-) -> list[str]:
- """Verify ``ci_gate: true`` in test-quality-coverage.yaml is real.
-
- If a dimension claims ``ci_gate: true``, then either the declared
- ``tool`` invocation or the canonical devtools gate command must appear
- in some workflow ``run:`` step. Otherwise the manifest is claiming a
- CI gate that does not exist.
- """
- errors: list[str] = []
- path = plans_dir / "test-quality-coverage.yaml"
- if not path.exists():
- return errors
- try:
- data = load_manifest(path)
- except ValueError as exc:
- return [str(exc)]
-
- wf = inventory if inventory is not None else inventory_workflows(plans_dir.parent.parent / ".github" / "workflows")
-
- dimensions = data.get("dimensions")
- if not isinstance(dimensions, dict):
- return errors
-
- for dim_name, dim in dimensions.items():
- if not isinstance(dim, dict):
- continue
- if dim.get("ci_gate") is not True:
- continue
- label = f"{path}: dimensions.{dim_name}"
- tool = dim.get("tool") if isinstance(dim.get("tool"), str) else ""
- # Probe candidates: the tool string (e.g. "pytest-cov"), and the
- # canonical devtools gate for known tools.
- candidates: list[str] = []
- if tool:
- candidates.append(tool)
- if tool in {"pytest-cov", "coverage"}:
- candidates.append("devtools verify coverage")
- if not any(_command_present_in_workflows(candidate, wf) for candidate in candidates):
- errors.append(f"{label} ci_gate=true but no workflow run step invokes any of {candidates!r}")
- return errors
-
-
-def check_pydantic_models(plans_dir: Path) -> list[str]:
- """Validate every YAML manifest against its Pydantic model schema."""
- errors: list[str] = []
- for path in sorted(plans_dir.glob("*.yaml")):
- try:
- data = load_manifest(path)
- except ValueError as exc:
- errors.append(str(exc))
- continue
- model_errors = validate_manifest(str(path), data)
- errors.extend(model_errors)
- return errors
-
-
-def main(argv: list[str] | None = None) -> int:
- """Run all manifest consistency checks. Returns exit code."""
- project_root = _get_root()
- plans_dir = project_root / "docs" / "plans"
-
- if not plans_dir.is_dir():
- print(f"error: plans directory not found: {plans_dir}", file=sys.stderr)
- return 1
-
- all_errors: list[str] = []
- for check in (
- check_pydantic_models,
- check_coverage_gaps,
- check_coverage_references,
- check_coverage_status_claims,
- check_campaign_coverage_catalog,
- check_distribution_ci_claims,
- check_test_quality_ci_claims,
- ):
- try:
- all_errors.extend(check(plans_dir))
- except Exception as exc:
- all_errors.append(f"{check.__name__}: {exc}")
-
- if all_errors:
- for err in all_errors:
- print(f" ✗ {err}", file=sys.stderr)
- plural = "s" if len(all_errors) != 1 else ""
- print(f"\n{len(all_errors)} manifest consistency error{plural}", file=sys.stderr)
- return 1
-
- print(" ✓ manifest consistency checks passed")
- return 0
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/verify_mutation_freshness.py b/devtools/verify_mutation_freshness.py
index 1935104b66..b3841dddb6 100644
--- a/devtools/verify_mutation_freshness.py
+++ b/devtools/verify_mutation_freshness.py
@@ -1,24 +1,23 @@
-"""Verify mutation-campaign coverage discipline (#1304).
+"""Verify mutation-campaign result freshness and kill rate.
-Reads ``docs/plans/campaign-coverage.yaml`` and checks, for every
-``status: active`` mutation campaign, whether a recent run artifact
+Reads the executable mutation-campaign catalog and checks, for every
+authored campaign, whether a recent run artifact
exists under the campaign's artifact glob (default
``.local/mutation-campaigns//*.json``).
Reports three classes of finding:
* ``missing`` — campaign has no run artifact at all.
-* ``stale`` — newest artifact is older than ``freshness_days``
- (defaults to 60 when the entry omits it).
+* ``stale`` — newest artifact is older than the selected freshness budget.
* ``unknown`` — campaign artifact references a name not present in
- the manifest. Surfaced so artifact directories don't silently fork
+ the executable catalog. Surfaced so artifact directories don't silently fork
away from the registry.
-Default behavior is **soft**: the command always exits 0 and reports
-findings as warnings, so ``devtools verify`` can include it without
-gating on local mutation-run cadence. Pass ``--strict`` to fail when
-any campaign is missing or stale — intended for nightly jobs and
-``devtools verify --lab``.
+Default behavior is **soft**: the command exits 0 and reports missing or stale
+artifacts as warnings. Pass ``--strict`` when an operator intentionally requires
+a complete recent campaign set. Rotating CI uses ``--enforce-kill-rate`` so it
+gates the campaigns actually run in that job without pretending the absent
+campaigns ran.
"""
from __future__ import annotations
@@ -31,18 +30,15 @@
from datetime import UTC, datetime
from pathlib import Path
-import yaml
-
from devtools import repo_root as _get_root
+from devtools.mutation_scenario_catalog import MUTATION_CAMPAIGNS
ROOT = _get_root()
-MANIFEST = ROOT / "docs" / "plans" / "campaign-coverage.yaml"
DEFAULT_FRESHNESS_DAYS = 60
DEFAULT_ARTIFACT_GLOB = ".local/mutation-campaigns/{name}/*.json"
# Conservative kill-rate floor (#1733 AC2/AC3). Mutation kill rates for
# well-tested modules sit well above this; 0.5 flags a genuinely under-killed
-# module without false-alarming on a healthy campaign. Ratchet up per-entry in
-# the manifest as real run data accrues. Only enforced under --enforce-kill-rate
+# module without false-alarming on a healthy campaign. Only enforced under --enforce-kill-rate
# and only against fresh campaigns (those that actually have a recent artifact).
DEFAULT_MIN_KILL_RATE = 0.5
@@ -50,7 +46,6 @@
@dataclass(frozen=True)
class CampaignFreshness:
name: str
- status: str
freshness_days: int
artifact_glob: str
artifact_count: int
@@ -60,37 +55,7 @@ class CampaignFreshness:
kill_rate: float | None
min_kill_rate: float | None
counts: dict[str, int]
- state: str # "fresh" | "stale" | "missing" | "inactive"
-
-
-def _coerce_int(value: object, default: int) -> int:
- if isinstance(value, bool) or value is None:
- return default
- if isinstance(value, int):
- return value
- if isinstance(value, str) and value.strip().isdigit():
- return int(value)
- return default
-
-
-def _coerce_float(value: object, default: float | None) -> float | None:
- if isinstance(value, bool) or value is None:
- return default
- if isinstance(value, (int, float)):
- return float(value)
- if isinstance(value, str):
- try:
- return float(value.strip())
- except ValueError:
- return default
- return default
-
-
-def _entry_glob(entry: dict[str, object]) -> str:
- glob = entry.get("artifact_glob")
- if not isinstance(glob, str) or not glob.strip():
- glob = DEFAULT_ARTIFACT_GLOB.format(name=entry["name"])
- return glob
+ state: str # "fresh" | "stale" | "missing"
def _resolve_artifacts(repo_root: Path, glob: str) -> list[Path]:
@@ -128,38 +93,18 @@ def _age_days(created_at: str | None, now: datetime) -> float | None:
def assess_campaign(
- entry: dict[str, object],
+ name: str,
*,
repo_root: Path,
now: datetime,
- default_freshness_days: int,
- default_min_kill_rate: float | None = None,
+ freshness_days: int,
+ min_kill_rate: float | None = None,
) -> CampaignFreshness:
- name = str(entry["name"])
- status = str(entry.get("status", "active"))
- freshness_days = _coerce_int(entry.get("freshness_days"), default_freshness_days)
- min_kill_rate = _coerce_float(entry.get("min_kill_rate"), default_min_kill_rate)
- glob = _entry_glob(entry)
+ glob = DEFAULT_ARTIFACT_GLOB.format(name=name)
artifacts = _resolve_artifacts(repo_root, glob)
- if status != "active":
- return CampaignFreshness(
- name=name,
- status=status,
- freshness_days=freshness_days,
- artifact_glob=glob,
- artifact_count=len(artifacts),
- newest_artifact=None,
- newest_created_at=None,
- newest_age_days=None,
- kill_rate=None,
- min_kill_rate=min_kill_rate,
- counts={},
- state="inactive",
- )
if not artifacts:
return CampaignFreshness(
name=name,
- status=status,
freshness_days=freshness_days,
artifact_glob=glob,
artifact_count=0,
@@ -186,7 +131,6 @@ def assess_campaign(
state = "stale" if age > freshness_days else "fresh"
return CampaignFreshness(
name=name,
- status=status,
freshness_days=freshness_days,
artifact_glob=glob,
artifact_count=len(artifacts),
@@ -201,7 +145,7 @@ def assess_campaign(
def _orphan_artifact_names(repo_root: Path, registered: Iterable[str]) -> list[str]:
- """Names appearing under .local/mutation-campaigns/ but not in the manifest."""
+ """Names appearing under .local/mutation-campaigns/ but not in the catalog."""
base = repo_root / ".local" / "mutation-campaigns"
if not base.is_dir():
return []
@@ -219,22 +163,18 @@ def _orphan_artifact_names(repo_root: Path, registered: Iterable[str]) -> list[s
return orphans
-def load_manifest(path: Path) -> dict[str, object]:
- with open(path, encoding="utf-8") as fh:
- data = yaml.safe_load(fh)
- if not isinstance(data, dict):
- raise ValueError(f"{path}: expected mapping at root")
- return data
+def catalog_entries() -> list[str]:
+ """Project executable campaigns, without a second declarative registry."""
+ return sorted(MUTATION_CAMPAIGNS)
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--yaml", type=Path, default=MANIFEST)
parser.add_argument(
"--default-freshness-days",
type=int,
default=DEFAULT_FRESHNESS_DAYS,
- help=f"Freshness budget for entries without freshness_days (default {DEFAULT_FRESHNESS_DAYS}).",
+ help=f"Freshness budget for campaign artifacts (default {DEFAULT_FRESHNESS_DAYS}).",
)
parser.add_argument(
"--strict",
@@ -244,46 +184,32 @@ def main(argv: list[str] | None = None) -> int:
parser.add_argument(
"--enforce-kill-rate",
action="store_true",
- help=(
- "Exit non-zero when a fresh campaign's kill rate is below its "
- "min_kill_rate threshold (per-entry, else --default-min-kill-rate)."
- ),
+ help="Exit non-zero when a fresh campaign's kill rate is below --default-min-kill-rate.",
)
parser.add_argument(
"--default-min-kill-rate",
type=float,
default=None,
- help=(
- "Kill-rate floor for entries without min_kill_rate. Defaults to the "
- f"manifest's top-level default_min_kill_rate, else {DEFAULT_MIN_KILL_RATE}."
- ),
+ help=(f"Kill-rate floor for every fresh campaign (default {DEFAULT_MIN_KILL_RATE})."),
)
parser.add_argument("--json", action="store_true", help="Emit a JSON report instead of human output.")
args = parser.parse_args(argv)
- manifest = load_manifest(args.yaml)
- entries = manifest.get("mutation_campaigns")
- if not isinstance(entries, list):
- print(f"{args.yaml}: missing or invalid mutation_campaigns list", file=sys.stderr)
- return 2
-
+ entries = catalog_entries()
default_min_kill_rate = (
- args.default_min_kill_rate
- if args.default_min_kill_rate is not None
- else _coerce_float(manifest.get("default_min_kill_rate"), DEFAULT_MIN_KILL_RATE)
+ args.default_min_kill_rate if args.default_min_kill_rate is not None else DEFAULT_MIN_KILL_RATE
)
now = datetime.now(UTC)
assessments = [
assess_campaign(
- entry,
+ name,
repo_root=ROOT,
now=now,
- default_freshness_days=args.default_freshness_days,
- default_min_kill_rate=default_min_kill_rate,
+ freshness_days=args.default_freshness_days,
+ min_kill_rate=default_min_kill_rate,
)
- for entry in entries
- if isinstance(entry, dict) and "name" in entry
+ for name in entries
]
registered_names = [a.name for a in assessments]
@@ -292,7 +218,6 @@ def main(argv: list[str] | None = None) -> int:
missing = [a for a in assessments if a.state == "missing"]
stale = [a for a in assessments if a.state == "stale"]
fresh = [a for a in assessments if a.state == "fresh"]
- inactive = [a for a in assessments if a.state == "inactive"]
below_threshold = [
a for a in fresh if a.kill_rate is not None and a.min_kill_rate is not None and a.kill_rate < a.min_kill_rate
]
@@ -312,7 +237,6 @@ def main(argv: list[str] | None = None) -> int:
"fresh": len(fresh),
"stale": len(stale),
"missing": len(missing),
- "inactive": len(inactive),
"below_kill_threshold": len(below_threshold),
"orphan_artifact_names": len(orphan_names),
},
@@ -327,12 +251,10 @@ def main(argv: list[str] | None = None) -> int:
sys.stdout.write("\n")
else:
prefix = "[BLOCK]" if args.strict else "[warn]"
- print(f"registered active mutation campaigns: {len(assessments) - len(inactive)}")
+ print(f"registered active mutation campaigns: {len(assessments)}")
print(f" fresh: {len(fresh)}")
print(f" stale: {len(stale)} (older than freshness_days)")
print(f" missing: {len(missing)} (no run artifact)")
- if inactive:
- print(f" inactive (skipped): {len(inactive)}")
for a in missing:
print(f"{prefix} missing artifact: {a.name} (glob={a.artifact_glob})")
for a in stale:
@@ -350,7 +272,7 @@ def main(argv: list[str] | None = None) -> int:
f"kill={a.kill_rate * 100:.1f}% (floor {a.min_kill_rate * 100:.1f}%)"
)
if orphan_names:
- print(f"[warn] orphan artifact directories (not in manifest): {len(orphan_names)}")
+ print(f"[warn] orphan artifact directories (not in catalog): {len(orphan_names)}")
for name in orphan_names[:25]:
print(f" {name}")
if fresh:
diff --git a/devtools/verify_position_derived_identity.py b/devtools/verify_position_derived_identity.py
deleted file mode 100644
index bef5f9928f..0000000000
--- a/devtools/verify_position_derived_identity.py
+++ /dev/null
@@ -1,384 +0,0 @@
-"""Verify no parser mints comparison identity from positional/index data.
-
-Background
-----------
-
-polylogue-hith/qkuq found and fixed a concrete bug: the Claude.ai attachment
-parser's synthetic id (``att-``) was seeded
-partly by array index, so a re-export that reordered or inserted attachment
-entries silently produced a different id for "the same" attachment,
-manufacturing false divergence in revision-authority membership comparison.
-The fix was not to remove the synthetic-id *generator* (still legitimate as
-a last-resort storage/display id, seed no longer includes ``index``) but to
-make ``attachment_identity_hash`` (``polylogue/pipeline/ids.py``) stop
-reading either the real or synthetic attachment id at all for comparison
-purposes.
-
-polylogue-gysk3 found the identical hazard one level up:
-``message_identity_hash`` (``polylogue/pipeline/ids.py``) hashes a message's
-``id`` directly, and that id IS ``provider_message_id`` -- multiple parsers
-construct it as ``f"msg-{index}"`` or similar whenever the raw record
-carries no native id of its own. The production repair removed every known
-instance. This lint (ds4b4 item 3) prevents the same shape returning in a
-parser or shared parser helper.
-
-What this lint checks
-----------------------
-
-Scans ``polylogue/sources/parsers/`` (and ``base_support.py``-style shared
-parser helpers alongside it) for an assignment or keyword argument whose
-target name is in ``IDENTITY_FIELD_NAMES`` (fields whose value is used as
-cross-revision comparison identity, not just a display/storage label) where
-the value expression is an f-string, ``str.format()`` call, or ``+``
-concatenation that references a variable named like a loop index/position
-(``index``, ``idx``, ``i``, ``pos``, ``position`` -- ``ENUMERATE_VAR_NAMES``).
-
-No current finding needs an acknowledgement. The optional acknowledgement
-manifest (``docs/plans/position-derived-identity-acks.json``) is absent while
-the audit is clean and is created only by ``--ack`` for a newly discovered,
-temporarily accepted finding with a tracked follow-up. An unacknowledged
-occurrence fails the gate; a stale acknowledgement fails it too.
-
-Scope and false-positive discipline
-------------------------------------
-
-Only ``IDENTITY_FIELD_NAMES`` trips this lint -- an ordinary loop variable
-named ``index`` used for anything else (slicing, logging, an unrelated
-counter) is untouched. ``ENUMERATE_VAR_NAMES`` is deliberately narrow (common
-loop-counter spellings); a differently-named counter is a residual
-false-negative, not a false-positive, and acceptable for a preventive lint of
-this kind (the goal is to catch the common, already-observed shape, not
-build a full data-flow/taint analysis). Position-derived values used for
-purely *structural* addressing that is never compared across independent
-captures of the same logical entity (e.g. ``blocks.block_id`` -- see
-CLAUDE.md's data model section) are out of scope by construction: this lint
-only matches the specific field-name list, not every f-string containing an
-index.
-
-Wired into ``devtools verify --lab`` (like classifier-fingerprints):
-static, archive-independent, sub-second.
-"""
-
-from __future__ import annotations
-
-import argparse
-import ast
-import json
-import re
-import sys
-from dataclasses import dataclass
-from pathlib import Path
-from typing import TypedDict
-
-from devtools import repo_root as _get_root
-
-ROOT = _get_root()
-PARSERS_ROOT = ROOT / "polylogue" / "sources" / "parsers"
-MANIFEST_PATH = ROOT / "docs" / "plans" / "position-derived-identity-acks.json"
-
-#: Field names whose value is used as cross-revision comparison identity
-#: (not just a storage/display label). Extend deliberately, with review --
-#: this is the allowlist that scopes the whole lint.
-IDENTITY_FIELD_NAMES = frozenset({"provider_message_id"})
-
-#: Common loop-counter/index spellings. Deliberately narrow (see module
-#: docstring's false-positive-discipline section).
-ENUMERATE_VAR_NAMES = frozenset({"index", "idx", "i", "pos", "position"})
-
-_REF_PATTERN = re.compile(r"^(polylogue-[a-z0-9][a-z0-9.]*|#\d+)$")
-_MIN_REASON_LEN = 15
-
-
-def _references_enumerate_var(node: ast.AST) -> bool:
- return any(isinstance(sub, ast.Name) and sub.id in ENUMERATE_VAR_NAMES for sub in ast.walk(node))
-
-
-def _value_is_position_derived(value: ast.expr) -> bool:
- if isinstance(value, ast.JoinedStr):
- return _references_enumerate_var(value)
- if isinstance(value, ast.BinOp) and isinstance(value.op, ast.Add):
- return _references_enumerate_var(value)
- if isinstance(value, ast.Call):
- func = value.func
- name = func.attr if isinstance(func, ast.Attribute) else func.id if isinstance(func, ast.Name) else None
- if name == "format" and _references_enumerate_var(value):
- return True
- # `str(x or f"...{index}")`, `str(x or f"...{index}")` etc: unwrap a
- # single-arg str()/BoolOp `or` chain to reach the fallback literal.
- if name == "str" and len(value.args) == 1:
- return _value_is_position_derived(value.args[0])
- if isinstance(value, ast.BoolOp) and isinstance(value.op, ast.Or):
- return any(_value_is_position_derived(v) for v in value.values)
- return False
-
-
-@dataclass(frozen=True, slots=True)
-class PositionIdentityFinding:
- qualname: str
- path: str
- lineno: int
- field: str
-
-
-def _enclosing_function_name(stack: list[ast.AST]) -> str:
- for node in reversed(stack):
- if isinstance(node, ast.FunctionDef | ast.AsyncFunctionDef):
- return node.name
- return ""
-
-
-def _resolve_via_local_bindings(value: ast.expr, bindings: dict[str, ast.expr], *, depth: int = 0) -> bool:
- """Follow a bare-name reference back to its last local assignment.
-
- The common shape in this codebase is not inline construction at the
- identity-field keyword/assign site -- it is ``msg_id = ... or
- f"msg-{idx}"`` a few lines earlier, then ``provider_message_id=msg_id``.
- A one-hop-per-name, last-write-wins backward resolution (approximating
- straight-line control flow, which is what these parsers use) catches
- that without a full data-flow analysis. ``depth`` guards against
- pathological self-referential rebinding.
- """
- if depth > 5:
- return False
- if _value_is_position_derived(value):
- return True
- if isinstance(value, ast.Name) and value.id in bindings:
- return _resolve_via_local_bindings(bindings[value.id], bindings, depth=depth + 1)
- if isinstance(value, ast.Call) and len(value.args) == 1:
- func = value.func
- name = func.attr if isinstance(func, ast.Attribute) else func.id if isinstance(func, ast.Name) else None
- if name == "str":
- return _resolve_via_local_bindings(value.args[0], bindings, depth=depth + 1)
- if isinstance(value, ast.BoolOp) and isinstance(value.op, ast.Or):
- return any(_resolve_via_local_bindings(v, bindings, depth=depth + 1) for v in value.values)
- return False
-
-
-def _scan_module(source: str, *, rel_path: str) -> list[PositionIdentityFinding]:
- try:
- tree = ast.parse(source)
- except SyntaxError:
- return []
- findings: list[PositionIdentityFinding] = []
- ordinal_by_key: dict[str, int] = {}
- stack: list[ast.AST] = []
- # Reset per function: a straight-line, last-write-wins map of local
- # simple-name bindings, rebuilt fresh at each FunctionDef so a name in
- # one function never leaks into another's resolution.
- bindings_by_function: dict[int, dict[str, ast.expr]] = {}
-
- def _current_bindings() -> dict[str, ast.expr]:
- for node in reversed(stack):
- if isinstance(node, ast.FunctionDef | ast.AsyncFunctionDef):
- return bindings_by_function.setdefault(id(node), {})
- return bindings_by_function.setdefault(0, {})
-
- def _record(field: str, value: ast.expr, *, lineno: int) -> None:
- if not _resolve_via_local_bindings(value, _current_bindings()):
- return
- func_name = _enclosing_function_name(stack)
- key = f"{rel_path}:{func_name}:{field}"
- ordinal = ordinal_by_key.get(key, 0)
- ordinal_by_key[key] = ordinal + 1
- qualname = key if ordinal == 0 else f"{key}#{ordinal}"
- findings.append(PositionIdentityFinding(qualname=qualname, path=rel_path, lineno=lineno, field=field))
-
- class _Visitor(ast.NodeVisitor):
- def generic_visit(self, node: ast.AST) -> None:
- stack.append(node)
- super().generic_visit(node)
- stack.pop()
-
- def visit_Assign(self, node: ast.Assign) -> None:
- for target in node.targets:
- if isinstance(target, ast.Name):
- if target.id in IDENTITY_FIELD_NAMES:
- _record(target.id, node.value, lineno=node.lineno)
- _current_bindings()[target.id] = node.value
- self.generic_visit(node)
-
- def visit_AnnAssign(self, node: ast.AnnAssign) -> None:
- if isinstance(node.target, ast.Name) and node.value is not None:
- if node.target.id in IDENTITY_FIELD_NAMES:
- _record(node.target.id, node.value, lineno=node.lineno)
- _current_bindings()[node.target.id] = node.value
- self.generic_visit(node)
-
- def visit_Call(self, node: ast.Call) -> None:
- for kw in node.keywords:
- if kw.arg in IDENTITY_FIELD_NAMES:
- _record(kw.arg, kw.value, lineno=kw.value.lineno)
- self.generic_visit(node)
-
- _Visitor().visit(tree)
- return findings
-
-
-def collect_position_derived_identity(root: Path = PARSERS_ROOT) -> dict[str, PositionIdentityFinding]:
- """Return every in-scope finding, keyed by a line-shift-stable qualname.
-
- Exposed standalone so a test can feed a synthetic source string via
- ``_scan_module`` directly.
- """
- found: dict[str, PositionIdentityFinding] = {}
- if not root.exists():
- return found
- for path in sorted(root.rglob("*.py")):
- rel = path.relative_to(ROOT).as_posix()
- source = path.read_text(encoding="utf-8")
- for finding in _scan_module(source, rel_path=rel):
- found[finding.qualname] = finding
- return found
-
-
-@dataclass(frozen=True, slots=True)
-class AckEntry:
- reason: str
- ref: str
-
-
-class ManifestJSON(TypedDict):
- acknowledged: dict[str, dict[str, str]]
-
-
-def load_manifest(path: Path = MANIFEST_PATH) -> dict[str, AckEntry]:
- if not path.exists():
- return {}
- raw: ManifestJSON = json.loads(path.read_text(encoding="utf-8"))
- return {
- qualname: AckEntry(reason=str(data["reason"]), ref=str(data["ref"]))
- for qualname, data in raw.get("acknowledged", {}).items()
- }
-
-
-def save_manifest(entries: dict[str, AckEntry], path: Path = MANIFEST_PATH) -> None:
- payload: ManifestJSON = {
- "acknowledged": {
- qualname: {"reason": entry.reason, "ref": entry.ref} for qualname, entry in sorted(entries.items())
- }
- }
- path.parent.mkdir(parents=True, exist_ok=True)
- path.write_text(json.dumps(payload, indent=2, sort_keys=False) + "\n", encoding="utf-8")
-
-
-def _validate_ack(reason: str, ref: str) -> str | None:
- if len(reason.strip()) < _MIN_REASON_LEN:
- return f"reason too short (must explain the tracked follow-up, >= {_MIN_REASON_LEN} chars)"
- if not _REF_PATTERN.match(ref):
- return "ref must be a bead id (polylogue-xxxx) or issue number (#N)"
- return None
-
-
-@dataclass(frozen=True, slots=True)
-class DriftReport:
- unacknowledged: tuple[str, ...]
- stale: tuple[str, ...]
-
- @property
- def ok(self) -> bool:
- return not self.unacknowledged and not self.stale
-
-
-def compute_drift_report(
- current: dict[str, PositionIdentityFinding] | None = None,
- manifest: dict[str, AckEntry] | None = None,
-) -> DriftReport:
- if current is None:
- current = collect_position_derived_identity()
- if manifest is None:
- manifest = load_manifest()
- unacknowledged = tuple(sorted(q for q in current if q not in manifest))
- stale = tuple(sorted(q for q in manifest if q not in current))
- return DriftReport(unacknowledged=unacknowledged, stale=stale)
-
-
-def _format_report(report: DriftReport, current: dict[str, PositionIdentityFinding]) -> str:
- lines = [
- f"unacknowledged position-derived identity constructions: {len(report.unacknowledged)}",
- f"stale manifest entries (finding no longer exists): {len(report.stale)}",
- ]
- if report.unacknowledged:
- lines.append("")
- lines.append(
- "New position-derived comparison-identity constructions (see module docstring -- "
- "polylogue-hith/qkuq's already-fixed attachment-id bug, polylogue-gysk3's tracked "
- "message-id sibling):"
- )
- for qualname in report.unacknowledged:
- finding = current[qualname]
- lines.append(f" {finding.path}:{finding.lineno} ({finding.field}) [{qualname}]")
- lines.append(
- " Fix: either derive identity from provider-native data instead of position, or "
- "acknowledge with `devtools lab policy position-derived-identity --ack "
- "--reason '...' --ref ` naming a tracked follow-up."
- )
- if report.stale:
- lines.append("")
- lines.append("Manifest entries whose finding no longer exists (remove them):")
- for qualname in report.stale:
- lines.append(f" {qualname}")
- lines.append(f" Fix: edit {MANIFEST_PATH.relative_to(ROOT)} and delete the stale entry.")
- if report.ok:
- lines.append("")
- lines.append("Position-derived identity policy intact.")
- return "\n".join(lines)
-
-
-def _cmd_ack(qualname: str, *, reason: str, ref: str) -> int:
- current = collect_position_derived_identity()
- if qualname not in current:
- print(f"error: {qualname!r} is not a currently discovered finding", file=sys.stderr)
- return 2
- problem = _validate_ack(reason, ref)
- if problem is not None:
- print(f"error: {problem}", file=sys.stderr)
- return 2
- manifest = load_manifest()
- manifest[qualname] = AckEntry(reason=reason, ref=ref)
- save_manifest(manifest)
- print(f"recorded {qualname}")
- return 0
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- )
- parser.add_argument("--json", action="store_true", help="emit machine-readable JSON")
- parser.add_argument(
- "--ack",
- metavar="QUALNAME",
- help="record an acknowledged position-derived identity finding, naming a tracked follow-up",
- )
- parser.add_argument("--reason", help="justification text for --ack (required with --ack)")
- parser.add_argument("--ref", help="bead id (polylogue-xxxx) or issue number (#N) for --ack (required with --ack)")
- args = parser.parse_args(argv)
-
- if args.ack:
- if not args.reason or not args.ref:
- parser.error("--ack requires --reason and --ref")
- return _cmd_ack(args.ack, reason=args.reason, ref=args.ref)
-
- current = collect_position_derived_identity()
- report = compute_drift_report(current)
-
- if args.json:
- print(
- json.dumps(
- {
- "unacknowledged": list(report.unacknowledged),
- "stale": list(report.stale),
- "ok": report.ok,
- },
- indent=2,
- )
- )
- else:
- print(_format_report(report, current))
-
- return 0 if report.ok else 1
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/verify_pytest_timeout_overrides.py b/devtools/verify_pytest_timeout_overrides.py
deleted file mode 100644
index dee54502a9..0000000000
--- a/devtools/verify_pytest_timeout_overrides.py
+++ /dev/null
@@ -1,601 +0,0 @@
-"""Verify explicit pytest timeout overrides remain bounded and reviewable.
-
-The repository-wide pytest-timeout default lives in ``pyproject.toml``. This
-gate only inspects explicit exceptions: test decorators and literal pytest
-commands owned by ``devtools``. It deliberately parses Python ASTs rather than
-searching source text, so prose and generated documentation are out of scope.
-
-Marker aliases are deliberately fail-closed: imported, unresolved, cyclic, or
-rebound names cannot prove the absence of a timeout override and are rejected.
-"""
-
-from __future__ import annotations
-
-import argparse
-import ast
-import json
-import math
-from dataclasses import dataclass
-from pathlib import Path
-from typing import Any
-
-import tomllib
-
-from devtools import repo_root as _get_root
-
-ROOT = _get_root()
-MANIFEST_RELATIVE_PATH = Path("devtools/pytest_timeout_overrides.toml")
-
-
-@dataclass(frozen=True, slots=True)
-class TimeoutOverride:
- path: str
- line: int
- value: float
- source: str
-
- @property
- def manifest_key(self) -> tuple[str, float]:
- return (self.path, self.value)
-
-
-@dataclass(frozen=True, slots=True)
-class ManifestEntry:
- path: str
- value: float
- rationale: str
-
- @property
- def key(self) -> tuple[str, float]:
- return (self.path, self.value)
-
-
-def _number_from_literal(node: ast.expr) -> float | None:
- if isinstance(node, ast.Constant) and not isinstance(node.value, bool) and isinstance(node.value, (int, float)):
- value = float(node.value)
- return value if math.isfinite(value) else None
- if isinstance(node, ast.UnaryOp) and isinstance(node.op, (ast.USub, ast.UAdd)):
- operand = _number_from_literal(node.operand)
- if operand is not None:
- return -operand if isinstance(node.op, ast.USub) else operand
- return None
-
-
-def _pytest_aliases(tree: ast.Module) -> tuple[set[str], set[str], set[str]]:
- """Return local names bound to ``pytest``, ``pytest.mark``, and ``pytest.param``."""
- pytest_names: set[str] = set()
- mark_names: set[str] = set()
- param_names: set[str] = set()
- for node in ast.walk(tree):
- if isinstance(node, ast.Import):
- for alias in node.names:
- if alias.name == "pytest":
- pytest_names.add(alias.asname or "pytest")
- elif isinstance(node, ast.ImportFrom) and node.module == "pytest":
- for alias in node.names:
- if alias.name == "mark":
- mark_names.add(alias.asname or "mark")
- elif alias.name == "param":
- param_names.add(alias.asname or "param")
- return pytest_names, mark_names, param_names
-
-
-def _is_pytest_timeout_decorator(node: ast.expr, pytest_names: set[str], mark_names: set[str]) -> bool:
- func = node.func if isinstance(node, ast.Call) else node
- return (
- isinstance(func, ast.Attribute)
- and func.attr == "timeout"
- and (
- (isinstance(func.value, ast.Name) and func.value.id in mark_names)
- or (
- isinstance(func.value, ast.Attribute)
- and func.value.attr == "mark"
- and isinstance(func.value.value, ast.Name)
- and func.value.value.id in pytest_names
- )
- )
- )
-
-
-def _is_pytest_param_call(node: ast.Call, pytest_names: set[str], param_names: set[str]) -> bool:
- return (isinstance(node.func, ast.Name) and node.func.id in param_names) or (
- isinstance(node.func, ast.Attribute)
- and node.func.attr == "param"
- and isinstance(node.func.value, ast.Name)
- and node.func.value.id in pytest_names
- )
-
-
-def _parse_decorator_override(path: str, node: ast.Call) -> tuple[TimeoutOverride | None, str | None]:
- location = f"{path}:{node.lineno}"
- if len(node.args) > 2:
- return None, f"{location}: malformed pytest timeout decorator; too many positional arguments"
- timeout_argument: ast.expr | None = node.args[0] if node.args else None
- method_argument: ast.expr | None = node.args[1] if len(node.args) == 2 else None
- seen_keywords: set[str] = set()
- for keyword in node.keywords:
- if keyword.arg not in {"timeout", "method", "func_only"} or keyword.arg in seen_keywords:
- return None, f"{location}: malformed pytest timeout decorator keyword"
- seen_keywords.add(keyword.arg)
- if keyword.arg == "timeout":
- if timeout_argument is not None:
- return None, f"{location}: malformed pytest timeout decorator has multiple timeout values"
- timeout_argument = keyword.value
- elif keyword.arg == "method":
- if method_argument is not None:
- return None, f"{location}: malformed pytest timeout decorator has multiple method values"
- method_argument = keyword.value
- elif not (isinstance(keyword.value, ast.Constant) and isinstance(keyword.value.value, bool)):
- return None, f"{location}: dynamic or malformed pytest timeout func_only option is forbidden"
- if timeout_argument is None:
- return None, f"{location}: malformed pytest timeout decorator is missing a timeout value"
- if method_argument is not None and (
- not isinstance(method_argument, ast.Constant)
- or not isinstance(method_argument.value, str)
- or method_argument.value not in {"signal", "thread"}
- ):
- return None, f"{location}: dynamic or malformed pytest timeout method option is forbidden"
- argument = timeout_argument
- if isinstance(argument, ast.Constant) and argument.value is None:
- return None, f"{location}: unbounded pytest timeout decorator is forbidden"
- value = _number_from_literal(argument)
- if value is None:
- return None, f"{location}: dynamic or malformed pytest timeout decorator is forbidden"
- if value <= 0:
- return None, f"{location}: pytest timeout must be positive, got {value:g}"
- return TimeoutOverride(path, node.lineno, value, "decorator"), None
-
-
-def _is_pytest_execution_call(node: ast.Call) -> bool:
- return isinstance(node.func, ast.Name) and node.func.id == "pytest_execution"
-
-
-def _module_assignments(tree: ast.Module) -> tuple[dict[str, ast.expr], set[str]]:
- """Return only module bindings that have one unambiguous source assignment."""
- assignments: dict[str, ast.expr] = {}
- rebound: set[str] = set()
- for node in tree.body:
- targets: list[ast.expr]
- value: ast.expr | None
- if isinstance(node, ast.Assign):
- targets, value = node.targets, node.value
- elif isinstance(node, (ast.AnnAssign, ast.AugAssign)):
- targets, value = [node.target], node.value
- else:
- continue
- if value is None:
- continue
- for target in targets:
- if not isinstance(target, ast.Name):
- continue
- if target.id in assignments or target.id in rebound:
- assignments.pop(target.id, None)
- rebound.add(target.id)
- else:
- assignments[target.id] = value
- return assignments, rebound
-
-
-def _resolve_alias(node: ast.expr, assignments: dict[str, ast.expr], seen: set[str] | None = None) -> ast.expr:
- if not isinstance(node, ast.Name) or node.id not in assignments:
- return node
- seen = set() if seen is None else seen
- if node.id in seen:
- return node
- seen.add(node.id)
- return _resolve_alias(assignments[node.id], assignments, seen)
-
-
-def _flatten_command_expression(node: ast.expr, assignments: dict[str, ast.expr]) -> tuple[list[ast.expr], bool] | None:
- node = _resolve_alias(node, assignments)
- if isinstance(node, (ast.List, ast.Tuple)):
- items: list[ast.expr] = []
- dynamic = False
- for item in node.elts:
- if isinstance(item, ast.Starred):
- flattened = _flatten_command_expression(item.value, assignments)
- if flattened is None:
- dynamic = True
- else:
- nested_items, nested_dynamic = flattened
- items.extend(nested_items)
- dynamic = dynamic or nested_dynamic
- else:
- items.append(item)
- return items, dynamic
- if isinstance(node, ast.BinOp) and isinstance(node.op, ast.Add):
- left = _flatten_command_expression(node.left, assignments)
- right = _flatten_command_expression(node.right, assignments)
- if left is None or right is None:
- if left is None and right is None:
- return None
- return [*(left[0] if left is not None else []), *(right[0] if right is not None else [])], True
- return [*left[0], *right[0]], left[1] or right[1]
- return None
-
-
-def _is_literal_pytest_command(nodes: list[ast.expr]) -> bool:
- return any(isinstance(node, ast.Constant) and node.value == "pytest" for node in nodes)
-
-
-def _dynamic_string_fragments(node: ast.expr) -> tuple[str, ...]:
- """Return literal pieces embedded in a dynamic string expression."""
- if isinstance(node, ast.JoinedStr):
- return tuple(
- value.value for value in node.values if isinstance(value, ast.Constant) and isinstance(value.value, str)
- )
- if isinstance(node, ast.BinOp) and isinstance(node.op, ast.Add):
- return (*_dynamic_string_fragments(node.left), *_dynamic_string_fragments(node.right))
- return ()
-
-
-def _is_dynamic_timeout_option(node: ast.expr, assignments: dict[str, ast.expr]) -> bool:
- node = _resolve_alias(node, assignments)
- return not isinstance(node, ast.Constant) and any(
- "--timeout" in fragment for fragment in _dynamic_string_fragments(node)
- )
-
-
-def _parse_command_overrides(
- path: str,
- line: int,
- nodes: list[ast.expr],
- assignments: dict[str, ast.expr],
- rebound: set[str],
-) -> tuple[list[TimeoutOverride], list[str]]:
- overrides: list[TimeoutOverride] = []
- errors: list[str] = []
- for index, node in enumerate(nodes):
- if isinstance(node, ast.Name) and node.id in rebound:
- errors.append(f"{path}:{node.lineno}: rebound managed pytest command alias is forbidden")
- continue
- resolved_node = _resolve_alias(node, assignments)
- if not isinstance(resolved_node, ast.Constant) or not isinstance(resolved_node.value, str):
- if _is_dynamic_timeout_option(node, assignments):
- location = f"{path}:{getattr(node, 'lineno', line)}"
- errors.append(f"{location}: dynamic or malformed pytest --timeout override is forbidden")
- continue
- token = resolved_node.value
- if token == "--timeout":
- location = f"{path}:{getattr(node, 'lineno', line)}"
- if index + 1 >= len(nodes):
- errors.append(f"{location}: unbounded pytest --timeout override is forbidden")
- continue
- value_node = nodes[index + 1]
- if not isinstance(value_node, ast.Constant) or not isinstance(value_node.value, str):
- errors.append(f"{location}: dynamic or malformed pytest --timeout override is forbidden")
- continue
- raw_value = value_node.value
- elif token.startswith("--timeout="):
- location = f"{path}:{getattr(node, 'lineno', line)}"
- raw_value = token.removeprefix("--timeout=")
- if not raw_value:
- errors.append(f"{location}: unbounded pytest --timeout override is forbidden")
- continue
- else:
- continue
- try:
- value = float(raw_value)
- except ValueError:
- errors.append(f"{location}: malformed pytest --timeout override {raw_value!r}")
- continue
- if not math.isfinite(value):
- errors.append(f"{location}: malformed pytest --timeout override {raw_value!r}")
- elif value <= 0:
- errors.append(f"{location}: pytest timeout must be positive, got {value:g}")
- else:
- overrides.append(TimeoutOverride(path, getattr(node, "lineno", line), value, "command"))
- return overrides, errors
-
-
-def _scan_timeout_marker(
- marker: ast.expr,
- *,
- path: str,
- pytest_names: set[str],
- mark_names: set[str],
-) -> tuple[TimeoutOverride | None, str | None]:
- if not _is_pytest_timeout_decorator(marker, pytest_names, mark_names):
- return None, None
- if not isinstance(marker, ast.Call):
- return None, f"{path}:{marker.lineno}: malformed pytest timeout decorator is missing a timeout value"
- return _parse_decorator_override(path, marker)
-
-
-def _flatten_marker_values(
- node: ast.expr,
- assignments: dict[str, ast.expr],
- rebound: set[str],
- seen: set[str] | None = None,
-) -> tuple[list[ast.expr], str | None]:
- """Resolve only immutable tuple marker aliases without evaluating Python."""
- if isinstance(node, ast.Name):
- if node.id in rebound:
- return [], "rebound pytest marker alias is forbidden"
- if node.id not in assignments:
- return [], "dynamic pytest marker alias is forbidden"
- if isinstance(assignments[node.id], ast.List):
- return [], "mutable pytest marker alias is forbidden; use an inline mark or tuple"
- seen = set() if seen is None else seen
- if node.id in seen:
- return [], "cyclic pytest marker alias is forbidden"
- seen.add(node.id)
- return _flatten_marker_values(assignments[node.id], assignments, rebound, seen)
- if isinstance(node, (ast.List, ast.Tuple)):
- markers: list[ast.expr] = []
- for item in node.elts:
- nested, error = _flatten_marker_values(item, assignments, rebound, set(seen or ()))
- if error is not None:
- return [], error
- markers.extend(nested)
- return markers, None
- return [node], None
-
-
-def _mentions_rebound_alias(node: ast.AST, rebound: set[str]) -> bool:
- return any(isinstance(descendant, ast.Name) and descendant.id in rebound for descendant in ast.walk(node))
-
-
-def _scan_timeout_markers(
- marker_expression: ast.expr,
- *,
- path: str,
- assignments: dict[str, ast.expr],
- rebound: set[str],
- pytest_names: set[str],
- mark_names: set[str],
-) -> tuple[list[TimeoutOverride], list[str]]:
- markers, flatten_error = _flatten_marker_values(marker_expression, assignments, rebound)
- if flatten_error is not None:
- return [], [f"{path}:{marker_expression.lineno}: {flatten_error}"]
- overrides: list[TimeoutOverride] = []
- errors: list[str] = []
- for marker in markers:
- override, error = _scan_timeout_marker(
- marker,
- path=path,
- pytest_names=pytest_names,
- mark_names=mark_names,
- )
- if override is not None:
- overrides.append(override)
- if error is not None:
- errors.append(error)
- return overrides, errors
-
-
-def _scan_python(
- path: Path, root: Path, *, scan_decorators: bool, scan_commands: bool
-) -> tuple[list[TimeoutOverride], list[str]]:
- relative = path.relative_to(root).as_posix()
- try:
- tree = ast.parse(path.read_text(encoding="utf-8"), filename=relative)
- except SyntaxError as exc:
- return [], [f"{relative}:{exc.lineno or 0}: cannot parse Python source: {exc.msg}"]
-
- overrides: list[TimeoutOverride] = []
- errors: list[str] = []
- pytest_names, mark_names, param_names = _pytest_aliases(tree)
- assignments, rebound = _module_assignments(tree)
- if scan_decorators:
- for top_level in tree.body:
- if not isinstance(top_level, (ast.Assign, ast.AnnAssign, ast.AugAssign)):
- continue
- targets = top_level.targets if isinstance(top_level, ast.Assign) else [top_level.target]
- value = top_level.value
- if value is None or not any(
- isinstance(target, ast.Name) and target.id == "pytestmark" for target in targets
- ):
- continue
- found, found_errors = _scan_timeout_markers(
- value,
- path=relative,
- assignments=assignments,
- rebound=rebound,
- pytest_names=pytest_names,
- mark_names=mark_names,
- )
- overrides.extend(found)
- errors.extend(found_errors)
- for candidate in ast.walk(tree):
- if scan_decorators and isinstance(candidate, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)):
- for decorator in candidate.decorator_list:
- override, error = _scan_timeout_marker(
- decorator,
- path=relative,
- pytest_names=pytest_names,
- mark_names=mark_names,
- )
- if override is not None:
- overrides.append(override)
- if error is not None:
- errors.append(error)
- if (
- scan_decorators
- and isinstance(candidate, ast.Call)
- and _is_pytest_param_call(candidate, pytest_names, param_names)
- ):
- for keyword in candidate.keywords:
- if keyword.arg != "marks":
- continue
- found, found_errors = _scan_timeout_markers(
- keyword.value,
- path=relative,
- assignments=assignments,
- rebound=rebound,
- pytest_names=pytest_names,
- mark_names=mark_names,
- )
- overrides.extend(found)
- errors.extend(found_errors)
- if not scan_commands:
- continue
- command_nodes: list[ast.expr] | None = None
- is_pytest_command = False
- line = getattr(candidate, "lineno", 0)
- if isinstance(candidate, (ast.List, ast.Tuple, ast.BinOp)):
- flattened = _flatten_command_expression(candidate, assignments)
- if flattened is not None:
- command_nodes, dynamic_expression = flattened
- is_pytest_command = _is_literal_pytest_command(command_nodes)
- if is_pytest_command and dynamic_expression and _is_dynamic_timeout_option(candidate, assignments):
- errors.append(f"{relative}:{line}: dynamic managed pytest command expression is forbidden")
- if is_pytest_command and _mentions_rebound_alias(candidate, rebound):
- errors.append(f"{relative}:{line}: rebound managed pytest command alias is forbidden")
- elif isinstance(candidate, ast.Call) and _is_pytest_execution_call(candidate):
- flattened = _flatten_command_expression(ast.Tuple(elts=candidate.args, ctx=ast.Load()), assignments)
- if flattened is None:
- if any(
- _is_dynamic_timeout_option(
- argument.value if isinstance(argument, ast.Starred) else argument,
- assignments,
- )
- for argument in candidate.args
- ):
- errors.append(f"{relative}:{line}: dynamic managed pytest command expression is forbidden")
- else:
- command_nodes, dynamic_expression = flattened
- is_pytest_command = True
- if dynamic_expression and any(
- _is_dynamic_timeout_option(
- argument.value if isinstance(argument, ast.Starred) else argument,
- assignments,
- )
- for argument in candidate.args
- ):
- errors.append(f"{relative}:{line}: dynamic managed pytest command expression is forbidden")
- if _mentions_rebound_alias(candidate, rebound):
- errors.append(f"{relative}:{line}: rebound managed pytest command alias is forbidden")
- if command_nodes is not None and is_pytest_command:
- found, found_errors = _parse_command_overrides(relative, line, command_nodes, assignments, rebound)
- overrides.extend(found)
- errors.extend(found_errors)
- return overrides, errors
-
-
-def _read_default_timeout(pyproject_path: Path) -> float:
- data = tomllib.loads(pyproject_path.read_text(encoding="utf-8"))
- timeout: object = data.get("tool", {}).get("pytest", {}).get("ini_options", {}).get("timeout")
- if (
- isinstance(timeout, bool)
- or not isinstance(timeout, (int, float))
- or not math.isfinite(float(timeout))
- or timeout <= 0
- ):
- raise ValueError("tool.pytest.ini_options.timeout must be a positive finite number")
- return float(timeout)
-
-
-def _read_manifest(manifest_path: Path, root: Path) -> tuple[list[ManifestEntry], list[str]]:
- if not manifest_path.exists():
- return [], [f"missing timeout override manifest: {manifest_path}"]
- try:
- data = tomllib.loads(manifest_path.read_text(encoding="utf-8"))
- except tomllib.TOMLDecodeError as exc:
- return [], [f"{manifest_path}: invalid TOML: {exc}"]
- raw_entries = data.get("exception", [])
- if not isinstance(raw_entries, list):
- return [], [f"{manifest_path}: exception must be an array of tables"]
-
- entries: list[ManifestEntry] = []
- errors: list[str] = []
- seen: set[tuple[str, float]] = set()
- for index, raw_entry in enumerate(raw_entries):
- label = f"{manifest_path}: exception[{index}]"
- if not isinstance(raw_entry, dict):
- errors.append(f"{label} must be a table")
- continue
- path = raw_entry.get("path")
- value = raw_entry.get("value")
- rationale = raw_entry.get("rationale")
- if not isinstance(path, str) or not path or Path(path).is_absolute() or ".." in Path(path).parts:
- errors.append(f"{label} path must be a repository-relative path")
- continue
- if (
- isinstance(value, bool)
- or not isinstance(value, (int, float))
- or not math.isfinite(float(value))
- or value <= 0
- ):
- errors.append(f"{label} value must be a positive finite number")
- continue
- if not isinstance(rationale, str) or not rationale.strip():
- errors.append(f"{label} rationale must be non-empty")
- continue
- entry = ManifestEntry(path, float(value), rationale.strip())
- if entry.key in seen:
- errors.append(f"{label} duplicates manifest entry for {path} value {entry.value:g}")
- continue
- seen.add(entry.key)
- entries.append(entry)
- return entries, errors
-
-
-def check_timeout_overrides(
- root: Path, *, pyproject_path: Path | None = None, manifest_path: Path | None = None
-) -> tuple[list[TimeoutOverride], list[str]]:
- """Return all valid overrides and every policy violation under ``root``."""
- root = root.resolve()
- pyproject_path = (pyproject_path or root / "pyproject.toml").resolve()
- manifest_path = (manifest_path or root / MANIFEST_RELATIVE_PATH).resolve()
- try:
- default_timeout = _read_default_timeout(pyproject_path)
- except (OSError, ValueError, tomllib.TOMLDecodeError) as exc:
- return [], [f"{pyproject_path}: cannot read pytest timeout default: {exc}"]
-
- overrides: list[TimeoutOverride] = []
- errors: list[str] = []
- tests_dir = root / "tests"
- if tests_dir.exists():
- for path in sorted(tests_dir.rglob("*.py")):
- found, found_errors = _scan_python(path, root, scan_decorators=True, scan_commands=False)
- overrides.extend(found)
- errors.extend(found_errors)
- devtools_dir = root / "devtools"
- if devtools_dir.exists():
- for path in sorted(devtools_dir.rglob("*.py")):
- found, found_errors = _scan_python(path, root, scan_decorators=False, scan_commands=True)
- overrides.extend(found)
- errors.extend(found_errors)
-
- entries, manifest_errors = _read_manifest(manifest_path, root)
- errors.extend(manifest_errors)
- exceptional = {override.manifest_key for override in overrides if override.value > default_timeout}
- declared = {entry.key for entry in entries}
- for entry_path, value in sorted(exceptional - declared):
- errors.append(f"{entry_path}: timeout {value:g}s exceeds {default_timeout:g}s without a manifest rationale")
- for entry_path, value in sorted(declared - exceptional):
- errors.append(f"stale timeout override manifest entry: {entry_path} value {value:g}")
- return overrides, errors
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--root", type=Path, default=ROOT, help="Repository root to inspect.")
- parser.add_argument("--pyproject", type=Path, help="pytest configuration path (defaults to ROOT/pyproject.toml).")
- parser.add_argument(
- "--manifest",
- type=Path,
- help="Exception manifest path (defaults to ROOT/devtools/pytest_timeout_overrides.toml).",
- )
- parser.add_argument("--json", action="store_true", help="Emit the policy result as JSON.")
- args = parser.parse_args(argv)
- overrides, errors = check_timeout_overrides(args.root, pyproject_path=args.pyproject, manifest_path=args.manifest)
- payload: dict[str, Any] = {
- "overrides": [
- {"path": item.path, "line": item.line, "value": item.value, "source": item.source} for item in overrides
- ],
- "errors": errors,
- "ok": not errors,
- }
- if args.json:
- print(json.dumps(payload, indent=2))
- else:
- print(f"pytest timeout overrides: {len(overrides)} explicit override(s), {len(errors)} violation(s)")
- for error in errors:
- print(f" {error}")
- return 0 if not errors else 1
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/devtools/verify_raw_authority_frontier_executability.py b/devtools/verify_raw_authority_frontier_executability.py
deleted file mode 100644
index e7326d13aa..0000000000
--- a/devtools/verify_raw_authority_frontier_executability.py
+++ /dev/null
@@ -1,261 +0,0 @@
-"""Statically verify every raw-authority frontier state has a reachable actuator.
-
-Background
-----------
-
-``polylogue.storage.raw_reconciler`` classifies every accepted raw-authority
-head into one of a small closed set of ``RawAuthorityFrontierState`` values,
-each paired with a ``RawAuthorityActuator``. Only actuators with a real
-``apply()`` dispatch branch (``_APPLY_DISPATCHED_ACTUATORS``) promise
-"something automatically executes this"; only states in ``_EXECUTABLE_STATES``
-are ever selected by daemon convergence (``item.executable``).
-polylogue-w32w found a state (``UNRESOLVED_PROVENANCE``)
-paired with a dispatched actuator (``REFINE_QUARANTINE``) that was NOT in
-``_EXECUTABLE_STATES`` -- 4,174 blockers demanded an actuator no path could
-ever select, and the gap accumulated silently for weeks because nothing
-checked the pairing except live production data eventually noticing the
-backlog never drained.
-
-``RawAuthorityFrontierItem.__post_init__`` now raises if a *constructed*
-instance has this shape (PR #3466) -- but that is a runtime assertion: it
-only fires on whichever (state, actuator) pairs a test happens to construct.
-A future contributor adding a new frontier state, or re-pairing an existing
-one, can ship a classification branch that is never exercised by any test
-fixture; the constructor guard stays silent until that branch runs against
-real archive data, which is exactly the failure mode that let the original
-defect accumulate for weeks undetected. This lint closes that gap: it
-statically enumerates every (state, actuator) pair
-``polylogue/storage/raw_reconciler.py``'s classification code can literally
-construct -- independent of whether any test ever exercises that branch --
-and re-validates the same invariant the constructor enforces, so the CHECK
-fails at review time, not months later against live data.
-
-What this lint checks
-----------------------
-
-Parses ``polylogue/storage/raw_reconciler.py`` and finds every call site that
-constructs a frontier item's ``state``/``actuator`` pairing with **literal**
-enum-attribute arguments:
-
-* ``_item(state=RawAuthorityFrontierState.X, actuator=RawAuthorityActuator.Y, ...)``
- -- the sole ``RawAuthorityFrontierItem`` builder.
-* ``_StrategyOverride(state=RawAuthorityFrontierState.X,
- actuator=RawAuthorityActuator.Y, ...)`` -- overrides that later flow into
- ``_item`` via ``_item(state=strategy_override.state,
- actuator=strategy_override.actuator, ...)``; that forwarding call site's
- arguments are not literal (they read a variable), so this lint checks the
- override's own literal construction instead -- the same (state, actuator)
- pair reaches ``RawAuthorityFrontierItem.__post_init__`` either way.
-
-For each literal pair found, re-checks the exact invariant
-``RawAuthorityFrontierItem.__post_init__`` enforces at runtime: an actuator in
-``_APPLY_DISPATCHED_ACTUATORS`` must only ever be paired with a state in
-``_EXECUTABLE_STATES``. Both sets are imported directly from
-``polylogue.storage.raw_reconciler`` (not re-declared here), so this lint
-never drifts out of sync with the real executability gate.
-
-A ``state=``/``actuator=`` argument that is not a literal
-``RawAuthorityFrontierState.X`` / ``RawAuthorityActuator.Y`` attribute access
-(e.g. a bare variable) cannot be resolved statically and is reported
-separately as "dynamic" -- informational only, never a failure, since every
-current dynamic pairing (the ``_item(state=strategy_override.state, ...)``
-forwarding call) is already covered by checking its override's own literal
-construction site. A future dynamic pairing with no literal source anywhere
-in this file would not be caught by this lint; it would still be caught by
-the runtime constructor guard the first time a test or live classification
-constructs it.
-
-Wired standalone via ``devtools lab policy raw-authority-frontier-executability``
-(like ``schema-versioning``): static, archive-independent, sub-second.
-"""
-
-from __future__ import annotations
-
-import argparse
-import ast
-import json
-import sys
-from dataclasses import dataclass
-from pathlib import Path
-
-from devtools import repo_root as _get_root
-from polylogue.storage.raw_reconciler import (
- _APPLY_DISPATCHED_ACTUATORS,
- _EXECUTABLE_STATES,
- RawAuthorityActuator,
- RawAuthorityFrontierState,
-)
-
-ROOT = _get_root()
-RECONCILER_PATH = ROOT / "polylogue" / "storage" / "raw_reconciler.py"
-
-_TARGET_CALLEES: tuple[str, ...] = ("_item", "_StrategyOverride")
-
-_EXECUTABLE_STATE_NAMES = {state.name for state in _EXECUTABLE_STATES}
-_APPLY_DISPATCHED_ACTUATOR_NAMES = {actuator.name for actuator in _APPLY_DISPATCHED_ACTUATORS}
-
-
-@dataclass(frozen=True, slots=True)
-class FrontierPair:
- callee: str
- lineno: int
- state: str
- actuator: str
-
-
-@dataclass(frozen=True, slots=True)
-class DynamicSite:
- callee: str
- lineno: int
- detail: str
-
-
-@dataclass(frozen=True, slots=True)
-class ExecutabilityReport:
- pairs: tuple[FrontierPair, ...]
- dynamic_sites: tuple[DynamicSite, ...]
- violations: tuple[FrontierPair, ...]
-
- @property
- def ok(self) -> bool:
- return not self.violations
-
-
-def _literal_enum_attr(node: ast.expr, *, enum_name: str) -> str | None:
- """Return ``X`` for an ``EnumName.X`` attribute access node, else ``None``."""
- if not isinstance(node, ast.Attribute):
- return None
- value = node.value
- if not isinstance(value, ast.Name) or value.id != enum_name:
- return None
- return node.attr
-
-
-def collect_frontier_pairs(path: Path = RECONCILER_PATH) -> tuple[tuple[FrontierPair, ...], tuple[DynamicSite, ...]]:
- """Statically enumerate every literal (state, actuator) construction pair."""
- tree = ast.parse(path.read_text(encoding="utf-8"))
- pairs: list[FrontierPair] = []
- dynamic: list[DynamicSite] = []
-
- for node in ast.walk(tree):
- if not isinstance(node, ast.Call):
- continue
- func = node.func
- if not isinstance(func, ast.Name) or func.id not in _TARGET_CALLEES:
- continue
- state_arg: ast.expr | None = None
- actuator_arg: ast.expr | None = None
- for keyword in node.keywords:
- if keyword.arg == "state":
- state_arg = keyword.value
- elif keyword.arg == "actuator":
- actuator_arg = keyword.value
- if state_arg is None or actuator_arg is None:
- # Every real call site names both explicitly by keyword; a call
- # missing either is not this lint's concern (it would fail at
- # import/call time as a TypeError against _item's/StrategyOverride's
- # own required signature).
- continue
- state_name = _literal_enum_attr(state_arg, enum_name="RawAuthorityFrontierState")
- actuator_name = _literal_enum_attr(actuator_arg, enum_name="RawAuthorityActuator")
- if state_name is None or actuator_name is None:
- dynamic.append(
- DynamicSite(
- callee=func.id,
- lineno=node.lineno,
- detail="state/actuator argument is not a literal EnumName.MEMBER attribute access",
- )
- )
- continue
- pairs.append(FrontierPair(callee=func.id, lineno=node.lineno, state=state_name, actuator=actuator_name))
-
- return tuple(pairs), tuple(dynamic)
-
-
-def compute_executability_report(path: Path = RECONCILER_PATH) -> ExecutabilityReport:
- pairs, dynamic_sites = collect_frontier_pairs(path)
- # Fail closed on an unknown name: a rename that outpaces this lint's own
- # enum imports must not silently pass as "no violation found".
- for pair in pairs:
- if pair.state not in {state.name for state in RawAuthorityFrontierState}:
- raise ValueError(f"{path}:{pair.lineno}: unknown RawAuthorityFrontierState member {pair.state!r}")
- if pair.actuator not in {actuator.name for actuator in RawAuthorityActuator}:
- raise ValueError(f"{path}:{pair.lineno}: unknown RawAuthorityActuator member {pair.actuator!r}")
- violations = tuple(
- pair
- for pair in pairs
- if pair.actuator in _APPLY_DISPATCHED_ACTUATOR_NAMES and pair.state not in _EXECUTABLE_STATE_NAMES
- )
- return ExecutabilityReport(pairs=pairs, dynamic_sites=dynamic_sites, violations=violations)
-
-
-def _format_report(report: ExecutabilityReport, *, path: Path) -> str:
- rel = path.relative_to(ROOT) if path.is_absolute() else path
- lines = [
- f"frontier (state, actuator) construction sites checked: {len(report.pairs)}",
- f"dynamic (unresolvable) sites, informational only: {len(report.dynamic_sites)}",
- f"unreachable-actuator violations: {len(report.violations)}",
- ]
- if report.violations:
- lines.append("")
- lines.append(
- "Frontier states pairing a dispatched actuator with a non-executable "
- "state -- daemon convergence would never select these:"
- )
- for pair in report.violations:
- lines.append(
- f" {rel}:{pair.lineno}: {pair.callee}(state={pair.state}, actuator={pair.actuator}) -- "
- f"{pair.actuator} has an apply() dispatch branch but {pair.state} is not in _EXECUTABLE_STATES"
- )
- lines.append(
- " Fix: either add the state to _EXECUTABLE_STATES (and prove the daemon "
- "convergence path can safely select it), or pair this classification with a non-dispatched "
- "actuator (RawAuthorityActuator.NONE, REACQUIRE, or REQUEST_JUDGMENT)."
- )
- if report.dynamic_sites:
- lines.append("")
- lines.append("Dynamic sites (state/actuator not a literal enum attribute -- not checked here):")
- for site in report.dynamic_sites:
- lines.append(f" {rel}:{site.lineno}: {site.callee}(...) -- {site.detail}")
- if report.ok:
- lines.append("")
- lines.append("Raw-authority frontier executability policy intact.")
- return "\n".join(lines)
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- )
- parser.add_argument("--json", action="store_true", help="emit machine-readable JSON")
- args = parser.parse_args(argv)
-
- report = compute_executability_report()
-
- if args.json:
- print(
- json.dumps(
- {
- "pairs_checked": len(report.pairs),
- "dynamic_sites": [
- {"callee": site.callee, "lineno": site.lineno, "detail": site.detail}
- for site in report.dynamic_sites
- ],
- "violations": [
- {"callee": pair.callee, "lineno": pair.lineno, "state": pair.state, "actuator": pair.actuator}
- for pair in report.violations
- ],
- "ok": report.ok,
- },
- indent=2,
- )
- )
- else:
- print(_format_report(report, path=RECONCILER_PATH))
-
- return 0 if report.ok else 1
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/verify_raw_payload_hash_purity.py b/devtools/verify_raw_payload_hash_purity.py
deleted file mode 100644
index 72eac08592..0000000000
--- a/devtools/verify_raw_payload_hash_purity.py
+++ /dev/null
@@ -1,217 +0,0 @@
-"""Verify no raw-capture write path mutates bytes before they reach the hasher.
-
-Background
-----------
-
-Polylogue-u19l found a concrete, confirmed bug: ``sources/live/batch.py``'s
-``_append_payload_for_provider`` used to prepend a synthetic
-``{"type":"session_meta","payload":{"id":...}}`` line ahead of every Codex
-append-mode capture's real tail bytes, *before* those bytes were hashed and
-stored as the raw's content (``session_meta + b"\\n" + payload``, the exact
-shape this lint forbids). That made the stored blob architecturally never a
-literal byte-slice of the live file, permanently defeating any live-source
-byte-identity re-verification even when the live file was completely
-untouched (~59 GB of quarantined raw rows, ~95% of which were, in fact,
-directly re-verifiable once the synthetic header was accounted for).
-
-The fix (PR #3539, polylogue-u19l) carries the identity as sidecar metadata
-(``raw_sessions.native_id``) instead of splicing it into the hashed bytes.
-This lint (polylogue-ds4b4 item 2) generalizes the regression test: it
-statically forbids the *pattern* that produced the bug -- concatenating a
-freshly synthesized literal (a bytes/str constant, or the result of a
-``json.dumps``/``.encode()`` call) onto a name/attribute reference -- anywhere
-in the raw-capture write-path modules, not just in the one function that
-already got fixed.
-
-What this lint checks
-----------------------
-
-For every module in ``WRITE_PATH_MODULES`` (the modules that construct or
-carry the ``bytes`` that ultimately reach ``write_raw_payload``/
-``BlobPublisher.write_from_bytes`` -- the content-hashing boundary for raw
-session capture), parse the AST and flag every ``BinOp`` using ``+`` where at
-least one operand is a freshly synthesized literal (a bytes/str ``Constant``,
-an f-string, or a call to something that looks like serialization --
-``dumps``/``encode``) and the other operand is not itself another literal of
-the same kind (i.e. this is a synthesize-and-splice, not two literals being
-joined for an unrelated purpose, e.g. building a log message).
-
-Scope and false-positive discipline
-------------------------------------
-
-In scope: only the fixed module list below -- the modules on the raw-capture
-write path. An unrelated string-concatenation elsewhere in the codebase (log
-messages, error text, SQL fragments) never fires. Within scope, ordinary
-byte-slicing, ``.join()``, and passing a bare ``Name``/``Attribute`` through
-unmodified are unaffected -- only literal-onto-variable splicing trips the
-gate. There is no ack/exception mechanism: unlike classifier-fingerprint
-drift (where a change can be a deliberate, reviewed decision), byte-mutation
-before the content hasher has no legitimate use case on this write path --
-identity/metadata belongs in a sidecar column, never spliced into the hashed
-payload. If a genuinely new, legitimate need for payload-adjacent literal
-bytes arises, it belongs in ``WRITE_PATH_MODULES`` exclusion criteria (edit
-this module's own scope, with review), not a per-line escape hatch.
-
-Wired into ``devtools verify --lab`` alongside the other static policy
-checks: archive-independent, sub-second.
-"""
-
-from __future__ import annotations
-
-import argparse
-import ast
-import json
-import sys
-from dataclasses import dataclass
-
-from devtools import repo_root as _get_root
-
-ROOT = _get_root()
-
-# The raw-capture write path: every module that constructs, transforms, or
-# forwards the bytes that ultimately reach a raw payload hasher
-# (``write_raw_payload`` / ``BlobPublisher.write_from_bytes``) for
-# ``raw_sessions`` capture. Deliberately a fixed, reviewed list, not a
-# directory glob -- widening scope to "everything under sources/" would
-# false-positive on unrelated string building far from any hashed payload.
-WRITE_PATH_MODULES: tuple[str, ...] = (
- "polylogue/sources/live/batch.py",
- "polylogue/sources/live/batch_support.py",
- "polylogue/sources/live/append_ingest.py",
- "polylogue/pipeline/services/archive_ingest.py",
- "polylogue/pipeline/services/acquisition_records.py",
- "polylogue/pipeline/services/ingest_batch/_core.py",
- "polylogue/sources/source_acquisition_components.py",
- "polylogue/sources/drive/__init__.py",
- "polylogue/storage/sqlite/archive_tiers/archive.py",
- "polylogue/storage/sqlite/archive_tiers/revision_governance.py",
-)
-
-_SERIALIZE_CALL_NAMES = {"dumps", "json_dumps", "encode"}
-
-
-@dataclass(frozen=True, slots=True)
-class HashPurityViolation:
- path: str
- lineno: int
- col_offset: int
- detail: str
-
-
-def _looks_synthesized(node: ast.expr) -> bool:
- """A literal or serialization-call operand -- the "freshly minted" half."""
- if isinstance(node, ast.Constant) and isinstance(node.value, bytes | str):
- return True
- if isinstance(node, ast.JoinedStr): # f-string
- return True
- if isinstance(node, ast.Call):
- func = node.func
- name = func.attr if isinstance(func, ast.Attribute) else func.id if isinstance(func, ast.Name) else None
- if name in _SERIALIZE_CALL_NAMES:
- return True
- return False
-
-
-def _looks_like_captured_bytes(node: ast.expr) -> bool:
- """A bare reference operand -- plausibly the read/captured payload."""
- return isinstance(node, ast.Name | ast.Attribute | ast.Subscript)
-
-
-def _scan_binop(node: ast.BinOp, *, path: str) -> HashPurityViolation | None:
- if not isinstance(node.op, ast.Add):
- return None
- left, right = node.left, node.right
- synthesized_left, synthesized_right = _looks_synthesized(left), _looks_synthesized(right)
- captured_left, captured_right = _looks_like_captured_bytes(left), _looks_like_captured_bytes(right)
- # Flag only an asymmetric splice: one side freshly synthesized, the other
- # a bare reference. Two literals joined together (e.g. building a fixed
- # log-message prefix) or two references concatenated (e.g. joining two
- # already-captured buffers) are not the hazard this lint targets.
- if (synthesized_left and captured_right) or (synthesized_right and captured_left):
- return HashPurityViolation(
- path=path,
- lineno=node.lineno,
- col_offset=node.col_offset,
- detail="literal/serialized value concatenated onto a bare reference before hashing",
- )
- return None
-
-
-def scan_source_for_payload_concatenation(source: str, *, path: str) -> list[HashPurityViolation]:
- """Return every literal-onto-reference splice in *source*.
-
- Exposed standalone (not just via the CLI) so a test can feed a synthetic
- source-string fixture directly, mirroring
- ``verify_timestamp_doctrine.scan_ddl_for_text_timestamps``.
- """
- try:
- tree = ast.parse(source)
- except SyntaxError:
- return []
- violations: list[HashPurityViolation] = []
- for node in ast.walk(tree):
- if isinstance(node, ast.BinOp):
- violation = _scan_binop(node, path=path)
- if violation is not None:
- violations.append(violation)
- return violations
-
-
-def _collect_write_path_violations(modules: tuple[str, ...] = WRITE_PATH_MODULES) -> list[HashPurityViolation]:
- violations: list[HashPurityViolation] = []
- for rel in modules:
- full_path = ROOT / rel
- if not full_path.exists():
- continue
- source = full_path.read_text(encoding="utf-8")
- violations.extend(scan_source_for_payload_concatenation(source, path=rel))
- return violations
-
-
-def _format_report(violations: list[HashPurityViolation]) -> str:
- if not violations:
- return (
- f"Raw-payload hash purity intact: no write-path module concatenates a "
- f"synthesized literal onto captured bytes before hashing ({len(WRITE_PATH_MODULES)} modules scanned)."
- )
- lines = [f"Raw-payload hash-purity violations: {len(violations)}", ""]
- for violation in violations:
- lines.append(f" {violation.path}:{violation.lineno}: {violation.detail}")
- lines.append("")
- lines.append(
- "Policy violation (polylogue-ds4b4/u19l): a raw-capture write path must never splice a "
- "synthesized literal (bytes/str constant, f-string, json.dumps()/.encode() result) onto "
- "captured bytes before they reach the content hasher. Carry identity/metadata as sidecar "
- "data (a separate column/return value), and reconstruct any parseable header at READ time "
- "instead, per _append_payload_for_provider's docstring in polylogue/sources/live/batch.py."
- )
- return "\n".join(lines)
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- )
- parser.add_argument("--json", action="store_true", help="emit machine-readable JSON")
- args = parser.parse_args(argv)
-
- violations = _collect_write_path_violations()
-
- if args.json:
- payload = {
- "violations": [
- {"path": v.path, "lineno": v.lineno, "col_offset": v.col_offset, "detail": v.detail} for v in violations
- ],
- "modules_scanned": list(WRITE_PATH_MODULES),
- "ok": not violations,
- }
- print(json.dumps(payload, indent=2))
- else:
- print(_format_report(violations))
-
- return 0 if not violations else 1
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/verify_schema_upgrade_lane.py b/devtools/verify_schema_upgrade_lane.py
index 763f6d1d5e..f7adf16ecb 100644
--- a/devtools/verify_schema_upgrade_lane.py
+++ b/devtools/verify_schema_upgrade_lane.py
@@ -14,18 +14,12 @@
What this lint checks
---------------------
-1. Scan derived-tier storage modules for upgrade-shaped helpers
- (``build_vN_to_vM``, ``_apply_version_upgrade_plan``, ``migrate_v*``,
- etc.). The names match the historical Polylogue conventions called
- out in ``docs/internals.md`` and in the witness archive
- (``.local/witnesses/new/*schema_upgrades*``).
-
-2. Fail if any legacy helper exists for a derived tier, or when the current
- index schema version lacks a delta-class declaration. Durable-tier migrations
+1. Fail when the current index schema version lacks a delta-class declaration.
+ Durable-tier migrations
must live under ``polylogue/storage/sqlite/migrations/{source,user}/`` as
numbered SQL resources.
-3. Validate every entry in the index-tier benign-DDL convergence registry
+2. Validate every entry in the index-tier benign-DDL convergence registry
(``polylogue.storage.sqlite.archive_tiers.index_convergence.
INDEX_BENIGN_DDL_REGISTRY``, polylogue-jc1b): each entry's SQL must be
exactly one of ``CREATE TABLE IF NOT EXISTS``, ``CREATE INDEX IF NOT
@@ -35,29 +29,24 @@
is the sanctioned same-version-open path being asked to do something a
version bump should gate instead, and is rejected here.
-The lint is intentionally narrow. It detects helper names associated
-with in-place upgrades; it does not try to infer arbitrary SQL patches.
+The lint validates structured schema carriers and executable SQL shapes. It
+does not infer architecture from Python function names.
Wired into ``devtools verify --lab`` rather than the fast default path
because the policy boundary is a lab/architectural concern, not a
per-edit gate.
-**Out of scope (polylogue-gucv):** this lint is keyed entirely to
-``INDEX_SCHEMA_VERSION``. It has no visibility into whether a parser or
-classifier under ``polylogue/sources/`` or
-``polylogue/archive/artifact_taxonomy/`` changed what it accepts for
-identical input bytes -- that reparse-requiring drift can land with no
-version bump at all, so this lint runs green while already-indexed rows go
-silently stale (PR #3428 is the confirmed case). See
-``devtools/verify_classifier_fingerprints.py`` (``devtools lab policy
-classifier-fingerprints``), which fingerprints those functions directly. A
-green run of *this* lint is not evidence that no reparse is needed.
+**Out of scope:** this lint is keyed entirely to ``INDEX_SCHEMA_VERSION``.
+Parser and lowering drift use the production fingerprints declared by
+``polylogue.sources.origin_specs`` instead: archive rows, candidate metadata,
+and live-proof receipts carry those fingerprints, and archive verification
+rejects stale or mixed values. A green run of *this* lint alone is therefore
+not evidence that no reparse is needed.
"""
from __future__ import annotations
import argparse
-import ast
import json
import re
import sys
@@ -84,60 +73,13 @@
from polylogue.storage.sqlite.lifecycle import IndexDeltaDeclarationReport, index_delta_declaration_report
ROOT = _get_root()
-STORAGE_SQLITE_DIR = ROOT / "polylogue" / "storage" / "sqlite"
-MIGRATIONS_DIR = STORAGE_SQLITE_DIR / "migrations"
+MIGRATIONS_DIR = ROOT / "polylogue" / "storage" / "sqlite" / "migrations"
ALLOWED_MIGRATION_TIERS = {"source", "user", "audit"}
-# Upgrade-shaped helper name patterns. Matched against ``def ``
-# at the top level of any module under ``polylogue/storage/sqlite/``.
-#
-# Patterns are derived from the historical naming used by upgrade
-# helpers that have since been removed (preserved in the witness
-# archive under ``.local/witnesses/new/*schema_upgrades*``) and from
-# the ``build_vN_to_vM`` / ``_apply_version_upgrade_plan`` naming
-# called out as the policy-violating shape in ``docs/internals.md``.
-_HELPER_PATTERNS: tuple[re.Pattern[str], ...] = (
- re.compile(r"^build_v\d+_to_v\d+$"),
- re.compile(r"^_?apply_version_upgrade(_plan)?$"),
- re.compile(r"^_?upgrade_v\d+_to_v\d+$"),
- re.compile(r"^_?migrate_v\d+(_to_v\d+)?$"),
- re.compile(r"^ensure_schema_upgrades_v\d+$"),
-)
-
_DURABLE_MIGRATION_SQL_RE = re.compile(r"^\d{3,}_[a-z0-9_]+\.sql$")
_DURABLE_MIGRATION_SIDECAR_RE = re.compile(r"^\d{3,}\.train\.json$")
-@dataclass(frozen=True, slots=True)
-class HelperHit:
- name: str
- path: Path
- lineno: int
-
-
-def _is_helper_name(name: str) -> bool:
- return any(pattern.match(name) for pattern in _HELPER_PATTERNS)
-
-
-def _collect_upgrade_helpers() -> list[HelperHit]:
- """Return upgrade-shaped helpers outside the durable migration runner."""
- hits: list[HelperHit] = []
- if not STORAGE_SQLITE_DIR.exists():
- return hits
- for path in sorted(STORAGE_SQLITE_DIR.rglob("*.py")):
- rel_parts = path.relative_to(STORAGE_SQLITE_DIR).parts
- if rel_parts[:1] == ("migrations",) or path.name == "migrations.py":
- continue
- try:
- tree = ast.parse(path.read_text(encoding="utf-8"))
- except SyntaxError:
- continue
- for node in ast.walk(tree):
- if isinstance(node, ast.FunctionDef | ast.AsyncFunctionDef) and _is_helper_name(node.name):
- hits.append(HelperHit(name=node.name, path=path, lineno=node.lineno))
- return hits
-
-
# Index-tier benign-DDL registry entries (polylogue-jc1b) must be exactly one
# of these idempotent shapes -- the whole point is that re-applying an entry
# on every same-version open is always a no-op past the first time.
@@ -246,7 +188,6 @@ def durable_migration_collision_report(
def _format_report(
*,
- helpers: list[HelperHit],
invalid_migrations: list[Path],
delta_report: IndexDeltaDeclarationReport,
benign_ddl_violations: list[BenignDDLViolation],
@@ -268,7 +209,6 @@ def _format_report(
durable_migration_collisions = durable_migration_collisions or {}
collision_entries = cast(tuple[object, ...], durable_migration_collisions.get("collisions", ()))
lines = [
- f"derived-tier upgrade helpers found: {len(helpers)}",
f"invalid durable migration resources found: {len(invalid_migrations)}",
f"durable change-train reservations found: {len(durable_reservations)}",
f"durable change-train violations found: {len(durable_violations)}",
@@ -276,14 +216,6 @@ def _format_report(
f"undeclared index schema deltas found: {len(delta_report['missing_versions'])}",
f"invalid index benign-DDL registry entries found: {len(benign_ddl_violations)}",
]
- if helpers:
- lines.append("")
- lines.append("Discovered upgrade helpers:")
- for hit in helpers:
- rel = hit.path.relative_to(ROOT)
- lines.append(f" {rel}:{hit.lineno} def {hit.name}")
- lines.append("")
- lines.append("Policy violation: derived tiers must rebuild or blue-green replace, not migrate in place.")
if invalid_migrations:
lines.append("")
lines.append("Invalid migration resources:")
@@ -322,8 +254,7 @@ def _format_report(
lines.append("Durable migration slot collisions:")
lines.extend(f" {collision}" for collision in collision_entries)
if (
- not helpers
- and not invalid_migrations
+ not invalid_migrations
and bool(delta_report["ok"])
and not benign_ddl_violations
and not durable_violations
@@ -342,7 +273,6 @@ def main(argv: list[str] | None = None) -> int:
parser.add_argument("--json", action="store_true", help="emit machine-readable JSON")
args = parser.parse_args(argv)
- helpers = _collect_upgrade_helpers()
invalid_migrations = _invalid_migration_paths()
durable_change_train_reports = {
tier.value: durable_change_train_policy_report(tier)
@@ -353,8 +283,7 @@ def main(argv: list[str] | None = None) -> int:
benign_ddl_violations = _invalid_benign_ddl_entries()
ok = (
- not helpers
- and not invalid_migrations
+ not invalid_migrations
and bool(delta_report["ok"])
and not benign_ddl_violations
and all(bool(report.get("ok")) for report in durable_change_train_reports.values())
@@ -363,9 +292,6 @@ def main(argv: list[str] | None = None) -> int:
if args.json:
payload = {
- "upgrade_helpers": [
- {"name": hit.name, "path": str(hit.path.relative_to(ROOT)), "line": hit.lineno} for hit in helpers
- ],
"invalid_migration_resources": [str(path.relative_to(ROOT)) for path in invalid_migrations],
"durable_change_trains": durable_change_train_reports,
"durable_migration_collisions": durable_migration_collisions,
@@ -379,7 +305,6 @@ def main(argv: list[str] | None = None) -> int:
else:
print(
_format_report(
- helpers=helpers,
invalid_migrations=invalid_migrations,
delta_report=delta_report,
benign_ddl_violations=benign_ddl_violations,
diff --git a/devtools/verify_slos.py b/devtools/verify_slos.py
index 9cb949c7ba..008208539c 100644
--- a/devtools/verify_slos.py
+++ b/devtools/verify_slos.py
@@ -13,7 +13,6 @@
from __future__ import annotations
import argparse
-import hashlib
import json
import os
import subprocess
@@ -23,25 +22,13 @@
from devtools import repo_root as _get_root
from devtools.benchmark_results import parse_pytest_benchmark_stats
-from devtools.verify_runs import apply_managed_pytest_runtime_policy, force_managed_pytest_scratch, git_head
-from polylogue.scenarios.workload import (
- BudgetMeasure,
- BudgetSemantics,
- MeasurementScope,
- WorkloadBudget,
- WorkloadEnvelopeSpec,
- WorkloadInputRef,
- WorkloadPhaseObservation,
- WorkloadReceipt,
- WorkloadRunStatus,
-)
+from devtools.verify_runs import apply_managed_pytest_runtime_policy, force_managed_pytest_scratch
ROOT = _get_root()
SLO_CATALOG = ROOT / "docs" / "plans" / "slo-catalog.yaml"
SLO_GATES = frozenset({"required", "informational"})
SLO_TIERS = frozenset({"cheap-local", "lab"})
DEFAULT_TIER = "cheap-local"
-SLO_WORKLOAD_RECEIPT = ROOT / ".cache" / "verify" / "current-slo-workload-receipt.json"
# ---------------------------------------------------------------------------
@@ -176,76 +163,6 @@ def _estimate_p95(entry_stats: dict[str, float]) -> float:
return mean + 1.645 * stddev
-def _slo_workload_receipt(
- *,
- catalog_text: str,
- surfaces: dict[str, dict[str, object]],
- active_tiers: frozenset[str] | None,
- passed: list[dict[str, object]],
- violations: list[dict[str, object]],
- blocking: bool,
-) -> dict[str, object]:
- """Adapt percentile SLO rows into named shared-receipt phases."""
- measured = {str(row["surface"]): row for row in (*passed, *violations) if isinstance(row.get("surface"), str)}
- phases: list[str] = []
- budgets: list[WorkloadBudget] = []
- observations: list[WorkloadPhaseObservation] = []
- for surface_name, config in sorted(surfaces.items()):
- tier, tier_error = _surface_tier(surface_name, config)
- gate, gate_error = _surface_gate(surface_name, config)
- if tier_error is not None or gate_error is not None or tier is None or gate is None:
- continue
- if active_tiers is not None and tier not in active_tiers:
- continue
- row = measured.get(surface_name)
- for statistic in ("p50", "p95"):
- target = config.get(f"{statistic}_ms")
- if not isinstance(target, int):
- continue
- phase = f"{surface_name}:{statistic}"
- phases.append(phase)
- budgets.append(
- WorkloadBudget(
- BudgetMeasure.WALL_MS,
- target,
- (BudgetSemantics.REGRESSION_GATE if gate == "required" else BudgetSemantics.MEASURE_ONLY),
- phase=phase,
- )
- )
- actual = row.get(f"actual_{statistic}_ms") if row is not None else None
- observations.append(
- WorkloadPhaseObservation(
- name=phase,
- wall_ms=float(actual) if isinstance(actual, int | float) else None,
- unavailable=("wall_ms",) if not isinstance(actual, int | float) else (),
- )
- )
- catalog_id = hashlib.sha256(catalog_text.encode("utf-8")).hexdigest()
- spec = WorkloadEnvelopeSpec(
- workload_id="read-surface-slo-catalog",
- family_id="read-surface-slo",
- version=1,
- inputs=(WorkloadInputRef(input_id=f"slo-catalog:sha256:{catalog_id}"),),
- phases=tuple(phases),
- measurement_scope=MeasurementScope.PROCESS_TREE,
- budgets=tuple(budgets),
- )
- head = git_head(ROOT)
- receipt = WorkloadReceipt.from_observations(
- spec=spec,
- status=WorkloadRunStatus.FAILED if blocking else WorkloadRunStatus.SUCCEEDED,
- build_id=f"git:{head}" if head is not None else None,
- runtime_id=f"python:{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
- archive_id=None,
- generation_id=None,
- frame_id=None,
- phases=tuple(observations),
- evidence_refs=(str(SLO_WORKLOAD_RECEIPT.relative_to(ROOT)),),
- notes=("Each surface percentile is a named phase so p50 and p95 retain distinct budgets.",),
- )
- return dict(receipt.to_payload())
-
-
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
@@ -410,16 +327,6 @@ def main(argv: list[str] | None = None) -> int:
# 5. Report
blocking = bool(catalog_errors or violations or missing_required)
- workload_receipt = _slo_workload_receipt(
- catalog_text=catalog_text,
- surfaces=surfaces,
- active_tiers=active_tiers,
- passed=passed,
- violations=violations,
- blocking=blocking,
- )
- SLO_WORKLOAD_RECEIPT.parent.mkdir(parents=True, exist_ok=True)
- SLO_WORKLOAD_RECEIPT.write_text(json.dumps(workload_receipt, indent=2, ensure_ascii=False) + "\n")
if args.json:
json.dump(
{
@@ -431,7 +338,6 @@ def main(argv: list[str] | None = None) -> int:
"passed": passed,
"uncovered_informational": uncovered_informational,
"skipped_tier": skipped_tier,
- "workload_receipt": workload_receipt,
},
sys.stdout,
indent=2,
@@ -485,7 +391,6 @@ def main(argv: list[str] | None = None) -> int:
if active_tiers is not None:
print(f"active_tiers={sorted(active_tiers)}")
- print(f"workload_receipt={workload_receipt['receipt_id']} artifact={SLO_WORKLOAD_RECEIPT.relative_to(ROOT)}")
print(f"blocking={blocking}")
return 1 if blocking else 0
diff --git a/devtools/verify_table_exists_duplication.py b/devtools/verify_table_exists_duplication.py
deleted file mode 100644
index 8f417faeb2..0000000000
--- a/devtools/verify_table_exists_duplication.py
+++ /dev/null
@@ -1,148 +0,0 @@
-"""Forbid a new duplicate SQLite existence-check helper outside the canonical module.
-
-Background
-----------
-
-polylogue-48h found ~25 independently maintained copies of
-``_table_exists``/``table_exists``/``_column_exists``/``_index_exists`` (and
-their async variants) scattered across ``cli/``, ``daemon/``, ``storage/``,
-``sources/``, ``insights/``, and ``operations/`` -- each trivially small and
-subtly different (a ``schema=`` kwarg on some, ``type IN (...)`` alternatives
-that never actually match anything in ``sqlite_master`` on others). They were
-consolidated into ``polylogue.storage.introspection`` (``table_exists``,
-``table_exists_async``, ``column_exists``, ``column_exists_async``,
-``index_exists``, ``index_exists_async``). This grep-based tripwire keeps the
-consolidation from silently regrowing: a module that wants a table/column/
-index existence check should import from ``polylogue.storage.introspection``,
-not redefine its own.
-
-What this lint checks
-----------------------
-
-Every ``polylogue/**/*.py`` file except ``polylogue/storage/introspection.py``
-itself is scanned line-by-line for a top-level (column 0) ``def``/``async def``
-whose name matches the forbidden shape:
-
-* ``_table_exists`` / ``table_exists`` (+ ``_sync``/``_async`` suffix variants)
-* ``_column_exists`` / ``column_exists`` (+ suffix variants)
-* ``_index_exists`` / ``index_exists`` (+ suffix variants)
-
-A thin, behaviorally-distinct wrapper that *delegates* to the canonical
-module (e.g. one that also swallows a specific ``sqlite3.OperationalError``,
-or checks an ATTACHed schema alias that may not exist yet) is not itself
-flagged by name matching alone -- this lint only catches the exact duplicate
-*names*, on the theory that a genuinely new name (``_attached_table_exists``,
-``_named_table_exists_sync``, ``_schema_object_exists``) signals a real design
-choice made under review, while reusing one of the exact retired names is the
-easy way to silently reintroduce the duplication this bead removed.
-
-Wired into ``devtools verify --quick`` (the static/generated-surface gate,
-alongside the other ``lab policy`` checks): archive-independent, sub-second.
-"""
-
-from __future__ import annotations
-
-import argparse
-import json
-import re
-import sys
-from dataclasses import dataclass
-
-from devtools import repo_root as _get_root
-
-ROOT = _get_root()
-
-# The one place these names are allowed to be defined.
-CANONICAL_MODULE = "polylogue/storage/introspection.py"
-
-_FORBIDDEN_BASE_NAMES = ("table_exists", "column_exists", "index_exists")
-_SUFFIXES = ("", "_sync", "_async")
-
-_FORBIDDEN_NAMES = frozenset(
- f"{prefix}{base}{suffix}" for prefix in ("", "_") for base in _FORBIDDEN_BASE_NAMES for suffix in _SUFFIXES
-)
-
-_DEF_PATTERN = re.compile(r"^(?:async\s+)?def\s+(?P[A-Za-z_][A-Za-z0-9_]*)\s*\(")
-
-
-@dataclass(frozen=True, slots=True)
-class DuplicationViolation:
- path: str
- lineno: int
- name: str
-
-
-def scan_source_for_duplicate_definitions(source: str, *, path: str) -> list[DuplicationViolation]:
- """Return every forbidden-named top-level def in *source*.
-
- Exposed standalone so a test can feed a synthetic source-string fixture
- directly, mirroring ``verify_raw_payload_hash_purity.scan_source_for_payload_concatenation``.
- """
- violations: list[DuplicationViolation] = []
- for lineno, line in enumerate(source.splitlines(), start=1):
- match = _DEF_PATTERN.match(line)
- if match is None:
- continue
- name = match.group("name")
- if name in _FORBIDDEN_NAMES:
- violations.append(DuplicationViolation(path=path, lineno=lineno, name=name))
- return violations
-
-
-def _collect_violations() -> list[DuplicationViolation]:
- violations: list[DuplicationViolation] = []
- for full_path in sorted((ROOT / "polylogue").rglob("*.py")):
- rel = full_path.relative_to(ROOT).as_posix()
- if rel == CANONICAL_MODULE:
- continue
- source = full_path.read_text(encoding="utf-8")
- violations.extend(scan_source_for_duplicate_definitions(source, path=rel))
- return violations
-
-
-def _format_report(violations: list[DuplicationViolation]) -> str:
- if not violations:
- return (
- "Table/column/index existence-check consolidation intact: no module outside "
- f"{CANONICAL_MODULE} redefines table_exists/column_exists/index_exists (polylogue-48h)."
- )
- lines = [f"SQLite existence-check duplication violations: {len(violations)}", ""]
- for violation in violations:
- lines.append(f" {violation.path}:{violation.lineno}: def {violation.name}(...)")
- lines.append("")
- lines.append(
- "Policy violation (polylogue-48h): table/column/index existence checks are "
- f"centralized in {CANONICAL_MODULE} (table_exists, table_exists_async, column_exists, "
- "column_exists_async, index_exists, index_exists_async). Import from there instead of "
- "redefining one of these names. If you genuinely need different error-handling or "
- "schema-quoting behavior, write a differently-named thin wrapper that delegates to the "
- "canonical function (see polylogue/storage/usage.py's _table_exists_in_schema for the pattern)."
- )
- return "\n".join(lines)
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- )
- parser.add_argument("--json", action="store_true", help="emit machine-readable JSON")
- args = parser.parse_args(argv)
-
- violations = _collect_violations()
-
- if args.json:
- payload = {
- "violations": [{"path": v.path, "lineno": v.lineno, "name": v.name} for v in violations],
- "canonical_module": CANONICAL_MODULE,
- "ok": not violations,
- }
- print(json.dumps(payload, indent=2))
- else:
- print(_format_report(violations))
-
- return 0 if not violations else 1
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/verify_test_infra_currency.py b/devtools/verify_test_infra_currency.py
deleted file mode 100644
index f2f74300c7..0000000000
--- a/devtools/verify_test_infra_currency.py
+++ /dev/null
@@ -1,248 +0,0 @@
-"""Verify ``tests/infra/`` helpers stay current with the live SQLite schema.
-
-Background: ``tests/infra/storage_records.py`` and sibling helpers contain
-hand-written SQL fragments that mirror production write paths (stats upsert,
-identity-preserving repoint, etc.). When archive tier DDL changes and new
-tables are introduced (see #1208: v15 -> v16 -> v17 added
-``user_marks`` / ``user_annotations``), helpers that reference those tables
-silently break against any in-memory test connection that does not run the
-full schema bootstrap. The breakage hides behind testmon selection until an
-unrelated change invalidates the affected test set.
-
-This lint closes that drift class:
-
-1. Collect the set of tables declared by ``polylogue/storage/sqlite/archive_tiers/*.py``
- (the current archive DDL surface).
-2. Scan every ``tests/infra/*.py`` helper for SQL table references
- (``FROM ``, ``UPDATE ``, ``INSERT INTO ``,
- ``DELETE FROM ``).
-3. Fail loudly when any referenced table is not present in the live schema.
- That asymmetric direction is the actionable one: a helper that targets a
- nonexistent / renamed table will crash at runtime against any DB built
- from the current schema, exactly the cliff #1208 documents.
-
-The lint is intentionally narrow. It does NOT require every schema table
-to appear in helpers — that direction would push us toward boilerplate
-references for tables that test infra has no reason to touch.
-
-This is a static check: no DB is opened, no Python imports beyond AST
-parsing of the helper modules.
-"""
-
-from __future__ import annotations
-
-import argparse
-import ast
-import json
-import re
-import sys
-from pathlib import Path
-
-from devtools import repo_root as _get_root
-
-ROOT = _get_root()
-SCHEMA_DDL_DIR = ROOT / "polylogue" / "storage" / "sqlite"
-SCHEMA_SUPPORT_DDL_FILES = (ROOT / "polylogue" / "storage" / "fts" / "sql.py",)
-TEST_INFRA_DIR = ROOT / "tests" / "infra"
-
-# Match CREATE TABLE [IF NOT EXISTS] .
-_CREATE_TABLE_RE = re.compile(
- r"CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?([a-zA-Z_][a-zA-Z0-9_]*)",
- re.IGNORECASE,
-)
-# Match CREATE VIRTUAL TABLE USING fts5(...).
-_CREATE_VTABLE_RE = re.compile(
- r"CREATE\s+VIRTUAL\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?([a-zA-Z_][a-zA-Z0-9_]*)",
- re.IGNORECASE,
-)
-# Table references in helper SQL. Keep these conservative — only match
-# bare identifiers, not subqueries / quoted-identifier edge cases.
-_REF_RES = (
- re.compile(r"\bFROM\s+([a-zA-Z_][a-zA-Z0-9_]*)", re.IGNORECASE),
- re.compile(r"\bUPDATE\s+([a-zA-Z_][a-zA-Z0-9_]*)", re.IGNORECASE),
- re.compile(
- r"\bINSERT\s+(?:OR\s+(?:IGNORE|REPLACE|ABORT|FAIL|ROLLBACK)\s+)?INTO\s+([a-zA-Z_][a-zA-Z0-9_]*)", re.IGNORECASE
- ),
- re.compile(r"\bDELETE\s+FROM\s+([a-zA-Z_][a-zA-Z0-9_]*)", re.IGNORECASE),
- re.compile(r"\bJOIN\s+([a-zA-Z_][a-zA-Z0-9_]*)", re.IGNORECASE),
-)
-
-# SQL keywords / common aliases that show up in match position but are not
-# table names. Used to reduce false positives in the "FROM x" matcher.
-_SQL_KEYWORDS = frozenset(
- {
- "select",
- "where",
- "values",
- "set",
- "into",
- "on",
- "as",
- "and",
- "or",
- "not",
- "null",
- "case",
- "when",
- "then",
- "else",
- "end",
- }
-)
-
-# Tables that exist outside the polylogue schema (SQLite built-ins, FTS5
-# internals, etc.). Referencing them from helpers is legitimate.
-_SQLITE_BUILTIN_TABLES = frozenset(
- {
- "sqlite_master",
- "sqlite_sequence",
- "sqlite_stat1",
- "sqlite_stat4",
- "sqlite_temp_master",
- }
-)
-
-
-def _collect_schema_tables() -> frozenset[str]:
- tables: set[str] = set()
- ddl_files = [*list((SCHEMA_DDL_DIR / "archive_tiers").glob("*.py")), *SCHEMA_SUPPORT_DDL_FILES]
- for ddl_file in ddl_files:
- text = ddl_file.read_text(encoding="utf-8")
- tables.update(name.lower() for name in _CREATE_TABLE_RE.findall(text))
- tables.update(name.lower() for name in _CREATE_VTABLE_RE.findall(text))
- return frozenset(tables)
-
-
-_SQL_VERB_RE = re.compile(
- r"\b(?:SELECT|INSERT|UPDATE|DELETE|CREATE|REPLACE|UPSERT|WITH)\b",
- re.IGNORECASE,
-)
-
-
-def _looks_like_sql(literal: str) -> bool:
- """Heuristic: only scan literals that contain at least one SQL verb.
-
- Eliminates docstring / log-message false positives like "schema from".
- """
- return bool(_SQL_VERB_RE.search(literal))
-
-
-def _iter_string_literals(text: str) -> list[tuple[str, int]]:
- """Return ``(literal_value, lineno)`` for every non-docstring string literal.
-
- Only string nodes are returned, so Python ``import`` statements and bare
- identifiers cannot generate false positives. SQL fragments live inside
- triple-quoted or single-line string literals in production helpers.
-
- Docstrings (the first ``Constant`` child of a module/class/function body)
- are skipped — they routinely contain English prose that happens to use
- SQL verbs like ``CREATE`` or ``WITH``.
- """
- results: list[tuple[str, int]] = []
- try:
- tree = ast.parse(text)
- except SyntaxError:
- return results
-
- docstring_nodes: set[int] = set()
- for node in ast.walk(tree):
- if isinstance(node, ast.Module | ast.ClassDef | ast.FunctionDef | ast.AsyncFunctionDef):
- body = getattr(node, "body", None) or []
- if (
- body
- and isinstance(body[0], ast.Expr)
- and isinstance(body[0].value, ast.Constant)
- and isinstance(body[0].value.value, str)
- ):
- docstring_nodes.add(id(body[0].value))
-
- for node in ast.walk(tree):
- if isinstance(node, ast.Constant) and isinstance(node.value, str):
- if id(node) in docstring_nodes:
- continue
- results.append((node.value, node.lineno))
- return results
-
-
-def _collect_helper_table_refs() -> dict[str, set[tuple[Path, int]]]:
- """Return ``{table_name: {(helper_path, line_no), ...}}``.
-
- Helper modules express SQL as string literals (often triple-quoted). We
- parse each helper's AST, pull out string literals, and only then run the
- table-reference regex against those literals. That guarantees Python
- ``from x import y`` or ``UPDATE`` used as a method name never produces
- false positives.
- """
- refs: dict[str, set[tuple[Path, int]]] = {}
- for helper in sorted(TEST_INFRA_DIR.rglob("*.py")):
- if helper.name.startswith("test_"):
- # Tests under tests/infra/ are exercised by the suite itself;
- # the lint targets shared helper modules.
- continue
- text = helper.read_text(encoding="utf-8")
- for literal, lineno in _iter_string_literals(text):
- if not _looks_like_sql(literal):
- continue
- for matcher in _REF_RES:
- for name in matcher.findall(literal):
- lowered = name.lower()
- if lowered in _SQL_KEYWORDS:
- continue
- if lowered in _SQLITE_BUILTIN_TABLES:
- continue
- refs.setdefault(lowered, set()).add((helper, lineno))
- return refs
-
-
-def _format_report(
- *,
- tables: frozenset[str],
- refs: dict[str, set[tuple[Path, int]]],
- missing: dict[str, set[tuple[Path, int]]],
-) -> str:
- lines = [
- f"schema tables: {len(tables)}",
- f"helper table refs: {len(refs)}",
- f"helper refs without matching schema table: {len(missing)}",
- ]
- if missing:
- lines.append("")
- lines.append("Stale helper references:")
- for table, hits in sorted(missing.items()):
- for path, lineno in sorted(hits):
- rel = path.relative_to(ROOT)
- lines.append(f" {rel}:{lineno} references unknown table {table!r}")
- return "\n".join(lines)
-
-
-def main(argv: list[str] | None = None) -> int:
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- )
- parser.add_argument("--json", action="store_true", help="emit machine-readable JSON")
- args = parser.parse_args(argv)
-
- tables = _collect_schema_tables()
- refs = _collect_helper_table_refs()
- missing = {table: hits for table, hits in refs.items() if table not in tables}
-
- if args.json:
- payload = {
- "schema_tables": sorted(tables),
- "helper_table_refs": sorted(refs),
- "missing": {
- table: [{"path": str(path.relative_to(ROOT)), "line": lineno} for path, lineno in sorted(hits)]
- for table, hits in sorted(missing.items())
- },
- "ok": not missing,
- }
- print(json.dumps(payload, indent=2))
- else:
- print(_format_report(tables=tables, refs=refs, missing=missing))
-
- return 0 if not missing else 1
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/devtools/visual_artifacts.py b/devtools/visual_artifacts.py
deleted file mode 100644
index f4edfc13d7..0000000000
--- a/devtools/visual_artifacts.py
+++ /dev/null
@@ -1,151 +0,0 @@
-"""Committed reader visual artifact inventory for docs and lab-smoke payloads."""
-
-from __future__ import annotations
-
-from dataclasses import dataclass
-
-
-@dataclass(frozen=True, slots=True)
-class VisualArtifact:
- """One browserless reader artifact emitted by tests/visual."""
-
- artifact_id: str
- owner: str
- fixture_id: str
- routes: tuple[str, ...]
- evidence_kind: str = "browserless-dom"
-
- def as_payload(self) -> dict[str, object]:
- """Return the machine-readable inventory shape for lab-smoke reports."""
- return {
- "artifact_id": self.artifact_id,
- "owner": self.owner,
- "fixture_id": self.fixture_id,
- "routes": list(self.routes),
- "evidence_kind": self.evidence_kind,
- }
-
-
-READER_VISUAL_SMOKE_PYTEST_COMMAND: tuple[str, ...] = ("python", "-m", "pytest", "-q", "tests/visual")
-READER_VISUAL_SMOKE_DEVTOOLS_COMMAND: tuple[str, ...] = ("uv", "run", "devtools", "test", "tests/visual")
-READER_VISUAL_SMOKE_REPORT: str = ".local/visual/reader-smoke/reader-visual-smoke.json"
-
-READER_VISUAL_ARTIFACTS: tuple[VisualArtifact, ...] = (
- VisualArtifact(
- artifact_id="polylogue.local_reader.search",
- owner="tests/visual/test_reader_dom_smoke.py",
- fixture_id="reader-visual-synthetic-v1",
- routes=("/", "/api/sessions", "/api/facets", "/api/facets?origin=...", "/api/facets?query=..."),
- ),
- VisualArtifact(
- artifact_id="polylogue.local_reader.workspace.stack",
- owner="tests/visual/test_reader_dom_smoke.py",
- fixture_id="reader-visual-synthetic-workspace-v1",
- routes=("/w/stack?ids=...&focus=...", "/api/stack?ids=..."),
- ),
- VisualArtifact(
- artifact_id="polylogue.local_reader.workspace.compare",
- owner="tests/visual/test_reader_dom_smoke.py",
- fixture_id="reader-visual-synthetic-workspace-v1",
- routes=("/w/compare?left=...&right=...&align=prompt", "/api/compare?left=...&right=...&align=prompt"),
- ),
- VisualArtifact(
- artifact_id="polylogue.local_reader.session",
- owner="tests/visual/test_reader_dom_smoke.py",
- fixture_id="reader-visual-synthetic-v1",
- routes=("/s/{id}", "/api/sessions/{id}", "/api/sessions/{id}/messages", "/api/sessions/{id}/raw"),
- ),
- VisualArtifact(
- artifact_id="polylogue.local_reader.search.query",
- owner="tests/visual/test_reader_dom_smoke.py",
- fixture_id="reader-visual-synthetic-v1",
- routes=("/api/sessions?query=...",),
- ),
- VisualArtifact(
- artifact_id="polylogue.local_reader.cost_panel",
- owner="tests/visual/test_reader_dom_smoke.py",
- fixture_id="reader-visual-synthetic-v1",
- routes=("/api/sessions/{id}/cost",),
- ),
- VisualArtifact(
- artifact_id="polylogue.local_reader.evidence_panel",
- owner="tests/visual/test_reader_dom_smoke.py",
- fixture_id="reader-visual-synthetic-v1",
- routes=("/s/{id}", "/api/sessions/{id}/artifacts", "/api/sessions/{id}/neighbors"),
- ),
- VisualArtifact(
- artifact_id="polylogue.local_reader.overlay_mutations",
- owner="tests/visual/test_reader_dom_smoke.py",
- fixture_id="reader-visual-synthetic-v1",
- routes=("/s/{id}", "/api/overlays/*"),
- ),
- VisualArtifact(
- artifact_id="polylogue.local_reader.operator_flow",
- owner="tests/visual/test_reader_dom_smoke.py",
- fixture_id="reader-visual-synthetic-v1",
- routes=("/s/{id}", "/api/sessions/{id}/context", "/api/overlays/*"),
- ),
- VisualArtifact(
- artifact_id="polylogue.local_reader.insights_browser",
- owner="tests/visual/test_reader_dom_smoke.py",
- fixture_id="reader-visual-synthetic-v1",
- routes=("/api/insights/sessions/{id}",),
- ),
- VisualArtifact(
- artifact_id="polylogue.local_reader.degraded",
- owner="tests/visual/test_reader_dom_smoke.py",
- fixture_id="reader-visual-synthetic-empty-and-degraded-v1",
- routes=("/api/sessions?query=...",),
- ),
- VisualArtifact(
- artifact_id="polylogue.local_reader.paste_spans",
- owner="tests/visual/test_reader_paste_spans.py",
- fixture_id="reader-visual-synthetic-v1+diff",
- routes=("/p", "/api/paste-browser"),
- ),
- VisualArtifact(
- artifact_id="polylogue.local_reader.paste_browser_empty",
- owner="tests/visual/test_reader_paste_spans.py",
- fixture_id="reader-visual-empty-archive",
- routes=("/api/paste-browser",),
- ),
- VisualArtifact(
- artifact_id="polylogue.local_reader.attachment_surface",
- owner="tests/visual/test_reader_attachments.py",
- fixture_id="reader-visual-attachments-v1",
- routes=("/a", "/api/attachments", "/api/sessions/{id}/attachments"),
- ),
- VisualArtifact(
- artifact_id="polylogue.local_reader.attachment_library_empty",
- owner="tests/visual/test_reader_attachments.py",
- fixture_id="reader-visual-attachments-empty",
- routes=("/api/attachments",),
- ),
- VisualArtifact(
- artifact_id="polylogue.local_reader.message_card",
- owner="tests/visual/test_reader_action_rail.py",
- fixture_id="reader-visual-synthetic-v1",
- routes=("/", "/api/sessions", "/api/messages/{id}/actions"),
- ),
- VisualArtifact(
- artifact_id="polylogue.local_reader.semantic_cards",
- owner="tests/visual/test_reader_semantic_cards.py",
- fixture_id="reader-visual-synthetic-v1",
- routes=("/", "/api/sessions/{id}"),
- ),
-)
-
-
-def reader_visual_artifact_payloads() -> list[dict[str, object]]:
- """Return the inventory in stable JSON order."""
- return [artifact.as_payload() for artifact in READER_VISUAL_ARTIFACTS]
-
-
-__all__ = [
- "READER_VISUAL_ARTIFACTS",
- "READER_VISUAL_SMOKE_DEVTOOLS_COMMAND",
- "READER_VISUAL_SMOKE_PYTEST_COMMAND",
- "READER_VISUAL_SMOKE_REPORT",
- "VisualArtifact",
- "reader_visual_artifact_payloads",
-]
diff --git a/docs/README.md b/docs/README.md
index 6bddf4e443..695b73271b 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -34,7 +34,7 @@ Start with **Guides** for a task, **Reference** for a surface contract, and **Ar
| Document | Description |
|----------|-------------|
| [CLI Reference](cli-reference.md) | Generated command reference from live help output. |
-| [MCP Reference](mcp-reference.md) | Generated MCP tool and contract reference. |
+| [MCP Reference](mcp-reference.md) | MCP tools, capability opt-ins, and client setup. |
| [Library API](library-api.md) | Async archive API, filters, and query patterns. |
| [MCP Integration](mcp-integration.md) | Model Context Protocol server setup and usage. |
| [Agent Integration Reference](agent-integration-reference.md) | Generated typed contract, recipes, client delivery, and cutover reconciliation reference. |
@@ -74,36 +74,18 @@ Start with **Guides** for a task, **Reference** for a surface contract, and **Ar
|----------|-------------|
| [Developer Tools](devtools.md) | Generated surfaces, validation, and repo hygiene. |
| [Branch-Local Development Loop](dev-loop.md) | Daemon, web-shell, browser-capture, and extension debugging workflow. |
-| [Test Economics](test-economics.md) | Test-selection and verification cost model. |
-| [Test Quality Workflows](test-quality-workflows.md) | Executable mutation-campaign and benchmark registries. |
| [Visual Evidence](visual-evidence.md) | Synthetic reader DOM/media evidence lanes and local screenshot boundaries. |
| [Release Checklist](release.md) | Cut-time packaging, installed-artifact, and publish checks. |
-| [Tracker Authority](tracker-authority.md) | GitHub and Beads authority split, and the reconciliation script that checks it. |
-| [Acceptance Contract Wave](plans/beads-acceptance-contracts-2026-08-07.md) | Guarded structured acceptance contracts for the current Beads execution wave. |
-| [Acceptance Contract Reconciliation](plans/beads-acceptance-reconciliation.md) | Read-only authority reconciliation and guarded targeted import protocol for the acceptance-contract wave. |
## Demos, Evidence, and Product
| Document | Description |
|----------|-------------|
| [Demos and Proofs](demos.md) | Reproducible proofs, construct-valid demo doctrine, and flagship demonstrations. |
-| [Cursor Authority Census, 2026-08-04](evidence/polylogue-xeck9-cursor-authority-census-2026-08-04.md) | Privacy-safe read-only census of cursor and accepted-head readiness evidence. |
-| [Topology Live-Proof Residue, 2026-08-06](evidence/polylogue-topology-live-proof-2026-08-06.md) | Candidate topology census, production-route cycle evidence, and unexercised live-archive residue. |
-| [Reindex Canary Differ Implementation, 2026-08-09](evidence/polylogue-0x7nh-reindex-canary-differ-implementation-2026-08-09.md) | Implementation packet, supersession proof, anti-vacuity evidence, and the remaining first-production-report gate. |
-| [Proof Artifacts](proof-artifacts.md) | Claim-to-proof map for public-facing demo and evidence claims. |
-| [README Public-Claims View](generated/public-claims/readme.md) | Generated compact status view for claims used in README-facing copy. |
-| [Launch Public-Claims View](generated/public-claims/launch.md) | Generated launch-copy claim status with evidence blockers and remediation refs. |
-| [Findings-Page Public-Claims View](generated/public-claims/findings-page.md) | Generated finding status with judgment, privacy, evidence, epoch, and frame qualifiers. |
-| [Verified Public-Claims Export](generated/public-claims/verified-export.md) | Generated full public-claim projection corresponding to the machine-readable export. |
-| [Structured Failure Follow-Up](findings/claim-vs-evidence.md) | Bounded field finding with oracle, sample frame, calibration, and caveats. |
+| [Structured Failure Follow-Up](findings/claim-vs-evidence.md) | Bounded finding with a structural oracle, sample frame, calibration, and caveats. |
| [Polylogue on Sinex](sinex-interop.md) | Current bridge, target authority split, and rebuild proof. |
| [Insights Rigor Matrix](insights-rigor-matrix.md) | Evidence strengths and limitations for insight families. |
-| [Query-Action Workflows](product/workflows.md) | Executable product contract for workflows, affordances, completions, and golden paths. |
-| [Demo Corpus Construct Audit](plans/demo-corpus-construct-audit.md) | Generated construct-coverage audit for the demo fixture world. |
-| [Release Readiness Gate](plans/release-readiness-gate.md) | Externally presentable release gate and required proof contract. |
-| [Demo Packet v2](examples/demo-packet-v2/README.md) | Worked private-data-free evidence packet. |
-| [Demo Tour Report](examples/demo-tour/report.md) | Recorded output and receipts from the demo tour. |
-| [UVX Installation Proof](examples/demo-tour/uvx-proof.md) | Recorded installation proof for the uvx distribution path. |
+| [Query-Action Workflows](product/workflows.md) | Selection rules, common paths, and executable demo-archive evidence. |
| [Visual Tape Examples](examples/visual-tapes/README.md) | Reader-evidence and visual-tape artifact catalog. |
| [Reader-Comprehension Test Harness](examples/reader-comprehension-test/README.md) | Single-blind N-arm cold-reader test harness for README/positioning candidates. |
| [Example and Proof Index](examples/README.md) | Index of recorded proof artifacts and worked examples. |
@@ -117,14 +99,10 @@ Start with **Guides** for a task, **Reference** for a surface contract, and **Ar
| [Archive Storytelling](design/archive-storytelling.md) | Narrative and artifact design for archives. |
| [Hermes Archival Export Contract](design/hermes-archival-export-contract.md) | Versioned Hermes session export schema, durable lifecycle-event spool, and snapshot reconciliation. |
| [Browser Capture Redesign](design/browser-capture-redesign/README.md) | Browser-capture redesign rationale and verification artifacts. |
-| [Incident 14:32 Proof World](design/incident-1432-proof-world.md) | Deterministic demo corpus and anti-circularity rules. |
| [Project Memory](design/project-memory.md) | Long-term memory model and product intent. |
-| [Storage Twins Divergences](plans/STORAGE_TWINS_DIVERGENCES.md) | Documented sync/async storage backend divergences, tracked for the twins regression test. |
-| [Query-Action Workflows Design](design/query-action-workflows.md) | Historical design pointer for the workflow contract. |
| [Query Set Algebra](design/query-set-algebra.md) | Set-composition semantics over query results. |
| [Session Lineage Model](design/session-lineage-model.md) | Fork, resume, compaction, and composition semantics. |
| [Content, Identity, and Lineage Architecture](plans/content-identity-lineage-design.md) | Implementation architecture for content hashing, event storage, lineage, origins, and raw byte authority. |
-| [Bead Readiness Audit](plans/bead-readiness-audit-implementation-cluster.md) | Execution-readiness audit for the implementation-cluster Beads and their verification boundaries. |
| [Analysis Rigor](design/analysis-rigor.md) | Rigor mechanisms for agent claims: population validity and comparative judgment. |
| [Prefix-Blob Reclamation](design/prefix-blob-reclamation.md) | Reference-blob representation for byte-proven superseded revision prefixes. |
| [Convergence Simplification Inventory](design/convergence-simplification-inventory.md) | Deletion/collapse inventory for the daemon convergence redesign (polylogue-m6tp). |
@@ -136,22 +114,9 @@ Start with **Guides** for a task, **Reference** for a surface contract, and **Ar
| Document | Description |
|----------|-------------|
-| [Closed-Issue Workload Audit](audits/2026-05-19-closed-issue-workload-audit.md) | Historical audit of closed-issue workload. |
-| [Cross-Surface Coherence Audit](audits/2026-05-20-cross-surface-coherence-audit.md) | Historical cross-surface coherence audit. |
-| [API Bypass Audit](audits/2026-05-25-api-bypass-audit.md) | Historical audit of API bypasses. |
-| [Daemon Loop Lock-Starvation Map](audits/2026-07-09-daemon-loop-lock-starvation-map.md) | Lock-starvation investigation record. |
-| [Hash Boundary Census](audits/2026-07-09-hash-boundary-census.md) | Hash-boundary investigation record. |
-| [Race Window Audit](audits/2026-07-09-race-window-audit.md) | Race-window investigation record. |
-| [Reindex Forcing-Class Audit](audits/2026-08-04-reindex-forcing-class-audit.md) | Forcing-class and reindex-gate evidence audit. |
-| [Blob-Reference Liveness Closure Audit](audits/2026-08-04-blob-ref-liveness-closure.md) | I3 live evidence, source-tier reconciliation safeguards, and the direct-reindex gate. |
-| [Raw-Failure Preflight](audits/2026-08-04-raw-failure-preflight.md) | Read-only raw-failure census before lifecycle evidence deployment. |
-| [ChatGPT Lifecycle-Anchor Evidence Packet](audits/2026-08-04-polylogue-uqwd-chatgpt-lifecycle-anchor.md) | Current-corpus evidence for ChatGPT generation lifecycle-anchor drift. |
-| [Audit Record Index](audits/README.md) | Index of dated investigation records. |
+| [Audit Record Index](audits/README.md) | Index of retained investigation records. |
| [1498 Cascade Retrospective](retro/2026-05-24-1498-cascade.md) | Historical cascade incident retrospective. |
| [Retrospective Index](retro/README.md) | Index of historical incident retrospectives. |
-| [Query Pipeline Substrate Plan](plans/query-pipeline-substrate.md) | Historical/active query pipeline design plan. |
-| [Nine-Bead Decision Adjudication](plans/decision-adjudication-kea7p-avna-cijx-uh6c-rxdo9-ze5-dx1-fie-ca4.md) | Implementation decisions and dependency graph for nine architecture Beads. |
-| [Semantic Card Tool Map](generated/semantic-card-tool-map.md) | Generated map from semantic cards to tools. |
## Contributor Workflow
diff --git a/docs/agent-forensics.md b/docs/agent-forensics.md
index 30d244236d..f9fbd947d1 100644
--- a/docs/agent-forensics.md
+++ b/docs/agent-forensics.md
@@ -4,11 +4,10 @@ Polylogue mines longitudinal agent usage through the normal archive analysis
surfaces, not a standalone report script. The useful outputs are composable:
coverage describes archive shape, cost rollups describe provider/model spend
evidence, usage timelines describe monthly token/cost movement, and the
-claim-vs-evidence workspace packet turns structured tool failures into an
-inspectable proof artifact.
+action query surface exposes provider-reported tool outcomes and their
+immediate follow-up classification.
-All commands below are read-only against the archive unless an explicit
-`--out-dir` is supplied for a demo packet.
+All commands below are read-only against the archive.
## Queries
@@ -28,9 +27,8 @@ polylogue analyze usage --origin codex-session --format json --limit 0
# Monthly usage movement by origin and model.
polylogue analyze insights usage-timeline --group-by month-origin-model --format json
-# Focused claim-vs-evidence packet for the current demo shelf.
-devtools workspace claim-vs-evidence --limit 5000 \
- --out-dir .agent/demos/claim-vs-evidence --json
+# Inspect structurally failed actions and their immediate follow-up class.
+polylogue --format json actions where is_error:true
```
The same analysis can be reproduced against the deterministic demo archive:
@@ -40,7 +38,7 @@ polylogue demo seed --root /tmp/demo-archive --force --with-overlays --format js
POLYLOGUE_ARCHIVE_ROOT=/tmp/demo-archive \
polylogue analyze insights usage-timeline --format json
POLYLOGUE_ARCHIVE_ROOT=/tmp/demo-archive \
- devtools workspace claim-vs-evidence --limit 5000 --out-dir /tmp/claim-vs-evidence --json
+ polylogue --format json actions where is_error:true
```
## What The Surfaces Report
@@ -56,9 +54,9 @@ POLYLOGUE_ARCHIVE_ROOT=/tmp/demo-archive \
estimates, catalog coverage gaps, and subscription-credit estimates through
`cost-rollups` and `usage-timeline`.
- **Model evolution:** usage buckets grouped by month, origin, and model.
-- **Structured failure follow-up:** `claim-vs-evidence` anchors on structured
- tool-result failures (`is_error=1` or non-zero `exit_code`) and classifies the
- immediately following assistant turn for explicit acknowledgment markers.
+- **Structured failure follow-up:** action queries anchor on provider-reported
+ tool-result failures (`is_error=1` or non-zero `exit_code`) and expose the
+ immediately following assistant turn's acknowledgment classification.
## Accuracy Notes
@@ -84,9 +82,9 @@ distinct:
which collapses fork/resume/replay chains by logical session and model. Use
the physical view for archive-materialization claims and the logical view for
logical-work claims; do not silently substitute one for the other.
-5. **Failure claims.** Claim-vs-evidence does not infer tool success or failure
- from assistant prose. Structured tool-result fields are the evidence anchor;
- prose is only a follow-up acknowledgment signal.
+5. **Failure classification.** Action queries do not infer tool success or
+ failure from assistant prose. Structured tool-result fields are the evidence
+ anchor; prose is only a follow-up acknowledgment signal.
Current caveat: all-provider logical-session repricing is still being repaired.
Treat physical usage totals as current archive measurements, not final billing
@@ -94,7 +92,6 @@ reconciliation or logical-work totals.
## Privacy
-The query outputs are aggregate statistics by default: no message content,
-session titles, or source paths. Demo packets that include samples should stay
-inside the local `.agent/demos/` shelf unless they have been explicitly
-redacted for publication.
+Aggregate analysis outputs omit message content, session titles, and source
+paths by default. Action queries can return archived content, so treat their
+output according to the archive's privacy boundary.
diff --git a/docs/agent-integration-reference.md b/docs/agent-integration-reference.md
index 04497e9d49..932e95cca0 100644
--- a/docs/agent-integration-reference.md
+++ b/docs/agent-integration-reference.md
@@ -721,30 +721,30 @@ Prompts: `cost_of`.
### Stable target resources
-- `polylogue://session/{id}` — objects session; required capability `read`; owner `polylogue-t46.8.2`; read-only object projection; resources never acquire instruction or mutation authority.
-- `polylogue://message/{id}` — objects message; required capability `read`; owner `polylogue-t46.8.2`; read-only object projection; resources never acquire instruction or mutation authority.
-- `polylogue://block/{id}` — objects block; required capability `read`; owner `polylogue-t46.8.2`; read-only object projection; resources never acquire instruction or mutation authority.
-- `polylogue://action/{id}` — objects action; required capability `read`; owner `polylogue-t46.8.2`; read-only object projection; resources never acquire instruction or mutation authority.
-- `polylogue://file/{id}` — objects file; required capability `read`; owner `polylogue-t46.8.2`; read-only object projection; resources never acquire instruction or mutation authority.
-- `polylogue://query/{id}` — objects query; required capability `read`; owner `polylogue-t46.8.2`; read-only object projection; resources never acquire instruction or mutation authority.
-- `polylogue://result-set/{id}` — objects result-set; required capability `read`; owner `polylogue-t46.8.2`; read-only object projection; resources never acquire instruction or mutation authority.
-- `polylogue://recall-pack/{id}` — objects recall-pack; required capability `read`; owner `polylogue-t46.8.3`; read-only object projection; resources never acquire instruction or mutation authority.
-- `polylogue://capabilities/query` — objects capability, query, result-set; required capability `read`; owner `polylogue-z9gh.3`; executable query vocabulary and recovery guidance; no mutation authority.
+- `polylogue://session/{id}` — objects session; required capability `read`; read-only object projection; resources never acquire instruction or mutation authority.
+- `polylogue://message/{id}` — objects message; required capability `read`; read-only object projection; resources never acquire instruction or mutation authority.
+- `polylogue://block/{id}` — objects block; required capability `read`; read-only object projection; resources never acquire instruction or mutation authority.
+- `polylogue://action/{id}` — objects action; required capability `read`; read-only object projection; resources never acquire instruction or mutation authority.
+- `polylogue://file/{id}` — objects file; required capability `read`; read-only object projection; resources never acquire instruction or mutation authority.
+- `polylogue://query/{id}` — objects query; required capability `read`; read-only object projection; resources never acquire instruction or mutation authority.
+- `polylogue://result-set/{id}` — objects result-set; required capability `read`; read-only object projection; resources never acquire instruction or mutation authority.
+- `polylogue://recall-pack/{id}` — objects recall-pack; required capability `read`; read-only object projection; resources never acquire instruction or mutation authority.
+- `polylogue://capabilities/query` — objects capability, query, result-set; required capability `read`; executable query vocabulary and recovery guidance; no mutation authority.
### Workflow prompts
-- `resume_context` — workflow `resume`; required capability `read`; mutation authority `none`; owner `polylogue-t46.8.2`.
-- `postmortem_last` — workflow `postmortem`; required capability `read`; mutation authority `none`; owner `polylogue-t46.8.2`.
-- `decisions_about` — workflow `decision-recovery`; required capability `read`; mutation authority `none`; owner `polylogue-t46.8.2`.
-- `unacknowledged_failures` — workflow `failure-recovery`; required capability `read`; mutation authority `none`; owner `polylogue-t46.8.2`.
-- `sessions_touching_file` — workflow `file-touch`; required capability `read`; mutation authority `none`; owner `polylogue-t46.8.2`.
-- `cost_of` — workflow `cost-analysis`; required capability `read`; mutation authority `none`; owner `polylogue-t46.8.2`.
-- `agent_coordination_brief` — workflow `coordination`; required capability `read`; mutation authority `none`; owner `polylogue-t46.8.3`.
-- `analyze_errors` — workflow `error-analysis`; required capability `read`; mutation authority `none`; owner `polylogue-il50`.
-- `summarize_week` — workflow `weekly-summary`; required capability `read`; mutation authority `none`; owner `polylogue-il50`.
-- `extract_code` — workflow `code-extraction`; required capability `read`; mutation authority `none`; owner `polylogue-il50`.
-- `compare_sessions` — workflow `session-comparison`; required capability `read`; mutation authority `none`; owner `polylogue-il50`.
-- `extract_patterns` — workflow `pattern-extraction`; required capability `read`; mutation authority `none`; owner `polylogue-il50`.
+- `resume_context` — workflow `resume`; required capability `read`; mutation authority `none`.
+- `postmortem_last` — workflow `postmortem`; required capability `read`; mutation authority `none`.
+- `decisions_about` — workflow `decision-recovery`; required capability `read`; mutation authority `none`.
+- `unacknowledged_failures` — workflow `failure-recovery`; required capability `read`; mutation authority `none`.
+- `sessions_touching_file` — workflow `file-touch`; required capability `read`; mutation authority `none`.
+- `cost_of` — workflow `cost-analysis`; required capability `read`; mutation authority `none`.
+- `agent_coordination_brief` — workflow `coordination`; required capability `read`; mutation authority `none`.
+- `analyze_errors` — workflow `error-analysis`; required capability `read`; mutation authority `none`.
+- `summarize_week` — workflow `weekly-summary`; required capability `read`; mutation authority `none`.
+- `extract_code` — workflow `code-extraction`; required capability `read`; mutation authority `none`.
+- `compare_sessions` — workflow `session-comparison`; required capability `read`; mutation authority `none`.
+- `extract_patterns` — workflow `pattern-extraction`; required capability `read`; mutation authority `none`.
## Source origins
diff --git a/docs/architecture-spine.md b/docs/architecture-spine.md
index 97d458f666..f8f121bb2b 100644
--- a/docs/architecture-spine.md
+++ b/docs/architecture-spine.md
@@ -32,13 +32,11 @@ change belongs or which production route must be exercised.
## Guardrails
-Every `docs/plans/*.yaml` manifest is enforced by a lint in `devtools verify`.
+Load-bearing policy files are parsed and enforced by the gate that owns their semantics.
| Manifest | Lint | What it prevents |
|----------|------|-----------------|
| `layering.yaml` | `verify layering` | Surface-to-substrate coupling |
-| `campaign-coverage.yaml` | `verify manifests` | Missing campaign declarations |
-| `coverage-manifest.yaml` | `verify manifests` | Stale gap/coverage declarations |
## Major Decisions
@@ -57,7 +55,8 @@ Every `docs/plans/*.yaml` manifest is enforced by a lint in `devtools verify`.
durable-tier change (loses irreplaceable `user.db` assertions); and full
Alembic-style forward/reverse upgrade chains for derived tiers (unnecessary —
they rebuild). The `devtools lab policy schema-versioning` lint enforces the
- boundary: numbered durable migrations allowed, derived-tier upgrade helpers forbidden.
+ boundary through numbered durable migration slots, declared derived lifecycle
+ deltas, and clone-safe SQL shapes rather than helper-name pattern matching.
- **Constraint**: Archive SQLite file set, WAL mode. Durable-tier migration
requires a backup manifest; derived-tier rebuild is operator-triggered on reject.
diff --git a/docs/audits/2026-05-19-closed-issue-workload-audit.md b/docs/audits/2026-05-19-closed-issue-workload-audit.md
deleted file mode 100644
index 25b9c55196..0000000000
--- a/docs/audits/2026-05-19-closed-issue-workload-audit.md
+++ /dev/null
@@ -1,74 +0,0 @@
-# Closed-Issue Workload Audit — 2026-05-19
-
-Ref: #1310
-
-## Summary
-
-Audit of ~110 closed issues from 2026-05-01 → 2026-05-18 (the last 17 days of
-closures, capturing the full window since the prior governance reset in
-#944/#970/#971/#972). Most closures are clean — the assured-close discipline
-introduced after #1002/#1004 has clearly raised the floor. Decomposition
-umbrellas (#994, #995, #1058, #998) close with explicit per-AC matrices and
-verified successors. The 2026-05-01 mass-NOT_PLANNED batch (#626–#633) cleanly
-folds into open composite owners (#614, #621, #623, #624). However, four cases
-violate the close-discipline contract and one chain-fold leaks scope across
-three issues.
-
-### Counts
-
-- Clean closures: ~95
-- **PARTIAL** (closed with explicit unfinished AC, no successor filed): **3**
-- **ABANDONED** (closed with "incremental / remaining / etc." and no `#NNN`): **2**
-- **ORPHANED-FOLD** (scope folded through a chain to a target that doesn't cover it): **1** (one chain, one root)
-
----
-
-## Findings
-
-### PARTIAL — closed with unfinished acceptance and no successor
-
-| # | Title | What fell through | Recommended remediation |
-|---|-------|-------------------|-------------------------|
-| **#1012** | Pre-existing test failures discovered during #1007 verification | The 2026-05-15 audit comment explicitly states "the issue is not closable yet" — `tests/unit/cli/test_command_aux_runtime.py::test_tags_command_plain_paths_cover_empty_hint_and_tabular_counts` remains XFAIL for provider-aware empty hint and Rich table renderer; stale xfails on the two XPASS rows were also flagged. Closed the next day by PR #1095 which addressed harness staleness only. The tags XFAIL is not in #1180 or any open issue. | File a successor issue: "fix(cli): provider-aware empty hint + Rich table for tags command (#1012 remainder)" — include the exact test node and the two stale xfails that should be removed. |
-| **#1283** | audit(devtools): agent inner-loop tooling and iteration speed | Issue body explicitly enumerates Tier-1 recommendations A, B, C, D (each annotated "≤N LOC"). PR #1285 ships only **Tier-1 C** (`failure-context`). Tier-1 **A** (`use_when` + `examples` in `--help`), **B** (`verification-impact --paths` speculative mode), and **D** (`pipeline-probe` quiet-mode default) have no successor. Only Tier-2 E was carried over (to #1289). | File three small successor issues (or one umbrella) for Tier-1 A, B, D. All are explicitly bounded, named, and scoped. |
-| **#802** | feat(acquisition): Claude Code + Codex hook integration for 100% session data coverage | Closing comment: "the paste-detection promise is not wired through to stored message/query semantics; leaving this issue closed and tracking reconciliation in #944." But #944 then closed with "no unique implementation scope remains here" (superseded by docs PR #1042). The hook → `has_paste` wiring is not in any open issue. #1199 mentions paste as an *attachment-surface concern* but does not own the UserPromptSubmit → message.has_paste pipeline AC. | Either reopen #802 or file a focused successor: "fix(pipeline): wire UserPromptSubmit hook events into message.has_paste facts (#802 remainder)". |
-
-### ABANDONED — closed with classic abandonment phrases, no `#NNN`
-
-| # | Title | Closing phrase | Recommended remediation |
-|---|-------|----------------|-------------------------|
-| **#723** | feat(api): formalize Python library API as the canonical Polylogue surface | "Closing: core implementation landed. **Remaining edges are incremental**." No issue number, no concrete scope handed off. The body AC said *every operation that touches the archive should have an API method* and *CLI and MCP tools call the same API methods rather than constructing queries independently* — both are still partial today (CLI/MCP still have local filter/query construction in several paths). | Either reopen, or file an audit issue: "audit(api): remaining CLI/MCP paths that bypass Polylogue API methods (#723 remainder)" with a concrete file inventory. |
-| **#849** | feat(publication): replace run-stage render/site with daemon-owned publication | "Closing as misframed... Existing static-site code can be retained as devtools/manual archive export only if it still earns its keep; otherwise cleanup belongs under #805/#826-style structural maintenance." Cleanup is named but unfiled — #805 and #826 are both *already closed*. No open issue owns the "decide whether site/render are dead; retain or delete" decision. | Confirm whether the dead-or-retain decision is genuinely complete (in which case no action). If `polylogue site` / `render` are still in the tree without active scope, file a successor "chore(maintenance): retain-or-delete polylogue site/render commands". |
-
-### ORPHANED-FOLD — scope leaked through a chain to a non-covering target
-
-| # | Chain | What was lost | Recommended remediation |
-|---|-------|---------------|-------------------------|
-| **#809** | #809 → folded into #815 → folded into #817 (OPEN/REOPENED) | #809 body: `_SESSION_INSIGHT_REBUILD_PAGE_SIZE = 1` causes ~17,240 SQL queries on rebuild; "increase to 50-200." Also flagged per-call FTS readiness COUNT(*), pre-computing provider metrics from `conversation_stats`, lazy content block lookup. **None of these perf items appear in #817's body or AC.** #817 is now scoped to FTS bloat, stale read paths, and trigger safety. | Add a perf line item to #817 AC, OR file "perf(storage): session insight rebuild page size + per-call FTS readiness (#809 remainder)". |
-
----
-
-## Notes on what did *not* trigger
-
-- The 2026-05-01 NOT_PLANNED batch (#626–#633): every "Superseded by #N" target (#614/#618/#621/#623/#624) verified — all closed COMPLETED with proper close-out commentary.
-- The 2026-05-04 NOT_PLANNED batch (#808/#812/#815/#816): folds verified. #808 → #828 (vector dimension AC present, completed via PR #975). #812 was a legitimate "not needed — single-user, fresh-on-mismatch" decision. #815 → #817 covers the FTS-repair-before-commit scope. **#816** (MCP `_safe_call` overloads, dead code, missing tool-name contracts) was folded into #811 — and #811's close-out comment says "MCP resource handler gaps should be tracked separately if still relevant." Marginal: the 6 items in #816 body are low-severity by author's own classification, so I did not flag this as ABANDONED, but it is the closest borderline case. Recommend a quick triage pass.
-- The MK3 decomposition (#956 → #993 → #1199–#1205) and the session/cost decompositions (#994/#995 → #1129–#1140) all close with verified-existing children.
-- The verifiability rollout (#1058) closes with an exhaustive child-PR matrix and names the remaining out-of-scope work with live issue numbers (#1019, #1022, #997, #845, #957, #999).
-
-## Method
-
-- `gh issue list --state closed --limit 200` (Sinity/polylogue), filtered to 2026-05-01+.
-- Per-issue `gh issue view --json body,comments,closedByPullRequestsReferences`.
-- Cross-referenced every "superseded by", "folded into", "tracking in", "subsumed by" target for state and scope coverage.
-- Spot-grepped closing PRs for AC satisfaction on the highest-risk closures.
-
-## Recommendation summary
-
-| Action | Targets |
-|--------|---------|
-| File successor issue | #1012, #1283 (×3 or ×1 umbrella), #802, #723, #849 (conditional), #809 |
-| Quick triage pass | #816 (borderline) |
-| Accept close as-is | ~95 clean closures |
-
-This audit does not itself reopen or file successor issues; remediation is left
-to repo owners.
diff --git a/docs/audits/2026-05-20-cross-surface-coherence-audit.md b/docs/audits/2026-05-20-cross-surface-coherence-audit.md
deleted file mode 100644
index 567380bce1..0000000000
--- a/docs/audits/2026-05-20-cross-surface-coherence-audit.md
+++ /dev/null
@@ -1,252 +0,0 @@
-# Cross-Surface Coherence Audit (2026-05-20)
-
-Audit of polylogue read/write surfaces against shared contract substrate.
-Ref #1282.
-
-## Scope
-
-Surfaces in scope:
-
-- **CLI** — `polylogue/cli/` (Click app, commands, query mode).
-- **MCP server** — `polylogue/mcp/` (FastMCP tools).
-- **Daemon HTTP** — `polylogue/daemon/http.py` (`/api/...` routes) and the
- satellite `polylogue/browser_capture/server.py` (`/v1/...` routes).
-- **Python API** — `polylogue/api/__init__.py` (`Polylogue` async facade
- composed via `PolylogueArchiveMixin`, `PolylogueInsightsMixin`,
- `PolylogueIngestMixin`).
-
-Out of scope here but enumerated where relevant: the daemon web reader,
-the TUI, the browser extension, and the `polylogue-hook` bash shim under
-`contrib/`.
-
-This is an audit, not a refactor. Every substantive finding is filed as a
-durable follow-up issue and cross-referenced below.
-
-## Substrate
-
-The contract substrate already exists:
-
-- `polylogue/surfaces/payloads.py` (1127 lines): canonical typed
- payload envelopes — `ConversationListResponse`,
- `ConversationListRowPayload`, `FacetsResponse`, `DaemonStatus`,
- `MachineErrorPayload`, mutation result types.
-- `polylogue/api/contracts/` — `CLIReadSurface`, `MCPReadSurface`,
- `APIReadSurface`, `TUIReadSurface`. These are `assert_implements`
- shadow adapters used by mypy contract checks. They are **not** in the
- request path of production CLI / MCP / HTTP code.
-- `polylogue/mcp/payloads.py` — MCP-local envelope variants
- (`MCPPaginatedQueryResultPayload`, `MCPErrorPayload`) plus direct use of
- the shared `SearchEnvelope`.
-- `polylogue/mcp/query_contracts.py` — `MCPConversationQueryRequest`,
- the typed input spec that already encodes every filter parameter
- declared one at a time in `mcp/server_tools.py`.
-
-The gap is wiring, not modeling.
-
-## Capability × Surface Matrix
-
-`yes` = native, first-class implementation on that surface.
-`indirect` = reachable through a different primitive but not a
-named peer.
-`partial` = present but with diverged envelope or partial coverage.
-`—` = absent.
-
-| Capability | CLI | MCP | Daemon HTTP | Python API |
-| --- | --- | --- | --- | --- |
-| List conversations | yes (`polylogue list`, query mode) | yes (`list_conversations`) | yes (`GET /api/conversations`) | yes (`Polylogue.list_conversations`) |
-| Search conversations | yes (query mode, `--lexical`/`--semantic`) | yes (`search`) | yes (`GET /api/conversations?query=`) | yes (`Polylogue.search`) |
-| Get conversation summary | yes (`polylogue show `) | yes (`get_conversation`, summary only) | yes (`GET /api/conversations/{id}`, full) | yes (`Polylogue.get_conversation`) |
-| Get conversation messages | yes (`show`) | yes (`get_messages`, separate call) | yes (folded into `get_conversation`) | yes |
-| Get raw acquired artifacts | yes (`polylogue raw`) | yes (`raw_artifacts`) | yes (`/api/conversations/{id}/raw`) | yes |
-| Per-conv cost | — | partial (forecast via `cost_outlook`) | yes (`/api/conversations/{id}/cost`) | indirect |
-| Provenance | — | — | yes (`/api/conversations/{id}/provenance`) | indirect |
-| Topology / lineage | — | partial (`get_session_tree`, different envelope) | yes (`/api/topology/...`) | indirect |
-| Similar / neighbors | — | partial (`neighbor_candidates`, different envelope) | yes (`/api/conversations/{id}/similar`) | yes |
-| Facets | — | — | partial (`providers`, `tags` only) | — |
-| Stats / coverage | yes (`polylogue stats`) | yes (`stats`, `archive_coverage`) | — | yes |
-| Daemon status | yes (`polylogue ops status`) | yes (`readiness_check`) | yes (`/api/status`, `/api/healthz`) | yes |
-| Session insights (profile, classification, phases, work events, threads) | yes (insights commands) | yes (per-insight tools) | yes (web shell + read endpoints) | yes |
-| Tag / metadata mutations | yes (`tags`) | yes (mutation tools) | yes (web shell routes) | yes |
-| Maintenance / convergence ops | yes (`check`, `reset`) | yes (maintenance tools) | yes (HTTP endpoints) | yes |
-| Browser captures intake | — | — | separate server (`/v1/...` on 8765) | — |
-| Hook events ingestion | shell shim only | — | — | — |
-
-## Findings
-
-### F1. Five list-row shapes for the same data (extends #859, #873, #1266)
-
-The "list of conversations" row is constructed independently in five
-places:
-
-- CLI rich rendering (`cli/query_output.py`).
-- CLI JSON output (`cli/query_output.py:_conv_to_dict`).
-- MCP (`MCPPaginatedQueryResultPayload` in `mcp/payloads.py`).
-- Daemon HTTP `_do_list` / `_do_search_list` in
- `polylogue/daemon/http.py` (inline dicts with reader-only enrichment:
- `target_ref`, `anchor`, `actions`, `flags`, `repo`, `cwd_display`).
-- TUI (`ConversationListResponse` in `surfaces/payloads.py`).
-
-The shared `ConversationListResponse` model is only used by the TUI
-and by the `api/contracts/` shadow adapters. Production CLI, MCP, and
-HTTP paths never call into it. #859 closed without wiring this through.
-
-**Recommendation R1.** New follow-up issue files the wiring work.
-
-### F2. Three search-hit shapes
-
-- Daemon HTTP returns `hits` with nested `match` (reader anchors,
- actions).
-- MCP returns the shared `SearchEnvelope`.
-- CLI rolls its own payload via `_search_hit_to_payload`.
-
-#1266 standardized the ranked envelope but the production CLI/MCP/HTTP
-search paths still construct local shapes.
-
-### F3. Three error wire formats
-
-- `MachineErrorPayload` — `{status, code, message, command, details}` —
- used by CLI JSON output and the cli-output schema artifacts under
- `docs/schemas/cli-output/`.
-- `MCPErrorPayload` — `{error, code, detail?}` — `mcp/payloads.py`.
-- Daemon HTTP — raw `{error: }` strings inline.
-- Browser-capture HTTP server (`browser_capture/server.py`) defines its
- own variants of all of the above.
-
-Same logical concept ("operation failed, here is structured why"); four
-encodings on the wire.
-
-### F4. Two HTTP servers running in parallel
-
-- Daemon `/api/...` on the configurable daemon port.
-- Browser-capture `/v1/browser-captures`, `/v1/archive-state`,
- `/v1/status` on default 8765 (`polylogue/browser_capture/server.py`).
-
-Each ships its own auth, CORS, error envelope, and status envelope code.
-Browser extension config points at 8765 by default.
-
-### F5. `FacetsResponse` half-implemented
-
-`FacetsResponse` (`surfaces/payloads.py:965`) declares nine facet
-dimensions. The daemon `_do_facets`
-(`polylogue/daemon/http.py:1821`) serves only `providers` and `tags`
-and hard-codes the other seven. CLI and MCP have no facet peer at all.
-Either the model is too wide for the current behavior, or seven
-fields are silently wrong.
-
-### F6. MCP `get_conversation` returns summary only
-
-Daemon HTTP and the Python API return the full conversation (header +
-messages) in one call. MCP `get_conversation` returns only the summary
-and requires a second `get_messages` round trip. The asymmetry is
-unflagged.
-
-### F7. MCP filter parameters duplicated 4 ways
-
-`polylogue/mcp/server_tools.py` declares the ~30 filter parameters for
-`list_conversations` and `search` by hand (lines 43–228, ~200 lines).
-`MCPConversationQueryRequest` in `mcp/query_contracts.py` already
-encodes every one of them. Adding a new filter today is a four-file
-edit: filter chain, `query_contracts.py`, `server_tools.py`, and the
-matching CLI flag.
-
-### F8. Read surfaces missing on CLI and MCP
-
-The daemon HTTP server exposes `/cost`, `/provenance`, `/topology`, and
-`/similar` per conversation, used by the web reader. CLI has no
-`polylogue conversation cost|provenance|topology|similar` peer.
-MCP has only partial peers (`cost_outlook` is forecast not retrieval;
-`get_session_tree` and `neighbor_candidates` use diverged envelopes).
-
-### F9. Browser-capture HTTP server is unprotected by daemon plumbing
-
-The browser-capture receiver has its own token-and-origin discipline
-(`BrowserCaptureReceiverConfig`). Any consolidation under F4 must
-preserve that surface as a route-level guard.
-
-### F10. `polylogue-hook` is an unpackaged bash shim
-
-`polylogue-hook` lives in `contrib/` as a shell script rather than a
-console_script entry point in `pyproject.toml`. Hook integration is the
-only first-party surface that is not pip-installable. #1213 covers the
-per-event library; the packaging gap is independent.
-
-### F11. Cluster of contract adapters is shadow-only
-
-`polylogue/api/contracts/{cli,mcp,api,tui}_*.py` exist solely to satisfy
-`assert_implements` mypy checks. The CLI/MCP/HTTP surfaces do not
-instantiate them. Resolving F1 / F2 / F3 in production code makes these
-adapters either the real implementation or removable; today they are
-neither.
-
-### F12. No OpenAPI emission from typed payloads
-
-`devtools render openapi` emits `docs/openapi/search.yaml` from the
-typed `SearchEnvelope` Pydantic models (#1266). The daemon's
-`/api/conversations`, `/api/conversations/{id}`, `/api/topology/...`,
-`/api/conversations/{id}/{cost,provenance,similar}`,
-`/api/facets`, `/api/status`, `/api/healthz`, and the browser-capture
-`/v1/...` routes have no machine-readable schema. Web reader, browser
-extension, and external clients hand-type each fetch.
-
-## Naming / vocabulary
-
-The `provider` vs `source` dual-vocabulary period (see
-`docs/architecture.md` § "Dual Vocabulary Period") affects every
-surface uniformly: storage column `provider_name`, CLI `--provider`,
-MCP `provider`, HTTP `?provider=`. No surface has moved yet;
-#1022 and #1214 track the staged transition. The audit confirms no
-half-moved surface exists today.
-
-`conversation_id` vs `conv_id` is split inside the daemon:
-`get_conversation`, `_do_get_conversation_attachments`,
-`_do_get_conversation_raw`, `_do_get_conversation_cost`, etc. accept
-`conv_id` parameters internally while the public path segment is the
-conversation ID; the public surface vocabulary is consistent.
-No external rename is required.
-
-## Pagination
-
-CLI, MCP, and HTTP all accept `limit` + `offset`. MCP and HTTP also
-accept opaque `cursor`. CLI does not surface cursor pagination, which
-is an asymmetric ergonomics gap but not a wire-format inconsistency
-(it is the same envelope; CLI just ignores the cursor field).
-Keyset pagination (#1268) is tracked separately.
-
-## Refs
-
-- #859 — shared read-surface query/status contracts (closed; F11 reopens
- the wiring gap as a new issue).
-- #873 — make ranked results explainable and pagination-stable (open).
-- #1266 — typed ranked-result envelope across surfaces (closed; F2
- remains for production wiring).
-- #1247 — typed import operation contract (open).
-- #1197 — persistent operation registry + status surface (open).
-- #1224 — health-endpoint contract tests (open).
-- #1269 — scoped vs global facets (open).
-- #1250 — route MCP through facade not direct services (open).
-- #1213 — per-event hook script library (open).
-- #1022 / #1214 — source-vocabulary refactor (open).
-- #1218 — CLI `status --convergence` parity (open).
-
-## Follow-up issues filed
-
-| Finding | Issue | Title |
-| --- | --- | --- |
-| F1, F11 | #1414 | refactor(surfaces): wire ConversationListResponse through CLI/MCP/daemon list paths |
-| F2, F3 | #1415 | refactor(surfaces): adopt MachineErrorPayload across MCP, daemon HTTP, browser-capture |
-| F7 | #1416 | refactor(mcp): auto-derive list/search tool parameters from MCPConversationQueryRequest |
-| F4, F9 | #1417 | refactor(daemon): fold browser-capture HTTP server into daemon /api/v1/captures |
-| F12 | #1418 | feat(devtools): emit daemon HTTP OpenAPI from typed payload models |
-| F6, F8 | #1419 | feat(surfaces): CLI and MCP peers for daemon /cost, /provenance, /topology, /similar |
-| F5 | #1420 | feat(facets): implement or shrink FacetsResponse dimensions (daemon serves 2 of 9) |
-| F10 | #1421 | feat(hooks): promote polylogue-hook to console_script entry point |
-
-R9 ("`polylogue serve {daemon,mcp,capture,all}` umbrella") from the
-parent issue is intentionally not filed as a separate ticket; it is a
-follow-on to R4 and would be reconsidered after F4 lands.
-
-## Verification
-
-This is an audit document. No production code is touched. The follow-up
-issues each carry their own acceptance criteria for the implementation
-PRs they will spawn.
diff --git a/docs/audits/2026-05-25-api-bypass-audit.md b/docs/audits/2026-05-25-api-bypass-audit.md
deleted file mode 100644
index 7b7e395a90..0000000000
--- a/docs/audits/2026-05-25-api-bypass-audit.md
+++ /dev/null
@@ -1,89 +0,0 @@
-# API Bypass Audit: CLI, MCP, and Daemon Paths (#1584)
-
-**Date**: 2026-05-25
-**Issue**: [#1584](https://github.com/Sinity/polylogue/issues/1584)
-**Source**: Governance audit [#1310](https://github.com/Sinity/polylogue/issues/1310) finding on [#723](https://github.com/Sinity/polylogue/issues/723)
-
-## Background
-
-Issue #723 (formalize Python library API) was closed with "core
-implementation landed. Remaining edges are incremental." Per the
-governance audit, no successor issue tracked which edges remained.
-
-This audit surveys the current state (post-#1022 column consolidation)
-and classifies every surviving direct-access path.
-
-## API Surface
-
-The canonical Python API is `Polylogue` (`polylogue/api/__init__.py`),
-a mixin-composed async class wrapping `ConversationRepository` +
-`SQLiteBackend`. CLI/MCP callers access it through:
-
-- **CLI**: `env.polylogue` (an `AppEnv` attr, sync-bridged via
- `polylogue.api.sync.bridge.run_coroutine_sync`)
-- **MCP**: `_tool_manager` → `ctx.polylogue` (a `Polylogue` instance)
-- **Daemon**: Internal services (`SQLiteBackend` directly, since the
- daemon IS the API's runtime host)
-
-## Findings
-
-### CLI Commands
-
-All 28 CLI commands were surveyed. The vast majority route through
-`env.polylogue` for archive operations (query, search, tags, insights,
-cost, facets, neighbors, resume, export). A small number of
-maintenance-oriented commands use direct connections legitimately:
-
-| Command | Access pattern | Why direct |
-|---------|---------------|------------|
-| `check` | `open_connection` for repair operations | Repair is a maintenance operation, not a read API call |
-| `reset` | Direct filesystem operations | Schema bootstrap happens before the API exists |
-| `doctor` | `open_connection` for deep repair | Same rationale as `check` |
-| `embed` | `open_connection` for embedding backfill | Embedding catch-up is a daemon-side batch operation |
-| `backup` | Direct filesystem copy | Not an archive operation |
-| `config` | TOML read/write | Not an archive operation |
-
-**Verdict**: All direct-access CLI paths are maintenance operations
-that legitimately bypass the read API. No query or search command
-constructs queries independently of `env.polylogue`.
-
-### MCP Tools
-
-All MCP tools route through `ctx.polylogue` (a `Polylogue` instance).
-The tool manager (`server_tools.py`) resolves tools by name and calls
-API methods. No MCP tool constructs queries independently.
-
-**Verdict**: MCP is fully API-conformant. No bypass paths found.
-
-### Daemon HTTP Handlers
-
-The daemon IS the API runtime — it owns the `SQLiteBackend` and
-`ConversationRepository`. Daemon HTTP handlers use internal services
-(`self.queries`, connection pools) rather than the public `Polylogue`
-class. This is by design: the API is a facade over the daemon's
-internals, not the other way around.
-
-**Verdict**: Daemon handlers are intentionally direct. This is not a
-bypass — the daemon is the implementation substrate.
-
-## Summary
-
-| Surface | API-conformant | Intentionally direct | Bypass (needs fix) |
-|---------|---------------|---------------------|-------------------|
-| CLI | 22 commands | 6 maintenance commands | 0 |
-| MCP | All tools | 0 | 0 |
-| Daemon | N/A (is the substrate) | All handlers | 0 |
-
-**Overall**: No CLI or MCP path constructs archive queries
-independently of the Python API. The original #723 AC ("every
-operation that touches the archive should have an API method" and
-"CLI and MCP tools call the same API methods") is satisfied in
-current practice. The six maintenance CLI commands that use direct
-connections are legitimate exceptions.
-
-## Recommendation
-
-Close #1584. The "remaining edges" from #723 have been absorbed
-through normal architectural evolution. If future maintenance
-commands proliferate, revisit the API boundary for maintenance
-operations specifically.
diff --git a/docs/audits/2026-07-09-hash-boundary-census.md b/docs/audits/2026-07-09-hash-boundary-census.md
deleted file mode 100644
index 92cd3954c1..0000000000
--- a/docs/audits/2026-07-09-hash-boundary-census.md
+++ /dev/null
@@ -1,180 +0,0 @@
-# Hash-boundary census: every digest producer/consumer classified
-
-**Date**: 2026-07-09
-**Bead**: polylogue-9e5.6
-**Method**: static read of every `hashlib.*`/`hash_text`/`hash_payload`/
-`hash_file` call site, plus every SQL/Python comparison that reads a
-`content_hash`-or-similar column back and gates a decision on it (skip,
-dedupe, invalidate, re-embed). No product code was changed to produce this
-census. Two genuine sibling bugs were found and filed separately (not fixed
-here — this bead is investigation-only, matching 9e5.4/9e5.13).
-
-## Motivating context
-
-A prior bead found and fixed a hash comparison of this exact shape: a
-"message content" digest that didn't actually cover the field the comparison
-claimed to protect. The surviving evidence of that fix is in the current
-source: `_message_content_hash`'s docstring
-(`polylogue/storage/sqlite/archive_tiers/write.py:1497`) says *"Digest the
-stored message content, not just its identity"* and explicitly cross-refs
-that `message_embeddings_meta.content_hash` freshness depends on this digest
-covering the text sent to the embedder. `_block_content_hash`'s docstring
-(same file, line 1543) similarly documents "excluding identity (svfj)" —
-bead polylogue-svfj, which added `blocks.content_hash` deliberately excluding
-session/message/position/tool_id so citation anchors survive fork-position
-shift and re-ingest renumbering. This census asks: are there siblings
-elsewhere — a hash that *looks* like it verifies real content equality but
-doesn't, or a comparison whose result nothing actually acts on?
-
-## Method and scope
-
-`rg 'hashlib\.(sha256|sha1|md5|blake2)'` across `polylogue/` returns **42**
-direct call sites. `polylogue/core/hashing.py`'s four helpers
-(`hash_text`, `hash_text_short`, `hash_payload`, `hash_file`) are called from
-**23** additional sites outside their own definitions. That is **65** total
-producer call sites, grouped below by what they protect rather than listed
-one-by-one (most are ID-generation helpers sharing one contract). Every site
-is accounted for in one of the groups; none were excluded.
-
-Classification:
-
-- **meaningful** — the hash's inputs genuinely correspond to what the
- consumer's comparison claims to protect, and the comparison gates a real,
- reachable decision.
-- **meaningful-by-construction (identifier)** — the hash is used only to
- derive a stable identifier (a PRIMARY KEY / dedup key), not compared for
- drift; "consumer" is the uniqueness constraint itself (`INSERT OR IGNORE`
- / `ON CONFLICT DO NOTHING`), which is a legitimate but different contract
- than a content-hash drift check.
-- **vacuous/suspect** — the hash's inputs are missing something the
- comparison implies is covered, or the comparison is dead / never reached,
- or the hash's own docstring claims a guarantee nothing enforces.
-
-## Table 1 — Content-hash / integrity drift checks (the load-bearing group)
-
-| # | Producer (file:line) | Inclusion contract (exact fields hashed) | Consumer (file:line) | Decision on match/mismatch | Classification |
-|---|---|---|---|---|---|
-| 1 | `session_content_hash` → `_session_hash_payload`/`_message_hash_payload` (`polylogue/pipeline/ids.py:99-169`) | title, created_at, updated_at, per-message {id, role, NFC-normalized text, timestamp, content_blocks (type/text/tool_name/tool_id/tool_input-hash/media_type)}, sorted attachments, session_events. NFC-normalized; None vs "" disambiguated via sentinels. **Excludes** user metadata (tags/corrections) by design. | `content_unchanged = existing_hash_hex == payload.content_hash` (`polylogue/pipeline/services/ingest_batch/_core.py:400`); also `sessions_writes.session_exists_by_hash` (`SELECT 1 FROM sessions WHERE content_hash = ?`, older async API path) | Match → skip re-parse/re-write (idempotent re-ingest); mismatch → full session replace + downstream FTS/embedding/insight invalidation | **meaningful** — verified the excluded-by-design claim (tagging doesn't trigger re-import) and the included fields (any message/attachment/event change flips it) |
-| 2 | `_message_content_hash` (`polylogue/storage/sqlite/archive_tiers/write.py:1497-1533`) | `"message"`, session_id, provider_message_id, position, variant_index, role, message_type, material_origin, text, user_context_text, then per-block {type, text, tool_name, tool_id, tool_input JSON, semantic_type, media_type, language, is_error, exit_code} | `em.content_hash != stale_m.content_hash` (`polylogue/storage/embeddings/materialization.py:493-495`, `_archive_stale_message_clause`); also surfaced read-only via `STALE_MESSAGES_SQL` (`polylogue/storage/embeddings/sql.py:57-71`) | See Table 2 — this is the freshness signal for embeddings, and it **is** correctly computed (this is the fixed bug's own docstring cross-reference) | **meaningful producer** — see Table 2 for the consumer-side finding |
-| 3 | `_block_content_hash` (`write.py:1543-1568`, bead svfj) | `"block"`, block_type, text, tool_name, tool_input_json, semantic_type, media_type, language, is_error, exit_code. **Deliberately excludes** session_id/message_id/position/tool_id | `resolve_block_anchor` (`polylogue/storage/block_anchor.py`) looks up `blocks.content_hash` to resolve a stored citation anchor to `ok`/`drifted_position`/`drifted_message`/`ambiguous`/`hash_mismatch`/`missing` | Anchor resolution across re-ingest/fork-position shift; `hash_mismatch` never auto-rewrites | **meaningful** — svfj's own empirical check (4.46M blocks, 0.069% collision rate) backs the "ambiguous is rare" design claim |
-| 4 | `_catalog_hash` (`polylogue/storage/sqlite/archive_tiers/pricing_seed.py:29-40`) | sorted `PRICING` dict entries: `model_name:input_rate:output_rate:cache_read_rate:cache_write_rate` | **none** — `price_catalogs.catalog_hash` is written once at seed time and never `SELECT`ed/compared anywhere in `polylogue/` | Docstring claims "for change-detection"; no branch reads it back, so no decision is ever made on it | **vacuous — filed as polylogue-w379** |
-| 5 | `deterministic_blob_hash`/`deterministic_history_sidecar_id` (`source_write.py:125,154`) | Raw payload bytes (blob); origin+source_path+content_hash (sidecar id) | PK uniqueness (`raw_sessions`/history-sidecar tables) | Same content → same id → `INSERT OR IGNORE`/upsert no-op; different content → new row | **meaningful-by-construction** |
-| 6 | `BlobStore.write_from_bytes`/`write_from_path` (`polylogue/storage/blob_store.py:99,147,193,246,319`) | Raw file/bytes content, streamed 1 MiB chunks | `BlobStore.verify()` (`blob_store.py:241`) re-hashes on-disk content and compares to the expected hash_hex (the filename/`raw_id`) | Match → blob intact; mismatch → corruption detected (used by `blob_integrity.py` restore/repair flows, e.g. `_restore_expected_hash_from_path`/`_restore_expected_hash_from_source_span`, lines 845-1050) | **meaningful** — content-addressed store, hash IS the address, verify re-derives and compares |
-| 7 | `hashlib.sha256` restore hash (`polylogue/storage/blob_integrity.py:1529`) | Recomputed hash of a payload recovered from a `source_path` span during blob-repair | Compared implicitly via blob-store addressing (new blob written under the recomputed hash; original row's `blob_hash` column is what integrity reports diff against) | Drives `_raw_backed_recovery_action` classification (repair vs skip) | **meaningful** |
-| 8 | `fingerprint_file`/`tail_hash_from_path`/`tail_hash_and_last_complete_newline_from_path` (`polylogue/sources/live/batch_support.py:161-221`) | Whole-file SHA-256 (full fingerprint) or bounded tail-window SHA-256 (last N bytes) | `CursorStore` compares stored fingerprint/tail-hash against current file state to detect truncation/rotation vs. append-only growth (`sources/live/cursor.py`) | Match → treat as pure append (incremental parse from last offset); mismatch → full re-parse | **meaningful** |
-| 9 | `_current_parser_fingerprint` (`polylogue/sources/live/batch.py:814`) | Parser module version/config identity | Compared against a stored fingerprint to decide whether cached parse state is still valid | Mismatch → invalidate cached batch parse state | **meaningful** (not deep-audited beyond signature; low risk — narrow blast radius, config/version string only) |
-| 10 | `fingerprint_hash` (`polylogue/schemas/observation_identity.py:29-32`) | `repr()` of a structural fingerprint tuple, truncated to 16 hex chars | `fingerprint_hash(...) == request.cluster_id` (`polylogue/schemas/operator/inference.py:297`) | Selects samples belonging to a schema cluster for operator review | **meaningful** — deterministic grouping key, real equality gate |
-| 11 | Content-hash citation anchor format (`format_block_anchor`, `block_anchor.py:86-112`) | Reuses block content_hash (row 3) as the anchor's hex suffix; validates 64-char hex | Parsed back by the anchor resolver | See row 3 | duplicate of row 3, listed for completeness of the anchor format itself |
-
-## Table 2 — Embedding freshness: does `message_embeddings_meta.content_hash` guard anything real?
-
-This was the bead's own named concern. Answer: **partially — the check is
-real and correctly computed, but 3 of 4 real selection call sites bypass it.**
-
-`select_pending_archive_session_window()`
-(`polylogue/storage/embeddings/materialization.py:263`) takes
-`include_stale_checks: bool = True`. When `True`, it folds
-`_archive_stale_message_clause` (an `EXISTS` comparing
-`em.content_hash != stale_m.content_hash` per message, materialization.py:
-482-497) into the "does this session still need embedding work" decision.
-This is the correct freshness signal — `messages.content_hash` (Table 1 row
-2) changes when the text sent to the embedder changes, and nothing else sets
-`embedding_status.needs_reindex=1` for a content-only edit (that flag is only
-set by `mark_all_archive_sessions_needs_reindex`, the model/dimension-change
-reconciler `_reconcile_embedding_config_change`, or an embedding error path).
-
-| Caller | File:line | `include_stale_checks` | Role |
-|---|---|---|---|
-| `_archive_pending_embedding_session_ids` (used by both `check` and `execute` of the daemon's per-source-path "embed" `ConvergenceStage`) | `daemon/convergence_stages.py:1219`, execute at `:1246` | relies on default `True` | **The only path that actually detects and re-embeds a content-changed message** — fires per ingested source path |
-| `_drain_archive_embedding_backlog_once` (daemon's bulk backlog-catchup sweep) | `daemon/embedding_backlog.py:127` | explicit `False` | Never detects content drift; only picks up missing/`needs_reindex=1` rows |
-| `polylogue embed` backfill (operator CLI) | `cli/commands/embed.py:619` | explicit `False` | Same — an operator manually running the main backfill command will not catch edited-message drift without `--rebuild` |
-| Embedding preflight/cost estimate | `storage/embeddings/preflight.py:224` | explicit `False` | Estimate window intentionally matches the backfill's own (stale-blind) selection, per its own comment — consistent with the backfill, but propagates the same blind spot |
-
-None of the three `False` sites carry a comment explaining the tradeoff.
-Net effect: content-edit drift is corrected **only if** the foreground
-per-source-path daemon convergence hook fires for that exact path before the
-session would otherwise be touched by the bulk backlog drain or a manual
-`polylogue embed` run. If embedding is enabled after the fact, the daemon
-isn't running at ingest time, or the per-path probe errors and the session
-falls through to backlog-style handling, the drift is silently never
-detected by any of the other three paths (short of an operator-invoked
-`--rebuild`, which re-embeds everything unconditionally rather than
-detecting the specific change).
-
-**Filed as polylogue-wmsc** (not fixed — investigation only).
-
-## Table 3 — ID-generation-only hash sites (no drift comparison; consumer = PK uniqueness)
-
-These 23 sites all call `hash_text`/`hash_text_short`/`hash_payload` purely
-to derive a short, stable identifier — the "consumer" is a uniqueness
-constraint or dict key, not a later equality check for change detection.
-Verified each has a real PK/uniqueness consumer (no dead identifiers):
-
-| Producer | Consumer |
-|---|---|
-| `polylogue/browser_capture/receiver.py:190` (`hash_text_short` session suffix) | session id disambiguation on capture |
-| `polylogue/archive/actions/fields.py:129` (`act-` id) | `actions` view row identity |
-| `polylogue/storage/runtime/archive/records.py:126` (`blk-` id) | synthetic block id fallback |
-| `polylogue/sources/parsers/drive_support_attachments.py:128-165` (inline-file / youtube-video ids) | attachment dedup key |
-| `polylogue/sources/parsers/base_support.py:131` (`att-` id) | attachment id fallback |
-| `polylogue/storage/insights/session/timeline_rows.py:54,217` (`wev-`/`sph-` ids) | work-event / session-phase row identity |
-| `polylogue/context/compiler.py:190,360` (`query-unit:`/`context-snapshot:` fingerprints) | context segment/snapshot ref, used as a cache/lookup key elsewhere in the context pipeline |
-| `polylogue/daemon/user_state_http.py:131,136` (`_default_saved_view_id`/`_default_annotation_id`) | default id when the operator's HTTP request omits one; PK on `saved_views`/`annotations` |
-| `polylogue/insights/transforms.py:2099` (evidence digest) | stable evidence-ref id for citation |
-| `polylogue/storage/artifacts/inspection.py:28` (`obs-` id) | observation-sample identity |
-| `polylogue/publication/__init__.py:53` (whole-file sha256 in an output manifest) | published-artifact manifest entry (informational checksum, not compared against a prior manifest — one-shot scan) |
-| `polylogue/core/security.py:35,47` (`original_hash`, truncated 12 chars) | masked-value display in logs (shows a stable short hash instead of the raw secret) — not a comparison, a redaction aid |
-| `polylogue/daemon/notification_backends/webhook.py:93` (`hmac.new(..., hashlib.sha256)`) | HMAC signature for outbound webhook payloads — verified by the receiver, out of this repo's scope |
-| `polylogue/schemas/sampling_db.py:37`, `schemas/validation/corpus.py:79` (`_blob_hash_hex`) | display/lookup helpers over an existing stored blob_hash column (not new hash computation) |
-
-All of these were spot-checked for a real consumer (uniqueness constraint or
-lookup key reachable from a real code path); none showed the "computed and
-discarded" shape of row 4 in Table 1.
-
-## Findings summary
-
-- **65 producer call sites** censused (42 direct `hashlib.*` + 23
- `core.hashing` helper call sites), zero left unclassified.
-- **1 vacuous producer/consumer pair**: `price_catalogs.catalog_hash` is
- computed with a docstring claiming "change-detection" but is never read
- back anywhere — filed **polylogue-w379**.
-- **1 partially-vacuous consumer pattern**: the embedding freshness check
- (`message_embeddings_meta.content_hash` vs `messages.content_hash`) is
- correctly computed and wired into exactly one of four real selection call
- sites; the other three (bulk backlog drain, manual CLI backfill, preflight
- estimate) explicitly disable it with no documented rationale — filed
- **polylogue-wmsc**.
-- All other content-hash-shaped comparisons audited (session identity hash,
- message content hash's own producer correctness, block content-hash
- citation anchors, blob-store integrity verify, cursor file-fingerprint
- change detection, schema-cluster fingerprint grouping) are **meaningful**:
- inputs match what the comparison claims, and the branch they gate is
- reachable in production.
-- ID-generation-only hash sites (23 of the 65) are a structurally different
- contract (uniqueness key, not drift detector) and were spot-checked rather
- than deep-audited per site; none showed a dead/unreachable consumer.
-
-## Register-or-fail lint
-
-Not built in this pass — documented as follow-up **polylogue-okpn**. The
-mechanical check ("every new hashlib/content_hash call site must be
-registered with a producer/consumer/classification entry") is real and
-worth having, but has non-trivial design surface of its own (registry format
-— generated-from-YAML vs. regexing this markdown table; whether pure
-ID-generation sites need the same schema as content-hash drift checks; where
-it plugs into `devtools verify --quick` without adding latency). Scoping it
-properly is more valuable than a rushed version bolted onto this audit pass.
-
-## Not fully verified
-
-- `polylogue/sources/parsers/codex.py:459` and a handful of the smaller
- `hashlib.sha256` sites in `polylogue/storage/sqlite/archive_tiers/
- user_write.py:168` and `async_sqlite_raw.py:110`/`queries/raw_writes.py:32`
- (the latter two are `hashlib.sha256(blob_hash).digest()` — re-hashing an
- *already-hashed* value, likely a sharding/bucketing transform rather than
- a content hash) were confirmed to have a real consumer by grep but not
- traced line-by-line to the same depth as Tables 1-2; nothing in their
- signatures or call sites suggested the vacuous-hash shape, but a deeper
- pass could still find something here.
-- `_current_parser_fingerprint` (batch.py:814, Table 1 row 9) was verified
- by signature and one caller, not fully traced end-to-end.
diff --git a/docs/audits/2026-07-09-race-window-audit.md b/docs/audits/2026-07-09-race-window-audit.md
deleted file mode 100644
index e8b62d1d0b..0000000000
--- a/docs/audits/2026-07-09-race-window-audit.md
+++ /dev/null
@@ -1,106 +0,0 @@
-# Get-\>modify-\>put race audit across daemon/CLI/MCP writers
-
-**Date**: 2026-07-09
-**Bead**: polylogue-9e5.4
-**Method**: static read of connection/transaction boundaries around every
-candidate read-then-write sequence named in the bead, plus other shared-writer
-surfaces discovered while tracing them. No product code was changed to
-produce this audit. Two race windows were substantiated with a minimal
-two-connection/two-step proof test (evidence only, not a fix) — see
-"Proof harness" below.
-
-## Method
-
-For each sequence: read the exact function(s), classify the connection
-boundary (one connection/one `with conn:` block spanning read+write, vs.
-separate `open_connection`/`sqlite3.connect` calls), classify the transaction
-boundary, state the invariant, construct a concrete two-actor interleaving,
-and give a verdict:
-
-- **safe-by-single-transaction** — read and write share one open transaction;
- no other connection can observe/mutate the intermediate state.
-- **safe-by-unique/upsert** — the write is a full-row `INSERT ... ON CONFLICT
- DO UPDATE` keyed by a real uniqueness constraint, and every writer computes
- the SAME deterministic absolute value (not a delta based on a prior read),
- so interleaving produces "last write wins" with no corrupted intermediate
- state.
-- **needs-harness** — a plausible unlocked read-then-write gap exists but
- static reading alone can't establish whether two real actors ever touch the
- same key concurrently in production.
-- **bug** — concrete two-actor interleaving with a reproducible bad outcome
- (lost update, stale read that gets persisted, or a safety mechanism that
- never actually engages).
-
-## Race-window table
-
-| # | Sequence | File:function | Connection boundary | Txn boundary | Invariant | Verdict |
-|---|----------|---------------|----------------------|---------------|-----------|---------|
-| 1a | Blob-lease acquire/release inside a write | `polylogue/archive/write_effects.py:commit_archive_write_effects` | Deliberately split: `acquire_blob_leases` on a **fresh immediate-commit connection** (line 76), the main data commit on the caller's `conn`, `release_operation_leases` back on `conn` after commit (or a fresh connection on the failure path, `_release_leases_on_failure`) | Each piece is its own single-statement commit; the split is intentional (comment lines 68-71) so the lease is visible to a concurrent GC connection before the data txn commits | Lease must be visible to GC before the referencing row commits, and released only after that row is durable | **safe-by-single-transaction reasoning holds for the acquire/release pair itself** — `INSERT OR IGNORE`/`DELETE` are each atomic single statements; the split-connection design is correct **if invoked**. See 1b for why it currently is not. |
-| 1b | Blob-lease **reachability** from real ingest | `polylogue/pipeline/services/ingest_batch/_core.py:_commit_sync_ingest_side_effects` (only production caller of `commit_archive_write_effects`) | N/A — the payload it builds never includes `_blob_hashes`/`_operation_id` | N/A | GC safety invariant #2 ("never delete a blob with an active lease", `blob_gc.py:11`) requires a lease to exist while a blob is acquired-but-not-yet-referenced | **BUG** — filed as polylogue-v7e0. `has_lease = bool(blob_hashes and operation_id)` (`write_effects.py:72`) is always `False` in production: a repo-wide grep confirms `_blob_hashes`/`_operation_id` are never set outside `write_effects.py`'s own `payload.get(...)` defaults and the unit tests that call `commit_archive_write_effects` directly. `acquire_blob_leases`/`release_operation_leases` are otherwise only referenced from `blob_gc.py` itself and tests. `WriteOperation.BLOB_STORE` is declared and never constructed anywhere. |
-| 2 | Blob GC check-then-unlink pass | `polylogue/storage/blob_gc.py:run_blob_gc_report` | One connection/one pass for the whole loop (`conn = open_connection(db_path)` at top, closed in `finally`); file `unlink()` itself is a separate, non-transactional OS call | `_reference_surfaces` (SELECT) and `_has_active_lease` (SELECT) run inside the same open connection as the eventual `INSERT INTO gc_generations` commit, but the file delete happens *between* those reads and that commit, with no lock preventing another writer from referencing the blob in between | Never delete a blob that a concurrent ingest is about to reference | **needs-harness given 1b.** With leases dead, the only defense against deleting a blob whose DB reference hasn't committed yet is the `MIN_AGE_S=60` + previous-generation-timestamp age gate (`run_blob_gc_report:394-405`). This is a real gap only when a single ingest's acquire→commit span exceeds ~60s (plausible for the documented multi-GiB streaming Claude Code path) **and** an operator or scheduled job runs `polylogue maintenance blob-gc --yes` (CLI, `cli/commands/maintenance.py:1790`) during that window — i.e. exactly the CLI-vs-daemon shared-writer scenario the bead is about. Not filed as a separate bug; it is a direct consequence of 1b and will close together with it. |
-| 3 | Ingest cursor failure bookkeeping | `polylogue/sources/live/cursor.py:CursorStore.mark_failed` / `.mark_excluded` / `.reset_failures` | `get_record(path)` opens+closes one `_connect_ops()` connection; the subsequent `self.set(...)` opens+closes a **second, independent** `_connect_ops()` connection. No lock spans the pair (`best_effort_cursor_write` is a lock-**retry** wrapper, not a cross-call lock) | Two separate single-statement transactions | `ingest_cursor.failure_count` accumulates real parse failures 1:1 so `_MAX_CURSOR_FAILURES_BEFORE_EXCLUDE=5` fires after 5 true failures, and exponential backoff (`delay_s = 60*2**(failures-1)`) is computed from the true count | **BUG** — filed as polylogue-qug2. Two actors calling `mark_failed(path)`/`reset_failures(path)`/`mark_excluded(path)` for the **same** `source_path` near-simultaneously (e.g. the live daemon watcher tailing a file while an operator's `polylogue import`/reprocess CLI batch-parses the same directory — both construct a `CursorStore` over the same `ops.db`) both read the same stale `failure_count`, both compute `+1` independently, and the second `set()`'s full-row upsert (`upsert_ingest_cursor`, `ops_write.py:135` `ON CONFLICT DO UPDATE SET failure_count = excluded.failure_count`) overwrites the first — one real failure is never counted. Consequence: delayed poison-pill exclusion / under-lengthened backoff, not data loss. Confirmed with a proof test (see below). |
-| 3b | Convergence-debt attempt counting | `polylogue/sources/live/cursor.py:CursorStore._sync_convergence_debt_to_ops` | Same shape as #3: a `SELECT attempts, next_retry_at, last_error` on one `_connect_ops()` connection, Python computes `attempts_delta`/`retry_at`, then a **second** `_connect_ops()` connection commits `add_archive_convergence_debt` | Two separate transactions | `convergence_debt.attempts` should count real failed convergence attempts for a `(stage, target_type, target_id)` key | Same root cause as #3 (not filed as a separate bead — same fix will address both call sites in `cursor.py`). |
-| 4 | Embedding `needs_reindex` transition on success | `polylogue/storage/embeddings/materialization.py:_record_archive_embedding_success` (embeds session, then blind `needs_reindex = 0`) vs. `polylogue/daemon/convergence_stages.py:_reconcile_embedding_config_change` (bulk `UPDATE embedding_status SET needs_reindex = 1` on model/dimension change, line 676) | Each write is its own single-statement upsert/UPDATE on its own connection — individually atomic | Individually safe-by-upsert (keyed on `session_id` PK), but the **pair** is not: neither write is conditioned on the other's generation/version | A session marked `needs_reindex=1` because the configured embedding model changed must stay `needs_reindex=1` until it is actually re-embedded **under the new model** | **BUG** — filed as polylogue-y337. `_reconcile_embedding_config_change` runs on every `_archive_embed_check*` probe call (`convergence_stages.py:1233,1268,1306`), not just at daemon startup. If it detects a model/dimension change and bulk-marks all rows `needs_reindex=1` *while* an in-flight `_embed_archive_sessions_sync`/`embed_archive_session_sync` pass for some session is mid-flight (already past its read of messages, still computing embeddings under the **old** model/provider), that pass's terminal `_record_archive_embedding_success` unconditionally sets `needs_reindex = 0` (`materialization.py:1044-1049`), silently clobbering the just-set reindex requirement. The session is left marked "fresh" while holding embeddings from the superseded model/dimension. Confirmed with a proof test (see below). |
-| 5 | FTS freshness snapshot writes | `polylogue/storage/fts/freshness.py:record_fts_surface_state_sync` / `mark_all_fts_stale_sync` | `INSERT ... ON CONFLICT(surface) DO UPDATE` — single statement, keyed on `surface` PK | Whatever transaction the caller is already in | `fts_freshness_state` reflects "state as of last probe" | **safe-by-unique/upsert + self-healing.** Every writer stamps a freshly-recomputed absolute snapshot (state + counts as of that read), never a delta, so a losing writer just leaves a one-cycle-stale snapshot that the next probe corrects — matching the documented `false_means_pending`/convergence-retry model (`daemon/convergence.py`). The one place this snapshot participates in a hard atomicity requirement — `suspend_fts_triggers_sync` calling `mark_all_fts_stale_sync` right before dropping FTS triggers for a bulk write — runs on the **same connection, same transaction** as the surrounding `commit_archive_write_effects`/ingest-batch `BEGIN IMMEDIATE` (`pipeline/services/ingest_batch/_core.py:975-979`, `storage/fts/fts_lifecycle.py:256-263`). This is exactly the "already single-transaction, do not misclassify" pattern the bead calls out. |
-| 6 | `commit_archive_write_effects` overall | `polylogue/archive/write_effects.py:commit_archive_write_effects` | One caller-owned `conn`; FTS trigger repair + `conn.commit()` all inside the function; blob-lease acquire/release are the *only* pieces deliberately outside that transaction (see #1a) | `ensure_fts_triggers_sync` → `repair_message_fts_index_sync` → `conn.commit()` is one unbroken sequence on one connection before the function returns | Row materialization, FTS repair, and commit land atomically together (#1242) | **safe-by-single-transaction**, confirmed by reading lines 84-116 directly — this is the sequence the bead explicitly warns not to misfile as a bug. |
-
-## Bug beads filed
-
-All three carry `discovered-from:polylogue-9e5.4`. No fixes were implemented;
-each bead's repro is the two-connection/two-step sketch from the table above
-plus (for 4.2 and 4.3) a runnable proof test.
-
-- **polylogue-v7e0** — Blob-lease safety mechanism (`pending_blob_refs`,
- `acquire_blob_leases`/`release_operation_leases`) is dead code: no real
- ingest caller populates `_blob_hashes`/`_operation_id`, so GC's "never
- delete a leased blob" invariant never actually engages; the sole real
- defense is the `MIN_AGE_S` timing heuristic. Includes the derived GC
- check-then-unlink exposure (table row #2) as the same root cause.
-- **polylogue-qug2** — `CursorStore.mark_failed`/`mark_excluded`/
- `reset_failures` (and `_sync_convergence_debt_to_ops`) do an unlocked
- get-on-one-connection, set-on-another read-modify-write; two concurrent
- callers touching the same `source_path`/subject lose an increment.
-- **polylogue-y337** — `_record_archive_embedding_success`'s unconditional
- `needs_reindex = 0` can silently clobber a concurrent
- `_reconcile_embedding_config_change`'s `needs_reindex = 1` bulk marker,
- leaving stale-model embeddings marked fresh.
-
-## Proof harness
-
-Two minimal, deterministic (no real threads — the interleaving is driven
-explicitly by call order, which is the strongest and least flaky way to
-demonstrate a two-actor race) tests were added as evidence, not a fix:
-
-- `tests/unit/sources/test_cursor_failure_count_race_evidence.py::test_mark_failed_lost_update_when_two_actors_read_before_either_writes`
- — seeds `failure_count=2`, has two "actors" call the real
- `CursorStore.get_record`/`.set` in the exact interleaved order the table
- describes, and asserts the final `failure_count` is `3`, not `4` — the
- literal lost update. **Result: passes, i.e. reproduces the bug.**
-- `tests/unit/storage/test_embedding_needs_reindex_race_evidence.py::test_embedding_success_write_clobbers_concurrent_reindex_request`
- — builds a bare `embedding_status` table (the real DDL fragment), seeds a
- `needs_reindex=0` row, runs the real config-change bulk-mark SQL, then the
- real `_record_archive_embedding_success`, and asserts the row ends up
- `needs_reindex=0` despite the intervening mark. **Result: passes, i.e.
- reproduces the bug.**
-
-Verification: `devtools test -k test_mark_failed_lost_update_when_two_actors_read_before_either_writes` and `devtools test -k test_embedding_success_write_clobbers_concurrent_reindex_request` both pass locally (only these two new tests; no broad run for the audit itself).
-
-## Sequences classified safe (no bead filed)
-
-- `commit_archive_write_effects` (#6) — safe-by-single-transaction, matches
- the bead's own flagged pitfall exactly.
-- Blob-lease acquire/release mechanics in isolation (#1a) — safe-by-design
- if invoked; the bug is that it is never invoked (#1b).
-- `fts_freshness_state` writes (#5) — safe-by-upsert + self-healing probe
- design; the one atomicity-sensitive use is already single-transaction.
-- `embedding_status` per-message/per-session upserts in the non-racing case
- — safe-by-upsert (keyed on `session_id`/`message_id` PKs, deterministic
- absolute writes).
-
-## Other shared-writer surfaces surveyed, no further findings
-
-`session_profiles` upserts and the `gc_generations` insert (`blob_gc.py:497`)
-are both single-statement, single-transaction writes with no preceding
-cross-connection read of the same row; not included as separate table rows
-above because they do not fit the get-modify-put shape at all (they are pure
-inserts/upserts of freshly-computed values, the same reasoning as row #5).
diff --git a/docs/audits/2026-08-04-blob-ref-liveness-closure.md b/docs/audits/2026-08-04-blob-ref-liveness-closure.md
deleted file mode 100644
index 1e19918c4a..0000000000
--- a/docs/audits/2026-08-04-blob-ref-liveness-closure.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# Blob-reference liveness closure audit
-
-Date: 2026-08-04
-
-Scope: `polylogue-0v4tn` and merged PR #3705.
-
-## Decision
-
-PR #3705 delivered the guarded source-tier reconciliation actuator, but it did not itself apply that actuator to the live archive. The live archive is still red for I3, so this change makes I3 a direct rebuild preflight gate. It does not claim that the live bookkeeping repair is complete.
-
-## Acceptance matrix
-
-| Requirement | Evidence | Status |
-| --- | --- | --- |
-| Set-based `raw_payload` referent check | `BLOB_REF_LIVENESS_JOIN` maps `raw_payload` to `raw_sessions.raw_id`; the classifier uses a `LEFT JOIN` per mapped ref type. | Satisfied |
-| Set-based attachment referent check | `attachment` maps to the parent `raw_sessions.raw_id`, not retired index-tier attachment identity. The archive verifier now imports the same canonical mapping. | Satisfied |
-| Read-only default | `blob-reference-liveness` calls the reconciler without `--apply`, which opens `source.db` with `mode=ro`. | Satisfied |
-| Offline, fresh verified backup, and transaction safety for apply | Apply rejects a running daemon, checkpoints and validates the source backup before and inside `BEGIN IMMEDIATE`, fsyncs a prepared receipt, checks the exact delete count, runs `quick_check`, and commits or rolls back as one transaction. | Satisfied |
-| Receipt and blob safety | The receipt records the exact candidate digest before mutation and terminal state after it. The only actuator mutation is `DELETE FROM blob_refs`; it contains no blob-store unlink or file deletion. | Satisfied |
-| Direct reindex gate | `rebuild_index_from_source` now runs `blob-refs-liveness` against the actual archive root before it acquires a rebuild lease or creates generation state. | Satisfied |
-| Predicate anti-vacuity | The classifier fixture has a live and orphan ref for every mapped type and asserts the exact orphan matrix. Inverting the `LEFT JOIN ... IS NULL` predicate reports the four live rows instead and fails the assertion. | Satisfied |
-
-## Live I3 evidence
-
-Read-only command, run against `/realm/db/polylogue/source.db`:
-
-```sql
-SELECT 'raw_payload' AS ref_type, COUNT(*) AS orphaned
-FROM blob_refs AS b
-LEFT JOIN raw_sessions AS r ON r.raw_id = b.ref_id
-WHERE b.ref_type = 'raw_payload' AND r.raw_id IS NULL
-UNION ALL
-SELECT 'attachment' AS ref_type, COUNT(*) AS orphaned
-FROM blob_refs AS b
-LEFT JOIN raw_sessions AS r ON r.raw_id = b.ref_id
-WHERE b.ref_type = 'attachment' AND r.raw_id IS NULL
-ORDER BY ref_type;
-```
-
-Result:
-
-```text
-attachment|0
-raw_payload|73427
-```
-
-No live apply, source backup creation, blob deletion, namespace quarantine, GC run, or raw-authority operation occurred. A future offline operator pass must use `polylogue ops maintenance blob-reference-liveness --apply` with a fresh verified source backup and a new receipt path. The preflight gate will continue to reject direct reindexing until I3 reports zero unwaived orphan refs.
-
-## Adversarial review
-
-One independent read-only review found that the original apply test mocked the offline guard. This change adds a regression test that simulates a live daemon and proves refusal occurs before receipt creation or `blob_refs` mutation. Source tracing then found and repaired the verifier's stale attachment referent mapping and the missing direct-reindex preflight.
diff --git a/docs/audits/2026-08-04-polylogue-uqwd-chatgpt-lifecycle-anchor-receipt.json b/docs/audits/2026-08-04-polylogue-uqwd-chatgpt-lifecycle-anchor-receipt.json
deleted file mode 100644
index 3e829ee93a..0000000000
--- a/docs/audits/2026-08-04-polylogue-uqwd-chatgpt-lifecycle-anchor-receipt.json
+++ /dev/null
@@ -1,60 +0,0 @@
-{
- "denominators": {
- "logical_source_key_count": 2570,
- "membershipless_selected_raw_count": 0,
- "multi_candidate_cohort_count": 2555,
- "parsed_and_projected_raw_count": 7498,
- "raws_in_multi_candidate_cohorts": 7483,
- "selected_membership_row_count": 7498,
- "selected_quarantined_chatgpt_raw_count": 7498,
- "singleton_cohort_count": 15
- },
- "outcomes": {
- "classifier_cohort_counts": {
- "cohorts_with_accepted_raw": 2561,
- "cohorts_with_ambiguous_raw": 18,
- "cohorts_with_equivalent_raw": 2538
- },
- "pair_relation_counts": {
- "a_contains_b": 126,
- "b_contains_a": 82,
- "conflict": 71,
- "equal": 7348
- },
- "target_pair_count": 0
- },
- "provenance": {
- "archive_access": "SQLite source.db and index.db opened mode=ro; blob files read only; no archive writer created.",
- "index_db": {
- "mtime_ns": 1785748371749663866,
- "size_bytes": 40554500096,
- "sqlite_schema_version": 309,
- "sqlite_user_version": 46
- },
- "producer_git_revision": "257b851f2ce4bde2d6501ea364a987718be8cac2",
- "production_route": [
- "polylogue.sources.revision_backfill._parse_one",
- "polylogue.pipeline.ids.session_revision_projection",
- "polylogue.archive.session_revision_membership._relation",
- "polylogue.archive.session_revision_membership.classify_membership_revisions"
- ],
- "source_db": {
- "mtime_ns": 1785817591883760785,
- "size_bytes": 1891467264,
- "sqlite_schema_version": 157,
- "sqlite_user_version": 24
- }
- },
- "receipt_status": "historical_pre_repair",
- "repair_note": "Captured before the producer-cleanliness and blob-snapshot provenance contract. Retained as historical evidence only; do not use as a post-repair rerun receipt.",
- "schema": "polylogue.chatgpt-lifecycle-anchor-audit.v1",
- "scope": {
- "conclusion_limit": "A zero target_pair_count describes only this current parser-and-corpus snapshot. It does not establish the historical pre-fix replay required to reclassify or remove any graph gate.",
- "sanitized": "No raw ids, native ids, source paths, blob hashes, titles, or payload content are emitted."
- },
- "selection": {
- "population_sql": "SELECT raw_id\nFROM raw_sessions\nWHERE origin = 'chatgpt-export' AND revision_authority = 'quarantined'\nORDER BY raw_id",
- "sql": "SELECT r.raw_id, r.source_path, lower(hex(r.blob_hash)) AS blob_hash,\n m.logical_source_key, m.provider_session_id\nFROM raw_sessions AS r\nJOIN raw_session_memberships AS m ON m.raw_id = r.raw_id\nWHERE r.origin = 'chatgpt-export' AND r.revision_authority = 'quarantined'\nORDER BY m.logical_source_key, r.raw_id"
- },
- "target_predicate": "A pair in one persisted logical_source_key cohort where each parsed session has exactly one generation_lifecycle event, their source_message_provider_id anchors differ, message_contents and attachment_contents are equal, non-anchor lifecycle content hashes are equal, and the production _relation is conflict."
-}
diff --git a/docs/audits/2026-08-04-polylogue-uqwd-chatgpt-lifecycle-anchor.md b/docs/audits/2026-08-04-polylogue-uqwd-chatgpt-lifecycle-anchor.md
deleted file mode 100644
index 6ca4ae5ad2..0000000000
--- a/docs/audits/2026-08-04-polylogue-uqwd-chatgpt-lifecycle-anchor.md
+++ /dev/null
@@ -1,41 +0,0 @@
-# polylogue-uqwd evidence packet: ChatGPT lifecycle-anchor drift
-
-Date: 2026-08-04. Worktree: `feature/fix/chatgpt-anchor-audit`. Scope: record a reproducible current-corpus census for the `generation_lifecycle` moved-anchor conflict without changing Beads, source.db, index.db, the blob store, backups, daemon state, or services.
-
-## Verdict
-
-The prior census was only an untracked `/realm/tmp` report, so its current-corpus conclusion was not independently auditable. This packet is now backed by the committed, reproducible `devtools workspace chatgpt-lifecycle-anchor-audit` command and its sanitized receipt at `docs/audits/2026-08-04-polylogue-uqwd-chatgpt-lifecycle-anchor-receipt.json`.
-
-The historical semantic risk remains real in principle. `tests/unit/sources/test_parsers_chatgpt.py` now carries an end-to-end regression from two mapping orders through the ChatGPT parser, revision projection, relation, and classifier. The same fixture applies the pre-`b1e01d878` position tiebreak and asserts a `conflict` relation with both raws `ambiguous`, then asserts the current parser produces one accepted and one equivalent raw. The direct `ParsedSession` test in `tests/unit/archive/test_session_revision_membership.py` remains only as a classifier-only different-content guard.
-
-The receipt does **not** de-gate `uqwd`, `xselt`, or `818fy`. A zero result from the current parser and corpus is insufficient to establish the bead's required historical replay fixture. No graph state, archive state, blob store, daemon state, or service state was written by this work.
-
-## Reproducible receipt
-
-The command opens `source.db` and `index.db` with SQLite `mode=ro`, scans and verifies the blob namespace without writes, then invokes `_parse_one`, `session_revision_projection`, `_relation`, and `classify_membership_revisions`. It selects persisted `raw_session_memberships.logical_source_key` cohorts, reads current `raw_revision_heads` as classifier heads, and does not call a replay or writeback function. A newly generated version 2 receipt will bind the result to the exact producer `HEAD`, working-tree cleanliness and status digest, plus a deterministic full blob namespace snapshot and content-integrity digest whose aggregate identity includes each observed blob digest. Receipt output must resolve outside the archive root. Those fields are not present in the checked-in historical receipt below.
-
-The historical receipt checked into this packet predates the version 2 provenance contract. It is retained as historical evidence only and must not be presented as a post-repair rerun. The repaired command deliberately contains no raw ids, native ids, source paths, blob hashes, titles, or payload content. A fresh receipt records the same aggregate fields together with the producer and blob identities needed to make a rerun meaningful.
-
-The historical receipt's pairwise counts were `equal=7,348`, `a_contains_b=126`, `b_contains_a=82`, and `conflict=71`. Its target predicate count was zero under the pre-repair implementation. That value is not evidence that the repaired predicate has no target pair. The repaired target predicate counts exactly one `generation_lifecycle` event per side, permits other session events, compares normalized lifecycle content after removing the anchor, requires all other normalized event content to match, and requires the production conflict relation. This does not imply that the remaining conflicts are harmless or that historical gates can be removed.
-
-## Regression safeguards
-
-The end-to-end regression constructs two otherwise identical ChatGPT export mappings with different insertion orders, then invokes the real parser, projection, relation, and classifier. Under a test-only mutation that restores the historical position-based tiebreak, it asserts different anchors, a `conflict` relation, and two `ambiguous` raws. With the current parser it asserts a common anchor, an equal relation, one accepted raw, and one equivalent raw.
-
-The retained direct classifier guard constructs `ParsedSession` values with different lifecycle `state` content and moved anchors. It asserts conflict and ambiguity with an existing head. Its scope is limited to classifier behavior and it intentionally does not cover parser ordering.
-
-## Acceptance match
-
-| Acceptance criterion | Status | Evidence |
-| --- | --- | --- |
-| Run the real classifier and projection path against current quarantined ChatGPT data | Command ready, receipt pending | The repaired command binds parser, projection, relation, classifier, SQL selection, producer checkout and blob integrity. The checked-in receipt is pre-repair evidence only |
-| Confirm moved lifecycle anchors still produce conflicts | Satisfied in historical mutation fixture | The end-to-end regression asserts the real parser-to-classifier conflict and ambiguous result under the pre-fix tiebreak |
-| Implement the narrow comparison exception if reproduced | Satisfied | `_matches_target` compares normalized lifecycle content after removing `source_message_provider_id`, includes normalized timing semantics, and rejects unrelated event changes |
-| Preserve different-content moved-anchor behavior | Satisfied | The direct `ParsedSession` guard keeps changed lifecycle content conflicting; the parser-to-classifier regression owns ordering behavior |
-| Reclassify the current blocker edge honestly | Not satisfied | This packet makes no reclassification or de-gating recommendation until the retained historical replay fixture exists |
-
-## Graph disposition and residual uncertainty
-
-No graph-edge conclusion is made here. The historical mutation fixture establishes the classifier shape and the active parser remains protected against the known ordering bug, but the packet does not provide a retained pre-fix historical replay of the live corpus. The packet therefore preserves the no-de-gating stance for `uqwd`, `xselt`, and `818fy`.
-
-Residual uncertainty is limited to provenance of the archive transition between the 2026-08-03 negative lookup and this 2026-08-04 snapshot, and the absence of an archived pre-fix parser output for the original 10/136 sample. The live durable membership decisions remain unchanged because this lane performed no writeback.
diff --git a/docs/audits/2026-08-04-schema-disposition-audit.yaml b/docs/audits/2026-08-04-schema-disposition-audit.yaml
deleted file mode 100644
index 0ddbea9a58..0000000000
--- a/docs/audits/2026-08-04-schema-disposition-audit.yaml
+++ /dev/null
@@ -1,1688 +0,0 @@
-audit:
- bead: polylogue-gvzkr
- date: 2026-08-04
- phase: bounded read-only evidence gathering
- scope: Fresh-create executable DDL only. No archive or production data was opened or changed.
- method:
- canonical_inventory: Execute canonical DDL in memory and enumerate sqlite_master plus PRAGMA table_xinfo. The vec0 declaration is read directly because the vector extension is not loaded by stdlib SQLite.
- reader_writer_evidence: Index and embeddings evidence is a static production-code scan. Tests and DDL declarations are excluded. reader_columns and writer_columns are field-level results mapped to the sites on their owning object row. A field with no reader is UNCLEAR.
- non_goals: [production queries, migrations, code deletion, standing audit lint]
- finding_reuse:
- polylogue-664l: Retired index objects below are imported from its merged finding.
- polylogue-lr6dx: Named raw-authority rows are pre-classified pending its consumer cutover, without a duplicate audit.
- polylogue-oj4oo: Ops run statuses are vocabulary-unification work, not removal evidence.
- disposition_rules:
- KEEP: A production reader exists, or the object is structural machinery for a kept object.
- PURGE: An existing finding names the exact owning change train and removable code.
- UNCLEAR: Missing, incomplete, conflicted, or deferred evidence. It never authorizes a deletion.
-objects:
-- tier: source
- object_type: table
- name: blob_publication_reservations
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:486
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - publication_id
- - blob_hash
- - size_bytes
- - publisher_id
- - reserved_at_ms
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: blob_refs
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:473
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - blob_hash
- - ref_id
- - ref_type
- - source_path
- - size_bytes
- - acquired_at_ms
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: excised_content
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:684
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - removed_hash
- - hash_kind
- - reason
- - actor
- - prior_revision
- - span_start
- - span_end
- - excised_at_ms
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: gc_generations
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:497
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - generation_id
- - started_at_ms
- - completed_at_ms
- - reclaimed_count
- - reclaimed_bytes
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: history_sidecars
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:573
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - sidecar_id
- - origin
- - source_path
- - payload_json
- - observed_at_ms
- - content_hash
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: otlp_spans
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:551
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - span_id
- - trace_id
- - parent_span_id
- - origin
- - session_native_id
- - name
- - kind
- - attributes_json
- - events_json
- - started_at_ms
- - ended_at_ms
- - received_at_ms
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_append_chain_backfill_receipts
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:219
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - raw_id
- - logical_source_key
- - source_path
- - blob_hash
- - blob_size
- - append_start_offset
- - append_end_offset
- - matched_after_codex_header_strip
- - previous_revision_authority
- - compared_at_ms
- - tool_version
- - backup_manifest_path
- - detail
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_artifacts
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:505
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - artifact_id
- - raw_id
- - origin
- - source_path
- - source_index
- - artifact_kind
- - support_status
- - classification_reason
- - parse_as_session
- - schema_eligible
- - malformed_jsonl_lines
- - decode_error
- - cohort_id
- - link_group_key
- - sidecar_agent_type
- - first_observed_at_ms
- - last_observed_at_ms
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_authority_blockers
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:422
- disposition: PURGE
- execution_owner: polylogue-lr6dx source-tier cutover, then polylogue-6kur repair.py identity-block removal
- reader_sites: []
- writer_sites: []
- finding_reuse:
- - polylogue-lr6dx
- conflicts:
- - raw_authority_parser_census has an intentional-retention note in polylogue/maintenance/raw_authority_reset.py:20
- purge_unlocks:
- - polylogue-lr6dx source-tier cutover, then polylogue-6kur repair.py identity-block removal
- columns:
- - blocker_id
- - plan_id
- - census_id
- - reason
- - expected_json
- - observed_json
- - created_at_ms
- - resolved_at_ms
- - resolution
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_authority_census_plans
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:389
- disposition: PURGE
- execution_owner: polylogue-lr6dx source-tier cutover, then polylogue-6kur repair.py identity-block removal
- reader_sites: []
- writer_sites: []
- finding_reuse:
- - polylogue-lr6dx
- conflicts:
- - raw_authority_parser_census has an intentional-retention note in polylogue/maintenance/raw_authority_reset.py:20
- purge_unlocks:
- - polylogue-lr6dx source-tier cutover, then polylogue-6kur repair.py identity-block removal
- columns:
- - census_id
- - plan_id
- - ordinal
- - selected
- - outcome_status
- - reason
- - next_action
- - application_receipt_json
- - outcome_recorded
- - recorded_at_ms
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_authority_census_post_plans
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:414
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - census_id
- - plan_id
- - ordinal
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_authority_censuses
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:337
- disposition: PURGE
- execution_owner: polylogue-lr6dx source-tier cutover, then polylogue-6kur repair.py identity-block removal
- reader_sites: []
- writer_sites: []
- finding_reuse:
- - polylogue-lr6dx
- conflicts:
- - raw_authority_parser_census has an intentional-retention note in polylogue/maintenance/raw_authority_reset.py:20
- purge_unlocks:
- - polylogue-lr6dx source-tier cutover, then polylogue-6kur repair.py identity-block removal
- columns:
- - census_id
- - sequence_no
- - scope_json
- - residual_json
- - parser_fingerprint
- - mode
- - lifecycle_status
- - quiescent
- - inventory_digest
- - residual_digest
- - plan_count
- - post_inventory_digest
- - post_residual_json
- - post_residual_digest
- - post_plan_count
- - postflight_at_ms
- - executable_plan_count
- - residual_plan_count
- - predecessor_census_id
- - fixed_point
- - created_at_ms
- - completed_at_ms
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_authority_parser_census
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:328
- disposition: PURGE
- execution_owner: polylogue-lr6dx source-tier cutover, then polylogue-6kur repair.py identity-block removal
- reader_sites: []
- writer_sites: []
- finding_reuse:
- - polylogue-lr6dx
- conflicts:
- - raw_authority_parser_census has an intentional-retention note in polylogue/maintenance/raw_authority_reset.py:20
- purge_unlocks:
- - polylogue-lr6dx source-tier cutover, then polylogue-6kur repair.py identity-block removal
- columns:
- - raw_id
- - parser_fingerprint
- - status
- - logical_keys_json
- - detail
- - censused_at_ms
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_authority_plans
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:378
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - plan_id
- - input_digest
- - input_raw_ids_json
- - logical_keys_json
- - authority_witness_json
- - source_preconditions_json
- - index_preconditions_json
- - created_at_ms
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_authority_verdicts
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:461
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - raw_id
- - logical_source_key
- - verdict
- - cohort_member_count
- - cohort_fingerprint
- - computed_at_ms
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_byte_duplicate_supersession_receipts
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:249
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - raw_id
- - blob_hash
- - blob_size
- - duplicate_of_raw_id
- - duplicate_of_session_id
- - previous_revision_authority
- - promoted_at_ms
- - tool_version
- - backup_manifest_path
- - detail
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_capture_observations
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:110
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - raw_id
- - capture_mode
- - first_observed_at_ms
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_hook_events
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:531
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - hook_event_id
- - origin
- - native_id
- - session_native_id
- - source_path
- - event_type
- - payload_json
- - observed_at_ms
- - blob_hash
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_live_source_reconciliation_receipts
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:163
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - raw_id
- - verdict
- - previous_revision_authority
- - source_path
- - blob_hash
- - blob_size
- - compared_at_ms
- - tool_version
- - backup_manifest_path
- - detail
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_membership_census
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:148
- disposition: PURGE
- execution_owner: polylogue-lr6dx source-tier cutover, then polylogue-6kur repair.py identity-block removal
- reader_sites: []
- writer_sites: []
- finding_reuse:
- - polylogue-lr6dx
- conflicts:
- - raw_authority_parser_census has an intentional-retention note in polylogue/maintenance/raw_authority_reset.py:20
- purge_unlocks:
- - polylogue-lr6dx source-tier cutover, then polylogue-6kur repair.py identity-block removal
- columns:
- - raw_id
- - parser_fingerprint
- - status
- - member_count
- - censused_at_ms
- - detail
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_membership_writeback_receipts
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:185
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - raw_id
- - logical_source_key
- - provider_session_id
- - membership_decision
- - previous_revision_authority
- - promoted_at_ms
- - tool_version
- - backup_manifest_path
- - detail
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_quarantine_group_dedup_receipts
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:282
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - raw_id
- - source_path
- - blob_hash
- - blob_size
- - representative_raw_id
- - representative_session_id
- - promoted_at_ms
- - tool_version
- - backup_manifest_path
- - detail
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_session_memberships
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:120
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - raw_id
- - logical_source_key
- - provider_session_id
- - source_revision
- - normalized_content_hash
- - message_count
- - predecessor_raw_id
- - acquisition_generation
- - revision_authority
- - decision
- - decided_at_ms
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: raw_sessions
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:27
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - raw_id
- - origin
- - capture_mode
- - native_id
- - source_path
- - source_index
- - blob_hash
- - blob_size
- - acquired_at_ms
- - file_mtime_ms
- - parsed_at_ms
- - parse_error
- - validated_at_ms
- - validation_status
- - validation_error
- - validation_drift_count
- - validation_mode
- - detection_warnings_json
- - logical_source_key
- - revision_kind
- - source_revision
- - predecessor_source_revision
- - predecessor_raw_id
- - baseline_raw_id
- - append_start_offset
- - append_end_offset
- - acquisition_generation
- - revision_authority
- - revision_authority_evidence
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: sinex_publication_obligations
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:585
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - object_id
- - protocol_version
- - revision_id
- - manifest_digest
- - mode
- - status
- - attempt_count
- - last_attempt_at_ms
- - last_receipt_state
- - last_error
- - created_at_ms
- - updated_at_ms
- - retired_at_ms
- - next_attempt_at_ms
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: sinex_publication_payloads
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:611
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - object_id
- - protocol_version
- - revision_id
- - manifest_digest
- - manifest_bytes
- - manifest_sha256
- - manifest_size_bytes
- - segment_count
- - total_size_bytes
- - staged_at_ms
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: sinex_publication_receipts
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:647
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - object_id
- - protocol_version
- - revision_id
- - manifest_digest
- - attempt_number
- - request_id
- - receipt_state
- - receipt_detail
- - error_code
- - received_at_ms
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: sinex_publication_segments
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:629
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - object_id
- - protocol_version
- - revision_id
- - manifest_digest
- - position
- - segment_name
- - segment_bytes
- - segment_sha256
- - size_bytes
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: table
- name: verified_blob_receipts
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:701
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites: []
- writer_sites: []
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
- columns:
- - blob_hash
- - st_dev
- - st_ino
- - st_size
- - st_mtime_ns
- - st_ctime_ns
- - verified_at_ms
- column_audit: deferred after index and embeddings; current-DDL object evidence only
-
-- tier: source
- object_type: index
- name: idx_blob_publication_reservations_hash
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:494
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for blob_publication_reservations
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_blob_refs_ref_id
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:483
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for blob_refs
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_history_sidecars_path_hash
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:582
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for history_sidecars
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_otlp_spans_session
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:569
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for otlp_spans
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_otlp_spans_trace
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:566
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for otlp_spans
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_append_chain_backfill_receipts_compared_at
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:235
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_append_chain_backfill_receipts
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_artifacts_raw_id
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:528
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_artifacts
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_artifacts_source_identity
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:525
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_artifacts
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_authority_blockers_open_plan
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:435
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_authority_blockers
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_authority_census_plans_attempts
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:410
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_authority_census_plans
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_authority_census_plans_status
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:407
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_authority_census_plans
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_authority_verdicts_logical_source
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:470
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_authority_verdicts
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_byte_duplicate_supersession_receipts_duplicate_of
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:265
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_byte_duplicate_supersession_receipts
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_byte_duplicate_supersession_receipts_promoted_at
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:262
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_byte_duplicate_supersession_receipts
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_capture_observations_raw_id
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:117
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_capture_observations
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_hook_events_session
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:548
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_hook_events
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_live_source_reconciliation_receipts_compared_at
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:176
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_live_source_reconciliation_receipts
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_membership_writeback_receipts_promoted_at
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:204
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_membership_writeback_receipts
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_quarantine_group_dedup_receipts_promoted_at
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:295
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_quarantine_group_dedup_receipts
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_quarantine_group_dedup_receipts_representative
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:298
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_quarantine_group_dedup_receipts
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_session_memberships_logical
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:141
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_session_memberships
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_session_memberships_pending
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:144
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_session_memberships
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_sessions_blob_hash
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:91
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_sessions
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_sessions_blob_hash_raw_id
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:98
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_sessions
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_sessions_logical_revision
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:78
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_sessions
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_sessions_origin
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:62
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_sessions
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_sessions_origin_native
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:65
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_sessions
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_sessions_parse_ready
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:72
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_sessions
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_raw_sessions_source_path
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:69
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for raw_sessions
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_sinex_publication_obligations_object
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:608
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for sinex_publication_obligations
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_sinex_publication_obligations_pending
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:604
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for sinex_publication_obligations
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-
-- tier: source
- object_type: index
- name: idx_sinex_publication_receipts_recent
- ddl_anchor: polylogue/storage/sqlite/archive_tiers/source.py:668
- disposition: UNCLEAR
- execution_owner: polylogue-60i5 durable change train
- reader_sites:
- - SQLite query planner for sinex_publication_receipts
- writer_sites:
- - SQLite index maintenance
- finding_reuse: []
- conflicts: []
- purge_unlocks: []
-- {tier: index, object_type: table, name: action_pairs, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:24', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/insights/session_label.py:150'], writer_sites: ['polylogue/storage/sqlite/action_pairs.py:23'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [tool_use_block_id, session_id, message_id, tool_id, use_rank, tool_name, semantic_type, tool_command, tool_path, tool_result_block_id, is_error, exit_code], reader_columns: [tool_use_block_id, session_id, message_id, tool_id, use_rank, tool_name, semantic_type, tool_command, tool_path, tool_result_block_id, is_error, exit_code], writer_columns: [tool_use_block_id, session_id, message_id, tool_id, use_rank, tool_name, semantic_type, tool_command, tool_path, tool_result_block_id, is_error, exit_code], unclear_columns: []}
-- {tier: index, object_type: table, name: agent_meta_sidecar_purge_receipts, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:296', disposition: UNCLEAR, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [], writer_sites: ['polylogue/maintenance/agent_meta_sidecar_purge_apply.py:127'], finding_reuse: [], conflicts: [writer receipt exists without application reader], purge_unlocks: [], columns: [session_id, origin, native_id, raw_id, source_path, purged_at_ms, tool_version, backup_manifest_path, detail], reader_columns: [session_id, origin, native_id, raw_id, source_path, detail], writer_columns: [session_id, origin, native_id, raw_id, source_path, purged_at_ms, tool_version, backup_manifest_path, detail], unclear_columns: [purged_at_ms, tool_version, backup_manifest_path]}
-
-- {tier: index, object_type: table, name: attachment_native_ids, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:401', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/maintenance/corpus_fidelity.py:129'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/write.py:2524'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [ref_id, id_kind, native_id], reader_columns: [ref_id, id_kind, native_id], writer_columns: [ref_id, native_id], unclear_columns: []}
-
-- {tier: index, object_type: table, name: attachment_refs, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:772', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/cli/query_stats.py:162'], writer_sites: ['polylogue/storage/attachment_relink.py:347'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [ref_id, attachment_id, session_id, message_id, position, upload_origin, source_url, caption], reader_columns: [ref_id, attachment_id, session_id, message_id, position, upload_origin, source_url, caption], writer_columns: [ref_id, attachment_id, session_id, message_id, position, upload_origin, source_url, caption], unclear_columns: []}
-
-- {tier: index, object_type: table, name: attachments, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1259', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/api/archive.py:2073'], writer_sites: ['polylogue/api/archive.py:2073'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [attachment_id, display_name, media_type, byte_count, blob_hash, acquisition_status, ref_count], reader_columns: [attachment_id, display_name, media_type, byte_count, blob_hash, acquisition_status, ref_count], writer_columns: [attachment_id, display_name, media_type, byte_count, blob_hash, acquisition_status, ref_count], unclear_columns: []}
-
-- {tier: index, object_type: table, name: blocks, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:42', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/api/archive.py:2005'], writer_sites: ['polylogue/api/archive.py:2054'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [block_id, message_id, session_id, position, block_type, text, tool_name, tool_id, tool_input, semantic_type, media_type, language, tool_result_is_error, tool_result_exit_code, tool_result_outcome_unknown_reason, signature, content_hash, tool_command, tool_path, search_text, tool_detail_text], reader_columns: [block_id, message_id, session_id, position, block_type, text, tool_name, tool_id, tool_input, semantic_type, media_type, language, tool_result_is_error, tool_result_exit_code, tool_result_outcome_unknown_reason, signature, content_hash, tool_command, tool_path, search_text, tool_detail_text], writer_columns: [block_id, message_id, session_id, position, block_type, text, tool_name, tool_id, tool_input, semantic_type, media_type, language, tool_result_is_error, tool_result_exit_code, tool_result_outcome_unknown_reason, signature, content_hash, tool_command, tool_path, search_text, tool_detail_text], unclear_columns: []}
-
-- {tier: index, object_type: virtual_table, name: blocks_command_trigram, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:433', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/maintenance/archive_verification.py:657'], writer_sites: ['polylogue/storage/fts/sql.py:462'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [tool_detail_text, blocks_command_trigram, rank], reader_columns: [tool_detail_text, blocks_command_trigram, rank], writer_columns: [tool_detail_text, blocks_command_trigram, rank], unclear_columns: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: blocks_command_trigram_config, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: blocks_command_trigram_data, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: blocks_command_trigram_docsize, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: blocks_command_trigram_idx, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-- {tier: index, object_type: table, name: delegation_facts, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:35', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/insights/delegation_work_evidence.py:7'], writer_sites: ['polylogue/storage/sqlite/delegation_facts.py:19'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [delegation_id, parent_session_id, child_session_id, mapping_state, link_confidence, link_method, inheritance, branch_point_message_id, instruction_message_id, instruction_tool_use_block_id, instruction_payload, dispatch_turn_model, requested_model, artifact_block_id, artifact_text, result_is_error, result_exit_code, result_status, parent_origin, parent_session_dominant_model, parent_session_dominant_model_family, parent_terminal_state, child_session_dominant_model, child_session_dominant_model_family, child_cost_usd, child_cost_is_estimated, child_tokens, child_wall_ms, child_terminal_state], reader_columns: [parent_session_id, child_session_id, mapping_state, link_confidence, link_method, inheritance, branch_point_message_id, instruction_message_id, instruction_tool_use_block_id, instruction_payload, dispatch_turn_model, requested_model, artifact_block_id, artifact_text, result_is_error, result_exit_code, result_status, parent_origin, parent_session_dominant_model, parent_session_dominant_model_family, parent_terminal_state, child_session_dominant_model, child_session_dominant_model_family, child_cost_usd, child_cost_is_estimated, child_tokens, child_wall_ms, child_terminal_state], writer_columns: [parent_session_id, child_session_id, mapping_state, link_confidence, link_method, inheritance, branch_point_message_id, instruction_message_id, instruction_tool_use_block_id, instruction_payload, dispatch_turn_model, requested_model, artifact_block_id, artifact_text, result_is_error, result_exit_code, result_status, parent_origin, parent_session_dominant_model, parent_session_dominant_model_family, parent_terminal_state, child_session_dominant_model, child_session_dominant_model_family, child_cost_usd, child_cost_is_estimated, child_tokens, child_wall_ms, child_terminal_state], unclear_columns: [delegation_id]}
-
-- {tier: index, object_type: table, name: delegation_refresh_scope, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1830', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/sqlite/delegation_facts.py:57'], writer_sites: ['polylogue/storage/sqlite/delegation_facts.py:47'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [parent_session_id], reader_columns: [parent_session_id], writer_columns: [parent_session_id], unclear_columns: []}
-
-- {tier: index, object_type: table, name: derived_refresh_guard, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:446', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/maintenance/sharded_rebuild.py:377'], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [guard_name], reader_columns: [guard_name], writer_columns: [], unclear_columns: []}
-
-- {tier: index, object_type: table, name: file_edits, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:52', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/cli/read_view_handlers.py:41'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/write.py:2526'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [tool_use_block_id, session_id, message_id, file_path, structured_patch_json, original_file, old_string, new_string, replace_all, user_modified, observed_at_ms], reader_columns: [tool_use_block_id, session_id, message_id, file_path, structured_patch_json, original_file, old_string, new_string, replace_all, user_modified, observed_at_ms], writer_columns: [tool_use_block_id, session_id, message_id, file_path, original_file, old_string, new_string, replace_all, user_modified, observed_at_ms], unclear_columns: []}
-
-- {tier: index, object_type: table, name: fts_freshness_state, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:178', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/daemon/fts_startup.py:293'], writer_sites: ['polylogue/storage/fts/freshness.py:162'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [surface, state, checked_at, source_rows, indexed_rows, missing_rows, excess_rows, duplicate_rows, detail], reader_columns: [surface, state, checked_at, source_rows, indexed_rows, missing_rows, excess_rows, duplicate_rows, detail], writer_columns: [surface, state, checked_at, source_rows, indexed_rows, missing_rows, excess_rows, duplicate_rows, detail], unclear_columns: []}
-
-- {tier: index, object_type: table, name: insight_materialization, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:304', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/daemon/convergence_stages.py:1985'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/write.py:1116'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [insight_type, session_id, materializer_version, materialized_at_ms, source_updated_at_ms, source_sort_key_ms, input_high_water_mark_ms, input_high_water_mark_source, input_row_count], reader_columns: [insight_type, session_id, materializer_version, materialized_at_ms, source_updated_at_ms, source_sort_key_ms, input_high_water_mark_ms, input_high_water_mark_source, input_row_count], writer_columns: [insight_type, session_id, materializer_version, materialized_at_ms, source_updated_at_ms, source_sort_key_ms, input_high_water_mark_ms, input_high_water_mark_source, input_row_count], unclear_columns: []}
-
-- {tier: index, object_type: table, name: messages, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:39', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/api/archive.py:20'], writer_sites: ['polylogue/api/archive.py:2094'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [message_id, session_id, native_id, parent_message_id, position, role, message_type, material_origin, model_name, model_effort, sender_name, recipient, delivery_status, end_turn, user_context_text, has_tool_use, has_thinking, has_paste, paste_boundary, variant_index, is_active_path, is_active_leaf, word_count, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, duration_ms, content_hash, occurred_at_ms, stop_reason], reader_columns: [message_id, session_id, native_id, parent_message_id, position, role, message_type, material_origin, model_name, model_effort, sender_name, recipient, delivery_status, end_turn, user_context_text, has_tool_use, has_thinking, has_paste, paste_boundary, variant_index, is_active_path, is_active_leaf, word_count, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, duration_ms, content_hash, occurred_at_ms, stop_reason], writer_columns: [message_id, session_id, native_id, parent_message_id, position, role, message_type, material_origin, model_name, model_effort, sender_name, recipient, delivery_status, end_turn, user_context_text, has_tool_use, has_thinking, has_paste, paste_boundary, variant_index, is_active_path, is_active_leaf, word_count, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, duration_ms, content_hash, occurred_at_ms, stop_reason], unclear_columns: []}
-
-- {tier: index, object_type: virtual_table, name: messages_fts, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:181', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/daemon/convergence_stages.py:1235'], writer_sites: ['polylogue/storage/fts/sql.py:119'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [block_id, message_id, session_id, block_type, text, messages_fts, rank], reader_columns: [block_id, message_id, session_id, block_type, text, messages_fts, rank], writer_columns: [block_id, message_id, session_id, block_type, text, messages_fts, rank], unclear_columns: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: messages_fts_config, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: messages_fts_data, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-- {tier: index, object_type: virtual_shadow_table, name: messages_fts_docsize, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:733', disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: messages_fts_identity, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: messages_fts_idx, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: table, name: paste_spans, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:772', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/daemon/web_shell_paste.py:205'], writer_sites: ['polylogue/daemon/http.py:2523'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [paste_id, message_id, session_id, position, start_offset, end_offset, boundary_state, source_event_id, source_marker, content_hash, observed_at_ms], reader_columns: [paste_id, message_id, session_id, position, start_offset, end_offset, boundary_state, source_event_id, source_marker, content_hash, observed_at_ms], writer_columns: [paste_id, message_id, session_id, position, start_offset, end_offset, boundary_state, source_marker, content_hash, observed_at_ms], unclear_columns: []}
-
-- {tier: index, object_type: table, name: query_unit_frame_state, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:483', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/archive/query/transaction.py:100'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/archive.py:5803'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [singleton, epoch], reader_columns: [singleton, epoch], writer_columns: [singleton, epoch], unclear_columns: []}
-
-- {tier: index, object_type: table, name: raw_revision_applications, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:490', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/archive_readiness.py:356'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/revision_application.py:223'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [decision_id, raw_id, session_id, logical_source_key, source_revision, acquisition_generation, decision, accepted_raw_id, accepted_source_revision, accepted_content_hash, baseline_raw_id, predecessor_raw_id, append_end_offset, detail, decided_at_ms], reader_columns: [decision_id, raw_id, session_id, logical_source_key, source_revision, acquisition_generation, decision, accepted_raw_id, accepted_source_revision, accepted_content_hash, baseline_raw_id, predecessor_raw_id, append_end_offset, detail, decided_at_ms], writer_columns: [decision_id, raw_id, session_id, logical_source_key, source_revision, acquisition_generation, decision, accepted_raw_id, accepted_source_revision, accepted_content_hash, baseline_raw_id, predecessor_raw_id, append_end_offset, detail, decided_at_ms], unclear_columns: []}
-
-- {tier: index, object_type: table, name: raw_revision_heads, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:524', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/raw_authority.py:669'], writer_sites: ['polylogue/storage/repair.py:2680'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [logical_source_key, session_id, accepted_raw_id, accepted_source_revision, accepted_content_hash, accepted_frontier_kind, accepted_frontier, acquisition_generation, append_end_offset, decided_at_ms], reader_columns: [logical_source_key, session_id, accepted_raw_id, accepted_source_revision, accepted_content_hash, accepted_frontier_kind, accepted_frontier, acquisition_generation, append_end_offset, decided_at_ms], writer_columns: [logical_source_key, session_id, accepted_raw_id, accepted_source_revision, accepted_content_hash, accepted_frontier_kind, accepted_frontier, acquisition_generation, append_end_offset, decided_at_ms], unclear_columns: []}
-
-- {tier: index, object_type: table, name: repo_checkouts, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1195', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/insights/session/repo_observations.py:291'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/write.py:5213'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [repo_id, root_path, first_seen_at_ms, last_seen_at_ms], reader_columns: [repo_id, root_path, first_seen_at_ms, last_seen_at_ms], writer_columns: [repo_id, root_path, first_seen_at_ms, last_seen_at_ms], unclear_columns: []}
-
-- {tier: index, object_type: table, name: repos, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1129', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/api/archive.py:775'], writer_sites: ['polylogue/api/archive.py:775'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [repo_id, origin_url, root_path, repo_name, first_seen_at_ms, last_seen_at_ms], reader_columns: [repo_id, origin_url, root_path, repo_name, first_seen_at_ms, last_seen_at_ms], writer_columns: [repo_id, origin_url, root_path, repo_name, first_seen_at_ms, last_seen_at_ms], unclear_columns: []}
-
-- {tier: index, object_type: table, name: session_agent_policies, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:773', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/sqlite/archive_tiers/ingest_precedence.py:297'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/write.py:6071'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [policy_id, session_id, source_message_id, position, approval_policy, sandbox_policy, network_policy, observed_at_ms], reader_columns: [policy_id, session_id, source_message_id, position, approval_policy, sandbox_policy, network_policy, observed_at_ms], writer_columns: [policy_id, session_id, source_message_id, position, approval_policy, sandbox_policy, network_policy, observed_at_ms], unclear_columns: []}
-- {tier: embeddings, object_type: virtual_table, name: message_embeddings, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/embeddings.py:11', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/daemon/metrics.py:693'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/embedding_write.py:333'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [embedding_input_hash, embedding, model], reader_columns: [embedding_input_hash, embedding, model], writer_columns: [embedding_input_hash, embedding, model], unclear_columns: []}
-
-- {tier: embeddings, object_type: table, name: message_embeddings_meta, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/embeddings.py:11', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/daemon/convergence_stages.py:1057'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/embedding_write.py:327'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [embedding_input_hash, model, dimension, embedded_at_ms, recipe_hash, output_contract_hash], reader_columns: [embedding_input_hash, model, dimension, embedded_at_ms, recipe_hash, output_contract_hash], writer_columns: [embedding_input_hash, model, dimension, embedded_at_ms, recipe_hash, output_contract_hash], unclear_columns: []}
-
-- {tier: embeddings, object_type: table, name: message_embedding_refs, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/embeddings.py:46', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/daemon/metrics.py:692'], writer_sites: ['polylogue/storage/embeddings/reconcile.py:334'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [message_id, session_id, origin, embedding_input_hash, embedded_at_ms], reader_columns: [message_id, session_id, origin, embedding_input_hash, embedded_at_ms], writer_columns: [message_id, session_id, origin, embedding_input_hash, embedded_at_ms], unclear_columns: []}
-
-- {tier: embeddings, object_type: table, name: embedding_status, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/embeddings.py:60', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/daemon/convergence_stages.py:1057'], writer_sites: ['polylogue/daemon/convergence_stages.py:1164'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [session_id, origin, message_count_embedded, last_embedded_at_ms, needs_reindex, error_message], reader_columns: [session_id, origin, message_count_embedded, last_embedded_at_ms, needs_reindex, error_message], writer_columns: [session_id, origin, message_count_embedded, last_embedded_at_ms, needs_reindex, error_message], unclear_columns: []}
-
-- {tier: embeddings, object_type: table, name: embedding_derivation_state, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/embeddings.py:69', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/sqlite/archive_tiers/embedding_write.py:435'], writer_sites: ['polylogue/daemon/convergence_stages.py:1106'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [session_id, origin, generation, derivation_key, source_hash, recipe_hash, output_contract_hash, attempt_state, message_count, updated_at_ms], reader_columns: [session_id, origin, generation, derivation_key, source_hash, recipe_hash, output_contract_hash, attempt_state, message_count, updated_at_ms], writer_columns: [session_id, origin, generation, derivation_key, source_hash, recipe_hash, output_contract_hash, attempt_state, message_count, updated_at_ms], unclear_columns: []}
-
-- {tier: embeddings, object_type: table, name: embedding_failures, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/embeddings.py:87', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/sqlite/archive_tiers/embedding_write.py:695'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/embedding_write.py:497'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [failure_id, session_id, origin, message_refs_json, provider, model, error_class, error_message, retryable, lifecycle_state, created_at_ms, updated_at_ms, resolved_at_ms, resolution_action, resolution_note, superseded_by, generation, derivation_key, source_hash, recipe_hash], reader_columns: [failure_id, session_id, origin, message_refs_json, provider, model, error_class, error_message, retryable, lifecycle_state, created_at_ms, updated_at_ms, resolved_at_ms, resolution_action, resolution_note, superseded_by, generation, derivation_key, source_hash, recipe_hash], writer_columns: [failure_id, session_id, origin, message_refs_json, provider, model, error_class, error_message, retryable, lifecycle_state, created_at_ms, updated_at_ms, resolved_at_ms, resolution_action, resolution_note, superseded_by, generation, derivation_key, source_hash, recipe_hash], unclear_columns: []}
-
-- {tier: embeddings, object_type: index, name: idx_message_embedding_refs_hash, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/embeddings.py:54', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for message_embedding_refs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: embeddings, object_type: index, name: idx_message_embedding_refs_session, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/embeddings.py:57', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for message_embedding_refs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: embeddings, object_type: index, name: idx_embedding_derivation_pending, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/embeddings.py:84', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for embedding_derivation_state], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: embeddings, object_type: index, name: idx_embedding_failures_active, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/embeddings.py:112', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for embedding_failures], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-- {tier: user, object_type: table, name: annotation_batches, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:265', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [batch_id, schema_id, schema_version, target_ref, source_result_ref, actor_ref, model_ref, prompt_ref, total_count, valid_count, invalid_count, abstained_count, assertion_refs_json, validation_failures_json, metadata_json, created_at_ms], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: user, object_type: table, name: annotation_schemas, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:236', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [schema_id, schema_version, definition_json, definition_sha256, registered_at_ms], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: user, object_type: table, name: assertions, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:19', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [assertion_id, scope_ref, target_ref, key, kind, value_json, body_text, author_ref, author_kind, evidence_refs_json, status, visibility, confidence, staleness_json, context_policy_json, supersedes_json, created_at_ms, updated_at_ms], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: user, object_type: table, name: context_deliveries, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:318', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [snapshot_ref, recipient_ref, run_ref, boundary, inheritance_mode, context_image_json, context_image_sha256, segment_refs_json, evidence_refs_json, assertion_refs_json, omissions_json, caveats_json, metadata_json, delivered_by_ref, delivered_at_ms], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: user, object_type: table, name: holdout_access_receipts, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:221', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [receipt_id, result_set_id, accessor_ref, declared_confirmation, contamination, reason, accessed_at_ms], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: user, object_type: table, name: queries, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:67', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [query_hash, canonical_plan_json, grain, lane, rank_policy, created_at_ms, definition_protocol_version], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: user, object_type: table, name: query_edges, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:116', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [src_query_hash, dst_query_hash, edge_kind, created_at_ms], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: user, object_type: table, name: query_evaluation_receipts, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:136', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [receipt_id, query_hash, result_set_id, source_generation, user_generation, index_generation, runtime_build_ref, model_refs_json, resolved_bounds_json, degradation_json, created_at_ms], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: user, object_type: table, name: query_names, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:78', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [name, query_hash, supersedes_query_hash, updated_at_ms, watch], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: user, object_type: table, name: query_unit_frame_state, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:8', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [singleton, epoch], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: user, object_type: table, name: result_set_holdout_policies, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:206', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [result_set_id, frame, selection_definition_json, intended_confirmation_use, authority, created_epoch, created_at_ms], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: user, object_type: table, name: result_set_members, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:108', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [result_set_id, rank, member_ref], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: user, object_type: table, name: result_sets, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:92', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [result_set_id, query_hash, grain, corpus_epoch, member_count, membership_merkle_root, ordered_rank_hash, exactness, persistence_class, created_at_ms], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: user, object_type: table, name: retained_query_runs, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:129', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [run_id, query_hash, result_set_id, retained_at_ms], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: user, object_type: table, name: user_settings, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:308', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [setting_key, value_json, updated_at_ms, author_ref], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: user, object_type: table, name: watched_query_baselines, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:155', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [query_hash, result_set_id, updated_at_ms], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: user, object_type: trigger, name: query_evaluation_receipts_result_set_query_match_insert, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:173', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite trigger program on query_evaluation_receipts], writer_sites: [fires on writes to query_evaluation_receipts], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: trigger, name: query_evaluation_receipts_result_set_query_match_update, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:180', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite trigger program on query_evaluation_receipts], writer_sites: [fires on writes to query_evaluation_receipts], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: trigger, name: query_unit_frame_assertions_delete, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:60', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite trigger program on assertions], writer_sites: [fires on writes to assertions], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: trigger, name: query_unit_frame_assertions_insert, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:52', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite trigger program on assertions], writer_sites: [fires on writes to assertions], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: trigger, name: query_unit_frame_assertions_update, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:56', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite trigger program on assertions], writer_sites: [fires on writes to assertions], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: trigger, name: retained_query_runs_result_set_query_match_insert, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:161', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite trigger program on retained_query_runs], writer_sites: [fires on writes to retained_query_runs], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: trigger, name: retained_query_runs_result_set_query_match_update, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:167', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite trigger program on retained_query_runs], writer_sites: [fires on writes to retained_query_runs], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: trigger, name: watched_query_baselines_result_set_query_match_insert, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:187', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite trigger program on watched_query_baselines], writer_sites: [fires on writes to watched_query_baselines], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: trigger, name: watched_query_baselines_result_set_query_match_update, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:193', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite trigger program on watched_query_baselines], writer_sites: [fires on writes to watched_query_baselines], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: index, name: idx_annotation_batches_schema_target_time, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:299', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite query planner for annotation_batches], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: index, name: idx_annotation_batches_source_result_time, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:302', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite query planner for annotation_batches], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: index, name: idx_assertions_kind_status_updated, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:43', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite query planner for assertions], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: index, name: idx_assertions_scope_kind_status, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:49', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite query planner for assertions], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: index, name: idx_assertions_target_kind, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:40', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite query planner for assertions], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: index, name: idx_assertions_target_kind_status_visibility, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:46', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite query planner for assertions], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: index, name: idx_context_deliveries_recipient_time, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:336', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite query planner for context_deliveries], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: index, name: idx_context_deliveries_run_time, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:339', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite query planner for context_deliveries], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: index, name: idx_holdout_access_receipts_result_set, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:230', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite query planner for holdout_access_receipts], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: index, name: idx_query_edges_dst_kind, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:124', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite query planner for query_edges], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: index, name: idx_query_evaluation_receipts_query_time, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:150', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite query planner for query_evaluation_receipts], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: index, name: idx_query_names_query_hash, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:86', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite query planner for query_names], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: index, name: idx_query_names_watch, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:89', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite query planner for query_names], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: user, object_type: index, name: idx_result_sets_query_epoch, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/user.py:105', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite query planner for result_sets], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-- {tier: ops, object_type: table, name: convergence_debt, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:136', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [debt_id, stage, target_type, target_id, status, priority, attempts, last_error, next_retry_at, materializer_version, created_at_ms, updated_at_ms], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: ops, object_type: table, name: cursor_lag_samples, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:155', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [sample_id, family, source_path, lag_ms, stuck_file_count, p50_lag_ms, p95_lag_ms, severity, sampled_at_ms], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: ops, object_type: table, name: daemon_events, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:182', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [id, ts_ms, kind, operation_id, payload_json], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: ops, object_type: table, name: daemon_lifecycle, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:193', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [run_id, started_at_ms, stopped_at_ms, last_heartbeat_at_ms, signal, exit_kind, details_json], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: ops, object_type: table, name: daemon_stage_events, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:170', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [event_id, attempt_id, stage, status, observed_at_ms, payload_json], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: ops, object_type: table, name: embedding_catchup_runs, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:67', disposition: KEEP, execution_owner: polylogue-oj4oo vocabulary-unification change train, reader_sites: [], writer_sites: [], finding_reuse: [polylogue-oj4oo], conflicts: [status remains live while its vocabulary is unified], purge_unlocks: [], columns: [run_id, started_at_ms, finished_at_ms, status, origin, scanned_sessions, embedded_sessions, skipped_sessions, error_count, embedded_messages, estimated_cost_usd, error_message], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: ops, object_type: table, name: fts_drift_samples, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:307', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [sample_id, surface, state, source_rows, indexed_rows, missing_rows, excess_rows, duplicate_rows, identity_mismatch_rows, sampled_at_ms], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: ops, object_type: table, name: ingest_attempts, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:39', disposition: KEEP, execution_owner: polylogue-oj4oo vocabulary-unification change train, reader_sites: [], writer_sites: [], finding_reuse: [polylogue-oj4oo], conflicts: [status remains live while its vocabulary is unified], purge_unlocks: [], columns: [attempt_id, source_path, origin, status, phase, storage_route, started_at_ms, heartbeat_at_ms, finished_at_ms, parsed_raw_count, materialized_count, error_message, source_paths_json, outcome_code, retryable, evidence_ref, diagnostic, remediation], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: ops, object_type: table, name: ingest_cursor, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:84', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [source_path, origin, stat_size, byte_offset, last_complete_newline, record_count, last_record_ts_ms, parser_fingerprint, content_fingerprint, tail_hash, st_dev, st_ino, mtime_ns, failure_count, next_retry_at, excluded, deferred_end_offset, updated_at_ms], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: ops, object_type: table, name: mcp_call_log, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:236', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [call_id, tool_name, session_id, started_at_ms, finished_at_ms, duration_ms, success, error_detail], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: ops, object_type: table, name: mcp_call_session_refs, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:256', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [call_id, session_id, relation], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: ops, object_type: table, name: route_observations, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:274', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [observation_id, trace_id, surface, route, verb, daemon_path, phase, started_at_ms, duration_ms, status, git_head, archive_epoch, attributes_json, sampled], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: ops, object_type: table, name: schema_drift_samples, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:20', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [sample_id, origin, element_kind, classification, unseen_key_signature, native_id_example, raw_id, observed_at_ms], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: ops, object_type: table, name: secret_scan_status, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:225', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [session_id, scanner_version, scanned_at_ms, blocks_scanned, candidates_found], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-
-- {tier: ops, object_type: index, name: idx_convergence_debt_stage, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:152', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for convergence_debt], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_cursor_lag_samples_family_time, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:167', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for cursor_lag_samples], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_daemon_events_kind, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:190', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for daemon_events], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_daemon_events_ts, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:191', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for daemon_events], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_daemon_lifecycle_latest, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:203', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for daemon_lifecycle], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_daemon_stage_events_attempt_observed, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:179', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for daemon_stage_events], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_fts_drift_samples_surface_time, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:320', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for fts_drift_samples], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_ingest_attempts_status, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:119', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for ingest_attempts], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_ingest_attempts_storage_route, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:122', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for ingest_attempts], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_ingest_cursor_attention, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:114', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for ingest_cursor], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_ops_mcp_call_log_session, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:247', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for mcp_call_log], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_ops_mcp_call_log_started, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:253', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for mcp_call_log], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_ops_mcp_call_log_tool, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:250', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for mcp_call_log], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_ops_mcp_call_session_refs_session, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:263', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for mcp_call_session_refs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_route_observations_started, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:297', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for route_observations], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_route_observations_surface_route, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:291', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for route_observations], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_route_observations_trace, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:294', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for route_observations], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_schema_drift_samples_origin_time, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:31', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for schema_drift_samples], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_schema_drift_samples_time, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:34', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for schema_drift_samples], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: ops, object_type: index, name: idx_secret_scan_status_version, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/ops.py:233', disposition: UNCLEAR, execution_owner: unassigned ops-tier disposition, reader_sites: [SQLite query planner for secret_scan_status], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-- {tier: index, object_type: virtual_table, name: messages_fts, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:181', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/daemon/convergence_stages.py:1235'], writer_sites: ['polylogue/storage/fts/sql.py:119'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [block_id, message_id, session_id, block_type, text, messages_fts, rank], reader_columns: [block_id, message_id, session_id, block_type, text, messages_fts, rank], writer_columns: [block_id, message_id, session_id, block_type, text, messages_fts, rank], unclear_columns: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: messages_fts_config, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: messages_fts_data, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: messages_fts_docsize, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:733', disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: messages_fts_identity, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: messages_fts_idx, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: table, name: paste_spans, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:772', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/daemon/web_shell_paste.py:205'], writer_sites: ['polylogue/daemon/http.py:2523'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [paste_id, message_id, session_id, position, start_offset, end_offset, boundary_state, source_event_id, source_marker, content_hash, observed_at_ms], reader_columns: [paste_id, message_id, session_id, position, start_offset, end_offset, boundary_state, source_event_id, source_marker, content_hash, observed_at_ms], writer_columns: [paste_id, message_id, session_id, position, start_offset, end_offset, boundary_state, source_marker, content_hash, observed_at_ms], unclear_columns: []}
-
-- {tier: index, object_type: table, name: query_unit_frame_state, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:483', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/archive/query/transaction.py:100'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/archive.py:5803'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [singleton, epoch], reader_columns: [singleton, epoch], writer_columns: [singleton, epoch], unclear_columns: []}
-
-- {tier: index, object_type: table, name: raw_revision_applications, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:490', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/archive_readiness.py:356'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/revision_application.py:223'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [decision_id, raw_id, session_id, logical_source_key, source_revision, acquisition_generation, decision, accepted_raw_id, accepted_source_revision, accepted_content_hash, baseline_raw_id, predecessor_raw_id, append_end_offset, detail, decided_at_ms], reader_columns: [decision_id, raw_id, session_id, logical_source_key, source_revision, acquisition_generation, decision, accepted_raw_id, accepted_source_revision, accepted_content_hash, baseline_raw_id, predecessor_raw_id, append_end_offset, detail, decided_at_ms], writer_columns: [decision_id, raw_id, session_id, logical_source_key, source_revision, acquisition_generation, decision, accepted_raw_id, accepted_source_revision, accepted_content_hash, baseline_raw_id, predecessor_raw_id, append_end_offset, detail, decided_at_ms], unclear_columns: []}
-
-- {tier: index, object_type: table, name: raw_revision_heads, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:524', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/raw_authority.py:669'], writer_sites: ['polylogue/storage/repair.py:2680'], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [logical_source_key, session_id, accepted_raw_id, accepted_source_revision, accepted_content_hash, accepted_frontier_kind, accepted_frontier, acquisition_generation, append_end_offset, decided_at_ms], reader_columns: [logical_source_key, session_id, accepted_raw_id, accepted_source_revision, accepted_content_hash, accepted_frontier_kind, accepted_frontier, acquisition_generation, append_end_offset, decided_at_ms], writer_columns: [logical_source_key, session_id, accepted_raw_id, accepted_source_revision, accepted_content_hash, accepted_frontier_kind, accepted_frontier, acquisition_generation, append_end_offset, decided_at_ms], unclear_columns: []}
-- {tier: index, object_type: table, name: session_tag_rollups, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:421', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/api/insights.py:346'], writer_sites: ['polylogue/storage/sqlite/queries/session_insight_summary_queries.py:59'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {tag: KEEP, bucket_day: KEEP, source_name: KEEP, materializer_version: KEEP, materialized_at: KEEP, source_updated_at: KEEP, source_sort_key: KEEP, input_high_water_mark: KEEP, input_high_water_mark_source: KEEP, input_row_count: KEEP, session_count: KEEP, logical_session_count: KEEP, logical_session_ids_json: UNCLEAR, explicit_count: KEEP, auto_count: KEEP, repo_breakdown_json: KEEP, search_text: KEEP}}
-
-- {tier: index, object_type: table, name: session_tags, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1411', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/antigravity_phantom_sweep.py:84'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/session_annotations_write.py:144'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {session_id: KEEP, tag: KEEP, tag_source: KEEP, method: KEEP, confidence: KEEP, evidence_json: KEEP}}
-
-- {tier: index, object_type: table, name: session_work_events, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1485', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/api/insights.py:370'], writer_sites: ['polylogue/storage/fts/dangling_repair.py:107'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {event_id: KEEP, session_id: KEEP, position: KEEP, work_event_type: KEEP, summary: KEEP, confidence: KEEP, start_index: KEEP, end_index: KEEP, started_at_ms: KEEP, ended_at_ms: KEEP, duration_ms: KEEP, file_paths_json: KEEP, tools_used_json: KEEP, input_high_water_mark: KEEP, input_high_water_mark_source: KEEP, evidence_json: KEEP, inference_json: KEEP, search_text: KEEP}}
-
-- {tier: index, object_type: virtual_table, name: session_work_events_fts, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1513', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/daemon/fts_status.py:473'], writer_sites: ['polylogue/storage/fts/dangling_repair.py:108'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {event_id: KEEP, session_id: KEEP, work_event_type: KEEP, text: KEEP, session_work_events_fts: KEEP, rank: KEEP}}
-
-- {tier: index, object_type: virtual_shadow_table, name: session_work_events_fts_config, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: session_work_events_fts_content, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: session_work_events_fts_data, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: session_work_events_fts_docsize, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: virtual_shadow_table, name: session_work_events_fts_idx, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: owning declared FTS virtual table, reader_sites: [SQLite-managed FTS shadow], writer_sites: [SQLite FTS maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: table, name: session_working_dirs, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1171', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/sqlite/archive_tiers/archive.py:4076'], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {session_id: KEEP, path: KEEP, position: KEEP}}
-
-- {tier: index, object_type: table, name: sessions, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:45', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/agent_integration/spec.py:274'], writer_sites: ['polylogue/archive/write_effects.py:226'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {session_id: KEEP, native_id: KEEP, origin: KEEP, parent_session_id: KEEP, root_session_id: KEEP, raw_id: KEEP, branch_type: KEEP, active_leaf_message_id: KEEP, title: KEEP, session_kind: KEEP, title_source: KEEP, title_ref: KEEP, title_confidence: KEEP, display_name: KEEP, run_settings_json: KEEP, pending_drafts_json: KEEP, git_branch: KEEP, git_repository_url: KEEP, provider_project_ref: KEEP, commit_hash: KEEP, instructions_text: KEEP, reported_duration_ms: KEEP, reported_cost_usd: KEEP, message_count: KEEP, word_count: KEEP, tool_use_count: KEEP, thinking_count: KEEP, paste_count: KEEP, user_message_count: KEEP, authored_user_message_count: KEEP, assistant_message_count: KEEP, system_message_count: KEEP, tool_message_count: KEEP, user_word_count: KEEP, authored_user_word_count: KEEP, assistant_word_count: KEEP, content_hash: KEEP, created_at_ms: KEEP, updated_at_ms: KEEP, sort_key_ms: KEEP}}
-
-- {tier: index, object_type: table, name: thread_sessions, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1164', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/sqlite/archive_tiers/archive.py:3088'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/write.py:3984'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {thread_id: KEEP, session_id: KEEP, position: KEEP}}
-
-- {tier: index, object_type: table, name: threads, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1127', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/api/user_state_resolver.py:49'], writer_sites: ['polylogue/api/archive.py:5398'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {thread_id: KEEP, dominant_repo_id: UNCLEAR, materializer_version: KEEP, materialized_at: KEEP, source_updated_at: KEEP, input_high_water_mark: KEEP, input_high_water_mark_source: KEEP, input_row_count: KEEP, start_time: KEEP, end_time: KEEP, dominant_repo: KEEP, session_ids_json: KEEP, session_count: KEEP, depth: KEEP, branch_count: KEEP, total_messages: KEEP, total_cost_usd: KEEP, wall_duration_ms: KEEP, work_event_breakdown_json: KEEP, payload_json: KEEP, search_text: KEEP, created_at_ms: KEEP}}
-
-- {tier: index, object_type: table, name: web_content_constructs, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:740', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/cli/read_view_handlers.py:51'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/write.py:2527'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {construct_id: KEEP, session_id: KEEP, message_id: KEEP, block_id: KEEP, position: KEEP, provider: KEEP, construct_type: KEEP, provider_key: KEEP, title: KEEP, url: KEEP, text: KEEP, source_id: KEEP, group_id: KEEP, group_title: KEEP, query: KEEP, asset_pointer: KEEP, mime_type: KEEP, status: KEEP, task_id: KEEP, task_type: KEEP, rank: KEEP, start_index: KEEP, end_index: KEEP}}
-
-- {tier: index, object_type: table, name: work_evidence_edges, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1866', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/sqlite/queries/work_evidence.py:169'], writer_sites: ['polylogue/insights/claude_workflow_materializer.py:667'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {graph_id: KEEP, edge_ref: KEEP, edge_kind: KEEP, source_ref: KEEP, target_ref: KEEP, evidence_refs_json: KEEP, corpus_snapshot_ref: KEEP, authority: KEEP, confidence: KEEP, occurred_at_ms: KEEP, association_state: KEEP}}
-- {tier: index, object_type: table, name: work_evidence_graphs, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1841', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/insights/claude_workflow_materializer.py:528'], writer_sites: ['polylogue/insights/claude_workflow_materializer.py:620'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {graph_id: KEEP, corpus_snapshot_ref: KEEP}}
-
-- {tier: index, object_type: table, name: work_evidence_nodes, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1846', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/sqlite/queries/work_evidence.py:164'], writer_sites: ['polylogue/insights/claude_workflow_materializer.py:628'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {graph_id: KEEP, node_ref: KEEP, node_kind: KEEP, label: KEEP, evidence_refs_json: KEEP, corpus_snapshot_ref: KEEP, authority: KEEP, confidence: KEEP, occurred_at_ms: KEEP, actor_ref: KEEP, execution_context_id: KEEP, execution_context_known_json: KEEP, execution_context_unknown_json: KEEP, execution_context_addressed: KEEP, association_state: KEEP, claim_text: KEEP}}
-
-- {tier: index, object_type: view, name: actions, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:715', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/agent_integration/spec.py:266'], writer_sites: [read-only derived view], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: view, name: delegation_facts_source, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1888', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/sqlite/archive_tiers/archive.py:704'], writer_sites: [read-only derived view], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: view, name: delegations, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1112', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/sqlite/archive_tiers/archive.py:723'], writer_sites: [read-only derived view], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: blocks_action_pairs_ad, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:2176', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on blocks], writer_sites: [fires on writes to blocks], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: blocks_action_pairs_ai, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:2165', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on blocks], writer_sites: [fires on writes to blocks], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: blocks_action_pairs_au, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:2187', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on blocks], writer_sites: [fires on writes to blocks], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: blocks_command_trigram_ad, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:919', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on blocks], writer_sites: [fires on writes to blocks], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: blocks_command_trigram_ai, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:904', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on blocks], writer_sites: [fires on writes to blocks], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: blocks_command_trigram_au, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:926', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on blocks], writer_sites: [fires on writes to blocks], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: messages_fts_ad, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on blocks], writer_sites: [fires on writes to blocks], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: messages_fts_ai, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on blocks], writer_sites: [fires on writes to blocks], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: messages_fts_au, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on blocks], writer_sites: [fires on writes to blocks], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_blocks_delete, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1453', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on blocks], writer_sites: [fires on writes to blocks], finding_reuse: [], conflicts: [], purge_unlocks: []}
-- {tier: index, object_type: trigger, name: query_unit_frame_blocks_insert, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1445', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on blocks], writer_sites: [fires on writes to blocks], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_blocks_update, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1449', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on blocks], writer_sites: [fires on writes to blocks], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_delegation_facts_delete, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1825', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on delegation_facts], writer_sites: [fires on writes to delegation_facts], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_delegation_facts_insert, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1817', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on delegation_facts], writer_sites: [fires on writes to delegation_facts], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_delegation_facts_update, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1821', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on delegation_facts], writer_sites: [fires on writes to delegation_facts], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_messages_delete, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1441', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on messages], writer_sites: [fires on writes to messages], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_messages_insert, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1433', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on messages], writer_sites: [fires on writes to messages], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_messages_update, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1437', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on messages], writer_sites: [fires on writes to messages], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_session_links_delete, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1122', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on session_links], writer_sites: [fires on writes to session_links], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_session_links_insert, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1114', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on session_links], writer_sites: [fires on writes to session_links], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_session_links_update, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1118', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on session_links], writer_sites: [fires on writes to session_links], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_session_profiles_delete, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1682', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on session_profiles], writer_sites: [fires on writes to session_profiles], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_session_profiles_insert, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1674', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on session_profiles], writer_sites: [fires on writes to session_profiles], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_session_profiles_update, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1678', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on session_profiles], writer_sites: [fires on writes to session_profiles], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_session_tags_delete, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1465', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on session_tags], writer_sites: [fires on writes to session_tags], finding_reuse: [], conflicts: [], purge_unlocks: []}
-- {tier: index, object_type: trigger, name: query_unit_frame_session_tags_insert, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1457', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on session_tags], writer_sites: [fires on writes to session_tags], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_session_tags_update, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1461', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on session_tags], writer_sites: [fires on writes to session_tags], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_sessions_delete, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1429', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on sessions], writer_sites: [fires on writes to sessions], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_sessions_insert, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1421', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on sessions], writer_sites: [fires on writes to sessions], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: query_unit_frame_sessions_update, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1425', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on sessions], writer_sites: [fires on writes to sessions], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: session_links_delegation_facts_ai, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:2198', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on session_links], writer_sites: [fires on writes to session_links], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: session_links_delegation_facts_au, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:2217', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on session_links], writer_sites: [fires on writes to session_links], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: session_profiles_delegation_facts_ai, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:2208', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on session_profiles], writer_sites: [fires on writes to session_profiles], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: session_profiles_delegation_facts_au, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:2234', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on session_profiles], writer_sites: [fires on writes to session_profiles], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: session_work_events_fts_ad, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on session_work_events], writer_sites: [fires on writes to session_work_events], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: session_work_events_fts_ai, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on session_work_events], writer_sites: [fires on writes to session_work_events], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: trigger, name: session_work_events_fts_au, ddl_anchor: polylogue/storage/sqlite/archive_tiers/index.py, disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite trigger program on session_work_events], writer_sites: [fires on writes to session_work_events], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_action_pairs_message, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:964', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for action_pairs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_action_pairs_outcome, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:973', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for action_pairs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_action_pairs_path, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:970', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for action_pairs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-- {tier: index, object_type: index, name: idx_action_pairs_semantic, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:968', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for action_pairs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_action_pairs_session_order, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:962', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for action_pairs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_action_pairs_tool, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:966', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for action_pairs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_action_pairs_tool_result_block, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:989', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for action_pairs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_agent_meta_sidecar_purge_receipts_purged_at, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:2306', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for agent_meta_sidecar_purge_receipts], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_attachment_native_ids_native, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1305', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for attachment_native_ids], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_attachment_refs_message, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1297', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for attachment_refs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_attachment_refs_session, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1294', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for attachment_refs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_attachment_refs_upload_origin, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1301', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for attachment_refs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_blocks_content_hash, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:707', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for blocks], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_blocks_search_text_populated, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:736', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for blocks], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_blocks_session_position, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:704', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for blocks], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_blocks_tool_id, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:728', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for blocks], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_blocks_tool_result_outcome, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:718', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for blocks], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_blocks_type, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:710', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for blocks], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-- {tier: index, object_type: index, name: idx_blocks_type_tool, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:722', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for blocks], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_delegation_facts_model, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1811', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for delegation_facts], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_delegation_facts_parent_order, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1807', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for delegation_facts], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_delegation_facts_state, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1809', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for delegation_facts], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_file_edits_file_path, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:831', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for file_edits], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_file_edits_message, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:828', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for file_edits], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_file_edits_session, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:821', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for file_edits], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_messages_active_leaf, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:695', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for messages], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_messages_active_path, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:691', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for messages], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_messages_embedding_prose, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:684', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for messages], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_messages_material_origin, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:676', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for messages], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_messages_message_type, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:673', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for messages], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_messages_parent, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:660', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for messages], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_messages_role, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:667', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for messages], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_messages_session_material_origin, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:670', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for messages], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-- {tier: index, object_type: index, name: idx_messages_session_position, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:645', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for messages], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_messages_session_role, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:664', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for messages], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_messages_session_sortkey, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:657', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for messages], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_paste_spans_session, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1329', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for paste_spans], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_raw_revision_applications_identity, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:515', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for raw_revision_applications], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_raw_revision_applications_logical, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:521', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for raw_revision_applications], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_repos_root_path, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1205', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for repos], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_agent_policies_source_message, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1055', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_agent_policies], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_commits_hash, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1252', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_commits], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_commits_repo, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1255', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_commits], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_events_source_message, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1039', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_events], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_latency_profiles_date, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1574', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_latency_profiles], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_latency_profiles_provider, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1571', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_latency_profiles], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_latency_profiles_stuck, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1577', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_latency_profiles], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_links_dst, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1105', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_links], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-- {tier: index, object_type: index, name: idx_session_links_dst_native, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1109', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_links], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_phases_session, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1543', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_phases], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_profiles_canonical_date, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1669', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_profiles], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_profiles_first_message, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1666', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_profiles], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_profiles_logical_session, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1660', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_profiles], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_profiles_provider, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1657', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_profiles], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_profiles_sort, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1663', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_profiles], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_provider_usage_events_session, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1404', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_provider_usage_events], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_provider_usage_events_source_message, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1407', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_provider_usage_events], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_refs_kind, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:850', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_refs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_repos_repo, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1237', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_repos], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_tag_rollups_day, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:2283', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_tag_rollups], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_tag_rollups_provider, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:2286', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_tag_rollups], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_work_events_session, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1507', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_work_events], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_session_work_events_type, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1510', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for session_work_events], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-- {tier: index, object_type: index, name: idx_sessions_origin_sort, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:625', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for sessions], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_sessions_parent, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:628', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for sessions], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_sessions_raw_id, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:636', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for sessions], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_sessions_root, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:632', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for sessions], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_threads_time, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1152', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for threads], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_web_constructs_message, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:786', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for web_content_constructs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_web_constructs_query, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:793', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for web_content_constructs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_web_constructs_session_type, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:767', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for web_content_constructs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_web_constructs_url, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:789', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for web_content_constructs], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_work_evidence_edges_source, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1883', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for work_evidence_edges], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-
-- {tier: index, object_type: index, name: idx_work_evidence_edges_target, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1885', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: [SQLite query planner for work_evidence_edges], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-- {tier: source, object_type: table, name: raw_unknown_export_reclassification_receipts, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/source.py:684', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], columns: [raw_id, previous_origin, new_origin, previous_capture_mode, new_capture_mode, embedded_provider, source_path, blob_hash, blob_size, reclassified_at_ms, tool_version, backup_manifest_path, index_reparse_required, detail], column_audit: deferred after index and embeddings; current-DDL object evidence only}
-- {tier: source, object_type: index, name: idx_raw_unknown_export_reclassification_receipts_reclassified_at, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/source.py:681', disposition: UNCLEAR, execution_owner: polylogue-60i5 durable change train, reader_sites: [SQLite query planner for raw_unknown_export_reclassification_receipts], writer_sites: [SQLite index maintenance], finding_reuse: [], conflicts: [], purge_unlocks: []}
-- {tier: index, object_type: table, name: session_commits, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1240', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/sqlite/queries/session_commits.py:39'], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {session_id: KEEP, commit_sha: KEEP, repo_id: KEEP, detection_type: KEEP, method: KEEP, confidence: KEEP, evidence_json: KEEP, created_at_ms: KEEP}}
-
-- {tier: index, object_type: table, name: session_events, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:81', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/api/archive.py:5644'], writer_sites: ['polylogue/pipeline/ids.py:546'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {event_id: KEEP, session_id: KEEP, source_message_id: KEEP, source_message_provider_id: KEEP, position: KEEP, event_type: KEEP, summary: KEEP, payload_json: KEEP, occurred_at_ms: KEEP}}
-
-- {tier: index, object_type: table, name: session_latency_profiles, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1546', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/repair.py:5076'], writer_sites: [], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {session_id: KEEP, materializer_version: KEEP, materialized_at: KEEP, source_updated_at: KEEP, source_sort_key: KEEP, input_high_water_mark: KEEP, input_high_water_mark_source: KEEP, input_row_count: KEEP, source_name: KEEP, title: KEEP, first_message_at: KEEP, last_message_at: KEEP, canonical_session_date: KEEP, median_tool_call_ms: KEEP, p90_tool_call_ms: KEEP, max_tool_call_ms: KEEP, stuck_tool_count: KEEP, median_agent_response_ms: KEEP, median_user_response_ms: KEEP, tool_call_count_by_category_json: KEEP, evidence_payload_json: KEEP, search_text: KEEP}}
-
-- {tier: index, object_type: table, name: session_links, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:49', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/api/insights.py:227'], writer_sites: ['polylogue/api/archive.py:2552'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {src_session_id: KEEP, dst_origin: KEEP, dst_native_id: KEEP, link_type: KEEP, resolved_dst_session_id: KEEP, branch_point_message_id: KEEP, inheritance: KEEP, status: KEEP, parent_tool_use_block_id: KEEP, method: KEEP, confidence: KEEP, evidence_json: KEEP, observed_at_ms: KEEP, resolved_at_ms: KEEP}}
-
-- {tier: index, object_type: table, name: session_model_usage, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:124', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/daemon/convergence_stages.py:2014'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/index_convergence.py:98'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {session_id: KEEP, model_name: KEEP, input_tokens: KEEP, output_tokens: KEEP, cache_read_tokens: KEEP, cache_write_tokens: KEEP, message_count: KEEP, cost_usd: KEEP, cost_credits: KEEP, cost_provenance: KEEP}}
-
-- {tier: index, object_type: table, name: session_phases, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1524', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/api/insights.py:420'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/session_annotations_write.py:381'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {phase_id: KEEP, session_id: KEEP, position: KEEP, start_index: KEEP, end_index: KEEP, started_at_ms: KEEP, ended_at_ms: KEEP, duration_ms: KEEP, tool_counts_json: KEEP, word_count: KEEP, input_high_water_mark: KEEP, input_high_water_mark_source: KEEP, evidence_json: KEEP, inference_json: KEEP, search_text: KEEP}}
-
-- {tier: index, object_type: table, name: session_profiles, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:384', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/api/user_state_resolver.py:47'], writer_sites: ['polylogue/demo/seed.py:1351'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {session_id: KEEP, logical_session_id: KEEP, materializer_version: KEEP, materialized_at: KEEP, source_updated_at: KEEP, source_sort_key: KEEP, input_high_water_mark: KEEP, input_high_water_mark_source: KEEP, input_row_count: KEEP, source_name: KEEP, title: KEEP, first_message_at: KEEP, last_message_at: KEEP, canonical_session_date: KEEP, repo_paths_json: UNCLEAR, repo_names_json: KEEP, tags_json: KEEP, auto_tags_json: KEEP, message_count: KEEP, substantive_count: KEEP, attachment_count: KEEP, work_event_count: KEEP, phase_count: KEEP, word_count: KEEP, tool_use_count: KEEP, thinking_count: KEEP, total_cost_usd: KEEP, total_duration_ms: KEEP, engaged_duration_ms: KEEP, tool_active_duration_ms: KEEP, wall_duration_ms: KEEP, workflow_shape: KEEP, workflow_shape_method: UNCLEAR, workflow_shape_confidence: KEEP, workflow_shape_features_json: KEEP, terminal_state: KEEP, terminal_state_method: KEEP, terminal_state_confidence: KEEP, terminal_state_evidence_json: KEEP, cost_is_estimated: KEEP, thinking_duration_ms: KEEP, output_duration_ms: KEEP, tool_duration_ms: KEEP, latency_percentiles_ms_json: KEEP, tool_calls_per_minute: KEEP, timing_provenance: KEEP, total_input_tokens: KEEP, total_output_tokens: KEEP, total_cache_read_tokens: KEEP, total_cache_write_tokens: KEEP, total_credit_cost: KEEP, cost_provenance: KEEP, per_model_cost_json: KEEP, evidence_payload_json: KEEP, inference_payload_json: KEEP, enrichment_payload_json: KEEP, evidence_search_text: KEEP, inference_search_text: KEEP, enrichment_search_text: KEEP, enrichment_version: KEEP, enrichment_family: KEEP, inference_version: KEEP, inference_family: KEEP, search_text: KEEP, duration_ms: KEEP, cost_credits: KEEP, cost_usd: KEEP, priced_with: KEEP, priced_at_ms: KEEP, primary_model_name: KEEP, primary_model_family: KEEP}}
-
-- {tier: index, object_type: table, name: session_provider_usage_events, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:391', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/storage/usage.py:1347'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/write.py:6202'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {usage_event_id: UNCLEAR, session_id: KEEP, source_message_id: KEEP, position: KEEP, provider_event_type: KEEP, model_name: KEEP, last_input_tokens: KEEP, last_output_tokens: KEEP, last_cached_input_tokens: KEEP, last_cache_write_tokens: KEEP, last_reasoning_output_tokens: KEEP, last_total_tokens: KEEP, total_input_tokens: KEEP, total_output_tokens: KEEP, total_cached_input_tokens: KEEP, total_cache_write_tokens: KEEP, total_reasoning_output_tokens: KEEP, total_tokens: KEEP, occurred_at_ms: KEEP}}
-
-- {tier: index, object_type: table, name: session_refs, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:56', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/insights/hermes_integration_health.py:259'], writer_sites: ['polylogue/sources/import_explain.py:169'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {ref_id: KEEP, session_id: KEEP, position: KEEP, kind: KEEP, repo: KEEP, ref_number: UNCLEAR, url: KEEP, observed_at_ms: KEEP}}
-
-- {tier: index, object_type: table, name: session_repos, ddl_anchor: 'polylogue/storage/sqlite/archive_tiers/index.py:1223', disposition: KEEP, execution_owner: polylogue-818fy derived-tier rebuild change train, reader_sites: ['polylogue/api/archive.py:827'], writer_sites: ['polylogue/storage/sqlite/archive_tiers/write.py:5223'], finding_reuse: [], conflicts: [], purge_unlocks: [], column_dispositions: {session_id: KEEP, repo_id: KEEP, root_path: KEEP, branch_name: KEEP, observed_at_ms: KEEP}}
-retired_objects:
-- {tier: index, object_type: retired_column_batch, name: session_provider_usage_events Hermes billing columns and model_context_window, disposition: PURGED, evidence: [polylogue-664l, 'polylogue/storage/sqlite/archive_tiers/index.py:391'], execution_owner: 'polylogue-664l, merged PR #3698', purge_unlocks: [already executed], conflicts: []}
-- {tier: index, object_type: retired_check_member, name: attachment_native_ids.id_kind source, disposition: PURGED, evidence: [polylogue-664l, 'polylogue/storage/sqlite/archive_tiers/index.py:401'], execution_owner: 'polylogue-664l, merged PR #3698', purge_unlocks: [already executed], conflicts: ['664l corrected its original URL write-only hypothesis after finding a production identity-search reader']}
-- {tier: index, object_type: retired_table, name: price_catalogs, disposition: PURGED, evidence: ['polylogue/storage/sqlite/archive_tiers/index_convergence.py:94'], execution_owner: polylogue-resk index fast-forward change train, purge_unlocks: [already executed], conflicts: []}
-- {tier: index, object_type: retired_table, name: threads_fts, disposition: PURGED, evidence: ['polylogue/storage/sqlite/archive_tiers/index.py:1335'], execution_owner: polylogue-eizc index change train, purge_unlocks: [already executed], conflicts: []}
diff --git a/docs/audits/README.md b/docs/audits/README.md
index 5c08dcca19..87539c159d 100644
--- a/docs/audits/README.md
+++ b/docs/audits/README.md
@@ -1,16 +1,10 @@
-# Audit Records
+# Preserved Audit Records
-These are dated investigation records, not current product or operator guides.
-Use the current [Architecture](../architecture.md), [Internals](../internals.md),
-and [Developer Tools](../devtools.md) references for present-tense behavior.
+These dated documents are historical evidence retained for open Beads. They do
+not describe current product behavior and are not generated validation gates.
+For current behavior, use [Architecture](../architecture.md),
+[Internals](../internals.md), and [Developer Tools](../devtools.md).
-- [Closed issue workload audit](2026-05-19-closed-issue-workload-audit.md)
-- [Cross-surface coherence audit](2026-05-20-cross-surface-coherence-audit.md)
-- [API bypass audit](2026-05-25-api-bypass-audit.md)
- [Daemon loop lock-starvation map](2026-07-09-daemon-loop-lock-starvation-map.md)
-- [Hash boundary census](2026-07-09-hash-boundary-census.md)
-- [Race window audit](2026-07-09-race-window-audit.md)
-- [Reindex forcing-class audit](2026-08-04-reindex-forcing-class-audit.md)
-- [Blob-reference liveness closure audit](2026-08-04-blob-ref-liveness-closure.md)
- [Raw-failure preflight](2026-08-04-raw-failure-preflight.md)
-- [ChatGPT lifecycle-anchor evidence packet](2026-08-04-polylogue-uqwd-chatgpt-lifecycle-anchor.md)
+- [Reindex forcing-class audit](2026-08-04-reindex-forcing-class-audit.md)
diff --git a/docs/cli-reference.md b/docs/cli-reference.md
index 89b36c80b4..9be925d441 100644
--- a/docs/cli-reference.md
+++ b/docs/cli-reference.md
@@ -18,7 +18,7 @@ Usage: polylogue [OPTIONS] [COMMAND] [ARGS]...
Quoted query text is also accepted when followed by an action:
`polylogue 'QUERY' then read`.
Run `polylogue --help` to see the full subcommand list, or
- `polylogue --diagnose ` to have the parser explain how it
+ `polylogue --diagnose find "migration"` to have the parser explain how it
routed your invocation.
Product roles:
@@ -61,7 +61,7 @@ Usage: polylogue [OPTIONS] [COMMAND] [ARGS]...
polylogue tutorial # first-run setup checklist
polylogue find --help # query workflow help
polylogue --help # per-subcommand help
- polylogue --diagnose # explain parser decisions
+ polylogue --diagnose find "migration" # explain parser decisions
Options:
--help-markdown Same content as `polylogue manual`; emit the
@@ -759,49 +759,3 @@ Options:
--non-interactive Skip prompts; print the stage diagnostic and exit.
--help Show this message and exit.
```
-
-## Public Action Contracts
-
-This section is generated from `polylogue.operations.action_contracts.ACTION_CONTRACTS`.
-It records the public action floor, not every utility command in the Click tree.
-
-| Action | Effect | Target | Input | Cardinality | Safety | Formats | Destinations | Confirm | Select | Machine envelope | Guards | Next actions | Completion |
-| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
-| `polylogue find` | `read` | `none` | `none` | `any` | `safe` | `human`, `json`, `ndjson` | `terminal`, `stdout`, `file`, `api`, `mcp` | - | - | `result_set` | `explicit_query_intent` | `select`, `read`, `analyze`, `continue`, `mark`, `delete` | `query_expression` |
-| `polylogue read` | `read` | `selection` | `query_result_set` | `explicit_multi` | `safe` | `human`, `json`, `ndjson` | `terminal`, `stdout`, `browser`, `clipboard`, `file`, `api`, `mcp` | - | `polylogue find QUERY then select` | `item` | `single_match_unless_all_or_first`, `file_destination_requires_out` | `continue`, `mark`, `delete` | `session_id` |
-| `polylogue continue` | `read` | `selection` | `query_result_set` | `singleton` | `safe` | `human`, `json` | `terminal`, `stdout`, `clipboard`, `file`, `api`, `mcp` | - | `polylogue find QUERY then select` | `item` | - | `read`, `mark` | `session_id` |
-| `polylogue select` | `read` | `selection` | `query_result_set` | `singleton` | `safe` | `human`, `json` | `terminal`, `stdout`, `api`, `mcp` | - | - | `item` | - | `read`, `continue`, `analyze`, `mark`, `delete` | `session_id` |
-| `polylogue mark` | `write` | `selection` | `query_result_set` | `explicit_multi` | `mutating` | `human`, `json` | `terminal`, `stdout`, `api`, `mcp` | - | `polylogue find QUERY then select` | `mutation` | `single_match_unless_all_or_first` | `read`, `analyze` | `session_id` |
-| `polylogue judge` | `write` | `candidate` | `assertion_candidate` | `explicit_multi` | `mutating` | `human`, `json` | `terminal`, `stdout`, `api`, `mcp` | - | `polylogue judge --review` | `item` | `explicit_candidate_ref_for_mutation`, `authenticated_injection_opt_in` | `read`, `judge` | - |
-| `polylogue analyze` | `read` | `selection` | `query_result_set` | `any` | `safe` | `human`, `json`, `ndjson` | `terminal`, `stdout`, `file`, `api`, `mcp` | - | - | `result_set` | - | `select`, `read` | `query_expression` |
-| `polylogue delete` | `destructive` | `selection` | `query_result_set` | `destructive_multi` | `destructive` | `human`, `json` | `terminal`, `stdout`, `api`, `mcp` | `polylogue find QUERY then delete --dry-run` | `polylogue find QUERY then select` | `mutation` | `dry_run_or_yes_required`, `single_match_unless_all` | `find` | `session_id` |
-| `polylogue import` | `import` | `path` | `path` | `singleton` | `mutating` | `human` | `terminal`, `stdout`, `api` | - | - | `mutation` | `path_exists_or_demo`, `daemon_accepts_schedule` | `ops`, `read`, `analyze` | `filesystem_path` |
-| `polylogue config` | `config` | `config` | `config` | `any` | `operational` | `human`, `json` | `terminal`, `stdout` | - | - | `item` | `secret_values_redacted` | `ops` | `config_key` |
-| `polylogue ops` | `ops` | `runtime` | `runtime` | `any` | `operational` | `human` | `terminal`, `stdout`, `api` | - | - | `item` | - | `find`, `read` | - |
-
-## Published Machine Output Schemas
-
-This section is generated from `devtools.render_cli_output_schemas.SCHEMAS`.
-The schema files live under `docs/schemas/cli-output/`.
-
-| Schema | Model | Surfaces |
-| --- | --- | --- |
-| `session-list-row` | `SessionListEnvelope` | `polylogue read --all --format json` `polylogue read --all --format ndjson` `polylogue read --all --format yaml` |
-| `session-summary` | `SessionSummaryEnvelope` | `polylogue analyze --format json (rows)` `polylogue --format json (hits[].session)` |
-| `session-message-row` | `MessageRowEnvelope` | `polylogue read --view messages --format ndjson` `polylogue read --view messages --format json (messages[])` |
-| `session-messages-response` | `SessionMessagesResponsePayload` | `polylogue read --view messages --format json` |
-| `session-search-hit` | `SessionSearchHitPayload` | `polylogue --format json ` `polylogue --format ndjson ` |
-| `search-envelope` | `SearchEnvelope` | `polylogue --format json ` `GET /api/sessions?query=...` |
-| `query-unit-envelope` | `QueryUnitEnvelope` | `polylogue --format json messages where ...` `polylogue --format json actions where ...` `polylogue --format json blocks where ...` `polylogue --format json assertions where ...` `polylogue --format json files where ...` `polylogue --format json runs where ...` `polylogue --format json observed-events where ...` `polylogue --format json context-snapshots where ...` `polylogue --format json delegations where ...` `Polylogue.query_units(...)` `MCP query_units` `GET /api/query-units?expression=...` |
-| `query-unit-aggregate-envelope` | `QueryUnitAggregateEnvelope` | `polylogue --format json messages where ... | group by role | count` `Polylogue.query_units(...)` `MCP query_units` `GET /api/query-units?expression=...` |
-| `import-explain` | `ImportExplainPayload` | `polylogue import PATH --explain --format json` `polylogue import PATH --explain --format ndjson (entries)` |
-| `archive-debt-list` | `ArchiveDebtListPayload` | `polylogue ops debt list --format json` |
-| `tool-counts` | `ToolCountPayload` | `polylogue analyze tools --format json` |
-| `tool-family-comparison` | `ToolFamilyComparisonPayload` | `polylogue analyze tools --compare-family FAMILY --format json` |
-| `session-neighbor-candidate` | `SessionNeighborCandidatePayload` | `polylogue read --view neighbors --format json` |
-| `mutation-result` | `MutationResultPayload` | `polylogue find then delete --dry-run` `polylogue find then delete --yes` `MCP mutation tools` `daemon mutation endpoints` |
-| `action-affordance-list` | `ActionAffordanceListPayload` | `polylogue config action-affordances` `GET /api/action-affordances` `MCP action_affordances` |
-| `migrate-tier-result` | `MigrateTierResultPayload` | `polylogue ops maintenance migrate-tier --output-format json` |
-| `machine-error` | `MachineErrorPayload` | `polylogue * --machine (error path)` |
-| `machine-success` | `MachineSuccessPayload` | `polylogue * --machine (success path)` |
-| `query-error` | `QueryErrorPayload` | `GET /api/sessions?query=... (error path)` `daemon query/read error responses` `MCP query/read error responses` |
diff --git a/docs/code-navigation.md b/docs/code-navigation.md
index 4899bdee19..e031a2a889 100644
--- a/docs/code-navigation.md
+++ b/docs/code-navigation.md
@@ -201,5 +201,5 @@ registry or declaration, not the rendered output.
| Parser or identity semantics | provider fixture, eager/streaming/replay equivalence, and content-hash/fingerprint tests |
| Any merge candidate | `devtools verify --quick` plus the PR's affected-area tests |
-For the complete verification and cost model, see [Testing](../TESTING.md),
-[Test Economics](test-economics.md), and [Developer Tools](devtools.md).
+For the complete verification model, see [Testing](../TESTING.md) and
+[Developer Tools](devtools.md).
diff --git a/docs/cost-model.md b/docs/cost-model.md
index 52b1f1fed4..52fbf18036 100644
--- a/docs/cost-model.md
+++ b/docs/cost-model.md
@@ -438,6 +438,7 @@ candidates.
* [Data model](data-model.md) — typed payloads and storage shape.
* [CLI reference](cli-reference.md) — `polylogue analyze --cost-outlook` flags
and JSON schema.
-* [MCP reference](mcp-reference.md) — `cost_outlook` tool contract.
+* [MCP reference](mcp-reference.md) — MCP setup; cost outlook is resolved with
+ `get(ref="cost-outlook:")`.
* [Configuration](configuration.md) — `[[cost.subscription.plans]]` in
`polylogue.toml`.
diff --git a/docs/demos.md b/docs/demos.md
index 13d13d4b6a..74f51bfcc8 100644
--- a/docs/demos.md
+++ b/docs/demos.md
@@ -27,7 +27,12 @@ The human transcript is deliberately evidence-first rather than audit-first:
5. read a fork as one composed chronicle while preserving parent refs;
6. only then zoom out to archive facets.
-The full fixture audit remains machine-readable in `report.json`, so the public story stays compact without weakening verification. The current fixture world covers every wired origin (ChatGPT, Claude.ai, Claude Code, Codex, AI Studio/Gemini, Gemini CLI, Antigravity, and Hermes), structured tool outcomes, attachment bytes, browser-capture coalescing, lineage, a subagent, a compaction boundary, context snapshots, user overlays, and deterministic synthetic embeddings. See the [construct audit](plans/demo-corpus-construct-audit.md) and [proof map](proof-artifacts.md).
+The current fixture world covers every wired origin (ChatGPT, Claude.ai,
+Claude Code, Codex, AI Studio/Gemini, Gemini CLI, Antigravity, and Hermes),
+structured tool outcomes, attachment bytes, browser-capture coalescing,
+lineage, a subagent, a compaction boundary, context snapshots, user overlays,
+and deterministic synthetic embeddings. Run `polylogue demo verify` to measure
+the current fixture directly.
## Current public proofs
@@ -55,13 +60,6 @@ The full fixture audit remains machine-readable in `report.json`, so the public
**Does not prove:** that every possible source outage is currently detected.
-## Field finding: claim versus structural failure
-
-
-The historical packet generated on 2026-07-04 sampled 5,000 structured failures from a frame of 42,033. It classified 1,205 cases as silent proceed on the next assistant turn, a 24.1% lower bound, while 3,375 cases remained ambiguous. This is a field observation from one archive and one method—not a population estimate or an automatically current claim.
-
-Read the full [finding, method, calibration, and caveats](findings/claim-vs-evidence.md), then check the generated [findings-page claim status](generated/public-claims/findings-page.md) before reusing the number.
-
## Flagship demonstrations under construction
These are roadmap items, not present capabilities unless their packets are linked above.
@@ -84,38 +82,20 @@ A view of exactly which evidence and reviewed assertions an agent received, what
A preregistered paired comparison between strong raw-reference access and a generated resume packet. A workflow demonstration is insufficient; any benefit claim requires fixed sampling, equal budgets, preserved outputs, and independent scoring.
-## Demo Packet v2 contract
-
-The Demo Finding Packet contains:
-
-- an executable prompt;
-- a provenance stanza;
-- a fixed-section report;
-- evidence and query rows;
-- checks, unsupported claims, and coverage notes;
-- the raw run transcript.
-
-The versioned machine contract is
-[`schemas/demo-packet-v2.schema.json`](schemas/demo-packet-v2.schema.json). It
-also requires exactly one primary construct, a receipt-backed claim declared
-before execution, an independent oracle, a comparative baseline, negative and
-missing-evidence controls, an explicit falsifier, bounded non-claims, and local
-SHA-256-bound receipt artifacts. `devtools lab policy demo-packet-registry`
-validates every registered packet and rejects unregistered v2 packets.
-
-The production gate resolves every nested receipt citation through the
-top-level receipt table, confines each artifact path to its packet, verifies
-the artifact bytes against the declared SHA-256 digest, and confirms that the
-ref occurs in those same bytes. Reports use `## Claim` through `## Reproduce`
-exactly once and in the canonical order. The gate also rejects contradictory
-falsifier state and duplicate control IDs or measurement names. See the
-[worked contract example](examples/demo-packet-v2/README.md).
+## Demo evidence
+
+Substantive demo directories retain their prompt, report, raw command output,
+and machine-readable observations for human review. Those artifacts are
+examples, not release authority: a committed hash proves only which bytes were
+reviewed, not that a self-described oracle was independent or that prose claims
+are true. Product and release claims must be established by the executable
+route, behavior tests, and current runtime evidence that actually support them.
A deterministic public packet proves a product contract on the approved seed
1843 fixture world. It does not establish field prevalence, production scale,
or model behavior in the wild. Private-archive benchmarks remain a separate
local-only lane with their own sampling and privacy obligations.
-## Why the anti-demo belongs beside the successes
+## Negative evidence
-Polylogue’s category claim is not merely “it can answer difficult questions.” It is also “it can say when the archive does not support an answer.” A public portfolio that publishes only successful reconstructions would hide the project’s most important epistemic behavior.
+Polylogue must say when the archive does not support an answer. Demonstrations and runtime surfaces should expose unsupported reconstruction rather than fabricate a successful result.
diff --git a/docs/design/README.md b/docs/design/README.md
index a0b6d74789..babddb9d7b 100644
--- a/docs/design/README.md
+++ b/docs/design/README.md
@@ -19,9 +19,9 @@ domain models rather than plans:
| [Analysis rigor](analysis-rigor.md) | Rigor mechanisms for agent claims: population-validity (metric hashes, pre-registration, holdouts) + comparative judgment (Bradley-Terry rankings, agent judges, cascades) (polylogue-rxdo.9) |
| [Query set algebra](query-set-algebra.md) | Set-composition semantics over query results (polylogue-fnm.13) |
| [Agent-first MCP](agent-first-mcp.md) | MCP surface doctrine (polylogue-t46.8, polylogue-rsad) |
-| [Incident 14:32 proof world](incident-1432-proof-world.md) | Shared deterministic demo corpus model + anti-circularity/anti-vacuity rules (polylogue-212.11, polylogue-212.12) |
| [Project memory](project-memory.md) · [Second brain](second-brain.md) · [Time machine](time-machine.md) · [Archive storytelling](archive-storytelling.md) · [Whole product](whole-product.md) | Vision statements feeding horizon beads |
-| [Query-action workflows](query-action-workflows.md) | Moved pointer to the generated `docs/product/workflows.md` |
+| [Query-action workflows](../product/workflows.md) | Standing selection, cardinality, and executable-evidence guide |
+| [Incident 14:32 proof world](incident-1432-proof-world.md) | Shared deterministic adversarial corpus for the still-open proof-world work (polylogue-212.11) |
| [Prefix-blob reclamation](prefix-blob-reclamation.md) | Reference-blob representation for byte-proven superseded revision prefixes; consent-gated durable-tier reclamation (polylogue-vzn6) |
| [Convergence simplification inventory](convergence-simplification-inventory.md) | Deletion/collapse inventory for the daemon convergence redesign — what phases (b)-(d) remove and why (polylogue-m6tp) |
diff --git a/docs/design/query-action-workflows.md b/docs/design/query-action-workflows.md
deleted file mode 100644
index ee5f44ed56..0000000000
--- a/docs/design/query-action-workflows.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Query-Action Workflows
-
-The executable `find QUERY then ACTION` product contract moved to the generated
-product surface:
-
-- [Executable Query-Action Workflows](../product/workflows.md)
-
-That document is rendered from `polylogue/product/workflows.py` and the live CLI
-action contracts, including context-image and continuation handoff flows. It
-powers the demo-archive golden-path tests for #2305/#2306. Edit the registry or
-action contracts, then run:
-
-```bash
-devtools render product-workflows
-devtools render product-workflows --check
-devtools test tests/unit/product/test_query_action_workflows.py
-```
diff --git a/docs/devtools.md b/docs/devtools.md
index c025f96930..33fe32fc93 100644
--- a/docs/devtools.md
+++ b/docs/devtools.md
@@ -25,20 +25,16 @@ Routine command placement:
- prefer validation lanes and `devtools verify --lab` to compose executable
lab checks rather than duplicating domain checks inside `devtools verify`.
-## Beads execution sets
+## Beads graph checks
-Treat the Beads population as four distinct, derived sets. Full ambition is every open or in-progress Bead. The active set is the explicitly admitted non-epic work with `metadata.frontier=active`. Execution focus is the ready, unclaimed subset of admitted active leaves that the report can schedule after existing claims, direct blocking leverage, footprint conflicts, and its declared schema/live-state resource policy. Dependency-ready means that `bd ready` currently reports no unmet hard dependency; it does not imply that the item belongs in the active set or is safe to run alongside another lane.
-
-Use the complete structured surfaces, never an output page, to make that distinction:
+Use `bd ready` to inspect executable work and `workspace bead-cluster` before
+parallel dispatch. Validate branch-local dependency records without importing
+an aging worktree into the shared Beads database:
```bash
-devtools workspace frontier --json
-devtools lab policy bead-graph --json
-devtools lab policy backlog-hygiene --json
+devtools lab policy bead-graph --export .beads/issues.jsonl --json
```
-`workspace frontier --json` emits the complete auditable full-ambition set plus every selected and deferred execution-focus candidate, the occupied claims, and the policy that caused each deferral. It never changes claims or admission metadata. `lab policy bead-graph --json` stays fail-closed for empty `acceptance_criteria`, validates parent-child integrity from dependency records, and includes every missing-AC ID with deterministic partitions by status, priority, program-or-parent, and declared campaign relevance. `backlog-hygiene --json` remains the bounded exported-snapshot structure gate for the active-set metadata itself.
-
## Command Catalog
@@ -59,41 +55,29 @@ They are not a proof ledger or end-user archive workflow.
| Command | Role |
| --- | --- |
-| `devtools lab graph` | Inspect the authored runtime graph and see which scenarios currently cover declared artifacts and operations. |
-| `devtools lab lanes` | List, dry-run, or execute authored validation lanes from the executable lane registry. |
-| `devtools lab policy backlog-hygiene` | Enforce the standing backlog-hygiene invariant lint (polylogue-8jg9.1): 20 checks over the Beads export catching dangling dependency refs, blocks-cycles, missing horizon/AC/design content on tech-tree beads, P0/P1 beads without acceptance criteria, unlabeled non-epic beads, epics with no members or description, stale 'adopted' decisions left open, duplicate titles, bead ids named but never created, an unclean/corrupt bd JSONL sync receipt (S1, consuming polylogue-gxjh.1's monotonic sync contract), an active leaf that is itself an epic (F1), an active leaf with a missing/dangling/mismatched program ref (F2), a stale in_progress claim with no recent activity (F3, configurable window), and a frontier_program=active program with no admitted active leaves (F4) -- catches backlog structure drift before it needs an archaeology sweep to recover, instead of only a manually-invoked script. Also reports a non-blocking active-set size diagnostic (soft target/warn bands, never a hard cap or failure). |
-| `devtools lab policy bead-graph` | Run right before shipping a bead-state delta (matches the sinex bead-graph-lint convention). Checks LIVE `bd dep cycles` / `bd list --all --json` output rather than the exported .beads/issues.jsonl snapshot, so it catches drift not yet re-exported. It fails closed for real missing acceptance criteria and validates zero-or-one structured parent-child parents. `--json` emits the complete deterministic missing-AC census, never a display page. INTENTIONAL DIVERGENCE from sinex: only duplicate `wave:` labels are flagged (polylogue's `lane:`/`delivery:`/`horizon:` taxonomy is local and not enforced here). |
-| `devtools lab policy acceptance-contracts` | Run the source-digest-bound acceptance-contract gate before shipping Beads state. It validates typed contract fields, rendered criteria equality, planner-review dispatch markers, safety and receipt clauses, and the committed 218-Bead manifest. |
-| `devtools lab policy acceptance-contract-reconcile` | Run this file-level dry run before a coordinator applies acceptance contracts. It reports authority differences, refuses source-digest mismatches, and emits a targeted wave made from live rows with only acceptance_criteria and metadata.acceptance_contract_v1 changed. It never invokes bd or mutates Dolt. |
-| `devtools lab policy campaign-archive-boundaries` | Catch a regression of the phantom-benchmark.db bug (polylogue-ovme.3): a campaign reintroducing a 'benchmark.db' sentinel, an ad hoc tier-path sibling derivation, or an entry point (generate_archive/run_full_campaign/run_campaign._run) that no longer routes through CampaignArchiveLocation. Scoped to the devtools campaign boundary only -- the broader storage/diagnostics/daemon/maintenance/transitions boundary audit is polylogue-ovme.2's migration surface. |
-| `devtools lab policy demo-packet-registry` | Enforce the 212 portfolio contract (polylogue-212.7): every demo prompt in .agent/demos/registry.json must have a packet directory carrying PROMPT.md, finding.yaml (five-part provenance stanza), report.md (fixed section order), evidence.ndjson, queries.ndjson, checks.json, and run.log. Catches a missing or malformed packet before it silently drops out of the demo shelf. |
-| `devtools lab policy demo-tour-freshness` | Catch drift between what `polylogue demo tour` actually emits at runtime (transcript, report, per-step command output, recording tape) and the committed copies under docs/examples/demo-tour/, modulo an explicit wall-clock-duration mask (polylogue-3tl.17). Runs the real tour (~10s), so it lives in the lab tier rather than --quick. |
-| `devtools lab policy docs-drift` | Catch doc-vs-code drift in the hand-maintained Reference-docs table (CLAUDE.md): a backtick-quoted file path that no longer exists, a ' schema version N' claim ahead of the tier's current constant, or a watchlisted table name renamed to a different current name (e.g. `artifact_observations` renamed to `raw_artifacts`) still asserted as current (polylogue-9e5.13). |
-| `devtools lab policy insight-honesty` | Enforce that polylogue.insights.registry.INSIGHT_REGISTRY and polylogue.insights.rigor's contract matrix/exemption list never drift apart (9e5.28) -- a registered product with neither a RigorContract nor a RIGOR_EXEMPT entry used to silently vanish from `polylogue ops insights audit` instead of showing as uncovered. |
+| `devtools lab provider completeness` | Inspect detector, parser, fixture, schema, docs, ImportExplain, and caveat coverage before claiming a provider/importer mode is product-ready. |
+| `devtools lab graph` | Inspect declared runtime artifacts, operations, paths, and maintenance targets. |
+| `devtools lab testmon-proof` | Validate the affected-test harness itself: a disposable copy of a real Polylogue module and existing route test is seeded, semantically mutated, edge-severed, restored, and checked for bounded unrelated-change selection. |
+| `devtools lab snapshot read-surface` | Freeze archive read-surface behavior before archive work, then compare candidate archives against the captured envelope baseline. |
| `devtools lab policy schema-versioning` | Enforce the policy boundary documented in docs/internals.md § 'Schema Versioning Model'. Durable tiers use explicit additive migrations with a backup gate; derived tiers are rebuilt or blue-green replaced from source evidence. |
+| `devtools lab policy bead-graph` | Run before shipping a bead-state delta. With no source option it checks live `bd` state; `--export .beads/issues.jsonl` validates the branch snapshot without importing it into the shared database. The gate reads dependency records only and does not make prose, labels, or campaign-specific edge lists machine authority. |
| `devtools lab policy timestamp-doctrine` | Enforce the time doctrine (UTC epoch-ms canon, docs/internals.md) at DDL-review time (cpf.1): a TEXT timestamp in source.db/user.db re-introduces tz-unknown ambiguity and lexicographic-vs-temporal sort divergence, and durable tiers need an explicit additive migration to fix later -- catching it before merge is orders cheaper than a copy-forward migration after. |
-| `devtools lab provider completeness` | Inspect detector, parser, fixture, schema, docs, ImportExplain, and caveat coverage before claiming a provider/importer mode is product-ready. |
-| `devtools lab probe capture-regression` | Turn a live or probe failure JSON summary into a replayable local regression artifact. |
+| `devtools lab policy insight-honesty` | Enforce that polylogue.insights.registry.INSIGHT_REGISTRY and polylogue.insights.rigor's contract matrix/exemption list never drift apart (9e5.28) -- a registered product with neither a RigorContract nor a RIGOR_EXEMPT entry used to silently vanish from `polylogue ops insights audit` instead of showing as uncovered. |
| `devtools lab probe cost-reconciliation` | Validate archive token accounting against optional local Codex state_5.sqlite and Claude stats-cache.json before publishing cost or usage-analysis claims. |
| `devtools lab probe pipeline` | Run real pipeline stages and optionally capture emitted summaries as regression cases. |
| `devtools lab probe turso` | Collect executable evidence before changing production storage backends: Python binding availability, generated-column support, FTS compatibility, MVCC, CDC, vector functions, ATTACH, and WAL pragma behavior. |
-| `devtools lab projections` | Inspect the unified projection inventory that feeds runtime coverage, generated docs, and control-plane maps. |
| `devtools lab run` | Run a scenario such as rebuild-safety through the direct lab command path. |
| `devtools lab smoke` | Run direct archive and reader smoke sets outside the archive CLI. |
-| `devtools lab schema audit` | Check committed schema package quality gates without presenting them as normal archive usage. |
-| `devtools lab schema commit` | Actually regenerate and write `polylogue/schemas/providers//versions/...` from the live archive -- 'lab schema generate' only ever previews and never writes committed package files. |
+| `devtools lab schema list` | Inspect committed provider schema package catalogs without presenting them as normal archive usage. |
| `devtools lab schema compare` | Review schema package drift between committed versions in the lab surface. |
| `devtools lab schema explain` | Inspect schema package annotations, semantic roles, and review evidence from the lab surface. |
| `devtools lab schema generate` | Refresh provider schema package artifacts from archive observations outside the archive CLI. |
-| `devtools lab schema list` | Inspect committed provider schema package catalogs without presenting them as normal archive usage. |
-| `devtools lab schema parser-diff` | Scope a parser batch by evidence before a rebuild: ranks every schema key nothing reads by how many records actually carry it. Output is a triage queue, not a verdict -- parser-side matching is name-based, so read the parser before acting on a row. |
+| `devtools lab schema commit` | Actually regenerate and write `polylogue/schemas/providers//versions/...` from the live archive -- 'lab schema generate' only ever previews and never writes committed package files. |
| `devtools lab schema promote` | Turn reviewed schema evidence clusters into committed provider schema packages. |
+| `devtools lab schema audit` | Check committed schema package quality gates without presenting them as normal archive usage. |
+| `devtools lab schema parser-diff` | Scope a parser batch by evidence before a rebuild: ranks every schema key nothing reads by how many records actually carry it. Output is a triage queue, not a verdict -- parser-side matching is name-based, so read the parser before acting on a row. |
| `devtools lab schema roundtrip` | Close the schema inference-validation loop: package manifests must roundtrip through typed models, and every supported element schema must be reachable from the runtime registry. |
-| `devtools lab seed-receipt-compare` | Judge a seed-testmon or focused pytest run's resource receipt against a named baseline receipt (e.g. a prior incident) — confirms both runs share workload identity and terminated cleanly, then scores wall-time speedup and peak-PSS ceiling targets, naming a blocker and linked follow-up for any unmet target instead of silently dropping it. |
-| `devtools lab snapshot read-surface` | Freeze archive read-surface behavior before archive work, then compare candidate archives against the captured envelope baseline. |
-| `devtools lab test-economics` | Decide where test-writing effort or test-suite pruning actually pays off, by cross-referencing coverage percent, historical fix-commit density, testmon wall-time cost exposure, and testmon selection fan-out per top-level package. |
-| `devtools lab testmon-blind-spots` | Inspect an existing coverage JSON report against an existing pytest-testmon database. Declaration-only modules are reported separately from executable validator risk; this command does not run pytest or regenerate coverage. |
-| `devtools lab testmon-proof` | Validate the affected-test harness itself: a disposable copy of a real Polylogue module and existing route test is seeded, semantically mutated, edge-severed, restored, and checked for bounded unrelated-change selection. |
+| `devtools lab probe capture-regression` | Turn a live or probe failure JSON summary into a replayable local regression artifact. |
## Core Loop
@@ -109,36 +93,6 @@ These are the commands worth remembering during normal repo work:
Common forms: `devtools test tests/unit/pipeline`, `devtools test -k hybrid`, `devtools test tests/unit/storage -x`.
- `devtools bench mutation`: Run or inspect focused mutation-testing work without shrinking the committed mutmut scope.
Common forms: `devtools bench mutation list`, `devtools bench mutation run filters`.
-- `devtools bench campaign`: Record durable benchmark artifacts or compare a candidate run against a baseline artifact.
- Common forms: `devtools bench campaign list`, `devtools bench campaign run search-filters`, `devtools bench campaign compare baseline.json candidate.json`.
-
-## Workspace disposition audit
-
-The utf.1 triage retains workspace commands with operator history, reusable output, or focused tests. The stale archive-schema-fast-forward name is removed in favor of the registered index fast-forward command.
-
-| Named entry | Disposition | Evidence | Replacement |
-| --- | --- | --- | --- |
-| `devtools workspace index-fast-forward` | `retain` | Recent production commits plus focused devtools/storage tests; emits a reusable proof receipt. | Keep the registered command as the index-tier actuator. |
-| `workspace archive-schema-fast-forward` | `remove` | No current CommandSpec, implementation module, focused test, or history entry exists for this name. | Use workspace index-fast-forward for declared derived-index fast-forwards. |
-| `devtools workspace degraded-archive-proof` | `retain` | Focused tests and deterministic self-healing proof artifacts cover the command. | Keep the registered command for archive repair evidence. |
-| `devtools workspace frontier` | `retain` | Operator-facing frontier report with documented workflow use and structured report output. | Keep the registered command for frontier batching and wait-ahead decisions. |
-| `devtools workspace temporal-read-profile` | `retain` | Focused tests cover the report and JSON timing output is reusable for read tuning. | Keep the registered command as the temporal read profiling entrypoint. |
-| `devtools workspace temporal-devloop` | `retain` | Focused tests cover structured and Markdown event sources; output is a reusable evidence window. | Keep the registered command as the devloop temporal evidence entrypoint. |
-| `devtools workspace temporal-archive-aggregates` | `retain` | Focused tests cover aggregate report construction and reusable archive artifacts. | Keep the registered command as the run-projection aggregate entrypoint. |
-| `devtools workspace lineage-validation` | `retain` | Focused tests cover lineage evidence and the command emits reusable count and composition proof. | Keep the registered command before publishing archive cardinality claims. |
-| `devtools workspace cli-surface-audit` | `retain` | Focused tests cover bounded output and stale-artifact pruning; the audit shelf is reusable. | Keep the registered command as the current CLI surface audit entrypoint. |
-| `devtools demo real-slice-screen` | `retain` | Focused privacy-screening tests cover redaction, PII review, and report generation. | Keep the registered command as the read-only real-archive screening entrypoint. |
-
-Catalog bypass audit sites are machine-checked across workflow runs, CI-owned npm scripts, hooks, and devtools process launches. Direct hook adapters require declared sanctioned exceptions with an exact occurrence and cardinality.
-
-| Site | Status | Registered command | Occurrence | Reason |
-| --- | --- | --- | --- | --- |
-| `.github/workflows/mutation-testing.yml` | `registered` | `devtools verify mutation-freshness` | not applicable | CI invokes the catalog command so inventory and workflow validation see the freshness gate. |
-| `.github/workflows/nightly-scale.yml` | `registered` | `devtools bench nightly-compare` | not applicable | CI invokes the catalog command so the nightly comparison is discoverable and checked. |
-| `devtools/pre_push_gate.py` | `registered` | `devtools lab policy backlog-hygiene` | not applicable | The intentional Beads-only route remains narrow while using the registered policy command. |
-| `docs/test-economics.md` | `sanctioned-bypass` | `devtools lab test-economics` | not applicable | The generated provenance header preserves the module that emitted the document; operators use the catalog command. |
-| `.githooks/pre-push` | `sanctioned-bypass` | `hook adapter` | line 21 (1 expected) | The hook adapter must receive Git's staged stdin update stream before dispatching its catalog-aware gate. |
-| `.beads-hooks/pre-push` | `sanctioned-bypass` | `hook adapter` | line 21 (1 expected) | The Beads-augmented hook retains the same stdin adapter before its managed Beads section runs. |
### Core
@@ -152,19 +106,12 @@ Catalog bypass audit sites are machine-checked across workflow runs, CI-owned np
| --- | --- |
| `devtools render agent-manual` | Render the declaration-generated six-tool agent manual and packaged integration assets. |
| `devtools render all` | Refresh or verify generated docs and agent files. |
-| `devtools render api-operation-parity` | Render the committed semantic-operation parity matrix and Python facade reference. |
| `devtools render cli-output-schemas` | Render JSON Schema artifacts for stable CLI output payloads under docs/schemas/cli-output/. |
| `devtools render cli-reference` | Render docs/cli-reference.md from live CLI help. |
-| `devtools render demo-corpus-datasheet` | Render docs/plans/demo-corpus-construct-audit.md from the demo family registry and a measured seed archive. |
| `devtools render devtools-reference` | Render the command catalog inside docs/devtools.md. |
| `devtools render docs-surface` | Render docs/README.md and the README documentation table. |
-| `devtools render mcp-equivalence` | Render docs/generated/mcp-equivalence.json from executable MCP declarations. |
-| `devtools render mcp-tool-index` | Render the generated exhaustive tool-name appendix into docs/mcp-reference.md. |
| `devtools render openapi` | Render docs/openapi/search.yaml from typed daemon query payload models. |
| `devtools render pages` | Build the GitHub Pages documentation site into .cache/site/. |
-| `devtools render product-workflows` | Render docs/product/workflows.md from executable query-action workflow registries. |
-| `devtools render public-claims` | Render README, launch, findings-page, and verified-export claim views from FINDING assertions. |
-| `devtools render quality-reference` | Render docs/test-quality-workflows.md from executable lane, mutation, and benchmark registries. |
| `devtools render query-discovery` | Render parser-gated query discovery examples and result semantics into docs/search.md. |
| `devtools render visual-tapes` | Write VHS tape files and optionally capture GIFs for the default visual evidence specs. |
| `devtools render webui-client` | Render the committed WebUI TypeScript client from docs/openapi/search.yaml. |
@@ -175,39 +122,22 @@ Catalog bypass audit sites are machine-checked across workflow runs, CI-owned np
| Command | Description |
| --- | --- |
| `devtools release build-package` | Build the default Nix package with the out-link under .local/result. |
-| `devtools release readiness` | Validate the externally-presentable release gate definition. |
| `devtools release verify-distribution` | Verify wheel/sdist installed artifacts expose only supported runtime entrypoints. |
### Lab Checks
| Command | Description |
| --- | --- |
-| `devtools lab graph` | Render the runtime artifact, operation, and scenario-coverage map. |
-| `devtools lab lanes` | Run named validation lanes. |
-| `devtools lab policy acceptance-contract-apply` | Apply an exact acceptance wave to a guarded JSONL file copy. |
-| `devtools lab policy acceptance-contract-reconcile` | Reconcile canonical acceptance contracts with a read-only live Beads export. |
-| `devtools lab policy acceptance-contracts` | Validate structured Beads acceptance contracts and the committed contract manifest. |
-| `devtools lab policy backlog-hygiene` | Verify Beads backlog structure invariants (.beads/issues.jsonl). |
-| `devtools lab policy bead-graph` | Bead-graph invariant lint and complete missing-AC census over live `bd` state. |
-| `devtools lab policy campaign-archive-boundaries` | Verify devtools synthetic benchmark/scale campaigns route through ArchiveLocation. |
-| `devtools lab policy classifier-fingerprints` | Verify parser/classifier decision-boundary changes are declared as reparse-requiring or acknowledged. |
-| `devtools lab policy demo-packet-registry` | Verify every registered 212 demo has a conforming Demo Finding Packet. |
-| `devtools lab policy demo-tour-freshness` | Verify a freshly-run demo tour matches the committed docs/examples/demo-tour/ evidence artifacts. |
-| `devtools lab policy docs-drift` | Verify checkable factual claims in the Reference-docs table against current source. |
+| `devtools lab graph` | Render the runtime artifact and operation graph. |
+| `devtools lab policy bead-graph` | Validate typed dependency endpoints, uniqueness, parent cardinality, and cycles in the Beads graph. |
| `devtools lab policy insight-honesty` | Verify every registered insight product is rigor-contracted or exempt. |
-| `devtools lab policy position-derived-identity` | Verify no parser mints cross-revision comparison identity from positional/index data. |
-| `devtools lab policy raw-authority-frontier-executability` | Verify every raw-authority frontier state has a reachable actuator. |
-| `devtools lab policy raw-payload-hash-purity` | Verify no raw-capture write path splices a synthesized literal onto captured bytes before hashing. |
| `devtools lab policy schema-versioning` | Verify durable-tier migration and derived-tier rebuild boundaries. |
-| `devtools lab policy table-exists-duplication` | Verify no module outside storage/introspection.py redefines table_exists/column_exists/index_exists. |
| `devtools lab policy timestamp-doctrine` | Verify durable-tier DDL never stores a timestamp column as TEXT. |
| `devtools lab probe capture-regression` | Capture pipeline-probe summaries as durable local regression cases. |
| `devtools lab probe cost-reconciliation` | Reconcile Polylogue token accounting against private provider stores. |
| `devtools lab probe pipeline` | Run typed pipeline probes against synthetic, staged, or archive-subset inputs. |
| `devtools lab probe turso` | Probe Turso Database compatibility against Polylogue storage assumptions. |
-| `devtools lab projections` | Render the authored scenario-bearing verification projections. |
| `devtools lab provider completeness` | Report provider/importer package completeness by origin and capture mode. |
-| `devtools lab pytest-witness-repetitions` | Repeat the exact optimize, WAL, and embedding seed-hang witnesses with durable receipts. |
| `devtools lab run` | Run a named archive verification scenario. |
| `devtools lab schema audit` | Run committed provider schema package quality checks. |
| `devtools lab schema commit` | Persist a real full-corpus schema generation into committed provider packages. |
@@ -218,49 +148,34 @@ Catalog bypass audit sites are machine-checked across workflow runs, CI-owned np
| `devtools lab schema parser-diff` | List observed provider wire keys that no parser references. |
| `devtools lab schema promote` | Promote a schema evidence cluster into a registered package version. |
| `devtools lab schema roundtrip` | Verify committed provider schema packages reload and roundtrip cleanly. |
-| `devtools lab seed-receipt-compare` | Compare two workload receipts for a clean, like-for-like seed/incident proof (polylogue-b054.1.1.3). |
| `devtools lab smoke` | Run direct archive and reader smoke sets. |
| `devtools lab snapshot read-surface` | Capture and compare archive read-surface snapshots. |
-| `devtools lab test-economics` | Report per-package coverage/fix-density/test-cost economics (polylogue-9e5.11). |
-| `devtools lab testmon-blind-spots` | Audit coverage-known files that are absent from the testmon fingerprint graph. |
| `devtools lab testmon-proof` | Prove real testmon affected selection against a semantic production mutation. |
### Verification
| Command | Description |
| --- | --- |
-| `devtools reindex-canary` | Run the product's representative inactive-generation reindex canary. |
| `devtools test` | Run a focused pytest selection through the managed harness. |
| `devtools verify` | Run the local verification baseline before pushing or creating a PR. |
| `devtools verify agent-integration` | Verify manual compilation, parser examples, continuation, native delivery, packaging, and live cutover signatures. |
-| `devtools verify catalog-bypasses` | Reject direct devtools module or script execution outside sanctioned adapters. |
-| `devtools verify ci-workflows` | Verify CI workflow files reference locally-known devtools commands and existing paths. |
-| `devtools verify closure-matrix` | Verify docs/plans/test-closure-matrix.yaml stays grounded in the realized tree. |
+| `devtools verify ci-commands` | Validate devtools invocations in structured CI run fields. |
| `devtools verify corpus-fidelity` | Run the production corpus-fidelity acceptance gate against an archive root. |
| `devtools verify coverage` | Run pytest with the repository coverage floor from pyproject.toml. |
-| `devtools verify degrade-loudly` | Verify broad except-handlers in daemon/storage/insights/coordination log or signal on failure. |
-| `devtools verify doc-commands` | Verify README/docs command examples resolve to live polylogue, polylogued, and devtools commands. |
-| `devtools verify docs-coverage` | Verify every public CLI command, MCP tool, config key, and stable daemon route is named in the docs tree. |
-| `devtools verify evidence` | Render the pytest-first evidence dashboard. |
+| `devtools verify doc-commands` | Validate executable documentation examples against live command inventories. |
| `devtools verify layering` | Check inter-package imports against declared layering rules from docs/plans/layering.yaml. |
-| `devtools verify manifests` | Verify internal consistency across all docs/plans/*.yaml manifest files. |
-| `devtools verify mutation-freshness` | Verify fresh mutation campaigns meet their declared kill-rate thresholds. |
-| `devtools verify public-claims` | Verify generated public-claim views, preset parity, sanitized refs, coverage markers, and retired copy. |
-| `devtools verify pytest-timeout-overrides` | Verify explicit pytest timeout overrides are positive, bounded, and justified. |
+| `devtools verify mutation-freshness` | Verify executable mutation campaigns meet the selected freshness and kill-rate thresholds. |
| `devtools verify schema-inference-gate` | Run the read-only schema-inference prerequisite and persist a PASS/FAIL receipt. |
-| `devtools verify test-infra-currency` | Verify tests/infra/ helpers reference only tables that exist in the current SCHEMA_VERSION. |
### Benchmarking
| Command | Description |
| --- | --- |
-| `devtools bench campaign` | Run or compare benchmark campaigns. |
-| `devtools bench coordination-latency` | Measure compact coordination status p50/p95 with raw stage samples. |
| `devtools bench help-latency` | Check `--help` wall-clock latency against the interactive-tier cold-CLI budget (polylogue-20d.2). |
| `devtools bench ingest-amplification` | Measure deterministic per-tier ingest write amplification on a synthetic fixture (#1851). |
| `devtools bench ingest-throughput` | Measure ingest wall-clock throughput on a synthetic fixture. |
| `devtools bench memory` | Measure query-memory envelopes on generated fixtures. |
-| `devtools bench mutation` | Run focused mutation campaigns and maintain their local index. |
+| `devtools bench mutation` | Run focused mutation campaigns with isolated execution and JSON artifacts. |
| `devtools bench nightly-compare` | Compare nightly pytest-benchmark output with the committed baseline. |
| `devtools bench slo` | Check read-surface latency budgets in docs/plans/slo-catalog.yaml against benchmark measurements. |
| `devtools bench synthetic` | Run synthetic benchmark campaigns over generated archives. |
@@ -277,31 +192,21 @@ Catalog bypass audit sites are machine-checked across workflow runs, CI-owned np
| `devtools workspace antigravity-phantom-sweep` | List antigravity-session rows that are brain-metadata phantom fragments. |
| `devtools workspace attachment-reacquisition` | Classify historically-unfetched attachments for a source-backed backfill. |
| `devtools workspace attachment-reacquisition-apply` | Backfill acquisition for historically-unfetched attachments. |
-| `devtools workspace backlog-calibration` | Measured lead-time/discovery/staleness distributions over the bead corpus. |
-| `devtools workspace bead-batch-show` | Batch-show beads: id, status, prio, title, desc head, deps, notes tail. |
| `devtools workspace bead-cluster` | Footprint/overlap/contention clustering of ready Beads (execution frontier). |
| `devtools workspace bead-reimport-guard` | Monotonic, receipted guard/reconcile/export for bd's JSONL synchronization. |
-| `devtools workspace beads-state-report` | Self-contained HTML state-of-the-backlog report over the whole bead population. |
| `devtools workspace binary-artifact-reclassify-apply` | Persist raw_artifacts classification for binary-shaped raw rows. |
| `devtools workspace binary-artifact-sweep` | Find raw_sessions rows whose bytes are a non-session binary format (SQLite, etc). |
-| `devtools workspace chatgpt-lifecycle-anchor-audit` | Census the current quarantined ChatGPT corpus for lifecycle-anchor conflicts. |
-| `devtools workspace claim-vs-evidence` | Build a structured failure follow-up claim-vs-evidence demo. |
-| `devtools workspace cli-surface-audit` | Capture a current-curated CLI surface audit demo. |
+| `devtools workspace claim-vs-evidence` | Analyze structured failures and the assistant behavior that followed. |
+| `devtools workspace continuity-evidence` | Replay continuity scenarios and verify their query routes are discoverable. |
| `devtools workspace degraded-archive-proof` | Build a degraded archive self-healing proof artifact. |
-| `devtools workspace delivery-gate-status` | Per-release-gate progress board over .beads/issues.jsonl (delivery: / lane: overlay). |
-| `devtools workspace demo-shelf` | Refresh or verify current demo shelf indexes. |
| `devtools workspace deployment-smoke` | Probe deployed Polylogue binaries, daemon/web routes, and browser-capture archive flow. |
| `devtools workspace dev-loop` | Preflight branch-local daemon, web-shell, and browser-capture development loops. |
| `devtools workspace failure-context` | Join testmon, git history, and fixtures for a pytest failure ID into a JSON envelope. |
-| `devtools workspace frontier` | Derive a complete, non-mutating execution focus from live Beads state. |
| `devtools workspace index-fast-forward` | Plan and prove a declared index fast-forward against retained raw replay. |
-| `devtools workspace lane-brief` | Generate a dispatch brief for a bead lane with live footprint/prior-art evidence. |
| `devtools workspace lane-init` | Provision a fanout lane worktree: branch, isolated venv, guard check, ledger record. |
| `devtools workspace lineage-validation` | Validate lineage-count evidence before citing archive counts externally. |
-| `devtools workspace mandate-continuity-replay` | Wire t8t continuity scenarios + work-evidence effects + discovery into one mandate artifact. |
| `devtools workspace merge` | Merge boundary wrapper: refuses `gh pr merge` without a fresh merge-gate receipt. |
-| `devtools workspace merge-conductor` | Mechanical-conflict triage for the PR merge train (dry-run by default). |
-| `devtools workspace merge-gate` | Structural pre-merge safety check: fresh local-verification receipt + no late review comments. |
+| `devtools workspace merge-gate` | Structural pre-merge safety check: fresh local verification + resolved review threads. |
| `devtools workspace pr-scope` | Render stable PR scope intent and inspect its mutable merge attestation. |
| `devtools workspace raw-append-chain-backfill-apply` | Promote membershipless append raws proven correct by live-source verification. |
| `devtools workspace raw-authority-artifact-census` | Census quarantined raws into five authority buckets; apply pages raw_artifacts upserts and records durable receipts. |
@@ -316,9 +221,7 @@ Catalog bypass audit sites are machine-checked across workflow runs, CI-owned np
| `devtools workspace raw-quarantine-group-dedup-apply` | Promote one representative raw per fully-quarantined byte-identical (source_path, blob_hash) group. |
| `devtools workspace read-package` | Render a declarative package of Polylogue read artifacts. |
| `devtools workspace scale-regression` | Run the seeded large-archive scale-regression probe. |
-| `devtools workspace tasks` | Record and query local agent task execution history. |
| `devtools workspace temporal-archive-aggregates` | Build run-projection aggregate artifacts from the active archive. |
-| `devtools workspace temporal-devloop` | Compose git and operating-log events into a temporal evidence window. |
| `devtools workspace temporal-read-profile` | Measure read --view temporal phase timings on the active archive. |
| `devtools workspace tool-result-history-reclassify-apply` | Persist raw_artifacts classification for tool-result/file-history-shaped raw rows. |
| `devtools workspace tool-result-history-sweep` | Find claude-code-session raw rows that should reclassify as tool-result/file-history sidecars. |
@@ -366,8 +269,8 @@ polylogue ops maintenance cursor-authority-reconcile --apply \
When changing semantics, validation, or surfaces:
```bash
-devtools lab lanes --list
-devtools lab lanes --lane frontier-local
+devtools verify
+devtools test tests/unit/path/to/test_file.py
devtools lab smoke run archive-smoke --tier 0
devtools lab smoke run reader-visual-smoke
devtools bench memory --max-rss-mb 1536 -- polylogue --plain analyze
diff --git a/docs/evidence/polylogue-0x7nh-reindex-canary-differ-implementation-2026-08-09.md b/docs/evidence/polylogue-0x7nh-reindex-canary-differ-implementation-2026-08-09.md
deleted file mode 100644
index 552a1e037d..0000000000
--- a/docs/evidence/polylogue-0x7nh-reindex-canary-differ-implementation-2026-08-09.md
+++ /dev/null
@@ -1,105 +0,0 @@
-# Polylogue 0x7nh reindex canary differ implementation packet
-
-Date: 2026-08-09
-
-Branch: `feature/maintenance/reindex-canary-differ-roundout`
-
-Status: implementation complete. The first production canary report and the
-reviewed zero-unclassified-diff receipt remain open under `polylogue-0x7nh`.
-The Bead is not closed by this packet.
-
-## Scope and disposition
-
-This lane owns the implementation-grade slice of the reindex canary differ.
-It does not claim the first live report, production source remediation, or
-manual review of that report. No live canary was run and no production archive
-was mutated.
-
-| Acceptance area | Disposition | Evidence |
-| --- | --- | --- |
-| Daemon-owned, inactive, no-promote replay | Satisfied | `run_daemon_canary_rebuild` submits the rebuild through `daemon_write_coordinator` with `promote=False`; the runner does not call the rebuild primitive directly. |
-| Representative selection | Satisfied | Existing origin quotas are retained and explicit pathology plus live-anchor selections are carried through the selection receipt. |
-| One canonical comparator | Satisfied | The production `compare_reindex_generations` route remains the comparison authority; no second row-difference vocabulary was introduced. |
-| Evidence binding | Satisfied | Reports bind source root, current index, candidate index, selected raw/session IDs, replay closure, parser fingerprints, lowering fingerprint, and rebuild receipt. |
-| Row coverage | Satisfied | Canonical relation discovery covers sessions, messages, blocks, `session_links`, and derived rows, with direct lineage coverage in tests. |
-| Fail-closed classification | Satisfied | Durable reports require exact review coverage. Expected rows require a structured `bead:` or `delta:` authority; unexpected rows require a structured `successor:` authority. |
-| First production zero-diff review | Open | Requires the first post-remediation production report and human review. No receipt was fabricated. |
-
-## Historical transplant and supersession proof
-
-Historical commit `1f334acee1c0e8c07addb9e6998c70805cf4caa1` is not an ancestor
-of the fresh-master base. The ancestry check returned exit status 1. Its old
-`polylogue/maintenance/reindex_canary.py` and unit test were not copied
-blindly.
-
-The capability was already substantially superseded on master by the current
-canary route and its hardening sequence:
-
-- `1ac438c1a` added the maintenance canary gate.
-- `e1da54320` refused live-archive canary rebuilds.
-- `0b943aaa4` rejected invalid candidates before insights.
-- `3822bc771` separated canary replay evidence from durable state.
-- `64edbf518` closed provenance-boundary gaps.
-- `e6228af5c` isolated inactive candidate durable writes.
-
-This branch therefore transplanted only the remaining differ/report contract:
-daemon ownership, parser and source binding, structured classification, and
-real-route coverage for the current architecture.
-
-## Implementation commits
-
-- `3ebcfe4d5` `feat: harden daemon-owned reindex canary differ`
-
-The signed commit contains the production route, CLI adaptation, real-route
-fixtures, and anti-vacuity tests.
-
-## Anti-vacuity evidence
-
-- Candidate construction is asserted through the captured inactive candidate
- request and `promote=False`; the real no-promote path also verifies that the
- active index remains unchanged.
-- The active index is not accepted as both comparator inputs; the route and
- active-generation rotation tests preserve distinct current and candidate
- evidence.
-- A `session_links` inheritance mutation produces a `session_links` row diff,
- proving the relation is not omitted from the canonical census.
-- Parser fingerprint mutation and raw membership/logical-key expansion both
- reject changed evidence before comparison or approval.
-- Missing review coverage and invalid authority kinds fail closed; a durable
- report cannot contain an unclassified difference.
-
-## Verification
-
-All focused tests used the managed harness with
-`POLYLOGUE_PYTEST_WORKERS=1`:
-
-```text
-direnv exec . env POLYLOGUE_PYTEST_WORKERS=1 python -m devtools test tests/unit/maintenance/test_reindex_canary.py
-45 passed
-
-direnv exec . env POLYLOGUE_PYTEST_WORKERS=1 python -m devtools test tests/unit/cli/test_reindex_canary_cli.py
-30 passed
-
-direnv exec . python -m devtools render all --check
-exit 0; generated surfaces sync OK
-
-direnv exec . env POLYLOGUE_PYTEST_WORKERS=1 python -m devtools verify --quick
-exit 0; format, lint, mypy, render, layering, and policy checks passed
-```
-
-`git diff --check` passed. The acceptance-contract policy command also reports
-an inherited failure for `polylogue-7rds`: `source_digest does not match the
-Bead source snapshot`. This lane did not invoke `bd`, edit `.beads`, or change
-that Bead state.
-
-The full suite and `--seed-testmon` were not run. No production or live canary
-was run.
-
-## Publication boundary
-
-This is a clean signed branch and a non-draft publication packet. It is ready
-for publication when the coordinator's frontier permits a slot. Do not close
-`polylogue-0x7nh` from this packet: the implementation is complete, but the
-first production canary report and reviewed zero-unclassified-diff receipt
-remain an explicit live gate under that Bead. No named successor in the frozen
-Bead record owns that residual work.
diff --git a/docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json b/docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json
deleted file mode 100644
index ecfa0d281e..0000000000
--- a/docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json
+++ /dev/null
@@ -1 +0,0 @@
-{"anti_vacuity":{"indexed_authority":"byte_proven_source_raw_and_revision_head","indexed_session_count":1,"indexed_session_count_before":0,"typed_terminal_artifact":"terminal_corrupt_input","unchanged_excluded_attempt_present":false},"cases":[{"attempt":{"evidence_ref":null,"outcome_code":"success","retryable":false,"status":"completed"},"attempt_present":true,"case_id":"indexed","fingerprint_changed_before_catch_up":true,"indexed":{"indexed_sessions":1,"parsed_raw":2},"indexed_before":{"indexed_sessions":0,"parsed_raw":1},"metrics":{"failed_file_count":0,"full_file_count":1,"succeeded_file_count":1},"proof_attempt_count":1,"retry_state":{"excluded":false,"failed_with_retry":false,"failure_count":0,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"fbe00b1bf4fe9b647b143e5f002a8edfd9d3685944fa44125586a679c4cc6534","terminal_evidence":null},{"attempt":null,"attempt_present":false,"case_id":"still-excluded","fingerprint_changed_before_catch_up":false,"indexed":{"indexed_sessions":0,"parsed_raw":0},"metrics":{"failed_file_count":0,"full_file_count":0,"succeeded_file_count":0},"proof_attempt_count":0,"retry_state":{"excluded":true,"failed_with_retry":false,"failure_count":5,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"cb7b4873a5dc05a7cac589c60a8069dc9f91f234af3076f8ea558bfafe69612a","terminal_evidence":null},{"attempt":{"evidence_ref":null,"outcome_code":"success","retryable":false,"status":"completed"},"attempt_present":true,"case_id":"typed-terminal","fingerprint_changed_before_catch_up":true,"indexed":{"indexed_sessions":0,"parsed_raw":0},"metrics":{"failed_file_count":0,"full_file_count":1,"succeeded_file_count":1},"proof_attempt_count":1,"retry_state":{"excluded":false,"failed_with_retry":false,"failure_count":0,"parser_fingerprint":"live-batched-v2","retry_due":false},"source_content_sha256":"2e5c27f8ae0c2f4176892776a5a0ac5e1d598178676396f86fa4f6d608778d75","terminal_evidence":{"artifact_kind":"terminal_corrupt_input","parse_error_present":true,"support_status":"decode_failed"}}],"execution":{"live_census":"not_run","live_residual":"Historical excluded population and current live file states were not accessed.","mode":"candidate_fixture","residual_successor":"polylogue-excluded-cursor-live-proof","terminal_frontier_residual":"The typed-terminal candidate has no accepted byte head, so its readiness gate was injected for this case only."},"fairness":{"planner":"_interleave_by_source","property":"browser-capture drains first; among non-browser-capture families, one candidate from each present family reaches the first round"},"fixture_version":"candidate-codex-live-compatible-2026-08-06","outcomes":{"indexed":true,"still_excluded":true,"typed_terminal":true},"production_route":{"catch_up":"LiveWatcher._catch_up -> _scan_catch_up_candidates -> _catch_up_candidates -> _plan_catch_up -> coordinated chunk ingest","cursor_gate":"LiveWatcher._needs_work","ingest":"LiveWatcher._ingest_files -> LiveBatchProcessor.ingest_files","retry_state":"ops.ingest_cursor and ops.ingest_attempts","terminal_evidence":"source.raw_artifacts","transition":"CursorStore.revive_replaced_exclusion"},"receipt_sha256":"69e75004783fc3f0af38b85ef01136ac8ece609db850b730773b42b56589e350","schema":"polylogue.excluded-cursor-live-proof.v1"}
diff --git a/docs/evidence/polylogue-topology-live-proof-2026-08-06.md b/docs/evidence/polylogue-topology-live-proof-2026-08-06.md
deleted file mode 100644
index d3f5027f03..0000000000
--- a/docs/evidence/polylogue-topology-live-proof-2026-08-06.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# Topology live-proof residue, 2026-08-06
-
-## Scope
-
-This report records the proof surface implemented for `polylogue-topology-live-proof`. The census reuses `devtools workspace lineage-validation` and the production topology write/read seams. The candidate evidence is a frozen test index populated by `write_parsed_session_to_archive`; it is not a claim about the operator's live archive.
-
-## Candidate proof
-
-The candidate fixture contains two resolved links and one unresolved native-parent link, all written through the production writer. The production writer supplies a non-empty method for all three rows. The census derives the ordinary `resolved` and `unresolved` states from `resolved_dst_session_id`, while preserving the nullable raw `status` column contract. The bounded unresolved-parent read sample exercises `read_archive_session_envelope` and proves the child remains child-local: no parent session is composed, and the served message count equals the child-owned count. Each receipt binds the report to the database and any SQLite sidecars by content digest, file identity, a held read transaction, and a second SQLite observer that rejects any concurrent commit between the snapshot read and both file-set hashes. With a fixed capture time, an unchanged source reproduces the receipt, while a source mutation changes its binding.
-
-| Evidence | Result |
-| --- | ---: |
-| effective topology states | `resolved=2`, `unresolved=1` |
-| empty effective states | `0` |
-| empty methods | `0` |
-| raw nullable status values | `3` ordinary NULLs, reported transparently |
-| unresolved-parent reads sampled | `1` |
-| unresolved-parent reads safe | `true` |
-| cycle-quarantine evidence in candidate | `0` |
-| candidate snapshot stable during census | `true` |
-
-The production-route cycle fixture separately proves a `quarantined` closing edge with `cycle_rejected` evidence. Valid evidence must carry a closed cycle path anchored to the quarantined source and asserted parent, with every return hop present in the stored projection. The production writer records walk-budget exhaustion as an indeterminate `cycle_walk_budget_exhausted` quarantine, never as a demonstrated cycle, and preserves the child's full transcript. Its census has `resolved=1`, `quarantined=1`, zero empty effective states, zero empty methods, one valid cycle-evidence row, and zero malformed quarantine-evidence rows. Mutations that blank a method, provide fabricated closed-cycle JSON, exhaust the walk budget, or give a quarantined row a resolved parent each make the census fail, and the reader leaves the contradictory quarantined row uncomposed.
-
-## Live residue
-
-No live archive was opened or mutated in this lane. The live database path is outside the assigned worktree and is excluded by the repository operating boundary. Therefore this report does not claim live zero-empty counts, archive convergence, or a post-reindex status distribution. The remaining named follow-up is `polylogue-live-operation-receipts`: run the read-only census against the approved live or activated candidate index, retain the generated receipt, and compare `effective_status_counts`, `empty_effective_status_count`, `empty_method_count`, `cycle_evidence_count`, and `unresolved_read_sample`.
-
-## Verification
-
-```text
-devtools test tests/unit/devtools/test_lineage_validation.py tests/unit/storage/test_topology_cycle_quarantine_live.py
-```
-
-The tests include mutations that blank a method, introduce an unknown status, make an unresolved child claim a parent in `sessions.parent_session_id`, provide malformed or unrelated cycle evidence, exhaust cycle-walk budget, make a quarantined row resolve a parent, and commit through a second WAL connection between the held reader snapshot and file hashing. Each mutation makes the relevant proof fail. The live receipt step was not run, so the live census remains explicitly not observed.
diff --git a/docs/evidence/polylogue-xeck9-cursor-authority-census-2026-08-04.md b/docs/evidence/polylogue-xeck9-cursor-authority-census-2026-08-04.md
deleted file mode 100644
index 49f32fdab4..0000000000
--- a/docs/evidence/polylogue-xeck9-cursor-authority-census-2026-08-04.md
+++ /dev/null
@@ -1,85 +0,0 @@
-# Cursor authority census, 2026-08-04
-
-## Scope and safety boundary
-
-This report records the read-only production census for `polylogue-xeck9`.
-It intentionally contains no source paths, raw IDs, session IDs, titles, hashes, or payload excerpts. No production database, cursor, raw row, accepted head, blob, or daemon state was changed while collecting it.
-
-The investigation covered only the raw-frontier readiness projection:
-
-```text
-polylogue.storage.raw_retention.raw_frontier_integrity_projection()
- -> raw_frontier_integrity_snapshot(source.db read-only)
- -> _active_index_raw_authority(index.db read-only)
- -> _ops_cursor_byte_offsets(ops.db read-only)
- -> _check_cursor_ahead_of_accepted(...)
-```
-
-Accepted heads remain the comparison authority. The projection joins each accepted head's `accepted_raw_id` to `source.raw_sessions.source_path`, then compares an active `ops.ingest_cursor.byte_offset` with every accepted byte frontier on that path. Semantic heads are intentionally not byte-comparable.
-
-## Census
-
-The direct read-only projection reported:
-
-| Fact | Count |
-| --- | ---: |
-| Active non-excluded cursors with byte offsets | 20,041 |
-| Byte-comparable cursor paths | 16,879 |
-| Cursor/head byte comparisons | 16,881 |
-| True cursor-ahead rows | 1 |
-| True ahead comparisons | 1 |
-| Incomparable cursor/head authority rows | 727 |
-| Semantic-only accepted-head paths, deliberately outside byte comparison | 2,435 |
-
-The one proven violation belongs to an `unknown-export` cursor. Its committed cursor offset is 11,166,810 bytes and its sole accepted byte head is a byte-proven full raw at frontier 11,166,556, a difference of 254 bytes. The head's source and index generations agree at zero. This is a real cursor-ahead condition, not an incomparable state.
-
-The 727 incomparables classify as follows:
-
-| Typed evidence state | Count | Meaning |
-| --- | ---: | --- |
-| `source_raws_without_accepted_head` | 725 | Source-tier raw evidence exists for the cursor path, but no accepted index head is present. |
-| `cursor_path_absent_from_source` | 2 | The active cursor path has no current source-tier raw row. |
-
-The existing status DTO renders these separately from the proven violation: `cursor_ahead_count=1`, `cursor_authority_gap_count=727`, `cursor_ahead_status="violated"`, and `overall_status="violated"`. The reason string reports both populations. Since a violation dominates unknown evidence, incomparability cannot make this result green.
-
-## Root-cause conclusion
-
-No demonstrated defect was found in the cursor write path or comparison predicate on the current branch. The comparison is strict `cursor_offset > accepted_frontier`, consumes the durable accepted head, and its regression coverage already exercises the real `raw_frontier_integrity_snapshot()` route. The production defect was at the readiness consumers: raw convergence and reindex did not consume this proof before selecting source rows. Reclassifying the true violation as incomparable or comparing against a non-accepted raw would contradict the current projection and its existing tests.
-
-The live cursor is ahead of its accepted full-head frontier. That is production reconciliation work, not evidence for a code change. The 725 source-backed incomparables are deferred authority states that must remain visible. The 2 source-absent cursor paths likewise must remain explicit until their durable history is reconciled; this report does not authorize a cursor reset or source-row edit.
-
-## Safe reconciliation contract, not performed
-
-There is no cursor-specific dry-run/apply actuator that can safely repair this condition without re-running the real ingest path. Do not use raw-authority frontier inspection as a cursor repair shortcut: it records census observations, while daemon convergence applies only executable proof-backed plans under its writer coordinator, and neither path reconciles the cursor condition. The safe sequence for an operator is:
-
-1. Stop or confirm quiescence of the daemon, then capture a backup plan and an initial read-only full status receipt:
-
- ```bash
- polylogue ops maintenance backup-plan --output-format json > /realm/tmp/work/polylogue-xeck9-backup-plan.json
- polylogue ops status --json --full > /realm/tmp/work/polylogue-xeck9-before.json
- ```
-
-2. Run the targeted reconciliation through the normal ingest/materialization route for the affected source, with its normal backup gate. The operator must retain the daemon/ingest receipt and the exact source selection externally; this report intentionally does not publish the private path.
-
-3. Capture the post-run status using the same read-only command and compare these fields: `cursor_ahead_count`, `cursor_authority_gap_count`, `cursor_ahead_samples`, `cursor_authority_gap_samples`, and `overall_status`.
-
-4. Accept the run only if the receipt proves the accepted head advanced to cover the cursor, or the cursor did not advance and an explicit retry/deferred state remains. The postcondition must preserve accepted-head authority, leave source rows untouched outside normal ingest, report every remaining incomparable row, and show `cursor_ahead_count=0`. A nonzero incomparable count remains justified only when its typed evidence state is retained in the receipt.
-
-The two read-only commands are intentionally published but were not executed in this lane because the task forbids production mutation and the backup planner exposes archive metadata. The normal ingest/reconciliation action was also not performed.
-
-## Reproduction commands used
-
-```bash
-env PYTHONPATH="$PWD" .venv/bin/python - <<'PY'
-from pathlib import Path
-from polylogue.storage.raw_retention import raw_frontier_integrity_projection
-
-projection = raw_frontier_integrity_projection(
- Path("/home/sinity/.local/share/polylogue"),
- {"available": True, "lost_source_evidence_count": 0, "lost_source_evidence_samples": []},
-)
-print(projection.to_dict())
-PY
-```
-
-The report records only the privacy-safe aggregate and fixed numeric evidence from that output.
diff --git a/docs/examples/README.md b/docs/examples/README.md
index 26d6a02174..f9a256955b 100644
--- a/docs/examples/README.md
+++ b/docs/examples/README.md
@@ -3,8 +3,5 @@
These artifacts are reproducible examples and recorded outputs. Start with
[Demos and Proofs](../demos.md) for the current supported demonstration path.
-- [Demo packet v2](demo-packet-v2/README.md)
-- [Demo tour report](demo-tour/report.md)
-- [UVX installation proof](demo-tour/uvx-proof.md)
- [Visual tape catalog](visual-tapes/README.md)
- [Reader-comprehension test harness](reader-comprehension-test/README.md)
diff --git a/docs/examples/demo-packet-v2/README.md b/docs/examples/demo-packet-v2/README.md
deleted file mode 100644
index e801eee75e..0000000000
--- a/docs/examples/demo-packet-v2/README.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# Demo Packet v2 example
-
-The smallest production-validated example is the registered
-[`_packet-contract-stub`](../../../.agent/demos/_packet-contract-stub/).
-The same validator also covers the public behavioral-archaeology packet and
-the missing-evidence anti-demo; none is grandfathered.
-
-A conforming packet:
-
-1. cites at least one receipt from `claim.receipts`;
-2. declares every cited ref once in the top-level `receipts` table;
-3. binds every receipt to a packet-local artifact with `sha256`;
-4. places the receipt ref in the bound artifact bytes;
-5. uses the exact ordered `## Claim`, `## Corpus`, `## Method`, `## Findings`,
- `## Specimens`, `## Counterexamples`, `## Limits`, `## Non-claims`, and
- `## Reproduce` report headings;
-6. keeps falsifier state consistent and control IDs and measurement names
- unique.
-
-Run the same production gate used by repository verification:
-
-```bash
-devtools lab policy demo-packet-registry
-```
-
-The focused mutation suite removes the claim citation, receipt digest, and
-canonical Claim heading, then introduces contradictory falsifier state and
-duplicate identities. Each case names the production guard whose removal would
-let that invalid packet pass.
diff --git a/docs/examples/demo-tour/command-output/01-claim-versus-receipt.txt b/docs/examples/demo-tour/command-output/01-claim-versus-receipt.txt
deleted file mode 100644
index f2ad4a3156..0000000000
--- a/docs/examples/demo-tour/command-output/01-claim-versus-receipt.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-Polylogue evidence receipt
-archive:
-verdict: contradicted_at_claim_time_then_repaired
-
-assistant claim: All tests pass. The clock fix is complete.
-claim evidence: block:codex-session:demo-receipts:n:receipts-a-claim:0
-
-at claim time:
- tool: shell (exec_command)
- command: pytest tests/test_clock.py -q
- exit: 1 (failed=true)
- result: {"metadata": {"exit_code": 1}, "output": "F tests/test_clock.py::test_uses_monotonic_clock\n1 failed in 0.18s"}
- evidence: block:codex-session:demo-receipts:n:call-receipts-test-fail:0
-
-later recovery:
- tool: shell (exec_command)
- command: pytest tests/test_clock.py -q
- exit: 0 (failed=false)
- result: {"metadata": {"exit_code": 0}, "output": ". 1 passed in 0.16s"}
- evidence: block:codex-session:demo-receipts:n:call-receipts-test-pass:0
-
-anti-grep control:
- prose hits for 'error': 2
- structurally failed actions: 0
- control session: session:codex-session:demo-anti-grep
-
-source material:
- raw_id: d5513a27ef4a35603881e2907ff5e6dff3e0146bf222c36ed5ef032dc58479c2
- blob_sha256: 9fd0dbdb080058070935924534a903cc63a8dcba571f6b2734f92a96576b59d7
-
-completion-claim experiment:
- sample manifest: 014380e82576a22360db0b18c25a984b62fdb057e535aadd1c9b448cf40f2466
- denominator: 2
-unsupported by structural evidence: 0 (0.0%)
-neutral prior outcome: 0 (0.0%)
-contradicted then repaired: 1 (50.0%)
-contradicted without recorded repair: 1 (50.0%)
diff --git a/docs/examples/demo-tour/command-output/02-failed-actions-aggregate.txt b/docs/examples/demo-tour/command-output/02-failed-actions-aggregate.txt
deleted file mode 100644
index 2de9160686..0000000000
--- a/docs/examples/demo-tour/command-output/02-failed-actions-aggregate.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-tool=Bash count=4
-tool=exec_command count=2
-tool=Edit count=1
diff --git a/docs/examples/demo-tour/command-output/03-composed-lineage.txt b/docs/examples/demo-tour/command-output/03-composed-lineage.txt
deleted file mode 100644
index db27303bb4..0000000000
--- a/docs/examples/demo-tour/command-output/03-composed-lineage.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-# Session Chronicle
-
-- Sessions: 1
-- Edge limit: 8
-- Body policy: authored-dialogue
-
-## Map the demo lineage base context.
-
-- Session: `codex-session:demo-lineage-fork`
-- Origin: codex-session
-- Matching prose messages: 4
-- Included: 4
-- Omitted middle messages: 0
-
-### First Messages
-
-### 2026-07-04T10:00:01+00:00 - user / message
-
-Map the demo lineage base context.
-
-`codex-session:demo-lineage-parent:n:parent-u0`
-
-### 2026-07-04T10:00:02+00:00 - assistant / message
-
-I have the base context and can branch the analysis.
-
-`codex-session:demo-lineage-parent:n:parent-a1`
-
-### 2026-07-04T10:01:03+00:00 - user / message
-
-Now take the forked branch and audit construct validity.
-
-`codex-session:demo-lineage-fork:n:fork-u2`
-
-### 2026-07-04T10:01:04+00:00 - assistant / message
-
-The fork diverges into demo corpus construct checks.
-
-`codex-session:demo-lineage-fork:n:fork-a3`
-
-### Last Messages
-
-_No distinct matching prose in the last edge._
diff --git a/docs/examples/demo-tour/command-output/04-archive-facets.txt b/docs/examples/demo-tour/command-output/04-archive-facets.txt
deleted file mode 100644
index 907d5c2aca..0000000000
--- a/docs/examples/demo-tour/command-output/04-archive-facets.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-Facets (global) — matched result set:
- readiness: ready (cost_class=cheap; budget 0.01s/2.00s)
- sessions: 19 messages: 71
- Family states:
- total_counts: Total counts — complete
- origins: Provider origins — complete
- tags: User tags — complete
- repos: Canonical repositories — deferred (deferred_by_default; use --include-deferred); prefer repo_name or origin_url; omit archive/path tokens that are not product repo identities
- role_counts: Provider-role counts — deferred (deferred_by_default; use --include-deferred); provider-reported message role; not authoredness
- material_origins: Material origins — deferred (deferred_by_default; use --include-deferred); authoredness/protocol provenance; separates human text from runtime or assistant material
- message_types: Message content types — deferred (deferred_by_default; use --include-deferred)
- action_types: Action types — deferred (deferred_by_default; use --include-deferred)
- has_flags: Content flags — deferred (deferred_by_default; use --include-deferred)
- Provider origins:
- codex-session: 7
- claude-code-session: 4
- chatgpt-export: 3
- aistudio-drive: 1
- antigravity-session: 1
- claude-ai-export: 1
- gemini-cli-session: 1
- hermes-session: 1
- User tags:
- pytest-triage: 1
- IDF (higher = rarer, partitions more strongly):
- [origins]
- aistudio-drive: 2.944
- antigravity-session: 2.944
- claude-ai-export: 2.944
- gemini-cli-session: 2.944
- hermes-session: 2.944
- chatgpt-export: 1.846
- claude-code-session: 1.558
- codex-session: 0.999
- [tags]
- pytest-triage: 2.944
diff --git a/docs/examples/demo-tour/recording.tape b/docs/examples/demo-tour/recording.tape
deleted file mode 100644
index 01c21fa7d5..0000000000
--- a/docs/examples/demo-tour/recording.tape
+++ /dev/null
@@ -1,15 +0,0 @@
-Output "demo-tour.gif"
-Set FontSize 18
-Set Width 1080
-Set Height 720
-Set Padding 18
-Set TypingSpeed 0.04
-Type "polylogue demo tour --out-dir polylogue-demo-tour"
-Enter
-Sleep 15s
-Type "cat polylogue-demo-tour/transcript.txt"
-Enter
-Sleep 4s
-Type "cat polylogue-demo-tour/report.md"
-Enter
-Sleep 2s
diff --git a/docs/examples/demo-tour/report.json b/docs/examples/demo-tour/report.json
deleted file mode 100644
index d63167c127..0000000000
--- a/docs/examples/demo-tour/report.json
+++ /dev/null
@@ -1,731 +0,0 @@
-{
- "archive_root": "archive",
- "baseline": {
- "name": "command-exit-only smoke test",
- "result": {
- "would_not_verify_planted_constructs": true
- }
- },
- "claim": {
- "declared_before_execution": true,
- "scope": "the generated fixture archive and commands in this report only",
- "statement": "The recorded tour commands complete successfully against the deterministic private-data-free archive.",
- "status": "supported"
- },
- "controls": {
- "missing_evidence": {
- "description": "The report retains verifier problems and does not convert absent overlays or constructs into success.",
- "passed": true
- },
- "negative": {
- "description": "A failed command or failed semantic verifier makes the tour fail.",
- "passed": true
- }
- },
- "demo_packet_contract_version": "2.0.0",
- "falsifier": {
- "condition": "The semantic verifier fails, a public command exits nonzero, or a timing budget is exceeded.",
- "result": "pass",
- "triggered": false
- },
- "first_result_s": 1.362,
- "non_claims": [
- "The deterministic tour does not establish field prevalence, production scale, or provider completeness.",
- "The deterministic tour does not establish memory uplift, invoice accuracy, selective deletion, or the Sinex backend.",
- "The private-archive Receipts benchmark is a separate local-only lane and is not simulated by this fixture."
- ],
- "ok": true,
- "oracle": {
- "description": "The semantic fixture verifier checks planted archive constructs independently of the tour narration.",
- "expected": {
- "command_exit_codes": [
- 0,
- 0,
- 0,
- 0
- ],
- "verify_ok": true
- },
- "independent": true,
- "method": "Run demo verification before the public CLI steps and retain its structured result."
- },
- "output_dir": ".",
- "primary_construct": {
- "id": "demo.public-tour",
- "product_primitives": [
- "demo seed",
- "demo verify",
- "find",
- "read",
- "analyze"
- ],
- "statement": "The deterministic tour exercises public read and analysis paths over a verified fixture archive."
- },
- "problems": [],
- "recording_tape_path": "recording.tape",
- "report_json_path": "report.json",
- "report_markdown_path": "report.md",
- "seed": {
- "archive_root": "archive",
- "assertion_count": 8,
- "construct_coverage": [
- {
- "construct_id": "multi_origin_sessions",
- "label": "Multi-origin sessions",
- "minimum": 3,
- "observed": 8,
- "ok": true
- },
- {
- "construct_id": "session_profiles",
- "label": "Session profiles",
- "minimum": 3,
- "observed": 19,
- "ok": true
- },
- {
- "construct_id": "tool_use_blocks",
- "label": "Tool-use blocks",
- "minimum": 1,
- "observed": 26,
- "ok": true
- },
- {
- "construct_id": "tool_result_blocks",
- "label": "Tool-result blocks",
- "minimum": 1,
- "observed": 28,
- "ok": true
- },
- {
- "construct_id": "failed_tool_results",
- "label": "Failed tool results",
- "minimum": 1,
- "observed": 7,
- "ok": true
- },
- {
- "construct_id": "provider_usage_messages",
- "label": "Provider usage messages",
- "minimum": 1,
- "observed": 9,
- "ok": true
- },
- {
- "construct_id": "attachment_rows",
- "label": "Attachment rows",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "acquired_attachment_rows",
- "label": "Acquired attachment rows",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "temporary_session_rows",
- "label": "Temporary session rows",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "token_budget_web_constructs",
- "label": "Token-budget web constructs",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "capture_gap_events",
- "label": "Capture-gap events",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "browser_capture_raw_variants",
- "label": "Browser-capture raw variants",
- "minimum": 3,
- "observed": 3,
- "ok": true
- },
- {
- "construct_id": "browser_capture_coalesced_session",
- "label": "Browser-capture coalesced session",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "source_outage_interval_events",
- "label": "Source-outage interval events",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "ambiguous_cross_material_duplicate",
- "label": "Ambiguous cross-material duplicate",
- "minimum": 1,
- "observed": 2,
- "ok": true
- },
- {
- "construct_id": "compaction_omits_failed_attempt",
- "label": "Compaction omits a failed attempt",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "gemini_cli_origin_rows",
- "label": "Gemini CLI origin rows",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "antigravity_origin_rows",
- "label": "Antigravity origin rows",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "hermes_origin_rows",
- "label": "Hermes origin rows",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "session_link_rows",
- "label": "Session-link rows",
- "minimum": 1,
- "observed": 3,
- "ok": true
- },
- {
- "construct_id": "generic_branch_links",
- "label": "Generic branch links",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "prefix_sharing_links",
- "label": "Prefix-sharing lineage links",
- "minimum": 1,
- "observed": 2,
- "ok": true
- },
- {
- "construct_id": "continuation_links",
- "label": "Continuation links",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "subagent_links",
- "label": "Subagent links",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "sidechain_sessions",
- "label": "Sidechain sessions",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "compaction_events",
- "label": "Compaction events",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "run_projection_rows",
- "label": "Run projection rows",
- "minimum": 1,
- "observed": 19,
- "ok": true
- },
- {
- "construct_id": "observed_event_rows",
- "label": "Observed-event rows",
- "minimum": 1,
- "observed": 43,
- "ok": true
- },
- {
- "construct_id": "context_snapshot_rows",
- "label": "Context snapshot rows",
- "minimum": 1,
- "observed": 19,
- "ok": true
- },
- {
- "construct_id": "subagent_context_snapshots",
- "label": "Subagent context snapshots",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "subagent_run_rows",
- "label": "Subagent run rows",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "unfinished_terminal_state_rows",
- "label": "Unfinished terminal-state rows",
- "minimum": 1,
- "observed": 5,
- "ok": true
- },
- {
- "construct_id": "error_terminal_state_rows",
- "label": "Error terminal-state rows",
- "minimum": 1,
- "observed": 2,
- "ok": true
- },
- {
- "construct_id": "receipts_failed_test_action",
- "label": "Receipts failed test action",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "receipts_successful_recovery_action",
- "label": "Receipts successful recovery action",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "receipts_conflicting_claim",
- "label": "Receipts conflicting claim",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "anti_grep_control",
- "label": "Anti-grep negative control",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "embedding_candidate_prose_messages",
- "label": "Embedding candidate prose messages",
- "minimum": 1,
- "observed": 41,
- "ok": true
- },
- {
- "construct_id": "synthetic_message_embedding_rows",
- "label": "Synthetic message embedding rows",
- "minimum": 1,
- "observed": 2,
- "ok": true
- },
- {
- "construct_id": "embedding_status_rows",
- "label": "Embedding status rows",
- "minimum": 1,
- "observed": 1,
- "ok": true
- }
- ],
- "healed_tiers": [],
- "message_count": 71,
- "overlays_seeded": true,
- "session_count": 19,
- "session_ids": [
- "aistudio-drive:demo-00",
- "antigravity-session:demo-00",
- "chatgpt-export:cross-material-duplicate-01",
- "chatgpt-export:cross-material-duplicate-02",
- "chatgpt-export:dc13ca54-0bba-4298-a38f-09068c2ef2c5",
- "claude-ai-export:demo-temporary-claude-ai",
- "claude-code-session:63705dcc-f3e5-4378-8118-8bc21e53bbb6",
- "claude-code-session:demo-lineage-compaction-parent",
- "claude-code-session:demo-lineage-compaction-parent:agent-acompact-demo",
- "claude-code-session:demo-lineage-sidechain",
- "codex-session:demo-00",
- "codex-session:demo-anti-grep",
- "codex-session:demo-lineage-fork",
- "codex-session:demo-lineage-parent",
- "codex-session:demo-lineage-subagent",
- "codex-session:demo-receipts",
- "codex-session:demo-terminal-error",
- "gemini-cli-session:demo-00",
- "hermes-session:demo-00"
- ],
- "source_root": "archive/demo-fixture-world-source"
- },
- "steps": [
- {
- "bytes_written": 1405,
- "command": [
- "polylogue",
- "demo",
- "receipts"
- ],
- "duration_s": 1.362,
- "exit_code": 0,
- "name": "claim versus receipt",
- "output_path": "command-output/01-claim-versus-receipt.txt"
- },
- {
- "bytes_written": 62,
- "command": [
- "polylogue",
- "actions where is_error:true | group by tool | count"
- ],
- "duration_s": 1.839,
- "exit_code": 0,
- "name": "failed actions aggregate",
- "output_path": "command-output/02-failed-actions-aggregate.txt"
- },
- {
- "bytes_written": 944,
- "command": [
- "polylogue",
- "--id",
- "codex-session:demo-lineage-fork",
- "read",
- "--view",
- "chronicle"
- ],
- "duration_s": 1.695,
- "exit_code": 0,
- "name": "composed lineage",
- "output_path": "command-output/03-composed-lineage.txt"
- },
- {
- "bytes_written": 1652,
- "command": [
- "polylogue",
- "analyze",
- "--facets"
- ],
- "duration_s": 1.629,
- "exit_code": 0,
- "name": "archive facets",
- "output_path": "command-output/04-archive-facets.txt"
- }
- ],
- "total_duration_s": 27.096,
- "transcript_path": "transcript.txt",
- "verify": {
- "absolute_path_leaks": [],
- "archive_root": "archive",
- "construct_coverage": [
- {
- "construct_id": "multi_origin_sessions",
- "label": "Multi-origin sessions",
- "minimum": 3,
- "observed": 8,
- "ok": true
- },
- {
- "construct_id": "session_profiles",
- "label": "Session profiles",
- "minimum": 3,
- "observed": 19,
- "ok": true
- },
- {
- "construct_id": "tool_use_blocks",
- "label": "Tool-use blocks",
- "minimum": 1,
- "observed": 26,
- "ok": true
- },
- {
- "construct_id": "tool_result_blocks",
- "label": "Tool-result blocks",
- "minimum": 1,
- "observed": 28,
- "ok": true
- },
- {
- "construct_id": "failed_tool_results",
- "label": "Failed tool results",
- "minimum": 1,
- "observed": 7,
- "ok": true
- },
- {
- "construct_id": "provider_usage_messages",
- "label": "Provider usage messages",
- "minimum": 1,
- "observed": 9,
- "ok": true
- },
- {
- "construct_id": "attachment_rows",
- "label": "Attachment rows",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "acquired_attachment_rows",
- "label": "Acquired attachment rows",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "temporary_session_rows",
- "label": "Temporary session rows",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "token_budget_web_constructs",
- "label": "Token-budget web constructs",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "capture_gap_events",
- "label": "Capture-gap events",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "browser_capture_raw_variants",
- "label": "Browser-capture raw variants",
- "minimum": 3,
- "observed": 3,
- "ok": true
- },
- {
- "construct_id": "browser_capture_coalesced_session",
- "label": "Browser-capture coalesced session",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "source_outage_interval_events",
- "label": "Source-outage interval events",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "ambiguous_cross_material_duplicate",
- "label": "Ambiguous cross-material duplicate",
- "minimum": 1,
- "observed": 2,
- "ok": true
- },
- {
- "construct_id": "compaction_omits_failed_attempt",
- "label": "Compaction omits a failed attempt",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "gemini_cli_origin_rows",
- "label": "Gemini CLI origin rows",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "antigravity_origin_rows",
- "label": "Antigravity origin rows",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "hermes_origin_rows",
- "label": "Hermes origin rows",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "session_link_rows",
- "label": "Session-link rows",
- "minimum": 1,
- "observed": 3,
- "ok": true
- },
- {
- "construct_id": "generic_branch_links",
- "label": "Generic branch links",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "prefix_sharing_links",
- "label": "Prefix-sharing lineage links",
- "minimum": 1,
- "observed": 2,
- "ok": true
- },
- {
- "construct_id": "continuation_links",
- "label": "Continuation links",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "subagent_links",
- "label": "Subagent links",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "sidechain_sessions",
- "label": "Sidechain sessions",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "compaction_events",
- "label": "Compaction events",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "run_projection_rows",
- "label": "Run projection rows",
- "minimum": 1,
- "observed": 19,
- "ok": true
- },
- {
- "construct_id": "observed_event_rows",
- "label": "Observed-event rows",
- "minimum": 1,
- "observed": 43,
- "ok": true
- },
- {
- "construct_id": "context_snapshot_rows",
- "label": "Context snapshot rows",
- "minimum": 1,
- "observed": 19,
- "ok": true
- },
- {
- "construct_id": "subagent_context_snapshots",
- "label": "Subagent context snapshots",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "subagent_run_rows",
- "label": "Subagent run rows",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "unfinished_terminal_state_rows",
- "label": "Unfinished terminal-state rows",
- "minimum": 1,
- "observed": 5,
- "ok": true
- },
- {
- "construct_id": "error_terminal_state_rows",
- "label": "Error terminal-state rows",
- "minimum": 1,
- "observed": 2,
- "ok": true
- },
- {
- "construct_id": "receipts_failed_test_action",
- "label": "Receipts failed test action",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "receipts_successful_recovery_action",
- "label": "Receipts successful recovery action",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "receipts_conflicting_claim",
- "label": "Receipts conflicting claim",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "anti_grep_control",
- "label": "Anti-grep negative control",
- "minimum": 1,
- "observed": 1,
- "ok": true
- },
- {
- "construct_id": "embedding_candidate_prose_messages",
- "label": "Embedding candidate prose messages",
- "minimum": 1,
- "observed": 41,
- "ok": true
- },
- {
- "construct_id": "synthetic_message_embedding_rows",
- "label": "Synthetic message embedding rows",
- "minimum": 1,
- "observed": 2,
- "ok": true
- },
- {
- "construct_id": "embedding_status_rows",
- "label": "Embedding status rows",
- "minimum": 1,
- "observed": 1,
- "ok": true
- }
- ],
- "message_count": 71,
- "ok": true,
- "overlays_present": true,
- "problems": [],
- "query_hits": [
- "claude-code-session:63705dcc-f3e5-4378-8118-8bc21e53bbb6",
- "codex-session:demo-00",
- "codex-session:demo-receipts",
- "codex-session:demo-terminal-error"
- ],
- "session_count": 19
- }
-}
diff --git a/docs/examples/demo-tour/report.md b/docs/examples/demo-tour/report.md
deleted file mode 100644
index 360ae26834..0000000000
--- a/docs/examples/demo-tour/report.md
+++ /dev/null
@@ -1,73 +0,0 @@
-# Polylogue Demo Tour Report
-
-Status: **passed**
-
-This report was produced by `polylogue demo tour` against the deterministic
-private-data-free demo archive. The transcript is ordered as an evidence story:
-one claim-versus-receipt contradiction, a structural aggregate, copied-lineage composition, then archive scope.
-
-## What this tour proves
-
-- Assistant prose can be compared with provider-normalized structural evidence at the exact claim boundary.
-- A later successful run can be distinguished from the failed evidence that existed when the claim was made.
-- A prose-only negative control can contain the word error while contributing zero failed actions.
-- The query surface can aggregate failed actions from structured fields rather than keyword matching assistant prose.
-- A fork can be read as a logical chronicle while inherited messages keep their original refs.
-- One deterministic archive can expose multiple provider origins through the same read and analysis surfaces.
-- The fixture verifier found 40/40 declared constructs and no absolute-path leaks.
-
-## What this tour does not prove
-
-- It is not a scale or latency claim for a private multi-million-message archive.
-- It does not prove complete capture fidelity for every supported provider or every historical export variant.
-- It does not prove that semantic retrieval, reviewed memory, or context injection improves agent outcomes.
-- It does not prove the proposed Sinex-backed storage architecture or selective physical deletion.
-- It is a deterministic product-contract demonstration, not a provider invoice or general model-behavior study.
-
-## Claim
-
-The recorded public commands complete successfully against the verified fixture archive.
-
-## Oracle
-
-The semantic fixture verifier runs before the narrated commands and checks planted constructs independently of the report prose.
-
-## Non-claims
-
-- This deterministic tour does not establish field prevalence, production scale, or provider completeness.
-- It does not establish memory uplift, invoice accuracy, selective deletion, or the Sinex backend.
-- The private-archive Receipts benchmark is a separate local-only lane and is not simulated here.
-
-## Timings
-
-- First evidence result: 1.362s (budget 30s)
-- Full tour: 27.096s (budget 420s)
-
-## Archive
-
-- Archive root: `archive`
-- Sessions: 19
-- Messages: 71
-- User overlays: present
-- Declared fixture constructs: 40/40 satisfied
-
-## Steps
-
-| Step | Exit | Duration | Bytes | Output |
-| --- | ---: | ---: | ---: | --- |
-| claim versus receipt | 0 | 1.362s | 1405 | `command-output/01-claim-versus-receipt.txt` |
-| failed actions aggregate | 0 | 1.839s | 62 | `command-output/02-failed-actions-aggregate.txt` |
-| composed lineage | 0 | 1.695s | 944 | `command-output/03-composed-lineage.txt` |
-| archive facets | 0 | 1.629s | 1652 | `command-output/04-archive-facets.txt` |
-
-## Problems
-
-- none
-
-## Artifacts
-
-- Human-readable evidence story: `transcript.txt`
-- Complete machine-readable fixture, verification, timing, and command record: `report.json`
-- This bounded scope statement: `report.md`
-- VHS recording recipe: `recording.tape`
-- Raw command outputs: `command-output/`
diff --git a/docs/examples/demo-tour/transcript.txt b/docs/examples/demo-tour/transcript.txt
deleted file mode 100644
index b2c248db62..0000000000
--- a/docs/examples/demo-tour/transcript.txt
+++ /dev/null
@@ -1,140 +0,0 @@
-# prepare deterministic proof archive
-Seeded 19 sessions, 71 messages, and 8 user-state assertions in 20.556s. Fixture audit: 40/40 declared constructs satisfied.
-
-# verify evidence before presenting it
-Verification passed in 0.013s; 0 path leaks and 0 semantic problems. The complete fixture and verification audit remains in report.json.
-
-$ polylogue demo receipts
-Start with a falsifiable disagreement: assistant prose claims the tests pass, while the provider-normalized tool result says exit 1. A later run repairs the result, and a prose-only 'error' control demonstrates why keyword matching is not the oracle.
-exit=0 duration=1.362s bytes=1405
-Polylogue evidence receipt
-archive:
-verdict: contradicted_at_claim_time_then_repaired
-
-assistant claim: All tests pass. The clock fix is complete.
-claim evidence: block:codex-session:demo-receipts:n:receipts-a-claim:0
-
-at claim time:
- tool: shell (exec_command)
- command: pytest tests/test_clock.py -q
- exit: 1 (failed=true)
- result: {"metadata": {"exit_code": 1}, "output": "F tests/test_clock.py::test_uses_monotonic_clock\n1 failed in 0.18s"}
- evidence: block:codex-session:demo-receipts:n:call-receipts-test-fail:0
-
-later recovery:
- tool: shell (exec_command)
- command: pytest tests/test_clock.py -q
- exit: 0 (failed=false)
- result: {"metadata": {"exit_code": 0}, "output": ". 1 passed in 0.16s"}
- evidence: block:codex-session:demo-receipts:n:call-receipts-test-pass:0
-
-anti-grep control:
- prose hits for 'error': 2
- structurally failed actions: 0
- control session: session:codex-session:demo-anti-grep
-
-source material:
- raw_id: d5513a27ef4a35603881e2907ff5e6dff3e0146bf222c36ed5ef032dc58479c2
- blob_sha256: 9fd0dbdb080058070935924534a903cc63a8dcba571f6b2734f92a96576b59d7
-
-completion-claim experiment:
- sample manifest: 014380e82576a22360db0b18c25a984b62fdb057e535aadd1c9b448cf40f2466
- denominator: 2
-unsupported by structural evidence: 0 (0.0%)
-neutral prior outcome: 0 (0.0%)
-contradicted then repaired: 1 (50.0%)
-contradicted without recorded repair: 1 (50.0%)
-
-$ polylogue 'actions where is_error:true | group by tool | count'
-Now aggregate the same structural field across providers. This query counts normalized failed actions; it does not search prose for the word 'error'.
-exit=0 duration=1.839s bytes=62
-tool=Bash count=4
-tool=exec_command count=2
-tool=Edit count=1
-
-$ polylogue --id codex-session:demo-lineage-fork read --view chronicle
-Read a fork as one logical chronicle: inherited parent messages remain attributable to their origin while the fork contributes only its divergent tail.
-exit=0 duration=1.695s bytes=944
-# Session Chronicle
-
-- Sessions: 1
-- Edge limit: 8
-- Body policy: authored-dialogue
-
-## Map the demo lineage base context.
-
-- Session: `codex-session:demo-lineage-fork`
-- Origin: codex-session
-- Matching prose messages: 4
-- Included: 4
-- Omitted middle messages: 0
-
-### First Messages
-
-### 2026-07-04T10:00:01+00:00 - user / message
-
-Map the demo lineage base context.
-
-`codex-session:demo-lineage-parent:n:parent-u0`
-
-### 2026-07-04T10:00:02+00:00 - assistant / message
-
-I have the base context and can branch the analysis.
-
-`codex-session:demo-lineage-parent:n:parent-a1`
-
-### 2026-07-04T10:01:03+00:00 - user / message
-
-Now take the forked branch and audit construct validity.
-
-`codex-session:demo-lineage-fork:n:fork-u2`
-
-### 2026-07-04T10:01:04+00:00 - assistant / message
-
-The fork diverges into demo corpus construct checks.
-
-`codex-session:demo-lineage-fork:n:fork-a3`
-
-### Last Messages
-
-_No distinct matching prose in the last edge._
-
-$ polylogue analyze --facets
-Only after inspecting evidence, zoom out to the archive across 8 origins, with deferred families labeled rather than silently guessed.
-exit=0 duration=1.629s bytes=1652
-Facets (global) — matched result set:
- readiness: ready (cost_class=cheap; budget 0.01s/2.00s)
- sessions: 19 messages: 71
- Family states:
- total_counts: Total counts — complete
- origins: Provider origins — complete
- tags: User tags — complete
- repos: Canonical repositories — deferred (deferred_by_default; use --include-deferred); prefer repo_name or origin_url; omit archive/path tokens that are not product repo identities
- role_counts: Provider-role counts — deferred (deferred_by_default; use --include-deferred); provider-reported message role; not authoredness
- material_origins: Material origins — deferred (deferred_by_default; use --include-deferred); authoredness/protocol provenance; separates human text from runtime or assistant material
- message_types: Message content types — deferred (deferred_by_default; use --include-deferred)
- action_types: Action types — deferred (deferred_by_default; use --include-deferred)
- has_flags: Content flags — deferred (deferred_by_default; use --include-deferred)
- Provider origins:
- codex-session: 7
- claude-code-session: 4
- chatgpt-export: 3
- aistudio-drive: 1
- antigravity-session: 1
- claude-ai-export: 1
- gemini-cli-session: 1
- hermes-session: 1
- User tags:
- pytest-triage: 1
- IDF (higher = rarer, partitions more strongly):
- [origins]
- aistudio-drive: 2.944
- antigravity-session: 2.944
- claude-ai-export: 2.944
- gemini-cli-session: 2.944
- hermes-session: 2.944
- chatgpt-export: 1.846
- claude-code-session: 1.558
- codex-session: 0.999
- [tags]
- pytest-triage: 2.944
diff --git a/docs/examples/demo-tour/uvx-proof.md b/docs/examples/demo-tour/uvx-proof.md
deleted file mode 100644
index 058b373f6a..0000000000
--- a/docs/examples/demo-tour/uvx-proof.md
+++ /dev/null
@@ -1,48 +0,0 @@
-# Demo Tour Install-Path Proof
-
-This proof was run on July 10, 2026 from the local package source using
-`uvx --from ` as the pre-release equivalent of the public command:
-
-```bash
-uvx --from polylogue demo tour --out-dir --force --format json
-```
-
-Result:
-
-- Status: passed
-- End-to-end `uvx` process time, including resolution/install: 29.27s
-- First evidence result after the command began: 2.109s
-- Tour execution time reported by Polylogue: 6.038s
-- Demo archive: 13 sessions, 55 messages, overlays present
-- Declared fixture constructs: 34/34 satisfied
-- Query/read steps: claim versus receipt, failed-actions aggregate, composed lineage, archive facets
-- Problems: none
-
-The environment emitted package-index warnings about obsolete release artifacts;
-those warnings did not change the command exit status or proof result. This is a
-source-install receipt, not yet a published-index receipt.
-
-A second clean source-install proof exercised the self-contained first-contact command directly:
-
-```bash
-env -u POLYLOGUE_ARCHIVE_ROOT UV_NO_CACHE=1 \
- uvx --from polylogue demo receipts --format json
-```
-
-Result:
-
-- Status: passed
-- End-to-end process time, including a no-cache build and dependency install: 14.75s
-- The command seeded its own archive under the current working directory
-- Verdict: `contradicted_at_claim_time_then_repaired`
-- Failed structural receipt: exit code 1
-- Later recovery receipt: exit code 0
-- Anti-grep control: two text hits for `error`, zero failed actions
-
-The release-path command is intended to be:
-
-```bash
-uvx polylogue demo receipts
-```
-
-A published-index proof remains a release gate rather than a current claim.
diff --git a/docs/examples/reader-comprehension-test/README.md b/docs/examples/reader-comprehension-test/README.md
index f8ed0d004c..a96eb7b54e 100644
--- a/docs/examples/reader-comprehension-test/README.md
+++ b/docs/examples/reader-comprehension-test/README.md
@@ -2,8 +2,8 @@
# Reader-Comprehension Test Harness (polylogue-3tl.19)
-A structural coverage lint (`devtools verify docs-coverage`) or a public-claims
-ledger entry can prove a README claim is *true*. Neither proves it *lands* —
+A structural source check or a human review can prove a README claim is *true*.
+Neither proves it *lands*:
that a stranger who sees the first fold for a fixed exposure can actually
state the category, the outcome, the differentiator, and the one thing it
explicitly does not claim. This harness measures that, as a bounded,
@@ -34,7 +34,7 @@ those terms instead of introducing a parallel scoring scheme:
| --- | --- | --- |
| Category, outcome, differentiator | **claim** recognition | Did the reader state the same claim the copy makes, unprompted? |
| Boundary/non-claim | **non-claims** | Did the reader notice the one thing the copy explicitly says it does *not* establish? |
-| False beliefs | **falsifier** | Any nonzero false-belief count falsifies the arm regardless of its other scores — this is the harness's explicit falsifier, matching the demo-packet contract's requirement that every proof declare one. |
+| False beliefs | **falsifier** | Any nonzero false-belief count falsifies the arm regardless of its other scores, so a superficially clearer arm cannot advance by teaching readers something false. |
| Independent scorer, not the participant | **oracle** | The score comes from a scorer applying the rubric, not the participant's self-report of how well they think they did. |
| A comparative baseline (>=2 arms, one of them `current`) | **comparative baseline** | A single-arm "reads fine" result is not comparative; the harness always configures at least a current-vs-candidate pair. |
diff --git a/docs/examples/visual-tapes/README.md b/docs/examples/visual-tapes/README.md
index 07d0b1cd51..9b618e15a3 100644
--- a/docs/examples/visual-tapes/README.md
+++ b/docs/examples/visual-tapes/README.md
@@ -9,13 +9,9 @@ Regenerate from the repository root:
devtools render visual-tapes --output-dir docs/examples/visual-tapes --capture
```
-The full default inventory also renders `demo-tour.gif`; the canonical copy for
-that larger demo packet lives at `docs/examples/demo-tour/demo-tour.gif`.
-
## Files
-- `demo-tour.tape` — tape spec for the one-command demo tour; its canonical GIF
- copy lives in `docs/examples/demo-tour/demo-tour.gif`.
+- `demo-tour.tape` — tape spec for the one-command demo tour.
- `evidence-receipt.tape` / `evidence-receipt.png` — reproducible command flow
and static first-contact receipt for an assistant claim checked against
failed and successful test outcomes.
diff --git a/docs/findings/claim-vs-evidence.md b/docs/findings/claim-vs-evidence.md
index 633000b1ee..fe1302fb2f 100644
--- a/docs/findings/claim-vs-evidence.md
+++ b/docs/findings/claim-vs-evidence.md
@@ -42,7 +42,8 @@ falsified by a representative, sufficiently large calibration frame showing
that visible marker absence does not track human labels for this narrow
observable.
-The generated [findings-page public-claims view](../generated/public-claims/findings-page.md) is the authority for whether this historical number is currently supported, stale, private-held, or unresolved.
+This page deliberately labels the number historical. A newly generated result
+is not a current public claim merely because the report command completed.
This is a lower-bound field observation from one archive and one method. It is not a prevalence estimate for all agents, models, users, providers, or tasks.
@@ -106,12 +107,14 @@ The calibration is small. The method therefore keeps 3,375 cases ambiguous inste
## First-party evidence boundary
-The current report is a regenerable local evidence artifact, not a registered
-analysis definition, immutable analysis run, or finding. Those first-party
-objects require the pending durable user-tier kernel and migration admission;
-until that work is accepted, this page must not promote a newly generated
-packet into a current public claim. The generated public-claims view remains
-the authority for claim status.
+The command is read-only by default. With explicit `--materialize-evidence`, it
+records a content-addressed analysis definition, result-set membership,
+evaluation receipt, and finding through the archive's existing user-tier
+writers. It emits a public-claim declaration only when the run's own
+minimum-sample and classified-outcome gates pass. The surviving
+`PublicClaimProjection` applies publication, privacy, freshness, frame, and
+evidence-integrity state independently; report generation alone never upgrades
+this historical page into a supported current claim.
## Interpretation
@@ -142,19 +145,16 @@ Operators with the relevant archive can run:
```bash
devtools workspace claim-vs-evidence \
--limit 5000 \
- --out-dir .agent/demos/claim-vs-evidence \
+ --out-dir .local/evidence/claim-vs-evidence \
--json
-
-devtools workspace demo-shelf
```
## Evidence and caveats
See:
-- [Proof Artifacts](../proof-artifacts.md);
- `devtools/claim_vs_evidence.py`;
- `tests/unit/devtools/test_claim_vs_evidence.py`;
-- the local `.agent/demos/claim-vs-evidence/` packet when generated.
+- the local `.local/evidence/claim-vs-evidence/` packet when generated.
Publication requires the packet’s archive cursor, measure version, commit SHA, sample-frame predicate, and run date. If any is missing or stale, the finding page should refuse regeneration rather than silently retain an old number.
diff --git a/docs/generated/api-operation-parity.json b/docs/generated/api-operation-parity.json
deleted file mode 100644
index 639eff4a2c..0000000000
--- a/docs/generated/api-operation-parity.json
+++ /dev/null
@@ -1,1168 +0,0 @@
-{
- "authority": {
- "documentation": "docs/library-api.md",
- "drift_owner": "polylogue-s1kr",
- "facade": "polylogue.api.Polylogue",
- "operation_declarations": "polylogue/api/operation_parity.py"
- },
- "exclusions": [
- {
- "authority": "polylogue-s1kr",
- "binding": "ArchiveStats",
- "reason": "Result data model, not an executable archive operation."
- },
- {
- "authority": "polylogue-s1kr",
- "binding": "select_pending_embedding_session_window",
- "reason": "Public adapter helper for daemon/CLI window selection. It is intentionally not a facade operation."
- },
- {
- "authority": "polylogue-s1kr",
- "binding": "Polylogue.__repr__",
- "reason": "Diagnostic representation protocol, not an archive operation."
- }
- ],
- "generated_by": "devtools render api-operation-parity",
- "operation_count": 15,
- "operations": [
- {
- "cli": {
- "intentional_absence_authority": "polylogue-s1kr",
- "names": []
- },
- "mcp": {
- "intentional_absence_authority": "polylogue-s1kr",
- "names": []
- },
- "operation_id": "api.lifecycle.construct",
- "python": [
- {
- "binding": "Polylogue"
- },
- {
- "async": false,
- "binding": "Polylogue.__init__",
- "signature": "(archive_root: 'str | Path | None' = None, db_path: 'str | Path | None' = None, *, runtime: 'ResolvedRuntimeConfig | None' = None, config: 'Config | None' = None) -> 'None'"
- },
- {
- "async": false,
- "binding": "Polylogue.open",
- "signature": "(*, config: 'Config | None' = None, runtime: 'ResolvedRuntimeConfig | None' = None, **kwargs: 'object') -> 'Polylogue'"
- },
- {
- "async": true,
- "binding": "Polylogue.__aenter__",
- "signature": "(self) -> 'Polylogue'"
- },
- {
- "async": true,
- "binding": "Polylogue.__aexit__",
- "signature": "(self, exc_type: 'object', exc_val: 'object', exc_tb: 'object') -> 'None'"
- },
- {
- "async": true,
- "binding": "Polylogue.close",
- "signature": "(self) -> 'None'"
- }
- ],
- "route_class": "lifecycle",
- "section": "Lifecycle and builders",
- "summary": "Construct, open, and close a facade bound to one archive runtime."
- },
- {
- "cli": {
- "intentional_absence_authority": null,
- "names": [
- "ops embed status"
- ]
- },
- "mcp": {
- "intentional_absence_authority": null,
- "names": [
- "status"
- ]
- },
- "operation_id": "api.embedding.status",
- "python": [
- {
- "async": false,
- "binding": "Polylogue.embedding_status",
- "signature": "(self, *, detail: 'bool' = False) -> 'dict[str, object]'"
- }
- ],
- "route_class": "embedding-status",
- "section": "Embedding readiness",
- "summary": "Read the no-spend embedding readiness state."
- },
- {
- "cli": {
- "intentional_absence_authority": null,
- "names": [
- "ops embed preflight"
- ]
- },
- "mcp": {
- "intentional_absence_authority": null,
- "names": [
- "status"
- ]
- },
- "operation_id": "api.embedding.preflight",
- "python": [
- {
- "async": false,
- "binding": "Polylogue.embedding_preflight",
- "signature": "(self, *, rebuild: 'bool' = False, max_sessions: 'int | None' = None, max_messages: 'int | None' = None, max_cost_usd: 'float | None' = None) -> 'dict[str, object]'"
- }
- ],
- "route_class": "embedding-preflight",
- "section": "Embedding readiness",
- "summary": "Calculate a bounded no-provider-call embedding catch-up window."
- },
- {
- "cli": {
- "intentional_absence_authority": null,
- "names": [
- "find similar"
- ]
- },
- "mcp": {
- "intentional_absence_authority": null,
- "names": [
- "query"
- ]
- },
- "operation_id": "api.embedding.search",
- "python": [
- {
- "async": true,
- "binding": "Polylogue.search_similar_sessions",
- "signature": "(self, session_id: 'str', *, limit: 'int' = 10, vector_provider: 'VectorProvider | None' = None, voyage_api_key: 'str | None' = None) -> 'dict[str, object]'"
- }
- ],
- "route_class": "embedding-read",
- "section": "Embedding retrieval",
- "summary": "Search stored session vectors using the embeddings tier."
- },
- {
- "cli": {
- "intentional_absence_authority": null,
- "names": [
- "import"
- ]
- },
- "mcp": {
- "intentional_absence_authority": null,
- "names": [
- "run"
- ]
- },
- "operation_id": "api.ingest.parse",
- "python": [
- {
- "async": true,
- "binding": "Polylogue.parse_file",
- "signature": "(self, path: 'str | Path', *, source_name: 'str | None' = None) -> 'ParseResult'"
- },
- {
- "async": true,
- "binding": "Polylogue.parse_sources",
- "signature": "(self, sources: 'list[Source] | None' = None, *, download_assets: 'bool' = True) -> 'ParseResult'"
- }
- ],
- "route_class": "source-index-write",
- "section": "Ingestion and derived maintenance",
- "summary": "Parse configured or explicit sources into source and index tiers."
- },
- {
- "cli": {
- "intentional_absence_authority": null,
- "names": [
- "ops reset --index"
- ]
- },
- "mcp": {
- "intentional_absence_authority": null,
- "names": [
- "maintenance"
- ]
- },
- "operation_id": "api.index.rebuild",
- "python": [
- {
- "async": true,
- "binding": "Polylogue.rebuild_index",
- "signature": "(self) -> 'bool'"
- },
- {
- "async": true,
- "binding": "Polylogue.update_index",
- "signature": "(self, session_ids: 'list[str]') -> 'bool'"
- },
- {
- "async": true,
- "binding": "Polylogue.rebuild_insights",
- "signature": "(self, session_ids: 'Sequence[str] | None' = None, *, progress_callback: 'ProgressCallback | None' = None) -> 'SessionInsightCounts'"
- }
- ],
- "route_class": "index-write",
- "section": "Ingestion and derived maintenance",
- "summary": "Rebuild or update the derived index through the mutation executor."
- },
- {
- "cli": {
- "intentional_absence_authority": null,
- "names": [
- "find",
- "read"
- ]
- },
- "mcp": {
- "intentional_absence_authority": null,
- "names": [
- "query",
- "read",
- "get",
- "status"
- ]
- },
- "operation_id": "api.archive.session-read",
- "python": [
- {
- "async": true,
- "binding": "Polylogue.get_session",
- "signature": "(self, session_id: 'str', *, content_projection: 'ContentProjectionSpec | None' = None) -> 'Session | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_sessions",
- "signature": "(self, session_ids: 'list[str]', *, content_projection: 'ContentProjectionSpec | None' = None) -> 'list[Session]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_actions_batch",
- "signature": "(self, session_ids: 'builtins.list[str]') -> 'dict[str, tuple[Action, ...]]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_sessions",
- "signature": "(self, origin: 'str | None' = None, limit: 'int | None' = None, content_projection: 'ContentProjectionSpec | None' = None) -> 'list[Session]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_summaries",
- "signature": "(self, *, limit: 'int | None' = 50, offset: 'int' = 0, origin: 'str | None' = None) -> 'builtins.list[SessionSummary]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_sessions_for_spec",
- "signature": "(self, spec: 'SessionQuerySpec', *, content_projection: 'ContentProjectionSpec | None' = None) -> 'list[Session]'"
- },
- {
- "async": true,
- "binding": "Polylogue.search_session_hits",
- "signature": "(self, spec: 'SessionQuerySpec') -> 'builtins.list[SessionSearchHit]'"
- },
- {
- "async": true,
- "binding": "Polylogue.search",
- "signature": "(self, query: 'str', *, limit: 'int' = 100, source: 'str | None' = None, since: 'str | None' = None) -> 'SearchResult'"
- },
- {
- "async": true,
- "binding": "Polylogue.search_envelope",
- "signature": "(self, query: 'str', *, limit: 'int' = 50, offset: 'int' = 0, origin: 'str | None' = None, since: 'str | None' = None, until: 'str | None' = None, retrieval_lane: 'str' = 'auto', sort: 'str | None' = None, cursor: 'str | None' = None) -> 'SearchEnvelope'"
- },
- {
- "async": true,
- "binding": "Polylogue.archive_count_sessions",
- "signature": "(self, *, origin: 'str | None' = None, excluded_origins: 'Sequence[str]' = (), tags: 'Sequence[str]' = (), excluded_tags: 'Sequence[str]' = (), repo_names: 'Sequence[str]' = (), project_refs: 'Sequence[str]' = (), has_types: 'Sequence[str]' = (), has_tool_use: 'bool' = False, has_thinking: 'bool' = False, has_paste: 'bool' = False, tool_terms: 'Sequence[str]' = (), excluded_tool_terms: 'Sequence[str]' = (), action_terms: 'Sequence[str]' = (), excluded_action_terms: 'Sequence[str]' = (), action_sequence: 'Sequence[str]' = (), action_text_terms: 'Sequence[str]' = (), referenced_paths: 'Sequence[str]' = (), cwd_prefix: 'str | None' = None, typed_only: 'bool' = False, message_type: 'str | None' = None, title: 'str | None' = None, min_messages: 'int | None' = None, max_messages: 'int | None' = None, min_words: 'int | None' = None, max_words: 'int | None' = None, since: 'str | None' = None, until: 'str | None' = None) -> 'int'"
- },
- {
- "async": true,
- "binding": "Polylogue.archive_get_session",
- "signature": "(self, session_id: 'str') -> 'ArchiveSessionEnvelope | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_messages_paginated",
- "signature": "(self, session_id: 'str', *, message_role: 'MessageRoleFilter' = (), message_type: 'MessageTypeName | None' = None, material_origin: 'tuple[MaterialOrigin, ...]' = (), limit: 'int' = 50, offset: 'int' = 0, content_projection: 'ContentProjectionSpec | None' = None) -> 'tuple[list[Message], int, LineageCompleteness]'"
- },
- {
- "async": false,
- "binding": "Polylogue.iter_messages",
- "signature": "(self, session_id: 'str', *, message_roles: 'MessageRoleFilter' = (), material_origin: 'tuple[MaterialOrigin, ...]' = (), limit: 'int | None' = None) -> 'AsyncIterator[Message]'"
- },
- {
- "async": true,
- "binding": "Polylogue.bulk_get_messages",
- "signature": "(self, session_ids: 'Sequence[str]', *, since: 'str | None' = None, until: 'str | None' = None, message_role: 'MessageRoleFilter' = (), material_origin: 'tuple[MaterialOrigin, ...]' = (), content_projection: 'ContentProjectionSpec | None' = None) -> 'dict[str, list[Message]]'"
- },
- {
- "async": true,
- "binding": "Polylogue.query_sessions",
- "signature": "(self, *, origin: 'str | None' = None, tag: 'str | None' = None, since: 'str | None' = None, until: 'str | None' = None, sort: 'str | None' = None, limit: 'int | None' = None, offset: 'int' = 0, has_tool_use: 'bool' = False, has_thinking: 'bool' = False, has_paste: 'bool' = False, typed_only: 'bool' = False, min_messages: 'int | None' = None, max_messages: 'int | None' = None, min_words: 'int | None' = None, **kwargs: 'object') -> 'builtins.list[dict[str, object]]'"
- },
- {
- "async": true,
- "binding": "Polylogue.count_sessions",
- "signature": "(self, *, origin: 'str | None' = None, since: 'str | None' = None, until: 'str | None' = None, **kwargs: 'object') -> 'int'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_session_summary",
- "signature": "(self, session_id: 'str') -> 'SessionSummary | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_session_stats",
- "signature": "(self, session_id: 'str') -> 'dict[str, int]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_stats_by",
- "signature": "(self, group_by: 'str' = 'origin') -> 'dict[str, int]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_index_status",
- "signature": "(self) -> 'IndexStatus'"
- },
- {
- "async": true,
- "binding": "Polylogue.stats",
- "signature": "(self) -> 'ArchiveStats'"
- },
- {
- "async": true,
- "binding": "Polylogue.storage_stats",
- "signature": "(self) -> 'StorageArchiveStats'"
- },
- {
- "async": true,
- "binding": "Polylogue.facets",
- "signature": "(self, spec: 'SessionQuerySpec | None' = None, *, include_idf: 'bool' = True, include_deferred: 'bool' = True) -> 'FacetsResponse'"
- },
- {
- "async": true,
- "binding": "Polylogue.health_check",
- "signature": "(self) -> 'ReadinessReport'"
- },
- {
- "async": false,
- "binding": "Polylogue.filter",
- "signature": "(self) -> 'SessionFilter'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_read_view_profiles",
- "signature": "(self) -> 'list[JSONDocument]'"
- }
- ],
- "route_class": "index-read",
- "section": "Archive reads",
- "summary": "Read sessions, summaries, messages, actions, and archive statistics from the index tier."
- },
- {
- "cli": {
- "intentional_absence_authority": null,
- "names": [
- "find",
- "read",
- "analyze"
- ]
- },
- "mcp": {
- "intentional_absence_authority": null,
- "names": [
- "query",
- "read",
- "get",
- "explain"
- ]
- },
- "operation_id": "api.archive.query-analysis",
- "python": [
- {
- "async": true,
- "binding": "Polylogue.explain_query_expression",
- "signature": "(self, expression: 'str') -> 'JSONDocument'"
- },
- {
- "async": true,
- "binding": "Polylogue.query_units",
- "signature": "(self, expression: 'str | None' = None, *, limit: 'int | None' = None, offset: 'int | None' = None, origin: 'str | None' = None, origins: 'tuple[str, ...]' = (), excluded_origins: 'tuple[str, ...]' = (), tag: 'str | None' = None, tags: 'tuple[str, ...]' = (), excluded_tags: 'tuple[str, ...]' = (), repo: 'str | None' = None, repo_names: 'tuple[str, ...]' = (), project: 'str | None' = None, project_refs: 'tuple[str, ...]' = (), has_types: 'tuple[str, ...]' = (), tool_terms: 'tuple[str, ...]' = (), excluded_tool_terms: 'tuple[str, ...]' = (), action_terms: 'tuple[str, ...]' = (), excluded_action_terms: 'tuple[str, ...]' = (), action_sequence: 'tuple[str, ...]' = (), action_text_terms: 'tuple[str, ...]' = (), referenced_paths: 'tuple[str, ...]' = (), cwd_prefix: 'str | None' = None, title: 'str | None' = None, since: 'str | None' = None, until: 'str | None' = None, has_tool_use: 'bool' = False, has_thinking: 'bool' = False, has_paste: 'bool' = False, typed_only: 'bool' = False, min_messages: 'int | None' = None, max_messages: 'int | None' = None, min_words: 'int | None' = None, max_words: 'int | None' = None, message_type: 'str | None' = None, continuation: 'str | None' = None) -> 'QueryUnitResultEnvelope'"
- },
- {
- "async": true,
- "binding": "Polylogue.query_completions",
- "signature": "(self, kind: 'str', *, incomplete: 'str' = '', unit: 'str | None' = None, field: 'str | None' = None) -> 'JSONDocument'"
- },
- {
- "async": true,
- "binding": "Polylogue.diagnose_query_miss",
- "signature": "(self, spec: 'SessionQuerySpec', *, full: 'bool' = False) -> 'QueryMissDiagnostics'"
- },
- {
- "async": true,
- "binding": "Polylogue.resolve_ref",
- "signature": "(self, ref: 'str') -> 'PublicRefResolutionPayload'"
- },
- {
- "async": true,
- "binding": "Polylogue.export_otel",
- "signature": "(self, *, source_ref: 'str', expressions: 'Sequence[str]', limit: 'int' = 50, include_message_text: 'bool' = False) -> 'OtelProjectionPayload'"
- },
- {
- "async": true,
- "binding": "Polylogue.neighbor_candidates",
- "signature": "(self, *, session_id: 'str | None' = None, query: 'str | None' = None, origin: 'str | None' = None, limit: 'int' = 10, window_hours: 'int' = 24) -> 'list[SessionNeighborCandidate]'"
- },
- {
- "async": true,
- "binding": "Polylogue.neighbor_candidate_payloads",
- "signature": "(self, *, session_id: 'str | None' = None, query: 'str | None' = None, origin: 'str | None' = None, limit: 'int' = 10, window_hours: 'int' = 24) -> 'list[JSONDocument]'"
- },
- {
- "async": true,
- "binding": "Polylogue.session_correlation_payload",
- "signature": "(self, session_id: 'str', *, repo_path: 'str | None' = None, since_hours: 'int' = 2, confidence_threshold: 'float' = 0.3) -> 'JSONDocument | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.origin_usage_report",
- "signature": "(self, *, origin: 'str | None' = None, limit: 'int | None' = 25, detail: 'str' = 'full') -> 'ProviderUsageReport'"
- },
- {
- "async": true,
- "binding": "Polylogue.session_usage_reconciliation",
- "signature": "(self, session_id: 'str') -> 'SessionUsageReconciliation'"
- },
- {
- "async": true,
- "binding": "Polylogue.resume_brief",
- "signature": "(self, session_id: 'str', *, related_limit: 'int' = 6, repo_path: 'str | None' = None, recent_files: 'Sequence[str]' = ()) -> 'ResumeBrief | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.find_resume_candidates",
- "signature": "(self, *, repo_path: 'str', cwd: 'str | None' = None, recent_files: 'Sequence[str]' = (), limit: 'int' = 10) -> 'tuple[ResumeCandidate, ...]'"
- }
- ],
- "route_class": "index-read",
- "section": "Archive reads",
- "summary": "Compile, explain, diagnose, and resolve archive query and reference projections."
- },
- {
- "cli": {
- "intentional_absence_authority": null,
- "names": [
- "read",
- "analyze"
- ]
- },
- "mcp": {
- "intentional_absence_authority": null,
- "names": [
- "read",
- "explain"
- ]
- },
- "operation_id": "api.archive.source-evidence-read",
- "python": [
- {
- "async": true,
- "binding": "Polylogue.explain_import",
- "signature": "(self, path: 'str | Path | None' = None, *, raw_ref: 'str | None' = None, source_path: 'str | None' = None, source_name: 'str' = 'unknown', limit: 'int' = 100, redact_paths: 'bool' = True) -> 'ImportExplainPayload'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_raw_artifacts_for_session",
- "signature": "(self, session_id: 'str', *, limit: 'int' = 50, offset: 'int' = 0) -> 'tuple[list[dict[str, object]], int]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_hook_event_summary_for_session",
- "signature": "(self, session_id: 'str') -> 'dict[str, object] | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_session_events",
- "signature": "(self, session_id: 'str', *, event_type: 'str | None' = None, limit: 'int | None' = None) -> 'list[dict[str, object]] | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_file_edits",
- "signature": "(self, session_id: 'str') -> 'list[dict[str, object]] | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_web_content_constructs",
- "signature": "(self, session_id: 'str', *, construct_type: 'str | None' = None) -> 'list[dict[str, object]] | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_agent_policies",
- "signature": "(self, session_id: 'str') -> 'list[dict[str, object]] | None'"
- }
- ],
- "route_class": "source-read",
- "section": "Source evidence reads",
- "summary": "Read raw artifacts and provider-side evidence retained in the durable source tier."
- },
- {
- "cli": {
- "intentional_absence_authority": null,
- "names": [
- "analyze",
- "read"
- ]
- },
- "mcp": {
- "intentional_absence_authority": null,
- "names": [
- "query",
- "get",
- "status",
- "explain"
- ]
- },
- "operation_id": "api.archive.insight-read",
- "python": [
- {
- "async": true,
- "binding": "Polylogue.get_session_insight_status",
- "signature": "(self) -> 'SessionInsightStatusSnapshot'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_session_profile_insight",
- "signature": "(self, session_id: 'str', *, tier: 'str' = 'merged') -> 'SessionProfileInsight | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_session_profile_record",
- "signature": "(self, session_id: 'str') -> 'SessionProfileRecord | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_session_profile_insights",
- "signature": "(self, query: 'SessionProfileInsightQuery | None' = None) -> 'list[SessionProfileInsight]'"
- },
- {
- "async": true,
- "binding": "Polylogue.insight_readiness_report",
- "signature": "(self, query: 'InsightReadinessQuery | None' = None) -> 'InsightReadinessReport'"
- },
- {
- "async": true,
- "binding": "Polylogue.insight_rigor_audit",
- "signature": "(self, query: 'InsightRigorAuditQuery | None' = None) -> 'InsightRigorAuditReport'"
- },
- {
- "async": true,
- "binding": "Polylogue.archive_debt",
- "signature": "(self, *, kinds: 'Iterable[str] | None' = None, only_actionable: 'bool' = False, limit: 'int | None' = None, exact_fts: 'bool' = False) -> 'ArchiveDebtListPayload'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_session_work_event_insights",
- "signature": "(self, session_id: 'str') -> 'list[SessionWorkEventInsight]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_session_work_event_insights",
- "signature": "(self, query: 'SessionWorkEventInsightQuery | None' = None) -> 'list[SessionWorkEventInsight]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_session_phase_insights",
- "signature": "(self, session_id: 'str') -> 'list[SessionPhaseInsight]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_session_phase_insights",
- "signature": "(self, query: 'SessionPhaseInsightQuery | None' = None) -> 'list[SessionPhaseInsight]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_thread_insight",
- "signature": "(self, thread_id: 'str') -> 'ThreadInsight | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_thread_insights",
- "signature": "(self, query: 'ThreadInsightQuery | None' = None) -> 'list[ThreadInsight]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_session_tag_rollup_insights",
- "signature": "(self, query: 'SessionTagRollupQuery | None' = None) -> 'list[SessionTagRollupInsight]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_archive_coverage_insights",
- "signature": "(self, query: 'ArchiveCoverageInsightQuery | None' = None) -> 'list[ArchiveCoverageInsight]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_tool_usage_insights",
- "signature": "(self, query: 'ToolUsageInsightQuery | None' = None) -> 'list[ToolUsageInsight]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_session_cost_insights",
- "signature": "(self, query: 'SessionCostInsightQuery | None' = None) -> 'list[SessionCostInsight]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_session_latency_profile_insight",
- "signature": "(self, session_id: 'str') -> 'SessionLatencyProfileInsight | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_session_latency_profile_insights",
- "signature": "(self, query: 'SessionLatencyProfileInsightQuery | None' = None) -> 'list[SessionLatencyProfileInsight]'"
- },
- {
- "async": true,
- "binding": "Polylogue.find_stuck_session_latency_profile_insights",
- "signature": "(self, query: 'SessionLatencyProfileInsightQuery | None' = None) -> 'list[SessionLatencyProfileInsight]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_cost_rollup_insights",
- "signature": "(self, query: 'CostRollupInsightQuery | None' = None) -> 'list[CostRollupInsight]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_usage_timeline_insights",
- "signature": "(self, query: 'UsageTimelineInsightQuery | None' = None) -> 'list[UsageTimelineInsight]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_archive_debt_insights",
- "signature": "(self, query: 'ArchiveDebtInsightQuery | None' = None) -> 'list[ArchiveDebtInsight]'"
- },
- {
- "async": true,
- "binding": "Polylogue.cost_outlook",
- "signature": "(self, plan_name: 'str', *, now: 'datetime | None' = None, method: 'ProjectionMethod' = ) -> 'CycleOutlook | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.aggregate_sessions",
- "signature": "(self, *, group_by: 'str' = 'workflow_shape', since: 'str | None' = None, until: 'str | None' = None, origin: 'str | None' = None) -> 'dict[str, object]'"
- },
- {
- "async": true,
- "binding": "Polylogue.workflow_shape_distribution",
- "signature": "(self, *, group_by: 'str' = 'week', since: 'str | None' = None, until: 'str | None' = None, origin: 'str | None' = None) -> 'dict[str, object]'"
- },
- {
- "async": true,
- "binding": "Polylogue.find_abandoned_sessions",
- "signature": "(self, *, since: 'str | None' = None, repo_path: 'str | None' = None, min_severity: 'str' = 'question_left', limit: 'int' = 20) -> 'dict[str, object]'"
- },
- {
- "async": true,
- "binding": "Polylogue.tool_call_latency_distribution",
- "signature": "(self, *, since: 'str | None' = None, until: 'str | None' = None, origin: 'str | None' = None, tool_category: 'str | None' = None, limit: 'int' = 500) -> 'dict[str, object]'"
- },
- {
- "async": true,
- "binding": "Polylogue.compare_sessions",
- "signature": "(self, session_ids: 'Sequence[str]') -> 'dict[str, object]'"
- },
- {
- "async": true,
- "binding": "Polylogue.find_similar_sessions_by_metadata",
- "signature": "(self, session_id: 'str', *, limit: 'int' = 10, candidate_pool_limit: 'int' = 200) -> 'dict[str, object] | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.correlate_sessions",
- "signature": "(self, *, metric_x: 'str', metric_y: 'str', origin: 'str | None' = None, since: 'str | None' = None, until: 'str | None' = None) -> 'dict[str, object]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_session_topology",
- "signature": "(self, session_id: 'str') -> 'SessionTopology | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_ancestors",
- "signature": "(self, session_id: 'str') -> 'list[SessionRef]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_descendants",
- "signature": "(self, session_id: 'str') -> 'list[SessionRef]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_siblings",
- "signature": "(self, session_id: 'str') -> 'list[SessionRef]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_thread",
- "signature": "(self, session_id: 'str') -> 'list[SessionRef]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_logical_session",
- "signature": "(self, session_id: 'str') -> 'LogicalSession | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_session_tree",
- "signature": "(self, session_id: 'str') -> 'list[Session]'"
- },
- {
- "async": true,
- "binding": "Polylogue.postmortem_bundle",
- "signature": "(self, spec: 'SessionQuerySpec | None' = None, *, limit: 'int | None' = None) -> 'PostmortemBundle'"
- },
- {
- "async": true,
- "binding": "Polylogue.pathology_report",
- "signature": "(self, spec: 'SessionQuerySpec | None' = None, *, limit: 'int | None' = None) -> 'PathologyReport'"
- },
- {
- "async": true,
- "binding": "Polylogue.portfolio_bundle",
- "signature": "(self, spec: 'SessionQuerySpec | None' = None, *, limit: 'int | None' = None, top_n: 'int' = 10) -> 'PortfolioBundle'"
- },
- {
- "async": true,
- "binding": "Polylogue.export_insight_bundle",
- "signature": "(self, request: 'InsightExportBundleRequest') -> 'InsightExportBundleResult'"
- },
- {
- "async": true,
- "binding": "Polylogue.regenerate_private_fable_packet",
- "signature": "(self, *, seed: 'str', requested_size: 'int', schema_id: 'str' = 'delegation.discourse', schema_version: 'int' = 1, exact_template_cap: 'int' = 1) -> 'FableDelegationPacket'"
- }
- ],
- "route_class": "index-read",
- "section": "Insights and topology",
- "summary": "Read materialized archive insights, topology, and derived archive health from the index tier."
- },
- {
- "cli": {
- "intentional_absence_authority": null,
- "names": [
- "continue",
- "read"
- ]
- },
- "mcp": {
- "intentional_absence_authority": null,
- "names": [
- "context",
- "get",
- "status"
- ]
- },
- "operation_id": "api.context.delivery",
- "python": [
- {
- "async": true,
- "binding": "Polylogue.compile_context",
- "signature": "(self, spec: 'ContextSpec') -> 'ContextImage'"
- },
- {
- "async": true,
- "binding": "Polylogue.context_image_payload",
- "signature": "(self, *, project_path: 'str | None' = None, project_repo: 'str | None' = None, since: 'str | None' = None, until: 'str | None' = None, origin: 'str | None' = None, query: 'str | None' = None, max_sessions: 'int' = 5, max_tokens: 'int | None' = None, max_messages_per_session: 'int | None' = 24, max_chars_per_message: 'int | None' = 1800, include_messages: 'bool' = True, include_assertions: 'bool' = True, redact_paths: 'bool' = True, seed_session_id: 'str | None' = None) -> 'ContextImage'"
- },
- {
- "async": true,
- "binding": "Polylogue.context_preamble_payload",
- "signature": "(self, session_id: 'str', *, related_limit: 'int' = 5) -> 'Any'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_context_delivery",
- "signature": "(self, snapshot_ref: 'str', *, recipient_ref: 'str') -> 'ArchiveContextDeliveryEnvelope | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_context_deliveries",
- "signature": "(self, *, recipient_ref: 'str | None' = None, assertion_ref: 'str | None' = None, limit: 'int' = 50) -> 'list[ArchiveContextDeliveryEnvelope]'"
- },
- {
- "async": true,
- "binding": "Polylogue.record_context_delivery",
- "signature": "(self, *, image: 'ContextImage', boundary: 'str', recipient_ref: 'str', delivered_by_ref: 'str', run_ref: 'str | None' = None, inheritance_mode: 'str' = 'explicit') -> 'ArchiveContextDeliveryEnvelope'"
- },
- {
- "async": true,
- "binding": "Polylogue.compile_and_record_context",
- "signature": "(self, *, recipient_ref: 'str', delivered_by_ref: 'str', boundary: 'str', query: 'str | None' = None, max_sessions: 'int' = 5, max_tokens: 'int | None' = None, include_messages: 'bool' = True, include_assertions: 'bool' = True, redact_paths: 'bool' = True, seed_session_id: 'str | None' = None, run_ref: 'str | None' = None, inheritance_mode: 'str' = 'explicit') -> 'ArchiveContextDeliveryEnvelope'"
- },
- {
- "async": true,
- "binding": "Polylogue.correlate_hermes_context_deliveries",
- "signature": "(self, hermes_session_native_id: 'str') -> 'tuple[HermesContextDeliveryCorrelation, ...]'"
- },
- {
- "async": true,
- "binding": "Polylogue.reconcile_hermes_session_lifecycle",
- "signature": "(self, hermes_session_native_id: 'str') -> 'HermesLifecycleReconciliation | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.reconcile_codex_spawn_edges",
- "signature": "(self) -> 'CodexSpawnEdgeReconciliation | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.hermes_integration_health",
- "signature": "(self) -> 'HermesIntegrationHealth'"
- }
- ],
- "route_class": "cross-tier",
- "section": "Context and evidence",
- "summary": "Compile context and record or inspect durable delivery receipts."
- },
- {
- "cli": {
- "intentional_absence_authority": null,
- "names": [
- "mark",
- "read"
- ]
- },
- "mcp": {
- "intentional_absence_authority": null,
- "names": [
- "write",
- "judge",
- "read"
- ]
- },
- "operation_id": "api.assertion.review",
- "python": [
- {
- "async": true,
- "binding": "Polylogue.import_annotation_batch",
- "signature": "(self, request: 'AnnotationBatchImportRequest', *, registry: 'AnnotationSchemaRegistry | None' = None) -> 'AnnotationBatchImportResult'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_assertion_claims",
- "signature": "(self, *, kinds: 'Sequence[str | AssertionKind] | None' = None, target_ref: 'str | None' = None, scope_ref: 'str | None' = None, statuses: 'Sequence[str | AssertionStatus] | None' = ('active', 'candidate'), context_inject: 'bool | None' = None, limit: 'int | None' = None) -> 'list[ArchiveAssertionEnvelope]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_assertion_claim_payloads",
- "signature": "(self, *, kinds: 'Sequence[str | AssertionKind] | None' = None, target_ref: 'str | None' = None, scope_ref: 'str | None' = None, statuses: 'Sequence[str | AssertionStatus] | None' = ('active', 'candidate'), context_inject: 'bool | None' = None, limit: 'int | None' = None) -> 'list[AssertionClaimPayload]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_assertion_candidates",
- "signature": "(self, *, target_ref: 'str | None' = None, kinds: 'Sequence[str | AssertionKind] | None' = None, limit: 'int | None' = None) -> 'list[AssertionClaimPayload]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_assertion_candidate_reviews",
- "signature": "(self, *, target_ref: 'str | None' = None, kinds: 'Sequence[str | AssertionKind] | None' = None, statuses: 'Sequence[str | AssertionStatus] | None' = None, limit: 'int | None' = None) -> 'AssertionCandidateReviewListPayload'"
- },
- {
- "async": true,
- "binding": "Polylogue.assertion_candidate_queue_health",
- "signature": "(self) -> 'AssertionCandidateQueueHealthPayload'"
- },
- {
- "async": true,
- "binding": "Polylogue.judge_assertion_candidate",
- "signature": "(self, *, candidate_ref: 'str', decision: 'str', reason: 'str | None' = None, actor_ref: 'str' = 'user:local', inject: 'bool' = False, replacement_kind: 'str | None' = None, replacement_body_text: 'str | None' = None, replacement_value: 'object | None' = None) -> 'AssertionJudgmentResultPayload'"
- },
- {
- "async": true,
- "binding": "Polylogue.capture_assertion_candidate",
- "signature": "(self, *, body_text: 'str', kind: 'AssertionKind', refs: 'Sequence[str]' = (), scope_refs: 'Sequence[str]' = (), cwd: 'Path | None' = None, author_ref: 'str' = 'user:local', author_kind: 'str' = 'user', idempotency_key: 'str | None' = None, ttl_seconds: 'int | None' = None) -> 'AssertionClaimPayload'"
- },
- {
- "async": true,
- "binding": "Polylogue.judge_assertion_candidates",
- "signature": "(self, *, items: 'Sequence[Any]') -> 'AssertionBulkJudgmentPayload'"
- },
- {
- "async": true,
- "binding": "Polylogue.record_comparative_judgment",
- "signature": "(self, judgment: 'ComparativeJudgment', *, author_kind: 'str' = 'user') -> 'ArchiveAssertionEnvelope'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_comparative_judgments",
- "signature": "(self) -> 'list[ComparativeJudgment]'"
- },
- {
- "async": true,
- "binding": "Polylogue.join_typed_annotations",
- "signature": "(self, *, schema_id: 'str', schema_version: 'int', statuses: 'Sequence[str | AssertionStatus]', target_kind: 'str | None' = None, group_by: \"Sequence[Literal['repo', 'model', 'time', 'origin']]\" = (), limit: 'int' = 500, offset: 'int' = 0) -> 'AnnotationStructuralJoinResult'"
- }
- ],
- "route_class": "cross-tier",
- "section": "Assertions and judgments",
- "summary": "Read, capture, and judge durable assertions and comparative evidence."
- },
- {
- "cli": {
- "intentional_absence_authority": null,
- "names": [
- "delete"
- ]
- },
- "mcp": {
- "intentional_absence_authority": null,
- "names": [
- "write"
- ]
- },
- "operation_id": "api.archive.session-delete",
- "python": [
- {
- "async": true,
- "binding": "Polylogue.delete_session",
- "signature": "(self, session_id: 'str') -> 'bool'"
- },
- {
- "async": true,
- "binding": "Polylogue.delete_session_safe",
- "signature": "(self, session_id: 'str', *, actor: 'str' = 'user:api') -> 'DeleteSessionResult'"
- }
- ],
- "route_class": "cross-tier",
- "section": "Archive mutations",
- "summary": "Delete a session and its archive records through the shared mutation executor."
- },
- {
- "cli": {
- "intentional_absence_authority": null,
- "names": [
- "read",
- "mark"
- ]
- },
- "mcp": {
- "intentional_absence_authority": null,
- "names": [
- "read",
- "get"
- ]
- },
- "operation_id": "api.user-state.read",
- "python": [
- {
- "async": true,
- "binding": "Polylogue.list_tags",
- "signature": "(self, *, origin: 'str | None' = None) -> 'dict[str, int]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_metadata",
- "signature": "(self, session_id: 'str') -> 'dict[str, str]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_marks",
- "signature": "(self, *, mark_type: 'str | None' = None, session_id: 'str | None' = None, target_type: 'str | None' = None, target_id: 'str | None' = None, message_id: 'str | None' = None) -> 'list[dict[str, str]]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_annotation",
- "signature": "(self, annotation_id: 'str') -> 'dict[str, str] | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_annotations",
- "signature": "(self, *, session_id: 'str | None' = None, target_type: 'str | None' = None, target_id: 'str | None' = None, message_id: 'str | None' = None) -> 'list[dict[str, str]]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_view",
- "signature": "(self, view_id: 'str') -> 'dict[str, str] | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_views",
- "signature": "(self) -> 'list[dict[str, str]]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_recall_pack",
- "signature": "(self, pack_id: 'str') -> 'dict[str, str] | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_recall_packs",
- "signature": "(self) -> 'list[dict[str, str]]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_workspace",
- "signature": "(self, workspace_id: 'str') -> 'dict[str, str] | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_workspaces",
- "signature": "(self) -> 'list[dict[str, str]]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_corrections",
- "signature": "(self, *, session_id: 'str | None' = None, kind: 'str | None' = None) -> 'list[LearningCorrection]'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_blackboard_notes",
- "signature": "(self, *, kind: 'str | None' = None, scope_repo: 'str | None' = None, unresolved: 'bool' = False, limit: 'int' = 20) -> 'list[BlackboardNote]'"
- },
- {
- "async": true,
- "binding": "Polylogue.get_setting",
- "signature": "(self, setting_key: 'str') -> 'ArchiveUserSettingEnvelope | None'"
- },
- {
- "async": true,
- "binding": "Polylogue.list_settings",
- "signature": "(self) -> 'list[ArchiveUserSettingEnvelope]'"
- }
- ],
- "route_class": "user-read",
- "section": "Durable user state",
- "summary": "Read tags, marks, annotations, views, recall packs, workspaces, corrections, notes, and settings from user.db."
- },
- {
- "cli": {
- "intentional_absence_authority": null,
- "names": [
- "mark",
- "delete"
- ]
- },
- "mcp": {
- "intentional_absence_authority": null,
- "names": [
- "write"
- ]
- },
- "operation_id": "api.user-state.write",
- "python": [
- {
- "async": true,
- "binding": "Polylogue.add_tag",
- "signature": "(self, session_id: 'str', tag: 'str', *, author_ref: 'str | None' = None, author_kind: 'str | None' = None) -> 'TagMutationResult'"
- },
- {
- "async": true,
- "binding": "Polylogue.remove_tag",
- "signature": "(self, session_id: 'str', tag: 'str') -> 'TagMutationResult'"
- },
- {
- "async": true,
- "binding": "Polylogue.update_metadata",
- "signature": "(self, session_id: 'str', key: 'str', value: 'str') -> 'bool'"
- },
- {
- "async": true,
- "binding": "Polylogue.set_metadata",
- "signature": "(self, session_id: 'str', key: 'str', value: 'object') -> 'MetadataMutationResult'"
- },
- {
- "async": true,
- "binding": "Polylogue.delete_metadata",
- "signature": "(self, session_id: 'str', key: 'str') -> 'MetadataMutationResult'"
- },
- {
- "async": true,
- "binding": "Polylogue.bulk_tag_sessions",
- "signature": "(self, session_ids: 'list[str]', tags: 'list[str]', *, author_ref: 'str | None' = None, author_kind: 'str | None' = None) -> 'BulkTagMutationResult'"
- },
- {
- "async": true,
- "binding": "Polylogue.add_mark",
- "signature": "(self, session_id: 'str', mark_type: 'str', *, target_type: 'str' = 'session', target_id: 'str | None' = None, message_id: 'str | None' = None) -> 'bool'"
- },
- {
- "async": true,
- "binding": "Polylogue.remove_mark",
- "signature": "(self, session_id: 'str', mark_type: 'str', *, target_type: 'str' = 'session', target_id: 'str | None' = None, message_id: 'str | None' = None) -> 'bool'"
- },
- {
- "async": true,
- "binding": "Polylogue.save_annotation",
- "signature": "(self, annotation_id: 'str', session_id: 'str', note_text: 'str', *, target_type: 'str' = 'session', target_id: 'str | None' = None, message_id: 'str | None' = None) -> 'bool'"
- },
- {
- "async": true,
- "binding": "Polylogue.delete_annotation",
- "signature": "(self, annotation_id: 'str') -> 'bool'"
- },
- {
- "async": true,
- "binding": "Polylogue.save_view",
- "signature": "(self, view_id: 'str', name: 'str', query_json: 'str') -> 'bool'"
- },
- {
- "async": true,
- "binding": "Polylogue.delete_view",
- "signature": "(self, view_id: 'str') -> 'bool'"
- },
- {
- "async": true,
- "binding": "Polylogue.create_recall_pack",
- "signature": "(self, pack_id: 'str', label: 'str', payload_json: 'str') -> 'bool'"
- },
- {
- "async": true,
- "binding": "Polylogue.delete_recall_pack",
- "signature": "(self, pack_id: 'str') -> 'bool'"
- },
- {
- "async": true,
- "binding": "Polylogue.save_workspace",
- "signature": "(self, workspace_id: 'str', name: 'str', mode: 'str', open_targets_json: 'str', layout_json: 'str', active_target_json: 'str' = '{}') -> 'bool'"
- },
- {
- "async": true,
- "binding": "Polylogue.delete_workspace",
- "signature": "(self, workspace_id: 'str') -> 'bool'"
- },
- {
- "async": true,
- "binding": "Polylogue.record_correction",
- "signature": "(self, session_id: 'str', kind: 'str', payload: 'dict[str, str]', *, note: 'str | None' = None, author_ref: 'str | None' = None, author_kind: 'str | None' = None) -> 'LearningCorrection'"
- },
- {
- "async": true,
- "binding": "Polylogue.delete_correction",
- "signature": "(self, session_id: 'str', kind: 'str') -> 'bool'"
- },
- {
- "async": true,
- "binding": "Polylogue.clear_corrections",
- "signature": "(self, session_id: 'str') -> 'int'"
- },
- {
- "async": true,
- "binding": "Polylogue.post_blackboard_note",
- "signature": "(self, *, kind: 'str', title: 'str', content: 'str', scope_repo: 'str | None' = None, scope_session: 'str | None' = None, scope_issue: 'int | None' = None, scope_path: 'str | None' = None, related_sessions: 'tuple[str, ...]' = (), author_ref: 'str | None' = None, author_kind: 'str' = 'user', evidence_refs: 'tuple[str, ...]' = (), staleness: 'dict[str, object] | None' = None, context_policy: 'dict[str, object] | None' = None) -> 'BlackboardNote'"
- },
- {
- "async": true,
- "binding": "Polylogue.set_setting",
- "signature": "(self, setting_key: 'str', value: 'object', *, author_ref: 'str' = 'user:local') -> 'ArchiveUserSettingEnvelope'"
- }
- ],
- "route_class": "user-write",
- "section": "Durable user state",
- "summary": "Mutate tags, metadata, marks, annotations, views, recall packs, workspaces, corrections, notes, and settings in user.db."
- }
- ],
- "schema_version": 1
-}
diff --git a/docs/generated/mcp-equivalence.json b/docs/generated/mcp-equivalence.json
deleted file mode 100644
index b26a3bb81f..0000000000
--- a/docs/generated/mcp-equivalence.json
+++ /dev/null
@@ -1,1636 +0,0 @@
-{
- "authority": {
- "declarations": "polylogue/mcp/declarations/registry.py",
- "independent_name_baseline": "tests/infra/mcp.py::MCP_TOOL_NAME_BASELINE",
- "independent_output_baseline": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT",
- "live_registration": "polylogue/mcp/declarations/adapter.py",
- "migration_authority": {
- "privileged": "polylogue-t46.8.3",
- "python_parity": "polylogue-s1kr",
- "read": "polylogue-t46.8.2"
- }
- },
- "compatibility_surface": {
- "governed_python_absence_count": 4,
- "python_binding_count": 6,
- "required_capability_counts": {
- "judge": 1,
- "maintenance": 1,
- "read": 6,
- "write": 2
- },
- "tool_count": 10,
- "tool_names": [
- "query",
- "read",
- "get",
- "explain",
- "context",
- "status",
- "write",
- "judge",
- "run",
- "maintenance"
- ]
- },
- "generated_by": "devtools render mcp-equivalence",
- "migration_groups": {
- "polylogue-t46.8.2": [
- "context",
- "explain",
- "get",
- "query",
- "read",
- "status"
- ],
- "polylogue-t46.8.3": [
- "judge",
- "maintenance",
- "run",
- "write"
- ]
- },
- "python_parity": {
- "bound_tools": [
- "context",
- "explain",
- "get",
- "judge",
- "query",
- "read"
- ],
- "governed_absences": [
- "maintenance",
- "run",
- "status",
- "write"
- ]
- },
- "schema_version": 1,
- "target_algebra": {
- "default_read_transaction_count": 6,
- "default_read_transactions": [
- {
- "migration_owner": "polylogue-t46.8.2",
- "name": "query",
- "object_kinds": [
- "query",
- "result-set"
- ],
- "purpose": "Execute a declared DSL or typed plan with explicit result semantics and continuation.",
- "required_capability": "read",
- "result_semantics": [
- "exhaustive_page",
- "top_k",
- "sample",
- "aggregate"
- ],
- "verb": "query"
- },
- {
- "migration_owner": "polylogue-t46.8.2",
- "name": "read",
- "object_kinds": [
- "object-ref",
- "evidence-ref"
- ],
- "purpose": "Read any stable archive ref through a declared projection/view.",
- "required_capability": "read",
- "result_semantics": [
- "single_object",
- "exhaustive_page",
- "bounded_context"
- ],
- "verb": "read"
- },
- {
- "migration_owner": "polylogue-t46.8.2",
- "name": "get",
- "object_kinds": [
- "object-ref"
- ],
- "purpose": "Resolve one exact object identity when a generic read would add ambiguity.",
- "required_capability": "read",
- "result_semantics": [
- "single_object"
- ],
- "verb": "get"
- },
- {
- "migration_owner": "polylogue-t46.8.2",
- "name": "explain",
- "object_kinds": [
- "query",
- "object-ref",
- "capability"
- ],
- "purpose": "Discover grammar, fields, values, plans, authority, and recovery routes.",
- "required_capability": "read",
- "result_semantics": [
- "single_object"
- ],
- "verb": "explain"
- },
- {
- "migration_owner": "polylogue-t46.8.3",
- "name": "context",
- "object_kinds": [
- "context-snapshot",
- "context-delivery"
- ],
- "purpose": "Compile and retrieve policy-gated bounded context plus receipts.",
- "required_capability": "read",
- "result_semantics": [
- "bounded_context"
- ],
- "verb": "context"
- },
- {
- "migration_owner": "polylogue-t46.8.2",
- "name": "status",
- "object_kinds": [
- "status",
- "receipt"
- ],
- "purpose": "Read archive, source, embedding, coordination, and operation status.",
- "required_capability": "read",
- "result_semantics": [
- "single_object",
- "aggregate"
- ],
- "verb": "status"
- }
- ],
- "privileged_transactions": [
- {
- "migration_owner": "polylogue-t46.8.3",
- "name": "write",
- "object_kinds": [
- "object-ref",
- "assertion"
- ],
- "purpose": "Apply a declaration-owned mutation after shared authorization.",
- "required_capability": "write",
- "result_semantics": [
- "mutation"
- ],
- "verb": "write"
- },
- {
- "migration_owner": "polylogue-t46.8.3",
- "name": "judge",
- "object_kinds": [
- "assertion-candidate",
- "judgment"
- ],
- "purpose": "Accept, reject, defer, or supersede candidates without collapsing candidate state.",
- "required_capability": "judge",
- "result_semantics": [
- "mutation"
- ],
- "verb": "judge"
- },
- {
- "migration_owner": "polylogue-t46.8.3",
- "name": "run",
- "object_kinds": [
- "saved-query",
- "recipe",
- "result-set"
- ],
- "purpose": "Execute a saved query or governed recipe ref.",
- "required_capability": "write",
- "result_semantics": [
- "exhaustive_page",
- "mutation"
- ],
- "verb": "run"
- },
- {
- "migration_owner": "polylogue-t46.8.3",
- "name": "maintenance",
- "object_kinds": [
- "maintenance-plan",
- "maintenance-operation"
- ],
- "purpose": "Preview, authorize, execute, inspect, and reconcile maintenance operations.",
- "required_capability": "maintenance",
- "result_semantics": [
- "maintenance"
- ],
- "verb": "maintenance"
- }
- ],
- "prompts": [
- {
- "migration_owner": "polylogue-t46.8.2",
- "mutation_authority": "none",
- "name": "resume_context",
- "required_capability": null,
- "workflow": "resume"
- },
- {
- "migration_owner": "polylogue-t46.8.2",
- "mutation_authority": "none",
- "name": "postmortem_last",
- "required_capability": null,
- "workflow": "postmortem"
- },
- {
- "migration_owner": "polylogue-t46.8.2",
- "mutation_authority": "none",
- "name": "decisions_about",
- "required_capability": null,
- "workflow": "decision-recovery"
- },
- {
- "migration_owner": "polylogue-t46.8.2",
- "mutation_authority": "none",
- "name": "unacknowledged_failures",
- "required_capability": null,
- "workflow": "failure-recovery"
- },
- {
- "migration_owner": "polylogue-t46.8.2",
- "mutation_authority": "none",
- "name": "sessions_touching_file",
- "required_capability": null,
- "workflow": "file-touch"
- },
- {
- "migration_owner": "polylogue-t46.8.2",
- "mutation_authority": "none",
- "name": "cost_of",
- "required_capability": null,
- "workflow": "cost-analysis"
- },
- {
- "migration_owner": "polylogue-t46.8.3",
- "mutation_authority": "none",
- "name": "agent_coordination_brief",
- "required_capability": null,
- "workflow": "coordination"
- },
- {
- "migration_owner": "polylogue-il50",
- "mutation_authority": "none",
- "name": "analyze_errors",
- "required_capability": null,
- "workflow": "error-analysis"
- },
- {
- "migration_owner": "polylogue-il50",
- "mutation_authority": "none",
- "name": "summarize_week",
- "required_capability": null,
- "workflow": "weekly-summary"
- },
- {
- "migration_owner": "polylogue-il50",
- "mutation_authority": "none",
- "name": "extract_code",
- "required_capability": null,
- "workflow": "code-extraction"
- },
- {
- "migration_owner": "polylogue-il50",
- "mutation_authority": "none",
- "name": "compare_sessions",
- "required_capability": null,
- "workflow": "session-comparison"
- },
- {
- "migration_owner": "polylogue-il50",
- "mutation_authority": "none",
- "name": "extract_patterns",
- "required_capability": null,
- "workflow": "pattern-extraction"
- }
- ],
- "resources": [
- {
- "authority": "read-only object projection; resources never acquire instruction or mutation authority",
- "migration_owner": "polylogue-t46.8.2",
- "object_kinds": [
- "session"
- ],
- "required_capability": null,
- "uri_template": "polylogue://session/{id}"
- },
- {
- "authority": "read-only object projection; resources never acquire instruction or mutation authority",
- "migration_owner": "polylogue-t46.8.2",
- "object_kinds": [
- "message"
- ],
- "required_capability": null,
- "uri_template": "polylogue://message/{id}"
- },
- {
- "authority": "read-only object projection; resources never acquire instruction or mutation authority",
- "migration_owner": "polylogue-t46.8.2",
- "object_kinds": [
- "block"
- ],
- "required_capability": null,
- "uri_template": "polylogue://block/{id}"
- },
- {
- "authority": "read-only object projection; resources never acquire instruction or mutation authority",
- "migration_owner": "polylogue-t46.8.2",
- "object_kinds": [
- "action"
- ],
- "required_capability": null,
- "uri_template": "polylogue://action/{id}"
- },
- {
- "authority": "read-only object projection; resources never acquire instruction or mutation authority",
- "migration_owner": "polylogue-t46.8.2",
- "object_kinds": [
- "file"
- ],
- "required_capability": null,
- "uri_template": "polylogue://file/{id}"
- },
- {
- "authority": "read-only object projection; resources never acquire instruction or mutation authority",
- "migration_owner": "polylogue-t46.8.2",
- "object_kinds": [
- "query"
- ],
- "required_capability": null,
- "uri_template": "polylogue://query/{id}"
- },
- {
- "authority": "read-only object projection; resources never acquire instruction or mutation authority",
- "migration_owner": "polylogue-t46.8.2",
- "object_kinds": [
- "result-set"
- ],
- "required_capability": null,
- "uri_template": "polylogue://result-set/{id}"
- },
- {
- "authority": "read-only object projection; resources never acquire instruction or mutation authority",
- "migration_owner": "polylogue-t46.8.3",
- "object_kinds": [
- "recall-pack"
- ],
- "required_capability": null,
- "uri_template": "polylogue://recall-pack/{id}"
- },
- {
- "authority": "executable query vocabulary and recovery guidance; no mutation authority",
- "migration_owner": "polylogue-z9gh.3",
- "object_kinds": [
- "capability",
- "query",
- "result-set"
- ],
- "required_capability": null,
- "uri_template": "polylogue://capabilities/query"
- }
- ]
- },
- "tools": [
- {
- "canonical_plan": "polylogue.api.Polylogue.query_units",
- "canonical_projection": "envelope:root",
- "capability": "read:query",
- "compatibility_route": "query",
- "continuation": {
- "continuation_ref": "q2",
- "exhaustive_route": null,
- "mode": "cursor_or_offset",
- "notes": "Continuation is opaque and must be the only resume input."
- },
- "deprecation_state": "retained",
- "description": "Execute a parser-owned terminal query page or resume its q2 continuation.",
- "field_discovery": [
- "polylogue://capabilities/query"
- ],
- "grammar_discovery": [
- "polylogue://capabilities/query"
- ],
- "incident_coverage": [
- "z9gh-workflow-incident"
- ],
- "input_contract": {
- "required_arguments": [
- "expression"
- ],
- "schema_mode": "FastMCP derives inputSchema from the cutover handler signature",
- "schema_source": "polylogue.mcp.server_cutover.query:inspect.signature"
- },
- "kernel": {
- "compatibility": {
- "access_result_shape": "query:exhaustive_page:envelope",
- "authority": "mcp-capability:read",
- "durability": "transport-adapter; domain-owner-controls-durability",
- "identity": "mcp-tool:query,result-set",
- "lifecycle": "registered-handler-retained"
- },
- "completeness_edges": [
- {
- "consumer": "tests.infra.mcp.EXPECTED_TOOL_NAMES",
- "kind": "discovery-name-equivalence",
- "owner_path": "tests/infra/mcp.py",
- "producer": "mcp.tool.query"
- }
- ],
- "declaration_id": "mcp.tool.query",
- "discovery_text": "Execute a parser-owned terminal query page or resume its q2 continuation.",
- "examples": [
- {
- "arguments": [
- [
- "expression",
- "messages where text:needle"
- ]
- ],
- "name": "minimal-valid-call",
- "summary": "Minimal cutover invocation for query."
- }
- ],
- "family_id": "mcp.tool.query",
- "handlers": [
- {
- "binding_key": "polylogue.mcp.server_cutover:query",
- "owner_path": "polylogue/mcp/server_cutover.py",
- "surface": "mcp",
- "symbol": "query"
- }
- ],
- "outputs": [
- {
- "kind": "envelope",
- "name": "runtime-contract",
- "schema_ref": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT",
- "target_path": "mcp://tool/query"
- }
- ],
- "owner_path": "polylogue/mcp/declarations/registry.py",
- "producer": "polylogue.api.Polylogue.query_units",
- "public_name": "query",
- "repair_command": "devtools render mcp-equivalence",
- "role_gate": "mcp.capability:read",
- "schema_ref": "polylogue.mcp.server_cutover.query:inspect.signature"
- },
- "minimal_arguments": {
- "expression": "messages where text:needle"
- },
- "name": "query",
- "object_kinds": [
- "query",
- "result-set"
- ],
- "observed_use": "observed",
- "operation_owner": "polylogue.api.Polylogue.query_units",
- "output_contract": {
- "envelope_fields": [
- "items",
- "query_ref",
- "result_ref",
- "continuation"
- ],
- "kind": "envelope",
- "schema_source": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT"
- },
- "prompt_alternatives": [],
- "python_parity": {
- "binding": "polylogue.api.Polylogue.query_units",
- "intentional_absence_authority": null,
- "reason": null
- },
- "registration": {
- "module": "polylogue.mcp.server_cutover",
- "registrar": "register_cutover_read_tools",
- "symbol": "query"
- },
- "required_capability": null,
- "resource_alternatives": [
- "polylogue://capabilities/query"
- ],
- "result_semantics": "exhaustive_page",
- "retirement_owner": "polylogue-t46.8.2",
- "telemetry_key": "query",
- "value_discovery": [
- "polylogue://capabilities/query"
- ],
- "verb": "query",
- "workflow_coverage": [
- "t8t-continuity",
- "z9gh-workflow-incident"
- ]
- },
- {
- "canonical_plan": "polylogue.api.Polylogue.resolve_ref",
- "canonical_projection": "envelope:root",
- "capability": "read:read",
- "compatibility_route": "read",
- "continuation": {
- "continuation_ref": "q2",
- "exhaustive_route": "query",
- "mode": "cursor_or_offset",
- "notes": "Continuation is opaque and must be the only resume input."
- },
- "deprecation_state": "retained",
- "description": "Read a stable archive URI or public ref through a declared view.",
- "field_discovery": [
- "polylogue://capabilities/query"
- ],
- "grammar_discovery": [
- "polylogue://capabilities/query"
- ],
- "incident_coverage": [
- "z9gh-workflow-incident"
- ],
- "input_contract": {
- "required_arguments": [
- "ref"
- ],
- "schema_mode": "FastMCP derives inputSchema from the cutover handler signature",
- "schema_source": "polylogue.mcp.server_cutover.read:inspect.signature"
- },
- "kernel": {
- "compatibility": {
- "access_result_shape": "read:exhaustive_page:envelope",
- "authority": "mcp-capability:read",
- "durability": "transport-adapter; domain-owner-controls-durability",
- "identity": "mcp-tool:object-ref,evidence-ref",
- "lifecycle": "registered-handler-retained"
- },
- "completeness_edges": [
- {
- "consumer": "tests.infra.mcp.EXPECTED_TOOL_NAMES",
- "kind": "discovery-name-equivalence",
- "owner_path": "tests/infra/mcp.py",
- "producer": "mcp.tool.read"
- }
- ],
- "declaration_id": "mcp.tool.read",
- "discovery_text": "Read a stable archive URI or public ref through a declared view.",
- "examples": [
- {
- "arguments": [
- [
- "ref",
- "session:codex-session:demo"
- ]
- ],
- "name": "minimal-valid-call",
- "summary": "Minimal cutover invocation for read."
- }
- ],
- "family_id": "mcp.tool.read",
- "handlers": [
- {
- "binding_key": "polylogue.mcp.server_cutover:read",
- "owner_path": "polylogue/mcp/server_cutover.py",
- "surface": "mcp",
- "symbol": "read"
- }
- ],
- "outputs": [
- {
- "kind": "envelope",
- "name": "runtime-contract",
- "schema_ref": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT",
- "target_path": "mcp://tool/read"
- }
- ],
- "owner_path": "polylogue/mcp/declarations/registry.py",
- "producer": "polylogue.api.Polylogue.resolve_ref",
- "public_name": "read",
- "repair_command": "devtools render mcp-equivalence",
- "role_gate": "mcp.capability:read",
- "schema_ref": "polylogue.mcp.server_cutover.read:inspect.signature"
- },
- "minimal_arguments": {
- "ref": "session:codex-session:demo"
- },
- "name": "read",
- "object_kinds": [
- "object-ref",
- "evidence-ref"
- ],
- "observed_use": "observed",
- "operation_owner": "polylogue.api.Polylogue.resolve_ref",
- "output_contract": {
- "envelope_fields": [
- "ref"
- ],
- "kind": "envelope",
- "schema_source": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT"
- },
- "prompt_alternatives": [],
- "python_parity": {
- "binding": "polylogue.api.Polylogue.resolve_ref",
- "intentional_absence_authority": null,
- "reason": null
- },
- "registration": {
- "module": "polylogue.mcp.server_cutover",
- "registrar": "register_cutover_read_tools",
- "symbol": "read"
- },
- "required_capability": null,
- "resource_alternatives": [
- "polylogue://capabilities/query"
- ],
- "result_semantics": "exhaustive_page",
- "retirement_owner": "polylogue-t46.8.2",
- "telemetry_key": "read",
- "value_discovery": [
- "polylogue://capabilities/query"
- ],
- "verb": "read",
- "workflow_coverage": [
- "t8t-continuity",
- "z9gh-workflow-incident"
- ]
- },
- {
- "canonical_plan": "polylogue.api.Polylogue.resolve_ref",
- "canonical_projection": "single_object:root",
- "capability": "read:get",
- "compatibility_route": "get",
- "continuation": {
- "continuation_ref": null,
- "exhaustive_route": "query",
- "mode": "none",
- "notes": "Continuation is opaque and must be the only resume input."
- },
- "deprecation_state": "retained",
- "description": "Resolve one exact stable object or evidence identity.",
- "field_discovery": [
- "polylogue://capabilities/query"
- ],
- "grammar_discovery": [
- "polylogue://capabilities/query"
- ],
- "incident_coverage": [
- "z9gh-workflow-incident"
- ],
- "input_contract": {
- "required_arguments": [
- "ref"
- ],
- "schema_mode": "FastMCP derives inputSchema from the cutover handler signature",
- "schema_source": "polylogue.mcp.server_cutover.get:inspect.signature"
- },
- "kernel": {
- "compatibility": {
- "access_result_shape": "get:single_object:single_object",
- "authority": "mcp-capability:read",
- "durability": "transport-adapter; domain-owner-controls-durability",
- "identity": "mcp-tool:object-ref",
- "lifecycle": "registered-handler-retained"
- },
- "completeness_edges": [
- {
- "consumer": "tests.infra.mcp.EXPECTED_TOOL_NAMES",
- "kind": "discovery-name-equivalence",
- "owner_path": "tests/infra/mcp.py",
- "producer": "mcp.tool.get"
- }
- ],
- "declaration_id": "mcp.tool.get",
- "discovery_text": "Resolve one exact stable object or evidence identity.",
- "examples": [
- {
- "arguments": [
- [
- "ref",
- "session:codex-session:demo"
- ]
- ],
- "name": "minimal-valid-call",
- "summary": "Minimal cutover invocation for get."
- }
- ],
- "family_id": "mcp.tool.get",
- "handlers": [
- {
- "binding_key": "polylogue.mcp.server_cutover:get",
- "owner_path": "polylogue/mcp/server_cutover.py",
- "surface": "mcp",
- "symbol": "get"
- }
- ],
- "outputs": [
- {
- "kind": "single_object",
- "name": "runtime-contract",
- "schema_ref": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT",
- "target_path": "mcp://tool/get"
- }
- ],
- "owner_path": "polylogue/mcp/declarations/registry.py",
- "producer": "polylogue.api.Polylogue.resolve_ref",
- "public_name": "get",
- "repair_command": "devtools render mcp-equivalence",
- "role_gate": "mcp.capability:read",
- "schema_ref": "polylogue.mcp.server_cutover.get:inspect.signature"
- },
- "minimal_arguments": {
- "ref": "session:codex-session:demo"
- },
- "name": "get",
- "object_kinds": [
- "object-ref"
- ],
- "observed_use": "observed",
- "operation_owner": "polylogue.api.Polylogue.resolve_ref",
- "output_contract": {
- "envelope_fields": [
- "ref"
- ],
- "kind": "single_object",
- "schema_source": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT"
- },
- "prompt_alternatives": [],
- "python_parity": {
- "binding": "polylogue.api.Polylogue.resolve_ref",
- "intentional_absence_authority": null,
- "reason": null
- },
- "registration": {
- "module": "polylogue.mcp.server_cutover",
- "registrar": "register_cutover_read_tools",
- "symbol": "get"
- },
- "required_capability": null,
- "resource_alternatives": [
- "polylogue://capabilities/query"
- ],
- "result_semantics": "single_object",
- "retirement_owner": "polylogue-t46.8.2",
- "telemetry_key": "get",
- "value_discovery": [
- "polylogue://capabilities/query"
- ],
- "verb": "get",
- "workflow_coverage": [
- "t8t-continuity",
- "z9gh-workflow-incident"
- ]
- },
- {
- "canonical_plan": "polylogue.api.Polylogue.explain_query_expression",
- "canonical_projection": "single_object:root",
- "capability": "read:explain",
- "compatibility_route": "explain",
- "continuation": {
- "continuation_ref": null,
- "exhaustive_route": "query",
- "mode": "none",
- "notes": "Continuation is opaque and must be the only resume input."
- },
- "deprecation_state": "retained",
- "description": "Explain parser grammar, capabilities, refs, result semantics, or recovery.",
- "field_discovery": [
- "polylogue://capabilities/query"
- ],
- "grammar_discovery": [
- "polylogue://capabilities/query"
- ],
- "incident_coverage": [
- "z9gh-workflow-incident"
- ],
- "input_contract": {
- "required_arguments": [
- "subject"
- ],
- "schema_mode": "FastMCP derives inputSchema from the cutover handler signature",
- "schema_source": "polylogue.mcp.server_cutover.explain:inspect.signature"
- },
- "kernel": {
- "compatibility": {
- "access_result_shape": "explain:single_object:single_object",
- "authority": "mcp-capability:read",
- "durability": "transport-adapter; domain-owner-controls-durability",
- "identity": "mcp-tool:query,capability,object-ref",
- "lifecycle": "registered-handler-retained"
- },
- "completeness_edges": [
- {
- "consumer": "tests.infra.mcp.EXPECTED_TOOL_NAMES",
- "kind": "discovery-name-equivalence",
- "owner_path": "tests/infra/mcp.py",
- "producer": "mcp.tool.explain"
- }
- ],
- "declaration_id": "mcp.tool.explain",
- "discovery_text": "Explain parser grammar, capabilities, refs, result semantics, or recovery.",
- "examples": [
- {
- "arguments": [
- [
- "subject",
- "capability"
- ]
- ],
- "name": "minimal-valid-call",
- "summary": "Minimal cutover invocation for explain."
- }
- ],
- "family_id": "mcp.tool.explain",
- "handlers": [
- {
- "binding_key": "polylogue.mcp.server_cutover:explain",
- "owner_path": "polylogue/mcp/server_cutover.py",
- "surface": "mcp",
- "symbol": "explain"
- }
- ],
- "outputs": [
- {
- "kind": "single_object",
- "name": "runtime-contract",
- "schema_ref": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT",
- "target_path": "mcp://tool/explain"
- }
- ],
- "owner_path": "polylogue/mcp/declarations/registry.py",
- "producer": "polylogue.api.Polylogue.explain_query_expression",
- "public_name": "explain",
- "repair_command": "devtools render mcp-equivalence",
- "role_gate": "mcp.capability:read",
- "schema_ref": "polylogue.mcp.server_cutover.explain:inspect.signature"
- },
- "minimal_arguments": {
- "subject": "capability"
- },
- "name": "explain",
- "object_kinds": [
- "query",
- "capability",
- "object-ref"
- ],
- "observed_use": "observed",
- "operation_owner": "polylogue.api.Polylogue.explain_query_expression",
- "output_contract": {
- "envelope_fields": [
- "subject"
- ],
- "kind": "single_object",
- "schema_source": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT"
- },
- "prompt_alternatives": [],
- "python_parity": {
- "binding": "polylogue.api.Polylogue.explain_query_expression",
- "intentional_absence_authority": null,
- "reason": null
- },
- "registration": {
- "module": "polylogue.mcp.server_cutover",
- "registrar": "register_cutover_read_tools",
- "symbol": "explain"
- },
- "required_capability": null,
- "resource_alternatives": [
- "polylogue://capabilities/query"
- ],
- "result_semantics": "single_object",
- "retirement_owner": "polylogue-t46.8.2",
- "telemetry_key": "explain",
- "value_discovery": [
- "polylogue://capabilities/query"
- ],
- "verb": "explain",
- "workflow_coverage": [
- "t8t-continuity",
- "z9gh-workflow-incident"
- ]
- },
- {
- "canonical_plan": "polylogue.api.Polylogue.context_image_payload",
- "canonical_projection": "single_object:root",
- "capability": "read:context",
- "compatibility_route": "context",
- "continuation": {
- "continuation_ref": null,
- "exhaustive_route": "query",
- "mode": "none",
- "notes": "Continuation is opaque and must be the only resume input."
- },
- "deprecation_state": "retained",
- "description": "Compile a policy-gated bounded context image with receipts.",
- "field_discovery": [
- "polylogue://capabilities/query"
- ],
- "grammar_discovery": [
- "polylogue://capabilities/query"
- ],
- "incident_coverage": [
- "z9gh-workflow-incident"
- ],
- "input_contract": {
- "required_arguments": [
- "intent"
- ],
- "schema_mode": "FastMCP derives inputSchema from the cutover handler signature",
- "schema_source": "polylogue.mcp.server_cutover.context:inspect.signature"
- },
- "kernel": {
- "compatibility": {
- "access_result_shape": "context:bounded_context:single_object",
- "authority": "mcp-capability:read",
- "durability": "transport-adapter; domain-owner-controls-durability",
- "identity": "mcp-tool:context-snapshot,context-delivery",
- "lifecycle": "registered-handler-retained"
- },
- "completeness_edges": [
- {
- "consumer": "tests.infra.mcp.EXPECTED_TOOL_NAMES",
- "kind": "discovery-name-equivalence",
- "owner_path": "tests/infra/mcp.py",
- "producer": "mcp.tool.context"
- }
- ],
- "declaration_id": "mcp.tool.context",
- "discovery_text": "Compile a policy-gated bounded context image with receipts.",
- "examples": [
- {
- "arguments": [
- [
- "intent",
- "resume"
- ]
- ],
- "name": "minimal-valid-call",
- "summary": "Minimal cutover invocation for context."
- }
- ],
- "family_id": "mcp.tool.context",
- "handlers": [
- {
- "binding_key": "polylogue.mcp.server_cutover:context",
- "owner_path": "polylogue/mcp/server_cutover.py",
- "surface": "mcp",
- "symbol": "context"
- }
- ],
- "outputs": [
- {
- "kind": "single_object",
- "name": "runtime-contract",
- "schema_ref": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT",
- "target_path": "mcp://tool/context"
- }
- ],
- "owner_path": "polylogue/mcp/declarations/registry.py",
- "producer": "polylogue.api.Polylogue.context_image_payload",
- "public_name": "context",
- "repair_command": "devtools render mcp-equivalence",
- "role_gate": "mcp.capability:read",
- "schema_ref": "polylogue.mcp.server_cutover.context:inspect.signature"
- },
- "minimal_arguments": {
- "intent": "resume"
- },
- "name": "context",
- "object_kinds": [
- "context-snapshot",
- "context-delivery"
- ],
- "observed_use": "observed",
- "operation_owner": "polylogue.api.Polylogue.context_image_payload",
- "output_contract": {
- "envelope_fields": [
- "receipt"
- ],
- "kind": "single_object",
- "schema_source": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT"
- },
- "prompt_alternatives": [],
- "python_parity": {
- "binding": "polylogue.api.Polylogue.context_image_payload",
- "intentional_absence_authority": null,
- "reason": null
- },
- "registration": {
- "module": "polylogue.mcp.server_cutover",
- "registrar": "register_cutover_read_tools",
- "symbol": "context"
- },
- "required_capability": null,
- "resource_alternatives": [
- "polylogue://capabilities/query"
- ],
- "result_semantics": "bounded_context",
- "retirement_owner": "polylogue-t46.8.2",
- "telemetry_key": "context",
- "value_discovery": [
- "polylogue://capabilities/query"
- ],
- "verb": "context",
- "workflow_coverage": [
- "t8t-continuity",
- "z9gh-workflow-incident"
- ]
- },
- {
- "canonical_plan": "polylogue.storage.sqlite.archive_tiers.archive.ArchiveStore.stats",
- "canonical_projection": "single_object:root",
- "capability": "read:status",
- "compatibility_route": "status",
- "continuation": {
- "continuation_ref": null,
- "exhaustive_route": "query",
- "mode": "none",
- "notes": "Continuation is opaque and must be the only resume input."
- },
- "deprecation_state": "retained",
- "description": "Report compact archive authority and readiness status.",
- "field_discovery": [
- "polylogue://capabilities/query"
- ],
- "grammar_discovery": [
- "polylogue://capabilities/query"
- ],
- "incident_coverage": [
- "z9gh-workflow-incident"
- ],
- "input_contract": {
- "required_arguments": [
- "scope"
- ],
- "schema_mode": "FastMCP derives inputSchema from the cutover handler signature",
- "schema_source": "polylogue.mcp.server_cutover.status:inspect.signature"
- },
- "kernel": {
- "compatibility": {
- "access_result_shape": "status:single_object:single_object",
- "authority": "mcp-capability:read",
- "durability": "transport-adapter; domain-owner-controls-durability",
- "identity": "mcp-tool:status",
- "lifecycle": "registered-handler-retained"
- },
- "completeness_edges": [
- {
- "consumer": "tests.infra.mcp.EXPECTED_TOOL_NAMES",
- "kind": "discovery-name-equivalence",
- "owner_path": "tests/infra/mcp.py",
- "producer": "mcp.tool.status"
- }
- ],
- "declaration_id": "mcp.tool.status",
- "discovery_text": "Report compact archive authority and readiness status.",
- "examples": [
- {
- "arguments": [
- [
- "scope",
- "archive"
- ]
- ],
- "name": "minimal-valid-call",
- "summary": "Minimal cutover invocation for status."
- }
- ],
- "family_id": "mcp.tool.status",
- "handlers": [
- {
- "binding_key": "polylogue.mcp.server_cutover:status",
- "owner_path": "polylogue/mcp/server_cutover.py",
- "surface": "mcp",
- "symbol": "status"
- }
- ],
- "outputs": [
- {
- "kind": "single_object",
- "name": "runtime-contract",
- "schema_ref": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT",
- "target_path": "mcp://tool/status"
- }
- ],
- "owner_path": "polylogue/mcp/declarations/registry.py",
- "producer": "polylogue.storage.sqlite.archive_tiers.archive.ArchiveStore.stats",
- "public_name": "status",
- "repair_command": "devtools render mcp-equivalence",
- "role_gate": "mcp.capability:read",
- "schema_ref": "polylogue.mcp.server_cutover.status:inspect.signature"
- },
- "minimal_arguments": {
- "scope": "archive"
- },
- "name": "status",
- "object_kinds": [
- "status"
- ],
- "observed_use": "observed",
- "operation_owner": "polylogue.storage.sqlite.archive_tiers.archive.ArchiveStore.stats",
- "output_contract": {
- "envelope_fields": [
- "archive"
- ],
- "kind": "single_object",
- "schema_source": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT"
- },
- "prompt_alternatives": [],
- "python_parity": {
- "binding": null,
- "intentional_absence_authority": "polylogue-s1kr",
- "reason": "The current MCP compatibility handler binds a lower-level owner or transport-only projection; polylogue-s1kr owns any public Python facade addition and docs parity."
- },
- "registration": {
- "module": "polylogue.mcp.server_cutover",
- "registrar": "register_cutover_read_tools",
- "symbol": "status"
- },
- "required_capability": null,
- "resource_alternatives": [
- "polylogue://capabilities/query"
- ],
- "result_semantics": "single_object",
- "retirement_owner": "polylogue-t46.8.2",
- "telemetry_key": "status",
- "value_discovery": [
- "polylogue://capabilities/query"
- ],
- "verb": "status",
- "workflow_coverage": [
- "t8t-continuity",
- "z9gh-workflow-incident"
- ]
- },
- {
- "canonical_plan": "mutate-write",
- "canonical_projection": "operation_result:root",
- "capability": "write:write",
- "compatibility_route": "write",
- "continuation": {
- "continuation_ref": null,
- "exhaustive_route": "query",
- "mode": "none",
- "notes": "Continuation is opaque and must be the only resume input."
- },
- "deprecation_state": "retained",
- "description": "Apply a declared mutation operation after shared authorization. Destructive operations (delete_session, remove_tag, remove_mark, delete_metadata, delete_annotation, delete_saved_view, delete_recall_pack, delete_workspace) require confirm=true and fail closed without it.",
- "field_discovery": [],
- "grammar_discovery": [],
- "incident_coverage": [],
- "input_contract": {
- "required_arguments": [
- "operation"
- ],
- "schema_mode": "FastMCP derives inputSchema from the cutover handler signature",
- "schema_source": "polylogue.mcp.server_cutover.write:inspect.signature"
- },
- "kernel": {
- "compatibility": {
- "access_result_shape": "write:mutation:operation_result",
- "authority": "mcp-capability:write",
- "durability": "transport-adapter; domain-owner-controls-durability",
- "identity": "mcp-tool:object-ref,assertion",
- "lifecycle": "registered-handler-retained"
- },
- "completeness_edges": [
- {
- "consumer": "tests.infra.mcp.EXPECTED_TOOL_NAMES",
- "kind": "discovery-name-equivalence",
- "owner_path": "tests/infra/mcp.py",
- "producer": "mcp.tool.write"
- }
- ],
- "declaration_id": "mcp.tool.write",
- "discovery_text": "Apply a declared mutation operation after shared authorization. Destructive operations (delete_session, remove_tag, remove_mark, delete_metadata, delete_annotation, delete_saved_view, delete_recall_pack, delete_workspace) require confirm=true and fail closed without it.",
- "examples": [
- {
- "arguments": [
- [
- "operation",
- "add_tag"
- ],
- [
- "session_id",
- "test:conv-mutation"
- ],
- [
- "tag",
- "review"
- ]
- ],
- "name": "minimal-valid-call",
- "summary": "Minimal cutover invocation for write."
- }
- ],
- "family_id": "mcp.tool.write",
- "handlers": [
- {
- "binding_key": "polylogue.mcp.server_cutover:write",
- "owner_path": "polylogue/mcp/server_cutover.py",
- "surface": "mcp",
- "symbol": "write"
- }
- ],
- "outputs": [
- {
- "kind": "operation_result",
- "name": "runtime-contract",
- "schema_ref": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT",
- "target_path": "mcp://tool/write"
- }
- ],
- "owner_path": "polylogue/mcp/declarations/registry.py",
- "producer": "mutate-write",
- "public_name": "write",
- "repair_command": "devtools render mcp-equivalence",
- "role_gate": "mcp.capability:write",
- "schema_ref": "polylogue.mcp.server_cutover.write:inspect.signature"
- },
- "minimal_arguments": {
- "operation": "add_tag",
- "session_id": "test:conv-mutation",
- "tag": "review"
- },
- "name": "write",
- "object_kinds": [
- "object-ref",
- "assertion"
- ],
- "observed_use": "observed",
- "operation_owner": "mutate-write",
- "output_contract": {
- "envelope_fields": [],
- "kind": "operation_result",
- "schema_source": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT"
- },
- "prompt_alternatives": [],
- "python_parity": {
- "binding": null,
- "intentional_absence_authority": "polylogue-s1kr",
- "reason": "The current MCP compatibility handler binds a lower-level owner or transport-only projection; polylogue-s1kr owns any public Python facade addition and docs parity."
- },
- "registration": {
- "module": "polylogue.mcp.server_cutover",
- "registrar": "register_cutover_privileged_tools",
- "symbol": "write"
- },
- "required_capability": "write",
- "resource_alternatives": [],
- "result_semantics": "mutation",
- "retirement_owner": "polylogue-t46.8.3",
- "telemetry_key": "write",
- "value_discovery": [],
- "verb": "write",
- "workflow_coverage": [
- "t46.8.3-privileged-contract"
- ]
- },
- {
- "canonical_plan": "polylogue.api.Polylogue.judge_assertion_candidates",
- "canonical_projection": "envelope:root",
- "capability": "judge:judge",
- "compatibility_route": "judge",
- "continuation": {
- "continuation_ref": null,
- "exhaustive_route": "query",
- "mode": "none",
- "notes": "Continuation is opaque and must be the only resume input."
- },
- "deprecation_state": "retained",
- "description": "Accept, reject, defer, or supersede assertion candidates without collapsing candidate state.",
- "field_discovery": [],
- "grammar_discovery": [],
- "incident_coverage": [],
- "input_contract": {
- "required_arguments": [],
- "schema_mode": "FastMCP derives inputSchema from the cutover handler signature",
- "schema_source": "polylogue.mcp.server_cutover.judge:inspect.signature"
- },
- "kernel": {
- "compatibility": {
- "access_result_shape": "judge:mutation:envelope",
- "authority": "mcp-capability:judge",
- "durability": "transport-adapter; domain-owner-controls-durability",
- "identity": "mcp-tool:assertion-candidate,judgment",
- "lifecycle": "registered-handler-retained"
- },
- "completeness_edges": [
- {
- "consumer": "tests.infra.mcp.EXPECTED_TOOL_NAMES",
- "kind": "discovery-name-equivalence",
- "owner_path": "tests/infra/mcp.py",
- "producer": "mcp.tool.judge"
- }
- ],
- "declaration_id": "mcp.tool.judge",
- "discovery_text": "Accept, reject, defer, or supersede assertion candidates without collapsing candidate state.",
- "examples": [
- {
- "arguments": [
- [
- "candidate_ref",
- "assertion:contract-candidate"
- ],
- [
- "decision",
- "accept"
- ]
- ],
- "name": "minimal-valid-call",
- "summary": "Minimal cutover invocation for judge."
- }
- ],
- "family_id": "mcp.tool.judge",
- "handlers": [
- {
- "binding_key": "polylogue.mcp.server_cutover:judge",
- "owner_path": "polylogue/mcp/server_cutover.py",
- "surface": "mcp",
- "symbol": "judge"
- }
- ],
- "outputs": [
- {
- "kind": "envelope",
- "name": "runtime-contract",
- "schema_ref": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT",
- "target_path": "mcp://tool/judge"
- }
- ],
- "owner_path": "polylogue/mcp/declarations/registry.py",
- "producer": "polylogue.api.Polylogue.judge_assertion_candidates",
- "public_name": "judge",
- "repair_command": "devtools render mcp-equivalence",
- "role_gate": "mcp.capability:judge",
- "schema_ref": "polylogue.mcp.server_cutover.judge:inspect.signature"
- },
- "minimal_arguments": {
- "candidate_ref": "assertion:contract-candidate",
- "decision": "accept"
- },
- "name": "judge",
- "object_kinds": [
- "assertion-candidate",
- "judgment"
- ],
- "observed_use": "observed",
- "operation_owner": "polylogue.api.Polylogue.judge_assertion_candidates",
- "output_contract": {
- "envelope_fields": [
- "items",
- "applied_count",
- "failed_count"
- ],
- "kind": "envelope",
- "schema_source": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT"
- },
- "prompt_alternatives": [],
- "python_parity": {
- "binding": "polylogue.api.Polylogue.judge_assertion_candidates",
- "intentional_absence_authority": null,
- "reason": null
- },
- "registration": {
- "module": "polylogue.mcp.server_cutover",
- "registrar": "register_cutover_privileged_tools",
- "symbol": "judge"
- },
- "required_capability": "judge",
- "resource_alternatives": [],
- "result_semantics": "mutation",
- "retirement_owner": "polylogue-t46.8.3",
- "telemetry_key": "judge",
- "value_discovery": [],
- "verb": "judge",
- "workflow_coverage": [
- "t46.8.3-privileged-contract"
- ]
- },
- {
- "canonical_plan": "mutate-run",
- "canonical_projection": "envelope:root",
- "capability": "write:run",
- "compatibility_route": "run",
- "continuation": {
- "continuation_ref": null,
- "exhaustive_route": "query",
- "mode": "none",
- "notes": "Continuation is opaque and must be the only resume input."
- },
- "deprecation_state": "retained",
- "description": "Execute a saved query or governed recipe ref.",
- "field_discovery": [],
- "grammar_discovery": [],
- "incident_coverage": [],
- "input_contract": {
- "required_arguments": [
- "ref"
- ],
- "schema_mode": "FastMCP derives inputSchema from the cutover handler signature",
- "schema_source": "polylogue.mcp.server_cutover.run:inspect.signature"
- },
- "kernel": {
- "compatibility": {
- "access_result_shape": "run:exhaustive_page:envelope",
- "authority": "mcp-capability:write",
- "durability": "transport-adapter; domain-owner-controls-durability",
- "identity": "mcp-tool:saved-query,recipe,result-set",
- "lifecycle": "registered-handler-retained"
- },
- "completeness_edges": [
- {
- "consumer": "tests.infra.mcp.EXPECTED_TOOL_NAMES",
- "kind": "discovery-name-equivalence",
- "owner_path": "tests/infra/mcp.py",
- "producer": "mcp.tool.run"
- }
- ],
- "declaration_id": "mcp.tool.run",
- "discovery_text": "Execute a saved query or governed recipe ref.",
- "examples": [
- {
- "arguments": [
- [
- "ref",
- "saved-view:contract-view"
- ]
- ],
- "name": "minimal-valid-call",
- "summary": "Minimal cutover invocation for run."
- }
- ],
- "family_id": "mcp.tool.run",
- "handlers": [
- {
- "binding_key": "polylogue.mcp.server_cutover:run",
- "owner_path": "polylogue/mcp/server_cutover.py",
- "surface": "mcp",
- "symbol": "run"
- }
- ],
- "outputs": [
- {
- "kind": "envelope",
- "name": "runtime-contract",
- "schema_ref": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT",
- "target_path": "mcp://tool/run"
- }
- ],
- "owner_path": "polylogue/mcp/declarations/registry.py",
- "producer": "mutate-run",
- "public_name": "run",
- "repair_command": "devtools render mcp-equivalence",
- "role_gate": "mcp.capability:write",
- "schema_ref": "polylogue.mcp.server_cutover.run:inspect.signature"
- },
- "minimal_arguments": {
- "ref": "saved-view:contract-view"
- },
- "name": "run",
- "object_kinds": [
- "saved-query",
- "recipe",
- "result-set"
- ],
- "observed_use": "observed",
- "operation_owner": "mutate-run",
- "output_contract": {
- "envelope_fields": [],
- "kind": "envelope",
- "schema_source": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT"
- },
- "prompt_alternatives": [],
- "python_parity": {
- "binding": null,
- "intentional_absence_authority": "polylogue-s1kr",
- "reason": "The current MCP compatibility handler binds a lower-level owner or transport-only projection; polylogue-s1kr owns any public Python facade addition and docs parity."
- },
- "registration": {
- "module": "polylogue.mcp.server_cutover",
- "registrar": "register_cutover_privileged_tools",
- "symbol": "run"
- },
- "required_capability": "write",
- "resource_alternatives": [],
- "result_semantics": "exhaustive_page",
- "retirement_owner": "polylogue-t46.8.3",
- "telemetry_key": "run",
- "value_discovery": [],
- "verb": "run",
- "workflow_coverage": [
- "t46.8.3-privileged-contract"
- ]
- },
- {
- "canonical_plan": "polylogue.maintenance.planner.preview_backfill",
- "canonical_projection": "operation_result:root",
- "capability": "maintenance:maintenance",
- "compatibility_route": "maintenance",
- "continuation": {
- "continuation_ref": null,
- "exhaustive_route": "query",
- "mode": "none",
- "notes": "Continuation is opaque and must be the only resume input."
- },
- "deprecation_state": "retained",
- "description": "Preview, execute, list, and inspect maintenance operations. execute with dry_run=false, rebuild_index, and rebuild_insights require confirm=true and fail closed without it.",
- "field_discovery": [],
- "grammar_discovery": [],
- "incident_coverage": [],
- "input_contract": {
- "required_arguments": [
- "operation"
- ],
- "schema_mode": "FastMCP derives inputSchema from the cutover handler signature",
- "schema_source": "polylogue.mcp.server_cutover.maintenance:inspect.signature"
- },
- "kernel": {
- "compatibility": {
- "access_result_shape": "maintenance:maintenance:operation_result",
- "authority": "mcp-capability:maintenance",
- "durability": "transport-adapter; domain-owner-controls-durability",
- "identity": "mcp-tool:maintenance-plan,maintenance-operation",
- "lifecycle": "registered-handler-retained"
- },
- "completeness_edges": [
- {
- "consumer": "tests.infra.mcp.EXPECTED_TOOL_NAMES",
- "kind": "discovery-name-equivalence",
- "owner_path": "tests/infra/mcp.py",
- "producer": "mcp.tool.maintenance"
- }
- ],
- "declaration_id": "mcp.tool.maintenance",
- "discovery_text": "Preview, execute, list, and inspect maintenance operations. execute with dry_run=false, rebuild_index, and rebuild_insights require confirm=true and fail closed without it.",
- "examples": [
- {
- "arguments": [
- [
- "operation",
- "list"
- ]
- ],
- "name": "minimal-valid-call",
- "summary": "Minimal cutover invocation for maintenance."
- }
- ],
- "family_id": "mcp.tool.maintenance",
- "handlers": [
- {
- "binding_key": "polylogue.mcp.server_cutover:maintenance",
- "owner_path": "polylogue/mcp/server_cutover.py",
- "surface": "mcp",
- "symbol": "maintenance"
- }
- ],
- "outputs": [
- {
- "kind": "operation_result",
- "name": "runtime-contract",
- "schema_ref": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT",
- "target_path": "mcp://tool/maintenance"
- }
- ],
- "owner_path": "polylogue/mcp/declarations/registry.py",
- "producer": "polylogue.maintenance.planner.preview_backfill",
- "public_name": "maintenance",
- "repair_command": "devtools render mcp-equivalence",
- "role_gate": "mcp.capability:maintenance",
- "schema_ref": "polylogue.mcp.server_cutover.maintenance:inspect.signature"
- },
- "minimal_arguments": {
- "operation": "list"
- },
- "name": "maintenance",
- "object_kinds": [
- "maintenance-plan",
- "maintenance-operation"
- ],
- "observed_use": "observed",
- "operation_owner": "polylogue.maintenance.planner.preview_backfill",
- "output_contract": {
- "envelope_fields": [],
- "kind": "operation_result",
- "schema_source": "tests/unit/mcp/test_envelope_contracts.py::TOOL_CONTRACT"
- },
- "prompt_alternatives": [],
- "python_parity": {
- "binding": null,
- "intentional_absence_authority": "polylogue-s1kr",
- "reason": "The current MCP compatibility handler binds a lower-level owner or transport-only projection; polylogue-s1kr owns any public Python facade addition and docs parity."
- },
- "registration": {
- "module": "polylogue.mcp.server_cutover",
- "registrar": "register_cutover_privileged_tools",
- "symbol": "maintenance"
- },
- "required_capability": "maintenance",
- "resource_alternatives": [],
- "result_semantics": "maintenance",
- "retirement_owner": "polylogue-t46.8.3",
- "telemetry_key": "maintenance",
- "value_discovery": [],
- "verb": "maintenance",
- "workflow_coverage": [
- "t46.8.3-privileged-contract"
- ]
- }
- ]
-}
diff --git a/docs/generated/public-claims/findings-page.json b/docs/generated/public-claims/findings-page.json
deleted file mode 100644
index 9b4e79e2d1..0000000000
--- a/docs/generated/public-claims/findings-page.json
+++ /dev/null
@@ -1,251 +0,0 @@
-{
- "authority": {
- "claims": "AssertionKind.FINDING + explicit capability declarations",
- "integrity": "polylogue-37t.14 EvidenceIntegrityVerdict",
- "projection": "polylogue/insights/measurement/public_claims.py"
- },
- "claim_count": 4,
- "claims": [
- {
- "badge": "[CAPABILITY ONLY]",
- "blind_spot_codes": [],
- "blocker_codes": [],
- "caveat": "This is a product-category capability statement, not a measured performance or prevalence claim.",
- "claim_key": "category.local-evidence-system",
- "integrity_status": null,
- "integrity_verdict_present": false,
- "presets": [
- "readme",
- "launch",
- "findings-page",
- "verified-export"
- ],
- "public_evidence_refs": [
- "file:README.md",
- "file:docs/architecture.md",
- "file:docs/proof-artifacts.md"
- ],
- "public_remediation_refs": [],
- "publication": "Polylogue archives your AI conversations - all of them, in one place, on your machine.",
- "qualifiers": {
- "definition_ref": null,
- "evaluation_ref": null,
- "finding_epoch": null,
- "finding_frame_ref": null,
- "verdict_as_of_epoch": null,
- "verdict_frame_ref": null
- },
- "reason_codes": [],
- "review": {
- "assertion_status": null,
- "judgment_ref": null,
- "privacy": "approved",
- "publication": "approved"
- },
- "scope": "The current local archive, query, evidence, judgment, and context surfaces.",
- "source_kind": "capability",
- "source_ref": null,
- "statistic": null,
- "status": "capability-only"
- },
- {
- "badge": "[UNKNOWN \u00b7 UNRESOLVED]",
- "blind_spot_codes": [],
- "blocker_codes": [
- "finding-candidate"
- ],
- "caveat": "The classes are method-defined tool-name groups, not severity labels; each group retains a large or material ambiguous remainder.",
- "claim_key": "finding.handler-class-split",
- "integrity_status": "unresolved",
- "integrity_verdict_present": false,
- "presets": [
- "readme",
- "launch",
- "findings-page",
- "verified-export"
- ],
- "public_evidence_refs": [
- "file:docs/findings/claim-vs-evidence.md",
- "file:.agent/demos/claim-vs-evidence/public-summary.json",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json"
- ],
- "public_remediation_refs": [
- "bead:polylogue-37t.14"
- ],
- "publication": "In that sample, the silent-continuation lower bound was 22.3% for consequential handlers, 27.1% for benign-recovery handlers, and 53.9% for other handlers.",
- "qualifiers": {
- "definition_ref": null,
- "evaluation_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration",
- "finding_epoch": "2026-07-04T08:55:53.667311+00:00",
- "finding_frame_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame",
- "verdict_as_of_epoch": null,
- "verdict_frame_ref": null
- },
- "reason_codes": [
- "integrity-verdict-not-computed"
- ],
- "review": {
- "assertion_status": "candidate",
- "judgment_ref": null,
- "privacy": "pending",
- "publication": "pending"
- },
- "scope": "The same 5,000 sampled failures, partitioned by the packet's explicit handler-class methodology: 4,175 consequential, 634 benign-recovery, and 191 other.",
- "source_kind": "finding",
- "source_ref": "assertion:assertion-finding:cbb4967fc2d33ce231978b76949205856a68d8306da46a610f478cb4244d2ad8",
- "statistic": {
- "op": "breakdown",
- "unit": "structured_failures",
- "value": {
- "benign_recovery": {
- "ambiguous": 455,
- "failed_outcomes": 634,
- "silent_proceed": 172,
- "silent_rate_lower_bound": 0.27129337539432175
- },
- "consequential": {
- "ambiguous": 2842,
- "failed_outcomes": 4175,
- "silent_proceed": 930,
- "silent_rate_lower_bound": 0.22275449101796407
- },
- "other": {
- "ambiguous": 78,
- "failed_outcomes": 191,
- "silent_proceed": 103,
- "silent_rate_lower_bound": 0.5392670157068062
- }
- }
- },
- "status": "unknown"
- },
- {
- "badge": "[UNKNOWN \u00b7 UNRESOLVED]",
- "blind_spot_codes": [],
- "blocker_codes": [
- "finding-candidate"
- ],
- "caveat": "These are inspection and frame counts, not provider prevalence estimates; the archive's origin mix and the bounded allocation determine them.",
- "claim_key": "finding.per-origin-inspection-counts",
- "integrity_status": "unresolved",
- "integrity_verdict_present": false,
- "presets": [
- "readme",
- "launch",
- "findings-page",
- "verified-export"
- ],
- "public_evidence_refs": [
- "file:docs/findings/claim-vs-evidence.md",
- "file:.agent/demos/claim-vs-evidence/public-summary.json",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json"
- ],
- "public_remediation_refs": [
- "bead:polylogue-37t.14"
- ],
- "publication": "The origin-stratified sample inspected 3,752 Claude Code, 1,241 Codex, and seven Claude AI structured failures from origin frames of 31,555, 10,429, and 49 respectively.",
- "qualifiers": {
- "definition_ref": null,
- "evaluation_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration",
- "finding_epoch": "2026-07-04T08:55:53.667311+00:00",
- "finding_frame_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame",
- "verdict_as_of_epoch": null,
- "verdict_frame_ref": null
- },
- "reason_codes": [
- "integrity-verdict-not-computed"
- ],
- "review": {
- "assertion_status": "candidate",
- "judgment_ref": null,
- "privacy": "pending",
- "publication": "pending"
- },
- "scope": "The 2026-07-04 bounded sample frame, selected deterministically by origin, session, tool, and result-message identifiers.",
- "source_kind": "finding",
- "source_ref": "assertion:assertion-finding:adb1c19ac49d5b835056e68eb12b9389656b83c6eb01d5f09eb7ad6dd5cf7edd",
- "statistic": {
- "op": "breakdown",
- "unit": "structured_failures",
- "value": {
- "claude-ai-export": {
- "frame_total": 49,
- "inspected": 7,
- "requested": 7
- },
- "claude-code-session": {
- "frame_total": 31555,
- "inspected": 3752,
- "requested": 3752
- },
- "codex-session": {
- "frame_total": 10429,
- "inspected": 1241,
- "requested": 1241
- }
- }
- },
- "status": "unknown"
- },
- {
- "badge": "[UNKNOWN \u00b7 UNRESOLVED]",
- "blind_spot_codes": [],
- "blocker_codes": [
- "finding-candidate"
- ],
- "caveat": "This is not a population estimate; 3,375 rows remained ambiguous, and support must be recomputed when the evidence epoch, definition, or frame changes.",
- "claim_key": "finding.silent-proceed-lower-bound",
- "integrity_status": "unresolved",
- "integrity_verdict_present": false,
- "presets": [
- "readme",
- "launch",
- "findings-page",
- "verified-export"
- ],
- "public_evidence_refs": [
- "file:docs/findings/claim-vs-evidence.md",
- "file:.agent/demos/claim-vs-evidence/public-summary.json",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json"
- ],
- "public_remediation_refs": [
- "bead:polylogue-37t.14"
- ],
- "publication": "In one bounded private-archive sample, 1,205 of 5,000 inspected structured failures were followed by silent continuation on the next assistant turn, a 24.1% lower bound.",
- "qualifiers": {
- "definition_ref": null,
- "evaluation_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration",
- "finding_epoch": "2026-07-04T08:55:53.667311+00:00",
- "finding_frame_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame",
- "verdict_as_of_epoch": null,
- "verdict_frame_ref": null
- },
- "reason_codes": [
- "integrity-verdict-not-computed"
- ],
- "review": {
- "assertion_status": "candidate",
- "judgment_ref": null,
- "privacy": "pending",
- "publication": "pending"
- },
- "scope": "One private archive; an origin-stratified 5,000-row sample from a 42,033-row structured-failure frame; next assistant turn only.",
- "source_kind": "finding",
- "source_ref": "assertion:assertion-finding:e5da9c88d1c236d15648fc52ad7898d8a6f7018277e84c624bdc9e7c7d037689",
- "statistic": {
- "ambiguous": 3375,
- "denominator": 5000,
- "numerator": 1205,
- "op": "lower_bound",
- "unit": "ratio",
- "value": 0.241
- },
- "status": "unknown"
- }
- ],
- "preset": "findings-page",
- "publishable_claim_keys": [
- "category.local-evidence-system"
- ],
- "schema": "polylogue.public-claims-view.v1"
-}
diff --git a/docs/generated/public-claims/findings-page.md b/docs/generated/public-claims/findings-page.md
deleted file mode 100644
index 898de26832..0000000000
--- a/docs/generated/public-claims/findings-page.md
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-# Findings-Page Public Claims
-
-This file is generated from FINDING assertions, canonical judgment state, and the shared evidence-integrity verdict. A badge is a current publication status, not a substitute for the cited evidence.
-
-## `category.local-evidence-system` [CAPABILITY ONLY]
-
-Polylogue archives your AI conversations - all of them, in one place, on your machine.
-
-- Scope: The current local archive, query, evidence, judgment, and context surfaces.
-- Caveat: This is a product-category capability statement, not a measured performance or prevalence claim.
-- Evidence: `file:README.md`, `file:docs/architecture.md`, `file:docs/proof-artifacts.md`
-- Epoch/frame: not applicable (capability statement; no measured result)
-- Review: assertion=n/a, publication=approved, privacy=approved, judgment=none
-
-## `finding.handler-class-split` [UNKNOWN · UNRESOLVED]
-
-In that sample, the silent-continuation lower bound was 22.3% for consequential handlers, 27.1% for benign-recovery handlers, and 53.9% for other handlers.
-
-- Scope: The same 5,000 sampled failures, partitioned by the packet's explicit handler-class methodology: 4,175 consequential, 634 benign-recovery, and 191 other.
-- Caveat: The classes are method-defined tool-name groups, not severity labels; each group retains a large or material ambiguous remainder.
-- Evidence: `file:docs/findings/claim-vs-evidence.md`, `file:.agent/demos/claim-vs-evidence/public-summary.json`, `file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json`
-- Epoch/frame: finding epoch=2026-07-04T08:55:53.667311+00:00; verdict as-of=unknown; finding frame=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame; verdict frame=unknown; evaluation=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration; definition=unknown
-- Review: assertion=candidate, publication=pending, privacy=pending, judgment=none
-- Status reasons: `finding-candidate`, `integrity-verdict-not-computed`
-- Remediation: `bead:polylogue-37t.14`
-
-## `finding.per-origin-inspection-counts` [UNKNOWN · UNRESOLVED]
-
-The origin-stratified sample inspected 3,752 Claude Code, 1,241 Codex, and seven Claude AI structured failures from origin frames of 31,555, 10,429, and 49 respectively.
-
-- Scope: The 2026-07-04 bounded sample frame, selected deterministically by origin, session, tool, and result-message identifiers.
-- Caveat: These are inspection and frame counts, not provider prevalence estimates; the archive's origin mix and the bounded allocation determine them.
-- Evidence: `file:docs/findings/claim-vs-evidence.md`, `file:.agent/demos/claim-vs-evidence/public-summary.json`, `file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json`
-- Epoch/frame: finding epoch=2026-07-04T08:55:53.667311+00:00; verdict as-of=unknown; finding frame=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame; verdict frame=unknown; evaluation=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration; definition=unknown
-- Review: assertion=candidate, publication=pending, privacy=pending, judgment=none
-- Status reasons: `finding-candidate`, `integrity-verdict-not-computed`
-- Remediation: `bead:polylogue-37t.14`
-
-## `finding.silent-proceed-lower-bound` [UNKNOWN · UNRESOLVED]
-
-In one bounded private-archive sample, 1,205 of 5,000 inspected structured failures were followed by silent continuation on the next assistant turn, a 24.1% lower bound.
-
-- Scope: One private archive; an origin-stratified 5,000-row sample from a 42,033-row structured-failure frame; next assistant turn only.
-- Caveat: This is not a population estimate; 3,375 rows remained ambiguous, and support must be recomputed when the evidence epoch, definition, or frame changes.
-- Evidence: `file:docs/findings/claim-vs-evidence.md`, `file:.agent/demos/claim-vs-evidence/public-summary.json`, `file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json`
-- Epoch/frame: finding epoch=2026-07-04T08:55:53.667311+00:00; verdict as-of=unknown; finding frame=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame; verdict frame=unknown; evaluation=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration; definition=unknown
-- Review: assertion=candidate, publication=pending, privacy=pending, judgment=none
-- Status reasons: `finding-candidate`, `integrity-verdict-not-computed`
-- Remediation: `bead:polylogue-37t.14`
diff --git a/docs/generated/public-claims/launch.json b/docs/generated/public-claims/launch.json
deleted file mode 100644
index 1b0dd92b75..0000000000
--- a/docs/generated/public-claims/launch.json
+++ /dev/null
@@ -1,227 +0,0 @@
-{
- "authority": {
- "claims": "AssertionKind.FINDING + explicit capability declarations",
- "integrity": "polylogue-37t.14 EvidenceIntegrityVerdict",
- "projection": "polylogue/insights/measurement/public_claims.py"
- },
- "claim_count": 4,
- "claims": [
- {
- "badge": "[CAPABILITY ONLY]",
- "blind_spot_codes": [],
- "blocker_codes": [],
- "caveat": "This is a product-category capability statement, not a measured performance or prevalence claim.",
- "claim_key": "category.local-evidence-system",
- "integrity_status": null,
- "integrity_verdict_present": false,
- "presets": [
- "readme",
- "launch",
- "findings-page",
- "verified-export"
- ],
- "public_evidence_refs": [
- "file:README.md",
- "file:docs/architecture.md",
- "file:docs/proof-artifacts.md"
- ],
- "public_remediation_refs": [],
- "publication": "Polylogue archives your AI conversations - all of them, in one place, on your machine.",
- "qualifiers": {
- "definition_ref": null,
- "evaluation_ref": null,
- "finding_epoch": null,
- "finding_frame_ref": null,
- "verdict_as_of_epoch": null,
- "verdict_frame_ref": null
- },
- "reason_codes": [],
- "scope": "The current local archive, query, evidence, judgment, and context surfaces.",
- "source_kind": "capability",
- "source_ref": null,
- "statistic": null,
- "status": "capability-only"
- },
- {
- "badge": "[UNKNOWN \u00b7 UNRESOLVED]",
- "blind_spot_codes": [],
- "blocker_codes": [
- "finding-candidate"
- ],
- "caveat": "The classes are method-defined tool-name groups, not severity labels; each group retains a large or material ambiguous remainder.",
- "claim_key": "finding.handler-class-split",
- "integrity_status": "unresolved",
- "integrity_verdict_present": false,
- "presets": [
- "readme",
- "launch",
- "findings-page",
- "verified-export"
- ],
- "public_evidence_refs": [
- "file:docs/findings/claim-vs-evidence.md",
- "file:.agent/demos/claim-vs-evidence/public-summary.json",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json"
- ],
- "public_remediation_refs": [
- "bead:polylogue-37t.14"
- ],
- "publication": "In that sample, the silent-continuation lower bound was 22.3% for consequential handlers, 27.1% for benign-recovery handlers, and 53.9% for other handlers.",
- "qualifiers": {
- "definition_ref": null,
- "evaluation_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration",
- "finding_epoch": "2026-07-04T08:55:53.667311+00:00",
- "finding_frame_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame",
- "verdict_as_of_epoch": null,
- "verdict_frame_ref": null
- },
- "reason_codes": [
- "integrity-verdict-not-computed"
- ],
- "scope": "The same 5,000 sampled failures, partitioned by the packet's explicit handler-class methodology: 4,175 consequential, 634 benign-recovery, and 191 other.",
- "source_kind": "finding",
- "source_ref": "assertion:assertion-finding:cbb4967fc2d33ce231978b76949205856a68d8306da46a610f478cb4244d2ad8",
- "statistic": {
- "op": "breakdown",
- "unit": "structured_failures",
- "value": {
- "benign_recovery": {
- "ambiguous": 455,
- "failed_outcomes": 634,
- "silent_proceed": 172,
- "silent_rate_lower_bound": 0.27129337539432175
- },
- "consequential": {
- "ambiguous": 2842,
- "failed_outcomes": 4175,
- "silent_proceed": 930,
- "silent_rate_lower_bound": 0.22275449101796407
- },
- "other": {
- "ambiguous": 78,
- "failed_outcomes": 191,
- "silent_proceed": 103,
- "silent_rate_lower_bound": 0.5392670157068062
- }
- }
- },
- "status": "unknown"
- },
- {
- "badge": "[UNKNOWN \u00b7 UNRESOLVED]",
- "blind_spot_codes": [],
- "blocker_codes": [
- "finding-candidate"
- ],
- "caveat": "These are inspection and frame counts, not provider prevalence estimates; the archive's origin mix and the bounded allocation determine them.",
- "claim_key": "finding.per-origin-inspection-counts",
- "integrity_status": "unresolved",
- "integrity_verdict_present": false,
- "presets": [
- "readme",
- "launch",
- "findings-page",
- "verified-export"
- ],
- "public_evidence_refs": [
- "file:docs/findings/claim-vs-evidence.md",
- "file:.agent/demos/claim-vs-evidence/public-summary.json",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json"
- ],
- "public_remediation_refs": [
- "bead:polylogue-37t.14"
- ],
- "publication": "The origin-stratified sample inspected 3,752 Claude Code, 1,241 Codex, and seven Claude AI structured failures from origin frames of 31,555, 10,429, and 49 respectively.",
- "qualifiers": {
- "definition_ref": null,
- "evaluation_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration",
- "finding_epoch": "2026-07-04T08:55:53.667311+00:00",
- "finding_frame_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame",
- "verdict_as_of_epoch": null,
- "verdict_frame_ref": null
- },
- "reason_codes": [
- "integrity-verdict-not-computed"
- ],
- "scope": "The 2026-07-04 bounded sample frame, selected deterministically by origin, session, tool, and result-message identifiers.",
- "source_kind": "finding",
- "source_ref": "assertion:assertion-finding:adb1c19ac49d5b835056e68eb12b9389656b83c6eb01d5f09eb7ad6dd5cf7edd",
- "statistic": {
- "op": "breakdown",
- "unit": "structured_failures",
- "value": {
- "claude-ai-export": {
- "frame_total": 49,
- "inspected": 7,
- "requested": 7
- },
- "claude-code-session": {
- "frame_total": 31555,
- "inspected": 3752,
- "requested": 3752
- },
- "codex-session": {
- "frame_total": 10429,
- "inspected": 1241,
- "requested": 1241
- }
- }
- },
- "status": "unknown"
- },
- {
- "badge": "[UNKNOWN \u00b7 UNRESOLVED]",
- "blind_spot_codes": [],
- "blocker_codes": [
- "finding-candidate"
- ],
- "caveat": "This is not a population estimate; 3,375 rows remained ambiguous, and support must be recomputed when the evidence epoch, definition, or frame changes.",
- "claim_key": "finding.silent-proceed-lower-bound",
- "integrity_status": "unresolved",
- "integrity_verdict_present": false,
- "presets": [
- "readme",
- "launch",
- "findings-page",
- "verified-export"
- ],
- "public_evidence_refs": [
- "file:docs/findings/claim-vs-evidence.md",
- "file:.agent/demos/claim-vs-evidence/public-summary.json",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json"
- ],
- "public_remediation_refs": [
- "bead:polylogue-37t.14"
- ],
- "publication": "In one bounded private-archive sample, 1,205 of 5,000 inspected structured failures were followed by silent continuation on the next assistant turn, a 24.1% lower bound.",
- "qualifiers": {
- "definition_ref": null,
- "evaluation_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration",
- "finding_epoch": "2026-07-04T08:55:53.667311+00:00",
- "finding_frame_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame",
- "verdict_as_of_epoch": null,
- "verdict_frame_ref": null
- },
- "reason_codes": [
- "integrity-verdict-not-computed"
- ],
- "scope": "One private archive; an origin-stratified 5,000-row sample from a 42,033-row structured-failure frame; next assistant turn only.",
- "source_kind": "finding",
- "source_ref": "assertion:assertion-finding:e5da9c88d1c236d15648fc52ad7898d8a6f7018277e84c624bdc9e7c7d037689",
- "statistic": {
- "ambiguous": 3375,
- "denominator": 5000,
- "numerator": 1205,
- "op": "lower_bound",
- "unit": "ratio",
- "value": 0.241
- },
- "status": "unknown"
- }
- ],
- "preset": "launch",
- "publishable_claim_keys": [
- "category.local-evidence-system"
- ],
- "schema": "polylogue.public-claims-view.v1"
-}
diff --git a/docs/generated/public-claims/launch.md b/docs/generated/public-claims/launch.md
deleted file mode 100644
index c0f8a9e03c..0000000000
--- a/docs/generated/public-claims/launch.md
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-# Launch Public Claims
-
-This file is generated from FINDING assertions, canonical judgment state, and the shared evidence-integrity verdict. A badge is a current publication status, not a substitute for the cited evidence.
-
-## `category.local-evidence-system` [CAPABILITY ONLY]
-
-Polylogue archives your AI conversations - all of them, in one place, on your machine.
-
-- Scope: The current local archive, query, evidence, judgment, and context surfaces.
-- Caveat: This is a product-category capability statement, not a measured performance or prevalence claim.
-- Evidence: `file:README.md`, `file:docs/architecture.md`, `file:docs/proof-artifacts.md`
-- Epoch/frame: not applicable (capability statement; no measured result)
-
-## `finding.handler-class-split` [UNKNOWN · UNRESOLVED]
-
-In that sample, the silent-continuation lower bound was 22.3% for consequential handlers, 27.1% for benign-recovery handlers, and 53.9% for other handlers.
-
-- Scope: The same 5,000 sampled failures, partitioned by the packet's explicit handler-class methodology: 4,175 consequential, 634 benign-recovery, and 191 other.
-- Caveat: The classes are method-defined tool-name groups, not severity labels; each group retains a large or material ambiguous remainder.
-- Evidence: `file:docs/findings/claim-vs-evidence.md`, `file:.agent/demos/claim-vs-evidence/public-summary.json`, `file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json`
-- Epoch/frame: finding epoch=2026-07-04T08:55:53.667311+00:00; verdict as-of=unknown; finding frame=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame; verdict frame=unknown; evaluation=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration; definition=unknown
-- Status reasons: `finding-candidate`, `integrity-verdict-not-computed`
-- Remediation: `bead:polylogue-37t.14`
-
-## `finding.per-origin-inspection-counts` [UNKNOWN · UNRESOLVED]
-
-The origin-stratified sample inspected 3,752 Claude Code, 1,241 Codex, and seven Claude AI structured failures from origin frames of 31,555, 10,429, and 49 respectively.
-
-- Scope: The 2026-07-04 bounded sample frame, selected deterministically by origin, session, tool, and result-message identifiers.
-- Caveat: These are inspection and frame counts, not provider prevalence estimates; the archive's origin mix and the bounded allocation determine them.
-- Evidence: `file:docs/findings/claim-vs-evidence.md`, `file:.agent/demos/claim-vs-evidence/public-summary.json`, `file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json`
-- Epoch/frame: finding epoch=2026-07-04T08:55:53.667311+00:00; verdict as-of=unknown; finding frame=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame; verdict frame=unknown; evaluation=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration; definition=unknown
-- Status reasons: `finding-candidate`, `integrity-verdict-not-computed`
-- Remediation: `bead:polylogue-37t.14`
-
-## `finding.silent-proceed-lower-bound` [UNKNOWN · UNRESOLVED]
-
-In one bounded private-archive sample, 1,205 of 5,000 inspected structured failures were followed by silent continuation on the next assistant turn, a 24.1% lower bound.
-
-- Scope: One private archive; an origin-stratified 5,000-row sample from a 42,033-row structured-failure frame; next assistant turn only.
-- Caveat: This is not a population estimate; 3,375 rows remained ambiguous, and support must be recomputed when the evidence epoch, definition, or frame changes.
-- Evidence: `file:docs/findings/claim-vs-evidence.md`, `file:.agent/demos/claim-vs-evidence/public-summary.json`, `file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json`
-- Epoch/frame: finding epoch=2026-07-04T08:55:53.667311+00:00; verdict as-of=unknown; finding frame=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame; verdict frame=unknown; evaluation=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration; definition=unknown
-- Status reasons: `finding-candidate`, `integrity-verdict-not-computed`
-- Remediation: `bead:polylogue-37t.14`
diff --git a/docs/generated/public-claims/readme.json b/docs/generated/public-claims/readme.json
deleted file mode 100644
index 4d17f633b5..0000000000
--- a/docs/generated/public-claims/readme.json
+++ /dev/null
@@ -1,203 +0,0 @@
-{
- "authority": {
- "claims": "AssertionKind.FINDING + explicit capability declarations",
- "integrity": "polylogue-37t.14 EvidenceIntegrityVerdict",
- "projection": "polylogue/insights/measurement/public_claims.py"
- },
- "claim_count": 4,
- "claims": [
- {
- "badge": "[CAPABILITY ONLY]",
- "caveat": "This is a product-category capability statement, not a measured performance or prevalence claim.",
- "claim_key": "category.local-evidence-system",
- "integrity_status": null,
- "integrity_verdict_present": false,
- "presets": [
- "readme",
- "launch",
- "findings-page",
- "verified-export"
- ],
- "public_evidence_refs": [
- "file:README.md",
- "file:docs/architecture.md",
- "file:docs/proof-artifacts.md"
- ],
- "public_remediation_refs": [],
- "publication": "Polylogue archives your AI conversations - all of them, in one place, on your machine.",
- "qualifiers": {
- "definition_ref": null,
- "evaluation_ref": null,
- "finding_epoch": null,
- "finding_frame_ref": null,
- "verdict_as_of_epoch": null,
- "verdict_frame_ref": null
- },
- "scope": "The current local archive, query, evidence, judgment, and context surfaces.",
- "source_kind": "capability",
- "source_ref": null,
- "statistic": null,
- "status": "capability-only"
- },
- {
- "badge": "[UNKNOWN \u00b7 UNRESOLVED]",
- "caveat": "The classes are method-defined tool-name groups, not severity labels; each group retains a large or material ambiguous remainder.",
- "claim_key": "finding.handler-class-split",
- "integrity_status": "unresolved",
- "integrity_verdict_present": false,
- "presets": [
- "readme",
- "launch",
- "findings-page",
- "verified-export"
- ],
- "public_evidence_refs": [
- "file:docs/findings/claim-vs-evidence.md",
- "file:.agent/demos/claim-vs-evidence/public-summary.json",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json"
- ],
- "public_remediation_refs": [
- "bead:polylogue-37t.14"
- ],
- "publication": "In that sample, the silent-continuation lower bound was 22.3% for consequential handlers, 27.1% for benign-recovery handlers, and 53.9% for other handlers.",
- "qualifiers": {
- "definition_ref": null,
- "evaluation_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration",
- "finding_epoch": "2026-07-04T08:55:53.667311+00:00",
- "finding_frame_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame",
- "verdict_as_of_epoch": null,
- "verdict_frame_ref": null
- },
- "scope": "The same 5,000 sampled failures, partitioned by the packet's explicit handler-class methodology: 4,175 consequential, 634 benign-recovery, and 191 other.",
- "source_kind": "finding",
- "source_ref": "assertion:assertion-finding:cbb4967fc2d33ce231978b76949205856a68d8306da46a610f478cb4244d2ad8",
- "statistic": {
- "op": "breakdown",
- "unit": "structured_failures",
- "value": {
- "benign_recovery": {
- "ambiguous": 455,
- "failed_outcomes": 634,
- "silent_proceed": 172,
- "silent_rate_lower_bound": 0.27129337539432175
- },
- "consequential": {
- "ambiguous": 2842,
- "failed_outcomes": 4175,
- "silent_proceed": 930,
- "silent_rate_lower_bound": 0.22275449101796407
- },
- "other": {
- "ambiguous": 78,
- "failed_outcomes": 191,
- "silent_proceed": 103,
- "silent_rate_lower_bound": 0.5392670157068062
- }
- }
- },
- "status": "unknown"
- },
- {
- "badge": "[UNKNOWN \u00b7 UNRESOLVED]",
- "caveat": "These are inspection and frame counts, not provider prevalence estimates; the archive's origin mix and the bounded allocation determine them.",
- "claim_key": "finding.per-origin-inspection-counts",
- "integrity_status": "unresolved",
- "integrity_verdict_present": false,
- "presets": [
- "readme",
- "launch",
- "findings-page",
- "verified-export"
- ],
- "public_evidence_refs": [
- "file:docs/findings/claim-vs-evidence.md",
- "file:.agent/demos/claim-vs-evidence/public-summary.json",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json"
- ],
- "public_remediation_refs": [
- "bead:polylogue-37t.14"
- ],
- "publication": "The origin-stratified sample inspected 3,752 Claude Code, 1,241 Codex, and seven Claude AI structured failures from origin frames of 31,555, 10,429, and 49 respectively.",
- "qualifiers": {
- "definition_ref": null,
- "evaluation_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration",
- "finding_epoch": "2026-07-04T08:55:53.667311+00:00",
- "finding_frame_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame",
- "verdict_as_of_epoch": null,
- "verdict_frame_ref": null
- },
- "scope": "The 2026-07-04 bounded sample frame, selected deterministically by origin, session, tool, and result-message identifiers.",
- "source_kind": "finding",
- "source_ref": "assertion:assertion-finding:adb1c19ac49d5b835056e68eb12b9389656b83c6eb01d5f09eb7ad6dd5cf7edd",
- "statistic": {
- "op": "breakdown",
- "unit": "structured_failures",
- "value": {
- "claude-ai-export": {
- "frame_total": 49,
- "inspected": 7,
- "requested": 7
- },
- "claude-code-session": {
- "frame_total": 31555,
- "inspected": 3752,
- "requested": 3752
- },
- "codex-session": {
- "frame_total": 10429,
- "inspected": 1241,
- "requested": 1241
- }
- }
- },
- "status": "unknown"
- },
- {
- "badge": "[UNKNOWN \u00b7 UNRESOLVED]",
- "caveat": "This is not a population estimate; 3,375 rows remained ambiguous, and support must be recomputed when the evidence epoch, definition, or frame changes.",
- "claim_key": "finding.silent-proceed-lower-bound",
- "integrity_status": "unresolved",
- "integrity_verdict_present": false,
- "presets": [
- "readme",
- "launch",
- "findings-page",
- "verified-export"
- ],
- "public_evidence_refs": [
- "file:docs/findings/claim-vs-evidence.md",
- "file:.agent/demos/claim-vs-evidence/public-summary.json",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json"
- ],
- "public_remediation_refs": [
- "bead:polylogue-37t.14"
- ],
- "publication": "In one bounded private-archive sample, 1,205 of 5,000 inspected structured failures were followed by silent continuation on the next assistant turn, a 24.1% lower bound.",
- "qualifiers": {
- "definition_ref": null,
- "evaluation_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration",
- "finding_epoch": "2026-07-04T08:55:53.667311+00:00",
- "finding_frame_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame",
- "verdict_as_of_epoch": null,
- "verdict_frame_ref": null
- },
- "scope": "One private archive; an origin-stratified 5,000-row sample from a 42,033-row structured-failure frame; next assistant turn only.",
- "source_kind": "finding",
- "source_ref": "assertion:assertion-finding:e5da9c88d1c236d15648fc52ad7898d8a6f7018277e84c624bdc9e7c7d037689",
- "statistic": {
- "ambiguous": 3375,
- "denominator": 5000,
- "numerator": 1205,
- "op": "lower_bound",
- "unit": "ratio",
- "value": 0.241
- },
- "status": "unknown"
- }
- ],
- "preset": "readme",
- "publishable_claim_keys": [
- "category.local-evidence-system"
- ],
- "schema": "polylogue.public-claims-view.v1"
-}
diff --git a/docs/generated/public-claims/readme.md b/docs/generated/public-claims/readme.md
deleted file mode 100644
index 1dada8b586..0000000000
--- a/docs/generated/public-claims/readme.md
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-# README Public Claims
-
-This file is generated from FINDING assertions, canonical judgment state, and the shared evidence-integrity verdict. A badge is a current publication status, not a substitute for the cited evidence.
-
-## `category.local-evidence-system` [CAPABILITY ONLY]
-
-Polylogue archives your AI conversations - all of them, in one place, on your machine.
-
-- Scope: The current local archive, query, evidence, judgment, and context surfaces.
-- Caveat: This is a product-category capability statement, not a measured performance or prevalence claim.
-- Evidence: `file:README.md`, `file:docs/architecture.md`, `file:docs/proof-artifacts.md`
-- Epoch/frame: not applicable (capability statement; no measured result)
-
-## `finding.handler-class-split` [UNKNOWN · UNRESOLVED]
-
-In that sample, the silent-continuation lower bound was 22.3% for consequential handlers, 27.1% for benign-recovery handlers, and 53.9% for other handlers.
-
-- Scope: The same 5,000 sampled failures, partitioned by the packet's explicit handler-class methodology: 4,175 consequential, 634 benign-recovery, and 191 other.
-- Caveat: The classes are method-defined tool-name groups, not severity labels; each group retains a large or material ambiguous remainder.
-- Evidence: `file:docs/findings/claim-vs-evidence.md`, `file:.agent/demos/claim-vs-evidence/public-summary.json`, `file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json`
-- Epoch/frame: finding epoch=2026-07-04T08:55:53.667311+00:00; verdict as-of=unknown; finding frame=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame; verdict frame=unknown; evaluation=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration; definition=unknown
-- Remediation: `bead:polylogue-37t.14`
-
-## `finding.per-origin-inspection-counts` [UNKNOWN · UNRESOLVED]
-
-The origin-stratified sample inspected 3,752 Claude Code, 1,241 Codex, and seven Claude AI structured failures from origin frames of 31,555, 10,429, and 49 respectively.
-
-- Scope: The 2026-07-04 bounded sample frame, selected deterministically by origin, session, tool, and result-message identifiers.
-- Caveat: These are inspection and frame counts, not provider prevalence estimates; the archive's origin mix and the bounded allocation determine them.
-- Evidence: `file:docs/findings/claim-vs-evidence.md`, `file:.agent/demos/claim-vs-evidence/public-summary.json`, `file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json`
-- Epoch/frame: finding epoch=2026-07-04T08:55:53.667311+00:00; verdict as-of=unknown; finding frame=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame; verdict frame=unknown; evaluation=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration; definition=unknown
-- Remediation: `bead:polylogue-37t.14`
-
-## `finding.silent-proceed-lower-bound` [UNKNOWN · UNRESOLVED]
-
-In one bounded private-archive sample, 1,205 of 5,000 inspected structured failures were followed by silent continuation on the next assistant turn, a 24.1% lower bound.
-
-- Scope: One private archive; an origin-stratified 5,000-row sample from a 42,033-row structured-failure frame; next assistant turn only.
-- Caveat: This is not a population estimate; 3,375 rows remained ambiguous, and support must be recomputed when the evidence epoch, definition, or frame changes.
-- Evidence: `file:docs/findings/claim-vs-evidence.md`, `file:.agent/demos/claim-vs-evidence/public-summary.json`, `file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json`
-- Epoch/frame: finding epoch=2026-07-04T08:55:53.667311+00:00; verdict as-of=unknown; finding frame=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame; verdict frame=unknown; evaluation=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration; definition=unknown
-- Remediation: `bead:polylogue-37t.14`
diff --git a/docs/generated/public-claims/verified-export.json b/docs/generated/public-claims/verified-export.json
deleted file mode 100644
index 06b6ae9181..0000000000
--- a/docs/generated/public-claims/verified-export.json
+++ /dev/null
@@ -1,251 +0,0 @@
-{
- "authority": {
- "claims": "AssertionKind.FINDING + explicit capability declarations",
- "integrity": "polylogue-37t.14 EvidenceIntegrityVerdict",
- "projection": "polylogue/insights/measurement/public_claims.py"
- },
- "claim_count": 4,
- "claims": [
- {
- "badge": "[CAPABILITY ONLY]",
- "blind_spot_codes": [],
- "blocker_codes": [],
- "caveat": "This is a product-category capability statement, not a measured performance or prevalence claim.",
- "claim_key": "category.local-evidence-system",
- "integrity_status": null,
- "integrity_verdict_present": false,
- "presets": [
- "readme",
- "launch",
- "findings-page",
- "verified-export"
- ],
- "public_evidence_refs": [
- "file:README.md",
- "file:docs/architecture.md",
- "file:docs/proof-artifacts.md"
- ],
- "public_remediation_refs": [],
- "publication": "Polylogue archives your AI conversations - all of them, in one place, on your machine.",
- "qualifiers": {
- "definition_ref": null,
- "evaluation_ref": null,
- "finding_epoch": null,
- "finding_frame_ref": null,
- "verdict_as_of_epoch": null,
- "verdict_frame_ref": null
- },
- "reason_codes": [],
- "review": {
- "assertion_status": null,
- "judgment_ref": null,
- "privacy": "approved",
- "publication": "approved"
- },
- "scope": "The current local archive, query, evidence, judgment, and context surfaces.",
- "source_kind": "capability",
- "source_ref": null,
- "statistic": null,
- "status": "capability-only"
- },
- {
- "badge": "[UNKNOWN \u00b7 UNRESOLVED]",
- "blind_spot_codes": [],
- "blocker_codes": [
- "finding-candidate"
- ],
- "caveat": "The classes are method-defined tool-name groups, not severity labels; each group retains a large or material ambiguous remainder.",
- "claim_key": "finding.handler-class-split",
- "integrity_status": "unresolved",
- "integrity_verdict_present": false,
- "presets": [
- "readme",
- "launch",
- "findings-page",
- "verified-export"
- ],
- "public_evidence_refs": [
- "file:docs/findings/claim-vs-evidence.md",
- "file:.agent/demos/claim-vs-evidence/public-summary.json",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json"
- ],
- "public_remediation_refs": [
- "bead:polylogue-37t.14"
- ],
- "publication": "In that sample, the silent-continuation lower bound was 22.3% for consequential handlers, 27.1% for benign-recovery handlers, and 53.9% for other handlers.",
- "qualifiers": {
- "definition_ref": null,
- "evaluation_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration",
- "finding_epoch": "2026-07-04T08:55:53.667311+00:00",
- "finding_frame_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame",
- "verdict_as_of_epoch": null,
- "verdict_frame_ref": null
- },
- "reason_codes": [
- "integrity-verdict-not-computed"
- ],
- "review": {
- "assertion_status": "candidate",
- "judgment_ref": null,
- "privacy": "pending",
- "publication": "pending"
- },
- "scope": "The same 5,000 sampled failures, partitioned by the packet's explicit handler-class methodology: 4,175 consequential, 634 benign-recovery, and 191 other.",
- "source_kind": "finding",
- "source_ref": "assertion:assertion-finding:cbb4967fc2d33ce231978b76949205856a68d8306da46a610f478cb4244d2ad8",
- "statistic": {
- "op": "breakdown",
- "unit": "structured_failures",
- "value": {
- "benign_recovery": {
- "ambiguous": 455,
- "failed_outcomes": 634,
- "silent_proceed": 172,
- "silent_rate_lower_bound": 0.27129337539432175
- },
- "consequential": {
- "ambiguous": 2842,
- "failed_outcomes": 4175,
- "silent_proceed": 930,
- "silent_rate_lower_bound": 0.22275449101796407
- },
- "other": {
- "ambiguous": 78,
- "failed_outcomes": 191,
- "silent_proceed": 103,
- "silent_rate_lower_bound": 0.5392670157068062
- }
- }
- },
- "status": "unknown"
- },
- {
- "badge": "[UNKNOWN \u00b7 UNRESOLVED]",
- "blind_spot_codes": [],
- "blocker_codes": [
- "finding-candidate"
- ],
- "caveat": "These are inspection and frame counts, not provider prevalence estimates; the archive's origin mix and the bounded allocation determine them.",
- "claim_key": "finding.per-origin-inspection-counts",
- "integrity_status": "unresolved",
- "integrity_verdict_present": false,
- "presets": [
- "readme",
- "launch",
- "findings-page",
- "verified-export"
- ],
- "public_evidence_refs": [
- "file:docs/findings/claim-vs-evidence.md",
- "file:.agent/demos/claim-vs-evidence/public-summary.json",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json"
- ],
- "public_remediation_refs": [
- "bead:polylogue-37t.14"
- ],
- "publication": "The origin-stratified sample inspected 3,752 Claude Code, 1,241 Codex, and seven Claude AI structured failures from origin frames of 31,555, 10,429, and 49 respectively.",
- "qualifiers": {
- "definition_ref": null,
- "evaluation_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration",
- "finding_epoch": "2026-07-04T08:55:53.667311+00:00",
- "finding_frame_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame",
- "verdict_as_of_epoch": null,
- "verdict_frame_ref": null
- },
- "reason_codes": [
- "integrity-verdict-not-computed"
- ],
- "review": {
- "assertion_status": "candidate",
- "judgment_ref": null,
- "privacy": "pending",
- "publication": "pending"
- },
- "scope": "The 2026-07-04 bounded sample frame, selected deterministically by origin, session, tool, and result-message identifiers.",
- "source_kind": "finding",
- "source_ref": "assertion:assertion-finding:adb1c19ac49d5b835056e68eb12b9389656b83c6eb01d5f09eb7ad6dd5cf7edd",
- "statistic": {
- "op": "breakdown",
- "unit": "structured_failures",
- "value": {
- "claude-ai-export": {
- "frame_total": 49,
- "inspected": 7,
- "requested": 7
- },
- "claude-code-session": {
- "frame_total": 31555,
- "inspected": 3752,
- "requested": 3752
- },
- "codex-session": {
- "frame_total": 10429,
- "inspected": 1241,
- "requested": 1241
- }
- }
- },
- "status": "unknown"
- },
- {
- "badge": "[UNKNOWN \u00b7 UNRESOLVED]",
- "blind_spot_codes": [],
- "blocker_codes": [
- "finding-candidate"
- ],
- "caveat": "This is not a population estimate; 3,375 rows remained ambiguous, and support must be recomputed when the evidence epoch, definition, or frame changes.",
- "claim_key": "finding.silent-proceed-lower-bound",
- "integrity_status": "unresolved",
- "integrity_verdict_present": false,
- "presets": [
- "readme",
- "launch",
- "findings-page",
- "verified-export"
- ],
- "public_evidence_refs": [
- "file:docs/findings/claim-vs-evidence.md",
- "file:.agent/demos/claim-vs-evidence/public-summary.json",
- "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json"
- ],
- "public_remediation_refs": [
- "bead:polylogue-37t.14"
- ],
- "publication": "In one bounded private-archive sample, 1,205 of 5,000 inspected structured failures were followed by silent continuation on the next assistant turn, a 24.1% lower bound.",
- "qualifiers": {
- "definition_ref": null,
- "evaluation_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration",
- "finding_epoch": "2026-07-04T08:55:53.667311+00:00",
- "finding_frame_ref": "file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame",
- "verdict_as_of_epoch": null,
- "verdict_frame_ref": null
- },
- "reason_codes": [
- "integrity-verdict-not-computed"
- ],
- "review": {
- "assertion_status": "candidate",
- "judgment_ref": null,
- "privacy": "pending",
- "publication": "pending"
- },
- "scope": "One private archive; an origin-stratified 5,000-row sample from a 42,033-row structured-failure frame; next assistant turn only.",
- "source_kind": "finding",
- "source_ref": "assertion:assertion-finding:e5da9c88d1c236d15648fc52ad7898d8a6f7018277e84c624bdc9e7c7d037689",
- "statistic": {
- "ambiguous": 3375,
- "denominator": 5000,
- "numerator": 1205,
- "op": "lower_bound",
- "unit": "ratio",
- "value": 0.241
- },
- "status": "unknown"
- }
- ],
- "preset": "verified-export",
- "publishable_claim_keys": [
- "category.local-evidence-system"
- ],
- "schema": "polylogue.public-claims-view.v1"
-}
diff --git a/docs/generated/public-claims/verified-export.md b/docs/generated/public-claims/verified-export.md
deleted file mode 100644
index 4847a85477..0000000000
--- a/docs/generated/public-claims/verified-export.md
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-# Verified Public-Claims Export
-
-This file is generated from FINDING assertions, canonical judgment state, and the shared evidence-integrity verdict. A badge is a current publication status, not a substitute for the cited evidence.
-
-## `category.local-evidence-system` [CAPABILITY ONLY]
-
-Polylogue archives your AI conversations - all of them, in one place, on your machine.
-
-- Scope: The current local archive, query, evidence, judgment, and context surfaces.
-- Caveat: This is a product-category capability statement, not a measured performance or prevalence claim.
-- Evidence: `file:README.md`, `file:docs/architecture.md`, `file:docs/proof-artifacts.md`
-- Epoch/frame: not applicable (capability statement; no measured result)
-- Review: assertion=n/a, publication=approved, privacy=approved, judgment=none
-
-## `finding.handler-class-split` [UNKNOWN · UNRESOLVED]
-
-In that sample, the silent-continuation lower bound was 22.3% for consequential handlers, 27.1% for benign-recovery handlers, and 53.9% for other handlers.
-
-- Scope: The same 5,000 sampled failures, partitioned by the packet's explicit handler-class methodology: 4,175 consequential, 634 benign-recovery, and 191 other.
-- Caveat: The classes are method-defined tool-name groups, not severity labels; each group retains a large or material ambiguous remainder.
-- Evidence: `file:docs/findings/claim-vs-evidence.md`, `file:.agent/demos/claim-vs-evidence/public-summary.json`, `file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json`
-- Epoch/frame: finding epoch=2026-07-04T08:55:53.667311+00:00; verdict as-of=unknown; finding frame=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame; verdict frame=unknown; evaluation=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration; definition=unknown
-- Review: assertion=candidate, publication=pending, privacy=pending, judgment=none
-- Status reasons: `finding-candidate`, `integrity-verdict-not-computed`
-- Remediation: `bead:polylogue-37t.14`
-
-## `finding.per-origin-inspection-counts` [UNKNOWN · UNRESOLVED]
-
-The origin-stratified sample inspected 3,752 Claude Code, 1,241 Codex, and seven Claude AI structured failures from origin frames of 31,555, 10,429, and 49 respectively.
-
-- Scope: The 2026-07-04 bounded sample frame, selected deterministically by origin, session, tool, and result-message identifiers.
-- Caveat: These are inspection and frame counts, not provider prevalence estimates; the archive's origin mix and the bounded allocation determine them.
-- Evidence: `file:docs/findings/claim-vs-evidence.md`, `file:.agent/demos/claim-vs-evidence/public-summary.json`, `file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json`
-- Epoch/frame: finding epoch=2026-07-04T08:55:53.667311+00:00; verdict as-of=unknown; finding frame=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame; verdict frame=unknown; evaluation=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration; definition=unknown
-- Review: assertion=candidate, publication=pending, privacy=pending, judgment=none
-- Status reasons: `finding-candidate`, `integrity-verdict-not-computed`
-- Remediation: `bead:polylogue-37t.14`
-
-## `finding.silent-proceed-lower-bound` [UNKNOWN · UNRESOLVED]
-
-In one bounded private-archive sample, 1,205 of 5,000 inspected structured failures were followed by silent continuation on the next assistant turn, a 24.1% lower bound.
-
-- Scope: One private archive; an origin-stratified 5,000-row sample from a 42,033-row structured-failure frame; next assistant turn only.
-- Caveat: This is not a population estimate; 3,375 rows remained ambiguous, and support must be recomputed when the evidence epoch, definition, or frame changes.
-- Evidence: `file:docs/findings/claim-vs-evidence.md`, `file:.agent/demos/claim-vs-evidence/public-summary.json`, `file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json`
-- Epoch/frame: finding epoch=2026-07-04T08:55:53.667311+00:00; verdict as-of=unknown; finding frame=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#sample_frame; verdict frame=unknown; evaluation=file:.agent/demos/claim-vs-evidence/claim-vs-evidence.report.json#calibration; definition=unknown
-- Review: assertion=candidate, publication=pending, privacy=pending, judgment=none
-- Status reasons: `finding-candidate`, `integrity-verdict-not-computed`
-- Remediation: `bead:polylogue-37t.14`
diff --git a/docs/generated/semantic-card-tool-map.json b/docs/generated/semantic-card-tool-map.json
deleted file mode 100644
index f74d1573c3..0000000000
--- a/docs/generated/semantic-card-tool-map.json
+++ /dev/null
@@ -1,531 +0,0 @@
-{
- "schema_version": "semantic-card-tool-map.v1",
- "card_schema_version": "semantic-card.v1",
- "classification_policy": {
- "precedence": [
- "structural_mcp_tool_identity",
- "persisted_semantic_type",
- "exact_provider_tool_alias",
- "fallback"
- ],
- "unknown_tool": "fallback_raw_evidence",
- "outcome_policy": "structural_fields_only",
- "null_outcome": "unknown"
- },
- "provider_families": [
- "antigravity",
- "beads",
- "chatgpt",
- "claude-ai",
- "claude-code",
- "codex",
- "gemini-cli",
- "grok",
- "hermes",
- "unknown"
- ],
- "card_kinds": [
- "shell",
- "file_read",
- "file_edit",
- "search",
- "web",
- "task",
- "mcp",
- "lineage",
- "attachment",
- "fallback"
- ],
- "status_counts": {
- "fallback": 1,
- "launch": 22,
- "model_only": 5
- },
- "provider_namespace_policies": [
- {
- "origin": "claude-code-session",
- "provider_family": "claude-code",
- "namespace": "open",
- "grounded_exact_aliases": 14,
- "unlisted_behavior": "structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence"
- },
- {
- "origin": "codex-session",
- "provider_family": "codex",
- "namespace": "open",
- "grounded_exact_aliases": 8,
- "unlisted_behavior": "structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence"
- },
- {
- "origin": "gemini-cli-session",
- "provider_family": "gemini-cli",
- "namespace": "open",
- "grounded_exact_aliases": 1,
- "unlisted_behavior": "structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence"
- },
- {
- "origin": "hermes-session",
- "provider_family": "hermes",
- "namespace": "open",
- "grounded_exact_aliases": 2,
- "unlisted_behavior": "structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence"
- },
- {
- "origin": "antigravity-session",
- "provider_family": "antigravity",
- "namespace": "open",
- "grounded_exact_aliases": 0,
- "unlisted_behavior": "structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence"
- },
- {
- "origin": "beads-issue",
- "provider_family": "beads",
- "namespace": "open",
- "grounded_exact_aliases": 0,
- "unlisted_behavior": "structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence"
- },
- {
- "origin": "grok-export",
- "provider_family": "grok",
- "namespace": "open",
- "grounded_exact_aliases": 0,
- "unlisted_behavior": "structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence"
- },
- {
- "origin": "chatgpt-export",
- "provider_family": "chatgpt",
- "namespace": "open",
- "grounded_exact_aliases": 3,
- "unlisted_behavior": "structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence"
- },
- {
- "origin": "claude-ai-export",
- "provider_family": "claude-ai",
- "namespace": "open",
- "grounded_exact_aliases": 0,
- "unlisted_behavior": "structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence"
- },
- {
- "origin": "aistudio-drive",
- "provider_family": "gemini-cli",
- "namespace": "open",
- "grounded_exact_aliases": 1,
- "unlisted_behavior": "structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence"
- },
- {
- "origin": "unknown-export",
- "provider_family": "unknown",
- "namespace": "open",
- "grounded_exact_aliases": 0,
- "unlisted_behavior": "structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence"
- }
- ],
- "semantic_type_policies": [
- {
- "semantic_type": "other",
- "card_kind": "fallback",
- "rendering_status": "fallback",
- "classification_basis": "persisted_semantic_type",
- "fallback_reason": "the persisted semantic family is intentionally generic"
- },
- {
- "semantic_type": "file_read",
- "card_kind": "file_read",
- "rendering_status": "launch",
- "classification_basis": "persisted_semantic_type",
- "fallback_reason": null
- },
- {
- "semantic_type": "file_write",
- "card_kind": "file_edit",
- "rendering_status": "launch",
- "classification_basis": "persisted_semantic_type",
- "fallback_reason": null
- },
- {
- "semantic_type": "file_edit",
- "card_kind": "file_edit",
- "rendering_status": "launch",
- "classification_basis": "persisted_semantic_type",
- "fallback_reason": null
- },
- {
- "semantic_type": "shell",
- "card_kind": "shell",
- "rendering_status": "launch",
- "classification_basis": "persisted_semantic_type",
- "fallback_reason": null
- },
- {
- "semantic_type": "git",
- "card_kind": "shell",
- "rendering_status": "launch",
- "classification_basis": "persisted_semantic_type",
- "fallback_reason": null
- },
- {
- "semantic_type": "search",
- "card_kind": "search",
- "rendering_status": "launch",
- "classification_basis": "persisted_semantic_type",
- "fallback_reason": null
- },
- {
- "semantic_type": "web",
- "card_kind": "web",
- "rendering_status": "launch",
- "classification_basis": "persisted_semantic_type",
- "fallback_reason": null
- },
- {
- "semantic_type": "agent",
- "card_kind": "task",
- "rendering_status": "model_only",
- "classification_basis": "persisted_semantic_type",
- "fallback_reason": null
- },
- {
- "semantic_type": "subagent",
- "card_kind": "task",
- "rendering_status": "model_only",
- "classification_basis": "persisted_semantic_type",
- "fallback_reason": null
- },
- {
- "semantic_type": "thinking",
- "card_kind": "fallback",
- "rendering_status": "fallback",
- "classification_basis": "persisted_semantic_type",
- "fallback_reason": "thinking is rendered from typed content blocks, not as a tool card"
- }
- ],
- "provider_semantic_coverage": [
- {
- "provider_family": "antigravity",
- "semantic_types": [],
- "exact_alias_count": 0
- },
- {
- "provider_family": "beads",
- "semantic_types": [],
- "exact_alias_count": 0
- },
- {
- "provider_family": "chatgpt",
- "semantic_types": [
- "file_edit",
- "other",
- "web"
- ],
- "exact_alias_count": 3
- },
- {
- "provider_family": "claude-ai",
- "semantic_types": [],
- "exact_alias_count": 0
- },
- {
- "provider_family": "claude-code",
- "semantic_types": [
- "agent",
- "file_edit",
- "file_read",
- "file_write",
- "search",
- "shell",
- "subagent",
- "web"
- ],
- "exact_alias_count": 14
- },
- {
- "provider_family": "codex",
- "semantic_types": [
- "file_edit",
- "search",
- "shell",
- "subagent",
- "web"
- ],
- "exact_alias_count": 8
- },
- {
- "provider_family": "gemini-cli",
- "semantic_types": [
- "file_read"
- ],
- "exact_alias_count": 1
- },
- {
- "provider_family": "grok",
- "semantic_types": [],
- "exact_alias_count": 0
- },
- {
- "provider_family": "hermes",
- "semantic_types": [
- "shell"
- ],
- "exact_alias_count": 2
- },
- {
- "provider_family": "unknown",
- "semantic_types": [],
- "exact_alias_count": 0
- }
- ],
- "rows": [
- {
- "provider_family": "claude-code",
- "tool_name": "Bash",
- "semantic_type": "shell",
- "card_kind": "shell",
- "rendering_status": "launch",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_base.py"
- },
- {
- "provider_family": "claude-code",
- "tool_name": "Edit",
- "semantic_type": "file_edit",
- "card_kind": "file_edit",
- "rendering_status": "launch",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_base.py"
- },
- {
- "provider_family": "claude-code",
- "tool_name": "Write",
- "semantic_type": "file_write",
- "card_kind": "file_edit",
- "rendering_status": "launch",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_base.py"
- },
- {
- "provider_family": "claude-code",
- "tool_name": "NotebookEdit",
- "semantic_type": "file_edit",
- "card_kind": "file_edit",
- "rendering_status": "launch",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_base.py"
- },
- {
- "provider_family": "claude-code",
- "tool_name": "Task",
- "semantic_type": "subagent",
- "card_kind": "task",
- "rendering_status": "model_only",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_base.py"
- },
- {
- "provider_family": "claude-code",
- "tool_name": "Read",
- "semantic_type": "file_read",
- "card_kind": "file_read",
- "rendering_status": "launch",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_base.py"
- },
- {
- "provider_family": "claude-code",
- "tool_name": "Grep",
- "semantic_type": "search",
- "card_kind": "search",
- "rendering_status": "launch",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_base.py"
- },
- {
- "provider_family": "claude-code",
- "tool_name": "Glob",
- "semantic_type": "search",
- "card_kind": "search",
- "rendering_status": "launch",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_base.py"
- },
- {
- "provider_family": "claude-code",
- "tool_name": "MultiEdit",
- "semantic_type": "file_edit",
- "card_kind": "file_edit",
- "rendering_status": "launch",
- "evidence_kind": "classifier_contract",
- "evidence": "polylogue/archive/viewport/tools.py"
- },
- {
- "provider_family": "claude-code",
- "tool_name": "WebFetch",
- "semantic_type": "web",
- "card_kind": "web",
- "rendering_status": "launch",
- "evidence_kind": "classifier_contract",
- "evidence": "polylogue/archive/viewport/tools.py"
- },
- {
- "provider_family": "claude-code",
- "tool_name": "WebSearch",
- "semantic_type": "web",
- "card_kind": "web",
- "rendering_status": "launch",
- "evidence_kind": "classifier_contract",
- "evidence": "polylogue/archive/viewport/tools.py"
- },
- {
- "provider_family": "claude-code",
- "tool_name": "AskUserQuestion",
- "semantic_type": "agent",
- "card_kind": "task",
- "rendering_status": "model_only",
- "evidence_kind": "classifier_contract",
- "evidence": "polylogue/archive/viewport/tools.py"
- },
- {
- "provider_family": "claude-code",
- "tool_name": "EnterPlanMode",
- "semantic_type": "agent",
- "card_kind": "task",
- "rendering_status": "model_only",
- "evidence_kind": "classifier_contract",
- "evidence": "polylogue/archive/viewport/tools.py"
- },
- {
- "provider_family": "claude-code",
- "tool_name": "ExitPlanMode",
- "semantic_type": "agent",
- "card_kind": "task",
- "rendering_status": "model_only",
- "evidence_kind": "classifier_contract",
- "evidence": "polylogue/archive/viewport/tools.py"
- },
- {
- "provider_family": "codex",
- "tool_name": "exec_command",
- "semantic_type": "shell",
- "card_kind": "shell",
- "rendering_status": "launch",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_codex_event_stream_contract.py"
- },
- {
- "provider_family": "codex",
- "tool_name": "shell",
- "semantic_type": "shell",
- "card_kind": "shell",
- "rendering_status": "launch",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_codex.py"
- },
- {
- "provider_family": "codex",
- "tool_name": "apply_patch",
- "semantic_type": "file_edit",
- "card_kind": "file_edit",
- "rendering_status": "launch",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_codex.py"
- },
- {
- "provider_family": "codex",
- "tool_name": "search",
- "semantic_type": "search",
- "card_kind": "search",
- "rendering_status": "launch",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_codex.py"
- },
- {
- "provider_family": "codex",
- "tool_name": "local_shell_call",
- "semantic_type": "shell",
- "card_kind": "shell",
- "rendering_status": "launch",
- "evidence_kind": "parser_record_type",
- "evidence": "polylogue/sources/parsers/codex.py"
- },
- {
- "provider_family": "codex",
- "tool_name": "tool_search_call",
- "semantic_type": "search",
- "card_kind": "search",
- "rendering_status": "launch",
- "evidence_kind": "parser_record_type",
- "evidence": "polylogue/sources/parsers/codex.py"
- },
- {
- "provider_family": "codex",
- "tool_name": "web_search_call",
- "semantic_type": "web",
- "card_kind": "web",
- "rendering_status": "launch",
- "evidence_kind": "parser_record_type",
- "evidence": "polylogue/sources/parsers/codex.py"
- },
- {
- "provider_family": "codex",
- "tool_name": "spawn_agent",
- "semantic_type": "subagent",
- "card_kind": "task",
- "rendering_status": "model_only",
- "evidence_kind": "classifier_contract",
- "evidence": "polylogue/archive/viewport/tools.py"
- },
- {
- "provider_family": "gemini-cli",
- "tool_name": "read_file",
- "semantic_type": "file_read",
- "card_kind": "file_read",
- "rendering_status": "launch",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_local_agent.py"
- },
- {
- "provider_family": "hermes",
- "tool_name": "shell",
- "semantic_type": "shell",
- "card_kind": "shell",
- "rendering_status": "launch",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_local_agent.py"
- },
- {
- "provider_family": "hermes",
- "tool_name": "run_shell_command",
- "semantic_type": "shell",
- "card_kind": "shell",
- "rendering_status": "launch",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_local_agent.py"
- },
- {
- "provider_family": "chatgpt",
- "tool_name": "canmore.update_textdoc",
- "semantic_type": "file_edit",
- "card_kind": "file_edit",
- "rendering_status": "launch",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_chatgpt.py"
- },
- {
- "provider_family": "chatgpt",
- "tool_name": "web",
- "semantic_type": "web",
- "card_kind": "web",
- "rendering_status": "launch",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_chatgpt.py"
- },
- {
- "provider_family": "chatgpt",
- "tool_name": "dalle.text2im",
- "semantic_type": "other",
- "card_kind": "fallback",
- "rendering_status": "fallback",
- "evidence_kind": "fixture_observed",
- "evidence": "tests/unit/sources/test_parsers_chatgpt.py"
- }
- ]
-}
diff --git a/docs/generated/semantic-card-tool-map.md b/docs/generated/semantic-card-tool-map.md
deleted file mode 100644
index edbfdebd2a..0000000000
--- a/docs/generated/semantic-card-tool-map.md
+++ /dev/null
@@ -1,114 +0,0 @@
-
-
-# Semantic card tool map
-
-This is the review surface for the provider-neutral `semantic-card.v1` registry.
-Structural MCP identity wins, then persisted semantic type, then a repository-grounded
-exact provider/tool alias. Provider namespaces are open: an unlisted tool always becomes a raw fallback card,
-and names or prose are never fuzzily classified.
-
-`launch` means the shared CLI/API/web renderer has a specialized card. `model_only` means
-the shared card is intentionally generic at the presentation leaf. `fallback` is intentional
-raw evidence, not a missing hidden heuristic.
-
-## Persisted semantic-family policy
-
-This table is exhaustive over `SemanticBlockType`. It is the provider-neutral path used
-when a parser has already persisted a trusted family, including provider-private names
-that cannot be enumerated in the exact-alias tables.
-
-| Persisted semantic type | Card kind | Status |
-|---|---|---|
-| `other` | `fallback` | `fallback` |
-| `file_read` | `file_read` | `launch` |
-| `file_write` | `file_edit` | `launch` |
-| `file_edit` | `file_edit` | `launch` |
-| `shell` | `shell` | `launch` |
-| `git` | `shell` | `launch` |
-| `search` | `search` | `launch` |
-| `web` | `web` | `launch` |
-| `agent` | `task` | `model_only` |
-| `subagent` | `task` | `model_only` |
-| `thinking` | `fallback` | `fallback` |
-
-## Executable-origin policy
-
-Every `Origin` value has an explicit provider family and open-world fallback policy.
-
-| Origin | Provider family | Namespace | Grounded exact aliases | Unlisted behavior |
-|---|---|---|---:|---|
-| `claude-code-session` | `claude-code` | `open` | 14 | `structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence` |
-| `codex-session` | `codex` | `open` | 8 | `structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence` |
-| `gemini-cli-session` | `gemini-cli` | `open` | 1 | `structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence` |
-| `hermes-session` | `hermes` | `open` | 2 | `structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence` |
-| `antigravity-session` | `antigravity` | `open` | 0 | `structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence` |
-| `beads-issue` | `beads` | `open` | 0 | `structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence` |
-| `grok-export` | `grok` | `open` | 0 | `structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence` |
-| `chatgpt-export` | `chatgpt` | `open` | 3 | `structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence` |
-| `claude-ai-export` | `claude-ai` | `open` | 0 | `structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence` |
-| `aistudio-drive` | `gemini-cli` | `open` | 1 | `structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence` |
-| `unknown-export` | `unknown` | `open` | 0 | `structural_mcp_then_persisted_semantic_type_then_fallback_raw_evidence` |
-
-## Provider exact-alias census
-
-## chatgpt
-
-| Exact tool name | Semantic type | Card kind | Status | Basis | Evidence |
-|---|---|---|---|---|---|
-| `canmore.update_textdoc` | `file_edit` | `file_edit` | `launch` | `fixture_observed` | `tests/unit/sources/test_parsers_chatgpt.py` |
-| `dalle.text2im` | `other` | `fallback` | `fallback` | `fixture_observed` | `tests/unit/sources/test_parsers_chatgpt.py` |
-| `web` | `web` | `web` | `launch` | `fixture_observed` | `tests/unit/sources/test_parsers_chatgpt.py` |
-
-## claude-code
-
-| Exact tool name | Semantic type | Card kind | Status | Basis | Evidence |
-|---|---|---|---|---|---|
-| `AskUserQuestion` | `agent` | `task` | `model_only` | `classifier_contract` | `polylogue/archive/viewport/tools.py` |
-| `Bash` | `shell` | `shell` | `launch` | `fixture_observed` | `tests/unit/sources/test_parsers_base.py` |
-| `Edit` | `file_edit` | `file_edit` | `launch` | `fixture_observed` | `tests/unit/sources/test_parsers_base.py` |
-| `EnterPlanMode` | `agent` | `task` | `model_only` | `classifier_contract` | `polylogue/archive/viewport/tools.py` |
-| `ExitPlanMode` | `agent` | `task` | `model_only` | `classifier_contract` | `polylogue/archive/viewport/tools.py` |
-| `Glob` | `search` | `search` | `launch` | `fixture_observed` | `tests/unit/sources/test_parsers_base.py` |
-| `Grep` | `search` | `search` | `launch` | `fixture_observed` | `tests/unit/sources/test_parsers_base.py` |
-| `MultiEdit` | `file_edit` | `file_edit` | `launch` | `classifier_contract` | `polylogue/archive/viewport/tools.py` |
-| `NotebookEdit` | `file_edit` | `file_edit` | `launch` | `fixture_observed` | `tests/unit/sources/test_parsers_base.py` |
-| `Read` | `file_read` | `file_read` | `launch` | `fixture_observed` | `tests/unit/sources/test_parsers_base.py` |
-| `Task` | `subagent` | `task` | `model_only` | `fixture_observed` | `tests/unit/sources/test_parsers_base.py` |
-| `WebFetch` | `web` | `web` | `launch` | `classifier_contract` | `polylogue/archive/viewport/tools.py` |
-| `WebSearch` | `web` | `web` | `launch` | `classifier_contract` | `polylogue/archive/viewport/tools.py` |
-| `Write` | `file_write` | `file_edit` | `launch` | `fixture_observed` | `tests/unit/sources/test_parsers_base.py` |
-
-## codex
-
-| Exact tool name | Semantic type | Card kind | Status | Basis | Evidence |
-|---|---|---|---|---|---|
-| `apply_patch` | `file_edit` | `file_edit` | `launch` | `fixture_observed` | `tests/unit/sources/test_parsers_codex.py` |
-| `exec_command` | `shell` | `shell` | `launch` | `fixture_observed` | `tests/unit/sources/test_codex_event_stream_contract.py` |
-| `local_shell_call` | `shell` | `shell` | `launch` | `parser_record_type` | `polylogue/sources/parsers/codex.py` |
-| `search` | `search` | `search` | `launch` | `fixture_observed` | `tests/unit/sources/test_parsers_codex.py` |
-| `shell` | `shell` | `shell` | `launch` | `fixture_observed` | `tests/unit/sources/test_parsers_codex.py` |
-| `spawn_agent` | `subagent` | `task` | `model_only` | `classifier_contract` | `polylogue/archive/viewport/tools.py` |
-| `tool_search_call` | `search` | `search` | `launch` | `parser_record_type` | `polylogue/sources/parsers/codex.py` |
-| `web_search_call` | `web` | `web` | `launch` | `parser_record_type` | `polylogue/sources/parsers/codex.py` |
-
-## gemini-cli
-
-| Exact tool name | Semantic type | Card kind | Status | Basis | Evidence |
-|---|---|---|---|---|---|
-| `read_file` | `file_read` | `file_read` | `launch` | `fixture_observed` | `tests/unit/sources/test_parsers_local_agent.py` |
-
-## hermes
-
-| Exact tool name | Semantic type | Card kind | Status | Basis | Evidence |
-|---|---|---|---|---|---|
-| `run_shell_command` | `shell` | `shell` | `launch` | `fixture_observed` | `tests/unit/sources/test_parsers_local_agent.py` |
-| `shell` | `shell` | `shell` | `launch` | `fixture_observed` | `tests/unit/sources/test_parsers_local_agent.py` |
-
-## Gap-reading rules
-
-- Every executable origin has an explicit open namespace; the exact-alias table is evidence-backed rather than aspirational.
-- A structural `mcp__server__tool` identity is classified before provider aliases and exposes both server and tool coordinates.
-- A provider can emit tool names not listed here. Those cards preserve exact raw input and result evidence.
-- A persisted `semantic_type` can safely specialize a provider-private name because classification already happened upstream.
-- `NULL` structural result fields remain `unknown`; a success-like sentence is not a success signal.
-- Cross-page pairing is orchestrated from a whole-session projection; a bounded storage-level pairing index remains a performance follow-on.
diff --git a/docs/getting-started.md b/docs/getting-started.md
index df5ad155de..6573c7ee73 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -102,7 +102,7 @@ polylogued status
| Command | Purpose |
|---------|---------|
-| `polylogue ` | Full-text search |
+| `polylogue find ` | Full-text search |
| `polylogue --since read --all` | List matched sessions |
| `polylogue --origin analyze --count` | Count matched sessions |
| `polylogue analyze --by origin` | Grouped statistics |
diff --git a/docs/hermes-operators.md b/docs/hermes-operators.md
index f4c99ba854..d08ed7b59b 100644
--- a/docs/hermes-operators.md
+++ b/docs/hermes-operators.md
@@ -386,7 +386,7 @@ This is the section to read before you trust anything above it.
oversight: composing the primitive into a named CLI/MCP surface is
separate, tracked follow-up work.
4. **The named Hermes forensics report does not exist yet.** There is no
- `polylogue forensics hermes` command or `read --view forensics`. What
+ dedicated Hermes forensics command or `read --view forensics`. What
exists today composes from generic, origin-agnostic primitives already
documented elsewhere: session topology (`get_session_topology`), the
postmortem bundle (`polylogue/insights/postmortem.py`,
@@ -469,13 +469,11 @@ identity used for the durable-retention guarantee above.
### MCP (agent-facing)
-The current standing MCP surface is a small set of unified verb tools —
-`query`, `read`, `get`, `explain`, `context`, `status` — the live contract
-enforced by `tests/infra/mcp.py:EXPECTED_TOOL_NAMES`
-(see `docs/agent-manual.md` for the generated, currently-accurate reference;
-treat `docs/mcp-reference.md`'s larger per-category tool list as describing
-an earlier surface generation, not this one). The `query` tool's typed
-request accepts an `origin` field
+The read-only MCP surface is the six unified tools `query`, `read`, `get`,
+`explain`, `context`, and `status`; write, judgment, and maintenance tools are
+separate capability opt-ins. Runtime declarations are authoritative and client
+discovery exposes the exact enabled surface. The `query` tool's typed request
+accepts an `origin` field
(`polylogue/mcp/query_contracts.py:88`) exactly like the CLI's `--origin`
flag, so `query(origin="hermes-session", ...)` scopes a search or aggregate
to Hermes sessions the same way.
diff --git a/docs/internals.md b/docs/internals.md
index 534d667129..dc51aaba0d 100644
--- a/docs/internals.md
+++ b/docs/internals.md
@@ -193,28 +193,19 @@ Polylogue has two schema-evolution regimes, keyed by tier durability.
batched before a live rebuild so the active archive is not reset repeatedly.
- `devtools lab policy schema-versioning` enforces the boundary: durable SQL
migrations are allowed only under the numbered migration resource roots, while
- derived-tier upgrade helpers remain forbidden. **This check is keyed to
- `INDEX_SCHEMA_VERSION` and cannot see parser/classifier drift** -- a
- `looks_like*`/`classify_artifact*` function under `polylogue/sources/` or
- `polylogue/archive/artifact_taxonomy/` can change what it accepts for
- identical input bytes with no version bump at all, running this lint green
- while already-indexed rows silently go stale (polylogue-gucv; PR #3428 is
- the confirmed case). The same blindness applies to a purely declarative
- admission table: `origin_specs.py`'s `OriginSpec.artifact_rules` sets a
- `parse_policy` (`session`/`fact`/`raw-only`) per native path family with no
- function body at all, and PR #3088 changed `parse_as_session` for four
- Claude Workflow artifact kinds by editing that table with no version bump
- (retroactively declared as the missing v48 delta by polylogue-lzh8;
- polylogue-qs4b). `devtools lab policy classifier-fingerprints`
- (`devtools/verify_classifier_fingerprints.py`) closes both gaps: it
- fingerprints every in-scope `looks_like*`/`classify_artifact*` function
- (AST hash, docstring excluded) **and** every `OriginArtifactRule` in
- `ORIGIN_SPECS` (hash of `path_pattern`/`parse_policy`/`parser_path`/
- `coverage_role`/`path_suffixes`, `fidelity_note` excluded) against a
- committed manifest (`docs/plans/classifier-fingerprints.json`) and fails on
- undeclared drift, requiring either a `SEMANTIC_REPARSE`-declared version
- bump or an explicit `acknowledged_safe` justification recorded in the
- manifest.
+ derived changes must use declared lifecycle deltas and clone-validated
+ fast-forward plans or rebuild. The gate validates those structured carriers
+ and SQL shapes rather than guessing intent from Python helper names.
+ Parser/classifier meaning is
+ governed separately by production fingerprints from
+ `polylogue.sources.origin_specs`: declared parser and assembly sources feed an
+ origin-scoped parser fingerprint, while shared lowering, replay routing, and
+ materialization have their own fingerprints. Archive rows and candidate/live
+ proof metadata carry these values; archive verification rejects stale or mixed
+ fingerprints. Behavioral tests prove that changing a declared parser,
+ assembly helper, or lowering source changes the corresponding fingerprint.
+ This makes semantic drift part of runtime archive authority instead of a
+ source-AST manifest that also fired on behavior-preserving refactors.
- User schema version 7 adds durable content-addressed `queries`, mutable
`query_names`, promoted `result_sets`/`result_set_members`, and planner
@@ -700,8 +691,10 @@ copy-forward design and explicit operator consent, never a routine migration.
`storage/sqlite/archive_tiers/bootstrap.py`
(ingest-cursor runtime fields, cursor-lag rollups). The
`devtools lab policy schema-versioning` lint enforces the whole boundary:
-numbered durable-tier migrations are allowed; derived-tier upgrade helpers are
-forbidden.
+numbered durable-tier migrations are allowed; derived-tier lifecycle deltas and
+same-version DDL are validated structurally. Ad hoc open-path upgrades are not a
+supported runtime route, but the lint does not pretend to detect them from
+function names.
## Archive Activation
@@ -801,15 +794,12 @@ the reconciled graph back through `SessionRepository.replace_work_evidence_graph
`reconcile-work-effects` reconciles an *existing* work-evidence graph against
independent repository effects; it never builds one. `polylogue/insights/
-incident_evidence_materialization.py` is the source-to-graph half: it adapts
+incident_evidence_materialization.py` materializes the source graph: it adapts
real per-session `ProjectedRun`/`ObservedEvent` evidence (one run node per
session run, `invoked`-linked parent→subagent; one session-segment node per
run; one `claim` node per subagent's own self-reported result; one
unresolved/inferred `effect` node per commit/PR/issue an in-session tool call
-mentioned) into a `WorkEvidenceGraph`, as opposed to
-`devtools/mandate_continuity_replay.py`'s `build_repository_claim_graph`,
-which builds claim nodes purely from the external `.beads/interactions.jsonl`
-ledger and never reads archived session/message/action content at all.
+mentioned) into a `WorkEvidenceGraph` from archived session evidence.
`polylogue/operations/incident_evidence_materialization.py`'s
`materialize_incident_work_evidence` is the production entry point — it
loads each selected session in full and compiles it through
@@ -1039,9 +1029,8 @@ implemented and unit-tested but **never reachable in production**: the only
call site that could have populated the lease payload keys
(`commit_archive_write_effects`'s `_blob_hashes`/`_operation_id`) was never
given them by any real ingest caller (`_commit_sync_ingest_side_effects`
-built its payload without them). A race-window audit
-(`docs/audits/2026-07-09-race-window-audit.md`, rows 1a/1b) confirmed zero
-production callers across the whole write path, so `has_lease` was always
+built its payload without them). Source-history review and the production-route
+tests confirmed zero production callers across the whole write path, so `has_lease` was always
`False` and the acquire/release calls never ran. The mechanism was removed
rather than left as dead code implying a protection that did not exist
(polylogue-v7e0). A deterministic provider-shaped measurement later proved
diff --git a/docs/library-api.md b/docs/library-api.md
index 2233aeebba..23e2dd0484 100644
--- a/docs/library-api.md
+++ b/docs/library-api.md
@@ -330,342 +330,6 @@ asyncio.run(main())
| `list_tool_usage_insights(query)` | Per-provider tool usage with explicit coverage gaps |
| `list_archive_debt_insights(query)` | List governed archive-debt insights |
-
-
-## Generated facade operation index
-
-This reference is generated from `polylogue/api/operation_parity.py`. Each live public facade callable is bound to a stable semantic operation ID; exported data models and adapter helpers are listed as intentional exclusions in the committed [machine-readable matrix](generated/api-operation-parity.json).
-
-### Lifecycle and builders
-
-#### `api.lifecycle.construct`
-
-Construct, open, and close a facade bound to one archive runtime.
-
-Route/tier class: `lifecycle`. CLI: Intentional absence: `polylogue-s1kr`. MCP: Intentional absence: `polylogue-s1kr`.
-
-| Python callable | Signature |
-|---|---|
-| `Polylogue` | Constructed facade builder |
-| `Polylogue.__init__` | `(archive_root: 'str | Path | None' = None, db_path: 'str | Path | None' = None, *, runtime: 'ResolvedRuntimeConfig | None' = None, config: 'Config | None' = None) -> 'None'` |
-| `Polylogue.open` | `(*, config: 'Config | None' = None, runtime: 'ResolvedRuntimeConfig | None' = None, **kwargs: 'object') -> 'Polylogue'` |
-| `Polylogue.__aenter__` | `async (self) -> 'Polylogue'` |
-| `Polylogue.__aexit__` | `async (self, exc_type: 'object', exc_val: 'object', exc_tb: 'object') -> 'None'` |
-| `Polylogue.close` | `async (self) -> 'None'` |
-
-### Embedding readiness
-
-#### `api.embedding.status`
-
-Read the no-spend embedding readiness state.
-
-Route/tier class: `embedding-status`. CLI: `ops embed status`. MCP: `status`.
-
-| Python callable | Signature |
-|---|---|
-| `Polylogue.embedding_status` | `(self, *, detail: 'bool' = False) -> 'dict[str, object]'` |
-
-#### `api.embedding.preflight`
-
-Calculate a bounded no-provider-call embedding catch-up window.
-
-Route/tier class: `embedding-preflight`. CLI: `ops embed preflight`. MCP: `status`.
-
-| Python callable | Signature |
-|---|---|
-| `Polylogue.embedding_preflight` | `(self, *, rebuild: 'bool' = False, max_sessions: 'int | None' = None, max_messages: 'int | None' = None, max_cost_usd: 'float | None' = None) -> 'dict[str, object]'` |
-
-### Embedding retrieval
-
-#### `api.embedding.search`
-
-Search stored session vectors using the embeddings tier.
-
-Route/tier class: `embedding-read`. CLI: `find similar`. MCP: `query`.
-
-| Python callable | Signature |
-|---|---|
-| `Polylogue.search_similar_sessions` | `async (self, session_id: 'str', *, limit: 'int' = 10, vector_provider: 'VectorProvider | None' = None, voyage_api_key: 'str | None' = None) -> 'dict[str, object]'` |
-
-### Ingestion and derived maintenance
-
-#### `api.ingest.parse`
-
-Parse configured or explicit sources into source and index tiers.
-
-Route/tier class: `source-index-write`. CLI: `import`. MCP: `run`.
-
-| Python callable | Signature |
-|---|---|
-| `Polylogue.parse_file` | `async (self, path: 'str | Path', *, source_name: 'str | None' = None) -> 'ParseResult'` |
-| `Polylogue.parse_sources` | `async (self, sources: 'list[Source] | None' = None, *, download_assets: 'bool' = True) -> 'ParseResult'` |
-
-#### `api.index.rebuild`
-
-Rebuild or update the derived index through the mutation executor.
-
-Route/tier class: `index-write`. CLI: `ops reset --index`. MCP: `maintenance`.
-
-| Python callable | Signature |
-|---|---|
-| `Polylogue.rebuild_index` | `async (self) -> 'bool'` |
-| `Polylogue.update_index` | `async (self, session_ids: 'list[str]') -> 'bool'` |
-| `Polylogue.rebuild_insights` | `async (self, session_ids: 'Sequence[str] | None' = None, *, progress_callback: 'ProgressCallback | None' = None) -> 'SessionInsightCounts'` |
-
-### Archive reads
-
-#### `api.archive.session-read`
-
-Read sessions, summaries, messages, actions, and archive statistics from the index tier.
-
-Route/tier class: `index-read`. CLI: `find`, `read`. MCP: `query`, `read`, `get`, `status`.
-
-| Python callable | Signature |
-|---|---|
-| `Polylogue.get_session` | `async (self, session_id: 'str', *, content_projection: 'ContentProjectionSpec | None' = None) -> 'Session | None'` |
-| `Polylogue.get_sessions` | `async (self, session_ids: 'list[str]', *, content_projection: 'ContentProjectionSpec | None' = None) -> 'list[Session]'` |
-| `Polylogue.get_actions_batch` | `async (self, session_ids: 'builtins.list[str]') -> 'dict[str, tuple[Action, ...]]'` |
-| `Polylogue.list_sessions` | `async (self, origin: 'str | None' = None, limit: 'int | None' = None, content_projection: 'ContentProjectionSpec | None' = None) -> 'list[Session]'` |
-| `Polylogue.list_summaries` | `async (self, *, limit: 'int | None' = 50, offset: 'int' = 0, origin: 'str | None' = None) -> 'builtins.list[SessionSummary]'` |
-| `Polylogue.list_sessions_for_spec` | `async (self, spec: 'SessionQuerySpec', *, content_projection: 'ContentProjectionSpec | None' = None) -> 'list[Session]'` |
-| `Polylogue.search_session_hits` | `async (self, spec: 'SessionQuerySpec') -> 'builtins.list[SessionSearchHit]'` |
-| `Polylogue.search` | `async (self, query: 'str', *, limit: 'int' = 100, source: 'str | None' = None, since: 'str | None' = None) -> 'SearchResult'` |
-| `Polylogue.search_envelope` | `async (self, query: 'str', *, limit: 'int' = 50, offset: 'int' = 0, origin: 'str | None' = None, since: 'str | None' = None, until: 'str | None' = None, retrieval_lane: 'str' = 'auto', sort: 'str | None' = None, cursor: 'str | None' = None) -> 'SearchEnvelope'` |
-| `Polylogue.archive_count_sessions` | `async (self, *, origin: 'str | None' = None, excluded_origins: 'Sequence[str]' = (), tags: 'Sequence[str]' = (), excluded_tags: 'Sequence[str]' = (), repo_names: 'Sequence[str]' = (), project_refs: 'Sequence[str]' = (), has_types: 'Sequence[str]' = (), has_tool_use: 'bool' = False, has_thinking: 'bool' = False, has_paste: 'bool' = False, tool_terms: 'Sequence[str]' = (), excluded_tool_terms: 'Sequence[str]' = (), action_terms: 'Sequence[str]' = (), excluded_action_terms: 'Sequence[str]' = (), action_sequence: 'Sequence[str]' = (), action_text_terms: 'Sequence[str]' = (), referenced_paths: 'Sequence[str]' = (), cwd_prefix: 'str | None' = None, typed_only: 'bool' = False, message_type: 'str | None' = None, title: 'str | None' = None, min_messages: 'int | None' = None, max_messages: 'int | None' = None, min_words: 'int | None' = None, max_words: 'int | None' = None, since: 'str | None' = None, until: 'str | None' = None) -> 'int'` |
-| `Polylogue.archive_get_session` | `async (self, session_id: 'str') -> 'ArchiveSessionEnvelope | None'` |
-| `Polylogue.get_messages_paginated` | `async (self, session_id: 'str', *, message_role: 'MessageRoleFilter' = (), message_type: 'MessageTypeName | None' = None, material_origin: 'tuple[MaterialOrigin, ...]' = (), limit: 'int' = 50, offset: 'int' = 0, content_projection: 'ContentProjectionSpec | None' = None) -> 'tuple[list[Message], int, LineageCompleteness]'` |
-| `Polylogue.iter_messages` | `(self, session_id: 'str', *, message_roles: 'MessageRoleFilter' = (), material_origin: 'tuple[MaterialOrigin, ...]' = (), limit: 'int | None' = None) -> 'AsyncIterator[Message]'` |
-| `Polylogue.bulk_get_messages` | `async (self, session_ids: 'Sequence[str]', *, since: 'str | None' = None, until: 'str | None' = None, message_role: 'MessageRoleFilter' = (), material_origin: 'tuple[MaterialOrigin, ...]' = (), content_projection: 'ContentProjectionSpec | None' = None) -> 'dict[str, list[Message]]'` |
-| `Polylogue.query_sessions` | `async (self, *, origin: 'str | None' = None, tag: 'str | None' = None, since: 'str | None' = None, until: 'str | None' = None, sort: 'str | None' = None, limit: 'int | None' = None, offset: 'int' = 0, has_tool_use: 'bool' = False, has_thinking: 'bool' = False, has_paste: 'bool' = False, typed_only: 'bool' = False, min_messages: 'int | None' = None, max_messages: 'int | None' = None, min_words: 'int | None' = None, **kwargs: 'object') -> 'builtins.list[dict[str, object]]'` |
-| `Polylogue.count_sessions` | `async (self, *, origin: 'str | None' = None, since: 'str | None' = None, until: 'str | None' = None, **kwargs: 'object') -> 'int'` |
-| `Polylogue.get_session_summary` | `async (self, session_id: 'str') -> 'SessionSummary | None'` |
-| `Polylogue.get_session_stats` | `async (self, session_id: 'str') -> 'dict[str, int]'` |
-| `Polylogue.get_stats_by` | `async (self, group_by: 'str' = 'origin') -> 'dict[str, int]'` |
-| `Polylogue.get_index_status` | `async (self) -> 'IndexStatus'` |
-| `Polylogue.stats` | `async (self) -> 'ArchiveStats'` |
-| `Polylogue.storage_stats` | `async (self) -> 'StorageArchiveStats'` |
-| `Polylogue.facets` | `async (self, spec: 'SessionQuerySpec | None' = None, *, include_idf: 'bool' = True, include_deferred: 'bool' = True) -> 'FacetsResponse'` |
-| `Polylogue.health_check` | `async (self) -> 'ReadinessReport'` |
-| `Polylogue.filter` | `(self) -> 'SessionFilter'` |
-| `Polylogue.list_read_view_profiles` | `async (self) -> 'list[JSONDocument]'` |
-
-#### `api.archive.query-analysis`
-
-Compile, explain, diagnose, and resolve archive query and reference projections.
-
-Route/tier class: `index-read`. CLI: `find`, `read`, `analyze`. MCP: `query`, `read`, `get`, `explain`.
-
-| Python callable | Signature |
-|---|---|
-| `Polylogue.explain_query_expression` | `async (self, expression: 'str') -> 'JSONDocument'` |
-| `Polylogue.query_units` | `async (self, expression: 'str | None' = None, *, limit: 'int | None' = None, offset: 'int | None' = None, origin: 'str | None' = None, origins: 'tuple[str, ...]' = (), excluded_origins: 'tuple[str, ...]' = (), tag: 'str | None' = None, tags: 'tuple[str, ...]' = (), excluded_tags: 'tuple[str, ...]' = (), repo: 'str | None' = None, repo_names: 'tuple[str, ...]' = (), project: 'str | None' = None, project_refs: 'tuple[str, ...]' = (), has_types: 'tuple[str, ...]' = (), tool_terms: 'tuple[str, ...]' = (), excluded_tool_terms: 'tuple[str, ...]' = (), action_terms: 'tuple[str, ...]' = (), excluded_action_terms: 'tuple[str, ...]' = (), action_sequence: 'tuple[str, ...]' = (), action_text_terms: 'tuple[str, ...]' = (), referenced_paths: 'tuple[str, ...]' = (), cwd_prefix: 'str | None' = None, title: 'str | None' = None, since: 'str | None' = None, until: 'str | None' = None, has_tool_use: 'bool' = False, has_thinking: 'bool' = False, has_paste: 'bool' = False, typed_only: 'bool' = False, min_messages: 'int | None' = None, max_messages: 'int | None' = None, min_words: 'int | None' = None, max_words: 'int | None' = None, message_type: 'str | None' = None, continuation: 'str | None' = None) -> 'QueryUnitResultEnvelope'` |
-| `Polylogue.query_completions` | `async (self, kind: 'str', *, incomplete: 'str' = '', unit: 'str | None' = None, field: 'str | None' = None) -> 'JSONDocument'` |
-| `Polylogue.diagnose_query_miss` | `async (self, spec: 'SessionQuerySpec', *, full: 'bool' = False) -> 'QueryMissDiagnostics'` |
-| `Polylogue.resolve_ref` | `async (self, ref: 'str') -> 'PublicRefResolutionPayload'` |
-| `Polylogue.export_otel` | `async (self, *, source_ref: 'str', expressions: 'Sequence[str]', limit: 'int' = 50, include_message_text: 'bool' = False) -> 'OtelProjectionPayload'` |
-| `Polylogue.neighbor_candidates` | `async (self, *, session_id: 'str | None' = None, query: 'str | None' = None, origin: 'str | None' = None, limit: 'int' = 10, window_hours: 'int' = 24) -> 'list[SessionNeighborCandidate]'` |
-| `Polylogue.neighbor_candidate_payloads` | `async (self, *, session_id: 'str | None' = None, query: 'str | None' = None, origin: 'str | None' = None, limit: 'int' = 10, window_hours: 'int' = 24) -> 'list[JSONDocument]'` |
-| `Polylogue.session_correlation_payload` | `async (self, session_id: 'str', *, repo_path: 'str | None' = None, since_hours: 'int' = 2, confidence_threshold: 'float' = 0.3) -> 'JSONDocument | None'` |
-| `Polylogue.origin_usage_report` | `async (self, *, origin: 'str | None' = None, limit: 'int | None' = 25, detail: 'str' = 'full') -> 'ProviderUsageReport'` |
-| `Polylogue.session_usage_reconciliation` | `async (self, session_id: 'str') -> 'SessionUsageReconciliation'` |
-| `Polylogue.resume_brief` | `async (self, session_id: 'str', *, related_limit: 'int' = 6, repo_path: 'str | None' = None, recent_files: 'Sequence[str]' = ()) -> 'ResumeBrief | None'` |
-| `Polylogue.find_resume_candidates` | `async (self, *, repo_path: 'str', cwd: 'str | None' = None, recent_files: 'Sequence[str]' = (), limit: 'int' = 10) -> 'tuple[ResumeCandidate, ...]'` |
-
-### Source evidence reads
-
-#### `api.archive.source-evidence-read`
-
-Read raw artifacts and provider-side evidence retained in the durable source tier.
-
-Route/tier class: `source-read`. CLI: `read`, `analyze`. MCP: `read`, `explain`.
-
-| Python callable | Signature |
-|---|---|
-| `Polylogue.explain_import` | `async (self, path: 'str | Path | None' = None, *, raw_ref: 'str | None' = None, source_path: 'str | None' = None, source_name: 'str' = 'unknown', limit: 'int' = 100, redact_paths: 'bool' = True) -> 'ImportExplainPayload'` |
-| `Polylogue.get_raw_artifacts_for_session` | `async (self, session_id: 'str', *, limit: 'int' = 50, offset: 'int' = 0) -> 'tuple[list[dict[str, object]], int]'` |
-| `Polylogue.get_hook_event_summary_for_session` | `async (self, session_id: 'str') -> 'dict[str, object] | None'` |
-| `Polylogue.get_session_events` | `async (self, session_id: 'str', *, event_type: 'str | None' = None, limit: 'int | None' = None) -> 'list[dict[str, object]] | None'` |
-| `Polylogue.get_file_edits` | `async (self, session_id: 'str') -> 'list[dict[str, object]] | None'` |
-| `Polylogue.get_web_content_constructs` | `async (self, session_id: 'str', *, construct_type: 'str | None' = None) -> 'list[dict[str, object]] | None'` |
-| `Polylogue.get_agent_policies` | `async (self, session_id: 'str') -> 'list[dict[str, object]] | None'` |
-
-### Insights and topology
-
-#### `api.archive.insight-read`
-
-Read materialized archive insights, topology, and derived archive health from the index tier.
-
-Route/tier class: `index-read`. CLI: `analyze`, `read`. MCP: `query`, `get`, `status`, `explain`.
-
-| Python callable | Signature |
-|---|---|
-| `Polylogue.get_session_insight_status` | `async (self) -> 'SessionInsightStatusSnapshot'` |
-| `Polylogue.get_session_profile_insight` | `async (self, session_id: 'str', *, tier: 'str' = 'merged') -> 'SessionProfileInsight | None'` |
-| `Polylogue.get_session_profile_record` | `async (self, session_id: 'str') -> 'SessionProfileRecord | None'` |
-| `Polylogue.list_session_profile_insights` | `async (self, query: 'SessionProfileInsightQuery | None' = None) -> 'list[SessionProfileInsight]'` |
-| `Polylogue.insight_readiness_report` | `async (self, query: 'InsightReadinessQuery | None' = None) -> 'InsightReadinessReport'` |
-| `Polylogue.insight_rigor_audit` | `async (self, query: 'InsightRigorAuditQuery | None' = None) -> 'InsightRigorAuditReport'` |
-| `Polylogue.archive_debt` | `async (self, *, kinds: 'Iterable[str] | None' = None, only_actionable: 'bool' = False, limit: 'int | None' = None, exact_fts: 'bool' = False) -> 'ArchiveDebtListPayload'` |
-| `Polylogue.get_session_work_event_insights` | `async (self, session_id: 'str') -> 'list[SessionWorkEventInsight]'` |
-| `Polylogue.list_session_work_event_insights` | `async (self, query: 'SessionWorkEventInsightQuery | None' = None) -> 'list[SessionWorkEventInsight]'` |
-| `Polylogue.get_session_phase_insights` | `async (self, session_id: 'str') -> 'list[SessionPhaseInsight]'` |
-| `Polylogue.list_session_phase_insights` | `async (self, query: 'SessionPhaseInsightQuery | None' = None) -> 'list[SessionPhaseInsight]'` |
-| `Polylogue.get_thread_insight` | `async (self, thread_id: 'str') -> 'ThreadInsight | None'` |
-| `Polylogue.list_thread_insights` | `async (self, query: 'ThreadInsightQuery | None' = None) -> 'list[ThreadInsight]'` |
-| `Polylogue.list_session_tag_rollup_insights` | `async (self, query: 'SessionTagRollupQuery | None' = None) -> 'list[SessionTagRollupInsight]'` |
-| `Polylogue.list_archive_coverage_insights` | `async (self, query: 'ArchiveCoverageInsightQuery | None' = None) -> 'list[ArchiveCoverageInsight]'` |
-| `Polylogue.list_tool_usage_insights` | `async (self, query: 'ToolUsageInsightQuery | None' = None) -> 'list[ToolUsageInsight]'` |
-| `Polylogue.list_session_cost_insights` | `async (self, query: 'SessionCostInsightQuery | None' = None) -> 'list[SessionCostInsight]'` |
-| `Polylogue.get_session_latency_profile_insight` | `async (self, session_id: 'str') -> 'SessionLatencyProfileInsight | None'` |
-| `Polylogue.list_session_latency_profile_insights` | `async (self, query: 'SessionLatencyProfileInsightQuery | None' = None) -> 'list[SessionLatencyProfileInsight]'` |
-| `Polylogue.find_stuck_session_latency_profile_insights` | `async (self, query: 'SessionLatencyProfileInsightQuery | None' = None) -> 'list[SessionLatencyProfileInsight]'` |
-| `Polylogue.list_cost_rollup_insights` | `async (self, query: 'CostRollupInsightQuery | None' = None) -> 'list[CostRollupInsight]'` |
-| `Polylogue.list_usage_timeline_insights` | `async (self, query: 'UsageTimelineInsightQuery | None' = None) -> 'list[UsageTimelineInsight]'` |
-| `Polylogue.list_archive_debt_insights` | `async (self, query: 'ArchiveDebtInsightQuery | None' = None) -> 'list[ArchiveDebtInsight]'` |
-| `Polylogue.cost_outlook` | `async (self, plan_name: 'str', *, now: 'datetime | None' = None, method: 'ProjectionMethod' = ) -> 'CycleOutlook | None'` |
-| `Polylogue.aggregate_sessions` | `async (self, *, group_by: 'str' = 'workflow_shape', since: 'str | None' = None, until: 'str | None' = None, origin: 'str | None' = None) -> 'dict[str, object]'` |
-| `Polylogue.workflow_shape_distribution` | `async (self, *, group_by: 'str' = 'week', since: 'str | None' = None, until: 'str | None' = None, origin: 'str | None' = None) -> 'dict[str, object]'` |
-| `Polylogue.find_abandoned_sessions` | `async (self, *, since: 'str | None' = None, repo_path: 'str | None' = None, min_severity: 'str' = 'question_left', limit: 'int' = 20) -> 'dict[str, object]'` |
-| `Polylogue.tool_call_latency_distribution` | `async (self, *, since: 'str | None' = None, until: 'str | None' = None, origin: 'str | None' = None, tool_category: 'str | None' = None, limit: 'int' = 500) -> 'dict[str, object]'` |
-| `Polylogue.compare_sessions` | `async (self, session_ids: 'Sequence[str]') -> 'dict[str, object]'` |
-| `Polylogue.find_similar_sessions_by_metadata` | `async (self, session_id: 'str', *, limit: 'int' = 10, candidate_pool_limit: 'int' = 200) -> 'dict[str, object] | None'` |
-| `Polylogue.correlate_sessions` | `async (self, *, metric_x: 'str', metric_y: 'str', origin: 'str | None' = None, since: 'str | None' = None, until: 'str | None' = None) -> 'dict[str, object]'` |
-| `Polylogue.get_session_topology` | `async (self, session_id: 'str') -> 'SessionTopology | None'` |
-| `Polylogue.get_ancestors` | `async (self, session_id: 'str') -> 'list[SessionRef]'` |
-| `Polylogue.get_descendants` | `async (self, session_id: 'str') -> 'list[SessionRef]'` |
-| `Polylogue.get_siblings` | `async (self, session_id: 'str') -> 'list[SessionRef]'` |
-| `Polylogue.get_thread` | `async (self, session_id: 'str') -> 'list[SessionRef]'` |
-| `Polylogue.get_logical_session` | `async (self, session_id: 'str') -> 'LogicalSession | None'` |
-| `Polylogue.get_session_tree` | `async (self, session_id: 'str') -> 'list[Session]'` |
-| `Polylogue.postmortem_bundle` | `async (self, spec: 'SessionQuerySpec | None' = None, *, limit: 'int | None' = None) -> 'PostmortemBundle'` |
-| `Polylogue.pathology_report` | `async (self, spec: 'SessionQuerySpec | None' = None, *, limit: 'int | None' = None) -> 'PathologyReport'` |
-| `Polylogue.portfolio_bundle` | `async (self, spec: 'SessionQuerySpec | None' = None, *, limit: 'int | None' = None, top_n: 'int' = 10) -> 'PortfolioBundle'` |
-| `Polylogue.export_insight_bundle` | `async (self, request: 'InsightExportBundleRequest') -> 'InsightExportBundleResult'` |
-| `Polylogue.regenerate_private_fable_packet` | `async (self, *, seed: 'str', requested_size: 'int', schema_id: 'str' = 'delegation.discourse', schema_version: 'int' = 1, exact_template_cap: 'int' = 1) -> 'FableDelegationPacket'` |
-
-### Context and evidence
-
-#### `api.context.delivery`
-
-Compile context and record or inspect durable delivery receipts.
-
-Route/tier class: `cross-tier`. CLI: `continue`, `read`. MCP: `context`, `get`, `status`.
-
-| Python callable | Signature |
-|---|---|
-| `Polylogue.compile_context` | `async (self, spec: 'ContextSpec') -> 'ContextImage'` |
-| `Polylogue.context_image_payload` | `async (self, *, project_path: 'str | None' = None, project_repo: 'str | None' = None, since: 'str | None' = None, until: 'str | None' = None, origin: 'str | None' = None, query: 'str | None' = None, max_sessions: 'int' = 5, max_tokens: 'int | None' = None, max_messages_per_session: 'int | None' = 24, max_chars_per_message: 'int | None' = 1800, include_messages: 'bool' = True, include_assertions: 'bool' = True, redact_paths: 'bool' = True, seed_session_id: 'str | None' = None) -> 'ContextImage'` |
-| `Polylogue.context_preamble_payload` | `async (self, session_id: 'str', *, related_limit: 'int' = 5) -> 'Any'` |
-| `Polylogue.get_context_delivery` | `async (self, snapshot_ref: 'str', *, recipient_ref: 'str') -> 'ArchiveContextDeliveryEnvelope | None'` |
-| `Polylogue.list_context_deliveries` | `async (self, *, recipient_ref: 'str | None' = None, assertion_ref: 'str | None' = None, limit: 'int' = 50) -> 'list[ArchiveContextDeliveryEnvelope]'` |
-| `Polylogue.record_context_delivery` | `async (self, *, image: 'ContextImage', boundary: 'str', recipient_ref: 'str', delivered_by_ref: 'str', run_ref: 'str | None' = None, inheritance_mode: 'str' = 'explicit') -> 'ArchiveContextDeliveryEnvelope'` |
-| `Polylogue.compile_and_record_context` | `async (self, *, recipient_ref: 'str', delivered_by_ref: 'str', boundary: 'str', query: 'str | None' = None, max_sessions: 'int' = 5, max_tokens: 'int | None' = None, include_messages: 'bool' = True, include_assertions: 'bool' = True, redact_paths: 'bool' = True, seed_session_id: 'str | None' = None, run_ref: 'str | None' = None, inheritance_mode: 'str' = 'explicit') -> 'ArchiveContextDeliveryEnvelope'` |
-| `Polylogue.correlate_hermes_context_deliveries` | `async (self, hermes_session_native_id: 'str') -> 'tuple[HermesContextDeliveryCorrelation, ...]'` |
-| `Polylogue.reconcile_hermes_session_lifecycle` | `async (self, hermes_session_native_id: 'str') -> 'HermesLifecycleReconciliation | None'` |
-| `Polylogue.reconcile_codex_spawn_edges` | `async (self) -> 'CodexSpawnEdgeReconciliation | None'` |
-| `Polylogue.hermes_integration_health` | `async (self) -> 'HermesIntegrationHealth'` |
-
-### Assertions and judgments
-
-#### `api.assertion.review`
-
-Read, capture, and judge durable assertions and comparative evidence.
-
-Route/tier class: `cross-tier`. CLI: `mark`, `read`. MCP: `write`, `judge`, `read`.
-
-| Python callable | Signature |
-|---|---|
-| `Polylogue.import_annotation_batch` | `async (self, request: 'AnnotationBatchImportRequest', *, registry: 'AnnotationSchemaRegistry | None' = None) -> 'AnnotationBatchImportResult'` |
-| `Polylogue.list_assertion_claims` | `async (self, *, kinds: 'Sequence[str | AssertionKind] | None' = None, target_ref: 'str | None' = None, scope_ref: 'str | None' = None, statuses: 'Sequence[str | AssertionStatus] | None' = ('active', 'candidate'), context_inject: 'bool | None' = None, limit: 'int | None' = None) -> 'list[ArchiveAssertionEnvelope]'` |
-| `Polylogue.list_assertion_claim_payloads` | `async (self, *, kinds: 'Sequence[str | AssertionKind] | None' = None, target_ref: 'str | None' = None, scope_ref: 'str | None' = None, statuses: 'Sequence[str | AssertionStatus] | None' = ('active', 'candidate'), context_inject: 'bool | None' = None, limit: 'int | None' = None) -> 'list[AssertionClaimPayload]'` |
-| `Polylogue.list_assertion_candidates` | `async (self, *, target_ref: 'str | None' = None, kinds: 'Sequence[str | AssertionKind] | None' = None, limit: 'int | None' = None) -> 'list[AssertionClaimPayload]'` |
-| `Polylogue.list_assertion_candidate_reviews` | `async (self, *, target_ref: 'str | None' = None, kinds: 'Sequence[str | AssertionKind] | None' = None, statuses: 'Sequence[str | AssertionStatus] | None' = None, limit: 'int | None' = None) -> 'AssertionCandidateReviewListPayload'` |
-| `Polylogue.assertion_candidate_queue_health` | `async (self) -> 'AssertionCandidateQueueHealthPayload'` |
-| `Polylogue.judge_assertion_candidate` | `async (self, *, candidate_ref: 'str', decision: 'str', reason: 'str | None' = None, actor_ref: 'str' = 'user:local', inject: 'bool' = False, replacement_kind: 'str | None' = None, replacement_body_text: 'str | None' = None, replacement_value: 'object | None' = None) -> 'AssertionJudgmentResultPayload'` |
-| `Polylogue.capture_assertion_candidate` | `async (self, *, body_text: 'str', kind: 'AssertionKind', refs: 'Sequence[str]' = (), scope_refs: 'Sequence[str]' = (), cwd: 'Path | None' = None, author_ref: 'str' = 'user:local', author_kind: 'str' = 'user', idempotency_key: 'str | None' = None, ttl_seconds: 'int | None' = None) -> 'AssertionClaimPayload'` |
-| `Polylogue.judge_assertion_candidates` | `async (self, *, items: 'Sequence[Any]') -> 'AssertionBulkJudgmentPayload'` |
-| `Polylogue.record_comparative_judgment` | `async (self, judgment: 'ComparativeJudgment', *, author_kind: 'str' = 'user') -> 'ArchiveAssertionEnvelope'` |
-| `Polylogue.list_comparative_judgments` | `async (self) -> 'list[ComparativeJudgment]'` |
-| `Polylogue.join_typed_annotations` | `async (self, *, schema_id: 'str', schema_version: 'int', statuses: 'Sequence[str | AssertionStatus]', target_kind: 'str | None' = None, group_by: "Sequence[Literal['repo', 'model', 'time', 'origin']]" = (), limit: 'int' = 500, offset: 'int' = 0) -> 'AnnotationStructuralJoinResult'` |
-
-### Archive mutations
-
-#### `api.archive.session-delete`
-
-Delete a session and its archive records through the shared mutation executor.
-
-Route/tier class: `cross-tier`. CLI: `delete`. MCP: `write`.
-
-| Python callable | Signature |
-|---|---|
-| `Polylogue.delete_session` | `async (self, session_id: 'str') -> 'bool'` |
-| `Polylogue.delete_session_safe` | `async (self, session_id: 'str', *, actor: 'str' = 'user:api') -> 'DeleteSessionResult'` |
-
-### Durable user state
-
-#### `api.user-state.read`
-
-Read tags, marks, annotations, views, recall packs, workspaces, corrections, notes, and settings from user.db.
-
-Route/tier class: `user-read`. CLI: `read`, `mark`. MCP: `read`, `get`.
-
-| Python callable | Signature |
-|---|---|
-| `Polylogue.list_tags` | `async (self, *, origin: 'str | None' = None) -> 'dict[str, int]'` |
-| `Polylogue.get_metadata` | `async (self, session_id: 'str') -> 'dict[str, str]'` |
-| `Polylogue.list_marks` | `async (self, *, mark_type: 'str | None' = None, session_id: 'str | None' = None, target_type: 'str | None' = None, target_id: 'str | None' = None, message_id: 'str | None' = None) -> 'list[dict[str, str]]'` |
-| `Polylogue.get_annotation` | `async (self, annotation_id: 'str') -> 'dict[str, str] | None'` |
-| `Polylogue.list_annotations` | `async (self, *, session_id: 'str | None' = None, target_type: 'str | None' = None, target_id: 'str | None' = None, message_id: 'str | None' = None) -> 'list[dict[str, str]]'` |
-| `Polylogue.get_view` | `async (self, view_id: 'str') -> 'dict[str, str] | None'` |
-| `Polylogue.list_views` | `async (self) -> 'list[dict[str, str]]'` |
-| `Polylogue.get_recall_pack` | `async (self, pack_id: 'str') -> 'dict[str, str] | None'` |
-| `Polylogue.list_recall_packs` | `async (self) -> 'list[dict[str, str]]'` |
-| `Polylogue.get_workspace` | `async (self, workspace_id: 'str') -> 'dict[str, str] | None'` |
-| `Polylogue.list_workspaces` | `async (self) -> 'list[dict[str, str]]'` |
-| `Polylogue.list_corrections` | `async (self, *, session_id: 'str | None' = None, kind: 'str | None' = None) -> 'list[LearningCorrection]'` |
-| `Polylogue.list_blackboard_notes` | `async (self, *, kind: 'str | None' = None, scope_repo: 'str | None' = None, unresolved: 'bool' = False, limit: 'int' = 20) -> 'list[BlackboardNote]'` |
-| `Polylogue.get_setting` | `async (self, setting_key: 'str') -> 'ArchiveUserSettingEnvelope | None'` |
-| `Polylogue.list_settings` | `async (self) -> 'list[ArchiveUserSettingEnvelope]'` |
-
-#### `api.user-state.write`
-
-Mutate tags, metadata, marks, annotations, views, recall packs, workspaces, corrections, notes, and settings in user.db.
-
-Route/tier class: `user-write`. CLI: `mark`, `delete`. MCP: `write`.
-
-| Python callable | Signature |
-|---|---|
-| `Polylogue.add_tag` | `async (self, session_id: 'str', tag: 'str', *, author_ref: 'str | None' = None, author_kind: 'str | None' = None) -> 'TagMutationResult'` |
-| `Polylogue.remove_tag` | `async (self, session_id: 'str', tag: 'str') -> 'TagMutationResult'` |
-| `Polylogue.update_metadata` | `async (self, session_id: 'str', key: 'str', value: 'str') -> 'bool'` |
-| `Polylogue.set_metadata` | `async (self, session_id: 'str', key: 'str', value: 'object') -> 'MetadataMutationResult'` |
-| `Polylogue.delete_metadata` | `async (self, session_id: 'str', key: 'str') -> 'MetadataMutationResult'` |
-| `Polylogue.bulk_tag_sessions` | `async (self, session_ids: 'list[str]', tags: 'list[str]', *, author_ref: 'str | None' = None, author_kind: 'str | None' = None) -> 'BulkTagMutationResult'` |
-| `Polylogue.add_mark` | `async (self, session_id: 'str', mark_type: 'str', *, target_type: 'str' = 'session', target_id: 'str | None' = None, message_id: 'str | None' = None) -> 'bool'` |
-| `Polylogue.remove_mark` | `async (self, session_id: 'str', mark_type: 'str', *, target_type: 'str' = 'session', target_id: 'str | None' = None, message_id: 'str | None' = None) -> 'bool'` |
-| `Polylogue.save_annotation` | `async (self, annotation_id: 'str', session_id: 'str', note_text: 'str', *, target_type: 'str' = 'session', target_id: 'str | None' = None, message_id: 'str | None' = None) -> 'bool'` |
-| `Polylogue.delete_annotation` | `async (self, annotation_id: 'str') -> 'bool'` |
-| `Polylogue.save_view` | `async (self, view_id: 'str', name: 'str', query_json: 'str') -> 'bool'` |
-| `Polylogue.delete_view` | `async (self, view_id: 'str') -> 'bool'` |
-| `Polylogue.create_recall_pack` | `async (self, pack_id: 'str', label: 'str', payload_json: 'str') -> 'bool'` |
-| `Polylogue.delete_recall_pack` | `async (self, pack_id: 'str') -> 'bool'` |
-| `Polylogue.save_workspace` | `async (self, workspace_id: 'str', name: 'str', mode: 'str', open_targets_json: 'str', layout_json: 'str', active_target_json: 'str' = '{}') -> 'bool'` |
-| `Polylogue.delete_workspace` | `async (self, workspace_id: 'str') -> 'bool'` |
-| `Polylogue.record_correction` | `async (self, session_id: 'str', kind: 'str', payload: 'dict[str, str]', *, note: 'str | None' = None, author_ref: 'str | None' = None, author_kind: 'str | None' = None) -> 'LearningCorrection'` |
-| `Polylogue.delete_correction` | `async (self, session_id: 'str', kind: 'str') -> 'bool'` |
-| `Polylogue.clear_corrections` | `async (self, session_id: 'str') -> 'int'` |
-| `Polylogue.post_blackboard_note` | `async (self, *, kind: 'str', title: 'str', content: 'str', scope_repo: 'str | None' = None, scope_session: 'str | None' = None, scope_issue: 'int | None' = None, scope_path: 'str | None' = None, related_sessions: 'tuple[str, ...]' = (), author_ref: 'str | None' = None, author_kind: 'str' = 'user', evidence_refs: 'tuple[str, ...]' = (), staleness: 'dict[str, object] | None' = None, context_policy: 'dict[str, object] | None' = None) -> 'BlackboardNote'` |
-| `Polylogue.set_setting` | `async (self, setting_key: 'str', value: 'object', *, author_ref: 'str' = 'user:local') -> 'ArchiveUserSettingEnvelope'` |
-
-### Intentional exclusions
-
-| Export | Reason | Authority |
-|---|---|---|
-| `ArchiveStats` | Result data model, not an executable archive operation. | `polylogue-s1kr` |
-| `select_pending_embedding_session_window` | Public adapter helper for daemon/CLI window selection. It is intentionally not a facade operation. | `polylogue-s1kr` |
-| `Polylogue.__repr__` | Diagnostic representation protocol, not an archive operation. | `polylogue-s1kr` |
-
-
---
diff --git a/docs/maintenance.md b/docs/maintenance.md
index d039765175..83a2559699 100644
--- a/docs/maintenance.md
+++ b/docs/maintenance.md
@@ -683,22 +683,6 @@ strings. `polylogue ops doctor` reports a `messages_fts` discrepancy.
`polylogue ops diagnostics workload`
shows non-empty `fts_trigger_state.missing` or `regressed` triggers.
-For a deployment-bound, read-only gate that checks schema versions, exact FTS
-debt, raw frontier integrity, replay candidates, cursor failures, and
-convergence debt, add `--preflight`:
-
-```bash
-polylogue ops diagnostics workload --preflight --json > preflight.json
-jq '.preflight_ledger | {state, blocking_checks, warning_checks}' preflight.json
-```
-
-The preflight reports quarantined raw bytes and missing
-`raw_membership_census` rows by origin. Quarantine is authority-pending
-evidence, not an automatic failure. Missing census is `coverage_unknown` and
-blocks the gate until a verdict exists. Only source rows with present,
-non-terminal census evidence are classified as actionable parse/validation
-debt.
-
**Root cause.** `messages_fts` is a contentless FTS5 table
(`content=''`, `contentless_delete=1`) indexing `blocks.search_text`,
kept in sync by three rowid-keyed triggers on `blocks`
diff --git a/docs/mcp-reference.md b/docs/mcp-reference.md
index 9d8d66bbbd..7ba2b6a68f 100644
--- a/docs/mcp-reference.md
+++ b/docs/mcp-reference.md
@@ -21,20 +21,13 @@ explicit config-opt-in capability flags (see Configuration below):
- `judge` (judge capability) — accept, reject, defer, or supersede assertion candidates.
- `maintenance` (maintenance capability) — preview, execute, list, and inspect maintenance operations.
-The exhaustive, currently-registered tool name set is a test-enforced contract, not hand
-duplicated here: `tests/infra/mcp.py:EXPECTED_TOOL_NAMES`. Adding a tool requires updating
-that set plus its tool contract (see `CLAUDE.md` § MCP gotchas).
+The runtime declaration registry is authoritative. Its tests derive the
+expected tool names from those declarations and exercise registration; this
+page is operator guidance, not a second inventory.
-## Resources
-
-- `polylogue://stats` — Archive-wide summary stats.
-- `polylogue://sessions` — Recent session list.
-- `polylogue://session/{conv_id}` — Individual session by ID.
-- `polylogue://tags` — Known tag vocabulary.
-- `polylogue://messages/{conv_id}` — Messages for a session.
-- `polylogue://session-tree/{conv_id}` — Lineage-composed session tree.
-- `polylogue://origin/{name}/recent` — Recent sessions for one origin.
-- `polylogue://readiness` — Daemon/archive readiness snapshot.
+MCP clients discover resources and operation schemas from the running server.
+Use that discovery response when exact current capabilities matter rather than
+copying a static resource list from documentation.
## Configuration
@@ -69,23 +62,3 @@ Add to your Claude Code `.mcp.json`:
See `docs/mcp-integration.md` for the full client-integration walkthrough
(Claude Code, Codex, other MCP clients).
-
-
-## All Registered Tools
-
-
-
-Every currently-registered MCP tool name (10 total), for lookup and doc-coverage purposes. See the category breakdown above for what each group is for.
-
-- `context`
-- `explain`
-- `get`
-- `judge`
-- `maintenance`
-- `query`
-- `read`
-- `run`
-- `status`
-- `write`
-
-
diff --git a/docs/openapi/search.yaml b/docs/openapi/search.yaml
index 1532200a43..452ca60d5a 100644
--- a/docs/openapi/search.yaml
+++ b/docs/openapi/search.yaml
@@ -4491,6 +4491,34 @@ x-polylogue-route-contracts:
auth_policy: credential_if_configured
response_contract: SearchEnvelope / SessionListResponse with route_state
notes: Local UDS-only root-request parameter envelope; daemon owns query compilation.
+- method: POST
+ pattern: /api/cli/delete/prepare
+ kind: maintenance
+ stability: private
+ auth_policy: bearer_if_configured_and_same_origin
+ response_contract: delete preview envelope
+ notes: Local CLI transport; validates a bounded exact selection before entering writer authority.
+- method: POST
+ pattern: /api/cli/delete/authorize
+ kind: maintenance
+ stability: private
+ auth_policy: bearer_if_configured_and_same_origin
+ response_contract: delete authorization envelope
+ notes: Local CLI transport; issues one daemon-held authorization for an authenticated preview owner.
+- method: POST
+ pattern: /api/cli/delete/cancel
+ kind: maintenance
+ stability: private
+ auth_policy: bearer_if_configured_and_same_origin
+ response_contract: delete cancellation envelope
+ notes: Local CLI transport; cancels an unconfirmed daemon-held preview under the writer gate.
+- method: POST
+ pattern: /api/cli/delete
+ kind: maintenance
+ stability: private
+ auth_policy: bearer_if_configured_and_same_origin
+ response_contract: MutationResultPayload
+ notes: Local CLI transport; consumes one daemon-held authorization under the writer gate.
- method: POST
pattern: /api/maintenance/rebuild-index
kind: maintenance
diff --git a/docs/plans/STORAGE_TWINS_DIVERGENCES.md b/docs/plans/STORAGE_TWINS_DIVERGENCES.md
deleted file mode 100644
index 590d418896..0000000000
--- a/docs/plans/STORAGE_TWINS_DIVERGENCES.md
+++ /dev/null
@@ -1,142 +0,0 @@
-# Storage Twins: Documented Divergences
-
-**Status**: Committed artifact for regression testing
-**Updated**: 2026-07-14
-**Author**: Sinity (agent)
-**Bead**: polylogue-pf1
-
----
-
-## Overview
-
-The Polylogue archive has two SQLite storage backends that serve different roles:
-
-- **Async backend** (`polylogue/storage/sqlite/async_sqlite*.py`):
- - Async/await API for daemon and MCP surfaces
- - Delegation-heavy, stateless per-operation
- - Mixin-based architecture for composition
- - Reads primarily via `self.queries` (SQLiteQueryStore)
-
-- **Sync backend** (`polylogue/storage/sqlite/archive_tiers/`):
- - Synchronous write-capable full DB owner
- - Organizes logic by tier (source, index, user, embeddings, ops)
- - Schema ownership and connection lifecycle management
- - Monolithic archive.py (11K lines) plus tier-specific modules
-
-## The 10 Documented Divergences
-
-All divergences are **architectural**, not bugs. They reflect the different roles and compositional boundaries. Each is listed with its file:line references and rationale.
-
-### 1. Method Naming: `_session_id_query` vs `session_id_query`
-
-**Async location**: `async_sqlite_archive.py` — delegates via `self.queries.session_id_query()`
-**Sync location**: `query_store_archive.py` — public `session_id_query` API
-**Rationale**: Private delegate naming convention vs public query-store API. Same underlying function; called through different architectural layers.
-**Status**: Architectural—no action needed.
-
-### 2. Search Sessions Delegation Path
-
-**Async location**: `async_sqlite_archive.py:search_sessions()` → delegates to `self.queries`
-**Sync location**: `query_store_archive.py:search_sessions()` → delegates to `search_session_hits()` → chains internal logic
-**Rationale**: Backend delegates to its composed query store; query store delegates to its own internal search implementation. Both reach identical result.
-**Status**: Architectural—no action needed.
-
-### 3. Get Messages: Content Blocks Attachment Strategy
-
-**Async location**: `async_sqlite_archive.py:get_messages()` — blocks pre-attached by query store
-**Sync location**: `query_store_archive.py:get_messages()` — canonical two-step load+merge pattern
-**Rationale**: Query store is the canonical read-only implementation; async backend inherits its behavior via composition.
-**Status**: Architectural—no action needed.
-
-### 4. Connection Management Strategy
-
-**Async location**: `async_sqlite.py:_get_connection()` — ensures schema before every use (backend responsibility)
-**Sync location**: `archive_tiers/archive.py:_connection_factory` — provides pre-configured read-only connections
-**Rationale**: Backend owns the DB and ensures schema; query store provides composable read-only connections that assume schema is ready.
-**Status**: Architectural—no action needed.
-
-### 5. Write Methods Exist Only on Backend
-
-**Async location**: `async_sqlite_archive.py` — `save_session_record()`, `save_messages()`, etc.
-**Sync location**: `archive_tiers/write.py`, `user_write.py`, etc. — write tier methods
-**Rationale**: Query store is deliberately read-only; write capability is backend-only by design. This enforces the read/write split.
-**Status**: Architectural—no action needed.
-
-### 6. Query API Methods Exist Only on Query Store
-
-**Async location**: `async_sqlite_archive.py` — accesses via `self.queries` (e.g., `queries.list_sessions()`)
-**Sync location**: `query_store_archive.py` — `list_sessions()`, `count_sessions()`, `search_action_*()` defined here
-**Rationale**: Read-only query operations belong only to the query-store layer. Backend doesn't reimplement these.
-**Status**: Architectural—no action needed.
-
-### 7. get_session_insight_status Implementation Location
-
-**Async location**: `async_sqlite_archive.py` — method on `SQLiteArchiveMixin`
-**Sync location**: `query_store.py` — separate independent implementation
-**Rationale**: Both backends provide this method; query store has its own version to maintain independence.
-**Status**: Architectural—no action needed.
-
-### 8. get_messages_batch: Early-Exit Clarity
-
-**Async location**: `async_sqlite_archive.py:get_messages_batch()` — delegates to `self.queries`
-**Sync location**: `query_store_archive.py:get_messages_batch()` — explicit empty-session_ids early exit with comment
-**Rationale**: Equivalent behavior; sync version adds explicit clarity on the empty-list edge case.
-**Status**: Architectural—no action needed.
-
-### 9. iter_messages: Chunk-Size Fast Path
-
-**Async location**: `async_sqlite.py:iter_messages()` — `chunk_size=100` optimization, delegates to query store
-**Sync location**: `query_store_archive.py:iter_messages()` — calls `messages_q.iter_messages()` directly
-**Rationale**: Both reach the same destination (message query module); async adds an optimization layer around the chunking.
-**Status**: Architectural—no action needed.
-
-### 10. search_session_hits: Access Pattern
-
-**Async location**: `async_sqlite_archive.py:search_session_hits()` — backend delegates to `self.queries`
-**Sync location**: `query_store_archive.py:search_session_hits()` — opens a direct connection to the query module
-**Rationale**: Same destination via different architectural layers (backend delegation vs direct query-store composition).
-**Status**: Architectural—no action needed.
-
----
-
-## Testing Strategy
-
-The regression test `tests/unit/storage/test_storage_twins.py` verifies:
-
-1. **Divergence count is stable**: All 10 are accounted for; new divergences fail the test.
-2. **Divergence documentation exists**: The source comment in `async_sqlite_archive.py:14-54` is present.
-3. **Architectural roles are clear**: Async uses mixins, sync uses tier modules.
-4. **Backend files exist**: References in the divergence table point to real files with expected content.
-
-### Running Tests
-
-```bash
-devtools test -k twin -v
-```
-
-Expected output: All tests pass, confirming the divergences are as documented.
-
----
-
-## Why Divergences Exist
-
-The async and sync backends serve different compositional goals:
-
-- **Async** (daemon/MCP): Needs `async def` signatures and delegation to external query stores for testability.
-- **Sync** (archive operations): Owns the full DB lifecycle, schema, and all write paths; monolithic but self-contained.
-
-The hiu epic (collapse storage twins onto sync core) plans to retire the async duplication by introducing an async adapter that wraps the sync core, eliminating the divergence maintenance burden while preserving the async API.
-
----
-
-## Future: hiu Epic Resolution
-
-**Bead**: polylogue-hiu
-**Decision**: Direction B — sync core, async adapter
-**Plan**:
-1. **Prerequisite (this bead, polylogue-pf1)**: Reconcile the 10 divergences INTO the sync store as the canonical implementation.
-2. **Adapter (hiu Step 1)**: Build an async executor wrapping the sync core.
-3. **Migration (hiu Steps 2+)**: Retire async_sqlite*.py mixin lane by mixin, keeping async API.
-4. **Cleanup (hiu Final)**: Delete async_sqlite.py, async_sqlite_archive.py, async_sqlite_raw.py.
-
-When hiu is complete, this divergence document will be retired in the same PR that deletes the async backends.
diff --git a/docs/plans/bead-readiness-audit-implementation-cluster.md b/docs/plans/bead-readiness-audit-implementation-cluster.md
deleted file mode 100644
index e6884a340c..0000000000
--- a/docs/plans/bead-readiness-audit-implementation-cluster.md
+++ /dev/null
@@ -1,332 +0,0 @@
-# Bead readiness audit: implementation cluster
-
-Audit date: 2026-08-03
-
-Audit base: `25434d0f0` (`refactor(sources): unify Claude Code eager and streaming parsers (#3691)`)
-
-Beads evidence: coordinator export `/realm/project/polylogue/.beads/issues.jsonl`; `bd --readonly --directory /realm/project/polylogue comments --json` for the four records with separate comments
-
-Scope: specification readiness only. This audit makes no production change and no Beads mutation.
-
-## Result
-
-| Readiness state | Count |
-| --- | ---: |
-| EXECUTION-READY | 0 |
-| EXECUTION-READY WITH PACKET | 3 |
-| DESIGN-BLOCKED | 14 |
-| EVIDENCE-BLOCKED | 4 |
-| DEPENDENCY-BLOCKED | 6 |
-| MISFRAMED/REDUNDANT | 10 |
-| Total | 37 |
-
-The safe next Luna wave is `polylogue-tw4ar`, `polylogue-io8np`, and `polylogue-rrxe4`. These lanes are disjoint at the production-write boundary. Review the existing unmerged `polylogue-yazae` commit `c22418c3f` before starting `rrxe4`, then merge that fixture work first if it is accepted. Do not dispatch `polylogue-a7xr.23`, `polylogue-a7xr.25`, `polylogue-6e7m`, or `polylogue-nas1` independently of the content/identity Sol lane.
-
-## Per-Bead audit
-
-The evidence column cites the decisive part of the full record, including design, acceptance criteria, notes, and comments where present. Parent-child edges are shown for context but are not treated as blockers.
-
-| Bead | Status | Full-content evidence | Current source anchors | Dependencies | Smallest missing artifact or dispatch action |
-| --- | --- | --- | --- | --- | --- |
-| `polylogue-1fijp` | EVIDENCE-BLOCKED | The design fixes the admission arms and the operator note narrows re-acquisition to opportunistic reads. PRs #3668, #3687, and #3688 landed the chokepoint, Drive structural classification, and Antigravity routing. The latest note says the remaining direct writers are structurally distinct and AC (e) still requires 72 hours with zero new quarantines. | `storage/sqlite/archive_tiers/raw_admission.py::admit_raw_observation`; `revision_governance.py::admit_raw_and_parsed_result`; direct `write_source_raw_session` sites in `revision_governance.py`, live batch paths, archive ingest, and repair | Parent `aggz` is closed | A 72-hour live receipt plus an explicit AC rewrite that distinguishes fresh observation admission from copy-forward, post-parse identity binding, and content-addressed replay. No new Luna implementation lane yet. |
-| `polylogue-taj0o` | MISFRAMED/REDUNDANT | The note said Stage 2 remained. Current HEAD is PR #3691 and implements exactly Stage 2: one `_claude_code_multiway_parse`, fallback-id primary selection, per-session sidecar accumulation, and deletion of both old grouping paths and Claude-specific reconciliation. | `sources/dispatch.py::_claude_code_multiway_parse`; `sources/parsers/claude/code_parser.py::_SessionAccumulator`; commit `25434d0f0` | None | Reconcile the open Bead against PR #3691. Any residual live old-versus-new archive comparison belongs to reindex verification, not another parser rewrite. |
-| `polylogue-rrxe4` | EXECUTION-READY WITH PACKET | Design and AC fix the production seam, one canonical equivalence comparator, four separate metamorphic properties, Hypothesis state-machine use, anti-vacuity mutation, and the focused selector. Both blocking inputs are now closed. | `tests/infra/convergence_harness.py`; `tests/infra/pathology_composer.py`; `maintenance/archive_verification.py::ARCHIVE_VERIFICATION_CHECKS`; existing state-machine precedents under `tests/property` and `tests/unit/storage` | `amrpx` closed; `t0m73` closed | Packet P1 below. Review and merge the existing `yazae` fixture commit first if it will be consumed. |
-| `polylogue-yazae` | MISFRAMED/REDUNDANT | The record specifies a production-ingest zoo, queryable manifest, registry and canary consumers, and a conventions rule. An unmerged worktree commit `c22418c3f` already adds `tests/infra/pathology_zoo.py` and its tests, but its two-file diff does not cover the registry, canary, or conventions AC. A fresh lane would duplicate existing work. | Existing HEAD has `tests/infra/pathology_composer.py`; unmerged `c22418c3f` adds `tests/infra/pathology_zoo.py` and `tests/infra/test_pathology_zoo.py` | `amrpx` closed | Review/cherry-pick or reject `c22418c3f`, then narrow this Bead to the missing consumer wiring and conventions rule. Do not regenerate the builder. |
-| `polylogue-ey4ro` | DEPENDENCY-BLOCKED | The design fixes five valid instrument kinds, anti-vacuity, `docs/plans/red-backlog.json`, and closure workflow. AC requires zoo, registry binding, dual-path equivalence, and hermeticity gaps to land or remain tracked. | `maintenance/archive_verification.py`; `.agent/CONVENTIONS.md`; missing `docs/plans/red-backlog.json`; test and campaign infrastructure | `rrxe4` open; `yazae` open; `t0m73` closed | Land or reconcile `rrxe4` and `yazae`, then produce one current gate census from `818fy` as the mapping input. |
-| `polylogue-wwph1` | DESIGN-BLOCKED | The taxonomy and forcing classes are detailed, but the canonical prompt named in the record is absent from this checkout. The design puts the final report under ignored `.agent/scratch/` while AC also requires committed rerunnable scripts. Those durability rules conflict. | `.agent/CONVENTIONS.md` states `.agent/scratch/` is gitignored; `.agent/scratch/2026-08-03-root-cause-audit-prompt-v2.md` is absent; `maintenance/archive_verification.py` is the graduation target | None | Decide the durable home for enumeration scripts and the final coverage ledger, and decide whether each class pass is one PR or campaign-local scratch plus a single final report. |
-| `polylogue-tw4ar` | EXECUTION-READY WITH PACKET | Migration 024 and fingerprint invalidation are landed. The remaining design fixes a bounded `DaemonConverger` stage, content-keyed stale detection, `false_means_pending`, typed-visible append skips, and a cache-hit proof. | `storage/raw_authority_verdict_cache.py`; `storage/raw_authority_verdict_projection.py`; `daemon/convergence_stages.py::make_default_convergence_stages`; `daemon/convergence.py::ConvergenceStage` | None | Packet P2 below. |
-| `polylogue-ds4b4` | MISFRAMED/REDUNDANT | The record asks for a third verdict-aware GC check. PR #3625 proved a stronger existing invariant: every live `raw_sessions` or `blob_refs` reference protects its blob for every `RawAuthorityVerdict`, and verdict classification is deliberately not a deletion trigger. Adding verdict logic to GC would create a weaker duplicate safety owner. | `storage/blob_gc.py::run_blob_gc_report`; `tests/unit/storage/test_blob_gc_raw_authority_verdict_invariant.py`; commit `a584cc62e` | Recorded blockers `tw4ar` and `w6hql` are irrelevant to the stronger row-reference proof | Reframe item 4 as satisfied by the existing row-reference invariant, or file a separate retirement-policy Bead if a future path deletes raw rows and needs a retained-successor proof. |
-| `polylogue-w6hql` | DEPENDENCY-BLOCKED | Its own design says it is now an umbrella. Enum, derivation, projection, and cache table are landed; closure requires cache convergence, append-cohort coverage, consumer migration, and retirement of fragmented writers. | `core/enums.py::RawAuthorityVerdict`; `archive/raw_authority_verdict.py`; `storage/raw_authority_verdict_projection.py`; `storage/raw_authority_verdict_cache.py`; source migration 024 | `lb39z` closed; `tw4ar` open; `lr6dx` open | Land `tw4ar`, then specify and land append verdict semantics before `lr6dx` removes old readers and writers. No umbrella implementation lane. |
-| `polylogue-zok3` | DESIGN-BLOCKED | The record correctly separates query predicates, view parameters, rendering, and globals, but it explicitly leaves three incompatible public shapes: per-view subcommands, a structured `--view`, or DSL projections. | `cli/query_verbs.py`; `cli/read_view_handlers.py::READ_VIEW_HANDLERS`; `archive/viewport/profiles.py::READ_VIEW_PROFILES`; `surfaces/projection_spec.py` | None | One public syntax decision shared with `4n8k` and `jnj.1`, plus a complete 34-flag classification table. |
-| `polylogue-4n8k` | DESIGN-BLOCKED | The full description is an agenda, not a decision. It asks each of roughly 18 views to be classified as projection, rendering, or action and asks which DSL extension to use. Those answers change grammar and public CLI compatibility. | Same read-algebra hotspot as `zok3`; grammar in `archive/query/expression.py`; view profiles in `archive/viewport/profiles.py` | None | A checked view-by-view classification and target spelling. Recommended default: units and evidence families are projections, encoding/destination are render concerns, and named views survive only as presets. |
-| `polylogue-a7xr.23` | DESIGN-BLOCKED | The record chooses content-defined chunking, but it does not define chunk parameters, manifest/transaction schema, raw reconstruction, GC ownership, or a safe transition from `revision_kind`. Current code uses `revision_kind` across more than forty source and storage modules. The claim that forks do not share root history also cannot support identity decisions here. | `storage/blob_store.py`; `storage/sqlite/archive_tiers/source.py`; revision governance and raw retention modules; broad `revision_kind` consumers | Parent `a7xr`; content/identity Sol lane owns the broader design | A content-addressed raw representation design with chunker versioning, reconstruction atomicity, reference/GC model, and an explicit statement of which revision semantics remain after storage dedup. |
-| `polylogue-cijx.2` | DESIGN-BLOCKED | The design chooses root-commit SHA as repository identity and says forks are safe because they do not share it. Real forks commonly share the same root commit, so that premise cannot distinguish fork from mirror. Current code has already moved to normalized remote identity plus `repo_checkouts` and skips bare directories, leaving the proposed root-commit cutover unresolved. | `storage/sqlite/archive_tiers/write.py::_write_repo_edges`, `repo_identity_key`; `archive/session/repo_identity.py`; index tables `repos`, `repo_checkouts`, `session_repos`; `sources/emitter.py::_append_repo_identity_evidence` | Parent `cijx` | Decide the repository equivalence relation for forks, mirrors, remote-less repos, and remote changes. Acceptance evidence must include two forks sharing a root commit and one mirror sharing all history. |
-| `polylogue-6e7m` | MISFRAMED/REDUNDANT | AC requires provider titles only in storage and a read-time structural label from repository, file shape, and message count. That implementation already exists and is exercised through real summary reads. | `insights/session_label.py::session_structural_label_for_session`; `tests/unit/insights/test_session_label.py`; `tests/unit/storage/test_title_source_queryable.py`; original implementation in `5e23e6abf` | None; content/identity Sol lane must preserve this contract | Reconcile as landed. A live collision-rate rerun can be a verification receipt, not another implementation. |
-| `polylogue-e98k` | DESIGN-BLOCKED | PR #3637 landed startup/rebuild observability and the computed Polylogue-side budget. Its body explicitly deferred AC 1, one declared value driving both Polylogue profiles and Sinnix cgroup limits. The Bead's optional-env proposal still omits allocation ratios and headroom policy. | `storage/sqlite/connection_profile.py::mapped_bytes_budget`; `core/metrics.py` cgroup readers; daemon and rebuild call sites; Sinnix `modules/services/polylogue.nix` outside this worktree | Cross-repo Sinnix contract, not represented by a dependency edge | Decide which repo owns the budget, how it allocates mmap/cache/read concurrency, and how `MemoryHigh`/`MemoryMax` headroom derives from it. Then split live canary and generation-retention checks from the cross-repo config change. |
-| `polylogue-6kur` | MISFRAMED/REDUNDANT | PR #3661 landed the safe FK-impossible cull. The notes correctly prohibit touching `empty_sessions` and expand the remainder into convergence parity, raw-authority drain deletion, and relocation to blob GC/raw retention. Those are separate owner modules and decisions, not the original safe subset. | `storage/repair.py`; `maintenance/preview.py`; `maintenance/targets.py`; commit `ca41b5463` | `ne6k` decision for empty sessions; raw-authority drain/retirement work | Reconcile the landed safe subset, then split remaining targets by owning invariant. Do not use this umbrella for a second broad repair rewrite. |
-| `polylogue-a7xr.26` | EVIDENCE-BLOCKED | The note fixes the intended result, deletion of the aiosqlite implementation while preserving async signatures, but explicitly requires a realistic wrapper benchmark and says to stop if the result exceeds roughly 2x. | `storage/sqlite/async_sqlite.py::SQLiteBackend`; `async_sqlite_archive.py`; `async_sqlite_raw.py`; sync archive/repository engine; async consumers in pipeline and repository | Parent `a7xr` | A reproducible realistic batch-read benchmark, with workload, archive size, concurrency, baseline, wrapper prototype, and result. |
-| `polylogue-a7xr.25` | DESIGN-BLOCKED | The operator chose the ride-the-rebuild retention rule, but the record does not fix how an event references one or more blocks. `session_events` has `source_message_id` and `payload_json`, no block-ref field or relation. "No DDL change" conflicts with "reference block ids otherwise" unless refs remain encoded inside JSON. | `storage/sqlite/archive_tiers/write.py::_write_session_events`, `_SESSION_EVENTS_REDUNDANT_TYPES`; `session_events` DDL; Codex event/block lowering | Parent `a7xr`; content/identity Sol lane owns the representation; rebuild campaign `818fy/xselt` owns application | Decide between a typed event-to-block relation and minimal reference JSON, including one-to-many mappings, unresolved refs, and consumer hydration. |
-| `polylogue-io8np` | EXECUTION-READY WITH PACKET | AC requires one bounded topology and parent-chain envelope builder used by MCP and daemon HTTP, with the same node limit. Current code still has independent MCP unbounded tuples and daemon bounded dictionaries. | `daemon/topology_http.py::build_topology_envelope`, `build_parent_chain_envelope`; `mcp/payloads.py::session_topology_payload`; `mcp/server_cutover.py` topology route | None | Packet P3 below. |
-| `polylogue-mjupn` | MISFRAMED/REDUNDANT | The finding is real, but it assumes CLI read views, MCP `read(view=topology)`, and MCP `get(projection=...)` are one vocabulary before `4n8k`/`jnj.1` decides that product contract. A shared table now would freeze the disputed model. | `cli/read_view_handlers.py`; `mcp/server_cutover.py` read/get branches; `surfaces/projection_spec.py`; `archive/viewport/profiles.py` | Read-algebra design cluster | Merge the evidence into `4n8k`/`jnj.1`; implement one registry only after the public projection boundary is decided. |
-| `polylogue-nbls5` | DESIGN-BLOCKED | AC explicitly permits either deleting dead scaffolding and correcting docs or wiring MCP. Current architecture exposes ten role-gated dispatcher tools, so adding eleven generated tools would contradict the consolidated MCP surface. The record does not choose a dispatcher operation instead. | `mcp/insight_tool_contracts.py::InsightListToolSpec`; `insights/registry.py::INSIGHT_REGISTRY`; `mcp/server_cutover.py::_INSIGHT_PROJECTIONS`; MCP declarations/contracts | None | Choose the supported MCP route. Recommended default: add registry names behind the existing `query` dispatcher, then delete per-tool scaffolding and correct claims. |
-| `polylogue-oj4oo` | MISFRAMED/REDUNDANT | The execution recipe chose canonical `OperationStatus`. PR #3657 moved it to `core/enums.py`, aliases `BackfillStatus`, generator-tied ops DDL, and removed the comment-only embedding translation. | `core/enums.py::OperationStatus`; `maintenance/planner.py::BackfillStatus`; `operations/operation_status.py`; ops DDL/write helpers; commit `0a39fe098` | None | Reconcile as landed. |
-| `polylogue-lm62x` | DESIGN-BLOCKED | The record itself asks whether query runs, route observations, and workflow surfaces need different granularity. The value sets represent execution transport, route transport, and product workflow, so a blind enum merge could erase valid distinctions. | `storage/sqlite/archive_tiers/ops.py` query/route tables; `archive/query/production_evaluator.py::Surface`; `product/workflows.py::WorkflowSurface`; `operations/route_observation.py` | None | Name and define the axes, then choose whether they share a transport enum plus a broader workflow enum. Required evidence is a join/use-site census, not member-set equality. |
-| `polylogue-jglh` | DESIGN-BLOCKED | AC delegates a semantic judgment for every pair. Several listed pairs are only coincidentally equal today, including completeness/exactness and provider-specific versus public fidelity. The Bead does not record those judgments. | Listed enum/Literal definitions across `core`, `archive/viewport`, `storage`, `sources`, `schemas`, `insights`, and `surfaces` | None | A pair-by-pair axis matrix: shared meaning, direction of dependency, canonical home, compatibility effect, and explicit keep-split rationale where applicable. |
-| `polylogue-mzp8` | DESIGN-BLOCKED | The InvalidationReason merge is fixed, but CostBasis still permits merge or rename and the other two pairs only say "rename the narrower one." Those names and axes are public typing/import contracts. | `maintenance/invalidation.py`; `maintenance/preview.py`; `archive/semantic/pricing.py`; `archive/semantic/cost_records.py`; `agent_integration/installer.py`; `operations/specs.py`; measurement modules | None | Choose canonical names and value mappings for all four pairs, including compatibility/import policy. Recommended default: merge InvalidationReason and distinctly name pricing-catalog basis versus recorded-cost authority. |
-| `polylogue-fbkr` | EVIDENCE-BLOCKED | The record gives two valid outcomes for manual frontier apply and reset: delete them if automatic convergence covers every safe case, or promote them to explicit consent if genuinely destructive judgment remains. The deciding coverage proof is absent. | `cli/commands/maintenance/_raw_identity.py`; `product/raw_authority.py::apply_frontier`; daemon automatic frontier application; `maintenance/raw_authority_reset.py` with test-only callers | Raw-authority Phase 1 drain is closed; retirement work remains | An executable-plan coverage receipt comparing automatic daemon application with every manual plan shape, plus a live post-drain reset-need check. |
-| `polylogue-5vft` | MISFRAMED/REDUNDANT | This combines three independent changes. Disposable-tier bootstrap and periodic preflight recovery landed in #3133, while `--only-missing` still forbids promotion and managed reset still refuses. Current daemon architecture also uses acquire-only degraded mode and resumable bulk rebuilds, which the old self-heal design predates. | `maintenance/rebuild_index.py::validate_rebuild_index_request`; `cli/commands/reset.py::_archive_index_targets`; `daemon/cli.py::_periodic_schema_preflight_recheck`; `daemon/bulk_rebuild.py` | None | Split into: effective-full selection promotion, managed-generation reset/replace consent, and derived-mismatch bulk-rebuild routing. Reconcile the already-landed ops bootstrap/recheck slice. |
-| `polylogue-1lm` | DEPENDENCY-BLOCKED | Its selector/transform/budget algebra is specific, including adjacency and resolvable omission refs, but it explicitly depends on `jnj.1` and says it must follow the shared projection normalizer. | `archive/semantic/content_projection.py::ContentProjectionSpec`; `surfaces/projection_spec.py::ProjectionSpec`; context compiler and rendering paths | `jnj.1` open; parent `4p1`; related `ap7` | Land the read-algebra ownership decision and normalizer first. Then refresh the stale, absent prework packet against current symbols. |
-| `polylogue-jnj.1` | DESIGN-BLOCKED | Its design lists unresolved ownership pairs: ProjectionSpec versus ContentProjectionSpec, RenderFormat versus formatting registries, destination ownership, and profiles versus handlers. It explicitly says to decide ownership before extending anything. | `surfaces/projection_spec.py`; `archive/semantic/content_projection.py`; `archive/viewport/profiles.py`; `cli/read_view_handlers.py`; rendering formatters | Parent `jnj` | One concern-to-owner matrix and hard-cut migration order. This decision must absorb `4n8k`, `zok3`, and `mjupn` evidence. |
-| `polylogue-jnj.2` | DESIGN-BLOCKED | Description says facets becomes a real verb. Design allows either a top-level command or a facets projection. The query-first command floor deliberately keeps a small verb set, so this is a public product choice. | CLI analyze/facets commands and tests; root request/filter mapping; shared query transaction from `z9gh.9.1` | `z9gh.9.1` closed; parent `jnj` | Choose verb versus named projection and define JSON envelope parity for exact-ID selection. Recommended default: a named analyze projection over the canonical relation, with any top-level spelling generated as the same operation rather than a second filter owner. |
-| `polylogue-jnj.9` | DESIGN-BLOCKED | The separate comment proves `config --show-layers` already satisfies most read/list scope. Remaining set/get semantics do not say which layer is writable, how Nix-managed values behave, or whether secrets may be written. | `cli/commands/config.py`; `config.py::effective_config_payload`, inventory and five-layer resolver; generated `docs/configuration.md` gap | Parent `jnj` | A writable-layer and secret policy. Recommended default: user-config writes only, refuse deployment/site/env-owned keys with an exact edit target, and generate docs from inventory. |
-| `polylogue-jnj.10` | MISFRAMED/REDUNDANT | The description asks for `polylogue syntax`; design proposes `help query` or `find --help-syntax`, completion installation in init/Nix/Homebrew, saved-query examples, zero-result hints, and success hints. AC is a generic query-parity template that does not verify these products. | Completion code and tests under `cli`; generated CLI reference; agent integration; distribution files outside this repo for Nix/Homebrew | Parent `jnj`; unnamed saved-view and empty-result coordination | Split into syntax-card generation, completion installation/distribution, and TTY-only teaching hints. Replace the unrelated AC before dispatch. |
-| `polylogue-f7zw` | DEPENDENCY-BLOCKED | The design and AC fully specify one language-neutral corpus, edge vectors, mutation failures, digest, and lockstep update. The deliverable explicitly requires identical fixtures and tests in both Polylogue and Sinex, while current Sinex has no counterpart. | `tests/fixtures/material_protocol/v1/small-session`; `docs/material-protocol-v1.md`; Python encoder; no matching Sinex fixture/encoder test | Parent `303r`; named counterpart `sinex-4j2.1` is not represented as a Beads edge here | Land or jointly schedule the Sinex encoder/test counterpart and choose the shared corpus source of truth. |
-| `polylogue-7aw` | DEPENDENCY-BLOCKED | Design fixes OriginSpec-based config evidence, content-addressed revisions, partial ExecutionContextRef resolution, and honest cohort claims. It consumes the still-open OriginSpec and actor/context contracts instead of defining parallel ones. | `sources/origin_specs.py`; `core/refs.py::{ActorRef,ExecutionContextRef}`; current work-evidence queries; agent integration and hook evidence | Parent `2qx` open; related `h6r` open; `37t.10` remains consumer | Land the relevant `2qx` OriginSpec extension contract and `h6r` execution-context identity before assigning storage and resolver files. |
-| `polylogue-37t.8` | EVIDENCE-BLOCKED | PR #2827 landed safe Claude/Codex routing, explicit unsupported results, and `continue --exec`. The note says the only remainder is a manual real-session reopen receipt. | `archive/resume_routing.py::route_resume`; `cli/query_verbs.py` continue route; unit tests | Parent `37t` | One operator-visible dogfood receipt for a real Claude and Codex session, including command and observed reopened harness. |
-| `polylogue-37t.7` | MISFRAMED/REDUNDANT | The design names the retired bespoke devloop as first consumer, contrary to current repository policy. It also combines product wiring with a separate chaos-drill experiment and leaves SessionStart versus explicit CLI injection as an alternative. | `devtools workspace failure-context`; `.cache/verify` receipts; `api/archive.py::compile_context`; current agent SessionStart integration | Parent `37t` | Rewrite around current `devtools verify` receipts and the installed agent integration. Split context construction from session-cut recovery experiments, and choose explicit versus automatic injection. |
-| `polylogue-nas1` | DEPENDENCY-BLOCKED | The ontology is settled: provider-native resume topology and context delivery are orthogonal, and heuristics cannot create resume edges. The chosen representation explicitly reuses `1vpm.6` work/context graph and `37t.22` receipts. | `session_links` write/queries; `storage/sqlite/archive_tiers/context_delivery_write.py`; context delivery surfaces; `core/refs.py` | `7s57` closed; `37t.22` closed; `1vpm.6` open; content/identity Sol lane owns reconciliation | Land the provider-neutral graph relation from `1vpm.6`, then let the content/identity lane fix the join and provenance contract. No standalone topology schema. |
-
-## Content/identity Sol lane reconciliation
-
-The content/identity lane owns `a7xr.23`, `a7xr.25`, `6e7m`, and `nas1` as one design problem. At audit time its worktree branch had no committed design document yet, so this audit records boundaries rather than guessing its conclusion.
-
-### No-duplication boundaries
-
-| Bead | This audit's boundary | Sol lane obligation |
-| --- | --- | --- |
-| `a7xr.23` | No CDC implementation packet. The current Bead lacks a raw manifest, transaction, reconstruction, and GC design. | State whether CDC changes storage only or also retires revision semantics. Define chunker versioning, chunk refs, reconstruction, atomic publication, and migration/rebuild policy. |
-| `a7xr.25` | No writer patch until event-to-block references have a declared representation. | Define the identity of an event-to-block reference, including one-to-many mappings, inherited/composed messages, unresolved refs, and whether the representation is typed DDL or minimal JSON. Preserve current `_SESSION_EVENTS_REDUNDANT_TYPES` evidence. |
-| `6e7m` | Treat the read-time structural label as landed. Do not introduce a stored derived title. | Preserve `sessions.title` as provider evidence and `insights/session_label.py` as a read projection. Any new identity design must keep provider title provenance and avoid stale serialized labels. |
-| `nas1` | No new `session_links` type for context use and no time/tool-name inference. | Compose provider-native resume assertions with `37t.22` delivery receipts through the `1vpm.6` graph. Define unresolved and abandoned deliveries without fabricating successor topology. |
-
-### Cross-Bead invariants
-
-1. Content identity, storage deduplication, and topology evidence are separate axes. Equal chunks do not prove session identity or resume topology.
-2. Provider evidence remains immutable input. Read-time labels and context-assistance joins are projections.
-3. Rebuildable index changes use canonical DDL and a declared `IndexDeltaDeclaration`; durable raw-byte or user-evidence changes require the durable-tier migration and backup regime.
-4. The Sol lane should cite the current implementations that already landed for `6e7m` and partial event filtering instead of proposing replacements from the old Bead snapshots.
-
-## Implementation packets
-
-### P1: `polylogue-rrxe4` convergence-property loop
-
-**Owned files and symbols**
-
-- `tests/infra/convergence_harness.py`: extend the existing production adapter, without a second convergence state machine.
-- `tests/infra/archive_equivalence.py`: add `canonical_archive_facts` and `assert_archives_equivalent`, owning canonical row comparison modulo declared generation/timestamp fields.
-- Four new property modules under `tests/property/` for order invariance, incremental-versus-bulk, idempotence, and append-prefix consistency.
-- Narrow fixture adapters consuming `tests/infra/pathology_composer.py` and, after review, `tests/infra/pathology_zoo.py`.
-
-**Avoided files**
-
-- Do not change `polylogue/daemon/convergence.py`, production stage semantics, `storage/sqlite/archive_tiers/write.py`, or `maintenance/archive_verification.py` merely to make the harness pass.
-- Do not edit the in-flight zoo builder until commit `c22418c3f` has been reviewed and ownership transferred.
-- Do not normalize away semantically meaningful differences in the comparator.
-
-**Production route**
-
-Corpus program to real raw/parsed input, production ingest writer, production `DaemonConverger` stages, then `ARCHIVE_VERIFICATION_CHECKS`. Bulk and trickle arms must call the same product routes with different schedules.
-
-**Anti-vacuity test**
-
-Use a historical deferred-tail or parent-arrival fixture. A mutation that disables session-link resolution/retry or makes one order skip the divergent tail must make order invariance fail while the unmodified production route passes. The comparator must also fail when one persisted message/block/action row is removed from one arm.
-
-**Focused verification**
-
-```text
-devtools test -k convergence_property
-devtools test tests/unit/daemon/test_convergence_restart_law.py
-devtools verify
-```
-
-**Commit boundary**
-
-One test-infrastructure commit containing the comparator, harness extension, and four property modules. Production fixes discovered by a red property belong in separate Beads/PRs.
-
-**Merge ordering**
-
-Review and merge `c22418c3f` first if the zoo becomes an input. This packet can run in parallel with P2 and P3 because it owns test infrastructure only.
-
-### P2: `polylogue-tw4ar` verdict-cache convergence
-
-**Owned files and symbols**
-
-The convergence implementation already exists on current master: `make_raw_authority_verdict_cache_stage()` is registered in `make_default_convergence_stages()`, performs bounded cache warming, skips append cohorts explicitly, and uses `false_means_pending=True`. This packet must not recreate those symbols. Its remaining scope is a current-tree audit of the implementation against the Bead's acceptance contract, plus any narrowly named residual tests or follow-up Beads discovered by that audit.
-
-- `polylogue/storage/raw_authority_verdict_cache.py` and `polylogue/daemon/convergence_stages.py`: inspect the landed stage and record only verified residuals.
-- `tests/unit/storage/test_raw_authority_verdict_cache.py` and `tests/unit/daemon/test_convergence_stages.py`: retain or extend real stage-interface coverage only where the current acceptance contract lacks evidence.
-
-**Avoided files**
-
-- Do not edit migration 024 or durable DDL unless current schema is proven insufficient.
-- Do not change `derive_raw_authority_verdict`, append-cohort semantics, blob GC, or fragmented-table retirement.
-- Do not run classification in a worker process. The daemon main process remains the sole SQLite writer.
-
-**Production route**
-
-`DaemonConverger` already invokes the registered stage. `check` discovers cohort keys missing from `raw_authority_verdicts` or mismatched by content fingerprint. `execute` calls the existing projection/cache write path in a bounded batch. Remaining work returns pending through `false_means_pending` and convergence debt. The packet is not implementation authorization for a duplicate stage; it is an evidence/reconciliation packet for the landed behavior.
-
-**Anti-vacuity test**
-
-Seed a cached cohort, mutate its `raw_sessions` membership/blob hash through production writers, and assert the stage detects the fingerprint change and refreshes the cache. A second stage pass must hit the cache without invoking `project_raw_authority_verdicts`. Seed an append cohort and assert a typed skipped count rather than an exception.
-
-**Focused verification**
-
-```text
-devtools test -k verdict_cache
-devtools test -k convergence
-devtools verify
-```
-
-**Commit boundary**
-
-One feature commit for the registered stage, helper query, and tests. Append verdict semantics and old-table retirement remain separate commits under `w6hql`/`lr6dx`.
-
-**Merge ordering**
-
-Land before any `w6hql` consumer cutover or `lr6dx` retirement. It is disjoint from P1 and P3.
-
-### P3: `polylogue-io8np` shared topology envelopes
-
-**Owned files and symbols**
-
-- `polylogue/insights/topology_envelope.py`: add `build_topology_envelope` and `build_parent_chain_envelope`, and own node/edge shaping, `DEFAULT_NODE_LIMIT`, `MAX_NODE_LIMIT`, readiness, and parent-chain derivation.
-- Migrate `polylogue/daemon/topology_http.py::build_topology_envelope` and `build_parent_chain_envelope` to thin adapters or re-exports.
-- Migrate `polylogue/mcp/payloads.py::session_topology_payload` and the MCP topology route to the shared builder and expose the same node limit.
-- Update focused daemon tests and add `tests/unit/mcp/test_topology_payload.py` for cross-surface parity.
-
-**Avoided files**
-
-- Do not change topology query semantics, `session_links`, lineage composition, or HTTP routing beyond accepting/passing the common limit.
-- Do not fold this into the unresolved general read-view registry work.
-- Preserve the typed MCP payload contract or regenerate its schema deliberately if the shared envelope adds truncation fields.
-
-**Production route**
-
-`Polylogue.get_session_topology` returns one `SessionTopology`; both daemon HTTP and MCP pass it through the same bounded projection. Parent-chain uses the same shared node/edge vocabulary.
-
-**Anti-vacuity test**
-
-Build a topology larger than `DEFAULT_NODE_LIMIT` with an edge whose parent is dropped. Both HTTP and MCP must return identical kept node/edge ids, truncation count, cycle/unresolved state, and no dangling edge. Removing the shared bound or restoring the MCP local constructor must fail the parity test.
-
-**Focused verification**
-
-```text
-devtools test tests/unit/daemon/test_topology_endpoint.py tests/unit/daemon/test_topology_stack.py
-devtools test tests/unit/mcp/test_topology_payload.py
-devtools verify
-```
-
-**Commit boundary**
-
-One refactor commit containing the shared builder, both adapters, and parity tests. No topology storage changes.
-
-**Merge ordering**
-
-Independent of P1 and P2. Merge before any later MCP projection-registry work so that work consumes one topology envelope.
-
-## Design agendas
-
-Every row below is a blocking decision. Size or difficulty is not the reason for any DESIGN-BLOCKED classification.
-
-| Bead | Exact decision question | Alternatives | Recommended default | Affected contracts | Acceptance evidence required |
-| --- | --- | --- | --- | --- | --- |
-| `wwph1` | Where do durable campaign scripts and the final coverage ledger live? | Ignored `.agent/scratch`; tracked `docs/plans` plus `devtools`; one final tracked report with transient scratch checkpoints | Track rerunnable enumerators under `devtools` or `.agent/scripts` and the final ledger under `docs/plans`; keep raw candidate dumps in scratch | Agent conventions, campaign reproducibility, registry graduation | Fresh clone can rerun one class and reproduce denominator/judgment counts without the missing prompt file |
-| `zok3` | What public syntax owns view-specific parameters? | Per-view subcommands; structured `--view`; DSL projection/profile syntax | DSL projection plus typed profile parameters, with hard removal of inapplicable flat flags | CLI grammar, help, completions, generated docs | One full 34-flag classification and equivalent command examples for transcript, neighbors, correlation, and context |
-| `4n8k` | Which current views are projections, renderings, presets, or distinct actions? | Preserve views; move all to units; classify individually | Individual classification, retaining named views only as presets over Query x Projection x Render | Query grammar, view registry, render profiles, MCP/read parity | Table for every current view plus round-trip/parity fixtures for each moved family |
-| `a7xr.23` | Does CDC replace only whole-file blob storage or also revision authority semantics? | Storage-only chunk manifests; full removal of revision model; hybrid interim prefix retirement | Storage-only CDC first. Keep provenance/revision semantics until every authority consumer has an explicit replacement | Durable source tier, blob GC, admission, replay, rebuild | Golden reconstruction, crash atomicity, chunker-version migration, corpus savings and wall-clock measurement |
-| `cijx.2` | What makes two observations the same repository when forks and mirrors share history? | Root commit; normalized remote; repository UUID/assertion; composite evidence cluster | Evidence cluster with root history plus explicit remote/forge identity, preserving mirror aliases and fork distinctions | Repo query, checkout observations, file evidence, reindex semantics | Fixtures for mirror, fork with shared root, remote rename, remote-less checkout, and reused path interval |
-| `e98k` | Which configuration owns the memory budget and how are profile/cgroup shares derived? | Sinnix-owned budget exported to Polylogue; Polylogue-owned budget imported by Nix; warning-only independent constants | Sinnix deployment budget with an explicit Polylogue env contract and documented deterministic profile/headroom ratios | Polylogue config, SQLite profiles, systemd limits, rebuild canary | Unit derivation tests in both repos and live journal/cgroup receipt during a canary rebuild |
-| `a7xr.25` | How does a session event reference all blocks that carry its lowered payload? | Minimal refs inside JSON; nullable single block id; normalized event-to-block relation | Normalized index-tier event-to-block relation, because one event can map to zero, one, or many blocks | Index DDL, writer, event readers, reprocess/reindex | One-to-many, unresolved, inherited-prefix, and consumer round-trip fixtures; size/write-volume census |
-| `nbls5` | How are registry insights exposed through the consolidated MCP tool set? | Eleven generated tools; no MCP support; existing dispatcher operation | Existing `query` dispatcher with registry-backed projection names; delete dead tool-generation scaffolding | MCP declarations, capability roles, tool contracts, registry docs | Discovery plus one call for every registry entry through the same dispatcher, with no new top-level tools |
-| `lm62x` | Are query surface, route transport, and workflow surface one axis? | One broad enum; transport enum plus workflow enum; three documented axes | A shared transport enum for physical call routes and a distinct broader workflow channel enum | ops DDL, evaluator, route observations, product workflows | Producer/consumer/join census and cross-table fixture showing lossless correlation |
-| `jglh` | Which identical member sets represent the same semantic axis? | Collapse every pair; keep every pair; pair-by-pair decision | Pair-by-pair decision with shared definitions moved to the lowest legal layer | Layering, public types, DDL helpers, payload schemas | One matrix row per listed pair and tests that semantic mappings, not spellings, remain correct |
-| `mzp8` | What are the canonical names and mappings for same-name divergent vocabularies? | Merge values; rename one axis; create a shared supertype | Merge InvalidationReason; rename catalog pricing basis and recorded cost authority; rename installer and metric-specific types | Imports, serialized values, schemas, docs | Call-site census, explicit old-to-new mapping, mypy and generated schema checks |
-| `jnj.1` | Which abstraction owns semantic inclusion, data projection, rendering, destination, and presets? | Extend current `ProjectionSpec`; prefer `ContentProjectionSpec`; create a normalizer over both | One normalized request with separate selection, content projection, and render/profile components; existing types become adapters then disappear | CLI/MCP/API/web/export/context | Concern-to-owner matrix, one canonical serialized spec, and cross-surface parity fixture |
-| `jnj.2` | Is facets a top-level verb or a named projection over analyze/query? | New verb; named projection; generated alias | Named projection over the canonical relation, with any convenience spelling calling that exact operation | CLI command floor, filter scope, JSON envelope | Exact-ID and full-filter positive/empty cases proving no scope broadening |
-| `jnj.9` | Which config layer may `set` mutate and how are managed/secret keys handled? | Write user config; edit winning layer; generate deployment instructions only | Mutate user config only. Refuse managed/site/env and secret writes with a precise edit target | Config resolver, CLI, docs generator, Nix ownership | Tests for user write, env override, Nix-managed refusal, unknown key, secret redaction, and generated docs |
-
-## Dependency DAG
-
-```text
-Testing and verification
- amrpx [closed] + t0m73 [closed]
- -> yazae existing commit review/narrowing
- -> rrxe4 [packet P1]
- yazae + rrxe4 + t0m73
- -> ey4ro
-
-Raw authority
- tw4ar [packet P2]
- -> w6hql umbrella completion
- append-verdict design + tw4ar
- -> lr6dx retirement
- ds4b4 item 4
- -> superseded by existing row-reference GC invariant
-
-Read algebra
- 4n8k + zok3 + mjupn evidence
- -> jnj.1 ownership decision
- jnj.1
- -> 1lm
- jnj.1 decision
- -> jnj.2 implementation shape
- io8np [packet P3]
- -> later MCP projection-registry work
-
-Content and identity
- content/identity Sol design
- -> a7xr.23
- -> a7xr.25
- -> nas1
- 1vpm.6
- -> nas1
- 6e7m [already landed]
- -> preserve as invariant in Sol design
-
-Interop and context
- 2qx OriginSpec + h6r execution context
- -> 7aw
- Sinex material-protocol counterpart
- -> f7zw
-
-Evidence gates
- 1fijp implementation [landed]
- -> 72-hour live receipt
- a7xr.26
- -> wrapper benchmark
- fbkr
- -> automatic-versus-manual plan coverage receipt
- 37t.8 implementation [landed]
- -> manual reopen receipts
-```
-
-## Shared hotspots and lane serialization
-
-| Hotspot | Beads | Rule |
-| --- | --- | --- |
-| `storage/sqlite/archive_tiers/write.py` and index DDL | `a7xr.25`, `cijx.2`, residual `1fijp` interpretation | Serialize under the content/identity design. No concurrent implementation lanes. |
-| CLI read algebra and grammar | `4n8k`, `zok3`, `mjupn`, `jnj.1`, `jnj.2`, `1lm` | One design lane, then one migration branch. Do not split by Bead because every item touches the same public contract and handlers. |
-| `core/enums.py`, ops DDL, generated schemas | `lm62x`, `jglh`, `mzp8`; `oj4oo` already landed | Resolve all vocabulary agendas first, cluster non-overlapping definitions, and serialize shared-file edits. |
-| Raw-authority cache/convergence | `tw4ar`, `w6hql`, `lr6dx` | Land P2 first. Append semantics second. Consumer/write-path retirement last. |
-| MCP payload and projection dispatch | `io8np`, `nbls5`, `mjupn` | P3 may land now. Hold dispatcher/registry work until the read-algebra decision; rebase it after P3. |
-| Test pathology infrastructure | `yazae`, `rrxe4`, `ey4ro` | Review existing yazae commit first. P1 next. Red-backlog mapping last. |
-
-## Safe parallel plan
-
-Wave 0 is reconciliation work, not a Luna implementation lane:
-
-1. Review `c22418c3f` for `yazae` against its production-route and manifest AC.
-2. Reconcile landed open Beads `taj0o`, `6e7m`, `oj4oo`, and `ds4b4` in coordinator state.
-3. Wait for the content/identity Sol document before dispatching its four covered Beads.
-
-Wave 1 can use three Luna lanes in parallel:
-
-1. P2 `tw4ar`, daemon/storage cache convergence.
-2. P3 `io8np`, shared topology envelopes.
-3. P1 `rrxe4`, convergence property harness, after the `yazae` review determines whether to consume its builder.
-
-Wave 2 begins only after Wave 1 and design decisions:
-
-1. `ey4ro` after `rrxe4` and narrowed `yazae` land.
-2. Raw-authority append verdict coverage, then `lr6dx`, then close the `w6hql` umbrella.
-3. One read-algebra branch covering `4n8k`/`zok3`/`mjupn`/`jnj.1`, followed by `1lm` and the chosen `jnj.2` surface.
-4. MCP registry exposure after the read-algebra decision and P3.
-
-## Corrections to prior readiness claims
-
-Several records carry old delivery labels such as `readiness=A-implementation-ready` or point to snapshot packets under `.agent/handoffs/...` that are absent from this checkout. Those labels are not current specifications and were not accepted as readiness evidence.
-
-- `taj0o`: a title-level audit would call it open parser work. Full notes plus current history show PR #3691 already landed the entire remaining stage.
-- `6e7m`: its open title suggests missing title design. Current source already implements its decisive AC as a read-time structural label and keeps provider evidence in storage.
-- `oj4oo`: the open vocabulary title is stale after PR #3657.
-- `ds4b4`: its title suggests a missing GC invariant. Full source and the anti-vacuity suite show the requested verdict-specific check would duplicate the stronger existing row-reference invariant.
-- `37t.8`: the implementation is landed; only manual evidence remains.
-- `e98k`: many AC and detailed design text do not make it fully ready. The already-landed PR explicitly deferred the one-source-of-truth cross-repo contract, and the remaining scaling/headroom policy is unspecified.
-- `jnj.1`, `1lm`, `7aw`, `37t.7`, and `37t.8`: old prework-packet pointers were generated from `8a975a40` and the referenced files are absent. Current symbols and current architecture control this audit.
-- `37t.7`: the old `A-implementation-ready` label also names the retired devloop as first consumer, so it cannot be dispatched without reframing.
-- `yazae`: the open Bead is no longer greenfield because an unmerged implementation commit exists. Dispatch must begin with review, not another builder.
-
-## Residual uncertainty
-
-The content/identity Sol worktree had not committed its design document when this audit was written. Its eventual decisions may change the readiness of `a7xr.23`, `a7xr.25`, and `nas1`, but they must preserve the no-duplication boundaries above. The coordinator export was slightly older than this worktree's local `.beads/issues.jsonl`; the coordinator export was used by instruction, and separate comments were read with explicit read-only coordinator-directory commands. No live archive mutation or live 72-hour measurement was performed.
diff --git a/docs/plans/beads-acceptance-contracts-2026-08-07.md b/docs/plans/beads-acceptance-contracts-2026-08-07.md
deleted file mode 100644
index de5f49f2a3..0000000000
--- a/docs/plans/beads-acceptance-contracts-2026-08-07.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Beads acceptance-contract wave — 2026-08-07
-
-- Source export targets: 218
-- Canonical snapshot status: exact typed-carrier regeneration is committed for all 218 manifest IDs
-- Dispatch status: guarded by the committed route registry and exact source/dependency digests
-- Structured contract key: `metadata.acceptance_contract_v1`
-- Validator: `devtools lab policy acceptance-contracts --manifest docs/plans/beads-acceptance-contracts-2026-08-07.txt`
-- Route registry: `docs/plans/beads-acceptance-route-registry.json`
-- Regenerator: `python -m devtools.regenerate_acceptance_contracts`
-
-The validator does not use arbitrary natural-language process prose as authority. It validates a typed named route identifier whose dispatch class is compatible with the contract type, outcome/evidence/verification/anti-vacuity/safety/closure fields, a managed focused/default verification route for implementation and test contracts, and a positive live-operation receipt carrier with archive, operation, target, before-state, after-state, and result-status bindings. It recomputes a scope-bearing source SHA-256 with a stable dependency projection, plus a separate dependency digest. Lifecycle status and timestamps are deliberately excluded. Human-readable acceptance criteria must be an exact rendering of the structured contract, including the partial-closure successor rule. Every evidence item must carry exactly one typed carrier naming the Bead title, description, design, or notes field, containing that field's UTF-8 snapshot, snapshot SHA-256, half-open byte range, and exact range-text SHA-256; the range must decode and equal the evidence item. Incomplete, fabricated, truncated, or self-attested completeness fields are dispatch-blocked.
-
-The `devtools lab policy acceptance-contracts` gate ratchets the committed manifest at 218 IDs and emits a sorted `regeneration_required` report in JSON mode. The exact-head snapshot has been regenerated by the deterministic regenerator, and each canonical route identifier resolves through the committed registry with a matching route class, contract type, dispatch class, and target list. `lab policy bead-graph` consumes the same manifest authority and rejects missing or invalid contracts. `lane-brief` validates the full current Bead record, source digest, dependency digest, route registry, and rendered criteria before dispatch. `polylogue-gvzkr` is currently classified as a read-only audit with per-table/per-column dispositions, so this lane does not rewrite it.
-
-The archived source bundle and its `apply_acceptance_contracts.py` helper predate the final digest projection and typed carriers. They are operationally incompatible with this exact head and must not be used for regeneration, dry runs, or import. The committed snapshot and route registry supersede them.
-
-Sparse records remain marked `confidence=planner-review`; that flag is not permission for a Luna implementation worker to make architectural choices. It requires planner review before dispatch.
diff --git a/docs/plans/beads-acceptance-contracts-2026-08-07.txt b/docs/plans/beads-acceptance-contracts-2026-08-07.txt
deleted file mode 100644
index 01c59a5644..0000000000
--- a/docs/plans/beads-acceptance-contracts-2026-08-07.txt
+++ /dev/null
@@ -1,218 +0,0 @@
-polylogue-01fe
-polylogue-075v
-polylogue-07pt
-polylogue-0nvk
-polylogue-0v4tn
-polylogue-194qk
-polylogue-1c6j
-polylogue-1fijp
-polylogue-1k9l
-polylogue-1suq6
-polylogue-26hv
-polylogue-2ara
-polylogue-2bc2
-polylogue-2jga
-polylogue-2kcd
-polylogue-2t0vp
-polylogue-2ux5m
-polylogue-34h3
-polylogue-3a61
-polylogue-3loh
-polylogue-3szyi
-polylogue-3ycw
-polylogue-4j9j
-polylogue-4n8k
-polylogue-4p1.4
-polylogue-4uzoo
-polylogue-54gj
-polylogue-59qy
-polylogue-5fh4
-polylogue-5gjre
-polylogue-5jnq
-polylogue-5slz
-polylogue-5tkbt
-polylogue-5yig
-polylogue-6j9c
-polylogue-6kur
-polylogue-6olqi
-polylogue-6ou1q
-polylogue-6pii
-polylogue-6tue
-polylogue-74wvj
-polylogue-7dgf
-polylogue-7f8yc
-polylogue-7ilr
-polylogue-7mgx
-polylogue-7qw4
-polylogue-7rds
-polylogue-7zj4t
-polylogue-80ks
-polylogue-8ifs
-polylogue-8u1p
-polylogue-8ykm
-polylogue-923uc
-polylogue-9hq2
-polylogue-9kjtc
-polylogue-a7xr.24
-polylogue-a7xr.25
-polylogue-a7xr.26
-polylogue-adre
-polylogue-azh1l
-polylogue-b4cs
-polylogue-b4n2
-polylogue-bfc7a
-polylogue-bfwg
-polylogue-bwo2l
-polylogue-c2qsm
-polylogue-c5mb
-polylogue-ck5v
-polylogue-d0ew
-polylogue-d0kj
-polylogue-d4kq
-polylogue-d70d
-polylogue-dlmc1
-polylogue-e2uns
-polylogue-e6a0
-polylogue-ei0d
-polylogue-enrpa
-polylogue-erf3
-polylogue-es7b
-polylogue-ey3r
-polylogue-f7cd
-polylogue-f9kk
-polylogue-fbkr
-polylogue-fe8fv
-polylogue-fjg91
-polylogue-fjvi
-polylogue-fqnv
-polylogue-frqp
-polylogue-fyyro
-polylogue-g16g
-polylogue-g193e
-polylogue-g31s
-polylogue-ganm
-polylogue-gb4e
-polylogue-gcy1
-polylogue-gmw2
-polylogue-gody
-polylogue-grdt
-polylogue-gvr2
-polylogue-gvzkr
-polylogue-h2sf6
-polylogue-hgk1
-polylogue-hhg58
-polylogue-ht3n
-polylogue-hwwtq
-polylogue-ic5i
-polylogue-ihro
-polylogue-iiu6r
-polylogue-in94
-polylogue-inoh
-polylogue-ioz2
-polylogue-ioz7
-polylogue-iuyr
-polylogue-iy3n
-polylogue-j1vs
-polylogue-j7sin
-polylogue-j8yo
-polylogue-jglh
-polylogue-jtek
-polylogue-jwqj
-polylogue-kbsy5
-polylogue-kc26
-polylogue-kcdg
-polylogue-kea7p
-polylogue-knc7
-polylogue-lbk1
-polylogue-lk2w
-polylogue-lm62x
-polylogue-lqhi7
-polylogue-lzank
-polylogue-m1s98
-polylogue-m69yv
-polylogue-m8nj
-polylogue-mgf6
-polylogue-mia3
-polylogue-mkk0
-polylogue-mlqrt
-polylogue-mnds
-polylogue-mznm
-polylogue-mzp8
-polylogue-n8ft
-polylogue-nfl5
-polylogue-nqx2
-polylogue-nvqb
-polylogue-o2jin
-polylogue-o56w
-polylogue-ofry
-polylogue-oj4oo
-polylogue-om8dh
-polylogue-oou3c
-polylogue-oqib
-polylogue-oxrv
-polylogue-p21v
-polylogue-p6rz
-polylogue-pfdf
-polylogue-pkst
-polylogue-px4h
-polylogue-pzxm
-polylogue-q1at
-polylogue-q9hl
-polylogue-qj5x
-polylogue-ql2fb
-polylogue-qqi1
-polylogue-qut1
-polylogue-qwgi
-polylogue-rpuqn
-polylogue-rsz1
-polylogue-rxfo
-polylogue-s9irb
-polylogue-sg80
-polylogue-sgdp
-polylogue-shnc
-polylogue-siet
-polylogue-sr6u
-polylogue-sze30
-polylogue-t73c2
-polylogue-t83q
-polylogue-tas4
-polylogue-tf8p
-polylogue-trjb
-polylogue-tztk
-polylogue-u8x7
-polylogue-ubdxf
-polylogue-ubwg
-polylogue-uhjv
-polylogue-ujitw
-polylogue-upbv
-polylogue-ut3r
-polylogue-uxrim
-polylogue-uyci
-polylogue-v6xh
-polylogue-v73m
-polylogue-vid0
-polylogue-vp2ky
-polylogue-vp9d
-polylogue-vqt48
-polylogue-vs5x
-polylogue-vwdj
-polylogue-w96f
-polylogue-wbuf
-polylogue-wf8a
-polylogue-x1gd
-polylogue-xecca
-polylogue-xla90
-polylogue-y0ven
-polylogue-y9106
-polylogue-yhgc
-polylogue-yl8t
-polylogue-ymqp
-polylogue-z1rdw
-polylogue-z3sv
-polylogue-zahj
-polylogue-zdtqj
-polylogue-zn1k
-polylogue-zocm
-polylogue-zok3
-polylogue-zqph
-polylogue-zwyc
diff --git a/docs/plans/beads-acceptance-reconciliation.md b/docs/plans/beads-acceptance-reconciliation.md
deleted file mode 100644
index a56287b026..0000000000
--- a/docs/plans/beads-acceptance-reconciliation.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# Acceptance contract reconciliation protocol
-
-`devtools lab policy acceptance-contract-reconcile` is a file-level, fail-closed boundary between the canonical repository JSONL and a read-only live Beads export. It never invokes `bd`, never writes Dolt, never parses acceptance prose, and never chooses an authority for a changed source record.
-
-## Lane output
-
-The command first loads the ratcheted 218-ID manifest inside `reconcile`; every manifest ID must exist in the canonical repository JSONL and carry a valid contract before any wave is generated. The fixed `contract_denominator` is therefore always 218, never the count of contracts discovered in a partial input. It then compares rows by Bead ID and recomputes the source and dependency digests with the merged acceptance-contract validator. Reconciliation is blocked when any canonical contract is invalid or stale. The reconciliation report has separate ID sets for `master_only`, `live_only`, `master_newer`, `live_newer`, `same_timestamp_different`, and `contract_refused`. It also records the fixed contract denominator, manifest digest, full canonical and live population digests, refused IDs and reasons, the ordered targeted IDs, per-row wave digests, and the exact guarded-wave digest.
-
-The targeted JSONL contains only guarded records. Each record starts as the live row and changes only `acceptance_criteria` and `metadata.acceptance_contract_v1`. Dependencies, comments, status, notes, timestamps, and every other live field remain equal in the non-contract projection; the equality digest removes only the contract key and an empty metadata container, while retaining every non-contract metadata key. A live source digest must equal the contract's `source_digest`; otherwise that ID is refused and is absent from the wave. Both `updated_at` values are parsed as canonical Beads RFC3339 timestamps before classification; arbitrary strings never authorize a wave. Malformed live metadata or timestamps are refused explicitly. Live-newer contract rows are separately deferred and are never put in the wave, even when their source digest matches.
-
-Acceptance contracts carry route authority as a structured named `route_spec.identifier` plus a type-compatible dispatch class. The identifier must resolve in `docs/plans/beads-acceptance-route-registry.json`, bind to the same Bead and target list, and agree with the registered contract class. Evidence completeness is not inferred from prose or a self-attested `complete` flag: every evidence item requires an exact typed `evidence_spans` carrier naming one of the Bead's title, description, design, or notes fields, carrying that field's UTF-8 source snapshot, its SHA-256 digest, a half-open byte range, and the SHA-256 digest of the exact range text. The range must decode and equal the evidence item; extra or missing carrier fields, fabricated snapshots, truncated snapshots, and digest mismatches are rejected.
-
-The exact-head self-reconciliation against the committed canonical snapshot is an idempotent no-op: all 218 canonical records are already guarded, with no targeted rows, refusals, or deferred rows. A real live export is still required for an operational import; this local check does not invent live authority or adjudicate live-only and timestamp-conflict rows.
-
-## Coordinator-only apply sequence
-
-The implementation lane stops before this sequence. The coordinator must retain every output and receipt under a named run directory.
-
-1. Confirm the six-PR merge frontier is no longer full and identify the exact repository head and Beads database identity. Take a Dolt backup using the site-approved Beads backup procedure, verify that backup, and retain its manifest or receipt before any import.
-2. Acquire the site-approved exclusive Beads/Dolt writer lease, or stop/quiesce every Beads writer for the whole operation. The lease must cover the live export, generator, dry-run, real import, and post-import export. If exclusive writer ownership cannot be established, stop; `--allow-stale` is not a concurrency lock and the after-check is not permission to discover a race after mutation.
-3. Capture a read-only live export from the schema-compatible client. The installed client for the current v63 database is `/etc/profiles/per-user/sinity/bin/bd`; the devshell `bd` is v62 and must not be used. Do not run either client from this lane.
-4. Run the generator against the committed repository JSONL and that export:
-
- ```text
- devtools lab policy acceptance-contract-reconcile --repository .beads/issues.jsonl --live RUN/live-before.jsonl --wave RUN/targeted.jsonl --report RUN/reconciliation.json --json
- ```
-
-5. Review the report. Require the contract refusal and deferred denominators and every refused/deferred ID to be named. Adjudicate master-only, live-only, master-newer, live-newer, and same-timestamp-different rows separately. Do not add `polylogue-5bxpy`, `polylogue-g8v5z`, or any live-newer row to the wave. Do not regenerate timestamps. Record `live_population_digest` as the exact pre-import live population binding.
-6. Run the schema-compatible client's dry-run targeted import with `--allow-stale`, using only `RUN/targeted.jsonl`. The dry run must report exactly the generated guarded IDs. Do not use the normal stale-snapshot wrapper, because equal timestamps are intentionally crossed by this explicit, targeted `--allow-stale` operation.
-7. After reviewing the dry-run receipt, run the real targeted import with the same client, the same wave, and `--allow-stale`, while still holding the exclusive writer lease. The coordinator must not add flags that permit unrelated rows, candidate-only rows, or source-digest bypasses.
-8. Capture a post-import read-only export as `RUN/live-after.jsonl` with the same schema-compatible client. Verify the exact report, ordered wave, every wave row against the canonical source, and the unchanged remainder:
-
- ```text
- devtools lab policy acceptance-contract-reconcile --verify-repository .beads/issues.jsonl --verify-report RUN/reconciliation.json --verify-before RUN/live-before.jsonl --verify-after RUN/live-after.jsonl --verify-wave RUN/targeted.jsonl --json
- ```
-
- This checks that the report and wave digests match, the wave order is unchanged, every wave row still equals the canonical guarded row, the full before and after population digests are recorded, and no record outside the wave changed.
-9. Run the merged contract validator against the post-import repository export and then run the graph-policy check. The graph check is a live-state check and must use the schema-compatible client. A green validator does not adjudicate live-only or live-newer records.
-10. Reconcile the repository JSONL from the post-import export only after the live export and graph-policy checks pass. Review the resulting diff for exactly the guarded contract fields. Retain the before export, after export, wave, report, backup receipt, dry-run receipt, real-import receipt, validator output, and graph-policy output together.
-11. Compare the full before and after population digests in the post-import receipt with the exact report and require the post-import record universe to be identical. A mismatch blocks publication and requires restoring from the retained backup or reopening the reconciliation. No direct SQL, hand-edited JSONL, ordinary `bd` invocation, or second wave is permitted. Release the writer lease only after all receipts are durable.
-
-The local guarded actuator is `devtools lab policy acceptance-contract-apply`. It consumes the exact canonical repository, before export, reconciliation report, and wave, writes only a file copy, refuses stale or altered inputs, and treats an identical existing output as an idempotent reimport. It never invokes `bd`.
-
-## Residual boundary
-
-This branch regenerates and validates all 218 canonical manifest records against the exact route registry and typed carrier shape. It does not perform a live Beads export, Dolt backup, dry-run import, real import, graph-policy check, or live mutation. The old source bundle and applier are operationally incompatible because their source and route digests predate this exact-head authority; the committed registry, regenerated JSONL, reconciliation report, and guarded file applier supersede them.
diff --git a/docs/plans/beads-acceptance-route-registry.json b/docs/plans/beads-acceptance-route-registry.json
deleted file mode 100644
index 3ef6ec5cf6..0000000000
--- a/docs/plans/beads-acceptance-route-registry.json
+++ /dev/null
@@ -1,2188 +0,0 @@
-{
- "manifest_count": 218,
- "manifest_digest": "703df11c81dae8af6d7106bc4737502ca8baddc9013916bbb68922696d8206b5",
- "routes": [
- {
- "bead_id": "polylogue-01fe",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-01fe",
- "targets": [
- "Exercise the implementation through these named production surfaces: `get/read`, `origin bogus-origin`, `GET /api/sessions?query=x&origin=bogus-origin`, `unknown-export`."
- ]
- },
- {
- "bead_id": "polylogue-075v",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-075v",
- "targets": [
- "Exercise the implementation through these named production surfaces: `route/DOM`, `project/title/uuid.`."
- ]
- },
- {
- "bead_id": "polylogue-07pt",
- "class": "TestHarnessRoute",
- "contract_type": "test_harness",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-07pt",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/build.test.js`, `timing/race`."
- ]
- },
- {
- "bead_id": "polylogue-0nvk",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-0nvk",
- "targets": [
- "Exercise the implementation through these named production surfaces: `audits-2026-07-31/leak-surfaces.html`."
- ]
- },
- {
- "bead_id": "polylogue-0v4tn",
- "class": "LiveOperationRoute",
- "contract_type": "live_operation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-0v4tn",
- "targets": [
- "Exercise the implementation through these named production surfaces: `300/300`, `100/100`, `i3zo/PR`, `.agent/scratch/reindex-baseline-2026-08-03.md`."
- ]
- },
- {
- "bead_id": "polylogue-194qk",
- "class": "LiveOperationRoute",
- "contract_type": "live_operation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-194qk",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/sources/test_source_laws.py`, `sources/dispatch.py`, `detection/list`."
- ]
- },
- {
- "bead_id": "polylogue-1c6j",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-1c6j",
- "targets": [
- "Exercise the implementation through these named production surfaces: `docs/cli-reference.md`, `docs/schemas/cli-output/search-envelope.schema.json`, `hits/total/limit/offset/query/retrieval_lane`, `items/limit/mode/next_cursor/next_offset/offset/origin/query/retrieval_lane/total`, `polylogue --format json`, `env -u POLYLOGUE_ARCHIVE_ROOT polylogue --no-daemon --limit 3 --json find 'frozen_clock'`, `GET /api/sessions?query=frozen_clock&limit=3`."
- ]
- },
- {
- "bead_id": "polylogue-1fijp",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-1fijp",
- "targets": [
- "Exercise the implementation through these named production surfaces: `sources/live/batch.py`, `sources/drive/__init__.py`, `2/5`, `rotate/vanish`."
- ]
- },
- {
- "bead_id": "polylogue-1k9l",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-1k9l",
- "targets": [
- "Exercise the real production entry point for “111 raws stuck with parse_error (59 truncated-JSONL claude-code, 25 no-session unknown-export, 19 CAS-frontier, 6 decode, 2 hermes)”; direct fixture-row insertion, mocks that bypass the owning layer, and test-only helpers do not satisfy the criterion."
- ]
- },
- {
- "bead_id": "polylogue-1suq6",
- "class": "TestHarnessRoute",
- "contract_type": "test_harness",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-1suq6",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/cli/test_status.py`, `tests/unit/daemon/test_daemon_status.py`, `index.db/source.db`, `tests/infra`, `subprocess/git`."
- ]
- },
- {
- "bead_id": "polylogue-26hv",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-26hv",
- "targets": [
- "Exercise the implementation through these named production surfaces: `quarantine-2026-07/6a3f9296-3500-83eb-b31b-f4ccf9720574.md`, `id/content`, `quarantine-2026-07/2026-06-27_22-19-13_Claude_Chat_Optimizing_NixOS_Configuration_Blueprints_-_Claude_-_https.md`, `browser-spool-2026-07-10/chatgpt/6a506bcf-852c-83eb-82e6-e23ac8a418e1-d42dead8db48.json`."
- ]
- },
- {
- "bead_id": "polylogue-2ara",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-2ara",
- "targets": [
- "Exercise the implementation through these named production surfaces: `closes/unclaims`, `.beads/issues.jsonl`, `feature/devtools/worktree-import-guard`, `reviewed/finished/merged`, `bd invocations from stale worktrees silently revert recent bead writes (live incident: 5 reverts in one hour)`."
- ]
- },
- {
- "bead_id": "polylogue-2bc2",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-2bc2",
- "targets": [
- "Exercise the implementation through these named production surfaces: `cyclic/duplicate`, `dedupe/repair`, `bd list --all infinite recursion: tree renderer loops on cyclic/duplicate parent-child edge, wrote 54GB before kill`."
- ]
- },
- {
- "bead_id": "polylogue-2jga",
- "class": "LiveOperationRoute",
- "contract_type": "live_operation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-2jga",
- "targets": [
- "Exercise the implementation through these named production surfaces: `docs/plans/test-closure-matrix.yaml`, `devtools/verify_closure_matrix.py`, `target_files/representative_tests`, `moved/renamed`, `git history (d068d6482, 054dfa9e1, dc6fa632a) shows only refactor/consolidation`."
- ]
- },
- {
- "bead_id": "polylogue-2kcd",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-2kcd",
- "targets": [
- "Exercise the implementation through these named production surfaces: `.agent/archive/retired-demos/ handoff files`, `audits-2026-07-31/leak-surfaces.html`, `b4cs/3loh.`."
- ]
- },
- {
- "bead_id": "polylogue-2t0vp",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-2t0vp",
- "targets": [
- "Exercise the implementation through these named production surfaces: `codex/sessions`, `mid-rewrite/truncation`, `append/full`, `lb39z/w6hql`."
- ]
- },
- {
- "bead_id": "polylogue-2ux5m",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-2ux5m",
- "targets": [
- "Exercise the implementation through these named production surfaces: `BeadDict/JSONL`, `devtools/bead_cluster.py`, `.beads/issues.jsonl`, `devtools/bead_loader.py`, `bd ready --json`, `bd list --json`."
- ]
- },
- {
- "bead_id": "polylogue-34h3",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-34h3",
- "targets": [
- "Exercise the implementation through these named production surfaces: `api/archive.py`, `cli/commands/status.py`, `operations/archive_debt.py`, `security/excision.py`."
- ]
- },
- {
- "bead_id": "polylogue-3a61",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-3a61",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/core/test_json.py`, `tests/unit/core/test_filters_props.py`, `origins/exclusions`, `try/except`, `com/Sinity/polylogue/pull/3528`, `feature/test/fix-tautological-assertions-3a61`, `assert len(result) >= 1`."
- ]
- },
- {
- "bead_id": "polylogue-3loh",
- "class": "ProcessRoute",
- "contract_type": "process",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-3loh",
- "targets": [
- "Exercise the implementation through these named production surfaces: `archive/.`, `.beads-hooks/pre-commit`, `devtools/pre_push_gate.py`, `polylogue/security/secret_scan.py`."
- ]
- },
- {
- "bead_id": "polylogue-3szyi",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-3szyi",
- "targets": [
- "Exercise the implementation through these named production surfaces: `storage/sqlite/archive_tiers/common.py`, `storage/sqlite/query_objects.py`, `status/interrupted-vs-cancelled`, `luck/discipline`."
- ]
- },
- {
- "bead_id": "polylogue-3ycw",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-3ycw",
- "targets": [
- "Exercise the implementation through these named production surfaces: `seed/tour`, `fresh/cold`, `file/dir`, `0/expected`."
- ]
- },
- {
- "bead_id": "polylogue-4j9j",
- "class": "LiveOperationRoute",
- "contract_type": "live_operation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-4j9j",
- "targets": [
- "Exercise the implementation through these named production surfaces: `feature/perf/pipelined-rebuild-parse-apply`, `dedup/content-cache`."
- ]
- },
- {
- "bead_id": "polylogue-4n8k",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-4n8k",
- "targets": [
- "Exercise the implementation through these named production surfaces: `origin/master`, `find/read/analyze/mark/select/delete/continue`, `sessions/actions/messages/observed-events`."
- ]
- },
- {
- "bead_id": "polylogue-4p1.4",
- "class": "DecisionRoute",
- "contract_type": "decision",
- "dispatch": "decision",
- "identifier": "acceptance/polylogue-4p1.4",
- "targets": [
- "Exercise the implementation through these named production surfaces: `message/session`, `surfaces/payloads.py`, `archive/message/models.py`, `target_ref/anchor/actions`."
- ]
- },
- {
- "bead_id": "polylogue-4uzoo",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-4uzoo",
- "targets": [
- "Exercise the implementation through these named production surfaces: `pagination/plan_count`, `polylogue/storage/raw_authority.py`, `plan_count/post_plan_count`, `census/blocker`."
- ]
- },
- {
- "bead_id": "polylogue-54gj",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-54gj",
- "targets": [
- "Exercise the implementation through these named production surfaces: `x.com/twitter.com`, `archiveProviderForUrl/conversationIdForUrl`, `GraphQL/REST`, `GrokBackfillAdapter/grok.js`."
- ]
- },
- {
- "bead_id": "polylogue-59qy",
- "class": "TestHarnessRoute",
- "contract_type": "test_harness",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-59qy",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/core/test_schema_generation.py`, `tests/unit/storage/test_insight_materialization_laws.py`, `tests/unit/sources/test_parsers_props.py`, `xfail/skip`, `tests/unit/cost/test_contract_suite.py`, `devtools test tests/unit/core/test_schema_generation.py -v -rs -> 32 passed, 1 SKIPPED`."
- ]
- },
- {
- "bead_id": "polylogue-5fh4",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-5fh4",
- "targets": [
- "Exercise the implementation through these named production surfaces: `page-cache/mmap`."
- ]
- },
- {
- "bead_id": "polylogue-5gjre",
- "class": "LiveOperationRoute",
- "contract_type": "live_operation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-5gjre",
- "targets": [
- "Exercise the implementation through these named production surfaces: `backfill/GC`, `acquired_reachable_count/acquired_unreachable_count`."
- ]
- },
- {
- "bead_id": "polylogue-5jnq",
- "class": "ProcessRoute",
- "contract_type": "process",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-5jnq",
- "targets": [
- "Exercise the implementation through these named production surfaces: `.agent/scratch/live/beads-handling-design-2026-07-31.html`, `descriptions/design/acceptance-criteria`, `insights/work_effects.py`, `.beads/issues.jsonl`."
- ]
- },
- {
- "bead_id": "polylogue-5slz",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-5slz",
- "targets": [
- "Exercise the implementation through these named production surfaces: `docs/search.md`, `webui/facet`, `before/after.`, `polylogue/archive/query/retrieval_search.py`."
- ]
- },
- {
- "bead_id": "polylogue-5tkbt",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-5tkbt",
- "targets": [
- "Exercise the implementation through these named production surfaces: `lkrc/hjpx`, `.agent/scratch/archive-invariants-2026-08-03.py`."
- ]
- },
- {
- "bead_id": "polylogue-5yig",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-5yig",
- "targets": [
- "Exercise the real production entry point for “19 prefix-sharing children whose earliest message predates the branch-point timestamp”; direct fixture-row insertion, mocks that bypass the owning layer, and test-only helpers do not satisfy the criterion."
- ]
- },
- {
- "bead_id": "polylogue-6j9c",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-6j9c",
- "targets": [
- "Exercise the implementation through these named production surfaces: `models/gemini-2.5-pro`, `models/gemini-3-pro-preview`, `1.25/10.0`, `input/output`, `python3 -c \"from polylogue.archive.semantic.pricing import _normalize_model; print(_normalize_model('models/gemini-2.5-pro'))\"`."
- ]
- },
- {
- "bead_id": "polylogue-6kur",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-6kur",
- "targets": [
- "Exercise the implementation through these named production surfaces: `repair/maintenance`, `storage/repair.py`, `storage/sqlite/connection_profile.py`, `FK/CASCADE`, `claude_workflow`, `sinex_publication`, `repair.py`."
- ]
- },
- {
- "bead_id": "polylogue-6olqi",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-6olqi",
- "targets": [
- "Exercise the implementation through these named production surfaces: `docs/schema.md`, `copy-forward/consent`, `benign-DDL/SEMANTIC_REPARSE`."
- ]
- },
- {
- "bead_id": "polylogue-6ou1q",
- "class": "TestHarnessRoute",
- "contract_type": "test_harness",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-6ou1q",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/cost/test_contract_suite.py`, `tests/unit/cost/test_outlook.py`, `outlook/plans`, `duplicate/overlapping`, `CLI/MCP`."
- ]
- },
- {
- "bead_id": "polylogue-6pii",
- "class": "TestHarnessRoute",
- "contract_type": "test_harness",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-6pii",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/demo/test_demo_seed_verify.py`, `direct/GDPR`, `precedence/sequence`, `3179/ingest_precedence.py`, `9/9`, `polylogue-lrdh 3 failing browser-capture title-precedence tests. #3179 added a mirror`."
- ]
- },
- {
- "bead_id": "polylogue-6tue",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-6tue",
- "targets": [
- "Exercise the implementation through these named production surfaces: `browsing/search.`."
- ]
- },
- {
- "bead_id": "polylogue-74wvj",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-74wvj",
- "targets": [
- "Exercise the implementation through these named production surfaces: `daemon/cli.py`, `check/execute`."
- ]
- },
- {
- "bead_id": "polylogue-7dgf",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-7dgf",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/core/enums.py`, `polylogue/sources/parsers/base_support.py`, `polylogue/sources/parsers/codex.py`."
- ]
- },
- {
- "bead_id": "polylogue-7f8yc",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-7f8yc",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/storage/raw_reconciler.py`, `duplicate/browser-capture/etc.`, `schema/behavior-bearing`, `polylogue/storage/raw_reconciler.py assume a 'planned', unresolved-outcome census plan's`."
- ]
- },
- {
- "bead_id": "polylogue-7ilr",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-7ilr",
- "targets": [
- "Exercise the implementation through these named production surfaces: `ambiguous/deferred`, `select_rebuild_raw_ids/all_index_rebuild_raw_ids/next_raw_page`, `storage/index_generation.py`, `storage/sqlite/archive_tiers/archive.py`, `polylogue ops maintenance raw-authority-frontier --apply-plan --yes`, `polylogue ops maintenance raw-authority-debt-summary`, `raw_materialization_replay_backlog`."
- ]
- },
- {
- "bead_id": "polylogue-7mgx",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-7mgx",
- "targets": [
- "Exercise the implementation through these named production surfaces: `Producer/consumer`, `archive_tiers/write.py`, `sources/live/hook_paste_enrichment.py`, `daemon/web_shell_paste.py`."
- ]
- },
- {
- "bead_id": "polylogue-7qw4",
- "class": "TestHarnessRoute",
- "contract_type": "test_harness",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-7qw4",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/storage/test_store_ops.py`, `tests/benchmarks/test_reader_api.py`, `attachment/provider`, `polylogue/storage/sqlite/queries/stats.py`, `polylogue/cli/query_stats.py`, `AG1/AG2`, `pytest-benchmark timing test with no correctness assertions (tests/benchmarks/test_reader_api.py:112).`."
- ]
- },
- {
- "bead_id": "polylogue-7rds",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-7rds",
- "targets": [
- "Exercise the implementation through these named production surfaces: `orphan/dedup`, `2026-07-12/13`, `polylogue/daemon/cli.py`, `polylogue/daemon/blob_gc_periodic.py`."
- ]
- },
- {
- "bead_id": "polylogue-7zj4t",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-7zj4t",
- "targets": [
- "Exercise the implementation through these named production surfaces: `dots/claude/settings.json`, `modules/features/dev/agents/hooks.nix`, `local/share/polylogue/hooks`, `sinnix Codex hooks.nix still bakes stale --sidecar-dir (swqu parity gap)`."
- ]
- },
- {
- "bead_id": "polylogue-80ks",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-80ks",
- "targets": [
- "Exercise the implementation through these named production surfaces: `attachments/images/audio`, `browser_capture/models.py`, `parsers/browser_capture.py`, `image/audio`."
- ]
- },
- {
- "bead_id": "polylogue-8ifs",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-8ifs",
- "targets": [
- "Exercise the implementation through these named production surfaces: `daemon/http.py`, `timeline/phases/threads`, `false/count`, `daemon/status.py`."
- ]
- },
- {
- "bead_id": "polylogue-8u1p",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-8u1p",
- "targets": [
- "Exercise the implementation through these named production surfaces: `turn/event`, `thoughts/token`, `GROUP_PROVIDERS/STREAM_RECORD_PROVIDERS`, `polylogue-hs3y's fix (dispatch.py + local_agent.py) taught detect_provider`, `.json`, `/`, `.jsonl`."
- ]
- },
- {
- "bead_id": "polylogue-8ykm",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-8ykm",
- "targets": [
- "Exercise the implementation through these named production surfaces: `archive_tiers/archive.py`, `Producer/consumer`, `storage/repository/__init__.py`, `get/list_session_latency_profile_records`."
- ]
- },
- {
- "bead_id": "polylogue-923uc",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-923uc",
- "targets": [
- "Exercise the implementation through these named production surfaces: `queries/web_content_constructs.py`, `repository/API`, `aggregate/insight`, `search_result, canvas, image_result, and additional construct types`."
- ]
- },
- {
- "bead_id": "polylogue-9hq2",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-9hq2",
- "targets": [
- "Exercise the implementation through these named production surfaces: `feature/devtools/backlog-execution-tooling`, `daemon/status.py`, `P0/P1`, `audits-2026-07-31/backlog-execution-design.html`."
- ]
- },
- {
- "bead_id": "polylogue-9kjtc",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-9kjtc",
- "targets": [
- "Exercise the implementation through these named production surfaces: `input_tokens/output_tokens`, `polylogue/archive/semantic/cost_compute.py`, `docs/cost-model.md`, `Reprice/reclassify`."
- ]
- },
- {
- "bead_id": "polylogue-a7xr.24",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-a7xr.24",
- "targets": [
- "Exercise the implementation through these named production surfaces: `.agent/scratch/dissection-ledger.md`, `stop_reason/is_active_leaf`, `INSERT/SELECT`, `storage/runtime/archive/records.py`."
- ]
- },
- {
- "bead_id": "polylogue-a7xr.25",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-a7xr.25",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tool-call/reasoning`, `custom_tool_call/_output`, `tool_use/tool_result/thinking`, `queries/session_events`."
- ]
- },
- {
- "bead_id": "polylogue-a7xr.26",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-a7xr.26",
- "targets": [
- "Exercise the implementation through these named production surfaces: `repository/__init__.py`, `ingest_batch/_core`, `cli/shared/types`, `cli/read_views/chronicle.`."
- ]
- },
- {
- "bead_id": "polylogue-adre",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-adre",
- "targets": [
- "Exercise the implementation through these named production surfaces: `Producer/consumer`, `user/009_result_set_holdouts.sql`, `user/004_user_settings.sql`, `INSERT/SELECT`."
- ]
- },
- {
- "bead_id": "polylogue-azh1l",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-azh1l",
- "targets": [
- "Exercise the implementation through these named production surfaces: `census/byte-authority`, `ds4b4/lb39z`."
- ]
- },
- {
- "bead_id": "polylogue-b4cs",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-b4cs",
- "targets": [
- "Exercise the implementation through these named production surfaces: `github.com/Sinity/polylogue.`, `.agent/handoffs/.`, `chatgpt.com/share/`, `.agent/`."
- ]
- },
- {
- "bead_id": "polylogue-b4n2",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-b4n2",
- "targets": [
- "Exercise the implementation through these named production surfaces: `rebuild/reclassification`."
- ]
- },
- {
- "bead_id": "polylogue-bfc7a",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-bfc7a",
- "targets": [
- "Exercise the implementation through these named production surfaces: `devtools/generated_surfaces.py`, `devtools: make the generated-surfaces gate total (topology-projection + visual-tapes outside GENERATED_SURFACES)`."
- ]
- },
- {
- "bead_id": "polylogue-bfwg",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-bfwg",
- "targets": [
- "Exercise the implementation through these named production surfaces: `enrichment_version/family`, `inference_version/family`, `daemon/convergence_stages.py`, `storage/insights/session/status.py`."
- ]
- },
- {
- "bead_id": "polylogue-bwo2l",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-bwo2l",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/cli/test_archive_maintenance_cli.py`, `test_live_watcher.py/test_live_batch_support.py`, `response_item/message/input_text`, `vqt48/6mpy`, `devtools test tests/unit/cli/test_archive_maintenance_cli.py`, `polylogue-9ykn: refusing session (codex, source_path= .jsonl)`."
- ]
- },
- {
- "bead_id": "polylogue-c2qsm",
- "class": "TestHarnessRoute",
- "contract_type": "test_harness",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-c2qsm",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/insights/test_cost_basis_split.py`, `tests/unit/core/test_pricing.py`, `sessions/models`, `dead/unused`, `estimate_session_cost/estimate_message_cost/compute_session_cost`, `Session/Message`."
- ]
- },
- {
- "bead_id": "polylogue-c5mb",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-c5mb",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/sources/live/tool_result_sidecars.py`, `sources/dispatch.py`, `sources/parsers/claude/code_parser.py`, `forks/resumes/auto-compaction`, `python3 -c \"`, `polylogue ops reset --index && polylogued run`."
- ]
- },
- {
- "bead_id": "polylogue-ck5v",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-ck5v",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/sources/drive/__init__.py`, `inbox/polylogue-aistudio-legacy-backfill-sha256`, `_inject_live_drive_attachment_bytes`, `iter_drive_raw_data`, `polylogue/sources/drive/__init__.py:253`."
- ]
- },
- {
- "bead_id": "polylogue-d0ew",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-d0ew",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/storage/sqlite/queries/sessions_identity.py`, `queries/sessions.py`, `facets/MCP/API`, `polylogue facets --format json`, `provider:`."
- ]
- },
- {
- "bead_id": "polylogue-d0kj",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-d0kj",
- "targets": [
- "Exercise the implementation through these named production surfaces: `docs/internals.md`, `devtools/verify_schema_upgrade_lane.py`, `storage/sqlite/archive_tiers/index_convergence.py`."
- ]
- },
- {
- "bead_id": "polylogue-d4kq",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-d4kq",
- "targets": [
- "Exercise the real production entry point for “Refusal path cannot feed claude_parse_coverage: no session-scoped sink for refused records”; direct fixture-row insertion, mocks that bypass the owning layer, and test-only helpers do not satisfy the criterion."
- ]
- },
- {
- "bead_id": "polylogue-d70d",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-d70d",
- "targets": [
- "Exercise the implementation through these named production surfaces: `daemon/fts_startup.py`, `SIGKILL-recovery/trigger-restoration`, `daemon/lineage_startup.py`, `daemon/cli.py`."
- ]
- },
- {
- "bead_id": "polylogue-dlmc1",
- "class": "LiveOperationRoute",
- "contract_type": "live_operation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-dlmc1",
- "targets": [
- "Exercise the implementation through these named production surfaces: `ops/maintenance`, `polylogue/cli/commands/maintenance/__init__.py`."
- ]
- },
- {
- "bead_id": "polylogue-e2uns",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-e2uns",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tested/used`, `devtools/X.py`, `.github/workflows/nightly-scale.yml`, `.github/workflows/mutation-testing.yml`, `python -m devtools.X`, `python devtools/X.py`, `render all --check`."
- ]
- },
- {
- "bead_id": "polylogue-e6a0",
- "class": "TestHarnessRoute",
- "contract_type": "test_harness",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-e6a0",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/devtools/test_index_v37_fast_forward.py`, `polylogue/storage/sqlite/runtime_indexes.py`, `tables/indexes/triggers`, `work_evidence_edges/nodes/graphs`, `indexes/triggers`, `devtools/index_v37_fast_forward.py computes canonical schema by executing`, `devtools/index_v37_fast_forward.py is a completed one-time migration tool`."
- ]
- },
- {
- "bead_id": "polylogue-ei0d",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-ei0d",
- "targets": [
- "Exercise the implementation through these named production surfaces: `storage/sqlite/archive_tiers/write.py`, `archive_tiers/self_verify.py`, `insights/claude_workflow_materializer.py`, `storage/sqlite/lifecycle.py`, `payload_json`, `insights/claude_workflow_materializer.py:458`, `session_events`."
- ]
- },
- {
- "bead_id": "polylogue-enrpa",
- "class": "LiveOperationRoute",
- "contract_type": "live_operation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-enrpa",
- "targets": [
- "Exercise the implementation through these named production surfaces: `rows/0`, `daemon/http.py`, `routes/modules/tables`, `V6/V7`."
- ]
- },
- {
- "bead_id": "polylogue-erf3",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-erf3",
- "targets": [
- "Exercise the real production entry point for “claude.ai export zip detects as unknown-export at the container level”; direct fixture-row insertion, mocks that bypass the owning layer, and test-only helpers do not satisfy the criterion."
- ]
- },
- {
- "bead_id": "polylogue-es7b",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-es7b",
- "targets": [
- "Exercise the implementation through these named production surfaces: `storage/embeddings/materialization.py`, `retry/backoff`, `None/unknown`, `daemon/write_coordinator.py`."
- ]
- },
- {
- "bead_id": "polylogue-ey3r",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-ey3r",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue ops maintenance verify-archive`, `source-index-coverage`, `superseded_equivalent`."
- ]
- },
- {
- "bead_id": "polylogue-f7cd",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-f7cd",
- "targets": [
- "Exercise the implementation through these named production surfaces: `archive/repo`, `feature/devtools/backlog-execution-tooling`, `design/notes`."
- ]
- },
- {
- "bead_id": "polylogue-f9kk",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-f9kk",
- "targets": [
- "Exercise the implementation through these named production surfaces: `absent/failing`, `archive/query/retrieval_search.py`, `archive/query/search_hits.py`, `api/archive.py`."
- ]
- },
- {
- "bead_id": "polylogue-fbkr",
- "class": "LiveOperationRoute",
- "contract_type": "live_operation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-fbkr",
- "targets": [
- "Exercise the implementation through these named production surfaces: `docs/daemon.md`, `byte/provenance-safe`, `polylogue/maintenance/raw_authority_reset.py`, `polylogue-hjpx/lkrc/t93b`."
- ]
- },
- {
- "bead_id": "polylogue-fe8fv",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-fe8fv",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/sources/test_claude_code_normalization_laws.py`, `eager/streaming`, `positions/active-leaf`, `streaming/eager`, `sidecar_seen/sidecar_persisted/empty_dropped_by_record_type`."
- ]
- },
- {
- "bead_id": "polylogue-fjg91",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-fjg91",
- "targets": [
- "Exercise the implementation through these named production surfaces: `devtools/benchmark_compare_nightly.py`, `.github/workflows/nightly-scale.yml`, `devtools/command_catalog.py`, `docs/devtools.md`."
- ]
- },
- {
- "bead_id": "polylogue-fjvi",
- "class": "LiveOperationRoute",
- "contract_type": "live_operation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-fjvi",
- "targets": [
- "Exercise the implementation through these named production surfaces: `docs/architecture-spine.md`, `storage/blob_gc.py`."
- ]
- },
- {
- "bead_id": "polylogue-fqnv",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-fqnv",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/core/test_schema_laws.py`, `polylogue/schemas/generation/dynamic_keys.py`, `polylogue-* fixed collapse_dynamic_keys (polylogue/schemas/generation/dynamic_keys.py:243)`."
- ]
- },
- {
- "bead_id": "polylogue-frqp",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-frqp",
- "targets": [
- "Exercise the implementation through these named production surfaces: `Producer/consumer`, `list_otlp_spans/read_otlp_span`, `insights/otlp_correlation.py`, `daemon/otlp_receiver.py`."
- ]
- },
- {
- "bead_id": "polylogue-fyyro",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-fyyro",
- "targets": [
- "Exercise the implementation through these named production surfaces: `archive_tiers/self_verify.py`, `devtools/self_verify.py`."
- ]
- },
- {
- "bead_id": "polylogue-g16g",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-g16g",
- "targets": [
- "Exercise the implementation through these named production surfaces: `audits-2026-07-31/leak-surfaces.html`."
- ]
- },
- {
- "bead_id": "polylogue-g193e",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-g193e",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/cli/test_terminal_snapshots.py`, `tests/infra/pty_cli.py`, `environment/live`, `machine/worktree`, `archive-root/config`, `stale/incidental`, `polylogue ops doctor --help`."
- ]
- },
- {
- "bead_id": "polylogue-g31s",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-g31s",
- "targets": [
- "Exercise the implementation through these named production surfaces: `Producer/consumer`, `storage/fts/drift_sampling.py`."
- ]
- },
- {
- "bead_id": "polylogue-ganm",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-ganm",
- "targets": [
- "Exercise the implementation through these named production surfaces: `feature/chore/purge-meta-machinery`, `docs/plans/topology-target.yaml`, `devtools/build_topology_projection.py`, `devtools/verify_topology.py`, `devtools/build_topology_projection.py, then only checked against itself by`, `devtools/verify_topology.py's orphan/missing/conflict checks (which need only`, `render all --check`."
- ]
- },
- {
- "bead_id": "polylogue-gb4e",
- "class": "ProcessRoute",
- "contract_type": "process",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-gb4e",
- "targets": [
- "Exercise the implementation through these named production surfaces: `module/table/tool`, `V3/R2`."
- ]
- },
- {
- "bead_id": "polylogue-gcy1",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-gcy1",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/archive/test_coverage_diagnostics.py`, `analyze_coverage/ArchiveCoverage`, `archive/coverage.py`, `status/insights`, `archive/semantic/subscription_models.py`."
- ]
- },
- {
- "bead_id": "polylogue-gmw2",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-gmw2",
- "targets": [
- "Exercise the implementation through these named production surfaces: `dedup/backoff`."
- ]
- },
- {
- "bead_id": "polylogue-gody",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-gody",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/storage/search/models.py`, `polylogue/storage/search/query_builders.py`, `polylogue/storage/search/runtime.py`, `polylogue/api/archive.py`, `polylogue/storage/search/models.py:12 -- SearchHit is a frozen dataclass with`, `polylogue/storage/search/query_builders.py:50,111 -- SQL explicitly does`, `s.origin AS source_name`."
- ]
- },
- {
- "bead_id": "polylogue-grdt",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-grdt",
- "targets": [
- "Exercise the implementation through these named production surfaces: `operations/archive_debt.py`, `storage/usage.py`, `storage/embeddings/support.py`, `storage/table_existence.py`."
- ]
- },
- {
- "bead_id": "polylogue-gvr2",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-gvr2",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/storage/sqlite/archive_tiers/index.py`, `self-standing/indexed`."
- ]
- },
- {
- "bead_id": "polylogue-gvzkr",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-gvzkr",
- "targets": [
- "Trace every table and column through storage/sqlite/archive_tiers/*.py, SELECT and read sites, dataclass and Pydantic consumers, serializers, and write sites.",
- "Cross-reference each PURGE candidate against repair and restatement owners polylogue-6kur and polylogue-4p1/a7xr.24."
- ]
- },
- {
- "bead_id": "polylogue-h2sf6",
- "class": "TestHarnessRoute",
- "contract_type": "test_harness",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-h2sf6",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/devtools/test_pytest_witness_repetitions.py`, `devtools/pytest_witness_repetitions.py`, `docs/devtools.md`, `module/tests/docs/catalog`."
- ]
- },
- {
- "bead_id": "polylogue-hgk1",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-hgk1",
- "targets": [
- "Exercise the implementation through these named production surfaces: `docs/examples/visual-tapes/browser-capture-tour.gif`, `unrun/pending`, `devtools/visual_vhs.py`, `docs/examples/visual-tapes`."
- ]
- },
- {
- "bead_id": "polylogue-hhg58",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-hhg58",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/core/test_sampling.py`, `xdist/test-order`, `iter_schema_units/_iter_schema_units_from_db`, `path/singleton`, `polylogue/schemas/sampling_db.py`."
- ]
- },
- {
- "bead_id": "polylogue-ht3n",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-ht3n",
- "targets": [
- "Exercise the implementation through these named production surfaces: `Producer/consumer`, `insights/delegation_work_evidence.py`, `materialize-incident-evidence/reconcile-work-effects`, `operations/work_effect_reconciliation.py`."
- ]
- },
- {
- "bead_id": "polylogue-hwwtq",
- "class": "LiveOperationRoute",
- "contract_type": "live_operation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-hwwtq",
- "targets": [
- "Exercise the implementation through these named production surfaces: `cli/commands/maintenance/_rebuild_index.py`, `88/113`, `run/record`, `V2/R3`."
- ]
- },
- {
- "bead_id": "polylogue-ic5i",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-ic5i",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/storage/sqlite/holdout_cohorts.py`, `polylogue/insights/fable_packet.py`, `polylogue/storage/block_anchor.py`, `repository/service`, `polylogue/storage/sqlite/holdout_cohorts.py 260 loc, 10 exports`, `polylogue/insights/fable_packet.py 306 loc, 6 exports`."
- ]
- },
- {
- "bead_id": "polylogue-ihro",
- "class": "TestHarnessRoute",
- "contract_type": "test_harness",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-ihro",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/sources/test_dispatch_payloads.py`, `origin/master`, `dispatch/identity`."
- ]
- },
- {
- "bead_id": "polylogue-iiu6r",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-iiu6r",
- "targets": [
- "Exercise the implementation through these named production surfaces: `manual/legacy`, `docs/design/convergence-simplification-inventory.md`, `polylogue/daemon/cli.py`, `raw-id/--only-missing/--max-blob-mb/--shard-count/--plan`, `polylogue ops maintenance rebuild-index`, `_maybe_route_daemon_bulk_rebuild`, `_parse_unique_retained_raws`."
- ]
- },
- {
- "bead_id": "polylogue-in94",
- "class": "ProcessRoute",
- "contract_type": "process",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-in94",
- "targets": [
- "Exercise the implementation through these named production surfaces: `model/effort`, `briefed/dispatched/committed/pushed/PR/merged/beads-closed`, `feature/devtools/lane-init`, `.cache/fanout/lanes.jsonl`."
- ]
- },
- {
- "bead_id": "polylogue-inoh",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-inoh",
- "targets": [
- "Exercise the implementation through these named production surfaces: `claude-code-session/hermes-session/grok-export/unknown-export`, `low-priority/different-shape`, `GC/retention`, `set/order/attachment`, `polylogue-hith, polylogue-nuec; all descend from polylogue-bu1i). That`, `polylogue-9dxn's general \"persisted ambiguous verdicts never get`, `parse_payload`."
- ]
- },
- {
- "bead_id": "polylogue-ioz2",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-ioz2",
- "targets": [
- "Exercise the implementation through these named production surfaces: `L19/L20`, `hygiene/observability`, `orphan/temp`, `audits-2026-07-31/leak-surfaces.html`."
- ]
- },
- {
- "bead_id": "polylogue-ioz7",
- "class": "LiveOperationRoute",
- "contract_type": "live_operation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-ioz7",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/maintenance/test_agent_meta_sidecar_purge_apply.py`, `tests/unit/storage/test_index_fast_forward_lifecycle.py/test_index_fast_forward_executor.py/test_schema_policy_contracts.py/test_archive_tiers_ddl.py`, `source_path/artifact_kind`, `feature/maintenance/agent-meta-sidecar-purge`, `polylogue/storage/agent_meta_sidecar_sweep.py`, `dry-run/--apply`, `polylogue backup --output-dir --profile full_evidence --verify`."
- ]
- },
- {
- "bead_id": "polylogue-iuyr",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-iuyr",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue-shnc/gt1z.`, `archive/semantic/cost_compute.py`, `gpt-5.6-sol/terra`, `polylogue-shnc/gt1z`."
- ]
- },
- {
- "bead_id": "polylogue-iy3n",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-iy3n",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/storage/test_repair.py`, `raw_sessions/index-tier`, `polylogue/storage/sqlite/archive_tiers/archive.py`, `repair.py/raw_authority.py/revision_application`, `raw_sessions/index.db`, `polylogue/storage/repository/**, and`, `polylogue/storage/sqlite/archive_tiers/archive.py /`."
- ]
- },
- {
- "bead_id": "polylogue-j1vs",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-j1vs",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/surfaces/projection_spec.py`, `polylogue/cli/query_verbs.py`, `polylogue/cli/query_contracts.py`, `read_views/base.py`, `destination: str`, `RenderFormat.`."
- ]
- },
- {
- "bead_id": "polylogue-j7sin",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-j7sin",
- "targets": [
- "Exercise the implementation through these named production surfaces: `daemon/status_snapshot.py`, `raw_parse_failures/raw_validation_failures/raw_quarantined/raw_maintenance_failures/raw_detection_warnings`."
- ]
- },
- {
- "bead_id": "polylogue-j8yo",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-j8yo",
- "targets": [
- "Exercise the implementation through these named production surfaces: `fetch/XHR`, `aistudio.google.com/prompts/1cVKebxYa9oOCM05J3BqQQizFzIgfjvyH`, `rpc/google.internal.alkali.applications.makersuite.v1`, `application/json`, `drive.googleapis.com`, `application/json+protobuf`."
- ]
- },
- {
- "bead_id": "polylogue-jglh",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-jglh",
- "targets": [
- "Exercise the implementation through these named production surfaces: `audit/census.py`, `archive/viewport/enums.py`, `core/enums.py`, `insights/transforms.py`."
- ]
- },
- {
- "bead_id": "polylogue-jtek",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-jtek",
- "targets": [
- "Exercise the real production entry point for “rebuild perf: overlap the up-front census classification pass with replay”; direct fixture-row insertion, mocks that bypass the owning layer, and test-only helpers do not satisfy the criterion."
- ]
- },
- {
- "bead_id": "polylogue-jwqj",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-jwqj",
- "targets": [
- "Exercise the implementation through these named production surfaces: `RUN_STATE/HIGHLIGHT/PROMPT_EVAL`, `BLOCKER/HANDOFF`, `Producer/consumer`, `writer/reader`."
- ]
- },
- {
- "bead_id": "polylogue-kbsy5",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-kbsy5",
- "targets": [
- "Exercise the implementation through these named production surfaces: `clear/visible`, `config/UI`, `session/subagent`, `operator/coordinator`."
- ]
- },
- {
- "bead_id": "polylogue-kc26",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-kc26",
- "targets": [
- "Exercise the implementation through these named production surfaces: `.beads/issues.jsonl`, `audits-2026-07-31/leak-surfaces.html`."
- ]
- },
- {
- "bead_id": "polylogue-kcdg",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-kcdg",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/cli/read_view_handlers.py`, `polylogue/cli/read_views/standard.py`, `polylogue/cli/query_verbs.py`, `rename/removal`."
- ]
- },
- {
- "bead_id": "polylogue-kea7p",
- "class": "DecisionRoute",
- "contract_type": "decision",
- "dispatch": "decision",
- "identifier": "acceptance/polylogue-kea7p",
- "targets": [
- "Exercise the implementation through these named production surfaces: `fingerprint/hash/backfill`, `sessions/messages`, `pipeline/services/ingest_batch/_core.py`, `origins/surfaces`."
- ]
- },
- {
- "bead_id": "polylogue-knc7",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-knc7",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/cost/plans.py`, `she-llac.com/claude-limits`, `archive/semantic/subscription_pricing.py`, `10/50`, `polylogue/cost/plans.py models only a MONTHLY quota (SubscriptionPlan has quota, quota_basis, billing_cycle_days, cycle_anchor_day). It has NO session-window or weekly field. The two limits that actually bind in practice are therefore unmodelled.`."
- ]
- },
- {
- "bead_id": "polylogue-lbk1",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-lbk1",
- "targets": [
- "Exercise the implementation through these named production surfaces: `result_sets/query_runs.exactness`, `Literal/enum`, `archive_tiers/user.py`, `core/enums.py`, `assertions.status`, `nullable_check(\"status\", AssertionStatus)`, `query_edges.edge_kind`."
- ]
- },
- {
- "bead_id": "polylogue-lk2w",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-lk2w",
- "targets": [
- "Exercise the implementation through these named production surfaces: `daemon-web/api`, `daemon-http/web`, `archive/query/production_evaluator.py`, `operations/route_observation.py`."
- ]
- },
- {
- "bead_id": "polylogue-lm62x",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-lm62x",
- "targets": [
- "Exercise the implementation through these named production surfaces: `call/request`, `storage/sqlite/archive_tiers/ops.py`, `polylogue/archive/query/production_evaluator.py`, `CLI/MCP`."
- ]
- },
- {
- "bead_id": "polylogue-lqhi7",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-lqhi7",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/daemon/health.py`, `daemon/cli.py`."
- ]
- },
- {
- "bead_id": "polylogue-lzank",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-lzank",
- "targets": [
- "Exercise the implementation through these named production surfaces: `Merge/retire`, `devtools/bead_batch_show.py`, `id/status/prio/title`, `truncation/formatting`, `devtools/bead_batch_show.py (49 lines) is a subprocess wrapper that calls 'bd show --json' once per argument and reformats to id/status/prio/title + truncated (280-char) desc + deps + truncated (240-char) notes tail.`."
- ]
- },
- {
- "bead_id": "polylogue-m1s98",
- "class": "ProcessRoute",
- "contract_type": "process",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-m1s98",
- "targets": [
- "Exercise the implementation through these named production surfaces: `total/match`."
- ]
- },
- {
- "bead_id": "polylogue-m69yv",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-m69yv",
- "targets": [
- "Exercise the implementation through these named production surfaces: `dumps/2026-01-01_02-58-23_ChatGPT_I._Mathematical_formalization_of_a_system.md`."
- ]
- },
- {
- "bead_id": "polylogue-m8nj",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-m8nj",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/storage/test_delegations_view.py`, `tests/unit/pipeline/test_delegation_provider_fixtures.py`, `instruction_payload/artifact_text`, `polylogue/storage/sqlite/delegation_facts.py`, `tool_input/output_text`, `bo9n/v6i3`."
- ]
- },
- {
- "bead_id": "polylogue-mgf6",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-mgf6",
- "targets": [
- "Exercise the implementation through these named production surfaces: `temperature/topP`, `thinkingLevel/safetySettings/enable`, `polylogue-2qx.4/cgfy`, `archive/query/expression.py`, `COUNT_FIELD COMP_OP INT`, `f\"{table_alias}.{column}\"`, `json_extract(run_settings_json, '$.temperature')`."
- ]
- },
- {
- "bead_id": "polylogue-mia3",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-mia3",
- "targets": [
- "Exercise the implementation through these named production surfaces: `pipeline/services/ingest_batch/_core.py`."
- ]
- },
- {
- "bead_id": "polylogue-mkk0",
- "class": "LiveOperationRoute",
- "contract_type": "live_operation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-mkk0",
- "targets": [
- "Exercise the implementation through these named production surfaces: `daemon/cli.py`, `before/after`, `flag/path`, `session/message/block/session_links`, `polylogue ops maintenance rebuild-index`, `rebuild-index`, `ops maintenance rebuild-index`."
- ]
- },
- {
- "bead_id": "polylogue-mlqrt",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-mlqrt",
- "targets": [
- "Exercise the implementation through these named production surfaces: `how/whether`."
- ]
- },
- {
- "bead_id": "polylogue-mnds",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-mnds",
- "targets": [
- "Exercise the real production entry point for “Blob store residue: 1,590 orphan blobs (1.49GB) + 52 stale .blob.* temp files (66MB), all pre-2026-07-19”; direct fixture-row insertion, mocks that bypass the owning layer, and test-only helpers do not satisfy the criterion."
- ]
- },
- {
- "bead_id": "polylogue-mznm",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-mznm",
- "targets": [
- "Exercise the implementation through these named production surfaces: `daemon/cli.py`, `product/raw_authority.py`, `storage/repair.py`, `CLI/HTTP`."
- ]
- },
- {
- "bead_id": "polylogue-mzp8",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-mzp8",
- "targets": [
- "Exercise the implementation through these named production surfaces: `stale/missing`, `polylogue/maintenance/invalidation.py`, `polylogue/maintenance/preview.py`, `polylogue/archive/semantic/pricing.py`."
- ]
- },
- {
- "bead_id": "polylogue-n8ft",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-n8ft",
- "targets": [
- "Exercise the implementation through these named production surfaces: `repos/repo_checkouts`, `Producer/consumer`, `storage/insights/session/repo_observations.py`, `archive_tiers/write.py`."
- ]
- },
- {
- "bead_id": "polylogue-nfl5",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-nfl5",
- "targets": [
- "Exercise the implementation through these named production surfaces: `SUPERSEDED/receipted`, `message/event/attachment`, `take/keep`, `capture/export`."
- ]
- },
- {
- "bead_id": "polylogue-nqx2",
- "class": "TestHarnessRoute",
- "contract_type": "test_harness",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-nqx2",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/core/test_message_types.py`, `polylogue/archive/message/artifacts.py`, `cost/user-word`, `2/3/4`, `5/6`, `devtools test tests/unit/core/test_message_types.py -k`, `if False:`."
- ]
- },
- {
- "bead_id": "polylogue-nvqb",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-nvqb",
- "targets": [
- "Exercise the implementation through these named production surfaces: `Watchdog/telemetry`, `daemon/cli.py`, `storage/fts/drift_sampling.py`, `daemon/otlp_receiver.py`."
- ]
- },
- {
- "bead_id": "polylogue-o2jin",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-o2jin",
- "targets": [
- "Exercise the implementation through these named production surfaces: `cli/commands/maintenance/_shared.py`, `mcp/server_cutover.py`, `since/until`."
- ]
- },
- {
- "bead_id": "polylogue-o56w",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-o56w",
- "targets": [
- "Exercise the implementation through these named production surfaces: `index-rebuild-transactions/857984cb-b4cc-4537-b0fb-eae89ca3fa96.receipts/pass-000000.json`, `revision-chain/membership/quarantine`, `pragma/batching`."
- ]
- },
- {
- "bead_id": "polylogue-ofry",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-ofry",
- "targets": [
- "Exercise the implementation through these named production surfaces: `Producer/consumer`, `pipeline/services/ingest_batch/_core.py`, `try/except.`, `env/config`."
- ]
- },
- {
- "bead_id": "polylogue-oj4oo",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-oj4oo",
- "targets": [
- "Exercise the implementation through these named production surfaces: `run/attempt/operation`, `storage/sqlite/archive_tiers/ops.py`, `cli/commands/embed.py`, `polylogue/maintenance/planner.py`."
- ]
- },
- {
- "bead_id": "polylogue-om8dh",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-om8dh",
- "targets": [
- "Exercise the implementation through these named production surfaces: `sites/migration`, `polylogue-lm62x/z22ml/oj4oo/h57ic/3szyi`."
- ]
- },
- {
- "bead_id": "polylogue-oou3c",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-oou3c",
- "targets": [
- "Exercise the implementation through these named production surfaces: `production/diagnostic`, `M4/R5`, `cli/commands/maintenance/_run.py`, `apply/dry-run`."
- ]
- },
- {
- "bead_id": "polylogue-oqib",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-oqib",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/core/test_filters_props.py`, `archive/query/plan.py`, `archive/filter/builder.py`, `archive/query/fields.py`, `archive/query/expression.py`, `sessions.parent_session_id`, `Session.is_root`."
- ]
- },
- {
- "bead_id": "polylogue-oxrv",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-oxrv",
- "targets": [
- "Exercise the implementation through these named production surfaces: `read_views/standard.py`, `live/running-daemon`."
- ]
- },
- {
- "bead_id": "polylogue-p21v",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-p21v",
- "targets": [
- "Exercise the implementation through these named production surfaces: `origin/master.`, `daemon/metrics.py`, `dashboard/alerting`, `polylogue_embedding_catchup_sessions{state=\"planned\"}`, `polylogue_embedding_catchup_sessions{state=\"processed\"}`."
- ]
- },
- {
- "bead_id": "polylogue-p6rz",
- "class": "TestHarnessRoute",
- "contract_type": "test_harness",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-p6rz",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/cli/test_color_and_layout.py`, `tests/unit/storage/test_durable_migrations.py`, `polylogue/cli/shared/formatting.py`, `Signature/test`, `cost/usage`, `devtools verify --all (first full run in a while on this branch) surfaced ~30-40 test`, `return no_color`."
- ]
- },
- {
- "bead_id": "polylogue-pfdf",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-pfdf",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/storage/test_attachment_reacquisition.py`, `com/Sinity/polylogue/pull/3590`, `feature/storage/attachment-reacquisition-backfill`, `polylogue/storage/attachment_reacquisition.py`, `session/message`, `polylogue/storage/attachment_reacquisition.py, mirroring attachment_relink.py (ref-linkage backfill, same real-ingest_record-reparse pattern) and blob_integrity.py's raw actuators:`, `devtools workspace attachment-reacquisition`."
- ]
- },
- {
- "bead_id": "polylogue-pkst",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-pkst",
- "targets": [
- "Exercise the implementation through these named production surfaces: `unresolved/resolved/repaired/quarantined`, `core/enums.py`, `storage/sqlite/archive_tiers/index.py`, `storage/sqlite/queries/session_links.py`."
- ]
- },
- {
- "bead_id": "polylogue-px4h",
- "class": "LiveOperationRoute",
- "contract_type": "live_operation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-px4h",
- "targets": [
- "Exercise the implementation through these named production surfaces: `reserved_at_ms/1000`, `storage/blob_publication.py`."
- ]
- },
- {
- "bead_id": "polylogue-pzxm",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-pzxm",
- "targets": [
- "Exercise the implementation through these named production surfaces: `storage/sqlite/connection_profile.py`, `threads/processes`, `FTS/trigram/action_pairs`, `apply/K`."
- ]
- },
- {
- "bead_id": "polylogue-q1at",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-q1at",
- "targets": [
- "Exercise the implementation through these named production surfaces: `CLI/HTTP`, `capability/policy`, `old/disabled`, `None/False.`."
- ]
- },
- {
- "bead_id": "polylogue-q9hl",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-q9hl",
- "targets": [
- "Exercise the implementation through these named production surfaces: `storage/fts/sql.py`, `set/clear`, `501/792`, `2206/2268`."
- ]
- },
- {
- "bead_id": "polylogue-qj5x",
- "class": "DecisionRoute",
- "contract_type": "decision",
- "dispatch": "decision",
- "identifier": "acceptance/polylogue-qj5x",
- "targets": [
- "Exercise the implementation through these named production surfaces: `.agent/scratch/live/beads-handling-design-2026-07-31.html`, `249/2`, `descriptions/design/AC`, `insights/work_effects.py`."
- ]
- },
- {
- "bead_id": "polylogue-ql2fb",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-ql2fb",
- "targets": [
- "Exercise the real production entry point for “cursor_lag_samples producer never runs under default health_check_tiers=fast”; direct fixture-row insertion, mocks that bypass the owning layer, and test-only helpers do not satisfy the criterion."
- ]
- },
- {
- "bead_id": "polylogue-qqi1",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-qqi1",
- "targets": [
- "Exercise the real production entry point for “read --view summary silently falls through to transcript”; direct fixture-row insertion, mocks that bypass the owning layer, and test-only helpers do not satisfy the criterion."
- ]
- },
- {
- "bead_id": "polylogue-qut1",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-qut1",
- "targets": [
- "Exercise the implementation through these named production surfaces: `audits-2026-07-31/leak-surfaces.html`."
- ]
- },
- {
- "bead_id": "polylogue-qwgi",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-qwgi",
- "targets": [
- "Exercise the implementation through these named production surfaces: `read/summary`, `profile/usage-table`, `0.0/unknown`, `cost/usage`, `read --json`."
- ]
- },
- {
- "bead_id": "polylogue-rpuqn",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-rpuqn",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/daemon/cli.py`, `docs/design/convergence-simplification-inventory.md`, `trickle/CLI-built`, `.beads/issues.jsonl`."
- ]
- },
- {
- "bead_id": "polylogue-rsz1",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-rsz1",
- "targets": [
- "Exercise the implementation through these named production surfaces: `FTS/status`, `1/1`, `origin/master`, `planned/processed`."
- ]
- },
- {
- "bead_id": "polylogue-rxfo",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-rxfo",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/core/test_hashing.py`, `tests/unit/pipeline/test_pipeline_ids.py`, `parse_sources/ingest_sources`, `polylogue/pipeline/services/parsing.py`, `_resolve_session_graph/_prefix_sharing_edge_sync`."
- ]
- },
- {
- "bead_id": "polylogue-s9irb",
- "class": "LiveOperationRoute",
- "contract_type": "live_operation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-s9irb",
- "targets": [
- "Exercise the implementation through these named production surfaces: `devtools/index_fast_forward.py`, `devtools/index_v37_fast_forward.py`, `devtools/archive_schema_fast_forward.py`, `v32/v35/v36`."
- ]
- },
- {
- "bead_id": "polylogue-sg80",
- "class": "TestHarnessRoute",
- "contract_type": "test_harness",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-sg80",
- "targets": [
- "Exercise the real production entry point for “Semantic-frontier quarantine refinement: byte-proof actuator cannot resolve semantically-accepted raws”; direct fixture-row insertion, mocks that bypass the owning layer, and test-only helpers do not satisfy the criterion."
- ]
- },
- {
- "bead_id": "polylogue-sgdp",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-sgdp",
- "targets": [
- "Exercise the implementation through these named production surfaces: `origin/master`."
- ]
- },
- {
- "bead_id": "polylogue-shnc",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-shnc",
- "targets": [
- "Exercise the implementation through these named production surfaces: `cost/catalog`, `417/3`, `unpriced/contradictory`."
- ]
- },
- {
- "bead_id": "polylogue-siet",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-siet",
- "targets": [
- "Exercise the implementation through these named production surfaces: `storage/archive_identity.py`, `devtools/campaign_archive_location.py`, `maintenance/rebuild_index.py`, `storage/index_generation.py`, `devtools/campaign_archive_location.py:70 and maintenance/rebuild_index.py:459.`, `polylogue mark id:X --star`, `delete --yes`."
- ]
- },
- {
- "bead_id": "polylogue-sr6u",
- "class": "AuditRoute",
- "contract_type": "audit",
- "dispatch": "read-only",
- "identifier": "acceptance/polylogue-sr6u",
- "targets": [
- "Exercise the implementation through these named production surfaces: `watch/baseline/retained-run`, `Producer/consumer`, `CLI/MCP`, `daemon/convergence_standing_queries.py`."
- ]
- },
- {
- "bead_id": "polylogue-sze30",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-sze30",
- "targets": [
- "Exercise the real production entry point for “RETIRED_FULL_REVISION_GOVERNANCE_DETAILS: durable state keyed on a prose sentence, not an enum code”; direct fixture-row insertion, mocks that bypass the owning layer, and test-only helpers do not satisfy the criterion."
- ]
- },
- {
- "bead_id": "polylogue-t73c2",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-t73c2",
- "targets": [
- "Exercise the implementation through these named production surfaces: `session/subagent`, `reindex/daemon-restart`."
- ]
- },
- {
- "bead_id": "polylogue-t83q",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-t83q",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/archive/semantic/subscription_pricing.py`, `docs/cost-model.md`, `10/50`, `6/30`."
- ]
- },
- {
- "bead_id": "polylogue-tas4",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-tas4",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/daemon/fts_startup.py`, `readiness/repair`, `daemon/convergence_stages.py`."
- ]
- },
- {
- "bead_id": "polylogue-tf8p",
- "class": "DocumentationRoute",
- "contract_type": "documentation",
- "dispatch": "documentation",
- "identifier": "acceptance/polylogue-tf8p",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/infra/mcp.py`, `resources/prompts`, `docs/cli-reference.md`, `root/judge/ops/ops`, `doctor/ops`, `h, --help`."
- ]
- },
- {
- "bead_id": "polylogue-trjb",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-trjb",
- "targets": [
- "Exercise the implementation through these named production surfaces: `STALE/PARTIAL/LIVE`, `feature/devtools/bead-landing-check`, `hashes/PR`, `deferred/xfail/not`, `polylogue-4fm3 (consumer check inconclusive on a non-Python change),`, `polylogue-6pii (consumer check found no grep-visible caller despite a`, `devtools workspace bead-landing-check`."
- ]
- },
- {
- "bead_id": "polylogue-tztk",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-tztk",
- "targets": [
- "Exercise the implementation through these named production surfaces: `L13/L14/L15`, `type/loc`, `audits-2026-07-31/leak-surfaces.html`."
- ]
- },
- {
- "bead_id": "polylogue-u8x7",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-u8x7",
- "targets": [
- "Exercise the implementation through these named production surfaces: `web_content_constructs/file_edits`, `messages/blocks`, `polylogue/storage/sqlite/archive_tiers/write.py`, `_write_web_constructs/_write_file_edits`, `polylogue/storage/sqlite/archive_tiers/write.py).`, `polylogue/storage/sqlite/archive_tiers/write.py.`."
- ]
- },
- {
- "bead_id": "polylogue-ubdxf",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-ubdxf",
- "targets": [
- "Exercise the implementation through these named production surfaces: `1GB/day`, `census_plans/post_plans`, `plan/post-plan`, `whether/where`."
- ]
- },
- {
- "bead_id": "polylogue-ubwg",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-ubwg",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/pipeline/ids.py`, `message_identity_hash/attachment_identity_hash/event_base_identity_hash/event_canonical_identity_hash`, `docs/plans/hash-boundary-registry.yaml`, `hashlib/core.hashing`."
- ]
- },
- {
- "bead_id": "polylogue-uhjv",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-uhjv",
- "targets": [
- "Exercise the implementation through these named production surfaces: `migrations/user/009_result_set_holdouts.sql`, `archive_tiers/user.py`."
- ]
- },
- {
- "bead_id": "polylogue-ujitw",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-ujitw",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/core/test_synthetic_semantics.py`, `tests/unit/core/test_synthetic_semantic_wiring.py`, `synthetic/test`, `devtools/schemas`, `polylogue/schemas/synthetic/`, `polylogue-h7y0j.`, `*.md.metadata.json`."
- ]
- },
- {
- "bead_id": "polylogue-upbv",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-upbv",
- "targets": [
- "Exercise the implementation through these named production surfaces: `ledger/UI`, `popup/badge`, `cheap/idempotent`, `log/state`."
- ]
- },
- {
- "bead_id": "polylogue-ut3r",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-ut3r",
- "targets": [
- "Exercise the implementation through these named production surfaces: `docs/security.md`, `claude/codex`, `audits-2026-07-31/leak-surfaces.html`."
- ]
- },
- {
- "bead_id": "polylogue-uxrim",
- "class": "TestHarnessRoute",
- "contract_type": "test_harness",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-uxrim",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/api/test_facade_contracts.py`, `tests/infra/frozen_clock.py`, `parsed_at=datetime.now(UTC).isoformat()`."
- ]
- },
- {
- "bead_id": "polylogue-uyci",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-uyci",
- "targets": [
- "Exercise the implementation through these named production surfaces: `sessions.display_name/run_settings_json`, `feature/chore/promote-schemas-and-wire-gates`, `CLI/MCP/API`, `polylogue/storage/runtime/archive/records.py`, `display_name`, `read --view`."
- ]
- },
- {
- "bead_id": "polylogue-v6xh",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-v6xh",
- "targets": [
- "Exercise the implementation through these named production surfaces: `health_convergence_debt/health_cursor_lag`, `daemon/notifications.py`, `polylogue/config.py`."
- ]
- },
- {
- "bead_id": "polylogue-v73m",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-v73m",
- "targets": [
- "Exercise the implementation through these named production surfaces: `L7/L9`, `audits-2026-07-31/leak-surfaces.html`."
- ]
- },
- {
- "bead_id": "polylogue-vid0",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-vid0",
- "targets": [
- "Exercise the real production entry point for “1,413 unresolved subagent links; 58 of 85 distinct targets already acquired as raws but never parsed”; direct fixture-row insertion, mocks that bypass the owning layer, and test-only helpers do not satisfy the criterion."
- ]
- },
- {
- "bead_id": "polylogue-vp2ky",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-vp2ky",
- "targets": [
- "Exercise the real production entry point for “classify_raw_revision_cohort's check_source_path_identity_split boolean is a missing function split”; direct fixture-row insertion, mocks that bypass the owning layer, and test-only helpers do not satisfy the criterion."
- ]
- },
- {
- "bead_id": "polylogue-vp9d",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-vp9d",
- "targets": [
- "Exercise the implementation through these named production surfaces: `1/4`, `parse/ingest`, `1/7`, `py-spy/faulthandler`, `ingest_chunk`, `_periodic_raw_materialization_convergence`, `_browser_capture_spool_has_pending_files()`."
- ]
- },
- {
- "bead_id": "polylogue-vqt48",
- "class": "ProcessRoute",
- "contract_type": "process",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-vqt48",
- "targets": [
- "Exercise the implementation through these named production surfaces: `test_live_watcher.py/test_live_batch_support.py`."
- ]
- },
- {
- "bead_id": "polylogue-vs5x",
- "class": "TestHarnessRoute",
- "contract_type": "test_harness",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-vs5x",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/infra/clock_guard.py`, `tests/infra`, `pytest has already imported the test module. A clock read at module level`, `test-clock-allowlist.yaml`, `frozen_clock`."
- ]
- },
- {
- "bead_id": "polylogue-vwdj",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-vwdj",
- "targets": [
- "Exercise the implementation through these named production surfaces: `docs/plans/layering.yaml`, `devtools/verify_layering.py`, `polylogue/storage/sqlite/archive_tiers`, `annotations/write.py`, `devtools/verify_layering.py:243-286 (_mutation_calls / _mutation_sql /`."
- ]
- },
- {
- "bead_id": "polylogue-w96f",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-w96f",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/storage/test_query_objects.py`, `tests/unit/daemon/test_standing_queries.py`, `storage/sqlite/query_objects.py`, `daemon/convergence_standing_queries.py`, `CLI/MCP/insights/api`, `staleness/provenance`."
- ]
- },
- {
- "bead_id": "polylogue-wbuf",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-wbuf",
- "targets": [
- "Exercise the implementation through these named production surfaces: `storage/embeddings/progress.py`, `daemon/metrics.py`."
- ]
- },
- {
- "bead_id": "polylogue-wf8a",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-wf8a",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/daemon/test_raw_materialization_parse_stage_equivalence.py`, `polylogue/daemon/parse_prefetch.py`, `watcher/catch-up`, `flag-on/off`, `feature/feat/watcher-parallel-parse-stage`."
- ]
- },
- {
- "bead_id": "polylogue-x1gd",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-x1gd",
- "targets": [
- "Exercise the implementation through these named production surfaces: `polylogue/sources/live/tool_result_sidecars.py`, `storage/sqlite/lifecycle.py`, `double/triple/N-counted`, `min/max`, `polylogue ops reset --index && polylogued run`."
- ]
- },
- {
- "bead_id": "polylogue-xecca",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-xecca",
- "targets": [
- "Exercise the implementation through these named production surfaces: `thread/process`, `M6/R4`, `ingest_batch/_core.py`, `Prereq/context`."
- ]
- },
- {
- "bead_id": "polylogue-xla90",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-xla90",
- "targets": [
- "Exercise the implementation through these named production surfaces: `ArchiveStore.write_parsed/SessionRepository.save_parsed_session`, `pipeline/services/ingest_batch/_core.py`."
- ]
- },
- {
- "bead_id": "polylogue-y0ven",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-y0ven",
- "targets": [
- "Exercise the implementation through these named production surfaces: `lag/stuck-files/percentiles/severity`, `DB/blob`, `cursor/stale`."
- ]
- },
- {
- "bead_id": "polylogue-y9106",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-y9106",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/core/test_sampling.py`, `1/2`, `fixture/db`, `codex/sessions`, `polylogue/schemas/sampling_db.py`, `devtools test tests/unit/core/test_sampling.py -k \\`, `polylogue.schemas.sampling.build_raw_payload_envelope to always raise ValueError,`."
- ]
- },
- {
- "bead_id": "polylogue-yhgc",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-yhgc",
- "targets": [
- "Exercise the implementation through these named production surfaces: `storage/sqlite/archive_tiers/write.py`, `api/archive.py`, `archive/query/archive_execution.py`."
- ]
- },
- {
- "bead_id": "polylogue-yl8t",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-yl8t",
- "targets": [
- "Exercise the implementation through these named production surfaces: `tests/unit/sources/test_claude_code_normalization_laws.py`, `streaming/eager`, `origin/master`, `sidecar_seen/empty_drop`, `re-deriving/re-ordering`."
- ]
- },
- {
- "bead_id": "polylogue-ymqp",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-ymqp",
- "targets": [
- "Exercise the implementation through these named production surfaces: `local/share/polylogue`, `storage/index_generation.py`, `failed/abandoned`."
- ]
- },
- {
- "bead_id": "polylogue-z1rdw",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-z1rdw",
- "targets": [
- "Exercise the implementation through these named production surfaces: `thread_goal_updated/sub_agent_activity/task_started/task_complete/turn_aborted/thread_settings_applied/collab_`, `producer/consumer`, `sources/parsers/codex.py`, `response_item/event_msg`, `_CODEX_KNOWN_RESPONSE_ITEM_TYPES`, `agent_reasoning`, `_compact_response_payload`."
- ]
- },
- {
- "bead_id": "polylogue-z3sv",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-z3sv",
- "targets": [
- "Exercise the implementation through these named production surfaces: `core/timestamps.py`, `naive/aware`, `sinex/material_adapter.py`, `archive/query/source_freshness.py`."
- ]
- },
- {
- "bead_id": "polylogue-zahj",
- "class": "DecisionRoute",
- "contract_type": "decision",
- "dispatch": "decision",
- "identifier": "acceptance/polylogue-zahj",
- "targets": [
- "Exercise the implementation through these named production surfaces: `raw_sessions/blob_refs/index.db`, `the `blob/a8/` content-addressed directory shard`, `the `blob/ba/` content-addressed directory shard`, `69GB/100K-object`, `polylogue ops maintenance blob-publications --abandon f1c44ec2-4250-4f12-87d3-97412cd08144 --abandon 0d21f742-779e-49e3-b96f-c8f1abeecc59 --yes`."
- ]
- },
- {
- "bead_id": "polylogue-zdtqj",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-zdtqj",
- "targets": [
- "Exercise the implementation through these named production surfaces: `True/False`, `crash-safe/re-derivable`."
- ]
- },
- {
- "bead_id": "polylogue-zn1k",
- "class": "ProcessRoute",
- "contract_type": "process",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-zn1k",
- "targets": [
- "Exercise the implementation through these named production surfaces: `reparse/purge`."
- ]
- },
- {
- "bead_id": "polylogue-zocm",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-zocm",
- "targets": [
- "Exercise the implementation through these named production surfaces: `group.results/items/search_results/sources`, `feature/parsers/chatgpt-april-content-types-and-web-constructs`, `content_references/citations`, `codex/claude`."
- ]
- },
- {
- "bead_id": "polylogue-zok3",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-zok3",
- "targets": [
- "Exercise the implementation through these named production surfaces: `origin/master.`, `format/--to`."
- ]
- },
- {
- "bead_id": "polylogue-zqph",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-zqph",
- "targets": [
- "Exercise the implementation through these named production surfaces: `replay/rebuild`, `reclassification/removal`, `Code/Codex`, `tracked/repaired`, `polylogue check --cleanup`."
- ]
- },
- {
- "bead_id": "polylogue-zwyc",
- "class": "ImplementationRoute",
- "contract_type": "implementation",
- "dispatch": "production",
- "identifier": "acceptance/polylogue-zwyc",
- "targets": [
- "Exercise the implementation through these named production surfaces: `stop_reason/tool_result_outcome_unknown_reason`, `storage/hydrators.py`, `MCP/CLI/API`, `PR/commit`, `polylogue/archive/query/archive_execution.py::_message_to_domain and`, `polylogue/api/archive.py::_archive_message_to_domain build Message.blocks`, `stop_reason: str | None = None`."
- ]
- }
- ],
- "schema_version": 1
-}
diff --git a/docs/plans/campaign-coverage.yaml b/docs/plans/campaign-coverage.yaml
deleted file mode 100644
index 2e64f3e2d5..0000000000
--- a/docs/plans/campaign-coverage.yaml
+++ /dev/null
@@ -1,318 +0,0 @@
-# Campaign-coverage manifest.
-#
-# Documents active mutation and benchmark campaigns, their paths,
-# and their coverage targets. Consumed by devtools bench mutation
-# and devtools bench campaign.
-#
-# Each mutation_campaigns entry may carry:
-# freshness_days — Only declare per-entry when overriding the default.
-# `devtools verify manifests` treats a declared freshness_days as
-# a *hard* claim of a recent matching artifact, while
-# verify-mutation-freshness uses a 60-day default budget
-# as a soft warning when the entry omits freshness_days.
-# artifact_glob — glob (relative to repo root) where run artifacts land.
-# Defaults to .local/mutation-campaigns//*.json when
-# unset. Resolved by mutmut_campaign.default_artifact_paths
-# and the freshness lint.
-# min_kill_rate — per-entry kill-rate floor (0..1) enforced by
-# verify-mutation-freshness --enforce-kill-rate against a
-# fresh campaign's latest artifact. Overrides the top-level
-# default_min_kill_rate below. Ratchet up as real run data
-# accrues; only fresh campaigns (with a recent artifact) are
-# checked, so the gate never fails on a campaign that simply
-# has not been run.
-#
-# Updated 2026-06-09 — kill-rate threshold enforcement wired for #1733.
-
-description: Mutation and benchmark campaign registry with covered paths, test targets, and freshness budgets.
-
-# Conservative floor applied to every active campaign unless its entry overrides
-# it with min_kill_rate. Enforced by the weekly mutation CI job (#1733).
-default_min_kill_rate: 0.5
-
-mutation_campaigns:
- - name: cli-query
- description: >
- Query command planning, action routing, and summary output contracts
- paths_to_mutate:
- - polylogue/cli/query.py
- - polylogue/archive/query/plan.py
- - polylogue/cli/query_actions.py
- - polylogue/cli/query_output.py
- tests:
- - tests/unit/cli/test_query_verbs_runtime.py
- - tests/unit/cli/test_query_exec_laws.py
- - tests/unit/cli/test_query_fmt.py
- status: active
-
- - name: drive-client
- description: >
- Drive auth, transport, JSON payload parsing, and ingest attachment contracts
- paths_to_mutate:
- - polylogue/sources/drive/source.py
- - polylogue/sources/drive/gateway.py
- - polylogue/sources/drive/auth.py
- - polylogue/sources/drive/__init__.py
- tests:
- - tests/unit/sources/test_drive_source_client.py
- - tests/unit/sources/test_drive_gateway.py
- - tests/unit/sources/test_drive_auth.py
- - tests/unit/sources/test_drive_ops.py
- status: active
-
- - name: filters
- description: >
- SessionFilter semantics and summary/picker contracts
- paths_to_mutate:
- - polylogue/archive/filter/filters.py
- tests:
- - tests/unit/core/test_filters_props.py
- status: active
-
- - name: hybrid
- description: >
- Reciprocal Rank Fusion — the shared ranking primitive production hybrid
- retrieval composes directly (polylogue-a7xr.10 removed the unproven
- FTS5Provider/HybridSearchProvider classes and their fts5/hybrid
- campaigns; only reciprocal_rank_fusion in hybrid.py remains).
- paths_to_mutate:
- - polylogue/storage/search_providers/hybrid.py
- tests:
- - tests/unit/core/test_filters_props.py
- - tests/unit/archive/test_query_search_runtime.py
- status: active
-
- - name: json
- description: >
- JSON serialization and parser laws
- paths_to_mutate:
- - polylogue/core/json.py
- tests:
- - tests/unit/core/test_json.py
- status: active
-
- - name: models
- description: >
- Message/Session semantic helpers and pairing logic
- paths_to_mutate:
- - polylogue/archive/models.py
- tests:
- - tests/unit/core/test_models.py
- - tests/unit/core/test_message_laws.py
- - tests/unit/core/test_session_semantics.py
- status: active
-
- - name: pipeline-services
- description: >
- Acquire/validate/parse planning and stage contracts
- paths_to_mutate:
- - polylogue/pipeline/services
- tests:
- - tests/unit/pipeline/test_acquisition_streams.py
- - tests/unit/pipeline/test_parsing_service.py
- - tests/unit/pipeline/test_indexing.py
- - tests/unit/pipeline/test_ingest_batch.py
- - tests/unit/pipeline/test_stage_independence.py
- - tests/unit/pipeline/test_resilience.py
- status: active
-
- - name: provider-parsers
- description: >
- Provider parser semantic correctness where message extraction and compaction detection live
- paths_to_mutate:
- - polylogue/sources/parsers/chatgpt.py
- - polylogue/sources/parsers/claude/code_parser.py
- - polylogue/sources/parsers/codex.py
- - polylogue/sources/parsers/claude/index.py
- - polylogue/pipeline/semantic_capture.py
- tests:
- - tests/unit/sources/test_parsers_chatgpt.py
- - tests/unit/sources/test_parsers_codex.py
- - tests/unit/sources/test_parsers_props.py
- - tests/unit/sources/test_parser_crashlessness.py
- - tests/unit/sources/test_compaction.py
- - tests/unit/sources/test_assembly.py
- status: active
-
- - name: providers-semantics
- description: >
- Provider semantic extraction, harmonization, and viewport contracts
- paths_to_mutate:
- - polylogue/sources/providers
- - polylogue/schemas/registry.py
- tests:
- - tests/unit/sources/test_null_guard_properties.py
- - tests/unit/sources/test_models.py
- - tests/unit/sources/test_parsers_props.py
- - tests/unit/sources/test_assembly.py
- status: active
-
- - name: repository
- description: >
- Repository query, projection, and CRUD contracts
- paths_to_mutate:
- - polylogue/storage/repository/__init__.py
- tests:
- - tests/unit/storage/test_store_ops.py
- - tests/unit/storage/test_tree_laws.py
- status: active
-
- - name: schema-core
- description: >
- Schema generation, privacy, verification, and safety contracts
- paths_to_mutate:
- - polylogue/schemas/operator/schema_inference.py
- - polylogue/schemas/validator.py
- - polylogue/schemas/operator/verification.py
- tests:
- - tests/unit/core/test_schema_validation.py
- - tests/unit/core/test_schema_generation.py
- - tests/unit/core/test_schema_annotation_contracts.py
- - tests/unit/core/test_schema_laws.py
- - tests/unit/core/test_schema_privacy.py
- - tests/unit/core/test_verification.py
- - tests/unit/storage/test_schema_safety.py
- status: active
-
- - name: schema-inference
- description: >
- Schema inference and privacy heuristics
- paths_to_mutate:
- - polylogue/schemas/operator/schema_inference.py
- tests:
- - tests/unit/core/test_schema_generation.py
- - tests/unit/core/test_schema_laws.py
- - tests/unit/core/test_schema_privacy.py
- status: active
-
- - name: schema-validation
- description: >
- Schema validator and verification contracts
- paths_to_mutate:
- - polylogue/schemas/validator.py
- - polylogue/schemas/operator/verification.py
- tests:
- - tests/unit/core/test_schema_validation.py
- - tests/unit/core/test_schema_laws.py
- - tests/unit/core/test_verification.py
- - tests/unit/storage/test_schema_safety.py
- status: active
-
- - name: source-detection
- description: >
- Source detection, sniffing, and parser dispatch
- paths_to_mutate:
- - polylogue/sources/source_parsing.py
- - polylogue/sources/source_acquisition.py
- - polylogue/sources/dispatch.py
- - polylogue/sources/decoders.py
- tests:
- - tests/unit/sources/test_source_laws.py
- - tests/unit/sources/test_parsers_base.py
- - tests/unit/sources/test_parsers_chatgpt.py
- - tests/unit/sources/test_parsers_codex.py
- - tests/unit/sources/test_parsers_props.py
- - tests/unit/sources/test_parsers_drive.py
- status: active
-
- - name: sources-parse
- description: >
- Provider detection, parsing, harmonization, and parser laws
- paths_to_mutate:
- - polylogue/sources
- - polylogue/schemas/registry.py
- tests:
- - tests/unit/sources/test_parsers_props.py
- - tests/unit/sources/test_source_laws.py
- - tests/unit/sources/test_parsers_base.py
- - tests/unit/sources/test_parsers_chatgpt.py
- - tests/unit/sources/test_parsers_codex.py
- - tests/unit/sources/test_parsers_drive.py
- - tests/unit/sources/test_drive_source_client.py
- - tests/unit/sources/test_drive_gateway.py
- - tests/unit/sources/test_drive_auth.py
- - tests/unit/sources/test_drive_ops.py
- - tests/unit/sources/test_null_guard_properties.py
- - tests/unit/sources/test_models.py
- - tests/unit/sources/test_token_store.py
- status: active
-
- - name: ui-core
- description: >
- UI prompt, progress, and facade interaction contracts
- paths_to_mutate:
- - polylogue/ui/__init__.py
- - polylogue/ui/facade.py
- tests:
- - tests/unit/ui/test_ui.py
- - tests/unit/ui/test_ui_visual.py
- - tests/unit/ui/test_tui.py
- status: active
-
- - name: daemon-http
- description: >
- Daemon HTTP API endpoint handler contracts
- paths_to_mutate:
- - polylogue/daemon/http.py
- tests:
- - tests/unit/daemon/test_daemon_http.py
- status: active
-
- - name: repair-core
- description: >
- Storage repair logic, preview/idempotence/failure state effects
- paths_to_mutate:
- - polylogue/storage/repair.py
- tests:
- - tests/unit/storage/test_repair.py
- status: active
-
-benchmark_campaigns:
- - name: archive-maintenance
- description: >
- Archive backup planning, blob-GC dry-run, and space-report benchmark domain
- tests:
- - tests/benchmarks/test_archive_maintenance.py
- status: active
-
- - name: pipeline
- description: >
- Index rebuild/update, action repair, plus hashing/semantic helper benchmark domain
- tests:
- - tests/benchmarks/test_pipeline.py
- status: active
-
- - name: search-filters
- description: >
- FTS and SessionFilter benchmark domain
- tests:
- - tests/benchmarks/test_search_filters.py
- status: active
-
- - name: storage
- description: >
- Repository/backend list/get-many/save benchmark domain
- tests:
- - tests/benchmarks/test_storage.py
- status: active
-
- - name: reader-api
- description: >
- Reader HTTP API list/get/facets/context-image/cost-rollup benchmark domain
- tests:
- - tests/benchmarks/test_reader_api.py
- status: active
-
- - name: session-digest
- description: >
- Deterministic session digest transform benchmark domain
- tests:
- - tests/benchmarks/test_session_digest.py
- status: active
-
- - name: daemon-convergence
- description: >
- Daemon ingest convergence at synthetic scale tiers — single-file and multi-session
- tests:
- - tests/benchmarks/test_daemon_convergence.py
- status: active
diff --git a/docs/plans/classifier-fingerprints.json b/docs/plans/classifier-fingerprints.json
deleted file mode 100644
index 3439772203..0000000000
--- a/docs/plans/classifier-fingerprints.json
+++ /dev/null
@@ -1,374 +0,0 @@
-{
- "functions": {
- "polylogue/archive/artifact_taxonomy/runtime.py:classify_artifact": {
- "fingerprint": "549ac414a67a49c7a083004caf7666f0a79dc8ef447473b15b609454edc6e350",
- "covered_by": {
- "kind": "semantic_reparse_version",
- "reason": "provider-agnostic tool-results path override + file-history-snapshot content override",
- "ref": "polylogue-omsw",
- "version": 58
- }
- },
- "polylogue/archive/artifact_taxonomy/runtime.py:classify_artifact_path": {
- "fingerprint": "32b6f26516b4cc9ed0342c262e492fca469aaca9fb47a66e4ca1c76b7f58987a",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Strong-only admission helper preserves this classifier output; no archived payload classification changes.",
- "ref": "#3952"
- }
- },
- "polylogue/archive/artifact_taxonomy/support.py:looks_like_beads_interaction": {
- "fingerprint": "ca8524db458408ef6a18bcc4a4f91d811e436fa9d2fdd7f6a109d9c602343c35",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/archive/artifact_taxonomy/support.py:looks_like_file_history_snapshot_only_stream": {
- "fingerprint": "a807f08bb16ac02caeb353e3e66603e32aee656ebca49bd9802cf19d0bf84335",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "new content-shape helper backing classify_artifact's file-history-snapshot override",
- "ref": "polylogue-omsw"
- }
- },
- "polylogue/archive/artifact_taxonomy/support.py:looks_like_hook_event": {
- "fingerprint": "9f5c4061bae7c70195d55fcd8d02a461009f62a11cd082ed6eb8e47bc3ca34f8",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/archive/artifact_taxonomy/support.py:looks_like_hook_event_stream": {
- "fingerprint": "03fdb9a9d03cda22fc81907e765ecd2bff30a8d3c0e07270c139e062cd4a056a",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/archive/artifact_taxonomy/support.py:looks_like_message_entry": {
- "fingerprint": "797d7d85a75d45baf5cbda223f081ede31e9c086c52525ff37d594c52f204075",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/archive/artifact_taxonomy/support.py:looks_like_record_entry": {
- "fingerprint": "99a3dbdeb5b420b5e9059d965f6e8749860d7d9b637fdb0bf9efcbb369f69784",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "PR #3428 (ab8a92c1a) tightened this without an INDEX_SCHEMA_VERSION bump; retroactively acknowledged. Existing misclassified rows tracked by the repair pass.",
- "ref": "polylogue-zqph"
- }
- },
- "polylogue/archive/artifact_taxonomy/support.py:looks_like_record_stream": {
- "fingerprint": "f717bdffdfd50a5aefa11d0f9a5c147bfa5e71a1bd57973c6dd2b25141db6ed1",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/archive/artifact_taxonomy/support.py:looks_like_session_document": {
- "fingerprint": "3c0e09f04a43fbae1b84a8b08a0659fe723714548c31a0b89cb1612757664844",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/origin_specs.py:artifact_rule:claude-code-session:adopt_manifest": {
- "fingerprint": "000a0f9c6f225b0ffa559169cf0d62474eb9b61ace6bf5ce6e716a09002a9e1a",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at artifact-rule fingerprint coverage introduction (polylogue-qs4b).",
- "ref": "polylogue-qs4b"
- }
- },
- "polylogue/sources/origin_specs.py:artifact_rule:claude-code-session:agent_sidecar_meta": {
- "fingerprint": "82d457c459d996e7dee23653b85a4200b9bbd560b8eee047da2337f0d577e26d",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at artifact-rule fingerprint coverage introduction (polylogue-qs4b).",
- "ref": "polylogue-qs4b"
- }
- },
- "polylogue/sources/origin_specs.py:artifact_rule:claude-code-session:agent_transcript": {
- "fingerprint": "223b85d5751ef5efefe0b6c06becaf85bfe29b7f19558fbc488c181a54e4377e",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at artifact-rule fingerprint coverage introduction (polylogue-qs4b).",
- "ref": "polylogue-qs4b"
- }
- },
- "polylogue/sources/origin_specs.py:artifact_rule:claude-code-session:coordinator_session_stream": {
- "fingerprint": "37ede4aefc1d2eaf9b27e39bbaa53b1de19a94ecd33436fe0019428c1916d785",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at artifact-rule fingerprint coverage introduction (polylogue-qs4b).",
- "ref": "polylogue-qs4b"
- }
- },
- "polylogue/sources/origin_specs.py:artifact_rule:claude-code-session:todo_snapshot": {
- "fingerprint": "10655aec3060b735df6a0c061fb162164febba4efe379b2215ed41e684496f6a",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at artifact-rule fingerprint coverage introduction (polylogue-qs4b).",
- "ref": "polylogue-qs4b"
- }
- },
- "polylogue/sources/origin_specs.py:artifact_rule:claude-code-session:tool_result_sidecar": {
- "fingerprint": "fec746c784f5ce11a8b1b11819cad93ceb45e0a8b8fec067abfe2561197b4faa",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Tightens acceptance only: tool-results/*.json sidecars (overflow tool-call output Claude Code persists verbatim, joined to their owning tool_result block by tool_use_id -- see sources/live/tool_result_sidecars.py) were never a real independent conversation; content heuristics alone cannot refuse them since a tool call's own output can coincidentally reproduce a genuine session-document shape (verified live against a real ~/.claude/projects corpus: a tool-results/*.txt sidecar whose content was a real claude.ai export document classified as SESSION_DOCUMENT/parse_as_session=True under the prior content-only rules; path_suffixes scoped to .json only -- not the .txt/.html also found live -- since artifact_suffixes_for_provider feeds live/watcher.py's acquisition suffix filter and widening it is out of this fix's scope). No reparse of existing rows: the already-planned index rebuild (polylogue-x1gd) is the retroactive cleanup path, not this change.",
- "ref": "polylogue-omsw"
- }
- },
- "polylogue/sources/origin_specs.py:artifact_rule:claude-code-session:workflow_journal": {
- "fingerprint": "9d39e1590195ca7a767f42f03401add2441e5f947dddb25241df25282fbbd99d",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at artifact-rule fingerprint coverage introduction (polylogue-qs4b).",
- "ref": "polylogue-qs4b"
- }
- },
- "polylogue/sources/origin_specs.py:artifact_rule:claude-code-session:workflow_run_snapshot": {
- "fingerprint": "9f363d410e569da2c5b5d4e4d7d8b1c8a1af1ab1db68da761ac0d8bf03d83576",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at artifact-rule fingerprint coverage introduction (polylogue-qs4b).",
- "ref": "polylogue-qs4b"
- }
- },
- "polylogue/sources/parsers/antigravity.py:looks_like_brain_metadata": {
- "fingerprint": "5e80c04e8f9e78920d1bbbd16d1698a330e6e3ccdc2373ae4b9f17fefa144e3a",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/antigravity.py:looks_like_markdown_export": {
- "fingerprint": "90525b09e2883d8b3093a20ae5f0ae12bc4040d3ab6f763fa794fceb44e8f920",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/beads.py:looks_like": {
- "fingerprint": "9608a73247813b989ac6e857c374eea112d8f0f342da376a23530cd5ba293079",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/browser_capture.py:looks_like": {
- "fingerprint": "7b6ca34dac7d1d9a9ca4ddade693396d217a07288e5d1c442f7e56a7cbae9aeb",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/chatgpt.py:looks_like": {
- "fingerprint": "01785fab9f2de11eda09cf4ed017bacc8f427987962e5f79b72b8c783b9e48fc",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/chatgpt.py:looks_like_fragment": {
- "fingerprint": "382354bf93637c22bfcec6fc80b9f09b7f040687b97cdd7b1b5ab0c5aefefdb1",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/chatgpt.py:looks_like_shared_decode": {
- "fingerprint": "37a68475cdef7916bf2c2552676bb7267f7aa429fc0be78c02690fbfb7ea161e",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "New provider-shape detector for the ChatGPT shared-page stream-decode format (polylogue-4zqh3): flat messages list, no mapping key.",
- "ref": "polylogue-4zqh3"
- }
- },
- "polylogue/sources/parsers/chatgpt_codex_sidecar.py:looks_like": {
- "fingerprint": "273bc13adae90435566dc75ef802a83beae650e03894a2146e44e897394dc8d9",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/claude/__init__.py:looks_like_ai": {
- "fingerprint": "4f2c5a0787adfe9647e40238d43efbe035ae87645fb7b2de2201d4bd460d5499",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/claude/ai_parser.py:looks_like_ai": {
- "fingerprint": "d30a5251e41ab079c8465c6892bd3124bcdd634a352edfaaf3b4c3faf21d080d",
- "covered_by": {
- "kind": "semantic_reparse_version",
- "reason": "PR #3537 tightened looks_like_ai to require positive chat_messages evidence (role/sender+text/content), same shape as PR #3428's looks_like_code fix",
- "ref": "polylogue-t0ta",
- "version": 54
- }
- },
- "polylogue/sources/parsers/claude/ai_parser.py:looks_like_claude_design": {
- "fingerprint": "bd03581f209d7ade36485652ccb863d1652adf05abc8b14332cebcd25ce8779e",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/claude/ai_parser.py:looks_like_claude_memories": {
- "fingerprint": "a6c6a33039f82b0329eb88c54a7614be7881068812e4e030f1b55bcb610ced5f",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/claude/code_detection.py:looks_like_code": {
- "fingerprint": "ed3bdb0d2d5414198aba472a62e0ae466307eefb84a728103ad3d7c96324b734",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "PR #3428 (ab8a92c1a) tightened this without an INDEX_SCHEMA_VERSION bump; retroactively acknowledged. Existing misclassified rows tracked by the repair pass.",
- "ref": "polylogue-zqph"
- }
- },
- "polylogue/sources/parsers/codex.py:looks_like": {
- "fingerprint": "d552a69c42b30ac6eca88642668d53d1005cf884b6547f7c7839c0b740d09852",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/codex_state.py:looks_like_state_db_payload": {
- "fingerprint": "9b053731eba94db843149fc65f7ceb1766db882d1a122784489b5b115a39eb93",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/drive.py:looks_like": {
- "fingerprint": "c997b2b0853c7f0ba25b4f75e09dda86d6c9ec48279853ab9c6f3d2aa80d7b2b",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Only tightens acceptance for a chunkedPrompt.chunks envelope with zero (or wrong-typed) chunks, a shape that never validly represented a real Gemini/Drive conversation -- no genuine session ever had an empty chunk list. Sibling fix to PR #3428/#3537's classifier tightening.",
- "ref": "polylogue-mvcbi"
- }
- },
- "polylogue/sources/parsers/drive.py:looks_like_chunk": {
- "fingerprint": "3ba252b8c1f859e351ee54eb6651e8d96d1f8b757df9fd260aed7aad37f4ed49",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/grok.py:looks_like_conversation": {
- "fingerprint": "330f18d22cf6faf5d56bc7b5e051f70036720d9f2b803693b01ed0b00b7afbe3",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/grok.py:looks_like_export": {
- "fingerprint": "de586e71c6bebdb4f703e33a7754c32c3600098ec100e6ffbfdea83ab2d8eb07",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/hermes_spans.py:looks_like_atif_payload": {
- "fingerprint": "c8297259d89eec1adec78f5f229ad252d0accefc81d53e04ba916f77c06bb0cb",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/hermes_spans.py:looks_like_atof_payload": {
- "fingerprint": "41b75f1be8f76d56f5d46104c371ea55ce1867744c97d65ee64a95c77e155649",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/hermes_state.py:looks_like_state_db_path": {
- "fingerprint": "ca8622ef35e983ab1f7553dc2a081397c2c814b38dc1341203d5e2e29876f6cf",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Immutable blob reads retain the classifier's structural table probe while preventing sidecar creation; parser-output parity is not claimed here.",
- "ref": "polylogue-84ake"
- }
- },
- "polylogue/sources/parsers/hermes_state.py:looks_like_state_db_payload": {
- "fingerprint": "0d4ab96a369419e5487fe1a80b6df03eec779527121dd8ed6d0c3084409a869b",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/hermes_verification.py:looks_like_verification_evidence_db_path": {
- "fingerprint": "ca8622ef35e983ab1f7553dc2a081397c2c814b38dc1341203d5e2e29876f6cf",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Immutable blob reads retain the classifier's structural table probe while preventing sidecar creation; parser-output parity is not claimed here.",
- "ref": "polylogue-84ake"
- }
- },
- "polylogue/sources/parsers/hermes_verification.py:looks_like_verification_evidence_db_payload": {
- "fingerprint": "a639334d5ba5ca66247f53ea40944271b5893139ae794a25cfed4b5272e540a3",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/local_agent.py:looks_like_gemini_cli": {
- "fingerprint": "7fc8e19b0ba0058d8fb1b8606ad4560e810ecf0b4c7356b191b9152e507bff9c",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/parsers/local_agent.py:looks_like_hermes": {
- "fingerprint": "1bc55fdde8189754f9b69c8ddd4f77735e514625e7b1c8486f18fa932246c9ea",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "Baseline snapshot at classifier-fingerprint gate introduction (polylogue-gucv).",
- "ref": "polylogue-gucv"
- }
- },
- "polylogue/sources/sqlite_snapshot.py:looks_like_sqlite_bytes": {
- "fingerprint": "73553ae410ddc2daa4078915b3e9abec780c6998a52b870b10a6fc7c0fe2654d",
- "covered_by": {
- "kind": "acknowledged_safe",
- "reason": "polylogue-hbtj2: delegated to the shared core.binary_signatures.looks_like_sqlite_bytes detector to avoid duplicating the magic-byte constant; byte-for-byte identical behavior (same SQLite magic header check), no semantic reparse.",
- "ref": "polylogue-hbtj2"
- }
- }
- }
-}
diff --git a/docs/plans/decision-adjudication-kea7p-avna-cijx-uh6c-rxdo9-ze5-dx1-fie-ca4.md b/docs/plans/decision-adjudication-kea7p-avna-cijx-uh6c-rxdo9-ze5-dx1-fie-ca4.md
deleted file mode 100644
index 89df92fb97..0000000000
--- a/docs/plans/decision-adjudication-kea7p-avna-cijx-uh6c-rxdo9-ze5-dx1-fie-ca4.md
+++ /dev/null
@@ -1,707 +0,0 @@
-# Decision adjudication: kea7p, avna, cijx, uh6c, rxdo.9, ze5, dx1, fie, ca4
-
-Status: Sol adjudication packet, 2026-08-03. Scope is decision and implementation slicing only. This packet does not change production code or Beads state.
-
-## Executive decisions
-
-| Bead | Final decision | Policy owner | Readiness |
-| --- | --- | --- | --- |
-| `polylogue-kea7p` | Build differential reindex as a declared, fingerprint-gated transition state machine. A hash match alone never authorizes a skip. Preserve from-empty rebuild as recovery and equivalence proof. | Implementer, constrained by existing derived-tier doctrine | dependency-blocked |
-| `polylogue-avna` | Generalize `seq()` into an actions-only row-pattern model with embedded event-order semantics, captures, measures, explicit overlap, and SQL/Python parity. Keep mixed streams and fuzzy semantic tokens out of v1. | Implementer, following the corrective contract | execution-ready with packet |
-| `polylogue-cijx` | Model repository and file trajectories as graded observations, checkpoints, and replay receipts. Repository identity is evidence-ranked, file identity is not path identity, and Polylogue does not become a VCS. | Implementer, following the corrective contract | execution-ready with packet |
-| `polylogue-uh6c` | Separate membership, affinity, and confidence in types, storage, queries, and renderers. One operator choice is required for existing unqualified tag migration. | Model is settled; namespace migration is operator-owned | operator-decision-blocked |
-| `polylogue-rxdo.9` | Treat rigor as one frame-exact claim protocol over canonical definitions and evidence axes. Reconcile landed primitives into production routes and consume the `stc` experiment definition rather than creating another one. | Operator doctrine is settled; implementation is constrained by dependencies | dependency-blocked |
-| `polylogue-ze5` | Keep unified `assertions` storage, derive a four-class lens, add relation and revision tables in the next user-tier migration, and use class-appropriate surface nouns. | Operator-ratified | execution-ready with packet |
-| `polylogue-dx1` | Proceed with Starlette and uvicorn through an ASGI-fronted compatibility ramp. Keep browser capture separate and preserve all security and byte contracts. | Operator-ratified | execution-ready with packet |
-| `polylogue-fie` | Keep everything permanently. Proceed with blob zstd, measure before FTS sharding, and retain blue-green fresh-first rebuilds. Do not adopt mutation-only index maintenance. | Operator-ratified | evidence-blocked |
-| `polylogue-ca4` | Stay SQLite-only now. DuckDB may become an optional read lowerer only after canonical measure lowering exists and a real five-query probe meets the ratified 10x gate. | Operator-ratified | dependency-blocked |
-
-The only current operator question is the namespace assigned to existing unqualified tags. Every other choice is either ratified already or follows directly from current durability, provenance, and single-writer invariants.
-
-## Evidence method and global constraints
-
-The Bead records were read directly from `.beads/issues.jsonl`, including description, design, acceptance criteria, notes, comments, dependencies, and status. `bd` was not invoked because every `bd` call can re-import an aging worktree's JSONL into shared state. Merged history was inspected on `origin/master`. Current source, tests, schemas, and the read-only live archive were inspected from this worktree. `polylogue-qj5x` was not adjudicated. It appears below only where it blocks the fingerprint-bootstrap rebuild.
-
-The following architecture rules apply to every lane:
-
-1. Durable source and user changes use numbered additive migrations and a verified backup manifest. Derived index changes use canonical DDL plus a declared lifecycle delta.
-2. Public surfaces consume product, insights, operations, or API contracts. They do not add new direct substrate imports.
-3. Content-addressed identities include every semantic field that can change a result. Friendly names are aliases, not competing identities.
-4. Unknown, absent, ambiguous, stale, and failed are distinct states. Confidence never substitutes for evidence grade or frame coverage.
-5. Tests must traverse the production writer, reader, lowerer, or actuator. A fixture-only replica is not acceptance evidence.
-6. The next lane that owns `storage/sqlite/archive_tiers/user.py` owns the entire user-schema version bump. The next lane that owns `storage/sqlite/archive_tiers/index.py` owns the entire index-schema bump. Parallel lanes must not edit those files concurrently.
-
-## `polylogue-kea7p`: differential reindex
-
-### Current state and unresolved decision
-
-The ordinary ingest writer already performs the useful T1 primitive. `_write_session` in `polylogue/pipeline/services/ingest_batch/_core.py` compares `sessions.content_hash` with `SessionWritePayload.content_hash`, refreshes flags and raw links, schedules per-session FTS repair when needed, and returns before row replacement on a match. `session_content_hash` in `polylogue/pipeline/ids.py` covers the normalized parsed payload. It does not prove historical lowering fidelity, contextual lineage composition, derived-at-write columns, identity, or multi-session raw membership.
-
-`polylogue/storage/sqlite/lifecycle.py` already distinguishes clone-safe operations, `SHAPE_FORWARD_TARGETED_REPROCESS`, and `SEMANTIC_REPARSE`. `polylogue/storage/index_generation.py`, `polylogue/maintenance/rebuild_index.py`, and `polylogue/daemon/bulk_rebuild.py` already supply owned generations, resumable transactions, source-snapshot staleness, bulk terminal convergence, promotion, and one retained superseded generation. The unresolved decision is how to reuse these mechanisms without allowing a stale semantic result to pass a cheap skip.
-
-Current sessions have no trustworthy semantics stamps. `polylogue-xselt` is intended to add parser and lowering fingerprints, but it is blocked by `polylogue-slshy`. The production bootstrap `polylogue-818fy` also depends on the deliberately excluded `polylogue-qj5x`. Therefore the current archive cannot safely use differential semantic skips.
-
-### Final adjudication
-
-Adopt a four-input skip oracle and a transition state machine. A session is skippable only when all of these are true:
-
-1. The raw is an accepted current authority head under the current authority fingerprint.
-2. The stored parser fingerprint equals the current fingerprint for the origin.
-3. The stored lowering fingerprint equals the current shared lowering fingerprint.
-4. When parsing is performed, the current parsed content hash equals the stored content hash.
-
-The authority fingerprint covers raw revision selection, membership arbitration, identity derivation policy, and accepted-head semantics. The parser fingerprint covers origin-specific detection, parser, sidecar assembly, and parser-owned classifications. The lowering fingerprint covers parsed-tree identity and hashing, normalized row lowering, search text, material-origin and message-type classification, lineage composition, and write-time projections. Fingerprints are semantic dependency manifests, not git commit ids or whole-package hashes.
-
-The state machine is:
-
-1. `DISCOVER`: acquire the current source authority epoch, active index epoch, schema versions, fingerprints, and declared delta set.
-2. `CLASSIFY`: classify each delta as clone-safe DDL, projection backfill, parser semantic, lowering semantic, authority semantic, derived convergence, or full-rebuild-only.
-3. `PLAN`: compute affected origins, raw heads, session and lineage closure, reverse-census scope, estimated changed bytes, temporary disk, and the in-place versus blue-green cost.
-4. `SNAPSHOT`: for in-place work, create an owned reflink rollback generation. If an exact cheap snapshot is unavailable, select blue-green.
-5. `APPLY_SHAPE`: apply only declared clone-safe canonical DDL. A `SEMANTIC_REPARSE` declaration can never be converted into a shape-only operation.
-6. `T0_CENSUS`: skip parsing only for accepted raw heads whose materialization receipt and every member session carry current authority, parser, and lowering fingerprints. Missing stamps are a mandatory miss.
-7. `T1_PARSE_COMPARE`: parse every remaining raw. Replace the affected session closure when content differs or when a semantic fingerprint differs. A hash match may avoid payload replacement only after fingerprint equality; it cannot avoid a declared projection or convergence obligation.
-8. `T2_BACKFILL`: run projection-only backfills whose declaration names source columns, target columns, scope, producer version, and verifier. If values depend on parser semantics, this state routes through reprocess instead.
-9. `REVERSE_CENSUS`: tombstone sessions whose expected identity is no longer emitted by an accepted head, verify the expected session-id set per raw, and prove membership conservation for every multi-session raw.
-10. `CONVERGE_CORE`: refresh every index-local dependency required for a self-consistent reader snapshot, including lineage closure, FTS, action pairs, delegation facts, and affected index insights. In-place mode performs writes, core convergence, and proof inside one bounded SQLite transaction; if that transaction would violate the writer budget, the planner must select blue-green.
-11. `PROVE`: compare the affected closure against a from-empty scratch materialization, validate canonical table manifests, verify stored-row hashes independently of the stored content hash, and run archive invariants before the in-place commit or candidate promotion.
-12. `COMMIT` or `ACTIVATE`: commit the bounded in-place transaction after proof, or atomically promote the exact-ready candidate generation. Record the source epoch, delta manifest, fingerprints, counts, timing, and proof roots.
-13. `CONVERGE_FOLLOW_ON`: enqueue embeddings and any other cross-tier or intentionally deferred model. `false_means_pending` records convergence debt. The reindex operation remains pending until required follow-on stages reach their declared freshness target, even though readers may use the core-consistent index with explicit freshness/debt metadata.
-14. `CLEANUP`: retain one exact rollback generation and prune only generations already covered by retention policy.
-15. `STALE`, `ROLLBACK`, or `ESCALATE`: source-authority change before proof makes the plan stale. Replan changed raws until a fixed point. Any proof failure restores the rollback generation and escalates the same declaration to blue-green or a full rebuild.
-
-In-place remains the default only when canonical DDL is compatible, an exact reflink rollback exists, the affected closure and proof fit one bounded transaction, and the measured cost model favors it. Selection uses estimated changed bytes and graph closure, not a hard-coded percentage. Blue-green remains mandatory for incompatible DDL, unavailable rollback, multi-pass core mutation, large contextual closure, uncertain authority, or failed differential proof.
-
-### Rejected alternatives
-
-- Hash-only skip is rejected because historical lowering bugs, derived columns, identity drift, and lineage context can survive a matching parsed-payload hash.
-- Parser fingerprint without lowering and authority fingerprints is rejected because it cannot detect shared writer, identity, classifier, or raw-selection changes.
-- Whole-archive `SEMANTIC_REPARSE` as the permanent default is rejected because origin and surface declarations can safely bound future work after bootstrap.
-- Mutation-only index maintenance is rejected. The from-empty builder remains the recovery oracle, periodic audit path, and proof reference required by the fresh-first doctrine.
-- Per-session reverse existence checks are rejected because they miss identity changes and wrong membership splits.
-
-### Contract, schema, compatibility, failure, and rollback
-
-Add `authority_fingerprint`, `parser_fingerprint`, and `lowering_fingerprint` to derived session rows, plus a derived `raw_materialization_receipts` relation containing raw id, fingerprints, expected membership digest and count, materialized session ids digest, source authority epoch, and producer version. `xselt` currently specifies only parser and lowering stamps; its implementation should leave the authority column and receipt shape to `kea7p` or be extended before bootstrap. This is an index-tier semantic-reparse change. Existing rows cannot be backfilled truthfully from stored columns.
-
-Projection declarations extend `IndexDeltaDeclaration` with affected surface, origin scope, dependency fingerprints, backfill plan, convergence stages, and proof plan. They do not weaken the existing rule that any crossed semantic-reparse delta blocks SQL fast-forward.
-
-Compatibility: routine semantic transitions stop instructing operators to reset the index after the fingerprint bootstrap. The full rebuild command remains as recovery and audit. Privacy is unchanged because fingerprints and membership digests contain no content. Performance improves only after the initial bootstrap. Failure is fail-closed: missing stamps, source drift, ambiguous membership, or proof mismatch means reprocess or rebuild. Rollback is atomic pointer restoration to the exact pre-operation generation, not reversal by best-effort SQL.
-
-### Implementation slices
-
-| Order | Slice and owner files | Avoid list | Dependencies and parallel safety |
-| --- | --- | --- | --- |
-| K0 | Finish stamp preconditions in `polylogue-slshy`, then `polylogue-xselt` owns `sources/origin_specs.py`, `storage/sqlite/archive_tiers/index.py`, `storage/sqlite/archive_tiers/write.py`, `storage/sqlite/lifecycle.py`, and archive verification. | Differential planning and mode selection | Serial index-schema owner. Blocks every later slice. |
-| K1 | Transition contracts in a new `polylogue/maintenance/differential_reindex.py`; extend lifecycle declarations without executing writes. | `user.py`, daemon HTTP, query DSL | Parallel with non-index work after K0's schema lands. |
-| K2 | Raw materialization receipts and reverse census in the same maintenance module plus focused helpers in raw authority and index generation. | Provider parsers except declared fingerprint inputs | Serial with any lane editing `write.py` or index DDL. |
-| K3 | Planner and cost model integration in `maintenance/rebuild_index.py`, `storage/index_generation.py`, and `daemon/bulk_rebuild.py`. | Public CLI grammar and unrelated convergence stages | Depends on K1 and K2; serial with `b5l` changes in these files. |
-| K4 | Convergence and proof integration in `daemon/convergence.py`, `maintenance/archive_verification.py`, and a canonical table-manifest helper. | Embedding implementation internals unless its declared stage changes | Can parallelize proof helper and convergence adapter with separate files. |
-| K5 | CLI and daemon operation adapters plus retirement of reset-as-routine guidance. | Full rebuild engine and recovery command | Last, after behavior is proven. |
-
-### Acceptance evidence and anti-vacuity
-
-- Property test every delta class against the planner: any parser, lowering, or authority fingerprint mutation selects every affected raw and cannot reach T0.
-- Mutation test that removes each fingerprint conjunct. The bootstrap fixture must then incorrectly skip and the test must fail.
-- Real-writer test: build a fixture through `write_parsed_session_to_archive`, rerun unchanged, mutate a parser semantic input, a lowering input, and authority selection, and observe T0, T1, and replacement paths respectively.
-- Identity test: one raw changes emitted session id. The old id is tombstoned and the new id is written.
-- Membership property: arbitrary multi-session raw revisions preserve exactly the expected member set across reorder, split, merge, duplicate, and supersession cases.
-- Lineage test: a parent change expands the affected closure to prefix-sharing descendants and matches a from-empty scratch build.
-- Projection test: a projection-only delta backfills without parsing, while relabeling the same delta semantic-reparse makes parsing mandatory.
-- Failure tests cover crash after snapshot, after DDL, midway through parse, after reverse census, and during proof. Restart resumes or rolls back without exposing an unproved state.
-- Live proof after bootstrap records affected raw count, parsed count, hash skips, fingerprint skips, tombstones, convergence debt, table manifests, source epoch, elapsed time, I/O, and rollback-generation id.
-
-Anti-vacuity requires the production ordinary ingest writer and generation promoter. Removing the content-hash early return must increase writes; removing a fingerprint conjunct must create a detected mismatch; disabling reverse census must leave a stale identity and fail the manifest comparison.
-
-Readiness: **dependency-blocked** on `slshy -> xselt -> 818fy`. `818fy` also depends on excluded `qj5x`; that is the only qj5x relationship recorded here.
-
-## `polylogue-avna`: typed row-pattern matching
-
-### Current state and unresolved decision
-
-`QuerySequencePredicate` in `polylogue/archive/query/predicate.py` models fixed action subsequences with `ordered`, `next`, and `within` edges. The Lark grammar in `expression.py` only accepts action field clauses inside `seq()`. `_action_sequence_steps_clause` in `storage/sqlite/archive_tiers/archive.py` orders by message position, variant index, and block position; `within` additionally requires nondecreasing timestamps. `runtime_matching.py` implements a separate Python matcher. `query_ast_schema.py` persists the strict sequence fragment. Matches currently filter sessions and discard bindings.
-
-The unresolved decision is the smallest honest generalization that supports repetition, absence, captures, measures, and explicit overlap without making timestamp order or future semantic classifiers look structural.
-
-### Final adjudication
-
-Introduce a content-addressed `PatternDefinition` embedded in the canonical query AST. It contains an `EventOrderSpec`; no independent order registry is created. `seq()` becomes syntax sugar for a fixed concatenation pattern and lowers through the same engine.
-
-Actions-only v1 has these types:
-
-- `EventOrderSpec`: partition key, physical-session lineage policy, unit kind `action`, structural coordinate definition, optional event-time field, tie policy, evidence grade, horizon/as-of receipt, and relation-manifest version.
-- `PatternExpr`: typed row predicate, concat, alternation, group, repetition with bounded or explicit unbounded maximum, optional, negative interval, start/end anchor, and capture.
-- `MatchPolicy`: `first`, `all`, or `leftmost-longest`; `AfterMatchPolicy`: `skip-past-last` by default or declared overlap.
-- `MeasureSpec`: capture-derived start/end, duration, count, field, and bounded aggregate measures. It consumes canonical metric identity when the output is a quantitative claim.
-- `PatternMatch`: partition ref, structural span, captures, measures, order receipt, evidence grade, and ambiguity state.
-- `MatchSet`: its own content identity over pattern ref, corpus epoch, relation manifest, order and overlap policy, ordered match membership, captures, measures, and Merkle roots. It may reference a result set projection, but is not a result-set alias.
-
-Default ordering is the structural action coordinate already used by SQL. Event timestamps may constrain a structural sequence but do not establish order by themselves. Event-time ordering requires `reject-ambiguous` ties by default. A declared structural fallback yields a distinguishable order receipt and cannot claim replay-verified temporal order. Equal timestamps therefore remain ambiguous or visibly downgraded.
-
-The execution plan is SQL prefilter plus a bounded Python Thompson NFA. Fixed, quantifier-free, absence-free action patterns keep a SQL fast path. Both paths consume one shared predicate and order contract and emit the same match protocol. Candidate and per-partition row caps produce a typed boundedness error rather than truncating silently.
-
-### Rejected alternatives
-
-- Strict adjacency by default is rejected because unrelated actions are normal. `next` remains alphabet-relative and explicit.
-- Timestamp-only sequence is rejected because missing and equal timestamps cannot prove order or absence.
-- A standalone `EventOrderSpec` registry is rejected until the order definition has an independent lifecycle.
-- Full SQL lowering for arbitrary patterns is rejected because absence, repetition, captures, and overlap make it complex and backend-specific.
-- A Python-only implementation is rejected because current fixed sequences already have an efficient SQL path and parity is an acceptance criterion.
-- Fuzzy `test-fail` or `unresolved` tokens are deferred. V1 accepts structural action predicates and explicitly versioned rule classifiers only. Judged outcome and goal-resolution semantics remain separate later work.
-- Mixed action/message/session streams are rejected in v1.
-
-### Contract, schema, compatibility, failure, and rollback
-
-PACK-A is storage-free except for the canonical query payload and generated AST schemas. PACK-B adds durable tables only for explicitly retained match sets: `pattern_match_sets` and `pattern_matches` in `user.db`, keyed to canonical query and corpus epoch, with JSON captures/measures/order receipts and membership roots. Routine results stay transient. This is an additive durable migration and must share or follow the exclusive user-schema migration owner.
-
-Existing saved `seq()` queries retain their original query identity and definition protocol version. At load, a versioned adapter normalizes the legacy sequence node into an equivalent `PatternDefinition`; newly authored queries use the pattern node. The old SQL and Python sequence implementations are removed after parity fixtures prove the adapter, leaving one matcher. Rollback disables the new grammar and retained-match writes while legacy `seq()` remains executable through the adapter.
-
-Privacy follows the referenced action fields. Captures containing commands, paths, or output remain private unless an existing projection redacts them. Performance is bounded by SQL prefilter, row caps, and explicit rejection of an unbounded corpus scan. A missing order field, ambiguous tie, candidate overflow, or relation-manifest drift yields an explicit non-match/ambiguous/error state, never a false negative presented as exact.
-
-### Implementation slices
-
-| Order | Slice and owner files | Avoid list | Dependencies and parallel safety |
-| --- | --- | --- | --- |
-| A1 | Domain protocol in new `archive/query/patterns.py`; AST additions in `predicate.py` and `query_ast_schema.py`. | SQL storage, user schema, semantic classifier ontology | Parallel-safe except for other query AST work. |
-| A2 | Grammar and canonicalization in `expression.py`; legacy `seq()` normalization. | Runtime and SQL matcher bodies | Depends on A1; owns the Lark grammar exclusively. |
-| A3 | Python NFA in new `archive/query/pattern_matching.py`, using shared action order keys. | SQL lowering and storage | Parallel with A4 after A1. |
-| A4 | SQL fast path in a new SQLite query helper, replacing `_action_sequence_steps_clause` after parity. | Python NFA | Parallel with A3; serial final deletion in `archive.py`. |
-| A5 | Match-grain payloads and query pipeline integration in `unit_results.py`, metadata, API/MCP/CLI adapters. | User persistence | Depends on A2 through A4. |
-| A6 | Retained match-set migration and repository methods in `user.py`, a numbered user migration, and focused user read/write modules. | Any ze5 or uh6c migration running concurrently | Exclusive user-schema lane; after ze5's version allocation. |
-
-### Acceptance evidence and anti-vacuity
-
-- Metamorphic generation of fixed action patterns proves SQL and Python emit identical ordered captures, measures, overlap, and ambiguity receipts.
-- Property tests cover repetition, alternation, optional groups, anchors, absence intervals, empty matches, and overlap policies without catastrophic runtime.
-- Equal-timestamp fixtures vary tie policy and evidence grade. No default path establishes event-time order.
-- A mixed-stream parse fails with a named deferred-capability error.
-- A candidate-overflow fixture returns a boundedness error and no partial exact result.
-- Retained match-set tests mutate one capture, overlap policy, order spec, classifier ref, or relation manifest and prove the content identity changes.
-- Cross-surface production tests run one expression through CLI, MCP, daemon, and API and compare the same match refs and provenance.
-
-Anti-vacuity requires both production lowerers. Removing `EventOrderSpec` from either lowerer, changing `next` to gap-tolerant, or ignoring overlap must fail the parity corpus.
-
-Readiness: **execution-ready with packet**. PACK-A through A5 can start. A6 waits for the exclusive user migration sequence.
-
-## `polylogue-cijx`: repository and file evidence identity
-
-### Current state and unresolved decision
-
-The repository substrate is farther along than the Bead's last AC wording. `repo_identity.py` normalizes repository paths and projects repo-relative paths. `repo_observations.py` writes `repos`, `repo_checkouts`, and `session_repos`. `write_parsed_session_to_archive` writes parser-reported checkout commits to `session_commits`, and `queries/session_commits.py` plus `correlation_view.py` read them. `file_edits` now stores structured patches and original-file checkpoints from Claude Code wire evidence. Merged commits `8beef5f6a` and `5e23e6abf` supplied the current checkout-commit and file-edit evidence.
-
-The remaining gaps are repository identity without a remote, path identity across renames, explicit observation/checkpoint/replay grades, coverage receipts, safe reproduction, and separation of checkout-head facts from heuristic live-git correlation.
-
-### Final adjudication
-
-Adopt evidence-ranked repository identity and observation-based file identity.
-
-Repository resolution uses the strongest available evidence in this order:
-
-1. Canonical remote identity, normalized across SSH, HTTPS, trailing `.git`, and case rules for the host.
-2. Git history-root identity, including object format and the sorted root commit set, as ancestry evidence for a repository with no remote. It is not canonical repository identity when independent forks share that history; the result remains ambiguous/provisional until corroborating evidence exists.
-3. Git common-dir identity for an empty or history-unavailable local repository, graded provisional.
-4. Checkout root only as checkout identity. A cwd without git evidence remains a directory and never creates a repository.
-
-`RepositoryIdentityReceipt` records the chosen key, authority, aliases, observed remote, common dir, history roots, checkout root, and observation time. Stronger later evidence merges aliases through an explicit `same-repository` edge; it never silently rewrites unrelated repositories.
-
-A file entity is scoped to a repository and is not equal to a path or blob. `FileObservation` records session/action refs, checkout, repository, file entity, repo-relative path, operation, proposed/applied/reverted/unknown state, pre/post hashes when captured, tool outcome, observation time, evidence grade, and coverage gaps. Rename/same-file edges require explicit tool or git-diff evidence. Equal content alone never merges file entities.
-
-Grades are:
-
-- `observed`: action-derived evidence only, with explicit gaps for shell side effects, generators, human changes, concurrency, and external processes.
-- `checkpointed`: a pre/post file hash, git tree, or equivalent state anchors the interval.
-- `replay-verified`: a bounded disposable-worktree reconstruction matches the checkpoint and verifier receipt.
-
-The existing `session_commits` relation becomes the narrow checkout-head fact. Add `checkout_head` to its detection vocabulary, attach repository identity/evidence grade, and keep heuristic time-window/file-overlap correlation as a visibly separate derived view. No request-time live-git computation may masquerade as the persisted checkout relation.
-
-Reproduction prefers applying a captured patch or checking out a target commit at the recorded base. A disposable worktree is not a host sandbox: `safe_verify` is a command classification, not authorization to execute repository-controlled code. Automatic execution requires an actual filesystem/process/network sandbox with credentials and ambient archive access denied, or explicit operator authorization recorded in the receipt. `mutating_patch` is allowed only inside the disposable worktree and sandbox. `networked`, `secret_sensitive`, `interactive`, and `unknown` remain plan-only without explicit authorization. The receipt cites original evidence, exact base/target, commands, sandbox/authorization identity, environment fingerprint, outputs, and cleanup state.
-
-### Rejected alternatives
-
-- Cwd or absolute root as repository identity is rejected because it breaks across subdirectories, worktrees, and renames.
-- Remote-only identity is rejected because local repositories may have no remote.
-- Blob hash as file identity is rejected because content changes and identical files are common.
-- Git-style line authorship is rejected. The product reports proposer, applier, generator, and observed committer only where evidence supports them.
-- Replaying every historical command is rejected as unsafe and less reproducible than applying the resulting patch or target commit.
-- A generic VCS or replay executor is rejected.
-
-### Contract, schema, compatibility, failure, and rollback
-
-Add derived index relations for repository identity receipts, repository aliases, file entities, file observations, identity/rename edges, trajectory checkpoints, and replay receipts. Extend `session_commits` and normalize its detection vocabulary. This is a derived semantic-reparse schema change because repository ids and file observations depend on parser, git, and trajectory semantics.
-
-Promoted evaluation definitions and operator judgments remain assertions or `stc` experiment records in `user.db`; the trajectory substrate does not add durable truth tables. Existing `repos` ids become aliases when the new resolver can prove continuity. Public paths are repo-relative. Absolute checkout paths, original file bodies, and verifier output are private evidence and pass existing redaction before public projection.
-
-Failure to resolve a repository leaves a directory observation. Missing pre/post bytes leaves hashes unknown. A deleted checkpoint automatically downgrades dependent trajectory claims. Disposable worktrees are created under the established temporary-work policy, have no credentials injected by default, and are removed after a receipt records cleanup. Rollback is an index-generation rebuild; no durable user data is destructively migrated.
-
-### Implementation slices
-
-| Order | Slice and owner files | Avoid list | Dependencies and parallel safety |
-| --- | --- | --- | --- |
-| C1 | Repository identity domain in `archive/session/repo_identity.py` and new identity receipt types. | Index DDL and file observations | Parallel-safe with C2 design tests if symbols do not overlap. |
-| C2 | File observation/checkpoint domain in new `insights/file_trajectory.py`, reusing `file_edits`. | Reproduction execution and public surfaces | Parallel with C1. |
-| C3 | Exclusive index schema and writer/readers in `archive_tiers/index.py`, `write.py`, `storage/insights/session/repo_observations.py`, and focused query modules. | User schema, query DSL, work-evidence tracker adapters | Depends on C1 and C2; exclusive index-schema lane. |
-| C4 | Correlation view conversion so persisted checkout-head and heuristic candidates are distinct. | Session parser metadata writer | Depends on C3. |
-| C5 | Safe reproduction planner/executor under `operations` and `insights`, with an actuator classification contract. | Daemon HTTP and arbitrary shell replay | Can parallelize with C4 after C2. |
-| C6 | G1/G2/G4/G5/G7 readers and privacy-aware API/MCP/CLI projections. | G3 authorship claims, G6/G8 causal evaluation | Depends on C3; G6/G8 additionally depend on rxdo/stc. |
-
-### Acceptance evidence and anti-vacuity
-
-- Fixtures cover one remote through two worktrees, SSH/HTTPS spellings, repository rename, no-remote history, empty git repository, and plain directory.
-- Property tests prove path normalization cannot escape the repo root and equal blobs do not imply same-file identity.
-- A tool edit plus an uncaptured external edit renders observed coverage gaps and cannot claim exact tree, authorship, or replay.
-- Removing a checkpoint downgrades all dependent claims; changing a captured hash makes replay verification fail.
-- The reproduction integration test creates a real disposable git worktree, applies a patch or target commit, runs a declared safe verifier, and compares the checkpoint. Networked and unknown commands never execute.
-- A production write/read test persists checkout-head metadata, reads it through repository/API, and proves disabling the writer removes the fact. The live-git heuristic must not recreate it.
-- G5 tests a selected repository generation, dead path, renamed path with evidence, and unresolved repository.
-
-Anti-vacuity depends on real `write_parsed_session_to_archive`, git worktree operations, and the public correlation reader. Mock-only git graphs are insufficient.
-
-Readiness: **execution-ready with packet**. Tracker effects that later consume repository observations must follow the eventual qj5x outcome, but file/repository trajectory work does not need qj5x to start.
-
-## `polylogue-uh6c`: tag membership, affinity, and confidence
-
-### Current state and unresolved decision
-
-Current `session_tags` in index.db combines tag text, `user|auto` source, method, scalar confidence, and evidence. `_all_session_tags_sql` unions parser auto rows with active user-tier `AssertionKind.TAG` rows. `upsert_session_tag_assertion` explicitly calls `require_promotion=False`; its comment says tags are categorization rather than epistemic claims. This contradicts the Bead's corrective authority requirement because an agent-authored membership can become active without the canonical judgment transaction. Public filters and mutations use ambiguous free-form `tag` strings.
-
-The three-axis model is settled. The unresolved operator decision is how existing unqualified durable tags map into namespaces.
-
-### Final adjudication
-
-Adopt three independent protocols:
-
-- `TagMembership`: asserted membership of a subject in a `TagRef`, with actor, authority, status, qualifiers, evidence refs, and judgment lineage. Operator-authored membership may be active directly. Parser-structural membership may be active with a structural definition receipt. Agent, model, detector, and heuristic membership is always a non-injected candidate until the canonical `37t.12` transaction accepts it.
-- `TagAffinity`: a derived score between a subject and content-addressed prototype under a named embedding/model and evaluation world. It lives in a rebuildable derived relation and never grants membership.
-- `TagConfidenceReceipt`: calibrated uncertainty about a classifier or judgment, bound to assertion ref, actor, execution context, definition, calibration ref, and evaluation world. An uncalibrated scalar is labeled uncalibrated and never grants membership or affinity.
-
-`TagRef` is namespace plus name. It is plural and non-hierarchical; the namespace separator carries no parent/child semantics. A prototype is a separate `prototype:` resource associated with a tag for discovery, not the tag's identity.
-
-Public predicates are axis-specific: `tagged:`, `tag-affinity:`, and `tag-confidence:`. `tag:x>0.7` is rejected. Any axis conversion requires a content-addressed conversion definition and emits a new receipt.
-
-### Operator decision brief: existing unqualified tags
-
-Exact question: **Should existing user-authored tags map to `personal/` and parser-authored tags map to `system/`?**
-
-Option A, recommended: map user rows to `personal`, parser structural rows to `system`, copy-forward durable user assertions with supersession relations, and provide a read-only bare-name compatibility resolver for saved queries. This preserves known authority, gives useful namespaces, changes canonical API values, and requires a verified user.db migration.
-
-Option B: map all existing strings to `legacy/` and keep authority only in membership receipts. This makes no product-semantic guess and is easiest to roll back, but leaves the main corpus in a permanent low-information namespace and makes ordinary user tags less pleasant.
-
-Option C: retain an unqualified default namespace. This maximizes wire compatibility but contradicts the ratified namespaced model and is rejected unless the operator explicitly changes that policy.
-
-Compatibility/cost/risk: A changes canonical refs and therefore saved query and assertion ids; it needs copy-forward, aliases, and backup. B changes refs too but does not split by authority. Neither option loses original rows. Smallest answer needed: `A` or `B`, plus replacement namespace names only if `personal` and `system` are not desired. Blocked work: durable migration, canonical API examples, saved-query rewriting, and final membership fixtures. Affinity and confidence domain work can proceed independently.
-
-### Rejected alternatives
-
-- One scalar over membership, similarity, and confidence is rejected as a category error.
-- Thresholding affinity into membership without a conversion definition and judgment is rejected.
-- A prototype id as tag identity is rejected because model/prototype changes must not rename membership.
-- Tag-specific review queues are rejected. Membership uses `37t.12`.
-- The current `require_promotion=False` agent path is rejected.
-- Implicit hierarchical semantics are rejected.
-
-### Contract, schema, compatibility, failure, and rollback
-
-Replace derived `session_tags` with a clearly named structural `session_tag_memberships` relation. Durable user and agent membership remains `AssertionKind.TAG`, with an axis-qualified value and normal assertion lifecycle. Add a durable content-addressed `tag_prototypes` definition table only if prototypes need operator retention; vectors and affinity rows stay in embeddings/index derived tiers. `tag_affinities` records subject, prototype, model, evaluation world, score, definition, source epoch, and evidence. Structured confidence receipts live in the assertion value; the existing top-level confidence remains a convenience projection only when its calibration is declared.
-
-The index change is semantic-reparse. Prototype and durable membership copy-forward are additive user migration plus data migration behind backup. Privacy: private membership, prototype text, and affinity are not exposed by default. Performance: membership uses equality indexes; affinity uses bounded vector candidate retrieval and never joins every subject to every prototype. Unknown axis data remains unknown. Failure to resolve a conversion, calibration, or judgment fails closed. Rollback restores the user backup and prior index generation; compatibility aliases are read-only and cannot create new legacy rows.
-
-### Implementation slices
-
-| Order | Slice and owner files | Avoid list | Dependencies and parallel safety |
-| --- | --- | --- | --- |
-| U1 | `TagRef`, membership, affinity, confidence, prototype, and conversion contracts in new core/insights modules. | User and index schemas, query grammar | Can start before operator answer. |
-| U2 | Fix agent membership lifecycle in `user_write.py` and canonical judgment integration. | Namespace migration and affinity storage | Depends on `37t.12`; serial with ze5/rxdo edits to `user_write.py`. |
-| U3 | Derived membership and affinity schema/readers. | Durable user migration | Exclusive index-schema lane; can proceed with namespace parameter abstracted. |
-| U4 | Durable prototype and namespace copy-forward migration. | Any concurrent user-schema lane | Operator answer required; exclusive user-schema lane after ze5. |
-| U5 | DSL predicates and lowerers in query grammar, metadata, and SQLite/runtime matching. | Pattern grammar changes in avna | Serialize with avna grammar ownership. |
-| U6 | API/MCP/CLI/renderers and saved-query compatibility. | Storage internals | Depends on U2 through U5. |
-
-### Acceptance evidence and anti-vacuity
-
-- Seed high affinity without membership, membership with unknown affinity, and low-confidence classifier output without either axis changing.
-- Run agent `add_tag` and bulk tag through production actuators. Before judgment the candidate is `inject:false` and invisible to `tagged:`. After canonical acceptance it becomes visible exactly once.
-- An existing same-name row tests axis, actor authority, and judgment state; it cannot short-circuit a new candidate into active state.
-- Changing prototype/model/world changes affinity receipt identity but not `TagRef`.
-- Axis-mixing expressions fail with a named conversion requirement.
-- Cross-surface payloads retain axis, actor, definition, calibration, and evidence.
-- Migration tests start from a real pre-migration user.db and prove aliases, supersession, idempotency, backup manifest, and rollback.
-
-Anti-vacuity requires the real tag actuators, assertion promotion transaction, query lowerer, and union read path. Removing `require_promotion` enforcement must make the pre-judgment visibility test fail.
-
-Readiness: **operator-decision-blocked** for the durable namespace cutover. U1 can start; U2 additionally waits on `37t.12`.
-
-## `polylogue-rxdo.9`: analysis rigor
-
-### Current state and unresolved decision
-
-The operator adopted the program, but the program is not complete. Current child state is: `.9.1`, `.9.6`, `.9.7`, and `.9.12` in progress; `.9.4`, `.9.8`, and `.9.10` open; the other mechanism children are closed. Landed primitives include `EvidenceValue`, content-addressed metrics and ratios, registration ordering, public-claim validation, negative-control validation, comparative judgments, rankers, blinding, calibration, elicitation, cascades, and experiment projection.
-
-Several contracts are not yet coherent. `docs/design/analysis-rigor.md` still opens with the superseded population claim. `MetricDefinition` has a second measurement-authority vocabulary and uses `required_enumeration="exact"`, while `EvidenceValue` owns the canonical census/sample/inferred-partial axes. `registration_status` compares timestamps, epochs, and metric/query refs but not a frozen analysis-definition digest. `FindingAssertion` can store query/result/frame/evaluation refs but does not require one canonical evidence envelope. `experiments.py` consumes a structural `ExperimentDefinitionLike` because `stc` has not landed. Many mechanism modules have narrow or no production consumers.
-
-The unresolved decision is not whether the mechanisms remain. It is the closure contract that turns primitives into enforceable production claim semantics without parallel identities.
-
-### Final adjudication
-
-Adopt one `AnalysisDefinition` and one `EvidenceValue` envelope across measurements, findings, controls, experiments, and judgments.
-
-`AnalysisDefinition` is content-addressed over query refs, metric refs, frame definition, enumeration requirement, exclusions, stopping rule, analysis plan, controls, claim class, and relevant actor/execution context. Preregistration stores this definition ref before execution. Evaluation must cite the identical definition ref and a later corpus epoch. Any change yields exploratory definition drift.
-
-`EvidenceValue` remains the canonical independent-axis protocol. Exact means census-exact over the named stored frame and definition. Frame coverage, capture coverage, measurement authority, classifier uncertainty, judgment uncertainty, freshness, and temporal quality remain independent. No sampling interval appears for a census value; incomplete capture and model-derived measurement still render.
-
-`MetricDefinition` imports the core authority and enumeration vocabularies. `catalog-estimated` maps to `catalog-derived`; generic `heuristic` is removed in favor of explicit `rule-derived` or `model-derived`. Hash changes are correct because the old definition was less precise. Friendly metric names may point to the new refs, but old refs are never silently reinterpreted.
-
-`FindingAssertion` requires `analysis_definition_ref`, `metric_ref` when quantitative, and a serialized evidence value or a typed non-measurement capability declaration. Public support verdicts require frame, definition, as-of epoch, and evidence ancestry. Circular, stale, expired, private-only, or unresolved evidence blocks current-supported and cold export.
-
-Mechanism J consumes the actual versioned `stc ExperimentDefinition`, assignments, exposures, preregistration, frame, exclusions, stopping, outcomes, and metric definition. Without all of them, the result is observational/exploratory. The structural protocol remains only as a boundary interface if it prevents a layering cycle; it cannot be satisfied solely by tests with no production producer.
-
-Comparative judgment keeps tie, incomparable, abstain, insufficient evidence, partial order, judge actor, and execution-context calibration. Confidence intervals for latent rankings are judgment-process uncertainty, not sampling intervals over archive counts.
-
-### Rejected alternatives
-
-- Unqualified population exactness is rejected. The correct claim is frame-exact under named definitions.
-- A second `MeasureSpec`, `JudgeSpec`, universal receipt table, or experiment object is rejected.
-- Bootstrap intervals for missing capture/parser bias are rejected.
-- Causal wording without preregistration, assignment, exposure, and outcomes is rejected.
-- Design adoption or unit-only primitives as program completion is rejected.
-- Dashboard-first work that does not change a claim or action gate is rejected.
-
-### Contract, schema, compatibility, failure, and rollback
-
-Most finding and judgment changes fit typed assertion `value_json` without a schema bump. Immutable analysis definitions should reuse the existing durable query/definition substrate or add one narrowly owned table in a coordinated user migration; do not store them in ops. `stc` owns experiment identity and lifecycle. Derived evaluation outputs remain rebuildable unless explicitly retained as findings.
-
-Compatibility uses versioned definition protocols and friendly-name aliases. It does not preserve old hashes as if they meant the new vocabulary. Privacy and blinding are projection policies over retained provenance, not destructive omission. Performance is bounded by ancestry depth, result-set manifests, and declared evaluation budgets. Any missing required ref degrades or blocks the claim; it does not fill with prose. Rollback disables new publication/actuation gates only by restoring the prior user backup or code, while stored definitions and assertions remain readable by version.
-
-### Implementation slices
-
-| Order | Slice and owner files | Avoid list | Dependencies and parallel safety |
-| --- | --- | --- | --- |
-| R1 | Correct doctrine and canonical vocabularies in `docs/design/analysis-rigor.md`, `core/evidence_value.py`, and `insights/measurement/metric.py`. | User schema and experiments | Parallel-safe except with other evidence vocabulary work. |
-| R2 | Add `AnalysisDefinition` and definition-digest verification to measurement registration and canonicalization. | stc identity and query identity | Depends on R1. |
-| R3 | Tighten `FindingAssertion`, writer validation, public claims, and finding provenance around the common evidence envelope. | Comparative judgment storage | Serial with ze5/uh6c in `user_write.py`. |
-| R4 | Finish holdout and sampled-only uncertainty children through real query planner and result-set routes. | Generic statistics dependency | Can parallelize by separate modules after R1. |
-| R5 | Wire blinding, controls, calibration, elicitation, and cascades through all production judgment surfaces. | New judgment identity | Depends on `37t.12`; split by surface files but keep one contract owner. |
-| R6 | Replace test-only experiment fixtures with actual `stc` definitions and receipts. | Any second experiment table/type | Hard dependency on `polylogue-stc` and R2. |
-| R7 | Program reconciliation matrix for all `.9.1` through `.9.16`, with falsification receipts. | Beads state in implementation lanes | Last. Coordinator owns Beads reconciliation. |
-
-### Acceptance evidence and anti-vacuity
-
-- A census-exact value with incomplete capture and model-derived measurement renders all three facts and no sampling interval.
-- Changing any analysis-definition field after registration produces exploratory definition drift even when metric and query refs are unchanged.
-- Circular, stale, expired, ambiguous, or private-only ancestry blocks current-supported and cold export through production renderers.
-- A production experiment without any one of preregistration, assignment, exposure, frame, exclusions, stopping, or outcome receipts cannot produce a causal/confirmatory result.
-- Judgment aggregation preserves nondirected verdicts and partial-order ambiguity; actor and execution context remain separate calibration strata.
-- Every child identifies a production consumer and a mutation/removal that makes its test fail. Zero-caller modules do not satisfy program closure.
-
-Anti-vacuity requires the actual query planner, finding writer, publication exporter, compare/judge surfaces, and eventual stc producer.
-
-Readiness: **dependency-blocked** on `stc`, `9l5.7`, `37t.12`, and unfinished child work. R1 and R2 are immediately executable.
-
-## `polylogue-ze5`: user.db vocabulary and record sufficiency
-
-### Current state and unresolved decision
-
-The operator already ratified the four-class lens and surface nouns. The migration recipe is stale: current `USER_SCHEMA_VERSION` is 10, `assertions.confidence` already exists, `user_settings` is already separate state, and annotation schemas/batches already have dedicated tables. `supersedes_json` exists but there is no normalized relation table. Upserts overwrite mutable fields and preserve no general revision history. `ASSERTION_CLAIM_KINDS` is an informal epistemic subset, not a complete class registry.
-
-The unresolved implementation decision is how to land the ratified model without storing a second class value that can drift or losing durable history.
-
-### Final adjudication
-
-Keep the unified assertions table and derive `AssertionClass = epistemic | curation | workspace | comms` exhaustively from `AssertionKind`. Do not add a stored class column.
-
-Initial mapping:
-
-- Epistemic: annotation, correction, decision, caveat, lesson, blocker, run_state, prompt_eval, ontology_candidate, ontology_governance, transform_candidate, pathology, finding, judgment, comparative_judgment, secret_candidate, and excision_record.
-- Curation: mark, highlight, suppression, tag, and metadata.
-- Workspace: saved_query, recall_pack, and workspace_note.
-- Comms: note, handoff, and excision_request.
-
-`NOTE` remains comms because the current helper uses it for blackboard notes. User-facing epistemic objects use “notes”; API types and operations use “records”; `assertion` remains storage/enum terminology. Domain-specific curation, workspace, and comms surfaces retain their own nouns.
-
-The next user migration, version 11 unless another migration lands first, adds:
-
-- `assertion_relations(src_assertion_id, dst_assertion_id, relation, created_at_ms)` with relation `supersedes | contradicts | refines`, FKs, indexes in both directions, and no self-edge.
-- `assertion_revisions(assertion_id, revision_seq, body_json, created_at_ms)` with immutable per-record sequence. `body_json` is a canonical snapshot of every mutable semantic field, not only `body_text`.
-- A trigger or the single writer chokepoint inserts the old snapshot only when semantic fields change. Updated-at-only idempotent writes do not create revisions.
-
-Migration backfills `supersedes_json` into normalized relation rows. New writes use normalized relations. The old durable column remains physically present because durable destructive migration is forbidden, but it is no longer authoritative. Older binaries cannot open schema v11, so dual-writing obsolete JSON is unnecessary.
-
-Relations and revisions cascade on an authorized physical deletion so privacy excision removes historical content too. Ordinary retraction remains status plus reason and retains history.
-
-### Rejected alternatives
-
-- Per-class tables are rejected because the unified audit/query/lifecycle substrate is load-bearing.
-- A stored class column is rejected because class is a pure exhaustive derivation from kind.
-- Reusing `supersedes_json` for contradiction and refinement is rejected because relations need indexed traversal and integrity.
-- Capturing only changed prose is rejected because value, status, confidence, visibility, and policy changes are also belief/history changes.
-- Adding confidence again is rejected because it already exists. Calibrated confidence semantics belong to the owning record contract.
-- Dual-writing normalized relations and JSON indefinitely is rejected.
-
-### Contract, schema, compatibility, failure, and rollback
-
-This is an additive durable user migration with backup manifest and one-version-at-a-time upgrade. Fresh DDL and migration SQL must match. The relation vocabulary has one typed Python owner and a generator-tied DDL check or schema-policy assertion. The exhaustive class map fails if a new `AssertionKind` lacks placement.
-
-Surface compatibility changes labels and payload names only at class-appropriate boundaries. Storage ids, assertion refs, and enum wire values remain. Existing API fields may retain versioned aliases where clients depend on them, but new documentation must not call saved views or tags assertions.
-
-Revision bodies can contain private content and inherit the assertion's privacy and excision policy. Indexes keep relation traversal bounded. A failed migration restores the verified user.db backup. A failed revision insert aborts the assertion update in the same transaction. Binary downgrade requires restoring the pre-v11 database, not ignoring the version.
-
-### Implementation slices
-
-| Order | Slice and owner files | Avoid list | Dependencies and parallel safety |
-| --- | --- | --- | --- |
-| Z1 | Class registry and surface vocabulary audit in `core/enums.py`, a focused vocabulary module, glossary, and surface payload names. | User DDL and relation writers | Parallel-safe with Z2 planning, but serialize enum edits with rxdo/uh6c. |
-| Z2 | Exclusive migration: `user.py`, next numbered migration, backup/version tests, relation/revision domain types. | Any avna or uh6c user migration | Sole user-schema owner. |
-| Z3 | Writer integration and supersedes backfill/read conversion in `user_write.py` and focused relation/revision modules. | Tag authority and finding rigor changes | Depends on Z2; serial hotspot ownership. |
-| Z4 | Judge queue contradiction pairing and record history readers through API/MCP/CLI. | Storage terminology | Depends on `37t.12` for final judge transaction integration. |
-| Z5 | Generated OpenAPI/CLI schemas and vocabulary docs. | Product code | Last. |
-
-### Acceptance evidence and anti-vacuity
-
-- Upgrade a real v10 fixture through the backup-aware migrator; verify schema 11, backfilled supersedes edges, referential integrity, and restore.
-- Exhaustively map every current `AssertionKind`; adding an unmapped kind must fail registry validation.
-- Two conflicting lessons can be linked, traversed in both directions, and presented together in the production judge queue.
-- Updating semantic fields creates one immutable old snapshot. Repeating an identical upsert creates none. Updating status/confidence creates a revision.
-- Physical privacy deletion removes assertion, relations, and revisions.
-- Surface contract tests show notes/records for epistemic records, tags/marks for curation, saved views/workspaces for state, and messages/handoffs for comms.
-
-Anti-vacuity requires the production `upsert_assertion`, migration runner, judge queue reader, and public payloads. A test that inserts directly only into a fixture schema is insufficient.
-
-Readiness: **execution-ready with packet**. Z4 waits on `37t.12`; Z1 through Z3 can proceed in the exclusive user-schema lane.
-
-## `polylogue-dx1`: daemon HTTP substrate
-
-### Current state and unresolved decision
-
-The operator ratified ASGI with a presumption to proceed. Current evidence strengthens that decision: `polylogue/daemon/http.py` is about 5,500 lines, `stable_route_contracts()` declares 48 API routes, and host admission, authentication, and origin/CSRF remain separate handler calls. The daemon runs TCP and UDS `ThreadingHTTPServer` instances through `asyncio.to_thread`; shutdown needs a dedicated daemon thread to avoid `serve_forever` deadlocks. Archive reads use a bounded executor because accepted connections otherwise create unbounded threads. `/api/events` already has SSE and polling, but its handler sleeps in a request thread once per second.
-
-Starlette and uvicorn are currently transitive through MCP, not direct runtime dependencies. Browser capture is a separate `BrowserCaptureHTTPServer` and must remain outside this migration. The unresolved work is the precise compatibility ramp, lifecycle ownership, and measurable abort gate.
-
-### Final adjudication
-
-Proceed with one in-process Starlette application and one uvicorn worker for the daemon API. Add Starlette and uvicorn as direct constrained dependencies. Do not migrate the browser-capture receiver under this Bead.
-
-The ASGI app owns the public TCP and UDS listeners, composed middleware, typed parameter decoding, response/error envelopes, SSE cancellation/backpressure, route contracts, and lifecycle hooks. During migration, unmatched routes proxy to a private legacy server over an internal UDS. New routes never land on the legacy handler. One route family moves per slice, and the compatibility proxy and legacy server are deleted when the legacy route count reaches zero.
-
-Security middleware composes, in order, trusted Host admission, credential resolution, exact Origin/CSRF policy, route capability/role, request budget, and sanitized error handling. `route_contracts.py` remains the migration authority until `polylogue-3utv` generates the router, OpenAPI, and client from one typed declaration.
-
-Probe thresholds are implementer-owned guardrails: on a representative status/read/mutation/SSE mix, p95 non-streaming latency must not regress by both more than 20 percent and more than 5 ms; idle RSS must not regress by both more than 15 percent and more than 50 MiB; sustained SSE disconnects must leave no leaked tasks; write coordination, UDS, SPA, and extension-facing behavior must be compatible. A threshold breach pauses migration for diagnosis and can trigger the ratified abort.
-
-### Rejected alternatives
-
-- Staying hand-rolled is rejected by the ratified decision and growing private-framework cost.
-- New-routes-only permanent hybrid is rejected because it leaves two security and lifecycle substrates indefinitely.
-- A big-bang rewrite is rejected because 48 route contracts, the SPA, UDS clients, and mutations need family-level rollback.
-- Migrating browser capture together is rejected because it is a separate receiver and would enlarge the blast radius.
-- Multiple uvicorn workers are rejected because the daemon is one process and one SQLite writer.
-- Reimplementing auth per endpoint is rejected; it belongs in middleware plus route policy.
-
-### Contract, compatibility, performance, failure, and rollback
-
-There is no database schema change. `/metrics`, `/healthz/live`, and `/healthz/ready` remain byte-stable, including content type and status. API JSON, headers, cookies, errors, pagination, cache validators, SSE ids, heartbeat/coalescing, TCP loopback default, UDS path/mode, bearer behavior, web credentials, and write-coordinator semantics are compatibility contracts.
-
-Request bodies and paths become typed at the router boundary; domain handlers remain transport-neutral. Privacy projections remain downstream of authentication. Uvicorn uses one event loop and bounded thread offload only for blocking SQLite/domain functions. Cancellation must interrupt or abandon reads through the existing execution context without leaking a write.
-
-During the ramp, a configuration switch selects ASGI-fronted or legacy listener ownership. Rollback switches the public listener back to legacy while the route family remains available there. Once a family is removed from legacy, rollback is the prior release, not an in-tree duplicate implementation. The final deletion occurs only after a full dogfood window and zero legacy contracts.
-
-### Implementation slices
-
-| Order | Slice and owner files | Avoid list | Dependencies and parallel safety |
-| --- | --- | --- | --- |
-| D1 | Direct dependencies, ASGI app factory, typed request/error helpers, composed security middleware, and contract parity tests in new daemon modules. | Existing handler route bodies, browser capture | Parallel-safe with domain route extraction. |
-| D2 | Alternate-port probe for status plus events/SSE, with latency/RSS/task receipts. | Canonical listener ownership | Depends on D1; no deployment change. |
-| D3 | Listener lifecycle, TCP/UDS ownership, internal legacy UDS proxy, and shutdown integration in `daemon/cli.py`. | Browser capture lifecycle | Serial lifecycle hotspot. |
-| D4 | Migrate read-only route families: health/observability, sessions/query, then insights/reference. | Mutations and maintenance | One family per PR, mostly parallel extraction but serialized router registration. |
-| D5 | Migrate user mutations, ingest/reset, and maintenance through the existing write coordinator. | New write executor | Depends on D4 security and error parity. |
-| D6 | Migrate SPA/static/bootstrap, delete legacy proxy/server at zero routes, simplify shutdown and bounded-read scaffolding. | Browser capture receiver | Last, after dogfood and client smoke. |
-
-### Acceptance evidence and anti-vacuity
-
-- Byte/golden parity for health, metrics, representative JSON, errors, headers, cookies, cache validators, and SSE frames across legacy and ASGI.
-- Security matrix varies Host, Authorization, cookie credential, Origin, method, route policy, TCP/UDS, and auth-disabled local mode. Removing any middleware must expose a failing case.
-- Real daemon tests cover concurrent reads, bounded admission, timeouts, cancellation, writer serialization, graceful shutdown, UDS clients, SSE reconnect and coalescing.
-- Probe records p50/p95/p99, throughput, idle and loaded RSS, thread/task counts, disconnect cleanup, and code-per-route.
-- Required client proof: SPA smoke, extension smoke, concurrent spool/dedup, and capture-gap fixture. The receiver remains unchanged, but integrations must not regress.
-
-Anti-vacuity requires a real uvicorn listener and the production daemon app, not only Starlette's in-process test client.
-
-Readiness: **execution-ready with packet**. This adjudication unblocks `polylogue-3utv` after D1 establishes the target declaration shape.
-
-## `polylogue-fie`: archive scaling doctrine
-
-### Current state and unresolved decision
-
-The keep-everything and lever-order decisions are ratified. Current read-only evidence on 2026-08-03 shows:
-
-- Active index target: 40,554,500,096 bytes, 23,496 sessions, 4,949,871 messages, 5,070,427 blocks, and 5,001,240 FTS rows.
-- Durable source.db: 1,891,467,264 bytes and 43,124 raw rows. Logical raw blob bytes total 100,142,342,655; distinct raw blob hashes account for 72,045,958,857 bytes before the blob-directory census.
-- embeddings.db: 845,926,400 bytes; ops.db: 86,810,624 bytes; user.db: 425,984 bytes.
-- Promoted rebuild transaction wall windows: 4.37 hours for 41,363 raws and 99.0 GB, 34.95 hours for 101,347 raws and 97.4 GB, and 74.01 hours for 36,451 raws and 97.1 GB. These windows include bounded-pass idle time and are recovery-window evidence, not pure CPU benchmarks.
-
-The current code already has blue-green owned generations, one-generation rollback retention, resumable byte progress, cost receipts, bulk terminal FTS/projection rebuild, and optional sharded from-empty builds. `devtools/archive_space_report.py` can produce a dbstat census, and `tests/benchmarks/test_sharded_rebuild.py` proves small-fixture K=1/4/8 equivalence. What is missing is the required immutable-copy object census, growth projection, and current/3x/10x resource benchmark. Therefore the conditional FTS decision remains evidence-blocked, not design-blocked.
-
-### Final adjudication
-
-Keep every session and raw observation permanently unless a separate explicit privacy deletion applies. The lever order is fixed:
-
-1. Implement `polylogue-83u.5` blob zstd unconditionally with content-hash and restore proof.
-2. Measure FTS footprint and rebuild cost. Shard hot/cold FTS only if FTS is the measured dominant degradation.
-3. Continue blue-green, resumable, fresh-first index rebuilds, including from-empty sharding and kea7p differential convergence where proof permits.
-4. Do not adopt mutation-only incremental index maintenance as the source of truth.
-
-Kea7p does not violate this ruling. It replays authoritative source evidence through ordinary materialization, preserves from-empty equivalence, and escalates to blue-green. It is a convergence optimization, not abandonment of rebuildability.
-
-Cold means access-temperature placement or compression, never deletion or loss of queryability. Any cold split has one logical query contract, exact freshness metadata, and an automatic fallback when a shard is unavailable.
-
-### Rejected alternatives
-
-- Retention windows, pruning, sampling away old sessions, and destructive cold storage are rejected by permanent operator policy.
-- FTS sharding before a dbstat/consumer/rebuild census is rejected.
-- Treating historical rebuild transaction wall time as pure engine performance is rejected.
-- Incremental-only index evolution is rejected because it removes the recovery oracle and compounds semantic drift.
-- Multiple simultaneous live full walks are rejected. Measurement uses one immutable/reflink copy and one reader.
-- DuckDB is not an archive scaling lever here; ca4 owns optional analytical lowering.
-
-### Contract, schema, compatibility, failure, and rollback
-
-Blob compression is a durable source/blob representation change and needs a versioned envelope or manifest, atomic write, hash-over-uncompressed-content semantics, mixed compressed/uncompressed reads during conversion, backup/restore proof, and no recompression on dedup. FTS sharding is derived index architecture and requires a semantic index generation, unified query/continuation ordering, and exact per-shard freshness.
-
-Blue-green temporarily amplifies derived disk usage by roughly one active index plus candidate and rollback overhead. The planner must preflight free space and refuse before work. Compression must not leak private content into shared dictionaries. Corruption or unsupported codec fails closed while preserving the original blob until verified conversion. Rollback reads old envelopes and atomically restores the prior generation.
-
-### Implementation and evidence slices
-
-| Order | Slice and owner files | Avoid list | Dependencies and parallel safety |
-| --- | --- | --- | --- |
-| F1 | Serialized reflink census using `devtools/archive_space_report.py`: every table/index bytes, rows, producer, consumers, rebuild cost, unread classification. | Live write paths and parallel walkers | Independent evidence lane. |
-| F2 | Growth model from ops/source telemetry with 12/24 month ranges and assumptions. | Retention policy changes | Parallel with F1. |
-| F3 | Current/3x/10x full-index and FTS benchmark harness, recording elapsed, compute versus idle, I/O, RSS, disk amplification, and recovery window. | Production live archive and policy defaults | Depends on representative scenario fixtures; serialized heavy lane. |
-| F4 | `83u.5` zstd implementation in blob store, source metadata/migration, readers, GC, and restore tooling. | FTS and index schema | Independent implementation lane; durable blob owner. |
-| F5 | Conditional FTS shard design and implementation only if F1/F3 identify FTS as dominant. | Blob format and general query algebra | Evidence gate; exclusive index/query owner. |
-| F6 | Doctrine and operator runbook with capacity alerts, preflight, recovery, and rollback. | New policy | Last, summarizes receipts. |
-
-### Acceptance evidence and anti-vacuity
-
-- F1 scans one immutable/reflink copy with one reader and enumerates every object, including expensive unread structures with exact consumer search evidence.
-- F3 uses the real rebuild and FTS engines, not a toy loop. Remove bulk-build suppression or sharding and the timing/resource receipts must change.
-- Zstd property tests round-trip arbitrary bytes, preserve SHA-256 over original bytes, deduplicate mixed envelopes, survive crash boundaries, and restore from backup.
-- Query parity spans hot/cold boundary, global ranking, continuation, counts, and stale/unavailable shard states if FTS sharding is admitted.
-- Capacity failure tests refuse insufficient disk before creating a candidate and preserve active availability throughout a failed rebuild.
-
-Readiness: **evidence-blocked** overall. F4 is execution-ready independently; F5 cannot start until F1 and F3 prove FTS is the bottleneck.
-
-## `polylogue-ca4`: optional DuckDB OLAP
-
-### Current state and unresolved decision
-
-There is no DuckDB product dependency or lowering path. Polylogue's repository and `ArchiveStore` abstractions are SQLite-specific, and query-unit aggregate lowering is owned by SQLite. Named `agg` currently fetches at most 50,001 rows and reduces 50,000 in Python, marking larger results inexact. `polylogue-9l5.7` remains open and owns honest measure composition; `polylogue-4p1` remains open and owns the executable read algebra; `polylogue-5dx` owns evaluated optional dependency policy. A separate audit-tool Bead mentions DuckDB as development tooling, which does not authorize a product dependency.
-
-The operator ratified the decision threshold: below 10x, including the 3x to 10x band, remain SQLite-only. The unresolved work is when to trigger the probe and where a successful lowerer would live.
-
-### Final adjudication
-
-Stay SQLite-only now. Do not run or implement a DuckDB product probe until `9l5.7` defines canonical measures and at least five real analytics workloads exceed the SQLite/Python ceiling.
-
-If triggered, the probe runs both engines from the same engine-neutral `AnalysisPlan` or measure-lowering IR. SQLite remains the default and correctness oracle. DuckDB is an optional `analytics` extra and a read-only lowerer selected only for plans explicitly classified heavy.
-
-The adoption gate is:
-
-1. Exact result parity on seeded and live-snapshot data, including NULLs, integer/float/decimal behavior, timestamps, ordering, collation, percentiles, and empty groups.
-2. Five real queries spanning transition/process joins, window/survival analysis, percentile/group aggregation, block scans, and one current named-aggregate ceiling.
-3. Median warm wall-time speedup at least 10x, at least four of five queries at least 3x, no query more than 20 percent slower, and peak RSS no more than 2x unless the absolute memory budget is separately approved.
-4. Safe concurrency through an immutable SQLite snapshot or a proven WAL-consistent scanner path. Direct attachment to an actively written live file is not assumed safe.
-
-Query ownership stays in insights/product analysis definitions and `9l5.7` lowerer interfaces. Backend adapters emit SQLite or DuckDB SQL. DuckDB never owns public query semantics, canonical identity, persistence, writes, migrations, or source truth.
-
-### Rejected alternatives
-
-- Adopting from generic 10x to 100x database reputation is rejected; Polylogue needs real workload evidence.
-- A 3x middle-band adoption is rejected by ratified policy because a second engine has ongoing dependency and parity cost.
-- Direct DuckDB calls from CLI/MCP/daemon or storage repository mixins are rejected as architecture leaks.
-- Attaching the live WAL database without a concurrency proof is rejected.
-- Persisting DuckDB copies or results as a second archive is rejected.
-- Using DuckDB to avoid implementing canonical measure semantics is rejected.
-
-### Contract, compatibility, privacy, failure, and rollback
-
-No schema change is authorized now. A successful future adoption adds only an optional dependency group, an engine-neutral lowerer protocol, and a DuckDB adapter. Canonical query/metric refs hash engine-neutral semantics, not selected backend. Receipts record engine, versions, snapshot epoch, plan ref, timing, RSS, and parity hash.
-
-The optional path sees the same private data as SQLite and must use local files, private temp permissions, no extension auto-download, and no network. Missing dependency or adapter failure falls back to SQLite only when the plan remains within its budget; otherwise it returns a typed unavailable/over-budget result. It never silently returns a capped Python sample as exact. Rollback removes the optional adapter and leaves every stored identity/result readable through SQLite.
-
-### Implementation slices
-
-| Order | Slice and owner files | Avoid list | Dependencies and parallel safety |
-| --- | --- | --- | --- |
-| O1 | `9l5.7` canonical measure identity and engine-neutral lowering IR. | DuckDB dependency and adapter | Hard prerequisite; owns measure semantics. |
-| O2 | Select and freeze five production workloads plus correctness fixtures. | Engine-specific optimizations | Depends on analytics consumers and O1. |
-| O3 | Read-only DuckDB lab probe, using snapshot and resource receipts. | Runtime product dependency | Evidence-only and optional dev environment. |
-| O4 | Decision gate evaluation. Stay SQLite-only or authorize the optional adapter. | Product code before receipt | Coordinator/operator record; no implementation if threshold fails. |
-| O5 | If authorized, add `[analytics]`, adapter, planner selection, and one heavy production measure. | Writes, source tiers, public surface branching | Depends on `4p1`, `5dx`, and O4. |
-
-### Acceptance evidence and anti-vacuity
-
-- Query parity compares typed values and deterministic ordering, not only row counts.
-- Concurrency tests run a real daemon writer while the probe uses the declared snapshot/scanner method and detect locks, stale reads, or WAL omissions.
-- Benchmark runs cold and warm repetitions, records versions and cache state, and reports wall time plus RSS.
-- The production demonstration, if adopted, executes the same `AnalysisPlan` through both real lowerers. Removing DuckDB selection must change the engine receipt while preserving results; mutating NULL/order semantics must fail parity.
-- Absence of DuckDB must leave all default CLI, MCP, API, daemon, and package tests functional.
-
-Readiness: **dependency-blocked** on `9l5.7`, real analytics workloads, and then `4p1`/`5dx` for any adoption. The current executable decision is to remain SQLite-only.
-
-## Cross-Bead dependency graph and Luna dispatch order
-
-```text
-slshy -> xselt -> 818fy -> kea7p K1-K5
- ^
- +-- qj5x (excluded content/identity lane)
-
-b5l -----------------------> kea7p planner/prove/activate
- +------------------------> fie blue-green recovery doctrine
-
-ze5 Z1-Z3 --exclusive user schema--> avna A6
- +---------------------------> uh6c U4
-37t.12 ------------------------------> uh6c U2 and rxdo R5
-
-4p1 query algebra -----> avna integration
- +---> ca4 future adapter
-9l5.7 -------------> rxdo metric/statistical closure
- +----------------> ca4 probe IR
-stc ----------------> rxdo experiment projection
-
-cijx trajectories ---> rxdo G6/G8 evaluation evidence
-avna match sets ------> rxdo pattern-derived analyses
-83u.5 ----------------> fie unconditional compression
-dx1 D1 ---------------> 3utv typed route registry
-```
-
-Recommended dispatch waves:
-
-1. Wave 0, blockers and exclusive migrations: `slshy`, then `xselt`; ze5 Z1 through Z3 as the sole user-schema lane; dx1 D1/D2 probe; fie F1/F2 evidence. These have disjoint primary files except global enum edits, which the coordinator must serialize.
-2. Wave 1, independent domains: avna A1/A3, cijx C1/C2, uh6c U1, rxdo R1/R2, fie F3/F4, and dx1 D3. Do not let avna and uh6c edit query grammar concurrently. Do not let cijx and kea7p edit index DDL/write concurrently.
-3. Wave 2, storage and production wiring: cijx C3 as exclusive index owner, then uh6c U3, then kea7p K2/K3 after bootstrap. Run avna A2/A4/A5 when it owns query files. Run ze5 Z4 and rxdo R3/R5 only with explicit `user_write.py` ownership.
-4. Wave 3, dependency consumers: avna A6 after ze5; uh6c U4 after the operator namespace answer and ze5; rxdo R6 after stc; ca4 O1/O2 after 9l5.7; dx1 route-family migration; conditional FTS work only after fie evidence.
-5. Wave 4, closures: differential proof and activation, ASGI zero-route legacy deletion, rxdo child reconciliation, scaling doctrine report, and optional DuckDB gate. The coordinator, not implementation lanes, updates or closes Beads.
-
-Hotspot exclusion matrix:
-
-| Hotspot | Sole owner at a time | Lanes that must wait |
-| --- | --- | --- |
-| `storage/sqlite/archive_tiers/user.py` and user migrations | ze5, then avna A6 or uh6c U4 | rxdo durable definition work |
-| `storage/sqlite/archive_tiers/index.py` and `write.py` | xselt, then cijx C3, uh6c U3, kea7p K2 | fie FTS schema work |
-| `archive/query/expression.py`, predicate/AST, metadata | avna A1/A2/A5 | uh6c U5, ca4 plan syntax |
-| `storage/sqlite/archive_tiers/user_write.py` | ze5 Z3, uh6c U2, rxdo R3/R5 | all other assertion lanes |
-| `daemon/cli.py` and HTTP lifecycle | dx1 D3/D6 | kea7p daemon adapter changes |
-| `maintenance/rebuild_index.py`, `storage/index_generation.py` | kea7p K3 with b5l coordination | fie rebuild implementation changes |
-
-## Evidence commands used for this adjudication
-
-All commands were read-only except creation of this document and its commit.
-
-```text
-jq select(...) .beads/issues.jsonl
-rg and sed over query AST, runtime matching, SQLite lowerers, repository identity, file edits, tags, assertions, judgment/measurement modules, daemon routing/lifecycle, tier DDL, rebuild code, optional dependencies, and tests
-git log origin/master --oneline, git log -S, and git log --grep over the relevant files and concepts
-readlink -f /realm/db/polylogue/index.db
-stat on the active index target and archive tier files
-sqlite3 -readonly against index.db and source.db for row and byte counts
-read-only parsing of .index-rebuild-transactions/*.json
-```
-
-The live object-level dbstat census and representative current/3x/10x rebuild benchmarks were not completed here. They are deliberately retained as `fie` evidence work rather than inferred from file size or historical transaction wall windows.
diff --git a/docs/plans/degrade-loudly-allowlist.yaml b/docs/plans/degrade-loudly-allowlist.yaml
deleted file mode 100644
index c2965fa0c8..0000000000
--- a/docs/plans/degrade-loudly-allowlist.yaml
+++ /dev/null
@@ -1,516 +0,0 @@
-# Pre-approved broad except-handlers for `devtools verify degrade-loudly`
-# (polylogue-cpf.4). Each entry documents WHY the handler already carries a
-# degradation signal (or is safely fail-closed) despite having no log call.
-# Keyed by (path, function qualname, exception set, occurrence-within-function)
-# rather than line number, so unrelated edits elsewhere in the file don't
-# require re-numbering. New broad excepts must either log, or be added here
-# with a real rationale -- not a rubber stamp.
-#
-# Generated 2026-07-12 during the polylogue-cpf.4 degrade-loudly sweep after
-# converting ~35 genuine silent-failure sites to log/signal; these are the
-# audited remainder that already signal via a typed return value, a
-# convergence_debt/HealthAlert/_repair_result-style mechanism, or a
-# documented fail-safe direction.
-
-entries:
-- path: polylogue/daemon/backup.py
- function: ._check_prerequisites
- exceptions:
- - Exception
- occurrence: 0
- reason: 'Appends f"disk space check failed: {exc}" to the warnings list it returns -- a typed signal
- via the list itself, not a log call.'
-- path: polylogue/daemon/backup.py
- function: ._readable_sqlite
- exceptions:
- - Error
- occurrence: 0
- reason: Returns str(exc) itself as the "why unreadable" reason -- the exception text is the signal.
-- path: polylogue/daemon/backup.py
- function: ._verify_backup_result
- exceptions:
- - Exception
- occurrence: 0
- reason: 'Both sites already build {"ok": False, "error": str(exc)} / result.error = f"...: {exc}" typed
- signals.'
-- path: polylogue/daemon/backup.py
- function: ._verify_backup_result
- exceptions:
- - Exception
- occurrence: 1
- reason: 'Both sites already build {"ok": False, "error": str(exc)} / result.error = f"...: {exc}" typed
- signals.'
-- path: polylogue/daemon/cli.py
- function: ._close_raw_materialization_fts
- exceptions:
- - Exception
- occurrence: 0
- reason: Records the failure via _record_raw_materialization_fts_debt(index_db, reason) -- signals through
- convergence_debt, the pattern polylogue-cpf.4 explicitly says to leave alone.
-- path: polylogue/daemon/cli.py
- function: ._close_raw_materialization_fts
- exceptions:
- - Exception
- occurrence: 1
- reason: Records the failure via _record_raw_materialization_fts_debt(index_db, reason) -- signals through
- convergence_debt, the pattern polylogue-cpf.4 explicitly says to leave alone.
-- path: polylogue/daemon/convergence_debt_alert.py
- function: .source_family_for_path
- exceptions:
- - Exception
- occurrence: 0
- reason: Returns the explicit "unknown" sentinel, distinguishable from any real family token.
-- path: polylogue/daemon/fts_startup.py
- function: ._blocks_search_text_has_rows_sync
- exceptions:
- - Error
- occurrence: 0
- reason: None triggers the not-ready path in the startup repair decision (fail-toward-needs-work).
-- path: polylogue/daemon/fts_startup.py
- function: ._count_or_zero
- exceptions:
- - Error
- occurrence: 0
- reason: Narrow startup probe; 0 is the fail-toward-repair default consumed by the FTS startup-readiness
- decision (safe direction, matches the 1xc.11 precedent).
-- path: polylogue/daemon/fts_startup.py
- function: ._message_fts_docsize_has_rows_sync
- exceptions:
- - Error
- occurrence: 0
- reason: False triggers the not-ready path in the startup repair decision (fail-toward-needs-work).
-- path: polylogue/daemon/fts_startup.py
- function: ._message_fts_freshness_row_sync
- exceptions:
- - Error
- occurrence: 0
- reason: None triggers the not-ready path in the startup repair decision (fail-toward-needs-work).
-- path: polylogue/daemon/health.py
- function: ._archive_repeated_stage_failure_info
- exceptions:
- - Error
- occurrence: 0
- reason: 'Internal fallback: None triggers the local-tier query in the caller (_check_repeated_stage_failures_medium),
- which itself returns a typed HealthAlert(severity=ERROR) on its own failure.'
-- path: polylogue/daemon/health.py
- function: ._check_blob_integrity_expensive
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_blob_reference_debt_expensive
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_convergence_debt_medium
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_cursor_lag_anomaly_layer
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_cursor_lag_medium
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_daemon_liveness_fast
- exceptions:
- - Exception
- occurrence: 0
- reason: 'Returns HealthAlert(severity=ERROR, message=f"...: {exc}") -- a typed degradation signal, the
- established pattern for every _check_*_{fast,medium,expensive} probe in this file.'
-- path: polylogue/daemon/health.py
- function: ._check_db_integrity_expensive
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_disk_space_fast
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_embedding_coverage_expensive
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_fts_readiness_medium
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_health_tier_coverage_fast
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_heartbeat_staleness_fast
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_hook_flow_fast
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_insight_freshness_medium
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_raw_failures_medium
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_repeated_stage_failures_medium
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_schema_drift_medium
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern (polylogue-da1).'
-- path: polylogue/daemon/health.py
- function: ._check_schema_version_fast
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_source_availability_fast
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_stale_ingest_attempts_medium
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/health.py
- function: ._check_wal_size_fast
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See _check_daemon_liveness_fast: same HealthAlert(severity=ERROR) pattern.'
-- path: polylogue/daemon/http.py
- function: ._handle_health
- exceptions:
- - Error
- - OSError
- occurrence: 0
- reason: quick_check_ok=False is the safe fail-toward-unhealthy direction and is itself the boolean field
- the JSON response reports.
-- path: polylogue/daemon/metrics.py
- function: .format_metrics
- exceptions:
- - Exception
- occurrence: 0
- reason: polylogue_version = "unknown" is an explicit sentinel distinguishable from any real version
- string.
-- path: polylogue/daemon/status.py
- function: ._archive_debt_status_summary
- exceptions:
- - Exception
- occurrence: 0
- reason: 'Returns {"available": False, ...} -- the available flag already distinguishes this from a successful
- lookup.'
-- path: polylogue/daemon/status.py
- function: ._archive_insight_freshness_info
- exceptions:
- - Error
- occurrence: 0
- reason: 'Internal fallback: None triggers the local-DB query in the caller (_insight_freshness_info),
- which now logs on its own failure (fixed in this sweep).'
-- path: polylogue/daemon/status.py
- function: ._archive_live_cursor_summary_info
- exceptions:
- - Error
- occurrence: 0
- reason: 'Internal fallback: None triggers the local-DB query in the caller (_live_cursor_summary_info),
- which now logs on its own failure (fixed in this sweep).'
-- path: polylogue/daemon/status.py
- function: ._archive_live_ingest_attempt_summary_info
- exceptions:
- - Error
- occurrence: 0
- reason: 'Internal fallback: None triggers the local-DB query in the caller (_live_ingest_attempt_summary_info),
- which now logs on its own failure (fixed in this sweep).'
-- path: polylogue/daemon/status.py
- function: ._raw_replay_backlog_info
- exceptions:
- - Exception
- occurrence: 0
- reason: 'Returns {"available": False, "reason": str(exc), ...} -- an already-typed signal.'
-- path: polylogue/daemon/status_snapshot.py
- function: ._minimal_status_payload
- exceptions:
- - Exception
- occurrence: 0
- reason: Captures refresh_error = refresh_error or str(exc), threaded into the returned snapshot payload
- -- a typed signal.
-- path: polylogue/daemon/status_snapshot.py
- function: .refresh_status_snapshot
- exceptions:
- - Exception
- occurrence: 0
- reason: Captures refresh_error = str(exc) and passes it into _minimal_status_payload(refresh_error=...)
- -- a typed signal.
-- path: polylogue/insights/audit.py
- function: .build_insight_rigor_audit_report
- exceptions:
- - Exception
- occurrence: 0
- reason: 'Captures error = f"{type(exc).__name__}: {exc}" and merges it into the returned entry via model_copy(update={"error":
- error}) -- a typed signal.'
-- path: polylogue/storage/archive_readiness.py
- function: .missing_source_raw_session_evidence
- exceptions:
- - Error
- occurrence: 0
- reason: 'Returns {"available": False, "reason": str(exc), ...} -- an already-typed signal.'
-- path: polylogue/storage/archive_readiness.py
- function: .raw_materialization_readiness_snapshot
- exceptions:
- - Exception
- occurrence: 0
- reason: 'Returns {"available": False, "error": str(exc)} -- an already-typed signal.'
-- path: polylogue/storage/archive_readiness.py
- function: ._action_readiness_counts
- exceptions:
- - Error
- occurrence: 0
- reason: 'Sets actions_view_error = str(exc) in the returned counts dict -- an already-typed signal.
- Extracted from polylogue/cli/commands/status.py (polylogue-ogn1 layering fix); pre-existing
- behavior, unchanged by the move.'
-- path: polylogue/storage/archive_readiness.py
- function: .archive_readiness_status
- exceptions:
- - Error
- occurrence: 0
- reason: 'Returns {"checked": False, "reason": str(exc), "surfaces": {}} -- an already-typed signal.
- Extracted from polylogue/cli/commands/status.py (polylogue-ogn1 layering fix); pre-existing
- behavior, unchanged by the move.'
-- path: polylogue/insights/schema_drift.py
- function: .schema_drift_status
- exceptions:
- - Error
- occurrence: 0
- reason: 'Returns {"available": False, "reason": str(exc)} -- an already-typed signal.
- Extracted from polylogue/cli/commands/status.py (import-tax fix); pre-existing
- behavior, unchanged by the move.'
-- path: polylogue/insights/schema_drift.py
- function: .schema_drift_status
- exceptions:
- - Error
- occurrence: 1
- reason: 'Returns {"available": False, "reason": str(exc)} -- an already-typed signal.
- Extracted from polylogue/cli/commands/status.py (import-tax fix); pre-existing
- behavior, unchanged by the move.'
-- path: polylogue/storage/artifacts/inspection.py
- function: ._hermes_state_db_schema_version
- exceptions:
- - Error
- occurrence: 0
- reason: Narrow schema-version probe; None ("unknown version") is the fail-safe default already distinct
- from a real version int.
-- path: polylogue/storage/artifacts/inspection.py
- function: .inspect_raw_artifact
- exceptions:
- - Exception
- occurrence: 0
- reason: Falls through to classify_artifact_path()-derived kind/reason fields on the constructed record
- rather than raising -- an already-typed fallback classification, not a bare default.
-- path: polylogue/storage/blob_gc.py
- function: ._database_has_table
- exceptions:
- - Error
- occurrence: 0
- reason: Narrow schema probe; False ("table absent") is the fail-safe direction already consumed defensively
- by callers.
-- path: polylogue/storage/embeddings/materialization.py
- function: ._embedding_status_row_exists
- exceptions:
- - Error
- occurrence: 0
- reason: 'True on error is the conservative default for this specific caller: it runs immediately after
- vec_provider.upsert() succeeded, so treating a post-hoc verification-query failure as "row exists"
- avoids a false no_embeddable_messages misclassification of a session that was actually embedded. This
- is not the 1xc.11 fail-toward-needs-work pattern; the safe direction here is inverted by the calling
- context.'
-- path: polylogue/storage/embeddings/materialization.py
- function: ._qualified_table_exists
- exceptions:
- - Error
- occurrence: 0
- reason: Narrow schema probe; False ("table absent") is the fail-safe direction.
-- path: polylogue/storage/embeddings/materialization.py
- function: ._table_columns
- exceptions:
- - Error
- occurrence: 0
- reason: Narrow schema probe; an empty column set is the fail-safe direction (callers treat missing columns
- as "feature unavailable").
-- path: polylogue/storage/embeddings/materialization.py
- function: ._qualified_table_columns
- exceptions:
- - Error
- occurrence: 0
- reason: Attached-schema sibling of _table_columns; same narrow schema probe over a cross-database qualified
- table name. An empty column set is the fail-safe direction -- callers (the v3 freshness-predicate column
- check) treat missing columns as "legacy/pre-v3 fixture" and fall back to the content-aware selector.
-- path: polylogue/storage/embeddings/materialization.py
- function: .embed_archive_session_sync
- exceptions:
- - Exception
- occurrence: 0
- reason: Calls mark_session_embedding_error(...) -- an already-typed signal recorded in the embedding_status
- tier.
-- path: polylogue/storage/embeddings/materialization.py
- function: .embed_session_sync
- exceptions:
- - Exception
- occurrence: 0
- reason: Calls _record_embedding_failure(...) and returns EmbedSessionOutcome(status="error", error=str(exc))
- -- an already-typed signal.
-- path: polylogue/storage/embeddings/preflight.py
- function: ._is_archive_index
- exceptions:
- - Error
- occurrence: 0
- reason: Narrow probe; False ("not a usable archive index") is the fail-safe direction that causes the
- candidate path to be skipped rather than mistakenly opened.
-- path: polylogue/storage/embeddings/status_payload.py
- function: ._archive_catchup_runs
- exceptions:
- - Error
- occurrence: 0
- reason: Feeds latest_catchup_run/latest_material_catchup_run, informational display fields that render
- as null for both "no runs" and "query failed" -- low severity (not a gating/health signal).
-- path: polylogue/storage/embeddings/status_payload.py
- function: ._sqlite_stat1_index_rows
- exceptions:
- - Error
- occurrence: 0
- reason: Narrow planner-stat probe; None ("unknown") is the fail-safe default for an optional diagnostic
- field.
-- path: polylogue/storage/repair.py
- function: ._archive_index_present
- exceptions:
- - Error
- occurrence: 0
- reason: Narrow probe; False ("index not present/versioned") is the fail-safe direction.
-- path: polylogue/storage/repair.py
- function: .repair_empty_sessions
- exceptions:
- - Exception
- occurrence: 0
- reason: 'Returns _repair_result(..., success=False, detail=f"Repair failed: {exc}") -- an already-typed
- signal, the established pattern for every repair_* function in this file (formerly the
- shared _run_sql_repair helper, inlined here on polylogue-ne6k since the empty-session
- predicate is no longer pure SQL).'
-- path: polylogue/storage/repair.py
- function: ._raw_artifact_positively_fails_classification
- exceptions:
- - Exception
- occurrence: 0
- reason: 'Classification failure is not itself an error worth surfacing here: absence of
- positive evidence (including a raw artifact that fails to decode/classify) always means
- "retain", the same fail-safe direction as every other predicate in this function. The
- caller (repair_empty_sessions) already surfaces any real repair-level failure through its
- own typed _repair_result.'
-- path: polylogue/storage/repair.py
- function: .repair_session_insights
- exceptions:
- - Exception
- occurrence: 0
- reason: 'See repair_empty_sessions: same _repair_result(success=False, detail=f"...: {exc}") pattern.'
-- path: polylogue/storage/sqlite/archive_tiers/archive_plan.py
- function: ._read_user_version
- exceptions:
- - Error
- occurrence: 0
- reason: 'Narrow user_version probe (two except blocks: connect, then PRAGMA read); None ("unknown version")
- is the fail-safe default.'
-- path: polylogue/storage/sqlite/archive_tiers/archive_plan.py
- function: ._read_user_version
- exceptions:
- - Error
- occurrence: 1
- reason: 'Narrow user_version probe (two except blocks: connect, then PRAGMA read); None ("unknown version")
- is the fail-safe default.'
-- path: polylogue/storage/sqlite/maintenance.py
- function: .maybe_optimize_archive_tiers
- exceptions:
- - Error
- occurrence: 0
- reason: Appends a SqliteOptimizeObservation capturing the exception -- an already-typed signal.
-- path: polylogue/storage/sqlite/maintenance.py
- function: .maybe_optimize_sqlite
- exceptions:
- - Error
- occurrence: 0
- reason: Returns SqliteOptimizeObservation(reason=reason, ran=False, ...) with the exception captured
- -- an already-typed signal.
-- path: polylogue/storage/sqlite/sqlite_vec_extension.py
- function: .try_load_sqlite_vec
- exceptions:
- - Exception
- occurrence: 0
- reason: Returns (False, exc) -- the exception object itself is the signal, not discarded.
-- path: polylogue/storage/sqlite/sqlite_vec_extension.py
- function: .try_load_sqlite_vec_async
- exceptions:
- - Exception
- occurrence: 0
- reason: Returns (False, exc) -- the exception object itself is the signal, not discarded.
-- path: polylogue/storage/sqlite/wal_checkpoint.py
- function: .maybe_checkpoint_wal
- exceptions:
- - Error
- occurrence: 0
- reason: Captures error = str(exc), included in the returned checkpoint result -- an already-typed signal.
-- path: polylogue/storage/usage.py
- function: ._source_raw_stats
- exceptions:
- - Error
- occurrence: 0
- reason: 'Returns ({}, {}, f"...: {exc}") -- the third tuple element is an already-typed reason string.'
-- path: polylogue/storage/usage.py
- function: ._source_schema_alias
- exceptions:
- - Error
- occurrence: 0
- reason: Narrow ATTACH-DATABASE probe; None ("no usable source alias") is the fail-safe direction.
-- path: polylogue/storage/usage.py
- function: ._table_exists_in_schema
- exceptions:
- - Error
- occurrence: 0
- reason: Narrow schema probe; False ("table absent") is the fail-safe direction.
diff --git a/docs/plans/demo-corpus-construct-audit.md b/docs/plans/demo-corpus-construct-audit.md
deleted file mode 100644
index 29eb4dab49..0000000000
--- a/docs/plans/demo-corpus-construct-audit.md
+++ /dev/null
@@ -1,104 +0,0 @@
-# Demo Corpus Construct Audit
-
-
-
-This datasheet is generated from the deterministic demo family registry, the declared construct registry, and a fresh no-daemon seed/verify run. It exists to keep demo claims construct-valid instead of relying on a hand-maintained table.
-
-## Evidence Snapshot
-
-- Seed command: `devtools render demo-corpus-datasheet` seeds a throwaway archive under `.cache/demo-corpus-datasheet/archive` with overlays enabled.
-- Verifier: `polylogue demo verify --require-overlays` semantics via `verify_demo_archive`.
-- Verifier result: `ok`.
-- Problems: —
-
-## Current Demo Archive Coverage
-
-| Fact | Current |
-| --- | ---: |
-| Sessions | 19 |
-| Messages | 71 indexed |
-| Blocks | 121 |
-| Session profiles | 19 |
-| Origins | aistudio-drive, antigravity-session, chatgpt-export, claude-ai-export, claude-code-session, codex-session, gemini-cli-session, hermes-session |
-| Run rows | 19 |
-| Observed-event rows | 43 |
-| Context-snapshot rows | 19 |
-
-## Declared Source Families
-
-| Family | Provider | Source paths | Construct IDs | Synthetic |
-| --- | --- | --- | --- | --- |
-| `chatgpt-dialogue` | `chatgpt` | `chatgpt/demo-00.json` | `multi_origin_sessions` `session_profiles` | `true` |
-| `claude-code-tools` | `claude-code` | `claude-code/demo-00.jsonl` | `tool_use_blocks` `tool_result_blocks` `failed_tool_results` `provider_usage_messages` `run_projection_rows` `observed_event_rows` `context_snapshot_rows` | `true` |
-| `claude-ai-temporary` | `claude-ai` | `claude-ai/temporary-demo.json` | `temporary_session_rows` `token_budget_web_constructs` | `false` |
-| `browser-capture-gap` | `browser-capture` | `browser-capture/chatgpt-raw-provider.json` `browser-capture/chatgpt-dom-fallback.json` | `capture_gap_events` `browser_capture_raw_variants` `browser_capture_coalesced_session` `source_outage_interval_events` | `false` |
-| `cross-material-duplicate` | `chatgpt` | `chatgpt/duplicate-source-export.json` `browser-capture/duplicate-capture.json` | `ambiguous_cross_material_duplicate` | `false` |
-| `codex-tools` | `codex` | `codex/demo-00.jsonl` | `tool_use_blocks` `tool_result_blocks` `failed_tool_results` | `true` |
-| `evidence-lab-receipts` | `codex` | `codex/receipts.jsonl` `codex/anti-grep-control.jsonl` | `receipts_failed_test_action` `receipts_successful_recovery_action` `receipts_conflicting_claim` `anti_grep_control` | `false` |
-| `gemini-attachments` | `gemini` | `gemini/demo-00.json` | `attachment_rows` `acquired_attachment_rows` | `true` |
-| `gemini-cli-session` | `gemini-cli` | `gemini-cli/demo-00.json` | `gemini_cli_origin_rows` | `false` |
-| `antigravity-session` | `antigravity` | `antigravity/demo-00.json` | `antigravity_origin_rows` | `false` |
-| `hermes-session` | `hermes` | `hermes/demo-00.json` | `hermes_origin_rows` | `false` |
-| `agent-lineage-matrix` | `mixed-agent` | `codex/lineage-parent.jsonl` `codex/lineage-fork.jsonl` `codex/lineage-subagent.jsonl` `codex/terminal-error.jsonl` `claude-code/lineage-compaction-parent.jsonl` `claude-code/agent-acompact-demo.jsonl` `claude-code/lineage-sidechain.jsonl` | `session_link_rows` `generic_branch_links` `prefix_sharing_links` `continuation_links` `subagent_links` `sidechain_sessions` `compaction_events` `subagent_context_snapshots` `subagent_run_rows` `unfinished_terminal_state_rows` `error_terminal_state_rows` `compaction_omits_failed_attempt` | `false` |
-| `embedding-lane-prose` | `derived-embedding` | `claude-code/demo-00.jsonl` `embeddings.db` | `embedding_candidate_prose_messages` `synthetic_message_embedding_rows` `embedding_status_rows` | `false` |
-
-## Declared Construct Coverage
-
-| Construct | Required coverage | Status |
-| --- | ---: | --- |
-| Multi-origin sessions (`multi_origin_sessions`) | >= 3 | `ok` |
-| Session profiles (`session_profiles`) | >= 3 | `ok` |
-| Tool-use blocks (`tool_use_blocks`) | >= 1 | `ok` |
-| Tool-result blocks (`tool_result_blocks`) | >= 1 | `ok` |
-| Failed tool results (`failed_tool_results`) | >= 1 | `ok` |
-| Provider usage messages (`provider_usage_messages`) | >= 1 | `ok` |
-| Attachment rows (`attachment_rows`) | >= 1 | `ok` |
-| Acquired attachment rows (`acquired_attachment_rows`) | >= 1 | `ok` |
-| Temporary session rows (`temporary_session_rows`) | >= 1 | `ok` |
-| Token-budget web constructs (`token_budget_web_constructs`) | >= 1 | `ok` |
-| Capture-gap events (`capture_gap_events`) | >= 1 | `ok` |
-| Browser-capture raw variants (`browser_capture_raw_variants`) | >= 3 | `ok` |
-| Browser-capture coalesced session (`browser_capture_coalesced_session`) | >= 1 | `ok` |
-| Source-outage interval events (`source_outage_interval_events`) | >= 1 | `ok` |
-| Ambiguous cross-material duplicate (`ambiguous_cross_material_duplicate`) | >= 1 | `ok` |
-| Compaction omits a failed attempt (`compaction_omits_failed_attempt`) | >= 1 | `ok` |
-| Gemini CLI origin rows (`gemini_cli_origin_rows`) | >= 1 | `ok` |
-| Antigravity origin rows (`antigravity_origin_rows`) | >= 1 | `ok` |
-| Hermes origin rows (`hermes_origin_rows`) | >= 1 | `ok` |
-| Session-link rows (`session_link_rows`) | >= 1 | `ok` |
-| Generic branch links (`generic_branch_links`) | >= 1 | `ok` |
-| Prefix-sharing lineage links (`prefix_sharing_links`) | >= 1 | `ok` |
-| Continuation links (`continuation_links`) | >= 1 | `ok` |
-| Subagent links (`subagent_links`) | >= 1 | `ok` |
-| Sidechain sessions (`sidechain_sessions`) | >= 1 | `ok` |
-| Compaction events (`compaction_events`) | >= 1 | `ok` |
-| Run projection rows (`run_projection_rows`) | >= 1 | `ok` |
-| Observed-event rows (`observed_event_rows`) | >= 1 | `ok` |
-| Context snapshot rows (`context_snapshot_rows`) | >= 1 | `ok` |
-| Subagent context snapshots (`subagent_context_snapshots`) | >= 1 | `ok` |
-| Subagent run rows (`subagent_run_rows`) | >= 1 | `ok` |
-| Unfinished terminal-state rows (`unfinished_terminal_state_rows`) | >= 1 | `ok` |
-| Error terminal-state rows (`error_terminal_state_rows`) | >= 1 | `ok` |
-| Receipts failed test action (`receipts_failed_test_action`) | >= 1 | `ok` |
-| Receipts successful recovery action (`receipts_successful_recovery_action`) | >= 1 | `ok` |
-| Receipts conflicting claim (`receipts_conflicting_claim`) | >= 1 | `ok` |
-| Anti-grep negative control (`anti_grep_control`) | >= 1 | `ok` |
-| Embedding candidate prose messages (`embedding_candidate_prose_messages`) | >= 1 | `ok` |
-| Synthetic message embedding rows (`synthetic_message_embedding_rows`) | >= 1 | `ok` |
-| Embedding status rows (`embedding_status_rows`) | >= 1 | `ok` |
-
-## Interpretation Notes
-
-- Families go through normal parser/storage paths; the demo does not patch rows directly into the index tier.
-- Codex `forked_from_id` is measured as a generic `branch` link with `prefix-sharing` inheritance because source evidence proves parentage and shared prefix, not fork-vs-resume.
-- Claude Code `agent-acompact-*` measures a continuation link and compaction event; the sidechain source measures typed sidechain session state.
-- Browser-capture convergence is measured across `source.db` and `index.db`: three raw observations for the same ChatGPT native id remain durable while the canonical indexed session stays singular and raw-linked.
-- Resume/abandonment demo coverage is grounded in structural `session_profiles.terminal_state` values (`question_left`, `tool_left`, `error_left`). The demo intentionally does not invent a source-declared `abandoned` or `censored` flag.
-- Parent-side subagent runs use distinct `run_ref` values from the child session's own main run, so both execution views can coexist.
-- Embedding coverage uses deterministic synthetic vectors over authored demo prose; it proves non-empty embedding-tier/status surfaces without contacting an external provider.
-
-## Residual Gaps
-
-| Gap | Current evidence | Driver beads |
-| --- | --- | --- |
-| None | Every declared construct currently has non-empty seeded coverage. | — |
diff --git a/docs/plans/distribution-coverage.yaml b/docs/plans/distribution-coverage.yaml
deleted file mode 100644
index d8aec5fc13..0000000000
--- a/docs/plans/distribution-coverage.yaml
+++ /dev/null
@@ -1,204 +0,0 @@
-# Distribution-coverage manifest.
-#
-# Documents the current state of install-artifact parity across
-# wheel, sdist, Nix package, and OCI container. The local distribution
-# gate now builds wheel/sdist artifacts, rebuilds from unpacked sdist
-# without .git, smokes installed runtime entrypoints, and is wired into
-# CI (.github/workflows/ci.yml::distribution). PyPI Trusted Publishing
-# and GHCR container push run from .github/workflows/release.yml on
-# `vX.Y.Z` tag push.
-#
-# Updated 2026-05-17 for #953 — broad-distribution packaging.
-
-description: >
- Wheel/sdist/Nix install parity for polylogue. Documents build
- configuration, verification gates, and known gaps for each
- artifact type.
-
-artifacts:
- wheel:
- description: Python wheel distribution (bdist_wheel)
- build_system: hatchling
- config_location: pyproject.toml
- build_command: devtools release verify-distribution
- install_command: pip install polylogue
- verification_command: devtools release verify-distribution
- ci_build: true
- ci_test: true
- notes: >
- pyproject.toml uses [build-system] with hatchling.
- The distribution gate (ci.yml::distribution) builds wheel +
- sdist, installs each in a fresh venv, and smokes polylogue,
- polylogued, polylogue-mcp, and python -m polylogue. Tagged
- releases publish to PyPI via OIDC Trusted Publishing
- (release.yml::publish-pypi).
-
- sdist:
- description: Python source distribution (sdist)
- build_system: hatchling
- config_location: pyproject.toml
- build_command: devtools release verify-distribution
- install_command: pip install polylogue
- verification_command: devtools release verify-distribution
- ci_build: true
- ci_test: true
- notes: >
- Source distribution embeds polylogue/_build_info.py. The
- distribution gate unpacks the sdist outside .git, rebuilds
- a wheel from it, installs that wheel, and runs the same
- runtime smoke surface (ci.yml::distribution). Tagged releases
- publish to PyPI via OIDC Trusted Publishing.
-
- nix_package:
- description: Nix flake package derivation
- build_system: nix flake
- config_location: flake.nix
- build_command: nix build
- install_command: nix profile install
- ci_build: true
- ci_test: true
- notes: >
- Nix flake check runs in CI (nix-build gate). nix flake
- check validates the derivation can build. Nix is the
- primary distribution mechanism for the project author.
- Python version is managed by Nix, not pip. The flake exposes
- apps.{polylogue,polylogued,polylogue-mcp} for `nix run
- github:Sinity/polylogue#`, a NixOS module
- (nixosModules.default) wiring services.polylogue, and a Home
- Manager module (homeManagerModules.default) wiring
- programs.polylogued. The cachix workflow
- (.github/workflows/cachix.yml) pushes the package + devshell
- closures to the polylogue cachix cache on master pushes and
- tags; the flakehub workflow (.github/workflows/flakehub.yml)
- publishes the flake to FlakeHub on tag push.
-
- dev_install:
- description: Editable development install
- build_system: hatchling (pip install -e .)
- config_location: pyproject.toml
- build_command: pip install -e .
- install_command: pip install -e .
- ci_build: false
- ci_test: false
- notes: >
- Development install via pip install -e . (hatchling).
- Used locally but not verified in CI. The devshell
- (nix develop) is the canonical dev environment.
-
- oci_container:
- description: OCI image with polylogue / polylogued / polylogue-mcp on PATH
- build_system: packaging/Containerfile (multi-stage, uv wheel build + slim runtime)
- config_location: packaging/Containerfile
- build_command: docker buildx build -f packaging/Containerfile .
- install_command: podman pull ghcr.io/sinity/polylogue:latest
- ci_build: false
- ci_test: false
- notes: >
- Builder stage uses `uv build --wheel`; runtime stage installs the
- wheel into python:3.13-slim-bookworm under a non-root user with
- tini as PID 1. Volumes /data (XDG_DATA_HOME) and /config
- (XDG_CONFIG_HOME) are declared. Build + push to GHCR runs from
- .github/workflows/container.yml on master and `vX.Y.Z` tag pushes;
- pull requests touching the container surface run an amd64 smoke build.
-
- browser_extension:
- description: Manifest V3 browser extension (Chrome .zip + Firefox .xpi)
- build_system: node scripts/build.mjs (pure-JS, zip(1) or python zipfile fallback)
- config_location: browser-extension/manifest.json + browser-extension/scripts/build.mjs
- build_command: npm run build
- install_command: chrome://extensions Load unpacked / about:debugging Load Temporary
- verification_command: npm run validate
- ci_build: true
- ci_test: true
- notes: >
- Packed Chrome .zip and Firefox .xpi attached to GitHub Releases by
- .github/workflows/extension-release.yml on vX.Y.Z tag push. The
- build script reads the canonical project version from the [project]
- table of pyproject.toml and rewrites browser-extension/manifest.json
- + package.json to match before packaging. Firefox manifest is a
- generated variant with browser_specific_settings.gecko populated.
- web-ext lint runs against the unpacked Firefox bundle as a CI gate.
- Playwright captures store-submission screenshots at the Chrome Web
- Store and AMO required aspect ratios. Store submission itself
- (Chrome Web Store + Mozilla AMO) is tracked separately under
- coverage_gaps.browser-extension-store.
-
- devshell:
- description: Nix development shell
- build_system: nix flake (devShells.default)
- config_location: flake.nix
- build_command: nix develop
- ci_present: true
- notes: >
- Primary development environment. Enters automatically
- via direnv. Installs all dependencies and git hooks.
- Verified by nix flake check in CI.
-
- devtools:
- description: Source-checkout repository control plane
- build_system: source checkout / Nix devshell wrapper
- config_location: flake.nix
- install_command: nix develop
- ci_present: true
- notes: >
- Devtools are intentionally source-checkout-only. They are
- exposed in the devshell by the devtools wrapper in flake.nix.
-
- pip_dependencies:
- count: null
- resolved_by: flake.nix (overrides pyproject.toml)
-
- platform_coverage:
- linux: ci_test
- macos: false
- windows: false
- notes: >
- CI tests on Linux only (3 Python versions: 3.11, 3.12,
- 3.13). No macOS or Windows runners.
-
-coverage_gaps:
- - id: distribution.dev-install-ci
- artifact: dev_install
- gap: Not verified in CI; devshell is canonical environment
- owner: distribution
- severity: minor
- declared_at: "2026-05-02"
- review_after: "2026-08-01"
- issue: 593
- next_evidence: devtools release verify-distribution
- - id: distribution.macos-ci
- platform: macos
- gap: No macOS CI runner
- owner: distribution
- severity: minor
- declared_at: "2026-05-02"
- review_after: "2026-08-01"
- issue: 593
- next_evidence: devtools release verify-distribution
- - id: distribution.windows-ci
- platform: windows
- gap: No Windows CI runner
- owner: distribution
- severity: minor
- declared_at: "2026-05-02"
- review_after: "2026-08-01"
- issue: 593
- next_evidence: devtools release verify-distribution
- - id: distribution.nix-wheel-parity
- concern: install_parity
- gap: Local gate smokes wheel and sdist-built wheel, but exact Nix/devshell parity is not yet compared in CI
- owner: distribution
- severity: major
- declared_at: "2026-05-02"
- review_after: "2026-08-01"
- issue: 593
- next_evidence: devtools release verify-distribution
- - id: distribution.browser-extension-store
- artifact: browser_extension
- gap: Packed .zip/.xpi ship on GitHub releases (#1238), but Chrome Web Store / Mozilla AMO submission still requires non-engineering store sign-up + review.
- owner: distribution
- severity: minor
- declared_at: "2026-05-17"
- review_after: "2026-08-01"
- issue: 953
- next_evidence: devtools release verify-distribution
diff --git a/docs/plans/docs-coverage-baseline.yaml b/docs/plans/docs-coverage-baseline.yaml
deleted file mode 100644
index 31645c2673..0000000000
--- a/docs/plans/docs-coverage-baseline.yaml
+++ /dev/null
@@ -1,174 +0,0 @@
-# Docs-coverage baseline (polylogue-3tl.9)
-#
-# Pre-existing public surfaces (CLI commands, MCP tools, config keys, stable
-# daemon routes) with no doc-tree mention as of the introduction of
-# `devtools verify docs-coverage`. This is TRACKED DEBT, not an allowlist to
-# extend: new surfaces must be documented, not added here. Remove an entry
-# once the surface is documented anywhere in README.md or docs/**/*.md -- the
-# lint reports stale baseline entries so this stays honest.
-#
-# Schema: gaps. is a list of {name, reason} entries. Surfaces:
-# cli (command display name), mcp (tool name), config (flat config key),
-# route (daemon HTTP route pattern).
-#
-# Follow-up: polylogue-ccma (full claim-by-claim docs sweep) and future docs
-# passes should retire entries here rather than leaving the baseline static.
-
-gaps:
- cli:
- - name: 'agents status'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'agents work-item'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'analyze insights debt'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'analyze insights timeline'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'analyze insights tool-usage'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'analyze pace'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'analyze turns'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'annotations import'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'annotations join'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'config query-completions'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'ops diagnostics space'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'ops embed resolve-failure'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'ops insights export'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'ops insights status'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'ops maintenance assertion-export'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'ops maintenance attachment-acquisition-debt'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'ops maintenance blob-gc'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'ops maintenance blob-reference-recovery-plan'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'ops maintenance browser-canonical-authority-conflicts'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); missed in the initial baseline sweep, not a new surface"
- - name: 'ops maintenance browser-capture-origin-mismatches'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'ops maintenance duplicate-raw-identity'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); missed in the initial baseline sweep, not a new surface"
- - name: 'ops maintenance embedding-orphan-reconcile'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'ops maintenance gc-history'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'ops maintenance legacy-browser-capture-missing-native-id'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'ops maintenance missing-raw-blob-cursors'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'ops maintenance quarantined-accepted-raws'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'ops maintenance status'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- config:
- - name: 'browser_capture_host'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'browser_capture_port'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'daemon_host'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'daemon_port'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'embedding_dimension'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'embedding_model'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'health_blob_integrity_sample_size'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'health_convergence_debt'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'health_cursor_lag'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'notification_apprise_urls'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'notification_email_from'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'notification_email_host'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'notification_email_max_per_hour'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'notification_email_password'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'notification_email_port'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'notification_email_subject_prefix'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'notification_email_to'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'notification_email_use_starttls'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'notification_email_use_tls'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'notification_email_username'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'notification_webhook_secret'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'notification_webhook_url'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'source_roots'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'subscription_plans'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: 'watch_debounce_s'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- route:
- - name: '/api/agents/coordination'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/import/explain'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/insights/sessions/:id'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/maintenance/operations'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/maintenance/status/:id'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/overview'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/provider-usage'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/query-completions'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/read-view-profiles'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/sessions/:id/attachments'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/sessions/:id/cost'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/sessions/:id/evidence-summary'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/sessions/:id/raw'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/sessions/:id/similar'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/sessions/:id/topology'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/sessions/:id/topology/parent-chain'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/thread-continue-templates'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/user/annotations'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/user/annotations/:id'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/user/recall-packs'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/user/recall-packs/:id'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/user/workspaces'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/api/user/workspaces/:id'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/s/:session_id'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
- - name: '/w/:mode'
- reason: "pre-existing gap at gate introduction (polylogue-3tl.9); needs a doc entry, not baseline growth"
diff --git a/docs/plans/docs-media-coverage.yaml b/docs/plans/docs-media-coverage.yaml
deleted file mode 100644
index d00b68fe5d..0000000000
--- a/docs/plans/docs-media-coverage.yaml
+++ /dev/null
@@ -1,116 +0,0 @@
-# Docs-and-media coverage manifest.
-#
-# Documents the documentation surfaces under polylogue. Only fields
-# consumed by an executable check are retained — `path` is verified
-# against the filesystem, `generated_by` and `verified_by` are checked
-# against the devtools command catalog (see verify_manifests.
-# check_coverage_references). Aspirational fields (freshness_days,
-# sections, providers, related_paths, count) were removed under #1064
-# because no check consumed them.
-#
-# Updated 2026-05-16 under #1064 (Pack C — coverage-manifest reality).
-
-description: >
- Documentation surfaces under polylogue. Each entry's `path` is
- verified to exist; `generated_by` and `verified_by` are verified
- to resolve to a known command. Notes are documentation only.
-
-surfaces:
- readme:
- path: README.md
- notes: >
- Top-level README at docs/README.md (generated by
- devtools render docs-surface). Links to architecture,
- CLI reference, library API, MCP integration, providers.
- Root-level README.md updated by render all.
-
- cli_reference:
- path: docs/cli-reference.md
- generated_by: devtools render cli-reference
- verified_by: devtools render all --check
- notes: >
- docs/cli-reference.md generated from live Click help
- output. Verified as part of devtools verify and
- pre-commit hooks.
-
- architecture:
- path: docs/architecture.md
- notes: >
- docs/architecture.md describes system rings, ownership
- boundaries, data flow. Manually maintained.
-
- internals:
- path: docs/internals.md
- notes: >
- docs/internals.md is the working implementation reference.
- Manually maintained. Documents hot files, extension points,
- debugging landmarks.
-
- devtools_reference:
- path: docs/devtools.md
- generated_by: devtools render devtools-reference
- verified_by: devtools render all --check
- notes: >
- docs/devtools.md command catalog generated from
- devtools/command_catalog.py. Verified by render all --check.
-
- quality_reference:
- path: docs/test-quality-workflows.md
- generated_by: devtools render quality-reference
- verified_by: devtools render all --check
- notes: >
- docs/test-quality-workflows.md from live validation,
- mutation, and benchmark registries. Generated.
-
- # User-facing media is rendered on demand from demo fixtures or
- # lab environments when a release/article/site actually
- # needs it. The root README no longer references committed architecture
- # diagrams, screenshots, or VHS tapes, so there is no docs/media surface
- # in the repository. A future committed media asset must arrive with an
- # owning render command, a --check freshness gate, and a coverage row.
-
- provider_docs:
- path: docs/providers/
- notes: >
- Per-provider notes in docs/providers/. Provider README
- indexes ChatGPT, Claude AI, Claude Code, Codex, and Gemini.
- Manually maintained.
-
- configuration_docs:
- path: docs/configuration.md
- notes: >
- Documents XDG paths, environment variables, and runtime
- configuration. Manually maintained.
-
- data_model_docs:
- path: docs/data-model.md
- notes: >
- Documents archive entities, storage shape, metadata rules.
- Manually maintained.
-
- contributing_docs:
- path: CONTRIBUTING.md
- verified_by: devtools render all --check
- notes: >
- Contributor workflow, branching, PRs, versioning policy.
- Root-level, manually maintained.
-
- testing_docs:
- path: TESTING.md
- notes: >
- Test suite layout, patterns, demo verification, mutation testing
- policy. Root-level, manually maintained.
-
- agent_guide:
- path: CLAUDE.md
- notes: >
- Standalone agent onboarding — architecture understanding and working
- rules. Manually maintained. AGENTS.md is a symlink to CLAUDE.md.
-
- release_docs:
- path: docs/release.md
- notes: >
- Release checklist, pre-flight checks, tagging procedure.
- Manually maintained. Updated on version bumps.
-
-coverage_gaps: []
diff --git a/docs/plans/mutation-census.yaml b/docs/plans/mutation-census.yaml
deleted file mode 100644
index 6aa47e68b2..0000000000
--- a/docs/plans/mutation-census.yaml
+++ /dev/null
@@ -1,398 +0,0 @@
-# Mutation census (polylogue-kwsb.2 AC1).
-#
-# Classifies every destructive/mutating public operation and adapter:
-# `executor-routed` (drives OperationExecutor + a MutationActuator),
-# `declared-not-routed` (still enforces authorization independently -- named
-# Phase 2 debt, not silent absence), or `typed-exemption` (a reviewed reason
-# it cannot/should not route through MutationTransaction).
-#
-# `tests/unit/operations/test_mutation_census.py` enforces:
-# - every row's `operation` exists in `polylogue.operations.specs`'s
-# declared catalog when `spec_name` is set, and its `executor_status`
-# matches this row's `status`.
-# - every row has a `status` in the closed vocabulary above and, for
-# `typed-exemption`, a non-empty `reason`.
-#
-# Phase 1 (t46.9/kwsb.2) shipped the two named destructive routes (session
-# delete/excision, derived identity reset), fully executor-routed on every
-# surface that exposes them. Phase 2 adds the `reversible`-class tag,
-# metadata, and mark mutation families (role_only-strength executor routes,
-# per AC4: reversible writes must not acquire unnecessary interactive
-# confirmation). Phase 3 adds the annotation family (reversible, role_only)
-# and raw-authority blocker resolution (reset class, confirm_flag --
-# discovered mid-session as an unclassified mutating operation, not merely
-# an un-migrated one: it had a CLI adapter but no census row at all). Phase 4
-# adds the saved-view/recall-pack/workspace family (same reversible/role_only
-# pattern; each pair's ArchiveStore primitive is a create-or-update upsert
-# paired with a soft-delete). Phase 5 adds the learning-corrections family
-# (reversible, role_only); the bulk `clear_corrections` actuator resolves
-# the exact live set of correction kinds at PREPARE time (not the caller's
-# request shape), so a concurrent `record_correction` between AUTHORIZE and
-# EXECUTE changes the plan hash and forces a replan instead of silently
-# clearing a kind the caller never previewed. Phase 6 adds the
-# blackboard-post family (reversible, role_only): `blackboard_post` had NO
-# OperationSpec entry at all before this phase -- an unclassified mutation,
-# not merely an un-migrated one, closed the same way
-# `mutate-resolve-raw-authority-blocker` was in phase 3. Phases 1-5 landed as
-# separate PRs (#3249/#3253/#3258/#3262/#3294); phase 6 (this revision) is
-# the next PR in the same sequence. Every remaining operation below is
-# inventoried honestly as `declared-not-routed` -- visible debt for a later
-# phase, not a claim of completion.
-
-schema_version: 1
-
-rows:
- # --- Phase 1: executor-routed (t46.9 AC2 named routes) ---------------------
- - operation: mutate-delete-session
- spec_name: mutate-delete-session
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.SessionDeleteActuator
- surfaces: [cli, mcp, api]
- adapters:
- - polylogue.cli.archive_query._emit_delete
- - polylogue.api.archive.PolylogueArchiveMixin.delete_session_safe
- - polylogue.mcp.server_cutover._dispatch_write (operation=delete_session, via delete_session_safe)
-
- - operation: mutate-session-excision
- spec_name: mutate-session-excision
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.SessionExcisionActuator
- surfaces: [cli]
- adapters:
- - polylogue.cli.commands.excise.excise_command
-
- - operation: mutate-session-lifecycle-request
- spec_name: mutate-session-lifecycle-request
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.SessionLifecycleRequestActuator
- surfaces: [cli]
- adapters:
- - polylogue.cli.commands.excise.excise_command (--mode mirror/primary)
-
- - operation: mutate-identity-reset
- spec_name: mutate-identity-reset
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.IdentityResetActuator
- surfaces: [cli]
- adapters:
- - polylogue.cli.commands.reset.reset_command (--session/--source)
-
- # --- Phase 2: executor-routed (reversible class, role_only confirmation) ---
- - operation: mutate-add-tag
- spec_name: mutate-add-tag
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.TagAddActuator
- surfaces: [facade, mcp, api]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.add_tag
- - polylogue.mcp.server_cutover._dispatch_write (operation=add_tag, via add_tag)
-
- - operation: mutate-remove-tag
- spec_name: mutate-remove-tag
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.TagRemoveActuator
- surfaces: [facade, mcp, api]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.remove_tag
- - polylogue.mcp.server_cutover._dispatch_write (operation=remove_tag, via remove_tag)
-
- - operation: mutate-bulk-tag-sessions
- spec_name: mutate-bulk-tag-sessions
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.BulkTagActuator
- surfaces: [mcp, api]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.bulk_tag_sessions
- - polylogue.mcp.server_cutover._dispatch_write (operation=bulk_tag_sessions, via bulk_tag_sessions)
-
- - operation: mutate-set-metadata
- spec_name: mutate-set-metadata
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.MetadataSetActuator
- surfaces: [facade, mcp, api]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.set_metadata
- - polylogue.mcp.server_cutover._dispatch_write (operation=set_metadata, via set_metadata)
-
- - operation: mutate-delete-metadata
- spec_name: mutate-delete-metadata
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.MetadataDeleteActuator
- surfaces: [mcp, api]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.delete_metadata
- - polylogue.mcp.server_cutover._dispatch_write (operation=delete_metadata, via delete_metadata)
-
- - operation: mutate-add-mark
- spec_name: mutate-add-mark
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.MarkAddActuator
- surfaces: [mcp, api]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.add_mark
- - polylogue.mcp.server_cutover._dispatch_write (operation=add_mark, via add_mark)
-
- - operation: mutate-remove-mark
- spec_name: mutate-remove-mark
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.MarkRemoveActuator
- surfaces: [mcp, api]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.remove_mark
- - polylogue.mcp.server_cutover._dispatch_write (operation=remove_mark, via remove_mark)
-
- # --- Phase 3: executor-routed (annotation family; reversible class) --------
-
- - operation: mutate-save-annotation
- spec_name: mutate-save-annotation
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.AnnotationSaveActuator
- surfaces: [mcp, api]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.save_annotation
- - polylogue.mcp.server_cutover._dispatch_write (operation=save_annotation, via save_annotation)
-
- - operation: mutate-delete-annotation
- spec_name: mutate-delete-annotation
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.AnnotationDeleteActuator
- surfaces: [mcp, api]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.delete_annotation
- - polylogue.mcp.server_cutover._dispatch_write (operation=delete_annotation, via delete_annotation)
-
- # --- Phase 3: executor-routed (raw-authority blocker resolution) -----------
- # Routine raw-authority frontier application is intentionally not an
- # operator mutation row. It is a daemon convergence sub-route under the
- # writer coordinator; the operator frontier command is inspection-only.
- # Tonight-discovered operator gap (2026-07-21/22): resolve_raw_authority_
- # blocker had a working CLI adapter (raw-authority-blocker-resolve, its own
- # --yes gate) but NO census entry and no authorization path shared with any
- # other destructive route -- an unclassified mutating operation, not merely
- # an un-migrated one. Also added: raw-authority-blockers (read-only list,
- # no census row needed) so an operator can discover an unresolved
- # --blocker-id without page-walking raw-authority-census/-detail or writing
- # an ad hoc script against the live archive.
- - operation: mutate-resolve-raw-authority-blocker
- spec_name: mutate-resolve-raw-authority-blocker
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.BlockerResolveActuator
- surfaces: [cli]
- adapters:
- - polylogue.cli.commands.maintenance._raw_identity.raw_authority_blocker_resolve_command
-
- - operation: mutate-reset-raw-authority-census
- spec_name: mutate-reset-raw-authority-census
- status: executor-routed
- execution_owner: offline-operator-maintenance
- recovery_continuation: offline-durable-intent
- actuator: polylogue.maintenance.raw_authority_recovery.ResetRawAuthorityCensusActuator
- surfaces: [cli]
- adapters:
- - polylogue.cli.commands.maintenance._raw_authority_recovery.raw_authority_recovery_command
-
- - operation: mutate-prune-orphaned-index-revision-seeds
- spec_name: mutate-prune-orphaned-index-revision-seeds
- status: executor-routed
- execution_owner: offline-operator-maintenance
- recovery_continuation: offline-durable-intent
- actuator: polylogue.maintenance.raw_authority_recovery.PruneOrphanedIndexRevisionSeedsActuator
- surfaces: [cli]
- adapters:
- - polylogue.cli.commands.maintenance._raw_authority_recovery.raw_authority_recovery_command
-
- # --- Phase 4: executor-routed (saved-view/recall-pack/workspace family) ----
-
- - operation: mutate-save-saved-view
- spec_name: mutate-save-saved-view
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.SavedViewSaveActuator
- surfaces: [mcp, api, daemon]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.save_view
- - polylogue.mcp.server_cutover._dispatch_write (operation=save_saved_view, via save_view)
- - polylogue.daemon.user_state_http.handle_save_view (via save_view)
-
- - operation: mutate-delete-saved-view
- spec_name: mutate-delete-saved-view
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.SavedViewDeleteActuator
- surfaces: [mcp, api, daemon]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.delete_view
- - polylogue.mcp.server_cutover._dispatch_write (operation=delete_saved_view, via delete_view)
- - polylogue.daemon.user_state_http.handle_delete_saved_view (via delete_view)
-
- - operation: mutate-save-recall-pack
- spec_name: mutate-save-recall-pack
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.RecallPackSaveActuator
- surfaces: [mcp, api, daemon]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.create_recall_pack
- - polylogue.mcp.server_cutover._dispatch_write (operation=save_recall_pack, via create_recall_pack)
- - polylogue.daemon.user_state_http.handle_save_recall_pack (via create_recall_pack)
-
- - operation: mutate-delete-recall-pack
- spec_name: mutate-delete-recall-pack
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.RecallPackDeleteActuator
- surfaces: [mcp, api, daemon]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.delete_recall_pack
- - polylogue.mcp.server_cutover._dispatch_write (operation=delete_recall_pack, via delete_recall_pack)
- - polylogue.daemon.user_state_http.handle_delete_recall_pack (via delete_recall_pack)
-
- - operation: mutate-save-workspace
- spec_name: mutate-save-workspace
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.WorkspaceSaveActuator
- surfaces: [mcp, api, daemon]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.save_workspace
- - polylogue.mcp.server_cutover._dispatch_write (operation=save_workspace, via save_workspace)
- - polylogue.daemon.user_state_http.handle_save_workspace (via save_workspace)
-
- - operation: mutate-delete-workspace
- spec_name: mutate-delete-workspace
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.WorkspaceDeleteActuator
- surfaces: [mcp, api, daemon]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.delete_workspace
- - polylogue.mcp.server_cutover._dispatch_write (operation=delete_workspace, via delete_workspace)
- - polylogue.daemon.user_state_http.handle_delete_workspace (via delete_workspace)
-
- # --- Phase 5: executor-routed (learning-corrections family) -----------------
-
- - operation: record_correction
- spec_name: mutate-record-correction
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.CorrectionRecordActuator
- surfaces: [mcp, api]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.record_correction
- - polylogue.mcp.server_cutover._dispatch_write (operation=record_correction, via record_correction)
-
- - operation: delete_correction
- spec_name: mutate-delete-correction
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.CorrectionDeleteActuator
- surfaces: [mcp, api]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.delete_correction
- - polylogue.mcp.server_cutover._dispatch_write (operation=clear_corrections with kind, via delete_correction)
-
- - operation: clear_corrections
- spec_name: mutate-clear-corrections
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.CorrectionsClearActuator
- surfaces: [mcp, api]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.clear_corrections
- - polylogue.mcp.server_cutover._dispatch_write (operation=clear_corrections without kind, via clear_corrections)
-
- # --- Phase 6: executor-routed (blackboard-post family) ----------------------
-
- - operation: blackboard_post
- spec_name: mutate-blackboard-post
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.BlackboardPostActuator
- surfaces: [mcp, api]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.post_blackboard_note
- - polylogue.mcp.server_cutover._dispatch_write (operation=blackboard_post, via post_blackboard_note)
-
- # --- Phase 7: executor-routed (derived maintenance rebuilds) ---------------
- # These facade methods are the shared gateway for the MCP maintenance
- # operations. The existing MCP confirmation gates remain in place; the
- # executor now owns target planning, capability binding, and receipts for
- # the underlying derived-tier effects.
- - operation: rebuild_index
- spec_name: mutate-rebuild-index
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.IndexRebuildActuator
- surfaces: [facade, mcp]
- adapters:
- - polylogue.api.ingest.PolylogueIngestMixin.rebuild_index
- - polylogue.mcp.server_cutover._dispatch_maintenance (operation=rebuild_index, via facade)
-
- - operation: update_index
- spec_name: mutate-update-index
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.IndexRebuildActuator
- surfaces: [facade, mcp]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.update_index
- - polylogue.mcp.server_cutover._dispatch_maintenance (operation=update_index, via facade)
-
- - operation: rebuild_insights
- spec_name: mutate-rebuild-insights
- status: executor-routed
- actuator: polylogue.operations.mutation_actuators.InsightsRebuildActuator
- surfaces: [facade, mcp]
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.rebuild_insights
- - polylogue.mcp.server_cutover._dispatch_maintenance (operation=rebuild_insights, via facade)
-
- # --- Phase 3+ debt: declared-not-routed -------------------------------------
- # MCP-only mutation family with no OperationSpec entry yet (pre-existing
- # gap, not introduced by this PR). jn40's confirm-boolean sweep was the
- # interim mitigation for the destructive members of this family. add_mark/
- # remove_mark (phase 2), save_annotation/delete_annotation (phase 3), the
- # saved-view/recall-pack/workspace family (phase 4), record_correction/
- # delete_correction/clear_corrections (phase 5), and blackboard_post
- # (phase 6, above) and the derived maintenance trio (phase 7, above) are
- # all executor-routed now; the rest of this family
- # remains debt for a later phase.
-
- - operation: capture_assertion_candidate
- spec_name: mutate-capture-assertion-candidate
- status: executor-routed
- surfaces: [facade, cli, mcp]
- actuator: polylogue.operations.mutation_actuators.CaptureAssertionCandidateActuator
- adapters:
- - polylogue.api.archive.PolylogueArchiveMixin.capture_assertion_candidate
- - polylogue.cli.commands.note.capture_note_command
- - polylogue.mcp.server_cutover._dispatch_write (operation=capture_assertion_candidate)
-
- - operation: import_annotation_batch
- spec_name: mutate-import-annotation-batch
- status: executor-routed
- surfaces: [facade, cli, mcp]
- actuator: polylogue.annotations.importer.AnnotationBatchImportActuator
- adapters:
- - polylogue.annotations.importer.import_annotation_batch
- - polylogue.api.archive.PolylogueArchiveMixin.import_annotation_batch
- - polylogue.cli.commands.annotations.import_annotations_command
- - polylogue.mcp.server_cutover._dispatch_write (operation=import_annotation_batch)
-
- - operation: maintenance_execute (resumable maintenance run)
- status: declared-not-routed
- surfaces: [mcp, daemon]
- reason: >
- The resumable target-catalog replay has a separate operation-id,
- cursor, failure-isolation, and partial-resume contract. This slice
- routes the facade/MCP rebuild_index, update_index, and rebuild_insights
- methods only; the maintenance run family remains deferred.
-
- - operation: ops reset --database/--index/--blob/--assets/--cache/--auth
- status: declared-not-routed
- surfaces: [cli]
- adapters: [polylogue.cli.commands.reset.reset_command]
- reason: >
- Bulk filesystem-tier deletion (whole .db/cache/blob-store files, not
- addressable session/message/block object refs). Already has --yes
- gating and a preview listing; Phase 2 should decide whether to extend
- MutationPlan's target-ref vocabulary to file-tier targets or keep this
- a typed exemption permanently (it is closer to an operator
- infrastructure command than a content mutation).
-
- # --- Reviewed exemptions -----------------------------------------------------
- - operation: seed-demo-archive
- spec_name: seed-demo-archive
- status: typed-exemption
- surfaces: [cli, tests, validation-lane]
- reason: >
- Test/demo fixture seeding into a disposable demo archive root, not a
- production destructive route; no real user evidence at risk.
diff --git a/docs/plans/query-pipeline-substrate.md b/docs/plans/query-pipeline-substrate.md
deleted file mode 100644
index dba788790a..0000000000
--- a/docs/plans/query-pipeline-substrate.md
+++ /dev/null
@@ -1,72 +0,0 @@
-# Query pipeline substrate
-
-Owning issue: #2006.
-
-## Purpose
-
-Polylogue needs a richer query language without becoming its own query engine.
-The surface language should lower onto the archive storage and search layers
-already present in the project. The Lark grammar in
-`polylogue/archive/query/expression.py` is the query grammar; compact field/text
-clauses and explicit Boolean predicates are entry shapes in that grammar, not
-separate floor/ceiling languages.
-
-## Current state
-
-The current implemented query substrate already handles compact session filters,
-grouped Boolean predicates, message/action/block/assertion `exists`
-predicates, ordered action sequences, FTS predicates, lineage predicates, a
-semantic seed plus residual filter, and terminal row-producing
-`messages/actions/blocks/assertions/runs/observed-events/context-snapshots
-where ...` queries. Runtime-transform terminal rows for runs, observed events,
-and context snapshots lower through the recovery/run projection rather than a
-SQL table, so unsupported scoped session fields must fail closed instead of
-broadening results.
-
-## Design decision
-
-Build a typed AST and lowering layer.
-
-Predicate nodes: And, Or, Not, Leaf, Fts, Semantic, Structural, Sequence, Lineage, Relational.
-
-Pipeline stages: source or filter, traverse, transform, aggregate, sort/limit,
-and terminal action or view.
-
-Implemented units: session, message, action, block, assertion, run, observed
-event, context snapshot, lineage.
-
-Target units still needing real lowerers: bundle/work packet, external work
-refs, phase, thread, span.
-
-## Surface ladder
-
-Compact examples: repo filters, origin filters, tags, date filters, phrases, and the current `find QUERY then ACTION` shape.
-
-Power examples: grouped conditions, numeric operators, semantic clauses, message predicates, sequence predicates, lineage predicates, and pipelines that change unit from sessions to messages or lineage and back.
-
-## Implementation phases
-
-These are coherent PR-sized implementation phases, not conceptual
-micro-slices. Each phase should land useful executable queries and tests.
-
-1. Keep compact and explicit Boolean syntax on the same Lark grammar and AST
- path.
-2. Extend explain output to show terminal unit sources, unsupported
- unit/pipeline stages, and the concrete lowerer/execution legs selected.
-3. Keep runtime-transform unit execution covered across CLI, Python API, MCP,
- daemon, docs, generated schemas, and completions as new fields are added.
-4. Add traversal stages that change the active unit and lower to SQL/recursive
- CTEs or existing read models.
-5. Add aggregation/sort/limit stages over supported units.
-6. Lower terminal stages through existing read/analyze/bundle/action contracts.
-7. Add completion/query-builder metadata from the same grammar, unit, field,
- operator, and action registries.
-
-## Acceptance criteria
-
-- The AST represents compact and explicit query syntax through one grammar.
-- Unsupported forms fail with typed errors and do not broaden results.
-- CLI, daemon, MCP, web, and completion can share the same parser and AST.
-- Natural-language query tools target the AST.
-- Query surfaces should name and call the grammar/AST/lowering path directly.
- There is no separate compatibility compiler or floor grammar.
diff --git a/docs/plans/reindex-incident-coverage.json b/docs/plans/reindex-incident-coverage.json
deleted file mode 100644
index 58385913dd..0000000000
--- a/docs/plans/reindex-incident-coverage.json
+++ /dev/null
@@ -1,3826 +0,0 @@
-{
- "schema_version": 1,
- "ledger_id": "polylogue-incident-coverage-ledger",
- "target_bead_id": "polylogue-818fy",
- "graph_fixture_id": "reindex-campaign-graph-6a63a4f71f",
- "dependency_kinds": [
- "blocks",
- "discovered-from",
- "parent-child",
- "relates-to",
- "supersedes"
- ],
- "fixtures": {
- "campaign-graph": {
- "kind": "campaign-graph",
- "source": "tests/fixtures/reindex_incident_coverage/campaign_graph.json",
- "mutation_ids": [
- "mutation-a7xr-25",
- "mutation-polylogue-052vs",
- "mutation-polylogue-0qfy",
- "mutation-polylogue-0v4tn",
- "mutation-polylogue-1fijp",
- "mutation-polylogue-1xc-8",
- "mutation-polylogue-2qrx",
- "mutation-polylogue-2qx",
- "mutation-polylogue-2qx-3",
- "mutation-polylogue-2tfug",
- "mutation-polylogue-3m3de",
- "mutation-polylogue-4987i",
- "mutation-polylogue-4v2d3",
- "mutation-polylogue-5q2u",
- "mutation-polylogue-6753s",
- "mutation-polylogue-6bebe",
- "mutation-polylogue-6k0na",
- "mutation-polylogue-6krh",
- "mutation-polylogue-7zp4",
- "mutation-polylogue-84ake",
- "mutation-polylogue-8ac0",
- "mutation-polylogue-9kc0",
- "mutation-polylogue-9qnzy",
- "mutation-polylogue-a7gmk",
- "mutation-polylogue-a7xr-25",
- "mutation-polylogue-aex0",
- "mutation-polylogue-amrpx",
- "mutation-polylogue-b5l-1",
- "mutation-polylogue-byte-supersession-live-proof",
- "mutation-polylogue-c831",
- "mutation-polylogue-canonical-snapshot",
- "mutation-polylogue-cc4k",
- "mutation-polylogue-cijx-2",
- "mutation-polylogue-cursor-authority-live-proof",
- "mutation-polylogue-cursor-authority-reconcile-implementation",
- "mutation-polylogue-dcrmm",
- "mutation-polylogue-ds4b4",
- "mutation-polylogue-dudtn",
- "mutation-polylogue-dyica",
- "mutation-polylogue-e98k",
- "mutation-polylogue-ehzfn",
- "mutation-polylogue-eqq02",
- "mutation-polylogue-es7b",
- "mutation-polylogue-excluded-cursor-live-proof",
- "mutation-polylogue-ey4ro",
- "mutation-polylogue-f47j",
- "mutation-polylogue-g8v5z",
- "mutation-polylogue-gxig",
- "mutation-polylogue-gysk3",
- "mutation-polylogue-h57ic",
- "mutation-polylogue-h7y0j",
- "mutation-polylogue-hjwr",
- "mutation-polylogue-hook-reconciliation-apply-proof",
- "mutation-polylogue-i3zo",
- "mutation-polylogue-in24n",
- "mutation-polylogue-incident-coverage-ledger",
- "mutation-polylogue-inygw",
- "mutation-polylogue-iuyr",
- "mutation-polylogue-ix5r",
- "mutation-polylogue-k8wv",
- "mutation-polylogue-kmqwm",
- "mutation-polylogue-ksgg",
- "mutation-polylogue-lb39z",
- "mutation-polylogue-lkrc",
- "mutation-polylogue-lr6dx",
- "mutation-polylogue-lyv4",
- "mutation-polylogue-mvcbi",
- "mutation-polylogue-nhbvf",
- "mutation-polylogue-o8c3m",
- "mutation-polylogue-ohkfy",
- "mutation-polylogue-omsw",
- "mutation-polylogue-pr-scope-contract",
- "mutation-polylogue-qhk8z",
- "mutation-polylogue-r9xsj",
- "mutation-polylogue-raw-dedupe-apply-proof",
- "mutation-polylogue-reindex-preflight-authorization",
- "mutation-polylogue-reindex-proof-edge-correction",
- "mutation-polylogue-reindex-registry-two-plane-subset",
- "mutation-polylogue-reindex-source-remediation",
- "mutation-polylogue-rrxe4",
- "mutation-polylogue-s8s54",
- "mutation-polylogue-slshy",
- "mutation-polylogue-stalled-cursor-live-proof",
- "mutation-polylogue-swqu",
- "mutation-polylogue-t0m73",
- "mutation-polylogue-tnqqt",
- "mutation-polylogue-tu1f",
- "mutation-polylogue-tw4ar",
- "mutation-polylogue-uecir",
- "mutation-polylogue-un60n",
- "mutation-polylogue-uqwd",
- "mutation-polylogue-vp2ky",
- "mutation-polylogue-w6hql",
- "mutation-polylogue-xeck9",
- "mutation-polylogue-xselt",
- "mutation-polylogue-yazae",
- "mutation-polylogue-yla8",
- "mutation-polylogue-z22ml",
- "mutation-polylogue-zm4w8",
- "mutation-polylogue-zoek0",
- "mutation-reindex-source-remediation",
- "mutation-xselt"
- ],
- "mutation_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "mutation_registry": "MUTATION_REGISTRIES.campaign_graph"
- },
- "campaign-corpus": {
- "kind": "real-campaign-corpus",
- "source": "tests/infra/reindex_campaign.py",
- "mutation_ids": [
- "mutation-a7xr-25",
- "mutation-campaign-corpus"
- ],
- "mutation_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "mutation_registry": "MUTATION_REGISTRIES.campaign_corpus"
- },
- "canary-corpus": {
- "kind": "canary-selection",
- "source": "tests/infra/reindex_differential.py",
- "mutation_ids": [
- "mutation-canary-corpus"
- ],
- "mutation_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "mutation_registry": "MUTATION_REGISTRIES.canary_corpus"
- },
- "vintage-reorder": {
- "kind": "vintage-reorder",
- "source": "tests/infra/reindex_campaign.py",
- "mutation_ids": [
- "mutation-vintage-reorder"
- ],
- "mutation_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "mutation_registry": "MUTATION_REGISTRIES.vintage_reorder"
- },
- "lifecycle-anchor-drift": {
- "kind": "lifecycle-anchor-drift",
- "source": "tests/infra/reindex_campaign.py",
- "mutation_ids": [
- "mutation-lifecycle-anchor-drift"
- ],
- "mutation_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "mutation_registry": "MUTATION_REGISTRIES.lifecycle_anchor_drift"
- },
- "origin-matrix": {
- "kind": "origin-matrix",
- "source": "tests/infra/reindex_campaign.py",
- "mutation_ids": [
- "mutation-origin-matrix"
- ],
- "mutation_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "mutation_registry": "MUTATION_REGISTRIES.origin_matrix"
- },
- "raw-authority-census": {
- "kind": "raw-authority-census",
- "source": "tests/unit/storage/test_raw_authority_ledger.py",
- "mutation_ids": [
- "mutation-raw-authority-census"
- ],
- "mutation_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "mutation_registry": "MUTATION_REGISTRIES.raw_authority_census"
- },
- "sidecar-admission": {
- "kind": "sidecar-admission",
- "source": "tests/infra/reindex_campaign.py",
- "mutation_ids": [
- "mutation-sidecar-admission"
- ],
- "mutation_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "mutation_registry": "MUTATION_REGISTRIES.sidecar_admission"
- },
- "drive-revision": {
- "kind": "drive-revision",
- "source": "tests/unit/sources/test_drive_gateway.py",
- "mutation_ids": [
- "mutation-drive-revision"
- ],
- "mutation_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "mutation_registry": "MUTATION_REGISTRIES.drive_revision"
- },
- "lineage-corpus": {
- "kind": "lineage-corpus",
- "source": "tests/infra/reindex_campaign.py",
- "mutation_ids": [
- "mutation-lineage-corpus"
- ],
- "mutation_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "mutation_registry": "MUTATION_REGISTRIES.lineage_corpus"
- },
- "derived-model": {
- "kind": "derived-model",
- "source": "tests/infra/reindex_differential.py",
- "mutation_ids": [
- "mutation-derived-model"
- ],
- "mutation_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "mutation_registry": "MUTATION_REGISTRIES.derived_model"
- },
- "title-census": {
- "kind": "title-census",
- "source": "tests/unit/maintenance/test_reindex_campaign.py",
- "mutation_ids": [
- "mutation-title-census"
- ],
- "mutation_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "mutation_registry": "MUTATION_REGISTRIES.title_census"
- },
- "parser-replay": {
- "kind": "parser-replay",
- "source": "tests/unit/maintenance/test_reindex_campaign.py",
- "mutation_ids": [
- "mutation-parser-replay"
- ],
- "mutation_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "mutation_registry": "MUTATION_REGISTRIES.parser_replay"
- },
- "excluded-cursor-proof": {
- "kind": "candidate-live-compatible",
- "source": "tests/infra/excluded_cursor_live_proof.py",
- "mutation_ids": [
- "mutation-excluded-cursor-proof"
- ],
- "mutation_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "mutation_registry": "MUTATION_REGISTRIES.excluded_cursor_proof"
- }
- },
- "checks": {
- "campaign-coverage": {
- "kind": "registry",
- "source": "docs/plans/reindex-incident-coverage.json"
- },
- "canary-differ": {
- "kind": "registry",
- "source": "tests/unit/maintenance/test_reindex_canary.py"
- },
- "content-fidelity": {
- "kind": "registry",
- "source": "tests/infra/reindex_campaign.py"
- },
- "cursor-freshness": {
- "kind": "registry",
- "source": "tests/infra/reindex_campaign.py"
- },
- "origin-matrix": {
- "kind": "registry",
- "source": "tests/infra/reindex_campaign.py"
- },
- "content-hash-stability": {
- "kind": "registry",
- "source": "tests/infra/reindex_campaign.py"
- },
- "lineage-differential": {
- "kind": "registry",
- "source": "tests/infra/reindex_differential.py"
- },
- "topology-status": {
- "kind": "registry",
- "source": "tests/unit/storage/test_raw_authority_ledger.py"
- },
- "parser-replay": {
- "kind": "registry",
- "source": "tests/infra/reindex_campaign.py"
- },
- "convergence": {
- "kind": "registry",
- "source": "tests/infra/reindex_campaign.py"
- },
- "raw-authority": {
- "kind": "registry",
- "source": "tests/unit/storage/test_raw_authority_ledger.py"
- },
- "title-resolution": {
- "kind": "registry",
- "source": "tests/unit/maintenance/test_reindex_campaign.py"
- },
- "deployment-sync": {
- "kind": "receipt-gate",
- "source": "tests/infra/reindex_campaign.py"
- },
- "event-projection": {
- "kind": "registry",
- "source": "tests/infra/reindex_campaign.py"
- },
- "corpus-fidelity": {
- "kind": "registry",
- "source": "tests/infra/reindex_campaign.py"
- },
- "material-origin": {
- "kind": "registry",
- "source": "tests/infra/reindex_campaign.py"
- },
- "sidecar-admission": {
- "kind": "registry",
- "source": "tests/infra/reindex_campaign.py"
- },
- "derived-convergence": {
- "kind": "registry",
- "source": "tests/infra/reindex_differential.py"
- },
- "promotion-proof": {
- "kind": "registry",
- "source": "tests/infra/reindex_campaign.py"
- },
- "convergence-properties": {
- "kind": "registry",
- "source": "tests/infra/reindex_campaign.py"
- },
- "origin-repair": {
- "kind": "registry",
- "source": "tests/infra/reindex_campaign.py"
- },
- "parser-stamps": {
- "kind": "registry",
- "source": "tests/unit/maintenance/test_reindex_campaign.py"
- },
- "revision-lineage": {
- "kind": "registry",
- "source": "tests/unit/sources/test_drive_gateway.py"
- },
- "archive-invariants": {
- "kind": "registry",
- "source": "tests/unit/storage/test_raw_authority_ledger.py"
- },
- "lifecycle-anchor": {
- "kind": "registry",
- "source": "tests/infra/reindex_campaign.py"
- }
- },
- "snapshots": {
- "reindex-baseline-2026-08-03": {
- "kind": "expected-snapshot",
- "source": "docs/audits/2026-08-04-reindex-forcing-class-audit.md"
- },
- "canary-candidate": {
- "kind": "expected-snapshot",
- "source": "tests/unit/maintenance/test_reindex_canary.py"
- },
- "live-preflight-2026-08-04": {
- "kind": "expected-snapshot",
- "source": "docs/evidence/polylogue-xeck9-cursor-authority-census-2026-08-04.md"
- },
- "post-reindex-acceptance": {
- "kind": "expected-snapshot",
- "source": "docs/plans/reindex-incident-coverage.json"
- },
- "derived-model-candidate": {
- "kind": "expected-snapshot",
- "source": "tests/infra/reindex_differential.py"
- }
- },
- "receipts": {
- "live-proof-5xxmc": {
- "kind": "live-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-5xxmc",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "live-proof-7zp4": {
- "kind": "live-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-7zp4",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "live-proof-gzgyl": {
- "kind": "live-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-gzgyl",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "live-proof-mvcbi": {
- "kind": "live-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-mvcbi",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "live-proof-qsagp": {
- "kind": "live-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-qsagp",
- "source": "tests/infra/reindex_differential.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "excluded-cursor-proof-receipt": {
- "kind": "proof-receipt",
- "status": "recorded",
- "owner_bead_id": "polylogue-ix5r",
- "source": "docs/evidence/polylogue-excluded-cursor-live-proof-2026-08-06.json",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-6k0na": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-6k0na",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-xeck9": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-xeck9",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-0qfy": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-0qfy",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-7zp4": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-7zp4",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-gysk3": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-gysk3",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-052vs": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-052vs",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-1xc-8": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-1xc.8",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-2qx-3": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-2qx.3",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-8ac0": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-8ac0",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-9kc0": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-9kc0",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-c831": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-c831",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-cc4k": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-cc4k",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-gxig": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-gxig",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-h57ic": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-h57ic",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-h7y0j": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-h7y0j",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-hjwr": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-hjwr",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-i3zo": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-i3zo",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-kmqwm": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-kmqwm",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-lb39z": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-lb39z",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-lyv4": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-lyv4",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-qhk8z": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-qhk8z",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-swqu": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-swqu",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-z22ml": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-z22ml",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-zoek0": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-zoek0",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-6753s": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-6753s",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-ix5r": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-ix5r",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-nhbvf": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-nhbvf",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-zm4w8": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-zm4w8",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-eqq02": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-eqq02",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-reindex-proof-edge-correction": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-reindex-proof-edge-correction",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-2qrx": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-2qrx",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-dcrmm": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-dcrmm",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-dudtn": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-dudtn",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-mvcbi": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-mvcbi",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-o8c3m": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-o8c3m",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-84ake": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-84ake",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-amrpx": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-amrpx",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-canonical-snapshot": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-canonical-snapshot",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- },
- "implementation-proof-polylogue-ehzfn": {
- "kind": "implementation-proof",
- "status": "recorded",
- "owner_bead_id": "polylogue-ehzfn",
- "source": "tests/infra/reindex_campaign.py",
- "registry_source": "tests/fixtures/reindex_incident_coverage/registries.py",
- "registry": "RECEIPT_PRODUCERS"
- }
- },
- "successors": {
- "polylogue-claude-vintage-live-proof": {
- "kind": "named-child-bead",
- "source": "polylogue-claude-vintage-live-proof"
- },
- "polylogue-active-leaf-live-proof": {
- "kind": "named-child-bead",
- "source": "polylogue-active-leaf-live-proof"
- },
- "polylogue-stalled-cursor-live-proof": {
- "kind": "named-child-bead",
- "source": "polylogue-stalled-cursor-live-proof"
- },
- "polylogue-codex-804-live-proof": {
- "kind": "named-child-bead",
- "source": "polylogue-codex-804-live-proof"
- },
- "polylogue-byte-supersession-live-proof": {
- "kind": "named-child-bead",
- "source": "polylogue-byte-supersession-live-proof"
- },
- "polylogue-hook-authority-conflict-proof": {
- "kind": "named-child-bead",
- "source": "polylogue-hook-authority-conflict-proof"
- },
- "polylogue-excluded-cursor-live-proof": {
- "kind": "named-child-bead",
- "source": "polylogue-excluded-cursor-live-proof"
- },
- "polylogue-chatgpt-content-live-proof": {
- "kind": "named-child-bead",
- "source": "polylogue-chatgpt-content-live-proof"
- }
- },
- "rows": [
- {
- "bead_id": "polylogue-a7xr.25",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-a7xr-25",
- "bead_id": "polylogue-a7xr.25",
- "forcing_class": "event-projection"
- },
- "route": {
- "kind": "decision",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "preflight",
- "order": 1
- },
- "expected_snapshot": {
- "snapshot_id": "derived-model-candidate",
- "state": "blocking"
- },
- "registry_checks": [
- "event-projection"
- ],
- "red_mutation": {
- "fixture_id": "campaign-corpus",
- "mutation_id": "mutation-a7xr-25"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-reindex-source-remediation",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-reindex-source-remediation",
- "bead_id": "polylogue-reindex-source-remediation",
- "forcing_class": "deployment"
- },
- "route": {
- "kind": "operation",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "preflight",
- "order": 2
- },
- "expected_snapshot": {
- "snapshot_id": "live-preflight-2026-08-04",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-reindex-source-remediation"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-xselt",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-xselt",
- "bead_id": "polylogue-xselt",
- "forcing_class": "parser-stamps"
- },
- "route": {
- "kind": "registry",
- "entrypoint": "reindex-final-proof"
- },
- "schedule": {
- "phase": "promotion",
- "order": 3
- },
- "expected_snapshot": {
- "snapshot_id": "post-reindex-acceptance",
- "state": "blocking"
- },
- "registry_checks": [
- "parser-stamps",
- "promotion-proof"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-xselt"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-6k0na",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-6k0na",
- "bead_id": "polylogue-6k0na",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 4
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-6k0na"
- },
- "receipts": [
- "implementation-proof-polylogue-6k0na"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-a7gmk",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-a7gmk",
- "bead_id": "polylogue-a7gmk",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 5
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-a7gmk"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-byte-supersession-live-proof",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-byte-supersession-live-proof",
- "bead_id": "polylogue-byte-supersession-live-proof",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 6
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-byte-supersession-live-proof"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-cursor-authority-live-proof",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-cursor-authority-live-proof",
- "bead_id": "polylogue-cursor-authority-live-proof",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 7
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-cursor-authority-live-proof"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-cursor-authority-reconcile-implementation",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-cursor-authority-reconcile-implementation",
- "bead_id": "polylogue-cursor-authority-reconcile-implementation",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 8
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-cursor-authority-reconcile-implementation"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-dyica",
- "bead_status": "in_progress",
- "incident": {
- "incident_id": "incident-polylogue-dyica",
- "bead_id": "polylogue-dyica",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 9
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-dyica"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-excluded-cursor-live-proof",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-excluded-cursor-live-proof",
- "bead_id": "polylogue-excluded-cursor-live-proof",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 10
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-excluded-cursor-live-proof"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-hook-reconciliation-apply-proof",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-hook-reconciliation-apply-proof",
- "bead_id": "polylogue-hook-reconciliation-apply-proof",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 11
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-hook-reconciliation-apply-proof"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-raw-dedupe-apply-proof",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-raw-dedupe-apply-proof",
- "bead_id": "polylogue-raw-dedupe-apply-proof",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 12
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-raw-dedupe-apply-proof"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-reindex-preflight-authorization",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-reindex-preflight-authorization",
- "bead_id": "polylogue-reindex-preflight-authorization",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 13
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-reindex-preflight-authorization"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-s8s54",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-s8s54",
- "bead_id": "polylogue-s8s54",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 14
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-s8s54"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-stalled-cursor-live-proof",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-stalled-cursor-live-proof",
- "bead_id": "polylogue-stalled-cursor-live-proof",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 15
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-stalled-cursor-live-proof"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-uecir",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-uecir",
- "bead_id": "polylogue-uecir",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 16
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-uecir"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-xeck9",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-xeck9",
- "bead_id": "polylogue-xeck9",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 17
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-xeck9"
- },
- "receipts": [
- "implementation-proof-polylogue-xeck9"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-0qfy",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-0qfy",
- "bead_id": "polylogue-0qfy",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 18
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-0qfy"
- },
- "receipts": [
- "implementation-proof-polylogue-0qfy"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-7zp4",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-7zp4",
- "bead_id": "polylogue-7zp4",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 19
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-7zp4"
- },
- "receipts": [
- "implementation-proof-polylogue-7zp4"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-gysk3",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-gysk3",
- "bead_id": "polylogue-gysk3",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 20
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-gysk3"
- },
- "receipts": [
- "implementation-proof-polylogue-gysk3"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-slshy",
- "bead_status": "in_progress",
- "incident": {
- "incident_id": "incident-polylogue-slshy",
- "bead_id": "polylogue-slshy",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 21
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-slshy"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-uqwd",
- "bead_status": "in_progress",
- "incident": {
- "incident_id": "incident-polylogue-uqwd",
- "bead_id": "polylogue-uqwd",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 22
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-uqwd"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-052vs",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-052vs",
- "bead_id": "polylogue-052vs",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 23
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-052vs"
- },
- "receipts": [
- "implementation-proof-polylogue-052vs"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-1xc.8",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-1xc-8",
- "bead_id": "polylogue-1xc.8",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 24
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-1xc-8"
- },
- "receipts": [
- "implementation-proof-polylogue-1xc-8"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-2qx.3",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-2qx-3",
- "bead_id": "polylogue-2qx.3",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 25
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-2qx-3"
- },
- "receipts": [
- "implementation-proof-polylogue-2qx-3"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-2tfug",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-2tfug",
- "bead_id": "polylogue-2tfug",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 26
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-2tfug"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-5q2u",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-5q2u",
- "bead_id": "polylogue-5q2u",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 27
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-5q2u"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-6bebe",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-6bebe",
- "bead_id": "polylogue-6bebe",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 28
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-6bebe"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-6krh",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-6krh",
- "bead_id": "polylogue-6krh",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 29
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-6krh"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-8ac0",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-8ac0",
- "bead_id": "polylogue-8ac0",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 30
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-8ac0"
- },
- "receipts": [
- "implementation-proof-polylogue-8ac0"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-9kc0",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-9kc0",
- "bead_id": "polylogue-9kc0",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 31
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-9kc0"
- },
- "receipts": [
- "implementation-proof-polylogue-9kc0"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-9qnzy",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-9qnzy",
- "bead_id": "polylogue-9qnzy",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 32
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-9qnzy"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-aex0",
- "bead_status": "in_progress",
- "incident": {
- "incident_id": "incident-polylogue-aex0",
- "bead_id": "polylogue-aex0",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 33
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-aex0"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-b5l.1",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-b5l-1",
- "bead_id": "polylogue-b5l.1",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 34
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-b5l-1"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-c831",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-c831",
- "bead_id": "polylogue-c831",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 35
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-c831"
- },
- "receipts": [
- "implementation-proof-polylogue-c831"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-cc4k",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-cc4k",
- "bead_id": "polylogue-cc4k",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 36
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-cc4k"
- },
- "receipts": [
- "implementation-proof-polylogue-cc4k"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-cijx.2",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-cijx-2",
- "bead_id": "polylogue-cijx.2",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 37
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-cijx-2"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-ds4b4",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-ds4b4",
- "bead_id": "polylogue-ds4b4",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 38
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-ds4b4"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-e98k",
- "bead_status": "in_progress",
- "incident": {
- "incident_id": "incident-polylogue-e98k",
- "bead_id": "polylogue-e98k",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 39
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-e98k"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-es7b",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-es7b",
- "bead_id": "polylogue-es7b",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 40
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-es7b"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-f47j",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-f47j",
- "bead_id": "polylogue-f47j",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 41
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-f47j"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-gxig",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-gxig",
- "bead_id": "polylogue-gxig",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 42
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-gxig"
- },
- "receipts": [
- "implementation-proof-polylogue-gxig"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-h57ic",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-h57ic",
- "bead_id": "polylogue-h57ic",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 43
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-h57ic"
- },
- "receipts": [
- "implementation-proof-polylogue-h57ic"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-h7y0j",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-h7y0j",
- "bead_id": "polylogue-h7y0j",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 44
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-h7y0j"
- },
- "receipts": [
- "implementation-proof-polylogue-h7y0j"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-hjwr",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-hjwr",
- "bead_id": "polylogue-hjwr",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 45
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-hjwr"
- },
- "receipts": [
- "implementation-proof-polylogue-hjwr"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-i3zo",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-i3zo",
- "bead_id": "polylogue-i3zo",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 46
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-i3zo"
- },
- "receipts": [
- "implementation-proof-polylogue-i3zo"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-iuyr",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-iuyr",
- "bead_id": "polylogue-iuyr",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 47
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-iuyr"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-k8wv",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-k8wv",
- "bead_id": "polylogue-k8wv",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 48
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-k8wv"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-kmqwm",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-kmqwm",
- "bead_id": "polylogue-kmqwm",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 49
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-kmqwm"
- },
- "receipts": [
- "implementation-proof-polylogue-kmqwm"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-ksgg",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-ksgg",
- "bead_id": "polylogue-ksgg",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 50
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-ksgg"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-lb39z",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-lb39z",
- "bead_id": "polylogue-lb39z",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 51
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-lb39z"
- },
- "receipts": [
- "implementation-proof-polylogue-lb39z"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-lkrc",
- "bead_status": "in_progress",
- "incident": {
- "incident_id": "incident-polylogue-lkrc",
- "bead_id": "polylogue-lkrc",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 52
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-lkrc"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-lyv4",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-lyv4",
- "bead_id": "polylogue-lyv4",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 53
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-lyv4"
- },
- "receipts": [
- "implementation-proof-polylogue-lyv4"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-qhk8z",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-qhk8z",
- "bead_id": "polylogue-qhk8z",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 54
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-qhk8z"
- },
- "receipts": [
- "implementation-proof-polylogue-qhk8z"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-swqu",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-swqu",
- "bead_id": "polylogue-swqu",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 55
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-swqu"
- },
- "receipts": [
- "implementation-proof-polylogue-swqu"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-tnqqt",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-tnqqt",
- "bead_id": "polylogue-tnqqt",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 56
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-tnqqt"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-tu1f",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-tu1f",
- "bead_id": "polylogue-tu1f",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 57
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-tu1f"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-tw4ar",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-tw4ar",
- "bead_id": "polylogue-tw4ar",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 58
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-tw4ar"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-vp2ky",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-vp2ky",
- "bead_id": "polylogue-vp2ky",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 59
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-vp2ky"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-w6hql",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-w6hql",
- "bead_id": "polylogue-w6hql",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 60
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-w6hql"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-yla8",
- "bead_status": "in_progress",
- "incident": {
- "incident_id": "incident-polylogue-yla8",
- "bead_id": "polylogue-yla8",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 61
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-yla8"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-z22ml",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-z22ml",
- "bead_id": "polylogue-z22ml",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 62
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-z22ml"
- },
- "receipts": [
- "implementation-proof-polylogue-z22ml"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-zoek0",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-zoek0",
- "bead_id": "polylogue-zoek0",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 63
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-zoek0"
- },
- "receipts": [
- "implementation-proof-polylogue-zoek0"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-6753s",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-6753s",
- "bead_id": "polylogue-6753s",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 64
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-6753s"
- },
- "receipts": [
- "implementation-proof-polylogue-6753s"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-ix5r",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-ix5r",
- "bead_id": "polylogue-ix5r",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 65
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-ix5r"
- },
- "receipts": [
- "implementation-proof-polylogue-ix5r"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-nhbvf",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-nhbvf",
- "bead_id": "polylogue-nhbvf",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 66
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-nhbvf"
- },
- "receipts": [
- "implementation-proof-polylogue-nhbvf"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-zm4w8",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-zm4w8",
- "bead_id": "polylogue-zm4w8",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 67
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-zm4w8"
- },
- "receipts": [
- "implementation-proof-polylogue-zm4w8"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-eqq02",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-eqq02",
- "bead_id": "polylogue-eqq02",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 68
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-eqq02"
- },
- "receipts": [
- "implementation-proof-polylogue-eqq02"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-incident-coverage-ledger",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-incident-coverage-ledger",
- "bead_id": "polylogue-incident-coverage-ledger",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 69
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-incident-coverage-ledger"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-pr-scope-contract",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-pr-scope-contract",
- "bead_id": "polylogue-pr-scope-contract",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 70
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-pr-scope-contract"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-reindex-proof-edge-correction",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-reindex-proof-edge-correction",
- "bead_id": "polylogue-reindex-proof-edge-correction",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 71
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-reindex-proof-edge-correction"
- },
- "receipts": [
- "implementation-proof-polylogue-reindex-proof-edge-correction"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-2qrx",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-2qrx",
- "bead_id": "polylogue-2qrx",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 72
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-2qrx"
- },
- "receipts": [
- "implementation-proof-polylogue-2qrx"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-1fijp",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-1fijp",
- "bead_id": "polylogue-1fijp",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 73
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-1fijp"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-dcrmm",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-dcrmm",
- "bead_id": "polylogue-dcrmm",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 74
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-dcrmm"
- },
- "receipts": [
- "implementation-proof-polylogue-dcrmm"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-dudtn",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-dudtn",
- "bead_id": "polylogue-dudtn",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 75
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-dudtn"
- },
- "receipts": [
- "implementation-proof-polylogue-dudtn"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-3m3de",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-3m3de",
- "bead_id": "polylogue-3m3de",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 76
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-3m3de"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-4987i",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-4987i",
- "bead_id": "polylogue-4987i",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 77
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-4987i"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-mvcbi",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-mvcbi",
- "bead_id": "polylogue-mvcbi",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 78
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-mvcbi"
- },
- "receipts": [
- "implementation-proof-polylogue-mvcbi"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-o8c3m",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-o8c3m",
- "bead_id": "polylogue-o8c3m",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 79
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-o8c3m"
- },
- "receipts": [
- "implementation-proof-polylogue-o8c3m"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-omsw",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-omsw",
- "bead_id": "polylogue-omsw",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 80
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-omsw"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-r9xsj",
- "bead_status": "in_progress",
- "incident": {
- "incident_id": "incident-polylogue-r9xsj",
- "bead_id": "polylogue-r9xsj",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 81
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-r9xsj"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-lr6dx",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-lr6dx",
- "bead_id": "polylogue-lr6dx",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 82
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-lr6dx"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-ey4ro",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-ey4ro",
- "bead_id": "polylogue-ey4ro",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 83
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-ey4ro"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-ohkfy",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-ohkfy",
- "bead_id": "polylogue-ohkfy",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 84
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-ohkfy"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-t0m73",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-t0m73",
- "bead_id": "polylogue-t0m73",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 85
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-t0m73"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-inygw",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-inygw",
- "bead_id": "polylogue-inygw",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 86
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-inygw"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-0v4tn",
- "bead_status": "in_progress",
- "incident": {
- "incident_id": "incident-polylogue-0v4tn",
- "bead_id": "polylogue-0v4tn",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 87
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-0v4tn"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-84ake",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-84ake",
- "bead_id": "polylogue-84ake",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 88
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-84ake"
- },
- "receipts": [
- "implementation-proof-polylogue-84ake"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-2qx",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-2qx",
- "bead_id": "polylogue-2qx",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 89
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-2qx"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-rrxe4",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-rrxe4",
- "bead_id": "polylogue-rrxe4",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 90
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-rrxe4"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-yazae",
- "bead_status": "in_progress",
- "incident": {
- "incident_id": "incident-polylogue-yazae",
- "bead_id": "polylogue-yazae",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 91
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-yazae"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-in24n",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-in24n",
- "bead_id": "polylogue-in24n",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 92
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-in24n"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-reindex-registry-two-plane-subset",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-reindex-registry-two-plane-subset",
- "bead_id": "polylogue-reindex-registry-two-plane-subset",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 93
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-reindex-registry-two-plane-subset"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-4v2d3",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-4v2d3",
- "bead_id": "polylogue-4v2d3",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 94
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-4v2d3"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-amrpx",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-amrpx",
- "bead_id": "polylogue-amrpx",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 95
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-amrpx"
- },
- "receipts": [
- "implementation-proof-polylogue-amrpx"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-canonical-snapshot",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-canonical-snapshot",
- "bead_id": "polylogue-canonical-snapshot",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 96
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-canonical-snapshot"
- },
- "receipts": [
- "implementation-proof-polylogue-canonical-snapshot"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-ehzfn",
- "bead_status": "closed",
- "incident": {
- "incident_id": "incident-polylogue-ehzfn",
- "bead_id": "polylogue-ehzfn",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 97
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-ehzfn"
- },
- "receipts": [
- "implementation-proof-polylogue-ehzfn"
- ],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-un60n",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-un60n",
- "bead_id": "polylogue-un60n",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 98
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-un60n"
- },
- "receipts": [],
- "residual_successor": null
- },
- {
- "bead_id": "polylogue-g8v5z",
- "bead_status": "open",
- "incident": {
- "incident_id": "incident-polylogue-g8v5z",
- "bead_id": "polylogue-g8v5z",
- "forcing_class": "transitive-blocker"
- },
- "route": {
- "kind": "campaign",
- "entrypoint": "reindex-campaign"
- },
- "schedule": {
- "phase": "transitive-forcing-closure",
- "order": 99
- },
- "expected_snapshot": {
- "snapshot_id": "reindex-baseline-2026-08-03",
- "state": "blocking"
- },
- "registry_checks": [
- "campaign-coverage"
- ],
- "red_mutation": {
- "fixture_id": "campaign-graph",
- "mutation_id": "mutation-polylogue-g8v5z"
- },
- "receipts": [],
- "residual_successor": null
- }
- ],
- "routes": {
- "reindex-campaign": {
- "kind": "campaign-route",
- "source": "devtools/incident_coverage_ledger.py",
- "registry": "ROUTE_REGISTRY"
- },
- "reindex-final-proof": {
- "kind": "final-proof-route",
- "source": "devtools/incident_coverage_ledger.py",
- "registry": "ROUTE_REGISTRY"
- }
- }
-}
diff --git a/docs/plans/reindex-incident-coverage.schema.json b/docs/plans/reindex-incident-coverage.schema.json
deleted file mode 100644
index a588348109..0000000000
--- a/docs/plans/reindex-incident-coverage.schema.json
+++ /dev/null
@@ -1,189 +0,0 @@
-{
- "$schema": "https://json-schema.org/draft/2020-12/schema",
- "$id": "https://polylogue.local/schemas/reindex-incident-coverage-v1.json",
- "title": "Polylogue reindex incident coverage ledger",
- "type": "object",
- "required": [
- "schema_version",
- "ledger_id",
- "target_bead_id",
- "graph_fixture_id",
- "dependency_kinds",
- "fixtures",
- "checks",
- "snapshots",
- "receipts",
- "successors",
- "routes",
- "rows"
- ],
- "properties": {
- "schema_version": {"const": 1},
- "ledger_id": {"const": "polylogue-incident-coverage-ledger"},
- "target_bead_id": {"const": "polylogue-818fy"},
- "graph_fixture_id": {"type": "string", "minLength": 1},
- "dependency_kinds": {
- "type": "array",
- "minItems": 1,
- "uniqueItems": true,
- "items": {"$ref": "#/$defs/dependencyKind"}
- },
- "fixtures": {"$ref": "#/$defs/fixtureCatalog"},
- "checks": {"$ref": "#/$defs/catalog"},
- "snapshots": {"$ref": "#/$defs/catalog"},
- "receipts": {"$ref": "#/$defs/receiptCatalog"},
- "successors": {"$ref": "#/$defs/catalog"},
- "routes": {"$ref": "#/$defs/catalog"},
- "rows": {
- "type": "array",
- "minItems": 1,
- "items": {"$ref": "#/$defs/row"}
- }
- },
- "additionalProperties": false,
- "$defs": {
- "catalog": {
- "type": "object",
- "minProperties": 1,
- "additionalProperties": {
- "type": "object",
- "required": ["kind", "source"],
- "properties": {
- "kind": {"type": "string", "minLength": 1},
- "source": {"type": "string", "minLength": 1},
- "status": {"type": "string", "minLength": 1},
- "owner_bead_id": {"type": "string", "pattern": "^polylogue-[a-z0-9][a-z0-9.-]*$"}
- },
- "additionalProperties": true
- }
- },
- "fixtureCatalog": {
- "type": "object",
- "minProperties": 1,
- "additionalProperties": {
- "type": "object",
- "required": ["kind", "source", "mutation_ids"],
- "properties": {
- "kind": {"type": "string", "minLength": 1},
- "source": {"type": "string", "minLength": 1},
- "mutation_ids": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "string", "minLength": 1}}
- },
- "additionalProperties": true
- }
- },
- "dependencyKind": {
- "type": "string",
- "enum": ["blocks", "discovered-from", "parent-child", "relates-to", "supersedes"]
- },
- "routeKind": {
- "type": "string",
- "enum": ["campaign", "canary", "decision", "operation", "registry"]
- },
- "receiptCatalog": {
- "type": "object",
- "minProperties": 1,
- "additionalProperties": {
- "type": "object",
- "required": ["kind", "source", "owner_bead_id"],
- "properties": {
- "kind": {"type": "string", "minLength": 1},
- "source": {"type": "string", "minLength": 1},
- "status": {"type": "string", "minLength": 1},
- "owner_bead_id": {"type": "string", "pattern": "^polylogue-[a-z0-9][a-z0-9.-]*$"}
- },
- "additionalProperties": true
- }
- },
- "row": {
- "type": "object",
- "required": [
- "bead_id",
- "bead_status",
- "incident",
- "route",
- "schedule",
- "expected_snapshot",
- "registry_checks",
- "red_mutation",
- "receipts",
- "residual_successor"
- ],
- "properties": {
- "bead_id": {"type": "string", "pattern": "^polylogue-[a-z0-9][a-z0-9.-]*$"},
- "bead_status": {"enum": ["open", "in_progress", "closed"]},
- "incident": {
- "type": "object",
- "required": ["incident_id", "bead_id", "forcing_class"],
- "properties": {
- "incident_id": {"type": "string", "minLength": 1},
- "bead_id": {"type": "string", "minLength": 1},
- "forcing_class": {"type": "string", "minLength": 1}
- },
- "additionalProperties": false
- },
- "route": {
- "type": "object",
- "required": ["kind", "entrypoint"],
- "properties": {
- "kind": {"$ref": "#/$defs/routeKind"},
- "entrypoint": {"type": "string", "minLength": 1}
- },
- "additionalProperties": false
- },
- "schedule": {
- "type": "object",
- "required": ["phase", "order"],
- "properties": {
- "phase": {"type": "string", "minLength": 1},
- "order": {"type": "integer", "minimum": 1}
- },
- "additionalProperties": false
- },
- "expected_snapshot": {
- "type": "object",
- "required": ["snapshot_id", "state"],
- "properties": {
- "snapshot_id": {"type": "string", "minLength": 1},
- "state": {"enum": ["blocking", "green", "red", "unknown"]}
- },
- "additionalProperties": false
- },
- "registry_checks": {
- "type": "array",
- "minItems": 1,
- "items": {"type": "string", "minLength": 1},
- "uniqueItems": true
- },
- "red_mutation": {
- "type": "object",
- "required": ["fixture_id", "mutation_id"],
- "properties": {
- "fixture_id": {"type": "string", "minLength": 1},
- "mutation_id": {"type": "string", "minLength": 1}
- },
- "additionalProperties": false
- },
- "receipts": {
- "type": "array",
- "items": {"type": "string", "minLength": 1},
- "uniqueItems": true
- },
- "residual_successor": {
- "oneOf": [
- {"type": "null"},
- {
- "type": "object",
- "required": ["bead_id", "kind"],
- "properties": {
- "bead_id": {"type": "string", "minLength": 1},
- "kind": {"type": "string", "minLength": 1}
- },
- "additionalProperties": false
- }
- ]
- }
- },
- "additionalProperties": false
- }
- }
-}
diff --git a/docs/plans/release-readiness-gate.md b/docs/plans/release-readiness-gate.md
deleted file mode 100644
index cecc452a2a..0000000000
--- a/docs/plans/release-readiness-gate.md
+++ /dev/null
@@ -1,135 +0,0 @@
-# Release Readiness Gate
-
-Issue: #1827.
-
-This gate decides whether Polylogue is externally presentable enough to merge a
-release PR. A green release workflow is not sufficient: the release must be
-installable, demoable without private data, and truthful about shipped command,
-read, import, and output surfaces.
-
-## Gate Rule
-
-The release PR remains held unless every required item below is either:
-
-- `satisfied`, with a PR/check/document citation; or
-- `scoped out`, with release notes that explicitly avoid claiming the missing
- capability.
-
-Do not use release pressure to force unrelated architecture work. Design-frontier
-issues can stay open when the README and release notes do not advertise them as
-shipped product behavior.
-
-## Required Local Commands
-
-Run these from a clean checkout inside the devshell:
-
-```bash
-devtools release readiness
-devtools release readiness --release-body-file /tmp/release-pr-body.md
-devtools verify --quick
-devtools verify public-claims
-devtools verify --lab
-devtools release build-package
-devtools render pages
-devtools verify doc-commands
-```
-
-Add focused commands for changed release surfaces:
-
-```bash
-devtools test tests/unit/cli/test_query_verbs_runtime.py
-devtools test tests/unit/storage/test_blackboard_facade.py
-devtools test tests/unit/cli/test_demo_command.py tests/unit/demo/test_demo_seed_verify.py tests/visual
-```
-
-If packaging, Nix, or dependency metadata changed, also run:
-
-```bash
-nix flake check
-```
-
-## Automated Gate Matrix
-
-| Area | Required Evidence | Current Owner |
-| --- | --- | --- |
-| Command floor | Final public command tree has no stale command aliases or undocumented examples. | #1842 |
-| Machine output | JSON is finite, NDJSON is streaming, mutation/error envelopes are typed, and machine-output prompts do not block. | #1818, #1816 |
-| README commands | README examples resolve against live commands and do not cite stale APIs. | #1841 |
-| Import/demo | Public import vocabulary is stable and demo mode has deterministic private-data-free fixtures. | #1815, #1843 |
-| Session digest/context | Agent-session context bundles are available only to the extent claimed by README/release notes. | #1880, #1838 |
-| Assertion/user state | User-tier assertion data is preserved and reset/delete flows are guarded. | #1883 |
-| Public vocabulary | Public surfaces use session/origin vocabulary; provider/conversation terms are raw-source or historical only. | #1810 |
-| Web/API | Any advertised web/API surface has stable DTOs, auth posture, and route vocabulary. | #1847, #1846 |
-| Static/docs surface | Generated docs, pages, media, and topology status are current. | #1848, #1849 |
-| CI reliability | Known benchmark/test flakes are resolved or explicitly excluded from the release gate with rationale. | #1878 |
-| Packaging | Wheel/sdist/Nix package expose only supported runtime entrypoints. | `devtools release build-package`, `nix flake check` |
-
-## Manual Release Review
-
-Before merging a release PR, record the answers in the PR body and run `devtools release readiness --release-body-file ` against that exact body text:
-
-| Question | Required Answer |
-| --- | --- |
-| What can a new user run first? | Exact command sequence, including archive root/demo root. |
-| Does the sequence touch private archives? | No, unless the user supplied an explicit source path. |
-| Which origins are advertised? | Only origins with current parser/import/read evidence. |
-| Which features are deliberately not shipped? | Listed in release notes, with open issue refs. |
-| What irreversible publication happens? | PyPI/GHCR/tag behavior stated before merge. |
-| Which local gates ran? | Exact commands and key pass/fail line. |
-
-## Current Status
-
-Satisfied:
-
-- #1810 public session/origin vocabulary sweep is closed.
-- #1816 action-contract coverage is derived from `ACTION_CONTRACTS` and the
- generated CLI output schemas; the old hand-maintained assurance registry is
- gone.
-- #1818 machine-output concrete violations are closed.
-- #1841 README cockpit is landed and command examples are checked by
- `verify doc-commands`.
-- #1878 benchmark convergence flake is closed.
-- #1880 has session digest registry, extraction, CLI read view, Python API
- facade, GitHub/check event extraction slices, and source-aligned query DSL
- documentation for currently shipped recovery/query behavior.
-- #1883 has the assertions table, write-through adapters, delete/status
- transitions, reset user.db guard, and blackboard assertion metadata slices.
-- #1843 has deterministic demo corpus specs and the `polylogue import --demo`
- scheduling surface plus fixture-world convergence coverage.
-- #1848 static/rendering redundancy pruning is closed.
-- #1849 replaced decorative verification with code-coupled tests and generated evidence
- surfaces; release notes must still avoid claiming any detached confidence
- layer.
-- #1825 MCP/Python parity is closed for the shared query/read contracts that
- exist today; new route or mutation surfaces still need parity evidence in
- their owning issues.
-- #1838 successor context outputs are implemented as on-demand evidence bundles
- with raw-ref/lossiness semantics for currently shipped context surfaces.
-
-Still blocking external release claims:
-
-- #1847/#1846 web/API release scope is not settled.
-- #2006 advanced query language claims are scoped to shipped Lark grammar,
- lowerers, typed errors, docs, and fixture coverage; do not advertise future
- pipeline/run/event/assertion query units until they land.
-- #1807 remains open until the README, CLI help, docs site, daemon shell, and
- release notes tell one truthful product story over the shipped surfaces.
-
-## Release PR Body Requirements
-
-Use this section in the release PR:
-
-```text
-Release gate:
-- Command floor:
-- Machine output:
-- README/demo:
-- Import/demo fixture:
-- Session digest/context:
-- Web/API scope:
-- Packaging:
-- Known caveats scoped out:
-
-Verification:
-- —
-```
diff --git a/docs/plans/scenario-coverage.yaml b/docs/plans/scenario-coverage.yaml
deleted file mode 100644
index 8dbb050b55..0000000000
--- a/docs/plans/scenario-coverage.yaml
+++ /dev/null
@@ -1,146 +0,0 @@
-# Scenario-coverage manifest.
-#
-# Declares verification scenario families and their subject coverage.
-# Each family groups scenarios that verify a common surface or
-# concern. Verification closure comes from executable scenarios and
-# coverage gaps, not maturity self-declarations.
-#
-# Updated 2026-04-29 from realized codebase state.
-
-description: >
- Scenario families and their subject coverage across Polylogue lab
- surfaces. Documents which surfaces have executable scenario specifications
- and which lack them.
-
-families:
- - name: cli_surfaces
- description: CLI command surface checks
- subject: cli_surface
- scenario_count: dynamic
- location: polylogue/scenarios/cli_surfaces.py
- notes: >
- Generates CLI-surface checks and variants (live, memory
- budget) from CliSurfaceFamily definitions. Covers all CLI
- commands via help-output and exit-code assertions.
-
- - name: insight_surfaces
- description: Insight command surface checks
- subject: cli_surface
- scenario_count: dynamic
- location: polylogue/scenarios/insight_surfaces.py
- notes: >
- Covers insight commands (resume, insights) and their
- rendering contracts. Includes live and contract variants.
-
- - name: operational_surfaces
- description: Operational surface checks
- subject: operational_resilience
- scenario_count: dynamic
- location: polylogue/scenarios/operational_surfaces.py
- notes: >
- Covers maintenance operations, repair, check commands.
- Includes live and memory budget lanes.
-
- - name: corpus_scenarios
- description: Synthetic corpus scenario specs
- subject: provider_coverage
- scenario_count: dynamic
- location: polylogue/scenarios/corpus.py
- notes: >
- CorpusScenario subclass generates synthetic archives for
- all 5 providers. Configurable profiles, source kinds, and
- counts. Used by verification workspaces and pipeline probes.
-
- - name: executable_scenarios
- description: Named executable scenario wrappers
- subject: unclassified
- scenario_count: dynamic
- location: polylogue/scenarios/executable.py
- notes: >
- Minimal ExecutableScenario wraps a NamedScenarioSource
- into an executable form. Used as adapter for scenario
- dispatch.
-
- - name: assertion_scenarios
- description: Assertion specs for scenario verification
- subject: spec_accuracy
- scenario_count: dynamic
- location: polylogue/scenarios/assertions.py
- notes: >
- AssertionSpec types (exit-code, stdout-contains, etc.)
- for composing scenario verification predicates.
-
- - name: projection_scenarios
- description: Scenario-to-evidence projection specs
- subject: spec_completeness
- scenario_count: dynamic
- location: polylogue/scenarios/projections.py
- notes: >
- ScenarioProjectionSource maps scenarios to verification
- projections. Supports scenario-aware evidence reference
- rendering.
-
- - name: runtime_scenarios
- description: Scenario execution runtime
- subject: pipeline_correctness
- scenario_count: dynamic
- location: polylogue/scenarios/runtime.py
- notes: >
- Execution dispatch, runner invocation, and result handling
- for scenario execution. Supports pytest, CLI, devtools,
- and pipeline-probe execution kinds.
-
- - name: storage_correctness
- description: Archive-backed storage correctness scenario family
- subject: storage_correctness
- scenario_count: 4
- location: devtools/storage_correctness_scenario.py
- bead: polylogue-9e5.19
- notes: >
- Realized from the prior scenario.storage-correctness gap.
- Runs through the devtools lab smoke/lane registry against
- real ArchiveStore split-tier writes. Covers content-hash
- idempotency, canonical message FTS trigger drift and production
- recovery, lineage prefix-sharing composition, and current blob
- GC invariants. The old blob-lease wording was stale because no
- production writer populated it. This family instead covers
- publication/reference survival, gc_generations age/snapshot
- gating, and typed reclaim evidence.
-
-coverage_gaps:
- - id: scenario.performance
- subject: performance
- gap: No scenario family exercising memory or throughput budgets
- owner: scenario-coverage
- severity: major
- declared_at: "2026-05-02"
- review_after: "2026-08-01"
- bead: polylogue-20d.16
- next_evidence: devtools lab projections
- - id: scenario.security-privacy
- subject: security_privacy
- gap: Security verification uses unit tests, not scenario specs
- owner: scenario-coverage
- severity: major
- declared_at: "2026-05-02"
- review_after: "2026-08-01"
- bead: polylogue-kwsb
- next_evidence: devtools lab projections
- - id: scenario.distribution
- subject: distribution
- gap: No scenario for install/package verification
- owner: scenario-coverage
- severity: major
- declared_at: "2026-05-02"
- review_after: "2026-08-01"
- bead: polylogue-3tl.7
- next_evidence: devtools lab projections
- - id: scenario.schema-rebuild-safety
- subject: schema_rebuild_safety
- gap: No scenario for schema rebuild safety verification
- owner: scenario-coverage
- severity: major
- declared_at: "2026-05-02"
- review_after: "2026-08-01"
- bead: polylogue-1xc.8
- next_evidence: devtools lab projections
diff --git a/docs/plans/security-privacy-coverage.yaml b/docs/plans/security-privacy-coverage.yaml
deleted file mode 100644
index a15c090a6a..0000000000
--- a/docs/plans/security-privacy-coverage.yaml
+++ /dev/null
@@ -1,252 +0,0 @@
-# Security-and-privacy coverage manifest.
-#
-# Documents the current security and privacy verification surface
-# across path sanitization, attachment security, MCP safety, exec
-# command validation, SSRF prevention, HTML sanitization, schema
-# privacy, and token-store security.
-#
-# Updated 2026-07-12 from realized codebase state.
-
-description: >
- Security and privacy verification surface for polylogue.
- Documents implemented controls, test coverage, and gaps.
-
-areas:
- xss_prevention:
- description: Cross-site scripting defense in rendered HTML and the daemon web shell
- implemented: true
- controls:
- - jinja2_autoescape: Jinja2 template autoescaping is active
- - html_sanitizer: >
- sanitize_html() filter in polylogue/rendering/renderers/
- html_sanitizer.py strips