pluribus-context 0.3.40 → 0.3.42

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 (46) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +3 -2
  3. package/bin/pluribus.js +3 -1
  4. package/docs/.nojekyll +0 -0
  5. package/docs/.well-known/agent-skills/context-receipts/SKILL.md +206 -0
  6. package/docs/.well-known/agent-skills/index.json +19 -0
  7. package/docs/.well-known/agent-skills/skill-policy-receipts/SKILL.md +77 -0
  8. package/docs/agent-surface-proof-chain.md +176 -0
  9. package/docs/cursor-claude-context-handoff.md +68 -0
  10. package/docs/index.html +38 -0
  11. package/docs/receipt-playground.html +304 -0
  12. package/docs/session-preflight-receipts.md +77 -0
  13. package/examples/claude-md-read-receipts/README.md +70 -0
  14. package/examples/claude-md-read-receipts/check-read-receipt.mjs +119 -0
  15. package/examples/claude-md-read-receipts/sample-read-receipt.json +45 -0
  16. package/examples/claude-md-read-receipts/stale-read-receipt.json +18 -0
  17. package/examples/context-attention-receipts/README.md +41 -0
  18. package/examples/context-attention-receipts/attention-receipt-fail.json +49 -0
  19. package/examples/context-attention-receipts/attention-receipt-pass.json +53 -0
  20. package/examples/context-attention-receipts/check-attention-receipt.mjs +97 -0
  21. package/examples/context-sufficiency-trace/README.md +22 -0
  22. package/examples/context-sufficiency-trace/check-context-sufficiency.mjs +40 -0
  23. package/examples/context-sufficiency-trace/context-trace-pass.json +28 -0
  24. package/examples/context-sufficiency-trace/context-trace.json +47 -0
  25. package/examples/context-sufficiency-trace/ground-truth.json +13 -0
  26. package/examples/provider-degradation-canaries/README.md +79 -0
  27. package/examples/provider-degradation-canaries/check-degradation-receipt.mjs +64 -0
  28. package/examples/provider-degradation-canaries/healthy-decision.json +27 -0
  29. package/examples/provider-degradation-canaries/unsafe-write-decision.json +26 -0
  30. package/examples/semantic-anchor-receipts/README.md +49 -0
  31. package/examples/semantic-anchor-receipts/check-semantic-anchors.mjs +153 -0
  32. package/examples/semantic-anchor-receipts/cleaned-paste.md +17 -0
  33. package/examples/semantic-anchor-receipts/original-paste.md +19 -0
  34. package/examples/semantic-anchor-receipts/sample-receipt.json +62 -0
  35. package/examples/session-preflight-receipts/README.md +25 -0
  36. package/examples/session-preflight-receipts/session-preflight-receipt.json +39 -0
  37. package/examples/session-preflight-receipts/session-preflight.mdc +18 -0
  38. package/examples/task-scoped-mcp-config/README.md +60 -0
  39. package/examples/task-scoped-mcp-config/mcp-catalog.json +46 -0
  40. package/examples/task-scoped-mcp-config/select-mcp-config.mjs +64 -0
  41. package/examples/task-scoped-mcp-config/tasks/browser-debug.json +7 -0
  42. package/package.json +5 -2
  43. package/skills/context-receipts/README.md +13 -2
  44. package/skills/context-receipts/SKILL.md +65 -0
  45. package/src/commands/demo.js +81 -1
  46. package/src/utils/version.js +1 -1
@@ -90,6 +90,74 @@ I am building Acme Billing, a TypeScript service used by finance operators.
90
90
  4. **Audit:** run `pluribus audit` locally or in CI to catch drift when someone edits generated files directly.
91
91
  5. **Use memory separately:** if you also run an MCP memory server, keep the recall/store protocol in `pluribus.md` and let the memory server store durable facts.
92
92
 
93
+ ## What usually breaks first
94
+
95
+ When developers switch seriously between Cursor, Claude Code, Codex/Copilot-style tools, Windsurf, and terminal agents, the failure is rarely “there is no context anywhere.” It is usually one of these smaller breaks:
96
+
97
+ | Break | Symptom | Fast check |
98
+ | --- | --- | --- |
99
+ | Source file stale | `AGENTS.md`, `CLAUDE.md`, or `.cursorrules` still describes old paths, commands, or architecture | Run `pluribus audit`; compare generated output to the committed `pluribus.md` source |
100
+ | Tool-specific layer diverged | Cursor rules say one convention, Claude/Codex instructions say another | Keep tool-specific files generated/thin; review manual edits as drift |
101
+ | Memory became authority | An MCP memory/Obsidian/Notion note overrides the current repo state | Put memory recall/store policy in `pluribus.md`; require code/tests/current docs to win over recalled facts |
102
+ | Commands or paths changed | The agent follows a dead build/test command copied from an older chat | Keep commands in `package.json`, `Makefile`, `justfile`, or scripts; link to them from context instead of duplicating shell snippets |
103
+ | Context was never loaded | The right file exists, but the active tool/session did not read it | Ask for a short handoff receipt before edits: which source file, generated target, memory recall, and test command were actually used |
104
+
105
+ ## Copyable handoff receipt
106
+
107
+ Use this as a lightweight debugging note before a risky cross-tool handoff. It is intentionally privacy-safe: hashes, paths, and decisions instead of raw prompt transcripts or private source content.
108
+
109
+ ```json
110
+ {
111
+ "handoff_id": "cursor-to-claude-2026-06-16-001",
112
+ "from_tool": "cursor",
113
+ "to_tool": "claude-code",
114
+ "repo_ref": {
115
+ "branch": "main",
116
+ "head_sha": "abc1234"
117
+ },
118
+ "source_of_truth": {
119
+ "path": "pluribus.md",
120
+ "sha256": "hash-of-current-project-context",
121
+ "validated_at": "2026-06-16T00:00:00Z"
122
+ },
123
+ "generated_context": [
124
+ {
125
+ "tool": "cursor",
126
+ "path": ".cursorrules",
127
+ "status": "in_sync"
128
+ },
129
+ {
130
+ "tool": "claude-code",
131
+ "path": "CLAUDE.md",
132
+ "status": "in_sync"
133
+ },
134
+ {
135
+ "tool": "openclaw-or-codex-style-agent",
136
+ "path": "AGENTS.md",
137
+ "status": "in_sync"
138
+ }
139
+ ],
140
+ "memory_policy": {
141
+ "mcp_memory_allowed": true,
142
+ "current_repo_overrides_memory": true,
143
+ "store_new_facts_without_review": false
144
+ },
145
+ "active_task": {
146
+ "summary": "Implement the smallest safe patch for issue #123",
147
+ "allowed_paths": ["src/billing/**", "tests/billing/**"],
148
+ "required_checks": ["npm test -- billing"]
149
+ },
150
+ "loaded_evidence": {
151
+ "agent_says_it_read": ["CLAUDE.md", "package.json"],
152
+ "missing_or_deferred": ["old Obsidian architecture note"],
153
+ "stale_conflicts_found": []
154
+ },
155
+ "safe_to_continue": true
156
+ }
157
+ ```
158
+
159
+ The receipt should be boring. If it shows stale conflicts, missing generated files, or memory overriding current repo state, stop and fix the source of truth before asking another agent to write code.
160
+
93
161
  ## What this deliberately does not solve
94
162
 
95
163
  - It does not move active chat state from Cursor to Claude Code.
@@ -0,0 +1,38 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Pluribus Context Receipts</title>
7
+ <style>
8
+ :root { color-scheme: dark light; --bg:#0b1020; --card:#121a33; --text:#e8ecf8; --muted:#aab4cf; --accent:#8ee6c4; --border:#283454; }
9
+ body { margin:0; font:16px/1.55 system-ui,-apple-system,Segoe UI,sans-serif; background:var(--bg); color:var(--text); }
10
+ main { max-width:880px; margin:0 auto; padding:56px 20px; }
11
+ a { color:var(--accent); }
12
+ .card { background:var(--card); border:1px solid var(--border); border-radius:18px; padding:24px; margin:20px 0; }
13
+ code { background:#060a15; padding:.15rem .35rem; border-radius:6px; }
14
+ </style>
15
+ </head>
16
+ <body>
17
+ <main>
18
+ <h1>Pluribus Context Receipts</h1>
19
+ <p>Privacy-safe evidence for AI context boundaries: what crossed into the agent, what stayed out, and what should stop before edits or tool calls.</p>
20
+ <div class="card">
21
+ <h2>Browser playground</h2>
22
+ <p>Try receipt validation without installing anything or sending data to a server. Current samples cover MCP tool-surface diffs, retrieved-context attention, CLAUDE.md rule-attention drift, skill install provenance, and retrieval adoption evidence. If you are debugging MCP context bloat before startup, use the <a href="https://github.com/caioribeiroclw-pixel/pluribus/tree/main/examples/task-scoped-mcp-config">task-scoped MCP config receipt demo</a>. If a Skill or paste-cleaning CLI claims token savings, use the <a href="https://github.com/caioribeiroclw-pixel/pluribus/tree/main/examples/semantic-anchor-receipts">semantic anchor preservation receipt demo</a> to prove it kept version/API/security anchors. If a Cursor/Claude Code workflow requires a first tool or pre-tool hook before edits, use the <a href="session-preflight-receipts.md">session preflight receipt</a> and <a href="https://github.com/caioribeiroclw-pixel/pluribus/tree/main/examples/session-preflight-receipts">copyable rule/example</a>.</p>
23
+ <p><a href="receipt-playground.html">Open the receipt playground →</a></p>
24
+ </div>
25
+ <div class="card">
26
+ <h2>CLI quick checks</h2>
27
+ <p><code>npx --yes pluribus-context@latest demo tool-surface-diff --json</code></p>
28
+ <p><code>npx --yes pluribus-context@latest validate</code></p>
29
+ </div>
30
+ <div class="card">
31
+ <h2>Agent Skills discovery</h2>
32
+ <p>Pluribus publishes a well-known Agent Skills index so compatible clients can discover the low-authority <code>context-receipts</code> and <code>skill-policy-receipts</code> skills without scraping GitHub.</p>
33
+ <p><a href=".well-known/agent-skills/index.json">Open <code>/.well-known/agent-skills/index.json</code> →</a></p>
34
+ </div>
35
+ <p><a href="https://github.com/caioribeiroclw-pixel/pluribus">GitHub repo</a> · <a href="https://www.npmjs.com/package/pluribus-context">npm package</a></p>
36
+ </main>
37
+ </body>
38
+ </html>
@@ -0,0 +1,304 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Pluribus Receipt Playground</title>
7
+ <style>
8
+ :root { color-scheme: dark light; --bg:#0b1020; --card:#121a33; --text:#e8ecf8; --muted:#aab4cf; --accent:#8ee6c4; --bad:#ff8f9c; --warn:#ffd166; --ok:#8ee6c4; --border:#283454; }
9
+ * { box-sizing:border-box; }
10
+ body { margin:0; font:15px/1.5 system-ui,-apple-system,Segoe UI,sans-serif; background:linear-gradient(180deg,#0b1020,#10182e); color:var(--text); }
11
+ main { max-width:1120px; margin:0 auto; padding:34px 18px 48px; }
12
+ h1 { font-size:clamp(2rem,4vw,3.4rem); line-height:1.05; margin:.2rem 0 1rem; letter-spacing:-.04em; }
13
+ h2 { margin-top:0; }
14
+ p, li { color:var(--muted); }
15
+ a { color:var(--accent); }
16
+ .grid { display:grid; grid-template-columns:1fr; gap:16px; }
17
+ @media (min-width:900px) { .grid { grid-template-columns:1.1fr .9fr; } }
18
+ .card { background:rgba(18,26,51,.92); border:1px solid var(--border); border-radius:18px; padding:18px; box-shadow:0 20px 80px rgba(0,0,0,.24); }
19
+ textarea { width:100%; min-height:560px; resize:vertical; border:1px solid var(--border); border-radius:14px; padding:14px; background:#060a15; color:#e8ecf8; font:13px/1.45 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; }
20
+ button, select { border:1px solid var(--border); border-radius:999px; background:#182344; color:var(--text); padding:10px 14px; cursor:pointer; }
21
+ button:hover, select:hover { border-color:var(--accent); }
22
+ .controls { display:flex; flex-wrap:wrap; gap:10px; align-items:center; margin:0 0 12px; }
23
+ .result { white-space:pre-wrap; overflow:auto; border-radius:14px; padding:14px; background:#060a15; border:1px solid var(--border); min-height:210px; font:13px/1.45 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; }
24
+ .ok { color:var(--ok); }
25
+ .bad { color:var(--bad); }
26
+ .warn { color:var(--warn); }
27
+ .pill { display:inline-block; border:1px solid var(--border); border-radius:999px; padding:.2rem .55rem; color:var(--muted); margin:.1rem .2rem .1rem 0; }
28
+ code { background:#060a15; padding:.12rem .32rem; border-radius:6px; color:#d7e2ff; }
29
+ </style>
30
+ </head>
31
+ <body>
32
+ <main>
33
+ <p><a href="index.html">← Pluribus</a></p>
34
+ <h1>Receipt playground</h1>
35
+ <p>Paste a Pluribus receipt and validate the boundary evidence locally in your browser. No network calls, no raw prompts/results required.</p>
36
+ <div class="grid">
37
+ <section class="card">
38
+ <div class="controls">
39
+ <select id="sample">
40
+ <option value="toolSurface">Sample: MCP tool-surface diff</option>
41
+ <option value="attentionPass">Sample: context attention pass</option>
42
+ <option value="attentionFail">Sample: context attention fail</option>
43
+ <option value="ruleAttention">Sample: CLAUDE.md rule attention drift</option>
44
+ <option value="skillInstall">Sample: Agent Skill install provenance</option>
45
+ <option value="retrievalAdoption">Sample: retrieval adoption receipt</option>
46
+ </select>
47
+ <button id="load">Load sample</button>
48
+ <button id="validate">Validate</button>
49
+ </div>
50
+ <textarea id="receipt" spellcheck="false"></textarea>
51
+ </section>
52
+ <aside class="card">
53
+ <h2>Validation result</h2>
54
+ <div id="result" class="result">Click Validate.</div>
55
+ <h2>What this checks</h2>
56
+ <p><span class="pill">tool-surface diff</span> proves runtime discovery changes without logging raw schemas/prompts/results.</p>
57
+ <p><span class="pill">context attention</span> proves required retrieved context was delivered, acknowledged, and cited before edits.</p>
58
+ <p><span class="pill">rule attention</span> shows whether project rules were re-read, cited in the pre-edit plan, and checked before changes.</p>
59
+ <p><span class="pill">skill install provenance</span> shows which <code>SKILL.md</code> source path won, which mirrors were ignored, and whether install metadata stayed content-safe.</p>
60
+ <p><span class="pill">retrieval adoption</span> shows whether an available graph/RAG tool was actually used before claims, not just configured.</p>
61
+ <h2>CLI equivalent</h2>
62
+ <p><code>npx --yes pluribus-context@latest demo tool-surface-diff --json</code></p>
63
+ </aside>
64
+ </div>
65
+ </main>
66
+ <script>
67
+ const samples = {
68
+ toolSurface: {
69
+ schema: 'pluribus.mcp_tool_surface_diff_receipt.v1',
70
+ run_id: 'tool-surface-diff-demo',
71
+ generated_at: '2026-06-09T13:00:00Z',
72
+ platform: { name: 'enterprise-mcp-dynamic-discovery', audit_sink: 'admin-center-or-siem' },
73
+ catalog: { server_id: 'mcp://sales-ops-gateway', previous_hash: 'sha256:previous-catalog-redacted', current_hash: 'sha256:current-catalog-redacted' },
74
+ runtime_discovery: { enabled: true, trigger: 'runtime_tool_catalog_diff' },
75
+ privacy_boundary: { raw_schemas: 'omitted_hash_only', raw_prompts: 'omitted', raw_results: 'omitted' },
76
+ tools: [
77
+ { tool_id: 'tool:crm.search_accounts', name_hash: 'sha256:0cc2...', schema_hash: 'sha256:6f4f...', status: 'activated', validation_outcome: 'accepted', diff_summary: { added_fields: 1, removed_fields: 0, changed_fields: 0 } },
78
+ { tool_id: 'tool:crm.export_contacts', name_hash: 'sha256:f38f...', schema_hash: 'sha256:95dd...', status: 'blocked', validation_outcome: 'blocked_by_rai', diff_summary: { added_fields: 4, removed_fields: 0, changed_fields: 2 } },
79
+ { tool_id: 'tool:billing.refund_invoice', name_hash: 'sha256:abfd...', schema_hash: 'sha256:3b4f...', status: 'withheld', validation_outcome: 'entitlement_filtered', diff_summary: { added_fields: 0, removed_fields: 0, changed_fields: 0 } }
80
+ ]
81
+ },
82
+ attentionPass: {
83
+ schema: 'pluribus.context_attention_receipt.v1', receipt_id: 'attn_demo_pass', task_id: 'claude-code-refactor-184', agent_surface: 'claude_code', retrieval_system: 'graph_memory_mcp',
84
+ required_context: [{ id: 'ctx:architecture:tenant-routing' }, { id: 'ctx:decision:readonly-audit-first' }],
85
+ delivery: { surface: 'mcp_tool_response', delivered_context_ids: ['ctx:architecture:tenant-routing', 'ctx:decision:readonly-audit-first'], raw_context_omitted: true, evidence_path: '.pluribus/receipts/context-attention.ndjson' },
86
+ attention: { acknowledged_before_plan: ['ctx:architecture:tenant-routing', 'ctx:decision:readonly-audit-first'], cited_in_plan: ['ctx:architecture:tenant-routing', 'ctx:decision:readonly-audit-first'], missing_context_stop: false },
87
+ privacy: { raw_prompts_omitted: true, raw_documents_omitted: true, source_code_omitted: true, tool_outputs_omitted: true, tokens_omitted: true, customer_data_omitted: true },
88
+ result: { status: 'safe_to_continue', next_safe_action: 'continue with dry-run refactor plan' }
89
+ },
90
+ attentionFail: {
91
+ schema: 'pluribus.context_attention_receipt.v1', receipt_id: 'attn_demo_fail', task_id: 'claude-code-refactor-185', agent_surface: 'claude_code', retrieval_system: 'graph_memory_mcp',
92
+ required_context: [{ id: 'ctx:architecture:tenant-routing' }, { id: 'ctx:decision:readonly-audit-first' }],
93
+ delivery: { surface: 'mcp_tool_response', delivered_context_ids: ['ctx:architecture:tenant-routing', 'ctx:decision:readonly-audit-first'], raw_context_omitted: true, evidence_path: '.pluribus/receipts/context-attention.ndjson' },
94
+ attention: { acknowledged_before_plan: ['ctx:architecture:tenant-routing'], cited_in_plan: [], missing_context_stop: false },
95
+ privacy: { raw_prompts_omitted: true, raw_documents_omitted: true, source_code_omitted: true, tool_outputs_omitted: true, tokens_omitted: true, customer_data_omitted: true },
96
+ result: { status: 'unsafe_to_continue', next_safe_action: 'stop and re-deliver required context before editing' }
97
+ },
98
+ ruleAttention: {
99
+ schema: 'pluribus.claude_code_rule_attention_receipt.v1',
100
+ receipt_id: 'rule_attn_demo_62087',
101
+ task_id: 'claude-code-long-session-62087',
102
+ agent_surface: 'claude_code',
103
+ context_boundary: { session_phase: 'post-compaction-long-session', before_first_edit: true },
104
+ rules: [
105
+ { rule_id: 'CLAUDE.md:test-after-plan', source: 'CLAUDE.md#workflow', last_loaded_at: '2026-06-09T22:41:00Z', last_referenced_at: null, cited_in_pre_edit_plan: false, edit_check: 'missing', violation_category: 'loaded_but_not_referenced' },
106
+ { rule_id: 'CLAUDE.md:no-skip-steps', source: 'CLAUDE.md#workflow', last_loaded_at: '2026-06-09T22:41:00Z', last_referenced_at: '2026-06-09T22:58:00Z', cited_in_pre_edit_plan: true, edit_check: 'pass', violation_category: null }
107
+ ],
108
+ privacy: { raw_prompts_omitted: true, raw_claude_md_omitted: true, source_code_omitted: true, tool_outputs_omitted: true, tokens_omitted: true, customer_data_omitted: true },
109
+ result: { status: 'unsafe_to_edit', next_safe_action: 'stop, re-read missing rule ids, and restate the pre-edit plan with citations' }
110
+ },
111
+ retrievalAdoption: {
112
+ schema: 'pluribus.retrieval_adoption_receipt.v1',
113
+ receipt_id: 'retrieval_adoption_graph_demo',
114
+ task_id: 'medusa-code-audit-graph-usage',
115
+ agent_surface: 'claude_code',
116
+ retrieval_surface: { kind: 'knowledge_graph_mcp', name: 'project-graph', available: true, forced: false },
117
+ claim: { expected_use: 'graph_retrieval_before_code_audit', evaluation_window: 'before_final_audit_claims' },
118
+ availability_evidence: {
119
+ tool_catalog_contains: ['graph.search', 'graph.neighbors', 'graph.explain_path'],
120
+ graph_index: { nodes: 3863, edges: 11204, snapshot_hash: 'sha256:graph-snapshot-redacted' },
121
+ raw_graph_omitted: true
122
+ },
123
+ adoption_evidence: {
124
+ retrieval_calls: [],
125
+ native_escape_hatch_calls: [
126
+ { kind: 'grep', count: 14 },
127
+ { kind: 'read_file', count: 39 }
128
+ ],
129
+ cited_retrieved_context_ids: [],
130
+ graph_grounded_findings: 0,
131
+ raw_tool_outputs_omitted: true
132
+ },
133
+ boundary_checks: {
134
+ retrieval_available_but_unused: true,
135
+ required_retrieval_gate_present: false,
136
+ no_retrieval_claim_allowed: true
137
+ },
138
+ privacy: { raw_prompts_omitted: true, raw_graph_nodes_omitted: true, source_code_omitted: true, tool_outputs_omitted: true, customer_data_omitted: true },
139
+ result: { status: 'availability_not_adoption', next_safe_action: 'treat graph/RAG as unadopted unless a gate requires or verifies retrieval before final claims' }
140
+ },
141
+ skillInstall: {
142
+ schema: 'pluribus.agent_skill_install_provenance_receipt.v1',
143
+ receipt_id: 'skill_install_openskills_demo',
144
+ installer: { name: 'agent-skill-package-manager', mode: 'universal', target_agent_dir: '.agent/skills' },
145
+ source: { kind: 'github_repo', repo: 'caioribeiroclw-pixel/pluribus', requested_ref: 'v0.3.40', resolved_sha: 'sha256:resolved-commit-redacted' },
146
+ discovery: {
147
+ requested_skill_names: ['context-receipts', 'skill-policy-receipts'],
148
+ discovered_source_paths: [
149
+ 'skills/context-receipts/SKILL.md',
150
+ 'examples/agent-skills/context-receipts/SKILL.md',
151
+ 'docs/.well-known/agent-skills/context-receipts/SKILL.md',
152
+ 'skills/skill-policy-receipts/SKILL.md',
153
+ 'examples/agent-skills/skill-policy-receipts/SKILL.md',
154
+ 'docs/.well-known/agent-skills/skill-policy-receipts/SKILL.md'
155
+ ],
156
+ duplicate_resolution: 'prefer_top_level_skills_dir'
157
+ },
158
+ selected_skills: [
159
+ { name: 'context-receipts', selected_source_path: 'skills/context-receipts/SKILL.md', target_path: '.agent/skills/context-receipts/SKILL.md', operation: 'install', lockfile_entry_written: true },
160
+ { name: 'skill-policy-receipts', selected_source_path: 'skills/skill-policy-receipts/SKILL.md', target_path: '.agent/skills/skill-policy-receipts/SKILL.md', operation: 'install', lockfile_entry_written: true }
161
+ ],
162
+ ignored_duplicates: [
163
+ { name: 'context-receipts', ignored_source_path: 'examples/agent-skills/context-receipts/SKILL.md', reason: 'duplicate_mirror_not_canonical' },
164
+ { name: 'context-receipts', ignored_source_path: 'docs/.well-known/agent-skills/context-receipts/SKILL.md', reason: 'duplicate_mirror_not_canonical' },
165
+ { name: 'skill-policy-receipts', ignored_source_path: 'examples/agent-skills/skill-policy-receipts/SKILL.md', reason: 'duplicate_mirror_not_canonical' },
166
+ { name: 'skill-policy-receipts', ignored_source_path: 'docs/.well-known/agent-skills/skill-policy-receipts/SKILL.md', reason: 'duplicate_mirror_not_canonical' }
167
+ ],
168
+ safety: { content_sanitizers: ['frontmatter-parse', 'markdown-only'], raw_secret_or_env_values_copied: false, scripts_or_hooks_installed: false, network_capability_added: false, manual_review_required: true },
169
+ privacy: { raw_skill_body_omitted: true, raw_env_values_omitted: true, auth_headers_omitted: true, customer_data_omitted: true },
170
+ result: { status: 'safe_to_install_after_review', installed_count: 2, ignored_duplicate_count: 4 }
171
+ }
172
+ }
173
+
174
+ const receiptEl = document.querySelector('#receipt')
175
+ const resultEl = document.querySelector('#result')
176
+ document.querySelector('#load').addEventListener('click', loadSample)
177
+ document.querySelector('#validate').addEventListener('click', validate)
178
+ document.querySelector('#sample').addEventListener('change', loadSample)
179
+ loadSample()
180
+
181
+ function loadSample() {
182
+ const key = document.querySelector('#sample').value
183
+ receiptEl.value = JSON.stringify(samples[key], null, 2)
184
+ validate()
185
+ }
186
+
187
+ function validate() {
188
+ let receipt
189
+ try { receipt = JSON.parse(receiptEl.value) }
190
+ catch (error) { return render({ ok:false, errors:[`invalid JSON: ${error.message}`], warnings:[] }) }
191
+ if (receipt.schema === 'pluribus.mcp_tool_surface_diff_receipt.v1') return render(validateToolSurface(receipt))
192
+ if (receipt.schema === 'pluribus.context_attention_receipt.v1') return render(validateAttention(receipt))
193
+ if (receipt.schema === 'pluribus.claude_code_rule_attention_receipt.v1') return render(validateRuleAttention(receipt))
194
+ if (receipt.schema === 'pluribus.agent_skill_install_provenance_receipt.v1') return render(validateSkillInstall(receipt))
195
+ if (receipt.schema === 'pluribus.retrieval_adoption_receipt.v1') return render(validateRetrievalAdoption(receipt))
196
+ render({ ok:false, errors:[`unsupported schema: ${receipt.schema || '(missing)'}`], warnings:[] })
197
+ }
198
+
199
+ function validateToolSurface(r) {
200
+ const errors = [], warnings = []
201
+ const privacy = r.privacy_boundary || {}
202
+ if (!r.catalog?.current_hash) errors.push('catalog.current_hash is required')
203
+ if (!Array.isArray(r.tools) || r.tools.length === 0) errors.push('tools must include at least one discovered/activated/withheld/blocked tool')
204
+ for (const field of ['raw_schemas','raw_prompts','raw_results']) if (!String(privacy[field] || '').startsWith('omitted')) errors.push(`privacy_boundary.${field} must be omitted`)
205
+ const counts = countBy(r.tools || [], 'status')
206
+ if (!counts.activated && !counts.withheld && !counts.blocked) warnings.push('receipt has no activated/withheld/blocked status counts')
207
+ return { ok: errors.length === 0, schema:r.schema, summary:counts, errors, warnings }
208
+ }
209
+
210
+ function validateAttention(r) {
211
+ const errors = [], warnings = []
212
+ const required = ids((r.required_context || []).map(x => x.id))
213
+ const delivered = ids(r.delivery?.delivered_context_ids)
214
+ const ack = ids(r.attention?.acknowledged_before_plan)
215
+ const cited = ids(r.attention?.cited_in_plan)
216
+ if (!required.length) errors.push('required_context must name at least one id')
217
+ for (const id of required) {
218
+ if (!delivered.includes(id)) errors.push(`required context not delivered: ${id}`)
219
+ if (!ack.includes(id)) errors.push(`required context not acknowledged before plan: ${id}`)
220
+ if (!cited.includes(id)) errors.push(`required context not cited in plan: ${id}`)
221
+ }
222
+ if (r.delivery?.raw_context_omitted !== true) errors.push('delivery.raw_context_omitted must be true')
223
+ for (const field of ['raw_prompts_omitted','raw_documents_omitted','source_code_omitted','tool_outputs_omitted','tokens_omitted','customer_data_omitted']) if (r.privacy?.[field] !== true) errors.push(`privacy.${field} must be true`)
224
+ if (errors.length && r.attention?.missing_context_stop !== true) errors.push('missing_context_stop must be true when required attention evidence is incomplete')
225
+ if (!r.delivery?.evidence_path) warnings.push('delivery.evidence_path is missing')
226
+ return { ok: errors.length === 0, schema:r.schema, required_count:required.length, delivered_count:delivered.length, acknowledged_count:ack.length, cited_count:cited.length, errors, warnings }
227
+ }
228
+
229
+ function validateRuleAttention(r) {
230
+ const errors = [], warnings = []
231
+ const rules = Array.isArray(r.rules) ? r.rules : []
232
+ if (!rules.length) errors.push('rules must include at least one project rule')
233
+ for (const rule of rules) {
234
+ if (!rule.rule_id) errors.push('each rule must include rule_id')
235
+ if (!rule.source) errors.push(`${rule.rule_id || 'rule'} must include source`)
236
+ if (!rule.last_loaded_at) errors.push(`${rule.rule_id || 'rule'} must include last_loaded_at`)
237
+ if (rule.cited_in_pre_edit_plan !== true) warnings.push(`${rule.rule_id || 'rule'} was not cited in the pre-edit plan`)
238
+ if (!['pass','fail','missing'].includes(rule.edit_check)) errors.push(`${rule.rule_id || 'rule'} edit_check must be pass, fail, or missing`)
239
+ }
240
+ for (const field of ['raw_prompts_omitted','raw_claude_md_omitted','source_code_omitted','tool_outputs_omitted','tokens_omitted','customer_data_omitted']) if (r.privacy?.[field] !== true) errors.push(`privacy.${field} must be true`)
241
+ const missing = rules.filter(rule => rule.cited_in_pre_edit_plan !== true || rule.edit_check !== 'pass')
242
+ if (missing.length && r.result?.status === 'safe_to_edit') errors.push('result.status cannot be safe_to_edit while a required rule is uncited or failing')
243
+ return { ok: errors.length === 0 && missing.length === 0, schema:r.schema, rules_count:rules.length, uncited_or_failing_rules:missing.map(rule => rule.rule_id), errors, warnings }
244
+ }
245
+
246
+
247
+ function validateRetrievalAdoption(r) {
248
+ const errors = [], warnings = []
249
+ const catalogTools = Array.isArray(r.availability_evidence?.tool_catalog_contains) ? r.availability_evidence.tool_catalog_contains : []
250
+ const retrievalCalls = Array.isArray(r.adoption_evidence?.retrieval_calls) ? r.adoption_evidence.retrieval_calls : []
251
+ const escapeCalls = Array.isArray(r.adoption_evidence?.native_escape_hatch_calls) ? r.adoption_evidence.native_escape_hatch_calls : []
252
+ const cited = Array.isArray(r.adoption_evidence?.cited_retrieved_context_ids) ? r.adoption_evidence.cited_retrieved_context_ids : []
253
+ if (!r.retrieval_surface?.kind) errors.push('retrieval_surface.kind is required')
254
+ if (r.retrieval_surface?.available !== true) errors.push('retrieval_surface.available must be true before adoption can be measured')
255
+ if (!catalogTools.length) errors.push('availability_evidence.tool_catalog_contains must list at least one retrieval tool')
256
+ if (r.availability_evidence?.raw_graph_omitted !== true) errors.push('availability_evidence.raw_graph_omitted must be true')
257
+ if (r.adoption_evidence?.raw_tool_outputs_omitted !== true) errors.push('adoption_evidence.raw_tool_outputs_omitted must be true')
258
+ for (const field of ['raw_prompts_omitted','raw_graph_nodes_omitted','source_code_omitted','tool_outputs_omitted','customer_data_omitted']) if (r.privacy?.[field] !== true) errors.push(`privacy.${field} must be true`)
259
+ const graphGroundedFindings = Number(r.adoption_evidence?.graph_grounded_findings || 0)
260
+ const usedRetrieval = retrievalCalls.length > 0 || cited.length > 0 || graphGroundedFindings > 0
261
+ if (r.boundary_checks?.retrieval_available_but_unused === true && usedRetrieval) errors.push('retrieval_available_but_unused cannot be true when retrieval calls/citations/findings exist')
262
+ if (!usedRetrieval && r.boundary_checks?.no_retrieval_claim_allowed !== true) errors.push('no_retrieval_claim_allowed must be true when retrieval was available but no adoption evidence exists')
263
+ if (!usedRetrieval && !escapeCalls.length) warnings.push('no retrieval adoption and no native escape-hatch calls recorded; receipt may be missing usage telemetry')
264
+ return { ok: errors.length === 0, schema:r.schema, retrieval_available:r.retrieval_surface?.available === true, retrieval_call_count:retrievalCalls.length, cited_context_count:cited.length, graph_grounded_findings:graphGroundedFindings, native_escape_hatch_calls:escapeCalls, status: usedRetrieval ? 'retrieval_adopted' : 'availability_not_adoption', errors, warnings }
265
+ }
266
+
267
+ function validateSkillInstall(r) {
268
+ const errors = [], warnings = []
269
+ const selected = Array.isArray(r.selected_skills) ? r.selected_skills : []
270
+ const ignored = Array.isArray(r.ignored_duplicates) ? r.ignored_duplicates : []
271
+ const discovered = Array.isArray(r.discovery?.discovered_source_paths) ? r.discovery.discovered_source_paths : []
272
+ if (!r.source?.repo) errors.push('source.repo is required')
273
+ if (!r.source?.resolved_sha) errors.push('source.resolved_sha is required')
274
+ if (!r.installer?.target_agent_dir) errors.push('installer.target_agent_dir is required')
275
+ if (!selected.length) errors.push('selected_skills must include at least one installed skill')
276
+ for (const skill of selected) {
277
+ if (!skill.name) errors.push('each selected skill must include name')
278
+ if (!skill.selected_source_path) errors.push(`${skill.name || 'skill'} must include selected_source_path`)
279
+ if (!skill.target_path) errors.push(`${skill.name || 'skill'} must include target_path`)
280
+ if (skill.lockfile_entry_written !== true) warnings.push(`${skill.name || 'skill'} did not write lockfile metadata`)
281
+ }
282
+ const selectedNames = selected.map(skill => skill.name).filter(Boolean)
283
+ for (const name of selectedNames) {
284
+ const discoveredForName = discovered.filter(path => path.includes(`/${name}/`) || path.includes(`${name}/SKILL.md`)).length
285
+ const ignoredForName = ignored.filter(item => item.name === name).length
286
+ if (discoveredForName > 1 && ignoredForName === 0) errors.push(`${name} has multiple discovered paths but no ignored_duplicates evidence`)
287
+ }
288
+ if (r.safety?.raw_secret_or_env_values_copied !== false) errors.push('safety.raw_secret_or_env_values_copied must be false')
289
+ if (r.safety?.scripts_or_hooks_installed !== false) errors.push('safety.scripts_or_hooks_installed must be false for a low-authority skill receipt')
290
+ if (r.safety?.network_capability_added !== false) errors.push('safety.network_capability_added must be false for a skill-only install')
291
+ for (const field of ['raw_skill_body_omitted','raw_env_values_omitted','auth_headers_omitted','customer_data_omitted']) if (r.privacy?.[field] !== true) errors.push(`privacy.${field} must be true`)
292
+ if (selected.length !== new Set(selectedNames).size) errors.push('selected_skills contains duplicate names after resolution')
293
+ return { ok: errors.length === 0, schema:r.schema, selected_count:selected.length, ignored_duplicate_count:ignored.length, discovered_source_count:discovered.length, selected_source_paths:selected.map(skill => skill.selected_source_path), errors, warnings }
294
+ }
295
+
296
+ function countBy(items, key) { return items.reduce((acc, item) => (acc[item[key] || 'unknown'] = (acc[item[key] || 'unknown'] || 0) + 1, acc), {}) }
297
+ function ids(v) { return Array.isArray(v) ? v.filter(x => typeof x === 'string' && x) : [] }
298
+ function render(obj) {
299
+ resultEl.className = 'result ' + (obj.ok ? 'ok' : 'bad')
300
+ resultEl.textContent = JSON.stringify(obj, null, 2)
301
+ }
302
+ </script>
303
+ </body>
304
+ </html>
@@ -0,0 +1,77 @@
1
+ # Session preflight receipts
2
+
3
+ Cursor Forum users are asking for a "required first tool" or pre-tool hook so an agent cannot skip required project context before Grep, Shell, Write, or MCP calls. A behavioral rule is not enough: the first useful question is whether the session actually initialized its context before work began.
4
+
5
+ A **session preflight receipt** is a small, privacy-safe record produced before any side-effecting agent work. It does not log raw memory, prompts, secrets, or file contents. It records which required context sources were checked, which tool surfaces were available, and whether the agent is allowed to proceed.
6
+
7
+ Use this when rules like "read `MEMORY.md` first" or "call `session_init` before work" are important enough to audit.
8
+
9
+ ## Minimal receipt
10
+
11
+ ```json
12
+ {
13
+ "schema": "pluribus.session_preflight_receipt.v1",
14
+ "session_id": "local-2026-06-17T11:00Z",
15
+ "client": "cursor",
16
+ "required_first_step": {
17
+ "kind": "mcp_tool",
18
+ "name": "session_guard.session_init",
19
+ "enforcement": "behavioral_rule_only"
20
+ },
21
+ "required_context": [
22
+ {
23
+ "id": "project-memory",
24
+ "path": "MEMORY.md",
25
+ "status": "loaded",
26
+ "fingerprint": "sha256:example-non-secret-digest"
27
+ }
28
+ ],
29
+ "tool_surface": {
30
+ "mcp_servers_seen": ["session-guard", "playwright"],
31
+ "side_effecting_tools_blocked_until_preflight": ["Shell", "Write"]
32
+ },
33
+ "decision": {
34
+ "allowed_to_start_work": true,
35
+ "mode": "read_then_patch",
36
+ "reason": "required context was checked before tool use"
37
+ }
38
+ }
39
+ ```
40
+
41
+ ## What this proves
42
+
43
+ - The agent had an explicit preflight gate before work.
44
+ - Required context sources were checked or clearly missing.
45
+ - Side-effecting tools were blocked, downgraded, or allowed for a reason.
46
+ - A reviewer can tell whether the run began from known project context or from blind rediscovery.
47
+
48
+ ## What this does not prove
49
+
50
+ - It is not an authorization decision.
51
+ - It does not prove the model fully understood the context.
52
+ - It does not replace Cursor, Claude Code, or MCP-native enforcement.
53
+ - It does not require logging private memory content.
54
+
55
+ ## Failure modes to record
56
+
57
+ ```json
58
+ {
59
+ "schema": "pluribus.session_preflight_receipt.v1",
60
+ "decision": {
61
+ "allowed_to_start_work": false,
62
+ "mode": "read_only",
63
+ "reason": "required context missing or session_init skipped"
64
+ },
65
+ "failures": [
66
+ {
67
+ "kind": "required_context_missing",
68
+ "id": "project-memory",
69
+ "path": "MEMORY.md"
70
+ }
71
+ ]
72
+ }
73
+ ```
74
+
75
+ The key distinction: **a required first tool is the enforcement hook; the receipt is the evidence that the hook actually ran before work.**
76
+
77
+ See `examples/session-preflight-receipts/` for a copyable Cursor-style rule and JSON fixture.
@@ -0,0 +1,70 @@
1
+ # CLAUDE.md read receipt
2
+
3
+ A tiny, manual-first receipt for Claude Code sessions where `CLAUDE.md` is read at startup but trust erodes after a long session, compaction, `/clear`, or a topic switch.
4
+
5
+ Use it before asking the agent to edit again. The agent does **not** need to dump raw prompts or file contents. It should name the routing/index files it reloaded, the constraints it is carrying forward, and the relevant files it intentionally did not load.
6
+
7
+ ## Prompt pattern
8
+
9
+ ```text
10
+ Before continuing, give me a context read receipt:
11
+ - current task/topic
12
+ - session state: fresh, compacted, topic_switched, or resumed
13
+ - indexed files you reloaded and why
14
+ - 3-5 active constraints carried forward
15
+ - relevant files you did not load
16
+ - stale/historical notes you are not treating as current authority
17
+ - whether it is safe to edit now
18
+ ```
19
+
20
+ If the agent cannot name what it reloaded, it probably has not grounded.
21
+
22
+ ## Run the sample checker
23
+
24
+ ```bash
25
+ cd examples/claude-md-read-receipts
26
+ node check-read-receipt.mjs --receipt sample-read-receipt.json
27
+ ```
28
+
29
+ The bundled passing receipt models a topic switch from payments work to upload API work. It keeps `CLAUDE.md` as the router, reloads the topic doc and migration notes, lists active constraints, and marks the session safe to edit.
30
+
31
+ A stale receipt should fail:
32
+
33
+ ```bash
34
+ node check-read-receipt.mjs --receipt stale-read-receipt.json
35
+ ```
36
+
37
+ ## Receipt shape
38
+
39
+ ```json
40
+ {
41
+ "schema": "pluribus.claude_md_read_receipt.v1",
42
+ "session_state": "topic_switched",
43
+ "current_task": "Update upload API retry handling",
44
+ "reloaded_files": [
45
+ { "path": "CLAUDE.md", "role": "router", "why": "Selects topic-specific docs" }
46
+ ],
47
+ "active_constraints": [
48
+ "Do not log raw file contents",
49
+ "Preserve max 3 retries with exponential backoff",
50
+ "Treat v2.4.0 migration notes as current authority"
51
+ ],
52
+ "not_loaded_files": [
53
+ { "path": "docs/payments.md", "why": "Previous topic only" }
54
+ ],
55
+ "safe_to_edit": true
56
+ }
57
+ ```
58
+
59
+ ## Why this exists
60
+
61
+ The market signal from Claude Code users is practical: people already maintain lean `CLAUDE.md` index files and topic memory docs, but they still have to ask whether the agent actually re-read the right material after a topic switch or compaction.
62
+
63
+ This receipt keeps the ritual lightweight and falsifiable:
64
+
65
+ - `CLAUDE.md` can stay small and act as a router.
66
+ - Topic docs can be reloaded only when relevant.
67
+ - Current authority is separated from stale/historical notes.
68
+ - `safe_to_edit=false` is allowed when the session cannot prove it is grounded.
69
+
70
+ Pair this with Pluribus' sync/audit workflow when file drift is the problem. Use this receipt when runtime grounding is the problem.