@tea-agent/loop-agent 0.40.0-next.1 → 0.40.0-next.11

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 (213) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +114 -109
  3. package/README.md +2 -2
  4. package/dist/application/dag/generate-task-dag.js +6 -2
  5. package/dist/application/task-lifecycle/advance.js +12 -0
  6. package/dist/build-stamp.json +3 -3
  7. package/dist/cli/update/runtime-activity.js +1 -29
  8. package/dist/commands/dag-rerun.js +1 -1
  9. package/dist/executors/dag-pi-executor.js +69 -7
  10. package/dist/executors/pi-executor.js +4 -2
  11. package/dist/executors/pi-sdk-executor.js +46 -1
  12. package/dist/executors/pi-writer-tool-policy.js +57 -1
  13. package/dist/executors/shell-executor.js +107 -20
  14. package/dist/executors/workspace-write-snapshot.js +68 -0
  15. package/dist/governance/checks.js +1 -0
  16. package/dist/infrastructure/harness/atomic-write.js +23 -0
  17. package/dist/shared/dag-prompt-override.js +4 -5
  18. package/dist/shared/update/npm-client.js +33 -11
  19. package/dist/task/config-types.js +10 -0
  20. package/dist/task/contract/apply.js +11 -1
  21. package/dist/task/contract/constants.js +2 -0
  22. package/dist/task/contract/hash.js +3 -0
  23. package/dist/task/contract/observe.js +25 -4
  24. package/dist/task/contract/paths.js +2 -1
  25. package/dist/task/contract/project.js +15 -1
  26. package/dist/task/contract/schema.js +2 -0
  27. package/dist/task/contract/transaction.js +12 -0
  28. package/dist/task/source-prepare/completeness.js +188 -0
  29. package/dist/task/source-prepare/fragment-inventory.js +474 -0
  30. package/dist/task/source-prepare/index.js +3 -0
  31. package/dist/task/source-prepare/ledger-reconciliation.js +127 -0
  32. package/dist/task/source-prepare/ledger-review.js +214 -0
  33. package/dist/task/source-prepare/ledger.js +545 -0
  34. package/dist/task/source-prepare/prepare.js +262 -1
  35. package/dist/task/source-prepare/semantic-intake.js +19 -3
  36. package/dist/task/source-prepare/source-fidelity-pi.js +384 -0
  37. package/dist/task/source-prepare/types.js +22 -0
  38. package/dist/worker/cli.js +12 -26
  39. package/dist/worker/console/chat/chat-event-store.js +75 -5
  40. package/dist/worker/console/chat/context-panel.js +7 -0
  41. package/dist/worker/console/chat/deferred-turn.js +12 -0
  42. package/dist/worker/console/chat/pi-runtime.js +331 -18
  43. package/dist/worker/console/chat/provider-error.js +98 -0
  44. package/dist/worker/console/chat/routes.js +389 -56
  45. package/dist/worker/console/chat/session-stats.js +179 -0
  46. package/dist/worker/console/chat/session-store.js +93 -63
  47. package/dist/worker/console/chat/todos.js +115 -0
  48. package/dist/worker/console/chat/tool-preview.js +42 -0
  49. package/dist/worker/console/chat/turn-process.js +20 -55
  50. package/dist/worker/console/chat/user-questions.js +266 -0
  51. package/dist/worker/console/chat/workspace-landing.js +79 -0
  52. package/dist/worker/console/console-handoff.js +82 -0
  53. package/dist/worker/console/console-update-and-init.js +115 -0
  54. package/dist/worker/console/console-update-runtime.js +84 -0
  55. package/dist/worker/console/dag-execution-receipt.js +20 -2
  56. package/dist/worker/console/draft-store.js +49 -0
  57. package/dist/worker/console/native-directory-picker.js +13 -0
  58. package/dist/worker/console/operation-store.js +1 -1
  59. package/dist/worker/console/operator-actions.js +133 -7
  60. package/dist/worker/console/operator-surface-health.js +1 -0
  61. package/dist/worker/console/prd-intake-bridge.js +13 -0
  62. package/dist/worker/console/routes.js +312 -1
  63. package/dist/worker/console/security.js +4 -4
  64. package/dist/worker/console/server.js +583 -172
  65. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-Br92EGb7.js → abnfDiagram-N423BO3Z-Bs-CDAXM.js} +1 -1
  66. package/dist/worker/console/static/assets/{arc-oulImtQq.js → arc-CAkA3We3.js} +1 -1
  67. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-tyHc6aqO.js → architectureDiagram-T3A2C74G-DEmI_zqr.js} +1 -1
  68. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-CY86BSpT.js → blockDiagram-VBNYF7ZC-uDHANebE.js} +1 -1
  69. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BKKsDmNs.js → c4Diagram-5PPSVZJV-Bv97b4_B.js} +1 -1
  70. package/dist/worker/console/static/assets/channel-amxUpk7o.js +1 -0
  71. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-CXZdjl3B.js → chunk-2GRJ4B5K-shmQKsFz.js} +1 -1
  72. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-B-aIFDQ5.js → chunk-2Q5K7J3B-BAraNvcN.js} +1 -1
  73. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BDgAW_B2.js → chunk-5RXB4S5H-BirhxUop.js} +1 -1
  74. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-DABa4UPR.js → chunk-5VM5RSS4-C9LgUJpR.js} +1 -1
  75. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-aGbysVOx.js → chunk-6Q2QTUOP-DrU-s-t7.js} +1 -1
  76. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-B8MSZDVs.js → chunk-GF5L2VYU-Tx-H_FA2.js} +1 -1
  77. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-CpelV73g.js → chunk-JWPE2WC7-BjLtNFrR.js} +1 -1
  78. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BE04ty3z.js → chunk-KBJHAD2P-UNLVwSsy.js} +1 -1
  79. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-BUxTkaaR.js → chunk-RYQCIY6F-CBEUX8XD.js} +1 -1
  80. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CYYBVKfX.js → chunk-XXDRQBXY-WTL7IZOq.js} +1 -1
  81. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-bejwBVIz.js +1 -0
  82. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-bejwBVIz.js +1 -0
  83. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CEQF_xmQ.js → cose-bilkent-JH36ORCC-CkHG6W3s.js} +1 -1
  84. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-CqpxN5IT.js → cynefin-VYW2F7L2-BRzFqTaL.js} +1 -1
  85. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-B3PzanVi.js → cynefinDiagram-MW4NZA55-2_CFp_i7.js} +1 -1
  86. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BSUGCNx1.js → dagre-VZM6K2ZE-BJtsmdkE.js} +1 -1
  87. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-CdLevU5T.js → diagram-7IWD3JNH-DNEFFo6w.js} +1 -1
  88. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-BjpF_Kok.js → diagram-B4RE2ZJO-B_IWV7eo.js} +1 -1
  89. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-C4I6NJny.js → diagram-LBJQPF4R-DvvRx2dz.js} +1 -1
  90. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-C8hecCr5.js → diagram-Q27KOJAE-CsibsWLg.js} +1 -1
  91. package/dist/worker/console/static/assets/{diagram-UB23O5K3-Daod6tOS.js → diagram-UB23O5K3-les_djBQ.js} +1 -1
  92. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BvvmazGv.js → ebnfDiagram-BXEA7PRR-BEm2n7qJ.js} +1 -1
  93. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DeN_vfV4.js → erDiagram-JOGREHBK-BI7vHHVm.js} +1 -1
  94. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-D6dq1t9z.js → flowDiagram-UKHOOZJN-CUFCERrB.js} +1 -1
  95. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DziIdNY4.js → ganttDiagram-PKOTCBZU-wxyLiGWt.js} +1 -1
  96. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Dy4s5CXr.js → gitGraphDiagram-DS77QQ5N-Bt897K8Z.js} +1 -1
  97. package/dist/worker/console/static/assets/index-BHhUOTri.css +1 -0
  98. package/dist/worker/console/static/assets/index-DqJbO3-p.js +407 -0
  99. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-Czv5eYx2.js → infoDiagram-6WML65LV-DYNx_IPv.js} +1 -1
  100. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-Bsk3nFRT.js → ishikawaDiagram-WSZJBQD7-CzpLNEu6.js} +1 -1
  101. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DxGmNj5K.js → journeyDiagram-NVQOT4AX-97f9owNU.js} +1 -1
  102. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-CYCFqkO_.js → kanban-definition-27J2QSJJ-BxM9hyBn.js} +1 -1
  103. package/dist/worker/console/static/assets/{linear-B0YzRwrd.js → linear-ByuxcHvp.js} +1 -1
  104. package/dist/worker/console/static/assets/{mermaid.core-t3EZtIGh.js → mermaid.core-DwPGvpCv.js} +5 -5
  105. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-BTXpTv0T.js → mindmap-definition-FAOFIHXS-DCoqG9RT.js} +1 -1
  106. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-DU8UkKqA.js → pegDiagram-VL7TDLO6-BLSBmBMx.js} +1 -1
  107. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-DP4y8ohp.js → pieDiagram-7S7Q4E2Y-B0t_0oJW.js} +1 -1
  108. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-B07vNaYR.js → quadrantDiagram-CIZ2JOQS-sTzDk7Nt.js} +1 -1
  109. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-xDWktb2i.js → railroadDiagram-AXF67PYL-B3jRdATC.js} +1 -1
  110. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-BLNMKqeS.js → requirementDiagram-LRYGKXZP-D-cTtXEN.js} +1 -1
  111. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-n0adalxH.js → sankeyDiagram-W5VNT64P-B25igJRE.js} +1 -1
  112. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-BbnS-2DL.js → sequenceDiagram-SI44F4Z6-jW_lM1_D.js} +1 -1
  113. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-B4uPpCLu.js → sizeCapture-X5ZJPWSS-CrzTgsHE.js} +1 -1
  114. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA--MMbB0fX.js → stateDiagram-OKZ733FA-B01MvlqE.js} +1 -1
  115. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BvFKEtm2.js +1 -0
  116. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-BXUgp2QY.js → swimlanes-SLNWSIFB-YcF12FiU.js} +2 -2
  117. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DIB2eVg-.js +8 -0
  118. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CsaMxki7.js → timeline-definition-Z64GVDOM-ClnRcg2s.js} +1 -1
  119. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-C2IuG9iH.js → vennDiagram-T6HMQDX7-B6gr_z-q.js} +1 -1
  120. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-CmEWOXCW.js → wardleyDiagram-T6FBY63Y-CvSgguGH.js} +1 -1
  121. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-D_9LE0MG.js → xychartDiagram-ELKLHX3M-23OtSZCb.js} +1 -1
  122. package/dist/worker/console/static/index.html +2 -2
  123. package/dist/worker/console/static-src/app/console-types.js +68 -4
  124. package/dist/worker/console/static-src/app/useConsoleShell.js +30 -12
  125. package/dist/worker/console/static-src/app/useOperatorActions.js +41 -6
  126. package/dist/worker/console/static-src/app/useRecoveryConsole.js +10 -11
  127. package/dist/worker/console/static-src/app/useRunProgress.js +2 -1
  128. package/dist/worker/console/static-src/app/useTaskWizard.js +74 -2
  129. package/dist/worker/console/static-src/night/useNightBoard.js +8 -5
  130. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +141 -8
  131. package/dist/worker/console/static-src/operator-chat/compaction-message.js +79 -0
  132. package/dist/worker/console/static-src/operator-chat/details-dag-actions.js +122 -0
  133. package/dist/worker/console/static-src/operator-chat/refs.js +3 -0
  134. package/dist/worker/console/static-src/operator-chat/runtime-selection-labels.js +27 -0
  135. package/dist/worker/console/static-src/operator-chat/spatial-overlay.js +1 -2
  136. package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +25 -0
  137. package/dist/worker/console/static-src/operator-chat/turn-submission.js +3 -2
  138. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +181 -87
  139. package/dist/worker/console/static-src/operator-chat/useChatStream.js +159 -44
  140. package/dist/worker/console/static-src/operator-chat/useChatThread.js +177 -8
  141. package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +63 -9
  142. package/dist/worker/console/static-src/operator-chat/useWorkspaceBrowserGate.js +4 -0
  143. package/dist/worker/console/static-src/operator-chat/workspace-layout-mode.js +3 -3
  144. package/dist/worker/console/static-src/shell/useWorkspaces.js +299 -0
  145. package/dist/worker/console/static-src/shell/workspace-route.js +339 -0
  146. package/dist/worker/console/workspace-context.js +234 -0
  147. package/dist/worker/console/workspace-registry.js +214 -0
  148. package/dist/worker/observability/init-runtime-activity.js +26 -0
  149. package/dist/worker/observe/node-input.js +88 -2
  150. package/dist/worker/observe/routes.js +188 -0
  151. package/dist/worker/observe/server.js +4 -0
  152. package/dist/worker/observe/static/api.js +29 -9
  153. package/dist/worker/observe/static/app.js +18 -70
  154. package/dist/worker/observe/static/dag-node-purpose.d.ts +6 -0
  155. package/dist/worker/observe/static/dag-node-purpose.js +203 -0
  156. package/dist/worker/observe/static/format.js +37 -0
  157. package/dist/worker/observe/static/index.html +6 -1
  158. package/dist/worker/observe/static/inspect-workspace.js +307 -0
  159. package/dist/worker/observe/static/operator-chrome.css +145 -20
  160. package/dist/worker/observe/static/operator-chrome.d.ts +20 -3
  161. package/dist/worker/observe/static/operator-chrome.js +330 -100
  162. package/dist/worker/observe/static/prompt-restart-candidates.d.ts +18 -0
  163. package/dist/worker/observe/static/prompt-restart-candidates.js +36 -0
  164. package/dist/worker/observe/static/router.d.ts +46 -0
  165. package/dist/worker/observe/static/router.js +25 -1
  166. package/dist/worker/observe/static/state.d.ts +50 -0
  167. package/dist/worker/observe/static/state.js +174 -2
  168. package/dist/worker/observe/static/styles.css +357 -35
  169. package/dist/worker/observe/static/views/dag-graph.js +4 -2
  170. package/dist/worker/observe/static/views/dag-inspector.js +533 -79
  171. package/dist/worker/observe/static/views/dag.d.ts +13 -0
  172. package/dist/worker/observe/static/views/dag.js +6 -4
  173. package/dist/worker/observe/static/views/dashboard.js +6 -4
  174. package/dist/worker/observe/static/views/night.js +2 -2
  175. package/dist/worker/observe/static/views/pool.js +1 -0
  176. package/dist/worker/observe/static/views/run.js +3 -1
  177. package/dist/worker/observe/static/views/task.js +56 -1
  178. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +186 -8
  179. package/dist/workflows/dag/backend-test-markdown-workflow.js +176 -1
  180. package/dist/workflows/dag/backend-test-pytest-collection.js +168 -16
  181. package/dist/workflows/dag/backend-test-result-contract.js +4 -0
  182. package/dist/workflows/dag/backend-test-scenario-param.js +339 -53
  183. package/dist/workflows/dag/backend-test-writer-completeness.js +28 -17
  184. package/dist/workflows/dag/dynamic-runtime/map.js +1 -0
  185. package/dist/workflows/dag/frontend-implementation-contract.js +88 -2
  186. package/dist/workflows/dag/frontend-plan-render.js +24 -0
  187. package/dist/workflows/dag/frontend-prewrite-gate.js +197 -0
  188. package/dist/workflows/dag/frontend-review-context.js +92 -10
  189. package/dist/workflows/dag/init-hybrid.js +239 -52
  190. package/dist/workflows/dag/interrupt-request.js +3 -3
  191. package/dist/workflows/dag/lifecycle.js +3 -3
  192. package/dist/workflows/dag/node-execution.js +45 -0
  193. package/dist/workflows/dag/types.js +62 -12
  194. package/docs/README.md +2 -0
  195. package/docs/architecture/evolution.md +45 -0
  196. package/docs/init-surface.manifest.json +1 -0
  197. package/docs/operations/local-development-environment.md +21 -0
  198. package/docs/templates/README.md +1 -1
  199. package/docs/templates/agent-dag.schema.json +18 -0
  200. package/docs/templates/backend-test-dag.json +267 -238
  201. package/docs/templates/frontend-implementation-contract.schema.json +681 -24
  202. package/harness.json +3 -3
  203. package/package.json +3 -1
  204. package/skills/loop-agent/references/hybrid-dag.md +7 -0
  205. package/dist/worker/console/static/assets/channel-TY36zt-i.js +0 -1
  206. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-Dk7QCChM.js +0 -1
  207. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-Dk7QCChM.js +0 -1
  208. package/dist/worker/console/static/assets/index-C3GgHg-g.css +0 -1
  209. package/dist/worker/console/static/assets/index-Ci8ksvBm.js +0 -406
  210. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BqOigMQ4.js +0 -1
  211. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Caxz9UA2.js +0 -8
  212. package/dist/worker/console/static-src/operator-chat/activity-rail-presentation.js +0 -73
  213. package/dist/worker/console/static-src/operator-chat/useActivityRailTransition.js +0 -59
@@ -0,0 +1,84 @@
1
+ import os from "node:os";
2
+ import { readPackageVersion } from "../../shared/package-metadata.js";
3
+ import { createNpmUpdateClient } from "../../shared/update/npm-client.js";
4
+ import { acquireUpdateLock, updateLockPath } from "../../shared/update/state.js";
5
+ import { readInitRuntimeActivity } from "../observability/init-runtime-activity.js";
6
+ import { performConsoleUpdateAndInit, } from "./console-update-and-init.js";
7
+ import { TERMINAL_OPERATION_STATES } from "./operation-store.js";
8
+ export function createConsoleUpdateExecutor(input) {
9
+ return async (channel) => {
10
+ const currentVersion = readPackageVersion(input.packageRoot);
11
+ if (!currentVersion) {
12
+ return {
13
+ state: "failed",
14
+ errorCode: "PACKAGE_IDENTITY_UNAVAILABLE",
15
+ errorMessage: "Console package version cannot be proven",
16
+ maintenance: {
17
+ package: { status: "failed", channel },
18
+ initialization: { status: "not-run", pendingPaths: [] },
19
+ handoff: { status: "not-needed" },
20
+ },
21
+ };
22
+ }
23
+ const npm = createNpmUpdateClient({
24
+ currentVersion,
25
+ packageRoot: input.packageRoot,
26
+ cwd: input.repoRoot,
27
+ });
28
+ return performConsoleUpdateAndInit({
29
+ currentVersion,
30
+ preflight: async () => {
31
+ const [activity, operations] = await Promise.all([
32
+ readInitRuntimeActivity(input.repoRoot),
33
+ input.operations.list(),
34
+ ]);
35
+ if (activity.workerProjectionError ||
36
+ activity.activeDagRunIds.length > 0 ||
37
+ activity.activeWorkerTasks > 0 ||
38
+ activity.activeWorkerBatches > 0) {
39
+ return {
40
+ ok: false,
41
+ code: "ACTIVE_RUNTIME",
42
+ message: "active DAG/Worker runtime exists or cannot be proven inactive",
43
+ };
44
+ }
45
+ if (input.activeChatTurnCount() > 0) {
46
+ return {
47
+ ok: false,
48
+ code: "CHAT_TURN_ACTIVE",
49
+ message: "an Operator Chat turn is active",
50
+ };
51
+ }
52
+ const liveOtherOperation = operations.some((operation) => operation.action !== "consoleUpdateAndInit" &&
53
+ !TERMINAL_OPERATION_STATES.has(operation.state));
54
+ return liveOtherOperation
55
+ ? {
56
+ ok: false,
57
+ code: "OPERATION_ACTIVE",
58
+ message: "another Console operation is active",
59
+ }
60
+ : { ok: true };
61
+ },
62
+ acquireLock: () => acquireUpdateLock(updateLockPath(os.homedir())),
63
+ resolveVersion: (selectedChannel) => npm.distTagVersionCheck(selectedChannel),
64
+ canAutoInstall: () => npm.canAutoInstall(),
65
+ installExact: (version, selectedChannel) => npm.installExact(version, selectedChannel),
66
+ verifyInstalled: (version) => npm.verifyInstalled(version),
67
+ applySafeInit: async () => {
68
+ const result = await input.client.runExternal("loop-agent", ["init", "update", "--apply-safe", "--repo-root", input.repoRoot], {
69
+ cwd: input.repoRoot,
70
+ artifactName: "console-update-safe-init",
71
+ timeoutMs: 120_000,
72
+ });
73
+ return result.ok
74
+ ? { ok: true, pendingPaths: [] }
75
+ : {
76
+ ok: false,
77
+ message: result.stderr || result.stdout || "safe initialization failed",
78
+ pendingPaths: [],
79
+ };
80
+ },
81
+ requestHandoff: async ({ targetVersion }) => input.requestHandoff(targetVersion),
82
+ }, channel);
83
+ };
84
+ }
@@ -176,8 +176,26 @@ export function deriveEligibilityFactsFromDagSpec(input) {
176
176
  }));
177
177
  const allWriteSetEntries = writers.flatMap((writer) => writer.writeSet);
178
178
  const broadWriteSetRisk = allWriteSetEntries.some(isBroadWriteSetEntry);
179
- const forbiddenOverlapRisk = tasks.some((task) => stringList(task.writeSet).some((entry) => [...stringList(task.forbiddenPaths), ...input.forbiddenPaths].some((forbidden) => pathMatchesPattern(entry, forbidden) ||
180
- pathMatchesPattern(forbidden, entry))));
179
+ const taskForbidden = input.forbiddenPaths.map(normalizePathEntry);
180
+ const forbiddenOverlapRisk = tasks.some((task) => stringList(task.writeSet).some((entry) => {
181
+ const normalizedEntry = normalizePathEntry(entry);
182
+ return stringList(task.forbiddenPaths).some((forbidden) => {
183
+ const normalizedForbidden = normalizePathEntry(forbidden);
184
+ const isTaskGlobal = taskForbidden.includes(normalizedForbidden);
185
+ if (isTaskGlobal) {
186
+ // Task-level forbidden paths are hard global boundaries. A broad
187
+ // writer that could include one is not autonomously eligible.
188
+ return (pathMatchesPattern(normalizedEntry, normalizedForbidden) ||
189
+ pathMatchesPattern(normalizedForbidden, normalizedEntry));
190
+ }
191
+ // Node-local forbidden paths may intentionally carve a narrower
192
+ // child (for example md/README.md) out of a broader writer
193
+ // writeSet. That exclusion is enforced by the runtime write guard.
194
+ // It is a conflict only when the writer entry itself is wholly
195
+ // inside the forbidden boundary.
196
+ return pathMatchesPattern(normalizedEntry, normalizedForbidden);
197
+ });
198
+ }));
181
199
  const hasStructuredVerification = tasks.some((task) => {
182
200
  if (task.executor !== "shell" || !task.shell)
183
201
  return false;
@@ -1,5 +1,51 @@
1
1
  import path from "node:path";
2
2
  import { readJsonIfExists, sha256Json, writeSecureJson, } from "./app-data.js";
3
+ /**
4
+ * 从任意上游载荷安全投影 ledger 摘要(未知形状丢弃,绝不抛错、绝不信任字段外的数据)。
5
+ * 供 DraftStore / prd-intake-bridge 把 prepare/advance 结果中的 ledger 摘要带入草稿。
6
+ */
7
+ export function summarizeLedgerPayload(value) {
8
+ if (!value || typeof value !== "object")
9
+ return undefined;
10
+ const record = value;
11
+ if (record.present !== true)
12
+ return undefined;
13
+ const num = (key) => {
14
+ const raw = record[key];
15
+ return typeof raw === "number" && Number.isFinite(raw) ? raw : 0;
16
+ };
17
+ const gateRaw = record.gateStatus;
18
+ const gateStatus = gateRaw === "pass" || gateRaw === "fail" || gateRaw === "unknown"
19
+ ? gateRaw
20
+ : "unknown";
21
+ const failureCode = typeof record.failureCode === "string" && record.failureCode
22
+ ? record.failureCode
23
+ : null;
24
+ const rawExclusions = Array.isArray(record.exclusions) ? record.exclusions : [];
25
+ const exclusions = [];
26
+ for (const item of rawExclusions) {
27
+ if (!item || typeof item !== "object")
28
+ continue;
29
+ const entry = item;
30
+ const fragmentId = typeof entry.fragmentId === "string" ? entry.fragmentId : "";
31
+ const reason = typeof entry.reason === "string" ? entry.reason : "";
32
+ if (!fragmentId)
33
+ continue;
34
+ exclusions.push({ fragmentId, reason });
35
+ }
36
+ return {
37
+ present: true,
38
+ fragmentCount: num("fragmentCount"),
39
+ canonicalRequirementCount: num("canonicalRequirementCount"),
40
+ contextOnlyCount: num("contextOnlyCount"),
41
+ duplicateCount: num("duplicateCount"),
42
+ unresolvedCount: num("unresolvedCount"),
43
+ conflictCount: num("conflictCount"),
44
+ gateStatus,
45
+ failureCode,
46
+ exclusions,
47
+ };
48
+ }
3
49
  function draftPath(appData, taskId) {
4
50
  const safe = taskId.replace(/[^a-zA-Z0-9._-]+/g, "_");
5
51
  return path.join(appData.drafts, `${safe}.json`);
@@ -86,6 +132,9 @@ export function toCanonicalDraftForCli(draft) {
86
132
  if (draft.interviewAssessmentRef) {
87
133
  canonical.interviewAssessmentRef = draft.interviewAssessmentRef;
88
134
  }
135
+ // AC-BLOCK-002:canonical draft JSON 绝不携带 ledgerSummary 字段(strict
136
+ // taskContractDraftSchema 拒绝未知键)。摘要仅留在 prd-intake-bridge 响应与
137
+ // console-types 的 LedgerSummaryView(UI 视图模型),不进入持久化 draft。
89
138
  return canonical;
90
139
  }
91
140
  export class DraftStore {
@@ -0,0 +1,13 @@
1
+ /**
2
+ * DSH's native directory-picker adapter.
3
+ *
4
+ * The published DSH host package uses the modern Win32 IFileOpenDialog in a
5
+ * dedicated child process (plus osascript/Zenity/KDialog on other platforms),
6
+ * so the Console does not pay PowerShell startup cost or lose the chooser
7
+ * behind the browser window.
8
+ */
9
+ import { pickNativeDirectory, } from "@deepseek-ai/dsh-host-directory-picker-native";
10
+ /** Open the host OS single-folder chooser. Cancellation is a null result. */
11
+ export async function pickNativeWorkspaceDirectory(signal, internals = {}) {
12
+ return pickNativeDirectory(signal, internals);
13
+ }
@@ -1,7 +1,7 @@
1
1
  import { randomBytes } from "node:crypto";
2
2
  import path from "node:path";
3
3
  import { listJsonFiles, readJsonIfExists, sha256Json, writeSecureJson, } from "./app-data.js";
4
- export const TERMINAL_OPERATION_STATES = new Set(["succeeded", "failed", "timed-out"]);
4
+ export const TERMINAL_OPERATION_STATES = new Set(["succeeded", "failed", "timed-out", "restarting"]);
5
5
  function operationFile(appData, operationId) {
6
6
  return path.join(appData.operations, `${operationId}.json`);
7
7
  }
@@ -536,6 +536,106 @@ async function acceptOperation(ctx, input) {
536
536
  },
537
537
  };
538
538
  }
539
+ async function acceptConsoleUpdateAndInit(ctx, clientRequestId, channel) {
540
+ if (!ctx.consoleUpdateExecutor) {
541
+ return {
542
+ kind: "error",
543
+ status: 503,
544
+ body: operatorFailed({
545
+ command: "consoleUpdateAndInit",
546
+ outcome: "blocked",
547
+ code: "CONSOLE_UPDATE_UNAVAILABLE",
548
+ message: "Console update runtime is unavailable",
549
+ }),
550
+ };
551
+ }
552
+ const created = await ctx.operations.create({
553
+ clientRequestId,
554
+ action: "consoleUpdateAndInit",
555
+ actionParams: { channel },
556
+ });
557
+ if (created.kind === "conflict") {
558
+ return {
559
+ kind: "error",
560
+ status: 409,
561
+ body: operatorFailed({
562
+ command: "consoleUpdateAndInit",
563
+ outcome: "conflict",
564
+ code: "REQUEST_ID_REUSE_CONFLICT",
565
+ message: created.message,
566
+ }),
567
+ };
568
+ }
569
+ if (created.kind === "idempotent") {
570
+ return {
571
+ kind: "accepted",
572
+ status: 202,
573
+ body: {
574
+ operationId: created.operation.operationId,
575
+ state: created.operation.state,
576
+ clientRequestId: created.operation.clientRequestId,
577
+ action: created.operation.action,
578
+ },
579
+ };
580
+ }
581
+ queueMicrotask(() => {
582
+ void (async () => {
583
+ const operationId = created.operation.operationId;
584
+ await ctx.operations.update(operationId, {
585
+ state: "running",
586
+ startedAt: new Date().toISOString(),
587
+ });
588
+ ctx.events.append(operationId, {
589
+ at: new Date().toISOString(),
590
+ kind: "state",
591
+ state: "running",
592
+ message: `checking runtime, npm ${channel}, and safe initialization`,
593
+ });
594
+ try {
595
+ const result = await ctx.consoleUpdateExecutor(channel);
596
+ const state = result.state;
597
+ const next = await ctx.operations.update(operationId, {
598
+ state,
599
+ finishedAt: new Date().toISOString(),
600
+ result: result,
601
+ ...(result.errorCode ? { errorCode: result.errorCode } : {}),
602
+ ...(result.errorMessage ? { errorMessage: result.errorMessage } : {}),
603
+ });
604
+ ctx.events.append(operationId, {
605
+ at: new Date().toISOString(),
606
+ kind: "state",
607
+ state: next.state,
608
+ message: result.errorMessage ?? `console maintenance ${next.state}`,
609
+ });
610
+ }
611
+ catch (error) {
612
+ const message = error instanceof Error ? error.message : String(error);
613
+ const next = await ctx.operations.update(operationId, {
614
+ state: "needs-reconcile",
615
+ finishedAt: new Date().toISOString(),
616
+ errorCode: "CONSOLE_UPDATE_EXCEPTION",
617
+ errorMessage: message,
618
+ });
619
+ ctx.events.append(operationId, {
620
+ at: new Date().toISOString(),
621
+ kind: "error",
622
+ state: next.state,
623
+ message,
624
+ });
625
+ }
626
+ })();
627
+ });
628
+ return {
629
+ kind: "accepted",
630
+ status: 202,
631
+ body: {
632
+ operationId: created.operation.operationId,
633
+ state: created.operation.state,
634
+ clientRequestId: created.operation.clientRequestId,
635
+ action: created.operation.action,
636
+ },
637
+ };
638
+ }
539
639
  export async function dispatchOperatorAction(ctx, req) {
540
640
  const action = req.action?.trim();
541
641
  if (!action) {
@@ -566,6 +666,31 @@ export async function dispatchOperatorAction(ctx, req) {
566
666
  };
567
667
  }
568
668
  const p = paramsOf(req);
669
+ if (action === "consoleUpdateAndInit") {
670
+ if (req.source !== "human-ui") {
671
+ return {
672
+ kind: "error",
673
+ status: 403,
674
+ body: operatorFailed({
675
+ command: action,
676
+ outcome: "blocked",
677
+ code: "HUMAN_UI_REQUIRED",
678
+ message: "consoleUpdateAndInit is available only from the Operate UI",
679
+ }),
680
+ };
681
+ }
682
+ if (!req.clientRequestId?.trim()) {
683
+ return invalid(action, "clientRequestId is required");
684
+ }
685
+ if (Object.keys(p).some((key) => key !== "channel")) {
686
+ return invalid(action, "only channel may be provided");
687
+ }
688
+ const channel = p.channel ?? "latest";
689
+ if (channel !== "latest" && channel !== "next") {
690
+ return invalid(action, "channel must be latest or next");
691
+ }
692
+ return acceptConsoleUpdateAndInit(ctx, req.clientRequestId, channel);
693
+ }
569
694
  switch (action) {
570
695
  case "operatorCapabilities": {
571
696
  const doc = buildOperatorCapabilitiesDocument();
@@ -1516,9 +1641,10 @@ export async function dispatchOperatorAction(ctx, req) {
1516
1641
  broadWriteSetRisk: typeof reviewPacket.broadWriteSetRisk === "boolean"
1517
1642
  ? reviewPacket.broadWriteSetRisk
1518
1643
  : derivedFacts.broadWriteSetRisk,
1519
- forbiddenOverlapRisk: typeof reviewPacket.forbiddenOverlapRisk === "boolean"
1520
- ? reviewPacket.forbiddenOverlapRisk
1521
- : derivedFacts.forbiddenOverlapRisk,
1644
+ // Always use the staged DAG + live task boundary derivation here.
1645
+ // The generation review packet lacks task-boundary scope and can
1646
+ // mistake a narrower node-local exclusion for a global overlap.
1647
+ forbiddenOverlapRisk: derivedFacts.forbiddenOverlapRisk,
1522
1648
  hasStructuredVerification: packetShellVerification,
1523
1649
  };
1524
1650
  const assessment = assessAutonomousExecutionEligibility(eligibility);
@@ -2159,8 +2285,8 @@ export async function dispatchOperatorAction(ctx, req) {
2159
2285
  return accepted;
2160
2286
  }
2161
2287
  case "dagPromptOverrideConfig": {
2162
- // Experimental internal switch; the browser UI hides the prompt-edit
2163
- // entry unless this reports enabled=true.
2288
+ // The prompt-edit entry is visible by default. The internal environment
2289
+ // switch remains an emergency kill switch and is reflected here.
2164
2290
  return {
2165
2291
  kind: "sync",
2166
2292
  status: 200,
@@ -2182,7 +2308,7 @@ export async function dispatchOperatorAction(ctx, req) {
2182
2308
  }
2183
2309
  if (parsedOverrides.overrides.length > 0 &&
2184
2310
  !isDagRerunPromptOverrideEnabled()) {
2185
- return invalid(action, `prompt override rerun is disabled; set ${DAG_RERUN_PROMPT_OVERRIDE_ENV}=1 to enable this experimental capability`);
2311
+ return invalid(action, `prompt override rerun is disabled by ${DAG_RERUN_PROMPT_OVERRIDE_ENV}; unset it or use a value other than 0, false, or off to enable this experimental capability`);
2186
2312
  }
2187
2313
  const overrideArgs = parsedOverrides.overrides.length > 0
2188
2314
  ? await buildPromptOverrideCliArgs(ctx, parsedOverrides.overrides)
@@ -2215,7 +2341,7 @@ export async function dispatchOperatorAction(ctx, req) {
2215
2341
  }
2216
2342
  if (parsedOverrides.overrides.length > 0 &&
2217
2343
  !isDagRerunPromptOverrideEnabled()) {
2218
- return invalid(action, `prompt override rerun is disabled; set ${DAG_RERUN_PROMPT_OVERRIDE_ENV}=1 to enable this experimental capability`);
2344
+ return invalid(action, `prompt override rerun is disabled by ${DAG_RERUN_PROMPT_OVERRIDE_ENV}; unset it or use a value other than 0, false, or off to enable this experimental capability`);
2219
2345
  }
2220
2346
  const overrideArgs = parsedOverrides.overrides.length > 0
2221
2347
  ? await buildPromptOverrideCliArgs(ctx, parsedOverrides.overrides)
@@ -12,6 +12,7 @@ export function buildOperatorSurfaceHealthV1(input) {
12
12
  repoName: input.repoRoot.split(/[\\/]/).filter(Boolean).pop() ?? "repository",
13
13
  packageName,
14
14
  packageVersion,
15
+ consoleInstanceId: input.consoleInstanceId,
15
16
  piReadiness: input.piReadiness,
16
17
  inspect: {
17
18
  ready: input.inspectReady,
@@ -9,6 +9,7 @@ import { getTaskPaths } from "../../task/runtime.js";
9
9
  import { SEMANTIC_INTAKE_ARTIFACT_REL, } from "../../task/source-prepare/semantic-intake.js";
10
10
  import { extractRequirementFactsFromMarkdown } from "../../task/source-prepare/parse-intent.js";
11
11
  import { filterPlaceholderPaths, isNonPlaceholderPath, } from "../../task/source-prepare/placeholder-paths.js";
12
+ import { summarizeLedgerPayload, } from "./draft-store.js";
12
13
  import { emptyDraft } from "./interview/grill-me.js";
13
14
  import { normalizeConsoleWorkflowKind } from "./workflow-kinds.js";
14
15
  function asStringList(value) {
@@ -219,6 +220,15 @@ export async function buildDraftFromTaskIntake(input) {
219
220
  const paths = getTaskPaths(input.repoRoot, input.taskId);
220
221
  const warnings = warningList(input.advanceJson);
221
222
  const lifecycleState = lifecycleFromAdvanceJson(input.advanceJson);
223
+ // Source fidelity ledger 安全摘要透传(AC-009):来自 advance/prepare 结果,
224
+ // 未知形状安全丢弃,绝不携带未截断原文。
225
+ const advanceRoot = input.advanceJson && typeof input.advanceJson === "object"
226
+ ? input.advanceJson
227
+ : {};
228
+ const ledgerSummary = summarizeLedgerPayload(advanceRoot.ledgerSummary) ??
229
+ summarizeLedgerPayload(advanceRoot.result && typeof advanceRoot.result === "object"
230
+ ? advanceRoot.result.ledgerSummary
231
+ : undefined);
222
232
  const semanticApplied = warnings.some((w) => w.code === "SEMANTIC_INTAKE_APPLIED");
223
233
  const semanticFailed = warnings.find((w) => w.code === "SEMANTIC_INTAKE_PI_FAILED" ||
224
234
  w.code === "SEMANTIC_INTAKE_INVALID_OUTPUT" ||
@@ -427,11 +437,14 @@ export async function buildDraftFromTaskIntake(input) {
427
437
  if (input.engineering) {
428
438
  draft = applyEngineeringBoundaryToDraft(draft, input.engineering);
429
439
  }
440
+ // AC-BLOCK-002:摘要仅经响应返回 UI 视图模型,不写入 draft(防止 strict
441
+ // taskContractDraftSchema 因未知 ledgerSummary 键拒绝 canonical draft)。
430
442
  return {
431
443
  draft,
432
444
  parseStatus,
433
445
  semanticIntake,
434
446
  gaps,
447
+ ...(ledgerSummary ? { ledgerSummary } : {}),
435
448
  lifecycleState,
436
449
  };
437
450
  }