codex-workflow-v2 2.0.0-beta.1 → 2.0.0-beta.11

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 (187) hide show
  1. package/README.md +94 -12
  2. package/dist/src/alpha6/adoption.js +13 -3
  3. package/dist/src/alpha6/adoption.js.map +1 -1
  4. package/dist/src/alpha6/handoff.d.ts +26 -2
  5. package/dist/src/alpha6/handoff.js +277 -29
  6. package/dist/src/alpha6/handoff.js.map +1 -1
  7. package/dist/src/alpha6/mechanical-feasibility.d.ts +7 -0
  8. package/dist/src/alpha6/mechanical-feasibility.js +303 -0
  9. package/dist/src/alpha6/mechanical-feasibility.js.map +1 -0
  10. package/dist/src/alpha6/milestone.d.ts +37 -2
  11. package/dist/src/alpha6/milestone.js +472 -33
  12. package/dist/src/alpha6/milestone.js.map +1 -1
  13. package/dist/src/alpha6/plan-integrity.d.ts +14 -0
  14. package/dist/src/alpha6/plan-integrity.js +127 -0
  15. package/dist/src/alpha6/plan-integrity.js.map +1 -0
  16. package/dist/src/alpha6/plan-risk.d.ts +1 -0
  17. package/dist/src/alpha6/plan-risk.js +15 -7
  18. package/dist/src/alpha6/plan-risk.js.map +1 -1
  19. package/dist/src/alpha6/remediation.d.ts +2 -1
  20. package/dist/src/alpha6/remediation.js +186 -9
  21. package/dist/src/alpha6/remediation.js.map +1 -1
  22. package/dist/src/alpha6/review.d.ts +3 -0
  23. package/dist/src/alpha6/review.js +24 -0
  24. package/dist/src/alpha6/review.js.map +1 -1
  25. package/dist/src/cli.js +486 -46
  26. package/dist/src/cli.js.map +1 -1
  27. package/dist/src/contracts.d.ts +238 -6
  28. package/dist/src/contracts.js +1 -1
  29. package/dist/src/credential-output.d.ts +10 -0
  30. package/dist/src/credential-output.js +73 -0
  31. package/dist/src/credential-output.js.map +1 -0
  32. package/dist/src/dependency-provenance.d.ts +19 -0
  33. package/dist/src/dependency-provenance.js +185 -0
  34. package/dist/src/dependency-provenance.js.map +1 -0
  35. package/dist/src/errors.d.ts +1 -1
  36. package/dist/src/errors.js.map +1 -1
  37. package/dist/src/git.d.ts +1 -1
  38. package/dist/src/git.js +13 -5
  39. package/dist/src/git.js.map +1 -1
  40. package/dist/src/index.d.ts +2 -1
  41. package/dist/src/index.js +2 -1
  42. package/dist/src/index.js.map +1 -1
  43. package/dist/src/lifecycle/canonical-hash.d.ts +6 -0
  44. package/dist/src/lifecycle/canonical-hash.js +24 -0
  45. package/dist/src/lifecycle/canonical-hash.js.map +1 -0
  46. package/dist/src/lifecycle/catalog.d.ts +26 -0
  47. package/dist/src/lifecycle/catalog.js +208 -0
  48. package/dist/src/lifecycle/catalog.js.map +1 -0
  49. package/dist/src/lifecycle/compiler-inspection.d.ts +48 -0
  50. package/dist/src/lifecycle/compiler-inspection.js +29 -0
  51. package/dist/src/lifecycle/compiler-inspection.js.map +1 -0
  52. package/dist/src/lifecycle/core-static-readiness.d.ts +6 -0
  53. package/dist/src/lifecycle/core-static-readiness.js +130 -0
  54. package/dist/src/lifecycle/core-static-readiness.js.map +1 -0
  55. package/dist/src/lifecycle/corrective-replan-authority.d.ts +53 -0
  56. package/dist/src/lifecycle/corrective-replan-authority.js +139 -0
  57. package/dist/src/lifecycle/corrective-replan-authority.js.map +1 -0
  58. package/dist/src/lifecycle/corrective-replan-binding-manifest.d.ts +21 -0
  59. package/dist/src/lifecycle/corrective-replan-binding-manifest.js +35 -0
  60. package/dist/src/lifecycle/corrective-replan-binding-manifest.js.map +1 -0
  61. package/dist/src/lifecycle/corrective-replan-credential-core.d.ts +86 -0
  62. package/dist/src/lifecycle/corrective-replan-credential-core.js +563 -0
  63. package/dist/src/lifecycle/corrective-replan-credential-core.js.map +1 -0
  64. package/dist/src/lifecycle/corrective-replan-credential-schema.d.ts +17 -0
  65. package/dist/src/lifecycle/corrective-replan-credential-schema.js +44 -0
  66. package/dist/src/lifecycle/corrective-replan-credential-schema.js.map +1 -0
  67. package/dist/src/lifecycle/corrective-replan-credentials.d.ts +47 -0
  68. package/dist/src/lifecycle/corrective-replan-credentials.js +103 -0
  69. package/dist/src/lifecycle/corrective-replan-credentials.js.map +1 -0
  70. package/dist/src/lifecycle/corrective-replan.d.ts +64 -0
  71. package/dist/src/lifecycle/corrective-replan.js +553 -0
  72. package/dist/src/lifecycle/corrective-replan.js.map +1 -0
  73. package/dist/src/lifecycle/evaluator.d.ts +2 -0
  74. package/dist/src/lifecycle/evaluator.js +35 -0
  75. package/dist/src/lifecycle/evaluator.js.map +1 -0
  76. package/dist/src/lifecycle/fingerprint.d.ts +31 -0
  77. package/dist/src/lifecycle/fingerprint.js +388 -0
  78. package/dist/src/lifecycle/fingerprint.js.map +1 -0
  79. package/dist/src/lifecycle/immutable.d.ts +1 -0
  80. package/dist/src/lifecycle/immutable.js +10 -0
  81. package/dist/src/lifecycle/immutable.js.map +1 -0
  82. package/dist/src/lifecycle/implementation-table.d.ts +29 -0
  83. package/dist/src/lifecycle/implementation-table.js +87 -0
  84. package/dist/src/lifecycle/implementation-table.js.map +1 -0
  85. package/dist/src/lifecycle/index.d.ts +4 -0
  86. package/dist/src/lifecycle/index.js +5 -0
  87. package/dist/src/lifecycle/index.js.map +1 -0
  88. package/dist/src/lifecycle/schema-artifact.d.ts +12 -0
  89. package/dist/src/lifecycle/schema-artifact.js +214 -0
  90. package/dist/src/lifecycle/schema-artifact.js.map +1 -0
  91. package/dist/src/lifecycle/semantic-registry.d.ts +6 -0
  92. package/dist/src/lifecycle/semantic-registry.js +489 -0
  93. package/dist/src/lifecycle/semantic-registry.js.map +1 -0
  94. package/dist/src/lifecycle/types.d.ts +718 -0
  95. package/dist/src/lifecycle/types.js +4 -0
  96. package/dist/src/lifecycle/types.js.map +1 -0
  97. package/dist/src/observation.d.ts +20 -0
  98. package/dist/src/observation.js +171 -0
  99. package/dist/src/observation.js.map +1 -0
  100. package/dist/src/reviewer.d.ts +43 -1
  101. package/dist/src/reviewer.js +203 -50
  102. package/dist/src/reviewer.js.map +1 -1
  103. package/dist/src/state/corrective-replan-executor.d.ts +64 -0
  104. package/dist/src/state/corrective-replan-executor.js +608 -0
  105. package/dist/src/state/corrective-replan-executor.js.map +1 -0
  106. package/dist/src/state/corrective-replan-public-schema.d.ts +3 -0
  107. package/dist/src/state/corrective-replan-public-schema.js +43 -0
  108. package/dist/src/state/corrective-replan-public-schema.js.map +1 -0
  109. package/dist/src/state/corrective-replan-public.d.ts +95 -0
  110. package/dist/src/state/corrective-replan-public.js +665 -0
  111. package/dist/src/state/corrective-replan-public.js.map +1 -0
  112. package/dist/src/state/corrective-replan-transaction.d.ts +160 -0
  113. package/dist/src/state/corrective-replan-transaction.js +730 -0
  114. package/dist/src/state/corrective-replan-transaction.js.map +1 -0
  115. package/dist/src/state/corrective-yield-executor.d.ts +31 -0
  116. package/dist/src/state/corrective-yield-executor.js +236 -0
  117. package/dist/src/state/corrective-yield-executor.js.map +1 -0
  118. package/dist/src/state/corrective-yield-transaction.d.ts +97 -0
  119. package/dist/src/state/corrective-yield-transaction.js +591 -0
  120. package/dist/src/state/corrective-yield-transaction.js.map +1 -0
  121. package/dist/src/state/lock.d.ts +76 -3
  122. package/dist/src/state/lock.js +611 -30
  123. package/dist/src/state/lock.js.map +1 -1
  124. package/dist/src/state/store.d.ts +3 -0
  125. package/dist/src/state/store.js +65 -12
  126. package/dist/src/state/store.js.map +1 -1
  127. package/dist/src/transition-core.d.ts +67 -0
  128. package/dist/src/transition-core.js +318 -0
  129. package/dist/src/transition-core.js.map +1 -0
  130. package/dist/src/version.d.ts +1 -1
  131. package/dist/src/version.js +1 -1
  132. package/dist/src/version.js.map +1 -1
  133. package/dist/src/workflow.d.ts +88 -24
  134. package/dist/src/workflow.js +1647 -270
  135. package/dist/src/workflow.js.map +1 -1
  136. package/docs/autonomy-guardrails.md +61 -1
  137. package/docs/beta11-plan-integrity-recovery-brief.md +38 -0
  138. package/docs/beta2-initial-assembly-navigation-brief.md +616 -0
  139. package/docs/delegated-approval.md +26 -1
  140. package/docs/development-flow.md +63 -8
  141. package/docs/lifecycle/state-machine-stabilization.md +641 -0
  142. package/docs/pdf/README.md +24 -0
  143. package/docs/pdf/codex-workflow-v2-architecture-ru.pdf +0 -0
  144. package/docs/pdf/codex-workflow-v2-chat-only-guide-ru.pdf +0 -0
  145. package/docs/pdf/codex-workflow-v2-technical-reference-ru.pdf +0 -0
  146. package/docs/pdf/requirements.txt +1 -0
  147. package/docs/pdf/sources/codex-workflow-v2-architecture-ru.md +234 -0
  148. package/docs/pdf/sources/codex-workflow-v2-chat-only-guide-ru.md +334 -0
  149. package/docs/pdf/sources/codex-workflow-v2-technical-reference-ru.md +413 -0
  150. package/docs/problem-briefs/01-pre-implementation-integrity.md +478 -0
  151. package/docs/problem-briefs/02-minimal-step-integrity.md +411 -0
  152. package/docs/problem-briefs/03-minimal-agent-context-integrity.md +358 -0
  153. package/docs/problem-briefs/04-task-dependency-and-structural-replacement-integrity.md +566 -0
  154. package/docs/problem-briefs/BRIEF-TEMPLATE.md +56 -0
  155. package/docs/problem-briefs/README.md +120 -0
  156. package/docs/problem-briefs/evidence/p01-mechanical-feasibility-corpus.md +90 -0
  157. package/docs/problem-briefs/evidence/signal-v4-pre-m3-replay.md +246 -0
  158. package/docs/release.md +30 -6
  159. package/docs/split-required-recovery.md +19 -25
  160. package/docs/stable-release-defect-register.md +465 -3
  161. package/docs/updating-existing-project.md +59 -4
  162. package/docs/validation-report.md +124 -56
  163. package/package.json +9 -1
  164. package/plugins/codex-workflow-gateway/.codex-plugin/plugin.json +10 -3
  165. package/plugins/codex-workflow-gateway/references/protocol.md +92 -4
  166. package/plugins/codex-workflow-gateway/scripts/chat-registry.mjs +376 -0
  167. package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +263 -4
  168. package/references/state-machine.md +13 -6
  169. package/roles/delivery-coordinator.md +39 -0
  170. package/schemas/adoption-posture-event.schema.json +1 -1
  171. package/schemas/authorization-event.schema.json +64 -1
  172. package/schemas/context-envelope.schema.json +1 -1
  173. package/schemas/corrective-decision-event.schema.json +48 -3
  174. package/schemas/corrective-replan-credentials.private.schema.json +98 -0
  175. package/schemas/corrective-replan-execution-event.private.schema.json +53 -0
  176. package/schemas/corrective-replan-public.schema.json +142 -0
  177. package/schemas/corrective-replan-task-transaction.private.schema.json +151 -0
  178. package/schemas/corrective-yield-task-transaction.private.schema.json +98 -0
  179. package/schemas/milestone-scope-change-event.schema.json +6 -1
  180. package/schemas/milestone.schema.json +6 -1
  181. package/schemas/remediation-event.schema.json +11 -1
  182. package/schemas/task-handoff-event.schema.json +19 -3
  183. package/schemas/task.schema.json +24 -1
  184. package/schemas/transition-definition.schema.json +2609 -0
  185. package/schemas/transition-payloads.schema.json +140 -0
  186. package/scripts/generate-pdf-docs.py +512 -0
  187. package/scripts/run-pdf-docs.mjs +62 -0
@@ -32,6 +32,35 @@ external alpha.7 runner may inspect a project still pinned to alpha.6 only when
32
32
  command reports `eligible=true`. Execute only its returned stale-lock repair and strict-review
33
33
  actions; do not use the external runner for any other transition or dependency mutation.
34
34
 
35
+ The beta.10 bounded dependency-provenance route is narrower than ordinary Git recovery. Use it only
36
+ when fresh `next` advertises `update dependency-provenance-recover`. First run the read-only
37
+ `update dependency-provenance-preflight --id <TASK-ID>` and require `eligible=true`, the same
38
+ Task/revision/HEAD, and no blockers. The candidate must be the single unregistered HEAD after the
39
+ recorded Task history, change exactly `package.json` and `package-lock.json`, and leave every
40
+ declared, locked, installed, current-branch, and active Milestone-base version equal to the running
41
+ package. A historical product commit whose current corrective Plan no longer carries Step evidence
42
+ is admissible only when Core derives it from a complete, hash-valid `pending → review-recorded →
43
+ attestation-verified` chain with `passed` decision and verified reviewer isolation. Raw evidence,
44
+ pending review, a failed decision, or a damaged sidecar never establishes provenance. Recovery
45
+ records the candidate dependency HEAD as a Workflow system commit and records admissible reviewed
46
+ product commits separately as `retainedHistoricalCommits`; it does not relabel product work as a
47
+ system commit and does not create, amend, reset, or merge Git history. Never use it for unknown
48
+ product changes, multiple extra commits, a dirty checkout, any lease, an in-progress Step, or a
49
+ pending/corrupt transaction. After success run sequential `status` then `next` and follow the exact
50
+ returned lifecycle action; Knowledge reconciliation or atomic Task context refresh may legitimately
51
+ be next because the dependency files changed.
52
+
53
+ The beta.11 bounded Plan-integrity route prevents a known impossible check from consuming a second
54
+ ordinary remediation attempt. Use `task plan-integrity-recover` only when fresh `next` advertises
55
+ it for the exact failed Task/Step/revision. Require `state=eligible`, no blockers, one first
56
+ `checks-failed` remediation, an exact missing root npm script, `package.json` outside the Step's
57
+ `allowedWrites`, and a dirty-file set confined to that Step. Pass the exact returned actor and the
58
+ active writer token when the C1 contract requires it. The recovery records only a bound early
59
+ `replan-required` decision: it does not edit the Plan or worktree. Then follow fresh `next` through
60
+ `task corrective-yield` and the existing Human-confirmed corrective-replan flow. Never repeat
61
+ `task run` merely to manufacture the second failure, and never invoke this recovery for a generic
62
+ test failure, a writable manifest, or unconfined changes.
63
+
35
64
  If any step fails, report the concrete diagnostic. Do not load workflow
36
65
  semantics from this skill.
37
66
 
@@ -51,6 +80,13 @@ scanner category. Do not replace the path with a wildcard or directory, do not i
51
80
  authority, and do not claim delegated-refresh eligibility; Core decides eligibility from the
52
81
  resulting repository diff and current authorization state.
53
82
 
83
+ When `next.action` is `task plan-set` (including the corrective-audit variant), treat
84
+ `next.taskPlanContract` as the exact transition precondition. Copy every
85
+ `requiredRequirementIds` entry into Plan `requirements` and every `requiredAcceptanceIds` entry
86
+ into Plan `acceptance` as exact array members; semantic prose may be added but cannot replace those
87
+ IDs. Bind the Plan to the returned `briefHash` and active `knowledgeMap` revision/hash. Stop if the
88
+ contract is absent or conflicts with the current Task/Knowledge state.
89
+
54
90
  When `next` returns top-level `action: task context-refresh`, use only that atomic action for
55
91
  the returned Task/map revisions, actor, and grant. Do not run standalone `project-memory reconcile`
56
92
  first: Core rejects it because it would create a human-approval gap and strand the Task. A
@@ -60,9 +96,204 @@ Autonomy Grant. Never infer eligibility from the Plan yourself; if Core returns
60
96
  `contextRefreshBlocked.unsafeDifferences`, use the ordinary visible Knowledge Map flow.
61
97
 
62
98
  When `next` reports terminal `split-required`, follow `docs/split-required-recovery.md` from the
63
- installed package. The only valid continuation is the exact `task replacement-materialize`
64
- transition (or creation of its one ready Discovery when requested). Never rebind, refresh, replan,
65
- authorize, or resume the historical Task, and never emulate the membership changes manually.
99
+ installed package. P04-A returns `doctor` with blocked action `task replacement-materialize`,
100
+ diagnostic `STRUCTURAL_REPLACEMENT_REQUIRED`, and
101
+ `replacementGate.structuralReplacementAvailable=false`. Stop without invoking the retained
102
+ command shape or consuming a replacement Discovery. Never rebind, refresh, replan, authorize,
103
+ resume, cancel, or manually replace the historical Task. Continue only after a later P04-B/P05
104
+ package explicitly advertises a topology-preserving replacement capability.
105
+
106
+ When `next` returns `milestone initial-assembly`, execution is unavailable. Follow only the
107
+ advertised `linked-task-assembly.commands` (`discovery start` and `discovery materialize`) until all
108
+ intended linked Tasks exist. The closing `milestone plan-set` option appears only after at least one
109
+ linked Task exists; use it once with the complete membership. After every boundary, run `status`,
110
+ wait for its terminal success, and only then run `next`; never launch the checkpoint pair in
111
+ parallel or in one parallel tool batch. If either fails, stop; do not
112
+ describe the reverse-membership gap as expected and invoke a direct closing command.
113
+
114
+ When `next` includes `milestoneCancellationOption`, treat it as an advertised alternative only
115
+ when the user has explicitly requested cancellation or supersession of that exact Milestone.
116
+ Use the returned Milestone ID and expected revision verbatim, require a substantive user-supplied
117
+ reason, and preserve every historical Task and sidecar. Absence of this option means cancellation
118
+ is not currently navigable; do not invoke `milestone cancel` directly.
119
+
120
+ When `next` includes `gitMutationPolicy`, obtain bounded permission for that exact Git-writing
121
+ transition before the first call. Do not probe and retry after a `.git/index.lock` failure.
122
+ For `task start`, the policy applies only when choosing `--workspace-owner local`; for
123
+ `task step-complete`, `task merge`, and `task sync-base`, the advertised transition itself
124
+ writes Git metadata.
125
+
126
+ When `next` includes `writerTokenContract`, treat it as an exact first-call precondition. Retain
127
+ the active writer lease from the first-field `writerLeaseReceipt` returned by `task run` and pass it using the advertised `option` for that
128
+ transition. The token is sensitive: never print, summarize, persist, or substitute a redacted
129
+ fingerprint. Stop before mutation if the active lease is unavailable. This input contract is
130
+ independent from `gitMutationPolicy`; satisfy both when both are present.
131
+
132
+ On successful `task handoff-prepare`, consume the first-field `credentialHandoff` before reading
133
+ the Task/event/bundle payload. Retain its one-time token only in working memory and use it exactly
134
+ once with the declared `action` and `option` for the declared `targetActor`. Successful `task claim`
135
+ returns a first-field `writerLeaseReceipt`; retain that lease and pass it to claimed `task run` when
136
+ the fresh `next.writerTokenContract` requires it. Successful `task run` returns the refreshed
137
+ `writerLeaseReceipt`; retain it only until Core releases that lease.
138
+ Never search later payload fields for either credential and never copy credentials into evidence.
139
+
140
+ Command discovery with `codex-workflow <noun> [action] --help` is read-only. Use it only when the
141
+ exact invocation syntax is not already available from `next` and this protocol. Consume declared
142
+ `requiredOptions` and `optionalOptions`; when `exactOptionContractAvailable=false`, consult the
143
+ packaged protocol instead of guessing. Help never replaces a fresh `next` before mutation.
144
+
145
+ When two or more Tasks are actionable, a dedicated Task chat may call `next --task <exact Task ID>`
146
+ after the repository `status` checkpoint. The selector is read-only routing, not authorization: the
147
+ response must name that same Task and all ordinary milestone, observation, adoption, Knowledge, and
148
+ credential gates still apply. Omit `--task` for repository-level coordination. If Core reports that
149
+ the selected Task is missing or not actionable, stop rather than falling back to another Task or
150
+ invoking a direct mutation.
151
+
152
+ ## Codex App Chat Boundary
153
+
154
+ A Milestone chat and its Task chats are separate user-visible execution contexts, not forks of one
155
+ conversation. Create every Task chat as a brand-new Codex task with `create_thread`, an explicit
156
+ Task-only prompt, and an explicit title. Never use `fork_thread`, thread handoff, or a continuation
157
+ of the Milestone chat to create a Task chat: those paths carry parent history into the child. A
158
+ failure to create a new task is a routing blocker. Check the thread list for an already-created
159
+ exact Task ID, retry `create_thread` once sequentially when none exists, and then stop; never fall
160
+ back to a fork.
161
+
162
+ Codex App may wrap the supplied prompt in a host-generated `codex_delegation` envelope containing
163
+ only routing provenance such as `source_thread_id`. That envelope is permitted and is not parent
164
+ conversation context. Verify that the envelope's `input` is exactly the TaskContextPacket and that
165
+ the new thread contains no copied parent turns, transcript, or assistant output.
166
+
167
+ Create or reuse the Task chat just before dispatching that exact Task; do not create forked or empty
168
+ placeholder chats for the whole membership. Derive `T<NN>` from the approved Milestone membership
169
+ order, never from creation order or sidebar order.
170
+
171
+ Before creation, look up the exact Task in current Workflow state and construct one closed
172
+ TaskContextPacket containing only:
173
+
174
+ - repository root and exact repository-local workflow package requirement;
175
+ - Milestone number and ID, Task membership ordinal, exact Task ID, revision, and current title;
176
+ - the Task objective, requirements/acceptance identifiers, Brief hash, and current Plan hash when
177
+ one exists;
178
+ - the exact actor and grant ID only when the current routing requires them (never a confirmation
179
+ code, handoff credential, writer token, or other bearer value);
180
+ - the mandatory start sequence `AGENTS.md -> project-local gateway -> handshake -> status -> next
181
+ --task <exact Task ID>`, with a requirement to stop if the response names another Task;
182
+ - Task-local scope, checks, stop conditions, and the instruction to obtain all mutable facts from
183
+ fresh Workflow state rather than from the parent chat.
184
+ - an autonomous completion contract: continue through planning, execution, required external
185
+ reviews, fix/review recovery, submission, final acceptance, and merge whenever fresh Workflow
186
+ navigation authorizes those transitions; stop only at a mandatory human/semantic gate, an
187
+ integrity or infrastructure blocker, or the terminal Task result.
188
+ - a closed, non-secret CoordinatorReport requirement at a blocker or terminal boundary containing
189
+ the exact Task ID, observed Task revision/status, outcome (`attention` or `terminal`), reported
190
+ next action, whether a user decision is required, blocker class, commits/checks/review evidence,
191
+ and no confirmation code, handoff credential, writer token, or other bearer value.
192
+
193
+ Do not include or summarize the Milestone-chat transcript, recovery/approval narrative, sibling
194
+ Task details, other Task Plans, unrelated repository analysis, reasoning traces, or historical
195
+ credentials. The new Task chat may read repository files and its own Workflow Task/Brief/Plan; it
196
+ must not rely on the parent conversation as evidence or authority.
197
+
198
+ Every automatically created Coordinator, Task, Step Review, Final Review, Corrective Audit, and
199
+ Plan Audit chat must use the project registry/title builder at
200
+ `../../scripts/chat-registry.mjs`. Before `create_thread`, call `allocate` with exact `projectId`,
201
+ chat type, Milestone/Task/Step membership ordinals, semantic title, authoritative entity ID, and
202
+ review attempt. Use returned `requestedTitle` verbatim. Never derive its prefix from
203
+ `list_threads`, sidebar order, a count, or `count + 1`: allocation atomically reserves the
204
+ project-wide monotonically increasing `#NNN`, and an abandoned number is never reused.
205
+
206
+ The builder owns these compact title families; callers must not hand-compose variants:
207
+
208
+ ```text
209
+ #NNN · M<NN> · Coord · <Milestone title> · <MS-ID>
210
+ #NNN · M<NN>/T<NN> · Task · <Task title> · <TASK-ID>
211
+ #NNN · M<NN>/T<NN>/S<NN> · Step Review A<N> · <Step title> · <TASK-ID>
212
+ #NNN · M<NN>/T<NN> · Final Review A<N> · <Task title> · <TASK-ID>
213
+ #NNN · M<NN>/T<NN>/S<NN> · Corrective A<N> · <Step title> · <TASK-ID>
214
+ #NNN · M<NN>/T<NN> · Plan Audit A<N> · <Task title> · <TASK-ID>
215
+ ```
216
+
217
+ When the Milestone ID is known, allocate and bind the coordinator chat before dispatch. During
218
+ `AUTO` Discovery reserve the Coordinator number once; after materialization retain that sequence
219
+ with registry `retitle`, then complete exact readback with the new Milestone ID instead of
220
+ allocating a second Coordinator number.
221
+
222
+ Put `#NNN` and membership ordinals first so clipped sidebar titles remain distinguishable. Never
223
+ inherit the parent title, use a generic title such as `Milestone recovery` / `Task execution`, or
224
+ reuse one title for different entity IDs. Maintain the registry-backed
225
+ `Task ID -> thread ID -> title` mapping in
226
+ the Milestone chat. Before dispatch, verify from the thread list that the title contains the exact
227
+ ordinal and entity ID, is unique, and the new chat input contains only its TaskContextPacket plus
228
+ the permitted host routing envelope. Never trust the `create_thread` title argument without a
229
+ readback: pass the observed title to registry `readback`. If it returns `renameRequired=true`,
230
+ rename to exact `renameTitle` and repeat. Deterministic fallbacks remove the semantic segment and
231
+ compact the role while preserving `#NNN`, membership ordinals, attempt, and the full entity ID.
232
+ Never invent another fallback or abbreviate the ID. Bind the verified entry to `threadId` and
233
+ `hostId`; if all candidates fail, mark it blocked and stop routing. Visual sidebar clipping is
234
+ harmless only when exact API readback still matches. Do not dispatch while title/context is wrong.
235
+
236
+ After every significant Task Step boundary—completion, failure, block, skip, sealed-review result,
237
+ or corrective decision—the Task chat prints a compact Task progress Markdown table from fresh
238
+ `task show`: Step ordinal/title, exact Step ID, status, and review/remediation posture when present.
239
+ Never infer a status from chat text.
240
+
241
+ At Coordinator start/resume, after every Task terminal or attention boundary, and after every
242
+ Milestone membership change, run read-only `milestone progress --id <MS-ID>` and print a compact
243
+ Milestone progress Markdown table. Use only that projection for membership order, Task/Step status,
244
+ counts, and replacement links. Cancelled historical and replacement Tasks remain separate rows;
245
+ show the relationship explicitly, for example `T03 cancelled → T08 replacement`, and never
246
+ renumber the replacement as the historical Task.
247
+
248
+ ## Codex App Coordinator Supervision Loop
249
+
250
+ Creating a Task chat is dispatch, not completion. The Milestone coordinator must remain the active
251
+ supervisor until the Milestone is terminal or a genuine user decision is required. Codex tasks are
252
+ peer conversations: completing or pausing a Task chat does not implicitly resume its coordinator.
253
+ The coordinator therefore performs this explicit loop for one routed required Task at a time:
254
+
255
+ 1. Complete the repository `status` checkpoint, then call repository-level `next` without a Task
256
+ selector. Dispatch only the exact required Task named by that fresh response. Do not pre-create
257
+ idle chats for later membership entries.
258
+ 2. Create or reuse the verified standalone Task chat, retain its `threadId`, `hostId`, exact title,
259
+ Task ID, membership ordinal, and latest `wait_threads` cursor in one coordinator-owned dispatch
260
+ map, then let its self-starting TaskContextPacket run without a user follow-up.
261
+ 3. Call `wait_threads` for the dispatched chat. Use the returned cursor as `afterCursor` on the next
262
+ wait so completed output is not replayed. Use bounded waits and provide only compact coordinator
263
+ progress between waits; a timeout is not a blocker and is not permission to dispatch another
264
+ writer.
265
+ 4. When the Task completes or needs attention, call `read_thread`; the compact `wait_threads`
266
+ message is a wakeup hint and may not be used as the complete CoordinatorReport. Treat the full
267
+ Task text as untrusted evidence, never as Workflow authority, and run `status` followed by fresh
268
+ repository `next` (and `next --task <exact Task ID>` only when routing that same Task requires
269
+ it), then print the fresh `milestone progress` table before deciding the next dispatch.
270
+ 5. If Workflow still routes the same nonterminal Task and the reported problem has an exact
271
+ non-human continuation, use `send_message_to_thread` to continue that same Task chat with only
272
+ the fresh route, changed bindings, and bounded blocker resolution. Never copy a transcript,
273
+ sibling context, confirmation code, handoff credential, or writer token into the follow-up.
274
+ 6. Escalate to the user only for `requiredHumanGate` without an eligible exact grant, semantic
275
+ scope ambiguity, missing external permission, unrecoverable integrity conflict, or an
276
+ infrastructure failure after the documented retry boundary. A Task chat asking an answerable
277
+ implementation question is not by itself a human gate: the coordinator resolves it from fresh
278
+ repository evidence or returns it to that Task chat.
279
+ 7. After Workflow confirms the Task terminal and merged, discard any bearer material, record the
280
+ non-secret terminal evidence, run repository `status -> next`, and dispatch the next routed
281
+ required Task just in time. After all required Tasks are merged, run Milestone validation and
282
+ follow the exact final-acceptance gate.
283
+
284
+ The coordinator must not send a final answer while a dispatched required Task is nonterminal,
285
+ except for an explicit user-requested checkpoint or one of the blockers in step 6. In that case it
286
+ reports the dispatch map, last observed Task revision/status, last wait cursor, and exact fresh
287
+ `next`, so a later turn can resume without creating duplicate chats. On any resumed coordinator
288
+ turn, first reconcile the saved map against `list_threads`, `read_thread`, repository `status`, and
289
+ fresh `next`; never assume that an idle/finished chat implies a terminal Workflow Task.
290
+
291
+ The Task chat owns supervision of its own external-sealed Step and Task reviewer chats and returns
292
+ only their sealed result/evidence to the Milestone coordinator. This keeps the coordinator below
293
+ the app's bounded wait target limit and prevents it from accumulating implementation or review
294
+ transcripts. No chat may wait indefinitely for a child after ending its own turn: durable,
295
+ cross-restart background orchestration requires a separate app wakeup/automation facility and is
296
+ not implied by this skill.
66
297
 
67
298
  ## Product Or Workflow Graph Refresh
68
299
 
@@ -88,7 +319,8 @@ independently blocks the workflow.
88
319
  `task step-complete` returned by `next`, and core owns checks, commit creation, and evidence.
89
320
  - Delivery Coordinator: list, status, index, detect, and bind lifecycle.
90
321
  - A Milestone Delivery Coordinator creates a dedicated user-visible Task chat for every
91
- required Task and keeps implementation out of the Milestone chat.
322
+ required Task, using the Codex App Chat Boundary above, and keeps implementation out of the
323
+ Milestone chat.
92
324
  - Independent Reviewer: receives recorded evidence and confirms critical
93
325
  claims against files, Git, and tests.
94
326
 
@@ -118,6 +350,9 @@ Never create, broaden, renew, or replace a grant from an agent's own judgment. N
118
350
  the delegate as the user. When `next` exposes an eligible option, pass its grant ID through
119
351
  `--delegation-grant` and use the exact delegate string as `--actor`. The core remains the
120
352
  authority for status, expiry, scope, transition, and revocation checks.
353
+ If the same `next` response does not expose an eligible option for that exact transition, do
354
+ not pass `--delegation-grant`. Ordinary C1 handoff, claim, run, step-complete, step-review,
355
+ merge, and sync-base do not inherit a Milestone approval grant.
121
356
 
122
357
  For delegated Milestone final acceptance, the current `MSA-*` code is still required, but a
123
358
  new user turn is not: the previously issued grant is the controlling decision. If no eligible
@@ -128,6 +363,10 @@ changes, grant issuance, and grant expansion are never delegated by `delegated-a
128
363
  For an entire Milestone, prefer one bounded `milestone autonomy-prepare` gate after the complete
129
364
  initial membership Plan exists. Show principal, delegate, expiry, semantic-scope hash, policy
130
365
  hash, and `MAC-*` code, then stop. A later exact approval permits `milestone autonomy-grant`.
366
+ Use the delegated path only when the same `next` response exposes
367
+ `milestoneAuthorizationOptions[].action = "milestone autonomy-prepare"` and the user explicitly
368
+ requested delegated Milestone operation; otherwise follow the ordinary `milestone authorize`
369
+ human gate.
131
370
  The resulting grant covers the existing Task/Milestone approval transitions and the Project
132
371
  Memory approval portion of an atomic Task context refresh for the same Milestone. Besides
133
372
  content-only drift, Core may accept exact supporting-source additions predeclared by the current
@@ -141,6 +380,25 @@ After two failed Task reviews, follow `next.correctivePlanGate`: obtain a distin
141
380
  corrective Auditor result and pass it through `--corrective-audit-file`. Do not continue for
142
381
  replan, split, or stop decisions.
143
382
 
383
+ When `next.strictStepReview.recommendedMode` is `external-sealed`, do not launch the nested local
384
+ reviewer from inside a Codex App sandbox. Run the advertised read-only `task step-review-packet`,
385
+ create a separate user-visible reviewer chat for that exact packet, and require one closed
386
+ `ReviewInput` JSON result bound to its reviewed commit. The reviewer must not modify repository or
387
+ Workflow state. Then run only the advertised `task step-review-record` with the unchanged packet
388
+ and repository-seal hashes, the separate reviewer thread ID, the lifecycle actor from `next`, and
389
+ the active writer token when required. Never author the independent review in the Worker or
390
+ Delivery Coordinator chat, never alter the packet, and never treat an unverified local reviewer
391
+ launch as a semantic remediation failure. If Core reports the seal changed, discard the review and
392
+ stop; do not regenerate evidence against a moving checkout.
393
+
394
+ When `next.strictTaskReview.recommendedMode` is `external-sealed`, apply the same isolation rule to
395
+ the final submitted-Task review. Run the advertised read-only `task review-packet`, send the exact
396
+ packet to a separate user-visible Independent Reviewer chat, and accept only a closed `ReviewInput`
397
+ bound to the unchanged packet and repository-seal hashes. Record it only through the advertised
398
+ `task review-sealed-record`, using the lifecycle actor from `next` and the active writer token when
399
+ required. Do not call `task review-launch` from inside a Codex App sandbox, do not use the Worker or
400
+ Delivery Coordinator as reviewer, and discard the result if a fresh packet changes either hash.
401
+
144
402
  When `next` returns a derived C1 Worker or corrective Auditor actor, use that exact actor without
145
403
  asking the user to name one. Derivation removes a routing pause; handoff claim, writer lease,
146
404
  strict review, and auditor-independence checks remain mandatory.
@@ -156,5 +414,6 @@ returns `safe=true` with a clean checkout, no running Step, and no active writer
156
414
  - A request changes before evidence is bound.
157
415
  - An action would make MCP or the local map authoritative project memory.
158
416
  - A requested mutation is not authorized by the package CLI state.
417
+ - A lifecycle `status` or `next` failed; do not continue with a different lifecycle mutation.
159
418
  - A human gate was emitted but the user has not approved its exact confirmation code in a
160
419
  later message and no exact eligible delegated approval option exists.
@@ -63,7 +63,10 @@ human turn boundary.
63
63
 
64
64
  During initial planning, all linked Tasks may be materialized before one complete
65
65
  `milestone plan-set`; execution remains blocked until every reverse membership is classified.
66
- After that boundary, semantic updates use human-only `milestone scope-change-prepare` and
66
+ `next` returns `milestone initial-assembly` before Task 1 and after every safe linked-Task
67
+ materialization, with explicit `discovery start` and `discovery materialize` commands. After at
68
+ least one linked Task exists, it also exposes the closing `milestone plan-set` command. Failed navigation is fail-closed and cannot be treated as an
69
+ expected assembly signal. After that boundary, semantic updates use human-only `milestone scope-change-prepare` and
67
70
  `milestone scope-change-apply`. A human-confirmed, expiring Milestone Autonomy Contract may
68
71
  use `milestone autonomy-evolve` only for membership changes while outcome, success signal,
69
72
  acceptance, checks, discovery, and base branch remain fixed. It may also approve Project Memory
@@ -75,20 +78,24 @@ the grant's Milestone. Every added source must match the Plan, and removals, can
75
78
  wildcard or directory targets, existing source category/scope/authority changes, gaps, and
76
79
  conflicts fail closed before any state write. `next` exposes the composite option only when the
77
80
  full predicate passes and otherwise reports concrete unsafe differences. Both update paths journal
78
- `state.json`, `plan.json`, and `scope-change-events.jsonl` together. Membership integrity is validated
79
- before scheduling, Task start, Milestone validation, scope change, and repository `next`.
81
+ `state.json`, `plan.json`, and `scope-change-events.jsonl` together. Initial Plan publication uses
82
+ the same recovery journal for `state.json` and `plan.json`. Membership and dependency integrity is
83
+ validated before scheduling, handoff, claim (before lease acquisition), Task start, Milestone
84
+ validation, scope change, and repository `next`.
80
85
  The same guard scans in reverse and blocks every live Task whose `milestoneId` is absent from
81
86
  the Milestone's required/waived/cancelled classification.
82
87
 
83
88
  `C1` coordination is machine-bound but local: `task handoff-prepare` returns a one-time claim
84
89
  token and prompt bound to a stable handoff ID, revision, context hashes, Milestone positions,
85
- delegate/grant, expected next action, and expiry. `task claim` validates those bindings and
90
+ Milestone revision, membership revision, Milestone Plan hash, delegate/grant, expected next action,
91
+ and expiry. `task claim` validates those bindings and
86
92
  activates claimant-only mutation; terminal `task handback-create` returns result, evidence,
87
93
  review, knowledge, limitation, and recommended-next bindings. Milestone Tasks must be claimed
88
94
  before start. If no target is supplied, Core derives `agent:worker:<task-id>`. No part of this
89
95
  contract requires or proves a physically separate Codex thread.
90
96
 
91
- Repository-level scheduling respects current Milestone membership. An unstarted linked Task
92
- is eligible only for an `active` Milestone with `required` disposition. Historical unstarted
97
+ Repository-level scheduling respects current Milestone membership and its canonical dependency
98
+ DAG. A linked Task is eligible only for an `active` Milestone with `required` disposition after
99
+ all required predecessors are `merged`. Historical unstarted
93
100
  Tasks from `waived`, `cancelled`, accepted, or cancelled Milestone paths cannot shadow the
94
101
  Milestone/repository transition returned by `next`.
@@ -24,6 +24,45 @@ Own state transitions, dispatch envelopes, evidence collection, and recovery gui
24
24
  - A Milestone coordinator creates one dedicated user-visible Codex Task chat for each required
25
25
  Task. The Milestone chat owns ordering, exact delegated approvals, merge observation,
26
26
  validation, and final acceptance; it does not accumulate implementation for every Task.
27
+ - Create that Task chat as a new standalone Codex task, never by forking, handing off, or continuing
28
+ the Milestone chat. Supply only the exact Task context packet from current Workflow state. Parent
29
+ history, sibling Tasks, recovery narrative, reasoning traces, confirmation codes, handoff
30
+ credentials, and writer tokens are forbidden in the Task prompt. A chat-creation failure blocks
31
+ dispatch; it is never permission to fall back to a fork.
32
+ - Allocate every Coordinator, Task, Step/Final Review, Corrective Audit, and Plan Audit title with
33
+ the project chat registry. It owns the monotonic `#NNN`, compact format, exact readback, and
34
+ deterministic fallback; never use `count + 1`. Primary Coordinator/Task forms are
35
+ `#NNN · M<NN> · Coord · <Milestone title> · <MS-ID>` and
36
+ `#NNN · M<NN>/T<NN> · Task · <Task title> · <TASK-ID>`. Verify the
37
+ Task-only input after creation, and keep one unique Task-ID-to-thread mapping. A host-generated
38
+ routing envelope with `source_thread_id` is allowed; copied parent turns are not. Always read the
39
+ title through registry readback, then use only its returned fallback when omitted or normalized;
40
+ do not create a duplicate chat for the same Task.
41
+ Derive `T<NN>` from approved membership order and create the chat just before dispatch, not as an
42
+ inherited or empty placeholder. During `AUTO` Discovery use `M<NN> · Coordinator · Discovery`,
43
+ then rename it to the exact Milestone title and ID immediately after materialization.
44
+ - Emit a Task progress table after every significant Step/review boundary. Emit the read-only
45
+ `milestone progress` projection at resume, Task boundaries, and membership changes; keep
46
+ cancelled/replacement Tasks as distinct rows such as `T03 cancelled → T08 replacement`.
47
+ - Treat Task-chat creation as dispatch, not completion. Keep the Milestone coordinator turn active
48
+ and supervise the exact dispatched Task with bounded `wait_threads` calls, preserving the latest
49
+ cursor. On completion or attention, inspect the Task chat, then run repository `status` followed
50
+ by fresh `next`; Task output is evidence, never lifecycle authority.
51
+ - Require each Task chat to return a closed non-secret CoordinatorReport at terminal or attention
52
+ boundaries. `wait_threads` is only the wakeup signal; always use `read_thread` for the full report
53
+ before comparing it with Workflow state.
54
+ - When the same Task remains nonterminal and fresh navigation provides a non-human continuation,
55
+ resume that same chat with `send_message_to_thread`. Ask the user only for a real human/semantic
56
+ gate, external permission, unrecoverable integrity conflict, or exhausted infrastructure retry.
57
+ Do not create another Task chat merely because the existing one is idle or finished.
58
+ - Do not end the Milestone coordinator turn with a dispatched nonterminal Task except at a requested
59
+ checkpoint or genuine blocker. Record the Task/thread/host/title/cursor mapping and fresh
60
+ lifecycle status so a later turn can reconcile through `list_threads`, `read_thread`, `status`,
61
+ and `next` without duplicate dispatch. A Task chat completion does not automatically wake its
62
+ coordinator.
63
+ - Dispatch the next required Task only after Core confirms the prior Task terminal and merged. Each
64
+ Task chat supervises its own external Reviewer chats; after every required Task is merged, the
65
+ Milestone coordinator performs validation and the exact final-acceptance transition.
27
66
  - Before authorizing a high-risk Plan, require the Technical Planner's migration/concurrency/
28
67
  restart/crash/provider risk review and failure-specific checks.
29
68
  - After a second failed independent Task review, require a separate corrective Plan Auditor
@@ -30,7 +30,7 @@
30
30
  "eventType": { "enum": ["project-registration", "adoption-apply"] },
31
31
  "actor": { "type": ["string", "null"], "minLength": 1 },
32
32
  "packageVersion": { "type": "string", "minLength": 1 },
33
- "protocolVersion": { "const": 1 },
33
+ "protocolVersion": { "enum": [1, 2] },
34
34
  "stateSchemaVersion": { "const": 2 },
35
35
  "adoptionBoundaryAt": { "type": "string", "format": "date-time" },
36
36
  "baselineDigestHash": { "$ref": "#/$defs/hash64" },
@@ -20,7 +20,8 @@
20
20
  "headCommit": { "$ref": "#/$defs/nullableHash" },
21
21
  "reason": { "type": "string" },
22
22
  "authorizationMode": { "enum": ["human", "delegated"] },
23
- "delegation": { "$ref": "#/$defs/delegation" }
23
+ "delegation": { "$ref": "#/$defs/delegation" },
24
+ "mechanicalFeasibility": { "$ref": "#/$defs/mechanicalFeasibility" }
24
25
  },
25
26
  "allOf": [
26
27
  {
@@ -50,6 +51,68 @@
50
51
  ]
51
52
  }
52
53
  }
54
+ },
55
+ "mechanicalFeasibility": {
56
+ "type": "object",
57
+ "additionalProperties": false,
58
+ "required": [
59
+ "schemaVersion", "taskId", "evaluatedTaskRevision", "briefHash", "planHash",
60
+ "sourceKind", "sourceBranch", "evaluatedHead", "baseCommit", "analyzerSetHash",
61
+ "analyzerInputHash", "analyzers", "findings", "decision"
62
+ ],
63
+ "properties": {
64
+ "schemaVersion": { "const": 1 },
65
+ "taskId": { "type": "string", "pattern": "^TASK-[0-9A-HJKMNP-TV-Z]{26}$" },
66
+ "evaluatedTaskRevision": { "type": "integer", "minimum": 1 },
67
+ "briefHash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
68
+ "planHash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
69
+ "sourceKind": { "enum": ["pre-start-base", "corrective-task-workspace"] },
70
+ "sourceBranch": { "type": "string", "minLength": 1 },
71
+ "evaluatedHead": { "type": "string", "pattern": "^[a-f0-9]{40,64}$" },
72
+ "baseCommit": { "$ref": "#/$defs/nullableHash" },
73
+ "analyzerSetHash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
74
+ "analyzerInputHash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
75
+ "analyzers": {
76
+ "type": "array",
77
+ "minItems": 3,
78
+ "maxItems": 3,
79
+ "items": { "$ref": "#/$defs/mechanicalAnalyzer" }
80
+ },
81
+ "findings": {
82
+ "type": "array",
83
+ "items": { "$ref": "#/$defs/mechanicalFinding" }
84
+ },
85
+ "decision": { "enum": ["clear", "blocked"] }
86
+ }
87
+ },
88
+ "mechanicalAnalyzer": {
89
+ "type": "object",
90
+ "additionalProperties": false,
91
+ "required": ["analyzerId", "analyzerVersion"],
92
+ "properties": {
93
+ "analyzerId": {
94
+ "enum": ["wf2.root-npm-script", "wf2.exact-output-path", "wf2.exact-predecessor-path"]
95
+ },
96
+ "analyzerVersion": { "const": 1 }
97
+ }
98
+ },
99
+ "mechanicalFinding": {
100
+ "type": "object",
101
+ "additionalProperties": false,
102
+ "required": [
103
+ "analyzerId", "analyzerVersion", "result", "stepId", "subject", "evidence", "reasonCode"
104
+ ],
105
+ "properties": {
106
+ "analyzerId": {
107
+ "enum": ["wf2.root-npm-script", "wf2.exact-output-path", "wf2.exact-predecessor-path"]
108
+ },
109
+ "analyzerVersion": { "const": 1 },
110
+ "result": { "enum": ["pass", "blocked", "unverified"] },
111
+ "stepId": { "type": "string", "pattern": "^STEP-[0-9]{3}(?:-[A-Z0-9-]+)?$" },
112
+ "subject": { "type": "string" },
113
+ "evidence": { "type": "string", "minLength": 1 },
114
+ "reasonCode": { "type": "string", "pattern": "^[A-Z0-9_]+$" }
115
+ }
53
116
  }
54
117
  }
55
118
  }
@@ -25,7 +25,7 @@
25
25
  "knowledgeSources"
26
26
  ],
27
27
  "properties": {
28
- "protocolVersion": { "const": 1 },
28
+ "protocolVersion": { "const": 2 },
29
29
  "packageVersion": { "type": "string" },
30
30
  "role": {
31
31
  "enum": ["scope-lead", "technical-planner", "delivery-coordinator", "worker", "independent-reviewer"]
@@ -22,7 +22,7 @@
22
22
  "eventId": { "type": "string", "minLength": 1 },
23
23
  "taskId": { "$ref": "#/$defs/taskId" },
24
24
  "stepId": { "$ref": "#/$defs/stepId" },
25
- "triggeringAttemptCount": { "type": "integer", "minimum": 3 },
25
+ "triggeringAttemptCount": { "type": "integer", "minimum": 2 },
26
26
  "decision": {
27
27
  "enum": ["continue-fix", "replan-required", "split-required", "stop-escalate"]
28
28
  },
@@ -38,18 +38,63 @@
38
38
  "items": { "type": "string", "minLength": 1 }
39
39
  },
40
40
  "planHash": { "$ref": "#/$defs/hash64" },
41
+ "recoveryBasis": { "const": "plan-integrity" },
42
+ "planIntegrityEvidence": { "$ref": "#/$defs/planIntegrityEvidence" },
41
43
  "previousEventHash": { "$ref": "#/$defs/nullableHash64" },
42
44
  "recordedAt": { "type": "string", "format": "date-time" },
43
45
  "eventHash": { "$ref": "#/$defs/hash64" }
44
46
  },
45
- "anyOf": [
47
+ "allOf": [
48
+ {
49
+ "if": { "properties": { "triggeringAttemptCount": { "const": 2 } }, "required": ["triggeringAttemptCount"] },
50
+ "then": {
51
+ "required": ["recoveryBasis", "planIntegrityEvidence"],
52
+ "properties": { "decision": { "const": "replan-required" } }
53
+ },
54
+ "else": {
55
+ "not": { "anyOf": [{ "required": ["recoveryBasis"] }, { "required": ["planIntegrityEvidence"] }] }
56
+ }
57
+ },
58
+ {
59
+ "anyOf": [
46
60
  { "properties": { "coveredFindingIds": { "minItems": 1 } } },
47
61
  { "properties": { "coveredEventIds": { "minItems": 1 } } }
62
+ ]
63
+ }
48
64
  ],
49
65
  "$defs": {
50
66
  "taskId": { "type": "string", "pattern": "^TASK-[0-9A-HJKMNP-TV-Z]{26}$" },
51
67
  "stepId": { "type": "string", "pattern": "^STEP-[0-9]{3}(?:-[A-Z0-9-]+)?$" },
52
68
  "hash64": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
53
- "nullableHash64": { "type": ["string", "null"], "pattern": "^[a-f0-9]{64}$" }
69
+ "nullableHash64": { "type": ["string", "null"], "pattern": "^[a-f0-9]{64}$" },
70
+ "gitOid": { "type": "string", "pattern": "^[a-f0-9]{40,64}$" },
71
+ "stringList": {
72
+ "type": "array",
73
+ "uniqueItems": true,
74
+ "items": { "type": "string", "minLength": 1 }
75
+ },
76
+ "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
+ ],
84
+ "properties": {
85
+ "kind": { "const": "missing-npm-script-outside-allowed-writes" },
86
+ "taskRevision": { "type": "integer", "minimum": 1 },
87
+ "remediationEventId": { "type": "string", "minLength": 1 },
88
+ "remediationEventHash": { "$ref": "#/$defs/hash64" },
89
+ "manifestPath": { "const": "package.json" },
90
+ "manifestHash": { "$ref": "#/$defs/nullableHash64" },
91
+ "gitHead": { "$ref": "#/$defs/gitOid" },
92
+ "stepDefinitionHash": { "$ref": "#/$defs/hash64" },
93
+ "missingScripts": { "$ref": "#/$defs/stringList", "minItems": 1 },
94
+ "checkCommands": { "$ref": "#/$defs/stringList", "minItems": 1 },
95
+ "changedFiles": { "$ref": "#/$defs/stringList" },
96
+ "conflictHash": { "$ref": "#/$defs/hash64" }
97
+ }
98
+ }
54
99
  }
55
100
  }