strata-agent-memory 0.2.4__tar.gz → 0.2.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. {strata_agent_memory-0.2.4/strata_agent_memory.egg-info → strata_agent_memory-0.2.6}/PKG-INFO +8 -4
  2. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/README.md +7 -3
  3. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/__init__.py +1 -1
  4. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/audit.py +87 -6
  5. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/cli.py +385 -50
  6. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/compact.py +2 -0
  7. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/compiler.py +6 -1
  8. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/contracts.py +53 -15
  9. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/evidence.py +951 -76
  10. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/hooks.py +12 -9
  11. strata_agent_memory-0.2.6/agent_memory/lane.py +932 -0
  12. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/ledger.py +74 -7
  13. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/mcp_server.py +50 -12
  14. strata_agent_memory-0.2.6/agent_memory/measure.py +692 -0
  15. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/pathmap.py +36 -5
  16. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/recheck.py +54 -18
  17. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/records.py +142 -2
  18. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/relay/adapters.py +5 -3
  19. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/relay/cli.py +31 -9
  20. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/relay/client.py +329 -25
  21. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/relay/core.py +115 -11
  22. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/reliability.py +107 -21
  23. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/remote.py +16 -4
  24. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/serve.py +130 -7
  25. strata_agent_memory-0.2.6/agent_memory/supersession.py +143 -0
  26. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/trust.py +45 -14
  27. strata_agent_memory-0.2.6/agent_memory/wake.py +296 -0
  28. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/mac/README.md +16 -3
  29. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/mac/agent-session.sh +9 -3
  30. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/mac/relay-agent.sh +34 -12
  31. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/plugins/README.md +39 -3
  32. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/plugins/claude-code/.claude-plugin/plugin.json +2 -2
  33. strata_agent_memory-0.2.6/deploy/plugins/claude-code/bin/agent-memory-wake +36 -0
  34. strata_agent_memory-0.2.6/deploy/plugins/claude-code/monitors/monitors.json +7 -0
  35. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/plugins/claude-code/skills/approvals/SKILL.md +2 -2
  36. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/plugins/claude-code/skills/approve/SKILL.md +2 -2
  37. strata_agent_memory-0.2.6/deploy/plugins/claude-code/skills/inbox/SKILL.md +27 -0
  38. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/plugins/claude-code/skills/reject/SKILL.md +2 -2
  39. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/relay/install-relay-mac.sh +46 -15
  40. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/relay/install-relay.sh +17 -10
  41. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/relay/macos/com.strata.agent-memory.relay.plist.template +4 -3
  42. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/pyproject.toml +2 -1
  43. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6/strata_agent_memory.egg-info}/PKG-INFO +8 -4
  44. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/strata_agent_memory.egg-info/SOURCES.txt +31 -1
  45. strata_agent_memory-0.2.6/tests/test_assessment_67b26eae.py +266 -0
  46. strata_agent_memory-0.2.6/tests/test_audit_lane_numbers_ea89ba26.py +289 -0
  47. strata_agent_memory-0.2.6/tests/test_audit_measurement_13190a20.py +441 -0
  48. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_backlog_check.py +3 -2
  49. strata_agent_memory-0.2.6/tests/test_changelog_guard_shallow_57a2f78e.py +168 -0
  50. strata_agent_memory-0.2.6/tests/test_ci_docs_only_353ce010.py +134 -0
  51. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_contracts.py +3 -1
  52. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_deploy_mac.py +4 -2
  53. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_deploy_relay.py +2 -2
  54. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_evidence.py +4 -3
  55. strata_agent_memory-0.2.6/tests/test_find_root_b4b5019b.py +216 -0
  56. strata_agent_memory-0.2.6/tests/test_lane_63b7cf8b.py +762 -0
  57. strata_agent_memory-0.2.6/tests/test_lane_priority_779d51ba.py +328 -0
  58. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_ledger.py +6 -2
  59. strata_agent_memory-0.2.6/tests/test_live_wake_c217c336.py +921 -0
  60. strata_agent_memory-0.2.6/tests/test_local_lanes_sibling_1411a2b2.py +275 -0
  61. strata_agent_memory-0.2.6/tests/test_outcome_commit_binding_b1de564d.py +527 -0
  62. strata_agent_memory-0.2.6/tests/test_outcome_needs_evidence_b1de564d.py +130 -0
  63. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_plugins.py +4 -4
  64. strata_agent_memory-0.2.6/tests/test_receipt_reports_274e6199.py +432 -0
  65. strata_agent_memory-0.2.6/tests/test_recheck_remote_8185d2d3.py +317 -0
  66. strata_agent_memory-0.2.6/tests/test_recheck_sandbox_543e48a7.py +615 -0
  67. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_relay_client.py +7 -2
  68. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_relay_core.py +3 -3
  69. strata_agent_memory-0.2.6/tests/test_relay_instance_2a2e3887.py +120 -0
  70. strata_agent_memory-0.2.6/tests/test_relay_release_526f5261.py +128 -0
  71. strata_agent_memory-0.2.6/tests/test_relay_release_gate_b3b3e487.py +383 -0
  72. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_remote.py +4 -2
  73. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_serve.py +42 -5
  74. strata_agent_memory-0.2.6/tests/test_sit_fleet_1b24b0b1.py +86 -0
  75. strata_agent_memory-0.2.6/tests/test_sit_fleet_ci_0d9b76a2.py +30 -0
  76. strata_agent_memory-0.2.6/tests/test_sit_var_bindings_e802ca84.py +288 -0
  77. strata_agent_memory-0.2.6/tests/test_supersedes_61416280.py +433 -0
  78. strata_agent_memory-0.2.6/tests/test_uv_lock_env_274e6199.py +245 -0
  79. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/LICENSE +0 -0
  80. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/__main__.py +0 -0
  81. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/approvals.py +0 -0
  82. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/export.py +0 -0
  83. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/identity.py +0 -0
  84. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/instances.py +0 -0
  85. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/kit.py +0 -0
  86. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/memorizer.py +0 -0
  87. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/relay/__init__.py +0 -0
  88. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/render.py +0 -0
  89. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/roster.py +0 -0
  90. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/signing.py +0 -0
  91. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/agent_memory/stats.py +0 -0
  92. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/mac/agent-keys.sh +0 -0
  93. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/mac/backup-tokens.sh +0 -0
  94. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/mac/install-hooks-mac.sh +0 -0
  95. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/mac/install-relay-driver.sh +0 -0
  96. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/mac/install-replica-driver.sh +0 -0
  97. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/mac/install-runner-driver.sh +0 -0
  98. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/mac/instances.example.json +0 -0
  99. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/mac/onboard-agent.sh +0 -0
  100. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/mac/seed-board.sh +0 -0
  101. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/mac/seed-mail-context.sh +0 -0
  102. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/mac/seed-topics.sh +0 -0
  103. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/mac/upgrade-driver.sh +0 -0
  104. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/plugins/.claude-plugin/marketplace.json +0 -0
  105. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/plugins/claude-code/bin/agent-memory-approvals +0 -0
  106. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/plugins/claude-code/hooks/hooks.json +0 -0
  107. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/plugins/claude-code/rules/approvals.md +0 -0
  108. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/plugins/codex/skills/agent-memory-answer/SKILL.md +0 -0
  109. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/plugins/codex/skills/agent-memory-answer/agents/openai.yaml +0 -0
  110. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/plugins/codex/skills/agent-memory-approvals/SKILL.md +0 -0
  111. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/plugins/codex/skills/agent-memory-approvals/agents/openai.yaml +0 -0
  112. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/plugins/codex/skills/agent-memory-approvals/rules/approvals.md +0 -0
  113. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/plugins/codex/skills/agent-memory-approvals/scripts/agent-memory-approvals +0 -0
  114. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/relay/README.md +0 -0
  115. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/relay/agent-memory-relay@.service +0 -0
  116. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/deploy/relay/relay-launch.sh +0 -0
  117. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/setup.cfg +0 -0
  118. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/strata_agent_memory.egg-info/dependency_links.txt +0 -0
  119. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/strata_agent_memory.egg-info/entry_points.txt +0 -0
  120. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/strata_agent_memory.egg-info/requires.txt +0 -0
  121. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/strata_agent_memory.egg-info/top_level.txt +0 -0
  122. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_audit.py +0 -0
  123. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_changelog_fragments.py +0 -0
  124. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_cli.py +0 -0
  125. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_compact.py +0 -0
  126. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_compiler.py +0 -0
  127. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_compiler_render.py +0 -0
  128. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_config.py +0 -0
  129. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_deploy_replica.py +0 -0
  130. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_deploy_tokens.py +0 -0
  131. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_hooks.py +0 -0
  132. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_identity.py +0 -0
  133. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_issue_bridge.py +0 -0
  134. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_ledger_index.py +0 -0
  135. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_memorizer.py +0 -0
  136. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_packaging.py +0 -0
  137. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_pathmap.py +0 -0
  138. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_phase2.py +0 -0
  139. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_recheck.py +0 -0
  140. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_records.py +0 -0
  141. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_redaction.py +0 -0
  142. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_relay_adapters.py +0 -0
  143. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_relay_codex.py +0 -0
  144. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_reliability.py +0 -0
  145. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_remote_signing.py +0 -0
  146. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_review2_fixes.py +0 -0
  147. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_review3_fixes.py +0 -0
  148. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_review_fixes.py +0 -0
  149. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_scale.py +0 -0
  150. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_signing.py +0 -0
  151. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_stats.py +0 -0
  152. {strata_agent_memory-0.2.4 → strata_agent_memory-0.2.6}/tests/test_trust.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: strata-agent-memory
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: Portable, auditable, cross-vendor memory for LLM agents: evidence-bound claims, trust tiers, and compiled context views.
5
5
  Author: Strata Intelligence
6
6
  License-Expression: Apache-2.0
@@ -75,7 +75,7 @@ pip install strata-agent-memory # the CLI is `agent-memory`; or, from a chec
75
75
  cd your-project && agent-memory init
76
76
 
77
77
  agent-memory run -- pytest -q # -> {"id": "ev_…", "kind": "test", "passed": 42, ...}
78
- agent-memory claim outcome "auth tests pass" -e ev_… --commit
78
+ agent-memory claim outcome "auth tests pass" -e ev_… # inside a git checkout it binds HEAD too
79
79
  agent-memory claim outcome "deployed" # -> rejected: outcome claims require at least one receipt
80
80
 
81
81
  agent-memory claim fact "sessions renew via renewSession()" --source src/auth.py
@@ -91,6 +91,7 @@ agent-memory claim fact "w3lib.get_meta_refresh takes baseurl" --source w3lib/ht
91
91
  agent-memory compile --role worker --task "extend auth" # a fork-mode brief; reports what memory holds nothing on
92
92
  agent-memory compile --role verifier --contract ctr_… --round 2 --lens security # isolated review brief with a lens
93
93
  agent-memory audit # tiers, static-only outcomes, taint chains, verifier lineage matrix
94
+ agent-memory audit --since 2026-09-21 --until 2026-09-28 # and the measurement section for that week (default: the last seven days)
94
95
  agent-memory reliability # how often claims like these were refuted, with n and an interval; fitted staleness
95
96
  AGENT_MEMORY_HARNESS=ollama agent-memory recheck --map /Users/craig/src=/home/chris/src # the nightly lane, from another machine
96
97
  agent-memory serve # HTTP API, SSE and remote MCP on loopback; add --tokens FILE
@@ -150,8 +151,11 @@ disposable replica: a SQLite index rebuilt from the shards, bearer-token
150
151
  identity, an HTTP API, server-sent events, a remote MCP endpoint
151
152
  (Streamable HTTP, revisions 2025-03-26, 2025-06-18 and the stateless
152
153
  2026-07-28, chosen per request) so cloud agents
153
- reach the ledger without a clone (Claude Code on the web only through an
154
- organization-managed connector; Codex cloud unverified), and scheduled
154
+ reach the ledger without a clone (Claude Code on the web through the repo's
155
+ `.mcp.json` in single-repo sessions, organization-managed connectors, beta
156
+ static-header connectors or self-hosted environments
157
+ ( https://code.claude.com/docs/en/claude-code-on-the-web ); Codex cloud
158
+ unverified), and scheduled
155
159
  recheck and git-sync lanes. Losing the service never loses state
156
160
  (docs/BETA-SPEC.md section 4, `examples/remote/`).
157
161
 
@@ -51,7 +51,7 @@ pip install strata-agent-memory # the CLI is `agent-memory`; or, from a chec
51
51
  cd your-project && agent-memory init
52
52
 
53
53
  agent-memory run -- pytest -q # -> {"id": "ev_…", "kind": "test", "passed": 42, ...}
54
- agent-memory claim outcome "auth tests pass" -e ev_… --commit
54
+ agent-memory claim outcome "auth tests pass" -e ev_… # inside a git checkout it binds HEAD too
55
55
  agent-memory claim outcome "deployed" # -> rejected: outcome claims require at least one receipt
56
56
 
57
57
  agent-memory claim fact "sessions renew via renewSession()" --source src/auth.py
@@ -67,6 +67,7 @@ agent-memory claim fact "w3lib.get_meta_refresh takes baseurl" --source w3lib/ht
67
67
  agent-memory compile --role worker --task "extend auth" # a fork-mode brief; reports what memory holds nothing on
68
68
  agent-memory compile --role verifier --contract ctr_… --round 2 --lens security # isolated review brief with a lens
69
69
  agent-memory audit # tiers, static-only outcomes, taint chains, verifier lineage matrix
70
+ agent-memory audit --since 2026-09-21 --until 2026-09-28 # and the measurement section for that week (default: the last seven days)
70
71
  agent-memory reliability # how often claims like these were refuted, with n and an interval; fitted staleness
71
72
  AGENT_MEMORY_HARNESS=ollama agent-memory recheck --map /Users/craig/src=/home/chris/src # the nightly lane, from another machine
72
73
  agent-memory serve # HTTP API, SSE and remote MCP on loopback; add --tokens FILE
@@ -126,8 +127,11 @@ disposable replica: a SQLite index rebuilt from the shards, bearer-token
126
127
  identity, an HTTP API, server-sent events, a remote MCP endpoint
127
128
  (Streamable HTTP, revisions 2025-03-26, 2025-06-18 and the stateless
128
129
  2026-07-28, chosen per request) so cloud agents
129
- reach the ledger without a clone (Claude Code on the web only through an
130
- organization-managed connector; Codex cloud unverified), and scheduled
130
+ reach the ledger without a clone (Claude Code on the web through the repo's
131
+ `.mcp.json` in single-repo sessions, organization-managed connectors, beta
132
+ static-header connectors or self-hosted environments
133
+ ( https://code.claude.com/docs/en/claude-code-on-the-web ); Codex cloud
134
+ unverified), and scheduled
131
135
  recheck and git-sync lanes. Losing the service never loses state
132
136
  (docs/BETA-SPEC.md section 4, `examples/remote/`).
133
137
 
@@ -9,4 +9,4 @@ see, what did it claim, and can the proof be re-run.
9
9
  The core is dependency-free (Python 3.10+ standard library only).
10
10
  """
11
11
 
12
- __version__ = "0.2.4"
12
+ __version__ = "0.2.6"
@@ -27,12 +27,14 @@ from collections import Counter, defaultdict
27
27
  from typing import Dict, List, Optional
28
28
 
29
29
  from . import evidence as ev
30
+ from . import measure as measure_mod
30
31
  from . import reliability as rel
32
+ from . import supersession as supersession_mod
31
33
  from . import roster as roster_mod
32
34
  from . import signing
33
35
  from .contracts import status_of
34
36
  from .ledger import UNTRUSTED_POLICY
35
- from .records import is_redacted, receipt_visible_to
37
+ from .records import is_assessment, is_redacted, receipt_visible_to
36
38
  from .trust import TIERS, assess, lineage_differs, summarize
37
39
 
38
40
  # Anything a compiled view would have to render on its own line. The renderer collapses
@@ -189,12 +191,15 @@ def _roster_sections(ledger, rep: Dict, by_id: Dict[str, dict], reader_user: Opt
189
191
 
190
192
 
191
193
  def report(ledger, recheck: bool = False, cwd: Optional[str] = None, timeout: Optional[float] = 300,
192
- path_map=None, reader_user: Optional[str] = None) -> dict:
194
+ path_map=None, reader_user: Optional[str] = None, since: Optional[str] = None,
195
+ until: Optional[str] = None) -> dict:
193
196
  """The audit, for one reader. ``reader_user`` is who is asking: a user-scoped claim is
194
197
  one person's private memory and is listed for its owner and for nobody else, the same
195
198
  rule ``receipt_visible_to`` applies everywhere a record is shown (verification review
196
199
  F1: the audit listed every user's private statements to any token). A local audit
197
- with no reader named sees everything, as the local ledger's owner does."""
200
+ with no reader named sees everything, as the local ledger's owner does. ``since`` and
201
+ ``until`` are the measurement section's window (measure.window; ValueError when it is
202
+ empty or a bound does not parse)."""
198
203
  assessment = assess(ledger)
199
204
  claims = ledger.claims()
200
205
  if reader_user is not None:
@@ -213,10 +218,14 @@ def report(ledger, recheck: bool = False, cwd: Optional[str] = None, timeout: Op
213
218
  "unrechecked_outcomes": [],
214
219
  "failing_receipt_outcomes": [],
215
220
  "static_only_outcomes": [],
221
+ "dirty_bound_outcomes": [],
216
222
  "assurance_overridden": [],
217
223
  "same_vendor_only": [],
218
224
  "self_verified_by_author": [],
219
225
  "same_session_different_harness": [],
226
+ # D6 (ctr_67b26eae6bff4b63): another identity's reading of a claim, asked for; listed
227
+ # here and nowhere a verdict is counted
228
+ "assessments": [],
220
229
  "formatted_statements": [],
221
230
  "redactions": {"count": 0, "ids": []},
222
231
  # absent and empty mean different things (an absent key is the starter default
@@ -227,6 +236,11 @@ def report(ledger, recheck: bool = False, cwd: Optional[str] = None, timeout: Op
227
236
  "same_lineage_refutation_rate": None,
228
237
  "cross_lineage_refutation_rate": None,
229
238
  "refuted": [],
239
+ # ctr_614162800937e387: outcomes replaced by a later one, records withdrawn as
240
+ # artefacts, and the old wrong retractions a PM may want to call artefacts
241
+ "superseded": [],
242
+ "withdrawn": [],
243
+ "artefact_candidates": [],
230
244
  "taint_chains": [],
231
245
  "stale": [],
232
246
  "asserted_facts": [],
@@ -241,6 +255,23 @@ def report(ledger, recheck: bool = False, cwd: Optional[str] = None, timeout: Op
241
255
  "verifications_outside_project_roster": {},
242
256
  "recheck": [],
243
257
  }
258
+ # retractions filed as wrong -- every one before kinds -- whose reason names the claim
259
+ # that replaced it or reads like a stray test record: the PM may file an artefact
260
+ # retraction beside each, which then decides the claim's kind, never editing the old
261
+ # record (ctr_614162800937e387)
262
+ for r in sorted(ledger.by_kind("retraction"), key=lambda rec: rec["ts"]):
263
+ body = r.get("body") if isinstance(r.get("body"), dict) else {}
264
+ claim_id = body.get("claim")
265
+ if claim_id not in by_id or supersession_mod.retraction_kind(r) != "wrong":
266
+ continue
267
+ if supersession_mod.operative_kind(ledger.retractions_for(claim_id)) != "wrong":
268
+ continue # already answered by an artefact retraction beside it
269
+ reason = str(body.get("reason") or "")
270
+ why = ("names the claim that replaced it" if supersession_mod.REPLACEMENT.search(reason)
271
+ else "reads like a stray test record" if supersession_mod.TEST_LEAK.search(reason) else None)
272
+ if why:
273
+ rep["artefact_candidates"].append({"retraction": r["id"], "claim": claim_id,
274
+ "reason": reason[:160], "why": why})
244
275
  # measured history, computed from the ledger alone: counts, intervals, and the word
245
276
  # "insufficient history" wherever there are too few of them
246
277
  measured = rel.report(ledger, assessment)
@@ -275,6 +306,12 @@ def report(ledger, recheck: bool = False, cwd: Optional[str] = None, timeout: Op
275
306
  if backed in ("static", "attested"):
276
307
  # a clean static gate is not evidence that the thing runs
277
308
  rep["static_only_outcomes"].append({**entry, "assurance": backed})
309
+ # the writer's own word that its receipts ran on a tree no sha reproduces: no
310
+ # lane checks those out, so a practice of it is a PM's question per author (S3)
311
+ heads = [item.get("sha") for item in b.get("evidence") or []
312
+ if isinstance(item, dict) and item.get("kind") == "commit" and item.get("dirty")]
313
+ if heads:
314
+ rep["dirty_bound_outcomes"].append({**entry, "user": a.get("user"), "head": heads[0]})
278
315
  # a measure, not a tier: every claim whose only verifiers are agents of its own
279
316
  # vendor, whether the ledger's policy lets that reach `verified` or not
280
317
  if info["verified_by"] and not info.get("cross_vendor") and not info.get("self_verified_by_author") \
@@ -287,10 +324,15 @@ def report(ledger, recheck: bool = False, cwd: Optional[str] = None, timeout: Op
287
324
  # byte for byte is not the audit this ledger promises
288
325
  deps = sorted(d for d in ledger.dependents_of(c["id"], through_kinds=("claim",)) if d in by_id)
289
326
  rep["refuted"].append({**entry, "reasons": info["reasons"], "dependents": len(deps)})
290
- if deps:
327
+ # the rule trust applies: a superseded claim taints nothing unless it was retracted as wrong
328
+ if deps and not supersession_mod.taint_skipped(info.get("superseded_by"), ledger.retractions_for(c["id"])):
291
329
  rep["taint_chains"].append({"root": c["id"], "tainted": [{"id": d, "statement": by_id[d]["body"]["statement"][:120]} for d in deps]})
292
330
  if info["tier"] == "stale":
293
331
  rep["stale"].append({**entry, "reasons": info["reasons"]})
332
+ if info.get("superseded_by"):
333
+ rep["superseded"].append({**entry, "superseded_by": info["superseded_by"], "tier": info["tier"]})
334
+ if info["tier"] == "withdrawn":
335
+ rep["withdrawn"].append({**entry, "reasons": info["reasons"]})
294
336
  if info["tier"] == "asserted" and b["type"] == "fact":
295
337
  rep["asserted_facts"].append(entry)
296
338
  for field in _FORMATTED_FIELDS:
@@ -323,6 +365,17 @@ def report(ledger, recheck: bool = False, cwd: Optional[str] = None, timeout: Op
323
365
  claim = by_id.get(v["body"].get("claim"))
324
366
  if claim is None:
325
367
  continue
368
+ if is_assessment(v): # a reading, not a verdict: its own column, never the matrix
369
+ rep["assessments"].append({
370
+ "id": v["id"], "claim": claim["id"], "verdict": v["body"]["verdict"],
371
+ "by": v["author"].get("harness"), "vendor": v["author"].get("vendor"),
372
+ "user": v["author"].get("user"), "ts": v["ts"],
373
+ "lineage": ("another lineage" if lineage_differs(claim["author"], v["author"])
374
+ else "same lineage: never counted"),
375
+ "note": str(v["body"].get("note") or "")[:160], "cited": list(v["body"].get("cited") or []),
376
+ "statement": claim["body"]["statement"][:120],
377
+ })
378
+ continue
326
379
  verdict = v["body"]["verdict"]
327
380
  key = f"{claim['author'].get('vendor')}->{v['author'].get('vendor')}"
328
381
  cell = rep["lineage_matrix"].setdefault(key, {"verified": 0, "refuted": 0, "inconclusive": 0})
@@ -421,8 +474,8 @@ def report(ledger, recheck: bool = False, cwd: Optional[str] = None, timeout: Op
421
474
  if recheck:
422
475
  for c in claims:
423
476
  info = assessment[c["id"]]
424
- if info["tier"] in ("refuted", "tainted"):
425
- continue
477
+ if info["tier"] in ("refuted", "withdrawn", "tainted") or info.get("superseded_by"):
478
+ continue # settled, a stray, or a replaced head: re-running says nothing
426
479
  unmet = set(ev.unmet_expectations(ledger, c))
427
480
  for r in ev.recheck_claim(ledger, c, cwd=cwd, timeout=timeout, path_map=path_map):
428
481
  if r["outcome"] == "skipped":
@@ -433,6 +486,13 @@ def report(ledger, recheck: bool = False, cwd: Optional[str] = None, timeout: Op
433
486
  if r["outcome"] == "match" and r["evidence"] in unmet:
434
487
  entry["note"] = ev.FAILING_RECEIPT_NOTE # reproducing a failure verifies nothing
435
488
  rep["recheck"].append(entry)
489
+ # what the reliability measurements leave out, and why (the PE's ruling, item 4)
490
+ rep["not_measured"] = {"superseded": len(rep["superseded"]), "artefact": len(rep["withdrawn"])}
491
+ # the vision's numbers for a window, recomputable by anyone with the shards
492
+ # (ctr_13190a200fbbd682; docs/BENCHMARK-PLAN.md section 3)
493
+ rep["measurement"] = measure_mod.measurement(
494
+ ledger, since, until, sees=lambda rec: _reader_sees(ledger, rec, by_id, reader_user),
495
+ assessment=assessment)
436
496
  return rep
437
497
 
438
498
 
@@ -486,6 +546,9 @@ def format_report(rep: dict) -> str:
486
546
  lambda r: f"{r['id']} [{r['by']}] {r['statement']} -- receipts: {', '.join(r['receipts'])}")
487
547
  section("Outcome claims backed only by static evidence (static-pass/dynamic-fail risk)",
488
548
  rep["static_only_outcomes"], lambda r: f"{r['id']} [{r['by']}, {r['assurance']}] {r['statement']}")
549
+ section("Outcome claims bound to a dirty tree (their commit is not what ran; no lane re-runs them at it)",
550
+ rep.get("dirty_bound_outcomes", []),
551
+ lambda r: f"{r['id']} [{r['by']}, {r['user']}] at {str(r['head'])[:12]} {r['statement']}")
489
552
  section("Receipts whose assurance was declared above the computed default", rep["assurance_overridden"],
490
553
  lambda r: f"{r['id']} [{r['by']}] declared {r['declared']}, computed {r['computed']}: {r['what']}"
491
554
  + (f" (cited by {', '.join(r['claims'])})" if r["claims"] else " (cited by no claim)"))
@@ -497,11 +560,22 @@ def format_report(rep: dict) -> str:
497
560
  rep.get("same_session_different_harness", []),
498
561
  lambda r: f"{r['id']} [{r['by']} -> {r['verified_by']}, {r['user']} session {r['session']}] "
499
562
  f"{r['statement']}")
563
+ section("Assessments (a reading on request, never a check: they move no tier)", rep.get("assessments", []),
564
+ lambda r: f"{r['id']} on {r['claim']} [{r['verdict']} by {r['by']}, {r['vendor']}, {r['user']}; "
565
+ f"{r['lineage']}] {r['note']}" + (f" (cites {', '.join(r['cited'])})" if r["cited"] else ""))
500
566
  section("Statements shaped like a document (injection risk)", rep.get("formatted_statements", []),
501
567
  lambda r: f"{r['id']} [{r['by']}] {r['field']} starts a line with: {r['line']}")
502
568
  section("Refuted", rep["refuted"], lambda r: f"{r['id']} {r['statement']} -- {'; '.join(r['reasons'])} (dependents: {r['dependents']})")
503
569
  section("Taint chains", rep["taint_chains"], lambda r: f"{r['root']} -> " + ", ".join(t['id'] for t in r['tainted']))
504
570
  section("Stale", rep["stale"], lambda r: f"{r['id']} {r['statement']} -- {'; '.join(r['reasons'])}")
571
+ section("Superseded outcomes (replaced by a later outcome of their contract; they count nowhere and block nothing)",
572
+ rep.get("superseded", []),
573
+ lambda r: f"{r['id']} {r['statement']} -- superseded by {', '.join(r['superseded_by'])} (was {r['tier']})")
574
+ section("Withdrawn as artefacts (stray or test records; they count nowhere and taint nothing)",
575
+ rep.get("withdrawn", []), lambda r: f"{r['id']} {r['statement']} -- {'; '.join(r['reasons'])}")
576
+ section("Retractions filed as wrong that read like an artefact (a PM may file an artefact retraction beside each)",
577
+ rep.get("artefact_candidates", []),
578
+ lambda r: f"{r['claim']} (retraction {r['retraction']}): {r['why']} -- {r['reason']}")
505
579
  section("Facts with no evidence (asserted)", rep["asserted_facts"], lambda r: f"{r['id']} [{r['by']}] {r['statement']}")
506
580
  section("Pinned sections over config.compile_pinned_chars",
507
581
  rep.get("pinned_over_cap", []),
@@ -571,10 +645,17 @@ def format_report(rep: dict) -> str:
571
645
  f"cross-lineage refutation rate: {_rate(rep['cross_lineage_refutation_rate'])}")
572
646
  if "reliability" in rep:
573
647
  lines.append("")
648
+ if rep.get("not_measured"):
649
+ nm = rep["not_measured"]
650
+ lines.append(f"Not measured below: {nm['superseded']} superseded outcome(s) and {nm['artefact']} "
651
+ f"artefact retraction(s); refuted counts verification mismatches and wrong retractions only")
574
652
  lines.append(rel.format_report({"table": rep["reliability"],
575
653
  "same_lineage_agreement": rep["same_lineage_agreement"],
576
654
  "staleness": rep["staleness"],
577
655
  "judgment_calibration": rep["judgment_calibration"]}).rstrip("\n"))
656
+ if rep.get("measurement"): # a replica older than this section sends none
657
+ lines.extend(measure_mod.format_noise(rep["measurement"]))
658
+ lines.extend(measure_mod.format_measurement(rep["measurement"]))
578
659
  if rep["recheck"]:
579
660
  section("Evidence re-check", rep["recheck"],
580
661
  lambda r: f"{r['claim']} {r['evidence']}: {r['outcome']} -- {r['detail']}"