@tea-agent/loop-agent 0.37.0 → 0.37.1-beta.0

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 (192) hide show
  1. package/AGENTS.md +2 -6
  2. package/CHANGELOG.md +71 -144
  3. package/README.md +1 -1
  4. package/bin/loop-agent.js +1 -37
  5. package/dist/application/task-lifecycle/advance.js +0 -1
  6. package/dist/application/task-lifecycle/observe.js +0 -15
  7. package/dist/application/task-lifecycle/plan-transitions.js +0 -15
  8. package/dist/cli/command-definitions.js +0 -7
  9. package/dist/cli/program.js +3 -8
  10. package/dist/commands/init-upgrade.js +19 -351
  11. package/dist/commands/init.js +67 -14
  12. package/dist/commands/run-dag-progress.js +0 -14
  13. package/dist/commands/task-advance.js +3 -33
  14. package/dist/executors/dag-pi-executor.js +30 -47
  15. package/dist/executors/pi-sdk-executor.js +0 -34
  16. package/dist/executors/shell-executor.js +95 -6
  17. package/dist/shared/operator/capabilities.js +13 -200
  18. package/dist/shared/package-metadata.js +0 -42
  19. package/dist/task/contract/project.js +0 -4
  20. package/dist/task/source-prepare/completeness.js +0 -53
  21. package/dist/task/source-prepare/parse-intent.js +12 -82
  22. package/dist/task/source-prepare/prepare.js +5 -102
  23. package/dist/task/source-prepare/semantic-intake.js +23 -144
  24. package/dist/worker/console/chat/artifact-card.js +1 -8
  25. package/dist/worker/console/chat/chat-event-store.js +0 -152
  26. package/dist/worker/console/chat/human-gate-card.js +1 -9
  27. package/dist/worker/console/chat/operation-card.js +2 -71
  28. package/dist/worker/console/chat/pi-runtime.js +62 -111
  29. package/dist/worker/console/chat/routes.js +10 -43
  30. package/dist/worker/console/chat/session-store.js +1 -9
  31. package/dist/worker/console/chat/shortcuts.js +7 -9
  32. package/dist/worker/console/chat/turn-process.js +23 -204
  33. package/dist/worker/console/chat/workspace-landing.js +1 -2
  34. package/dist/worker/console/operation-runner.js +6 -155
  35. package/dist/worker/console/operator-actions.js +14 -391
  36. package/dist/worker/console/operator-user-error.js +0 -4
  37. package/dist/worker/console/recovery-cta.js +3 -50
  38. package/dist/worker/console/static/assets/index-HX1pbOyl.css +1 -0
  39. package/dist/worker/console/static/assets/index-M0BLEBfh.js +56 -0
  40. package/dist/worker/console/static/index.html +2 -2
  41. package/dist/worker/console/static-src/app/console-types.js +9 -13
  42. package/dist/worker/console/static-src/app/useOperatorActions.js +2 -4
  43. package/dist/worker/console/static-src/app/useRecoveryActions.js +56 -65
  44. package/dist/worker/console/static-src/app/useRecoveryConsole.js +1 -73
  45. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +30 -114
  46. package/dist/worker/console/static-src/operator-chat/refs.js +0 -3
  47. package/dist/worker/console/static-src/operator-chat/spatial-overlay.js +1 -2
  48. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +13 -67
  49. package/dist/worker/console/static-src/operator-chat/useChatThread.js +6 -12
  50. package/dist/worker/console/static-src/operator-chat/useComposer.js +8 -45
  51. package/dist/worker/console/static-src/operator-chat/workspace-layout-mode.js +3 -7
  52. package/dist/worker/loop-agent/loop-agent-client.js +3 -17
  53. package/dist/worker/observability/read-model.js +0 -20
  54. package/dist/worker/observe/spec-evidence.js +8 -3
  55. package/dist/worker/observe/static/operator-chrome.d.ts +0 -1
  56. package/dist/worker/observe/static/operator-chrome.js +3 -10
  57. package/dist/worker/observe/static/views/dag-inspector.js +71 -6
  58. package/dist/worker/observe/static/views/dag.js +0 -12
  59. package/dist/worker/preflight.js +1 -2
  60. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +707 -37
  61. package/dist/workflows/dag/backend-test-case-manifest.js +4 -0
  62. package/dist/workflows/dag/backend-test-markdown-workflow.js +109 -7
  63. package/dist/workflows/dag/backend-test-module-stem.js +5 -0
  64. package/dist/workflows/dag/backend-test-pytest-collection.js +345 -24
  65. package/dist/workflows/dag/backend-test-scenario-param.js +890 -164
  66. package/dist/workflows/dag/backend-test-writer-completeness.js +47 -16
  67. package/dist/workflows/dag/dynamic-runtime/map.js +24 -8
  68. package/dist/workflows/dag/dynamic-runtime/shared.js +1 -9
  69. package/dist/workflows/dag/frontend-implementation-contract.js +39 -233
  70. package/dist/workflows/dag/frontend-prewrite-gate.js +61 -364
  71. package/dist/workflows/dag/frontend-repair.js +18 -219
  72. package/dist/workflows/dag/frontend-verification-trace.js +32 -47
  73. package/dist/workflows/dag/init-hybrid.js +82 -165
  74. package/dist/workflows/dag/node-execution.js +0 -89
  75. package/dist/workflows/dag/recovery-recommendation.js +0 -58
  76. package/dist/workflows/dag/runner.js +15 -333
  77. package/dist/workflows/dag/scheduler.js +3 -257
  78. package/dist/workflows/dag/types.js +9 -130
  79. package/docs/README.md +3 -3
  80. package/docs/architecture/evolution.md +67 -102
  81. package/docs/templates/backend-test-dag.json +50 -32
  82. package/docs/templates/init-managed-agents.md +2 -5
  83. package/harness.json +2 -2
  84. package/package.json +3 -9
  85. package/skills/loop-agent/SKILL.md +0 -1
  86. package/skills/loop-agent/references/command-reference.md +0 -4
  87. package/dist/build-stamp.json +0 -6
  88. package/dist/commands/dag-request-interrupt.js +0 -20
  89. package/dist/worker/console/chat/assistant-content.js +0 -121
  90. package/dist/worker/console/chat/semantic-activity.js +0 -477
  91. package/dist/worker/console/operation-run-facts.js +0 -190
  92. package/dist/worker/console/operation-wait.js +0 -355
  93. package/dist/worker/console/recovery-error-copy.js +0 -198
  94. package/dist/worker/console/static/assets/abnfDiagram-N423BO3Z-DSvF6RXQ.js +0 -1
  95. package/dist/worker/console/static/assets/arc-DuI4ogtJ.js +0 -1
  96. package/dist/worker/console/static/assets/architectureDiagram-T3A2C74G-DdBbgD4y.js +0 -36
  97. package/dist/worker/console/static/assets/blockDiagram-VBNYF7ZC-xQC2HELm.js +0 -132
  98. package/dist/worker/console/static/assets/c4Diagram-5PPSVZJV-DPMSgwIZ.js +0 -10
  99. package/dist/worker/console/static/assets/channel-DLVz9TYW.js +0 -1
  100. package/dist/worker/console/static/assets/chunk-2GRJ4B5K-WTEKTxin.js +0 -1
  101. package/dist/worker/console/static/assets/chunk-2Q5K7J3B-B6vZ0Pv_.js +0 -1
  102. package/dist/worker/console/static/assets/chunk-5RXB4S5H-BrerNAix.js +0 -231
  103. package/dist/worker/console/static/assets/chunk-5VM5RSS4-D_ch2aaI.js +0 -15
  104. package/dist/worker/console/static/assets/chunk-6Q2QTUOP-VvfacNrq.js +0 -88
  105. package/dist/worker/console/static/assets/chunk-GF5L2VYU-B-uGFIg2.js +0 -206
  106. package/dist/worker/console/static/assets/chunk-JWPE2WC7-BlysCtod.js +0 -1
  107. package/dist/worker/console/static/assets/chunk-KBJHAD2P-BjAUAfcT.js +0 -1
  108. package/dist/worker/console/static/assets/chunk-RYQCIY6F-BeZnBmb-.js +0 -1
  109. package/dist/worker/console/static/assets/chunk-XXDRQBXY-Bbfe3UJG.js +0 -1
  110. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BeAuGcO9.js +0 -1
  111. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BeAuGcO9.js +0 -1
  112. package/dist/worker/console/static/assets/cose-bilkent-JH36ORCC-BKJQnYVM.js +0 -1
  113. package/dist/worker/console/static/assets/cynefin-VYW2F7L2-B1wtI3hU.js +0 -166
  114. package/dist/worker/console/static/assets/cynefinDiagram-MW4NZA55-DCF6DBSu.js +0 -62
  115. package/dist/worker/console/static/assets/cytoscape.esm-yzknjiTM.js +0 -321
  116. package/dist/worker/console/static/assets/dagre-VZM6K2ZE-BJyNGRlP.js +0 -4
  117. package/dist/worker/console/static/assets/defaultLocale-DX6XiGOO.js +0 -1
  118. package/dist/worker/console/static/assets/diagram-7IWD3JNH-B7j1-VsZ.js +0 -30
  119. package/dist/worker/console/static/assets/diagram-B4RE2ZJO-BREJ140a.js +0 -3
  120. package/dist/worker/console/static/assets/diagram-LBJQPF4R-CDPHmHGH.js +0 -24
  121. package/dist/worker/console/static/assets/diagram-Q27KOJAE-BtZLrez1.js +0 -24
  122. package/dist/worker/console/static/assets/diagram-UB23O5K3-mzybu8oU.js +0 -41
  123. package/dist/worker/console/static/assets/ebnfDiagram-BXEA7PRR-Dk3I2uO6.js +0 -1
  124. package/dist/worker/console/static/assets/erDiagram-JOGREHBK-BT97u_tQ.js +0 -85
  125. package/dist/worker/console/static/assets/flowDiagram-UKHOOZJN-CMOtYzui.js +0 -156
  126. package/dist/worker/console/static/assets/ganttDiagram-PKOTCBZU-DiNydkuY.js +0 -292
  127. package/dist/worker/console/static/assets/gitGraphDiagram-DS77QQ5N-Cwt6fLkl.js +0 -106
  128. package/dist/worker/console/static/assets/graph-DOmOIIwC.js +0 -1
  129. package/dist/worker/console/static/assets/index-DQxiso1w.js +0 -325
  130. package/dist/worker/console/static/assets/index-_j0Hzo69.css +0 -1
  131. package/dist/worker/console/static/assets/infoDiagram-6WML65LV-AsGIGKKB.js +0 -2
  132. package/dist/worker/console/static/assets/init-Gi6I4Gst.js +0 -1
  133. package/dist/worker/console/static/assets/ishikawaDiagram-WSZJBQD7-BL8ITZh3.js +0 -70
  134. package/dist/worker/console/static/assets/journeyDiagram-NVQOT4AX-VPKAUX8M.js +0 -139
  135. package/dist/worker/console/static/assets/kanban-definition-27J2QSJJ-BL56hfGp.js +0 -89
  136. package/dist/worker/console/static/assets/layout-D-LzfAck.js +0 -1
  137. package/dist/worker/console/static/assets/linear-BmSG3nIZ.js +0 -1
  138. package/dist/worker/console/static/assets/map-DxJ2ADlA.js +0 -1
  139. package/dist/worker/console/static/assets/mermaid.core-DWGK9kwP.js +0 -308
  140. package/dist/worker/console/static/assets/mindmap-definition-FAOFIHXS--vvKLjo0.js +0 -96
  141. package/dist/worker/console/static/assets/ordinal-Cboi1Yqb.js +0 -1
  142. package/dist/worker/console/static/assets/pegDiagram-VL7TDLO6-B41mxb2-.js +0 -1
  143. package/dist/worker/console/static/assets/pieDiagram-7S7Q4E2Y-DTlu77sw.js +0 -39
  144. package/dist/worker/console/static/assets/quadrantDiagram-CIZ2JOQS-Bk5A7alv.js +0 -7
  145. package/dist/worker/console/static/assets/railroadDiagram-AXF67PYL-Csf9jzQy.js +0 -1
  146. package/dist/worker/console/static/assets/requirementDiagram-LRYGKXZP-CeptoSNx.js +0 -84
  147. package/dist/worker/console/static/assets/sankeyDiagram-W5VNT64P-A-DLCLer.js +0 -40
  148. package/dist/worker/console/static/assets/sequenceDiagram-SI44F4Z6-22VbPdOI.js +0 -162
  149. package/dist/worker/console/static/assets/sizeCapture-X5ZJPWSS-DWvAyBC9.js +0 -1
  150. package/dist/worker/console/static/assets/stateDiagram-OKZ733FA-qICZ75yT.js +0 -1
  151. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DzKvfHTX.js +0 -1
  152. package/dist/worker/console/static/assets/swimlanes-SLNWSIFB-xi7lcMyp.js +0 -2
  153. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Cxqr_qM1.js +0 -8
  154. package/dist/worker/console/static/assets/timeline-definition-Z64GVDOM-Bu6Nl6O2.js +0 -120
  155. package/dist/worker/console/static/assets/vennDiagram-T6HMQDX7-BzMz4Bn9.js +0 -34
  156. package/dist/worker/console/static/assets/wardleyDiagram-T6FBY63Y-CxaJnzc5.js +0 -78
  157. package/dist/worker/console/static/assets/xychartDiagram-ELKLHX3M-5JK-omQK.js +0 -7
  158. package/dist/worker/console/static/fonts/katex/KaTeX_AMS-Regular.woff2 +0 -0
  159. package/dist/worker/console/static/fonts/katex/KaTeX_Caligraphic-Bold.woff2 +0 -0
  160. package/dist/worker/console/static/fonts/katex/KaTeX_Caligraphic-Regular.woff2 +0 -0
  161. package/dist/worker/console/static/fonts/katex/KaTeX_Fraktur-Bold.woff2 +0 -0
  162. package/dist/worker/console/static/fonts/katex/KaTeX_Fraktur-Regular.woff2 +0 -0
  163. package/dist/worker/console/static/fonts/katex/KaTeX_Main-Bold.woff2 +0 -0
  164. package/dist/worker/console/static/fonts/katex/KaTeX_Main-BoldItalic.woff2 +0 -0
  165. package/dist/worker/console/static/fonts/katex/KaTeX_Main-Italic.woff2 +0 -0
  166. package/dist/worker/console/static/fonts/katex/KaTeX_Main-Regular.woff2 +0 -0
  167. package/dist/worker/console/static/fonts/katex/KaTeX_Math-BoldItalic.woff2 +0 -0
  168. package/dist/worker/console/static/fonts/katex/KaTeX_Math-Italic.woff2 +0 -0
  169. package/dist/worker/console/static/fonts/katex/KaTeX_SansSerif-Bold.woff2 +0 -0
  170. package/dist/worker/console/static/fonts/katex/KaTeX_SansSerif-Italic.woff2 +0 -0
  171. package/dist/worker/console/static/fonts/katex/KaTeX_SansSerif-Regular.woff2 +0 -0
  172. package/dist/worker/console/static/fonts/katex/KaTeX_Script-Regular.woff2 +0 -0
  173. package/dist/worker/console/static/fonts/katex/KaTeX_Size1-Regular.woff2 +0 -0
  174. package/dist/worker/console/static/fonts/katex/KaTeX_Size2-Regular.woff2 +0 -0
  175. package/dist/worker/console/static/fonts/katex/KaTeX_Size3-Regular.woff2 +0 -0
  176. package/dist/worker/console/static/fonts/katex/KaTeX_Size4-Regular.woff2 +0 -0
  177. package/dist/worker/console/static/fonts/katex/KaTeX_Typewriter-Regular.woff2 +0 -0
  178. package/dist/worker/console/static-src/operator-chat/activity-journey.js +0 -125
  179. package/dist/worker/console/static-src/operator-chat/activity-rail-presentation.js +0 -73
  180. package/dist/worker/console/static-src/operator-chat/activity-references.js +0 -20
  181. package/dist/worker/console/static-src/operator-chat/slash-palette-layout.js +0 -24
  182. package/dist/worker/console/static-src/operator-chat/slash-palette-nav.js +0 -141
  183. package/dist/worker/console/static-src/operator-chat/useActivityRailTransition.js +0 -59
  184. package/dist/worker/observability/interrupt-eligibility.js +0 -264
  185. package/dist/workflows/dag/contract-output-registry.js +0 -14
  186. package/dist/workflows/dag/contract-validator-registrations.js +0 -8
  187. package/dist/workflows/dag/frontend-recovery-plan.js +0 -73
  188. package/dist/workflows/dag/frontend-recovery-root-manifest.js +0 -123
  189. package/dist/workflows/dag/frontend-recovery-run.js +0 -539
  190. package/dist/workflows/dag/frontend-writer-recovery.js +0 -106
  191. package/dist/workflows/dag/frontend-writer-rollback.js +0 -821
  192. package/dist/workflows/dag/interrupt-request.js +0 -559
@@ -13,13 +13,6 @@ const CONTROLLER_PROTOCOL_CAPABILITIES = [
13
13
  "worker-attempt-revision-v1",
14
14
  "recovery-decision-v2",
15
15
  ];
16
- function officialModelCallable(coverage, kind) {
17
- if (coverage === "human-gated-required")
18
- return "prepare-only";
19
- if (coverage === "advanced" && kind !== "read")
20
- return "never";
21
- return "always";
22
- }
23
16
  const officialAction = (action, cli, kind, coverage) => ({
24
17
  action,
25
18
  cli,
@@ -58,7 +51,11 @@ const officialAction = (action, cli, kind, coverage) => ({
58
51
  ]
59
52
  : []),
60
53
  ],
61
- modelCallable: officialModelCallable(coverage, kind),
54
+ modelCallable: coverage === "human-gated-required"
55
+ ? "prepare-only"
56
+ : coverage === "advanced" && kind !== "read"
57
+ ? "never"
58
+ : "always",
62
59
  humanConfirmation: coverage === "human-gated-required" ? "required" : "none",
63
60
  });
64
61
  const OFFICIAL_ACTIONS = [
@@ -145,13 +142,13 @@ const OFFICIAL_ACTIONS = [
145
142
  ["stats", "loop-agent stats", "read", "model-callable"],
146
143
  [
147
144
  "promoteRun",
148
- "loop-agent task advance",
145
+ "loop-agent task advance <id> --json",
149
146
  "mutation",
150
147
  "model-callable",
151
148
  ],
152
149
  [
153
150
  "closeoutTask",
154
- "loop-agent task advance",
151
+ "loop-agent task advance <id> --json",
155
152
  "mutation",
156
153
  "model-callable",
157
154
  ],
@@ -448,49 +445,6 @@ export function buildOperatorCapabilitiesDocument() {
448
445
  modelCallable: "always",
449
446
  humanConfirmation: "none",
450
447
  },
451
- {
452
- action: "operationWait",
453
- cli: "console canonical operation wait (read-only event-driven long poll)",
454
- kind: "read",
455
- inputSchemaVersion: 1,
456
- resultSchemaVersion: 1,
457
- resultPolicy: { readOnly: true, bounded: true, redacted: true },
458
- envelopeSchemaVersion: 1,
459
- requiredErrorCodes: [
460
- "NOT_FOUND",
461
- "INVALID_INPUT",
462
- "EVENT_CURSOR_EXPIRED",
463
- ],
464
- description: "Read-only event-driven wait on the canonical operation event ring. Default wakeOn=meaningful: heartbeats never settle the wait and are never returned as event payload (nextSeq still covers them); state/result/stdout/stderr/reconcile/error settle immediately; terminal or needs-reconcile flushes immediately. Every subsequent wait MUST pass afterSeq equal to the previous response nextSeq; omitting or reusing an older cursor replays already-consumed startup events. The response includes recommendedNextCall with the safe cursor. wakeOn=all (diagnostic compatibility) resolves on the first new event including heartbeats. maxWaitMs elapsing returns timedOut:true (a success summary, not a command failure).",
465
- inputParams: [
466
- {
467
- name: "operationId",
468
- type: "string",
469
- required: true,
470
- description: "canonical operation id",
471
- },
472
- {
473
- name: "afterSeq",
474
- type: "number",
475
- required: false,
476
- description: "event cursor; first wait may use 0, every later wait MUST use the previous response nextSeq (>= 0)",
477
- },
478
- {
479
- name: "maxWaitMs",
480
- type: "number",
481
- required: false,
482
- description: "bounded wait budget; clamped server-side (default 180000, floor 60000)",
483
- },
484
- {
485
- name: "wakeOn",
486
- type: "string",
487
- required: false,
488
- description: "wake policy: meaningful (default; heartbeats are cursor-only liveness) | all (first event settles, diagnostics)",
489
- },
490
- ],
491
- modelCallable: "always",
492
- humanConfirmation: "none",
493
- },
494
448
  {
495
449
  action: "contractShow",
496
450
  cli: "loop-agent task status <taskId> --json",
@@ -942,74 +896,6 @@ export function buildOperatorCapabilitiesDocument() {
942
896
  modelCallable: "always",
943
897
  humanConfirmation: "none",
944
898
  },
945
- {
946
- action: "taskAdvance",
947
- cli: "loop-agent task advance <taskId> [title] --task-kind <kind> --allowed-path <glob> --forbidden-path <glob> --verify <label:command> --json",
948
- kind: "long-running",
949
- inputSchemaVersion: 1,
950
- resultSchemaVersion: 1,
951
- envelopeSchemaVersion: 1,
952
- requiredErrorCodes: [
953
- ...COMMON_MUTATION_ERRORS,
954
- "INVALID_INPUT",
955
- ],
956
- description: "Canonical typed task advance mutation. Use after task creation/PRD import to apply explicit taskKind and engineering boundaries, generate + strict-validate the DAG, and stop at the writeSet gate. Never pass placeholder ids such as <id>. A successful child process may still return a blocked business outcome; inspect lifecycleState, blockers, gate, and next.",
957
- inputParams: [
958
- {
959
- name: "taskId",
960
- type: "string",
961
- required: true,
962
- description: "canonical YYYY-MM-DD-<slug> task id; placeholders are rejected",
963
- },
964
- {
965
- name: "title",
966
- type: "string",
967
- required: false,
968
- description: "optional task title for create/first advance",
969
- },
970
- {
971
- name: "taskKind",
972
- type: "string",
973
- required: false,
974
- description: "business DAG template; ordinary fixes/docs use standard",
975
- },
976
- {
977
- name: "featureId",
978
- type: "string",
979
- required: false,
980
- description: "required only by feature-scoped task kinds such as knowledge-sync",
981
- },
982
- {
983
- name: "profile",
984
- type: "string",
985
- required: false,
986
- description: "governance profile auto|minimal|standard|reviewed|supervised",
987
- },
988
- {
989
- name: "allowedPaths",
990
- type: "array",
991
- itemsType: "string",
992
- required: false,
993
- description: "explicit writer boundary globs",
994
- },
995
- {
996
- name: "forbiddenPaths",
997
- type: "array",
998
- itemsType: "string",
999
- required: false,
1000
- description: "explicit forbidden path globs",
1001
- },
1002
- {
1003
- name: "verifyCommands",
1004
- type: "array",
1005
- itemsType: "string",
1006
- required: false,
1007
- description: "verification entries as label:command strings",
1008
- },
1009
- ],
1010
- modelCallable: "always",
1011
- humanConfirmation: "none",
1012
- },
1013
899
  {
1014
900
  action: "dagRunTask",
1015
901
  cli: "loop-agent task advance <taskId> --profile auto --dag-output <path> --json",
@@ -1079,7 +965,7 @@ export function buildOperatorCapabilitiesDocument() {
1079
965
  "CONTROLLER_MISMATCH",
1080
966
  "INVALID_INPUT",
1081
967
  ],
1082
- description: "Consume a single-use execution receipt and execute the reviewed DAG (prefer task advance --approve-gate when gate token present). accepted/queued/running/operationId are NOT completion — supervise via operationGet/status/dagReport/dagDoctor/operationWait.",
968
+ description: "Consume a single-use execution receipt and execute the reviewed DAG (prefer task advance --approve-gate when gate token present). accepted/queued/running/operationId are NOT completion — supervise via operationGet/status/dagReport/dagDoctor.",
1083
969
  inputParams: [
1084
970
  {
1085
971
  name: "executionId",
@@ -1102,7 +988,7 @@ export function buildOperatorCapabilitiesDocument() {
1102
988
  resultSchemaVersion: 1,
1103
989
  envelopeSchemaVersion: 1,
1104
990
  requiredErrorCodes: ["INVALID_INPUT", "NOT_FOUND"],
1105
- description: "Read-only R1 subgraph plan (no mutation). Call before dagRerun. Prefer primaryFailure.nodeId from dagReport. If eligible=false (writer/decision/fingerprint, unsafe shell, worker-managed, workspace/controller drift), do not force execute — Worker-owned runs use workerTaskRetry; standalone runs use standaloneTaskRerun or same-task advance after fixing the root cause (contract changes must be adopted first). Returns planHash required by execute.",
991
+ description: "Read-only R1 subgraph plan (no mutation). Call before dagRerun. Prefer primaryFailure.nodeId from dagReport. If eligible=false (writer/decision/fingerprint), do not force execute — fall back to standaloneTaskRerun or same-task advance. Returns planHash required by execute.",
1106
992
  inputParams: [
1107
993
  {
1108
994
  name: "runId",
@@ -1165,73 +1051,6 @@ export function buildOperatorCapabilitiesDocument() {
1165
1051
  modelCallable: "always",
1166
1052
  humanConfirmation: "none",
1167
1053
  },
1168
- {
1169
- action: "dagInterruptEligibility",
1170
- cli: "console dag-interrupt-eligibility",
1171
- kind: "read",
1172
- inputSchemaVersion: 1,
1173
- resultSchemaVersion: 1,
1174
- envelopeSchemaVersion: 1,
1175
- requiredErrorCodes: ["INVALID_INPUT", "NOT_FOUND"],
1176
- description: "Read-only eligibility for cooperative live-DAG interrupt. v1 only Console-owned active running operations. Worker-managed / unknown owner / orphaned / terminal runs return eligible=false with stable reasonCodes. Does not create a Human Gate receipt or mutate the run.",
1177
- inputParams: [
1178
- {
1179
- name: "runId",
1180
- type: "string",
1181
- required: true,
1182
- description: "active dag run id to inspect for interrupt eligibility",
1183
- },
1184
- ],
1185
- modelCallable: "always",
1186
- humanConfirmation: "none",
1187
- },
1188
- {
1189
- action: "dagRequestInterrupt",
1190
- cli: "loop-agent dag request-interrupt --run-id <id> --request-id <id> --target-operation-id <id> --reason-code <code> --reason <detail> --json",
1191
- kind: "mutation",
1192
- inputSchemaVersion: 1,
1193
- resultSchemaVersion: 1,
1194
- envelopeSchemaVersion: 1,
1195
- requiredErrorCodes: [
1196
- ...COMMON_MUTATION_ERRORS,
1197
- "HUMAN_CONFIRMATION_REQUIRED",
1198
- "RUN_NOT_ACTIVE",
1199
- "RUN_NOT_CONSOLE_OWNED",
1200
- "RUNNER_IDENTITY_MISMATCH",
1201
- "INTERRUPT_ALREADY_PENDING",
1202
- "RUN_ALREADY_TERMINAL",
1203
- "INTERRUPT_NEEDS_RECONCILE",
1204
- ],
1205
- description: "Request cooperative abort of a Console-owned running DAG. Success means interrupt.json is requested, not that the run has already stopped. Browser Human Gate only; model must not call this action.",
1206
- inputParams: [
1207
- {
1208
- name: "runId",
1209
- type: "string",
1210
- required: true,
1211
- description: "active dag run id",
1212
- },
1213
- {
1214
- name: "reasonCode",
1215
- type: "string",
1216
- required: true,
1217
- description: "requirements-changed | suspected-runaway | resource-protection | operator-request | other",
1218
- },
1219
- {
1220
- name: "reasonDetail",
1221
- type: "string",
1222
- required: true,
1223
- description: "10–500 character operator reason; do not auto-fill placeholders",
1224
- },
1225
- {
1226
- name: "confirmationId",
1227
- type: "string",
1228
- required: true,
1229
- description: "human confirmation receipt id from prepareMutationGate",
1230
- },
1231
- ],
1232
- modelCallable: "prepare-only",
1233
- humanConfirmation: "required",
1234
- },
1235
1054
  {
1236
1055
  action: "prepareMutationGate",
1237
1056
  cli: "console prepare-mutation-gate",
@@ -1240,13 +1059,13 @@ export function buildOperatorCapabilitiesDocument() {
1240
1059
  resultSchemaVersion: 1,
1241
1060
  envelopeSchemaVersion: 1,
1242
1061
  requiredErrorCodes: ["INVALID_INPUT", "NOT_FOUND"],
1243
- description: "Prepare a one-shot Human Gate receipt for destructive reconcile, live DAG interrupt, and Night Scheduler mutations. Model may prepare; only the browser mutation gate may consume. Do not use for dagRerun / standaloneTaskRerun / workerTaskRetry.",
1062
+ description: "Prepare a one-shot Human Gate receipt for Night Scheduler mutations. Model may prepare; only the browser mutation gate may consume.",
1244
1063
  inputParams: [
1245
1064
  {
1246
1065
  name: "action",
1247
1066
  type: "string",
1248
1067
  required: true,
1249
- description: "target action: dagReconcileRun | dagRequestInterrupt | workerAdmissionPrepare | workerSchedulerAdd | workerSchedulerCancel | workerSchedulerHarvest | workerSchedulerDiscard. Not for standaloneTaskRerun / workerTaskRetry / dagRerun (those are autonomous).",
1068
+ description: "target action: workerAdmissionPrepare | workerSchedulerAdd | workerSchedulerCancel | workerSchedulerHarvest | workerSchedulerDiscard",
1250
1069
  },
1251
1070
  {
1252
1071
  name: "actionParams",
@@ -1498,7 +1317,7 @@ export function buildOperatorCapabilitiesDocument() {
1498
1317
  "INVALID_INPUT",
1499
1318
  "HUMAN_CONFIRMATION_REQUIRED",
1500
1319
  ],
1501
- description: "Full standalone task regenerate → validate → execute with parent lineage. Only when node rerun plan is ineligible or primaryRecovery recommends rerun-task; the server checks read-only run facts before accepting. Regeneration reuses the CURRENT contract snapshot: if the failure requires contract changes (e.g. allowing a catalog index path), first update the contract (re-import PRD, or adopt externally-edited sources via `task contract adopt`) BEFORE calling this action, otherwise the regenerated DAG repeats the same failure.",
1320
+ description: "Full standalone task regenerate → validate → execute with parent lineage. Only when node rerun plan is ineligible or primaryRecovery recommends rerun-task; the server checks read-only run facts before accepting.",
1502
1321
  inputParams: [
1503
1322
  {
1504
1323
  name: "runId",
@@ -1619,7 +1438,7 @@ export const OPERATOR_COMMAND_COVERAGE = Object.freeze([
1619
1438
  {
1620
1439
  command: "loop-agent task advance",
1621
1440
  coverage: "model-callable",
1622
- action: "taskAdvance",
1441
+ action: "newTask",
1623
1442
  source: "loop-agent",
1624
1443
  },
1625
1444
  {
@@ -2059,12 +1878,6 @@ export const OPERATOR_COMMAND_COVERAGE = Object.freeze([
2059
1878
  action: "dagReconcileRun",
2060
1879
  source: "loop-agent",
2061
1880
  },
2062
- {
2063
- command: "loop-agent dag request-interrupt",
2064
- coverage: "human-gated-required",
2065
- action: "dagRequestInterrupt",
2066
- source: "loop-agent",
2067
- },
2068
1881
  {
2069
1882
  command: "loop-agent dag rerun",
2070
1883
  coverage: "model-callable",
@@ -45,48 +45,6 @@ export function readPackageName(packageDir) {
45
45
  }
46
46
  return undefined;
47
47
  }
48
- /**
49
- * Read the build stamp (git SHA + build time) written by the build pipeline
50
- * into `<packageDir>/dist/build-stamp.json`. `undefined` when absent (e.g.
51
- * running from source via tsx, or a hand-assembled package), which callers
52
- * treat as "no stamp available".
53
- */
54
- export function readBuildStamp(packageDir) {
55
- try {
56
- const raw = readFileSync(path.join(packageDir, "dist", "build-stamp.json"), "utf-8");
57
- const parsed = JSON.parse(raw);
58
- if (parsed.schemaVersion !== 1 ||
59
- typeof parsed.version !== "string" ||
60
- typeof parsed.builtAt !== "string")
61
- return undefined;
62
- return parsed;
63
- }
64
- catch {
65
- return undefined;
66
- }
67
- }
68
- /**
69
- * Human-readable CLI version label: plain version, enriched with the build
70
- * stamp (short git SHA + build date) when available so a stale dist/ that was
71
- * built from an old commit is immediately recognizable in `--version`.
72
- */
73
- export function readCliVersionLabel(packageDir) {
74
- const version = readPackageVersion(packageDir) ?? "0.0.0";
75
- const stamp = readBuildStamp(packageDir);
76
- if (!stamp?.gitSha)
77
- return version;
78
- return `${version} (build ${stamp.gitSha.slice(0, 8)} ${stamp.builtAt.slice(0, 10)})`;
79
- }
80
- /**
81
- * Strip the build-stamp suffix from a CLI `--version` label, returning the bare
82
- * SemVer. Controller-identity/preflight comparisons must use this rather than
83
- * the raw label so a build-stamped `0.35.0 (build 7f8c5b5b …)` still matches
84
- * `packageVersion === "0.35.0"`.
85
- */
86
- export function normalizeCliVersionLabel(label) {
87
- const match = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/.exec(label.trim());
88
- return match ? match[0] : label.trim();
89
- }
90
48
  /**
91
49
  * Compute the SHA-256 hash of a file on disk.
92
50
  *
@@ -46,10 +46,6 @@ export function projectRequirementMarkdown(draft) {
46
46
  lines.push(`- ${item}`);
47
47
  }
48
48
  }
49
- // References / Source Resolutions remain projected into 需求.md (durable
50
- // provenance for human readers); the managed read-back validator accepts
51
- // the projector's own canonical forms instead of rejecting them
52
- // (2026-08-16 L1: writer/reader round-trip invariant).
53
49
  if (draft.sourceResolutions && draft.sourceResolutions.length > 0) {
54
50
  lines.push("", "## Source Resolutions", "");
55
51
  for (const res of draft.sourceResolutions) {
@@ -2,13 +2,6 @@ const FRESH_SOURCE_MISSING_CODES = new Set([
2
2
  "MISSING_REQUIREMENT",
3
3
  "MISSING_CONSTRAINTS",
4
4
  ]);
5
- function hasKnowledgeSyncFeatureSurface(featureId, allowedPaths) {
6
- const featureRoot = `features/${featureId}/`;
7
- return allowedPaths.some((pathGlob) => {
8
- const normalized = pathGlob.replaceAll("\\", "/").replace(/^\.\//, "");
9
- return normalized === `features/${featureId}` || normalized.startsWith(featureRoot);
10
- });
11
- }
12
5
  export function isFreshLegacyUnversioned(state, sourceFilesPresent) {
13
6
  if (state.effectiveStatus !== "legacy-unversioned")
14
7
  return false;
@@ -68,15 +61,6 @@ export function listPrepareGaps(input) {
68
61
  level: "blocking",
69
62
  field: "objective",
70
63
  message: "requirement.objective is required",
71
- details: { headingAliases: ["目标", "objective", "业务目标", "需求概述"] },
72
- selfHealing: {
73
- action: "reimport-prd",
74
- steps: [
75
- "检查 PRD 是否含「## 目标」或「## Objective」章节;中文括号后缀(如「目标(概述)」)已被识别",
76
- "若确实缺失:补全 PRD 后重新 importPrd(同 taskId),advance 会自动重投影",
77
- "不要手改 source/需求.md(会触发 DIRTY_SOURCE);不要在 PRD 目录生成 sidecar draft JSON",
78
- ],
79
- },
80
64
  });
81
65
  }
82
66
  if (draft.requirement.acceptanceCriteria.length === 0) {
@@ -85,25 +69,6 @@ export function listPrepareGaps(input) {
85
69
  level: "blocking",
86
70
  field: "acceptanceCriteria",
87
71
  message: "at least one acceptance criterion is required",
88
- details: {
89
- recognizedHeadings: [
90
- "验收标准",
91
- "acceptance criteria",
92
- "完成标准",
93
- "完成定义",
94
- "验收",
95
- "dod",
96
- ],
97
- note: "标题含括号/破折号后缀会被自动归一;AC 需为列表项(- / 1.)或 AC-NNN 标题/行内格式",
98
- },
99
- selfHealing: {
100
- action: "reimport-prd",
101
- steps: [
102
- "检查 PRD 验收章节标题(如「完成标准(验收)」已可识别)与列表格式:需为「- 项目」或「AC-001: 文本」",
103
- "格式修正后重新 importPrd(同 taskId);advance 内置 semantic intake 兜底,文档语义完整时会自动结构化",
104
- "若 advance 已返回 SEMANTIC_INTAKE_FAILED:补全 PRD 后重试,不要手改 source/ 需求.md",
105
- ],
106
- },
107
72
  });
108
73
  }
109
74
  if (input.acceptanceConflicts && input.acceptanceConflicts.length > 0) {
@@ -140,16 +105,6 @@ export function listPrepareGaps(input) {
140
105
  message: "featureId is required when taskKind is knowledge-sync",
141
106
  });
142
107
  }
143
- if (draft.taskKind === "knowledge-sync" &&
144
- draft.featureId &&
145
- !hasKnowledgeSyncFeatureSurface(draft.featureId, draft.constraints.allowedPaths)) {
146
- gaps.push({
147
- code: "KNOWLEDGE_SYNC_PATH_MISMATCH",
148
- level: "blocking",
149
- field: "allowedPaths",
150
- message: `knowledge-sync for ${draft.featureId} requires an allowed path under features/${draft.featureId}/; ordinary docs-only work should use taskKind standard`,
151
- });
152
- }
153
108
  if (draft.requirement.scope.length === 0) {
154
109
  gaps.push({
155
110
  code: "EMPTY_SCOPE",
@@ -216,14 +171,6 @@ export function listPrepareGaps(input) {
216
171
  code: "DIRTY_SOURCE",
217
172
  level: "blocking",
218
173
  message: "existing non-empty or externally-modified source refuses --apply; use show/diff/adopt/recover or --force-overwrite-source",
219
- selfHealing: {
220
- action: "adopt-contract",
221
- steps: [
222
- "task status --json 读取 contract.observedCanonicalHash 与当前 revision",
223
- "若变更确属预期:task contract adopt --task <id> --expected-revision <n> --expected-observed-hash <hash> --request-id <id> --request-payload-sha256 <sha>",
224
- "若变更不是预期的:改 PRD 后重新 importPrd 走完整重投影;禁止手改 lifecycle.json / .transactions/ 绕过",
225
- ],
226
- },
227
174
  });
228
175
  risks.push({
229
176
  code: "DIRTY_SOURCE",
@@ -15,21 +15,7 @@ const HEADING_ALIASES = {
15
15
  "已确认需求",
16
16
  ]),
17
17
  nonGoals: new Set(["非目标", "out of scope", "non-goals", "non goals"]),
18
- acceptance: new Set([
19
- "验收标准",
20
- "acceptance criteria",
21
- "acceptance",
22
- // Common zh-CN product-writing variants seen in real PRDs; without
23
- // these a PRD re-import flips to deterministic parse and loses all AC
24
- // (EMPTY_ACCEPTANCE deadlock on the pendingPrdRefresh path).
25
- "完成定义",
26
- "完成标准",
27
- "验收",
28
- "验收条件",
29
- "验收准则",
30
- "dod",
31
- "definition of done",
32
- ]),
18
+ acceptance: new Set(["验收标准", "acceptance criteria", "acceptance"]),
33
19
  constraints: new Set(["约束", "constraints", "不变式", "invariants"]),
34
20
  openQuestions: new Set(["待决问题", "open questions", "open-questions"]),
35
21
  assumptions: new Set(["假设", "assumptions"]),
@@ -44,6 +30,15 @@ function stripFencedAndComments(text) {
44
30
  .replace(/~~~[\s\S]*?~~~/g, "\n")
45
31
  .replace(/<!--[\s\S]*?-->/g, "\n");
46
32
  }
33
+ function normalizeHeadingText(raw) {
34
+ return raw
35
+ .trim()
36
+ // Strip leading section numbers: "2. 业务目标" / "3.1 已确认范围" / "3.2、非目标"
37
+ .replace(/^(?:\d+(?:\.\d+)*[..、]?\s*)+/u, "")
38
+ .toLowerCase()
39
+ .replace(/[::]\s*$/u, "")
40
+ .replace(/\s+/g, " ");
41
+ }
47
42
  function normalizeAcceptanceId(raw) {
48
43
  return raw
49
44
  .trim()
@@ -60,67 +55,12 @@ function parseEmbeddedAcHeading(headingText) {
60
55
  const text = match[2]?.trim() || id;
61
56
  return { id, text };
62
57
  }
63
- function normalizeHeadingText(raw) {
64
- return raw
65
- .trim()
66
- // Strip leading section numbers: "2. 业务目标" / "3.1 已确认范围" / "3.2、非目标"
67
- .replace(/^(?:\d+(?:\.\d+)*[..、]?\s*)+/u, "")
68
- .toLowerCase()
69
- .replace(/[::]\s*$/u, "")
70
- .replace(/\s+/g, " ");
71
- }
72
- /**
73
- * Strip decorative suffixes that real PRD writers attach to section
74
- * headings: "完成标准(验收)" → "完成标准", "Acceptance Criteria (DoD):" →
75
- * "acceptance criteria", "验收标准 — 交付门槛" → "验收标准". Handles zh/en
76
- * parens, dashes, colons and trailing separators before the suffix.
77
- */
78
- function stripHeadingDecorations(normalized) {
79
- return normalized
80
- .replace(/[((][^(())]*[))]\s*$/u, "")
81
- .replace(/\s*[—–\-|]\s*[^—–\-|]+$/u, "")
82
- .replace(/[::]\s*$/u, "")
83
- .trim();
84
- }
85
- const HEADING_PREFIX_HINTS = [
86
- { key: "objective", hint: "目标" },
87
- { key: "objective", hint: "objective" },
88
- { key: "scope", hint: "范围" },
89
- { key: "scope", hint: "scope" },
90
- { key: "nonGoals", hint: "非目标" },
91
- { key: "nonGoals", hint: "out of scope" },
92
- { key: "acceptance", hint: "验收" },
93
- { key: "acceptance", hint: "acceptance" },
94
- { key: "acceptance", hint: "完成标准" },
95
- { key: "acceptance", hint: "完成定义" },
96
- { key: "acceptance", hint: "dod" },
97
- { key: "constraints", hint: "约束" },
98
- { key: "constraints", hint: "constraints" },
99
- { key: "openQuestions", hint: "待决问题" },
100
- { key: "openQuestions", hint: "open questions" },
101
- { key: "assumptions", hint: "假设" },
102
- { key: "assumptions", hint: "assumptions" },
103
- ];
104
58
  function classifyHeading(text) {
105
59
  const normalized = normalizeHeadingText(text);
106
60
  for (const [key, aliases] of Object.entries(HEADING_ALIASES)) {
107
61
  if (aliases.has(normalized))
108
62
  return key;
109
63
  }
110
- // Decoration-stripped exact match: "完成标准(验收)" → "完成标准".
111
- const stripped = stripHeadingDecorations(normalized);
112
- if (stripped && stripped !== normalized) {
113
- for (const [key, aliases] of Object.entries(HEADING_ALIASES)) {
114
- if (aliases.has(stripped))
115
- return key;
116
- }
117
- }
118
- // Prefix-contains fallback: "验收标准与测试" starts with "验收"; keep the
119
- // hint list narrow (whole-word/leading-substring) to avoid false hits.
120
- for (const { key, hint } of HEADING_PREFIX_HINTS) {
121
- if (stripped === hint || stripped.startsWith(hint))
122
- return key;
123
- }
124
64
  return "other";
125
65
  }
126
66
  function isAtxHeading(line) {
@@ -454,20 +394,10 @@ export function fillMissingRequirementFacts(base, supplemental) {
454
394
  export function parseVerifyFlag(raw) {
455
395
  const idx = raw.indexOf(":");
456
396
  if (idx <= 0 || idx === raw.length - 1) {
457
- // Actionable error with concrete examples (2026-08-16 L3'-style):
458
- // models were guessing flag names (--verify-label) and separator
459
- // shapes; the example makes the contract self-evident.
460
- const hint = !raw.includes(":")
461
- ? `no label separator found; write it as <label>:<command>, e.g. --verify "typecheck:npm run typecheck"`
462
- : `empty ${idx === 0 ? "label" : "command"}; write it as <label>:<command>, e.g. --verify "typecheck:npm run typecheck"`;
463
- throw new Error(`invalid --verify value "${raw}"; expected <label>:<command> — ${hint}`);
464
- }
465
- const label = raw.slice(0, idx).trim();
466
- if (!/^[a-z0-9][a-z0-9-]*$/i.test(label)) {
467
- throw new Error(`invalid --verify label "${label}"; use short kebab-case letters/digits/hyphens (e.g. typecheck, unit-tests, build) — value was "${raw}"`);
397
+ throw new Error(`invalid --verify value "${raw}"; expected <label>:<command>`);
468
398
  }
469
399
  return {
470
- label,
400
+ label: raw.slice(0, idx).trim(),
471
401
  command: raw.slice(idx + 1).trim(),
472
402
  };
473
403
  }