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,434 @@
1
+ # Claude Runtime Host For work-ally
2
+
3
+ ## Status
4
+
5
+ - Target project: `work-ally`
6
+ - Audience: product owner / implementation engineer
7
+ - Scope: Claude Runtime Host, Claude Agent SDK mapping, minimal app-server-like contract for `work-ally`
8
+ - Status: planning
9
+ - Goal: package Claude Agent SDK behind a minimal runtime host that matches the `work-ally` runtime contract closely enough for optional future integration
10
+
11
+ ## Summary
12
+
13
+ 这份 spec 是 **Phase 2 / 可选扩展 spec**。
14
+
15
+ 它不负责重构 `work-ally` 主线,也不负责立刻把 Claude 接进生产路径。
16
+
17
+ 它要做的事情只有一件:
18
+
19
+ > 基于 Claude Agent SDK,包装出一个面向 `work-ally` 的最小 Runtime Host,让上层未来可以像接入另一个 runtime impl 一样去接它。
20
+
21
+ 这里有两个边界必须先讲清楚:
22
+
23
+ 1. 它不是一个野心很大的“Claude App Server 通用平台”
24
+ 2. 它也不是把 `claude` CLI 随便包一层壳
25
+
26
+ 它应是一个**只服务于 `work-ally runtime contract` 的最小 host / shim**。
27
+
28
+ 因此,这条 spec 可以并行推进,也可以最后被砍掉:
29
+
30
+ - 如果做成了,`work-ally` 获得第二 runtime 选择
31
+ - 如果做不成,`work-ally` 仍然保持 Codex 主线稳定,不受影响
32
+
33
+ ## Relationship To Phase 1
34
+
35
+ ### 1. 逻辑关系
36
+
37
+ 产品顺序上:
38
+
39
+ - Phase 1 先定义并收稳 runtime abstraction
40
+ - Phase 2 再把 Claude 包装成符合该抽象的实现
41
+
42
+ ### 2. 执行关系
43
+
44
+ 工程推进上,Phase 2 可以部分并行:
45
+
46
+ - 可以先研究 Claude Agent SDK
47
+ - 可以先做独立 host prototype
48
+ - 可以先验证 SDK 到 host contract 的映射
49
+
50
+ 但最终要不要接入 `work-ally` 主线,仍然取决于:
51
+
52
+ - Phase 1 contract 是否稳定
53
+ - Claude host 是否满足最小接入条件
54
+
55
+ ### 3. 风险关系
56
+
57
+ 必须保证:
58
+
59
+ > Phase 2 失败,不得反伤 Phase 1,更不得损伤当前 Codex 用户。
60
+
61
+ ## Background
62
+
63
+ 支持 Claude 的动机,不应是“技术上很酷”,而应是清晰的产品理由:
64
+
65
+ - 降低组织内推广时的 runtime 偏好阻力
66
+ - 减少“先接受 Codex 才能接受 work-ally”的前置门槛
67
+ - 为未来开源留出更大的适用面
68
+
69
+ 但是否真的值得做 Claude,也必须持续反问:
70
+
71
+ > 同样能做事情,为什么一定要接 Claude?
72
+
73
+ 因此,这条 spec 从一开始就要自带 go / no-go 意识。
74
+
75
+ 另一方面,基于对 `nanoclaw` 的研究,可以确认三件事:
76
+
77
+ 1. Claude Agent SDK 足以承接会话、调度、隔离执行这些上层能力
78
+ 2. Claude 侧更像 `session + async iterator + hooks + permission callbacks`
79
+ 3. 它并不是 Codex App Server 的同构替代物
80
+
81
+ 这意味着正确方向不是“直接把 Claude SDK 塞进 bridge”,而是先包一层 host。
82
+
83
+ ## Problem Statement
84
+
85
+ Phase 2 要解决三个问题。
86
+
87
+ ### 1. Claude Agent SDK 与 `work-ally` 当前消费层级不一致
88
+
89
+ `work-ally` 当前更接近消费一个 runtime host / app-server 式能力面。
90
+
91
+ 而 Claude Agent SDK 暴露的是:
92
+
93
+ - session / resume
94
+ - async iterator message stream
95
+ - interrupt
96
+ - permission callbacks
97
+ - hooks
98
+ - settingSources
99
+ - MCP server wiring
100
+
101
+ 如果直接把这些原始语义灌进 `work-ally` bridge,会让上层抽象变脏。
102
+
103
+ ### 2. Claude 的 gate model 不等于 Codex 的 approval model
104
+
105
+ Codex 当前可以较自然地产生 approval / user-input 事件。
106
+
107
+ Claude 更可能通过:
108
+
109
+ - `canUseTool`
110
+ - permissionMode
111
+ - hooks
112
+ - session control
113
+
114
+ 来间接表达“这里需要人类决策”。
115
+
116
+ 如果不单独包 host,这种差异会直接污染产品主链路。
117
+
118
+ ### 3. 需要在接入前判断是否值得做
119
+
120
+ 不是所有“能接”的东西都值得接。
121
+
122
+ Claude host 必须先证明:
123
+
124
+ - 它能满足最小 contract
125
+ - 它的维护成本可接受
126
+ - 它不会迫使 `work-ally` 为它改坏现有 Codex 体验
127
+
128
+ ## Product Decision
129
+
130
+ ### Decision 1: Phase 2 是可选扩展,不是主线前提
131
+
132
+ Claude Runtime Host 不是当前产品成立的前提。
133
+
134
+ 它的地位应明确为:
135
+
136
+ - 可选扩展
137
+ - 价值验证项
138
+ - 做成再接,做不成就不接
139
+
140
+ ### Decision 2: Host 只做最小封装,不做通用平台
141
+
142
+ Host 的目标不是复刻一个完整的“Claude App Server”。
143
+
144
+ 它只需要满足 `work-ally` 真正需要的最小 contract。
145
+
146
+ 这意味着:
147
+
148
+ - 不做额外控制台
149
+ - 不做多租户平台
150
+ - 不做广义的 provider layer
151
+ - 不做超过 `work-ally` 需求的通用 server 野心
152
+
153
+ ### Decision 3: 先追求产品语义对齐,不追求协议长相一致
154
+
155
+ 我们追求的是:
156
+
157
+ - `work-ally` 上层看到的产品语义一致
158
+
159
+ 而不是:
160
+
161
+ - Claude host 在底层长得和 Codex App Server 一模一样
162
+
163
+ 因此允许:
164
+
165
+ - 底层实现不同
166
+ - 原生事件形状不同
167
+ - 只要 adapter / host 能提供同样的产品合同即可
168
+
169
+ ### Decision 4: Claude host 的核心难点是 gate semantics,不是 run turn
170
+
171
+ 跑一轮 prompt、拿一个结果,这不是最难的部分。
172
+
173
+ 真正难的是:
174
+
175
+ - 什么时候停下来找人
176
+ - 人如何回复
177
+ - 回复后如何继续
178
+ - 这些行为如何稳定映射到 Feishu 远程协作语义
179
+
180
+ 所以 Phase 2 的验收重点必须放在 gate semantics,而不是只放在“跑通一次会话”。
181
+
182
+ ## Goals
183
+
184
+ 1. 基于 Claude Agent SDK 定义一个最小 Runtime Host
185
+ 2. 让该 Host 能映射到 `work-ally` runtime contract
186
+ 3. 验证 Claude 路线在 `work-ally` 里是否具备现实接入价值
187
+ 4. 为后续正式接入提供清晰的 go / no-go 判断依据
188
+
189
+ ## Non-goals
190
+
191
+ Phase 2 不做:
192
+
193
+ - 承诺一定把 Claude 接进生产主线
194
+ - 复刻完整 Codex App Server 协议
195
+ - 提供一个通用外部开放平台供无关项目直接复用
196
+ - 在第一版就支持所有 Claude 能力或全部 SDK 特性
197
+ - 为了兼容 Claude 改坏 `work-ally` 主线抽象
198
+
199
+ ## Scope
200
+
201
+ ### In scope
202
+
203
+ 1. 研究 Claude Agent SDK 的正式能力面
204
+ 2. 定义一个最小 Claude Runtime Host contract
205
+ 3. 明确 SDK 到 host contract 的映射
206
+ 4. 明确 host 到 `work-ally` runtime contract 的映射
207
+ 5. 做最小 host prototype / spike
208
+ 6. 形成 capability matrix、降级语义和 go / no-go 结论
209
+
210
+ ### Out of scope
211
+
212
+ 1. 直接修改 `work-ally` 主线接入 Claude
213
+ 2. 承诺对外正式支持 Claude
214
+ 3. 设计多 runtime UI 或切换面板
215
+
216
+ ## Minimal Host Contract
217
+
218
+ Claude Runtime Host 至少应提供下面这些能力面。
219
+
220
+ ### 1. Required host surface
221
+
222
+ 1. `healthcheck`
223
+ 2. `start_session`
224
+ 3. `resume_session`
225
+ 4. `run_turn`
226
+ 5. `interrupt_turn`
227
+ 6. `read_session_status`
228
+ 7. `disconnect`
229
+
230
+ ### 2. Desired host surface
231
+
232
+ 1. progress stream
233
+ 2. gate semantics
234
+ 3. turn result recovery or bounded confirmation support
235
+ 4. session metadata
236
+ 5. capability declaration
237
+
238
+ ### 3. Explicitly allowed mismatch
239
+
240
+ 下面这些地方不要求与 Codex 完全同构:
241
+
242
+ - 原生 event 名称
243
+ - 原生 message shape
244
+ - session 内部实现方式
245
+ - permission / gate 的底层来源
246
+
247
+ 真正要求一致的是:
248
+
249
+ - host 对外提供给 `work-ally` 的 contract
250
+
251
+ ## Mapping: Claude SDK -> Host
252
+
253
+ 这部分是第二个工程师最需要的一节。
254
+
255
+ ### 1. Session lifecycle mapping
256
+
257
+ Claude SDK 侧重点能力:
258
+
259
+ - `query()`
260
+ - `resume`
261
+ - session object / persistent session 能力
262
+ - `interrupt()`
263
+
264
+ Host 要负责把这些能力映射成:
265
+
266
+ - start session
267
+ - resume session
268
+ - run turn
269
+ - interrupt current turn
270
+
271
+ ### 2. Progress mapping
272
+
273
+ Claude SDK 可能提供的相关信号包括:
274
+
275
+ - partial messages
276
+ - tool progress
277
+ - task notifications
278
+ - hook progress
279
+
280
+ Host 需要判断:
281
+
282
+ - 哪些可以转成 `work-ally` 的 progress events
283
+ - 哪些只能内部使用
284
+ - 哪些只能被合成为较粗粒度状态
285
+
286
+ ### 3. Gate mapping
287
+
288
+ 这是最关键映射。
289
+
290
+ Host 需要把下面这些 Claude-side 能力,整理成 `work-ally` 能消费的 gate semantics:
291
+
292
+ - `canUseTool`
293
+ - permission mode
294
+ - hooks
295
+ - 需要用户继续输入或确认的场景
296
+
297
+ 关键不是保留原始形状,而是产出统一合同:
298
+
299
+ - 触发什么 gate
300
+ - 发给用户什么信息
301
+ - 收到用户回复后怎么继续
302
+
303
+ ### 4. Context / instruction loading mapping
304
+
305
+ Claude SDK 有自己的 `settingSources`、`systemPrompt`、additional directories 等能力。
306
+
307
+ Host 需要明确:
308
+
309
+ - 如何承接项目级规则
310
+ - 如何承接 assistant desk 规则
311
+ - 是否支持 desk / project 双边界注入
312
+ - 何处是 host 自己的内部配置,何处由 `work-ally` 提供
313
+
314
+ ### 5. MCP mapping
315
+
316
+ Host 需要明确:
317
+
318
+ - Claude SDK 下 MCP server 如何挂接
319
+ - 与 `work-ally` 当前的 MCP 使用边界是否冲突
320
+ - 哪些 MCP 行为属于 host 内部,哪些属于上层 contract
321
+
322
+ ## Implementation Direction
323
+
324
+ ### Step 1: Capability inventory
325
+
326
+ 先做一份明确的 Claude SDK capability inventory:
327
+
328
+ - 会话能力
329
+ - 中断能力
330
+ - partial / progress 能力
331
+ - permission / hook 能力
332
+ - MCP 能力
333
+ - context / settingSources 能力
334
+
335
+ ### Step 2: Host contract draft
336
+
337
+ 基于 inventory 定义最小 host contract,而不是直接开写实现。
338
+
339
+ ### Step 3: Prototype
340
+
341
+ 做一个最小 host prototype,只验证:
342
+
343
+ - start
344
+ - resume
345
+ - run turn
346
+ - interrupt
347
+ - 最小 progress
348
+ - 最小 gate semantics
349
+
350
+ ### Step 4: Gap analysis
351
+
352
+ 输出 capability matrix:
353
+
354
+ - 已满足
355
+ - 可降级满足
356
+ - 当前缺失
357
+ - 必须阻塞正式接入
358
+
359
+ ### Step 5: Integration recommendation
360
+
361
+ 最后才给出结论:
362
+
363
+ - 值得进入 `work-ally`
364
+ - 暂缓
365
+ - 放弃
366
+
367
+ ## Go / No-Go Criteria
368
+
369
+ 满足以下条件,Claude Host 才值得进入下一步接入评审:
370
+
371
+ 1. 能稳定新建和恢复会话
372
+ 2. 能稳定跑完最小 turn
373
+ 3. 能中断
374
+ 4. 能给出至少可接受的 progress / working 语义
375
+ 5. 能稳定表达 gate semantics
376
+ 6. 不要求 `work-ally` 为它改坏当前 Codex 抽象
377
+ 7. 维护成本可接受
378
+
379
+ 任一关键项不满足,都可以判定:
380
+
381
+ - 暂不接入 `work-ally`
382
+
383
+ ## Deliverables
384
+
385
+ Phase 2 完成时,至少应交付:
386
+
387
+ 1. 一份 Claude SDK capability inventory
388
+ 2. 一份最小 Claude Runtime Host contract
389
+ 3. 一个 host prototype 或 spike 实现
390
+ 4. 一份 capability matrix
391
+ 5. 一份明确的 go / no-go 结论
392
+
393
+ ## Acceptance Criteria
394
+
395
+ 1. 第二个工程师只看这份 spec,就能理解 host 的目标、边界和成功标准
396
+ 2. spec 已明确写清:它是最小 host,不是通用平台
397
+ 3. spec 已明确写清:它可以并行推进,也可以最终被砍掉
398
+ 4. host 的关键难点和验收重心已放在 gate semantics,而不是只看单轮 prompt
399
+ 5. 输出物里包含 capability matrix 和接入建议,而不是只有 demo
400
+
401
+ ## Risks
402
+
403
+ ### 1. 误把 host 做成通用平台
404
+
405
+ 会迅速膨胀,也会偏离 `work-ally` 的真实需求。
406
+
407
+ ### 2. 误把 Claude permission model 当成 Codex approval model
408
+
409
+ 会导致抽象别扭、实现脆弱,最后逼着 `work-ally` 主链路到处打补丁。
410
+
411
+ ### 3. 只看“能跑起来”,忽视远程协作语义
412
+
413
+ 如果 host 只会本地跑 prompt,但无法提供稳定 gate semantics,就不适合接进 `work-ally`。
414
+
415
+ ### 4. 维护成本高于用户价值
416
+
417
+ 即使技术上能做,也不代表产品上值得做。
418
+
419
+ ## Open Questions
420
+
421
+ 1. Claude SDK 的哪条 session API 最适合作为 host 的稳定基础
422
+ 2. desk / project 双边界注入的最佳承接方式是什么
423
+ 3. gate semantics 应该在 host 内完成多少,留给 adapter 层多少
424
+ 4. 如果 progress 只能粗粒度合成,是否仍足以满足 `work-ally` 的远程协作要求
425
+
426
+ ## Product Judgment
427
+
428
+ Phase 2 的正确定位不是“我们一定要支持 Claude”。
429
+
430
+ 而是:
431
+
432
+ > 我们给自己一个低风险、可验证、可放弃的机会,去判断 Claude 路线是否真的值得成为 `work-ally` 的第二 runtime。
433
+
434
+ 如果答案是 yes,就接;如果答案是 no,就停。无论结果如何,都不应伤到当前 Codex 主线。
@@ -0,0 +1,236 @@
1
+ # SPEC: CLI-Only + Feishu/Codex 会话互通主线重构(Thread Read Pull 模式)
2
+
3
+ 更新时间:2026-03-31
4
+ 状态:In Progress
5
+ Owner:work-ally
6
+ 相关文档:
7
+ - `AGENTS.md`
8
+ - `README.md`
9
+ - `docs/product-spec-standard.md`
10
+ - `docs/planning/SPEC-codex-same-machine-session-handoff.md`
11
+ - `docs/planning/SPEC-managed-thread-entry-and-surface-mobility.md`
12
+
13
+ ## 1. Summary
14
+
15
+ 本次变更将 `work-ally` 从“CLI + Desktop 并行入口”收敛为单一主线,并把会话材料采集方式明确为 **Thread Read Pull**:
16
+
17
+ 1. 唯一产品入口是 CLI(`./ally.sh <command>`)。
18
+ 2. 产品核心价值是让用户可在 Feishu 与官方 `codex` CLI 间无缝切换并连续使用同一会话。
19
+ 3. 会话留痕不再由中间层按消息事件增量记录,也不使用 Hook 方案;统一改为按时机对 thread 执行 `thread/read(includeTurns=true)` 拉取并覆盖写本地材料。
20
+ 4. 记忆系统以 thread 拉取得到的“用户/assistant 对话正文”作为原材料,统一沉淀到 assistant desk。
21
+
22
+ 其中 `ally codex` 的定位是:
23
+
24
+ 1. 它是官方 `codex` 命令的受管启动入口(wrapper / launcher)。
25
+ 2. `work-ally` 在启动前注入 assistant 绑定的 profile 上下文(至少含 `CODEX_HOME` 与相关会话互通所需环境)。
26
+ 3. 真正执行会话的仍是官方 `codex`,不是中间层自实现 runtime。
27
+
28
+ 一句话定义:
29
+
30
+ > `work-ally` 是官方 Codex CLI 的会话互通层与渠道编排层,不是独立会话系统。
31
+
32
+ ## 2. 背景
33
+
34
+ 当前仓库存在两条并行叙事:
35
+
36
+ 1. Desktop Control Plane 作为正式包装入口。
37
+ 2. Feishu 与 CLI 的互通与接续能力持续增强。
38
+
39
+ 方向变更后,产品目标更明确:
40
+
41
+ 1. 不再支持桌面端。
42
+ 2. 主打“Feishu 可用 + 官方 Codex CLI 可用 + 同一会话连续”。
43
+ 3. 若用户临时离开 Feishu 转到官方 `codex`,会话仍可回溯与续接。
44
+
45
+ 同时,增量监听式会话落库在工程上会形成第二事实源;因此本次改为 thread 全量读取并覆盖写,保证“来源单一、结构稳定、实现可审计”。
46
+
47
+ ## 3. 问题定义
48
+
49
+ ### 3.1 入口与产品语义分散
50
+
51
+ Desktop 与 CLI 并行导致用户对“主入口”认知不一致,维护口径与文档口径被分散。
52
+
53
+ ### 3.2 会话真相源重复
54
+
55
+ 当中间层保存一套聊天记录、官方 Codex 再保存一套会话轨迹时,会出现:
56
+
57
+ 1. 事实源不唯一。
58
+ 2. 跨 Feishu 与官方 CLI 的会话连续性依赖额外映射。
59
+ 3. 用户离开 Feishu 后会话留存不稳定。
60
+
61
+ ### 3.3 profile 不统一导致无法无缝续接
62
+
63
+ 若不是由 `work-ally` 控制并复用同一 assistant profile(同一 `CODEX_HOME`),官方 `codex` CLI 无法稳定识别并续接同一会话上下文。
64
+
65
+ ### 3.4 记忆原材料来源未收敛
66
+
67
+ 记忆系统需要稳定输入;若 Feishu 和 Codex CLI 的会话采集不统一,记忆质量与可追溯性会持续波动。
68
+
69
+ ## 4. 目标 / 非目标
70
+
71
+ ### 4.1 目标
72
+
73
+ 1. 将产品明确收敛为 CLI-only,对外保留单一入口:`./ally.sh`。
74
+ 2. 支持“从 `work-ally` 启动官方 `codex` CLI”并强制复用 assistant 绑定 profile。
75
+ 3. 建立 Feishu 与官方 Codex CLI 的同一会话连续体(同一 session 语义,不做摘要复制式伪连续)。
76
+ 4. 以 `thread/read(includeTurns=true)` 作为统一会话采集机制,覆盖 Feishu 路径与官方 CLI 路径。
77
+ 5. 将会话采集结果统一沉淀到 assistant desk,作为记忆提炼原材料。
78
+ 6. 删除桌面端实现与对外口径,避免平行产品线继续演化。
79
+
80
+ ### 4.2 非目标
81
+
82
+ 1. 不在中间层重做一套会话引擎或聊天数据库。
83
+ 2. 不实现新的 GUI 入口替代 desktop。
84
+ 3. 不在本次引入多机协同、云端托管会话、跨设备自动同步。
85
+ 4. 不把记忆系统扩展成“全量知识库平台”;本次只收口“会话原材料 -> desk 记忆资产”。
86
+ 5. 不再推进 Codex Hook 采集方案。
87
+
88
+ ## 5. 产品定义与用户路径
89
+
90
+ ### 5.1 产品定义
91
+
92
+ `work-ally` 提供三件事:
93
+
94
+ 1. 渠道互通:Feishu 消息与 Codex 执行链路互通。
95
+ 2. 会话连续:Feishu 与官方 `codex` CLI 指向同一 assistant profile 与同一会话语义。
96
+ 3. 记忆沉淀:会话原材料统一汇总到 assistant desk 并可持续提炼。
97
+
98
+ ### 5.2 主路径 A:用户在 Feishu 发起并持续会话
99
+
100
+ 1. 用户在 Feishu 与 assistant 对话。
101
+ 2. `work-ally` 调用官方 Codex runtime 处理。
102
+ 3. 在关键时机(如 final reply 后)与定时任务中,对当前 thread 执行 `thread/read`。
103
+ 4. 仅抽取 user/assistant 对话正文并按天+thread 覆盖写原材料。
104
+
105
+ ### 5.3 主路径 B:用户从 work-ally 启动官方 codex CLI 接续同一会话
106
+
107
+ 1. 用户执行 `ally codex --assistant <name> [codex args...]`。
108
+ 2. `work-ally` 注入该 assistant 的 `CODEX_HOME/profile` 后启动官方 `codex`。
109
+ 3. 用户在官方 CLI 中继续同一 assistant 会话。
110
+ 4. 后台定时同步继续拉取该 thread 的完整会话正文。
111
+
112
+ ### 5.4 主路径 C:用户从官方 codex CLI 回到 Feishu
113
+
114
+ 1. 用户结束 CLI 操作后回到 Feishu。
115
+ 2. 后续消息仍命中同一 assistant 与同一会话连续体。
116
+ 3. 用户不需要迁移聊天记录,也不需要手工导出上下文。
117
+
118
+ ### 5.5 关键异常路径
119
+
120
+ 1. `thread/read` 临时失败:会话处理继续,下一次定时/关键时机补拉。
121
+ 2. profile 不匹配:拒绝启动并提示必须通过 `ally codex` 启动,避免产生分叉会话。
122
+ 3. 会话映射缺失:允许新会话启动,但明确标记为“新会话,不是续接”。
123
+
124
+ ## 6. 机制设计
125
+
126
+ ### 6.1 capability 分类(Core / Hybrid / Skill)
127
+
128
+ 本能力定义为 **Core**。
129
+
130
+ 原因:
131
+
132
+ 1. 它改变产品主语义(入口、会话真相、默认行为)。
133
+ 2. 它跨越 `internal/`、`bridge/`、`runtime/` 与文档口径。
134
+ 3. 它必须始终生效,不是按需触发的 workflow,不适合作为 Skill。
135
+
136
+ ### 6.2 核心对象
137
+
138
+ 1. `AssistantProfile`:assistant 绑定的 profile 真相,至少包含 `assistant_home`、`codex_home`、`workspace_root`。
139
+ 2. `SessionBinding`:外部会话(Feishu)与官方会话标识(Codex)之间的绑定关系。
140
+ 3. `SessionMaterial`:由 `thread/read` 拉取并归一化后的会话原材料事件。
141
+
142
+ ### 6.3 命令面
143
+
144
+ 1. 正式入口:`ally codex --assistant <name> [codex args...]`。
145
+ 2. 兼容:`ally handoff codex ...` 保留为兼容别名。
146
+ 3. 新增:`ally thread-sync [--thread <threadId>] [--json]`,用于手动触发 thread 拉取。
147
+
148
+ ### 6.4 采集机制(Thread Read Pull)
149
+
150
+ 1. 统一来源:只通过 `thread/read(includeTurns=true)` 获取会话数据。
151
+ 2. 统一过滤:仅保留 `userMessage` 与 `agentMessage`。
152
+ 3. 统一落盘:按天目录 + thread 文件覆盖写,目录结构:
153
+ - `.system/archive/YYYY/MM/DD/<threadId>.ndjson`
154
+ 4. 覆盖策略:每次同步对目标 thread 的目标日期文件执行完整替换,避免增量漂移。
155
+
156
+ ### 6.5 同步触发策略
157
+
158
+ 1. 定时同步:默认每小时同步一次所有“未归档且未关闭”的 work sessions。
159
+ 2. 回复后同步:发送 final reply 后,立即同步当前 thread。
160
+ 3. `/new` 前同步:创建新 thread 前,先同步当前 thread。
161
+ 4. 记忆整理前同步:memory digest routine 执行前先做一次全量同步。
162
+
163
+ ### 6.6 会话与记忆管线
164
+
165
+ 1. 记忆提炼只消费 thread pull 产物,不再依赖中间层消息事件落库。
166
+ 2. daily digest 仅扫描当天目录下 thread 文件。
167
+ 3. 记忆写回继续遵守 assistant desk 边界(`MEMORY.md` 等长期资产可审计、可版本化)。
168
+
169
+ ### 6.7 Desktop 退场合同
170
+
171
+ 1. 删除 `desktop/` 目录与对应测试、构建、发布脚本。
172
+ 2. README、DASHBOARD、quickstart 文档改为 CLI-only 口径。
173
+ 3. 删除或归档 desktop 相关 planning/implementation 文档,避免继续作为现行路线被引用。
174
+
175
+ ## 7. Scope / Phase
176
+
177
+ ### Phase 1:语义收敛与入口收口
178
+
179
+ 交付:
180
+
181
+ 1. 发布 CLI-only 产品定义与文档口径。
182
+ 2. 新增 `ally codex` 正式命令入口。
183
+ 3. desktop 能力下线并移除对外入口。
184
+
185
+ ### Phase 2:会话采集统一(Thread Read Pull)
186
+
187
+ 交付:
188
+
189
+ 1. `thread/read` 统一采集管线。
190
+ 2. 定时 + 关键时机补拉策略。
191
+ 3. `.system/archive/YYYY/MM/DD/<threadId>.ndjson` 覆盖写合同。
192
+
193
+ ### Phase 3:记忆消费收口
194
+
195
+ 交付:
196
+
197
+ 1. 记忆流水线统一消费 thread pull 材料。
198
+ 2. assistant desk 记忆资产持续更新并可追溯来源。
199
+
200
+ ## 8. 验收标准
201
+
202
+ ### 8.1 功能验收
203
+
204
+ 1. 用户可仅通过 `./ally.sh` 完成 setup/start/status/logs/codex/thread-sync 主路径。
205
+ 2. 执行 `ally codex --assistant <name>` 时,实际使用该 assistant 注册的 `codex_home`。
206
+ 3. 用户在 Feishu 与官方 CLI 间切换时,会话可续接且材料持续同步。
207
+ 4. `.system/archive/` 中只保留 thread pull 产物,不再写入中间层消息增量流水。
208
+ 5. desktop 相关入口、构建、发布不再出现在 shipped 文档与主脚本。
209
+
210
+ ### 8.2 回归验收
211
+
212
+ 1. `bash -n ally.sh`。
213
+ 2. 相关 `internal/` shell 脚本语法校验。
214
+ 3. `tests/shell/assistant.sh` 与 handoff/continuity 回归通过。
215
+ 4. 至少一条“重启后发送普通消息仍可继续处理”的自动化或人工闭环。
216
+ 5. `./ally.sh help` smoke 通过,且无 desktop 入口文案。
217
+
218
+ ## 9. 风险 / 假设 / 待决问题
219
+
220
+ ### 9.1 风险
221
+
222
+ 1. `thread/read` 在个别状态下不可用(如首条消息前),可能导致短窗口延迟。
223
+ 2. 若只同步 active thread 会漏多 thread;本方案通过“同步所有活跃 work sessions”规避。
224
+ 3. 迁移期间若旧 archive 与新 archive 混读,可能造成认知混乱。
225
+
226
+ ### 9.2 假设
227
+
228
+ 1. 官方 Codex CLI 继续作为唯一会话执行真相源。
229
+ 2. assistant profile 中的 `codex_home` 可稳定复用并能读取 thread。
230
+ 3. 用户接受 CLI-only 入口,不再依赖 desktop 控制面。
231
+
232
+ ### 9.3 待决问题
233
+
234
+ 1. 历史 archive 的迁移与清理策略(是否做一次性迁移脚本)。
235
+ 2. thread 文件是否需要额外索引(如最近更新时间索引)以加速大规模扫描。
236
+ 3. 对于超长 thread 的读取成本控制(按需分段 vs 全量读取)后续优化策略。