@tea-agent/loop-agent 0.36.4-beta.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 (118) hide show
  1. package/AGENTS.md +2 -6
  2. package/CHANGELOG.md +72 -163
  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/infrastructure/harness/atomic-write.js +1 -2
  18. package/dist/shared/operator/capabilities.js +13 -200
  19. package/dist/shared/package-metadata.js +0 -42
  20. package/dist/task/frontend-project-capability.js +12 -162
  21. package/dist/task/source-prepare/completeness.js +0 -17
  22. package/dist/task/source-prepare/parse-intent.js +1 -15
  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 -61
  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 -86
  29. package/dist/worker/console/chat/routes.js +8 -36
  30. package/dist/worker/console/chat/session-store.js +0 -3
  31. package/dist/worker/console/chat/shortcuts.js +7 -9
  32. package/dist/worker/console/chat/turn-process.js +23 -97
  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 +13 -373
  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 -89
  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 +11 -30
  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 +1 -6
  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/failure-routing.js +4 -9
  70. package/dist/workflows/dag/frontend-implementation-contract.js +39 -233
  71. package/dist/workflows/dag/frontend-prewrite-gate.js +62 -394
  72. package/dist/workflows/dag/frontend-repair.js +18 -219
  73. package/dist/workflows/dag/frontend-verification-trace.js +32 -47
  74. package/dist/workflows/dag/init-hybrid.js +86 -238
  75. package/dist/workflows/dag/lifecycle.js +0 -4
  76. package/dist/workflows/dag/node-execution.js +6 -105
  77. package/dist/workflows/dag/recovery-recommendation.js +0 -58
  78. package/dist/workflows/dag/report.js +0 -6
  79. package/dist/workflows/dag/retry-policy.js +0 -11
  80. package/dist/workflows/dag/runner.js +12 -314
  81. package/dist/workflows/dag/scheduler.js +3 -257
  82. package/dist/workflows/dag/types.js +9 -132
  83. package/dist/workflows/dag/validate.js +2 -7
  84. package/docs/README.md +3 -3
  85. package/docs/architecture/evolution.md +67 -102
  86. package/docs/templates/backend-test-dag.json +50 -32
  87. package/docs/templates/frontend-design-contract.md +14 -34
  88. package/docs/templates/frontend-task-constraints.md +13 -33
  89. package/docs/templates/frontend-task-requirement.md +20 -54
  90. package/docs/templates/init-managed-agents.md +2 -5
  91. package/harness.json +2 -2
  92. package/package.json +3 -4
  93. package/skills/loop-agent/SKILL.md +0 -1
  94. package/skills/loop-agent/references/command-reference.md +0 -3
  95. package/dist/build-stamp.json +0 -6
  96. package/dist/commands/dag-request-interrupt.js +0 -20
  97. package/dist/worker/console/chat/assistant-content.js +0 -121
  98. package/dist/worker/console/chat/semantic-activity.js +0 -471
  99. package/dist/worker/console/operation-run-facts.js +0 -190
  100. package/dist/worker/console/operation-wait.js +0 -355
  101. package/dist/worker/console/recovery-error-copy.js +0 -198
  102. package/dist/worker/console/static/assets/index-D83DYAFG.css +0 -1
  103. package/dist/worker/console/static/assets/index-IXm7oYjL.js +0 -59
  104. package/dist/worker/console/static-src/operator-chat/activity-journey.js +0 -125
  105. package/dist/worker/console/static-src/operator-chat/activity-rail-presentation.js +0 -73
  106. package/dist/worker/console/static-src/operator-chat/activity-references.js +0 -20
  107. package/dist/worker/console/static-src/operator-chat/slash-palette-layout.js +0 -24
  108. package/dist/worker/console/static-src/operator-chat/slash-palette-nav.js +0 -141
  109. package/dist/worker/console/static-src/operator-chat/useActivityRailTransition.js +0 -59
  110. package/dist/worker/observability/interrupt-eligibility.js +0 -264
  111. package/dist/workflows/dag/contract-output-registry.js +0 -14
  112. package/dist/workflows/dag/contract-validator-registrations.js +0 -8
  113. package/dist/workflows/dag/frontend-recovery-plan.js +0 -73
  114. package/dist/workflows/dag/frontend-recovery-root-manifest.js +0 -123
  115. package/dist/workflows/dag/frontend-recovery-run.js +0 -539
  116. package/dist/workflows/dag/frontend-writer-recovery.js +0 -106
  117. package/dist/workflows/dag/frontend-writer-rollback.js +0 -821
  118. package/dist/workflows/dag/interrupt-request.js +0 -559
@@ -1,104 +1,70 @@
1
1
  # 前端任务需求模板
2
2
 
3
- 本模板只承载**通用编写协议 + 三要素 + fail-closed 规则**,不包含任何具体业务组件名、项目专属路径或项目专属命令。填写时每一节都要给出「**要写什么** / **DAG 如何消费** / **缺失/冲突时 fail-closed**」三要素;缺节、空占位或与验收标准冲突时必须阻塞,不得由模型猜测补写。
4
-
5
3
  ## 用户目标
6
4
 
7
- - **要写什么**:以用户视角写清本次要交付的前端行为与用户价值——用户能完成什么、为什么需要它、成功后的可观察结果。必须可验证(可被界面状态或交互断言覆盖),不得只写技术动作或孤立关键词。
8
- - **DAG 如何消费**:`frontend-contract-pi` 把它映射为 Scope 与 `requirements[].expectedOutcome`,`frontend-plan-pi` 据它安排实现步骤并映射验收标准。
9
- - **缺失/冲突时 fail-closed**:缺失用户目标,或用户目标与验收标准互相矛盾时阻塞(`request-revision`/blocked),不得猜测补写或改写为技术实现描述。
5
+ TODO
10
6
 
11
7
  ## 目标页面/组件/路由
12
8
 
13
- - **要写什么**:明确本次交付涉及的目标路由、页面入口与组件范围,逐条列出路径/名称与职责边界;相关但超出范围的页面写清「不做」。
14
- - **DAG 如何消费**:对齐 `docs/runtime/frontend-implementation-workflow.md` §「需求.md 应包含」的「目标路由/页面/组件」,`frontend-contract-pi` 据它确定 `targets.files` / `targets.routes`,`frontend-plan-pi` 据它划定 writeSet 与实现步骤。
15
- - **缺失/冲突时 fail-closed**:无法确定目标路由/页面/组件,或范围与验收标准不一致时阻塞;只写泛化名词(如「页面」「组件」)而不给具体范围视为缺失。
9
+ TODO
16
10
 
17
11
  ## 用户流程
18
12
 
19
- - **要写什么**:写清端到端用户路径,从入口到结果,逐步列出触发动作、顺序与关键分支;涉及多页面/多状态时把每条路径分开写。
20
- - **DAG 如何消费**:`frontend-contract-pi` 据它抽取 `interactions[]`(每条带 `trigger` 与 `expectedBehavior`),`frontend-plan-pi` 据它安排组件/状态/交互实现步骤。
21
- - **缺失/冲突时 fail-closed**:缺少可执行的端到端路径、流程与验收标准冲突或关键分支未写时阻塞,不得只写「用户进入页面即可」。
13
+ TODO
22
14
 
23
15
  ## 必须状态
24
16
 
25
- 每个适用状态必须写清该状态的触发条件与预期界面表现;不适用状态必须写 `N/A` 并给出非空理由(对齐 runtime 的 `uiStates` / N/A state 规则)。
26
-
27
17
  ### loading
28
18
 
29
- - **要写什么**:loading 状态出现与结束的触发条件、展示内容(骨架/文案/禁用交互)与超时/失败转移。
30
- - **DAG 如何消费**:进入 implementation contract 的 `uiStates[]`(`name: "loading"`),`frontend-implement-pi` 按它实现,verify 用它的 `verificationTargetIds` 断言。
31
- - **缺失/冲突时 fail-closed**:适用但缺失预期行为时阻塞;不适用必须写 `N/A` 并给非空理由,只写 `N/A` 不带理由同样阻塞。
19
+ TODO
32
20
 
33
21
  ### empty
34
22
 
35
- - **要写什么**:无数据/无结果状态的触发条件与展示(空态文案/引导动作/是否可刷新)。
36
- - **DAG 如何消费**:进入 `uiStates[]`(`name: "empty"`),verify 断言空态展示与引导。
37
- - **缺失/冲突时 fail-closed**:适用但缺失预期行为、或与 success/error 展示冲突时阻塞;不适用写 `N/A` + 非空理由。
23
+ TODO
38
24
 
39
25
  ### error
40
26
 
41
- - **要写什么**:失败状态(请求失败/校验失败/权限失败)的触发条件、错误展示与可恢复动作。
42
- - **DAG 如何消费**:进入 `uiStates[]`(`name: "error"`),verify 断言错误展示与重试/回退行为。
43
- - **缺失/冲突时 fail-closed**:适用但缺失错误预期、或错误态会覆盖用户数据时阻塞;不适用写 `N/A` + 非空理由。
27
+ TODO
44
28
 
45
29
  ### success
46
30
 
47
- - **要写什么**:成功状态的触发条件与展示(数据呈现/确认反馈/后续入口)。
48
- - **DAG 如何消费**:进入 `uiStates[]`(`name: "success"`),verify 断言成功展示与验收标准对应。
49
- - **缺失/冲突时 fail-closed**:成功态与验收标准不一致、或缺失成功结果时阻塞;不适用写 `N/A` + 非空理由。
31
+ TODO
50
32
 
51
33
  ### disabled
52
34
 
53
- - **要写什么**:禁用/不可交互状态的触发条件(权限/前置未满足/进行中)与视觉/交互表现。
54
- - **DAG 如何消费**:进入 `uiStates[]`(`name: "disabled"`),verify 断言禁用态不会被误触。
55
- - **缺失/冲突时 fail-closed**:适用但缺失禁用条件、或禁用态与交互要求冲突时阻塞;不适用写 `N/A` + 非空理由。
35
+ TODO
56
36
 
57
37
  ## 目标运行环境
58
38
 
59
- 每个环境必须声明适用性;不适用环境写 `N/A` 并给非空理由。
60
-
61
39
  ### desktop
62
40
 
63
- - **要写什么**:desktop 视口下的适用性声明与关键布局/交互差异(断点、栅格、悬停等)。
64
- - **DAG 如何消费**:进入 contract 的 target runtime environment,`frontend-plan-pi` 据它决定响应式范围与样式策略。
65
- - **缺失/冲突时 fail-closed**:适用但缺失断点/布局说明,或与响应式要求冲突时阻塞;不适用写 `N/A` + 非空理由。
41
+ TODO
66
42
 
67
43
  ### mobile
68
44
 
69
- - **要写什么**:mobile 视口下的适用性声明与触控/布局/安全区差异。
70
- - **DAG 如何消费**:进入 target runtime environment,`frontend-plan-pi` 据它决定响应式范围与组件策略。
71
- - **缺失/冲突时 fail-closed**:适用但缺失移动端表现,或与交互要求冲突时阻塞;不适用写 `N/A` + 非空理由。
45
+ TODO
72
46
 
73
47
  ### tablet
74
48
 
75
- - **要写什么**:tablet 视口下的适用性声明与中间断点表现。
76
- - **DAG 如何消费**:进入 target runtime environment,`frontend-plan-pi` 据它决定响应式策略。
77
- - **缺失/冲突时 fail-closed**:适用但缺失 tablet 表现时阻塞;不适用写 `N/A` + 非空理由。
49
+ TODO
78
50
 
79
51
  ## 交互要求
80
52
 
81
- - **要写什么**:逐条写清每个可交互元素的触发动作与预期行为(点击/输入/提交/滚动/键盘等),可被自动化断言覆盖。
82
- - **DAG 如何消费**:对齐 §「需求.md 应包含」的「交互要求」,`frontend-contract-pi` 抽取 `interactions[]`(`trigger` + `expectedBehavior`),verify 用行为命令断言。
83
- - **缺失/冲突时 fail-closed**:交互触发或预期行为缺失、与 UI 状态冲突、或不可自动化断言时阻塞,不得用「用户可正常操作」这类空话。
53
+ TODO
84
54
 
85
55
  ## 接口与 Mock 输入
86
56
 
87
- - **接口文档/schema — 要写什么**:引用接口文档或任务附件路径与版本,声明请求/响应 schema 来源。**DAG 如何消费**:`frontend-plan-pi` 据此选择 Mock 策略并冻结 endpoint/fixture 映射。**缺失/冲突时 fail-closed**:涉及接口但未引用文档或 schema 时阻塞,不得自行发明字段。
88
- - **endpoint、method、关键请求/响应字段 — 要写什么**:逐条列出 method、path 与关键字段及含义。**DAG 如何消费**:写入 `mockApi.endpoints[]`(method/path/fixture/consumer)。**缺失/冲突时 fail-closed**:字段缺失、与接口文档冲突或路径不合法时阻塞。
89
- - **是否允许依赖真实后端 — 要写什么**:明确声明真实后端当前是否可调用、是否允许生产/预览依赖真实请求。**DAG 如何消费**:决定 `mockApi.strategy` 是否可选 `not-needed`(需要真实/无远程证据)。**缺失/冲突时 fail-closed**:未声明后端就绪度却要求真实数据时阻塞,选 `not-needed` 却没有真实/无远程证据会被拦截。
90
- - **是否要求离线或独立行为验证 — 要写什么**:声明是否需要离线、本地预览或自动化行为验证(或两者都要)。**DAG 如何消费**:决定生成期 `frontendMock.verifyCommands` 与冻结命令集。**缺失/冲突时 fail-closed**:要求离线/自动化却未声明确定性验证命令时,生成期收敛为 `not-needed` 或直接 blocked,plan-revision 无法修复。
91
- - **success/empty/error/permission 状态 — 要写什么**:逐条声明接口各响应状态对应的 UI 表现。**DAG 如何消费**:与「必须状态」交叉校验,写入 `uiStates[]` 与 fixture 映射。**缺失/冲突时 fail-closed**:接口状态与 UI 状态不匹配或缺失 permission 分支时阻塞。
92
- - **后端当前就绪状态与 Real Integration Gap — 要写什么**:写清后端是否就绪、未就绪时保留的 Real Integration Gap 与后端就绪后的复验路径。**DAG 如何消费**:进入 `evidenceGaps[]` 与 closeout 的 `Real integration: pending`。**缺失/冲突时 fail-closed**:声称已联通真实接口却无真实证据时阻塞;未就绪却把 Mock 结果写成真实联调会被 review 拒绝。
57
+ - 接口文档/schema:TODO
58
+ - endpoint、method、关键请求/响应字段:TODO
59
+ - 是否允许依赖真实后端:TODO
60
+ - 是否要求离线或独立行为验证:TODO
61
+ - success/empty/error/permission 状态:TODO
62
+ - 后端当前就绪状态与 Real Integration Gap:TODO
93
63
 
94
64
  ## 验收标准
95
65
 
96
- - **要写什么**:逐条编号(如 `AC-001`)写出可独立断言的前端验收标准,每条都能映射到需求与一个 verification target(可逐条追踪)。
97
- - **DAG 如何消费**:`frontend-contract-pi` 生成 `requirements[].verificationTargetIds` 映射,`frontend-plan-pi` 把每条 AC 落到有序步骤与验证命令,verify 逐条断言。
98
- - **缺失/冲突时 fail-closed**:无验收标准、AC 无法映射到需求/验证目标、或 AC 与其它节冲突时阻塞,不得把「看起来能用」当验收。
66
+ TODO
99
67
 
100
68
  ## 非目标
101
69
 
102
- - **要写什么**:明确列出本次不做的前端范围/排除项(页面、组件、交互、浏览器/视觉/无障碍检查等)。
103
- - **DAG 如何消费**:`frontend-contract-pi` 记录为 Non-goals,`frontend-review-pi` 据它拒绝范围扩散。
104
- - **缺失/冲突时 fail-closed**:非目标与目标/验收标准冲突、或范围被悄悄扩大时阻塞;明确不做前端时也必须写入非目标。
70
+ TODO
@@ -33,8 +33,7 @@
33
33
  | **允许** | 已发布 `loop-agent` / `agent-worker` CLI;只读 status/doctor/report/inspect/observe;准备 `source/*` 与 `task.json` 边界;human gate;shell 验证与 handoff。 |
34
34
  | **禁止** | 绕过 CLI 用宿主 Edit/Write/ApplyPatch 直接改业务实现;CLI/DAG 失败后「救火改文件」;用聊天自述代替 shell 验证。 |
35
35
  | **失败时** | 先 `dag report` / `dag doctor`;优先 `dag rerun --from-node` 安全子图续跑;仅契约/源真变或 plan 不合格时同 task 重 advance / `dag rerun-task`;paused 用 approve→`dag resume`。 |
36
- | **实现写入** | 业务代码 **只** 经受治理 DAG writer(`implement-pi` / `repair-pi`)经 `task advance`(批准 writeSet gate 后长跑)由 Console operation 后台持有;主会话**不得**在前台 Bash 直接执行 `task advance --approve-gate`,不得把长跑命令管道到 `tail`/`head`,不得自行拼接 `nohup` / `Start-Process` / `start`。 |
37
- | **契约漂移** | 直接编辑 `source/需求.md` / `执行约束.md` 后契约会进入 `externally-modified`,此时 advance/dagRunTask 拒用新内容(DIRTY_SOURCE / hash 不一致)。合法收编路径:`task contract adopt --task <id> --expected-revision <n> --expected-observed-hash <hash> --request-id <id> --request-payload-sha256 <sha>`(hash 从 `task status --json` 的 `contract.observedCanonicalHash` 取);或改 PRD 后重新 importPrd 走完整重投影。禁止手工改 `lifecycle.json` / `.transactions/` 绕过。 |
36
+ | **实现写入** | 业务代码 **只** 经受治理 DAG writer(`implement-pi` / `repair-pi`)经 `task advance`(批准 writeSet gate 后长跑)。 |
38
37
 
39
38
  **永远不要**:`loop-agent` / `agent-worker` 失败 ⇒ 主会话直接改仓库实现;也勿因 provider 抖动或只读节点失败**新建无关 task-id**。
40
39
 
@@ -110,8 +109,6 @@ loop-agent task status <task-id> --json
110
109
  # 有 plan 时收尾:loop-agent plan complete <plan-id> --summary "..."
111
110
  ```
112
111
 
113
- 长跑 DAG 采用 `prepareDagExecution → runDag → operationId` 异步 operation 路径(`--approve-gate` 不在前台 Bash 中同步等待);监督退避 60 → 90 → 120 → 180 秒,状态变化后重置为 60 秒,疑似 stall 用 30–60 秒复查。
114
-
115
112
  `--verify` 命令应取项目 `AGENTS.md` / `__LOOP_AGENT_GOVERNANCE_ROOT__/verification-matrix.md` 登记的验证命令(不要假定 `npm run typecheck` 存在);`--verify` 可选,省略时自动从 package.json scripts 或既有 managed `task.json.verifyCommands` 推导建议。
116
113
 
117
114
  `source/需求.md` 与 `source/执行约束.md` 仍必需(M8/M9),但默认由 `task advance --prd` 投影生成,而不是主会话手写。`plan create` 不是 `task advance` 的硬依赖。写入前同步 `task.json.allowedPaths` / `task.json.forbiddenPaths` 并审查 writer `writeSet`。高级任意 DagSpec 才用 `dag validate|execute|report`,不进入标准 happy path。
@@ -142,7 +139,7 @@ live run 先用 `loop-agent dag status --run-id <run-id>` 看 lifecycle 与 live
142
139
 
143
140
  **失败默认恢复序**:`dag report`/`dag doctor` → 优先 `dag rerun --from-node <node> --plan` 再带 `--plan-hash`(provider 抖动、plan/review/verify 安全下游;writer/decision/fingerprint 不合格勿硬跑)→ paused:approve→`dag resume` → 契约/源真变或 R1 不合格:同 task `task advance` / `dag rerun-task`(禁无理由新建 task-id)→ Worker-owned:`agent-worker task retry`。
144
141
 
145
- Operator 须监控 live run 至终态(FINISHED / FAILED / partial_failed)或 Decision Gate 需要 approve;监督退避 60 → 90 → 120 → 180 秒(状态变化后重置 60 秒,疑似 stall 用 30–60 秒复查),长跑 DAG 由 Console operation 后台持有(`prepareDagExecution → runDag → operationId`),禁止前台 Bash 直接 `task advance --approve-gate`、禁止管道 `tail`/`head`、禁止自行拼接 `nohup` / `Start-Process` / `start`;可在节点/rank 变化、verify/closeout、stall 或需 approve 时简短汇报(告知非请求确认)。判活须组合 runner heartbeat、session events 与 `dag doctor` liveness/provider meaningful progress(heartbeat alone ≠ progress)。bounded writer 运行期间不得并发修改工作区(write guard / write-guard 会把越界 diff 错误归因到 writer);只读 status/doctor/report 与 approve/reject/resume 仍允许。恢复:report/doctor → **优先** `dag rerun --from-node` → 必要时 rerun-task/同 task advance → shell verify。**禁止**把主会话直接 Edit 业务代码当作恢复手段。
142
+ Operator 须监控 live run 至终态(FINISHED / FAILED / partial_failed)或 Decision Gate 需要 approve;可在节点/rank 变化、verify/closeout、stall 或需 approve 时简短汇报(告知非请求确认)。判活须组合 runner heartbeat、session events 与 `dag doctor` liveness/provider meaningful progress(heartbeat alone ≠ progress)。bounded writer 运行期间不得并发修改工作区(write guard / write-guard 会把越界 diff 错误归因到 writer);只读 status/doctor/report 与 approve/reject/resume 仍允许。恢复:report/doctor → **优先** `dag rerun --from-node` → 必要时 rerun-task/同 task advance → shell verify。**禁止**把主会话直接 Edit 业务代码当作恢复手段。
146
143
 
147
144
  ### 运行态与验证
148
145
 
package/harness.json CHANGED
@@ -79,9 +79,9 @@
79
79
  },
80
80
  "executors": {
81
81
  "pi": {
82
- "description": "Pi 负责规划、评审、诊断;当 DAG toolProfile=write 时也可做有界写入。模型按复杂度三档配置,支持 provider/model 字符串或带 thinking 的对象;斜杠前为 Pi provider,后为 modelId,勿只写裸 modelId。",
82
+ "description": "Pi 负责规划、评审、诊断;当 DAG toolProfile=write 时也可做有界写入。模型按复杂度三档配置,格式为 provider/model 字符串(例:wizard-local/grok-4.5);斜杠前为 Pi provider,后为 modelId,勿只写裸 modelId。",
83
83
  "LOW": "wizard-local/minimax-m3",
84
- "MED": "wizard-local/grok-4.6",
84
+ "MED": "wizard-local/grok-4.5",
85
85
  "HIGH": "wizard-local/gpt-5.6-sol"
86
86
  }
87
87
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tea-agent/loop-agent",
3
- "version": "0.36.4-beta.0",
3
+ "version": "0.37.1-beta.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "loop-agent": "bin/loop-agent.js",
@@ -45,7 +45,7 @@
45
45
  "pi-prompt": "node --import tsx/esm src/cli.ts pi-prompt",
46
46
  "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
47
47
  "brand:sync": "node scripts/sync-brand-assets.mjs",
48
- "build": "npm run brand:sync && npm run clean && tsc -p tsconfig.build.json && node -e \"const fs=require('node:fs');const p='dist/worker/observe/static';fs.mkdirSync(p,{recursive:true});fs.cpSync('src/worker/observe/static',p,{recursive:true});\" && npm run console:build && node scripts/write-build-stamp.mjs",
48
+ "build": "npm run brand:sync && npm run clean && tsc -p tsconfig.build.json && node -e \"const fs=require('node:fs');const p='dist/worker/observe/static';fs.mkdirSync(p,{recursive:true});fs.cpSync('src/worker/observe/static',p,{recursive:true});\" && npm run console:build",
49
49
  "console:typecheck": "tsc -p src/worker/console/tsconfig.json",
50
50
  "console:build": "npm run console:typecheck && vite build --config src/worker/console/vite.config.ts",
51
51
  "prepack": "npm run build",
@@ -88,6 +88,5 @@
88
88
  "typescript": "^5.9.3",
89
89
  "vite": "^7.0.0",
90
90
  "vitest": "^3.2.4"
91
- },
92
- "packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319"
91
+ }
93
92
  }
@@ -24,7 +24,6 @@ references:
24
24
  ## 初始化升级路由
25
25
 
26
26
  - 写入型「**loop-agent初始化更新**」「loop-agent 初始化更新」「更新 loop-agent 初始化内容」「升级后对齐」统一运行 `loop-agent init upgrade --repo-root . --json`;处理 controller 返回的单文件 `allowedPaths`,以同一 run `--continue` 推进至终态,不停在中间状态。
27
- - 升级可能因 gitignore 迁移评估暂停:若 `.agents/` 存在已跟踪内容,需先审查是否有应团队共享的自定义内容;存在 staged 变更或 git 查询失败时需先解决 blocker,再重跑评估。建议的 `git rm -r --cached --ignore-unmatch` 只修改 index、保留工作区文件,且由用户执行而非 controller。
28
27
  - 「检查初始化更新」「初始化更新校验」「只检查,不要修改」仅运行 `loop-agent init check-update --repo-root . --markdown`,不得创建 run 或写入。
29
28
  - facts 位于 `.harness/init-upgrades/<run-id>/`;禁止业务源码和宽泛 glob。默认管理项目 `.opencode/plugins/`、`.pi/extensions/`、`.pi/settings.json`;Pi trust 后加载,默认不读写 `~/.pi/agent/settings.json`。
30
29
 
@@ -152,8 +152,6 @@ fresh init 将精确引用写到 `executors.pi.LOW/MED/HIGH`。fresh `loop-agent
152
152
 
153
153
  `init upgrade` 是写入型升级入口:首次运行冻结 controller identity、检查 npm latest、扫描 surface、自动执行安全动作,并把 run facts 持久化到 `.harness/init-upgrades/<run-id>/`。`--status` 与 `--report` 严格只读;`--continue` 会重新核验 identity、当前 hash 与不变量。版本选择、无法判定冲突、凭据、破坏性删除或 active writer 才进入 human decision。普通语义冲突返回具体单文件 `allowedPaths` merge task,主会话必须合并后继续,不能把 `needs-model-merge` 作为完成。默认管理项目级 OpenCode/Pi recovery 与 `.pi/settings.json` nested merge,保留显式 disabled,Pi trust 后才加载;默认不读写 `~/.pi/agent/settings.json`。旧 `init reconcile` 保留为兼容低层诊断。
154
154
 
155
- 升级在 managed block 收敛后生成只读 gitignore 迁移评估(`.harness/init-upgrades/<run-id>/gitignore-migration.json`):inventory 已跟踪的 `.harness/**` 与 `.agents/**`,建议 index-only 命令 `git rm -r --cached --ignore-unmatch .harness` / `.agents`(只改 index、保留工作区文件;`scripts/**` 与 `ai_workspace/loop-agent/**` 永不出现)。`.agents` 已跟踪内容会触发 human-decision 暂停等待审查;非 Git 仓库、git 查询失败或存在 staged 条目时 `status: blocked` 且无命令建议。controller 不自动修改 Git index。
156
-
157
155
  ### 查看或复制内置示例
158
156
 
159
157
  ```bash
@@ -321,7 +319,6 @@ loop-agent dag report [--run-id <run-id>] [--lifecycle active|paused|completed|a
321
319
  loop-agent dag reconcile-run --run-id <run-id> # 只读检查 effectiveStatus 与恢复/收口资格
322
320
  loop-agent dag reconcile-run --run-id <run-id> --action supersede --reason "..." # 显式保留证据并标记为任务已另行完成
323
321
  loop-agent dag reconcile-run --run-id <run-id> --action abandon --reason "..." # 显式保留证据并收口为已放弃
324
- loop-agent dag request-interrupt --run-id <run-id> --request-id <id> --target-operation-id <id> --reason-code <code> --reason <detail> [--json] # 协作中止:写入 interrupt.json(identity CAS);需配 --expected-runner-pid/--expected-runner-hostname 校验 runner 身份
325
322
  loop-agent dag rerun --run-id <run-id> --from-node <node-id> --plan [--json] # 从节点重跑资格预检(不执行)
326
323
  loop-agent dag rerun --run-id <run-id> --from-node <node-id> --plan-hash <sha256> --request-id <key> --reason "..." [--json] # 安全子图 continuation
327
324
  loop-agent dag rerun-task --run-id <run-id> --reason "..." --request-id <key> [--profile auto] [--task-id <id>] [--json] # standalone 完整任务重跑
@@ -1,6 +0,0 @@
1
- {
2
- "schemaVersion": 1,
3
- "version": "0.36.4-beta.0",
4
- "gitSha": "b4d154e6c1e109f754c059c22588cfd0298d4764",
5
- "builtAt": "2026-08-16T17:25:17.099Z"
6
- }
@@ -1,20 +0,0 @@
1
- import { DagInterruptError, executeDagRequestInterrupt, parseDagRequestInterruptArgs, } from "../workflows/dag/interrupt-request.js";
2
- export { parseDagRequestInterruptArgs, executeDagRequestInterrupt };
3
- export async function runDagRequestInterrupt(repoRoot, rawArgs) {
4
- try {
5
- const result = await executeDagRequestInterrupt(repoRoot, rawArgs);
6
- console.log(JSON.stringify(result, null, 2));
7
- }
8
- catch (error) {
9
- if (error instanceof DagInterruptError) {
10
- console.log(JSON.stringify({
11
- ok: false,
12
- code: error.code,
13
- message: error.message,
14
- }, null, 2));
15
- process.exitCode = 1;
16
- return;
17
- }
18
- throw error;
19
- }
20
- }
@@ -1,121 +0,0 @@
1
- /**
2
- * Assistant content-block helpers shared by Pi event mapping and Operator Chat UI.
3
- * Mirrors pi-web `lib/message-display.ts` (process vs answer split) without deferred fetch.
4
- */
5
- function asRecord(value) {
6
- if (!value || typeof value !== "object")
7
- return undefined;
8
- return value;
9
- }
10
- function readString(value) {
11
- return typeof value === "string" ? value : undefined;
12
- }
13
- /** Parse a persisted/SSE content array; unknown shapes are dropped. */
14
- export function parseAssistantContent(value) {
15
- if (!Array.isArray(value))
16
- return undefined;
17
- const blocks = [];
18
- for (const item of value) {
19
- const rec = asRecord(item);
20
- if (!rec)
21
- continue;
22
- const type = readString(rec.type) ?? "";
23
- if (type === "thinking" || type === "reasoning") {
24
- const thinking = readString(rec.thinking) ?? readString(rec.text) ?? "";
25
- blocks.push({ type: "thinking", thinking });
26
- continue;
27
- }
28
- if (type === "toolCall" ||
29
- type === "tool_call" ||
30
- type === "toolUse" ||
31
- type === "tool_use") {
32
- const toolCallId = readString(rec.toolCallId) ?? readString(rec.id) ?? "";
33
- if (!toolCallId)
34
- continue;
35
- const toolName = readString(rec.toolName) ?? readString(rec.name);
36
- blocks.push({
37
- type: "toolCall",
38
- toolCallId,
39
- ...(toolName ? { toolName } : {}),
40
- });
41
- continue;
42
- }
43
- if (type === "text" || type === "output_text" || type === "") {
44
- const text = readString(rec.text);
45
- if (text !== undefined)
46
- blocks.push({ type: "text", text });
47
- }
48
- }
49
- return blocks;
50
- }
51
- /**
52
- * Extract ordered assistant content blocks from a Pi SDK message object.
53
- * Thinking/reasoning blocks keep their own type so they never leak into answer text.
54
- */
55
- export function extractAssistantContentBlocks(message) {
56
- const rec = asRecord(message);
57
- if (!rec)
58
- return [];
59
- const contents = Array.isArray(rec.content) ? rec.content : [];
60
- const parts = Array.isArray(rec.parts) ? rec.parts : [];
61
- const fromArrays = parseAssistantContent([...contents, ...parts]) ?? [];
62
- if (fromArrays.length > 0)
63
- return fromArrays;
64
- const top = readString(rec.text);
65
- return top ? [{ type: "text", text: top }] : [];
66
- }
67
- /**
68
- * Pi emits message_end for user / toolResult / custom too. Only assistant
69
- * payloads belong in the Operator Chat assistant bubble (pi-web same split).
70
- */
71
- export function isAssistantSdkMessage(message) {
72
- const rec = asRecord(message);
73
- if (!rec)
74
- return false;
75
- const role = readString(rec.role);
76
- return role === undefined || role === "assistant";
77
- }
78
- /**
79
- * Latest assistant answer text (text blocks only). Thinking is excluded.
80
- * Preserves the historical `{ text }` / `{ parts: [{ text }] }` fallbacks.
81
- */
82
- export function extractAssistantText(message) {
83
- return extractAssistantContentBlocks(message)
84
- .filter((block) => block.type === "text")
85
- .map((block) => block.text)
86
- .join("");
87
- }
88
- export function isEmptyThinkingBlock(block, options = {}) {
89
- return (block.type === "thinking" &&
90
- !options.isStreaming &&
91
- block.thinking.trim() === "");
92
- }
93
- export function getDisplayableAssistantBlocks(blocks, options = {}) {
94
- return blocks.filter((block) => !isEmptyThinkingBlock(block, options));
95
- }
96
- function isFinalAnswerBlock(block) {
97
- return block.type === "text";
98
- }
99
- export function splitFinalAssistantBlocks(blocks, options = {}) {
100
- const displayable = getDisplayableAssistantBlocks(blocks, options);
101
- let lastProcessIndex = -1;
102
- for (let i = displayable.length - 1; i >= 0; i--) {
103
- if (!isFinalAnswerBlock(displayable[i])) {
104
- lastProcessIndex = i;
105
- break;
106
- }
107
- }
108
- if (lastProcessIndex === -1) {
109
- return { answerBlocks: displayable, processBlocks: [] };
110
- }
111
- return {
112
- answerBlocks: displayable.slice(lastProcessIndex + 1),
113
- processBlocks: displayable.slice(0, lastProcessIndex + 1),
114
- };
115
- }
116
- export function joinAssistantText(blocks) {
117
- return blocks
118
- .filter((block) => block.type === "text")
119
- .map((block) => block.text)
120
- .join("");
121
- }