work-ally 0.2.0-alpha.1

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 (172) hide show
  1. package/AGENTS.md +110 -0
  2. package/DASHBOARD.md +160 -0
  3. package/PRODUCT.md +113 -0
  4. package/README.md +403 -0
  5. package/ally.sh +171 -0
  6. package/bridge/src/approval-rules.ts +360 -0
  7. package/bridge/src/channel-delivery.ts +207 -0
  8. package/bridge/src/channel-types.ts +22 -0
  9. package/bridge/src/channels/fake/adapter.ts +31 -0
  10. package/bridge/src/channels/feishu/adapter.ts +411 -0
  11. package/bridge/src/channels/feishu/approvals.ts +6 -0
  12. package/bridge/src/channels/feishu/formatter.ts +276 -0
  13. package/bridge/src/channels/feishu/normalize.ts +368 -0
  14. package/bridge/src/codex-config.ts +52 -0
  15. package/bridge/src/config.ts +240 -0
  16. package/bridge/src/fake-runtime-client.ts +505 -0
  17. package/bridge/src/handoff-service.ts +494 -0
  18. package/bridge/src/logger.ts +194 -0
  19. package/bridge/src/memory-digest.ts +186 -0
  20. package/bridge/src/receiver-approval-autonomy.ts +158 -0
  21. package/bridge/src/receiver-control-core.ts +140 -0
  22. package/bridge/src/receiver-control-work-session.ts +218 -0
  23. package/bridge/src/receiver-control.ts +83 -0
  24. package/bridge/src/receiver-delivery.ts +136 -0
  25. package/bridge/src/receiver-helpers.ts +96 -0
  26. package/bridge/src/receiver-human-gate.ts +333 -0
  27. package/bridge/src/receiver-inbound-preflight.ts +162 -0
  28. package/bridge/src/receiver-recovery.ts +236 -0
  29. package/bridge/src/receiver-runtime-callbacks.ts +367 -0
  30. package/bridge/src/receiver-runtime-policy.ts +132 -0
  31. package/bridge/src/receiver-runtime-state.ts +124 -0
  32. package/bridge/src/receiver-support-actions.ts +189 -0
  33. package/bridge/src/receiver-thread-start.ts +57 -0
  34. package/bridge/src/receiver-turn-coordination.ts +94 -0
  35. package/bridge/src/receiver-turn-execution.ts +257 -0
  36. package/bridge/src/receiver-turn-failure.ts +143 -0
  37. package/bridge/src/receiver-turn-result.ts +185 -0
  38. package/bridge/src/receiver-turn-steer.ts +70 -0
  39. package/bridge/src/receiver-work-session.ts +76 -0
  40. package/bridge/src/receiver.ts +329 -0
  41. package/bridge/src/router.ts +62 -0
  42. package/bridge/src/runtime-client-agent-messages.ts +150 -0
  43. package/bridge/src/runtime-client-message-dispatch.ts +176 -0
  44. package/bridge/src/runtime-client-protocol.ts +411 -0
  45. package/bridge/src/runtime-client-request-ops.ts +56 -0
  46. package/bridge/src/runtime-client-run-turn.ts +158 -0
  47. package/bridge/src/runtime-client-thread-ops.ts +270 -0
  48. package/bridge/src/runtime-client-transport.ts +309 -0
  49. package/bridge/src/runtime-client-turn-poll.ts +224 -0
  50. package/bridge/src/runtime-client-turn-read.ts +185 -0
  51. package/bridge/src/runtime-client-turn-state.ts +105 -0
  52. package/bridge/src/runtime-client.ts +344 -0
  53. package/bridge/src/runtime-user-input.ts +403 -0
  54. package/bridge/src/scheduler.ts +239 -0
  55. package/bridge/src/server-handoff-command.ts +364 -0
  56. package/bridge/src/server-main.ts +80 -0
  57. package/bridge/src/server-routine-command.ts +60 -0
  58. package/bridge/src/server-routine-execution.ts +222 -0
  59. package/bridge/src/server-runtime-app-support.ts +107 -0
  60. package/bridge/src/server-runtime-app.ts +238 -0
  61. package/bridge/src/server-thread-sync-command.ts +63 -0
  62. package/bridge/src/server.ts +17 -0
  63. package/bridge/src/session-store-delivery.ts +220 -0
  64. package/bridge/src/session-store-human-gate.ts +380 -0
  65. package/bridge/src/session-store-inbound-acceptance.ts +66 -0
  66. package/bridge/src/session-store-meta.ts +134 -0
  67. package/bridge/src/session-store-turn-ledger.ts +272 -0
  68. package/bridge/src/session-store.ts +380 -0
  69. package/bridge/src/system-notify.ts +220 -0
  70. package/bridge/src/thread-sync.ts +200 -0
  71. package/bridge/src/translator.ts +494 -0
  72. package/bridge/src/types.ts +289 -0
  73. package/bridge/src/utils.ts +104 -0
  74. package/bridge/src/work-session-store.ts +471 -0
  75. package/docs/.gitkeep +0 -0
  76. package/docs/architecture/codex-feishu-bridge-proposal.md +2742 -0
  77. package/docs/completed/FEATURE-feishu-markdown-and-reply-support.md +327 -0
  78. package/docs/completed/README.md +21 -0
  79. package/docs/completed/SPEC-approval-autonomy-and-safe-defaults.md +205 -0
  80. package/docs/completed/SPEC-approval-batch-and-strict-reply-shortcuts.md +153 -0
  81. package/docs/completed/SPEC-conversation-noise-reduction-and-busy-input-gate.md +538 -0
  82. package/docs/completed/SPEC-engineering-sop-skillization.md +190 -0
  83. package/docs/completed/SPEC-faithful-bridge-core-thinning-v2.md +376 -0
  84. package/docs/completed/SPEC-faithful-bridge-core-thinning.md +1071 -0
  85. package/docs/completed/SPEC-group-chat-sender-identity.md +301 -0
  86. package/docs/completed/SPEC-middleware-exception-visibility.md +227 -0
  87. package/docs/completed/SPEC-nightly-memory-digest-visibility.md +121 -0
  88. package/docs/completed/SPEC-project-group-chat-human-centered-conversation-mapping.md +326 -0
  89. package/docs/completed/SPEC-remove-cli-persona-bootstrap.md +201 -0
  90. package/docs/developer-workflow.md +49 -0
  91. package/docs/implementation/SPEC-codex-same-machine-session-handoff-implementation.md +239 -0
  92. package/docs/implementation/test-coverage-map.md +363 -0
  93. package/docs/implementation/work-ally-implementation-guide.md +790 -0
  94. package/docs/issues/README.md +10 -0
  95. package/docs/issues/pending/ANALYSIS-ally-premature-recovery-notice-and-task-state-semantics-2026-03-18.md +295 -0
  96. package/docs/issues/resolved/ANALYSIS-approval-waiting-visible-but-approval-artifact-missing-2026-03-16.md +466 -0
  97. package/docs/issues/resolved/ANALYSIS-blocking-state-visible-without-user-actionable-artifact-2026-03-16.md +261 -0
  98. package/docs/issues/resolved/ANALYSIS-codex-app-server-transport-disconnect-semantics-2026-03-14.md +606 -0
  99. package/docs/issues/resolved/ANALYSIS-premature-terminalization-on-fresh-thread-poll-and-object-error-leak-2026-03-16.md +348 -0
  100. package/docs/issues/resolved/ANALYSIS-runtime-turn-delivery-and-recovery-2026-03-14.md +603 -0
  101. package/docs/issues/resolved/ANALYSIS-self-test-gap-approval-waiting-visible-but-approval-artifact-missing-2026-03-16.md +166 -0
  102. package/docs/issues/resolved/ANALYSIS-self-test-gap-blocking-state-visible-without-user-actionable-artifact-2026-03-16.md +186 -0
  103. package/docs/issues/resolved/ANALYSIS-self-test-gap-premature-terminalization-on-fresh-thread-poll-and-object-error-leak-2026-03-16.md +166 -0
  104. package/docs/issues/resolved/REPORT-ally-runtime-turn-delivery-3b42fb8-2026-03-15.md +373 -0
  105. package/docs/manual-acceptance.md +127 -0
  106. package/docs/ops-runbook.md +44 -0
  107. package/docs/planning/FEATURE-memory-system.md +748 -0
  108. package/docs/planning/SPEC-active-turn-steer-and-context-compaction-visibility.md +269 -0
  109. package/docs/planning/SPEC-approval-rules-inheritance-and-local-validation-lane.md +450 -0
  110. package/docs/planning/SPEC-assistant-persona-bootstrap.md +199 -0
  111. package/docs/planning/SPEC-assistant-rename.md +610 -0
  112. package/docs/planning/SPEC-bridge-app-server-protocol-alignment.md +667 -0
  113. package/docs/planning/SPEC-claude-runtime-host-for-work-ally.md +434 -0
  114. package/docs/planning/SPEC-cli-feishu-codex-session-unification.md +236 -0
  115. package/docs/planning/SPEC-codex-same-machine-session-handoff.md +873 -0
  116. package/docs/planning/SPEC-feishu-reaction-shortcuts.md +282 -0
  117. package/docs/planning/SPEC-local-stable-release-boundary.md +166 -0
  118. package/docs/planning/SPEC-managed-thread-entry-and-surface-mobility.md +862 -0
  119. package/docs/planning/SPEC-minimal-bridge-semantics-and-user-visible-surface.md +362 -0
  120. package/docs/planning/SPEC-npm-alpha-distribution-and-install-first-release.md +222 -0
  121. package/docs/planning/SPEC-remove-websocket-runtime-transport.md +364 -0
  122. package/docs/planning/SPEC-runtime-abstraction-phase-1.md +424 -0
  123. package/docs/planning/SPEC-runtime-connection-and-turn-recovery-semantics.md +274 -0
  124. package/docs/planning/SPEC-session-presence-and-state-visibility.md +397 -0
  125. package/docs/planning/SPEC-skill-first-capability-packaging.md +338 -0
  126. package/docs/planning/SPEC-stable-archive-contract.md +456 -0
  127. package/docs/planning/SPEC-supervised-start-boundary.md +127 -0
  128. package/docs/planning/SPEC-user-barrier-reduction-and-activation.md +832 -0
  129. package/docs/planning/ally-next.md +1278 -0
  130. package/docs/planning/assistant-workbench-spec.md +725 -0
  131. package/docs/planning/product-workbench.md +283 -0
  132. package/docs/product-onboarding.md +227 -0
  133. package/docs/product-spec-standard.md +528 -0
  134. package/docs/troubleshooting.md +45 -0
  135. package/docs/user-quickstart.md +46 -0
  136. package/internal/dispatch.sh +95 -0
  137. package/internal/lib/common.sh +1450 -0
  138. package/internal/modules/assistant/manage.sh +1312 -0
  139. package/internal/modules/bootstrap/setup.sh +144 -0
  140. package/internal/modules/config/init-env.sh +10 -0
  141. package/internal/modules/global/manage.sh +154 -0
  142. package/internal/modules/handoff/manage.sh +54 -0
  143. package/internal/modules/mcp/manage.sh +83 -0
  144. package/internal/modules/ops/logs.sh +76 -0
  145. package/internal/modules/routines/manage.sh +55 -0
  146. package/internal/modules/runtime/assistant-autosave.sh +26 -0
  147. package/internal/modules/runtime/restart.sh +6 -0
  148. package/internal/modules/runtime/start.sh +283 -0
  149. package/internal/modules/runtime/status.sh +194 -0
  150. package/internal/modules/runtime/stop.sh +55 -0
  151. package/internal/modules/runtime/supervisor.sh +216 -0
  152. package/internal/modules/runtime/update.sh +26 -0
  153. package/package.json +41 -0
  154. package/runtime/config/.gitkeep +0 -0
  155. package/runtime/host/.gitkeep +0 -0
  156. package/runtime/host/healthcheck-codex-app-server.ts +22 -0
  157. package/runtime/host/ping-pong-codex-app-server.ts +66 -0
  158. package/runtime/host/probe-codex-app-server.ts +115 -0
  159. package/skills/archive-reader/SKILL.md +9 -0
  160. package/skills/feishu-production-debug/SKILL.md +37 -0
  161. package/skills/feishu-production-debug/references/feishu-debug-order.md +49 -0
  162. package/skills/feishu-production-debug/references/platform-permission-baseline.md +23 -0
  163. package/skills/issue-to-spec-triage/SKILL.md +44 -0
  164. package/skills/issue-to-spec-triage/references/triage-rules.md +66 -0
  165. package/skills/memory-digest/SKILL.md +9 -0
  166. package/skills/post-implementation-closure/SKILL.md +39 -0
  167. package/skills/post-implementation-closure/references/closure-checklist.md +45 -0
  168. package/skills/post-implementation-closure/references/doc-drift-map.md +49 -0
  169. package/skills/product-spec/SKILL.md +244 -0
  170. package/templates/env.example +5 -0
  171. package/templates/routines/nightly-memory-digest.yaml +10 -0
  172. package/templates/workspace/AGENTS.md +26 -0
@@ -0,0 +1,261 @@
1
+ # 分析报告:阻塞态已对用户可见,但用户可操作实体缺失
2
+
3
+ 更新时间:2026-03-16
4
+ 状态:已修复并补门禁(2026-03-17)
5
+ 作者:Codex
6
+
7
+ ## 1. 这份报告回答什么
8
+
9
+ 这份报告不是只看某一条具体审批或某一次具体 user input 漏发,而是把最近两类真实事故收成同一个上位问题:
10
+
11
+ > bridge 已经对用户宣告“当前轮进入阻塞态”,但用户实际上没有拿到可操作的阻塞实体;随后 bridge 又继续把用户后续消息拦下来,导致会话被错误挂起。
12
+
13
+ 这份文档要回答的是:
14
+
15
+ 1. 这是不是同一个问题家族。
16
+ 2. 它和单点审批 bug 的关系是什么。
17
+ 3. 它到底暴露的是实现漏洞,还是状态机设计问题。
18
+ 4. 后续修复应该围绕什么硬原则展开。
19
+ 5. 需要补哪些专项测试门禁。
20
+
21
+ ## 2. 结论先说
22
+
23
+ 结论很明确:
24
+
25
+ - `waitingOnApproval` 缺审批卡
26
+ - `waitingOnUserInput` 缺问题实体
27
+ - MCP 纯读取应默认自动放行,但在真实链路中仍进入了 `waitingOnUserInput`
28
+
29
+ 这三件事,本质上是同一个上位问题:
30
+
31
+ > **bridge 把 runtime thread 的 waiting flag 误当成了“用户已经拿到可操作实体”的充分条件。**
32
+
33
+ 这会造成同一种坏结果:
34
+
35
+ 1. 用户先看到“等你审批”或“等你回复”。
36
+ 2. 但前台没有审批卡、没有问题内容、也没有可执行句柄。
37
+ 3. 用户继续发自然语言时,bridge 不再转给 Codex,而是本地拦截。
38
+ 4. 用户会感知为“中间层把事情吞了”。
39
+
40
+ ## 3. 两个现场案例
41
+
42
+ ## 3.1 案例 A:Ally 的审批阻塞
43
+
44
+ 相关材料:
45
+
46
+ - `docs/issues/resolved/ANALYSIS-approval-waiting-visible-but-approval-artifact-missing-2026-03-16.md`
47
+ - archive:`/Users/allenfeng/.work-ally/assistants/Ally/.system/archive/2026/03/16/feishu--oc_1890ff7f9132a7d90b09765f27ff5bc8.ndjson`
48
+ - timeline:`/Users/allenfeng/.work-ally/assistants/Ally/.system/logs/timeline-2026-03-16.log`
49
+
50
+ 已确认事实:
51
+
52
+ 1. runtime thread 进入了 `waitingOnApproval`。
53
+ 2. bridge 向用户发了:`当前已暂停,等待你审批后继续。`
54
+ 3. 但前台没有看到任何审批卡,也没有审批编号。
55
+ 4. 用户后续发 `进展如何?`、`同意`,都被 bridge 拦截,没有转给 Codex。
56
+ 5. 当前审批解析逻辑要求审批卡上下文或显式 `/approve <id>`;本次场景两者都不存在。
57
+
58
+ 该案例已经可以单独定义为:
59
+
60
+ > 用户可见“等待审批”,但审批实体缺失。
61
+
62
+ ## 3.2 案例 B:TiRTC-Copilot 的用户输入阻塞
63
+
64
+ 相关材料:
65
+
66
+ - archive:`/Users/allenfeng/.work-ally/assistants/TiRTC-Copilot/.system/archive/2026/03/16/feishu--oc_069d4ac4263d1a869e05ae86f095376a.ndjson`
67
+ - bridge log:`/Users/allenfeng/.work-ally/assistants/TiRTC-Copilot/.system/logs/bridge-2026-03-16.log`
68
+ - session meta:`/Users/allenfeng/.work-ally/assistants/TiRTC-Copilot/.system/runtime/sessions/feishu--oc_069d4ac4263d1a869e05ae86f095376a/meta.json`
69
+
70
+ 已确认事实:
71
+
72
+ 1. `2026-03-16T14:22:11Z` 左右,runtime thread 进入 `waitingOnUserInput`。
73
+ 2. bridge 向用户发了:`当前已暂停,等待你回复后继续。`
74
+ 3. 但 archive 里没有对应的 `user_input_requested` 可见实体,也没有任何真正的问题内容。
75
+ 4. session meta 中 `pendingUserInputRequestId` 仍为 `null`,说明 bridge 自己也没有拿到稳定的用户输入请求对象。
76
+ 5. 用户后续发 `继续`、`同意`,都被 bridge 按 `waiting_user_follow_up_intercepted` 拦截,没有转给 Codex。
77
+
78
+ 该案例可以定义为:
79
+
80
+ > 用户可见“等待补充信息”,但用户输入实体缺失。
81
+
82
+ ## 4. 关于 MCP 纯读取默认审批的额外判断
83
+
84
+ 从产品意图和现有实现口径看:
85
+
86
+ - Feishu MCP 的纯读取,本来应当默认自动放行;
87
+ - 现有代码里,MCP tool approval / elicitation 确实存在 auto-resolve 逻辑;
88
+ - 因此正常情况下,这类读取不应把用户卡在等待人工输入或等待人工审批。
89
+
90
+ 但 TiRTC-Copilot 的真实现场表明:
91
+
92
+ 1. 这次仍然进入了 `waitingOnUserInput`;
93
+ 2. 同时没有用户可见输入实体;
94
+ 3. 也没有自动放行结果稳定落地。
95
+
96
+ 所以当前可以得出的工程判断是:
97
+
98
+ > **MCP 默认自动放行这条产品承诺,并没有在所有真实运行态里被稳定兑现。**
99
+
100
+ 这不一定说明规则表完全错误,但至少说明:
101
+
102
+ - 要么 runtime 发出的 user input / elicitation 结构没有被当前 auto-resolve 逻辑识别;
103
+ - 要么这条 user input 实体在 `runtime-client -> receiver` 链路中漏接了;
104
+ - 要么 auto-resolve 生效前,bridge 已经先根据 waiting flag 把会话切进阻塞态。
105
+
106
+ 无论是哪一种,都属于中间层要修的问题,而不是用户侧的问题。
107
+
108
+ ## 5. 统一问题定义
109
+
110
+ 把两个案例并起来,这类问题的统一定义应该是:
111
+
112
+ > **bridge 目前把 runtime waiting flag 当成了“用户已具备下一步操作条件”的事实,但没有强制要求对应的用户可操作实体已经成功到达前台。**
113
+
114
+ 这里的“用户可操作实体”包括但不限于:
115
+
116
+ - 审批卡
117
+ - 审批编号
118
+ - user input 问题内容
119
+ - elicitation 表单 / schema 问题
120
+ - 被 auto-resolve 后的明确收口结果
121
+
122
+ 只要这些实体缺失,bridge 就不应把用户侧会话切进真正的 `waiting_user` 阻塞态。
123
+
124
+ ## 6. 根因分析
125
+
126
+ ### 6.1 第一层根因:阻塞态判定依据过早
127
+
128
+ 当前实现看到:
129
+
130
+ - `waitingOnApproval`
131
+ - 或 `waitingOnUserInput`
132
+
133
+ 就会先对用户发送等待提示,并更新本地 execution status。
134
+
135
+ 但这一步只说明 runtime thread 的内部状态变化,并不能证明:
136
+
137
+ - 审批对象已经到达用户前台;
138
+ - 问题表单已经到达用户前台;
139
+ - auto-resolve 已经生效并结束;
140
+ - 用户现在真的有能力采取下一步动作。
141
+
142
+ ### 6.2 第二层根因:阻塞态和“用户可操作实体”没有强绑定
143
+
144
+ 当前模型缺少一个关键约束:
145
+
146
+ > **只有当用户可操作实体已经被 bridge 成功持久化并成功发给前台时,阻塞态才允许成立。**
147
+
148
+ 现在这个约束不存在,所以才会出现:
149
+
150
+ - 有 waiting flag
151
+ - 没有实体
152
+ - 但已经阻塞会话
153
+
154
+ ### 6.3 第三层根因:follow-up 拦截条件过宽
155
+
156
+ 当前 follow-up 拦截是根据本地 `waitingState` 做的,而不是根据“当前是否真的存在用户可处理的 pending object”做的。
157
+
158
+ 于是就会出现:
159
+
160
+ - 用户发 `进展如何?`
161
+ - 用户发 `同意`
162
+ - 用户发 `继续`
163
+
164
+ bridge 一律不转给 Codex,而是直接回:
165
+
166
+ - 你还没审批
167
+ - 你还没补充信息
168
+
169
+ 这对用户来说是错误指控,因为前提条件根本不存在。
170
+
171
+ ### 6.4 第四层根因:auto-resolve 和 waiting state 缺少原子性
172
+
173
+ MCP 默认自动放行本来是为了减少人为阻塞,但现场说明:
174
+
175
+ - 这条自动决策没有在所有运行态里形成稳定闭环;
176
+ - `waitingOnUserInput` 可能先暴露给状态机;
177
+ - auto-resolve 或请求实体对账没有及时完成;
178
+ - 前台于是先进入错误阻塞态。
179
+
180
+ 因此,auto-resolve 不是单独一个小 feature,而必须纳入同一套阻塞状态机设计中。
181
+
182
+ ## 7. 修复原则
183
+
184
+ 这类问题后续应统一按下面四条原则修改。
185
+
186
+ ### 7.1 原则一:没有用户可操作实体,就不能进入真正阻塞态
187
+
188
+ - 没有审批卡,不得宣称“等待你审批”
189
+ - 没有 user input 问题内容,不得宣称“等待你回复”
190
+ - 没有稳定 auto-resolve 结果,也不得先把会话切成用户待处理
191
+
192
+ ### 7.2 原则二:waiting flag 只能是候选信号,不能直接当最终事实
193
+
194
+ `waitingOnApproval` / `waitingOnUserInput` 只能表示:
195
+
196
+ - 当前轮疑似进入阻塞环节
197
+
198
+ 它不能直接表示:
199
+
200
+ - 用户已经获得审批对象
201
+ - 用户已经获得输入问题
202
+ - 用户当前应该对 bridge 负责完成下一步
203
+
204
+ ### 7.3 原则三:阻塞态需要拆成“候选阻塞态”和“可操作阻塞态”
205
+
206
+ 建议至少拆出两层:
207
+
208
+ - `blocking_visibility_pending`
209
+ - 只看到了 waiting flag,或只知道当前轮可能卡在某个阻塞点
210
+ - 但用户侧可操作实体还没有稳定到达
211
+ - `waiting_user_action`
212
+ - 审批卡 / user input 请求 / auto-resolve 收口结果已经稳定就位
213
+ - 这时才允许真正阻塞后续自然语言
214
+
215
+ ### 7.4 原则四:follow-up 拦截要以“pending object 存在”为前提
216
+
217
+ 以后只有在以下前提成立时,才允许拦截用户自然语言:
218
+
219
+ - 当前有明确 pending approval record,且用户前台已见到对应卡片
220
+ - 或当前有明确 pending user input record,且用户前台已见到问题实体
221
+
222
+ 如果没有这些前提:
223
+
224
+ - 用户消息不应被误拦截
225
+ - 应继续转给 Codex,或进入更准确的“阻塞详情同步中”异常提示
226
+
227
+ ## 8. 建议测试门禁
228
+
229
+ 后续至少要补这几个专项场景:
230
+
231
+ 1. `waitingOnApproval` flag 出现,但审批卡缺失
232
+ 2. `waitingOnUserInput` flag 出现,但问题实体缺失
233
+ 3. MCP pure-read 本应 auto-resolve,但 waiting flag 先到
234
+ 4. waiting flag 和实体晚到的时序错位
235
+ 5. 用户在“只有 waiting flag、没有实体”阶段继续追问
236
+ 6. 用户在没有审批卡/没有问题表单的情况下直接发 `同意` / `继续`
237
+ 7. auto-resolve 成功后,不应再把会话留在用户阻塞态
238
+
239
+ ## 9. 一句话结论
240
+
241
+ 这不是两个分散 bug,而是一个统一设计缺口:
242
+
243
+ > **bridge 先根据 waiting flag 宣布“轮到用户处理”,却没有先证明用户真正拿到了可操作对象。**
244
+
245
+ 后续修复时,审批链路、用户输入链路、MCP auto-resolve 链路,都应按同一套阻塞状态机原则统一收口。
246
+
247
+ ## 10. 实现收口(2026-03-17)
248
+
249
+ 这个上位问题已按统一原则收口:
250
+
251
+ 1. waiting flag 不再直接等价于用户已拿到可操作实体。
252
+ 2. approval / user input 都改成“先 invisible 落库,发送成功后再 mark visible”。
253
+ 3. `classifyConversationState()` 与 follow-up interception 只认 session 中已经可见的 pending approval / pending user input,不再单靠 runtime waiting flag。
254
+ 4. 当 runtime 已进入 waiting,但实体还没同步到前台时,bridge 只发“详情同步中”的非阻塞提示,不再错误声称“正在等你审批 / 等你回复”。
255
+ 5. 对应门禁已补:
256
+ - `tests/integration/session/approval-flow.test.mjs`
257
+ - `tests/integration/session/user-input-flow.test.mjs`
258
+ - `tests/unit/session/session-store.test.mjs`
259
+
260
+ 这意味着 approval 缺卡、user input 缺题、waiting flag 晚于实体/早于实体的错位,都已经纳入同一套可验证的状态机约束。
261
+