@michelj/context-guard 0.4.3 → 0.6.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 (161) hide show
  1. package/Coordinator.md +88 -0
  2. package/Executor.md +53 -0
  3. package/README.md +89 -224
  4. package/README.zh-CN.md +89 -224
  5. package/SKILL.md +26 -684
  6. package/THIRD_PARTY_NOTICES.md +47 -0
  7. package/Tester.md +53 -0
  8. package/agents/openai.yaml +2 -2
  9. package/bin/build-runtime.mjs +96 -0
  10. package/bin/context-guard-skill.js +399 -78
  11. package/bin/postinstall.js +2 -2
  12. package/hooks.json +89 -13
  13. package/licenses/JSONParse-MIT.txt +24 -0
  14. package/licenses/Marked-MIT.txt +44 -0
  15. package/licenses/Portless-Apache-2.0.txt +201 -0
  16. package/package.json +35 -6
  17. package/prototype/LICENSES/Marked-MIT.txt +44 -0
  18. package/prototype/LICENSES/Ready-redistribution.txt +14 -0
  19. package/prototype/attachments.mjs +75 -0
  20. package/prototype/coordinator-markdown.mjs +283 -0
  21. package/prototype/coordinator-working-blot.mjs +124 -0
  22. package/prototype/vendor/marked.mjs +2189 -0
  23. package/prototype/workbench-app.js +5197 -0
  24. package/prototype/workbench-data.js +33 -0
  25. package/prototype/workbench-sync.mjs +898 -0
  26. package/prototype/workbench.css +1050 -0
  27. package/prototype/workbench.html +211 -0
  28. package/prototype/working-blot-atlas.png +0 -0
  29. package/references/agent-handoff.md +40 -0
  30. package/references/claude-runtime.md +120 -0
  31. package/references/cloud-sync-interface.md +66 -0
  32. package/references/design-current.md +14 -0
  33. package/references/map-mount.md +41 -0
  34. package/references/map-read.md +50 -0
  35. package/references/memory-definition.md +120 -0
  36. package/references/memory-filesystem-v2/Bug.en.md +162 -0
  37. package/references/memory-filesystem-v2/Bug.md +162 -0
  38. package/references/memory-filesystem-v2/Bug_Coordinater.md +8 -0
  39. package/references/memory-filesystem-v2/Bug_Executor.md +8 -0
  40. package/references/memory-filesystem-v2/Bug_Tester.md +7 -0
  41. package/references/memory-filesystem-v2/Idea.en.md +36 -0
  42. package/references/memory-filesystem-v2/Idea.md +36 -0
  43. package/references/memory-filesystem-v2/Node_Module_Index.en.md +88 -0
  44. package/references/memory-filesystem-v2/Node_Module_Index.md +88 -0
  45. package/references/memory-filesystem-v2/README.md +60 -0
  46. package/references/memory-filesystem-v2/Todo.en.md +137 -0
  47. package/references/memory-filesystem-v2/Todo.md +137 -0
  48. package/references/memory-filesystem-v2/Todo_Coordinater.md +7 -0
  49. package/references/memory-filesystem-v2/Todo_Executor.md +7 -0
  50. package/references/memory-filesystem-v2/Todo_Tester.md +7 -0
  51. package/references/named-workbench.md +124 -0
  52. package/references/plan-review.md +12 -0
  53. package/references/server-memory.md +276 -0
  54. package/references/test-check.md +7 -0
  55. package/references/user-reply.md +38 -0
  56. package/references/workbench-interface.md +531 -0
  57. package/roles.md +13 -0
  58. package/scripts/context_guard.py +1366 -7602
  59. package/scripts/context_guard_hook.py +1960 -711
  60. package/scripts/map_owns.py +699 -0
  61. package/scripts/shared/LICENSES/JSONParse-MIT.txt +24 -0
  62. package/scripts/shared/filesystem-v2.mjs +430 -0
  63. package/scripts/shared/io.mjs +117 -0
  64. package/scripts/shared/map-model.mjs +506 -0
  65. package/scripts/shared/memory-schema.mjs +13 -0
  66. package/scripts/shared/protocol-blobs.mjs +112 -0
  67. package/scripts/shared/protocol-map.mjs +146 -0
  68. package/scripts/shared/protocol-snapshots.mjs +84 -0
  69. package/scripts/shared/protocol-store.mjs +624 -0
  70. package/scripts/shared/protocol-workflow.mjs +226 -0
  71. package/scripts/shared/protocol.mjs +125 -0
  72. package/scripts/shared/vendor/jsonparse.cjs +413 -0
  73. package/scripts/workbench/access.mjs +496 -0
  74. package/scripts/workbench/attachments.mjs +92 -0
  75. package/scripts/workbench/browser-login.mjs +78 -0
  76. package/scripts/workbench/claude-runtime.mjs +372 -0
  77. package/scripts/workbench/cli.mjs +980 -0
  78. package/scripts/workbench/device-heartbeat.mjs +72 -0
  79. package/scripts/workbench/hook-status.mjs +38 -0
  80. package/scripts/workbench/inbox.mjs +155 -0
  81. package/scripts/workbench/journal.mjs +56 -0
  82. package/scripts/workbench/memory-merge.mjs +65 -0
  83. package/scripts/workbench/memory.mjs +252 -0
  84. package/scripts/workbench/named-proxy.mjs +108 -0
  85. package/scripts/workbench/named.mjs +152 -0
  86. package/scripts/workbench/portless-routes.mjs +51 -0
  87. package/scripts/workbench/project.mjs +327 -0
  88. package/scripts/workbench/projections.mjs +68 -0
  89. package/scripts/workbench/protocol-client.mjs +165 -0
  90. package/scripts/workbench/protocol-delivery.mjs +133 -0
  91. package/scripts/workbench/protocol-device.mjs +316 -0
  92. package/scripts/workbench/protocol-events.mjs +53 -0
  93. package/scripts/workbench/protocol-repository.mjs +58 -0
  94. package/scripts/workbench/reconcile.mjs +244 -0
  95. package/scripts/workbench/registry.mjs +111 -0
  96. package/scripts/workbench/runtime.mjs +54 -0
  97. package/scripts/workbench/server.mjs +1171 -0
  98. package/scripts/workbench/store.mjs +243 -0
  99. package/scripts/workbench/sync-coordinator.mjs +518 -0
  100. package/scripts/workbench/sync.mjs +86 -0
  101. package/references/context-template.md +0 -341
  102. package/references/feature-chain-methodology.md +0 -228
  103. package/references/register-template.md +0 -85
  104. package/references/task-case-template.md +0 -63
  105. package/tests/BC-20260618-063.sh +0 -116
  106. package/tests/BC-20260618-065.sh +0 -66
  107. package/tests/BC-20260626-080.sh +0 -48
  108. package/tests/BC-20260626-081.sh +0 -40
  109. package/tests/BC-20260626-082.sh +0 -32
  110. package/tests/BC-20260626-083.sh +0 -66
  111. package/tests/BC-20260627-084.sh +0 -74
  112. package/tests/BC-20260630-086.sh +0 -50
  113. package/tests/BC-20260630-087.sh +0 -103
  114. package/tests/BC-20260630-088.sh +0 -32
  115. package/tests/BC-20260630-089.sh +0 -63
  116. package/tests/BC-20260701-090.sh +0 -84
  117. package/tests/BC-20260702-096.sh +0 -48
  118. package/tests/BC-20260706-098.sh +0 -66
  119. package/tests/BC-20260707-099.sh +0 -47
  120. package/tests/BC-20260707-100.sh +0 -46
  121. package/tests/BC-20260707-101.sh +0 -47
  122. package/tests/BC-20260707-102.sh +0 -68
  123. package/tests/BC-20260707-103.sh +0 -59
  124. package/tests/BC-20260707-104.sh +0 -103
  125. package/tests/BC-20260707-105.sh +0 -109
  126. package/tests/BC-20260707-106.sh +0 -80
  127. package/tests/BC-20260707-107.sh +0 -74
  128. package/tests/BC-20260707-108.sh +0 -48
  129. package/tests/BC-20260707-109.sh +0 -56
  130. package/tests/BC-20260707-110.sh +0 -71
  131. package/tests/BC-20260707-111.sh +0 -70
  132. package/tests/BC-20260707-112.sh +0 -45
  133. package/tests/BC-20260707-113.sh +0 -73
  134. package/tests/BC-20260707-115.sh +0 -77
  135. package/tests/BC-20260707-116.sh +0 -77
  136. package/tests/BC-20260707-118.sh +0 -115
  137. package/tests/BC-20260707-119.sh +0 -47
  138. package/tests/BC-20260707-120.sh +0 -60
  139. package/tests/BC-20260707-121.sh +0 -66
  140. package/tests/BC-20260707-122.sh +0 -48
  141. package/tests/BC-20260707-123.sh +0 -43
  142. package/tests/BC-20260707-124.sh +0 -56
  143. package/tests/BC-20260707-125.sh +0 -64
  144. package/tests/BC-20260707-126.sh +0 -80
  145. package/tests/BC-20260707-127.sh +0 -88
  146. package/tests/BC-20260707-129.sh +0 -59
  147. package/tests/BC-20260707-130.sh +0 -69
  148. package/tests/BC-20260707-131.sh +0 -140
  149. package/tests/BC-20260707-132.sh +0 -150
  150. package/tests/BC-20260707-133.sh +0 -70
  151. package/tests/BC-20260708-136.sh +0 -210
  152. package/tests/BC-20260708-137.sh +0 -106
  153. package/tests/BC-20260708-138.sh +0 -168
  154. package/tests/BC-20260708-139.sh +0 -79
  155. package/tests/BC-20260709-002.sh +0 -63
  156. package/tests/BC-20260709-003.sh +0 -239
  157. package/tests/BC-20260709-006.sh +0 -76
  158. package/tests/BC-20260709-008.sh +0 -168
  159. package/tests/BC-20260710-001.sh +0 -61
  160. package/tests/BC-20260710-002.sh +0 -111
  161. package/tests/npm-install-smoke.sh +0 -53
@@ -1,70 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- SCRIPT="${1:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/scripts/context_guard.py}"
5
- ROOT="$(mktemp -d "${TMPDIR:-/tmp}/context-guard-dry-run-id-XXXXXX")"
6
- trap 'rm -rf "$ROOT"' EXIT
7
-
8
- python3 "$SCRIPT" init --root "$ROOT" >/dev/null
9
-
10
- cat >"$ROOT/.codex/context/bad-cases.md" <<'MD'
11
- ### BC-20260707-960: Dry-run 证据目录可能撞名
12
-
13
- - Status: resolved
14
- - First observed: 2026-07-07
15
- - Last checked: 2026-07-07
16
- - Scope: Context Guard Test Hub dry-run evidence
17
- - Tags: #feature-chain #test-hub #artifact-policy
18
- - Display summary: 快速连续 dry-run 不应把失败证据写到同一个目录。
19
- - Phenomenon: 秒级 run id 可能让同一条功能链的多次 dry-run 复用同一个 evidence path。
20
- - Trigger / reproduction: 快速连续运行两次失败的 `feature-chain-dry-run`。
21
- - Root cause: dry-run 目录名只使用秒级时间戳。
22
- - Fix method: dry-run/run 目录名改用微秒级唯一 run id。
23
- - Guard / verification: 快速连续失败 dry-run 应保留两个不同 evidence 目录。
24
- - Red condition: 两次失败 dry-run 输出相同 evidence preserved 路径。
25
- - Green condition: 两次失败 dry-run 输出不同 evidence preserved 路径,且目录都存在。
26
- - Expected failure reason: 证据路径撞名会覆盖或混杂失败日志,让 Codex 误判坏在哪个 checkpoint。
27
- MD
28
-
29
- PROPOSE_OUT="$ROOT/propose.out"
30
- python3 "$SCRIPT" feature-chain-propose \
31
- --root "$ROOT" \
32
- --title "Markdown 公式预览" \
33
- --entry "输入 Markdown 公式" \
34
- --exit-check "预览渲染公式" \
35
- --node-title "公式预览完成渲染" \
36
- --bad-cases "BC-20260707-960" \
37
- --check "公式预览必须完成渲染" >"$PROPOSE_OUT"
38
-
39
- CHAIN_ID="$(grep 'feature chain proposed:' "$PROPOSE_OUT" | awk '{print $NF}')"
40
- test -n "$CHAIN_ID"
41
-
42
- set +e
43
- python3 "$SCRIPT" feature-chain-dry-run \
44
- --root "$ROOT" \
45
- --chain-id "$CHAIN_ID" \
46
- --command-text "printf 'CG_CHECKPOINT:公式预览完成渲染:FAIL:第一次失败\\n'" >"$ROOT/fail-1.out" 2>&1
47
- STATUS_ONE=$?
48
- python3 "$SCRIPT" feature-chain-dry-run \
49
- --root "$ROOT" \
50
- --chain-id "$CHAIN_ID" \
51
- --command-text "printf 'CG_CHECKPOINT:公式预览完成渲染:FAIL:第二次失败\\n'" >"$ROOT/fail-2.out" 2>&1
52
- STATUS_TWO=$?
53
- set -e
54
-
55
- test "$STATUS_ONE" -ne 0
56
- test "$STATUS_TWO" -ne 0
57
-
58
- DIR_ONE="$(sed -n 's/.*dry-run evidence preserved: //p' "$ROOT/fail-1.out" | tail -n 1)"
59
- DIR_TWO="$(sed -n 's/.*dry-run evidence preserved: //p' "$ROOT/fail-2.out" | tail -n 1)"
60
- test -n "$DIR_ONE"
61
- test -n "$DIR_TWO"
62
- test "$DIR_ONE" != "$DIR_TWO"
63
- test -d "$DIR_ONE"
64
- test -d "$DIR_TWO"
65
-
66
- grep -q "第一次失败" "$DIR_ONE/$CHAIN_ID.log"
67
- grep -q "第二次失败" "$DIR_TWO/$CHAIN_ID.log"
68
-
69
- python3 "$SCRIPT" validate-feature-chains --root "$ROOT" >"$ROOT/validate.out"
70
- grep -q "feature-chain validation passed: 1 chain(s), 0 warning(s)" "$ROOT/validate.out"
@@ -1,210 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- SCRIPT="${1:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/scripts/context_guard.py}"
5
- ROOT="$(mktemp -d "${TMPDIR:-/tmp}/context-guard-multi-chain-XXXXXX")"
6
- trap 'rm -rf "$ROOT"' EXIT
7
-
8
- python3 "$SCRIPT" init --root "$ROOT" >/dev/null
9
- mkdir -p "$ROOT/.codex/context/test-hub/fixtures"
10
-
11
- cat >"$ROOT/.codex/context/bad-cases.md" <<'MD'
12
- ### BC-20260708-960: 晚间清单漏勾仍显示完成
13
-
14
- - Status: resolved
15
- - First observed: 2026-07-08
16
- - Last checked: 2026-07-08
17
- - Scope: Evening reset checklist
18
- - Tags: #feature-chain #life
19
- - Display summary: 晚间收纳清单不能在漏勾时显示完成。
20
- - Phenomenon: 用户只勾选部分事项,页面仍显示今晚重置完成。
21
- - Trigger / reproduction: 打开晚间重置清单,少勾一项后点击完成。
22
- - Root cause: 完成判断只看点击事件,没有检查全部事项。
23
- - Fix method: 完成前检查所有事项。
24
- - Guard / verification: 功能链 checkpoint 检查提前完成被阻止。
25
- - Red condition: 漏勾仍显示完成。
26
- - Green condition: 漏勾时提示未完成。
27
- - Expected failure reason: 完成判断回归时,生活清单功能链会失败。
28
-
29
- ### BC-20260708-961: 晚间清单完成后没有保存
30
-
31
- - Status: resolved
32
- - First observed: 2026-07-08
33
- - Last checked: 2026-07-08
34
- - Scope: Evening reset checklist
35
- - Tags: #feature-chain #life #persistence
36
- - Display summary: 晚间收纳清单完成后必须保存结果。
37
- - Phenomenon: 页面显示完成,但刷新或读取状态时没有保存完成记录。
38
- - Trigger / reproduction: 勾选全部事项并点击完成。
39
- - Root cause: UI 状态更新后没有写入 localStorage。
40
- - Fix method: 完成时写入 completed/count/total。
41
- - Guard / verification: 功能链 checkpoint 检查完成结果已保存。
42
- - Red condition: 完成后没有保存状态。
43
- - Green condition: 完成后保存 completed=true 且数量正确。
44
- - Expected failure reason: 保存回归时,生活清单功能链会失败。
45
-
46
- ### BC-20260708-962: 角色卡空白名字生成空主角
47
-
48
- - Status: resolved
49
- - First observed: 2026-07-08
50
- - Last checked: 2026-07-08
51
- - Scope: Story character card generator
52
- - Tags: #feature-chain #creative
53
- - Display summary: 角色卡生成器不能把空白名字直接写成空主角。
54
- - Phenomenon: 用户没填角色名时,生成文本出现空主角字段。
55
- - Trigger / reproduction: 只填写少量线索并点击生成角色卡。
56
- - Root cause: 输入规范化缺失。
57
- - Fix method: 空白角色名使用可读默认名。
58
- - Guard / verification: 功能链 checkpoint 检查输入被规范化。
59
- - Red condition: 空白角色名进入最终文本。
60
- - Green condition: 空白角色名被规范化为可读默认名。
61
- - Expected failure reason: 输入规范化回归时,创作工具功能链会失败。
62
-
63
- ### BC-20260708-963: 角色卡重复生成不稳定
64
-
65
- - Status: resolved
66
- - First observed: 2026-07-08
67
- - Last checked: 2026-07-08
68
- - Scope: Story character card generator
69
- - Tags: #feature-chain #creative #determinism
70
- - Display summary: 相同线索重复生成角色卡时输出应稳定。
71
- - Phenomenon: 用户用相同线索重复点击生成,角色卡文本不断变化。
72
- - Trigger / reproduction: 相同输入连续点击生成角色卡。
73
- - Root cause: 输出生成缺少稳定规则。
74
- - Fix method: 对同一输入使用确定性结构。
75
- - Guard / verification: 功能链 checkpoint 检查最终文本稳定可复制。
76
- - Red condition: 同一输入重复生成不同结果。
77
- - Green condition: 同一输入重复生成完全一致。
78
- - Expected failure reason: 稳定性回归时,创作工具功能链会失败。
79
- MD
80
-
81
- propose_life="$ROOT/propose-life.out"
82
- python3 "$SCRIPT" feature-chain-propose \
83
- --root "$ROOT" \
84
- --title "晚间收纳重置" \
85
- --entry "勾选晚间收纳事项并点击完成" \
86
- --exit-check "页面显示 3/3 完成并保存状态" \
87
- --node-title "阻止提前完成" \
88
- --bad-cases "BC-20260708-960" \
89
- --check "漏勾任一事项时不能显示完成" >"$propose_life"
90
- life_id="$(grep 'feature chain proposed:' "$propose_life" | awk '{print $NF}')"
91
- test -n "$life_id"
92
-
93
- python3 "$SCRIPT" feature-chain-attach-bc \
94
- --root "$ROOT" \
95
- --chain-id "$life_id" \
96
- --node-title "保存完成结果" \
97
- --bad-case "BC-20260708-961" \
98
- --check "完成后必须保存 completed=true 且 count=3 total=3" >/dev/null
99
-
100
- propose_story="$ROOT/propose-story.out"
101
- python3 "$SCRIPT" feature-chain-propose \
102
- --root "$ROOT" \
103
- --title "故事角色卡生成" \
104
- --entry "填写线索并点击生成角色卡" \
105
- --exit-check "生成稳定、完整、可复制的角色卡" \
106
- --node-title "输入被规范化" \
107
- --bad-cases "BC-20260708-962" \
108
- --check "空白角色名必须被规范化为可读默认名" >"$propose_story"
109
- story_id="$(grep 'feature chain proposed:' "$propose_story" | awk '{print $NF}')"
110
- test -n "$story_id"
111
-
112
- python3 "$SCRIPT" feature-chain-attach-bc \
113
- --root "$ROOT" \
114
- --chain-id "$story_id" \
115
- --node-title "最终文本稳定可复制" \
116
- --bad-case "BC-20260708-963" \
117
- --check "同一输入重复生成必须输出一致" >/dev/null
118
-
119
- life_runner="$ROOT/.codex/context/test-hub/fixtures/life_chain.sh"
120
- story_runner="$ROOT/.codex/context/test-hub/fixtures/story_chain.sh"
121
-
122
- cat >"$life_runner" <<'SH'
123
- #!/usr/bin/env bash
124
- set -euo pipefail
125
- echo "CG_CHECKPOINT:阻止提前完成:PASS"
126
- echo "CG_CHECKPOINT:保存完成结果:PASS"
127
- SH
128
- chmod +x "$life_runner"
129
-
130
- cat >"$story_runner" <<'SH'
131
- #!/usr/bin/env bash
132
- set -euo pipefail
133
- echo "CG_CHECKPOINT:输入被规范化:PASS"
134
- echo "CG_CHECKPOINT:最终文本稳定可复制:PASS"
135
- SH
136
- chmod +x "$story_runner"
137
-
138
- python3 "$SCRIPT" feature-chain-approve \
139
- --root "$ROOT" \
140
- --chain-id "$life_id" \
141
- --command-text "bash .codex/context/test-hub/fixtures/life_chain.sh" >"$ROOT/approve-life.out"
142
- grep -q "approval dry-run: passed" "$ROOT/approve-life.out"
143
-
144
- python3 "$SCRIPT" feature-chain-approve \
145
- --root "$ROOT" \
146
- --chain-id "$story_id" \
147
- --command-text "bash .codex/context/test-hub/fixtures/story_chain.sh" >"$ROOT/approve-story.out"
148
- grep -q "approval dry-run: passed" "$ROOT/approve-story.out"
149
-
150
- python3 "$SCRIPT" dev-complete --root "$ROOT" >"$ROOT/pass-two.out"
151
- grep -q "test hub: 2 passed, 0 failed, 0 blocked" "$ROOT/pass-two.out"
152
- grep -q "passed: 晚间收纳重置" "$ROOT/pass-two.out"
153
- grep -q "passed: 故事角色卡生成" "$ROOT/pass-two.out"
154
- grep -q "success artifacts cleaned" "$ROOT/pass-two.out"
155
-
156
- cat >"$story_runner" <<'SH'
157
- #!/usr/bin/env bash
158
- set -euo pipefail
159
- echo "CG_CHECKPOINT:输入被规范化:PASS"
160
- echo "CG_CHECKPOINT:最终文本稳定可复制:FAIL:相同线索重复生成了不同角色卡"
161
- printf "story output drifted\n" > "$CONTEXT_GUARD_TEST_RUN_DIR/story-drift.txt"
162
- SH
163
- chmod +x "$story_runner"
164
-
165
- if python3 "$SCRIPT" dev-complete --root "$ROOT" >"$ROOT/fail-one.out" 2>&1; then
166
- cat "$ROOT/fail-one.out"
167
- exit 1
168
- fi
169
- grep -q "test hub: 1 passed, 1 failed, 0 blocked" "$ROOT/fail-one.out"
170
- grep -q "passed: 晚间收纳重置" "$ROOT/fail-one.out"
171
- grep -q "failed: 故事角色卡生成 (checkpoint failed: 最终文本稳定可复制 - 相同线索重复生成了不同角色卡)" "$ROOT/fail-one.out"
172
- grep -q "evidence preserved" "$ROOT/fail-one.out"
173
-
174
- python3 - "$ROOT/.codex/context/test-hub/last-run.json" <<'PY'
175
- from pathlib import Path
176
- import json
177
- import sys
178
-
179
- run = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
180
- results = {item["title"]: item for item in run["results"]}
181
- assert results["晚间收纳重置"]["status"] == "passed", results
182
- story = results["故事角色卡生成"]
183
- assert story["status"] == "failed", story
184
- assert story["reason"] == "checkpoint failed: 最终文本稳定可复制 - 相同线索重复生成了不同角色卡", story
185
- assert [c["label"] for c in story["checkpoints"]] == ["输入被规范化", "最终文本稳定可复制"], story
186
- evidence = Path(story["log"]).parent / "story-drift.txt"
187
- assert evidence.exists(), evidence
188
- assert "story output drifted" in evidence.read_text(encoding="utf-8")
189
- PY
190
-
191
- cat >"$story_runner" <<'SH'
192
- #!/usr/bin/env bash
193
- set -euo pipefail
194
- echo "CG_CHECKPOINT:输入被规范化:PASS"
195
- echo "CG_CHECKPOINT:最终文本稳定可复制:PASS"
196
- SH
197
- chmod +x "$story_runner"
198
-
199
- python3 "$SCRIPT" dev-complete --root "$ROOT" >"$ROOT/final-pass.out"
200
- grep -q "test hub: 2 passed, 0 failed, 0 blocked" "$ROOT/final-pass.out"
201
- grep -q "success artifacts cleaned" "$ROOT/final-pass.out"
202
-
203
- python3 "$SCRIPT" feature-chain-summary --root "$ROOT" >"$ROOT/summary.out"
204
- grep -q "chains: 2" "$ROOT/summary.out"
205
- grep -q "covered bad cases: 4" "$ROOT/summary.out"
206
- grep -q "coverage density: 2.0 bad case(s) per covered chain" "$ROOT/summary.out"
207
- grep -q "reuse signal: one workflow covers up to 2 bad case(s)" "$ROOT/summary.out"
208
-
209
- python3 "$SCRIPT" validate-feature-chains --root "$ROOT" >"$ROOT/validate.out"
210
- grep -q "feature-chain validation passed: 2 chain(s), 0 warning(s)" "$ROOT/validate.out"
@@ -1,106 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- SCRIPT="${1:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/scripts/context_guard.py}"
5
- HOOK="$(cd "$(dirname "$SCRIPT")" && pwd)/context_guard_hook.py"
6
- SMALL_ROOT="$(mktemp -d "${TMPDIR:-/tmp}/context-guard-auto-chain-small-XXXXXX")"
7
- LARGE_ROOT="$(mktemp -d "${TMPDIR:-/tmp}/context-guard-auto-chain-large-XXXXXX")"
8
- trap 'rm -rf "$SMALL_ROOT" "$LARGE_ROOT"' EXIT
9
-
10
- python3 "$SCRIPT" init --root "$SMALL_ROOT" >/dev/null
11
- cat >"$SMALL_ROOT/.codex/context/bad-cases.md" <<'MD'
12
- ### BC-20260708-970: 次日没有自动重置
13
-
14
- - Status: resolved
15
- - First observed: 2026-07-08
16
- - Last checked: 2026-07-08
17
- - Scope: 晚间收纳重置清单
18
- - Tags: #life #reset
19
- - Display summary: 第二天打开清单时必须恢复为未完成状态。
20
- - Phenomenon: 昨天完成后,今天打开仍显示已完成。
21
- - Trigger / reproduction: 完成清单后把日期切到第二天再打开页面。
22
- - Root cause: 日期变化没有触发状态重置。
23
- - Fix method: 启动时比较日期并重置勾选状态。
24
- - Guard / verification: 自动功能链草案应把该问题归入收纳重置流程。
25
- - Red condition: 跨天后仍显示已完成。
26
- - Green condition: 跨天后清单恢复未完成。
27
- - Expected failure reason: 次日重置回归时,收纳重置功能链会失败。
28
-
29
- ### BC-20260708-971: 连续天数被错误清零
30
-
31
- - Status: resolved
32
- - First observed: 2026-07-08
33
- - Last checked: 2026-07-08
34
- - Scope: 晚间收纳重置清单
35
- - Tags: #life #reset
36
- - Display summary: 第二天未完成前不能清零连续天数。
37
- - Phenomenon: 用户第二天刚打开页面,连续完成天数立刻归零。
38
- - Trigger / reproduction: 昨天完成清单,今天打开但还没操作。
39
- - Root cause: 重置勾选状态时误清空 streak。
40
- - Fix method: 只重置当天勾选,不在未完成前清空 streak。
41
- - Guard / verification: 自动功能链草案应把该问题归入收纳重置流程。
42
- - Red condition: 次日打开立刻清零 streak。
43
- - Green condition: 次日未完成前保留昨天 streak。
44
- - Expected failure reason: 连续天数逻辑回归时,收纳重置功能链会失败。
45
- MD
46
-
47
- (cd "$SMALL_ROOT" && printf '{"cwd":"%s"}' "$SMALL_ROOT" | python3 "$HOOK" stop >/tmp/context-guard-hook-small.out 2>/tmp/context-guard-hook-small.err)
48
- grep -q "created proposed chains: 1" /tmp/context-guard-hook-small.err
49
- grep -q "next: ask the user to confirm" /tmp/context-guard-hook-small.err
50
-
51
- python3 - "$SMALL_ROOT/.codex/context/test-hub/feature-chains.json" <<'PY'
52
- from pathlib import Path
53
- import json
54
- import sys
55
-
56
- path = Path(sys.argv[1])
57
- data = json.loads(path.read_text(encoding="utf-8"))
58
- chains = data.get("chains", [])
59
- assert len(chains) == 1, chains
60
- chain = chains[0]
61
- assert chain["status"] == "proposed", chain
62
- assert chain["auto_proposed"] is True, chain
63
- assert chain["confirmation_required"] is True, chain
64
- assert not chain.get("command"), chain
65
- assert chain["source"] == "feature-chain-auto-propose", chain
66
- refs = chain["nodes"][0]["bad_cases"]
67
- assert refs == ["BC-20260708-970", "BC-20260708-971"], refs
68
- checks = chain["nodes"][0].get("checks", [])
69
- assert checks and "次日没有自动重置" in checks[0], chain["nodes"][0]
70
- PY
71
-
72
- python3 "$SCRIPT" validate-feature-chains --root "$SMALL_ROOT" >"$SMALL_ROOT/feature-chain-validation.out"
73
- grep -q "0 warning" "$SMALL_ROOT/feature-chain-validation.out"
74
-
75
- python3 "$SCRIPT" dev-complete --root "$SMALL_ROOT" >"$SMALL_ROOT/dev-complete.out"
76
- grep -q "no approved every-dev-completion tests" "$SMALL_ROOT/dev-complete.out"
77
-
78
- (cd "$SMALL_ROOT" && printf '{"cwd":"%s"}' "$SMALL_ROOT" | python3 "$HOOK" stop >/tmp/context-guard-hook-small-second.out 2>/tmp/context-guard-hook-small-second.err)
79
- python3 - "$SMALL_ROOT/.codex/context/test-hub/feature-chains.json" <<'PY'
80
- from pathlib import Path
81
- import json
82
- import sys
83
-
84
- chains = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8")).get("chains", [])
85
- assert len(chains) == 1, chains
86
- PY
87
-
88
- python3 "$SCRIPT" init --root "$LARGE_ROOT" >/dev/null
89
- {
90
- for idx in $(seq -w 1 13); do
91
- printf '### BC-20260708-9%s: 历史问题 %s\n\n' "$idx" "$idx"
92
- printf -- '- Status: resolved\n- Tags: #legacy #bulk\n- Display summary: 历史问题 %s。\n- Phenomenon: 历史记录。\n- Guard / verification: 历史验证。\n- Red condition: 历史红线。\n- Green condition: 历史绿线。\n- Expected failure reason: 历史失败原因。\n\n' "$idx"
93
- done
94
- } >"$LARGE_ROOT/.codex/context/bad-cases.md"
95
-
96
- (cd "$LARGE_ROOT" && printf '{"cwd":"%s"}' "$LARGE_ROOT" | python3 "$HOOK" stop >/tmp/context-guard-hook-large.out 2>/tmp/context-guard-hook-large.err)
97
- grep -q "historical baseline established: 13 bad cases" /tmp/context-guard-hook-large.err
98
- test ! -f "$LARGE_ROOT/.codex/context/test-hub/feature-chains.json"
99
- python3 - "$LARGE_ROOT/.codex/context/test-hub/feature-chain-auto-state.json" <<'PY'
100
- from pathlib import Path
101
- import json
102
- import sys
103
-
104
- state = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
105
- assert len(state.get("seen_bad_cases", [])) == 13, state
106
- PY
@@ -1,168 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- SCRIPT="${1:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/scripts/context_guard.py}"
5
- HOOK="$(cd "$(dirname "$SCRIPT")" && pwd)/context_guard_hook.py"
6
- ROOT="$(mktemp -d "${TMPDIR:-/tmp}/context-guard-multi-chain-hook-XXXXXX")"
7
- trap 'rm -rf "$ROOT"' EXIT
8
-
9
- python3 "$SCRIPT" init --root "$ROOT" >/dev/null
10
- cat >"$ROOT/.codex/context/bad-cases.md" <<'MD'
11
- ### BC-20260708-981: 未勾完也能完成清单
12
-
13
- - Status: resolved
14
- - Scope: 晚间重置流程
15
- - Tags: #checklist #completion
16
- - Display summary: 三项未勾完时不能写入完成记录。
17
- - Phenomenon: 只勾两项时仍能显示完成。
18
- - Trigger / reproduction: 勾选两项后点击完成。
19
- - Root cause: 完成入口缺少状态层校验。
20
- - Fix method: 完成前校验三项都为 true。
21
- - Guard / verification: 晚间重置流程功能链。
22
- - Guard type: feature-chain
23
- - Red condition: 两项勾选时写入完成。
24
- - Green condition: 三项全勾才完成。
25
- - Expected failure reason: 完成检查点应失败。
26
-
27
- ### BC-20260708-982: 完成后没有保存当天状态
28
-
29
- - Status: resolved
30
- - Scope: 晚间重置流程
31
- - Tags: #checklist #completion
32
- - Display summary: 完成三项后必须保存当天完成状态。
33
- - Phenomenon: 刷新页面后进度丢失。
34
- - Trigger / reproduction: 完成三项后刷新。
35
- - Root cause: 成功路径没有写入持久化状态。
36
- - Fix method: 完成后写入 localStorage。
37
- - Guard / verification: 晚间重置流程功能链。
38
- - Guard type: feature-chain
39
- - Red condition: 刷新后回到未完成。
40
- - Green condition: 刷新后仍显示今天已完成。
41
- - Expected failure reason: 保存检查点应失败。
42
-
43
- ### BC-20260708-983: 空角色名仍生成角色卡
44
-
45
- - Status: resolved
46
- - Scope: 角色卡输入校验
47
- - Tags: #story-card #validation
48
- - Display summary: 空角色名不能生成可复制卡片。
49
- - Phenomenon: 空角色名提交后出现旧卡片。
50
- - Trigger / reproduction: 先生成有效卡,再清空角色名提交。
51
- - Root cause: 无效输入没有清空旧结果。
52
- - Fix method: 校验失败时清空 latestCard 并禁用复制。
53
- - Guard / verification: 角色卡输入校验功能链。
54
- - Guard type: feature-chain
55
- - Red condition: 空角色名仍有可复制内容。
56
- - Green condition: 空角色名只显示错误且复制禁用。
57
- - Expected failure reason: 输入校验检查点应失败。
58
-
59
- ### BC-20260708-984: 缺少章节仍生成角色卡
60
-
61
- - Status: resolved
62
- - Scope: 角色卡输入校验
63
- - Tags: #story-card #validation
64
- - Display summary: 缺少章节不能生成不完整角色卡。
65
- - Phenomenon: 章节为空时仍生成卡片。
66
- - Trigger / reproduction: 填角色名和线索但不填章节。
67
- - Root cause: 章节没有纳入必填校验。
68
- - Fix method: 章节与角色名、线索同级校验。
69
- - Guard / verification: 角色卡输入校验功能链。
70
- - Guard type: feature-chain
71
- - Red condition: 章节为空仍生成卡片。
72
- - Green condition: 章节为空返回错误且无卡片。
73
- - Expected failure reason: 章节校验检查点应失败。
74
- MD
75
-
76
- (cd "$ROOT" && printf '{"cwd":"%s"}' "$ROOT" | python3 "$HOOK" stop >"$ROOT/hook-propose.out" 2>"$ROOT/hook-propose.err")
77
- grep -q "created proposed chains: 2" "$ROOT/hook-propose.err"
78
-
79
- SCRIPT_PATH="$SCRIPT" ROOT_PATH="$ROOT" python3 - <<'PY'
80
- from pathlib import Path
81
- import json
82
- import os
83
- import subprocess
84
- import sys
85
-
86
- script = os.environ["SCRIPT_PATH"]
87
- root = Path(os.environ["ROOT_PATH"])
88
- registry_path = root / ".codex/context/test-hub/feature-chains.json"
89
- data = json.loads(registry_path.read_text(encoding="utf-8"))
90
- chains = data.get("chains", [])
91
- assert len(chains) == 2, chains
92
- assert {chain["status"] for chain in chains} == {"proposed"}, chains
93
- assert {chain["title"] for chain in chains} == {"晚间重置流程", "角色卡输入校验"}, chains
94
-
95
- hub = root / ".codex/context/test-hub"
96
- for chain in chains:
97
- node_titles = [node["title"] for node in chain["nodes"]]
98
- script_path = hub / f"run-{chain['id']}.sh"
99
- body = (
100
- "#!/usr/bin/env bash\n"
101
- "set -euo pipefail\n"
102
- f"echo 'running {chain['title']}'\n"
103
- )
104
- body += "".join(f"echo 'CG_CHECKPOINT:{node_title}:PASS'\n" for node_title in node_titles)
105
- script_path.write_text(body, encoding="utf-8")
106
- script_path.chmod(0o755)
107
- subprocess.run(
108
- [
109
- sys.executable,
110
- script,
111
- "feature-chain-approve",
112
- "--root",
113
- str(root),
114
- "--chain-id",
115
- chain["id"],
116
- "--command-text",
117
- f"bash .codex/context/test-hub/run-{chain['id']}.sh",
118
- "--timeout-seconds",
119
- "30",
120
- ],
121
- check=True,
122
- stdout=subprocess.PIPE,
123
- stderr=subprocess.PIPE,
124
- text=True,
125
- )
126
-
127
- data = json.loads(registry_path.read_text(encoding="utf-8"))
128
- chains = data.get("chains", [])
129
- assert len(chains) == 2, chains
130
- assert {chain["status"] for chain in chains} == {"approved"}, chains
131
- assert all(chain.get("command") for chain in chains), chains
132
- PY
133
-
134
- python3 "$SCRIPT" validate-feature-chains --root "$ROOT" >"$ROOT/validate-approved.out"
135
- grep -q "2 chain(s), 0 warning" "$ROOT/validate-approved.out"
136
-
137
- python3 "$SCRIPT" dev-complete --root "$ROOT" >"$ROOT/dev-complete.out"
138
- grep -q "test hub: 2 passed, 0 failed, 0 blocked" "$ROOT/dev-complete.out"
139
- grep -q "success artifacts cleaned" "$ROOT/dev-complete.out"
140
-
141
- (cd "$ROOT" && printf '{"cwd":"%s"}' "$ROOT" | python3 "$HOOK" stop >"$ROOT/hook-run.out" 2>"$ROOT/hook-run.err")
142
- grep -q "test hub: 2 passed, 0 failed, 0 blocked" "$ROOT/hook-run.err"
143
- grep -q "final answer must include Test Hub summary: all approved tests passed (2 passed, 0 failed, 0 blocked)" "$ROOT/hook-run.err"
144
- grep -q "unassigned bad cases: 0" "$ROOT/hook-run.err"
145
-
146
- ROOT_PATH="$ROOT" python3 - <<'PY'
147
- from pathlib import Path
148
- import json
149
- import os
150
-
151
- root = Path(os.environ["ROOT_PATH"])
152
- data = json.loads((root / ".codex/context/test-hub/feature-chains.json").read_text(encoding="utf-8"))
153
- first = data["chains"][0]
154
- node_title = first["nodes"][0]["title"]
155
- script_path = root / ".codex/context/test-hub" / f"run-{first['id']}.sh"
156
- script_path.write_text(
157
- "#!/usr/bin/env bash\n"
158
- "set -euo pipefail\n"
159
- f"echo 'CG_CHECKPOINT:{node_title}:FAIL:intentional regression'\n",
160
- encoding="utf-8",
161
- )
162
- script_path.chmod(0o755)
163
- PY
164
-
165
- (cd "$ROOT" && printf '{"cwd":"%s"}' "$ROOT" | python3 "$HOOK" stop >"$ROOT/hook-fail.out" 2>"$ROOT/hook-fail.err" || true)
166
- grep -q "test hub: 1 passed, 1 failed, 0 blocked" "$ROOT/hook-fail.err"
167
- grep -q "TEST HUB BLOCKER" "$ROOT/hook-fail.err"
168
- grep -Eq '"decision"[[:space:]]*:[[:space:]]*"block"' "$ROOT/hook-fail.out"
@@ -1,79 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- SKILL_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
- SCRIPT="${1:-$SKILL_ROOT/scripts/context_guard.py}"
6
- HOOK="$(cd "$(dirname "$SCRIPT")" && pwd)/context_guard_hook.py"
7
- HOOKS_TEMPLATE="$SKILL_ROOT/hooks.json"
8
- if [[ ! -f "$HOOKS_TEMPLATE" ]]; then
9
- HOOKS_TEMPLATE="$SKILL_ROOT/../../hooks.json"
10
- fi
11
- ROOT="$(mktemp -d "${TMPDIR:-/tmp}/context-guard-subagent-hooks-XXXXXX")"
12
- trap 'rm -rf "$ROOT"' EXIT
13
-
14
- python3 - "$HOOKS_TEMPLATE" <<'PY'
15
- from pathlib import Path
16
- import json
17
- import sys
18
-
19
- hooks = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))["hooks"]
20
- assert "SubagentStart" in hooks, hooks.keys()
21
- assert "SubagentStop" in hooks, hooks.keys()
22
-
23
- def has_event(event, token):
24
- return any(
25
- token in hook.get("command", "")
26
- for group in hooks[event]
27
- for hook in group.get("hooks", [])
28
- )
29
-
30
- assert has_event("SubagentStart", "subagent-start"), hooks["SubagentStart"]
31
- assert has_event("SubagentStop", "subagent-stop"), hooks["SubagentStop"]
32
- PY
33
-
34
- (cd "$ROOT" && printf '{"cwd":"%s"}' "$ROOT" | python3 "$HOOK" subagent-start >"$ROOT/subagent-start.out" 2>"$ROOT/subagent-start.err")
35
- grep -q "subagent context" "$ROOT/subagent-start.err"
36
- test -f "$ROOT/.codex/context/index.md"
37
- test -f "$ROOT/.codex/context/roadmap.md"
38
-
39
- mkdir -p "$ROOT/.codex/context/test-hub"
40
- cat >"$ROOT/.codex/context/test-hub/subagent-pass.sh" <<'SH'
41
- #!/usr/bin/env bash
42
- set -euo pipefail
43
- printf 'subagent test passed\n'
44
- SH
45
- chmod +x "$ROOT/.codex/context/test-hub/subagent-pass.sh"
46
-
47
- python3 "$SCRIPT" test-hub-add \
48
- --root "$ROOT" \
49
- --title "Subagent 完成冒烟测试" \
50
- --command-text "bash .codex/context/test-hub/subagent-pass.sh" >/dev/null
51
-
52
- (cd "$ROOT" && printf '{"cwd":"%s"}' "$ROOT" | python3 "$HOOK" subagent-stop >"$ROOT/subagent-stop.out" 2>"$ROOT/subagent-stop.err")
53
- grep -q "SubagentStop checkpoint" "$ROOT/subagent-stop.err"
54
- grep -q "test hub: 1 passed, 0 failed, 0 blocked" "$ROOT/subagent-stop.err"
55
- grep -q "final answer must include Test Hub summary: all approved tests passed (1 passed, 0 failed, 0 blocked)" "$ROOT/subagent-stop.err"
56
- test -f "$ROOT/.codex/context/test-hub/last-run.json"
57
- python3 - "$ROOT/.codex/context/test-hub/last-run.json" <<'PY'
58
- from pathlib import Path
59
- import json
60
- import sys
61
-
62
- data = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
63
- statuses = [item["status"] for item in data["results"]]
64
- assert statuses == ["passed"], data
65
- PY
66
-
67
- cat >"$ROOT/.codex/context/test-hub/subagent-pass.sh" <<'SH'
68
- #!/usr/bin/env bash
69
- set -euo pipefail
70
- printf 'subagent test failed\n'
71
- exit 3
72
- SH
73
- chmod +x "$ROOT/.codex/context/test-hub/subagent-pass.sh"
74
-
75
- (cd "$ROOT" && printf '{"cwd":"%s"}' "$ROOT" | python3 "$HOOK" subagent-stop >"$ROOT/subagent-stop-fail.out" 2>"$ROOT/subagent-stop-fail.err" || true)
76
- grep -q "test hub: 0 passed, 1 failed, 0 blocked" "$ROOT/subagent-stop-fail.err"
77
- grep -q "TEST HUB BLOCKER" "$ROOT/subagent-stop-fail.err"
78
- grep -Eq '"decision"[[:space:]]*:[[:space:]]*"block"' "$ROOT/subagent-stop-fail.out"
79
- test -d "$ROOT/.codex/context/test-hub/runs"