pluribus-context 0.3.34 → 0.3.36

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 (85) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +2 -1
  3. package/bin/pluribus.js +12 -0
  4. package/docs/agent-firewall-denial-audit.md +95 -0
  5. package/docs/ai-pr-review-receipts.md +173 -0
  6. package/docs/canonical-output-receipts.md +107 -0
  7. package/docs/compaction-resume-receipts.md +43 -0
  8. package/docs/controlled-learning-queue.md +48 -0
  9. package/docs/dynamic-workflow-run-receipts.md +158 -0
  10. package/docs/install-plan-receipts.md +79 -0
  11. package/docs/loaded-resource-boundary.md +97 -0
  12. package/docs/mcp-tool-visibility-receipts.md +67 -0
  13. package/docs/memory-write-policy-receipts.md +41 -0
  14. package/docs/parallel-session-review-ledger.md +103 -0
  15. package/docs/phase-boundary-contracts.md +87 -0
  16. package/docs/review-primitive-gate.md +109 -0
  17. package/docs/skill-install-receipts.md +102 -0
  18. package/docs/skill-policy-receipts.md +87 -0
  19. package/docs/skill-use-rate-receipts.md +104 -0
  20. package/docs/subagent-role-receipts.md +95 -0
  21. package/docs/temporal-context-receipts.md +123 -0
  22. package/examples/agent-firewall-denial-audit/README.md +14 -0
  23. package/examples/agent-firewall-denial-audit/check-denial-audit.mjs +116 -0
  24. package/examples/agent-firewall-denial-audit/denial-envelope.json +9 -0
  25. package/examples/agent-firewall-denial-audit/operator-audit-record.json +20 -0
  26. package/examples/agent-skills/skill-policy-receipts/README.md +22 -0
  27. package/examples/agent-skills/skill-policy-receipts/SKILL.md +77 -0
  28. package/examples/ai-pr-review-receipts/.github/pull_request_template.md +31 -0
  29. package/examples/ai-pr-review-receipts/.github/workflows/ai-pr-review-receipt.yml +25 -0
  30. package/examples/ai-pr-review-receipts/README.md +55 -0
  31. package/examples/ai-pr-review-receipts/incomplete-review-primitive-receipt.json +43 -0
  32. package/examples/ai-pr-review-receipts/review-primitive-receipt.json +60 -0
  33. package/examples/canonical-output-receipts/canonical-output-receipt.json +55 -0
  34. package/examples/claude-code-review-hook/README.md +74 -0
  35. package/examples/claude-code-review-hook/check-review-receipt-hook.mjs +80 -0
  36. package/examples/claude-code-review-hook/sample-task-completed-event.json +6 -0
  37. package/examples/compaction-resume-receipts/README.md +12 -0
  38. package/examples/compaction-resume-receipts/check-resume-receipt.mjs +116 -0
  39. package/examples/compaction-resume-receipts/safe-resume-receipt.json +52 -0
  40. package/examples/compaction-resume-receipts/unsafe-resume-receipt.json +41 -0
  41. package/examples/controlled-learning-queue/README.md +26 -0
  42. package/examples/controlled-learning-queue/check-learning-queue.mjs +44 -0
  43. package/examples/controlled-learning-queue/leads/acme-job-card.md +12 -0
  44. package/examples/controlled-learning-queue/learning_queue.md +27 -0
  45. package/examples/controlled-learning-queue/memory/durable.md +10 -0
  46. package/examples/controlled-learning-queue/memory/working-notes.md +5 -0
  47. package/examples/controlled-learning-queue/role/job-contract.md +18 -0
  48. package/examples/controlled-learning-queue/skills/qualify-lead.md +17 -0
  49. package/examples/dynamic-workflow-run-receipts/README.md +18 -0
  50. package/examples/dynamic-workflow-run-receipts/workflow-run-receipt.json +112 -0
  51. package/examples/install-plan-receipts/README.md +34 -0
  52. package/examples/install-plan-receipts/agent-install-plan-receipt.json +56 -0
  53. package/examples/loaded-resource-boundary/README.md +22 -0
  54. package/examples/loaded-resource-boundary/check-loaded-resource-boundary.mjs +65 -0
  55. package/examples/loaded-resource-boundary/loaded-resource-boundary.json +69 -0
  56. package/examples/memory-write-policy/README.md +28 -0
  57. package/examples/memory-write-policy/approved-memory-update.json +48 -0
  58. package/examples/memory-write-policy/check-memory-update.mjs +120 -0
  59. package/examples/memory-write-policy/quarantined-memory-update.json +43 -0
  60. package/examples/parallel-session-review-ledger/README.md +13 -0
  61. package/examples/parallel-session-review-ledger/check-parallel-session-review-ledger.mjs +69 -0
  62. package/examples/parallel-session-review-ledger/parallel-session-review-ledger.json +72 -0
  63. package/examples/phase-boundary-contract/README.md +23 -0
  64. package/examples/phase-boundary-contract/check-phase-boundary.mjs +73 -0
  65. package/examples/phase-boundary-contract/phase-boundary-contract.json +68 -0
  66. package/examples/review-primitive-gate/README.md +19 -0
  67. package/examples/review-primitive-gate/check-review-receipt.mjs +100 -0
  68. package/examples/review-primitive-gate/fail-review-receipt.json +42 -0
  69. package/examples/review-primitive-gate/pass-review-receipt.json +54 -0
  70. package/examples/skill-install-receipts/README.md +31 -0
  71. package/examples/skill-install-receipts/check-skill-install-receipt.mjs +75 -0
  72. package/examples/skill-install-receipts/skill-install-receipt.json +79 -0
  73. package/examples/skill-use-rate-receipts/README.md +16 -0
  74. package/examples/skill-use-rate-receipts/check-skill-use-rate.mjs +89 -0
  75. package/examples/skill-use-rate-receipts/skill-use-rate-receipt.json +79 -0
  76. package/examples/subagent-role-receipts/README.md +15 -0
  77. package/examples/subagent-role-receipts/agents.toml +36 -0
  78. package/examples/temporal-context-receipts/CURRENT_STATE.md +13 -0
  79. package/examples/temporal-context-receipts/specs/2025-checkout-rewrite.md +10 -0
  80. package/examples/temporal-context-receipts/specs/2026-checkout-risk-notes.md +10 -0
  81. package/examples/temporal-context-receipts/temporal-authority-receipt.json +27 -0
  82. package/package.json +1 -1
  83. package/src/commands/demo.js +155 -0
  84. package/src/index.js +1 -0
  85. package/src/utils/version.js +1 -1
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+
5
+ const dir = process.argv[2] || new URL('.', import.meta.url).pathname;
6
+ const envelopePath = path.join(dir, 'denial-envelope.json');
7
+ const auditPath = path.join(dir, 'operator-audit-record.json');
8
+ const envelope = JSON.parse(fs.readFileSync(envelopePath, 'utf8'));
9
+ const audit = JSON.parse(fs.readFileSync(auditPath, 'utf8'));
10
+ const errors = [];
11
+
12
+ const secretLike = /(api[_-]?key|secret|password|token\s*[:=]|-----BEGIN|bearer\s+[a-z0-9._-]+|raw transcript|verbatim customer|full email)/i;
13
+ const rawCommandLike = /\b(rm\s+-rf|git\s+push|git\s+reset|npm\s+publish|curl\s+https?:|gh\s+(issue|pr)\s+(create|edit))\b/i;
14
+ const absolutePathLike = /(^|["'\s])\/(home|Users|var|etc|tmp)\/[\w./-]+/i;
15
+ const sha256Like = /^sha256:[a-f0-9]{64}$/;
16
+ const allowedReasonClasses = new Set([
17
+ 'destructive_git',
18
+ 'filesystem_write_out_of_scope',
19
+ 'outbound_after_secret_read',
20
+ 'credential_exposure_risk',
21
+ 'package_publish_requires_approval',
22
+ 'unknown_policy_boundary'
23
+ ]);
24
+ const retrySafety = new Set(['safe_to_retry', 'unsafe_until_approved', 'unsafe_do_not_retry']);
25
+
26
+ function requireString(object, field, label) {
27
+ if (typeof object[field] !== 'string' || object[field].trim() === '') {
28
+ errors.push(`${label}: missing ${field}`);
29
+ return '';
30
+ }
31
+ return object[field];
32
+ }
33
+
34
+ function inspectModelVisible(value, prefix = 'envelope') {
35
+ if (typeof value === 'string') {
36
+ if (secretLike.test(value)) errors.push(`${prefix}: possible secret/private payload leak`);
37
+ if (rawCommandLike.test(value)) errors.push(`${prefix}: raw command leaked to model-visible denial`);
38
+ if (absolutePathLike.test(value)) errors.push(`${prefix}: absolute private path leaked to model-visible denial`);
39
+ return;
40
+ }
41
+ if (Array.isArray(value)) {
42
+ value.forEach((item, index) => inspectModelVisible(item, `${prefix}[${index}]`));
43
+ return;
44
+ }
45
+ if (value && typeof value === 'object') {
46
+ for (const [key, item] of Object.entries(value)) {
47
+ if (/raw(command|input|prompt|policy|file|content)|secret|token|password/i.test(key)) {
48
+ errors.push(`${prefix}.${key}: forbidden model-visible field`);
49
+ }
50
+ inspectModelVisible(item, `${prefix}.${key}`);
51
+ }
52
+ }
53
+ }
54
+
55
+ if (envelope.type !== 'agent_firewall_denial.v1') errors.push('envelope: wrong type');
56
+ if (audit.type !== 'agent_firewall_operator_audit.v1') errors.push('audit: wrong type');
57
+ if (envelope.decision !== 'blocked') errors.push('envelope: decision must be blocked');
58
+ if (audit.decision !== 'blocked') errors.push('audit: decision must be blocked');
59
+
60
+ const correlationId = requireString(envelope, 'correlationId', 'envelope');
61
+ if (correlationId !== audit.correlationId) errors.push('audit: correlationId does not match envelope');
62
+
63
+ const reasonClass = requireString(envelope, 'reasonClass', 'envelope');
64
+ if (reasonClass && !allowedReasonClasses.has(reasonClass)) {
65
+ errors.push(`envelope: unknown or too-specific reasonClass ${reasonClass}`);
66
+ }
67
+
68
+ const alternative = requireString(envelope, 'safeAlternative', 'envelope');
69
+ if (alternative.length > 240) errors.push('envelope: safeAlternative should stay short');
70
+ if (typeof envelope.requiresApproval !== 'boolean') errors.push('envelope: requiresApproval must be boolean');
71
+ if (!retrySafety.has(envelope.retrySafety)) errors.push('envelope: invalid retrySafety');
72
+ inspectModelVisible(envelope);
73
+
74
+ if (!['Bash', 'Edit', 'Write', 'WebFetch', 'MCP', 'Task', 'Agent'].includes(audit.tool)) {
75
+ errors.push('audit: unexpected or missing tool class');
76
+ }
77
+ if (!sha256Like.test(audit.commandHash || '')) errors.push('audit: commandHash must be sha256:<64 hex>');
78
+ if (!sha256Like.test(audit.cwdHash || '')) errors.push('audit: cwdHash must be sha256:<64 hex>');
79
+ if (!Array.isArray(audit.matchedPolicyIds) || audit.matchedPolicyIds.length === 0) {
80
+ errors.push('audit: matchedPolicyIds must be a non-empty array');
81
+ }
82
+ if (!audit.sessionTaint || typeof audit.sessionTaint !== 'object') errors.push('audit: missing sessionTaint object');
83
+ if (!audit.approval || typeof audit.approval !== 'object') errors.push('audit: missing approval object');
84
+ if (!retrySafety.has(audit.retrySafety)) errors.push('audit: invalid retrySafety');
85
+ if (typeof audit.modelEnvelopeHash !== 'string' || !sha256Like.test(audit.modelEnvelopeHash)) {
86
+ errors.push('audit: modelEnvelopeHash must be sha256:<64 hex>');
87
+ }
88
+
89
+ function inspectAuditValues(value, prefix = 'audit') {
90
+ if (typeof value === 'string') {
91
+ if (/(api[_-]?key\s*[:=]|secret\s*[:=]|password\s*[:=]|token\s*[:=]|-----BEGIN|bearer\s+[a-z0-9._-]+|raw transcript|verbatim customer|full email)/i.test(value)) {
92
+ errors.push(`${prefix}: possible raw secret/private payload`);
93
+ }
94
+ return;
95
+ }
96
+ if (Array.isArray(value)) {
97
+ value.forEach((item, index) => inspectAuditValues(item, `${prefix}[${index}]`));
98
+ return;
99
+ }
100
+ if (value && typeof value === 'object') {
101
+ for (const [key, item] of Object.entries(value)) inspectAuditValues(item, `${prefix}.${key}`);
102
+ }
103
+ }
104
+
105
+ inspectAuditValues(audit);
106
+ if ('rawCommand' in audit || 'rawPrompt' in audit || 'rawPolicy' in audit || 'rawFileContent' in audit) {
107
+ errors.push('audit: raw private payload fields are not allowed');
108
+ }
109
+
110
+ if (errors.length) {
111
+ console.error(`agent firewall denial/audit failed (${errors.length}):`);
112
+ for (const error of errors) console.error(`- ${error}`);
113
+ process.exit(1);
114
+ }
115
+
116
+ console.log(`agent firewall denial/audit ok: ${correlationId}, ${reasonClass}, ${audit.matchedPolicyIds.length} policy id(s)`);
@@ -0,0 +1,9 @@
1
+ {
2
+ "type": "agent_firewall_denial.v1",
3
+ "decision": "blocked",
4
+ "reasonClass": "destructive_git",
5
+ "requiresApproval": true,
6
+ "safeAlternative": "Explain the planned git operation and wait for explicit approval.",
7
+ "retrySafety": "unsafe_until_approved",
8
+ "correlationId": "deny_2026_06_02_2200_7f3a"
9
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "type": "agent_firewall_operator_audit.v1",
3
+ "decision": "blocked",
4
+ "correlationId": "deny_2026_06_02_2200_7f3a",
5
+ "tool": "Bash",
6
+ "commandHash": "sha256:0e5751c026e543b2a6f2b4d7a7c8d8e5b81b69c5b9f7db2a5b94f31f987e7f44",
7
+ "cwdHash": "sha256:dcdb704109a454784b81229d2b05f368692e758bfa33cb61d04c1b93791b0273",
8
+ "matchedPolicyIds": ["git.destructive.requires_approval"],
9
+ "sessionTaint": {
10
+ "secretRead": false,
11
+ "privateFileRead": true,
12
+ "networkAccessed": false
13
+ },
14
+ "approval": {
15
+ "state": "missing",
16
+ "requiredFrom": "operator"
17
+ },
18
+ "retrySafety": "unsafe_until_approved",
19
+ "modelEnvelopeHash": "sha256:a1bcaa1cb2572ab0e735c30062a268391d0a9d1b3dd7ff4b14065d8b29513b2a"
20
+ }
@@ -0,0 +1,22 @@
1
+ # Skill policy receipts recipe
2
+
3
+ This is a copyable Agent Skill recipe for cases where a natural-language rule needs an inspectable guard.
4
+
5
+ Example use cases:
6
+
7
+ - a Skill must not generate tests for internal services;
8
+ - an agent must not edit generated files;
9
+ - a hook must not call production APIs;
10
+ - a migration helper must default to preview/dry-run unless `--apply` is explicit.
11
+
12
+ Copy `SKILL.md` into your Skill registry, adjust the policy and post-write guard, then ask the agent to emit `skill.policy.v1` receipts before writes and after guard checks.
13
+
14
+ The receipt should prove:
15
+
16
+ - intended targets were listed;
17
+ - each target was allowed or refused;
18
+ - refusal happened before writes;
19
+ - post-write guard passed or failed;
20
+ - no raw prompt, code, secret, customer data, stack trace, or full transcript was logged.
21
+
22
+ Related guide: [`docs/skill-policy-receipts.md`](../../../docs/skill-policy-receipts.md).
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: skill-policy-receipts
3
+ description: Use when a task must obey a hard project policy, such as "do not generate tests for internal services", "do not call production APIs", or "do not edit generated files". Emits a privacy-safe receipt before writes and after guard checks.
4
+ ---
5
+
6
+ # Skill Policy Receipts
7
+
8
+ This Skill turns natural-language guardrails into an inspectable policy receipt.
9
+
10
+ ## Preflight: decide before writing
11
+
12
+ Before creating or editing files:
13
+
14
+ 1. List intended targets using coarse paths or globs.
15
+ 2. For each target, decide `allowed` or `refused`.
16
+ 3. Give a short reason.
17
+ 4. If any target is refused, stop before writing.
18
+ 5. Emit a receipt with `write_started=false` and `stopped_at="policy_refused"`.
19
+
20
+ Receipt shape:
21
+
22
+ ```json
23
+ {
24
+ "receipt_type": "skill.policy.v1",
25
+ "skill": "skill-policy-receipts",
26
+ "policy_scope": "<short policy name>",
27
+ "targets": [
28
+ {
29
+ "target": "<coarse path or glob>",
30
+ "decision": "allowed|refused",
31
+ "reason": "<short reason>"
32
+ }
33
+ ],
34
+ "write_started": false,
35
+ "post_write_guard": "not_run",
36
+ "stopped_at": "policy_refused|all_targets_allowed"
37
+ }
38
+ ```
39
+
40
+ Do not include raw prompts, code, secrets, customer data, stack traces, or full tool output.
41
+
42
+ ## Write only after all targets are allowed
43
+
44
+ If every target is allowed:
45
+
46
+ 1. Emit or state `stopped_at="all_targets_allowed"`.
47
+ 2. Perform the write.
48
+ 3. Run the configured post-write guard.
49
+ 4. Emit whether the guard passed or failed.
50
+
51
+ Post-write receipt shape:
52
+
53
+ ```json
54
+ {
55
+ "receipt_type": "skill.policy.v1",
56
+ "skill": "skill-policy-receipts",
57
+ "policy_scope": "<short policy name>",
58
+ "write_started": true,
59
+ "post_write_guard": "passed|failed|not_configured",
60
+ "stopped_at": "guard_passed|guard_failed"
61
+ }
62
+ ```
63
+
64
+ ## Example policy: no internal-service unit tests
65
+
66
+ Policy:
67
+
68
+ > Do not generate unit tests for internal services. If the requested test imports `internal/`, `@/internal`, or a known private service module, refuse before writing and explain the safer target.
69
+
70
+ Example guard:
71
+
72
+ ```bash
73
+ grep -R "from ['\"]\.\./\.\./internal\|from ['\"]@/internal\|require(['\"]@/internal" \
74
+ -- '*test.*' '*spec.*'
75
+ ```
76
+
77
+ If the grep finds a match in generated tests, stop and report `post_write_guard="failed"`.
@@ -0,0 +1,31 @@
1
+ ## AI PR review receipt
2
+
3
+ This PR was prepared or modified by an AI coding agent. Review by blast radius, not by diff size alone.
4
+
5
+ ### Boundary receipt
6
+
7
+ | Boundary | Status | Evidence | Risk tier | Owner / blocker |
8
+ | --- | --- | --- | --- | --- |
9
+ | Schema / persisted data contract | `touched / not_touched / ambiguous` | | | |
10
+ | Live reader/writer compatibility | `checked / missing / n/a` | | | |
11
+ | Async jobs / queues / cron / webhooks | `touched / not_touched / ambiguous` | | | |
12
+ | Rollout gate / feature flag / kill switch | `present / missing / n/a` | | | |
13
+ | External side effects | `declared / not_touched / ambiguous` | | | |
14
+ | Generated files / public API / plugin config | `touched / not_touched / ambiguous` | | | |
15
+
16
+ ### Checks
17
+
18
+ - [ ] Tests relevant to touched boundaries passed.
19
+ - [ ] Migration/backfill/rollback behavior is explicit, or not applicable.
20
+ - [ ] External side effects are declared, or not touched.
21
+ - [ ] Any `ambiguous` boundary has an owner before merge.
22
+
23
+ ### Privacy
24
+
25
+ This receipt does not include raw prompts, transcripts, source code, secrets, customer data, stack traces, or raw tool output.
26
+
27
+ ### Decision
28
+
29
+ `merge_ready: yes/no`
30
+
31
+ `next_safe_action:`
@@ -0,0 +1,25 @@
1
+ name: AI PR review receipt gate
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, reopened, ready_for_review]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ review-receipt:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ # Put your agent/bot-generated receipt at this path, or adjust RECEIPT_PATH.
17
+ # Keep the receipt privacy-safe: no raw prompts, transcripts, source code,
18
+ # tool output, secrets, stack traces, or customer data.
19
+ - name: Validate AI PR review receipt
20
+ env:
21
+ RECEIPT_PATH: artifacts/review-primitive-receipt.json
22
+ run: |
23
+ test -f "$RECEIPT_PATH"
24
+ npm install --no-save --ignore-scripts pluribus-context@latest
25
+ node node_modules/pluribus-context/examples/review-primitive-gate/check-review-receipt.mjs "$RECEIPT_PATH"
@@ -0,0 +1,55 @@
1
+ # AI PR review receipts example
2
+
3
+ This example contains a copyable GitHub PR template and CI gate for agent-generated or agent-modified pull requests.
4
+
5
+ Use it when review risk depends on blast radius: schema/data contracts, async paths, rollout gates, external side effects, generated/public interfaces, or security-sensitive config.
6
+
7
+ The point is not to make every AI PR small. It is to make the risky boundaries reviewable enough that CI or a maintainer can decide: merge, route to a human owner, or stop.
8
+
9
+ ## Files
10
+
11
+ - [`.github/pull_request_template.md`](.github/pull_request_template.md) — human-readable PR body section for blast-radius review.
12
+ - [`.github/workflows/ai-pr-review-receipt.yml`](.github/workflows/ai-pr-review-receipt.yml) — copyable GitHub Actions gate that validates a machine-readable receipt.
13
+ - [`review-primitive-receipt.json`](review-primitive-receipt.json) — passing receipt fixture.
14
+ - [`incomplete-review-primitive-receipt.json`](incomplete-review-primitive-receipt.json) — failing fixture for partial/unsafe evidence.
15
+
16
+ ## 60-second local smoke
17
+
18
+ From the repository root:
19
+
20
+ ```bash
21
+ node examples/review-primitive-gate/check-review-receipt.mjs \
22
+ examples/ai-pr-review-receipts/review-primitive-receipt.json
23
+ ```
24
+
25
+ Expected: `ok: true`.
26
+
27
+ Then run the incomplete fixture:
28
+
29
+ ```bash
30
+ node examples/review-primitive-gate/check-review-receipt.mjs \
31
+ examples/ai-pr-review-receipts/incomplete-review-primitive-receipt.json
32
+ ```
33
+
34
+ Expected: non-zero exit. The failure is intentional: unapproved scope change, skipped required test, missing evidence, and `partial` resume state should not silently pass a merge gate.
35
+
36
+ ## GitHub Actions usage
37
+
38
+ 1. Copy `.github/workflows/ai-pr-review-receipt.yml` into your repo.
39
+ 2. Have your Claude Code / Codex / Cursor / OpenClaw / review bot emit a privacy-safe receipt at `artifacts/review-primitive-receipt.json`.
40
+ 3. Keep raw prompts, transcripts, source code, secrets, stack traces, customer data, and raw tool output out of the receipt.
41
+ 4. Let the workflow fail if the receipt is partial, unsafe, missing evidence, or outside approved boundaries.
42
+
43
+ The template and JSON receipt can be used together: the PR body explains the blast radius to humans, while the JSON receipt gives CI a hard decision primitive.
44
+
45
+ ## Why this exists
46
+
47
+ Large AI PRs are not automatically unsafe, and small PRs are not automatically reviewable. Diff size is a proxy. This receipt makes the underlying question explicit:
48
+
49
+ - Which assignment did the agent accept?
50
+ - What read/write boundaries were approved?
51
+ - Did scope or access change mid-run, and was it approved?
52
+ - Which required checks actually ran, with evidence?
53
+ - Did the agent refuse unsafe operations?
54
+ - Is the handoff `complete`, `partial`, or `unsafe-to-resume`?
55
+ - What is the next safe action for the reviewer?
@@ -0,0 +1,43 @@
1
+ {
2
+ "type": "agent.review_primitive_receipt.v1",
3
+ "assignment_id": "pr-483-agent-review",
4
+ "run_id": "run-2026-05-31T23-10Z",
5
+ "agent": {
6
+ "tool": "claude-code-github-actions",
7
+ "role": "pr-reviewer"
8
+ },
9
+ "approved_boundaries": {
10
+ "read": ["src/auth/**", "tests/auth/**"],
11
+ "write": ["tests/auth/**"],
12
+ "network": false
13
+ },
14
+ "scope_access_changes": [
15
+ {
16
+ "change": "write src/auth/session.ts",
17
+ "reason": "agent attempted to patch production auth code during review",
18
+ "approved": false,
19
+ "approved_by": ""
20
+ }
21
+ ],
22
+ "commands_and_checks": [
23
+ {
24
+ "name": "npm test -- tests/auth",
25
+ "kind": "required_test",
26
+ "status": "skipped",
27
+ "evidence": "not-run"
28
+ }
29
+ ],
30
+ "refused_operations": [],
31
+ "handoff": {
32
+ "changed_files_bucket": "under_10",
33
+ "evidence_path": "artifacts/pr-483/review-primitive-receipt.json",
34
+ "next_safe_action": "human must inspect attempted auth write and run required tests before merge"
35
+ },
36
+ "resume_state": "partial",
37
+ "privacy": {
38
+ "raw_prompts_logged": false,
39
+ "raw_tool_output_logged": false,
40
+ "source_code_logged": false,
41
+ "secrets_logged": false
42
+ }
43
+ }
@@ -0,0 +1,60 @@
1
+ {
2
+ "type": "agent.review_primitive_receipt.v1",
3
+ "assignment_id": "pr-482-agent-review",
4
+ "run_id": "run-2026-05-31T23-00Z",
5
+ "agent": {
6
+ "tool": "claude-code-github-actions",
7
+ "role": "pr-reviewer"
8
+ },
9
+ "approved_boundaries": {
10
+ "read": ["src/billing/**", "tests/billing/**", "docs/rollout/**"],
11
+ "write": ["tests/billing/**", "docs/review-receipts/**"],
12
+ "network": false
13
+ },
14
+ "scope_access_changes": [
15
+ {
16
+ "change": "read docs/rollout/**",
17
+ "reason": "verify feature-flag and rollback evidence for the PR receipt",
18
+ "approved": true,
19
+ "approved_by": "maintainer"
20
+ }
21
+ ],
22
+ "commands_and_checks": [
23
+ {
24
+ "name": "npm test -- tests/billing",
25
+ "kind": "required_test",
26
+ "status": "passed",
27
+ "evidence": "https://github.com/example/repo/actions/runs/123#billing-tests"
28
+ },
29
+ {
30
+ "name": "npm run lint",
31
+ "kind": "required_check",
32
+ "status": "passed",
33
+ "evidence": "https://github.com/example/repo/actions/runs/123#lint"
34
+ },
35
+ {
36
+ "name": "migration rollback smoke",
37
+ "kind": "required_check",
38
+ "status": "passed",
39
+ "evidence": "artifacts/pr-482/rollback-smoke.txt"
40
+ }
41
+ ],
42
+ "refused_operations": [
43
+ {
44
+ "operation": "write src/billing/charge-customer.ts",
45
+ "reason": "outside approved write boundary; reviewer requested tests/docs only"
46
+ }
47
+ ],
48
+ "handoff": {
49
+ "changed_files_bucket": "under_5",
50
+ "evidence_path": "artifacts/pr-482/review-primitive-receipt.json",
51
+ "next_safe_action": "review billing test assertions and rollback evidence before merge"
52
+ },
53
+ "resume_state": "complete",
54
+ "privacy": {
55
+ "raw_prompts_logged": false,
56
+ "raw_tool_output_logged": false,
57
+ "source_code_logged": false,
58
+ "secrets_logged": false
59
+ }
60
+ }
@@ -0,0 +1,55 @@
1
+ {
2
+ "type": "canonical.output.receipt.v1",
3
+ "artifact": {
4
+ "stable_id": "project-alpha-master-prompt-2026-05-30",
5
+ "name": "Project Alpha master prompt",
6
+ "kind": "master_prompt",
7
+ "canonical_path": "docs/prompts/project-alpha-master-prompt.md",
8
+ "current_version": "2026-05-30.1",
9
+ "content_hash": "sha256:example-only",
10
+ "status": "current",
11
+ "owner_label": "product-ops",
12
+ "created_at": "2026-05-30T21:40:00Z",
13
+ "last_reviewed_at": "2026-05-30T21:58:00Z"
14
+ },
15
+ "source": {
16
+ "workspace": "claude-project-alpha",
17
+ "source_session_id": "session-redacted-2026-05-30",
18
+ "source_tool": "claude-projects",
19
+ "source_chat_title": "Master prompt rebuild",
20
+ "source_url_or_path_redacted": true,
21
+ "raw_transcript_logged": false
22
+ },
23
+ "index": {
24
+ "exact_phrases_worth_grepping": [
25
+ "do not collapse escalation paths into summaries",
26
+ "billing exports are evidence, not source of truth",
27
+ "final prompt contract v3"
28
+ ],
29
+ "tags": ["master-prompt", "billing", "escalation", "current-state"],
30
+ "related_artifacts": ["billing-escalation-runbook-2026-05-28"]
31
+ },
32
+ "decisions": {
33
+ "accepted": [
34
+ "Use repo-owned markdown as the canonical copy, not old chats",
35
+ "Keep escalation criteria in the prompt body and test cases in a separate appendix"
36
+ ],
37
+ "rejected": [
38
+ {
39
+ "option": "Rely on Claude Project conversation search for recovery",
40
+ "reason": "exact phrase and project-scoped search were unreliable during rebuild"
41
+ }
42
+ ],
43
+ "open_questions": [
44
+ "Does support need a shorter handoff summary for weekend rotations?"
45
+ ],
46
+ "next_action": "Open a PR that adds the canonical prompt and this receipt to docs/prompts/"
47
+ },
48
+ "privacy": {
49
+ "raw_prompt_logged": false,
50
+ "raw_chat_logged": false,
51
+ "customer_data_logged": false,
52
+ "secrets_logged": false,
53
+ "proprietary_paths_logged": false
54
+ }
55
+ }
@@ -0,0 +1,74 @@
1
+ # Claude Code review hook bridge
2
+
3
+ This example wires the [review primitive gate](../review-primitive-gate/) into Claude Code hooks so a long agent run can be blocked at handoff time when the receipt says `partial` or `unsafe-to-resume`.
4
+
5
+ Use it when you already have Claude Code hooks, a local control-plane wrapper, or CI emitting `agent.review_primitive_receipt.v1` receipts and you want Claude Code to treat the receipt as a gate rather than a note.
6
+
7
+ ## Copy the hook
8
+
9
+ ```bash
10
+ mkdir -p .claude/hooks .pluribus/receipts
11
+ cp examples/claude-code-review-hook/check-review-receipt-hook.mjs .claude/hooks/
12
+ cp examples/review-primitive-gate/check-review-receipt.mjs .claude/hooks/
13
+ ```
14
+
15
+ Then add this to `.claude/settings.json`:
16
+
17
+ ```json
18
+ {
19
+ "hooks": {
20
+ "TaskCompleted": [
21
+ {
22
+ "matcher": "*",
23
+ "hooks": [
24
+ {
25
+ "type": "command",
26
+ "command": "node ${CLAUDE_PROJECT_DIR}/.claude/hooks/check-review-receipt-hook.mjs ${CLAUDE_PROJECT_DIR}/.pluribus/receipts/latest-review-receipt.json"
27
+ }
28
+ ]
29
+ }
30
+ ],
31
+ "PostCompact": [
32
+ {
33
+ "matcher": "*",
34
+ "hooks": [
35
+ {
36
+ "type": "command",
37
+ "command": "node ${CLAUDE_PROJECT_DIR}/.claude/hooks/check-review-receipt-hook.mjs ${CLAUDE_PROJECT_DIR}/.pluribus/receipts/latest-review-receipt.json"
38
+ }
39
+ ]
40
+ }
41
+ ]
42
+ }
43
+ }
44
+ ```
45
+
46
+ The same bridge can be attached to `SessionEnd` if your workflow writes the receipt only when a session exits.
47
+
48
+ ## What the hook does
49
+
50
+ Claude Code passes hook event JSON on stdin. The bridge reads that event for traceability, runs the review gate against the receipt path, and:
51
+
52
+ - exits `0` when the receipt is complete and privacy-safe;
53
+ - exits non-zero when required evidence is missing, checks failed/skipped, scope changes were unapproved, or `resume_state` is `partial` / `unsafe-to-resume`;
54
+ - prints a small JSON result that names the hook event, receipt path, and next safe action.
55
+
56
+ It does **not** log raw prompts, transcripts, tool output, source code, exact proprietary paths, secrets, or customer data.
57
+
58
+ ## Smoke test
59
+
60
+ ```bash
61
+ node examples/claude-code-review-hook/check-review-receipt-hook.mjs \
62
+ examples/review-primitive-gate/pass-review-receipt.json \
63
+ < examples/claude-code-review-hook/sample-task-completed-event.json
64
+
65
+ node examples/claude-code-review-hook/check-review-receipt-hook.mjs \
66
+ examples/review-primitive-gate/fail-review-receipt.json \
67
+ < examples/claude-code-review-hook/sample-task-completed-event.json
68
+ ```
69
+
70
+ The first command should pass. The second should fail and tell the reviewer why the handoff should not continue.
71
+
72
+ ## Why this exists
73
+
74
+ Claude Code hooks are good at triggering automation around `TaskCompleted`, `PostCompact`, and `SessionEnd`. Pluribus should not replace that control plane. This bridge makes the missing handoff proof explicit: before the next agent resumes, prove the assignment boundary, required checks, privacy flags, evidence path, and `complete / partial / unsafe-to-resume` state.