supipowers 1.5.3 → 2.0.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 (340) hide show
  1. package/README.md +14 -8
  2. package/bin/install.mjs +20 -5
  3. package/bin/install.ts +95 -0
  4. package/package.json +8 -4
  5. package/skills/context-mode/SKILL.md +17 -10
  6. package/skills/harness/SKILL.md +94 -0
  7. package/skills/ui-design/SKILL.md +63 -0
  8. package/skills/ui-design/sub-agent-templates/component-builder.md +29 -0
  9. package/skills/ui-design/sub-agent-templates/design-critic.md +46 -0
  10. package/skills/ui-design/sub-agent-templates/pencil/component-builder.md +29 -0
  11. package/skills/ui-design/sub-agent-templates/pencil/design-critic.md +42 -0
  12. package/skills/ui-design/sub-agent-templates/pencil/section-assembler.md +27 -0
  13. package/skills/ui-design/sub-agent-templates/section-assembler.md +27 -0
  14. package/skills/ultraplan-discover/SKILL.md +96 -0
  15. package/skills/ultraplan-intake/SKILL.md +89 -0
  16. package/skills/ultraplan-research/SKILL.md +129 -0
  17. package/skills/ultraplan-review/SKILL.md +86 -0
  18. package/skills/ultraplan-review-scope/SKILL.md +111 -0
  19. package/skills/ultraplan-review-structure/SKILL.md +120 -0
  20. package/skills/ultraplan-review-tdd/SKILL.md +142 -0
  21. package/skills/ultraplan-scout/SKILL.md +110 -0
  22. package/skills/ultraplan-synthesize/SKILL.md +124 -0
  23. package/src/{quality/ai-session.ts → ai/final-message.ts} +27 -0
  24. package/src/ai/schema-text.ts +129 -0
  25. package/src/ai/structured-output.ts +274 -0
  26. package/src/ai/template.ts +27 -0
  27. package/src/bootstrap.ts +63 -28
  28. package/src/commands/agents.ts +131 -42
  29. package/src/commands/ai-review.ts +251 -30
  30. package/src/commands/clear.ts +434 -0
  31. package/src/commands/commit.ts +1 -0
  32. package/src/commands/config.ts +242 -44
  33. package/src/commands/context.ts +55 -28
  34. package/src/commands/doctor.ts +234 -6
  35. package/src/commands/fix-pr.ts +306 -131
  36. package/src/commands/generate.ts +111 -21
  37. package/src/commands/memory.ts +192 -0
  38. package/src/commands/model-picker.ts +28 -21
  39. package/src/commands/model.ts +18 -8
  40. package/src/commands/optimize-context.ts +408 -29
  41. package/src/commands/plan.ts +2 -0
  42. package/src/commands/qa.ts +312 -137
  43. package/src/commands/release.ts +259 -76
  44. package/src/commands/review.ts +293 -59
  45. package/src/commands/status.ts +200 -13
  46. package/src/commands/supi.ts +3 -35
  47. package/src/commands/ui-design.ts +394 -0
  48. package/src/commands/ultraplan.ts +1518 -0
  49. package/src/commands/update.ts +86 -0
  50. package/src/config/defaults.ts +62 -0
  51. package/src/config/loader.ts +448 -60
  52. package/src/config/schema.ts +108 -2
  53. package/src/context/optimizer.ts +25 -33
  54. package/src/context/rule-renderer.ts +223 -0
  55. package/src/context/savings.ts +258 -0
  56. package/src/context/startup-check.ts +380 -0
  57. package/src/context/startup-optimizer.ts +355 -0
  58. package/src/context/tokenignore.ts +146 -0
  59. package/src/context-mode/cache-handle.ts +49 -0
  60. package/src/context-mode/cache-preview.ts +71 -0
  61. package/src/context-mode/cache-store.ts +738 -0
  62. package/src/context-mode/compressor.ts +131 -26
  63. package/src/context-mode/dedup.ts +108 -0
  64. package/src/context-mode/detector.ts +35 -4
  65. package/src/context-mode/event-extractor.ts +14 -12
  66. package/src/context-mode/event-store.ts +91 -36
  67. package/src/context-mode/hooks.ts +798 -56
  68. package/src/context-mode/knowledge/store.ts +255 -11
  69. package/src/context-mode/memory-store.ts +325 -0
  70. package/src/context-mode/metrics-recorder.ts +158 -0
  71. package/src/context-mode/metrics-store.ts +765 -0
  72. package/src/context-mode/model.ts +24 -0
  73. package/src/context-mode/processor-keys.ts +29 -0
  74. package/src/context-mode/processors/build.ts +66 -0
  75. package/src/context-mode/processors/docker.ts +57 -0
  76. package/src/context-mode/processors/git.ts +111 -0
  77. package/src/context-mode/processors/json.ts +112 -0
  78. package/src/context-mode/processors/k8s.ts +67 -0
  79. package/src/context-mode/processors/lint.ts +67 -0
  80. package/src/context-mode/processors/log.ts +86 -0
  81. package/src/context-mode/processors/registry.ts +116 -0
  82. package/src/context-mode/processors/test-runner.ts +102 -0
  83. package/src/context-mode/processors/types.ts +20 -0
  84. package/src/context-mode/repomap.ts +400 -0
  85. package/src/context-mode/routing.ts +97 -24
  86. package/src/context-mode/sandbox/runners.ts +5 -1
  87. package/src/context-mode/snapshot-builder.ts +106 -11
  88. package/src/context-mode/source-hash.ts +173 -0
  89. package/src/context-mode/tool-name.ts +11 -0
  90. package/src/context-mode/tools.ts +654 -22
  91. package/src/context-mode/web/fetcher.ts +31 -12
  92. package/src/debug/logger.ts +2 -1
  93. package/src/deps/registry.ts +1 -1
  94. package/src/discipline/failure-summarizer.ts +170 -0
  95. package/src/discipline/failure-taxonomy.ts +131 -0
  96. package/src/discipline/workflow-invariants.ts +125 -0
  97. package/src/discovery/index.ts +31 -0
  98. package/src/discovery/lsp.ts +87 -0
  99. package/src/discovery/rank.ts +144 -0
  100. package/src/discovery/sources.ts +89 -0
  101. package/src/discovery/workflow.ts +87 -0
  102. package/src/docs/contracts.ts +39 -0
  103. package/src/docs/drift.ts +117 -87
  104. package/src/fix-pr/assessment.ts +200 -0
  105. package/src/fix-pr/contracts.ts +47 -0
  106. package/src/fix-pr/fetch-comments.ts +80 -0
  107. package/src/fix-pr/prompt-builder.ts +58 -40
  108. package/src/fix-pr/scripts/exec.ts +34 -0
  109. package/src/fix-pr/scripts/trigger-review.ts +106 -0
  110. package/src/fix-pr/scripts/wait-and-check.ts +108 -0
  111. package/src/fix-pr/types.ts +4 -0
  112. package/src/git/branch-finish.ts +5 -0
  113. package/src/git/commit-contract.ts +83 -0
  114. package/src/git/commit.ts +121 -184
  115. package/src/git/status.ts +62 -8
  116. package/src/harness/anti_slop/architecture-parser.ts +210 -0
  117. package/src/harness/anti_slop/backend-factory.ts +30 -0
  118. package/src/harness/anti_slop/backend.ts +140 -0
  119. package/src/harness/anti_slop/desloppify-adapter.ts +319 -0
  120. package/src/harness/anti_slop/fallow-adapter.ts +305 -0
  121. package/src/harness/anti_slop/installer.ts +227 -0
  122. package/src/harness/anti_slop/queue.ts +216 -0
  123. package/src/harness/anti_slop/recommend.ts +84 -0
  124. package/src/harness/anti_slop/score.ts +180 -0
  125. package/src/harness/anti_slop/synthetic-edit-test.ts +128 -0
  126. package/src/harness/artifacts/agents-md.ts +88 -0
  127. package/src/harness/artifacts/checks-wiring.ts +57 -0
  128. package/src/harness/artifacts/docs-tree.ts +79 -0
  129. package/src/harness/artifacts/lint-configs.ts +136 -0
  130. package/src/harness/artifacts/review-agents.ts +67 -0
  131. package/src/harness/bare-entry.ts +108 -0
  132. package/src/harness/command.ts +1010 -0
  133. package/src/harness/default-agents/design.md +23 -0
  134. package/src/harness/default-agents/discover.md +18 -0
  135. package/src/harness/default-agents/implement.md +24 -0
  136. package/src/harness/default-agents/plan.md +19 -0
  137. package/src/harness/default-agents/research.md +21 -0
  138. package/src/harness/default-agents/validate.md +22 -0
  139. package/src/harness/gc/reporter.ts +28 -0
  140. package/src/harness/gc/runner.ts +136 -0
  141. package/src/harness/hooks/layer-context-inject.ts +155 -0
  142. package/src/harness/hooks/post-session-sweep.ts +130 -0
  143. package/src/harness/hooks/pre-edit-dupe-probe.ts +224 -0
  144. package/src/harness/hooks/register.ts +118 -0
  145. package/src/harness/model.ts +117 -0
  146. package/src/harness/pipeline.ts +348 -0
  147. package/src/harness/project-paths.ts +235 -0
  148. package/src/harness/stage-runner.ts +107 -0
  149. package/src/harness/stages/design.ts +386 -0
  150. package/src/harness/stages/discover.ts +454 -0
  151. package/src/harness/stages/implement.ts +162 -0
  152. package/src/harness/stages/plan.ts +335 -0
  153. package/src/harness/stages/research.ts +263 -0
  154. package/src/harness/stages/validate.ts +684 -0
  155. package/src/harness/storage.ts +467 -0
  156. package/src/harness/tools.ts +426 -0
  157. package/src/lsp/bridge.ts +56 -95
  158. package/src/lsp/capabilities.ts +108 -0
  159. package/src/lsp/contracts.ts +35 -0
  160. package/src/lsp/detector.ts +8 -12
  161. package/src/markdown-frontmatter.ts +68 -0
  162. package/src/mempalace/bridge.ts +135 -0
  163. package/src/mempalace/config.ts +75 -0
  164. package/src/mempalace/format.ts +163 -0
  165. package/src/mempalace/hooks.ts +370 -0
  166. package/src/mempalace/installer-helper.ts +194 -0
  167. package/src/mempalace/python/mempalace_bridge.py +440 -0
  168. package/src/mempalace/runtime.ts +565 -0
  169. package/src/mempalace/schema.ts +268 -0
  170. package/src/mempalace/session-summary.ts +198 -0
  171. package/src/mempalace/tool.ts +186 -0
  172. package/src/mempalace/uv.ts +256 -0
  173. package/src/migrate/runner.ts +354 -0
  174. package/src/planning/approval-flow.ts +206 -9
  175. package/src/planning/plan-writer-prompt.ts +4 -3
  176. package/src/planning/planning-ask-tool.ts +39 -0
  177. package/src/planning/render-markdown.ts +74 -0
  178. package/src/planning/spec.ts +42 -0
  179. package/src/planning/system-prompt.ts +11 -8
  180. package/src/planning/validate.ts +84 -0
  181. package/src/platform/omp.ts +15 -2
  182. package/src/platform/system-prompt.ts +37 -0
  183. package/src/platform/test-utils.ts +3 -0
  184. package/src/platform/types.ts +6 -1
  185. package/src/qa/config.ts +12 -6
  186. package/src/qa/detect-app-type.ts +13 -6
  187. package/src/qa/matrix.ts +12 -6
  188. package/src/qa/prompt-builder.ts +28 -30
  189. package/src/qa/scripts/dev-server-utils.ts +72 -0
  190. package/src/qa/scripts/run-e2e-tests.ts +226 -0
  191. package/src/qa/scripts/start-dev-server.ts +138 -0
  192. package/src/qa/scripts/stop-dev-server.ts +77 -0
  193. package/src/qa/session.ts +13 -7
  194. package/src/quality/ai-setup.ts +27 -25
  195. package/src/quality/contracts.ts +34 -0
  196. package/src/quality/gates/ai-review.ts +20 -58
  197. package/src/quality/gates/command.ts +249 -46
  198. package/src/quality/review-gates.ts +18 -2
  199. package/src/quality/runner.ts +63 -22
  200. package/src/quality/schemas.ts +37 -2
  201. package/src/quality/setup.ts +96 -16
  202. package/src/release/changelog.ts +1 -1
  203. package/src/release/channels/custom.ts +13 -3
  204. package/src/release/channels/types.ts +5 -0
  205. package/src/release/contracts.ts +90 -0
  206. package/src/release/executor.ts +122 -45
  207. package/src/release/prompt.ts +18 -2
  208. package/src/release/targets.ts +86 -0
  209. package/src/release/version.ts +96 -71
  210. package/src/review/agent-loader.ts +221 -109
  211. package/src/review/fixer.ts +10 -6
  212. package/src/review/multi-agent-runner.ts +114 -13
  213. package/src/review/output.ts +12 -139
  214. package/src/review/runner.ts +12 -6
  215. package/src/review/scope.ts +144 -24
  216. package/src/review/types.ts +1 -20
  217. package/src/review/validator.ts +12 -6
  218. package/src/storage/fix-pr-sessions.ts +21 -14
  219. package/src/storage/plans.ts +14 -5
  220. package/src/storage/qa-sessions.ts +25 -19
  221. package/src/storage/reliability-metrics.ts +180 -0
  222. package/src/storage/reports.ts +8 -7
  223. package/src/storage/review-sessions.ts +55 -20
  224. package/src/tool-catalog/active-tool-controller.ts +164 -0
  225. package/src/tool-catalog/active-tool-planner.ts +212 -0
  226. package/src/tool-catalog/tool-groups.ts +102 -0
  227. package/src/types.ts +1399 -5
  228. package/src/ui-design/backend-adapter.ts +78 -0
  229. package/src/ui-design/backends/local-html.ts +82 -0
  230. package/src/ui-design/backends/pencil-mcp.ts +111 -0
  231. package/src/ui-design/components-scanner.ts +124 -0
  232. package/src/ui-design/config.ts +55 -0
  233. package/src/ui-design/pen-scanner.ts +95 -0
  234. package/src/ui-design/pen-selector.ts +72 -0
  235. package/src/ui-design/prompt-builder.ts +73 -0
  236. package/src/ui-design/scanner.ts +136 -0
  237. package/src/ui-design/session.ts +974 -0
  238. package/src/ui-design/system-prompt.ts +312 -0
  239. package/src/ui-design/tokens-scanner.ts +181 -0
  240. package/src/ui-design/types.ts +96 -0
  241. package/src/ultraplan/agent-catalog.ts +522 -0
  242. package/src/ultraplan/authoring/agent-catalog.ts +310 -0
  243. package/src/ultraplan/authoring/authoring-tools.ts +552 -0
  244. package/src/ultraplan/authoring/command-handlers.ts +339 -0
  245. package/src/ultraplan/authoring/markdown.ts +510 -0
  246. package/src/ultraplan/authoring/model.ts +162 -0
  247. package/src/ultraplan/authoring/pipeline.ts +319 -0
  248. package/src/ultraplan/authoring/stage-runner.ts +141 -0
  249. package/src/ultraplan/authoring/stages/approve.ts +249 -0
  250. package/src/ultraplan/authoring/stages/discover.ts +289 -0
  251. package/src/ultraplan/authoring/stages/intake.ts +203 -0
  252. package/src/ultraplan/authoring/stages/research.ts +399 -0
  253. package/src/ultraplan/authoring/stages/review.ts +333 -0
  254. package/src/ultraplan/authoring/stages/scout.ts +188 -0
  255. package/src/ultraplan/authoring/stages/synthesize.ts +348 -0
  256. package/src/ultraplan/authoring/storage.ts +594 -0
  257. package/src/ultraplan/authoring/synth-gate.ts +165 -0
  258. package/src/ultraplan/authoring-draft.ts +653 -0
  259. package/src/ultraplan/authoring-persist.ts +180 -0
  260. package/src/ultraplan/authoring-tool.ts +608 -0
  261. package/src/ultraplan/authoring-wizard.ts +587 -0
  262. package/src/ultraplan/batch/merge.ts +98 -0
  263. package/src/ultraplan/batch/planner.ts +150 -0
  264. package/src/ultraplan/batch/presenter.ts +97 -0
  265. package/src/ultraplan/batch/storage.ts +420 -0
  266. package/src/ultraplan/batch/supervisor.ts +317 -0
  267. package/src/ultraplan/batch/worker.ts +26 -0
  268. package/src/ultraplan/batch/worktree.ts +110 -0
  269. package/src/ultraplan/contracts.ts +1593 -0
  270. package/src/ultraplan/default-agents/authoring/discoverer.md +12 -0
  271. package/src/ultraplan/default-agents/authoring/intake.md +12 -0
  272. package/src/ultraplan/default-agents/authoring/planner.md +12 -0
  273. package/src/ultraplan/default-agents/authoring/researcher.md +12 -0
  274. package/src/ultraplan/default-agents/authoring/scope-checker.md +12 -0
  275. package/src/ultraplan/default-agents/authoring/scout.md +12 -0
  276. package/src/ultraplan/default-agents/authoring/structure-checker.md +12 -0
  277. package/src/ultraplan/default-agents/authoring/tdd-checker.md +12 -0
  278. package/src/ultraplan/default-agents/backend-domain-reviewer.md +10 -0
  279. package/src/ultraplan/default-agents/backend-executor.md +10 -0
  280. package/src/ultraplan/default-agents/backend-stack-reviewer.md +10 -0
  281. package/src/ultraplan/default-agents/backend-tester.md +10 -0
  282. package/src/ultraplan/default-agents/frontend-domain-reviewer.md +10 -0
  283. package/src/ultraplan/default-agents/frontend-executor.md +10 -0
  284. package/src/ultraplan/default-agents/frontend-stack-reviewer.md +10 -0
  285. package/src/ultraplan/default-agents/frontend-tester.md +10 -0
  286. package/src/ultraplan/default-agents/infrastructure-domain-reviewer.md +10 -0
  287. package/src/ultraplan/default-agents/infrastructure-executor.md +10 -0
  288. package/src/ultraplan/default-agents/infrastructure-stack-reviewer.md +10 -0
  289. package/src/ultraplan/default-agents/infrastructure-tester.md +10 -0
  290. package/src/ultraplan/execution/contract.ts +71 -0
  291. package/src/ultraplan/execution/policy.ts +217 -0
  292. package/src/ultraplan/execution/runtime-tools.ts +107 -0
  293. package/src/ultraplan/execution/session-runner.ts +281 -0
  294. package/src/ultraplan/next-router.ts +85 -0
  295. package/src/ultraplan/presenter.ts +359 -0
  296. package/src/ultraplan/project-paths.ts +342 -0
  297. package/src/ultraplan/runtime/active-execution.ts +72 -0
  298. package/src/ultraplan/runtime/apply-mutation.ts +416 -0
  299. package/src/ultraplan/runtime/blockers.ts +243 -0
  300. package/src/ultraplan/runtime/hook-bridge.ts +486 -0
  301. package/src/ultraplan/runtime/launch-context.ts +207 -0
  302. package/src/ultraplan/runtime/migration.ts +524 -0
  303. package/src/ultraplan/runtime/normalize.ts +281 -0
  304. package/src/ultraplan/runtime/proof.ts +260 -0
  305. package/src/ultraplan/runtime/reducer.ts +416 -0
  306. package/src/ultraplan/runtime/repair.ts +251 -0
  307. package/src/ultraplan/runtime/tracker-storage.ts +368 -0
  308. package/src/ultraplan/session-selection.ts +291 -0
  309. package/src/ultraplan/storage.ts +374 -0
  310. package/src/utils/editor.ts +38 -0
  311. package/src/utils/executable.ts +80 -0
  312. package/src/utils/paths.ts +1 -20
  313. package/src/utils/shell.ts +31 -0
  314. package/src/visual/companion.ts +2 -1
  315. package/src/visual/scripts/frame-template.html +60 -0
  316. package/src/visual/scripts/index.js +59 -13
  317. package/src/visual/scripts/package.json +3 -0
  318. package/src/visual/start-server.ts +2 -1
  319. package/src/workspace/git-scope.ts +64 -0
  320. package/src/workspace/locks.ts +23 -0
  321. package/src/workspace/package-manager.ts +117 -0
  322. package/src/workspace/path-mapping.ts +75 -0
  323. package/src/workspace/project-slug.ts +92 -0
  324. package/src/workspace/repo-root.ts +137 -0
  325. package/src/workspace/selector.ts +115 -0
  326. package/src/workspace/state-paths.ts +118 -0
  327. package/src/workspace/targets.ts +313 -0
  328. package/src/fix-pr/scripts/diff-comments.sh +0 -33
  329. package/src/fix-pr/scripts/fetch-pr-comments.sh +0 -25
  330. package/src/fix-pr/scripts/trigger-review.sh +0 -36
  331. package/src/fix-pr/scripts/wait-and-check.sh +0 -37
  332. package/src/qa/scripts/detect-app-type.sh +0 -68
  333. package/src/qa/scripts/discover-routes.sh +0 -143
  334. package/src/qa/scripts/run-e2e-tests.sh +0 -131
  335. package/src/qa/scripts/start-dev-server.sh +0 -46
  336. package/src/qa/scripts/stop-dev-server.sh +0 -36
  337. package/src/review/prompts/fix-output-schema.md +0 -18
  338. package/src/review/prompts/review-output-schema.md +0 -38
  339. package/src/review/template.ts +0 -15
  340. /package/src/{review → ai}/prompts/invalid-output-retry.md +0 -0
@@ -0,0 +1,1593 @@
1
+ import { Type, type TSchema } from "@sinclair/typebox";
2
+ import { Value } from "@sinclair/typebox/value";
3
+ import type {
4
+ ResolvedUltraPlanCatalog,
5
+ ResolvedUltraPlanSlotBinding,
6
+ ThinkingLevel,
7
+ UltraPlanActorKind,
8
+ UltraPlanAgentDefinitionFrontmatter,
9
+ UltraPlanAgentSlotName,
10
+ UltraPlanAgentSlots,
11
+ UltraPlanAttemptOutcome,
12
+ UltraPlanAttemptRecord,
13
+ UltraPlanAuthoringFinding,
14
+ UltraPlanAuthoringFindingSeverity,
15
+ UltraPlanAuthoringFindingSource,
16
+ UltraPlanAuthoringFindingsArtifact,
17
+ UltraPlanAuthoringPipelineEvent,
18
+ UltraPlanAuthoringPipelineMode,
19
+ UltraPlanAuthoringSlotName,
20
+ UltraPlanAuthoringStage,
21
+ UltraPlanAuthoringStageStatus,
22
+ UltraPlanAuthoringState,
23
+ UltraPlanAuthoringArtifactRefs,
24
+ UltraPlanAuthoredArtifact,
25
+ UltraPlanBatchActiveRunLease,
26
+ UltraPlanBatchBlockerCode,
27
+ UltraPlanBatchJournalEvent,
28
+ UltraPlanBatchJournalEventType,
29
+ UltraPlanBatchNode,
30
+ UltraPlanBatchNodeBlockerKind,
31
+ UltraPlanBatchNodeState,
32
+ UltraPlanBatchRun,
33
+ UltraPlanBatchRunState,
34
+ UltraPlanBatchWave,
35
+ UltraPlanBlocker,
36
+ UltraPlanBlockerCandidate,
37
+ UltraPlanBlockerScope,
38
+ UltraPlanCursor,
39
+ UltraPlanDomain,
40
+ UltraPlanDomainReview,
41
+ UltraPlanHookEventName,
42
+ UltraPlanHookObservation,
43
+ UltraPlanIndex,
44
+ UltraPlanIndexEntry,
45
+ UltraPlanLaunchContext,
46
+ UltraPlanManifest,
47
+ UltraPlanMutationKind,
48
+ UltraPlanMutationPlan,
49
+ UltraPlanPendingMutation,
50
+ UltraPlanProof,
51
+ UltraPlanProofCandidate,
52
+ UltraPlanReducerAction,
53
+ UltraPlanRepairAction,
54
+ UltraPlanReviewerSlotName,
55
+ UltraPlanRuntimeTracker,
56
+ UltraPlanScenario,
57
+ UltraPlanSessionMigrationKind,
58
+ UltraPlanSessionMigrationRecord,
59
+ UltraPlanSourceAgent,
60
+ UltraPlanStack,
61
+ UltraPlanStackReview,
62
+ } from "../types.js";
63
+ import { getUltraPlanBatchGraphErrors } from "./batch/planner.js";
64
+
65
+ export type {
66
+ ResolvedUltraPlanCatalog,
67
+ ResolvedUltraPlanSlotBinding,
68
+ UltraPlanActorKind,
69
+ UltraPlanAgentDefinitionFrontmatter,
70
+ UltraPlanAgentSlots,
71
+ UltraPlanAttemptOutcome,
72
+ UltraPlanAttemptRecord,
73
+ UltraPlanAuthoringFinding,
74
+ UltraPlanAuthoringFindingSeverity,
75
+ UltraPlanAuthoringFindingSource,
76
+ UltraPlanAuthoringFindingsArtifact,
77
+ UltraPlanAuthoringPipelineEvent,
78
+ UltraPlanAuthoringPipelineMode,
79
+ UltraPlanAuthoringSlotName,
80
+ UltraPlanAuthoringStage,
81
+ UltraPlanAuthoringStageStatus,
82
+ UltraPlanAuthoringState,
83
+ UltraPlanAuthoringArtifactRefs,
84
+ UltraPlanAuthoredArtifact,
85
+ UltraPlanBatchActiveRunLease,
86
+ UltraPlanBatchBlockerCode,
87
+ UltraPlanBatchJournalEvent,
88
+ UltraPlanBatchJournalEventType,
89
+ UltraPlanBatchNode,
90
+ UltraPlanBatchNodeBlockerKind,
91
+ UltraPlanBatchNodeState,
92
+ UltraPlanBatchRun,
93
+ UltraPlanBatchRunState,
94
+ UltraPlanBatchWave,
95
+ UltraPlanBlocker,
96
+ UltraPlanBlockerCandidate,
97
+ UltraPlanBlockerScope,
98
+ UltraPlanCursor,
99
+ UltraPlanDomain,
100
+ UltraPlanDomainReview,
101
+ UltraPlanHookEventName,
102
+ UltraPlanHookObservation,
103
+ UltraPlanIndex,
104
+ UltraPlanIndexEntry,
105
+ UltraPlanLaunchContext,
106
+ UltraPlanManifest,
107
+ UltraPlanMutationKind,
108
+ UltraPlanMutationPlan,
109
+ UltraPlanPendingMutation,
110
+ UltraPlanProof,
111
+ UltraPlanProofCandidate,
112
+ UltraPlanReducerAction,
113
+ UltraPlanRepairAction,
114
+ UltraPlanReviewerSlotName,
115
+ UltraPlanRuntimeTracker,
116
+ UltraPlanScenario,
117
+ UltraPlanSessionMigrationKind,
118
+ UltraPlanSessionMigrationRecord,
119
+ UltraPlanSourceAgent,
120
+ UltraPlanStack,
121
+ UltraPlanStackReview,
122
+ } from "../types.js";
123
+
124
+ export const ULTRAPLAN_STACKS = ["frontend", "backend", "infrastructure"] as const;
125
+ export const ULTRAPLAN_LEVELS = ["unit", "integration", "e2e"] as const;
126
+ export const ULTRAPLAN_APPLICABILITY = ["applicable", "not-applicable"] as const;
127
+ export const ULTRAPLAN_SESSION_STATES = ["ready", "running", "blocked", "awaiting-user", "complete", "discarded"] as const;
128
+ export const ULTRAPLAN_SESSION_BUCKETS = ["pending", "ongoing", "idle", "done"] as const;
129
+ export const ULTRAPLAN_SCENARIO_STATUSES = [
130
+ "planned",
131
+ "red-running",
132
+ "red-proved",
133
+ "green-running",
134
+ "green-proved",
135
+ "in-review",
136
+ "review-passed",
137
+ "blocked",
138
+ "done",
139
+ ] as const;
140
+ export const ULTRAPLAN_REVIEW_STATUSES = ["pending", "running", "passed", "failed", "blocked"] as const;
141
+ export const ULTRAPLAN_EXECUTION_PHASES = ["red", "green", "review", "waiting", "complete"] as const;
142
+ export const ULTRAPLAN_CURSOR_TARGETS = ["scenario", "domain-review", "stack-review", "session"] as const;
143
+ export const ULTRAPLAN_AGENT_TYPES = ["built-in", "named"] as const;
144
+ export const ULTRAPLAN_PROOF_TYPES = ["test", "command", "review", "artifact"] as const;
145
+ export const ULTRAPLAN_BLOCKER_SCOPES = ["session", "stack", "domain", "scenario"] as const;
146
+ export const ULTRAPLAN_RECOVERY_MODES = ["retry", "await-user", "manual"] as const;
147
+ export const ULTRAPLAN_AGENT_SLOT_NAMES = [
148
+ "frontend-executor",
149
+ "frontend-tester",
150
+ "frontend-domain-reviewer",
151
+ "frontend-stack-reviewer",
152
+ "backend-executor",
153
+ "backend-tester",
154
+ "backend-domain-reviewer",
155
+ "backend-stack-reviewer",
156
+ "infrastructure-executor",
157
+ "infrastructure-tester",
158
+ "infrastructure-domain-reviewer",
159
+ "infrastructure-stack-reviewer",
160
+ ] as const;
161
+ export const ULTRAPLAN_THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"] as const satisfies ThinkingLevel[];
162
+ function isUltraPlanReviewerSlotName(slot: UltraPlanAgentSlotName): slot is UltraPlanReviewerSlotName {
163
+ return slot.endsWith("-domain-reviewer") || slot.endsWith("-stack-reviewer");
164
+ }
165
+ export const ULTRAPLAN_REVIEWER_SLOT_NAMES: readonly UltraPlanReviewerSlotName[] = ULTRAPLAN_AGENT_SLOT_NAMES.filter(
166
+ isUltraPlanReviewerSlotName,
167
+ );
168
+ export const ULTRAPLAN_SELECTION_SOURCES = ["default", "project"] as const;
169
+ export const ULTRAPLAN_DEFINITION_SOURCES = ["built-in", "global"] as const;
170
+ export const ULTRAPLAN_RESOLVED_VALUE_SOURCES = [
171
+ "project",
172
+ "global",
173
+ "built-in",
174
+ "unset",
175
+ ] as const;
176
+
177
+ // --- Authoring pipeline constants -------------------------------------------------
178
+
179
+ export const ULTRAPLAN_AUTHORING_STAGES = [
180
+ "intake",
181
+ "scout",
182
+ "discover",
183
+ "research",
184
+ "synthesize",
185
+ "review",
186
+ "approve",
187
+ ] as const satisfies readonly UltraPlanAuthoringStage[];
188
+
189
+ export const ULTRAPLAN_AUTHORING_STAGE_STATUSES = [
190
+ "pending",
191
+ "running",
192
+ "blocked",
193
+ "awaiting-user",
194
+ "done",
195
+ ] as const satisfies readonly UltraPlanAuthoringStageStatus[];
196
+
197
+ export const ULTRAPLAN_AUTHORING_SLOT_NAMES = [
198
+ "intake",
199
+ "scout",
200
+ "discoverer",
201
+ "researcher",
202
+ "planner",
203
+ "structure-checker",
204
+ "scope-checker",
205
+ "tdd-checker",
206
+ ] as const satisfies readonly UltraPlanAuthoringSlotName[];
207
+
208
+ export const ULTRAPLAN_AUTHORING_PIPELINE_MODES = [
209
+ "single-shot",
210
+ "multi-stage",
211
+ ] as const satisfies readonly UltraPlanAuthoringPipelineMode[];
212
+
213
+ export const ULTRAPLAN_AUTHORING_FINDING_SEVERITIES = [
214
+ "BLOCKER",
215
+ "WARNING",
216
+ ] as const satisfies readonly UltraPlanAuthoringFindingSeverity[];
217
+
218
+ export const ULTRAPLAN_AUTHORING_FINDING_SOURCES = [
219
+ "structure-checker",
220
+ "scope-checker",
221
+ "tdd-checker",
222
+ ] as const satisfies readonly UltraPlanAuthoringFindingSource[];
223
+
224
+
225
+ function keyedObject(keys: readonly string[], valueSchema: TSchema) {
226
+ return Type.Object(
227
+ Object.fromEntries(keys.map((key) => [key, valueSchema])) as Record<string, TSchema>,
228
+ { additionalProperties: false },
229
+ );
230
+ }
231
+
232
+ function sparseKeyedObject(keys: readonly string[], valueSchema: TSchema) {
233
+ return Type.Partial(keyedObject(keys, valueSchema));
234
+ }
235
+
236
+
237
+
238
+ function literalUnion<const TValue extends readonly string[]>(values: TValue) {
239
+ return Type.Union(values.map((value) => Type.Literal(value)));
240
+ }
241
+
242
+ export const UltraPlanProgressSummarySchema = Type.Object(
243
+ {
244
+ total: Type.Number({ minimum: 0 }),
245
+ terminal: Type.Number({ minimum: 0 }),
246
+ blocked: Type.Number({ minimum: 0 }),
247
+ },
248
+ { additionalProperties: false },
249
+ );
250
+
251
+ export const UltraPlanAffectedUnitRefSchema = Type.Object(
252
+ {
253
+ stack: Type.Union([literalUnion(ULTRAPLAN_STACKS), Type.Null()]),
254
+ domainId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
255
+ level: Type.Union([literalUnion(ULTRAPLAN_LEVELS), Type.Null()]),
256
+ scenarioId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
257
+ },
258
+ { additionalProperties: false },
259
+ );
260
+
261
+ export const UltraPlanProofEvidenceSchema = Type.Object(
262
+ {
263
+ summary: Type.String({ minLength: 1 }),
264
+ command: Type.Optional(Type.String({ minLength: 1 })),
265
+ outputRef: Type.Optional(Type.String({ minLength: 1 })),
266
+ metadata: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
267
+ },
268
+ { additionalProperties: false },
269
+ );
270
+
271
+ export const UltraPlanProofSchema = Type.Object(
272
+ {
273
+ type: literalUnion(ULTRAPLAN_PROOF_TYPES),
274
+ phase: literalUnion(ULTRAPLAN_EXECUTION_PHASES),
275
+ recordedAt: Type.String({ minLength: 1 }),
276
+ actor: Type.String({ minLength: 1 }),
277
+ evidence: UltraPlanProofEvidenceSchema,
278
+ artifactRef: Type.String({ minLength: 1 }),
279
+ },
280
+ { additionalProperties: false },
281
+ );
282
+
283
+ export const UltraPlanBlockerSchema = Type.Object(
284
+ {
285
+ code: Type.String({ minLength: 1 }),
286
+ message: Type.String({ minLength: 1 }),
287
+ scope: literalUnion(ULTRAPLAN_BLOCKER_SCOPES),
288
+ affected: UltraPlanAffectedUnitRefSchema,
289
+ recoverable: Type.Boolean(),
290
+ recoveryMode: literalUnion(ULTRAPLAN_RECOVERY_MODES),
291
+ nextAction: Type.String({ minLength: 1 }),
292
+ retryable: Type.Boolean(),
293
+ detectedAt: Type.String({ minLength: 1 }),
294
+ details: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
295
+ },
296
+ { additionalProperties: false },
297
+ );
298
+
299
+ export const UltraPlanAgentBindingSchema = Type.Object(
300
+ {
301
+ slot: literalUnion(ULTRAPLAN_AGENT_SLOT_NAMES),
302
+ agentType: literalUnion(ULTRAPLAN_AGENT_TYPES),
303
+ agentName: Type.String({ minLength: 1 }),
304
+ model: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
305
+ thinkingLevel: Type.Union([literalUnion(ULTRAPLAN_THINKING_LEVELS), Type.Null()]),
306
+ },
307
+ { additionalProperties: false },
308
+ );
309
+
310
+ export const UltraPlanAgentSlotsSchema = Type.Object(
311
+ {
312
+ executor: UltraPlanAgentBindingSchema,
313
+ tester: UltraPlanAgentBindingSchema,
314
+ domainReviewEnabled: Type.Boolean(),
315
+ stackReviewEnabled: Type.Boolean(),
316
+ domainReviewer: Type.Optional(UltraPlanAgentBindingSchema),
317
+ stackReviewer: Type.Optional(UltraPlanAgentBindingSchema),
318
+ },
319
+ { additionalProperties: false },
320
+ );
321
+
322
+ export const UltraPlanSlotOverrideSchema = Type.Object(
323
+ {
324
+ agentName: Type.Optional(Type.String({ minLength: 1 })),
325
+ model: Type.Optional(Type.String({ minLength: 1 })),
326
+ thinkingLevel: Type.Optional(literalUnion(ULTRAPLAN_THINKING_LEVELS)),
327
+ },
328
+ { additionalProperties: false },
329
+ );
330
+
331
+ export const UltraPlanReviewGatePolicySchema = Type.Object(
332
+ {
333
+ enabled: Type.Boolean(),
334
+ },
335
+ { additionalProperties: false },
336
+ );
337
+
338
+ export const UltraPlanConfigSchema = Type.Object(
339
+ {
340
+ slots: Type.Optional(sparseKeyedObject(ULTRAPLAN_AGENT_SLOT_NAMES, UltraPlanSlotOverrideSchema)),
341
+ reviewGates: Type.Optional(
342
+ sparseKeyedObject(ULTRAPLAN_REVIEWER_SLOT_NAMES, UltraPlanReviewGatePolicySchema),
343
+ ),
344
+ },
345
+ { additionalProperties: false },
346
+ );
347
+
348
+ export const UltraPlanAgentDefinitionFrontmatterSchema = Type.Object(
349
+ {
350
+ name: Type.String({ minLength: 1 }),
351
+ description: Type.String({ minLength: 1 }),
352
+ supportedSlots: Type.Array(literalUnion(ULTRAPLAN_AGENT_SLOT_NAMES), { minItems: 1 }),
353
+ model: Type.Optional(Type.String({ minLength: 1 })),
354
+ thinkingLevel: Type.Optional(literalUnion(ULTRAPLAN_THINKING_LEVELS)),
355
+ focus: Type.Optional(Type.String({ minLength: 1 })),
356
+ },
357
+ { additionalProperties: false },
358
+ );
359
+
360
+ export const ResolvedUltraPlanSlotBindingSchema = Type.Object(
361
+ {
362
+ slot: literalUnion(ULTRAPLAN_AGENT_SLOT_NAMES),
363
+ agentType: literalUnion(ULTRAPLAN_AGENT_TYPES),
364
+ agentName: Type.String({ minLength: 1 }),
365
+ model: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
366
+ thinkingLevel: Type.Union([literalUnion(ULTRAPLAN_THINKING_LEVELS), Type.Null()]),
367
+ selectionSource: literalUnion(ULTRAPLAN_SELECTION_SOURCES),
368
+ definitionSource: literalUnion(ULTRAPLAN_DEFINITION_SOURCES),
369
+ modelSource: literalUnion(ULTRAPLAN_RESOLVED_VALUE_SOURCES),
370
+ thinkingLevelSource: literalUnion(ULTRAPLAN_RESOLVED_VALUE_SOURCES),
371
+ definitionPath: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
372
+ },
373
+ { additionalProperties: false },
374
+ );
375
+
376
+ export const ResolvedUltraPlanCatalogSchema = Type.Object(
377
+ {
378
+ slots: keyedObject(
379
+ ULTRAPLAN_AGENT_SLOT_NAMES,
380
+ Type.Union([ResolvedUltraPlanSlotBindingSchema, Type.Null()]),
381
+ ),
382
+ reviewGates: sparseKeyedObject(
383
+ ULTRAPLAN_REVIEWER_SLOT_NAMES,
384
+ UltraPlanReviewGatePolicySchema,
385
+ ),
386
+ },
387
+ { additionalProperties: false },
388
+ );
389
+
390
+
391
+ const ULTRAPLAN_NON_TERMINAL_SCENARIO_STATUSES = [
392
+ "planned",
393
+ "red-running",
394
+ "red-proved",
395
+ "green-running",
396
+ "in-review",
397
+ "blocked",
398
+ ] as const;
399
+
400
+ const ULTRAPLAN_TERMINAL_SCENARIO_STATUSES = ["green-proved", "review-passed", "done"] as const;
401
+
402
+ const UltraPlanScenarioSharedShape = {
403
+ id: Type.String({ minLength: 1 }),
404
+ title: Type.String({ minLength: 1 }),
405
+ stack: literalUnion(ULTRAPLAN_STACKS),
406
+ domainId: Type.String({ minLength: 1 }),
407
+ level: literalUnion(ULTRAPLAN_LEVELS),
408
+ steps: Type.Array(Type.String({ minLength: 1 })),
409
+ assignedSlots: Type.Array(literalUnion(ULTRAPLAN_AGENT_SLOT_NAMES)),
410
+ dependencies: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
411
+ blocker: Type.Optional(Type.Union([UltraPlanBlockerSchema, Type.Null()])),
412
+ };
413
+
414
+ export const UltraPlanScenarioSchema = Type.Union([
415
+ Type.Object(
416
+ {
417
+ ...UltraPlanScenarioSharedShape,
418
+ status: literalUnion(ULTRAPLAN_NON_TERMINAL_SCENARIO_STATUSES),
419
+ proofs: Type.Array(UltraPlanProofSchema),
420
+ },
421
+ { additionalProperties: false },
422
+ ),
423
+ Type.Object(
424
+ {
425
+ ...UltraPlanScenarioSharedShape,
426
+ status: literalUnion(ULTRAPLAN_TERMINAL_SCENARIO_STATUSES),
427
+ proofs: Type.Array(UltraPlanProofSchema, { minItems: 1 }),
428
+ },
429
+ { additionalProperties: false },
430
+ ),
431
+ ]);
432
+
433
+ export const UltraPlanDomainReviewGateSchema = Type.Object(
434
+ {
435
+ enabled: Type.Boolean(),
436
+ status: literalUnion(ULTRAPLAN_REVIEW_STATUSES),
437
+ },
438
+ { additionalProperties: false },
439
+ );
440
+
441
+ export const UltraPlanDomainSchema = Type.Object(
442
+ {
443
+ id: Type.String({ minLength: 1 }),
444
+ name: Type.String({ minLength: 1 }),
445
+ unit: Type.Array(UltraPlanScenarioSchema),
446
+ integration: Type.Array(UltraPlanScenarioSchema),
447
+ e2e: Type.Array(UltraPlanScenarioSchema),
448
+ review: UltraPlanDomainReviewGateSchema,
449
+ progress: UltraPlanProgressSummarySchema,
450
+ },
451
+ { additionalProperties: false },
452
+ );
453
+
454
+ export const UltraPlanStackSchema = Type.Object(
455
+ {
456
+ stack: literalUnion(ULTRAPLAN_STACKS),
457
+ applicability: literalUnion(ULTRAPLAN_APPLICABILITY),
458
+ domains: Type.Array(UltraPlanDomainSchema),
459
+ status: literalUnion(ULTRAPLAN_SESSION_STATES),
460
+ agentSlots: UltraPlanAgentSlotsSchema,
461
+ progress: UltraPlanProgressSummarySchema,
462
+ },
463
+ { additionalProperties: false },
464
+ );
465
+
466
+ export const UltraPlanCursorSchema = Type.Object(
467
+ {
468
+ targetType: literalUnion(ULTRAPLAN_CURSOR_TARGETS),
469
+ stack: Type.Union([literalUnion(ULTRAPLAN_STACKS), Type.Null()]),
470
+ domainId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
471
+ level: Type.Union([literalUnion(ULTRAPLAN_LEVELS), Type.Null()]),
472
+ scenarioId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
473
+ phase: literalUnion(ULTRAPLAN_EXECUTION_PHASES),
474
+ status: literalUnion([
475
+ ...ULTRAPLAN_SCENARIO_STATUSES,
476
+ ...ULTRAPLAN_REVIEW_STATUSES,
477
+ ...ULTRAPLAN_SESSION_STATES,
478
+ ] as const),
479
+ summary: Type.String({ minLength: 1 }),
480
+ },
481
+ { additionalProperties: false },
482
+ );
483
+
484
+ export const UltraPlanDomainReviewSchema = Type.Object(
485
+ {
486
+ stack: literalUnion(ULTRAPLAN_STACKS),
487
+ domainId: Type.String({ minLength: 1 }),
488
+ reviewerSlot: literalUnion(ULTRAPLAN_AGENT_SLOT_NAMES),
489
+ status: literalUnion(ULTRAPLAN_REVIEW_STATUSES),
490
+ startedAt: Type.String({ minLength: 1 }),
491
+ completedAt: Type.Optional(Type.String({ minLength: 1 })),
492
+ summary: Type.String({ minLength: 1 }),
493
+ artifactRef: Type.String({ minLength: 1 }),
494
+ },
495
+ { additionalProperties: false },
496
+ );
497
+
498
+ export const UltraPlanStackReviewSchema = Type.Object(
499
+ {
500
+ stack: literalUnion(ULTRAPLAN_STACKS),
501
+ reviewerSlot: literalUnion(ULTRAPLAN_AGENT_SLOT_NAMES),
502
+ status: literalUnion(ULTRAPLAN_REVIEW_STATUSES),
503
+ startedAt: Type.String({ minLength: 1 }),
504
+ completedAt: Type.Optional(Type.String({ minLength: 1 })),
505
+ summary: Type.String({ minLength: 1 }),
506
+ artifactRef: Type.String({ minLength: 1 }),
507
+ },
508
+ { additionalProperties: false },
509
+ );
510
+
511
+ export const UltraPlanAuthoredArtifactSchema = Type.Object(
512
+ {
513
+ sessionId: Type.String({ minLength: 1 }),
514
+ title: Type.String({ minLength: 1 }),
515
+ goal: Type.String({ minLength: 1 }),
516
+ createdAt: Type.String({ minLength: 1 }),
517
+ updatedAt: Type.String({ minLength: 1 }),
518
+ stacks: Type.Array(UltraPlanStackSchema),
519
+ },
520
+ { additionalProperties: false },
521
+ );
522
+
523
+ export const UltraPlanManifestAuthoredRefsSchema = Type.Object(
524
+ {
525
+ json: Type.String({ minLength: 1 }),
526
+ markdown: Type.Optional(Type.String({ minLength: 1 })),
527
+ },
528
+ { additionalProperties: false },
529
+ );
530
+
531
+ export const UltraPlanManifestStackSummarySchema = Type.Object(
532
+ {
533
+ stack: literalUnion(ULTRAPLAN_STACKS),
534
+ applicability: literalUnion(ULTRAPLAN_APPLICABILITY),
535
+ progress: UltraPlanProgressSummarySchema,
536
+ domainCount: Type.Number({ minimum: 0 }),
537
+ terminalDomainCount: Type.Number({ minimum: 0 }),
538
+ },
539
+ { additionalProperties: false },
540
+ );
541
+
542
+ export const UltraPlanManifestReviewReferenceSchema = Type.Object(
543
+ {
544
+ type: literalUnion(["domain", "stack"] as const),
545
+ stack: literalUnion(ULTRAPLAN_STACKS),
546
+ domainId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
547
+ path: Type.String({ minLength: 1 }),
548
+ status: literalUnion(ULTRAPLAN_REVIEW_STATUSES),
549
+ },
550
+ { additionalProperties: false },
551
+ );
552
+
553
+ // --- Authoring pipeline schemas ---------------------------------------------------
554
+
555
+ export const UltraPlanAuthoringFindingSchema = Type.Object(
556
+ {
557
+ id: Type.String({ minLength: 1 }),
558
+ severity: literalUnion(ULTRAPLAN_AUTHORING_FINDING_SEVERITIES),
559
+ source: literalUnion(ULTRAPLAN_AUTHORING_FINDING_SOURCES),
560
+ target: Type.Object(
561
+ {
562
+ stack: Type.Union([literalUnion(ULTRAPLAN_STACKS), Type.Null()]),
563
+ domainId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
564
+ scenarioId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
565
+ },
566
+ { additionalProperties: false },
567
+ ),
568
+ message: Type.String({ minLength: 1 }),
569
+ recommendation: Type.String({ minLength: 1 }),
570
+ recordedAt: Type.String({ minLength: 1 }),
571
+ },
572
+ { additionalProperties: false },
573
+ );
574
+
575
+ export const UltraPlanAuthoringFindingsArtifactSchema = Type.Object(
576
+ {
577
+ iteration: Type.Integer({ minimum: 1 }),
578
+ draftRef: Type.String({ minLength: 1 }),
579
+ recordedAt: Type.String({ minLength: 1 }),
580
+ findings: Type.Array(UltraPlanAuthoringFindingSchema),
581
+ },
582
+ { additionalProperties: false },
583
+ );
584
+
585
+ export const UltraPlanAuthoringResearchRefSchema = Type.Object(
586
+ {
587
+ stack: literalUnion(ULTRAPLAN_STACKS),
588
+ path: Type.String({ minLength: 1 }),
589
+ },
590
+ { additionalProperties: false },
591
+ );
592
+
593
+ export const UltraPlanAuthoringArtifactRefsSchema = Type.Object(
594
+ {
595
+ intake: Type.Optional(Type.String({ minLength: 1 })),
596
+ scout: Type.Optional(Type.String({ minLength: 1 })),
597
+ discuss: Type.Optional(Type.String({ minLength: 1 })),
598
+ deferredIdeas: Type.Optional(Type.String({ minLength: 1 })),
599
+ research: Type.Optional(Type.Array(UltraPlanAuthoringResearchRefSchema)),
600
+ researchSummary: Type.Optional(Type.String({ minLength: 1 })),
601
+ draft: Type.Optional(Type.String({ minLength: 1 })),
602
+ draftMarkdown: Type.Optional(Type.String({ minLength: 1 })),
603
+ findings: Type.Optional(Type.String({ minLength: 1 })),
604
+ },
605
+ { additionalProperties: false },
606
+ );
607
+
608
+ export const UltraPlanAuthoringStateSchema = Type.Object(
609
+ {
610
+ pipeline: literalUnion(ULTRAPLAN_AUTHORING_PIPELINE_MODES),
611
+ stage: literalUnion(ULTRAPLAN_AUTHORING_STAGES),
612
+ stageStatus: literalUnion(ULTRAPLAN_AUTHORING_STAGE_STATUSES),
613
+ iteration: Type.Integer({ minimum: 1 }),
614
+ stallReentryCount: Type.Integer({ minimum: 0 }),
615
+ artifacts: UltraPlanAuthoringArtifactRefsSchema,
616
+ blocker: Type.Union([UltraPlanBlockerSchema, Type.Null()]),
617
+ startedAt: Type.String({ minLength: 1 }),
618
+ updatedAt: Type.String({ minLength: 1 }),
619
+ },
620
+ { additionalProperties: false },
621
+ );
622
+
623
+ export const UltraPlanAuthoringPipelineEventSchema = Type.Object(
624
+ {
625
+ recordedAt: Type.String({ minLength: 1 }),
626
+ stage: literalUnion(ULTRAPLAN_AUTHORING_STAGES),
627
+ stageStatus: literalUnion(ULTRAPLAN_AUTHORING_STAGE_STATUSES),
628
+ iteration: Type.Integer({ minimum: 1 }),
629
+ summary: Type.String(),
630
+ details: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
631
+ },
632
+ { additionalProperties: false },
633
+ );
634
+
635
+
636
+ export const UltraPlanManifestSchema = Type.Object(
637
+ {
638
+ sessionId: Type.String({ minLength: 1 }),
639
+ projectName: Type.String({ minLength: 1 }),
640
+ title: Type.String({ minLength: 1 }),
641
+ authored: UltraPlanManifestAuthoredRefsSchema,
642
+ state: literalUnion(ULTRAPLAN_SESSION_STATES),
643
+ cursor: Type.Union([UltraPlanCursorSchema, Type.Null()]),
644
+ lastCompleted: Type.Union([UltraPlanCursorSchema, Type.Null()]),
645
+ progress: UltraPlanProgressSummarySchema,
646
+ stacks: Type.Array(UltraPlanManifestStackSummarySchema),
647
+ blocker: Type.Union([UltraPlanBlockerSchema, Type.Null()]),
648
+ reviews: Type.Array(UltraPlanManifestReviewReferenceSchema),
649
+ createdAt: Type.String({ minLength: 1 }),
650
+ updatedAt: Type.String({ minLength: 1 }),
651
+ authoring: Type.Optional(UltraPlanAuthoringStateSchema),
652
+ },
653
+ { additionalProperties: false },
654
+ );
655
+
656
+ export const UltraPlanIndexEntrySchema = Type.Object(
657
+ {
658
+ sessionId: Type.String({ minLength: 1 }),
659
+ title: Type.String({ minLength: 1 }),
660
+ state: literalUnion(ULTRAPLAN_SESSION_STATES),
661
+ bucket: literalUnion(ULTRAPLAN_SESSION_BUCKETS),
662
+ createdAt: Type.String({ minLength: 1 }),
663
+ updatedAt: Type.String({ minLength: 1 }),
664
+ cursor: Type.Union([UltraPlanCursorSchema, Type.Null()]),
665
+ idleReason: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
666
+ authoringStage: Type.Optional(Type.Union([literalUnion(ULTRAPLAN_AUTHORING_STAGES), Type.Null()])),
667
+ },
668
+ { additionalProperties: false },
669
+ );
670
+
671
+ export const UltraPlanIndexSchema = Type.Object(
672
+ {
673
+ sessions: Type.Array(UltraPlanIndexEntrySchema),
674
+ },
675
+ { additionalProperties: false },
676
+ );
677
+
678
+ type UltraPlanTerminalProofRequirement = {
679
+ phase: UltraPlanProof["phase"];
680
+ types: readonly UltraPlanProof["type"][];
681
+ };
682
+
683
+ function getRequiredUltraPlanTerminalProofRequirements(
684
+ status: UltraPlanScenario["status"],
685
+ ): readonly UltraPlanTerminalProofRequirement[] | null {
686
+ switch (status) {
687
+ case "green-proved":
688
+ return [{ phase: "green", types: ["test", "command"] }];
689
+ case "review-passed":
690
+ return [{ phase: "review", types: ["review"] }];
691
+ case "done":
692
+ return [
693
+ { phase: "complete", types: ["artifact", "command", "test"] },
694
+ { phase: "review", types: ["review"] },
695
+ { phase: "green", types: ["test", "command"] },
696
+ ];
697
+ default:
698
+ return null;
699
+ }
700
+ }
701
+
702
+ function formatUltraPlanRequiredProofTypes(types: readonly UltraPlanProof["type"][]): string {
703
+ return types.length === 1
704
+ ? `\"${types[0]}\"`
705
+ : types.map((type) => `\"${type}\"`).join(" or ");
706
+ }
707
+
708
+ function formatUltraPlanTerminalProofRequirements(
709
+ requirements: readonly UltraPlanTerminalProofRequirement[],
710
+ ): string {
711
+ return requirements
712
+ .map((requirement) => `a \"${requirement.phase}\" proof of type ${formatUltraPlanRequiredProofTypes(requirement.types)}`)
713
+ .join(" or ");
714
+ }
715
+
716
+ export function hasRequiredUltraPlanScenarioProof(scenario: UltraPlanScenario): boolean {
717
+ const requirements = getRequiredUltraPlanTerminalProofRequirements(scenario.status);
718
+ return requirements === null
719
+ || requirements.some((requirement) =>
720
+ scenario.proofs.some((proof) => proof.phase === requirement.phase && requirement.types.includes(proof.type))
721
+ );
722
+ }
723
+
724
+ function collectUltraPlanScenarioProofErrors(
725
+ errors: string[],
726
+ level: UltraPlanScenario["level"],
727
+ scenarios: UltraPlanScenario[],
728
+ ): void {
729
+ for (const scenario of scenarios) {
730
+ const requirements = getRequiredUltraPlanTerminalProofRequirements(scenario.status);
731
+ if (!requirements || hasRequiredUltraPlanScenarioProof(scenario)) {
732
+ continue;
733
+ }
734
+
735
+ errors.push(
736
+ `/stacks/${scenario.stack}/domains/${scenario.domainId}/${level}/${scenario.id} terminal scenario \"${scenario.id}\" with status \"${scenario.status}\" requires at least one terminal proof: ${formatUltraPlanTerminalProofRequirements(requirements)}`,
737
+ );
738
+ }
739
+ }
740
+
741
+ function getUltraPlanAuthoredArtifactSemanticErrors(authored: UltraPlanAuthoredArtifact): string[] {
742
+ const errors: string[] = [];
743
+
744
+ for (const stack of authored.stacks) {
745
+ for (const domain of stack.domains) {
746
+ collectUltraPlanScenarioProofErrors(errors, "unit", domain.unit);
747
+ collectUltraPlanScenarioProofErrors(errors, "integration", domain.integration);
748
+ collectUltraPlanScenarioProofErrors(errors, "e2e", domain.e2e);
749
+ }
750
+ }
751
+
752
+ return errors;
753
+ }
754
+
755
+
756
+ export function getUltraPlanSchemaErrors(schema: TSchema, value: unknown): string[] {
757
+ return [...Value.Errors(schema, value)].map((error) => `${error.path || "/"} ${error.message}`);
758
+ }
759
+
760
+ function buildValidationResult<T>(schema: TSchema, value: unknown):
761
+ | { ok: true; value: T }
762
+ | { ok: false; errors: string[] } {
763
+ if (Value.Check(schema, value)) {
764
+ return { ok: true, value: value as T };
765
+ }
766
+
767
+ return {
768
+ ok: false,
769
+ errors: getUltraPlanSchemaErrors(schema, value),
770
+ };
771
+ }
772
+
773
+ export function validateUltraPlanIndex(value: unknown) {
774
+ return buildValidationResult<UltraPlanIndex>(UltraPlanIndexSchema, value);
775
+ }
776
+
777
+ export function validateUltraPlanManifest(value: unknown) {
778
+ return buildValidationResult<UltraPlanManifest>(UltraPlanManifestSchema, value);
779
+ }
780
+
781
+ export function validateUltraPlanAuthoringState(value: unknown) {
782
+ return buildValidationResult<UltraPlanAuthoringState>(UltraPlanAuthoringStateSchema, value);
783
+ }
784
+
785
+ export function validateUltraPlanAuthoringFindingsArtifact(value: unknown) {
786
+ return buildValidationResult<UltraPlanAuthoringFindingsArtifact>(
787
+ UltraPlanAuthoringFindingsArtifactSchema,
788
+ value,
789
+ );
790
+ }
791
+
792
+ export function validateUltraPlanAuthoringPipelineEvent(value: unknown) {
793
+ return buildValidationResult<UltraPlanAuthoringPipelineEvent>(
794
+ UltraPlanAuthoringPipelineEventSchema,
795
+ value,
796
+ );
797
+ }
798
+
799
+ export function validateUltraPlanAuthoredArtifact(value: unknown) {
800
+ const validation = buildValidationResult<UltraPlanAuthoredArtifact>(UltraPlanAuthoredArtifactSchema, value);
801
+ if (!validation.ok) {
802
+ return validation;
803
+ }
804
+
805
+ const semanticErrors = getUltraPlanAuthoredArtifactSemanticErrors(validation.value);
806
+ if (semanticErrors.length > 0) {
807
+ return { ok: false, errors: semanticErrors } as const;
808
+ }
809
+
810
+ return validation;
811
+ }
812
+
813
+ export function isUltraPlanAgentDefinitionFrontmatter(
814
+ value: unknown,
815
+ ): value is UltraPlanAgentDefinitionFrontmatter {
816
+ return Value.Check(UltraPlanAgentDefinitionFrontmatterSchema, value);
817
+ }
818
+
819
+ export function isResolvedUltraPlanSlotBinding(value: unknown): value is ResolvedUltraPlanSlotBinding {
820
+ return Value.Check(ResolvedUltraPlanSlotBindingSchema, value);
821
+ }
822
+
823
+ export function isResolvedUltraPlanCatalog(value: unknown): value is ResolvedUltraPlanCatalog {
824
+ return Value.Check(ResolvedUltraPlanCatalogSchema, value);
825
+ }
826
+
827
+
828
+ export function isUltraPlanProof(value: unknown): value is UltraPlanProof {
829
+ return Value.Check(UltraPlanProofSchema, value);
830
+ }
831
+
832
+ export function isUltraPlanBlocker(value: unknown): value is UltraPlanBlocker {
833
+ return Value.Check(UltraPlanBlockerSchema, value);
834
+ }
835
+
836
+ export function isUltraPlanScenario(value: unknown): value is UltraPlanScenario {
837
+ return Value.Check(UltraPlanScenarioSchema, value)
838
+ && hasRequiredUltraPlanScenarioProof(value as UltraPlanScenario);
839
+ }
840
+
841
+ export function isUltraPlanDomain(value: unknown): value is UltraPlanDomain {
842
+ return Value.Check(UltraPlanDomainSchema, value);
843
+ }
844
+
845
+ export function isUltraPlanAgentSlots(value: unknown): value is UltraPlanAgentSlots {
846
+ return Value.Check(UltraPlanAgentSlotsSchema, value);
847
+ }
848
+
849
+ export function isUltraPlanStack(value: unknown): value is UltraPlanStack {
850
+ return Value.Check(UltraPlanStackSchema, value);
851
+ }
852
+
853
+ export function isUltraPlanCursor(value: unknown): value is UltraPlanCursor {
854
+ return Value.Check(UltraPlanCursorSchema, value);
855
+ }
856
+
857
+ export function isUltraPlanDomainReview(value: unknown): value is UltraPlanDomainReview {
858
+ return Value.Check(UltraPlanDomainReviewSchema, value);
859
+ }
860
+
861
+ export function isUltraPlanStackReview(value: unknown): value is UltraPlanStackReview {
862
+ return Value.Check(UltraPlanStackReviewSchema, value);
863
+ }
864
+
865
+ export function isUltraPlanAuthoredArtifact(value: unknown): value is UltraPlanAuthoredArtifact {
866
+ return validateUltraPlanAuthoredArtifact(value).ok;
867
+ }
868
+
869
+ export function isUltraPlanManifest(value: unknown): value is UltraPlanManifest {
870
+ return Value.Check(UltraPlanManifestSchema, value);
871
+ }
872
+
873
+ export function isUltraPlanIndexEntry(value: unknown): value is UltraPlanIndexEntry {
874
+ return Value.Check(UltraPlanIndexEntrySchema, value);
875
+ }
876
+
877
+ export function isUltraPlanIndex(value: unknown): value is UltraPlanIndex {
878
+ return Value.Check(UltraPlanIndexSchema, value);
879
+ }
880
+
881
+
882
+ // ---------------------------------------------------------------------------
883
+ // Slice 2 runtime contracts: hook observations, attempts, tracker, reducer,
884
+ // mutation plan, migration record.
885
+ // ---------------------------------------------------------------------------
886
+
887
+ export const ULTRAPLAN_HOOK_EVENT_NAMES = [
888
+ "session_start",
889
+ "before_agent_start",
890
+ "tool_call",
891
+ "tool_result",
892
+ "agent_end",
893
+ "session_shutdown",
894
+ ] as const;
895
+
896
+ export const ULTRAPLAN_ACTOR_KINDS = ["slot", "main-orchestrator"] as const;
897
+ export const ULTRAPLAN_SOURCE_AGENTS = ["main", "sub-agent"] as const;
898
+ export const ULTRAPLAN_ATTEMPT_OUTCOMES = ["advanced", "blocked", "interrupted", "noop"] as const;
899
+ export const ULTRAPLAN_MUTATION_KINDS = [
900
+ "noop",
901
+ "start-attempt",
902
+ "stage-observation",
903
+ "advance",
904
+ "block",
905
+ "interrupt",
906
+ "repair",
907
+ "complete",
908
+ ] as const;
909
+ export const ULTRAPLAN_MIGRATION_KINDS = ["copied", "reconciled-no-op"] as const;
910
+ export const ULTRAPLAN_RUNTIME_BLOCKER_CODES = [
911
+ "correlation-ambiguous",
912
+ "proof-missing",
913
+ "proof-invalid",
914
+ "conflicting-evidence",
915
+ "interrupted-attempt",
916
+ "persistence-failure",
917
+ "unsafe-repair-required",
918
+ "migration-unsafe",
919
+ "migration-conflict",
920
+ ] as const;
921
+
922
+ export const UltraPlanLaunchContextSchema = Type.Object(
923
+ {
924
+ attemptId: Type.String({ minLength: 1 }),
925
+ attemptKey: Type.String({ minLength: 1 }),
926
+ sourceAgent: literalUnion(ULTRAPLAN_SOURCE_AGENTS),
927
+ launchedAt: Type.String({ minLength: 1 }),
928
+ },
929
+ { additionalProperties: false },
930
+ );
931
+
932
+ export const UltraPlanObservationTargetSchema = Type.Object(
933
+ {
934
+ targetType: literalUnion(ULTRAPLAN_CURSOR_TARGETS),
935
+ stack: Type.Union([literalUnion(ULTRAPLAN_STACKS), Type.Null()]),
936
+ domainId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
937
+ level: Type.Union([literalUnion(ULTRAPLAN_LEVELS), Type.Null()]),
938
+ scenarioId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
939
+ phase: literalUnion(ULTRAPLAN_EXECUTION_PHASES),
940
+ resolvedSlot: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
941
+ },
942
+ { additionalProperties: false },
943
+ );
944
+
945
+ export const UltraPlanObservationCorrelationFailureSchema = Type.Object(
946
+ {
947
+ reason: Type.String({ minLength: 1 }),
948
+ details: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
949
+ },
950
+ { additionalProperties: false },
951
+ );
952
+
953
+ export const UltraPlanHookObservationSchema = Type.Object(
954
+ {
955
+ sessionId: Type.String({ minLength: 1 }),
956
+ hookEvent: literalUnion(ULTRAPLAN_HOOK_EVENT_NAMES),
957
+ actorKind: literalUnion(ULTRAPLAN_ACTOR_KINDS),
958
+ attemptId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
959
+ attemptKey: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
960
+ sourceAgent: literalUnion(ULTRAPLAN_SOURCE_AGENTS),
961
+ occurredAt: Type.String({ minLength: 1 }),
962
+ causationId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
963
+ fingerprint: Type.String({ minLength: 1 }),
964
+ target: Type.Union([UltraPlanObservationTargetSchema, Type.Null()]),
965
+ correlationFailure: Type.Union([UltraPlanObservationCorrelationFailureSchema, Type.Null()]),
966
+ payloadSummary: Type.String(),
967
+ },
968
+ { additionalProperties: false },
969
+ );
970
+
971
+ export const UltraPlanProofCandidateTargetSchema = Type.Object(
972
+ {
973
+ targetType: literalUnion(ULTRAPLAN_CURSOR_TARGETS),
974
+ stack: Type.Union([literalUnion(ULTRAPLAN_STACKS), Type.Null()]),
975
+ domainId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
976
+ level: Type.Union([literalUnion(ULTRAPLAN_LEVELS), Type.Null()]),
977
+ scenarioId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
978
+ },
979
+ { additionalProperties: false },
980
+ );
981
+
982
+ export const UltraPlanProofCandidateSchema = Type.Object(
983
+ {
984
+ phase: literalUnion(ULTRAPLAN_EXECUTION_PHASES),
985
+ type: literalUnion(ULTRAPLAN_PROOF_TYPES),
986
+ target: UltraPlanProofCandidateTargetSchema,
987
+ evidence: UltraPlanProofEvidenceSchema,
988
+ artifactRef: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
989
+ observationFingerprint: Type.String({ minLength: 1 }),
990
+ fingerprint: Type.String({ minLength: 1 }),
991
+ },
992
+ { additionalProperties: false },
993
+ );
994
+
995
+ export const UltraPlanBlockerCandidateSchema = Type.Object(
996
+ {
997
+ blocker: UltraPlanBlockerSchema,
998
+ observationFingerprint: Type.String({ minLength: 1 }),
999
+ },
1000
+ { additionalProperties: false },
1001
+ );
1002
+
1003
+ export const UltraPlanAttemptRecordSchema = Type.Object(
1004
+ {
1005
+ attemptId: Type.String({ minLength: 1 }),
1006
+ attemptKey: Type.String({ minLength: 1 }),
1007
+ launchContext: UltraPlanLaunchContextSchema,
1008
+ cursorSnapshot: Type.Union([UltraPlanCursorSchema, Type.Null()]),
1009
+ observations: Type.Array(UltraPlanHookObservationSchema),
1010
+ proofCandidates: Type.Array(UltraPlanProofCandidateSchema),
1011
+ blockerCandidates: Type.Array(UltraPlanBlockerCandidateSchema),
1012
+ outcome: Type.Union([literalUnion(ULTRAPLAN_ATTEMPT_OUTCOMES), Type.Null()]),
1013
+ startedAt: Type.String({ minLength: 1 }),
1014
+ finalizedAt: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1015
+ },
1016
+ { additionalProperties: false },
1017
+ );
1018
+
1019
+ export const UltraPlanScenarioStatusUpdateSchema = Type.Object(
1020
+ {
1021
+ stack: literalUnion(ULTRAPLAN_STACKS),
1022
+ domainId: Type.String({ minLength: 1 }),
1023
+ level: literalUnion(ULTRAPLAN_LEVELS),
1024
+ scenarioId: Type.String({ minLength: 1 }),
1025
+ nextStatus: literalUnion(ULTRAPLAN_SCENARIO_STATUSES),
1026
+ appendProof: Type.Optional(UltraPlanProofSchema),
1027
+ },
1028
+ { additionalProperties: false },
1029
+ );
1030
+
1031
+ export const UltraPlanReviewStatusUpdateSchema = Type.Object(
1032
+ {
1033
+ type: literalUnion(["domain", "stack"] as const),
1034
+ stack: literalUnion(ULTRAPLAN_STACKS),
1035
+ domainId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1036
+ nextStatus: literalUnion(ULTRAPLAN_REVIEW_STATUSES),
1037
+ artifactRef: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1038
+ },
1039
+ { additionalProperties: false },
1040
+ );
1041
+
1042
+ export const UltraPlanBlockerUpdateSchema = Type.Object(
1043
+ {
1044
+ scope: literalUnion(ULTRAPLAN_BLOCKER_SCOPES),
1045
+ nextValue: Type.Union([UltraPlanBlockerSchema, Type.Null()]),
1046
+ clearedByObservationFingerprint: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1047
+ },
1048
+ { additionalProperties: false },
1049
+ );
1050
+
1051
+ export const UltraPlanRepairActionSchema = Type.Union([
1052
+ Type.Object(
1053
+ {
1054
+ op: Type.Literal("recompute-cursor"),
1055
+ reason: Type.String({ minLength: 1 }),
1056
+ },
1057
+ { additionalProperties: false },
1058
+ ),
1059
+ Type.Object(
1060
+ {
1061
+ op: Type.Literal("recompute-progress"),
1062
+ reason: Type.String({ minLength: 1 }),
1063
+ },
1064
+ { additionalProperties: false },
1065
+ ),
1066
+ Type.Object(
1067
+ {
1068
+ op: Type.Literal("clear-active-attempt"),
1069
+ reason: Type.String({ minLength: 1 }),
1070
+ },
1071
+ { additionalProperties: false },
1072
+ ),
1073
+ Type.Object(
1074
+ {
1075
+ op: Type.Literal("convert-active-to-interrupted"),
1076
+ attemptId: Type.String({ minLength: 1 }),
1077
+ reason: Type.String({ minLength: 1 }),
1078
+ },
1079
+ { additionalProperties: false },
1080
+ ),
1081
+ Type.Object(
1082
+ {
1083
+ op: Type.Literal("clear-blocker"),
1084
+ scope: literalUnion(ULTRAPLAN_BLOCKER_SCOPES),
1085
+ clearedByObservationFingerprint: Type.String({ minLength: 1 }),
1086
+ },
1087
+ { additionalProperties: false },
1088
+ ),
1089
+ ]);
1090
+
1091
+ export const UltraPlanTrackerAttemptFinalizationSchema = Type.Object(
1092
+ {
1093
+ attemptId: Type.String({ minLength: 1 }),
1094
+ outcome: literalUnion(ULTRAPLAN_ATTEMPT_OUTCOMES),
1095
+ finalizedAt: Type.String({ minLength: 1 }),
1096
+ },
1097
+ { additionalProperties: false },
1098
+ );
1099
+
1100
+ export const UltraPlanMutationPlanSchema = Type.Object(
1101
+ {
1102
+ kind: literalUnion(ULTRAPLAN_MUTATION_KINDS),
1103
+ rationale: Type.String({ minLength: 1 }),
1104
+ appendObservationFingerprint: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1105
+ scenarioStatusUpdate: Type.Union([UltraPlanScenarioStatusUpdateSchema, Type.Null()]),
1106
+ reviewStatusUpdate: Type.Union([UltraPlanReviewStatusUpdateSchema, Type.Null()]),
1107
+ blockerUpdate: Type.Union([UltraPlanBlockerUpdateSchema, Type.Null()]),
1108
+ cursorUpdate: Type.Union([UltraPlanCursorSchema, Type.Null()]),
1109
+ sessionStateUpdate: Type.Union([literalUnion(ULTRAPLAN_SESSION_STATES), Type.Null()]),
1110
+ trackerAttemptFinalization: Type.Union([UltraPlanTrackerAttemptFinalizationSchema, Type.Null()]),
1111
+ recomputeProgress: Type.Boolean(),
1112
+ repairActions: Type.Array(UltraPlanRepairActionSchema),
1113
+ notes: Type.Array(Type.String()),
1114
+ },
1115
+ { additionalProperties: false },
1116
+ );
1117
+
1118
+ export const UltraPlanPendingMutationSchema = Type.Object(
1119
+ {
1120
+ attemptId: Type.String({ minLength: 1 }),
1121
+ mutationPlan: UltraPlanMutationPlanSchema,
1122
+ expectedManifestFingerprint: Type.String({ minLength: 1 }),
1123
+ stagedAt: Type.String({ minLength: 1 }),
1124
+ },
1125
+ { additionalProperties: false },
1126
+ );
1127
+
1128
+ export const UltraPlanRuntimeTrackerSchema = Type.Object(
1129
+ {
1130
+ version: Type.Literal(1),
1131
+ sessionId: Type.String({ minLength: 1 }),
1132
+ activeAttempt: Type.Union([UltraPlanAttemptRecordSchema, Type.Null()]),
1133
+ finalizedAttempts: Type.Array(UltraPlanAttemptRecordSchema),
1134
+ appliedFingerprints: Type.Array(Type.String({ minLength: 1 })),
1135
+ pendingMutation: Type.Union([UltraPlanPendingMutationSchema, Type.Null()]),
1136
+ updatedAt: Type.String({ minLength: 1 }),
1137
+ },
1138
+ { additionalProperties: false },
1139
+ );
1140
+
1141
+ export const UltraPlanRepairDetailsSchema = Type.Object(
1142
+ {
1143
+ reason: Type.String({ minLength: 1 }),
1144
+ actions: Type.Array(UltraPlanRepairActionSchema),
1145
+ },
1146
+ { additionalProperties: false },
1147
+ );
1148
+
1149
+ export const UltraPlanReducerActionSchema = Type.Union([
1150
+ Type.Object(
1151
+ {
1152
+ kind: Type.Literal("session_started"),
1153
+ observation: UltraPlanHookObservationSchema,
1154
+ nowIso: Type.String({ minLength: 1 }),
1155
+ },
1156
+ { additionalProperties: false },
1157
+ ),
1158
+ Type.Object(
1159
+ {
1160
+ kind: Type.Literal("attempt_started"),
1161
+ observation: UltraPlanHookObservationSchema,
1162
+ launchContext: UltraPlanLaunchContextSchema,
1163
+ },
1164
+ { additionalProperties: false },
1165
+ ),
1166
+ Type.Object(
1167
+ {
1168
+ kind: Type.Literal("observation_staged"),
1169
+ observation: UltraPlanHookObservationSchema,
1170
+ },
1171
+ { additionalProperties: false },
1172
+ ),
1173
+ Type.Object(
1174
+ {
1175
+ kind: Type.Literal("attempt_finalized"),
1176
+ observation: UltraPlanHookObservationSchema,
1177
+ nowIso: Type.String({ minLength: 1 }),
1178
+ },
1179
+ { additionalProperties: false },
1180
+ ),
1181
+ Type.Object(
1182
+ {
1183
+ kind: Type.Literal("session_shutdown"),
1184
+ observation: UltraPlanHookObservationSchema,
1185
+ nowIso: Type.String({ minLength: 1 }),
1186
+ },
1187
+ { additionalProperties: false },
1188
+ ),
1189
+ Type.Object(
1190
+ {
1191
+ kind: Type.Literal("repair_applied"),
1192
+ nowIso: Type.String({ minLength: 1 }),
1193
+ details: UltraPlanRepairDetailsSchema,
1194
+ },
1195
+ { additionalProperties: false },
1196
+ ),
1197
+ ]);
1198
+
1199
+ export const UltraPlanSessionMigrationRecordSchema = Type.Object(
1200
+ {
1201
+ migratedAt: Type.String({ minLength: 1 }),
1202
+ legacyPath: Type.String({ minLength: 1 }),
1203
+ fingerprintBefore: Type.String({ minLength: 1 }),
1204
+ fingerprintAfter: Type.String({ minLength: 1 }),
1205
+ legacyRenamedTo: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1206
+ kind: literalUnion(ULTRAPLAN_MIGRATION_KINDS),
1207
+ },
1208
+ { additionalProperties: false },
1209
+ );
1210
+
1211
+ // ---------------------------------------------------------------------------
1212
+ // Semantic validators for contracts that express invariants above schema.
1213
+ // ---------------------------------------------------------------------------
1214
+
1215
+ const PROOF_REQUIRED_SCENARIO_STATUSES = new Set<UltraPlanScenario["status"]>([
1216
+ "red-proved",
1217
+ "green-proved",
1218
+ "review-passed",
1219
+ "done",
1220
+ ]);
1221
+
1222
+ function getUltraPlanAttemptRecordSemanticErrors(attempt: UltraPlanAttemptRecord): string[] {
1223
+ const errors: string[] = [];
1224
+ // Finalized attempts must pair outcome with finalizedAt, and vice versa.
1225
+ const hasOutcome = attempt.outcome !== null;
1226
+ const hasFinalizedAt = attempt.finalizedAt !== null;
1227
+ if (hasOutcome !== hasFinalizedAt) {
1228
+ errors.push(
1229
+ "attempt record outcome and finalizedAt must both be null or both be set",
1230
+ );
1231
+ }
1232
+ return errors;
1233
+ }
1234
+
1235
+ function getUltraPlanMutationPlanSemanticErrors(plan: UltraPlanMutationPlan): string[] {
1236
+ const errors: string[] = [];
1237
+
1238
+ const advancesScenarioWithProof = plan.scenarioStatusUpdate?.appendProof !== undefined;
1239
+ const advancesReviewToPassed = plan.reviewStatusUpdate?.nextStatus === "passed";
1240
+ const setsNewBlocker = plan.blockerUpdate !== null && plan.blockerUpdate.nextValue !== null;
1241
+ const advancesToProofRequiredStatus = plan.scenarioStatusUpdate
1242
+ ? PROOF_REQUIRED_SCENARIO_STATUSES.has(plan.scenarioStatusUpdate.nextStatus)
1243
+ : false;
1244
+
1245
+ // Rule 1: a single plan must not simultaneously advance with proof and set a new blocker.
1246
+ if ((advancesScenarioWithProof || advancesReviewToPassed) && setsNewBlocker) {
1247
+ errors.push(
1248
+ "mutation plan cannot both advance with proof and set a new blocker in one attempt finalization",
1249
+ );
1250
+ }
1251
+
1252
+ // Rule 2: advancement to a proof-required scenario status must include appendProof.
1253
+ if (plan.scenarioStatusUpdate && advancesToProofRequiredStatus && plan.scenarioStatusUpdate.appendProof === undefined) {
1254
+ errors.push(
1255
+ `scenario advancement to ${plan.scenarioStatusUpdate.nextStatus} must include appendProof`,
1256
+ );
1257
+ }
1258
+
1259
+ // Rule 3: a review advancement to passed must include an artifactRef for downstream validation.
1260
+ if (plan.reviewStatusUpdate && plan.reviewStatusUpdate.nextStatus === "passed"
1261
+ && plan.reviewStatusUpdate.artifactRef === null) {
1262
+ errors.push(
1263
+ "review advancement to passed must reference the validated review artifact",
1264
+ );
1265
+ }
1266
+
1267
+ // Rule 4: a review update referring to a stack-level target must not carry a domainId.
1268
+ if (plan.reviewStatusUpdate && plan.reviewStatusUpdate.type === "stack"
1269
+ && plan.reviewStatusUpdate.domainId !== null) {
1270
+ errors.push("stack review update must have domainId null");
1271
+ }
1272
+
1273
+ // Rule 5: kind must be consistent with the update envelope.
1274
+ if (plan.kind === "advance" && !plan.scenarioStatusUpdate && !plan.reviewStatusUpdate && !plan.sessionStateUpdate) {
1275
+ errors.push("advance mutation plan must carry at least one status update");
1276
+ }
1277
+ if (plan.kind === "block" && !setsNewBlocker) {
1278
+ errors.push("block mutation plan must set a non-null blocker");
1279
+ }
1280
+ if (plan.kind === "noop" && (plan.scenarioStatusUpdate || plan.reviewStatusUpdate || setsNewBlocker || plan.cursorUpdate || plan.sessionStateUpdate)) {
1281
+ errors.push("noop mutation plan must not carry any state update");
1282
+ }
1283
+
1284
+ return errors;
1285
+ }
1286
+
1287
+ function getUltraPlanRuntimeTrackerSemanticErrors(tracker: UltraPlanRuntimeTracker): string[] {
1288
+ const errors: string[] = [];
1289
+ if (tracker.activeAttempt) {
1290
+ errors.push(...getUltraPlanAttemptRecordSemanticErrors(tracker.activeAttempt));
1291
+ }
1292
+ for (const finalized of tracker.finalizedAttempts) {
1293
+ if (finalized.outcome === null || finalized.finalizedAt === null) {
1294
+ errors.push(`finalized attempt ${finalized.attemptId} must have outcome and finalizedAt set`);
1295
+ }
1296
+ errors.push(...getUltraPlanAttemptRecordSemanticErrors(finalized));
1297
+ }
1298
+ if (tracker.pendingMutation) {
1299
+ errors.push(...getUltraPlanMutationPlanSemanticErrors(tracker.pendingMutation.mutationPlan));
1300
+ }
1301
+ // Dedupe invariant: appliedFingerprints must not contain duplicates.
1302
+ const seen = new Set<string>();
1303
+ for (const fp of tracker.appliedFingerprints) {
1304
+ if (seen.has(fp)) {
1305
+ errors.push(`duplicate applied fingerprint ${fp}`);
1306
+ }
1307
+ seen.add(fp);
1308
+ }
1309
+ return errors;
1310
+ }
1311
+
1312
+ function getUltraPlanSessionMigrationRecordSemanticErrors(record: UltraPlanSessionMigrationRecord): string[] {
1313
+ const errors: string[] = [];
1314
+ if (record.fingerprintBefore.trim().length === 0) {
1315
+ errors.push("fingerprintBefore must be a non-empty string");
1316
+ }
1317
+ if (record.fingerprintAfter.trim().length === 0) {
1318
+ errors.push("fingerprintAfter must be a non-empty string");
1319
+ }
1320
+ // legacyPath must be absolute. Windows drive letters like "C:\path" are absolute; POSIX absolute paths start with "/".
1321
+ if (!isAbsolutePathToken(record.legacyPath)) {
1322
+ errors.push(`legacyPath must be absolute, received ${record.legacyPath}`);
1323
+ }
1324
+ if (record.legacyRenamedTo !== null && !isAbsolutePathToken(record.legacyRenamedTo)) {
1325
+ errors.push(`legacyRenamedTo must be absolute when present, received ${record.legacyRenamedTo}`);
1326
+ }
1327
+ return errors;
1328
+ }
1329
+
1330
+ function isAbsolutePathToken(candidate: string): boolean {
1331
+ if (typeof candidate !== "string" || candidate.length === 0) return false;
1332
+ if (candidate.startsWith("/")) return true;
1333
+ // Windows drive-rooted paths: "C:\\" or "C:/".
1334
+ return /^[A-Za-z]:[\/\\]/.test(candidate);
1335
+ }
1336
+
1337
+ export function validateUltraPlanRuntimeTracker(value: unknown) {
1338
+ const validation = buildValidationResult<UltraPlanRuntimeTracker>(UltraPlanRuntimeTrackerSchema, value);
1339
+ if (!validation.ok) {
1340
+ return validation;
1341
+ }
1342
+ const semanticErrors = getUltraPlanRuntimeTrackerSemanticErrors(validation.value);
1343
+ if (semanticErrors.length > 0) {
1344
+ return { ok: false, errors: semanticErrors } as const;
1345
+ }
1346
+ return validation;
1347
+ }
1348
+
1349
+ export function validateUltraPlanSessionMigrationRecord(value: unknown) {
1350
+ const validation = buildValidationResult<UltraPlanSessionMigrationRecord>(UltraPlanSessionMigrationRecordSchema, value);
1351
+ if (!validation.ok) {
1352
+ return validation;
1353
+ }
1354
+ const semanticErrors = getUltraPlanSessionMigrationRecordSemanticErrors(validation.value);
1355
+ if (semanticErrors.length > 0) {
1356
+ return { ok: false, errors: semanticErrors } as const;
1357
+ }
1358
+ return validation;
1359
+ }
1360
+
1361
+ export function isUltraPlanLaunchContext(value: unknown): value is UltraPlanLaunchContext {
1362
+ return Value.Check(UltraPlanLaunchContextSchema, value);
1363
+ }
1364
+
1365
+ export function isUltraPlanHookObservation(value: unknown): value is UltraPlanHookObservation {
1366
+ return Value.Check(UltraPlanHookObservationSchema, value);
1367
+ }
1368
+
1369
+ export function isUltraPlanProofCandidate(value: unknown): value is UltraPlanProofCandidate {
1370
+ return Value.Check(UltraPlanProofCandidateSchema, value);
1371
+ }
1372
+
1373
+ export function isUltraPlanBlockerCandidate(value: unknown): value is UltraPlanBlockerCandidate {
1374
+ return Value.Check(UltraPlanBlockerCandidateSchema, value);
1375
+ }
1376
+
1377
+ export function isUltraPlanAttemptRecord(value: unknown): value is UltraPlanAttemptRecord {
1378
+ if (!Value.Check(UltraPlanAttemptRecordSchema, value)) return false;
1379
+ return getUltraPlanAttemptRecordSemanticErrors(value as UltraPlanAttemptRecord).length === 0;
1380
+ }
1381
+
1382
+ export function isUltraPlanMutationPlan(value: unknown): value is UltraPlanMutationPlan {
1383
+ if (!Value.Check(UltraPlanMutationPlanSchema, value)) return false;
1384
+ return getUltraPlanMutationPlanSemanticErrors(value as UltraPlanMutationPlan).length === 0;
1385
+ }
1386
+
1387
+ export function isUltraPlanPendingMutation(value: unknown): value is UltraPlanPendingMutation {
1388
+ return Value.Check(UltraPlanPendingMutationSchema, value);
1389
+ }
1390
+
1391
+ export function isUltraPlanRuntimeTracker(value: unknown): value is UltraPlanRuntimeTracker {
1392
+ return validateUltraPlanRuntimeTracker(value).ok;
1393
+ }
1394
+
1395
+ export function isUltraPlanReducerAction(value: unknown): value is UltraPlanReducerAction {
1396
+ return Value.Check(UltraPlanReducerActionSchema, value);
1397
+ }
1398
+
1399
+ export function isUltraPlanSessionMigrationRecord(value: unknown): value is UltraPlanSessionMigrationRecord {
1400
+ return validateUltraPlanSessionMigrationRecord(value).ok;
1401
+ }
1402
+
1403
+ export function isUltraPlanRepairAction(value: unknown): value is UltraPlanRepairAction {
1404
+ return Value.Check(UltraPlanRepairActionSchema, value);
1405
+ }
1406
+
1407
+
1408
+ // ---------------------------------------------------------------------------
1409
+ // Slice 7 batch orchestration contracts.
1410
+ // ---------------------------------------------------------------------------
1411
+
1412
+ export const ULTRAPLAN_BATCH_RUN_STATES = ["paused", "running", "blocked", "complete", "abandoned"] as const;
1413
+ export const ULTRAPLAN_BATCH_NODE_STATES = [
1414
+ "pending",
1415
+ "preparing",
1416
+ "running",
1417
+ "merge-pending",
1418
+ "paused",
1419
+ "blocked",
1420
+ "awaiting-user",
1421
+ "merged",
1422
+ "abandoned",
1423
+ ] as const;
1424
+ export const ULTRAPLAN_BATCH_NODE_BLOCKER_KINDS = ["dependency", "session", "merge", "supervisor"] as const;
1425
+ export const ULTRAPLAN_BATCH_BLOCKER_CODES = [
1426
+ "project-identity-failed",
1427
+ "invalid-run",
1428
+ "supervisor-worktree-invalid",
1429
+ "base-drift",
1430
+ "merge-blocked",
1431
+ ] as const;
1432
+ export const ULTRAPLAN_BATCH_JOURNAL_EVENT_TYPES = [
1433
+ "run-created",
1434
+ "lease-acquired",
1435
+ "lease-released",
1436
+ "node-preparing",
1437
+ "node-running",
1438
+ "node-paused",
1439
+ "node-blocked",
1440
+ "node-awaiting-user",
1441
+ "node-merge-pending",
1442
+ "node-merged",
1443
+ "node-abandoned",
1444
+ "cleanup-warning",
1445
+ ] as const;
1446
+
1447
+ export const UltraPlanBatchWaveSchema = Type.Object(
1448
+ {
1449
+ waveIndex: Type.Number({ minimum: 0 }),
1450
+ sessionIds: Type.Array(Type.String({ minLength: 1 })),
1451
+ },
1452
+ { additionalProperties: false },
1453
+ );
1454
+
1455
+ export const UltraPlanBatchNodeSchema = Type.Object(
1456
+ {
1457
+ nodeId: Type.String({ minLength: 1 }),
1458
+ sessionId: Type.String({ minLength: 1 }),
1459
+ title: Type.String({ minLength: 1 }),
1460
+ waveIndex: Type.Number({ minimum: 0 }),
1461
+ dependencies: Type.Array(Type.String({ minLength: 1 })),
1462
+ state: literalUnion(ULTRAPLAN_BATCH_NODE_STATES),
1463
+ blockerKind: Type.Union([literalUnion(ULTRAPLAN_BATCH_NODE_BLOCKER_KINDS), Type.Null()]),
1464
+ blockerSummary: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1465
+ resumeRequestedAt: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1466
+ branchName: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1467
+ worktreePath: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1468
+ updatedAt: Type.String({ minLength: 1 }),
1469
+ },
1470
+ { additionalProperties: false },
1471
+ );
1472
+
1473
+ export const UltraPlanBatchRunSchema = Type.Object(
1474
+ {
1475
+ runId: Type.String({ minLength: 1 }),
1476
+ projectRoot: Type.String({ minLength: 1 }),
1477
+ baseBranch: Type.String({ minLength: 1 }),
1478
+ baseHead: Type.String({ minLength: 1 }),
1479
+ currentBaseHead: Type.String({ minLength: 1 }),
1480
+ createdAt: Type.String({ minLength: 1 }),
1481
+ updatedAt: Type.String({ minLength: 1 }),
1482
+ state: literalUnion(ULTRAPLAN_BATCH_RUN_STATES),
1483
+ maxParallelism: Type.Number({ minimum: 1 }),
1484
+ batchBlockerCode: Type.Union([literalUnion(ULTRAPLAN_BATCH_BLOCKER_CODES), Type.Null()]),
1485
+ batchBlockerSummary: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1486
+ batchResumeRequestedAt: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1487
+ supervisorWorktreePath: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1488
+ waves: Type.Array(UltraPlanBatchWaveSchema),
1489
+ nodes: Type.Array(UltraPlanBatchNodeSchema),
1490
+ },
1491
+ { additionalProperties: false },
1492
+ );
1493
+
1494
+ export const UltraPlanBatchActiveRunLeaseSchema = Type.Object(
1495
+ {
1496
+ runId: Type.String({ minLength: 1 }),
1497
+ ownerSessionId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1498
+ leaseAcquiredAt: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1499
+ leaseExpiresAt: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1500
+ updatedAt: Type.String({ minLength: 1 }),
1501
+ },
1502
+ { additionalProperties: false },
1503
+ );
1504
+
1505
+ export const UltraPlanBatchJournalEventSchema = Type.Object(
1506
+ {
1507
+ runId: Type.String({ minLength: 1 }),
1508
+ sessionId: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1509
+ type: literalUnion(ULTRAPLAN_BATCH_JOURNAL_EVENT_TYPES),
1510
+ recordedAt: Type.String({ minLength: 1 }),
1511
+ summary: Type.String({ minLength: 1 }),
1512
+ details: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
1513
+ },
1514
+ { additionalProperties: false },
1515
+ );
1516
+
1517
+ function parseBatchLeaseTimestamp(errors: string[], fieldName: string, value: string | null): number | null {
1518
+ if (value === null) {
1519
+ return null;
1520
+ }
1521
+ const millis = Date.parse(value);
1522
+ if (!Number.isFinite(millis)) {
1523
+ errors.push(`${fieldName} must be a valid ISO timestamp`);
1524
+ return null;
1525
+ }
1526
+ return millis;
1527
+ }
1528
+
1529
+ function getUltraPlanBatchActiveRunLeaseSemanticErrors(lease: UltraPlanBatchActiveRunLease): string[] {
1530
+ const errors: string[] = [];
1531
+ const hasOwner = lease.ownerSessionId !== null;
1532
+ const hasAcquiredAt = lease.leaseAcquiredAt !== null;
1533
+ const hasExpiresAt = lease.leaseExpiresAt !== null;
1534
+ if (hasOwner !== hasAcquiredAt || hasOwner !== hasExpiresAt) {
1535
+ return ["lease ownerSessionId, leaseAcquiredAt, and leaseExpiresAt must be all present or all null"];
1536
+ }
1537
+
1538
+ const acquiredAt = parseBatchLeaseTimestamp(errors, "leaseAcquiredAt", lease.leaseAcquiredAt);
1539
+ const expiresAt = parseBatchLeaseTimestamp(errors, "leaseExpiresAt", lease.leaseExpiresAt);
1540
+ if (acquiredAt !== null && expiresAt !== null && expiresAt <= acquiredAt) {
1541
+ errors.push("leaseExpiresAt must be after leaseAcquiredAt");
1542
+ }
1543
+
1544
+ return errors;
1545
+ }
1546
+
1547
+ export function validateUltraPlanBatchRun(value: unknown) {
1548
+ const validation = buildValidationResult<UltraPlanBatchRun>(UltraPlanBatchRunSchema, value);
1549
+ if (!validation.ok) {
1550
+ return validation;
1551
+ }
1552
+
1553
+ const semanticErrors = getUltraPlanBatchGraphErrors(validation.value);
1554
+ if (semanticErrors.length > 0) {
1555
+ return { ok: false, errors: semanticErrors } as const;
1556
+ }
1557
+
1558
+ return validation;
1559
+ }
1560
+
1561
+ export function validateUltraPlanBatchActiveRunLease(value: unknown) {
1562
+ const validation = buildValidationResult<UltraPlanBatchActiveRunLease>(UltraPlanBatchActiveRunLeaseSchema, value);
1563
+ if (!validation.ok) {
1564
+ return validation;
1565
+ }
1566
+
1567
+ const semanticErrors = getUltraPlanBatchActiveRunLeaseSemanticErrors(validation.value);
1568
+ if (semanticErrors.length > 0) {
1569
+ return { ok: false, errors: semanticErrors } as const;
1570
+ }
1571
+
1572
+ return validation;
1573
+ }
1574
+
1575
+ export function isUltraPlanBatchWave(value: unknown): value is UltraPlanBatchWave {
1576
+ return Value.Check(UltraPlanBatchWaveSchema, value);
1577
+ }
1578
+
1579
+ export function isUltraPlanBatchNode(value: unknown): value is UltraPlanBatchNode {
1580
+ return Value.Check(UltraPlanBatchNodeSchema, value);
1581
+ }
1582
+
1583
+ export function isUltraPlanBatchRun(value: unknown): value is UltraPlanBatchRun {
1584
+ return validateUltraPlanBatchRun(value).ok;
1585
+ }
1586
+
1587
+ export function isUltraPlanBatchActiveRunLease(value: unknown): value is UltraPlanBatchActiveRunLease {
1588
+ return validateUltraPlanBatchActiveRunLease(value).ok;
1589
+ }
1590
+
1591
+ export function isUltraPlanBatchJournalEvent(value: unknown): value is UltraPlanBatchJournalEvent {
1592
+ return Value.Check(UltraPlanBatchJournalEventSchema, value);
1593
+ }