@openprose/reactor-cradle 0.1.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +270 -0
  3. package/dist/assert/index.d.ts +35 -0
  4. package/dist/assert/index.d.ts.map +1 -0
  5. package/dist/assert/index.js +398 -0
  6. package/dist/baselines/cost-thesis/index.d.ts +103 -0
  7. package/dist/baselines/cost-thesis/index.d.ts.map +1 -0
  8. package/dist/baselines/cost-thesis/index.js +337 -0
  9. package/dist/baselines/naive-loop/index.d.ts +46 -0
  10. package/dist/baselines/naive-loop/index.d.ts.map +1 -0
  11. package/dist/baselines/naive-loop/index.js +188 -0
  12. package/dist/baselines/no-memo/index.d.ts +84 -0
  13. package/dist/baselines/no-memo/index.d.ts.map +1 -0
  14. package/dist/baselines/no-memo/index.js +226 -0
  15. package/dist/doubles/clock.d.ts +9 -0
  16. package/dist/doubles/clock.d.ts.map +1 -0
  17. package/dist/doubles/clock.js +42 -0
  18. package/dist/doubles/storage.d.ts +24 -0
  19. package/dist/doubles/storage.d.ts.map +1 -0
  20. package/dist/doubles/storage.js +191 -0
  21. package/dist/eval/index.d.ts +204 -0
  22. package/dist/eval/index.d.ts.map +1 -0
  23. package/dist/eval/index.js +596 -0
  24. package/dist/index.d.ts +24 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +39 -0
  27. package/dist/policy-author/index.d.ts +103 -0
  28. package/dist/policy-author/index.d.ts.map +1 -0
  29. package/dist/policy-author/index.js +358 -0
  30. package/dist/policy-drift/index.d.ts +64 -0
  31. package/dist/policy-drift/index.d.ts.map +1 -0
  32. package/dist/policy-drift/index.js +495 -0
  33. package/dist/policy-replay/index.d.ts +106 -0
  34. package/dist/policy-replay/index.d.ts.map +1 -0
  35. package/dist/policy-replay/index.js +361 -0
  36. package/dist/provider-parity/index.d.ts +91 -0
  37. package/dist/provider-parity/index.d.ts.map +1 -0
  38. package/dist/provider-parity/index.js +439 -0
  39. package/dist/recompile/index.d.ts +161 -0
  40. package/dist/recompile/index.d.ts.map +1 -0
  41. package/dist/recompile/index.js +690 -0
  42. package/dist/release-candidate/index.d.ts +139 -0
  43. package/dist/release-candidate/index.d.ts.map +1 -0
  44. package/dist/release-candidate/index.js +553 -0
  45. package/dist/release-parity/index.d.ts +80 -0
  46. package/dist/release-parity/index.d.ts.map +1 -0
  47. package/dist/release-parity/index.js +1035 -0
  48. package/dist/replay/model-gateway.d.ts +25 -0
  49. package/dist/replay/model-gateway.d.ts.map +1 -0
  50. package/dist/replay/model-gateway.js +166 -0
  51. package/dist/replay/parity.d.ts +110 -0
  52. package/dist/replay/parity.d.ts.map +1 -0
  53. package/dist/replay/parity.js +232 -0
  54. package/dist/rollback/index.d.ts +106 -0
  55. package/dist/rollback/index.d.ts.map +1 -0
  56. package/dist/rollback/index.js +694 -0
  57. package/dist/scenario/parser.d.ts +11 -0
  58. package/dist/scenario/parser.d.ts.map +1 -0
  59. package/dist/scenario/parser.js +490 -0
  60. package/dist/scenario/runner.d.ts +12 -0
  61. package/dist/scenario/runner.d.ts.map +1 -0
  62. package/dist/scenario/runner.js +345 -0
  63. package/dist/scenario/synthetic-world-adapter.d.ts +4 -0
  64. package/dist/scenario/synthetic-world-adapter.d.ts.map +1 -0
  65. package/dist/scenario/synthetic-world-adapter.js +82 -0
  66. package/dist/scenario/time.d.ts +4 -0
  67. package/dist/scenario/time.d.ts.map +1 -0
  68. package/dist/scenario/time.js +45 -0
  69. package/dist/scenario/types.d.ts +149 -0
  70. package/dist/scenario/types.d.ts.map +1 -0
  71. package/dist/scenario/types.js +5 -0
  72. package/dist/spikes/index.d.ts +10 -0
  73. package/dist/spikes/index.d.ts.map +1 -0
  74. package/dist/spikes/index.js +29 -0
  75. package/dist/spikes/k1-ensemble-spread.d.ts +88 -0
  76. package/dist/spikes/k1-ensemble-spread.d.ts.map +1 -0
  77. package/dist/spikes/k1-ensemble-spread.js +396 -0
  78. package/dist/spikes/k2-policy-author.d.ts +25 -0
  79. package/dist/spikes/k2-policy-author.d.ts.map +1 -0
  80. package/dist/spikes/k2-policy-author.js +503 -0
  81. package/dist/spikes/live-refresh.d.ts +150 -0
  82. package/dist/spikes/live-refresh.d.ts.map +1 -0
  83. package/dist/spikes/live-refresh.js +511 -0
  84. package/dist/world/index.d.ts +2 -0
  85. package/dist/world/index.d.ts.map +1 -0
  86. package/dist/world/index.js +17 -0
  87. package/dist/world/synthetic-world.d.ts +104 -0
  88. package/dist/world/synthetic-world.d.ts.map +1 -0
  89. package/dist/world/synthetic-world.js +449 -0
  90. package/package.json +139 -0
@@ -0,0 +1,694 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PLAN_INCOMPLETE_D2_BACKSTOP_FACT = exports.PLAN_INCOMPLETE_D2_MISSING_SOURCE_ID = exports.ROLLBACK_D2_RESPONSIBILITY_ID = exports.PLAN_INCOMPLETE_D2_SCENARIO_VERSION_V0 = exports.PLAN_INCOMPLETE_D2_SCENARIO_SCHEMA_V0 = exports.POLICY_ROLLBACK_D2_SCENARIO_VERSION_V0 = exports.POLICY_ROLLBACK_D2_SCENARIO_SCHEMA_V0 = void 0;
4
+ exports.makeRecordedPolicyRollbackD2ScenarioV0 = makeRecordedPolicyRollbackD2ScenarioV0;
5
+ exports.assertRecordedPolicyRollbackD2ScenarioV0 = assertRecordedPolicyRollbackD2ScenarioV0;
6
+ exports.runRecordedPolicyRollbackD2ProofV0 = runRecordedPolicyRollbackD2ProofV0;
7
+ exports.createRecordedPolicyRollbackPlannerDoubleV0 = createRecordedPolicyRollbackPlannerDoubleV0;
8
+ exports.normalizePolicyRollbackDecisionV0 = normalizePolicyRollbackDecisionV0;
9
+ exports.makeRecordedPlanIncompleteD2ScenarioV0 = makeRecordedPlanIncompleteD2ScenarioV0;
10
+ exports.assertRecordedPlanIncompleteD2ScenarioV0 = assertRecordedPlanIncompleteD2ScenarioV0;
11
+ exports.runRecordedPlanIncompleteD2ProofV0 = runRecordedPlanIncompleteD2ProofV0;
12
+ const node_crypto_1 = require("node:crypto");
13
+ const recompile_1 = require("../recompile");
14
+ const { executeShallowEvidencePlan, reconcileDeepRoam, } = loadReactorEvidencePlan();
15
+ const { POLICY_ARTIFACT_SCHEMA, POLICY_ARTIFACT_VERSION, POLICY_AUTHOR_HISTORY_QUERY_SCHEMA, validatePolicyArtifactV0, } = loadReactorPolicy();
16
+ const { canonicalizeForReceiptV0, createReceiptV0, hashCanonicalReceiptV0, verifyReceiptV0, } = loadReactorReceipt();
17
+ exports.POLICY_ROLLBACK_D2_SCENARIO_SCHEMA_V0 = "openprose.reactor-cradle.rollback-d2-scenario";
18
+ exports.POLICY_ROLLBACK_D2_SCENARIO_VERSION_V0 = 0;
19
+ exports.PLAN_INCOMPLETE_D2_SCENARIO_SCHEMA_V0 = "openprose.reactor-cradle.plan-incomplete-d2-scenario";
20
+ exports.PLAN_INCOMPLETE_D2_SCENARIO_VERSION_V0 = 0;
21
+ exports.ROLLBACK_D2_RESPONSIBILITY_ID = "incident-channel-current-briefing";
22
+ exports.PLAN_INCOMPLETE_D2_MISSING_SOURCE_ID = "crm-owner-map";
23
+ exports.PLAN_INCOMPLETE_D2_BACKSTOP_FACT = "kernel.deep_shallow_contradiction_count_7d";
24
+ function makeRecordedPolicyRollbackD2ScenarioV0() {
25
+ return {
26
+ schema: exports.POLICY_ROLLBACK_D2_SCENARIO_SCHEMA_V0,
27
+ v: exports.POLICY_ROLLBACK_D2_SCENARIO_VERSION_V0,
28
+ responsibility_id: exports.ROLLBACK_D2_RESPONSIBILITY_ID,
29
+ contract_revision: hashText([
30
+ "kind: responsibility",
31
+ "Goal: The incident channel has a current, accurate briefing.",
32
+ "Criteria: owner, impact, timeline, and next action are current.",
33
+ ].join("\n")),
34
+ as_of: "2026-05-19T12:00:00.000Z",
35
+ fresh_policy: {
36
+ policy_revision: "policy.d2.fresh-trips-early",
37
+ judged_activations_before_trip: 3,
38
+ activated_at: "2026-05-19T08:00:00.000Z",
39
+ first_trip_at: "2026-05-19T12:00:00.000Z",
40
+ },
41
+ last_known_good_policy: {
42
+ policy_revision: "policy.d2.last-known-good",
43
+ judged_activations_before_trip: 9,
44
+ activated_at: "2026-05-18T11:45:00.000Z",
45
+ first_trip_at: "2026-05-18T12:00:00.000Z",
46
+ },
47
+ };
48
+ }
49
+ function assertRecordedPolicyRollbackD2ScenarioV0(scenario) {
50
+ if (scenario.schema !== exports.POLICY_ROLLBACK_D2_SCENARIO_SCHEMA_V0) {
51
+ throw new Error("policy rollback D2 scenario schema is malformed");
52
+ }
53
+ if (scenario.v !== exports.POLICY_ROLLBACK_D2_SCENARIO_VERSION_V0) {
54
+ throw new Error("policy rollback D2 scenario version must be 0");
55
+ }
56
+ if (scenario.responsibility_id.length === 0) {
57
+ throw new Error("policy rollback D2 scenario responsibility_id is required");
58
+ }
59
+ if (!isContentHash(scenario.contract_revision)) {
60
+ throw new Error("policy rollback D2 scenario contract_revision must be a sha256 content hash");
61
+ }
62
+ parseReplayableInstantMs(scenario.as_of, "policy rollback D2 scenario as_of");
63
+ assertTripSummary(scenario.fresh_policy, "fresh_policy");
64
+ assertTripSummary(scenario.last_known_good_policy, "last_known_good_policy");
65
+ if (scenario.fresh_policy.judged_activations_before_trip >=
66
+ scenario.last_known_good_policy.judged_activations_before_trip) {
67
+ throw new Error("policy rollback D2 scenario must make the fresh policy trip in fewer judged activations");
68
+ }
69
+ }
70
+ async function runRecordedPolicyRollbackD2ProofV0(input) {
71
+ const scenario = input.scenario ?? makeRecordedPolicyRollbackD2ScenarioV0();
72
+ assertRecordedPolicyRollbackD2ScenarioV0(scenario);
73
+ const decision = normalizePolicyRollbackDecisionV0(await input.planPolicyRollbackV0(buildRollbackPlanInput(scenario)));
74
+ assertRollbackDecision(decision, scenario);
75
+ return {
76
+ scenario,
77
+ decision,
78
+ gateway_invocations: {
79
+ agent_launch_count: 0,
80
+ model_gateway_invocation_count: 0,
81
+ },
82
+ };
83
+ }
84
+ function createRecordedPolicyRollbackPlannerDoubleV0() {
85
+ return (input) => {
86
+ assertPositiveSafeInteger(input.fresh_policy_judged_activations_before_trip, "fresh_policy_judged_activations_before_trip");
87
+ if (input.last_known_good_revision === undefined ||
88
+ input.last_known_good_judged_activations_before_trip === undefined) {
89
+ return {
90
+ schema: "openprose.reactor-cradle.rollback-d2-planner-double",
91
+ v: 0,
92
+ outcome: "no-last-known-good",
93
+ fresh_policy_revision: input.fresh_policy_revision,
94
+ fresh_policy_judged_activations_before_trip: input.fresh_policy_judged_activations_before_trip,
95
+ };
96
+ }
97
+ assertPositiveSafeInteger(input.last_known_good_judged_activations_before_trip, "last_known_good_judged_activations_before_trip");
98
+ const outcome = input.fresh_policy_judged_activations_before_trip <
99
+ input.last_known_good_judged_activations_before_trip
100
+ ? "rollback"
101
+ : "keep-current";
102
+ return {
103
+ schema: "openprose.reactor-cradle.rollback-d2-planner-double",
104
+ v: 0,
105
+ outcome,
106
+ fresh_policy_revision: input.fresh_policy_revision,
107
+ fresh_policy_judged_activations_before_trip: input.fresh_policy_judged_activations_before_trip,
108
+ last_known_good_revision: input.last_known_good_revision,
109
+ last_known_good_judged_activations_before_trip: input.last_known_good_judged_activations_before_trip,
110
+ target_policy_revision: outcome === "rollback"
111
+ ? input.last_known_good_revision
112
+ : input.fresh_policy_revision,
113
+ };
114
+ };
115
+ }
116
+ function normalizePolicyRollbackDecisionV0(result) {
117
+ if (!isRecord(result)) {
118
+ throw new Error("policy rollback decision must be an object");
119
+ }
120
+ const freshPolicy = readOptionalRecord(result["fresh_policy"]);
121
+ const lastKnownGood = readOptionalRecord(result["last_known_good_policy"] ?? result["last_known_good"]);
122
+ const outcome = readRollbackOutcome(result["outcome"] ?? result["decision"] ?? result["status"] ?? result["kind"]);
123
+ const freshPolicyRevision = readNonEmptyString(result["fresh_policy_revision"] ?? freshPolicy?.["policy_revision"] ?? freshPolicy?.["revision"], "policy rollback fresh_policy_revision");
124
+ const freshTripCount = readSafeInteger(result["fresh_policy_judged_activations_before_trip"] ??
125
+ result["fresh_judged_activations_before_trip"] ??
126
+ freshPolicy?.["judged_activations_before_trip"], "policy rollback fresh_policy_judged_activations_before_trip");
127
+ const lastKnownGoodRevision = readOptionalNonEmptyString(result["last_known_good_revision"] ??
128
+ lastKnownGood?.["policy_revision"] ??
129
+ lastKnownGood?.["revision"], "policy rollback last_known_good_revision");
130
+ const lastKnownGoodTripCount = readOptionalSafeInteger(result["last_known_good_judged_activations_before_trip"] ??
131
+ result["last_known_good_policy_judged_activations_before_trip"] ??
132
+ lastKnownGood?.["judged_activations_before_trip"], "policy rollback last_known_good_judged_activations_before_trip");
133
+ const targetPolicyRevision = readOptionalNonEmptyString(result["target_policy_revision"] ??
134
+ result["target_revision"] ??
135
+ result["rollback_target_policy_revision"], "policy rollback target_policy_revision");
136
+ return {
137
+ outcome,
138
+ fresh_policy_revision: freshPolicyRevision,
139
+ fresh_policy_judged_activations_before_trip: freshTripCount,
140
+ ...(lastKnownGoodRevision === undefined
141
+ ? {}
142
+ : { last_known_good_revision: lastKnownGoodRevision }),
143
+ ...(lastKnownGoodTripCount === undefined
144
+ ? {}
145
+ : {
146
+ last_known_good_judged_activations_before_trip: lastKnownGoodTripCount,
147
+ }),
148
+ ...(targetPolicyRevision === undefined
149
+ ? {}
150
+ : { target_policy_revision: targetPolicyRevision }),
151
+ raw: result,
152
+ };
153
+ }
154
+ function makeRecordedPlanIncompleteD2ScenarioV0() {
155
+ const contractRevision = hashText([
156
+ "kind: responsibility",
157
+ "Goal: The incident channel has a current, accurate briefing.",
158
+ "Criteria: owner map must be consulted before declaring the next action current.",
159
+ ].join("\n"));
160
+ const responsibilityId = exports.ROLLBACK_D2_RESPONSIBILITY_ID;
161
+ const asOf = "2026-05-19T12:00:00.000Z";
162
+ const plannedReceipt = makeReceipt({
163
+ responsibility_id: responsibilityId,
164
+ contract_revision: contractRevision,
165
+ source_id: "incident-feed",
166
+ memo_key: "memo:incident-feed",
167
+ as_of: "2026-05-19T11:55:00.000Z",
168
+ next_forecast_recheck: asOf,
169
+ event_cause: "real-input",
170
+ role: "judge",
171
+ evidence_input_ids: [hashText("incident feed says status is green")],
172
+ status: "up",
173
+ fresh: 0,
174
+ reused: 4,
175
+ tags: ["plan-incomplete-d2", "shallow-plan", "incident-feed"],
176
+ });
177
+ const planAgeReceipt = makeReceipt({
178
+ responsibility_id: responsibilityId,
179
+ contract_revision: contractRevision,
180
+ source_id: "plan-age-clock",
181
+ memo_key: "memo:plan-age-clock",
182
+ as_of: asOf,
183
+ next_forecast_recheck: "2026-05-20T12:00:00.000Z",
184
+ event_cause: "forecast-recheck",
185
+ role: "judge",
186
+ evidence_input_ids: [hashText("plan age clock crossed audit threshold")],
187
+ status: "up",
188
+ fresh: 0,
189
+ reused: 1,
190
+ tags: ["plan-incomplete-d2", "plan-age"],
191
+ });
192
+ const missingDependencyReceipt = makeReceipt({
193
+ responsibility_id: responsibilityId,
194
+ contract_revision: contractRevision,
195
+ source_id: exports.PLAN_INCOMPLETE_D2_MISSING_SOURCE_ID,
196
+ memo_key: "memo:crm-owner-map",
197
+ as_of: asOf,
198
+ next_forecast_recheck: "2026-05-20T12:00:00.000Z",
199
+ event_cause: "real-input",
200
+ role: "judge",
201
+ evidence_input_ids: [hashText("CRM owner map says owner changed")],
202
+ status: "drifting",
203
+ fresh: 0,
204
+ reused: 1,
205
+ tags: ["plan-incomplete-d2", "deep-roam", exports.PLAN_INCOMPLETE_D2_MISSING_SOURCE_ID],
206
+ });
207
+ const planIncompleteReceipt = makeReceipt({
208
+ responsibility_id: responsibilityId,
209
+ contract_revision: contractRevision,
210
+ source_id: "plan-incomplete-backstop",
211
+ memo_key: "memo:plan-incomplete-backstop",
212
+ as_of: asOf,
213
+ next_forecast_recheck: asOf,
214
+ event_cause: "escalation",
215
+ role: "judge",
216
+ evidence_input_ids: [missingDependencyReceipt.content_hash],
217
+ status: "blocked",
218
+ blocked_reason: "backstop-divergence",
219
+ fix_target: "policy-artifact",
220
+ fresh: 0,
221
+ reused: 0,
222
+ tags: [
223
+ "plan-incomplete-d2",
224
+ "backstop-divergence",
225
+ "deep-shallow-contradiction",
226
+ ],
227
+ });
228
+ const oldReceiptHistory = [plannedReceipt, planAgeReceipt];
229
+ const policyArtifact = makePlanIncompletePolicyArtifact({
230
+ responsibility_id: responsibilityId,
231
+ contract_revision: contractRevision,
232
+ receipt_history: oldReceiptHistory,
233
+ });
234
+ const validation = validatePolicyArtifactV0(policyArtifact);
235
+ if (!validation.ok) {
236
+ throw new Error(`recorded plan-incomplete D2 policy artifact is invalid: ${validation.errors.join("; ")}`);
237
+ }
238
+ const incompletePlan = {
239
+ responsibility_id: responsibilityId,
240
+ contract_revision: contractRevision,
241
+ policy_artifact_namespace: policyArtifact.registry_id,
242
+ policy_artifact_revision: policyArtifact.policy_revision,
243
+ plan_revision: "compiled-plan.d2.omits-owner-map",
244
+ as_of: asOf,
245
+ evidence_order: "unordered",
246
+ sources: [
247
+ { id: "incident-feed", kind: "adapter", required: true },
248
+ { id: "plan-age-clock", kind: "forecast", required: true },
249
+ ],
250
+ };
251
+ return {
252
+ schema: exports.PLAN_INCOMPLETE_D2_SCENARIO_SCHEMA_V0,
253
+ v: exports.PLAN_INCOMPLETE_D2_SCENARIO_VERSION_V0,
254
+ responsibility_id: responsibilityId,
255
+ contract_revision: contractRevision,
256
+ as_of: asOf,
257
+ last_recompile_at: "2026-05-19T10:00:00.000Z",
258
+ last_policy_revalidated_at: "2026-05-19T00:00:00.000Z",
259
+ last_unforced_deep_at: asOf,
260
+ incomplete_plan: incompletePlan,
261
+ planned_receipt: plannedReceipt,
262
+ plan_age_receipt: planAgeReceipt,
263
+ missing_dependency_receipt: missingDependencyReceipt,
264
+ plan_incomplete_receipt: planIncompleteReceipt,
265
+ deep_roam_discovery: {
266
+ source_id: exports.PLAN_INCOMPLETE_D2_MISSING_SOURCE_ID,
267
+ kind: "dependency",
268
+ receipt_hash: missingDependencyReceipt.content_hash,
269
+ },
270
+ policy_artifact: policyArtifact,
271
+ policy_artifact_bytes: validation.bytes,
272
+ policy_artifact_content_hash: validation.content_hash,
273
+ receipt_history_after_discovery: [
274
+ plannedReceipt,
275
+ planAgeReceipt,
276
+ missingDependencyReceipt,
277
+ planIncompleteReceipt,
278
+ ],
279
+ };
280
+ }
281
+ function assertRecordedPlanIncompleteD2ScenarioV0(scenario) {
282
+ if (scenario.schema !== exports.PLAN_INCOMPLETE_D2_SCENARIO_SCHEMA_V0) {
283
+ throw new Error("plan-incomplete D2 scenario schema is malformed");
284
+ }
285
+ if (scenario.v !== exports.PLAN_INCOMPLETE_D2_SCENARIO_VERSION_V0) {
286
+ throw new Error("plan-incomplete D2 scenario version must be 0");
287
+ }
288
+ if (scenario.responsibility_id.length === 0) {
289
+ throw new Error("plan-incomplete D2 scenario responsibility_id is required");
290
+ }
291
+ if (!isContentHash(scenario.contract_revision)) {
292
+ throw new Error("plan-incomplete D2 scenario contract_revision must be a sha256 content hash");
293
+ }
294
+ parseReplayableInstantMs(scenario.as_of, "plan-incomplete D2 scenario as_of");
295
+ parseReplayableInstantMs(scenario.last_recompile_at, "plan-incomplete D2 scenario last_recompile_at");
296
+ parseReplayableInstantMs(scenario.last_policy_revalidated_at, "plan-incomplete D2 scenario last_policy_revalidated_at");
297
+ parseReplayableInstantMs(scenario.last_unforced_deep_at, "plan-incomplete D2 scenario last_unforced_deep_at");
298
+ for (const [label, receipt] of [
299
+ ["planned_receipt", scenario.planned_receipt],
300
+ ["plan_age_receipt", scenario.plan_age_receipt],
301
+ ["missing_dependency_receipt", scenario.missing_dependency_receipt],
302
+ ["plan_incomplete_receipt", scenario.plan_incomplete_receipt],
303
+ ]) {
304
+ const verification = verifyReceiptV0(receipt);
305
+ if (!verification.ok) {
306
+ throw new Error(`${label} is invalid: ${verification.errors.join("; ")}`);
307
+ }
308
+ }
309
+ const plannedSourceIds = scenario.incomplete_plan.sources.map((source) => source.id);
310
+ if (plannedSourceIds.includes(exports.PLAN_INCOMPLETE_D2_MISSING_SOURCE_ID)) {
311
+ throw new Error("plan-incomplete D2 scenario must omit the missing dependency from the shallow plan");
312
+ }
313
+ if (scenario.deep_roam_discovery.source_id !== exports.PLAN_INCOMPLETE_D2_MISSING_SOURCE_ID) {
314
+ throw new Error("plan-incomplete D2 scenario deep roam discovery must name the missing dependency");
315
+ }
316
+ if (scenario.deep_roam_discovery.receipt_hash !==
317
+ scenario.missing_dependency_receipt.content_hash) {
318
+ throw new Error("plan-incomplete D2 discovery must pin the missing dependency receipt");
319
+ }
320
+ if (!scenario.plan_incomplete_receipt.cost.tags.includes("backstop-divergence") ||
321
+ scenario.plan_incomplete_receipt.verdict.blocked?.reason !==
322
+ "backstop-divergence") {
323
+ throw new Error("plan-incomplete D2 scenario must record a backstop-divergence receipt");
324
+ }
325
+ const validation = validatePolicyArtifactV0(scenario.policy_artifact);
326
+ if (!validation.ok) {
327
+ throw new Error(`plan-incomplete D2 artifact is invalid: ${validation.errors.join("; ")}`);
328
+ }
329
+ if (validation.bytes !== scenario.policy_artifact_bytes) {
330
+ throw new Error("plan-incomplete D2 artifact bytes are stale");
331
+ }
332
+ if (validation.content_hash !== scenario.policy_artifact_content_hash) {
333
+ throw new Error("plan-incomplete D2 artifact content hash is stale");
334
+ }
335
+ if (scenario.policy_artifact.falsification_predicate.kind !==
336
+ "greater-than-or-equal" ||
337
+ scenario.policy_artifact.falsification_predicate.fact !==
338
+ exports.PLAN_INCOMPLETE_D2_BACKSTOP_FACT) {
339
+ throw new Error("plan-incomplete D2 artifact must trip on the deep-roam contradiction fact");
340
+ }
341
+ }
342
+ async function runRecordedPlanIncompleteD2ProofV0(input) {
343
+ const scenario = input.scenario ?? makeRecordedPlanIncompleteD2ScenarioV0();
344
+ assertRecordedPlanIncompleteD2ScenarioV0(scenario);
345
+ const consultedSources = [];
346
+ const shallow = executeShallowEvidencePlan(scenario.incomplete_plan, {
347
+ "incident-feed": (source) => {
348
+ consultedSources.push(source.id);
349
+ return scenario.planned_receipt;
350
+ },
351
+ "plan-age-clock": (source) => {
352
+ consultedSources.push(source.id);
353
+ return scenario.plan_age_receipt;
354
+ },
355
+ [exports.PLAN_INCOMPLETE_D2_MISSING_SOURCE_ID]: (source) => {
356
+ consultedSources.push(source.id);
357
+ return scenario.missing_dependency_receipt;
358
+ },
359
+ });
360
+ if (shallow.outcome !== "ready") {
361
+ throw new Error(`expected shallow plan to be ready, received ${shallow.outcome}`);
362
+ }
363
+ if (consultedSources.includes(exports.PLAN_INCOMPLETE_D2_MISSING_SOURCE_ID)) {
364
+ throw new Error("shallow execution must not roam to the omitted dependency");
365
+ }
366
+ const deepRoam = reconcileDeepRoam(scenario.incomplete_plan, "forecast-plan-age", [scenario.deep_roam_discovery]);
367
+ if (deepRoam.outcome !== "force-recompile") {
368
+ throw new Error(`expected deep roam to force recompile, received ${deepRoam.outcome}`);
369
+ }
370
+ const recompileRequest = (0, recompile_1.normalizePolicyRecompileDecisionV0)(await input.planPolicyRecompileV0(buildPlanIncompleteRecompileInput(scenario)));
371
+ assertPlanIncompleteRecompileRequest(recompileRequest, scenario);
372
+ return {
373
+ scenario,
374
+ shallow,
375
+ deep_roam: deepRoam,
376
+ recompile_request: recompileRequest,
377
+ gateway_invocations: {
378
+ agent_launch_count: 0,
379
+ model_gateway_invocation_count: 0,
380
+ },
381
+ };
382
+ }
383
+ function buildRollbackPlanInput(scenario) {
384
+ return {
385
+ responsibility_id: scenario.responsibility_id,
386
+ contract_revision: scenario.contract_revision,
387
+ as_of: scenario.as_of,
388
+ fresh_policy_revision: scenario.fresh_policy.policy_revision,
389
+ fresh_policy_judged_activations_before_trip: scenario.fresh_policy.judged_activations_before_trip,
390
+ last_known_good_revision: scenario.last_known_good_policy.policy_revision,
391
+ last_known_good_judged_activations_before_trip: scenario.last_known_good_policy.judged_activations_before_trip,
392
+ policy_trip_history: [
393
+ scenario.last_known_good_policy,
394
+ scenario.fresh_policy,
395
+ ],
396
+ };
397
+ }
398
+ function buildPlanIncompleteRecompileInput(scenario) {
399
+ return {
400
+ artifact: scenario.policy_artifact,
401
+ policy_artifact: scenario.policy_artifact,
402
+ receipts: scenario.receipt_history_after_discovery,
403
+ receipt_history: scenario.receipt_history_after_discovery,
404
+ as_of: scenario.as_of,
405
+ last_recompile_at: scenario.last_recompile_at,
406
+ last_policy_recompile_at: scenario.last_recompile_at,
407
+ last_policy_revalidated_at: scenario.last_policy_revalidated_at,
408
+ last_unforced_deep_at: scenario.last_unforced_deep_at,
409
+ };
410
+ }
411
+ function makePlanIncompletePolicyArtifact(input) {
412
+ const exploredReceiptHashes = input.receipt_history
413
+ .map((receipt) => receipt.content_hash)
414
+ .sort((left, right) => left.localeCompare(right));
415
+ const historyQuery = {
416
+ schema: POLICY_AUTHOR_HISTORY_QUERY_SCHEMA,
417
+ v: POLICY_ARTIFACT_VERSION,
418
+ selected_receipt_hashes: exploredReceiptHashes,
419
+ rationale: "recorded D2 plan-incomplete proof pins the shallow plan history before deep roam",
420
+ };
421
+ return {
422
+ schema: POLICY_ARTIFACT_SCHEMA,
423
+ v: POLICY_ARTIFACT_VERSION,
424
+ responsibility_id: input.responsibility_id,
425
+ registry_id: "registry.incident-channel-current-briefing.d2",
426
+ policy_revision: "policy.d2.plan-incomplete-before-roam",
427
+ no_anchor: true,
428
+ live_observables: PLAN_INCOMPLETE_LIVE_OBSERVABLES,
429
+ cadence: {
430
+ shallow_recheck_ms: 15 * 60 * 1000,
431
+ plan_audit_ms: 6 * 60 * 60 * 1000,
432
+ deep_revalidation_ms: 7 * 24 * 60 * 60 * 1000,
433
+ },
434
+ hysteresis: {
435
+ min_recompile_interval_ms: 60 * 60 * 1000,
436
+ enter_degraded_threshold: 0.34,
437
+ exit_degraded_threshold: 0.18,
438
+ warmup_judged_activations: 5,
439
+ },
440
+ thresholds: {
441
+ max_calibration_divergence_multiplier: 1.6,
442
+ escalation_precision_floor: 0.7,
443
+ backstop_deep_contradiction_count: 1,
444
+ stale_brief_minutes: 30,
445
+ fresh_tokens_per_day_ceiling: 500,
446
+ },
447
+ transitive_freshness_function: { kind: "kernel-default" },
448
+ falsification_predicate: {
449
+ kind: "greater-than-or-equal",
450
+ fact: exports.PLAN_INCOMPLETE_D2_BACKSTOP_FACT,
451
+ value: 1,
452
+ },
453
+ backstop_divergence_predicate: {
454
+ kind: "greater-than-or-equal",
455
+ fact: exports.PLAN_INCOMPLETE_D2_BACKSTOP_FACT,
456
+ value: 1,
457
+ },
458
+ provenance: {
459
+ contract_revision: input.contract_revision,
460
+ receipt_history_summary_hash: hashReceiptHistorySummary(input.receipt_history),
461
+ explored_receipt_hashes: exploredReceiptHashes,
462
+ history_query: historyQuery,
463
+ },
464
+ };
465
+ }
466
+ const PLAN_INCOMPLETE_LIVE_OBSERVABLES = [
467
+ {
468
+ id: exports.PLAN_INCOMPLETE_D2_BACKSTOP_FACT,
469
+ source: "kernel-backstop",
470
+ description: "deep roaming discovered a dependency outside the compiled evidence plan",
471
+ },
472
+ {
473
+ id: "cost.fresh_tokens_per_maintained_day",
474
+ source: "cost-ledger",
475
+ description: "fresh maintenance tokens per maintained day from receipt cost facts",
476
+ },
477
+ ];
478
+ function makeReceipt(input) {
479
+ return createReceiptV0({
480
+ core: {
481
+ responsibility_id: input.responsibility_id,
482
+ contract_revision: input.contract_revision,
483
+ event_cause: input.event_cause,
484
+ ...(input.event_cause === "forecast-recheck"
485
+ ? { recheck_kind: "plan-age" }
486
+ : {}),
487
+ memo_key: input.memo_key,
488
+ evidence_input_ids: input.evidence_input_ids,
489
+ as_of: input.as_of,
490
+ role: input.role,
491
+ },
492
+ sig: {
493
+ scheme: "none",
494
+ null_reason: "cradle recorded D2 rollback and plan-incomplete proof",
495
+ },
496
+ verdict: {
497
+ status: input.status,
498
+ confidence: {
499
+ value: input.status === "blocked" ? 0 : 0.82,
500
+ derivation_method: "recorded-cradle-d2-fixture",
501
+ calibration_grade: "none",
502
+ label_source: "none",
503
+ },
504
+ ...(input.status === "blocked"
505
+ ? {
506
+ blocked: {
507
+ reason: input.blocked_reason ?? "plan-incomplete",
508
+ fix_target: input.fix_target ?? "policy-artifact",
509
+ interrupt_cause: "needs-judgment",
510
+ },
511
+ }
512
+ : {}),
513
+ },
514
+ freshness: {
515
+ as_of: input.as_of,
516
+ next_forecast_recheck: input.next_forecast_recheck,
517
+ },
518
+ composition: {
519
+ consumed_receipts: [],
520
+ cycle_checked: true,
521
+ },
522
+ cost: {
523
+ provider: "cradle",
524
+ model: "recorded-d2-fixture",
525
+ role: input.role,
526
+ tags: input.tags,
527
+ responsibility_id: input.responsibility_id,
528
+ run_id: "rollback-d2-recorded",
529
+ as_of: input.as_of,
530
+ tokens: {
531
+ fresh: input.fresh,
532
+ reused: input.reused,
533
+ },
534
+ surprise_cause: input.event_cause,
535
+ },
536
+ });
537
+ }
538
+ function assertRollbackDecision(decision, scenario) {
539
+ if (decision.outcome !== "rollback") {
540
+ throw new Error(`expected rollback decision, received ${decision.outcome}`);
541
+ }
542
+ if (decision.fresh_policy_revision !== scenario.fresh_policy.policy_revision) {
543
+ throw new Error("rollback decision named the wrong fresh policy revision");
544
+ }
545
+ if (decision.last_known_good_revision !==
546
+ scenario.last_known_good_policy.policy_revision) {
547
+ throw new Error("rollback decision must name the last-known-good policy");
548
+ }
549
+ if (decision.fresh_policy_judged_activations_before_trip !==
550
+ scenario.fresh_policy.judged_activations_before_trip) {
551
+ throw new Error("rollback decision changed the fresh judged activation count");
552
+ }
553
+ if (decision.last_known_good_judged_activations_before_trip !==
554
+ scenario.last_known_good_policy.judged_activations_before_trip) {
555
+ throw new Error("rollback decision changed the last-known-good judged activation count");
556
+ }
557
+ if (decision.target_policy_revision !== undefined &&
558
+ decision.target_policy_revision !== scenario.last_known_good_policy.policy_revision) {
559
+ throw new Error("rollback decision target must be the last-known-good policy");
560
+ }
561
+ }
562
+ function assertPlanIncompleteRecompileRequest(decision, scenario) {
563
+ if (decision.outcome !== "recompile-requested") {
564
+ throw new Error(`expected plan-incomplete proof to route to recompile-requested, received ${decision.outcome}`);
565
+ }
566
+ if (decision.drift_outcome !== undefined &&
567
+ decision.drift_outcome !== "tripped") {
568
+ throw new Error(`plan-incomplete P3 route must preserve tripped drift evidence, received ${decision.drift_outcome}`);
569
+ }
570
+ if (!decision.evidence_receipt_hashes.includes(scenario.plan_incomplete_receipt.content_hash)) {
571
+ throw new Error("plan-incomplete P3 route must cite the backstop-divergence receipt");
572
+ }
573
+ }
574
+ function assertTripSummary(summary, label) {
575
+ if (summary.policy_revision.length === 0) {
576
+ throw new Error(`${label}.policy_revision must be non-empty`);
577
+ }
578
+ assertPositiveSafeInteger(summary.judged_activations_before_trip, `${label}.judged_activations_before_trip`);
579
+ parseReplayableInstantMs(summary.activated_at, `${label}.activated_at`);
580
+ parseReplayableInstantMs(summary.first_trip_at, `${label}.first_trip_at`);
581
+ if (parseReplayableInstantMs(summary.first_trip_at, `${label}.first_trip_at`) <
582
+ parseReplayableInstantMs(summary.activated_at, `${label}.activated_at`)) {
583
+ throw new Error(`${label}.first_trip_at must not precede activated_at`);
584
+ }
585
+ }
586
+ function hashReceiptHistorySummary(receiptHistory) {
587
+ return hashCanonicalReceiptV0(canonicalizeForReceiptV0(receiptHistory.map((receipt) => ({
588
+ content_hash: receipt.content_hash,
589
+ contract_revision: receipt.core.contract_revision,
590
+ as_of: receipt.core.as_of,
591
+ role: receipt.core.role,
592
+ event_cause: receipt.core.event_cause,
593
+ verdict_status: receipt.verdict.status,
594
+ next_forecast_recheck: receipt.freshness.next_forecast_recheck,
595
+ surprise_cause: receipt.cost.surprise_cause,
596
+ tags: receipt.cost.tags,
597
+ }))));
598
+ }
599
+ function readRollbackOutcome(value) {
600
+ if (value === "rollback" ||
601
+ value === "keep-current" ||
602
+ value === "no-last-known-good") {
603
+ return value;
604
+ }
605
+ throw new Error("policy rollback decision outcome must be rollback, keep-current, or no-last-known-good");
606
+ }
607
+ function readNonEmptyString(value, label) {
608
+ if (typeof value !== "string" || value.length === 0) {
609
+ throw new Error(`${label} must be a non-empty string`);
610
+ }
611
+ return value;
612
+ }
613
+ function readOptionalNonEmptyString(value, label) {
614
+ if (value === undefined) {
615
+ return undefined;
616
+ }
617
+ return readNonEmptyString(value, label);
618
+ }
619
+ function readSafeInteger(value, label) {
620
+ if (!Number.isSafeInteger(value) || value < 0) {
621
+ throw new Error(`${label} must be a non-negative safe integer`);
622
+ }
623
+ return value;
624
+ }
625
+ function readOptionalSafeInteger(value, label) {
626
+ if (value === undefined) {
627
+ return undefined;
628
+ }
629
+ return readSafeInteger(value, label);
630
+ }
631
+ function assertPositiveSafeInteger(value, label) {
632
+ if (!Number.isSafeInteger(value) || value <= 0) {
633
+ throw new Error(`${label} must be a positive safe integer`);
634
+ }
635
+ }
636
+ function parseReplayableInstantMs(value, label) {
637
+ const ms = Date.parse(value);
638
+ if (Number.isNaN(ms) ||
639
+ !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/.test(value)) {
640
+ throw new Error(`${label} must be a replayable ISO instant`);
641
+ }
642
+ return ms;
643
+ }
644
+ function hashText(value) {
645
+ return `sha256:${(0, node_crypto_1.createHash)("sha256").update(value).digest("hex")}`;
646
+ }
647
+ function isContentHash(value) {
648
+ return /^sha256:[a-f0-9]{64}$/.test(value);
649
+ }
650
+ function readOptionalRecord(value) {
651
+ return isRecord(value) ? value : undefined;
652
+ }
653
+ function isRecord(value) {
654
+ return typeof value === "object" && value !== null && !Array.isArray(value);
655
+ }
656
+ function loadReactorEvidencePlan() {
657
+ try {
658
+ return require("@openprose/reactor/evidence-plan");
659
+ }
660
+ catch (error) {
661
+ if (isMissingReactorSubpath(error, "@openprose/reactor/evidence-plan")) {
662
+ return require("../../../reactor/dist/evidence-plan");
663
+ }
664
+ throw error;
665
+ }
666
+ }
667
+ function loadReactorPolicy() {
668
+ try {
669
+ return require("@openprose/reactor/policy");
670
+ }
671
+ catch (error) {
672
+ if (isMissingReactorSubpath(error, "@openprose/reactor/policy")) {
673
+ return require("../../../reactor/dist/policy");
674
+ }
675
+ throw error;
676
+ }
677
+ }
678
+ function loadReactorReceipt() {
679
+ try {
680
+ return require("@openprose/reactor/receipt");
681
+ }
682
+ catch (error) {
683
+ if (isMissingReactorSubpath(error, "@openprose/reactor/receipt")) {
684
+ return require("../../../reactor/dist/receipt");
685
+ }
686
+ throw error;
687
+ }
688
+ }
689
+ function isMissingReactorSubpath(error, subpath) {
690
+ return (isRecord(error) &&
691
+ error["code"] === "MODULE_NOT_FOUND" &&
692
+ typeof error["message"] === "string" &&
693
+ error["message"].includes(subpath));
694
+ }