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.
- package/README.md +6 -1
- package/dist/reviewer-runtime-build.json +44 -20
- package/dist/src/alpha6/failed-step-planning-recovery.d.ts +10 -0
- package/dist/src/alpha6/failed-step-planning-recovery.js +93 -0
- package/dist/src/alpha6/failed-step-planning-recovery.js.map +1 -0
- package/dist/src/alpha6/plan-risk.d.ts +4 -0
- package/dist/src/alpha6/plan-risk.js +50 -13
- package/dist/src/alpha6/plan-risk.js.map +1 -1
- package/dist/src/alpha6/preexecution-replan.d.ts +38 -0
- package/dist/src/alpha6/preexecution-replan.js +130 -0
- package/dist/src/alpha6/preexecution-replan.js.map +1 -0
- package/dist/src/alpha6/remediation.d.ts +4 -2
- package/dist/src/alpha6/remediation.js +155 -20
- package/dist/src/alpha6/remediation.js.map +1 -1
- package/dist/src/alpha6/root-cause-replan-carryover.d.ts +18 -0
- package/dist/src/alpha6/root-cause-replan-carryover.js +396 -0
- package/dist/src/alpha6/root-cause-replan-carryover.js.map +1 -0
- package/dist/src/alpha7/autonomy.d.ts +3 -0
- package/dist/src/alpha7/autonomy.js +89 -42
- package/dist/src/alpha7/autonomy.js.map +1 -1
- package/dist/src/change-explanation.d.ts +64 -0
- package/dist/src/change-explanation.js +150 -0
- package/dist/src/change-explanation.js.map +1 -0
- package/dist/src/cli-actions.d.ts +3 -2
- package/dist/src/cli-actions.js +6 -0
- package/dist/src/cli-actions.js.map +1 -1
- package/dist/src/cli.js +73 -1
- package/dist/src/cli.js.map +1 -1
- package/dist/src/contracts.d.ts +38 -0
- package/dist/src/dependency-provenance.d.ts +3 -2
- package/dist/src/dependency-provenance.js +33 -2
- package/dist/src/dependency-provenance.js.map +1 -1
- package/dist/src/domain/plan-semantics.d.ts +11 -0
- package/dist/src/domain/plan-semantics.js +49 -0
- package/dist/src/domain/plan-semantics.js.map +1 -0
- package/dist/src/gateway-handshake.js +2 -0
- package/dist/src/gateway-handshake.js.map +1 -1
- package/dist/src/lifecycle/corrective-replan.js +3 -3
- package/dist/src/lifecycle/corrective-replan.js.map +1 -1
- package/dist/src/observed-routes.js +1 -0
- package/dist/src/observed-routes.js.map +1 -1
- package/dist/src/pending-review-update.d.ts +49 -0
- package/dist/src/pending-review-update.js +132 -0
- package/dist/src/pending-review-update.js.map +1 -0
- package/dist/src/repository.js +16 -4
- package/dist/src/repository.js.map +1 -1
- package/dist/src/reviewer.js +4 -1
- package/dist/src/reviewer.js.map +1 -1
- package/dist/src/state/corrective-replan-executor.js +3 -1
- package/dist/src/state/corrective-replan-executor.js.map +1 -1
- package/dist/src/state/corrective-replan-public.js +5 -4
- package/dist/src/state/corrective-replan-public.js.map +1 -1
- package/dist/src/state/corrective-yield-executor.js +12 -3
- package/dist/src/state/corrective-yield-executor.js.map +1 -1
- package/dist/src/state/store.d.ts +1 -1
- package/dist/src/state/store.js +17 -3
- package/dist/src/state/store.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/src/workflow.d.ts +84 -1
- package/dist/src/workflow.js +1616 -355
- package/dist/src/workflow.js.map +1 -1
- package/docs/beta13.2-signal-review-recovery.md +38 -0
- package/docs/change-model.md +118 -0
- package/docs/delegated-approval.md +26 -0
- package/docs/pdf/codex-workflow-v2-architecture-ru.pdf +0 -0
- package/docs/pdf/codex-workflow-v2-chat-only-guide-ru.pdf +0 -0
- package/docs/pdf/codex-workflow-v2-technical-reference-ru.pdf +0 -0
- package/docs/pdf/sources/codex-workflow-v2-architecture-ru.md +9 -1
- package/docs/pdf/sources/codex-workflow-v2-chat-only-guide-ru.md +9 -5
- package/docs/pdf/sources/codex-workflow-v2-technical-reference-ru.md +18 -3
- package/docs/pending-review-update.md +15 -0
- package/docs/release.md +267 -2
- package/docs/updating-existing-project.md +36 -6
- package/docs/validation-report.md +30 -9
- package/package.json +2 -1
- package/plugins/codex-workflow-gateway/references/chat-dispatch.md +204 -0
- package/plugins/codex-workflow-gateway/references/protocol.md +11 -0
- package/plugins/codex-workflow-gateway/scripts/chat-dispatch.mjs +298 -0
- package/plugins/codex-workflow-gateway/scripts/chat-model-policy.mjs +43 -0
- package/plugins/codex-workflow-gateway/scripts/chat-registry.mjs +55 -3
- package/plugins/codex-workflow-gateway/skills/codex-workflow-gateway/SKILL.md +218 -21
- package/schemas/plan-risk-audit-event.schema.json +1 -0
- package/schemas/preexecution-replan-event.schema.json +45 -0
- 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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
107
|
+
"sha256": "184d6bc81d09b06c4bb7b36d8e25dffeea3adf9b5f6671830a12a857b58b682a"
|
|
92
108
|
},
|
|
93
109
|
{
|
|
94
110
|
"path": "dist/src/cli.js",
|
|
95
|
-
"sha256": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
279
|
+
"sha256": "e222267fc52cbf6c9bcaf1fca9307ce9eafd745bdb7cc4dae3b549d77ec213ca"
|
|
256
280
|
},
|
|
257
281
|
{
|
|
258
282
|
"path": "dist/src/reviewer.js",
|
|
259
|
-
"sha256": "
|
|
283
|
+
"sha256": "a1a85660dbaecf3a5f8bca7c563d9b5dc2b533b901a330a1f8033645de36d30d"
|
|
260
284
|
},
|
|
261
285
|
{
|
|
262
286
|
"path": "dist/src/state/corrective-replan-executor.js",
|
|
263
|
-
"sha256": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
327
|
+
"sha256": "70af01eb723d930fc8a9ef129c9025924bd68f8d1a94d56c6318a6c251b9e374"
|
|
304
328
|
},
|
|
305
329
|
{
|
|
306
330
|
"path": "dist/src/workflow.js",
|
|
307
|
-
"sha256": "
|
|
331
|
+
"sha256": "c72cc02fa5137fb332408d895e73a06facae0907bdecd812062abe3a2ad85282"
|
|
308
332
|
}
|
|
309
333
|
],
|
|
310
334
|
"runtimeDependencies": [
|
|
@@ -1088,5 +1112,5 @@
|
|
|
1088
1112
|
]
|
|
1089
1113
|
}
|
|
1090
1114
|
],
|
|
1091
|
-
"fingerprint": "
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|