codex-workflow-v2 2.0.0-beta.12.10 → 2.0.0-beta.12.12

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 (37) hide show
  1. package/README.md +6 -4
  2. package/dist/src/alpha6/mechanical-feasibility.js +28 -12
  3. package/dist/src/alpha6/mechanical-feasibility.js.map +1 -1
  4. package/dist/src/alpha6/npm-check-contract.d.ts +11 -0
  5. package/dist/src/alpha6/npm-check-contract.js +36 -0
  6. package/dist/src/alpha6/npm-check-contract.js.map +1 -0
  7. package/dist/src/alpha6/plan-integrity.js +82 -26
  8. package/dist/src/alpha6/plan-integrity.js.map +1 -1
  9. package/dist/src/alpha6/remediation.js +88 -40
  10. package/dist/src/alpha6/remediation.js.map +1 -1
  11. package/dist/src/cli.js +26 -0
  12. package/dist/src/cli.js.map +1 -1
  13. package/dist/src/contracts.d.ts +37 -3
  14. package/dist/src/dependency-provenance.d.ts +18 -2
  15. package/dist/src/dependency-provenance.js +152 -11
  16. package/dist/src/dependency-provenance.js.map +1 -1
  17. package/dist/src/lifecycle/corrective-replan.js +1 -1
  18. package/dist/src/lifecycle/corrective-replan.js.map +1 -1
  19. package/dist/src/version.d.ts +1 -1
  20. package/dist/src/version.js +1 -1
  21. package/dist/src/workflow.d.ts +3 -0
  22. package/dist/src/workflow.js +315 -15
  23. package/dist/src/workflow.js.map +1 -1
  24. package/docs/delegated-approval.md +1 -1
  25. package/docs/pdf/codex-workflow-v2-architecture-ru.pdf +0 -0
  26. package/docs/pdf/codex-workflow-v2-chat-only-guide-ru.pdf +0 -0
  27. package/docs/pdf/codex-workflow-v2-technical-reference-ru.pdf +0 -0
  28. package/docs/pdf/sources/codex-workflow-v2-architecture-ru.md +22 -6
  29. package/docs/pdf/sources/codex-workflow-v2-chat-only-guide-ru.md +25 -8
  30. package/docs/pdf/sources/codex-workflow-v2-technical-reference-ru.md +45 -11
  31. package/docs/release.md +3 -2
  32. package/docs/updating-existing-project.md +35 -2
  33. package/docs/validation-report.md +119 -90
  34. package/package.json +1 -1
  35. package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +10 -0
  36. package/schemas/corrective-decision-event.schema.json +57 -10
  37. package/schemas/task.schema.json +23 -0
@@ -1,105 +1,134 @@
1
- # V2 beta.12.10 Validation Report
1
+ # V2 beta.12.12 Validation Report
2
2
 
3
- Release candidate `2.0.0-beta.12.10` was validated on 2026-08-31 (Europe/Moscow) with
3
+ Release candidate `2.0.0-beta.12.12` was validated on 2026-08-31 (Europe/Moscow) with
4
4
  Node.js 24.17.0.
5
5
 
6
6
  ## Automated release evidence
7
7
 
8
- - `npm ci` completed from the exact lockfile with 0 reported vulnerabilities.
9
- - `npm run validate` passed typecheck and `344/344` sequential tests with no failures, skips,
10
- cancellations, or todos in 2,087,253.659208 ms.
11
- - `npm run test:signal-remediation-e2e` passed the focused Signal-shaped end-to-end scenario.
12
- The test starts from an active Milestone whose required Task has a current `stop-escalate` Plan
13
- Risk Audit, materializes one audited upstream remediation Task, completes its Plan/audit/C1/Step/
14
- review/accept/merge lifecycle, replans the original Task, and completes a later Step there.
15
- - Negative coverage rejects a non-exact predecessor frontier, duplicate remediation, stale revisions,
16
- non-required or non-active Milestone posture, topology drift, reused audit evidence, and ordinary
17
- standalone/post-execution `stop-escalate` cases that must keep the existing `task plan-set` route.
18
- - The complete lifecycle inventory names `milestone remediation-materialize` and
19
- `WorkflowService.materializeAuditedRemediationTask`; read-only purity, transaction rollback/
20
- roll-forward, concurrent writers, credentials, Core receipts and prior Signal compatibility tests
21
- all passed.
22
- - Package dry-run produced `codex-workflow-v2-2.0.0-beta.12.10.tgz` with 278 files, 1,050,219 bytes
23
- packed and 4,196,113 bytes unpacked. The broad `docs` package allowlist was narrowed so the
24
- repository-local `docs/quality` observation journal cannot enter the tarball. The first invocation
25
- encountered a root-owned user npm cache (`EPERM`); the exact retry used an isolated temporary cache.
26
- - `npm run smoke:downstream` built and installed the tarball in a disposable consumer project and
8
+ - `npm ci` completed from the exact lockfile; the audit reported zero vulnerabilities.
9
+ - The first full `npm run validate` run found two compatibility regressions in the pre-existing
10
+ corrective-recovery suite. Plan-integrity preflight was made non-authoritative while a repairable
11
+ legacy remediation-history defect exists, and an old test was aligned with the intentional
12
+ corrective-yield-before-context-refresh priority. Both focused reproductions then passed.
13
+ - The mandatory second `npm run validate` passed typecheck and `348/348` sequential tests with no
14
+ failures, skips, cancellations, or todos in 2,149,397.21 ms.
15
+ - The full suite includes the beta.12.12 selector-contract E2E: four sequential failures of one
16
+ guarded Step, dependency-only update transport, exact compatibility registration, automatic
17
+ package-only Knowledge refresh, Plan-integrity recovery, corrective yield, and fresh corrective
18
+ replan without losing the Step worktree.
19
+ - `npm run test:signal-remediation-e2e` passed both focused scenarios (`2/2`). It still proves the
20
+ audited upstream-remediation route through a later Step and rejects unrelated Knowledge drift.
21
+ - Package dry-run produced `codex-workflow-v2-2.0.0-beta.12.12.tgz` with 281 files, 1,070,498 bytes
22
+ packed and 4,283,430 bytes unpacked. The tarball SHA-1 is
23
+ `349bcd371b09a2467496057166c78d879e99e937`. The first invocation encountered a root-owned user npm
24
+ cache (`EPERM`); the exact retry passed with an isolated temporary cache and no system permission
25
+ changes.
26
+ - `npm run smoke:downstream` built and installed that tarball in a disposable consumer project and
27
27
  returned `ok=true`. The sandboxed attempt could not resolve npm (`ENOTFOUND`); the same command
28
- passed with network access.
29
- - `npm run plugin:check` passed for bundled gateway
30
- `0.1.0+codex.20260830183000`.
31
- - `npm run docs:pdf:check` reported an empty stale set and exact beta.12.10 package binding.
32
- - `RELEASE_TAG=v2.0.0-beta.12.10 npm run release:check` and `git diff --check` passed after this
33
- report and the exact package allowlist were recorded.
34
-
35
- ## Root cause corrected by beta.12.10
36
-
37
- An active Milestone could reach a genuine pre-execution dead end when a required Task's current Plan
38
- Risk Audit truthfully returned `stop-escalate` because an upstream capability did not exist. The old
39
- choices were insufficient: replanning the same Task could not manufacture the missing capability,
40
- while the generic scope-change path required a separate human approval and permitted a much wider
41
- semantic change than the evidence justified.
42
-
43
- The problem was missing bounded topology authority, not an insufficient number of implementation or
44
- review attempts. Repeating the blocked Task could only reproduce the same unmet prerequisite.
28
+ passed with approved network access.
29
+ - `npm run plugin:check` passed for bundled gateway `0.1.0+codex.20260830183000`. The installed
30
+ Codex CLI exposes no `plugin validate` subcommand, so the repository validator plus successful
31
+ packaged downstream installation are the available plugin release evidence.
32
+ - `npm run docs:pdf:check` reported an empty stale set and exact beta.12.12 package binding.
33
+ - `RELEASE_TAG=v2.0.0-beta.12.12 npm run release:check` and `git diff --check` passed.
34
+ - `node scripts/validate-lifecycle-transcript.mjs --file
35
+ tests/fixtures/lifecycle-transcripts/valid-normal-sequence.jsonl` passed with four checked events;
36
+ the full validator suite also passed all positive and negative transcript fixtures.
37
+
38
+ ## Root cause corrected
39
+
40
+ Signal Task `TASK-01M1B79C660YMNSRRZ236NTR1T` reached revision 12 with four recorded
41
+ `checks-failed` events. The approved Step check was `npm run validate:affected`, while the existing
42
+ repository script delegates to `tools/validation/run.mjs affected`, whose public contract requires at
43
+ least one of `--base`, `--head`, or `--files`. The command therefore failed before validation and could
44
+ not become successful through another implementation attempt.
45
+
46
+ Two Workflow gaps made the state non-recoverable:
47
+
48
+ 1. mechanical feasibility proved that the npm script existed but did not verify the mandatory
49
+ selector contract of the repository-owned runner; and
50
+ 2. bounded Plan-integrity recovery recognized only the first failed attempt with no corrective
51
+ decision, so it could not convert the already accumulated four-event history into a fresh Plan.
52
+
53
+ The primary defect was an invalid executable Plan contract plus an incomplete late-recovery route,
54
+ not insufficient Worker effort and not an attempt-count problem.
45
55
 
46
56
  ## Implemented lifecycle contract
47
57
 
48
- - Fresh `next` advertises audited remediation only for an `awaiting_execution_authorization`
49
- required Task of an active Milestone with a current `stop-escalate` Plan Risk Audit. Standalone,
50
- post-execution, `split-required`, and other stop postures preserve their existing routes.
51
- - Coordinator first records a normal capability Discovery. `milestone remediation-materialize`
52
- then performs one project transaction that appends exactly one required remediation Task and adds
53
- exactly one dependency edge from the blocked Task to it.
54
- - The new Task must inherit the blocked Task's exact direct predecessor frontier, and every predecessor
55
- must already be merged. Milestone outcome, success signal, acceptance, checks, base, old memberships
56
- and all unrelated dependency edges remain byte-semantically unchanged.
57
- - The scope-change event binds Milestone revision, blocked Task revision, Brief/Plan hashes, exact Plan
58
- Risk Audit event/hash, remediation Discovery revision, new Task identity and predecessor frontier.
59
- Reuse or topology drift fails closed.
60
- - A `corrective-derived` authorization, bound to the audited evidence and exact actor
61
- `agent:milestone-remediation:<MS-ID>`, replaces the superseded Milestone execution authorization.
62
- It authorizes only current required Task execution acceptance transitions; it is neither a general
63
- delegation grant nor human impersonation.
64
- - The remediation route requires no human approval. After its Task merges, the original Task returns
65
- to `task plan-set`, must receive a semantically new Plan and fresh Plan Risk Audit, and then proceeds
66
- through the ordinary C1, checks, commits and reviews.
67
- - Public handshake capabilities include `audited-remediation-topology-v1` and
68
- `corrective-derived-task-authority-v1`.
69
-
70
- ## Signal-shaped evidence
71
-
72
- The release E2E mirrors the observed Signal deadlock: four already merged provider Tasks, one blocked
73
- required consumer Task, a current pre-execution `stop-escalate` audit, and a missing upstream
74
- capability. It proves the entire recovery cycle rather than only the new materialization command.
75
-
76
- Live Signal installation and mutation are intentionally separate post-publication actions. They must
77
- use exact repository-local beta.12.10, a clean/idle update boundary, fresh `status -> next`, and the
78
- advertised compatibility/recovery route if the dependency update advances active Milestone base
79
- state. No manual state edit, Git history rewrite, Task cancellation, or duplicate Milestone is part of
80
- the release mechanism.
58
+ - Mechanical feasibility now uses the versioned analyzer `wf2.root-npm-script-arguments@1`. It
59
+ conservatively recognizes only a root npm script whose command is a repository-relative Node
60
+ `affected` runner and whose source contains the established selector contract. A Plan check without
61
+ `--base`, `--head`, or `--files` is blocked when the runner is outside current/predecessor
62
+ `allowedWrites`; an explicit forwarded selector passes. Unsupported syntax remains `unverified`.
63
+ - Plan-integrity evidence schema v2 binds the current Task revision, Step and Plan hashes, every
64
+ sequential remediation event, package manifest and runner bytes, Git HEAD, dirty Step files, and a
65
+ canonical conflict hash. Existing v1 evidence remains readable.
66
+ - Recovery accepts one or more contiguous `checks-failed` events only when no corrective decision has
67
+ consumed them. It appends one `replan-required` decision at the next ordinal and covers the complete
68
+ failed history; it does not synthesize an extra failure.
69
+ - A published update from beta.12.11 is permitted only through the read-only
70
+ `update plan-integrity-update-preflight` proof. Transport may commit only `package.json` and
71
+ `package-lock.json` on the active Milestone base and carry that exact dependency commit to the Task
72
+ branch while preserving all product bytes.
73
+ - Fresh `next` then advertises `update plan-integrity-dependency-recover` only when current HEAD,
74
+ package version, parent commit, Task/Step/Plan, remediation IDs, dirty paths and their content hash,
75
+ absence of leases, and transaction state still match the preflight boundary.
76
+ - Dependency registration and a Project Knowledge refresh are one Project transaction. The refresh is
77
+ allowed without a Human gate only when the sole canonical drift is the exact Workflow pin in
78
+ `package.json`; any unrelated Knowledge change fails closed.
79
+ - The compatibility record is authority only for the exact post-update Plan-integrity recovery. A
80
+ fresh replacement Plan must bind the current Knowledge Map and replace the invalid check with an
81
+ executable selector-bearing command. Ordinary authorization, C1, Core commit, strict review, and
82
+ subsequent navigation remain mandatory.
83
+ - A repairable legacy remediation-mode defect outranks this new preflight. Plan-integrity assessment
84
+ reports itself ineligible and leaves `next` free to advertise the established
85
+ `task remediation-mode-recover` route.
86
+ - Handshake adds `plan-integrity-update-recovery-v1`; protocol and state schema remain `2/2`.
87
+
88
+ ## Signal-shaped and negative evidence
89
+
90
+ The new synthetic E2E reproduces the real Signal boundary rather than testing a helper in isolation:
91
+
92
+ - beta.12.11 package/lock and approved Knowledge Map;
93
+ - an active claimed guarded Step with four distinct `checks-failed` events;
94
+ - the same missing selector contract as Signal;
95
+ - the exact allowlisted dirty worktree;
96
+ - a dependency-only beta.12.12 commit;
97
+ - automatic package-only Knowledge refresh and compatibility registration;
98
+ - writer credential replacement, Plan-integrity recovery, corrective yield, and fresh corrective
99
+ replan preparation.
100
+
101
+ Negative coverage rejects a runner inside the current Step write scope, unrelated dirty files,
102
+ tampered evidence, an active lease, wider dependency commits, changed worktree bytes, stale
103
+ Task/Plan/Step bindings, transaction conflicts, and unrelated Knowledge drift. Existing tests also
104
+ prove that Plan-integrity preflight cannot hide the older remediation-mode recovery route.
105
+
106
+ Live Signal mutation remains post-publication work. It must preserve the three current Worker files,
107
+ transport only package/lock, use fresh repository-local handshake/status/next before each mutation,
108
+ and follow only advertised recovery actions. No manual Workflow-state edit, history rewrite, Task
109
+ cancellation, duplicate Task, or replacement Milestone is authorized by this release.
81
110
 
82
111
  ## PDF release documentation evidence
83
112
 
84
- - All three tracked Russian PDFs were regenerated from beta.12.10 Markdown sources.
85
- - Architecture is 8 pages, the delegated chat-only guide is 10 pages, and the technical reference is
86
- 12 pages. All 30 pages were rendered and visually inspected; the changed recovery sections were
87
- checked at full-page resolution.
88
- - Titles, package bindings, Cyrillic text, tables, code blocks, margins, footers and section transitions
89
- have no visible clipping, overlap or unreadable content.
113
+ - All three tracked Russian PDFs were regenerated from beta.12.12 Markdown sources.
114
+ - Architecture is 9 pages, the delegated chat-only guide is 10 pages, and the technical reference is
115
+ 13 pages. All 32 pages were rendered and visually inspected through contact sheets.
116
+ - Titles, version bindings, Cyrillic text, tables, code blocks, margins, footers and selector-recovery
117
+ sections show no clipping, overlap, or unreadable content.
90
118
 
91
119
  ## Existing boundaries and non-claims
92
120
 
93
- - The new route does not permit arbitrary Task insertion, task removal, semantic Milestone scope
94
- change, arbitrary dependency rewiring, completed-Step adoption or `split-required` replacement.
95
- - Human approval is removed only from this exact evidence-derived corrective topology transition.
96
- Final Milestone acceptance and generic semantic scope changes retain their existing authority model.
97
- - Protocol version remains 2 and state schema remains 2; older projects remain readable without a
98
- state migration.
99
- - No Git commit, tag, remote push, npm publication or live Signal recovery is claimed by this
100
- pre-publication report.
101
-
102
- Confidence is high for the package implementation, topology invariants, no-human corrective authority,
103
- regression compatibility, tarball composition, downstream installation, plugin and documentation.
104
- Live Signal confidence remains conditional on successful publication, exact dependency installation,
105
- fresh Core readback and Coordinator completion of the advertised remediation route.
121
+ - The analyzer does not execute or infer arbitrary shell grammar and does not claim to understand
122
+ every repository validation framework.
123
+ - The compatibility route cannot change product files, Plan semantics, Milestone topology, Task
124
+ membership, dependency edges, completed-Step provenance, or unrelated Knowledge.
125
+ - The release does not make a failing implementation pass, approve a broken check, or increase retry
126
+ limits. It creates a bounded route to replace a mechanically impossible approved check.
127
+ - Protocol version remains 2 and state schema remains 2; no state migration is required.
128
+ - This report does not claim Git commit/tag/push, npm publication, live Signal installation, or Task
129
+ completion before those operations receive their own readbacks.
130
+
131
+ Confidence is high for selector detection, repeated-failure recovery, update compatibility,
132
+ transaction atomicity, regression compatibility, package composition, downstream installation,
133
+ gateway and documentation. Live Signal confidence remains conditional on exact publication,
134
+ installation, fresh Core readback, and completion of the previously blocked Step.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-workflow-v2",
3
- "version": "2.0.0-beta.12.10",
3
+ "version": "2.0.0-beta.12.12",
4
4
  "description": "Requirements-first Codex development workflow with local state and explicit Git ownership.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -156,6 +156,16 @@ free-form Milestone scope change. Follow only the advertised route:
156
156
  record a fresh Risk Audit, use the same current derived approval only when advertised, and
157
157
  continue through at least the next ordinary Step boundary.
158
158
 
159
+ An exact package update may make the approved Knowledge Map stale while this route is active. Continue
160
+ without a Human approval only when fresh `next` includes
161
+ `auditedRemediation.dependencyKnowledgeRefresh.eligible=true`. Core must prove that `package.json` is
162
+ the sole changed Knowledge source, every version surface equals the repository-local runtime, and every
163
+ Git commit that changed the approved manifest content altered only the exact Workflow dependency in
164
+ `package.json`/`package-lock.json`. Do not run standalone reconcile first. The refresh is committed
165
+ atomically by `milestone remediation-materialize` with corrective-derived evidence. Any other Knowledge
166
+ path, classification, gap, conflict, dirty checkout, unaligned version or wider commit returns to the
167
+ ordinary explicit Knowledge flow.
168
+
159
169
  This is an idempotent, additive topology transition bound to one exact Plan Risk Audit. Dirty Git,
160
170
  any lease/transaction/Core operation, a started blocked Task, stale Task/Milestone/audit bindings,
161
171
  non-merged or non-exact predecessors, duplicate use of the audit, or any changed Milestone semantic
@@ -50,11 +50,16 @@
50
50
  "then": {
51
51
  "required": ["recoveryBasis", "planIntegrityEvidence"],
52
52
  "properties": { "decision": { "const": "replan-required" } }
53
- },
54
- "else": {
55
- "not": { "anyOf": [{ "required": ["recoveryBasis"] }, { "required": ["planIntegrityEvidence"] }] }
56
53
  }
57
54
  },
55
+ {
56
+ "if": { "required": ["recoveryBasis"] },
57
+ "then": {
58
+ "required": ["planIntegrityEvidence"],
59
+ "properties": { "decision": { "const": "replan-required" } }
60
+ },
61
+ "else": { "not": { "required": ["planIntegrityEvidence"] } }
62
+ },
58
63
  {
59
64
  "anyOf": [
60
65
  { "properties": { "coveredFindingIds": { "minItems": 1 } } },
@@ -74,13 +79,14 @@
74
79
  "items": { "type": "string", "minLength": 1 }
75
80
  },
76
81
  "planIntegrityEvidence": {
77
- "type": "object",
78
- "additionalProperties": false,
79
- "required": [
80
- "kind", "taskRevision", "remediationEventId", "remediationEventHash",
81
- "manifestPath", "manifestHash", "gitHead", "stepDefinitionHash",
82
- "missingScripts", "checkCommands", "changedFiles", "conflictHash"
83
- ],
82
+ "oneOf": [
83
+ { "$ref": "#/$defs/planIntegrityEvidenceV1" },
84
+ { "$ref": "#/$defs/planIntegrityEvidenceV2" }
85
+ ]
86
+ },
87
+ "planIntegrityEvidenceV1": {
88
+ "type": "object", "additionalProperties": false,
89
+ "required": ["kind", "taskRevision", "remediationEventId", "remediationEventHash", "manifestPath", "manifestHash", "gitHead", "stepDefinitionHash", "missingScripts", "checkCommands", "changedFiles", "conflictHash"],
84
90
  "properties": {
85
91
  "kind": { "const": "missing-npm-script-outside-allowed-writes" },
86
92
  "taskRevision": { "type": "integer", "minimum": 1 },
@@ -95,6 +101,47 @@
95
101
  "changedFiles": { "$ref": "#/$defs/stringList" },
96
102
  "conflictHash": { "$ref": "#/$defs/hash64" }
97
103
  }
104
+ },
105
+ "planIntegrityEvidenceV2": {
106
+ "type": "object", "additionalProperties": false,
107
+ "required": ["kind", "taskRevision", "remediationEvents", "manifestPath", "manifestHash", "gitHead", "stepDefinitionHash", "conflicts", "changedFiles", "conflictHash"],
108
+ "properties": {
109
+ "kind": { "const": "non-executable-npm-check-outside-allowed-writes" },
110
+ "taskRevision": { "type": "integer", "minimum": 1 },
111
+ "remediationEvents": {
112
+ "type": "array", "minItems": 1,
113
+ "items": {
114
+ "type": "object", "additionalProperties": false,
115
+ "required": ["eventId", "eventHash", "attemptOrdinal"],
116
+ "properties": {
117
+ "eventId": { "type": "string", "minLength": 1 },
118
+ "eventHash": { "$ref": "#/$defs/hash64" },
119
+ "attemptOrdinal": { "type": "integer", "minimum": 1 }
120
+ }
121
+ }
122
+ },
123
+ "manifestPath": { "const": "package.json" },
124
+ "manifestHash": { "$ref": "#/$defs/nullableHash64" },
125
+ "gitHead": { "$ref": "#/$defs/gitOid" },
126
+ "stepDefinitionHash": { "$ref": "#/$defs/hash64" },
127
+ "conflicts": {
128
+ "type": "array", "minItems": 1,
129
+ "items": {
130
+ "type": "object", "additionalProperties": false,
131
+ "required": ["reasonCode", "script", "command", "scriptCommand", "runnerPath", "runnerHash"],
132
+ "properties": {
133
+ "reasonCode": { "enum": ["MISSING_NPM_SCRIPT", "REQUIRED_SELECTOR_MISSING"] },
134
+ "script": { "type": "string", "minLength": 1 },
135
+ "command": { "type": "string", "minLength": 1 },
136
+ "scriptCommand": { "type": ["string", "null"] },
137
+ "runnerPath": { "type": ["string", "null"] },
138
+ "runnerHash": { "$ref": "#/$defs/nullableHash64" }
139
+ }
140
+ }
141
+ },
142
+ "changedFiles": { "$ref": "#/$defs/stringList" },
143
+ "conflictHash": { "$ref": "#/$defs/hash64" }
144
+ }
98
145
  }
99
146
  }
100
147
  }
@@ -177,6 +177,29 @@
177
177
  "retainedCommitSha": { "type": "string", "pattern": "^[a-f0-9]{40}$" }
178
178
  },
179
179
  "additionalProperties": false
180
+ },
181
+ "planIntegrity": {
182
+ "type": "object",
183
+ "required": ["stepId", "planHash", "conflictHash", "dirtyFiles", "dirtyWorktreeHash", "remediationEventIds"],
184
+ "properties": {
185
+ "stepId": { "type": "string", "pattern": "^STEP-[A-Z0-9][A-Z0-9-]{2,63}$" },
186
+ "planHash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
187
+ "conflictHash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
188
+ "dirtyFiles": {
189
+ "type": "array",
190
+ "minItems": 1,
191
+ "uniqueItems": true,
192
+ "items": { "type": "string", "minLength": 1 }
193
+ },
194
+ "dirtyWorktreeHash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
195
+ "remediationEventIds": {
196
+ "type": "array",
197
+ "minItems": 1,
198
+ "uniqueItems": true,
199
+ "items": { "type": "string", "minLength": 1 }
200
+ }
201
+ },
202
+ "additionalProperties": false
180
203
  }
181
204
  },
182
205
  "additionalProperties": false