@huseynsnmz/pi-board 0.15.3 → 0.17.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 (216) hide show
  1. package/CHANGELOG.md +24 -4
  2. package/CONTRIBUTING.md +7 -0
  3. package/README.md +55 -419
  4. package/SECURITY.md +19 -0
  5. package/docs/how-it-works.md +31 -0
  6. package/docs/reference.md +277 -0
  7. package/package.json +5 -11
  8. package/src/commands/agent-board.ts +26 -2
  9. package/src/commands/attach-flow.ts +4 -0
  10. package/src/core/double-press.mjs +6 -2
  11. package/src/core/slash-commands.mjs +52 -0
  12. package/src/index.ts +1 -1
  13. package/src/runtime/service.mjs +12 -0
  14. package/src/ui/dashboard.ts +59 -25
  15. package/src/ui/pty-attach.ts +8 -3
  16. package/IMPLEMENTATION_PLAN.md +0 -920
  17. package/PRD.md +0 -484
  18. package/PROGRESS.md +0 -142
  19. package/VERIFY.md +0 -115
  20. package/docs/BATCH_SELECTION_READ_FLOW.md +0 -277
  21. package/docs/EXPLORATION.md +0 -187
  22. package/docs/PTY_ATTACH_IMPLEMENTATION_PLAN.md +0 -581
  23. package/docs/RELEASE.md +0 -148
  24. package/docs/superpowers/plans/2026-08-15-screenlog-gc.md +0 -704
  25. package/docs/superpowers/plans/2026-08-16-attach-double-cursor-jiggle-retry.md +0 -499
  26. package/docs/superpowers/plans/2026-08-21-attach-coldstart-jiggle-rearm.md +0 -797
  27. package/docs/superpowers/plans/2026-08-21-dashboard-keypress-lag.md +0 -366
  28. package/docs/superpowers/plans/2026-08-21-issue-14-needs-input-no-auto-done.md +0 -576
  29. package/docs/superpowers/plans/2026-08-22-jiggle-shrink-and-hold.md +0 -337
  30. package/docs/superpowers/plans/2026-08-22-launch-cwd-favorites.md +0 -916
  31. package/docs/superpowers/plans/2026-08-22-question-tool-grouping.md +0 -211
  32. package/docs/superpowers/plans/2026-08-22-rename-state-labels.md +0 -182
  33. package/docs/superpowers/plans/2026-08-22-stable-list-order.md +0 -51
  34. package/docs/superpowers/plans/2026-08-27-locks-acquirelock-spin.md +0 -614
  35. package/docs/superpowers/plans/2026-08-27-pty-runner-test-flaky.md +0 -32
  36. package/docs/superpowers/plans/2026-08-29-code-refs-badges.md +0 -223
  37. package/docs/superpowers/plans/2026-08-30-circular-navigation.md +0 -308
  38. package/docs/superpowers/plans/2026-08-30-post-exit-timing-fix.md +0 -37
  39. package/docs/superpowers/plans/2026-08-30-pty-attach-quality-debt.md +0 -311
  40. package/docs/superpowers/plans/2026-08-30-readme-v2.md +0 -294
  41. package/docs/superpowers/plans/2026-09-01-attach-detach-gate-cursor-anchor.md +0 -284
  42. package/docs/superpowers/plans/2026-09-02-attach-detach-editor-state.md +0 -722
  43. package/docs/superpowers/plans/2026-09-03-code-refs-pr-backlink-narrow.md +0 -551
  44. package/docs/superpowers/plans/2026-09-03-detach-gate-glyph-fallback.md +0 -146
  45. package/docs/superpowers/plans/2026-09-04-evidence-outputpreview.md +0 -209
  46. package/docs/superpowers/plans/2026-09-04-warm-host-reclaim.md +0 -796
  47. package/docs/superpowers/plans/2026-09-05-issue-13-drainnextfollowup-pty-probe.md +0 -114
  48. package/docs/superpowers/plans/2026-09-05-issue-38-windows-wezterm-ime-cursor.md +0 -73
  49. package/docs/superpowers/plans/2026-09-05-issue-39-truncate-codepoint-boundary.md +0 -143
  50. package/docs/superpowers/plans/2026-09-05-issue-61-mention-fallback-guards.md +0 -226
  51. package/docs/superpowers/plans/2026-09-05-issue-63-flaky-manual-completion.md +0 -87
  52. package/docs/superpowers/plans/2026-09-05-issue-64-changelog-release-helper.md +0 -53
  53. package/docs/superpowers/plans/2026-09-05-pty-host-stacking-sock-race.md +0 -731
  54. package/docs/superpowers/plans/2026-09-08-attach-ctrl-left-detach.md +0 -30
  55. package/docs/superpowers/plans/2026-09-08-dashboard-shrink-repaint.md +0 -68
  56. package/docs/superpowers/plans/2026-09-08-issue-11-attach-runtime-desync-heal.md +0 -917
  57. package/docs/superpowers/plans/2026-09-08-legacy-stale-host-recovery.md +0 -125
  58. package/docs/superpowers/plans/2026-09-08-spawn-async-error-swallow.md +0 -56
  59. package/docs/superpowers/plans/2026-09-08-stale-model-attach-guard.md +0 -96
  60. package/docs/superpowers/plans/2026-09-09-claimpid-blocks-replace.md +0 -267
  61. package/docs/superpowers/plans/2026-09-09-harden-runner-architecture.md +0 -603
  62. package/docs/superpowers/plans/2026-09-09-single-writer-completion.md +0 -252
  63. package/docs/superpowers/plans/2026-09-10-reader-consistency.md +0 -115
  64. package/docs/superpowers/plans/2026-09-14-attach-cursor-dectcem-gate.md +0 -469
  65. package/docs/superpowers/plans/2026-09-14-attach-snapshot.md +0 -92
  66. package/docs/superpowers/plans/2026-09-14-host-meta-orphan-lock.md +0 -771
  67. package/docs/superpowers/plans/2026-09-14-issue-106-terminal-frame-cognition.md +0 -299
  68. package/docs/superpowers/plans/2026-09-14-issue-113-foreground-preview-race.md +0 -609
  69. package/docs/superpowers/plans/2026-09-14-terminal-model.md +0 -145
  70. package/docs/superpowers/plans/2026-09-15-coordinator-pipe-root-normalize.md +0 -224
  71. package/docs/superpowers/plans/2026-09-15-lease-publish-eprem-reclaim.md +0 -341
  72. package/docs/superpowers/plans/2026-09-18-detach-anchor-reporter-endpoint.md +0 -875
  73. package/docs/superpowers/plans/2026-09-20-control-lifecycle.md +0 -116
  74. package/docs/superpowers/plans/2026-09-20-issue-121-perf-gate-out-of-coverage.md +0 -517
  75. package/docs/superpowers/plans/2026-09-23-a5-mid-stream-assertion.md +0 -25
  76. package/docs/superpowers/plans/2026-09-23-cwd-browse-tab-drill.md +0 -393
  77. package/docs/superpowers/plans/2026-09-23-terminal-query-forwarding.md +0 -51
  78. package/docs/superpowers/plans/2026-09-23-unconditional-detach-key.md +0 -58
  79. package/docs/superpowers/plans/2026-09-24-control-reconcile-flake.md +0 -698
  80. package/docs/superpowers/plans/2026-09-24-probe-attached-clients.md +0 -605
  81. package/docs/superpowers/plans/2026-09-29-issue-145-holding-semantic-state.md +0 -1183
  82. package/docs/superpowers/plans/2026-09-29-issue-145-user-verification.md +0 -66
  83. package/docs/superpowers/plans/2026-09-30-board-delete-key-x-y-confirm.md +0 -649
  84. package/docs/superpowers/plans/2026-09-30-issue-153-runner-stop-boot-window.md +0 -618
  85. package/docs/superpowers/plans/2026-09-30-issue-95-test-discipline.md +0 -555
  86. package/docs/superpowers/plans/2026-09-30-publish-dispatch-tag-check.md +0 -259
  87. package/docs/superpowers/plans/2026-10-06-attach-settle-scheme-delivery.md +0 -751
  88. package/docs/superpowers/plans/2026-10-09-issue-167-attach-middle-paste.md +0 -509
  89. package/docs/superpowers/plans/2026-10-09-issue-169-fullscreen-mouse-ownership.md +0 -346
  90. package/docs/superpowers/plans/2026-10-10-attach-delete-in-place.md +0 -832
  91. package/docs/superpowers/plans/2026-10-10-issue-174-selection-mirror-paste-source.md +0 -510
  92. package/docs/superpowers/plans/2026-10-14-issue-170-attach-reply-guard.md +0 -771
  93. package/docs/superpowers/plans/2026-10-14-issue-178-accept-registration-race.md +0 -1257
  94. package/docs/superpowers/plans/2026-10-14-issue-184-snapshot-window-contract.md +0 -657
  95. package/docs/superpowers/plans/2026-10-14-issue-185-attach-wheel-alt-screen.md +0 -47
  96. package/docs/superpowers/plans/2026-10-14-issue-187-motionless-drag.md +0 -931
  97. package/docs/superpowers/plans/2026-10-14-issue-189-mixed-input-segments.md +0 -823
  98. package/docs/superpowers/plans/2026-10-15-issue-188-x10-mouse-release.md +0 -526
  99. package/docs/superpowers/plans/2026-10-16-issue-198-attach-wheel-forward-fallback.md +0 -32
  100. package/docs/superpowers/plans/2026-10-18-attach-wheel-replay-pseudo-scrollback.md +0 -437
  101. package/docs/superpowers/plans/2026-10-19-issue-213-reply-guard-csi-key.md +0 -257
  102. package/docs/superpowers/plans/2026-10-19-issue-214-attach-forward-alt-modifier.md +0 -202
  103. package/docs/superpowers/plans/2026-10-21-issue-221-ask-user-question.md +0 -198
  104. package/docs/superpowers/plans/2026-10-23-issue-222-attach-ready.md +0 -290
  105. package/docs/superpowers/plans/2026-10-23-issue-225-monotonic-foreground-state.md +0 -450
  106. package/docs/superpowers/plans/2026-10-23-issue-229-vim-jkl.md +0 -449
  107. package/docs/superpowers/plans/2026-10-23-issue-232-attach-bg-only-cells.md +0 -153
  108. package/docs/superpowers/plans/2026-10-23-lease-heartbeat-staleness.md +0 -537
  109. package/docs/superpowers/plans/2026-10-23-selected-row-highlight.md +0 -405
  110. package/docs/superpowers/plans/2026-10-24-issue-217-windows-pid-reuse-stopping.md +0 -367
  111. package/docs/superpowers/plans/2026-10-24-issue-230-warm-host-background-runs.md +0 -806
  112. package/docs/superpowers/plans/2026-10-24-issue-238-windows-process-identity-token.md +0 -490
  113. package/docs/superpowers/plans/2026-10-24-issue-241-coordinator-root-exit.md +0 -461
  114. package/docs/superpowers/plans/2026-10-25-issue-239-coordinator-replacement-identity.md +0 -504
  115. package/docs/superpowers/plans/2026-10-26-issue-245-key-hints-doc-sync.md +0 -244
  116. package/docs/superpowers/plans/2026-10-27-issue-172-fullscreen-selection-clear.md +0 -344
  117. package/docs/superpowers/plans/2026-10-27-issue-252-select-key-hints.md +0 -209
  118. package/docs/superpowers/plans/2026-10-28-issue-255-coordinator-endpoint-zombie.md +0 -442
  119. package/docs/superpowers/plans/2026-10-28-issue-257-legacy-pty-runner-endpoint-cleanup.md +0 -256
  120. package/docs/superpowers/plans/2026-11-03-cwd-favorites-full-pool.md +0 -266
  121. package/docs/superpowers/specs/2026-08-15-screenlog-gc-design.md +0 -105
  122. package/docs/superpowers/specs/2026-08-16-attach-double-cursor-jiggle-retry-design.md +0 -142
  123. package/docs/superpowers/specs/2026-08-21-attach-coldstart-jiggle-rearm-design.md +0 -110
  124. package/docs/superpowers/specs/2026-08-21-dashboard-keypress-lag-design.md +0 -59
  125. package/docs/superpowers/specs/2026-08-21-issue-14-needs-input-no-auto-done-design.md +0 -109
  126. package/docs/superpowers/specs/2026-08-22-cwd-favorites-design.md +0 -131
  127. package/docs/superpowers/specs/2026-08-22-jiggle-shrink-and-hold-design.md +0 -111
  128. package/docs/superpowers/specs/2026-08-22-question-tool-grouping-design.md +0 -114
  129. package/docs/superpowers/specs/2026-08-22-rename-state-labels-design.md +0 -80
  130. package/docs/superpowers/specs/2026-08-27-locks-acquirelock-spin-design.md +0 -97
  131. package/docs/superpowers/specs/2026-08-27-pty-runner-test-flaky-design.md +0 -35
  132. package/docs/superpowers/specs/2026-08-29-code-refs-badges-design.md +0 -128
  133. package/docs/superpowers/specs/2026-08-30-circular-navigation-design.md +0 -47
  134. package/docs/superpowers/specs/2026-08-30-eprm-atomicwrite-race-design.md +0 -77
  135. package/docs/superpowers/specs/2026-08-30-post-exit-timing-fix-design.md +0 -80
  136. package/docs/superpowers/specs/2026-08-30-pty-attach-quality-debt-design.md +0 -105
  137. package/docs/superpowers/specs/2026-08-30-readme-v2-design.md +0 -115
  138. package/docs/superpowers/specs/2026-09-01-attach-detach-gate-cursor-anchor-design.md +0 -78
  139. package/docs/superpowers/specs/2026-09-02-attach-detach-editor-state-design.md +0 -120
  140. package/docs/superpowers/specs/2026-09-03-code-refs-pr-backlink-narrow-design.md +0 -92
  141. package/docs/superpowers/specs/2026-09-03-detach-gate-glyph-fallback-design.md +0 -99
  142. package/docs/superpowers/specs/2026-09-04-evidence-outputpreview-design.md +0 -50
  143. package/docs/superpowers/specs/2026-09-04-warm-host-reclaim-design.md +0 -106
  144. package/docs/superpowers/specs/2026-09-05-issue-13-drainnextfollowup-pty-probe-design.md +0 -64
  145. package/docs/superpowers/specs/2026-09-05-issue-38-windows-wezterm-ime-design.md +0 -48
  146. package/docs/superpowers/specs/2026-09-05-issue-39-truncate-codepoint-boundary-design.md +0 -64
  147. package/docs/superpowers/specs/2026-09-05-issue-61-mention-fallback-design.md +0 -71
  148. package/docs/superpowers/specs/2026-09-05-issue-63-flaky-manual-completion-design.md +0 -49
  149. package/docs/superpowers/specs/2026-09-05-issue-64-changelog-helper-design.md +0 -76
  150. package/docs/superpowers/specs/2026-09-05-pty-host-stacking-sock-race-design.md +0 -510
  151. package/docs/superpowers/specs/2026-09-07-issue-11-attach-runtime-desync-heal-design.md +0 -130
  152. package/docs/superpowers/specs/2026-09-08-attach-ctrl-left-detach-design.md +0 -58
  153. package/docs/superpowers/specs/2026-09-08-dashboard-shrink-repaint-design.md +0 -52
  154. package/docs/superpowers/specs/2026-09-08-legacy-stale-host-recovery-design.md +0 -87
  155. package/docs/superpowers/specs/2026-09-08-spawn-async-error-swallow-design.md +0 -56
  156. package/docs/superpowers/specs/2026-09-08-stale-model-attach-guard-design.md +0 -79
  157. package/docs/superpowers/specs/2026-09-09-claimpid-blocks-replace-design.md +0 -147
  158. package/docs/superpowers/specs/2026-09-09-harden-runner-architecture-design.md +0 -304
  159. package/docs/superpowers/specs/2026-09-14-attach-cursor-dectcem-gate-design.md +0 -114
  160. package/docs/superpowers/specs/2026-09-14-host-meta-orphan-lock-design.md +0 -120
  161. package/docs/superpowers/specs/2026-09-14-issue-106-terminal-frame-cognition-design.md +0 -146
  162. package/docs/superpowers/specs/2026-09-14-issue-113-foreground-preview-race-design.md +0 -116
  163. package/docs/superpowers/specs/2026-09-15-coordinator-pipe-root-normalize-design.md +0 -84
  164. package/docs/superpowers/specs/2026-09-15-lease-publish-eprem-reclaim-design.md +0 -92
  165. package/docs/superpowers/specs/2026-09-18-detach-anchor-reporter-endpoint-design.md +0 -123
  166. package/docs/superpowers/specs/2026-09-20-issue-121-perf-gate-out-of-coverage-design.md +0 -204
  167. package/docs/superpowers/specs/2026-09-23-a5-mid-stream-assertion-design.md +0 -43
  168. package/docs/superpowers/specs/2026-09-23-cwd-browse-tab-drill-design.md +0 -95
  169. package/docs/superpowers/specs/2026-09-23-terminal-query-forwarding-design.md +0 -63
  170. package/docs/superpowers/specs/2026-09-23-unconditional-detach-key-design.md +0 -57
  171. package/docs/superpowers/specs/2026-09-24-control-reconcile-flake-design.md +0 -98
  172. package/docs/superpowers/specs/2026-09-24-probe-attached-clients-design.md +0 -190
  173. package/docs/superpowers/specs/2026-09-29-issue-145-holding-semantic-state-design.md +0 -394
  174. package/docs/superpowers/specs/2026-09-30-board-delete-key-x-y-confirm-design.md +0 -86
  175. package/docs/superpowers/specs/2026-09-30-issue-153-runner-stop-boot-window-design.md +0 -75
  176. package/docs/superpowers/specs/2026-09-30-issue-95-test-discipline-design.md +0 -226
  177. package/docs/superpowers/specs/2026-09-30-publish-dispatch-tag-check-design.md +0 -129
  178. package/docs/superpowers/specs/2026-10-06-attach-settle-scheme-delivery-design.md +0 -196
  179. package/docs/superpowers/specs/2026-10-09-issue-167-attach-middle-paste-design.md +0 -125
  180. package/docs/superpowers/specs/2026-10-09-issue-169-fullscreen-mouse-ownership-design.md +0 -130
  181. package/docs/superpowers/specs/2026-10-10-attach-delete-in-place-design.md +0 -224
  182. package/docs/superpowers/specs/2026-10-10-issue-174-selection-mirror-paste-source-design.md +0 -154
  183. package/docs/superpowers/specs/2026-10-14-issue-170-attach-reply-guard-design.md +0 -195
  184. package/docs/superpowers/specs/2026-10-14-issue-178-accept-registration-race-design.md +0 -287
  185. package/docs/superpowers/specs/2026-10-14-issue-184-snapshot-window-contract-design.md +0 -288
  186. package/docs/superpowers/specs/2026-10-14-issue-185-attach-wheel-alt-screen-design.md +0 -126
  187. package/docs/superpowers/specs/2026-10-14-issue-187-motionless-drag-design.md +0 -269
  188. package/docs/superpowers/specs/2026-10-14-issue-189-mixed-input-segments-design.md +0 -369
  189. package/docs/superpowers/specs/2026-10-15-issue-188-x10-mouse-release-design.md +0 -252
  190. package/docs/superpowers/specs/2026-10-16-issue-198-attach-wheel-forward-fallback-design.md +0 -67
  191. package/docs/superpowers/specs/2026-10-18-attach-wheel-replay-pseudo-scrollback-design.md +0 -250
  192. package/docs/superpowers/specs/2026-10-19-issue-213-reply-guard-csi-key-design.md +0 -165
  193. package/docs/superpowers/specs/2026-10-19-issue-214-attach-forward-alt-modifier-design.md +0 -131
  194. package/docs/superpowers/specs/2026-10-20-issue-221-ask-user-question-design.md +0 -270
  195. package/docs/superpowers/specs/2026-10-22-issue-225-monotonic-foreground-state-design.md +0 -225
  196. package/docs/superpowers/specs/2026-10-23-issue-222-attach-ready-design.md +0 -204
  197. package/docs/superpowers/specs/2026-10-23-issue-229-vim-jkl-design.md +0 -90
  198. package/docs/superpowers/specs/2026-10-23-issue-232-attach-bg-only-cells-design.md +0 -146
  199. package/docs/superpowers/specs/2026-10-23-lease-heartbeat-staleness-design.md +0 -271
  200. package/docs/superpowers/specs/2026-10-23-selected-row-highlight-design.md +0 -191
  201. package/docs/superpowers/specs/2026-10-24-issue-217-windows-pid-reuse-stopping-design.md +0 -334
  202. package/docs/superpowers/specs/2026-10-24-issue-230-warm-host-background-runs-design.md +0 -283
  203. package/docs/superpowers/specs/2026-10-24-issue-238-windows-process-identity-token-design.md +0 -286
  204. package/docs/superpowers/specs/2026-10-24-issue-241-coordinator-root-exit-design.md +0 -381
  205. package/docs/superpowers/specs/2026-10-25-issue-239-coordinator-replacement-identity-design.md +0 -331
  206. package/docs/superpowers/specs/2026-10-26-issue-245-key-hints-doc-sync-design.md +0 -72
  207. package/docs/superpowers/specs/2026-10-27-issue-172-fullscreen-selection-clear-design.md +0 -248
  208. package/docs/superpowers/specs/2026-10-27-issue-252-select-key-hints-design.md +0 -95
  209. package/docs/superpowers/specs/2026-10-28-issue-255-coordinator-endpoint-zombie-design.md +0 -380
  210. package/docs/superpowers/specs/2026-10-28-issue-257-legacy-pty-runner-endpoint-cleanup-design.md +0 -197
  211. package/docs/superpowers/specs/2026-11-03-cwd-favorites-full-pool-design.md +0 -106
  212. package/scripts/budget-audit.mjs +0 -135
  213. package/scripts/release.mjs +0 -446
  214. package/scripts/release_helper.mjs +0 -309
  215. package/scripts/run-perf-gate.mjs +0 -40
  216. package/scripts/run-tests.mjs +0 -375
@@ -1,576 +0,0 @@
1
- # Issue #14: Needs-input While Running + No Auto-Done Implementation Plan
2
-
3
- > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
-
5
- **Goal:** 运行中(alive)session 的文本提问归类 `needs_input`;auto-state 永不自动归类 `completed`(开关可回退)。
6
-
7
- **Architecture:** 纯函数级改动。`events.mjs` `reduceEvent()` 的 `message_end` 分支按 `detectNeedsInput` 结果设 semanticState;`auto-state.mjs` 内新增 `autoStateDoneDisabled(env)` 开关(`AGENT_BOARD_AUTO_STATE_NO_DONE`,默认禁用自动 done),启发式与模型分类统一降级为 `in_progress`;`applyAutoState*` 增加 completed guard 保护手动标记。
8
-
9
- **Tech Stack:** Node.js (>=20), node:test, plain .mjs modules, JSDoc typedefs(无 TypeScript 构建)。
10
-
11
- ## Global Constraints
12
-
13
- - 所有测试用 `node --test`,断言库 `node:assert/strict`(与现有 test/*.test.mjs 一致)。
14
- - 不改 UI 显示/分组/排序;不改 detached 回复路径;不改 alive guard。
15
- - 环境变量名:`AGENT_BOARD_AUTO_STATE_NO_DONE`(默认未设置 = 禁用自动 done;`0`/`false`/`off`/`no` = 恢复自动 done)。
16
- - 复用 `isOff()` 语义(`/^(0|false|off|no)$/i`)。
17
- - 所有改动在 worktree `/home/elling/git-repo/github/pi-agent-board/.pi/worktrees/issue-14-needs-input-no-auto-done` 内,禁止碰 main checkout。
18
-
19
- ---
20
-
21
- ### Task 1: 运行中文本提问 → needs_input(events.mjs)
22
-
23
- **Files:**
24
- - Modify: `src/core/events.mjs`(`reduceEvent()` 的 `message_end` 分支,约 L121-139)
25
- - Test: `test/events.test.mjs`(新增 2 用例)
26
-
27
- **Interfaces:**
28
- - Consumes: `detectNeedsInput(text)` → `{ needsInput: boolean, question: string|null }`(`src/core/heuristics.mjs` 已有,勿改)。
29
- - Produces: 运行中 `status.semanticState` 可为 `"needs_input"`;`projectViewState().needsInput` 联动(已有逻辑,勿改)。
30
-
31
- - [ ] **Step 1: 写失败测试(在 `test("message_end assistant updates preview and detects question"` 用例之后追加)**
32
-
33
- ```js
34
- test("message_end text ending with a question moves alive run to needs_input", () => {
35
- const s = createRunStatus(cfg(), 1, 1000);
36
- reduceEvent(
37
- s,
38
- { type: "message_end", message: { role: "assistant", content: [{ type: "text", text: "Should I continue with option A?" }] } },
39
- 2000,
40
- );
41
- assert.equal(s.semanticState, "needs_input");
42
- assert.match(s.question, /option A/);
43
- assert.equal(projectViewState(s, 2100).needsInput, true);
44
- });
45
-
46
- test("alive run returns to working after a following message without a question", () => {
47
- const s = createRunStatus(cfg(), 1, 1000);
48
- reduceEvent(
49
- s,
50
- { type: "message_end", message: { role: "assistant", content: [{ type: "text", text: "Which target should I use?" }] } },
51
- 2000,
52
- );
53
- assert.equal(s.semanticState, "needs_input");
54
- reduceEvent(
55
- s,
56
- { type: "message_end", message: { role: "assistant", content: [{ type: "text", text: "Proceeding with the default target." }] } },
57
- 2500,
58
- );
59
- assert.equal(s.semanticState, "working");
60
- assert.equal(s.question, null);
61
- });
62
- ```
63
-
64
- - [ ] **Step 2: 运行测试验证失败**
65
-
66
- Run: `cd /home/elling/git-repo/github/pi-agent-board/.pi/worktrees/issue-14-needs-input-no-auto-done && node --test test/events.test.mjs`
67
- Expected: 2 个新用例 FAIL(`assert.equal(s.semanticState, "needs_input")` 实际为 `"working"`)。
68
-
69
- - [ ] **Step 3: 最小实现(`src/core/events.mjs` `message_end` 分支)**
70
-
71
- 将现有:
72
-
73
- ```js
74
- if (msg?.role === "assistant") {
75
- status.turns += 1;
76
- if (msg.model && !status.model) status.model = msg.model;
77
- if (msg.stopReason) status.stopReason = msg.stopReason;
78
- if (msg.errorMessage) status.error = msg.errorMessage;
79
- else if (msg.stopReason === "stop") status.error = null;
80
- const text = assistantText(msg);
81
- if (text) {
82
- // Store the full latest text (truncated) so peek shows meaningful output;
83
- // deriveSummary() condenses it to a first sentence for the row.
84
- status.latestAssistantPreview = truncate(text, PREVIEW_MAX);
85
- const nb = detectNeedsInput(text);
86
- status.question = nb.question;
87
- }
88
- status.semanticState = "working";
89
- preservePendingQuestion(status);
90
- ```
91
-
92
- 改为:
93
-
94
- ```js
95
- if (msg?.role === "assistant") {
96
- status.turns += 1;
97
- if (msg.model && !status.model) status.model = msg.model;
98
- if (msg.stopReason) status.stopReason = msg.stopReason;
99
- if (msg.errorMessage) status.error = msg.errorMessage;
100
- else if (msg.stopReason === "stop") status.error = null;
101
- const text = assistantText(msg);
102
- let nb = { needsInput: false, question: null };
103
- if (text) {
104
- // Store the full latest text (truncated) so peek shows meaningful output;
105
- // deriveSummary() condenses it to a first sentence for the row.
106
- status.latestAssistantPreview = truncate(text, PREVIEW_MAX);
107
- nb = detectNeedsInput(text);
108
- status.question = nb.question;
109
- }
110
- status.semanticState = nb.needsInput ? "needs_input" : "working";
111
- preservePendingQuestion(status);
112
- ```
113
-
114
- 注意:`preservePendingQuestion(status)` 保持在最后一行,保证 pending question 优先语义不变。
115
-
116
- - [ ] **Step 4: 运行测试验证通过**
117
-
118
- Run: `node --test test/events.test.mjs`
119
- Expected: 全部 PASS(含既有 "interactive ask_questions waits for input" 与 "interactive questions remain visible across parallel activity until each call ends" 回归绿)。
120
-
121
- - [ ] **Step 5: Commit**
122
-
123
- ```bash
124
- cd /home/elling/git-repo/github/pi-agent-board/.pi/worktrees/issue-14-needs-input-no-auto-done
125
- git add test/events.test.mjs src/core/events.mjs
126
- git commit -m "feat: classify running text questions as needs_input (issue #14)"
127
- ```
128
-
129
- ---
130
-
131
- ### Task 2: heuristicAutoState 永不自动 done + env 开关(auto-state.mjs)
132
-
133
- **Files:**
134
- - Modify: `src/core/auto-state.mjs`(新增 `autoStateDoneDisabled()`;改 `heuristicAutoState()`)
135
- - Test: `test/auto-state.test.mjs`(更新 1 断言 + 新增 1 用例)
136
-
137
- **Interfaces:**
138
- - Produces: `export function autoStateDoneDisabled(env = process.env) → boolean`(默认 true;`AGENT_BOARD_AUTO_STATE_NO_DONE` 为 `0/false/off/no` 时返回 false)。
139
- - `heuristicAutoState(latestAssistantText, opts)` 的 `opts` 新增可选 `env`(默认 `process.env`)。既有调用点不传 env,行为自动跟随进程环境。
140
-
141
- - [ ] **Step 1: 写失败测试**
142
-
143
- 在 `test/auto-state.test.mjs` 顶部 import 行追加 `autoStateDoneDisabled`:
144
-
145
- ```js
146
- import { applyAutoStateToStatus, autoStateDoneDisabled, autoStateFromModelOrHeuristic, heuristicAutoState, parseAutoStateModelOutput } from "../src/core/auto-state.mjs";
147
- ```
148
-
149
- 将既有断言:
150
-
151
- ```js
152
- test("heuristicAutoState detects done and in-progress turns", () => {
153
- assert.equal(heuristicAutoState("Done. Fixed the bug and tests pass.").kind, "done");
154
- assert.equal(heuristicAutoState("I updated one file. Next step is to add tests.").kind, "in_progress");
155
- });
156
- ```
157
-
158
- 改为(默认不再 done):
159
-
160
- ```js
161
- test("heuristicAutoState detects done and in-progress turns", () => {
162
- assert.equal(heuristicAutoState("Done. Fixed the bug and tests pass.").kind, "in_progress");
163
- assert.equal(heuristicAutoState("I updated one file. Next step is to add tests.").kind, "in_progress");
164
- });
165
-
166
- test("heuristicAutoState restores done classification when auto-done flag is off", () => {
167
- assert.equal(
168
- heuristicAutoState("Done. Fixed the bug and tests pass.", { env: { AGENT_BOARD_AUTO_STATE_NO_DONE: "0" } }).kind,
169
- "done",
170
- );
171
- assert.equal(autoStateDoneDisabled({}), true);
172
- assert.equal(autoStateDoneDisabled({ AGENT_BOARD_AUTO_STATE_NO_DONE: "0" }), false);
173
- assert.equal(autoStateDoneDisabled({ AGENT_BOARD_AUTO_STATE_NO_DONE: "off" }), false);
174
- });
175
- ```
176
-
177
- - [ ] **Step 2: 运行测试验证失败**
178
-
179
- Run: `node --test test/auto-state.test.mjs`
180
- Expected: `heuristicAutoState detects done and in-progress turns` FAIL(实际 `"done"` 不等于 `"in_progress"`);新增用例 FAIL(`autoStateDoneDisabled` 未导出)。
181
-
182
- - [ ] **Step 3: 最小实现(`src/core/auto-state.mjs`)**
183
-
184
- 在 `autoStateModel()` 函数之后、`isOff()` 之前插入:
185
-
186
- ```js
187
- /**
188
- * Whether automatic `done` classification is disabled.
189
- * Default (env unset): disabled — completed is only ever set by the user.
190
- * Set AGENT_BOARD_AUTO_STATE_NO_DONE to 0/false/off/no to restore auto-done.
191
- * @param {NodeJS.ProcessEnv|Record<string,string|undefined>} [env]
192
- */
193
- export function autoStateDoneDisabled(env = process.env) {
194
- const raw = env.AGENT_BOARD_AUTO_STATE_NO_DONE;
195
- if (typeof raw !== "string" || !raw.trim()) return true;
196
- return !isOff(raw);
197
- }
198
- ```
199
-
200
- `heuristicAutoState` 的 done 分支(现有代码):
201
-
202
- ```js
203
- const lower = text.toLowerCase();
204
- const pending = hasPendingSignal(lower);
205
- const done = hasDoneSignal(lower);
206
- if (done && !pending) {
207
- return makeClassification("done", {
208
- source: "heuristic",
209
- confidence: hasStrongDoneSignal(lower) ? "high" : "medium",
210
- reason: "Assistant reported the work is complete",
211
- now: opts.now,
212
- lastAgentActivityAt: opts.lastAgentActivityAt ?? null,
213
- latestAssistantText: text,
214
- });
215
- }
216
- ```
217
-
218
- 改为:
219
-
220
- ```js
221
- const lower = text.toLowerCase();
222
- const pending = hasPendingSignal(lower);
223
- const done = hasDoneSignal(lower);
224
- const env = opts.env ?? process.env;
225
- if (done && !pending && !autoStateDoneDisabled(env)) {
226
- return makeClassification("done", {
227
- source: "heuristic",
228
- confidence: hasStrongDoneSignal(lower) ? "high" : "medium",
229
- reason: "Assistant reported the work is complete",
230
- now: opts.now,
231
- lastAgentActivityAt: opts.lastAgentActivityAt ?? null,
232
- latestAssistantText: text,
233
- });
234
- }
235
- if (done && !pending) {
236
- // Auto-done disabled: completion signals stay out of the completed bucket;
237
- // the user marks completed manually from the dashboard.
238
- return makeClassification("in_progress", {
239
- source: "heuristic",
240
- confidence: hasStrongDoneSignal(lower) ? "medium" : "low",
241
- reason: "Assistant reported completion but auto-done is disabled",
242
- now: opts.now,
243
- lastAgentActivityAt: opts.lastAgentActivityAt ?? null,
244
- latestAssistantText: text,
245
- });
246
- }
247
- ```
248
-
249
- 同时更新 `heuristicAutoState` 的 JSDoc opts 行:`@param {{ now?: number, lastAgentActivityAt?: number|null, env?: NodeJS.ProcessEnv|Record<string,string|undefined> }} [opts]`。
250
-
251
- - [ ] **Step 4: 运行测试验证通过**
252
-
253
- Run: `node --test test/auto-state.test.mjs`
254
- Expected: 全部 PASS。
255
-
256
- - [ ] **Step 5: Commit**
257
-
258
- ```bash
259
- git add test/auto-state.test.mjs src/core/auto-state.mjs
260
- git commit -m "feat: disable auto-done in heuristic classifier by default (issue #14)"
261
- ```
262
-
263
- ---
264
-
265
- ### Task 3: 模型输出 done 降级 + prompt 两态化(auto-state.mjs)
266
-
267
- **Files:**
268
- - Modify: `src/core/auto-state.mjs`(`parseAutoStateModelOutput()`、`buildAutoStatePrompt()`)
269
- - Test: `test/auto-state.test.mjs`(更新 1 断言 + 新增 1 用例)
270
-
271
- **Interfaces:**
272
- - `parseAutoStateModelOutput(raw, opts)` 的 `opts` 新增可选 `env`;`buildAutoStatePrompt(latestAssistantText, env = process.env)` 新增第二参数(既有调用点不传,兼容)。
273
- - 调用点(`runner/job-runner.mjs`、`runner/state-runner.mjs`)无需改动。
274
-
275
- - [ ] **Step 1: 写失败测试**
276
-
277
- 将既有断言:
278
-
279
- ```js
280
- test("parseAutoStateModelOutput normalizes model JSON", () => {
281
- const c = parseAutoStateModelOutput('{"state":"done","confidence":"high","reason":"tests passed","question":null}', {
282
- latestAssistantText: "Done. Tests passed.",
283
- lastAgentActivityAt: 42,
284
- });
285
- assert.equal(c.kind, "done");
286
- assert.equal(c.semanticState, "completed");
287
- ```
288
-
289
- 改为:
290
-
291
- ```js
292
- test("parseAutoStateModelOutput normalizes model JSON", () => {
293
- const c = parseAutoStateModelOutput('{"state":"done","confidence":"high","reason":"tests passed","question":null}', {
294
- latestAssistantText: "Done. Tests passed.",
295
- lastAgentActivityAt: 42,
296
- });
297
- assert.equal(c.kind, "in_progress");
298
- assert.equal(c.semanticState, "idle");
299
- assert.match(c.reason, /auto-done is disabled/i);
300
- ```
301
-
302
- (其余 `source/confidence/lastAgentActivityAt` 断言保留。)
303
-
304
- 在文件末尾追加:
305
-
306
- ```js
307
- test("parseAutoStateModelOutput keeps done when auto-done flag is off", () => {
308
- const c = parseAutoStateModelOutput('{"state":"done","confidence":"high","reason":"tests passed","question":null}', {
309
- latestAssistantText: "Done. Tests passed.",
310
- lastAgentActivityAt: 42,
311
- env: { AGENT_BOARD_AUTO_STATE_NO_DONE: "0" },
312
- });
313
- assert.equal(c.kind, "done");
314
- assert.equal(c.semanticState, "completed");
315
- });
316
-
317
- test("buildAutoStatePrompt omits done option by default and restores it when flag off", () => {
318
- assert.ok(!/^- done:/m.test(buildAutoStatePrompt("Fix the bug.")));
319
- assert.ok(/^- done:/m.test(buildAutoStatePrompt("Fix the bug.", { AGENT_BOARD_AUTO_STATE_NO_DONE: "0" })));
320
- });
321
- ```
322
-
323
- (import 行追加 `buildAutoStatePrompt`。)
324
-
325
- - [ ] **Step 2: 运行测试验证失败**
326
-
327
- Run: `node --test test/auto-state.test.mjs`
328
- Expected: 3 个用例 FAIL(kind 为 `"done"` 而非 `"in_progress"`;prompt 仍含 done 行)。
329
-
330
- - [ ] **Step 3: 最小实现**
331
-
332
- `buildAutoStatePrompt` 现有实现:
333
-
334
- ```js
335
- export function buildAutoStatePrompt(latestAssistantText) {
336
- const text = truncate(String(latestAssistantText || "").trim(), 6000);
337
- return `Classify the LAST assistant response for a coding-agent dashboard.\n\nChoose exactly one state:\n- needs_input: the assistant asks the user for a decision, clarification, approval, credentials, or is blocked waiting for the user.\n- in_progress: work is partial, next steps remain, verification is pending/failed, or the assistant says it will continue later.\n- done: the requested work is complete, final answer given, no user input required.\n\nReturn ONLY minified JSON with this shape:\n{"state":"needs_input|in_progress|done","confidence":"high|medium|low","reason":"short reason <=18 words","question":"user-facing question or null"}\n\nLast assistant response:\n${text}`;
338
- }
339
- ```
340
-
341
- 改为:
342
-
343
- ```js
344
- export function buildAutoStatePrompt(latestAssistantText, env = process.env) {
345
- const text = truncate(String(latestAssistantText || "").trim(), 6000);
346
- const doneLine = autoStateDoneDisabled(env)
347
- ? ""
348
- : "- done: the requested work is complete, final answer given, no user input required.\n";
349
- const doneNote = autoStateDoneDisabled(env)
350
- ? "The user marks completed manually in the dashboard, so completion signals (done/completed/finished) must be classified as in_progress.\n"
351
- : "";
352
- const states = autoStateDoneDisabled(env) ? "needs_input|in_progress" : "needs_input|in_progress|done";
353
- return `Classify the LAST assistant response for a coding-agent dashboard.\n\nChoose exactly one state:\n- needs_input: the assistant asks the user for a decision, clarification, approval, credentials, or is blocked waiting for the user.\n- in_progress: work is partial, next steps remain, verification is pending/failed, or the assistant says it will continue later.\n${doneLine}${doneNote}\nReturn ONLY minified JSON with this shape:\n{"state":"${states}","confidence":"high|medium|low","reason":"short reason <=18 words","question":"user-facing question or null"}\n\nLast assistant response:\n${text}`;
354
- }
355
- ```
356
-
357
- `parseAutoStateModelOutput` 现有代码:
358
-
359
- ```js
360
- const obj = extractJsonObject(raw);
361
- if (!obj) return null;
362
- const kind = normalizeKind(obj.state ?? obj.kind ?? obj.status);
363
- if (!kind) return null;
364
- ```
365
-
366
- 改为:
367
-
368
- ```js
369
- const obj = extractJsonObject(raw);
370
- if (!obj) return null;
371
- let kind = normalizeKind(obj.state ?? obj.kind ?? obj.status);
372
- if (!kind) return null;
373
- if (kind === "done" && autoStateDoneDisabled(opts.env ?? process.env)) {
374
- kind = "in_progress";
375
- }
376
- ```
377
-
378
- 并在 `makeClassification(kind, {...})` 的调用中把 reason 兜底交给 `defaultReason(kind)`(已有逻辑),另在 opts 里透传降级提示:把
379
-
380
- ```js
381
- return makeClassification(kind, {
382
- source: "model",
383
- confidence,
384
- reason: cleanReason(obj.reason) || defaultReason(kind),
385
- ```
386
-
387
- 改为:
388
-
389
- ```js
390
- return makeClassification(kind, {
391
- source: "model",
392
- confidence,
393
- reason: kind === "in_progress" && autoStateDoneDisabled(opts.env ?? process.env)
394
- ? "Model reported done but auto-done is disabled"
395
- : cleanReason(obj.reason) || defaultReason(kind),
396
- ```
397
-
398
- 并更新 `parseAutoStateModelOutput` 的 JSDoc:`opts` 增加 `env?: NodeJS.ProcessEnv|Record<string,string|undefined>`。
399
-
400
- - [ ] **Step 4: 运行测试验证通过**
401
-
402
- Run: `node --test test/auto-state.test.mjs`
403
- Expected: 全部 PASS。
404
-
405
- - [ ] **Step 5: Commit**
406
-
407
- ```bash
408
- git add test/auto-state.test.mjs src/core/auto-state.mjs
409
- git commit -m "feat: downgrade model done output and two-state prompt when auto-done disabled (issue #14)"
410
- ```
411
-
412
- ---
413
-
414
- ### Task 4: applyAutoState* completed guard(保护手动标记)
415
-
416
- **Files:**
417
- - Modify: `src/core/auto-state.mjs`(`applyAutoStateToStatus()`、`applyAutoStateToViewState()`)
418
- - Test: `test/auto-state.test.mjs`(新增 1 用例)
419
-
420
- **Interfaces:**
421
- - 不变更签名。行为:`semanticState === "completed"` 时直接 `return false`(与 failed/stopped 同列)。
422
-
423
- - [ ] **Step 1: 写失败测试**
424
-
425
- 追加:
426
-
427
- ```js
428
- test("applyAutoStateToStatus never overwrites a manually completed row", () => {
429
- const status = {
430
- processState: "exited",
431
- semanticState: "completed",
432
- currentTool: null,
433
- question: null,
434
- error: null,
435
- latestAssistantPreview: "Done. Fixed the bug and tests pass.",
436
- summary: "Done.",
437
- };
438
- const changed = applyAutoStateToStatus(status, heuristicAutoState(status.latestAssistantPreview), 100);
439
- assert.equal(changed, false);
440
- assert.equal(status.semanticState, "completed");
441
- assert.equal(status.autoState, undefined);
442
- });
443
- ```
444
-
445
- - [ ] **Step 2: 运行测试验证失败**
446
-
447
- Run: `node --test test/auto-state.test.mjs`
448
- Expected: 新用例 FAIL(`changed` 为 `true`,semanticState 被改为 `"idle"`)。
449
-
450
- - [ ] **Step 3: 最小实现**
451
-
452
- `applyAutoStateToStatus` 的 guard 行:
453
-
454
- ```js
455
- if (!classification || status.processState === "alive") return false;
456
- if (status.semanticState === "failed" || status.semanticState === "stopped") return false;
457
- ```
458
-
459
- 改为:
460
-
461
- ```js
462
- if (!classification || status.processState === "alive") return false;
463
- if (status.semanticState === "failed" || status.semanticState === "stopped" || status.semanticState === "completed") return false;
464
- ```
465
-
466
- `applyAutoStateToViewState` 的 guard 行做同样修改(`failed`/`stopped` 之后追加 `|| state.semanticState === "completed"`)。
467
-
468
- - [ ] **Step 4: 运行测试验证通过**
469
-
470
- Run: `node --test test/auto-state.test.mjs`
471
- Expected: 全部 PASS。
472
-
473
- - [ ] **Step 5: Commit**
474
-
475
- ```bash
476
- git add test/auto-state.test.mjs src/core/auto-state.mjs
477
- git commit -m "fix: never overwrite manual completed state in auto-state (issue #14)"
478
- ```
479
-
480
- ---
481
-
482
- ### Task 5: 集成测试同步 + 全量验证 + 收尾 commit
483
-
484
- **Files:**
485
- - Modify: `test/runner.integration.test.mjs`(L45-80、L114-126 两处 completed 断言)
486
- - Test: 同文件新增 1 用例(默认无自动 done)
487
-
488
- **Interfaces:**
489
- - fake worker 由 `process.env.FAKE_PI_MODE = "completed"` 驱动;job-runner 子进程继承父进程 env,所以 `AGENT_BOARD_AUTO_STATE_NO_DONE` 在 spawn 前设置即可生效。
490
-
491
- - [ ] **Step 1: 更新既有断言(两处)**
492
-
493
- `test("runner auto-classifies a completed fake worker and writes durable artifacts"` 用例(L45-80)的 env 设置块:
494
-
495
- ```js
496
- const root = mkdtempSync(join(tmpdir(), "agentview-run-"));
497
- const env = { ...process.env };
498
- process.env.FAKE_PI_MODE = "completed";
499
- process.env.AGENT_BOARD_SUMMARY_MODEL = "off";
500
- ```
501
-
502
- 改为:
503
-
504
- ```js
505
- const root = mkdtempSync(join(tmpdir(), "agentview-run-"));
506
- const env = { ...process.env };
507
- process.env.FAKE_PI_MODE = "completed";
508
- process.env.AGENT_BOARD_SUMMARY_MODEL = "off";
509
- process.env.AGENT_BOARD_AUTO_STATE_NO_DONE = "0";
510
- ```
511
-
512
- 其 finally 块在 `delete process.env.AGENT_BOARD_SUMMARY_MODEL;` 之后追加:
513
-
514
- ```js
515
- delete process.env.AGENT_BOARD_AUTO_STATE_NO_DONE;
516
- ```
517
-
518
- `test("runner protects dash-prefixed prompts passed via argv"` 用例(L114-126)同样:`process.env.AGENT_BOARD_SUMMARY_MODEL = "off";` 之后追加 `process.env.AGENT_BOARD_AUTO_STATE_NO_DONE = "0";`,finally 块同步 delete。
519
-
520
- - [ ] **Step 2: 新增默认行为用例(在 "runner protects dash-prefixed prompts" 用例之后追加)**
521
-
522
- ```js
523
- test("runner keeps a completed fake worker idle when auto-done is disabled", { timeout: 20000 }, async () => {
524
- const root = mkdtempSync(join(tmpdir(), "agentview-run-nodone-"));
525
- process.env.FAKE_PI_MODE = "completed";
526
- process.env.AGENT_BOARD_SUMMARY_MODEL = "off";
527
- delete process.env.AGENT_BOARD_AUTO_STATE_NO_DONE;
528
- try {
529
- const meta = createView(root, { id: "view_1", name: "fix", cwd: root });
530
- const config = makeConfig(root, "view_1", "run_1", meta.sessionFile, root, "fix the bug");
531
- const st = readState(root, "view_1");
532
- st.currentRunId = "run_1";
533
- const { writeState } = await import("../src/core/store.mjs");
534
- writeState(root, st);
535
- const { pid } = launchRun(root, config, { runnerScript: RUNNER });
536
- assert.ok(pid && pid > 0, "runner spawned");
537
- const status = await waitFor(() => {
538
- const s = readStatus(root, "view_1", "run_1");
539
- return s && s.endedAt ? s : null;
540
- });
541
- assert.ok(status, "status reached terminal state");
542
- assert.equal(status.semanticState, "idle");
543
- assert.equal(status.processState, "exited");
544
- assert.equal(status.autoState?.kind, "in_progress");
545
- } finally {
546
- delete process.env.FAKE_PI_MODE;
547
- delete process.env.AGENT_BOARD_SUMMARY_MODEL;
548
- rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 50 });
549
- }
550
- });
551
- ```
552
-
553
- - [ ] **Step 3: 运行集成测试**
554
-
555
- Run: `node --test test/runner.integration.test.mjs`
556
- Expected: 全部 PASS。若个别用例因 pre-existing flaky(并行全量偶发)失败,单文件重跑确认。
557
-
558
- - [ ] **Step 4: 全量验证**
559
-
560
- Run: `npm run verify`(= typecheck + test + pack:dry)
561
- Expected: 全绿。
562
-
563
- - [ ] **Step 5: Commit**
564
-
565
- ```bash
566
- git add test/runner.integration.test.mjs
567
- git commit -m "test: keep auto-done off by default in runner integration (issue #14)"
568
- ```
569
-
570
- ---
571
-
572
- ## Self-Review(对照 spec)
573
-
574
- 1. **Spec coverage**:变更 1(events.mjs)→ Task 1;变更 2 启发式 → Task 2;模型降级+prompt → Task 3;completed guard → Task 4;测试同步+全量验证 → Task 5;开关回退 → Task 2/3 测试均有 env-off 断言。✅
575
- 2. **Placeholder scan**:已把 Task 5 的省略注释落实为具体代码(Step 1/2 完整代码块)。其余任务无 TBD/TODO/省略。✅
576
- 3. **Type consistency**:`autoStateDoneDisabled(env)` 在各任务签名一致;`heuristicAutoState` opts.env、`parseAutoStateModelOutput` opts.env、`buildAutoStatePrompt(text, env)` 一致。✅