codex-workflow-v2 2.0.0-beta.13 → 2.0.0-beta.13.10

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 (86) hide show
  1. package/README.md +6 -1
  2. package/dist/reviewer-runtime-build.json +44 -20
  3. package/dist/src/alpha6/failed-step-planning-recovery.d.ts +10 -0
  4. package/dist/src/alpha6/failed-step-planning-recovery.js +93 -0
  5. package/dist/src/alpha6/failed-step-planning-recovery.js.map +1 -0
  6. package/dist/src/alpha6/plan-risk.d.ts +4 -0
  7. package/dist/src/alpha6/plan-risk.js +50 -13
  8. package/dist/src/alpha6/plan-risk.js.map +1 -1
  9. package/dist/src/alpha6/preexecution-replan.d.ts +38 -0
  10. package/dist/src/alpha6/preexecution-replan.js +130 -0
  11. package/dist/src/alpha6/preexecution-replan.js.map +1 -0
  12. package/dist/src/alpha6/remediation.d.ts +4 -2
  13. package/dist/src/alpha6/remediation.js +155 -20
  14. package/dist/src/alpha6/remediation.js.map +1 -1
  15. package/dist/src/alpha6/root-cause-replan-carryover.d.ts +18 -0
  16. package/dist/src/alpha6/root-cause-replan-carryover.js +396 -0
  17. package/dist/src/alpha6/root-cause-replan-carryover.js.map +1 -0
  18. package/dist/src/alpha7/autonomy.d.ts +3 -0
  19. package/dist/src/alpha7/autonomy.js +89 -42
  20. package/dist/src/alpha7/autonomy.js.map +1 -1
  21. package/dist/src/change-explanation.d.ts +64 -0
  22. package/dist/src/change-explanation.js +150 -0
  23. package/dist/src/change-explanation.js.map +1 -0
  24. package/dist/src/cli-actions.d.ts +3 -2
  25. package/dist/src/cli-actions.js +6 -0
  26. package/dist/src/cli-actions.js.map +1 -1
  27. package/dist/src/cli.js +73 -1
  28. package/dist/src/cli.js.map +1 -1
  29. package/dist/src/contracts.d.ts +38 -0
  30. package/dist/src/dependency-provenance.d.ts +3 -2
  31. package/dist/src/dependency-provenance.js +33 -2
  32. package/dist/src/dependency-provenance.js.map +1 -1
  33. package/dist/src/domain/plan-semantics.d.ts +11 -0
  34. package/dist/src/domain/plan-semantics.js +49 -0
  35. package/dist/src/domain/plan-semantics.js.map +1 -0
  36. package/dist/src/gateway-handshake.js +2 -0
  37. package/dist/src/gateway-handshake.js.map +1 -1
  38. package/dist/src/lifecycle/corrective-replan.js +3 -3
  39. package/dist/src/lifecycle/corrective-replan.js.map +1 -1
  40. package/dist/src/observed-routes.js +1 -0
  41. package/dist/src/observed-routes.js.map +1 -1
  42. package/dist/src/pending-review-update.d.ts +49 -0
  43. package/dist/src/pending-review-update.js +132 -0
  44. package/dist/src/pending-review-update.js.map +1 -0
  45. package/dist/src/repository.js +16 -4
  46. package/dist/src/repository.js.map +1 -1
  47. package/dist/src/reviewer.js +4 -1
  48. package/dist/src/reviewer.js.map +1 -1
  49. package/dist/src/state/corrective-replan-executor.js +3 -1
  50. package/dist/src/state/corrective-replan-executor.js.map +1 -1
  51. package/dist/src/state/corrective-replan-public.js +5 -4
  52. package/dist/src/state/corrective-replan-public.js.map +1 -1
  53. package/dist/src/state/corrective-yield-executor.js +12 -3
  54. package/dist/src/state/corrective-yield-executor.js.map +1 -1
  55. package/dist/src/state/store.d.ts +1 -1
  56. package/dist/src/state/store.js +17 -3
  57. package/dist/src/state/store.js.map +1 -1
  58. package/dist/src/version.d.ts +1 -1
  59. package/dist/src/version.js +1 -1
  60. package/dist/src/version.js.map +1 -1
  61. package/dist/src/workflow.d.ts +84 -1
  62. package/dist/src/workflow.js +1616 -355
  63. package/dist/src/workflow.js.map +1 -1
  64. package/docs/beta13.2-signal-review-recovery.md +38 -0
  65. package/docs/change-model.md +118 -0
  66. package/docs/delegated-approval.md +26 -0
  67. package/docs/pdf/codex-workflow-v2-architecture-ru.pdf +0 -0
  68. package/docs/pdf/codex-workflow-v2-chat-only-guide-ru.pdf +0 -0
  69. package/docs/pdf/codex-workflow-v2-technical-reference-ru.pdf +0 -0
  70. package/docs/pdf/sources/codex-workflow-v2-architecture-ru.md +9 -1
  71. package/docs/pdf/sources/codex-workflow-v2-chat-only-guide-ru.md +9 -5
  72. package/docs/pdf/sources/codex-workflow-v2-technical-reference-ru.md +18 -3
  73. package/docs/pending-review-update.md +15 -0
  74. package/docs/release.md +267 -2
  75. package/docs/updating-existing-project.md +36 -6
  76. package/docs/validation-report.md +30 -9
  77. package/package.json +2 -1
  78. package/plugins/codex-workflow-gateway/references/chat-dispatch.md +204 -0
  79. package/plugins/codex-workflow-gateway/references/protocol.md +11 -0
  80. package/plugins/codex-workflow-gateway/scripts/chat-dispatch.mjs +298 -0
  81. package/plugins/codex-workflow-gateway/scripts/chat-model-policy.mjs +43 -0
  82. package/plugins/codex-workflow-gateway/scripts/chat-registry.mjs +55 -3
  83. package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +218 -21
  84. package/schemas/plan-risk-audit-event.schema.json +1 -0
  85. package/schemas/preexecution-replan-event.schema.json +45 -0
  86. package/schemas/task.schema.json +55 -0
package/README.md CHANGED
@@ -54,6 +54,11 @@ automation do not import anything from the parent V1 project.
54
54
  - beta.12.16 check-support authority: migration checksum/catalog modules imported directly by an
55
55
  approved check must be owned by the producing Step; an already-running Step receives only the
56
56
  exact machine-proved support path without a Human replan or a synthetic second failure;
57
+ - beta.13.7 retains a completed Step's carryover as verified history so later Steps can
58
+ replan normally, and binds corrective continuation to the original Worker.
59
+ - beta.13.6 binds dirty work retained by a mechanical root-cause replan to its source failure,
60
+ exact replacement Plan and audit, current authorization, unchanged HEAD and content hash;
61
+ navigation and execution share that assessment instead of demanding a clean checkout after replan;
57
62
  - read-only Milestone progress projection with stable membership ordinals and replacement links;
58
63
  - one project-monotonic `#NNN` chat registry with compact titles, exact readback, and deterministic fallback;
59
64
  - narrow, read-only alpha.6 strict-review rescue preflight for the lifecycle deadlock fixed in alpha.7;
@@ -77,7 +82,7 @@ cross-machine synchronization are not part of its contract.
77
82
  Node.js 22 or newer is required. Consumers pin the exact package version:
78
83
 
79
84
  ```bash
80
- npm install --save-dev --save-exact codex-workflow-v2@2.0.0-beta.13
85
+ npm install --save-dev --save-exact codex-workflow-v2@2.0.0-beta.13.10
81
86
  npx codex-workflow gateway handshake --repo .
82
87
  npx codex-workflow doctor --repo .
83
88
  ```
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "protocol": "codex-workflow-runtime-build-manifest-v1",
3
3
  "packageName": "codex-workflow-v2",
4
- "packageVersion": "2.0.0-beta.13",
5
- "packageManifestSha256": "9415ccde21cb37ebfddf4939c32d164aaebaf1190b1c1c8e47ac4e7e0de0e050",
4
+ "packageVersion": "2.0.0-beta.13.10",
5
+ "packageManifestSha256": "0cc966ad73f63b7e73874346b19ca57fb493adb9daabddb5060c02b7e3967de1",
6
6
  "requiredEntrypoints": [
7
7
  "dist/src/cli.js",
8
8
  "dist/src/gateway-handshake.js",
@@ -26,6 +26,10 @@
26
26
  "path": "dist/src/alpha6/downstream-proof.js",
27
27
  "sha256": "91dda6e6054f75f245d4f6de55a3adae0d5a8dbd4256e26ab55a13638344bb76"
28
28
  },
29
+ {
30
+ "path": "dist/src/alpha6/failed-step-planning-recovery.js",
31
+ "sha256": "a9b1b85c02d9f4854b5077513177ff448575585adca651d893a82dccab8c5bef"
32
+ },
29
33
  {
30
34
  "path": "dist/src/alpha6/handoff.js",
31
35
  "sha256": "21a2e2f267fc7a18ee48bb9fb98cc28f3fdf5b6065042a9289fcbe37e19374b2"
@@ -52,7 +56,11 @@
52
56
  },
53
57
  {
54
58
  "path": "dist/src/alpha6/plan-risk.js",
55
- "sha256": "bacc58d04d9c2adf00c6cf11a5e3fbc7cd17d9aec461f2d7dd7e3888c1807eb2"
59
+ "sha256": "cb43dec551f76cd3effc54bd72f697af39ec0b7fb49ea84227f9b2669c87256f"
60
+ },
61
+ {
62
+ "path": "dist/src/alpha6/preexecution-replan.js",
63
+ "sha256": "5f4714ca51e7758e158b8fef1a6e81bd143c1dc24aef4ef4ec7ff68ef9940f87"
56
64
  },
57
65
  {
58
66
  "path": "dist/src/alpha6/remediation-cause.js",
@@ -60,19 +68,23 @@
60
68
  },
61
69
  {
62
70
  "path": "dist/src/alpha6/remediation.js",
63
- "sha256": "13cedaed1e9181ec85b0f312cf621ded840c57b975337ce211966ad1499409a8"
71
+ "sha256": "a3e5d308c3395f33c7f0519e7ea13032c465f1ba39e6cee89b5312549e2a6842"
64
72
  },
65
73
  {
66
74
  "path": "dist/src/alpha6/review.js",
67
75
  "sha256": "4eb05ae8fda755c70844f4b62e8bdc0d837376adc7f7ddec27e893fa1e9d3496"
68
76
  },
77
+ {
78
+ "path": "dist/src/alpha6/root-cause-replan-carryover.js",
79
+ "sha256": "146a9c8802ab4ac590aa25d8c2a8a8bc10c21ed973b2c587fe96d96f00c4c864"
80
+ },
69
81
  {
70
82
  "path": "dist/src/alpha6/store-sidecars.js",
71
83
  "sha256": "74245dfe73ef7950ee0aff5d86c35c999347f39364efaba623857847372da2eb"
72
84
  },
73
85
  {
74
86
  "path": "dist/src/alpha7/autonomy.js",
75
- "sha256": "9c05ea60cb1f77d62200a8a6506f08953473fe13ee56370ca3369ec741210d79"
87
+ "sha256": "8f8ce97ea1d765f2884daadc0278c3532c37a6deba8b0dcafebb0e0e7719ea31"
76
88
  },
77
89
  {
78
90
  "path": "dist/src/alpha7/corrective-recovery.js",
@@ -86,13 +98,17 @@
86
98
  "path": "dist/src/beta1/project-transaction.js",
87
99
  "sha256": "aca86d6baf103866ab7a4a54416e0a231bdd77eda322dae3c6fde35e7f969801"
88
100
  },
101
+ {
102
+ "path": "dist/src/change-explanation.js",
103
+ "sha256": "78dcf7feeb3a0770efc6df408942dc382e65ad29853c9055505ae4230e8a0810"
104
+ },
89
105
  {
90
106
  "path": "dist/src/cli-actions.js",
91
- "sha256": "ef8653d58eced33f41d788260207ca5e63dab5b19e95560b86124c4895f1f39a"
107
+ "sha256": "184d6bc81d09b06c4bb7b36d8e25dffeea3adf9b5f6671830a12a857b58b682a"
92
108
  },
93
109
  {
94
110
  "path": "dist/src/cli.js",
95
- "sha256": "6f8462aeae51176efc890d1af36efffa8bd99c6b045c1f1edefe693e93ec9107"
111
+ "sha256": "beb3c1c4114a9b09ec4b819b58d96a42637ae0830dfcb82e957933158fa353e6"
96
112
  },
97
113
  {
98
114
  "path": "dist/src/contracts.js",
@@ -112,7 +128,7 @@
112
128
  },
113
129
  {
114
130
  "path": "dist/src/dependency-provenance.js",
115
- "sha256": "b08717654880332d285dfe3f4984bda9892c913682cd8d4d8f614a8803429df6"
131
+ "sha256": "3b8d66bb25764600c73341603d584ab81fe197c2051ec28cdbdf6066b3ee2aaf"
116
132
  },
117
133
  {
118
134
  "path": "dist/src/diagnostics.js",
@@ -126,6 +142,10 @@
126
142
  "path": "dist/src/domain/discovery.js",
127
143
  "sha256": "29aeedd9f1f4b761fc8b20a8fe3629eb6d3b1b87ea4e20f3bd6e580ea780c4fb"
128
144
  },
145
+ {
146
+ "path": "dist/src/domain/plan-semantics.js",
147
+ "sha256": "9434557e45e18367f4fabce20bb061dea801eecf96c3e3fc572515f42254033d"
148
+ },
129
149
  {
130
150
  "path": "dist/src/domain/validation.js",
131
151
  "sha256": "a42b20451a24fd4eca5ae2ed2884df58b41defbf82940ac7a13a0ff0320fbc2a"
@@ -140,7 +160,7 @@
140
160
  },
141
161
  {
142
162
  "path": "dist/src/gateway-handshake.js",
143
- "sha256": "c99251ba299c08451728db2df0509a955a341f1abe693b2330b9a9a02c48666a"
163
+ "sha256": "17eaf24bda26450989ea72d5af0f15e2701f3840a87be6f4d4c528f39713b4f0"
144
164
  },
145
165
  {
146
166
  "path": "dist/src/git.js",
@@ -196,7 +216,7 @@
196
216
  },
197
217
  {
198
218
  "path": "dist/src/lifecycle/corrective-replan.js",
199
- "sha256": "d9bd1ddea57a0b7215eeb9c78c54e9125b93d14349e6948a0909fdb1c00824ed"
219
+ "sha256": "1fd24430d3adb8ce4b74b1c787fb63ab7e84c545326bea268ce0109ce68dca28"
200
220
  },
201
221
  {
202
222
  "path": "dist/src/lifecycle/evaluator.js",
@@ -244,23 +264,27 @@
244
264
  },
245
265
  {
246
266
  "path": "dist/src/observed-routes.js",
247
- "sha256": "a89c3cbeaa7a723a4457e09216684f98f513e396d51a40925c42bc9e2535dd3c"
267
+ "sha256": "a39d8ed6bf0ddb4f5e884a42526dfb83be619950e36b68cfd0bebb7785af10cd"
248
268
  },
249
269
  {
250
270
  "path": "dist/src/operational-contract.js",
251
271
  "sha256": "82b9059813aa248492833200c9def5fe0357132bafadef7de3cbe3b6410652b1"
252
272
  },
273
+ {
274
+ "path": "dist/src/pending-review-update.js",
275
+ "sha256": "1d0b33a28dc88257363613e99b9f2bce039cad40c6d0fc1c9f27e8ffb53b8216"
276
+ },
253
277
  {
254
278
  "path": "dist/src/repository.js",
255
- "sha256": "3e37a61a2283f291e15e341804112e4cf040616cd4e369d8df6d4c1a8d12b35e"
279
+ "sha256": "e222267fc52cbf6c9bcaf1fca9307ce9eafd745bdb7cc4dae3b549d77ec213ca"
256
280
  },
257
281
  {
258
282
  "path": "dist/src/reviewer.js",
259
- "sha256": "118555849d6527f247a58c414e628b723fcf10c454c509b929b616bd4e68b61d"
283
+ "sha256": "a1a85660dbaecf3a5f8bca7c563d9b5dc2b533b901a330a1f8033645de36d30d"
260
284
  },
261
285
  {
262
286
  "path": "dist/src/state/corrective-replan-executor.js",
263
- "sha256": "4de85b96b65b30fd8aa8881de54b026e4c9f0fc68a1a2daa2a0965afe85f03cc"
287
+ "sha256": "554a0239c87b8a84c7d3cf16a646095e34df5150ef362b74818e77a9c9d1ec55"
264
288
  },
265
289
  {
266
290
  "path": "dist/src/state/corrective-replan-public-schema.js",
@@ -268,7 +292,7 @@
268
292
  },
269
293
  {
270
294
  "path": "dist/src/state/corrective-replan-public.js",
271
- "sha256": "c833eb22aaade497dbcca73088e3fbfa5fe29c3ccae34ddeafcd156bf6f60a9b"
295
+ "sha256": "45963349816fa63636aa64f6d2ba07f7dc0432b461493b1c067f1b02f2f1ba6a"
272
296
  },
273
297
  {
274
298
  "path": "dist/src/state/corrective-replan-transaction.js",
@@ -276,7 +300,7 @@
276
300
  },
277
301
  {
278
302
  "path": "dist/src/state/corrective-yield-executor.js",
279
- "sha256": "d2e64c1685829ac99aede6784dc05b487b0ae890cfccd17cd73eae9d53dde97e"
303
+ "sha256": "29e4568f5fa2e35ed98fe8d3bb1e48278224152c7175205c1878bb8835f3efa9"
280
304
  },
281
305
  {
282
306
  "path": "dist/src/state/corrective-yield-transaction.js",
@@ -288,7 +312,7 @@
288
312
  },
289
313
  {
290
314
  "path": "dist/src/state/store.js",
291
- "sha256": "5aa930f73607ce38e0e9d76560e8fafa7390cafcdcbc97d29fdff01f7dfecbf0"
315
+ "sha256": "575f4bdad35c49dceb2fc2318344c057a801d94788010dc9f21c36f62d61d8c8"
292
316
  },
293
317
  {
294
318
  "path": "dist/src/transition-core.js",
@@ -300,11 +324,11 @@
300
324
  },
301
325
  {
302
326
  "path": "dist/src/version.js",
303
- "sha256": "532bbbc50b4b0cb61749cc253b2007477b266feefa28ece9c7f5d6c4d88cffec"
327
+ "sha256": "70af01eb723d930fc8a9ef129c9025924bd68f8d1a94d56c6318a6c251b9e374"
304
328
  },
305
329
  {
306
330
  "path": "dist/src/workflow.js",
307
- "sha256": "19ba1123fd91b42198783a7454d2458280f7987bc8fd5d92646cb3e750356b0f"
331
+ "sha256": "c72cc02fa5137fb332408d895e73a06facae0907bdecd812062abe3a2ad85282"
308
332
  }
309
333
  ],
310
334
  "runtimeDependencies": [
@@ -1088,5 +1112,5 @@
1088
1112
  ]
1089
1113
  }
1090
1114
  ],
1091
- "fingerprint": "24543f05f0991859ecc64ec32574ed7a925adf0bc424b9c4ce0dddcd5f2abb62"
1115
+ "fingerprint": "8a07276298cb9987ab90bbe533b17fa09537a9b3c48cf28ea9b04c280115efd7"
1092
1116
  }
@@ -0,0 +1,10 @@
1
+ import type { TaskState } from '../contracts.js';
2
+ import type { FileStateStore } from '../state/store.js';
3
+ /** A stopped rebound Plan is evidence for repair, never execution authority. */
4
+ export declare function readFailedStepPlanningRecovery(store: FileStateStore, task: TaskState): {
5
+ current: import("./plan-risk.js").CurrentPlanRiskAudit;
6
+ baseline: import("../contracts.js").PlanRiskAuditEvent;
7
+ priorAuthorization: import("../contracts.js").AuthorizationEvent;
8
+ authority: "planning-only";
9
+ } | null;
10
+ export declare function readCorrectivePlanningAudit(store: FileStateStore, task: TaskState): import("./plan-risk.js").CurrentPlanRiskAudit | null;
@@ -0,0 +1,93 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { WorkflowError } from '../errors.js';
4
+ import { hashKnowledgeMap } from '../memory.js';
5
+ import { canonicalJsonStringify, sha256Hex } from './store-sidecars.js';
6
+ import { readCurrentPlanRiskAudit, readCurrentPlanningObstructionAudit, readPlanRiskAuditEvents } from './plan-risk.js';
7
+ import { assertKnowledgeBindingOnlyPlanChange } from '../alpha7/corrective-recovery.js';
8
+ /** A stopped rebound Plan is evidence for repair, never execution authority. */
9
+ export function readFailedStepPlanningRecovery(store, task) {
10
+ if (task.status !== 'awaiting_execution_authorization' || !task.planHash
11
+ || task.workspaceOwner === null || !task.steps.some(step => step.status === 'failed')
12
+ || task.steps.some(step => step.status === 'in_progress'))
13
+ return null;
14
+ const current = readCurrentPlanningObstructionAudit(store, task);
15
+ if (!current || current.audit.decision !== 'stop-escalate')
16
+ return null;
17
+ const fail = (message) => { throw new WorkflowError('TRANSITION_BLOCKED', message, { taskId: task.id }); };
18
+ const map = store.readKnowledgeMap(task.projectId);
19
+ if (map.status !== 'active' || map.revision !== task.knowledgeMapRevision || hashKnowledgeMap(map) !== task.knowledgeMapHash)
20
+ fail('Planning recovery requires the current active Knowledge binding.');
21
+ const audits = readPlanRiskAuditEvents(store, task);
22
+ const root = store.taskRoot(task.projectId, task.id);
23
+ let hash = task.planHash;
24
+ let knowledgeRevision = task.knowledgeMapRevision;
25
+ let knowledgeHash = task.knowledgeMapHash;
26
+ const visited = new Set();
27
+ const plan = (h) => {
28
+ const text = readFileSync(h === task.planHash ? path.join(root, 'plan.md') : path.join(root, '.versions', `plan.md.${h}`), 'utf8');
29
+ if (sha256Hex(text) !== h)
30
+ fail('Planning recovery Plan artifact hash mismatch.');
31
+ return text;
32
+ };
33
+ while (!visited.has(hash)) {
34
+ visited.add(hash);
35
+ const links = task.knowledgeRebinds.filter(record => record.reboundPlanHash === hash);
36
+ if (links.length !== 1)
37
+ return fail('Planning recovery requires an unambiguous Knowledge rebind chain.');
38
+ const link = links[0];
39
+ if (link.toKnowledgeMapRevision !== knowledgeRevision || link.toKnowledgeMapHash !== knowledgeHash
40
+ || !link.previousPlanHash)
41
+ fail('Planning recovery Knowledge rebind endpoints are stale.');
42
+ const before = plan(link.previousPlanHash), after = plan(hash);
43
+ assertKnowledgeBindingOnlyPlanChange(before, after);
44
+ if (!before.includes(`- Knowledge map: revision ${link.fromKnowledgeMapRevision}, hash ${link.fromKnowledgeMapHash}\n`)
45
+ || !after.includes(`- Knowledge map: revision ${link.toKnowledgeMapRevision}, hash ${link.toKnowledgeMapHash}\n`))
46
+ fail('Planning recovery artifact Knowledge endpoints differ from the recorded rebind.');
47
+ hash = link.previousPlanHash;
48
+ knowledgeRevision = link.fromKnowledgeMapRevision;
49
+ knowledgeHash = link.fromKnowledgeMapHash;
50
+ const baseline = audits.filter(a => a.planHash === hash && a.briefHash === task.briefHash
51
+ && a.knowledgeMapRevision === knowledgeRevision && a.knowledgeMapHash === knowledgeHash
52
+ && ['approved', 'approved-with-rationale'].includes(a.decision)
53
+ && audits.indexOf(a) < audits.findIndex(event => event.eventHash === current.audit.eventHash)
54
+ && task.authorizations.some(grant => grant.kind === 'execution' && grant.decision === 'superseded'
55
+ && grant.planHash === a.planHash && grant.briefHash === a.briefHash
56
+ && Date.parse(grant.recordedAt) >= Date.parse(a.recordedAt))).at(-1);
57
+ if (!baseline)
58
+ continue;
59
+ // A negative audit may append an observed counterexample without erasing the
60
+ // historical proof. Prefix preservation is NOT proof of semantic strengthening:
61
+ // both audits remain planning evidence, and replacement requires its own gates.
62
+ const obstructionClassifications = structuredClone(current.audit.stepClassifications);
63
+ for (const [stepIndex, classification] of obstructionClassifications.entries()) {
64
+ const original = baseline.stepClassifications[stepIndex];
65
+ if (!original)
66
+ return fail('Planning recovery must preserve the approved Step classification ordering.');
67
+ const proofs = classification.proofObligations ?? [], originalProofs = original.proofObligations ?? [];
68
+ if (proofs.length !== originalProofs.length)
69
+ fail('Planning recovery must preserve the approved proof tuple count and ordering.');
70
+ for (const [proofIndex, proof] of proofs.entries()) {
71
+ const originalProof = originalProofs[proofIndex];
72
+ for (const field of ['counterexample', 'expectedResult']) {
73
+ if (!proof[field].startsWith(originalProof[field]))
74
+ fail('Planning recovery cannot truncate or replace historical proof narratives.');
75
+ proof[field] = originalProof[field];
76
+ }
77
+ }
78
+ }
79
+ if (canonicalJsonStringify(baseline.stepClassifications) !== canonicalJsonStringify(obstructionClassifications))
80
+ fail('Planning recovery must preserve the approved risk classifications and proof tuples.');
81
+ const grants = task.authorizations.filter(a => a.kind === 'execution' && a.decision === 'superseded'
82
+ && a.planHash === baseline.planHash && a.briefHash === baseline.briefHash
83
+ && Date.parse(a.recordedAt) >= Date.parse(baseline.recordedAt));
84
+ if (grants.length !== 1)
85
+ fail('Planning recovery requires one historical superseded Plan authorization.');
86
+ return { current, baseline, priorAuthorization: grants[0], authority: 'planning-only' };
87
+ }
88
+ return fail('Planning recovery Knowledge rebind chain contains a cycle.');
89
+ }
90
+ export function readCorrectivePlanningAudit(store, task) {
91
+ return readFailedStepPlanningRecovery(store, task)?.current ?? readCurrentPlanRiskAudit(store, task);
92
+ }
93
+ //# sourceMappingURL=failed-step-planning-recovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failed-step-planning-recovery.js","sourceRoot":"","sources":["../../../src/alpha6/failed-step-planning-recovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,wBAAwB,EAAE,mCAAmC,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACxH,OAAO,EAAE,oCAAoC,EAAE,MAAM,kCAAkC,CAAC;AAExF,gFAAgF;AAChF,MAAM,UAAU,8BAA8B,CAAC,KAAqB,EAAE,IAAe;IACnF,IAAI,IAAI,CAAC,MAAM,KAAK,kCAAkC,IAAI,CAAC,IAAI,CAAC,QAAQ;WACnE,IAAI,CAAC,cAAc,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC;WAClF,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,aAAa,CAAC;QAAE,OAAO,IAAI,CAAC;IACzE,MAAM,OAAO,GAAG,mCAAmC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACjE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,QAAQ,KAAK,eAAe;QAAE,OAAO,IAAI,CAAC;IACxE,MAAM,IAAI,GAAG,CAAC,OAAe,EAAS,EAAE,GAAG,MAAM,IAAI,aAAa,CAAC,oBAAoB,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1H,MAAM,GAAG,GAAG,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACnD,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI,CAAC,oBAAoB,IAAI,gBAAgB,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,gBAAgB;QAC1H,IAAI,CAAC,kEAAkE,CAAC,CAAC;IAC3E,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IACrD,IAAI,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC;IACzB,IAAI,iBAAiB,GAAG,IAAI,CAAC,oBAAoB,CAAC;IAClD,IAAI,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE;QACzB,MAAM,IAAI,GAAG,YAAY,CAAC,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QACnI,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,IAAI,CAAC,gDAAgD,CAAC,CAAC;QAClF,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IACF,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,eAAe,KAAK,IAAI,CAAC,CAAC;QACtF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,mEAAmE,CAAC,CAAC;QACzG,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QACvB,IAAI,IAAI,CAAC,sBAAsB,KAAK,iBAAiB,IAAI,IAAI,CAAC,kBAAkB,KAAK,aAAa;eAC7F,CAAC,IAAI,CAAC,gBAAgB;YAAE,IAAI,CAAC,yDAAyD,CAAC,CAAC;QAC7F,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/D,oCAAoC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,6BAA6B,IAAI,CAAC,wBAAwB,UAAU,IAAI,CAAC,oBAAoB,IAAI,CAAC;eAClH,CAAC,KAAK,CAAC,QAAQ,CAAC,6BAA6B,IAAI,CAAC,sBAAsB,UAAU,IAAI,CAAC,kBAAkB,IAAI,CAAC;YACjH,IAAI,CAAC,iFAAiF,CAAC,CAAC;QAC1F,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC;QAC7B,iBAAiB,GAAG,IAAI,CAAC,wBAAwB,CAAC;QAClD,aAAa,GAAG,IAAI,CAAC,oBAAoB,CAAC;QAC1C,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS;eACpF,CAAC,CAAC,oBAAoB,KAAK,iBAAiB,IAAI,CAAC,CAAC,gBAAgB,KAAK,aAAa;eACpF,CAAC,UAAU,EAAE,yBAAyB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;eAC5D,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,KAAK,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC;eAC1F,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,QAAQ,KAAK,YAAY;mBAC7F,KAAK,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC,SAAS,KAAK,CAAC,CAAC,SAAS;mBAChE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,QAAQ;YAAE,SAAS;QACxB,6EAA6E;QAC7E,gFAAgF;QAChF,gFAAgF;QAChF,MAAM,0BAA0B,GAAG,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACtF,KAAK,MAAM,CAAC,SAAS,EAAE,cAAc,CAAC,IAAI,0BAA0B,CAAC,OAAO,EAAE,EAAE,CAAC;YAC/E,MAAM,QAAQ,GAAG,QAAQ,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;YACzD,IAAI,CAAC,QAAQ;gBAAE,OAAO,IAAI,CAAC,4EAA4E,CAAC,CAAC;YACzG,MAAM,MAAM,GAAG,cAAc,CAAC,gBAAgB,IAAI,EAAE,EAAE,cAAc,GAAG,QAAQ,CAAC,gBAAgB,IAAI,EAAE,CAAC;YACvG,IAAI,MAAM,CAAC,MAAM,KAAK,cAAc,CAAC,MAAM;gBACzC,IAAI,CAAC,8EAA8E,CAAC,CAAC;YACvF,KAAK,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;gBACnD,MAAM,aAAa,GAAG,cAAc,CAAC,UAAU,CAAE,CAAC;gBAClD,KAAK,MAAM,KAAK,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,CAAU,EAAE,CAAC;oBAClE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;wBAChD,IAAI,CAAC,2EAA2E,CAAC,CAAC;oBACpF,KAAK,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;gBACtC,CAAC;YACH,CAAC;QACH,CAAC;QACD,IAAI,sBAAsB,CAAC,QAAQ,CAAC,mBAAmB,CAAC,KAAK,sBAAsB,CAAC,0BAA0B,CAAC;YAC7G,IAAI,CAAC,qFAAqF,CAAC,CAAC;QAC9F,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,QAAQ,KAAK,YAAY;eAC/F,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ,IAAI,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,SAAS;eACtE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;QAClE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,IAAI,CAAC,0EAA0E,CAAC,CAAC;QAC1G,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,CAAC,CAAC,CAAE,EAAE,SAAS,EAAE,eAAwB,EAAE,CAAC;IACpG,CAAC;IACD,OAAO,IAAI,CAAC,4DAA4D,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,KAAqB,EAAE,IAAe;IAChF,OAAO,8BAA8B,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,OAAO,IAAI,wBAAwB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACvG,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import type { AdoptionPostureEvent, PlanRiskAuditDecision, PlanRiskAuditEvent, PlanRiskAuditStepClassification, TaskState } from '../contracts.js';
2
2
  import type { FileStateStore } from '../state/store.js';
3
+ export declare const STRUCTURAL_PRODUCTION_EDGE_AUTHORITY: "required-v1";
3
4
  export interface PlanRiskAuditBoundary {
4
5
  scope: 'current-task-steps' | 'legacy-remaining-scope';
5
6
  postureEventType: AdoptionPostureEvent['eventType'];
@@ -23,11 +24,14 @@ export declare function readPlanRiskAuditBoundary(store: FileStateStore, task: T
23
24
  export declare function readCurrentPlanRiskAudit(store: FileStateStore, task: TaskState, options?: {
24
25
  requireCurrentTaskRevision?: boolean;
25
26
  }): CurrentPlanRiskAudit | null;
27
+ /** Planning evidence only: never use as execution or authorization authority. */
28
+ export declare function readCurrentPlanningObstructionAudit(store: FileStateStore, task: TaskState): CurrentPlanRiskAudit | null;
26
29
  export declare function buildPlanRiskAuditEvent(store: FileStateStore, task: TaskState, input: RecordPlanRiskAuditInput, recordedAt: string, now?: number): {
27
30
  boundary: PlanRiskAuditBoundary;
28
31
  entityRoot: string;
29
32
  event: Omit<PlanRiskAuditEvent, 'previousEventHash' | 'eventHash'>;
30
33
  };
34
+ export declare function buildCandidatePlanRiskAuditEvent(store: FileStateStore, task: TaskState, input: RecordPlanRiskAuditInput, recordedAt: string, now?: number): ReturnType<typeof buildPlanRiskAuditEvent>;
31
35
  export declare function appendCurrentPlanRiskAudit(store: FileStateStore, task: TaskState, input: RecordPlanRiskAuditInput, now: Date): PlanRiskAuditEvent;
32
36
  export declare function validateCorrectiveReplanRiskAuditPayload(task: TaskState, event: Pick<PlanRiskAuditEvent, 'taskId' | 'taskRevision' | 'briefHash' | 'planHash' | 'knowledgeMapRevision' | 'knowledgeMapHash' | 'planner' | 'auditor' | 'summary' | 'decision' | 'splitRationale' | 'stepClassifications'>, expectedStepIds: readonly string[]): void;
33
37
  export declare function appendReboundPlanRiskAudit(store: FileStateStore, sourceTask: TaskState, reboundTask: TaskState, sourceAudit: CurrentPlanRiskAudit, now: Date): PlanRiskAuditEvent;
@@ -48,6 +48,7 @@ const GUARDED_RISK_CATEGORY_ORDER = [
48
48
  ];
49
49
  const GUARDED_RISK_CATEGORY_SET = new Set(GUARDED_RISK_CATEGORY_ORDER);
50
50
  const GUARDED_RISK_CATEGORY_INDEX = new Map(GUARDED_RISK_CATEGORY_ORDER.map((category, index) => [category, index]));
51
+ export const STRUCTURAL_PRODUCTION_EDGE_AUTHORITY = 'required-v1';
51
52
  export function validatePlanRiskAuditCandidate(store, task, input) {
52
53
  const boundary = readPlanRiskAuditBoundary(store, task);
53
54
  if (!boundary) {
@@ -92,6 +93,13 @@ export function readPlanRiskAuditBoundary(store, task) {
92
93
  };
93
94
  }
94
95
  export function readCurrentPlanRiskAudit(store, task, options = {}) {
96
+ return readCurrentAudit(store, task, options, false);
97
+ }
98
+ /** Planning evidence only: never use as execution or authorization authority. */
99
+ export function readCurrentPlanningObstructionAudit(store, task) {
100
+ return readCurrentAudit(store, task, {}, true);
101
+ }
102
+ function readCurrentAudit(store, task, options, allowBlocking) {
95
103
  const boundary = readPlanRiskAuditBoundary(store, task);
96
104
  if (!boundary)
97
105
  return null;
@@ -108,7 +116,7 @@ export function readCurrentPlanRiskAudit(store, task, options = {}) {
108
116
  sidecar: PLAN_RISK_AUDIT_SIDECAR,
109
117
  });
110
118
  }
111
- const reviewRequiredStepIds = validateCurrentPlanRiskAudit(store, task, audit, boundary.expectedStepIds, options);
119
+ const reviewRequiredStepIds = validateCurrentPlanRiskAudit(store, task, audit, boundary.expectedStepIds, options, allowBlocking);
112
120
  return {
113
121
  ...boundary,
114
122
  audit,
@@ -116,6 +124,12 @@ export function readCurrentPlanRiskAudit(store, task, options = {}) {
116
124
  };
117
125
  }
118
126
  export function buildPlanRiskAuditEvent(store, task, input, recordedAt, now = Date.now()) {
127
+ return buildPlanRiskAuditEventWithAuthority(store, task, input, recordedAt, now, true, true);
128
+ }
129
+ export function buildCandidatePlanRiskAuditEvent(store, task, input, recordedAt, now = Date.now()) {
130
+ return buildPlanRiskAuditEventWithAuthority(store, task, input, recordedAt, now, true, false);
131
+ }
132
+ function buildPlanRiskAuditEventWithAuthority(store, task, input, recordedAt, now, bindStructuralProductionEdgeAuthority, requireStoredPlan) {
119
133
  const boundary = readPlanRiskAuditBoundary(store, task);
120
134
  if (!boundary) {
121
135
  throw new WorkflowError('TRANSITION_BLOCKED', 'Plan Risk Audit recording requires an active adoption posture boundary.', { taskId: task.id, sidecar: ADOPTION_POSTURE_SIDECAR });
@@ -123,14 +137,14 @@ export function buildPlanRiskAuditEvent(store, task, input, recordedAt, now = Da
123
137
  assertRecordableTask(task);
124
138
  const entityRoot = store.taskRoot(task.projectId, task.id);
125
139
  const briefHash = store.hashArtifact(entityRoot, 'brief.md');
126
- const planHash = store.hashArtifact(entityRoot, 'plan.md');
127
- if (task.briefHash !== briefHash || task.planHash !== planHash) {
140
+ const planHash = requireStoredPlan ? store.hashArtifact(entityRoot, 'plan.md') : task.planHash;
141
+ if (!planHash || task.briefHash !== briefHash || (requireStoredPlan && task.planHash !== planHash)) {
128
142
  throw new WorkflowError('STATE_CORRUPT', 'Task state does not match the current Brief or Plan artifacts required for Plan Risk Audit recording.', {
129
143
  taskId: task.id,
130
144
  stateBriefHash: task.briefHash,
131
145
  currentBriefHash: briefHash,
132
146
  statePlanHash: task.planHash,
133
- currentPlanHash: planHash,
147
+ currentPlanHash: planHash ?? null,
134
148
  });
135
149
  }
136
150
  if (task.knowledgeMapRevision === null || !task.knowledgeMapHash) {
@@ -153,6 +167,9 @@ export function buildPlanRiskAuditEvent(store, task, input, recordedAt, now = Da
153
167
  value: input.decision,
154
168
  }),
155
169
  splitRationale: normalizeOptionalNonEmptyString(input.splitRationale, 'Plan Risk Audit splitRationale'),
170
+ ...(bindStructuralProductionEdgeAuthority
171
+ ? { structuralProductionEdgeAuthority: STRUCTURAL_PRODUCTION_EDGE_AUTHORITY }
172
+ : {}),
156
173
  stepClassifications: normalizePlanRiskClassifications(input.stepClassifications, 'INVALID_ARGUMENT', {
157
174
  taskId: task.id,
158
175
  }),
@@ -160,7 +177,7 @@ export function buildPlanRiskAuditEvent(store, task, input, recordedAt, now = Da
160
177
  validatePlanRiskAuditPayload(task, event, boundary.expectedStepIds, 'INVALID_ARGUMENT', {
161
178
  taskId: task.id,
162
179
  expectedStepIds: boundary.expectedStepIds,
163
- });
180
+ }, true, bindStructuralProductionEdgeAuthority);
164
181
  return {
165
182
  boundary,
166
183
  entityRoot,
@@ -168,7 +185,10 @@ export function buildPlanRiskAuditEvent(store, task, input, recordedAt, now = Da
168
185
  };
169
186
  }
170
187
  export function appendCurrentPlanRiskAudit(store, task, input, now) {
171
- const prepared = buildPlanRiskAuditEvent(store, task, input, now.toISOString(), now.getTime());
188
+ return appendPlanRiskAuditWithAuthority(store, task, input, now, true);
189
+ }
190
+ function appendPlanRiskAuditWithAuthority(store, task, input, now, bindStructuralProductionEdgeAuthority) {
191
+ const prepared = buildPlanRiskAuditEventWithAuthority(store, task, input, now.toISOString(), now.getTime(), bindStructuralProductionEdgeAuthority, true);
172
192
  const existingEvents = readPlanRiskAuditEvents(store, task);
173
193
  assertPlanRiskAuditAppendAllowed(task, prepared.boundary, existingEvents);
174
194
  return store.appendSidecarEvent(prepared.entityRoot, PLAN_RISK_AUDIT_SIDECAR, prepared.event, {
@@ -183,7 +203,12 @@ export function validateCorrectiveReplanRiskAuditPayload(task, event, expectedSt
183
203
  }
184
204
  export function appendReboundPlanRiskAudit(store, sourceTask, reboundTask, sourceAudit, now) {
185
205
  assertReboundPlanRiskAuditAllowed(store, sourceTask, reboundTask, sourceAudit);
186
- return appendCurrentPlanRiskAudit(store, reboundTask, {
206
+ const sourceHasStructuralProductionEdgeAuthority = sourceAudit.audit.structuralProductionEdgeAuthority !== undefined
207
+ || Object.hasOwn(sourceTask, 'requiresProductionEdges')
208
+ || Object.hasOwn(sourceTask, 'productionEdges')
209
+ || Object.hasOwn(reboundTask, 'requiresProductionEdges')
210
+ || Object.hasOwn(reboundTask, 'productionEdges');
211
+ return appendPlanRiskAuditWithAuthority(store, reboundTask, {
187
212
  planner: sourceAudit.audit.planner,
188
213
  auditor: sourceAudit.audit.auditor,
189
214
  summary: `${sourceAudit.audit.summary} Rebound automatically after content-only Task context refresh.`,
@@ -198,7 +223,7 @@ export function appendReboundPlanRiskAudit(store, sourceTask, reboundTask, sourc
198
223
  ? { proofObligations: classification.proofObligations.map((obligation) => ({ ...obligation })) }
199
224
  : {}),
200
225
  })),
201
- }, now);
226
+ }, now, sourceHasStructuralProductionEdgeAuthority);
202
227
  }
203
228
  function readCurrentAdoptionPosture(store, projectId) {
204
229
  const sidecarFile = path.join(store.projectRoot(projectId), ADOPTION_POSTURE_SIDECAR);
@@ -468,13 +493,16 @@ function validateAdoptionBaseline(task, baseline, currentTaskStepIds, posture) {
468
493
  }
469
494
  }
470
495
  function validateStoredPlanRiskAuditEvent(event, task, file, line) {
496
+ const hasStructuralAuthorityBoundary = event.planHash === task.planHash && (event.structuralProductionEdgeAuthority !== undefined
497
+ || Object.hasOwn(task, 'requiresProductionEdges')
498
+ || Object.hasOwn(task, 'productionEdges'));
471
499
  validatePlanRiskAuditPayload(task, event, null, 'STATE_CORRUPT', {
472
500
  file,
473
501
  line,
474
502
  eventId: event.eventId,
475
- }, false);
503
+ }, false, hasStructuralAuthorityBoundary);
476
504
  }
477
- function validatePlanRiskAuditPayload(task, event, expectedStepIds, errorCode, details, requireCurrentStepChecks = true) {
505
+ function validatePlanRiskAuditPayload(task, event, expectedStepIds, errorCode, details, requireCurrentStepChecks = true, requireStructuralProductionEdgeAuthority = true) {
478
506
  if (event.taskId !== task.id) {
479
507
  throw new WorkflowError(errorCode, 'Plan Risk Audit task binding does not match its task root.', {
480
508
  ...details,
@@ -500,11 +528,20 @@ function validatePlanRiskAuditPayload(task, event, expectedStepIds, errorCode, d
500
528
  normalizeNonEmptyString(event.summary, 'Plan Risk Audit summary', { code: errorCode, ...details });
501
529
  normalizePlanRiskDecision(event.decision, errorCode, details);
502
530
  normalizeOptionalNonEmptyString(event.splitRationale, 'Plan Risk Audit splitRationale', { code: errorCode, ...details });
531
+ if (event.structuralProductionEdgeAuthority !== undefined
532
+ && event.structuralProductionEdgeAuthority !== STRUCTURAL_PRODUCTION_EDGE_AUTHORITY) {
533
+ throw new WorkflowError(errorCode, 'Plan Risk Audit structural production-edge authority marker is invalid.', {
534
+ ...details,
535
+ structuralProductionEdgeAuthority: event.structuralProductionEdgeAuthority,
536
+ });
537
+ }
503
538
  if (!Array.isArray(event.stepClassifications)) {
504
539
  throw new WorkflowError(errorCode, 'Plan Risk Audit stepClassifications must be an array.', details);
505
540
  }
506
541
  validateStepClassificationSet(task, event.stepClassifications, event.decision, event.splitRationale, expectedStepIds, errorCode, details, requireCurrentStepChecks);
507
- validateStructuralProductionEdgeAuthority(task, event.stepClassifications);
542
+ if (requireStructuralProductionEdgeAuthority) {
543
+ validateStructuralProductionEdgeAuthority(task, event.stepClassifications);
544
+ }
508
545
  }
509
546
  function validateStepClassificationSet(task, classifications, decision, splitRationale, expectedStepIds, errorCode, details, requireCurrentStepChecks = true) {
510
547
  const currentTaskStepIds = new Set(task.steps.map((step) => step.id));
@@ -572,7 +609,7 @@ function validateStepClassificationSet(task, classifications, decision, splitRat
572
609
  });
573
610
  }
574
611
  }
575
- function validateCurrentPlanRiskAudit(store, task, audit, expectedStepIds, options) {
612
+ function validateCurrentPlanRiskAudit(store, task, audit, expectedStepIds, options, allowBlocking = false) {
576
613
  const taskRoot = store.taskRoot(task.projectId, task.id);
577
614
  const briefHash = store.hashArtifact(taskRoot, 'brief.md');
578
615
  const planHash = store.hashArtifact(taskRoot, 'plan.md');
@@ -617,7 +654,7 @@ function validateCurrentPlanRiskAudit(store, task, audit, expectedStepIds, optio
617
654
  auditEventId: audit.eventId,
618
655
  expectedStepIds,
619
656
  });
620
- if (audit.decision === 'split-required' || audit.decision === 'stop-escalate') {
657
+ if (!allowBlocking && (audit.decision === 'split-required' || audit.decision === 'stop-escalate')) {
621
658
  throw new WorkflowError('TRANSITION_BLOCKED', `Plan Risk Audit decision ${audit.decision} blocks execution authorization.`, {
622
659
  taskId: task.id,
623
660
  auditEventId: audit.eventId,