@michelj/context-guard 0.4.3 → 0.4.4
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.
- package/README.md +103 -208
- package/README.zh-CN.md +103 -208
- package/SKILL.md +27 -678
- package/agents/openai.yaml +2 -2
- package/bin/context-guard-skill.js +159 -56
- package/bin/postinstall.js +1 -1
- package/hooks.json +11 -11
- package/package.json +9 -6
- package/prototype/workbench.html +4933 -0
- package/references/bug-record-template.md +37 -0
- package/references/context-template.md +14 -336
- package/scripts/context_guard.py +577 -7655
- package/scripts/context_guard_hook.py +179 -731
- package/scripts/map_owns.py +769 -0
- package/references/feature-chain-methodology.md +0 -228
- package/references/register-template.md +0 -85
- package/references/task-case-template.md +0 -63
- package/tests/BC-20260618-063.sh +0 -116
- package/tests/BC-20260618-065.sh +0 -66
- package/tests/BC-20260626-080.sh +0 -48
- package/tests/BC-20260626-081.sh +0 -40
- package/tests/BC-20260626-082.sh +0 -32
- package/tests/BC-20260626-083.sh +0 -66
- package/tests/BC-20260627-084.sh +0 -74
- package/tests/BC-20260630-086.sh +0 -50
- package/tests/BC-20260630-087.sh +0 -103
- package/tests/BC-20260630-088.sh +0 -32
- package/tests/BC-20260630-089.sh +0 -63
- package/tests/BC-20260701-090.sh +0 -84
- package/tests/BC-20260702-096.sh +0 -48
- package/tests/BC-20260706-098.sh +0 -66
- package/tests/BC-20260707-099.sh +0 -47
- package/tests/BC-20260707-100.sh +0 -46
- package/tests/BC-20260707-101.sh +0 -47
- package/tests/BC-20260707-102.sh +0 -68
- package/tests/BC-20260707-103.sh +0 -59
- package/tests/BC-20260707-104.sh +0 -103
- package/tests/BC-20260707-105.sh +0 -109
- package/tests/BC-20260707-106.sh +0 -80
- package/tests/BC-20260707-107.sh +0 -74
- package/tests/BC-20260707-108.sh +0 -48
- package/tests/BC-20260707-109.sh +0 -56
- package/tests/BC-20260707-110.sh +0 -71
- package/tests/BC-20260707-111.sh +0 -70
- package/tests/BC-20260707-112.sh +0 -45
- package/tests/BC-20260707-113.sh +0 -73
- package/tests/BC-20260707-115.sh +0 -77
- package/tests/BC-20260707-116.sh +0 -77
- package/tests/BC-20260707-118.sh +0 -115
- package/tests/BC-20260707-119.sh +0 -47
- package/tests/BC-20260707-120.sh +0 -60
- package/tests/BC-20260707-121.sh +0 -66
- package/tests/BC-20260707-122.sh +0 -48
- package/tests/BC-20260707-123.sh +0 -43
- package/tests/BC-20260707-124.sh +0 -56
- package/tests/BC-20260707-125.sh +0 -64
- package/tests/BC-20260707-126.sh +0 -80
- package/tests/BC-20260707-127.sh +0 -88
- package/tests/BC-20260707-129.sh +0 -59
- package/tests/BC-20260707-130.sh +0 -69
- package/tests/BC-20260707-131.sh +0 -140
- package/tests/BC-20260707-132.sh +0 -150
- package/tests/BC-20260707-133.sh +0 -70
- package/tests/BC-20260708-136.sh +0 -210
- package/tests/BC-20260708-137.sh +0 -106
- package/tests/BC-20260708-138.sh +0 -168
- package/tests/BC-20260708-139.sh +0 -79
- package/tests/BC-20260709-002.sh +0 -63
- package/tests/BC-20260709-003.sh +0 -239
- package/tests/BC-20260709-006.sh +0 -76
- package/tests/BC-20260709-008.sh +0 -168
- package/tests/BC-20260710-001.sh +0 -61
- package/tests/BC-20260710-002.sh +0 -111
- package/tests/npm-install-smoke.sh +0 -53
package/tests/BC-20260708-137.sh
DELETED
|
@@ -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
|
package/tests/BC-20260708-138.sh
DELETED
|
@@ -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"
|
package/tests/BC-20260708-139.sh
DELETED
|
@@ -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"
|
package/tests/BC-20260709-002.sh
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
SCRIPT="${CONTEXT_GUARD_SCRIPT:-$(cd "$(dirname "$0")/.." && pwd)/scripts/context_guard.py}"
|
|
5
|
-
ROOT="$(mktemp -d "${TMPDIR:-/tmp}/context-guard-subagent-complete-XXXXXX")"
|
|
6
|
-
trap 'rm -rf "$ROOT"' EXIT
|
|
7
|
-
|
|
8
|
-
mkdir -p "$ROOT/bin"
|
|
9
|
-
cat >"$ROOT/bin/subagent-smoke.sh" <<'SH'
|
|
10
|
-
#!/usr/bin/env bash
|
|
11
|
-
set -euo pipefail
|
|
12
|
-
echo "CG_CHECKPOINT:subagent smoke:PASS"
|
|
13
|
-
SH
|
|
14
|
-
chmod +x "$ROOT/bin/subagent-smoke.sh"
|
|
15
|
-
|
|
16
|
-
python3 "$SCRIPT" init --root "$ROOT" >/dev/null
|
|
17
|
-
python3 "$SCRIPT" test-hub-add \
|
|
18
|
-
--root "$ROOT" \
|
|
19
|
-
--title "Subagent smoke approved test" \
|
|
20
|
-
--command-text "./bin/subagent-smoke.sh" \
|
|
21
|
-
--run-policy every-dev-completion \
|
|
22
|
-
--test-status approved >/dev/null
|
|
23
|
-
|
|
24
|
-
python3 "$SCRIPT" subagent-complete \
|
|
25
|
-
--root "$ROOT" \
|
|
26
|
-
--agent-id "agent-smoke-001" \
|
|
27
|
-
--summary "Created a small static page and completed local validation." >/tmp/subagent-complete.out
|
|
28
|
-
|
|
29
|
-
grep -Fq "[context-guard] subagent handoff:" /tmp/subagent-complete.out
|
|
30
|
-
grep -Fq "[context-guard] test hub: 1 passed, 0 failed, 0 blocked." /tmp/subagent-complete.out
|
|
31
|
-
test -f "$ROOT/.codex/context/subagents.md"
|
|
32
|
-
test -f "$ROOT/.codex/context/test-hub/last-run.json"
|
|
33
|
-
grep -Fq "agent-smoke-001" "$ROOT/.codex/context/subagents.md"
|
|
34
|
-
grep -Fq "Subagent completion handoff" "$ROOT/.codex/context/roadmap.md"
|
|
35
|
-
|
|
36
|
-
python3 - "$ROOT/.codex/context/test-hub/last-run.json" <<'PY'
|
|
37
|
-
import json
|
|
38
|
-
import sys
|
|
39
|
-
from pathlib import Path
|
|
40
|
-
|
|
41
|
-
data = json.loads(Path(sys.argv[1]).read_text())
|
|
42
|
-
results = data.get("results", [])
|
|
43
|
-
assert len(results) == 1, results
|
|
44
|
-
assert results[0].get("status") == "passed", results
|
|
45
|
-
PY
|
|
46
|
-
|
|
47
|
-
cat >"$ROOT/bin/subagent-smoke.sh" <<'SH'
|
|
48
|
-
#!/usr/bin/env bash
|
|
49
|
-
set -euo pipefail
|
|
50
|
-
echo "CG_CHECKPOINT:subagent smoke:FAIL:forced failure"
|
|
51
|
-
exit 1
|
|
52
|
-
SH
|
|
53
|
-
chmod +x "$ROOT/bin/subagent-smoke.sh"
|
|
54
|
-
|
|
55
|
-
if python3 "$SCRIPT" subagent-complete \
|
|
56
|
-
--root "$ROOT" \
|
|
57
|
-
--agent-id "agent-smoke-002" \
|
|
58
|
-
--summary "Forced failing handoff." >/tmp/subagent-complete-fail.out 2>&1; then
|
|
59
|
-
echo "subagent-complete should fail when approved Test Hub tests fail" >&2
|
|
60
|
-
exit 1
|
|
61
|
-
fi
|
|
62
|
-
grep -Fq "[context-guard] test hub: 0 passed, 1 failed, 0 blocked." /tmp/subagent-complete-fail.out
|
|
63
|
-
grep -Fq "[context-guard] evidence preserved:" /tmp/subagent-complete-fail.out
|
package/tests/BC-20260709-003.sh
DELETED
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
SCRIPT="${CONTEXT_GUARD_SCRIPT:-$(cd "$(dirname "$0")/.." && pwd)/scripts/context_guard.py}"
|
|
5
|
-
ROOT="$(mktemp -d "${TMPDIR:-/tmp}/context-guard-subagent-auto-chain-XXXXXX")"
|
|
6
|
-
trap 'rm -rf "$ROOT"' EXIT
|
|
7
|
-
|
|
8
|
-
mkdir -p "$ROOT/bin"
|
|
9
|
-
cat >"$ROOT/bin/approved-smoke.sh" <<'SH'
|
|
10
|
-
#!/usr/bin/env bash
|
|
11
|
-
set -euo pipefail
|
|
12
|
-
test -f index.html
|
|
13
|
-
grep -Fq "Evening Reset" index.html
|
|
14
|
-
echo "CG_CHECKPOINT:approved smoke:PASS"
|
|
15
|
-
SH
|
|
16
|
-
chmod +x "$ROOT/bin/approved-smoke.sh"
|
|
17
|
-
|
|
18
|
-
cat >"$ROOT/index.html" <<'HTML'
|
|
19
|
-
<!doctype html>
|
|
20
|
-
<title>Evening Reset</title>
|
|
21
|
-
<main>Evening Reset</main>
|
|
22
|
-
HTML
|
|
23
|
-
|
|
24
|
-
python3 "$SCRIPT" init --root "$ROOT" >/dev/null
|
|
25
|
-
python3 "$SCRIPT" test-hub-add \
|
|
26
|
-
--root "$ROOT" \
|
|
27
|
-
--title "Subagent approved smoke" \
|
|
28
|
-
--command-text "./bin/approved-smoke.sh" \
|
|
29
|
-
--run-policy every-dev-completion \
|
|
30
|
-
--test-status approved >/dev/null
|
|
31
|
-
|
|
32
|
-
cat >"$ROOT/.codex/context/bad-cases.md" <<'MD'
|
|
33
|
-
### BC-20260709-810: 次日清单没有恢复待完成
|
|
34
|
-
|
|
35
|
-
- Status: resolved
|
|
36
|
-
- First observed: 2026-07-09
|
|
37
|
-
- Last checked: 2026-07-09
|
|
38
|
-
- Scope: 晚间收纳重置清单
|
|
39
|
-
- Tags: #evening-reset #persistence
|
|
40
|
-
- Display summary: 第二天打开页面时,昨晚完成的项目仍显示已完成。
|
|
41
|
-
- Phenomenon: 用户第二天进入页面,清单没有恢复到待完成状态。
|
|
42
|
-
- Trigger / reproduction: 完成三项清单后模拟跨天,再重新打开页面。
|
|
43
|
-
- Root cause: 持久化只保存勾选状态,没有保存并比较完成日期。
|
|
44
|
-
- Fix method: 保存完成日期,启动时发现日期变化就重置当天状态。
|
|
45
|
-
- Guard / verification: 应归入晚间收纳功能链,用跨天打开流程验证。
|
|
46
|
-
- Guard type: feature-chain
|
|
47
|
-
- Red condition: 跨天后仍显示已完成。
|
|
48
|
-
- Green condition: 跨天后清单显示待完成。
|
|
49
|
-
- Expected failure reason: 如果跨天重置回归,晚间收纳功能链会在恢复状态节点失败。
|
|
50
|
-
|
|
51
|
-
### BC-20260709-811: 部分完成刷新后进度丢失
|
|
52
|
-
|
|
53
|
-
- Status: resolved
|
|
54
|
-
- First observed: 2026-07-09
|
|
55
|
-
- Last checked: 2026-07-09
|
|
56
|
-
- Scope: 晚间收纳重置清单
|
|
57
|
-
- Tags: #evening-reset #persistence
|
|
58
|
-
- Display summary: 只完成一部分后刷新页面,已勾选项目被清空。
|
|
59
|
-
- Phenomenon: 用户完成两项后刷新,页面回到 0/3。
|
|
60
|
-
- Trigger / reproduction: 勾选两项,不点击最终完成,刷新页面。
|
|
61
|
-
- Root cause: 只在最终完成时写入 localStorage,未保存中间状态。
|
|
62
|
-
- Fix method: 每次勾选变化都保存进度。
|
|
63
|
-
- Guard / verification: 应归入晚间收纳功能链,用部分完成恢复节点验证。
|
|
64
|
-
- Guard type: feature-chain
|
|
65
|
-
- Red condition: 刷新后部分进度丢失。
|
|
66
|
-
- Green condition: 刷新后保留已勾选项目。
|
|
67
|
-
- Expected failure reason: 如果中间状态持久化回归,晚间收纳功能链会在部分完成节点失败。
|
|
68
|
-
MD
|
|
69
|
-
|
|
70
|
-
python3 "$SCRIPT" subagent-complete \
|
|
71
|
-
--root "$ROOT" \
|
|
72
|
-
--agent-id "agent-auto-chain-001" \
|
|
73
|
-
--summary "Built the Evening Reset page and resolved persistence issues." >/tmp/subagent-auto-chain.out
|
|
74
|
-
|
|
75
|
-
grep -Fq "[context-guard] subagent handoff:" /tmp/subagent-auto-chain.out
|
|
76
|
-
grep -Fq "[context-guard] test hub: 1 passed, 0 failed, 0 blocked." /tmp/subagent-auto-chain.out
|
|
77
|
-
grep -Fq "created proposed chains: 1" /tmp/subagent-auto-chain.out
|
|
78
|
-
grep -Fq "next: ask the user to confirm" /tmp/subagent-auto-chain.out
|
|
79
|
-
|
|
80
|
-
python3 - "$ROOT/.codex/context/test-hub/feature-chains.json" <<'PY'
|
|
81
|
-
from pathlib import Path
|
|
82
|
-
import json
|
|
83
|
-
import sys
|
|
84
|
-
|
|
85
|
-
path = Path(sys.argv[1])
|
|
86
|
-
data = json.loads(path.read_text(encoding="utf-8"))
|
|
87
|
-
chains = data.get("chains", [])
|
|
88
|
-
assert len(chains) == 1, chains
|
|
89
|
-
chain = chains[0]
|
|
90
|
-
assert chain["status"] == "proposed", chain
|
|
91
|
-
assert chain["run_policy"] == "every-dev-completion", chain
|
|
92
|
-
assert chain["auto_proposed"] is True, chain
|
|
93
|
-
assert chain["confirmation_required"] is True, chain
|
|
94
|
-
assert chain["source"] == "feature-chain-auto-propose", chain
|
|
95
|
-
assert chain.get("command", "") == "", chain
|
|
96
|
-
nodes = chain.get("nodes", [])
|
|
97
|
-
assert len(nodes) == 2, nodes
|
|
98
|
-
refs = [ref for node in nodes for ref in node.get("bad_cases", [])]
|
|
99
|
-
assert refs == ["BC-20260709-810", "BC-20260709-811"], refs
|
|
100
|
-
titles = [node.get("title", "") for node in nodes]
|
|
101
|
-
checks = [check for node in nodes for check in node.get("checks", [])]
|
|
102
|
-
assert any("次日清单没有恢复待完成" in title for title in titles), titles
|
|
103
|
-
assert any("部分完成刷新后进度丢失" in title for title in titles), titles
|
|
104
|
-
assert any("跨天打开流程" in check for check in checks), checks
|
|
105
|
-
assert any("部分完成恢复节点" in check for check in checks), checks
|
|
106
|
-
PY
|
|
107
|
-
|
|
108
|
-
python3 "$SCRIPT" dev-complete --root "$ROOT" >/tmp/subagent-auto-chain-dev-complete.out
|
|
109
|
-
grep -Fq "[context-guard] test hub: 1 passed, 0 failed, 0 blocked." /tmp/subagent-auto-chain-dev-complete.out
|
|
110
|
-
if grep -Fq "feature-chain" /tmp/subagent-auto-chain-dev-complete.out; then
|
|
111
|
-
echo "proposed feature chain should not run before user approval" >&2
|
|
112
|
-
exit 1
|
|
113
|
-
fi
|
|
114
|
-
|
|
115
|
-
cat >>"$ROOT/.codex/context/bad-cases.md" <<'MD'
|
|
116
|
-
|
|
117
|
-
### BC-20260709-812: 完成提示刷新后消失
|
|
118
|
-
|
|
119
|
-
- Status: resolved
|
|
120
|
-
- First observed: 2026-07-09
|
|
121
|
-
- Last checked: 2026-07-09
|
|
122
|
-
- Scope: 晚间收纳重置清单
|
|
123
|
-
- Tags: #evening-reset #persistence
|
|
124
|
-
- Display summary: 完成清单后刷新页面,完成提示没有保留。
|
|
125
|
-
- Phenomenon: 用户完成全部项目后刷新,页面不再显示完成提示。
|
|
126
|
-
- Trigger / reproduction: 勾选全部项目并刷新页面。
|
|
127
|
-
- Root cause: 完成提示没有和清单状态一起持久化。
|
|
128
|
-
- Fix method: 从持久化清单状态推导完成提示。
|
|
129
|
-
- Guard / verification: 应挂到已有晚间收纳功能链,而不是另建一条链。
|
|
130
|
-
- Guard type: feature-chain
|
|
131
|
-
- Red condition: 刷新后完成提示消失。
|
|
132
|
-
- Green condition: 刷新后仍能看到完成提示。
|
|
133
|
-
- Expected failure reason: 如果完成态持久化回归,晚间收纳功能链会在完成提示节点失败。
|
|
134
|
-
MD
|
|
135
|
-
|
|
136
|
-
python3 "$SCRIPT" subagent-complete \
|
|
137
|
-
--root "$ROOT" \
|
|
138
|
-
--agent-id "agent-auto-chain-002" \
|
|
139
|
-
--summary "Fixed another persistence issue in the same Evening Reset flow." >/tmp/subagent-auto-chain-attach.out
|
|
140
|
-
|
|
141
|
-
grep -Fq "[context-guard] test hub: 1 passed, 0 failed, 0 blocked." /tmp/subagent-auto-chain-attach.out
|
|
142
|
-
grep -Fq "created proposed chains: 0" /tmp/subagent-auto-chain-attach.out
|
|
143
|
-
grep -Fq "attached to proposed chains: 1" /tmp/subagent-auto-chain-attach.out
|
|
144
|
-
|
|
145
|
-
python3 - "$ROOT/.codex/context/test-hub/feature-chains.json" <<'PY'
|
|
146
|
-
from pathlib import Path
|
|
147
|
-
import json
|
|
148
|
-
import sys
|
|
149
|
-
|
|
150
|
-
data = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
|
|
151
|
-
chains = data.get("chains", [])
|
|
152
|
-
assert len(chains) == 1, chains
|
|
153
|
-
nodes = chains[0]["nodes"]
|
|
154
|
-
assert len(nodes) == 3, nodes
|
|
155
|
-
refs = [ref for node in nodes for ref in node.get("bad_cases", [])]
|
|
156
|
-
assert refs == ["BC-20260709-810", "BC-20260709-811", "BC-20260709-812"], refs
|
|
157
|
-
titles = [node.get("title", "") for node in nodes]
|
|
158
|
-
checks = [check for node in nodes for check in node.get("checks", [])]
|
|
159
|
-
assert any("完成提示刷新后消失" in item for item in titles), titles
|
|
160
|
-
assert any("已有晚间收纳功能链" in item for item in checks), checks
|
|
161
|
-
PY
|
|
162
|
-
|
|
163
|
-
python3 - "$ROOT/.codex/context/test-hub/feature-chains.json" <<'PY'
|
|
164
|
-
from pathlib import Path
|
|
165
|
-
import json
|
|
166
|
-
import sys
|
|
167
|
-
|
|
168
|
-
path = Path(sys.argv[1])
|
|
169
|
-
data = json.loads(path.read_text(encoding="utf-8"))
|
|
170
|
-
chains = data.get("chains", [])
|
|
171
|
-
base = chains[0]
|
|
172
|
-
base_key = str(base.get("auto_group_key") or "persistence")
|
|
173
|
-
parts = [part for part in base_key.split("|") if part]
|
|
174
|
-
secondary_key = parts[0] if parts else "evening-reset"
|
|
175
|
-
chains.append(
|
|
176
|
-
{
|
|
177
|
-
"id": "FC-20260709-999",
|
|
178
|
-
"title": "secondary overlapping chain",
|
|
179
|
-
"status": "proposed",
|
|
180
|
-
"run_policy": "every-dev-completion",
|
|
181
|
-
"entry": "overlap test",
|
|
182
|
-
"exit_check": "overlap test",
|
|
183
|
-
"command": "",
|
|
184
|
-
"timeout_seconds": 300,
|
|
185
|
-
"artifact_policy": "cleanup-on-pass",
|
|
186
|
-
"resource": "local",
|
|
187
|
-
"created": "2026-07-09",
|
|
188
|
-
"source": "feature-chain-auto-propose",
|
|
189
|
-
"auto_proposed": True,
|
|
190
|
-
"auto_group_key": secondary_key,
|
|
191
|
-
"confirmation_required": True,
|
|
192
|
-
"nodes": [],
|
|
193
|
-
}
|
|
194
|
-
)
|
|
195
|
-
path.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
|
196
|
-
PY
|
|
197
|
-
|
|
198
|
-
cat >>"$ROOT/.codex/context/bad-cases.md" <<'MD'
|
|
199
|
-
|
|
200
|
-
### BC-20260709-813: 下周模板提前污染今天清单
|
|
201
|
-
|
|
202
|
-
- Status: resolved
|
|
203
|
-
- First observed: 2026-07-09
|
|
204
|
-
- Last checked: 2026-07-09
|
|
205
|
-
- Scope: 晚间收纳重置清单
|
|
206
|
-
- Tags: #evening-reset #persistence
|
|
207
|
-
- Display summary: 下周计划确认后,今天的清单也被提前替换。
|
|
208
|
-
- Phenomenon: 用户在周复盘里确认下周模板,回到今天清单后发现今天的任务顺序或内容已经变了。
|
|
209
|
-
- Trigger / reproduction: 从周复盘生成下周模板,再回到今天清单。
|
|
210
|
-
- Root cause: 下周计划和今天模板共用同一份持久化状态。
|
|
211
|
-
- Fix method: 下周模板单独存储,到下周才应用。
|
|
212
|
-
- Guard / verification: 应只挂到一个最匹配的已有功能链,避免同一个 bad case 被多个 proposed 链重复覆盖。
|
|
213
|
-
- Guard type: feature-chain
|
|
214
|
-
- Red condition: 下周模板提前污染今天清单。
|
|
215
|
-
- Green condition: 下周模板确认后,今天清单保持原样。
|
|
216
|
-
- Expected failure reason: 如果自动挂载没有排除本轮已覆盖 BC,同一条 BC 会被多个 proposed 链重复挂载。
|
|
217
|
-
MD
|
|
218
|
-
|
|
219
|
-
python3 "$SCRIPT" subagent-complete \
|
|
220
|
-
--root "$ROOT" \
|
|
221
|
-
--agent-id "agent-auto-chain-overlap" \
|
|
222
|
-
--summary "Fixed next-week template persistence without changing today's checklist." >/tmp/subagent-auto-chain-overlap.out
|
|
223
|
-
|
|
224
|
-
grep -Fq "[context-guard] test hub: 1 passed, 0 failed, 0 blocked." /tmp/subagent-auto-chain-overlap.out
|
|
225
|
-
|
|
226
|
-
python3 - "$ROOT/.codex/context/test-hub/feature-chains.json" <<'PY'
|
|
227
|
-
from pathlib import Path
|
|
228
|
-
import json
|
|
229
|
-
import sys
|
|
230
|
-
|
|
231
|
-
data = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
|
|
232
|
-
refs = [
|
|
233
|
-
ref
|
|
234
|
-
for chain in data.get("chains", [])
|
|
235
|
-
for node in chain.get("nodes", [])
|
|
236
|
-
for ref in node.get("bad_cases", [])
|
|
237
|
-
]
|
|
238
|
-
assert refs.count("BC-20260709-813") == 1, refs
|
|
239
|
-
PY
|