@tea-agent/loop-agent 0.41.0 → 0.41.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 (200) hide show
  1. package/CHANGELOG.md +267 -33
  2. package/dist/application/dag/generate-task-dag.js +75 -19
  3. package/dist/application/task-lifecycle/advance.js +24 -5
  4. package/dist/application/task-lifecycle/observe.js +171 -17
  5. package/dist/application/task-lifecycle/plan-transitions.js +42 -7
  6. package/dist/application/task-lifecycle/recommendations.js +13 -2
  7. package/dist/build-stamp.json +3 -3
  8. package/dist/cli/command-definitions.js +7 -0
  9. package/dist/cli/program.js +5 -0
  10. package/dist/commands/client-recovery.js +3 -0
  11. package/dist/commands/dag-follow-up.js +138 -0
  12. package/dist/commands/init.js +27 -1
  13. package/dist/commands/task-advance.js +19 -0
  14. package/dist/executors/dag-pi-executor.js +3784 -231
  15. package/dist/executors/pi-executor.js +15 -4
  16. package/dist/executors/pi-read-budget-policy.js +239 -0
  17. package/dist/executors/shell-executor.js +945 -217
  18. package/dist/executors/shell-write-guard.js +7 -0
  19. package/dist/shared/dag-failure-category.js +12 -0
  20. package/dist/shared/openspec-spec.js +70 -4
  21. package/dist/shared/operator/capabilities.js +7 -0
  22. package/dist/task/config-types.js +34 -7
  23. package/dist/task/contract/adopt.js +4 -0
  24. package/dist/task/contract/import-revision.js +4 -0
  25. package/dist/task/contract/project.js +3 -0
  26. package/dist/task/contract/schema.js +2 -1
  27. package/dist/task/frontend-project-capability.js +203 -20
  28. package/dist/task/runtime.js +5 -2
  29. package/dist/task/source-prepare/build-draft.js +3 -3
  30. package/dist/task/source-prepare/fragment-inventory.js +15 -9
  31. package/dist/task/source-prepare/prepare.js +89 -1
  32. package/dist/task/source-prepare/semantic-intake.js +6 -2
  33. package/dist/task/source-references.js +22 -1
  34. package/dist/worker/console/chat/pi-runtime.js +2 -3
  35. package/dist/worker/console/chat/routes.js +3 -12
  36. package/dist/worker/console/chat/semantic-activity.js +11 -12
  37. package/dist/worker/console/chat/session-stats.js +0 -96
  38. package/dist/worker/console/chat/turn-process.js +4 -28
  39. package/dist/worker/console/frontend-human-decision-adapter.js +19 -0
  40. package/dist/worker/console/frontend-split-operation-adapter.js +20 -0
  41. package/dist/worker/console/index.js +3 -0
  42. package/dist/worker/console/operation-store.js +226 -6
  43. package/dist/worker/console/operator-actions.js +169 -7
  44. package/dist/worker/console/pi-plugins.js +1 -3
  45. package/dist/worker/console/server.js +3 -0
  46. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-DwVJxUxz.js → abnfDiagram-N423BO3Z-Bho4we4c.js} +1 -1
  47. package/dist/worker/console/static/assets/{arc-DqfCcXdu.js → arc-TBDkTeK0.js} +1 -1
  48. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-qMVtggRv.js → architectureDiagram-T3A2C74G-BF_fZrn2.js} +1 -1
  49. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-ECrV38dh.js → blockDiagram-VBNYF7ZC-CCnPgUe2.js} +1 -1
  50. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-DBaaLqQv.js → c4Diagram-5PPSVZJV-BCYZJLAT.js} +1 -1
  51. package/dist/worker/console/static/assets/channel-bnXW0U3C.js +1 -0
  52. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-BvfNHkAz.js → chunk-2GRJ4B5K-D8K6adhU.js} +1 -1
  53. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-C5StiIbc.js → chunk-2Q5K7J3B-DkT1Q78b.js} +1 -1
  54. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-HabGiJkS.js → chunk-5RXB4S5H-DuhvpIr7.js} +1 -1
  55. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-BiTg127i.js → chunk-5VM5RSS4-BnK6dC49.js} +1 -1
  56. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-CZsXBPuR.js → chunk-6Q2QTUOP-DPz__z7r.js} +1 -1
  57. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-D-r1MxLK.js → chunk-GF5L2VYU-0kkppM2j.js} +1 -1
  58. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-DQxb9plr.js → chunk-JWPE2WC7-BB41iK5t.js} +1 -1
  59. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-DMndGvCT.js → chunk-KBJHAD2P-CiVrxKHU.js} +1 -1
  60. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-ByL4BgOJ.js → chunk-RYQCIY6F-C2h9Xje1.js} +1 -1
  61. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-BVe1b1gL.js → chunk-XXDRQBXY-3iOSHdbM.js} +1 -1
  62. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-rZpq_twR.js +1 -0
  63. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-rZpq_twR.js +1 -0
  64. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-BAyGzN8j.js → cose-bilkent-JH36ORCC-BN3A7tkk.js} +1 -1
  65. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-C5yVYU7E.js → cynefin-VYW2F7L2-CTuBy0Or.js} +1 -1
  66. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-x-MwsEm9.js → cynefinDiagram-MW4NZA55-wb6tUlMN.js} +1 -1
  67. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-CT5Tle5F.js → dagre-VZM6K2ZE-GP1Ivx8B.js} +1 -1
  68. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-BARERhlS.js → diagram-7IWD3JNH-ejrcK6L0.js} +1 -1
  69. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-BwfUz0VM.js → diagram-B4RE2ZJO-YFkCCvUU.js} +1 -1
  70. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-Mk4r2WvJ.js → diagram-LBJQPF4R-B4rrvIaL.js} +1 -1
  71. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-KUrxuBs0.js → diagram-Q27KOJAE-C-YIZcUf.js} +1 -1
  72. package/dist/worker/console/static/assets/{diagram-UB23O5K3-CjZOceZn.js → diagram-UB23O5K3-BPF5wcL1.js} +1 -1
  73. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-rnwUCiEI.js → ebnfDiagram-BXEA7PRR-CU5SzXjO.js} +1 -1
  74. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DM4j23FM.js → erDiagram-JOGREHBK-CpL414DE.js} +1 -1
  75. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-DD5HdDEs.js → flowDiagram-UKHOOZJN-MrhLzNau.js} +1 -1
  76. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-CIAGSF47.js → ganttDiagram-PKOTCBZU-Bg4qFuUo.js} +1 -1
  77. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-DbwFbVEL.js → gitGraphDiagram-DS77QQ5N-ColxSXLR.js} +1 -1
  78. package/dist/worker/console/static/assets/index-D3CC4eUz.css +1 -0
  79. package/dist/worker/console/static/assets/index-DLt4ZFvD.js +437 -0
  80. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-B-Pb0T66.js → infoDiagram-6WML65LV-Czvtm6gc.js} +1 -1
  81. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-B9Unk-YX.js → ishikawaDiagram-WSZJBQD7-B7Xp8HyJ.js} +1 -1
  82. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-C2F3JkPt.js → journeyDiagram-NVQOT4AX-DWYZcvph.js} +1 -1
  83. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-Bl8-Xcoz.js → kanban-definition-27J2QSJJ-KTLZRUjx.js} +1 -1
  84. package/dist/worker/console/static/assets/{linear-yK4uZmC5.js → linear-_Exn7bfl.js} +1 -1
  85. package/dist/worker/console/static/assets/{mermaid.core-Bpa6PmuE.js → mermaid.core-Cxg8kX8V.js} +5 -5
  86. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-BfGRoCSe.js → mindmap-definition-FAOFIHXS-oKrlo2Bt.js} +1 -1
  87. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-Bz6_HtST.js → pegDiagram-VL7TDLO6-XAeteiNd.js} +1 -1
  88. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-i0Umbsby.js → pieDiagram-7S7Q4E2Y-BTf1K-lp.js} +1 -1
  89. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-DaVQBobe.js → quadrantDiagram-CIZ2JOQS-C0IlY0Jf.js} +1 -1
  90. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-DMTGnSq7.js → railroadDiagram-AXF67PYL-BVbKtZhW.js} +1 -1
  91. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-2ao_DaSq.js → requirementDiagram-LRYGKXZP-C5e4JFcr.js} +1 -1
  92. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-2SG1lTB9.js → sankeyDiagram-W5VNT64P-Cz30hc29.js} +1 -1
  93. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-BQYOLybR.js → sequenceDiagram-SI44F4Z6-DS33n6d0.js} +1 -1
  94. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-C8g3yjuI.js → sizeCapture-X5ZJPWSS-46w7v-9T.js} +1 -1
  95. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-q_F8nAQG.js → stateDiagram-OKZ733FA-pbcD5SsZ.js} +1 -1
  96. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-zBMYiUyi.js +1 -0
  97. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-8LrWpH2s.js → swimlanes-SLNWSIFB-DuivYBSj.js} +2 -2
  98. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-d_rms-5i.js +8 -0
  99. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-BQoY3qzl.js → timeline-definition-Z64GVDOM-Cb9VZVIl.js} +1 -1
  100. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-BDu1UjSp.js → vennDiagram-T6HMQDX7-D2-mfOgR.js} +1 -1
  101. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-C48M7Y0a.js → wardleyDiagram-T6FBY63Y-DeS2aC76.js} +1 -1
  102. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-YU6FTl_F.js → xychartDiagram-ELKLHX3M-WGsrFjxH.js} +1 -1
  103. package/dist/worker/console/static/index.html +2 -2
  104. package/dist/worker/console/static-src/active-run-badge.js +17 -0
  105. package/dist/worker/console/static-src/app/useRunProgress.js +2 -9
  106. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +0 -2
  107. package/dist/worker/console/static-src/operator-chat/useChatThread.js +0 -6
  108. package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +3 -28
  109. package/dist/worker/console/static-src/pages/tasks/run-panel-progress.js +0 -106
  110. package/dist/worker/console/workspace-context.js +111 -1
  111. package/dist/worker/materialize/frontend-split-task-materializer.js +72 -0
  112. package/dist/worker/observability/read-model.js +0 -4
  113. package/dist/worker/observe/static/dag-node-purpose.js +5 -0
  114. package/dist/worker/observe/static/views/dag-inspector.js +7 -2
  115. package/dist/worker/observe/static/views/session-timeline.js +15 -46
  116. package/dist/workflows/dag/backend-test-result-contract.js +1 -1
  117. package/dist/workflows/dag/contract-validator-registrations.js +1 -2
  118. package/dist/workflows/dag/dag-retry-schema.js +138 -0
  119. package/dist/workflows/dag/frontend-closeout.js +221 -0
  120. package/dist/workflows/dag/frontend-design-policy.js +400 -0
  121. package/dist/workflows/dag/frontend-human-decision.js +182 -0
  122. package/dist/workflows/dag/frontend-implementation-contract.js +932 -162
  123. package/dist/workflows/dag/frontend-plan-render.js +2 -1
  124. package/dist/workflows/dag/frontend-prewrite-gate.js +255 -349
  125. package/dist/workflows/dag/frontend-provider-capability-matrix.js +159 -0
  126. package/dist/workflows/dag/frontend-read-budgets.js +12 -0
  127. package/dist/workflows/dag/frontend-recovery-capsule.js +455 -0
  128. package/dist/workflows/dag/frontend-recovery-controller.js +202 -0
  129. package/dist/workflows/dag/frontend-recovery-lineage.js +178 -0
  130. package/dist/workflows/dag/frontend-recovery-plan.js +17 -10
  131. package/dist/workflows/dag/frontend-recovery-run.js +33 -20
  132. package/dist/workflows/dag/frontend-repair.js +1 -432
  133. package/dist/workflows/dag/frontend-review-context.js +261 -15
  134. package/dist/workflows/dag/frontend-review-findings.js +270 -0
  135. package/dist/workflows/dag/frontend-shadow-dual-write.js +914 -0
  136. package/dist/workflows/dag/frontend-shape-capsule-store.js +191 -0
  137. package/dist/workflows/dag/frontend-shape-facts.js +409 -0
  138. package/dist/workflows/dag/frontend-shape.js +427 -0
  139. package/dist/workflows/dag/frontend-source-fidelity-ledger.js +108 -0
  140. package/dist/workflows/dag/frontend-split-application-service.js +203 -0
  141. package/dist/workflows/dag/frontend-split-orchestrator.js +899 -0
  142. package/dist/workflows/dag/frontend-typed-event-store.js +452 -0
  143. package/dist/workflows/dag/frontend-typed-event-transaction.js +180 -0
  144. package/dist/workflows/dag/frontend-verification-trace.js +249 -24
  145. package/dist/workflows/dag/frontend-worktree-diff.js +250 -17
  146. package/dist/workflows/dag/frontend-writer-admission.js +285 -0
  147. package/dist/workflows/dag/frontend-writer-status.js +256 -0
  148. package/dist/workflows/dag/init-hybrid.js +685 -494
  149. package/dist/workflows/dag/interrupt-request.js +7 -0
  150. package/dist/workflows/dag/node-execution.js +732 -4
  151. package/dist/workflows/dag/prompt.js +34 -1
  152. package/dist/workflows/dag/recovery-lease.js +80 -0
  153. package/dist/workflows/dag/report.js +37 -1
  154. package/dist/workflows/dag/rerun-feedback.js +256 -1
  155. package/dist/workflows/dag/rerun-plan.js +10 -2
  156. package/dist/workflows/dag/rerun-run.js +23 -0
  157. package/dist/workflows/dag/rerun-task.js +29 -0
  158. package/dist/workflows/dag/retry-policy.js +214 -104
  159. package/dist/workflows/dag/runner.js +429 -122
  160. package/dist/workflows/dag/scheduler.js +114 -16
  161. package/dist/workflows/dag/types.js +239 -12
  162. package/dist/workflows/dag/validate.js +28 -12
  163. package/docs/init-surface.manifest.json +30 -12
  164. package/docs/skills/vetted-skill-registry.md +4 -2
  165. package/docs/templates/README.md +2 -0
  166. package/docs/templates/agent-dag-report.schema.json +8 -2
  167. package/docs/templates/agent-dag.schema.json +1 -1
  168. package/docs/templates/frontend-implementation-contract.schema.json +4 -1
  169. package/docs/templates/frontend-implementation-dag.json +89 -0
  170. package/docs/templates/spec-registry.schema.json +45 -0
  171. package/harness.json +3 -3
  172. package/package.json +1 -1
  173. package/skills/frontend-bounded-implement/SKILL.md +15 -14
  174. package/skills/frontend-bounded-implement/references/code-standards.md +19 -0
  175. package/skills/frontend-contract/SKILL.md +23 -0
  176. package/skills/frontend-contract/references/contract-protocol.md +34 -0
  177. package/skills/frontend-design-review/SKILL.md +22 -41
  178. package/skills/frontend-plan/SKILL.md +26 -0
  179. package/skills/frontend-plan/references/decision-contract.md +37 -0
  180. package/skills/frontend-plan/references/design-decisions.md +17 -0
  181. package/skills/frontend-review/SKILL.md +20 -15
  182. package/skills/frontend-review/references/review-findings.md +6 -7
  183. package/skills/frontend-scout/SKILL.md +25 -0
  184. package/skills/frontend-scout/references/design-evidence.md +16 -0
  185. package/skills/frontend-scout/references/scout-evidence.md +23 -0
  186. package/skills/frontend-verification/SKILL.md +1 -1
  187. package/skills/loop-agent/references/command-reference.md +1 -0
  188. package/skills/loop-agent/references/hybrid-dag.md +2 -2
  189. package/dist/worker/console/static/assets/channel-CL1NRAmS.js +0 -1
  190. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-PBGzzjZA.js +0 -1
  191. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-PBGzzjZA.js +0 -1
  192. package/dist/worker/console/static/assets/index-BfleX-qj.css +0 -1
  193. package/dist/worker/console/static/assets/index-Bih9w9h9.js +0 -451
  194. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DrxGBDJu.js +0 -1
  195. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BhpDxzAf.js +0 -8
  196. package/dist/worker/console/static-src/operator-chat/dag-progress-link.js +0 -22
  197. package/skills/frontend-implementation/SKILL.md +0 -52
  198. package/skills/frontend-implementation/references/code-standards.md +0 -33
  199. package/skills/frontend-implementation/references/design-spec.md +0 -56
  200. package/skills/frontend-implementation/references/node-contracts.md +0 -31
@@ -1,5 +1,9 @@
1
1
  import { randomBytes } from "node:crypto";
2
2
  import path from "node:path";
3
+ import { assertFrontendSplitProjectionSuccessor, frontendSplitProjectionSchema, } from "../../workflows/dag/frontend-split-application-service.js";
4
+ import { buildFrontendHumanDecisionProjection, consumeFrontendHumanDecision, materializeFrontendHumanDecision, parseFrontendHumanDecisionProjection, parseFrontendHumanDecisionReceipt, } from "../../workflows/dag/frontend-human-decision.js";
5
+ import { buildFrontendSplitAggregateCloseout, computeFrontendSplitDigest, finalizeFrontendSplitAggregate, frontendCommittedFactRefSchema, frontendSplitChildCloseoutFactsSchema, initializeFrontendSplitParent, } from "../../workflows/dag/frontend-split-orchestrator.js";
6
+ import { frontendCloseoutFactsSchema, frontendTestHandoffSchema, } from "../../workflows/dag/frontend-closeout.js";
3
7
  import { listJsonFiles, readJsonIfExists, sha256Json, writeSecureJson, } from "./app-data.js";
4
8
  export const TERMINAL_OPERATION_STATES = new Set(["succeeded", "failed", "timed-out", "restarting"]);
5
9
  function operationFile(appData, operationId) {
@@ -15,16 +19,21 @@ export function computeActionPayloadHash(action, actionParams) {
15
19
  export function newOperationId() {
16
20
  return `op_${randomBytes(12).toString("hex")}`;
17
21
  }
22
+ const sharedWriteChains = new Map();
18
23
  export class OperationStore {
19
24
  appData;
20
- /**
21
- * Per-key write lock. Concurrent update/save/create on the same operation
22
- * or clientRequestId must not race rename() into the same JSON path
23
- * (Windows EPERM) or last-write-wins lost patches.
24
- */
25
- writeChains = new Map();
25
+ /** Shared per-store-root, per-key write lock. Multiple OperationStore instances
26
+ * in one worker process must observe the same CAS critical section. */
27
+ writeChains;
26
28
  constructor(appData) {
27
29
  this.appData = appData;
30
+ const root = path.resolve(appData.operations);
31
+ let chains = sharedWriteChains.get(root);
32
+ if (!chains) {
33
+ chains = new Map();
34
+ sharedWriteChains.set(root, chains);
35
+ }
36
+ this.writeChains = chains;
28
37
  }
29
38
  serialize(key, op) {
30
39
  const prev = this.writeChains.get(key) ?? Promise.resolve();
@@ -66,6 +75,7 @@ export class OperationStore {
66
75
  payloadHash,
67
76
  state: "queued",
68
77
  createdAt: now,
78
+ revision: 1,
69
79
  taskId: input.taskId,
70
80
  cliArgs: input.cliArgs,
71
81
  ...(input.externalCommand
@@ -77,11 +87,61 @@ export class OperationStore {
77
87
  return { kind: "created", operation };
78
88
  });
79
89
  }
90
+ /**
91
+ * Idempotently materialize a split child/integration operation with a
92
+ * caller-specified deterministic operationId (from the split manifest).
93
+ * Unlike create() (random op_<hex> id) and save/update (no create), this is
94
+ * the durable cross-restart idempotency boundary for the production
95
+ * FrontendSplitTaskMaterializer backend: an existing operation file with the
96
+ * same taskId + payloadHash is returned as {created:false}; any drift fails
97
+ * closed instead of overwriting or silently diverging.
98
+ */
99
+ async ensureSplitMaterializedOperation(input) {
100
+ return this.serialize(input.operationId, async () => {
101
+ const existing = await this.get(input.operationId);
102
+ if (existing) {
103
+ if (existing.taskId !== input.taskId ||
104
+ existing.payloadHash !== input.payloadHash) {
105
+ throw new Error("frontend split operation materialization payload drift");
106
+ }
107
+ return { operation: existing, created: false };
108
+ }
109
+ const now = new Date().toISOString();
110
+ const operation = {
111
+ schemaVersion: 1,
112
+ operationId: input.operationId,
113
+ clientRequestId: `split:${input.operationId}`,
114
+ action: input.action,
115
+ actionParams: input.actionParams,
116
+ payloadHash: input.payloadHash,
117
+ state: "queued",
118
+ createdAt: now,
119
+ revision: 1,
120
+ taskId: input.taskId,
121
+ ...(input.cliArgs ? { cliArgs: input.cliArgs } : {}),
122
+ };
123
+ await writeSecureJson(operationFile(this.appData, input.operationId), operation);
124
+ return { operation, created: true };
125
+ });
126
+ }
80
127
  async get(operationId) {
81
128
  return readJsonIfExists(operationFile(this.appData, operationId));
82
129
  }
83
130
  async save(operation) {
84
131
  return this.serialize(operation.operationId, async () => {
132
+ const current = await this.get(operation.operationId);
133
+ if (current?.revision !== undefined && operation.revision !== current.revision)
134
+ throw new Error("operation revision may not be changed by save");
135
+ if (operation.frontendHumanDecision !== undefined || current?.frontendHumanDecision !== undefined) {
136
+ if (!current || JSON.stringify(operation) !== JSON.stringify(current))
137
+ throw new Error("human-decision projection may only be mutated by canonical CAS");
138
+ return current;
139
+ }
140
+ if (operation.frontendSplit !== undefined || current?.frontendSplit !== undefined) {
141
+ if (!current || JSON.stringify(operation) !== JSON.stringify(current))
142
+ throw new Error("split projection may only be mutated by compareAndSwapFrontendSplit");
143
+ return current;
144
+ }
85
145
  await writeSecureJson(operationFile(this.appData, operation.operationId), operation);
86
146
  return operation;
87
147
  });
@@ -92,6 +152,10 @@ export class OperationStore {
92
152
  if (!current) {
93
153
  throw new Error(`operation not found: ${operationId}`);
94
154
  }
155
+ if ("frontendHumanDecision" in patch || (current.frontendHumanDecision !== undefined && ("state" in patch || "frontendExecution" in patch)))
156
+ throw new Error("human-decision projection may only be mutated by canonical CAS");
157
+ if ("frontendSplit" in patch || "revision" in patch || (current.frontendSplit !== undefined && ("state" in patch || "frontendExecution" in patch)))
158
+ throw new Error("split projection may only be mutated by compareAndSwapFrontendSplit");
95
159
  const next = {
96
160
  ...current,
97
161
  ...patch,
@@ -106,6 +170,162 @@ export class OperationStore {
106
170
  return next;
107
171
  });
108
172
  }
173
+ async materializeFrontendHumanDecision(input) {
174
+ return this.serialize(input.operationId, async () => {
175
+ const current = await this.get(input.operationId);
176
+ if (!current || current.revision === undefined || current.revision !== input.expectedRecordRevision) {
177
+ const fallback = current?.frontendHumanDecision ?? buildFrontendHumanDecisionProjection({ status: "active", operationId: input.operationId, runId: input.envelope.runId, revision: Math.max(1, input.expectedRecordRevision) });
178
+ return { outcome: "rejected", reason: "record revision conflict or legacy record", projection: fallback };
179
+ }
180
+ const projection = current.frontendHumanDecision ?? buildFrontendHumanDecisionProjection({ status: "active", operationId: current.operationId, runId: input.envelope.runId, revision: current.revision });
181
+ const result = materializeFrontendHumanDecision({ projection, envelope: input.envelope, expectedRecordRevision: input.expectedRecordRevision, expectedProjectionDigest: input.expectedProjectionDigest });
182
+ if (result.outcome !== "applied")
183
+ return result;
184
+ const record = { ...current, revision: result.projection.revision, frontendHumanDecision: result.projection, state: "running" };
185
+ await writeSecureJson(operationFile(this.appData, current.operationId), record);
186
+ return result;
187
+ });
188
+ }
189
+ async consumeFrontendHumanDecision(input) {
190
+ return this.serialize(input.operationId, async () => {
191
+ const current = await this.get(input.operationId);
192
+ if (!current || current.revision === undefined || !current.frontendHumanDecision) {
193
+ const fallback = buildFrontendHumanDecisionProjection({ status: "active", operationId: input.operationId, runId: input.receipt.runId, revision: Math.max(1, input.expectedRecordRevision) });
194
+ return { outcome: "rejected", reason: "record has no mutable human-decision projection", projection: fallback };
195
+ }
196
+ const projection = parseFrontendHumanDecisionProjection(current.frontendHumanDecision);
197
+ if (current.revision !== input.expectedRecordRevision)
198
+ return { outcome: "rejected", reason: "record revision conflict", projection };
199
+ const result = consumeFrontendHumanDecision({ projection, receipt: input.receipt, expectedRecordRevision: input.expectedRecordRevision, expectedProjectionDigest: input.expectedProjectionDigest, currentTargetDigest: input.currentTargetDigest, now: input.now });
200
+ if (result.outcome !== "applied")
201
+ return result;
202
+ const record = { ...current, revision: result.projection.revision, frontendHumanDecision: result.projection };
203
+ await writeSecureJson(operationFile(this.appData, current.operationId), record);
204
+ return result;
205
+ });
206
+ }
207
+ async initializeFrontendHumanApprovedSplit(input) {
208
+ return this.serialize(input.operationId, async () => {
209
+ const current = await this.get(input.operationId);
210
+ const fallback = current?.frontendHumanDecision ?? buildFrontendHumanDecisionProjection({ status: "active", operationId: input.operationId, runId: input.receipt.runId, revision: Math.max(1, input.expectedRecordRevision) });
211
+ if (!current || current.revision === undefined || current.revision !== input.expectedRecordRevision || !current.frontendHumanDecision || !current.frontendExecution || current.frontendSplit)
212
+ return { outcome: "rejected", reason: "record is not an authoritative pending single-task split", projection: fallback };
213
+ const humanProjection = parseFrontendHumanDecisionProjection(current.frontendHumanDecision);
214
+ if (humanProjection.status !== "blocked-human" || humanProjection.envelope.kind !== "split-materialization-approval" || humanProjection.digest !== input.expectedProjectionDigest)
215
+ return { outcome: "rejected", reason: "pending split envelope conflict", projection: humanProjection };
216
+ const receipt = parseFrontendHumanDecisionReceipt(input.receipt);
217
+ if (receipt.kind !== "split-materialization-approval")
218
+ return { outcome: "rejected", reason: "receipt is not a split approval", projection: humanProjection };
219
+ if (JSON.stringify(current.frontendExecution) !== JSON.stringify(input.execution) || input.execution.kind !== "single-task")
220
+ return { outcome: "rejected", reason: "single-task execution conflict", projection: humanProjection };
221
+ const consumed = consumeFrontendHumanDecision({ projection: humanProjection, receipt, expectedRecordRevision: input.expectedRecordRevision, expectedProjectionDigest: input.expectedProjectionDigest, currentTargetDigest: input.currentTargetDigest, now: input.now });
222
+ if (consumed.outcome !== "applied")
223
+ return consumed;
224
+ const initialized = initializeFrontendSplitParent({
225
+ execution: input.execution,
226
+ manifest: input.manifest,
227
+ expectedOperationRevision: input.execution.operationRevision,
228
+ successorOperationRevision: consumed.projection.revision,
229
+ envelopeTargetDigest: humanProjection.envelope.targetDigest,
230
+ activeWriterOperationId: input.activeWriterOperationId,
231
+ activeProviderOperationId: input.activeProviderOperationId,
232
+ authorization: { mode: "human", envelope: humanProjection.envelope, receipt },
233
+ });
234
+ if (initialized.outcome !== "applied")
235
+ return { outcome: "rejected", reason: initialized.reason, projection: humanProjection };
236
+ const splitProjection = frontendSplitProjectionSchema.parse({ revision: consumed.projection.revision, execution: initialized.execution, manifest: input.manifest, parent: initialized.parent });
237
+ const { frontendExecution: _singleTask, ...withoutSingleTask } = current;
238
+ const record = { ...withoutSingleTask, revision: consumed.projection.revision, frontendHumanDecision: consumed.projection, frontendSplit: splitProjection, state: "running" };
239
+ await writeSecureJson(operationFile(this.appData, current.operationId), record);
240
+ return { outcome: "applied", projection: splitProjection, humanDecision: consumed.projection };
241
+ });
242
+ }
243
+ async compareAndSwapFrontendSplit(input) {
244
+ return this.serialize(input.operationId, async () => {
245
+ const current = await this.get(input.operationId);
246
+ if (!current || current.revision === undefined || current.revision !== input.expectedRevision)
247
+ return { outcome: "conflict" };
248
+ const currentProjection = current.frontendSplit;
249
+ if (currentProjection) {
250
+ if (currentProjection.execution.digest !== input.expectedExecutionDigest || currentProjection.parent.digest !== input.expectedParentDigest)
251
+ return { outcome: "conflict" };
252
+ }
253
+ else if (input.expectedExecutionDigest || input.expectedParentDigest)
254
+ return { outcome: "conflict" };
255
+ const next = currentProjection
256
+ ? assertFrontendSplitProjectionSuccessor(currentProjection, input.next)
257
+ : frontendSplitProjectionSchema.parse(input.next);
258
+ if (next.revision !== current.revision + 1 || next.parent.operationId !== input.operationId)
259
+ throw new Error("split CAS next revision or operation binding mismatch");
260
+ const state = next.parent.operationState === "success" ? "succeeded" : next.parent.operationTerminal !== undefined ? "failed" : current.state;
261
+ const record = { ...current, revision: next.revision, frontendSplit: next, state };
262
+ await writeSecureJson(operationFile(this.appData, input.operationId), record);
263
+ return { outcome: "applied", projection: next };
264
+ });
265
+ }
266
+ async loadChildCloseoutFacts(input) {
267
+ const factsDir = input.closeoutRef.ref;
268
+ const facts = await readJsonIfExists(path.join(factsDir, "frontend-closeout-facts.json"));
269
+ if (facts === undefined)
270
+ return frontendSplitChildCloseoutFactsSchema.parse({ childId: input.childId, residualRisks: [], frontendTestHandoffRef: undefined });
271
+ const parsedFacts = frontendCloseoutFactsSchema.parse(facts);
272
+ if (computeFrontendSplitDigest(parsedFacts) !== input.closeoutRef.digest)
273
+ throw new Error(`child closeout facts digest mismatch: ${input.childId}`);
274
+ const handoff = await readJsonIfExists(path.join(factsDir, "frontend-test-handoff.json"));
275
+ const frontendTestHandoffRef = handoff === undefined ? undefined : computeFrontendSplitDigest(frontendTestHandoffSchema.parse(handoff));
276
+ return frontendSplitChildCloseoutFactsSchema.parse({ childId: input.childId, residualRisks: parsedFacts.residualRisks ?? [], frontendTestHandoffRef });
277
+ }
278
+ async settleFrontendSplitAggregate(input) {
279
+ return this.serialize(input.operationId, async () => {
280
+ const record = await this.get(input.operationId);
281
+ if (!record || record.revision === undefined || record.revision !== input.expectedRevision || !record.frontendSplit)
282
+ return { outcome: "conflict" };
283
+ const authoritative = frontendSplitProjectionSchema.parse(record.frontendSplit);
284
+ if (authoritative.parent.operationId !== input.operationId
285
+ || authoritative.revision !== input.expectedRevision
286
+ || authoritative.execution.digest !== input.expectedExecutionDigest
287
+ || authoritative.parent.digest !== input.expectedParentDigest
288
+ || authoritative.manifest.digest !== input.expectedManifestDigest
289
+ || authoritative.candidateBinding?.digest !== input.expectedCandidateBindingDigest
290
+ || authoritative.integrationBinding?.digest !== input.expectedIntegrationBindingDigest)
291
+ return { outcome: "conflict" };
292
+ if (!authoritative.candidateBinding)
293
+ return { outcome: "conflict" };
294
+ const expectedAggregate = buildFrontendSplitAggregateCloseout(authoritative.parent, authoritative.manifest, authoritative.candidateBinding, authoritative.integrationBinding, input.childCloseoutFacts);
295
+ if (JSON.stringify(expectedAggregate) !== JSON.stringify(input.aggregate))
296
+ return { outcome: "conflict" };
297
+ const transaction = await input.prepareAggregate({
298
+ operationId: authoritative.parent.operationId,
299
+ aggregate: expectedAggregate,
300
+ });
301
+ try {
302
+ const committedRef = frontendCommittedFactRefSchema.parse(transaction.committedRef);
303
+ const finalized = finalizeFrontendSplitAggregate(authoritative.parent, expectedAggregate, committedRef);
304
+ const next = assertFrontendSplitProjectionSuccessor(authoritative, { ...authoritative, revision: authoritative.revision + 1, parent: finalized.parent, execution: finalized.execution, aggregateCloseout: { value: expectedAggregate, committedRef } });
305
+ const nextRecord = { ...record, revision: next.revision, frontendSplit: next, state: "succeeded" };
306
+ await transaction.commit({
307
+ parentRecordPath: operationFile(this.appData, record.operationId),
308
+ parentRecord: nextRecord,
309
+ });
310
+ return { outcome: "applied", projection: next };
311
+ }
312
+ catch (error) {
313
+ await transaction.rollback();
314
+ throw error;
315
+ }
316
+ });
317
+ }
318
+ async initializeFrontendSplit(expectedRevision, projectionValue) {
319
+ const projection = frontendSplitProjectionSchema.parse(projectionValue);
320
+ return this.serialize(projection.parent.operationId, async () => {
321
+ const current = await this.get(projection.parent.operationId);
322
+ if (!current || current.revision === undefined || current.revision !== expectedRevision || current.frontendSplit !== undefined || projection.revision !== expectedRevision + 1)
323
+ return { outcome: "conflict" };
324
+ const record = { ...current, revision: projection.revision, frontendSplit: projection };
325
+ await writeSecureJson(operationFile(this.appData, current.operationId), record);
326
+ return { outcome: "applied", projection };
327
+ });
328
+ }
109
329
  async list() {
110
330
  const files = await listJsonFiles(this.appData.operations);
111
331
  const ops = [];
@@ -64,6 +64,10 @@ function paramsOf(req) {
64
64
  function str(v) {
65
65
  return typeof v === "string" && v.trim() ? v.trim() : undefined;
66
66
  }
67
+ function appendExplicitTaskKindArg(args, taskKind, taskKindExplicit) {
68
+ if (taskKindExplicit)
69
+ args.push("--task-kind", taskKind);
70
+ }
67
71
  const TASK_ID_PLACEHOLDER_RE = /[<>]|^(?:id|task-?id|your-task-id|todo|tbd)$/i;
68
72
  /** Mirror of runtime GENERIC_TASK_SLUGS (not exported there); keep in sync. */
69
73
  const GENERIC_SLUG_SET = new Set(["test", "fix", "tmp", "new-task"]);
@@ -536,6 +540,84 @@ async function acceptOperation(ctx, input) {
536
540
  },
537
541
  };
538
542
  }
543
+ function splitRuntimeMissing(action) {
544
+ return {
545
+ kind: "error",
546
+ status: 503,
547
+ body: operatorFailed({
548
+ command: action,
549
+ outcome: "blocked",
550
+ code: "INTERNAL_ERROR",
551
+ message: `${action} is unavailable: frontend split runtime is not wired`,
552
+ }),
553
+ };
554
+ }
555
+ function numOf(v) {
556
+ return typeof v === "number" ? v : Number(v);
557
+ }
558
+ function splitCommandBase(p) {
559
+ return {
560
+ operationId: str(p.operationId) ?? "",
561
+ expectedRevision: numOf(p.expectedRevision),
562
+ expectedParentDigest: str(p.expectedParentDigest) ?? "",
563
+ expectedManifestDigest: str(p.expectedManifestDigest) ?? "",
564
+ };
565
+ }
566
+ function splitCommandDispatch(action, result) {
567
+ if (result.outcome === "conflict") {
568
+ return {
569
+ kind: "error",
570
+ status: 409,
571
+ body: operatorFailed({
572
+ command: action,
573
+ outcome: "conflict",
574
+ code: "CONFLICT",
575
+ message: "frontend split CAS conflict (stale revision or binding)",
576
+ }),
577
+ };
578
+ }
579
+ return { kind: "sync", status: 200, body: operatorSucceeded(action, result) };
580
+ }
581
+ async function runSplitAction(action, run) {
582
+ try {
583
+ const result = await run();
584
+ if (result && typeof result === "object" && "outcome" in result) {
585
+ return splitCommandDispatch(action, result);
586
+ }
587
+ return {
588
+ kind: "sync",
589
+ status: 200,
590
+ body: operatorSucceeded(action, result),
591
+ };
592
+ }
593
+ catch (error) {
594
+ return invalid(action, error instanceof Error ? error.message : String(error));
595
+ }
596
+ }
597
+ function humanDecisionDispatch(action, result) {
598
+ if (result.outcome === "rejected") {
599
+ return {
600
+ kind: "error",
601
+ status: 409,
602
+ body: operatorFailed({
603
+ command: action,
604
+ outcome: "conflict",
605
+ code: "CONFLICT",
606
+ message: result.reason,
607
+ details: { projection: result.projection },
608
+ }),
609
+ };
610
+ }
611
+ return { kind: "sync", status: 200, body: operatorSucceeded(action, result) };
612
+ }
613
+ async function runHumanDecisionAction(action, run) {
614
+ try {
615
+ return humanDecisionDispatch(action, await run());
616
+ }
617
+ catch (error) {
618
+ return invalid(action, error instanceof Error ? error.message : String(error));
619
+ }
620
+ }
539
621
  async function acceptConsoleUpdateAndInit(ctx, clientRequestId, channel) {
540
622
  if (!ctx.consoleUpdateExecutor) {
541
623
  return {
@@ -1877,7 +1959,7 @@ export async function dispatchOperatorAction(ctx, req) {
1877
1959
  const staged = await stageUtf8Text(ctx.appData, content, {
1878
1960
  extension: ".md",
1879
1961
  });
1880
- const imported = await run([
1962
+ const importArgs = [
1881
1963
  "task",
1882
1964
  "advance",
1883
1965
  taskId,
@@ -1886,8 +1968,10 @@ export async function dispatchOperatorAction(ctx, req) {
1886
1968
  staged.path,
1887
1969
  "--role",
1888
1970
  "requirement",
1889
- "--json",
1890
- ], {
1971
+ ];
1972
+ appendExplicitTaskKindArg(importArgs, taskKind, taskKindExplicit);
1973
+ importArgs.push("--json");
1974
+ const imported = await run(importArgs, {
1891
1975
  cwd: ctx.repoRoot,
1892
1976
  artifactName: "import-prd-task-advance",
1893
1977
  expectJson: true,
@@ -2862,6 +2946,75 @@ export async function dispatchOperatorAction(ctx, req) {
2862
2946
  }),
2863
2947
  };
2864
2948
  }
2949
+ case "frontendSplitWakeup": {
2950
+ if (!ctx.splitOrchestrator)
2951
+ return splitRuntimeMissing(action);
2952
+ return runSplitAction(action, () => ctx.splitOrchestrator.wakeupChildren(splitCommandBase(p)));
2953
+ }
2954
+ case "frontendSplitChildCallback": {
2955
+ if (!ctx.splitOrchestrator)
2956
+ return splitRuntimeMissing(action);
2957
+ return runSplitAction(action, () => ctx.splitOrchestrator.childCallback({
2958
+ ...splitCommandBase(p),
2959
+ observation: p.observation,
2960
+ }));
2961
+ }
2962
+ case "frontendSplitWakeupIntegration": {
2963
+ if (!ctx.splitOrchestrator)
2964
+ return splitRuntimeMissing(action);
2965
+ return runSplitAction(action, () => ctx.splitOrchestrator.wakeupIntegration(splitCommandBase(p)));
2966
+ }
2967
+ case "frontendSplitIntegrationCallback": {
2968
+ if (!ctx.splitOrchestrator)
2969
+ return splitRuntimeMissing(action);
2970
+ return runSplitAction(action, () => ctx.splitOrchestrator.integrationCallback({
2971
+ ...splitCommandBase(p),
2972
+ completion: p.completion,
2973
+ }));
2974
+ }
2975
+ case "frontendSplitFinalize": {
2976
+ if (!ctx.splitOrchestrator)
2977
+ return splitRuntimeMissing(action);
2978
+ return runSplitAction(action, () => ctx.splitOrchestrator.finalize(splitCommandBase(p)));
2979
+ }
2980
+ case "frontendHumanDecisionMaterialize": {
2981
+ if (!ctx.humanDecisionAdapter)
2982
+ return splitRuntimeMissing(action);
2983
+ return runHumanDecisionAction(action, () => ctx.humanDecisionAdapter.materialize({
2984
+ operationId: str(p.operationId) ?? "",
2985
+ expectedRecordRevision: numOf(p.expectedRecordRevision),
2986
+ expectedProjectionDigest: str(p.expectedProjectionDigest) ?? "",
2987
+ envelope: p.envelope,
2988
+ }));
2989
+ }
2990
+ case "frontendHumanDecisionApprove": {
2991
+ if (!ctx.humanDecisionAdapter)
2992
+ return splitRuntimeMissing(action);
2993
+ return runHumanDecisionAction(action, () => ctx.humanDecisionAdapter.consume({
2994
+ operationId: str(p.operationId) ?? "",
2995
+ expectedRecordRevision: numOf(p.expectedRecordRevision),
2996
+ expectedProjectionDigest: str(p.expectedProjectionDigest) ?? "",
2997
+ receipt: p.receipt,
2998
+ currentTargetDigest: str(p.currentTargetDigest) ?? "",
2999
+ now: str(p.now) ?? new Date().toISOString(),
3000
+ }));
3001
+ }
3002
+ case "frontendSplitInitialize": {
3003
+ if (!ctx.humanDecisionAdapter)
3004
+ return splitRuntimeMissing(action);
3005
+ return runHumanDecisionAction(action, () => ctx.humanDecisionAdapter.initializeSplit({
3006
+ operationId: str(p.operationId) ?? "",
3007
+ expectedRecordRevision: numOf(p.expectedRecordRevision),
3008
+ expectedProjectionDigest: str(p.expectedProjectionDigest) ?? "",
3009
+ execution: p.execution,
3010
+ manifest: p.manifest,
3011
+ receipt: p.receipt,
3012
+ currentTargetDigest: str(p.currentTargetDigest) ?? "",
3013
+ now: str(p.now) ?? new Date().toISOString(),
3014
+ activeWriterOperationId: str(p.activeWriterOperationId) ?? null,
3015
+ activeProviderOperationId: str(p.activeProviderOperationId) ?? null,
3016
+ }));
3017
+ }
2865
3018
  default: {
2866
3019
  // M5 official-command coverage uses one generic tail for newly registered
2867
3020
  // CLI actions. It remains inside dispatchOperatorAction (the sole dispatch
@@ -3246,7 +3399,14 @@ async function dispatchBootstrapFromPrd(ctx, p) {
3246
3399
  const title = identity.title;
3247
3400
  const run = ctx.runCommand ?? ((a, o) => ctx.client.run(a, o));
3248
3401
  // Standard lifecycle entry: task advance create + PRD import(s).
3249
- const advanceCreate = await run(["task", "advance", taskId, title, "--json"], {
3402
+ // Preserve an explicitly selected business workflow from the very first
3403
+ // task.json write. The task lifecycle otherwise defaults new tasks to
3404
+ // standard, which caused frontend tasks to be promoted only during the
3405
+ // final intake pass.
3406
+ const createArgs = ["task", "advance", taskId, title];
3407
+ appendExplicitTaskKindArg(createArgs, taskKind, taskKindExplicit);
3408
+ createArgs.push("--json");
3409
+ const advanceCreate = await run(createArgs, {
3250
3410
  cwd: ctx.repoRoot,
3251
3411
  artifactName: "bootstrap-task-advance-create",
3252
3412
  expectJson: true,
@@ -3280,7 +3440,7 @@ async function dispatchBootstrapFromPrd(ctx, p) {
3280
3440
  const staged = await stageUtf8Text(ctx.appData, text, {
3281
3441
  extension: ".md",
3282
3442
  });
3283
- const imported = await run([
3443
+ const importArgs = [
3284
3444
  "task",
3285
3445
  "advance",
3286
3446
  taskId,
@@ -3288,8 +3448,10 @@ async function dispatchBootstrapFromPrd(ctx, p) {
3288
3448
  staged.path,
3289
3449
  "--role",
3290
3450
  role,
3291
- "--json",
3292
- ], {
3451
+ ];
3452
+ appendExplicitTaskKindArg(importArgs, taskKind, taskKindExplicit);
3453
+ importArgs.push("--json");
3454
+ const imported = await run(importArgs, {
3293
3455
  cwd: ctx.repoRoot,
3294
3456
  artifactName: `bootstrap-task-advance-prd-${label}`,
3295
3457
  expectJson: true,
@@ -98,9 +98,7 @@ function getNpmRegistry() {
98
98
  /** 从 npm 配置的仓库拉取某包的全部已发布版本 + latest。 */
99
99
  export async function listPiPluginVersions(name) {
100
100
  const registry = (await getNpmRegistry()).replace(/\/+$/, "");
101
- // scoped 包名整段编码(@scope/name → %40scope%2Fname):与 npm 客户端请求
102
- // packument 的形式一致,npmjs.org 与内网 Nexus(要求 %2F 不还原)都接受。
103
- const url = `${registry}/${encodeURIComponent(name)}`;
101
+ const url = `${registry}/${encodeURIComponent(name).replace(/%2F/g, "/")}`;
104
102
  try {
105
103
  const res = await fetch(url, {
106
104
  headers: { accept: "application/json", "user-agent": "loop-agent/1.0" },
@@ -778,6 +778,9 @@ export async function createConsoleServer(options) {
778
778
  appData: startup.appData,
779
779
  operations: startup.operations,
780
780
  events: startup.events,
781
+ splitOrchestrator: startup.splitOrchestrator,
782
+ humanDecisionAdapter: startup.humanDecisionAdapter,
783
+ materializer: startup.materializer,
781
784
  getReadiness,
782
785
  operatorSessionId,
783
786
  registry,
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-CZsXBPuR.js";import{p as f}from"./chunk-JWPE2WC7-DQxb9plr.js";import{_ as n,l as o}from"./mermaid.core-Bpa6PmuE.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-C5yVYU7E.js";import"./index-Bih9w9h9.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
1
+ import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-DPz__z7r.js";import{p as f}from"./chunk-JWPE2WC7-BB41iK5t.js";import{_ as n,l as o}from"./mermaid.core-Cxg8kX8V.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-CTuBy0Or.js";import"./index-DLt4ZFvD.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
@@ -1 +1 @@
1
- import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-Bpa6PmuE.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
1
+ import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-Cxg8kX8V.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};