pi-amq 0.1.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 (264) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/LICENSE +21 -0
  3. package/README.md +92 -0
  4. package/THIRD_PARTY_NOTICES.md +33 -0
  5. package/dist/extension/guidance.d.ts +25 -0
  6. package/dist/extension/guidance.d.ts.map +1 -0
  7. package/dist/extension/guidance.js +121 -0
  8. package/dist/extension/guidance.js.map +1 -0
  9. package/dist/extension/guide.d.ts +30 -0
  10. package/dist/extension/guide.d.ts.map +1 -0
  11. package/dist/extension/guide.js +128 -0
  12. package/dist/extension/guide.js.map +1 -0
  13. package/dist/extension/index.d.ts +4 -0
  14. package/dist/extension/index.d.ts.map +1 -0
  15. package/dist/extension/index.js +6 -0
  16. package/dist/extension/index.js.map +1 -0
  17. package/dist/extension/runtime.d.ts +48 -0
  18. package/dist/extension/runtime.d.ts.map +1 -0
  19. package/dist/extension/runtime.js +1095 -0
  20. package/dist/extension/runtime.js.map +1 -0
  21. package/dist/extension/tools.d.ts +12 -0
  22. package/dist/extension/tools.d.ts.map +1 -0
  23. package/dist/extension/tools.js +198 -0
  24. package/dist/extension/tools.js.map +1 -0
  25. package/dist/extension/worker-runtime.d.ts +34 -0
  26. package/dist/extension/worker-runtime.d.ts.map +1 -0
  27. package/dist/extension/worker-runtime.js +974 -0
  28. package/dist/extension/worker-runtime.js.map +1 -0
  29. package/dist/extension/worker-tools.d.ts +140 -0
  30. package/dist/extension/worker-tools.d.ts.map +1 -0
  31. package/dist/extension/worker-tools.js +217 -0
  32. package/dist/extension/worker-tools.js.map +1 -0
  33. package/dist/integration/confirmed-bind-onboarding.d.ts +44 -0
  34. package/dist/integration/confirmed-bind-onboarding.d.ts.map +1 -0
  35. package/dist/integration/confirmed-bind-onboarding.js +199 -0
  36. package/dist/integration/confirmed-bind-onboarding.js.map +1 -0
  37. package/dist/integration/fleet-view.d.ts +66 -0
  38. package/dist/integration/fleet-view.d.ts.map +1 -0
  39. package/dist/integration/fleet-view.js +238 -0
  40. package/dist/integration/fleet-view.js.map +1 -0
  41. package/dist/integration/fresh-session-dispatcher.d.ts +66 -0
  42. package/dist/integration/fresh-session-dispatcher.d.ts.map +1 -0
  43. package/dist/integration/fresh-session-dispatcher.js +103 -0
  44. package/dist/integration/fresh-session-dispatcher.js.map +1 -0
  45. package/dist/integration/launch-preview.d.ts +31 -0
  46. package/dist/integration/launch-preview.d.ts.map +1 -0
  47. package/dist/integration/launch-preview.js +325 -0
  48. package/dist/integration/launch-preview.js.map +1 -0
  49. package/dist/integration/transport-port.d.ts +39 -0
  50. package/dist/integration/transport-port.d.ts.map +1 -0
  51. package/dist/integration/transport-port.js +2 -0
  52. package/dist/integration/transport-port.js.map +1 -0
  53. package/dist/integration/worker-completion-notifier.d.ts +22 -0
  54. package/dist/integration/worker-completion-notifier.d.ts.map +1 -0
  55. package/dist/integration/worker-completion-notifier.js +81 -0
  56. package/dist/integration/worker-completion-notifier.js.map +1 -0
  57. package/dist/transport/amq-cli-adapter.d.ts +41 -0
  58. package/dist/transport/amq-cli-adapter.d.ts.map +1 -0
  59. package/dist/transport/amq-cli-adapter.js +291 -0
  60. package/dist/transport/amq-cli-adapter.js.map +1 -0
  61. package/dist/transport/amq-message.d.ts +47 -0
  62. package/dist/transport/amq-message.d.ts.map +1 -0
  63. package/dist/transport/amq-message.js +173 -0
  64. package/dist/transport/amq-message.js.map +1 -0
  65. package/dist/transport/amq-operations.d.ts +105 -0
  66. package/dist/transport/amq-operations.d.ts.map +1 -0
  67. package/dist/transport/amq-operations.js +320 -0
  68. package/dist/transport/amq-operations.js.map +1 -0
  69. package/dist/transport/atomic-json.d.ts +18 -0
  70. package/dist/transport/atomic-json.d.ts.map +1 -0
  71. package/dist/transport/atomic-json.js +90 -0
  72. package/dist/transport/atomic-json.js.map +1 -0
  73. package/dist/transport/binding-resolver.d.ts +46 -0
  74. package/dist/transport/binding-resolver.d.ts.map +1 -0
  75. package/dist/transport/binding-resolver.js +389 -0
  76. package/dist/transport/binding-resolver.js.map +1 -0
  77. package/dist/transport/bridge-journal.d.ts +100 -0
  78. package/dist/transport/bridge-journal.d.ts.map +1 -0
  79. package/dist/transport/bridge-journal.js +459 -0
  80. package/dist/transport/bridge-journal.js.map +1 -0
  81. package/dist/transport/dlq-retry-audit.d.ts +28 -0
  82. package/dist/transport/dlq-retry-audit.d.ts.map +1 -0
  83. package/dist/transport/dlq-retry-audit.js +66 -0
  84. package/dist/transport/dlq-retry-audit.js.map +1 -0
  85. package/dist/transport/inbox-pump.d.ts +81 -0
  86. package/dist/transport/inbox-pump.d.ts.map +1 -0
  87. package/dist/transport/inbox-pump.js +558 -0
  88. package/dist/transport/inbox-pump.js.map +1 -0
  89. package/dist/transport/index.d.ts +12 -0
  90. package/dist/transport/index.d.ts.map +1 -0
  91. package/dist/transport/index.js +12 -0
  92. package/dist/transport/index.js.map +1 -0
  93. package/dist/transport/presence-projector.d.ts +29 -0
  94. package/dist/transport/presence-projector.d.ts.map +1 -0
  95. package/dist/transport/presence-projector.js +73 -0
  96. package/dist/transport/presence-projector.js.map +1 -0
  97. package/dist/transport/priority-delivery-scheduler.d.ts +85 -0
  98. package/dist/transport/priority-delivery-scheduler.d.ts.map +1 -0
  99. package/dist/transport/priority-delivery-scheduler.js +210 -0
  100. package/dist/transport/priority-delivery-scheduler.js.map +1 -0
  101. package/dist/transport/receiver-lease.d.ts +102 -0
  102. package/dist/transport/receiver-lease.d.ts.map +1 -0
  103. package/dist/transport/receiver-lease.js +778 -0
  104. package/dist/transport/receiver-lease.js.map +1 -0
  105. package/dist/transport/runtime-status.d.ts +48 -0
  106. package/dist/transport/runtime-status.d.ts.map +1 -0
  107. package/dist/transport/runtime-status.js +71 -0
  108. package/dist/transport/runtime-status.js.map +1 -0
  109. package/dist/workflow/atomic-storage.d.ts +12 -0
  110. package/dist/workflow/atomic-storage.d.ts.map +1 -0
  111. package/dist/workflow/atomic-storage.js +104 -0
  112. package/dist/workflow/atomic-storage.js.map +1 -0
  113. package/dist/workflow/budget.d.ts +18 -0
  114. package/dist/workflow/budget.d.ts.map +1 -0
  115. package/dist/workflow/budget.js +74 -0
  116. package/dist/workflow/budget.js.map +1 -0
  117. package/dist/workflow/index.d.ts +17 -0
  118. package/dist/workflow/index.d.ts.map +1 -0
  119. package/dist/workflow/index.js +17 -0
  120. package/dist/workflow/index.js.map +1 -0
  121. package/dist/workflow/lifecycle-projection.d.ts +18 -0
  122. package/dist/workflow/lifecycle-projection.d.ts.map +1 -0
  123. package/dist/workflow/lifecycle-projection.js +22 -0
  124. package/dist/workflow/lifecycle-projection.js.map +1 -0
  125. package/dist/workflow/model-fallback.d.ts +2 -0
  126. package/dist/workflow/model-fallback.d.ts.map +1 -0
  127. package/dist/workflow/model-fallback.js +17 -0
  128. package/dist/workflow/model-fallback.js.map +1 -0
  129. package/dist/workflow/pi-session-fork.d.ts +18 -0
  130. package/dist/workflow/pi-session-fork.d.ts.map +1 -0
  131. package/dist/workflow/pi-session-fork.js +80 -0
  132. package/dist/workflow/pi-session-fork.js.map +1 -0
  133. package/dist/workflow/run-artifacts.d.ts +5 -0
  134. package/dist/workflow/run-artifacts.d.ts.map +1 -0
  135. package/dist/workflow/run-artifacts.js +25 -0
  136. package/dist/workflow/run-artifacts.js.map +1 -0
  137. package/dist/workflow/run-cleanup.d.ts +70 -0
  138. package/dist/workflow/run-cleanup.d.ts.map +1 -0
  139. package/dist/workflow/run-cleanup.js +222 -0
  140. package/dist/workflow/run-cleanup.js.map +1 -0
  141. package/dist/workflow/run-gate.d.ts +43 -0
  142. package/dist/workflow/run-gate.d.ts.map +1 -0
  143. package/dist/workflow/run-gate.js +70 -0
  144. package/dist/workflow/run-gate.js.map +1 -0
  145. package/dist/workflow/run-store.d.ts +208 -0
  146. package/dist/workflow/run-store.d.ts.map +1 -0
  147. package/dist/workflow/run-store.js +2965 -0
  148. package/dist/workflow/run-store.js.map +1 -0
  149. package/dist/workflow/spawn-confirmation.d.ts +44 -0
  150. package/dist/workflow/spawn-confirmation.d.ts.map +1 -0
  151. package/dist/workflow/spawn-confirmation.js +228 -0
  152. package/dist/workflow/spawn-confirmation.js.map +1 -0
  153. package/dist/workflow/system-process-inspector.d.ts +9 -0
  154. package/dist/workflow/system-process-inspector.d.ts.map +1 -0
  155. package/dist/workflow/system-process-inspector.js +129 -0
  156. package/dist/workflow/system-process-inspector.js.map +1 -0
  157. package/dist/workflow/worker-child-extension.d.ts +3 -0
  158. package/dist/workflow/worker-child-extension.d.ts.map +1 -0
  159. package/dist/workflow/worker-child-extension.js +182 -0
  160. package/dist/workflow/worker-child-extension.js.map +1 -0
  161. package/dist/workflow/worker-gate.d.ts +74 -0
  162. package/dist/workflow/worker-gate.d.ts.map +1 -0
  163. package/dist/workflow/worker-gate.js +165 -0
  164. package/dist/workflow/worker-gate.js.map +1 -0
  165. package/dist/workflow/worker-launch.d.ts +65 -0
  166. package/dist/workflow/worker-launch.d.ts.map +1 -0
  167. package/dist/workflow/worker-launch.js +338 -0
  168. package/dist/workflow/worker-launch.js.map +1 -0
  169. package/dist/workflow/worker-model-catalog.d.ts +36 -0
  170. package/dist/workflow/worker-model-catalog.d.ts.map +1 -0
  171. package/dist/workflow/worker-model-catalog.js +105 -0
  172. package/dist/workflow/worker-model-catalog.js.map +1 -0
  173. package/dist/workflow/worker-process-supervisor.d.ts +110 -0
  174. package/dist/workflow/worker-process-supervisor.d.ts.map +1 -0
  175. package/dist/workflow/worker-process-supervisor.js +1188 -0
  176. package/dist/workflow/worker-process-supervisor.js.map +1 -0
  177. package/dist/workflow/worker-prompt-capsule.d.ts +32 -0
  178. package/dist/workflow/worker-prompt-capsule.d.ts.map +1 -0
  179. package/dist/workflow/worker-prompt-capsule.js +52 -0
  180. package/dist/workflow/worker-prompt-capsule.js.map +1 -0
  181. package/dist/workflow/worker-role-presets.d.ts +38 -0
  182. package/dist/workflow/worker-role-presets.d.ts.map +1 -0
  183. package/dist/workflow/worker-role-presets.js +201 -0
  184. package/dist/workflow/worker-role-presets.js.map +1 -0
  185. package/dist/workflow/workflow-doctor.d.ts +57 -0
  186. package/dist/workflow/workflow-doctor.d.ts.map +1 -0
  187. package/dist/workflow/workflow-doctor.js +289 -0
  188. package/dist/workflow/workflow-doctor.js.map +1 -0
  189. package/dist/workflow/workflow-lease.d.ts +125 -0
  190. package/dist/workflow/workflow-lease.d.ts.map +1 -0
  191. package/dist/workflow/workflow-lease.js +689 -0
  192. package/dist/workflow/workflow-lease.js.map +1 -0
  193. package/dist/workflow/workflow-types.d.ts +335 -0
  194. package/dist/workflow/workflow-types.d.ts.map +1 -0
  195. package/dist/workflow/workflow-types.js +11 -0
  196. package/dist/workflow/workflow-types.js.map +1 -0
  197. package/dist/workflow/workspace-paths.d.ts +4 -0
  198. package/dist/workflow/workspace-paths.d.ts.map +1 -0
  199. package/dist/workflow/workspace-paths.js +22 -0
  200. package/dist/workflow/workspace-paths.js.map +1 -0
  201. package/docs/conformance.md +116 -0
  202. package/docs/demo-transcript.md +34 -0
  203. package/docs/design.md +1481 -0
  204. package/docs/operator-guide.md +100 -0
  205. package/extension/guidance.ts +162 -0
  206. package/extension/guide.ts +155 -0
  207. package/extension/index.ts +8 -0
  208. package/extension/runtime.ts +1224 -0
  209. package/extension/tools.ts +221 -0
  210. package/extension/worker-runtime.ts +1150 -0
  211. package/extension/worker-tools.ts +276 -0
  212. package/integration/confirmed-bind-onboarding.ts +296 -0
  213. package/integration/fleet-view.ts +286 -0
  214. package/integration/fresh-session-dispatcher.ts +166 -0
  215. package/integration/launch-preview.ts +396 -0
  216. package/integration/transport-port.ts +29 -0
  217. package/integration/worker-completion-notifier.ts +98 -0
  218. package/package.json +55 -0
  219. package/roles/oracle.md +9 -0
  220. package/roles/researcher.md +8 -0
  221. package/roles/reviewer.md +9 -0
  222. package/roles/scout.md +8 -0
  223. package/roles/worker.md +10 -0
  224. package/scripts/demo-two-terminal.sh +59 -0
  225. package/skills/coordination-patterns/SKILL.md +41 -0
  226. package/skills/coordination-patterns/references/supervised-worker-fan-out.md +12 -0
  227. package/skills/coordination-patterns/references/today-mail-team.md +36 -0
  228. package/transport/amq-cli-adapter.ts +381 -0
  229. package/transport/amq-message.ts +218 -0
  230. package/transport/amq-operations.ts +482 -0
  231. package/transport/atomic-json.ts +115 -0
  232. package/transport/binding-resolver.ts +565 -0
  233. package/transport/bridge-journal.ts +588 -0
  234. package/transport/dlq-retry-audit.ts +97 -0
  235. package/transport/inbox-pump.ts +729 -0
  236. package/transport/index.ts +11 -0
  237. package/transport/presence-projector.ts +104 -0
  238. package/transport/priority-delivery-scheduler.ts +328 -0
  239. package/transport/receiver-lease.ts +945 -0
  240. package/transport/runtime-status.ts +112 -0
  241. package/workflow/.gitkeep +1 -0
  242. package/workflow/atomic-storage.ts +120 -0
  243. package/workflow/budget.ts +90 -0
  244. package/workflow/index.ts +16 -0
  245. package/workflow/lifecycle-projection.ts +37 -0
  246. package/workflow/model-fallback.ts +17 -0
  247. package/workflow/pi-session-fork.ts +96 -0
  248. package/workflow/run-artifacts.ts +36 -0
  249. package/workflow/run-cleanup.ts +315 -0
  250. package/workflow/run-gate.ts +122 -0
  251. package/workflow/run-store.ts +3890 -0
  252. package/workflow/spawn-confirmation.ts +305 -0
  253. package/workflow/system-process-inspector.ts +142 -0
  254. package/workflow/worker-child-extension.ts +193 -0
  255. package/workflow/worker-gate.ts +238 -0
  256. package/workflow/worker-launch.ts +485 -0
  257. package/workflow/worker-model-catalog.ts +165 -0
  258. package/workflow/worker-process-supervisor.ts +1504 -0
  259. package/workflow/worker-prompt-capsule.ts +81 -0
  260. package/workflow/worker-role-presets.ts +241 -0
  261. package/workflow/workflow-doctor.ts +400 -0
  262. package/workflow/workflow-lease.ts +905 -0
  263. package/workflow/workflow-types.ts +367 -0
  264. package/workflow/workspace-paths.ts +32 -0
@@ -0,0 +1,238 @@
1
+ import type { ReportFieldSchema, ReportSchemaV1 } from "./workflow-types.js";
2
+
3
+ export const WORKER_ATTEMPT_STATES = [
4
+ "pending",
5
+ "running",
6
+ "blocked",
7
+ "ambiguous",
8
+ "done",
9
+ "failed",
10
+ "cancelled",
11
+ ] as const;
12
+
13
+ export type WorkerAttemptState = (typeof WORKER_ATTEMPT_STATES)[number];
14
+
15
+ export function normalizeWorkerAttemptState(value: unknown): WorkerAttemptState {
16
+ switch (value) {
17
+ case "spawn-intent":
18
+ return "pending";
19
+ case "exited":
20
+ return "running";
21
+ case "pending":
22
+ case "running":
23
+ case "blocked":
24
+ case "ambiguous":
25
+ case "done":
26
+ case "failed":
27
+ case "cancelled":
28
+ return value;
29
+ default:
30
+ throw new TypeError("worker attempt state is invalid");
31
+ }
32
+ }
33
+
34
+ export interface WorkerGateFacts {
35
+ readonly evidence: { readonly exists: boolean };
36
+ readonly report: { readonly schemaDeclared: boolean; readonly matches: boolean };
37
+ readonly acceptanceCheck: { readonly declared: boolean; readonly exitCode: number | null };
38
+ readonly human: { readonly approvalRequired: boolean; readonly approved: boolean };
39
+ readonly budget: { readonly exceeded: boolean };
40
+ readonly runtime: {
41
+ readonly supervisorLost: boolean;
42
+ readonly effectsUncertain: boolean;
43
+ readonly certain?: boolean;
44
+ };
45
+ readonly failure?: { readonly observed: boolean };
46
+ readonly termination?: { readonly observed: boolean };
47
+ readonly wait?: { readonly declared: boolean };
48
+ readonly reconcile: { readonly decisionExists: boolean; readonly uncertaintyCleared?: boolean };
49
+ readonly input: {
50
+ readonly kind: "revise_contract" | "steer" | "peer_message" | null;
51
+ readonly correlationMatches: boolean;
52
+ };
53
+ readonly cancel: { readonly verbReceived: boolean };
54
+ }
55
+
56
+ export type WorkerGateGuard =
57
+ | "evidence.exists"
58
+ | "report.matches(report_schema)"
59
+ | "acceptance_check.exit == 0"
60
+ | "human.approved"
61
+ | "budget.not_exceeded"
62
+ | "runtime.uncertain"
63
+ | "runtime.certain"
64
+ | "failure.observed"
65
+ | "termination.observed"
66
+ | "wait.declared"
67
+ | "reconcile.decision.exists"
68
+ | "reconcile.uncertainty.cleared"
69
+ | "input.is_new"
70
+ | "input.correlation_matches"
71
+ | "cancel.verb";
72
+
73
+ export interface WorkerAttemptTransitionRule {
74
+ readonly from: WorkerAttemptState;
75
+ readonly to: WorkerAttemptState;
76
+ readonly guards: readonly WorkerGateGuard[];
77
+ }
78
+
79
+ const DONE_GUARDS: readonly WorkerGateGuard[] = [
80
+ "runtime.certain",
81
+ "evidence.exists",
82
+ "report.matches(report_schema)",
83
+ "acceptance_check.exit == 0",
84
+ "human.approved",
85
+ "budget.not_exceeded",
86
+ ];
87
+
88
+ const RECONCILE_GUARDS: readonly WorkerGateGuard[] = [
89
+ "reconcile.decision.exists",
90
+ "reconcile.uncertainty.cleared",
91
+ ];
92
+ const CANCELLED_GUARDS: readonly WorkerGateGuard[] = [
93
+ "cancel.verb",
94
+ "termination.observed",
95
+ "runtime.certain",
96
+ ];
97
+
98
+ export const WORKER_ATTEMPT_LEGALITY_TABLE: readonly WorkerAttemptTransitionRule[] = [
99
+ { from: "pending", to: "running", guards: [] },
100
+ { from: "pending", to: "failed", guards: ["failure.observed"] },
101
+ { from: "pending", to: "ambiguous", guards: ["runtime.uncertain"] },
102
+ { from: "pending", to: "cancelled", guards: CANCELLED_GUARDS },
103
+ { from: "running", to: "blocked", guards: ["wait.declared"] },
104
+ { from: "running", to: "done", guards: DONE_GUARDS },
105
+ { from: "running", to: "failed", guards: ["failure.observed"] },
106
+ { from: "running", to: "ambiguous", guards: ["runtime.uncertain"] },
107
+ { from: "running", to: "cancelled", guards: CANCELLED_GUARDS },
108
+ {
109
+ from: "blocked",
110
+ to: "running",
111
+ guards: ["input.is_new", "input.correlation_matches"],
112
+ },
113
+ { from: "blocked", to: "failed", guards: ["failure.observed"] },
114
+ { from: "blocked", to: "ambiguous", guards: ["runtime.uncertain"] },
115
+ { from: "blocked", to: "cancelled", guards: CANCELLED_GUARDS },
116
+ { from: "ambiguous", to: "pending", guards: RECONCILE_GUARDS },
117
+ { from: "ambiguous", to: "running", guards: RECONCILE_GUARDS },
118
+ { from: "ambiguous", to: "blocked", guards: [...RECONCILE_GUARDS, "wait.declared"] },
119
+ { from: "ambiguous", to: "done", guards: [...RECONCILE_GUARDS, ...DONE_GUARDS] },
120
+ { from: "ambiguous", to: "failed", guards: [...RECONCILE_GUARDS, "failure.observed"] },
121
+ {
122
+ from: "ambiguous",
123
+ to: "cancelled",
124
+ guards: [...RECONCILE_GUARDS, ...CANCELLED_GUARDS],
125
+ },
126
+ ] as const;
127
+
128
+ export type WorkerAttemptTransitionResult =
129
+ | { readonly allowed: true }
130
+ | {
131
+ readonly allowed: false;
132
+ readonly reason: "undeclared-transition" | "guard-failed";
133
+ readonly blockers: readonly WorkerGateGuard[];
134
+ };
135
+
136
+ export function evaluateWorkerAttemptTransition(
137
+ from: WorkerAttemptState,
138
+ to: WorkerAttemptState,
139
+ facts: WorkerGateFacts,
140
+ ): WorkerAttemptTransitionResult {
141
+ const rule = WORKER_ATTEMPT_LEGALITY_TABLE.find(
142
+ (candidate) => candidate.from === from && candidate.to === to,
143
+ );
144
+ if (!rule) {
145
+ return { allowed: false, reason: "undeclared-transition", blockers: [] };
146
+ }
147
+
148
+ const blockers = rule.guards.filter((guard) => !guardSatisfied(guard, facts));
149
+ return blockers.length === 0
150
+ ? { allowed: true }
151
+ : { allowed: false, reason: "guard-failed", blockers };
152
+ }
153
+
154
+ function guardSatisfied(guard: WorkerGateGuard, facts: WorkerGateFacts): boolean {
155
+ switch (guard) {
156
+ case "evidence.exists":
157
+ return facts.evidence.exists;
158
+ case "report.matches(report_schema)":
159
+ return !facts.report.schemaDeclared || facts.report.matches;
160
+ case "acceptance_check.exit == 0":
161
+ return !facts.acceptanceCheck.declared || facts.acceptanceCheck.exitCode === 0;
162
+ case "human.approved":
163
+ return !facts.human.approvalRequired || facts.human.approved;
164
+ case "budget.not_exceeded":
165
+ return !facts.budget.exceeded;
166
+ case "runtime.uncertain":
167
+ return facts.runtime.supervisorLost || facts.runtime.effectsUncertain;
168
+ case "runtime.certain":
169
+ return facts.runtime.certain === true
170
+ || (!facts.runtime.supervisorLost && !facts.runtime.effectsUncertain);
171
+ case "failure.observed":
172
+ return facts.failure?.observed === true;
173
+ case "termination.observed":
174
+ return facts.termination?.observed === true;
175
+ case "wait.declared":
176
+ return facts.wait?.declared === true;
177
+ case "reconcile.decision.exists":
178
+ return facts.reconcile.decisionExists;
179
+ case "reconcile.uncertainty.cleared":
180
+ return facts.reconcile.uncertaintyCleared === true;
181
+ case "input.is_new":
182
+ return facts.input.kind === "revise_contract"
183
+ || facts.input.kind === "steer"
184
+ || facts.input.kind === "peer_message";
185
+ case "input.correlation_matches":
186
+ return facts.input.correlationMatches;
187
+ case "cancel.verb":
188
+ return facts.cancel.verbReceived;
189
+ }
190
+ }
191
+
192
+ export const TERMINAL_ATTEMPT_PRIORITY = ["ambiguous", "cancelled", "failed", "running"] as const;
193
+
194
+ export function classifyObservedTermination(input: {
195
+ readonly runtimeCertain: boolean;
196
+ readonly effectsUncertain: boolean;
197
+ readonly cancellationRequested: boolean;
198
+ readonly terminationObserved: boolean;
199
+ readonly failureObserved: boolean;
200
+ }): WorkerAttemptState {
201
+ if (!input.runtimeCertain || input.effectsUncertain) return "ambiguous";
202
+ if (input.cancellationRequested && input.terminationObserved) return "cancelled";
203
+ if (input.failureObserved) return "failed";
204
+ return "running";
205
+ }
206
+
207
+ export function reportMatchesSchema(schema: ReportSchemaV1, report: unknown): boolean {
208
+ if (!isRecord(report)) return false;
209
+ for (const required of schema.required) {
210
+ if (!Object.prototype.hasOwnProperty.call(report, required)) return false;
211
+ }
212
+ for (const [name, field] of Object.entries(schema.properties)) {
213
+ if (!Object.prototype.hasOwnProperty.call(report, name)) continue;
214
+ if (!matchesFieldType(field, report[name])) return false;
215
+ }
216
+ return true;
217
+ }
218
+
219
+ function matchesFieldType(field: ReportFieldSchema, value: unknown): boolean {
220
+ switch (field.type) {
221
+ case "string":
222
+ return typeof value === "string";
223
+ case "number":
224
+ return typeof value === "number" && Number.isFinite(value);
225
+ case "boolean":
226
+ return typeof value === "boolean";
227
+ case "object":
228
+ return isRecord(value);
229
+ case "array":
230
+ return Array.isArray(value);
231
+ case "null":
232
+ return value === null;
233
+ }
234
+ }
235
+
236
+ function isRecord(value: unknown): value is Record<string, unknown> {
237
+ return typeof value === "object" && value !== null && !Array.isArray(value);
238
+ }