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,450 @@
1
+ # SPEC: Approval Rules Inheritance And Local Validation Lane
2
+
3
+ 更新时间:2026-03-22
4
+ 状态:Ready for review
5
+ Owner:work-ally product / engineering
6
+ 相关文档:
7
+ - `docs/completed/SPEC-approval-autonomy-and-safe-defaults.md`
8
+ - `docs/planning/SPEC-bridge-app-server-protocol-alignment.md`
9
+ - `AGENTS.md`
10
+ - `README.md`
11
+
12
+ ## 1. Summary
13
+
14
+ 这次要解决的不是“审批卡文案还可以更顺一点”,而是把 `work-ally` 的审批机制补到一个长期可用的产品基线。
15
+
16
+ 当前真实问题已经很明确:
17
+
18
+ 1. assistant 在当前项目内做连续本地验证时,仍会反复把 `cmake`、`ctest`、shell 包裹的本地编辑/验证命令抛给用户审批。
19
+ 2. 官方 Codex 已经提供了按命令前缀记住放行决策的 `.rules / prefix_rule` 机制,但 `work-ally` 还没有把这层能力接进自己的审批链路。
20
+ 3. 结果就是:用户已经明确放行过一类动作,下一次还是要继续在 Feishu 里回 `OK / 同意`,工作流被大量低价值确认打断。
21
+ 4. 对已经在官方 Codex 里做了很久的项目来说,全局 `~/.codex/rules/*.rules` 本身已经沉淀了大量历史放行资产;如果 `work-ally` 不持续继承这层资产,而是让用户重新从零审批,会造成明显的产品割裂。
22
+
23
+ 本次 feature 要同时做两件事:
24
+
25
+ 1. **兼容并复用官方 Codex 的 `.rules` 规则机制**,让“按前缀记住放行/拒绝”这件事在 `work-ally` 里真正生效。
26
+ 2. **扩大本地低风险验证 lane**,把当前项目根 / assistant desk 根内的 build、test、lint、诊断类命令纳入默认自治边界,不再继续要求用户逐条拍板。
27
+
28
+ 一句话定义:
29
+
30
+ > 用户只需要为真正的风险边界拍板;已经记住的前缀规则和明确属于本地低风险验证的动作,`work-ally` 应自动匹配并自动处理,而不是继续把用户拉进 assistant 的内部自测过程。
31
+
32
+ ## 2. 背景
33
+
34
+ ### 2.1 真实日志已经说明问题不是个例
35
+
36
+ 2026-03-22 的 `Matrix` assistant 日志里,单日出现了至少 30 次命令审批;其中 17 次集中在同一条 turn 内。
37
+
38
+ 主要类型包括:
39
+
40
+ - `python3 <<'PY'` 的本地仓库编辑命令
41
+ - `cmake -S/-B`
42
+ - `cmake --build`
43
+ - `ctest --test-dir ...`
44
+ - 相关 git 环境准备命令
45
+
46
+ 这说明问题不是“偶尔会多问一次”,而是当前审批边界和自动放行策略都还不够产品化。
47
+
48
+ ### 2.2 现有自治白名单过窄
49
+
50
+ 当前 shipped 基线已经做了一轮审批收口:
51
+
52
+ - 当前项目根 / assistant desk 根内的文件写入可自动放行
53
+ - 一小部分低风险命令可自动放行,例如 `git status/diff/add/commit`、`npm test`、`node --test`、`bash tests/shell/*.sh`
54
+
55
+ 但这条白名单明显还停留在 `work-ally` 自己常用的维护路径上,没有覆盖更一般的本地 build / test / validation 工作流。
56
+
57
+ 结果是:
58
+
59
+ - `cmake` / `ctest` 这类非常典型的本地验证命令仍然要审批
60
+ - shell 包裹的本地多段验证命令仍然要审批
61
+ - 用户已经认可“这类事可以审批”,但体验上仍被连续打断
62
+
63
+ ### 2.3 官方 Codex 已有 remembered-prefix 能力
64
+
65
+ 官方 Codex 现在已经有 `.rules` 机制,可以通过 `prefix_rule(pattern=[...], decision="allow|prompt|forbidden")` 记住一类命令前缀的处理策略。
66
+
67
+ 这意味着:
68
+
69
+ - `work-ally` 没必要重新发明一套新的规则文件格式
70
+ - 用户对官方 `.rules` 的已有理解和资产应尽量直接复用
71
+ - 如果 middle layer 还忽略这层能力,就会造成“官方能记住,接进 work-ally 反而记不住”的体验倒退
72
+
73
+ 这里还有一个关键产品判断必须明确:
74
+
75
+ - `~/.codex/rules/*.rules` 应被视为用户在 Codex 生态里的**持续生效事实源**
76
+ - 它不应只在 assistant 创建时被复制一次后就与 `work-ally` 分家
77
+ - 否则同一个项目一旦从官方 Codex 切到 Feishu / work-ally,就会重新冒出大量本已放行过的审批请求
78
+
79
+ ## 3. 问题定义
80
+
81
+ 当前问题有四层。
82
+
83
+ ### 3.1 同类本地低风险动作仍在重复审批
84
+
85
+ 用户已经接受“高风险动作走审批”,但无法接受一天里对几十条同类 build/test/编辑命令重复回同意。
86
+
87
+ 这会把用户从“负责人”降级成“按钮操作员”。
88
+
89
+ ### 3.2 `work-ally` 还没接住官方规则资产
90
+
91
+ 即使用户已经在官方 Codex 里使用 `.rules` 或未来希望沿用同样的 mental model,当前 `work-ally` 也不会在 bridge 收到 approval request 时去匹配这些规则。
92
+
93
+ 结果就是:
94
+
95
+ - 官方规则和 `work-ally` 规则割裂
96
+ - assistant 专属 `CODEX_HOME` 与全局 `~/.codex` 的规则资产没有形成一致产品语义
97
+
98
+ ### 3.3 规则记忆与本地安全默认值是两套机制,但目前只做了半套
99
+
100
+ 低风险本地验证 lane 和 `.rules` 前缀记忆并不是互斥关系。
101
+
102
+ - 本地安全默认值解决的是“这类动作本来就不值得打断用户”
103
+ - `.rules` 解决的是“即便默认不自动放行,用户放行过一次后,后续该能按前缀记住”
104
+
105
+ 当前只做了很窄的一层默认自治,没有接入规则记忆,所以两边都不完整。
106
+
107
+ ### 3.4 assistant 本地规则落点还没产品化
108
+
109
+ 官方规则机制支持全局规则,但 `work-ally` 的多 assistant 产品模型还需要一个额外判断:
110
+
111
+ - 这次“记住”应该写到全局还是 assistant 本地?
112
+
113
+ 如果不拍板,后续实现就会漂移。
114
+
115
+ ### 3.5 规则继承如果做成“创建时复制”,会让体验割裂
116
+
117
+ 如果 `work-ally` 只是 assistant 创建时把全局 rules 拷一份到本地,会出现三个问题:
118
+
119
+ 1. 用户之后在官方 Codex 新增的放行规则,`work-ally` 看不到。
120
+ 2. 用户之后修改或撤销的全局规则,`work-ally` 仍在沿用旧快照。
121
+ 3. 同一个项目在官方 Codex 和 Feishu / work-ally 之间切换时,会表现得像两套互不连通的授权世界。
122
+
123
+ 因此,“创建时复制一份”不是可接受方案。
124
+
125
+ ## 4. 目标 / 非目标
126
+
127
+ ### 4.1 目标
128
+
129
+ 1. 让 `work-ally` 在命令审批链路里兼容官方 `.rules / prefix_rule` 规则语法。
130
+ 2. 支持同时读取全局 `~/.codex/rules/*.rules` 与 assistant 本地 `<assistant-codex-home>/rules/*.rules`。
131
+ 3. 明确全局 `~/.codex/rules/*.rules` 是持续继承的事实源,而不是 assistant 创建时的一次性初始化快照。
132
+ 4. 在收到 runtime command approval 后,先按规则决定 `allow / prompt / forbidden`,再决定是否向用户发审批卡。
133
+ 5. 扩大本地低风险验证 lane,把当前项目根 / assistant desk 根内的典型 build / test / lint / diagnostics 命令纳入默认自治边界。
134
+ 6. 将“记住这次放行”的默认落点拍板为 assistant-local rules,而不是默认污染全局 rules。
135
+ 7. 保持 archive / timeline 可审计:自动放行、规则命中、规则拒绝都要留下稳定记录。
136
+
137
+ ### 4.2 非目标
138
+
139
+ 1. 本次不做新的远程规则同步系统。
140
+ 2. 本次不做独立的规则编辑 UI 或审批面板。
141
+ 3. 本次不支持完整重现官方所有 experimental rules 特性;只实现 `work-ally` 审批链路真正需要的稳定子集。
142
+ 4. 本次不把所有本地命令一律自动放开。
143
+ 5. 本次不修改 MCP tool approval 的已有 allowlist 设计;那条链路继续保留。
144
+
145
+ ## 5. 为什么它不是 Skill
146
+
147
+ 这次是 `Core`,不是 Skill。
148
+
149
+ 原因:
150
+
151
+ 1. 它直接改变 `work-ally` 的审批语义、默认行为和用户路径。
152
+ 2. 它作用于 bridge 主链路,是 runtime request 到用户可见审批之间的核心合同。
153
+ 3. 如果把它做成 Skill,就会导致“某个 Skill 在决定 bridge 是否发审批卡”,这会破坏核心边界。
154
+
155
+ 因此本专题必须留在 core。
156
+
157
+ ## 6. 产品定义与用户路径
158
+
159
+ ### 6.1 一句话定义
160
+
161
+ `work-ally` 的命令审批默认流程应变成:
162
+
163
+ 1. 先看它是不是本地低风险验证动作;如果是,静默自动放行。
164
+ 2. 否则再看是否命中 `.rules`;这里的 `.rules` 包括持续继承的全局 rules 和 assistant-local rules。命中 `allow` 就自动放行,命中 `forbidden` 就自动拒绝。
165
+ 3. 只有既不属于低风险自治 lane、也没有命中 remembered rules 的动作,才真正向用户发审批卡。
166
+
167
+ ### 6.2 主路径 A:本地低风险验证动作
168
+
169
+ 场景:assistant 在当前项目根或 assistant desk 根内运行 build / test / lint / diagnostics。
170
+
171
+ 路径:
172
+
173
+ 1. runtime 发出 command approval request。
174
+ 2. bridge 判断该命令属于本地低风险验证 lane。
175
+ 3. 直接向 runtime 回写 `accept`。
176
+ 4. 不向用户发送审批卡。
177
+ 5. 在 archive / timeline 记录 `approval_auto_resolved`,附带 `policy = local_self_validation` 或更细的 lane 原因。
178
+
179
+ ### 6.3 主路径 B:命中 remembered allow rule
180
+
181
+ 场景:某类命令不在默认自治白名单里,但用户之前已经明确允许过相同前缀。
182
+
183
+ 路径:
184
+
185
+ 1. runtime 发出 command approval request。
186
+ 2. bridge 按规则文件匹配到 `allow`。
187
+ 3. 直接向 runtime 回写 `accept`。
188
+ 4. 不向用户发送审批卡。
189
+ 5. 记录 `approval_auto_resolved`,`policy = rules_allow`,并带 `matched_rule`。
190
+
191
+ ### 6.4 主路径 C:命中 remembered forbidden rule
192
+
193
+ 场景:某类命令前缀已被规则标记为禁止。
194
+
195
+ 路径:
196
+
197
+ 1. runtime 发出 command approval request。
198
+ 2. bridge 匹配到 `forbidden`。
199
+ 3. 直接向 runtime 回写 `decline`。
200
+ 4. 不向用户发送审批卡。
201
+ 5. assistant 继续收到 runtime 的拒绝后果,前台只看到必要的失败结果或解释,不额外再发一张“要不要批准”卡。
202
+
203
+ ### 6.5 主路径 D:未命中规则,且不在低风险自治 lane
204
+
205
+ 场景:高风险、跨边界、未知命令。
206
+
207
+ 路径:
208
+
209
+ 1. runtime 发出 command approval request。
210
+ 2. bridge 先判断本地自治 lane,未命中。
211
+ 3. 再匹配规则文件,也未命中。
212
+ 4. 正常向用户发审批卡。
213
+
214
+ ### 6.6 规则写入路径
215
+
216
+ 先明确 V1 边界:
217
+
218
+ - V1 **不**在 Feishu 审批卡里提供“记住这次放行/拒绝”的前台写入入口。
219
+ - V1 先只做 rules 的读取、继承、匹配和自动处理,把“历史授权延续”这件事先收住。
220
+ - assistant-local rules 的默认写入路径先作为后续产品约束拍板,不要求本期就把前台入口做出来。
221
+
222
+ 当后续版本引入“记住这次放行/拒绝”类动作授权时:
223
+
224
+ 1. 默认写入 assistant 本地 `<assistant-codex-home>/rules/default.rules`。
225
+ 2. 不默认写入全局 `~/.codex/rules/default.rules`。
226
+ 3. 只有明确的全局管理动作,才允许修改全局规则。
227
+
228
+ 产品判断:
229
+
230
+ - assistant 是按项目长期驻留的,规则记忆默认也应跟 assistant 走。
231
+ - 全局 rules 仍可被持续读取并生效,但不应被普通日常审批顺手污染。
232
+
233
+ ### 6.7 规则继承语义
234
+
235
+ 必须明确:
236
+
237
+ 1. `work-ally` 对全局 `~/.codex/rules/*.rules` 的使用是**持续继承**,不是“创建 assistant 时复制快照”。
238
+ 2. assistant 创建、绑定或重启后,仍应看到最新的全局 rules 变化。
239
+ 3. assistant-local rules 是增量覆盖层,不是全局 rules 的替代副本。
240
+
241
+ 产品语义上,这意味着:
242
+
243
+ - 用户在官方 Codex 里已经放行过的前缀授权,不应因为切到 Feishu / work-ally 就失效。
244
+ - 用户后来新增、修改或撤销的全局规则,也应在 `work-ally` 里继续反映出来。
245
+
246
+ ## 7. 机制设计
247
+
248
+ ### 7.1 规则源与事实层级
249
+
250
+ V1 读取两层规则:
251
+
252
+ 1. 全局规则目录:`~/.codex/rules/`
253
+ 2. assistant 本地规则目录:`<assistant-codex-home>/rules/`
254
+
255
+ 读取规则:
256
+
257
+ - 只关心 `*.rules`
258
+ - 按文件名稳定排序后加载
259
+ - assistant 本地规则优先级高于全局规则
260
+ - 全局规则目录不是 assistant 创建时的模板来源,而是运行时持续继承的事实源
261
+
262
+ 理由:
263
+
264
+ - 全局 rules 适合个人通用偏好
265
+ - assistant 本地 rules 适合项目/助理特定偏好
266
+ - 本地应能覆盖全局,而不是反过来
267
+ - 只有把全局 rules 当持续事实源,而不是 copy-on-create 快照,才能避免官方 Codex 与 work-ally 两边授权历史割裂
268
+
269
+ ### 7.1.1 加载时机
270
+
271
+ 实现目标不是“每次审批都重新扫磁盘”,而是“语义上持续继承”。
272
+
273
+ V1 可接受的实现方式:
274
+
275
+ 1. bridge / runtime 启动时加载当前全局 + assistant-local rules。
276
+ 2. assistant 重启后必须重新看到最新的全局 rules。
277
+ 3. V1 **不要求**运行中的 bridge 在用户改动全局 rules 后立即热生效;只要求 assistant 重启后必须继承最新变化。
278
+ 4. 如后续成本允许,可再补简单热重载或基于 mtime 的刷新;但无论如何,不能退化成 assistant 创建时复制一份后长期脱钩。
279
+
280
+ 这条要求的重点是产品语义:
281
+
282
+ - **允许缓存**
283
+ - **V1 允许“运行中不热更新,但重启后更新”**
284
+ - **不允许 copy-on-create 分叉**
285
+
286
+ ### 7.2 支持的规则子集
287
+
288
+ V1 只支持 `prefix_rule`:
289
+
290
+ - `pattern=[...]`
291
+ - `decision="allow" | "prompt" | "forbidden"`
292
+
293
+ 不支持的语法:
294
+
295
+ - 其他非审批相关 experimental 规则形式
296
+ - 无法稳定映射到 command approval 的复杂表达式
297
+
298
+ 对于无法解析的行:
299
+
300
+ - 忽略该行
301
+ - 写 debug / warn 日志
302
+ - 不让整份 rules 文件失效
303
+
304
+ ### 7.3 命令匹配模型
305
+
306
+ 规则匹配对象是 runtime approval 提供的实际命令。
307
+
308
+ 匹配要求:
309
+
310
+ 1. 先做 shell unwrap,把 `/bin/zsh -lc '...'` 这类外壳剥掉到内部命令串。
311
+ 2. 若能安全切分出命令前缀,则按 argv 前缀匹配。
312
+ 3. 若历史 rules 本身就是对完整 shell wrapper 的前缀授权,V1 必须优先兼容这类真实历史资产;此时允许对原始命令串做保守前缀匹配,而不是强行 unwrap 后导致历史授权失效。
313
+ 4. 若命令包含复杂 shell 运算符、heredoc 或其他不适合前缀拆解的结构,则 V1 只做保守匹配:
314
+ - 规则命中必须足够明确
315
+ - 不能因为模糊匹配误放高风险命令
316
+
317
+ 产品原则:
318
+
319
+ - 宁可复杂命令回落到人工审批,也不能为了“多自动一点”而把不该放的命令误放。
320
+ - 但也不能因为实现只认 unwrap 后的 argv,就把用户已经在官方 Codex 里积累的 shell-wrapper 前缀授权整批作废。
321
+
322
+ ### 7.4 低风险验证 lane 扩展
323
+
324
+ 在现有 `local_self_validation` 基础上扩展支持至少以下类别:
325
+
326
+ - `cmake -S ... -B ...`
327
+ - `cmake --build ...`
328
+ - `ctest ...`
329
+ - `pytest ...`
330
+ - `cargo test ...`
331
+ - `cargo check ...`
332
+ - `flutter analyze`
333
+ - `dart test`
334
+ - 其他已经在仓库维护流程里稳定出现、且明确属于本地只读/本地验证的命令
335
+
336
+ 约束:
337
+
338
+ 1. `cwd` 必须位于当前项目根或 assistant desk 根内。
339
+ 2. 命令不得命中高风险黑名单。
340
+ 3. 对 shell 复合命令,只有当每个 segment 都属于低风险验证命令时才自动放行。
341
+
342
+ ### 7.5 决策优先级
343
+
344
+ 命令审批到达后的判断顺序固定为:
345
+
346
+ 1. 高风险黑名单校验
347
+ 2. 本地低风险验证 lane
348
+ 3. rules 匹配
349
+ 4. 默认人工审批
350
+
351
+ 其中:
352
+
353
+ - 高风险黑名单始终优先于 allow rule
354
+ - assistant 本地 rules 优先于全局 rules
355
+ - `forbidden` 优先于 `prompt`
356
+ - `allow` 只在没有更高优先级阻断时生效
357
+
358
+ ### 7.6 记录与可观测性
359
+
360
+ 新增或补齐以下审计信息:
361
+
362
+ - `approval_auto_resolved` 带 `policy = local_self_validation | rules_allow`
363
+ - `approval_auto_declined` 带 `policy = rules_forbidden`
364
+ - 规则命中时记录 `matched_rule` 与 `rule_source = assistant | global`
365
+ - 规则解析失败时写 warn 日志,但不打断正常运行
366
+ - `/status` 或排障输出里至少应能说明当前规则是否来自 global / assistant-local 两层,以避免用户误以为 work-ally 只看本地快照
367
+
368
+ ### 7.7 与现有 config 的关系
369
+
370
+ 当前的 `WORK_ALLY_MCP_TOOL_APPROVAL_ALLOWLIST` 继续只服务 MCP tool approval。
371
+
372
+ 本次新增的是 command approval 的 `.rules` 读取与匹配,不把两者混成一个统一 env 变量。
373
+
374
+ ### 7.8 V1 实现护栏
375
+
376
+ 这条专题很容易在“用户确实很痛”这个前提下,顺手把中间层做厚。为了守住 `work-ally` 的产品边界,V1 必须遵守以下护栏:
377
+
378
+ 1. **V1 只做 rules 的读取、继承、匹配与自动处理,不做 rules 写入能力。**
379
+ - 不新增 Feishu 前台“记住这次”入口。
380
+ - 不顺手补内部写入接口、双向同步逻辑或规则编辑器。
381
+ 2. **V1 只兼容官方 `prefix_rule` 的最小稳定子集。**
382
+ - 只支持 `allow / prompt / forbidden`。
383
+ - 不扩展自定义 DSL,不发明第二套规则语法。
384
+ 3. **V1 只要求启动加载,不要求运行中热更新。**
385
+ - 可以缓存。
386
+ - assistant 重启后必须看到最新 global rules。
387
+ - 不要求文件监听、增量同步、冲突合并。
388
+ 4. **本地低风险验证 lane 只收典型、通用、长期稳定的本地验证命令。**
389
+ - 不把 repo-specific 命令不断塞进 core 白名单。
390
+ - 若某项目需要额外放行,应优先通过继承的 global rules 或后续的 assistant-local rules 承接,而不是继续加厚 bridge 核心。
391
+ 5. **遇到无法安全判断的命令,宁可回落人工审批,也不靠更多中间层聪明度硬吃。**
392
+
393
+ 一句话护栏:
394
+
395
+ > 这次 feature 的目标是让 `work-ally` 更好地复用官方已有授权事实,并补一条最小本地验证自治 lane;不是把 bridge 发展成一套新的权限平台。
396
+
397
+ ## 8. 验收标准
398
+
399
+ 满足以下条件才算完成:
400
+
401
+ 1. assistant 在当前项目根 / assistant desk 根内运行典型 build/test/lint/diagnostics 命令时,不再向用户反复发审批卡。
402
+ 2. `cmake` / `ctest` 至少被纳入默认低风险验证 lane,并有自动化测试覆盖。
403
+ 3. bridge 能成功读取全局 `~/.codex/rules/*.rules` 与 assistant 本地 `rules/*.rules`。
404
+ 4. assistant 创建后,如果全局 rules 后续发生变化,assistant 重启后仍能继承最新变化,而不是停留在创建时快照。
405
+ 5. 命中 `allow` 规则的命令审批会被自动放行,不向用户发卡。
406
+ 6. 命中 `forbidden` 规则的命令审批会被自动拒绝,不向用户发卡。
407
+ 7. assistant 本地 rules 与全局 rules 冲突时,本地优先。
408
+ 8. 规则解析失败不会导致 bridge 崩溃,也不会让所有审批失效。
409
+ 9. archive / timeline 中能区分:本地安全默认自动放行、rules 自动放行、rules 自动拒绝、人工审批。
410
+ 10. README / quickstart / troubleshooting 同步更新,明确解释规则来源、持续继承语义、默认优先级与本地验证 lane。
411
+ 11. V1 不提供 Feishu 前台“记住这次”写入入口,但文档需明确这是后续能力,而不是遗漏。
412
+
413
+ ## 9. 验证建议
414
+
415
+ 至少补以下验证:
416
+
417
+ - unit:`.rules` 文件解析与无效行容错
418
+ - unit:命令前缀匹配优先级(assistant local > global)
419
+ - unit:`allow / forbidden / prompt` 三种命中结果
420
+ - unit:`cmake` / `ctest` / `pytest` 等命令被识别为低风险本地验证
421
+ - integration:命中 local_self_validation 时不发审批卡
422
+ - integration:命中 assistant-local rule allow 时不发审批卡
423
+ - integration:命中 global rule allow 且本地无覆盖时不发审批卡
424
+ - integration:命中 local forbidden 覆盖 global allow 时自动拒绝
425
+ - integration:未命中规则且不在自治 lane 时仍发人工审批卡
426
+ - integration:assistant 创建后新增一条 global rule,重启后仍能生效,证明不是 copy-on-create
427
+ - integration:重启后仍可继续读取相同 rules 生效
428
+ - integration:历史 global rule 若以完整 shell wrapper 为前缀,V1 仍能命中并延续既有授权
429
+
430
+ ## 10. 风险 / 假设 / 待决问题
431
+
432
+ ### 10.1 风险
433
+
434
+ - 如果对复杂 shell 命令的前缀解析过于激进,可能误放高风险命令。
435
+ - 如果低风险验证 lane 过宽,可能把带副作用的本地命令错归到自治路径。
436
+ - 如果文档不讲清楚“默认写 assistant-local rules”,用户可能误以为所有 remembered approvals 都是全局共享。
437
+ - 如果实现偷懒做成 assistant 创建时复制全局 rules,用户在官方 Codex 与 work-ally 间切换时会立即感受到授权历史割裂。
438
+ - 如果 V1 对历史 shell-wrapper 规则兼容不够,文档虽然声称“持续继承 global rules”,实际仍会丢掉一部分最有价值的历史授权资产。
439
+
440
+ ### 10.2 假设
441
+
442
+ - 官方 `.rules` 的 `prefix_rule` 语法在短期内足够稳定,至少可作为 `work-ally` 的兼容基础。
443
+ - 对 `work-ally` 的长期协作模型来说,assistant-local 规则比全局规则更符合产品语义。
444
+ - 用户对“同一个项目在官方 Codex 里已经放行过的前缀,在 work-ally 里也应继续有效”有强一致预期。
445
+
446
+ ### 10.3 待决问题
447
+
448
+ 1. 是否需要单独增加一条命令查看当前生效 rules 来源与命中结果,方便排障。
449
+ 2. 除 `cmake/ctest/pytest/cargo/flutter` 外,是否需要同步纳入更多团队常用本地验证命令。
450
+ 3. 后续若增加 Feishu 前台“记住这次”入口,是否还要支持写入全局 rules 的显式高级选项。
@@ -0,0 +1,199 @@
1
+ # Assistant Persona Bootstrap
2
+
3
+ 更新时间:2026-03-21
4
+ 状态:Superseded by `SPEC-remove-cli-persona-bootstrap.md`
5
+
6
+ ## 0. 状态说明
7
+
8
+ 本 spec 已被新的“删除 CLI persona bootstrap”方案取代。当前不应再按本文件继续实现 persona 参数能力;后续请改看 `docs/completed/SPEC-remove-cli-persona-bootstrap.md`。
9
+
10
+ ## 1. 背景
11
+
12
+ 当前 `ally setup <name>` 已经能把 assistant desk、最小配置和默认 `SOUL.md` 一次性创建出来。
13
+
14
+ 但在真实使用里还有一个明显摩擦点:
15
+
16
+ > 用户刚创建完 assistant,往往立刻就想把“这个人是谁、说话什么风格、做事像谁”一起定义掉。
17
+
18
+ 现在的路径要求用户:
19
+
20
+ 1. 先完成 `ally setup`
21
+ 2. 再理解 assistant desk 的存在
22
+ 3. 再手动打开 `SOUL.md`
23
+ 4. 再自己编辑人格内容
24
+
25
+ 这条路径对维护者是合理的,对普通使用者和新来的协作者并不自然。
26
+
27
+ ## 2. 问题定义
28
+
29
+ 当前缺口不是“没有 `SOUL.md`”,而是**缺少一个面向用户的人设输入层**。
30
+
31
+ 具体问题有三点:
32
+
33
+ ### 2.1 用户意图发生得比 desk 概念更早
34
+
35
+ 用户一上来最关心的是:
36
+
37
+ - 他叫什么
38
+ - 他是什么角色
39
+ - 他说话是什么感觉
40
+ - 有没有一句稳定签名
41
+
42
+ 而不是:
43
+
44
+ - `SOUL.md` 在哪个目录
45
+ - 是否需要打开 hidden desk 改 Markdown
46
+
47
+ ### 2.2 当前产品把人格编辑暴露成了文件操作
48
+
49
+ 虽然底层资产用文件表达是对的,但这不应该变成普通用户的第一交互负担。
50
+
51
+ 对用户来说,应该是:
52
+
53
+ - 我提供一段 persona
54
+ - 产品替我落进正确的长期资产
55
+
56
+ 而不是:
57
+
58
+ - 我自己去理解并编辑某个内部文件
59
+
60
+ ### 2.3 不能为了“结构化”把简单问题复杂化
61
+
62
+ 用户描述 persona 时,往往天然就是自然语言:
63
+
64
+ - 男性、架构师、冷静、一针见血
65
+ - 名字叫 Ramond
66
+ - 个性签名是某一句话
67
+
68
+ 如果产品一开始要求用户理解复杂 schema,例如 `role`、`tone`、`signature`、`gender` 之类的独立字段,成本反而更高。
69
+
70
+ ## 3. 目标
71
+
72
+ 在 assistant 创建阶段提供一个**自然语言 persona 输入能力**,让用户可以在 `ally setup` 时一次性把 assistant 的基础人设写进去。
73
+
74
+ 目标是:
75
+
76
+ 1. 普通用户无需先理解 hidden desk
77
+ 2. 用户无需直接编辑 `SOUL.md` 才能定义 assistant 人设
78
+ 3. 最终人格资产仍然沉淀到标准 `SOUL.md`
79
+ 4. 命令语义保持简单,不引入重型 schema
80
+
81
+ ## 4. 非目标
82
+
83
+ 本次不做:
84
+
85
+ - 自动 AI 生成人设
86
+ - 多套 persona 模板市场
87
+ - 细粒度 schema 化字段设计(如单独 `--role`、`--tone`、`--signature`)
88
+ - 独立 persona 管理面板
89
+ - 已创建 assistant 的交互式 persona 编辑器
90
+
91
+ ## 5. 用户场景
92
+
93
+ ### 场景 A:创建时直接给一句人设
94
+
95
+ 用户希望这样做:
96
+
97
+ ```bash
98
+ ally setup ramond --persona "男性、架构师、专业、冷静、一针见血。个性签名:系统千变万化,底层逻辑如一。专注构建优雅的跨平台基石。"
99
+ ```
100
+
101
+ 系统应完成:
102
+
103
+ - 创建 assistant desk
104
+ - 生成标准 `SOUL.md`
105
+ - 将这段 persona 注入 `SOUL.md` 的用户补充区域
106
+
107
+ ### 场景 B:人设内容较长,希望从文件导入
108
+
109
+ 用户可以这样做:
110
+
111
+ ```bash
112
+ ally setup ramond --persona-file ./ramond-persona.txt
113
+ ```
114
+
115
+ 系统应读取文本文件,并按与 `--persona` 相同的方式写入 `SOUL.md`。
116
+
117
+ ## 6. 产品定义
118
+
119
+ ### 6.1 对外命令语义
120
+
121
+ 新增两个参数:
122
+
123
+ - `--persona <text>`
124
+ - `--persona-file <path>`
125
+
126
+ 支持位置:
127
+
128
+ - `ally setup <name>`
129
+ - `ally assistant add <name>`
130
+ - `ally assistant ensure <name>`
131
+
132
+ ### 6.2 参数规则
133
+
134
+ - `--persona` 与 `--persona-file` 二选一,不允许同时传
135
+ - `--persona-file` 必须指向本地可读文本文件
136
+ - 传入空白内容视为无效输入,应直接报错
137
+
138
+ ### 6.3 对内资产规则
139
+
140
+ 对外暴露的是 persona,项目内部真实资产仍是 `SOUL.md`。
141
+
142
+ 也就是说:
143
+
144
+ - 不新增新的 persona 存储文件
145
+ - 不绕开 `SOUL.md`
146
+ - 不把 persona 只写进 registry description
147
+
148
+ ### 6.4 `SOUL.md` 写入策略
149
+
150
+ 默认模板继续保留。
151
+
152
+ persona 写入方式:
153
+
154
+ - 注入到 `SOUL.md` 里清晰的“用户补充设定”区域
155
+ - 不覆盖默认模板中的基础产品纪律
156
+ - 若该区域已存在且当前命令显式传入了 persona,则以新 persona 覆盖旧 persona 区域
157
+
158
+ 这意味着:
159
+
160
+ - `ally setup ramond --persona ...` 可以一次成型
161
+ - `ally assistant ensure ramond --persona ...` 可以更新 persona
162
+
163
+ ## 7. 核心产品判断
164
+
165
+ ### 7.1 用户输入的是“人设”,不是“文件”
166
+
167
+ `SOUL.md` 是正确的长期资产,但它属于实现和资产层,不应该成为普通用户的首要概念。
168
+
169
+ ### 7.2 先接受自然语言,再由中间层结构化
170
+
171
+ V1 应优先接受自然语言 persona,而不是要求用户学习结构化参数。
172
+
173
+ ### 7.3 中间层要吃掉复杂性,但不替用户发明人格
174
+
175
+ 产品负责把 persona 落到正确资产中;不负责擅自扩写、润色或改写用户输入的人设核心语义。
176
+
177
+ ## 8. 验收标准
178
+
179
+ 1. `ally setup <name> --persona "..."` 能成功创建 assistant,并把 persona 写入 `SOUL.md`
180
+ 2. `ally setup <name> --persona-file <path>` 能成功读取文件并写入 `SOUL.md`
181
+ 3. `--persona` 与 `--persona-file` 同时传入时明确报错
182
+ 4. 空 persona 或空文件内容时明确报错
183
+ 5. 默认模板中的基础人格纪律仍保留,不会被 persona 覆盖掉整份 `SOUL.md`
184
+ 6. `ally assistant ensure <name> --persona "..."` 能更新已有 assistant 的 persona 区域
185
+ 7. `docs/user-quickstart.md` 能直接指导用户完成“带 persona 招人”
186
+
187
+ ## 9. 建议实现点
188
+
189
+ 1. 在 shell 入口为 `setup` 与 `assistant add|ensure` 增加 persona 参数解析
190
+ 2. 在 assistant bootstrap 层增加 persona 文本归一化与注入逻辑
191
+ 3. 为 `SOUL.md` 模板增加稳定的“用户补充设定”区域标记
192
+ 4. 补 shell 回归测试覆盖 setup / ensure / persona-file 场景
193
+ 5. 同步更新 quickstart、README、manual acceptance、troubleshooting
194
+
195
+ ## 10. 风险与边界
196
+
197
+ - 若 persona 中包含复杂 Markdown,V1 不保证做富格式保真,只保证文本稳定落库
198
+ - 若 persona-file 不是文本文件,V1 直接按读取失败处理,不做编码探测增强
199
+ - 若用户后续手工编辑 `SOUL.md`,产品不阻止;但再次显式传 persona 时,会只覆盖 persona 区域,不重写整份文件