harness-everything 0.41.3 → 0.42.1

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 (50) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +18 -0
  4. package/benchmarks/results/codex-pr-metadata-2026-10-26/README.md +68 -0
  5. package/benchmarks/results/codex-pr-metadata-2026-10-26/green-final.log +162 -0
  6. package/benchmarks/results/codex-pr-metadata-2026-10-26/green.log +158 -0
  7. package/benchmarks/results/codex-pr-metadata-2026-10-26/live-installed-runtime-rejection.json +31 -0
  8. package/benchmarks/results/codex-pr-metadata-2026-10-26/luna-action-family-cross-product.js +143 -0
  9. package/benchmarks/results/codex-pr-metadata-2026-10-26/luna-action-family-cross-product.log +7 -0
  10. package/benchmarks/results/codex-pr-metadata-2026-10-26/luna-codex-action-gate-prehook-smoke.js +78 -0
  11. package/benchmarks/results/codex-pr-metadata-2026-10-26/luna-codex-action-gate-prehook-smoke.log +8 -0
  12. package/benchmarks/results/codex-pr-metadata-2026-10-26/luna-review.md +151 -0
  13. package/benchmarks/results/codex-pr-metadata-2026-10-26/original-rejection.json +31 -0
  14. package/benchmarks/results/codex-pr-metadata-2026-10-26/red.log +158 -0
  15. package/benchmarks/results/codex-pr-metadata-2026-10-26/review-descriptor-green.log +192 -0
  16. package/benchmarks/results/codex-pr-metadata-2026-10-26/review-descriptor-red.log +192 -0
  17. package/benchmarks/results/codex-pr-metadata-2026-10-26/review-family-green.log +206 -0
  18. package/benchmarks/results/codex-pr-metadata-2026-10-26/review-family-red.log +206 -0
  19. package/benchmarks/results/codex-pr-metadata-2026-10-26/review-hints-green.log +174 -0
  20. package/benchmarks/results/codex-pr-metadata-2026-10-26/review-hints-red.log +174 -0
  21. package/benchmarks/results/codex-pr-metadata-2026-10-26/verification.md +31 -0
  22. package/benchmarks/results/doc-evidence-e1/README.md +68 -0
  23. package/benchmarks/results/doc-evidence-e1/evidence.json +360 -0
  24. package/benchmarks/results/doc-evidence-e1/pilot-report.json +175 -0
  25. package/benchmarks/results/h1-provider-independence-qualification/README.md +95 -0
  26. package/benchmarks/results/live-host/opencode-d1-d2-2026-10-25/README.md +30 -0
  27. package/benchmarks/results/live-host/opencode-d1-d2-2026-10-25/evidence.json +128 -0
  28. package/ci/action-gate.test.js +86 -0
  29. package/ci/mechanism-2aa-codex-action-gate-policy.test.js +47 -0
  30. package/ci/mechanism-325-3b-h1-qualification.test.js +206 -0
  31. package/ci/mechanism-341-opencode-lane.test.js +465 -0
  32. package/ci/mechanism-task-git-authorization.test.js +12 -0
  33. package/docs/codex-action-gate.md +27 -1
  34. package/docs/doc-workflow-reconciliation.md +4 -3
  35. package/docs/document-lifecycle.md +3 -3
  36. package/docs/platform-capabilities.md +8 -2
  37. package/hooks/scripts/action-gate.js +35 -8
  38. package/hooks/scripts/lib/doc-reconciliation-pilot.js +40 -10
  39. package/hooks/scripts/lib/doc-reconciliation-provider.js +159 -11
  40. package/hooks/scripts/workflow-stop-gate.js +4 -1
  41. package/opencode-plugin/index.mjs +77 -5
  42. package/opencode-plugin/plugin.json +1 -1
  43. package/package.json +1 -1
  44. package/plugins/harness-everything/.codex-plugin/plugin.json +1 -1
  45. package/plugins/harness-everything/hooks/scripts/action-gate.js +35 -8
  46. package/plugins/harness-everything/hooks/scripts/lib/doc-reconciliation-pilot.js +40 -10
  47. package/plugins/harness-everything/hooks/scripts/lib/doc-reconciliation-provider.js +159 -11
  48. package/plugins/harness-everything/hooks/scripts/workflow-stop-gate.js +4 -1
  49. package/plugins/harness-everything/plugin.json +1 -1
  50. package/sbom.cdx.json +7 -7
@@ -0,0 +1,78 @@
1
+ 'use strict';
2
+ const fs = require('fs');
3
+ const os = require('os');
4
+ const path = require('path');
5
+ const cp = require('child_process');
6
+ const repoRoot = path.resolve(process.argv[2] || process.cwd());
7
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), 'luna-hook-boundary-'));
8
+ const hook = path.join(repoRoot, 'hooks/scripts/codex-action-gate-pre.js');
9
+ const env = {
10
+ ...process.env,
11
+ HARNESS_ACTION_GATE_HOST: 'codex',
12
+ HARNESS_STATE_HOME: root,
13
+ HARNESS_ACTION_GATE_STDIN_TIMEOUT_MS: '2000',
14
+ };
15
+ const input = { repository_full_name: 'acme/repo', pr_number: 376, body: 'fixture' };
16
+ const cases = [
17
+ ['metadata', { tool_input: input }],
18
+ ['required', { tool_input: input, workflowPlan: { actionGate: { required: true } } }],
19
+ ['descriptor-read-shell', { tool_input: input, action_descriptor: { action: 'read', toolFamily: 'shell' } }],
20
+ ['unsafe-state-null-required', { tool_input: { ...input, state: null }, action_descriptor: { action: 'read', toolFamily: 'shell' }, actionGate: { required: true } }],
21
+ ['delete-shell', { tool_input: input, action_descriptor: { action: 'delete', toolFamily: 'shell' } }],
22
+ ['near-name', { tool_name: 'mcp__demo__update_pull_requests', tool_input: input }],
23
+ ['conflicting-harness-required', {
24
+ tool_input: input,
25
+ actionGate: { required: false },
26
+ workflowPlan: { actionGate: { required: false } },
27
+ routerContract: { workflowPlan: { actionGate: { required: false } } },
28
+ harness: { workflowPlan: { actionGate: { required: true } } },
29
+ }],
30
+ ];
31
+ function files(dir) {
32
+ return fs.readdirSync(dir, { withFileTypes: true }).flatMap(entry =>
33
+ entry.isDirectory() ? files(path.join(dir, entry.name)) : [path.join(dir, entry.name)]);
34
+ }
35
+ try {
36
+ console.log(`Node ${process.version}; repo ${repoRoot}`);
37
+ for (let i = 0; i < cases.length; i++) {
38
+ const [label, extra] = cases[i];
39
+ const toolUseId = `hook-${i}`;
40
+ const payload = {
41
+ hook_event_name: 'PreToolUse',
42
+ session_id: `hook-review-${i}`,
43
+ turn_id: 'hook-review',
44
+ tool_use_id: toolUseId,
45
+ tool_name: 'mcp__codex_apps__github__update_pull_request',
46
+ ...extra,
47
+ };
48
+ const result = cp.spawnSync(process.execPath, [hook], {
49
+ cwd: root,
50
+ env,
51
+ input: JSON.stringify(payload),
52
+ encoding: 'utf8',
53
+ timeout: 20000,
54
+ });
55
+ const audit = files(root).filter(file => file.endsWith('.json')).map(file => {
56
+ try { return JSON.parse(fs.readFileSync(file, 'utf8')); } catch { return null; }
57
+ }).find(record => record?.toolUseId === toolUseId);
58
+ const summary = {
59
+ label,
60
+ exitCode: result.status,
61
+ stdout: result.stdout.trim(),
62
+ matchedRule: audit?.matchedRule || null,
63
+ disposition: audit?.disposition || null,
64
+ action: audit?.actionDescriptor?.action || null,
65
+ family: audit?.actionDescriptor?.toolFamily || null,
66
+ classification: audit?.actionDescriptor?.classification || null,
67
+ required: audit?.routerActionGate?.required ?? null,
68
+ };
69
+ console.log(JSON.stringify(summary));
70
+ if (result.error || result.status === null) throw result.error || new Error(`${label}: no process status`);
71
+ const expectedAllow = label === 'metadata' || label === 'descriptor-read-shell';
72
+ if (expectedAllow ? result.status !== 0 : result.status !== 2) throw new Error(`${label}: unexpected exit ${result.status}`);
73
+ if (expectedAllow && (audit?.actionDescriptor?.action !== 'mutate' || audit?.actionDescriptor?.toolFamily !== 'mcp')) throw new Error(`${label}: expected audited MCP mutation`);
74
+ if (!expectedAllow && result.status === 2 && !audit) throw new Error(`${label}: missing block audit`);
75
+ }
76
+ } finally {
77
+ fs.rmSync(root, { recursive: true, force: true });
78
+ }
@@ -0,0 +1,8 @@
1
+ Node v24.22.1; repo /Users/daniel.chang/Desktop/Skills/Harness-codex-pr-metadata
2
+ {"label":"metadata","exitCode":0,"stdout":"","matchedRule":"routine-pr-metadata-update","disposition":"deferred-to-host","action":"mutate","family":"mcp","classification":"gated","required":null}
3
+ {"label":"required","exitCode":2,"stdout":"","matchedRule":"structured-mutate","disposition":"rejected","action":"mutate","family":"mcp","classification":"gated","required":true}
4
+ {"label":"descriptor-read-shell","exitCode":0,"stdout":"","matchedRule":"routine-pr-metadata-update","disposition":"deferred-to-host","action":"mutate","family":"mcp","classification":"gated","required":null}
5
+ {"label":"unsafe-state-null-required","exitCode":2,"stdout":"","matchedRule":"structured-mutate","disposition":"rejected","action":"mutate","family":"mcp","classification":"gated","required":true}
6
+ {"label":"delete-shell","exitCode":2,"stdout":"","matchedRule":"structured-delete","disposition":"rejected","action":"delete","family":"mcp","classification":"gated","required":null}
7
+ {"label":"near-name","exitCode":2,"stdout":"","matchedRule":"structured-mutate","disposition":"rejected","action":"mutate","family":"mcp","classification":"gated","required":null}
8
+ {"label":"conflicting-harness-required","exitCode":2,"stdout":"","matchedRule":"structured-mutate","disposition":"rejected","action":"mutate","family":"mcp","classification":"gated","required":true}
@@ -0,0 +1,151 @@
1
+ # Independent cold review: Codex PR metadata action gate
2
+
3
+ ## Scope and evidence
4
+
5
+ - Repository: `/Users/daniel.chang/Desktop/Skills/Harness-codex-pr-metadata`
6
+ - Base: `b733cadec17542b9ae30aabb50c1ba3481a58d74`
7
+ - Final core SHA reviewed: `c170a96cf856295200d2d1a62c15a552c3cb2b37`
8
+ - Current repository HEAD: `a2edf4ed2204a414dd085635d2d9bf4464c59e9e` (evidence-only commit after the core review); current worktree has two additional evidence-only paths described below.
9
+ - The code path was cold-reviewed at `e160e00`, then re-reviewed through fixes `ff796c9`, `e9344de`, and `c170a96`. Final core behavior was independently exercised at `c170a96`.
10
+ - Requested model/effort: coordinator reports that the agent was routed with `model=gpt-6-luna`, `reasoning_effort=xhigh`. This agent has no host-issued runtime attestation, so actual model/effort identity remains unverified.
11
+ - Read independently: repository `AGENTS.md`, `docs/codex-action-gate.md`, code-review skill/playbook, issue [#110](https://github.com/dyphn1/Harness-everything/issues/110), issue [#122](https://github.com/dyphn1/Harness-everything/issues/122), issue [#135](https://github.com/dyphn1/Harness-everything/issues/135), complete base-to-HEAD diff, original worktree diff, and retained evidence logs/artifacts.
12
+ - Scope clauses, verbatim from the review task:
13
+ - C1 僅 Codex 精確 update_pull_request title/body metadata-only 例外,必須實查參數;
14
+ - C2 state/base_branch/maintainer_can_modify/unknown/mixed risk 不得豁免(包含 null);
15
+ - C3 actionGate.required=true 必須 gate;
16
+ - C4 保持 mutate/gated,無 Codex permissionDecision ask/allow、Host/task scope/GitHub authorization 仍生效;
17
+ - C5 create_pull_request 與 merge/close/delete/force-push/publish/deploy/send 既有行為不變;
18
+ - C6 不擴其他 Host、canonical/plugin parity,hash/redacted audit provenance/executed success+failure/rejected/integrity 行為保持;
19
+ - C7 RED→GREEN→regression 必須自行執行證明,live-host 不可從 unit/mechanism 宣稱 PASS;
20
+ - C8 無 #376 governance 實作、#341 E1/#320 授權擴張、禁自動 merge/繞 gate。
21
+
22
+ ### Paths reviewed in `base..a2edf4e`
23
+
24
+ - `CHANGELOG.md`
25
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/README.md`
26
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/green-final.log`
27
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/green.log`
28
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/original-rejection.json`
29
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/red.log`
30
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/review-descriptor-green.log`
31
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/review-descriptor-red.log`
32
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/review-family-green.log`
33
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/review-family-red.log`
34
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/review-hints-green.log`
35
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/review-hints-red.log`
36
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/luna-action-family-cross-product.js`
37
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/luna-action-family-cross-product.log`
38
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/luna-codex-action-gate-prehook-smoke.js`
39
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/luna-codex-action-gate-prehook-smoke.log`
40
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/verification.md` (current untracked evidence)
41
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/luna-review.md` (current untracked copied report)
42
+ - `benchmarks/results/codex-pr-metadata-2026-10-26/live-installed-runtime-rejection.json` (current untracked installed-runtime evidence)
43
+ - `ci/action-gate.test.js`
44
+ - `ci/mechanism-2aa-codex-action-gate-policy.test.js`
45
+ - `ci/mechanism-task-git-authorization.test.js`
46
+ - `docs/codex-action-gate.md`
47
+ - `docs/platform-capabilities.md`
48
+ - `hooks/scripts/action-gate.js`
49
+ - `plugins/harness-everything/hooks/scripts/action-gate.js`
50
+
51
+ The current uncommitted worktree delta is evidence-only: README status and installed-runtime provenance, `verification.md`, the copied report, and `live-installed-runtime-rejection.json`. The README now records core PASS and the independent review, while keeping candidate live-host UNCHECKED. Its linked `luna-review.md` copy still predates this final evidence adjudication and must be refreshed from this `/tmp` report before commit. No repository files were changed by this reviewer. Temporary snapshots and scripts/logs were created under `/tmp`; the two retained Luna scripts/logs were byte-compared with those files.
52
+
53
+ ## Findings and dispositions
54
+
55
+ ### [BLOCKER, resolved] Earlier optional hint hid a later required hint
56
+
57
+ - **Location:** `hooks/scripts/action-gate.js:380-392` @ `e160e00d265a2b427cdf6eb25783744470b0cb81`
58
+ - **Trigger:** Codex `PreToolUse` for exact `mcp__codex_apps__github__update_pull_request`, metadata input `{repository_full_name:"acme/repo",pr_number:376,body:"fixture"}`, top-level `actionGate:{required:false}`, and `workflowPlan.actionGate:{required:true}`.
59
+ - **Behavior → impact:** `routerActionGateHint` selected the first object. The new metadata branch saw `required:false`, returned `allow`/`deferred-to-host`, and bypassed an explicitly required gate.
60
+ - **Violates:** C3.
61
+ - **Witness:** Base `b733cade` blocked this mutation; `e160e00` exited 0 with empty stdout. Positive controls: plain metadata exited 0; a single required hint exited 2. The actual Codex PreToolUse stdin entrypoint reproduced the same outcomes.
62
+ - **Evidence tier:** executed/reproduced under Node 24.22.1.
63
+ - **Correction / regression:** `ff796c9` now prioritizes any supported `required:true` hint. The RED test from `1e77c26` failed 9 assertions on `e160e00`; the GREEN test passed. The retained test covers all four supported hint envelopes with conflicting optional hints.
64
+ - **Disposition:** resolved at `ff796c9`, rechecked at `c170a96`.
65
+
66
+ ### [MAJOR, resolved] Read/unknown action descriptors bypassed required gating and mixed-risk checks
67
+
68
+ - **Location:** `hooks/scripts/action-gate.js:156-159` @ `e160e00d265a2b427cdf6eb25783744470b0cb81`
69
+ - **Trigger:** exact Codex PR update with `tool_input` containing `state:"closed"` and `action_descriptor:{action:"read"}`, plus `workflowPlan.actionGate.required:true`.
70
+ - **Behavior → impact:** `structuredRule` returned early for a descriptor classified `safe`, before checking the required hint or the metadata allowlist. The hook returned allow with no audit; a mixed high-risk input escaped the intended metadata-only check.
71
+ - **Violates:** C2 and C3.
72
+ - **Witness:** Starting state: this behavior existed at base. Expected: block because `state` is an additional high-risk field and the workflow requires a gate. Actual: `allow`, exit 0, no decision record. Positive controls: replacing `read` with `delete` or removing the explicit descriptor blocks with exit 2.
73
+ - **Evidence tier:** executed across base, `e160e00`, and `ff796c9`; actual external reachability of an `action_descriptor` parameter depends on the active tool schema/adapter and was not established. The Codex PR connector schema recorded in the evidence does not list that input field.
74
+ - **Correction / regression:** `e9344de` normalizes read/unknown descriptor actions to `mutate` for exact Codex PR-update operations before the early safe branch. The RED test from `06a66c2` failed 11 assertions on `ff796c9`; GREEN passed. Final action/family cross-product and stdin smoke confirm `mutate`/`gated` audit provenance and rejection of mixed fields.
75
+ - **Disposition:** resolved for exact Codex PR update at `e9344de`, rechecked at `c170a96`. The pre-existing behavior for unrelated tools/hosts was not changed.
76
+
77
+ ### [MAJOR, resolved] Explicit shell family disguised an MCP PR update
78
+
79
+ - **Location:** `hooks/scripts/action-gate.js:156-159` @ `e9344de` (same early shell-family return in `e160e00`)
80
+ - **Trigger:** exact Codex PR update with `action_descriptor:{toolFamily:"shell",action:"delete"}` and otherwise metadata-only arguments.
81
+ - **Behavior → impact:** explicit descriptor family overrode the actual `mcp__...` tool identity; `structuredRule` returned at its shell branch without gating the `delete` action.
82
+ - **Violates:** C2, C3 and C4.
83
+ - **Witness:** Expected: a `delete` descriptor on a GitHub MCP update must be blocked and audited as MCP. Actual before the family fix: `allow`, exit 0, no record. Positive control: the same descriptor with `toolFamily:"mcp"` blocked with exit 2. The direct mechanism case was reproduced at the intermediate `e9344de` state.
84
+ - **Evidence tier:** executed at mechanism level; external reachability is subject to the same tool-schema boundary above.
85
+ - **Correction / regression:** `c170a96` derives the family from exact Codex PR tool identity, ignores a descriptor's family downgrade, and preserves `delete`/`publish`/`deploy`/`send` classifications. The RED test from `16f5e20` failed 14 assertions on `e9344de`; GREEN passed.
86
+ - **Disposition:** resolved at `c170a96`.
87
+
88
+ ### [MINOR, resolved in README; copied report refresh pending] README review status was stale
89
+
90
+ - **Location:** `benchmarks/results/codex-pr-metadata-2026-10-26/README.md` (uncommitted worktree delta)
91
+ - **Trigger:** The report and independent checks are now complete, while the README still says `Independent review | Pending Luna xhigh cold review`.
92
+ - **Behavior → impact:** The evidence index understates completed review status.
93
+ - **Violates:** C7 evidence-record accuracy.
94
+ - **Witness:** Starting state/input: README pending row plus completed `/tmp/luna-pr-metadata-review.md`. Expected: row updated to review result. Actual: pending text remains.
95
+ - **Evidence tier:** source-traced.
96
+ - **Minimal correction:** Update the status row with the final core review result and retain the separate full-regression/live-host boundaries.
97
+ - **Regression:** Negative: status remains pending after report is accepted; positive control: the same README correctly labels candidate live-host as UNCHECKED.
98
+ - **Disposition:** resolved in the current README, which now links the core PASS result. Refresh the copied `luna-review.md` so it does not retain the old pending statement; this is evidence-copy synchronization only, not a runtime blocker.
99
+
100
+ ## Independent verification
101
+
102
+ All local Node commands below explicitly used `/Users/daniel.chang/.nvm/versions/node/v24.22.1/bin` (`v24.22.1`).
103
+
104
+ | Check | Result / evidence |
105
+ | --- | --- |
106
+ | `node ci/action-gate.test.js` at `c170a96` | PASS, 0 failures |
107
+ | `node ci/mechanism-2aa-codex-action-gate-policy.test.js` at `c170a96` | PASS |
108
+ | `node ci/mechanism-task-git-authorization.test.js` at `c170a96` | PASS |
109
+ | `npm run test:plugin:openai` at `c170a96` | PASS; canonical/package parity and runtime checks |
110
+ | `npm run test:consistency` at `e160e00`; final `verify:all` at `c170a96` | PASS in both reviewed evidence runs |
111
+ | `npm run test:platform:compatibility` at `e160e00`; final `verify:all` at `c170a96` | PASS in both reviewed evidence runs |
112
+ | `npm run test:plugin:submission` at `e160e00`; final `verify:all` at `c170a96` | PASS in both reviewed evidence runs |
113
+ | Original RED: base archive `b733cade` + `db6c29b:ci/action-gate.test.js` | 12 expected failures; preceding baseline/dependency controls passed |
114
+ | Required-hint RED: `e160e00` archive + `1e77c26:ci/action-gate.test.js` | 9 expected failures |
115
+ | Descriptor RED: `ff796c9` archive + `06a66c2:ci/action-gate.test.js` | 11 expected failures |
116
+ | Family RED: `e9344de` archive + `16f5e20:ci/action-gate.test.js` | 14 expected failures |
117
+ | Final GREEN: `node ci/action-gate.test.js` at `c170a96` | PASS, 0 failures |
118
+ | Independent action × family × descriptor-envelope × required-hint/unsafe-field cross-product | PASS: 2,709 cases, 4,729 assertions, 0 failures; `/tmp/luna-action-family-cross-product-final.log` |
119
+ | Independent Codex PreToolUse stdin smoke | PASS: 7 subprocess cases; `/tmp/luna-codex-action-gate-prehook-smoke-final.log` |
120
+ | Base-versus-candidate controls: create, merge, close, delete, force-push, publish, deploy, send | Same outcomes; create remained host-deferred/mutate, all risky controls blocked |
121
+ | Original rejection hash provenance | PASS: parsed the cited transcript `CommandExecution.aggregated_output` (1,840 chars), reconstructed sorted compact JSON for repository/pr/body, SHA-256 matched audit `b9bda711…c87b` |
122
+ | Full `npm run verify:all` at final core SHA | PASS: exit 0, 13 PASS / 0 FAIL / 3 UNCHECKED (local Node 22 lanes); log SHA-256 `630159501b19d1d0178683262f0bfe7c0ec9cacb29a336057bb95094481129f4` |
123
+ | Candidate live-host behavior | UNCHECKED. The retained `live-installed-runtime-rejection.json` is an old installed runtime rejection, not candidate evidence. |
124
+
125
+ ## Contract review summary
126
+
127
+ - C1/C2: exact Codex operation plus strict parameter allowlist; additional fields including null remain gated; metadata descriptor stays `mutate`/`gated`; high-risk action descriptors remain gated.
128
+ - C3: any `required:true` hint across supported envelopes wins; audit preserves the required hint.
129
+ - C4: the prehook emits no Codex `permissionDecision` allow/ask for the deferred metadata call. Host task scope, Codex permissions, and GitHub authorization remain the execution authorities.
130
+ - C5: create-PR behavior and risky controls matched the base; regression tests retain the explicit required-gate case.
131
+ - C6: canonical/plugin byte parity, redacted audit, exact payload hash, execution success/failure, rejection, and integrity behavior passed mechanism tests. No other Host was widened.
132
+ - C7: RED/GREEN was independently reproduced at each correction boundary; no package/mechanism result is called a candidate live-host PASS.
133
+ - C8: reviewed changes contain no #376 governance implementation, #341 E1 credit, #320 authorization expansion, auto-merge, or gate bypass.
134
+
135
+ ## Final recommendation
136
+
137
+ No open runtime/code blocker remains at `c170a96`; the three code findings were fixed and rechecked. The final Node 24 full suite passed, with only the three explicit Node 22 lanes UNCHECKED. Candidate live-host behavior remains UNCHECKED. The README review-status minor is fixed in the current README; refresh the copied report before committing the evidence package.
138
+
139
+ ## Final evidence-only adjudication
140
+
141
+ - Raw log `/tmp/pr-metadata-verify-final.log`: independently hashed to `630159501b19d1d0178683262f0bfe7c0ec9cacb29a336057bb95094481129f4` (matches `verification.md`). Header pins core `c170a96cf856295200d2d1a62c15a552c3cb2b37`, Node `v24.22.1`, Darwin, default full gate set. Process exit is `0`.
142
+ - Summary verified from the raw log: 13 PASS, 0 FAIL, 3 UNCHECKED. The three unchecked lanes are Node 22 self-regression smoke, installer roundtrip smoke, and `npm ci` install; optional Waza readiness passed.
143
+ - `verification.md` matches the raw log hash, header, per-gate results, and summary.
144
+ - Current README closes the earlier pending-review row, reports the full-suite summary, preserves the `gpt-6-luna`/`xhigh` routing request with no host-issued runtime attestation, and keeps candidate live-host status UNCHECKED. It does not claim final-head CI is all green; its PR workflow reference is explicitly the initial run and says final-head status must be checked separately.
145
+ - No runtime or plugin path changed after frozen core `c170a96`; the post-core commit `a2edf4e` and worktree delta are evidence-only. The old installed runtime rejection audit points to installed runtime `0.42.0-f51078676b56`; it is not candidate live proof.
146
+ - Candidate live-host execution remains UNCHECKED. No new destructive remote operation was attempted by this reviewer.
147
+ - The copied `luna-review.md` currently contains the pre-final pending text and must be recopied from this report before the evidence commit.
148
+
149
+ Skipped: no Node 22 lane rerun and no candidate live-host execution. Risk: those evidence boundaries remain unverified; final core Node 24 gates passed.
150
+
151
+ STATUS: DONE
@@ -0,0 +1,31 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "toolName": "mcp__codex_apps__github__update_pull_request",
4
+ "toolUseId": "exec-8e76e1be-e5a3-493d-807b-2ad6cdbc7c31",
5
+ "commandHash": "b9bda7116fb01c045edd71a6b4fc3091c0ab707e0b797f1b4efca6e7a4edc87b",
6
+ "actionDescriptor": {
7
+ "schemaVersion": 1,
8
+ "toolFamily": "mcp",
9
+ "toolName": "mcp__codex_apps__github__update_pull_request",
10
+ "action": "mutate",
11
+ "resource": "dyphn1/Harness-everything",
12
+ "payloadHash": "b9bda7116fb01c045edd71a6b4fc3091c0ab707e0b797f1b4efca6e7a4edc87b",
13
+ "classification": "gated",
14
+ "reasonCodes": [
15
+ "tool-identity-inference"
16
+ ]
17
+ },
18
+ "matchedRule": "structured-mutate",
19
+ "ruleReason": "Structured mutate action requires pre-action authorization.",
20
+ "disposition": "rejected",
21
+ "host": "codex",
22
+ "permissionMode": "bypassPermissions",
23
+ "gatePolicy": "defer-to-host",
24
+ "routerActionGate": null,
25
+ "ruleTableSource": "/Users/daniel.chang/.codex/harness-everything/compat-hooks/runtime/0.42.0-f51078676b56/hooks/scripts/action-gate-rules.json",
26
+ "degradedRuleTable": false,
27
+ "degradationReason": null,
28
+ "createdAt": "2026-10-26T01:12:15.045Z",
29
+ "updatedAt": "2026-10-26T01:12:15.045Z",
30
+ "rejectionReason": "host-ask-decision-unverified-or-unsupported"
31
+ }
@@ -0,0 +1,158 @@
1
+ === Issue #85 Phase 5 — Pre-action gate ===
2
+ PASS production action-gate rule table loads without fallback
3
+ PASS production rule table is non-empty and keeps the destructive baseline
4
+ PASS rule table contains git-force-push
5
+ PASS rule table contains git-reset-hard
6
+ PASS rule table contains git-clean-force-delete
7
+ PASS rule table contains recursive-delete
8
+ PASS rule table contains powershell-recursive-force-delete
9
+ PASS rule table contains sql-destructive-ddl
10
+ PASS rule table contains package-publish
11
+ PASS rule table contains github-release-create
12
+ PASS rule table contains production-deploy
13
+ PASS Claude force-push defers to the host permission flow without forcing a prompt
14
+ PASS deferred decision still names the matched rule
15
+ PASS matched Claude action is audited as deferred-to-host
16
+ PASS audit records matched rule
17
+ PASS audit hashes the exact command payload
18
+ PASS always-ask policy restores the forced Claude prompt
19
+ PASS ask decision uses Claude PreToolUse hookSpecificOutput
20
+ PASS ask reason names the matched rule
21
+ PASS always-ask action is audited as pending-approval
22
+ PASS git status passes untouched
23
+ PASS safe unmatched command creates no gate audit record
24
+ PASS permission_mode=default defers to the host without a forced prompt
25
+ PASS audit records permission_mode=default
26
+ PASS permission_mode=acceptEdits defers to the host without a forced prompt
27
+ PASS audit records permission_mode=acceptEdits
28
+ PASS permission_mode=plan defers to the host without a forced prompt
29
+ PASS audit records permission_mode=plan
30
+ PASS permission_mode=auto defers to the host without a forced prompt
31
+ PASS audit records permission_mode=auto
32
+ PASS permission_mode=dontAsk defers to the host without a forced prompt
33
+ PASS audit records permission_mode=dontAsk
34
+ PASS permission_mode=bypassPermissions defers to the host without a forced prompt
35
+ PASS audit records permission_mode=bypassPermissions
36
+ PASS permission_mode=missing defers to the host without a forced prompt
37
+ PASS audit records permission_mode=missing
38
+ PASS command classification gates destructive action even when router hint says not required
39
+ PASS router actionGate hint is recorded without controlling enforcement
40
+ PASS safe command is not gated solely because prompt router predicted risk
41
+ PASS structured MCP delete is gated before execution
42
+ PASS audit retains normalized structured action identity
43
+ PASS structured action audit binds to exact payload hash
44
+ PASS structured action audit does not persist raw secret arguments
45
+ PASS read-only MCP fixture passes without a false gate
46
+ PASS obvious structured mutation is classified from tool identity
47
+ PASS non-shell local-function destructive fixture uses the same structured gate
48
+ PASS unknown structured action fails closed when workflow requires a gate
49
+ PASS unknown structured action is not fabricated as destructive without a gate requirement
50
+ PASS changed structured payload cannot reuse a prior approval/audit decision
51
+ PASS PowerShell recursive force delete outside scratch is gated
52
+ PASS PowerShell recursive force delete inside session scratch is exempt
53
+ PASS rm -rf outside scratch is gated
54
+ PASS rm -rf inside OS temp is exempt
55
+ PASS git reset --hard HEAD matches git-reset-hard
56
+ PASS git clean -fd matches git-clean-force-delete
57
+ PASS psql -c "DROP TABLE users" matches sql-destructive-ddl
58
+ PASS npm publish matches package-publish
59
+ PASS gh release create v1.2.3 matches github-release-create
60
+ PASS npm run deploy matches production-deploy
61
+ PASS host without verified ask-style decision blocks with exit 2
62
+ PASS non-ask host block reason names the matched rule
63
+ PASS non-ask host block is audited as rejected
64
+ PASS internal action-gate error on Claude defers to the host instead of allowing or forcing a prompt
65
+ PASS internal error is shown to the user as a systemMessage without a permission decision
66
+ PASS internal error on Claude is audited as deferred-to-host
67
+ PASS internal action-gate error under always-ask fails closed to ask
68
+ PASS internal error on host without ask fails closed to block
69
+ PASS missing/invalid rule table visibly falls back to built-in defaults
70
+ PASS built-in fallback still classifies and audits destructive action
71
+ PASS fallback degradation is shown to the user as a systemMessage
72
+ PASS valid empty rule table does not silently activate built-in defaults
73
+ PASS empty-table mutation control disables detection, proving production non-empty assertion is meaningful
74
+ PASS null-prototype serialization preserves an own __proto__ key
75
+ PASS own __proto__ key changes the full-input digest
76
+ PASS PostToolUse closes a deferred payload as executed
77
+ PASS executed audit keeps exact approved payload hash
78
+ PASS PostToolUseFailure records attempted execution without pretending success
79
+ PASS post-tool payload mismatch is never accepted as the approved command
80
+ PASS Stop closes unexecuted deferred and pending payloads
81
+ PASS unexecuted deferred payload is audited as rejected
82
+ PASS unexecuted always-ask approval is audited as rejected
83
+ PASS hook process returns no decision for a matched command under the default policy
84
+ PASS hook process audits the deferred command with its permission mode
85
+ PASS HARNESS_ACTION_GATE_POLICY=always-ask makes the hook process emit ask
86
+ PASS Claude hook manifest wires action-gate to shell and MCP pre-action surfaces
87
+ PASS Claude hook manifest audits successful tool execution
88
+ PASS Claude hook manifest audits failed tool execution
89
+ PASS Claude hook manifest closes unresolved approvals on Stop
90
+ PASS OpenAI plugin preserves the attribution-aware Codex shell action-gate adapter
91
+ PASS OpenAI plugin packages an isolated structured MCP pre-action adapter without widening unrelated hooks
92
+ PASS OpenAI plugin packages an isolated structured MCP post-action audit adapter
93
+ PASS Codex plugin does not declare unsupported PostToolUseFailure lifecycle event
94
+ PASS Codex plugin infers action-gate outcome from supported PostToolUse
95
+ PASS Codex PostToolUse maps zero exit code to success
96
+ PASS Codex PostToolUse maps non-zero exit code to failure
97
+ PASS Codex PostToolUse conservatively recognizes failure stderr without exit code
98
+ PASS OpenAI plugin closes pending approvals at Stop
99
+ PASS canonical and plugin action-gate rule tables are byte-identical
100
+ PASS OpenAI plugin packages action-gate runtime
101
+ FAIL update_pull_request body defers without a permission decision
102
+ PASS metadata remains a non-safe mutation
103
+ FAIL update_pull_request title defers without a permission decision
104
+ PASS metadata remains a non-safe mutation
105
+ FAIL update_pull_request title,body defers without a permission decision
106
+ PASS metadata remains a non-safe mutation
107
+ FAIL mcp__github__update_pull_request body defers without a permission decision
108
+ PASS metadata remains a non-safe mutation
109
+ FAIL mcp__github__update_pull_request title defers without a permission decision
110
+ PASS metadata remains a non-safe mutation
111
+ FAIL mcp__github__update_pull_request title,body defers without a permission decision
112
+ PASS metadata remains a non-safe mutation
113
+ FAIL mcp__codex_apps__github__update_pull_request body defers without a permission decision
114
+ PASS metadata remains a non-safe mutation
115
+ FAIL mcp__codex_apps__github__update_pull_request title defers without a permission decision
116
+ PASS metadata remains a non-safe mutation
117
+ FAIL mcp__codex_apps__github__update_pull_request title,body defers without a permission decision
118
+ PASS metadata remains a non-safe mutation
119
+ FAIL mcp__codex_apps__github_update_pull_request body defers without a permission decision
120
+ PASS metadata remains a non-safe mutation
121
+ FAIL mcp__codex_apps__github_update_pull_request title defers without a permission decision
122
+ PASS metadata remains a non-safe mutation
123
+ FAIL mcp__codex_apps__github_update_pull_request title,body defers without a permission decision
124
+ PASS metadata remains a non-safe mutation
125
+ PASS metadata with {"state":"closed"} remains gated
126
+ PASS metadata with {"state":"open"} remains gated
127
+ PASS metadata with {"state":null} remains gated
128
+ PASS metadata with {"base_branch":"other"} remains gated
129
+ PASS metadata with {"maintainer_can_modify":false} remains gated
130
+ PASS metadata with {"maintainer_can_modify":null} remains gated
131
+ PASS metadata with {"unknown":true} remains gated
132
+ PASS metadata with {"title":"mixed","state":"closed"} remains gated
133
+ PASS metadata with {"draft":true} remains gated
134
+ PASS metadata with {"base":"other"} remains gated
135
+ PASS metadata with {"action_descriptor":{"action":"delete"}} remains gated
136
+ PASS missing or malformed metadata remains gated
137
+ PASS missing or malformed metadata remains gated
138
+ PASS missing or malformed metadata remains gated
139
+ PASS missing or malformed metadata remains gated
140
+ PASS missing or malformed metadata remains gated
141
+ PASS missing or malformed metadata remains gated
142
+ PASS missing or malformed metadata remains gated
143
+ PASS missing or malformed metadata remains gated
144
+ PASS mcp__demo__update_pull_requests receives no metadata exception
145
+ PASS mcp__demo__foo_update_pull_request receives no metadata exception
146
+ PASS mcp__demo__update_pull_request_and_delete receives no metadata exception
147
+ PASS mcp__codex_apps__github_update_pull_request_extra receives no metadata exception
148
+ PASS mcp__demo__merge_pull_request receives no metadata exception
149
+ PASS mcp__demo__close_pull_request receives no metadata exception
150
+ PASS claude retains existing mutation rule
151
+ PASS opencode retains existing mutation rule
152
+ PASS unknown retains existing mutation rule
153
+ PASS explicit required metadata gate cannot be bypassed
154
+ PASS explicit required metadata gate cannot be bypassed
155
+ PASS explicit required metadata gate cannot be bypassed
156
+ PASS explicit required metadata gate cannot be bypassed
157
+
158
+ FAIL: action-gate phase 5 (12 failures)
@@ -0,0 +1,192 @@
1
+ === Issue #85 Phase 5 — Pre-action gate ===
2
+ PASS production action-gate rule table loads without fallback
3
+ PASS production rule table is non-empty and keeps the destructive baseline
4
+ PASS rule table contains git-force-push
5
+ PASS rule table contains git-reset-hard
6
+ PASS rule table contains git-clean-force-delete
7
+ PASS rule table contains recursive-delete
8
+ PASS rule table contains powershell-recursive-force-delete
9
+ PASS rule table contains sql-destructive-ddl
10
+ PASS rule table contains package-publish
11
+ PASS rule table contains github-release-create
12
+ PASS rule table contains production-deploy
13
+ PASS Claude force-push defers to the host permission flow without forcing a prompt
14
+ PASS deferred decision still names the matched rule
15
+ PASS matched Claude action is audited as deferred-to-host
16
+ PASS audit records matched rule
17
+ PASS audit hashes the exact command payload
18
+ PASS always-ask policy restores the forced Claude prompt
19
+ PASS ask decision uses Claude PreToolUse hookSpecificOutput
20
+ PASS ask reason names the matched rule
21
+ PASS always-ask action is audited as pending-approval
22
+ PASS git status passes untouched
23
+ PASS safe unmatched command creates no gate audit record
24
+ PASS permission_mode=default defers to the host without a forced prompt
25
+ PASS audit records permission_mode=default
26
+ PASS permission_mode=acceptEdits defers to the host without a forced prompt
27
+ PASS audit records permission_mode=acceptEdits
28
+ PASS permission_mode=plan defers to the host without a forced prompt
29
+ PASS audit records permission_mode=plan
30
+ PASS permission_mode=auto defers to the host without a forced prompt
31
+ PASS audit records permission_mode=auto
32
+ PASS permission_mode=dontAsk defers to the host without a forced prompt
33
+ PASS audit records permission_mode=dontAsk
34
+ PASS permission_mode=bypassPermissions defers to the host without a forced prompt
35
+ PASS audit records permission_mode=bypassPermissions
36
+ PASS permission_mode=missing defers to the host without a forced prompt
37
+ PASS audit records permission_mode=missing
38
+ PASS command classification gates destructive action even when router hint says not required
39
+ PASS router actionGate hint is recorded without controlling enforcement
40
+ PASS safe command is not gated solely because prompt router predicted risk
41
+ PASS structured MCP delete is gated before execution
42
+ PASS audit retains normalized structured action identity
43
+ PASS structured action audit binds to exact payload hash
44
+ PASS structured action audit does not persist raw secret arguments
45
+ PASS read-only MCP fixture passes without a false gate
46
+ PASS obvious structured mutation is classified from tool identity
47
+ PASS non-shell local-function destructive fixture uses the same structured gate
48
+ PASS unknown structured action fails closed when workflow requires a gate
49
+ PASS unknown structured action is not fabricated as destructive without a gate requirement
50
+ PASS changed structured payload cannot reuse a prior approval/audit decision
51
+ PASS PowerShell recursive force delete outside scratch is gated
52
+ PASS PowerShell recursive force delete inside session scratch is exempt
53
+ PASS rm -rf outside scratch is gated
54
+ PASS rm -rf inside OS temp is exempt
55
+ PASS git reset --hard HEAD matches git-reset-hard
56
+ PASS git clean -fd matches git-clean-force-delete
57
+ PASS psql -c "DROP TABLE users" matches sql-destructive-ddl
58
+ PASS npm publish matches package-publish
59
+ PASS gh release create v1.2.3 matches github-release-create
60
+ PASS npm run deploy matches production-deploy
61
+ PASS host without verified ask-style decision blocks with exit 2
62
+ PASS non-ask host block reason names the matched rule
63
+ PASS non-ask host block is audited as rejected
64
+ PASS internal action-gate error on Claude defers to the host instead of allowing or forcing a prompt
65
+ PASS internal error is shown to the user as a systemMessage without a permission decision
66
+ PASS internal error on Claude is audited as deferred-to-host
67
+ PASS internal action-gate error under always-ask fails closed to ask
68
+ PASS internal error on host without ask fails closed to block
69
+ PASS missing/invalid rule table visibly falls back to built-in defaults
70
+ PASS built-in fallback still classifies and audits destructive action
71
+ PASS fallback degradation is shown to the user as a systemMessage
72
+ PASS valid empty rule table does not silently activate built-in defaults
73
+ PASS empty-table mutation control disables detection, proving production non-empty assertion is meaningful
74
+ PASS null-prototype serialization preserves an own __proto__ key
75
+ PASS own __proto__ key changes the full-input digest
76
+ PASS PostToolUse closes a deferred payload as executed
77
+ PASS executed audit keeps exact approved payload hash
78
+ PASS PostToolUseFailure records attempted execution without pretending success
79
+ PASS post-tool payload mismatch is never accepted as the approved command
80
+ PASS Stop closes unexecuted deferred and pending payloads
81
+ PASS unexecuted deferred payload is audited as rejected
82
+ PASS unexecuted always-ask approval is audited as rejected
83
+ PASS hook process returns no decision for a matched command under the default policy
84
+ PASS hook process audits the deferred command with its permission mode
85
+ PASS HARNESS_ACTION_GATE_POLICY=always-ask makes the hook process emit ask
86
+ PASS Claude hook manifest wires action-gate to shell and MCP pre-action surfaces
87
+ PASS Claude hook manifest audits successful tool execution
88
+ PASS Claude hook manifest audits failed tool execution
89
+ PASS Claude hook manifest closes unresolved approvals on Stop
90
+ PASS OpenAI plugin preserves the attribution-aware Codex shell action-gate adapter
91
+ PASS OpenAI plugin packages an isolated structured MCP pre-action adapter without widening unrelated hooks
92
+ PASS OpenAI plugin packages an isolated structured MCP post-action audit adapter
93
+ PASS Codex plugin does not declare unsupported PostToolUseFailure lifecycle event
94
+ PASS Codex plugin infers action-gate outcome from supported PostToolUse
95
+ PASS Codex PostToolUse maps zero exit code to success
96
+ PASS Codex PostToolUse maps non-zero exit code to failure
97
+ PASS Codex PostToolUse conservatively recognizes failure stderr without exit code
98
+ PASS OpenAI plugin closes pending approvals at Stop
99
+ PASS canonical and plugin action-gate rule tables are byte-identical
100
+ PASS OpenAI plugin packages action-gate runtime
101
+ PASS update_pull_request body defers without a permission decision
102
+ PASS metadata remains a non-safe mutation
103
+ PASS update_pull_request title defers without a permission decision
104
+ PASS metadata remains a non-safe mutation
105
+ PASS update_pull_request title,body defers without a permission decision
106
+ PASS metadata remains a non-safe mutation
107
+ PASS mcp__github__update_pull_request body defers without a permission decision
108
+ PASS metadata remains a non-safe mutation
109
+ PASS mcp__github__update_pull_request title defers without a permission decision
110
+ PASS metadata remains a non-safe mutation
111
+ PASS mcp__github__update_pull_request title,body defers without a permission decision
112
+ PASS metadata remains a non-safe mutation
113
+ PASS mcp__codex_apps__github__update_pull_request body defers without a permission decision
114
+ PASS metadata remains a non-safe mutation
115
+ PASS mcp__codex_apps__github__update_pull_request title defers without a permission decision
116
+ PASS metadata remains a non-safe mutation
117
+ PASS mcp__codex_apps__github__update_pull_request title,body defers without a permission decision
118
+ PASS metadata remains a non-safe mutation
119
+ PASS mcp__codex_apps__github_update_pull_request body defers without a permission decision
120
+ PASS metadata remains a non-safe mutation
121
+ PASS mcp__codex_apps__github_update_pull_request title defers without a permission decision
122
+ PASS metadata remains a non-safe mutation
123
+ PASS mcp__codex_apps__github_update_pull_request title,body defers without a permission decision
124
+ PASS metadata remains a non-safe mutation
125
+ PASS provider-neutral selectors support metadata updates
126
+ PASS provider-neutral selectors support metadata updates
127
+ PASS own __proto__ field cannot escape the argument allowlist
128
+ PASS explicit higher-risk action cannot inherit metadata deferral
129
+ PASS metadata with {"state":"closed"} remains gated
130
+ PASS metadata with {"state":"open"} remains gated
131
+ PASS metadata with {"state":null} remains gated
132
+ PASS metadata with {"base_branch":"other"} remains gated
133
+ PASS metadata with {"maintainer_can_modify":false} remains gated
134
+ PASS metadata with {"maintainer_can_modify":null} remains gated
135
+ PASS metadata with {"unknown":true} remains gated
136
+ PASS metadata with {"title":"mixed","state":"closed"} remains gated
137
+ PASS metadata with {"draft":true} remains gated
138
+ PASS metadata with {"base":"other"} remains gated
139
+ PASS metadata with {"action_descriptor":{"action":"delete"}} remains gated
140
+ PASS missing or malformed metadata remains gated
141
+ PASS missing or malformed metadata remains gated
142
+ PASS missing or malformed metadata remains gated
143
+ PASS missing or malformed metadata remains gated
144
+ PASS missing or malformed metadata remains gated
145
+ PASS missing or malformed metadata remains gated
146
+ PASS missing or malformed metadata remains gated
147
+ PASS missing or malformed metadata remains gated
148
+ PASS mcp__demo__update_pull_requests receives no metadata exception
149
+ PASS mcp__demo__foo_update_pull_request receives no metadata exception
150
+ PASS mcp__demo__update_pull_request_and_delete receives no metadata exception
151
+ PASS mcp__codex_apps__github_update_pull_request_extra receives no metadata exception
152
+ PASS mcp__demo__merge_pull_request receives no metadata exception
153
+ PASS mcp__demo__close_pull_request receives no metadata exception
154
+ PASS claude retains existing mutation rule
155
+ PASS opencode retains existing mutation rule
156
+ PASS unknown retains existing mutation rule
157
+ PASS explicit required metadata gate cannot be bypassed
158
+ PASS explicit required metadata gate cannot be bypassed
159
+ PASS explicit required metadata gate cannot be bypassed
160
+ PASS explicit required metadata gate cannot be bypassed
161
+ PASS known Codex PR mutation cannot be downgraded to read
162
+ PASS downgrade refusal remains an audited mutation
163
+ PASS known Codex PR mutation cannot be downgraded to read
164
+ PASS downgrade refusal remains an audited mutation
165
+ PASS known Codex PR mutation cannot be downgraded to read
166
+ PASS downgrade refusal remains an audited mutation
167
+ PASS input read descriptor cannot hide a required PR mutation gate
168
+ PASS known Codex PR mutation cannot be downgraded to unknown
169
+ PASS downgrade refusal remains an audited mutation
170
+ PASS known Codex PR mutation cannot be downgraded to unknown
171
+ PASS downgrade refusal remains an audited mutation
172
+ PASS known Codex PR mutation cannot be downgraded to unknown
173
+ PASS downgrade refusal remains an audited mutation
174
+ PASS input unknown descriptor cannot hide a required PR mutation gate
175
+ PASS provider namespace read token cannot downgrade exact PR mutation
176
+ PASS claude explicit descriptor behavior remains unchanged
177
+ PASS opencode explicit descriptor behavior remains unchanged
178
+ PASS unknown explicit descriptor behavior remains unchanged
179
+ PASS required hint envelope 0 wins over optional envelopes
180
+ PASS audit retains required hint instead of a conflicting optional hint
181
+ PASS PR creation still honors the documented explicit required gate
182
+ PASS required hint envelope 1 wins over optional envelopes
183
+ PASS audit retains required hint instead of a conflicting optional hint
184
+ PASS PR creation still honors the documented explicit required gate
185
+ PASS required hint envelope 2 wins over optional envelopes
186
+ PASS audit retains required hint instead of a conflicting optional hint
187
+ PASS PR creation still honors the documented explicit required gate
188
+ PASS required hint envelope 3 wins over optional envelopes
189
+ PASS audit retains required hint instead of a conflicting optional hint
190
+ PASS PR creation still honors the documented explicit required gate
191
+
192
+ PASS: action-gate phase 5 (0 failures)