@tea-agent/loop-agent 0.43.0-next.17 → 0.43.0-next.3

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 (187) hide show
  1. package/CHANGELOG.md +9 -140
  2. package/dist/application/task-lifecycle/advance.js +4 -17
  3. package/dist/application/task-lifecycle/observe.js +29 -43
  4. package/dist/application/task-lifecycle/plan-transitions.js +4 -5
  5. package/dist/build-stamp.json +3 -3
  6. package/dist/commands/client-recovery.js +55 -20
  7. package/dist/commands/new-task.js +5 -0
  8. package/dist/commands/status.js +57 -0
  9. package/dist/commands/task-contract.js +269 -0
  10. package/dist/executors/dag-pi-executor.js +230 -269
  11. package/dist/executors/pi-executor.js +0 -2
  12. package/dist/executors/pi-sdk-executor.js +39 -77
  13. package/dist/executors/shell-executor.js +2 -3
  14. package/dist/executors/shell-write-guard.js +32 -27
  15. package/dist/shared/pi-context-pressure/extension.js +16 -26
  16. package/dist/shared/pi-retry-settings.js +0 -40
  17. package/dist/shared/prompts.js +26 -0
  18. package/dist/task/config.js +2 -0
  19. package/dist/task/contract/validate-draft.js +106 -0
  20. package/dist/task/goal.js +3 -0
  21. package/dist/task/index.js +12 -0
  22. package/dist/task/lifecycle.js +1 -0
  23. package/dist/task/operator/capabilities.js +6 -0
  24. package/dist/task/operator/envelope.js +2 -0
  25. package/dist/task/operator/index.js +5 -0
  26. package/dist/task/operator/registry.js +2 -0
  27. package/dist/task/operator/types.js +1 -0
  28. package/dist/task/paths.js +1 -0
  29. package/dist/task/source-prepare/source-fidelity-pi.js +2 -2
  30. package/dist/task/source-references.js +23 -48
  31. package/dist/task/source-state.js +1 -0
  32. package/dist/task/subagent-guidance.js +1 -0
  33. package/dist/worker/console/chat/assistant-content.js +2 -23
  34. package/dist/worker/console/chat/explore-tools.js +0 -13
  35. package/dist/worker/console/chat/pi-runtime.js +1182 -221
  36. package/dist/worker/console/chat/routes.js +71 -213
  37. package/dist/worker/console/chat/sdd-data-alignment.js +9 -65
  38. package/dist/worker/console/chat/session-catalog.js +0 -32
  39. package/dist/worker/console/chat/session-store.js +6 -22
  40. package/dist/worker/console/chat/shortcuts.js +0 -6
  41. package/dist/worker/console/chat/sift-bridge.js +1 -0
  42. package/dist/worker/console/chat/tool-preview.js +0 -11
  43. package/dist/worker/console/chat/tools.js +0 -6
  44. package/dist/worker/console/console-update-and-init.js +19 -1
  45. package/dist/worker/console/console-update-runtime.js +20 -5
  46. package/dist/worker/console/index.js +20 -0
  47. package/dist/worker/console/operator-actions.js +1 -13
  48. package/dist/worker/console/routes.js +0 -8
  49. package/dist/worker/console/server.js +29 -11
  50. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-C4NXyedy.js → abnfDiagram-N423BO3Z-hUmM_GRf.js} +1 -1
  51. package/dist/worker/console/static/assets/{arc-NZ3qXvBI.js → arc-Bt-xuieW.js} +1 -1
  52. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-COZSRvml.js → architectureDiagram-T3A2C74G-DTqkL4DJ.js} +1 -1
  53. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-Ck0Gxi9C.js → blockDiagram-VBNYF7ZC-Cy0MNnzV.js} +1 -1
  54. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BX5HQ4Ox.js → c4Diagram-5PPSVZJV-DDdlT0Pd.js} +1 -1
  55. package/dist/worker/console/static/assets/channel-BpzRnZmU.js +1 -0
  56. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-CoviemSL.js → chunk-2GRJ4B5K-3JawwNZ6.js} +1 -1
  57. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-DbOdOkbZ.js → chunk-2Q5K7J3B-DoTp7Cri.js} +1 -1
  58. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BsG2pmdQ.js → chunk-5RXB4S5H-CcirhZaS.js} +1 -1
  59. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-DGdvrNm8.js → chunk-5VM5RSS4-VrG21gnP.js} +1 -1
  60. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-BAy7Yd6y.js → chunk-6Q2QTUOP-DDOgIS70.js} +1 -1
  61. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-D9UA7hUb.js → chunk-GF5L2VYU-CBjmgvJ_.js} +1 -1
  62. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-DPz7SZ8V.js → chunk-JWPE2WC7-CCQSht8M.js} +1 -1
  63. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BmuEOIh7.js → chunk-KBJHAD2P-BpGMkUUV.js} +1 -1
  64. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CIhBWnd8.js → chunk-RYQCIY6F-DNDT41QL.js} +1 -1
  65. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CScR6mDD.js → chunk-XXDRQBXY-euXnDFbn.js} +1 -1
  66. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BhlMVqCc.js +1 -0
  67. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BhlMVqCc.js +1 -0
  68. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-BjpfWaUr.js → cose-bilkent-JH36ORCC-BJ6NAeql.js} +1 -1
  69. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BFQohJgT.js → cynefin-VYW2F7L2-F5JKIvIq.js} +1 -1
  70. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-D3gzRJnS.js → cynefinDiagram-MW4NZA55-Cwmkl_Gi.js} +1 -1
  71. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-5eojkhoA.js → dagre-VZM6K2ZE-BmCZ8815.js} +1 -1
  72. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-CpD8LWu_.js → diagram-7IWD3JNH-zWA3hUnX.js} +1 -1
  73. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B8_4qJ2a.js → diagram-B4RE2ZJO-BzA-888F.js} +1 -1
  74. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-HOsXf0eu.js → diagram-LBJQPF4R-tPNheoch.js} +1 -1
  75. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-BqwRwiWP.js → diagram-Q27KOJAE-Cdi7Fyqp.js} +1 -1
  76. package/dist/worker/console/static/assets/{diagram-UB23O5K3-BRVCNZe1.js → diagram-UB23O5K3-DFK9VBf1.js} +1 -1
  77. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-Cvb1TgGh.js → ebnfDiagram-BXEA7PRR-xCUr1kpg.js} +1 -1
  78. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DS0O0qG9.js → erDiagram-JOGREHBK-BANQHY_A.js} +1 -1
  79. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-BHIRvRr3.js → flowDiagram-UKHOOZJN-VHJYEMkP.js} +1 -1
  80. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DcCJ1JWx.js → ganttDiagram-PKOTCBZU-DiyZQ0C6.js} +1 -1
  81. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-B9ia5ony.js → gitGraphDiagram-DS77QQ5N-CZtIeBBa.js} +1 -1
  82. package/dist/worker/console/static/assets/index-BlN6ytLr.css +1 -0
  83. package/dist/worker/console/static/assets/index-CA-jfWlE.js +449 -0
  84. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-3ogpgegn.js → infoDiagram-6WML65LV-BuSspC0X.js} +1 -1
  85. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-4tgpQ5SL.js → ishikawaDiagram-WSZJBQD7-DRJZyPFy.js} +1 -1
  86. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DNfgHqFx.js → journeyDiagram-NVQOT4AX-DIfXIVuE.js} +1 -1
  87. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-Dz7ngC8z.js → kanban-definition-27J2QSJJ-CT10_7Lt.js} +1 -1
  88. package/dist/worker/console/static/assets/{linear-DI7Jv62E.js → linear-ufemj74H.js} +1 -1
  89. package/dist/worker/console/static/assets/{mermaid.core-CQA4Nzmo.js → mermaid.core-DEQe8-_m.js} +5 -5
  90. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-CtsMc8Mf.js → mindmap-definition-FAOFIHXS-BRLUrbrC.js} +1 -1
  91. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-ByppE9yH.js → pegDiagram-VL7TDLO6-BgibKtiF.js} +1 -1
  92. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-B5PtgFgt.js → pieDiagram-7S7Q4E2Y-D3eyfdV9.js} +1 -1
  93. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-Cq4p0k2K.js → quadrantDiagram-CIZ2JOQS-DXeTk5Px.js} +1 -1
  94. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-DjfkyljN.js → railroadDiagram-AXF67PYL-BgXdFEe7.js} +1 -1
  95. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-DzynNRSl.js → requirementDiagram-LRYGKXZP-CseC2A7R.js} +1 -1
  96. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Cj7TCpTJ.js → sankeyDiagram-W5VNT64P-D80PFzfJ.js} +1 -1
  97. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-C73C6ykA.js → sequenceDiagram-SI44F4Z6-BWzHW7LS.js} +1 -1
  98. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-BiNLgN2x.js → sizeCapture-X5ZJPWSS-xWQYTLAn.js} +1 -1
  99. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-UwvjS64-.js → stateDiagram-OKZ733FA-CLxtpZeL.js} +1 -1
  100. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-CiVoq4G-.js +1 -0
  101. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-CC7DH98r.js → swimlanes-SLNWSIFB-DwugtmWV.js} +2 -2
  102. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BkdgdpfR.js +8 -0
  103. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-LSBXTR70.js → timeline-definition-Z64GVDOM-DHEOwHIe.js} +1 -1
  104. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-BAuxWwGP.js → vennDiagram-T6HMQDX7-pmbZKlBK.js} +1 -1
  105. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y--E5_gjZx.js → wardleyDiagram-T6FBY63Y-CivHoM5q.js} +1 -1
  106. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-dJWNmyzF.js → xychartDiagram-ELKLHX3M-BfHIE7o6.js} +1 -1
  107. package/dist/worker/console/static/index.html +2 -2
  108. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +10 -122
  109. package/dist/worker/console/static-src/operator-chat/compaction-message.js +0 -7
  110. package/dist/worker/console/static-src/operator-chat/pending-user-message.js +15 -35
  111. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +62 -136
  112. package/dist/worker/console/static-src/operator-chat/useChatStream.js +68 -159
  113. package/dist/worker/console/static-src/operator-chat/useChatThread.js +56 -75
  114. package/dist/worker/console/static-src/operator-chat/useComposer.js +78 -206
  115. package/dist/worker/console/workspace-context.js +1 -21
  116. package/dist/worker/observe/static/router.js +1 -1
  117. package/dist/worker/observe/static/styles.css +4 -7
  118. package/dist/worker/observe/static/views/dag-inspector.js +19 -12
  119. package/dist/worker/observe/static/views/dag.js +2 -2
  120. package/dist/worker/scheduler/index.js +25 -0
  121. package/dist/workflows/dag/facts.js +4 -0
  122. package/dist/workflows/dag/frontend-closeout.js +1 -1
  123. package/dist/workflows/dag/frontend-design-policy.js +1 -2
  124. package/dist/workflows/dag/frontend-implementation-contract.js +4 -8
  125. package/dist/workflows/dag/frontend-prewrite-gate.js +3 -3
  126. package/dist/workflows/dag/frontend-repair.js +76 -55
  127. package/dist/workflows/dag/frontend-review-context.js +1 -2
  128. package/dist/workflows/dag/frontend-review-scopes.js +12 -34
  129. package/dist/workflows/dag/frontend-shape-facts.js +2 -12
  130. package/dist/workflows/dag/frontend-verification-trace.js +42 -8
  131. package/dist/workflows/dag/index.js +6 -0
  132. package/dist/workflows/dag/init-hybrid.js +160 -97
  133. package/dist/workflows/dynamic/index.js +7 -0
  134. package/docs/architecture/runtime-boundaries.md +3 -3
  135. package/docs/templates/frontend-implementation-dag.json +8 -9
  136. package/package.json +3 -7
  137. package/skills/frontend-bounded-implement/SKILL.md +3 -4
  138. package/skills/frontend-bounded-implement/references/code-standards.md +3 -3
  139. package/skills/frontend-contract/references/contract-protocol.md +1 -3
  140. package/skills/frontend-design-review/SKILL.md +7 -12
  141. package/skills/frontend-design-review/references/review-checklist.md +7 -7
  142. package/skills/frontend-plan/SKILL.md +0 -19
  143. package/skills/frontend-plan/references/decision-contract.md +19 -26
  144. package/skills/frontend-review/SKILL.md +18 -12
  145. package/skills/frontend-review/references/review-findings.md +43 -24
  146. package/dist/shared/pi-provider-recovery.js +0 -182
  147. package/dist/worker/console/chat/browser-automation.js +0 -363
  148. package/dist/worker/console/chat/browser-policy.js +0 -113
  149. package/dist/worker/console/chat/browser-routes.js +0 -162
  150. package/dist/worker/console/chat/pi-runtime/custom-tools/ask-user-question.js +0 -44
  151. package/dist/worker/console/chat/pi-runtime/custom-tools/browser-tools.js +0 -89
  152. package/dist/worker/console/chat/pi-runtime/custom-tools/explore-tools.js +0 -202
  153. package/dist/worker/console/chat/pi-runtime/custom-tools/goal-tools.js +0 -79
  154. package/dist/worker/console/chat/pi-runtime/custom-tools/operator-tools.js +0 -86
  155. package/dist/worker/console/chat/pi-runtime/custom-tools/todo-write.js +0 -38
  156. package/dist/worker/console/chat/pi-runtime/inspection-types.js +0 -28
  157. package/dist/worker/console/chat/pi-runtime/inspection.js +0 -439
  158. package/dist/worker/console/chat/pi-runtime/sdk-bindings.js +0 -153
  159. package/dist/worker/console/chat/pi-runtime/sdk-session.js +0 -5
  160. package/dist/worker/console/chat/scm-routes.js +0 -217
  161. package/dist/worker/console/chat/scm-service.js +0 -283
  162. package/dist/worker/console/chat/scm-tools.js +0 -111
  163. package/dist/worker/console/chat/session-mode-view.js +0 -49
  164. package/dist/worker/console/chat/session-mode.js +0 -220
  165. package/dist/worker/console/chat/terminal-routes.js +0 -216
  166. package/dist/worker/console/chat/terminal-sessions.js +0 -348
  167. package/dist/worker/console/chat/terminal-tools.js +0 -211
  168. package/dist/worker/console/static/assets/channel-BxdTlb_5.js +0 -1
  169. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-_ByA1Nf8.js +0 -1
  170. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-_ByA1Nf8.js +0 -1
  171. package/dist/worker/console/static/assets/index-B9goN3S5.css +0 -1
  172. package/dist/worker/console/static/assets/index-wXlQohNs.js +0 -469
  173. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-nLgMZ0D3.js +0 -1
  174. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BcYqTady.js +0 -8
  175. package/dist/worker/console/static-src/operator-chat/active-turn-tail.js +0 -10
  176. package/dist/worker/console/static-src/operator-chat/chat-link.js +0 -94
  177. package/dist/worker/console/static-src/operator-chat/chat-scroll-position.js +0 -24
  178. package/dist/worker/console/static-src/operator-chat/composer-session-ledger.js +0 -192
  179. package/dist/worker/console/static-src/operator-chat/process-label.js +0 -41
  180. package/dist/worker/console/static-src/operator-chat/turn-group-equality.js +0 -13
  181. package/dist/worker/console/static-src/operator-chat/turn-process-disclosure.js +0 -10
  182. package/dist/worker/console/static-src/operator-chat/use-searchable-hidden.js +0 -51
  183. package/dist/worker/console/static-src/operator-chat/user-turn-anchor-equality.js +0 -21
  184. package/dist/worker/console/workspace-initialization.js +0 -209
  185. package/dist/workflows/dag/frontend-capacity.js +0 -9
  186. package/dist/workflows/dag/frontend-plan-completeness.js +0 -186
  187. package/dist/workflows/dag/frontend-plan-recovery-policy.js +0 -18
@@ -0,0 +1,57 @@
1
+ import { getTaskDir, getTaskPaths, getTaskStatus, loadTaskConfig, } from "../task/runtime.js";
2
+ import { getArtifactPath } from "../shared/artifacts-core.js";
3
+ import { buildTaskReadModel } from "../task/read-model.js";
4
+ export async function runStatus(repoRoot, taskId) {
5
+ // Read-only: do not refresh/repair/migrate. Mutations belong to task advance.
6
+ const state = await getTaskStatus(repoRoot, taskId);
7
+ const taskConfig = await loadTaskConfig(repoRoot, taskId);
8
+ const taskDir = getTaskDir(repoRoot, taskId);
9
+ const taskPaths = getTaskPaths(repoRoot, taskId);
10
+ const readModel = await buildTaskReadModel(repoRoot, taskId);
11
+ console.log(JSON.stringify({
12
+ taskId,
13
+ taskDir,
14
+ taskRoot: taskDir,
15
+ sourceOfTruth: "task",
16
+ artifactPaths: {
17
+ taskConfig: taskPaths.taskConfigPath,
18
+ workflowState: taskPaths.statePath,
19
+ sourceDir: taskPaths.sourceDir,
20
+ artifactsDir: `${taskDir}/artifacts`,
21
+ analysis: getArtifactPath(taskDir, "analyze"),
22
+ plan: getArtifactPath(taskDir, "plan"),
23
+ modifyLog: getArtifactPath(taskDir, "implement"),
24
+ verifyResult: getArtifactPath(taskDir, "verify"),
25
+ retrospective: getArtifactPath(taskDir, "retrospective"),
26
+ },
27
+ runRefs: {
28
+ oneShotRuns: readModel.runRefs.oneShotRuns,
29
+ dagRuns: readModel.runRefs.dagRuns,
30
+ },
31
+ readModel,
32
+ actionContext: {
33
+ mode: "dag",
34
+ allowedEditRoots: taskConfig.allowedPaths,
35
+ forbiddenPaths: taskConfig.forbiddenPaths,
36
+ constraints: taskConfig.hardConstraints,
37
+ requiresPromotion: readModel.promotion.required && !readModel.promotion.ready,
38
+ },
39
+ currentStep: state.currentStep,
40
+ status: state.status,
41
+ complexity: taskConfig.complexity,
42
+ maxFixLoops: taskConfig.maxFixLoops,
43
+ verifyEnv: taskConfig.verifyEnv ?? "clean",
44
+ maxGoalContinuationsPerRun: taskConfig.maxGoalContinuationsPerRun ?? 5,
45
+ goal: state.goal,
46
+ sourceState: state.sourceState,
47
+ completedSteps: state.completedSteps,
48
+ decisionLogSize: state.decisionLog.length,
49
+ artifacts: state.artifacts,
50
+ // Prefer task advance/status; keep single next action (no parallel command arrays).
51
+ next: {
52
+ kind: "advance-or-status",
53
+ command: readModel.nextAction.command,
54
+ reason: readModel.nextAction.reason,
55
+ },
56
+ }, null, 2));
57
+ }
@@ -0,0 +1,269 @@
1
+ import { ContractMutationError, adoptTaskContract, applyTaskContract, diffTaskContract, doctorTaskContract, loadDraftFromPath, observeTaskContractState, recoverTaskContract, validateDraftForTask, } from "../task/contract/index.js";
2
+ import { operatorFailed, operatorSucceeded, processExitCodeForOutcome, writeOperatorJson, } from "../shared/operator/index.js";
3
+ const USAGE = `usage:
4
+ task contract validate --task <id> --input <path> [--json]
5
+ task contract diff --task <id> --input <path> [--json]
6
+
7
+ Advanced-only public leaves. Managed apply/show/adopt/doctor/recover are internal services
8
+ reached via task advance / task status (or application APIs), not public CLI subcommands.`;
9
+ export function parseTaskContractArgs(args) {
10
+ const options = {};
11
+ const positional = [];
12
+ for (let i = 0; i < args.length; i += 1) {
13
+ const token = args[i];
14
+ if (token === "--json") {
15
+ options.json = true;
16
+ continue;
17
+ }
18
+ if (token === "--task") {
19
+ options.task = args[i + 1];
20
+ i += 1;
21
+ continue;
22
+ }
23
+ if (token === "--input") {
24
+ options.input = args[i + 1];
25
+ i += 1;
26
+ continue;
27
+ }
28
+ if (token === "--expected-revision") {
29
+ const raw = args[i + 1];
30
+ const n = Number(raw);
31
+ if (!Number.isInteger(n) || n < 0) {
32
+ throw new Error(`invalid --expected-revision: ${raw}`);
33
+ }
34
+ options.expectedRevision = n;
35
+ i += 1;
36
+ continue;
37
+ }
38
+ if (token === "--expected-observed-hash") {
39
+ options.expectedObservedHash = args[i + 1];
40
+ i += 1;
41
+ continue;
42
+ }
43
+ if (token === "--request-id") {
44
+ options.requestId = args[i + 1];
45
+ i += 1;
46
+ continue;
47
+ }
48
+ if (token === "--request-payload-sha256") {
49
+ options.requestPayloadSha256 = args[i + 1];
50
+ i += 1;
51
+ continue;
52
+ }
53
+ if (token === "--tx-id") {
54
+ options.txId = args[i + 1];
55
+ i += 1;
56
+ continue;
57
+ }
58
+ if (token.startsWith("-")) {
59
+ throw new Error(`unknown flag ${token}\n${USAGE}`);
60
+ }
61
+ positional.push(token);
62
+ }
63
+ const subcommand = positional[0];
64
+ if (!subcommand) {
65
+ throw new Error(USAGE);
66
+ }
67
+ // show takes positional taskId; others prefer --task
68
+ let taskId = options.task;
69
+ if (subcommand === "show") {
70
+ taskId = positional[1] ?? options.task;
71
+ }
72
+ return { subcommand, taskId, options };
73
+ }
74
+ function mutationOutcome(code) {
75
+ switch (code) {
76
+ case "REVISION_CONFLICT":
77
+ case "OBSERVED_HASH_CONFLICT":
78
+ case "REQUEST_ID_REUSE_CONFLICT":
79
+ case "LEASE_HELD":
80
+ return "conflict";
81
+ case "NOT_FOUND":
82
+ return "not-found";
83
+ case "TRANSACTION_INCOMPLETE":
84
+ case "OPERATION_NEEDS_RECONCILE":
85
+ return "needs-reconcile";
86
+ case "EXTERNALLY_MODIFIED":
87
+ case "NOT_MANAGED":
88
+ case "BINDING_DRIFT":
89
+ return "blocked";
90
+ case "INVALID_INPUT":
91
+ case "PATH_OUTSIDE_REPO":
92
+ case "UNSUPPORTED_SCHEMA_VERSION":
93
+ return "invalid";
94
+ default:
95
+ return "rejected";
96
+ }
97
+ }
98
+ function emit(result, json) {
99
+ // Machine envelope is the default for task contract when --json is set;
100
+ // without --json still print the same document for dogfood consistency.
101
+ writeOperatorJson(result);
102
+ if (!json) {
103
+ // already wrote JSON; human path same for Phase 0.5
104
+ }
105
+ process.exitCode = processExitCodeForOutcome(result.outcome);
106
+ }
107
+ export async function runTaskContract(repoRoot, args) {
108
+ let subcommand;
109
+ let taskId;
110
+ let options;
111
+ try {
112
+ ({ subcommand, taskId, options } = parseTaskContractArgs(args));
113
+ }
114
+ catch (error) {
115
+ const result = operatorFailed({
116
+ command: "task contract",
117
+ outcome: "invalid",
118
+ code: "INVALID_INPUT",
119
+ message: error instanceof Error ? error.message : String(error),
120
+ });
121
+ emit(result, true);
122
+ return;
123
+ }
124
+ const command = `task contract ${subcommand}`;
125
+ try {
126
+ switch (subcommand) {
127
+ case "show": {
128
+ if (!taskId) {
129
+ throw new ContractMutationError("INVALID_INPUT", "task contract show requires <taskId>");
130
+ }
131
+ const state = await observeTaskContractState(repoRoot, taskId);
132
+ const result = operatorSucceeded(command, { taskId, state });
133
+ emit(result, options.json);
134
+ return;
135
+ }
136
+ case "validate": {
137
+ if (!taskId || !options.input) {
138
+ throw new ContractMutationError("INVALID_INPUT", "task contract validate requires --task and --input");
139
+ }
140
+ const { draft } = await loadDraftFromPath(options.input, repoRoot);
141
+ const validation = await validateDraftForTask({
142
+ repoRoot,
143
+ taskId,
144
+ draft,
145
+ });
146
+ if (!validation.ok) {
147
+ const result = operatorFailed({
148
+ command,
149
+ outcome: "invalid",
150
+ code: "INVALID_INPUT",
151
+ message: validation.errors.join("; "),
152
+ details: { errors: validation.errors },
153
+ });
154
+ emit(result, options.json);
155
+ return;
156
+ }
157
+ const result = operatorSucceeded(command, {
158
+ taskId,
159
+ valid: true,
160
+ warnings: validation.warnings,
161
+ });
162
+ emit(result, options.json);
163
+ return;
164
+ }
165
+ case "diff": {
166
+ if (!taskId || !options.input) {
167
+ throw new ContractMutationError("INVALID_INPUT", "task contract diff requires --task and --input");
168
+ }
169
+ const { draft } = await loadDraftFromPath(options.input, repoRoot);
170
+ const diff = await diffTaskContract({ repoRoot, taskId, draft });
171
+ const result = operatorSucceeded(command, diff);
172
+ emit(result, options.json);
173
+ return;
174
+ }
175
+ case "apply": {
176
+ if (!taskId ||
177
+ !options.input ||
178
+ options.expectedRevision === undefined ||
179
+ !options.expectedObservedHash ||
180
+ !options.requestId ||
181
+ !options.requestPayloadSha256) {
182
+ throw new ContractMutationError("INVALID_INPUT", "task contract apply requires --task --input --expected-revision --expected-observed-hash --request-id --request-payload-sha256");
183
+ }
184
+ const loaded = await loadDraftFromPath(options.input, repoRoot);
185
+ // Client-supplied payload hash must match file bytes
186
+ if (loaded.payloadSha256 !== options.requestPayloadSha256) {
187
+ throw new ContractMutationError("INVALID_INPUT", `request-payload-sha256 does not match input file hash (expected ${loaded.payloadSha256})`);
188
+ }
189
+ const applyResult = await applyTaskContract({
190
+ repoRoot,
191
+ taskId,
192
+ draft: loaded.draft,
193
+ expectedRevision: options.expectedRevision,
194
+ expectedObservedHash: options.expectedObservedHash,
195
+ requestId: options.requestId,
196
+ requestPayloadSha256: options.requestPayloadSha256,
197
+ rawDraftText: loaded.rawText,
198
+ });
199
+ const result = operatorSucceeded(command, applyResult);
200
+ emit(result, options.json);
201
+ return;
202
+ }
203
+ case "adopt": {
204
+ if (!taskId ||
205
+ options.expectedRevision === undefined ||
206
+ !options.expectedObservedHash ||
207
+ !options.requestId ||
208
+ !options.requestPayloadSha256) {
209
+ throw new ContractMutationError("INVALID_INPUT", "task contract adopt requires --task --expected-revision --expected-observed-hash --request-id --request-payload-sha256");
210
+ }
211
+ const adoptResult = await adoptTaskContract({
212
+ repoRoot,
213
+ taskId,
214
+ expectedRevision: options.expectedRevision,
215
+ expectedObservedHash: options.expectedObservedHash,
216
+ requestId: options.requestId,
217
+ requestPayloadSha256: options.requestPayloadSha256,
218
+ });
219
+ const result = operatorSucceeded(command, adoptResult);
220
+ emit(result, options.json);
221
+ return;
222
+ }
223
+ case "doctor": {
224
+ if (!taskId) {
225
+ throw new ContractMutationError("INVALID_INPUT", "task contract doctor requires --task");
226
+ }
227
+ const doctor = await doctorTaskContract({ repoRoot, taskId });
228
+ const result = operatorSucceeded(command, doctor);
229
+ emit(result, options.json);
230
+ return;
231
+ }
232
+ case "recover": {
233
+ if (!taskId) {
234
+ throw new ContractMutationError("INVALID_INPUT", "task contract recover requires --task");
235
+ }
236
+ const recover = await recoverTaskContract({
237
+ repoRoot,
238
+ taskId,
239
+ txId: options.txId,
240
+ });
241
+ const result = operatorSucceeded(command, recover);
242
+ emit(result, options.json);
243
+ return;
244
+ }
245
+ default:
246
+ throw new ContractMutationError("INVALID_INPUT", `unknown task contract subcommand: ${subcommand}\n${USAGE}`);
247
+ }
248
+ }
249
+ catch (error) {
250
+ if (error instanceof ContractMutationError) {
251
+ const result = operatorFailed({
252
+ command,
253
+ outcome: mutationOutcome(error.code),
254
+ code: error.code,
255
+ message: error.message,
256
+ details: error.details,
257
+ });
258
+ emit(result, options.json);
259
+ return;
260
+ }
261
+ const result = operatorFailed({
262
+ command,
263
+ outcome: "rejected",
264
+ code: "INTERNAL_ERROR",
265
+ message: error instanceof Error ? error.message : String(error),
266
+ });
267
+ emit(result, options.json);
268
+ }
269
+ }