devlog-tracker 0.22.0
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/LICENSE +201 -0
- package/README.md +234 -0
- package/bin/devlog-tracker.js +51 -0
- package/cli/init.js +55 -0
- package/cli/init.test.js +37 -0
- package/cli/merge-hooks.js +60 -0
- package/cli/merge-hooks.test.js +187 -0
- package/cli/platforms/codex.js +13 -0
- package/cli/platforms/cursor.js +13 -0
- package/cli/status.js +14 -0
- package/cli/status.test.js +33 -0
- package/cli/vendor.js +37 -0
- package/cli/vendor.test.js +84 -0
- package/codex/hooks/on-pre-tool.sh +19 -0
- package/codex/hooks/on-session-end.sh +31 -0
- package/codex/hooks/on-session-start.sh +37 -0
- package/codex/hooks/on-stop.sh +18 -0
- package/codex/hooks/on-user-prompt-submit.sh +15 -0
- package/codex/hooks/project-dir.sh +13 -0
- package/codex/hooks/test-adapters.sh +98 -0
- package/codex/hooks.json +54 -0
- package/commands/checkpoint.md +17 -0
- package/commands/clean.md +50 -0
- package/commands/compact.md +24 -0
- package/commands/continue.md +30 -0
- package/commands/keep.md +100 -0
- package/commands/lessons-drift.md +19 -0
- package/commands/lessons-off.md +16 -0
- package/commands/lessons-on.md +20 -0
- package/commands/lessons.md +20 -0
- package/commands/overview.md +32 -0
- package/commands/pause.md +20 -0
- package/commands/resume.md +18 -0
- package/commands/segment-watch.md +21 -0
- package/commands/span.md +13 -0
- package/commands/start.md +19 -0
- package/commands/status.md +14 -0
- package/cursor/hooks/on-pre-tool.sh +24 -0
- package/cursor/hooks/on-session-end.sh +11 -0
- package/cursor/hooks/on-session-start.sh +15 -0
- package/cursor/hooks/on-stop.sh +44 -0
- package/cursor/hooks/on-submit-prompt.sh +28 -0
- package/cursor/hooks/on-tool-failure.sh +16 -0
- package/cursor/hooks/project-dir.sh +10 -0
- package/cursor/hooks/test-adapters.sh +201 -0
- package/cursor/hooks.json +26 -0
- package/hooks/scripts/await-open.sh +23 -0
- package/hooks/scripts/checkpoint-set.sh +44 -0
- package/hooks/scripts/clean-devlog.sh +69 -0
- package/hooks/scripts/close-open-round.sh +186 -0
- package/hooks/scripts/compact-devlog.sh +72 -0
- package/hooks/scripts/detect-pending-question.sh +31 -0
- package/hooks/scripts/devlog-lock.sh +38 -0
- package/hooks/scripts/devlog-md.sh +222 -0
- package/hooks/scripts/devlog-path.sh +70 -0
- package/hooks/scripts/enforce-devlog.sh +629 -0
- package/hooks/scripts/files-snapshot.sh +70 -0
- package/hooks/scripts/json-field.sh +76 -0
- package/hooks/scripts/keep-move.sh +155 -0
- package/hooks/scripts/kept-list.sh +40 -0
- package/hooks/scripts/lessons-append.sh +93 -0
- package/hooks/scripts/lessons-drift-set.sh +42 -0
- package/hooks/scripts/lessons-off.sh +15 -0
- package/hooks/scripts/lessons-on.sh +21 -0
- package/hooks/scripts/lessons-read.sh +60 -0
- package/hooks/scripts/on-session-end.sh +14 -0
- package/hooks/scripts/on-stop-failure.sh +18 -0
- package/hooks/scripts/on-tool-failure.sh +25 -0
- package/hooks/scripts/pause-devlog.sh +13 -0
- package/hooks/scripts/redact-prompt.sh +19 -0
- package/hooks/scripts/resume-devlog.sh +41 -0
- package/hooks/scripts/round-start.sh +333 -0
- package/hooks/scripts/run-tests.sh +26 -0
- package/hooks/scripts/segment-watch-set.sh +47 -0
- package/hooks/scripts/segment-watch.sh +197 -0
- package/hooks/scripts/session-start-devlog.sh +157 -0
- package/hooks/scripts/span-close.sh +9 -0
- package/hooks/scripts/span-open.sh +21 -0
- package/hooks/scripts/start-devlog.sh +24 -0
- package/hooks/scripts/status-devlog.sh +43 -0
- package/hooks/scripts/tests/test-await-open.sh +112 -0
- package/hooks/scripts/tests/test-branch-scoped-integration.sh +108 -0
- package/hooks/scripts/tests/test-checkpoint-set.sh +36 -0
- package/hooks/scripts/tests/test-clean-devlog.sh +160 -0
- package/hooks/scripts/tests/test-cli-init-e2e.sh +37 -0
- package/hooks/scripts/tests/test-close-open-round.sh +325 -0
- package/hooks/scripts/tests/test-compact-devlog.sh +62 -0
- package/hooks/scripts/tests/test-devlog-lock.sh +37 -0
- package/hooks/scripts/tests/test-devlog-md.sh +530 -0
- package/hooks/scripts/tests/test-devlog-path.sh +118 -0
- package/hooks/scripts/tests/test-enforce-devlog-files.sh +233 -0
- package/hooks/scripts/tests/test-enforce-devlog-handoff-order.sh +223 -0
- package/hooks/scripts/tests/test-enforce-devlog-workspace.sh +333 -0
- package/hooks/scripts/tests/test-enforce-devlog.sh +1290 -0
- package/hooks/scripts/tests/test-files-snapshot.sh +142 -0
- package/hooks/scripts/tests/test-json-field.sh +57 -0
- package/hooks/scripts/tests/test-keep-move.sh +127 -0
- package/hooks/scripts/tests/test-kept-list.sh +80 -0
- package/hooks/scripts/tests/test-lessons-append.sh +138 -0
- package/hooks/scripts/tests/test-lessons-drift-set.sh +36 -0
- package/hooks/scripts/tests/test-lessons-on-off.sh +75 -0
- package/hooks/scripts/tests/test-lessons-read.sh +97 -0
- package/hooks/scripts/tests/test-on-interrupt.sh +186 -0
- package/hooks/scripts/tests/test-redact-prompt.sh +27 -0
- package/hooks/scripts/tests/test-resume-devlog.sh +35 -0
- package/hooks/scripts/tests/test-round-start.sh +825 -0
- package/hooks/scripts/tests/test-segment-watch-set.sh +75 -0
- package/hooks/scripts/tests/test-segment-watch.sh +468 -0
- package/hooks/scripts/tests/test-session-start-devlog.sh +508 -0
- package/hooks/scripts/tests/test-start-pause-devlog.sh +84 -0
- package/hooks/scripts/tests/test-status-span.sh +50 -0
- package/hooks/scripts/tests/test-workspace-snapshot.sh +130 -0
- package/hooks/scripts/workspace-snapshot.sh +69 -0
- package/package.json +37 -0
- package/skills/devlog-tracker/SKILL.md +411 -0
- package/skills/devlog-tracker/references/checkpoint-mode.md +42 -0
- package/skills/devlog-tracker/references/lessons-mode.md +32 -0
- package/skills/devlog-tracker/references/reply-fold.md +129 -0
- package/skills/devlog-tracker/references/round-segments.md +55 -0
- package/skills/devlog-tracker/references/span-mode.md +65 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Self-check for enforce-devlog.sh's #### 工作區 machine-verify (Phase 1,
|
|
3
|
+
# docs/design/devlog-as-ssot-assessment.md). Separate file from
|
|
4
|
+
# test-enforce-devlog.sh to avoid growing that suite further; still
|
|
5
|
+
# auto-discovered by run-tests.sh's tests/test-*.sh glob.
|
|
6
|
+
set -uo pipefail
|
|
7
|
+
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
9
|
+
TMP_ROOT="$(mktemp -d)"
|
|
10
|
+
trap 'rm -rf "$TMP_ROOT"' EXIT
|
|
11
|
+
|
|
12
|
+
export CLAUDE_PROJECT_DIR="$TMP_ROOT"
|
|
13
|
+
DEVLOG_DIR="$TMP_ROOT/.devlog"
|
|
14
|
+
mkdir -p "$DEVLOG_DIR"
|
|
15
|
+
touch "$DEVLOG_DIR/.enabled"
|
|
16
|
+
|
|
17
|
+
git -C "$TMP_ROOT" init -q -b main
|
|
18
|
+
git -C "$TMP_ROOT" config user.email test@example.com
|
|
19
|
+
git -C "$TMP_ROOT" config user.name test
|
|
20
|
+
echo '.devlog/' > "$TMP_ROOT/.gitignore"
|
|
21
|
+
git -C "$TMP_ROOT" add .gitignore
|
|
22
|
+
git -C "$TMP_ROOT" commit -q -m init
|
|
23
|
+
HASH="$(git -C "$TMP_ROOT" rev-parse --short HEAD)"
|
|
24
|
+
|
|
25
|
+
FAIL=0
|
|
26
|
+
assert_exit() {
|
|
27
|
+
local desc="$1" expected="$2" actual="$3"
|
|
28
|
+
if [ "$actual" -eq "$expected" ]; then
|
|
29
|
+
echo "PASS: $desc"
|
|
30
|
+
else
|
|
31
|
+
echo "FAIL: $desc (expected exit $expected, got $actual)"
|
|
32
|
+
FAIL=1
|
|
33
|
+
fi
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
# Round-current split: enforce-devlog.sh validates .round-current.md now
|
|
37
|
+
# (not devlog.md), and merges it into devlog.md on success. One assertion
|
|
38
|
+
# per "should succeed" case exercises that merge.
|
|
39
|
+
assert_round_merged() {
|
|
40
|
+
local desc="$1" marker="${2:-fixture}"
|
|
41
|
+
if [ -f "$DEVLOG_DIR/.round-current.md" ]; then
|
|
42
|
+
echo "FAIL: $desc (.round-current.md should be merged away)"
|
|
43
|
+
FAIL=1
|
|
44
|
+
elif ! grep -q "$marker" "$DEVLOG_DIR/devlog.md" 2>/dev/null; then
|
|
45
|
+
echo "FAIL: $desc (devlog.md missing merged content)"
|
|
46
|
+
FAIL=1
|
|
47
|
+
else
|
|
48
|
+
echo "PASS: $desc (round-current merged into devlog.md)"
|
|
49
|
+
fi
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
write_round() {
|
|
53
|
+
# $1 = workspace body (multi-line ok); empty string omits the section.
|
|
54
|
+
# Writes into .round-current.md — the file enforce-devlog.sh now validates
|
|
55
|
+
# (round-start.sh already opened a skeleton there; this overwrites it).
|
|
56
|
+
local ws="$1"
|
|
57
|
+
{
|
|
58
|
+
echo "## Round 1 — 2026-09-10T00:00:00+08:00"
|
|
59
|
+
echo ""
|
|
60
|
+
echo "### Summary"
|
|
61
|
+
echo "fixture"
|
|
62
|
+
echo ""
|
|
63
|
+
echo "### Reply"
|
|
64
|
+
echo "fixture reply."
|
|
65
|
+
echo ""
|
|
66
|
+
echo "### Handoff"
|
|
67
|
+
if [ -n "$ws" ]; then
|
|
68
|
+
echo "#### 工作區"
|
|
69
|
+
printf '%s\n' "$ws"
|
|
70
|
+
fi
|
|
71
|
+
echo "#### 現況"
|
|
72
|
+
echo "fixture"
|
|
73
|
+
echo "#### 完成條件"
|
|
74
|
+
echo "observable done via test."
|
|
75
|
+
echo "#### 下一步"
|
|
76
|
+
echo "edit hooks/scripts/enforce-devlog.sh"
|
|
77
|
+
echo ""
|
|
78
|
+
echo "### Status"
|
|
79
|
+
echo "IN_PROGRESS"
|
|
80
|
+
} > "$DEVLOG_DIR/.round-current.md"
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# --- exact match -> allowed --------------------------------------------------
|
|
84
|
+
bash "$SCRIPT_DIR/round-start.sh" < /dev/null
|
|
85
|
+
write_round "main @ ${HASH},工作樹乾淨"
|
|
86
|
+
echo '{}' | bash "$SCRIPT_DIR/enforce-devlog.sh" >/dev/null 2>&1
|
|
87
|
+
assert_exit "workspace matches live clean git state -> allowed" 0 $?
|
|
88
|
+
assert_round_merged "workspace matches live clean git state"
|
|
89
|
+
|
|
90
|
+
# --- missing section -> blocked, message shows exact expected text ----------
|
|
91
|
+
bash "$SCRIPT_DIR/round-start.sh" < /dev/null
|
|
92
|
+
write_round ""
|
|
93
|
+
MSG="$(echo '{}' | bash "$SCRIPT_DIR/enforce-devlog.sh" 2>&1)"
|
|
94
|
+
assert_exit "workspace section missing on IN_PROGRESS -> blocked" 2 $?
|
|
95
|
+
case "$MSG" in
|
|
96
|
+
*"跟目前 git 狀態不符"*) echo "PASS: message explains the mismatch" ;;
|
|
97
|
+
*) echo "FAIL: message should explain the mismatch, got: $MSG"; FAIL=1 ;;
|
|
98
|
+
esac
|
|
99
|
+
case "$MSG" in
|
|
100
|
+
*"main @ ${HASH},工作樹乾淨"*) echo "PASS: message includes the exact expected snapshot" ;;
|
|
101
|
+
*) echo "FAIL: message should include the exact expected snapshot, got: $MSG"; FAIL=1 ;;
|
|
102
|
+
esac
|
|
103
|
+
|
|
104
|
+
# --- stale hash -> blocked ---------------------------------------------------
|
|
105
|
+
bash "$SCRIPT_DIR/round-start.sh" < /dev/null
|
|
106
|
+
write_round "main @ 0000000,工作樹乾淨"
|
|
107
|
+
echo '{}' | bash "$SCRIPT_DIR/enforce-devlog.sh" >/dev/null 2>&1
|
|
108
|
+
assert_exit "workspace with stale hash -> blocked" 2 $?
|
|
109
|
+
|
|
110
|
+
# --- dirty tree, exact two-line match -> allowed -----------------------------
|
|
111
|
+
echo change >> "$TMP_ROOT/a.txt"
|
|
112
|
+
bash "$SCRIPT_DIR/round-start.sh" < /dev/null
|
|
113
|
+
write_round "main @ ${HASH}
|
|
114
|
+
未提交:a.txt"
|
|
115
|
+
echo '{}' | bash "$SCRIPT_DIR/enforce-devlog.sh" >/dev/null 2>&1
|
|
116
|
+
assert_exit "dirty tree, exact two-line workspace -> allowed" 0 $?
|
|
117
|
+
assert_round_merged "dirty tree, exact two-line workspace"
|
|
118
|
+
git -C "$TMP_ROOT" checkout -q -- a.txt 2>/dev/null || rm -f "$TMP_ROOT/a.txt"
|
|
119
|
+
|
|
120
|
+
# --- BLOCKED status is also enforced -----------------------------------------
|
|
121
|
+
bash "$SCRIPT_DIR/round-start.sh" < /dev/null
|
|
122
|
+
{
|
|
123
|
+
echo "## Round 2 — 2026-09-10T00:05:00+08:00"
|
|
124
|
+
echo ""
|
|
125
|
+
echo "### Summary"
|
|
126
|
+
echo "fixture"
|
|
127
|
+
echo ""
|
|
128
|
+
echo "### Reply"
|
|
129
|
+
echo "fixture reply."
|
|
130
|
+
echo ""
|
|
131
|
+
echo "### Handoff"
|
|
132
|
+
echo "#### 現況"
|
|
133
|
+
echo "缺使用者提供的 token(出現即繼續)"
|
|
134
|
+
echo "#### 完成條件"
|
|
135
|
+
echo "缺件已到且可觀察條件達成。"
|
|
136
|
+
echo "#### 下一步"
|
|
137
|
+
echo "等使用者提供 token 後接著改 hooks/foo.sh"
|
|
138
|
+
echo ""
|
|
139
|
+
echo "### Status"
|
|
140
|
+
echo "BLOCKED"
|
|
141
|
+
} > "$DEVLOG_DIR/.round-current.md"
|
|
142
|
+
echo '{}' | bash "$SCRIPT_DIR/enforce-devlog.sh" >/dev/null 2>&1
|
|
143
|
+
assert_exit "BLOCKED with missing workspace -> blocked" 2 $?
|
|
144
|
+
|
|
145
|
+
# --- DONE is unaffected (check only applies to IN_PROGRESS/BLOCKED) ---------
|
|
146
|
+
bash "$SCRIPT_DIR/round-start.sh" < /dev/null
|
|
147
|
+
{
|
|
148
|
+
echo "## Round 3 — 2026-09-10T00:10:00+08:00"
|
|
149
|
+
echo ""
|
|
150
|
+
echo "### Summary"
|
|
151
|
+
echo "fixture"
|
|
152
|
+
echo ""
|
|
153
|
+
echo "### Reply"
|
|
154
|
+
echo "fixture reply."
|
|
155
|
+
echo ""
|
|
156
|
+
echo "### Handoff"
|
|
157
|
+
echo "#### 現況"
|
|
158
|
+
echo "fixture"
|
|
159
|
+
echo ""
|
|
160
|
+
echo "### Status"
|
|
161
|
+
echo "DONE"
|
|
162
|
+
} > "$DEVLOG_DIR/.round-current.md"
|
|
163
|
+
echo '{}' | bash "$SCRIPT_DIR/enforce-devlog.sh" >/dev/null 2>&1
|
|
164
|
+
assert_exit "DONE with no workspace section -> allowed (check does not apply)" 0 $?
|
|
165
|
+
assert_round_merged "DONE with no workspace section"
|
|
166
|
+
|
|
167
|
+
# --- fenced example quoting #### 工作區 before the real section -> ignored,
|
|
168
|
+
# extractor still finds the real (unfenced) 工作區 body -------------------
|
|
169
|
+
bash "$SCRIPT_DIR/round-start.sh" < /dev/null
|
|
170
|
+
{
|
|
171
|
+
echo "## Round 4 — 2026-09-10T00:15:00+08:00"
|
|
172
|
+
echo ""
|
|
173
|
+
echo "### Summary"
|
|
174
|
+
echo "fixture"
|
|
175
|
+
echo ""
|
|
176
|
+
echo "### Reply"
|
|
177
|
+
echo "fixture reply."
|
|
178
|
+
echo ""
|
|
179
|
+
echo "### Handoff"
|
|
180
|
+
echo "#### 決策"
|
|
181
|
+
echo "範例格式:"
|
|
182
|
+
echo '```markdown'
|
|
183
|
+
echo "#### 工作區"
|
|
184
|
+
echo "main @ 0000000,工作樹乾淨"
|
|
185
|
+
echo '```'
|
|
186
|
+
echo "真正決策內容"
|
|
187
|
+
echo "#### 工作區"
|
|
188
|
+
echo "main @ ${HASH},工作樹乾淨"
|
|
189
|
+
echo "#### 現況"
|
|
190
|
+
echo "fixture"
|
|
191
|
+
echo "#### 完成條件"
|
|
192
|
+
echo "observable done via test."
|
|
193
|
+
echo "#### 下一步"
|
|
194
|
+
echo "edit hooks/scripts/enforce-devlog.sh"
|
|
195
|
+
echo ""
|
|
196
|
+
echo "### Status"
|
|
197
|
+
echo "IN_PROGRESS"
|
|
198
|
+
} > "$DEVLOG_DIR/.round-current.md"
|
|
199
|
+
echo '{}' | bash "$SCRIPT_DIR/enforce-devlog.sh" >/dev/null 2>&1
|
|
200
|
+
assert_exit "fenced example quoting #### 工作區 before the real section -> allowed" 0 $?
|
|
201
|
+
assert_round_merged "fenced example quoting #### 工作區 before the real section"
|
|
202
|
+
|
|
203
|
+
# --- unterminated fence in an earlier subsection -> fail-open, not a false
|
|
204
|
+
# block (final-review Fix 1). A ``` fence that never closes (odd fence-marker
|
|
205
|
+
# count) must never make a present, filled-in #### 下一步 register as missing.
|
|
206
|
+
# Pre-fix, the odd fence opened by #### 現況's (malformed) example got
|
|
207
|
+
# `fence` stuck at 1 for the rest of the round, so handoff_subsection_body()
|
|
208
|
+
# could no longer even find the "#### 下一步" heading — even though #### 工作區
|
|
209
|
+
# above it is exactly correct and #### 下一步 below it has real content.
|
|
210
|
+
bash "$SCRIPT_DIR/round-start.sh" < /dev/null
|
|
211
|
+
{
|
|
212
|
+
echo "## Round 5 — 2026-09-10T00:20:00+08:00"
|
|
213
|
+
echo ""
|
|
214
|
+
echo "### Summary"
|
|
215
|
+
echo "fixture"
|
|
216
|
+
echo ""
|
|
217
|
+
echo "### Reply"
|
|
218
|
+
echo "fixture reply."
|
|
219
|
+
echo ""
|
|
220
|
+
echo "### Handoff"
|
|
221
|
+
echo "#### 工作區"
|
|
222
|
+
echo "main @ ${HASH},工作樹乾淨"
|
|
223
|
+
echo "#### 現況"
|
|
224
|
+
echo "一段沒收尾的範例:"
|
|
225
|
+
echo '```markdown'
|
|
226
|
+
echo "沒收尾內容,一路吃到這個 Round 結尾"
|
|
227
|
+
echo "#### 完成條件"
|
|
228
|
+
echo "observable done via test."
|
|
229
|
+
echo "#### 下一步"
|
|
230
|
+
echo "edit hooks/scripts/enforce-devlog.sh"
|
|
231
|
+
echo ""
|
|
232
|
+
echo "### Status"
|
|
233
|
+
echo "IN_PROGRESS"
|
|
234
|
+
} > "$DEVLOG_DIR/.round-current.md"
|
|
235
|
+
echo '{}' | bash "$SCRIPT_DIR/enforce-devlog.sh" >/dev/null 2>&1
|
|
236
|
+
assert_exit "unterminated fence in 現況 -> fail-open, 下一步 still recognized" 0 $?
|
|
237
|
+
assert_round_merged "unterminated fence in 現況"
|
|
238
|
+
|
|
239
|
+
# --- DONE with a non-empty #### 檔案 (claims files were touched/committed)
|
|
240
|
+
# IS now checked: a DONE round that reports file changes but has no/wrong
|
|
241
|
+
# #### 工作區 is exactly the "已 commit 完成" false-claim case
|
|
242
|
+
# devlog-as-ssot-assessment.md flags as uncaught — machine-verify it the
|
|
243
|
+
# same way IN_PROGRESS/BLOCKED already are. A trivial DONE round with no
|
|
244
|
+
# #### 檔案 stays exempt (previous test above), matching SKILL.md's
|
|
245
|
+
# "瑣碎輪只留現況一句(沒有工作區)" convention untouched.
|
|
246
|
+
#
|
|
247
|
+
# The #### 檔案 body below is just "尚未 commit:" with no claimed paths —
|
|
248
|
+
# this suite only cares about triggering the 工作區 check via a non-empty
|
|
249
|
+
# #### 檔案, not about 檔案 content itself (that's
|
|
250
|
+
# test-enforce-devlog-files.sh's job, Phase 4). Any grammar-valid,
|
|
251
|
+
# always-passing body works here. ------------------------------------------
|
|
252
|
+
bash "$SCRIPT_DIR/round-start.sh" < /dev/null
|
|
253
|
+
{
|
|
254
|
+
echo "## Round 6 — 2026-09-10T00:25:00+08:00"
|
|
255
|
+
echo ""
|
|
256
|
+
echo "### Summary"
|
|
257
|
+
echo "fixture"
|
|
258
|
+
echo ""
|
|
259
|
+
echo "### Reply"
|
|
260
|
+
echo "fixture reply."
|
|
261
|
+
echo ""
|
|
262
|
+
echo "### Handoff"
|
|
263
|
+
echo "#### 檔案"
|
|
264
|
+
echo "尚未 commit:"
|
|
265
|
+
echo "#### 現況"
|
|
266
|
+
echo "fixture"
|
|
267
|
+
echo ""
|
|
268
|
+
echo "### Status"
|
|
269
|
+
echo "DONE"
|
|
270
|
+
} > "$DEVLOG_DIR/.round-current.md"
|
|
271
|
+
MSG_DONE="$(echo '{}' | bash "$SCRIPT_DIR/enforce-devlog.sh" 2>&1)"
|
|
272
|
+
assert_exit "DONE with #### 檔案 but no #### 工作區 -> blocked" 2 $?
|
|
273
|
+
case "$MSG_DONE" in
|
|
274
|
+
*"main @ ${HASH},工作樹乾淨"*) echo "PASS: DONE block message includes exact expected snapshot" ;;
|
|
275
|
+
*) echo "FAIL: DONE block message should include exact expected snapshot, got: $MSG_DONE"; FAIL=1 ;;
|
|
276
|
+
esac
|
|
277
|
+
|
|
278
|
+
bash "$SCRIPT_DIR/round-start.sh" < /dev/null
|
|
279
|
+
{
|
|
280
|
+
echo "## Round 6 — 2026-09-10T00:25:00+08:00"
|
|
281
|
+
echo ""
|
|
282
|
+
echo "### Summary"
|
|
283
|
+
echo "fixture"
|
|
284
|
+
echo ""
|
|
285
|
+
echo "### Reply"
|
|
286
|
+
echo "fixture reply."
|
|
287
|
+
echo ""
|
|
288
|
+
echo "### Handoff"
|
|
289
|
+
echo "#### 檔案"
|
|
290
|
+
echo "尚未 commit:"
|
|
291
|
+
echo "#### 工作區"
|
|
292
|
+
echo "main @ 0000000,工作樹乾淨"
|
|
293
|
+
echo "#### 現況"
|
|
294
|
+
echo "fixture"
|
|
295
|
+
echo ""
|
|
296
|
+
echo "### Status"
|
|
297
|
+
echo "DONE"
|
|
298
|
+
} > "$DEVLOG_DIR/.round-current.md"
|
|
299
|
+
echo '{}' | bash "$SCRIPT_DIR/enforce-devlog.sh" >/dev/null 2>&1
|
|
300
|
+
assert_exit "DONE with #### 檔案 and stale 工作區 hash -> blocked" 2 $?
|
|
301
|
+
|
|
302
|
+
bash "$SCRIPT_DIR/round-start.sh" < /dev/null
|
|
303
|
+
{
|
|
304
|
+
echo "## Round 6 — 2026-09-10T00:25:00+08:00"
|
|
305
|
+
echo ""
|
|
306
|
+
echo "### Summary"
|
|
307
|
+
echo "fixture"
|
|
308
|
+
echo ""
|
|
309
|
+
echo "### Reply"
|
|
310
|
+
echo "fixture reply."
|
|
311
|
+
echo ""
|
|
312
|
+
echo "### Handoff"
|
|
313
|
+
echo "#### 檔案"
|
|
314
|
+
echo "尚未 commit:"
|
|
315
|
+
echo "#### 工作區"
|
|
316
|
+
echo "main @ ${HASH},工作樹乾淨"
|
|
317
|
+
echo "#### 現況"
|
|
318
|
+
echo "fixture"
|
|
319
|
+
echo ""
|
|
320
|
+
echo "### Status"
|
|
321
|
+
echo "DONE"
|
|
322
|
+
} > "$DEVLOG_DIR/.round-current.md"
|
|
323
|
+
echo '{}' | bash "$SCRIPT_DIR/enforce-devlog.sh" >/dev/null 2>&1
|
|
324
|
+
assert_exit "DONE with #### 檔案 and matching 工作區 -> allowed" 0 $?
|
|
325
|
+
assert_round_merged "DONE with #### 檔案 and matching 工作區"
|
|
326
|
+
|
|
327
|
+
if [ "$FAIL" -eq 0 ]; then
|
|
328
|
+
echo "All checks passed."
|
|
329
|
+
exit 0
|
|
330
|
+
else
|
|
331
|
+
echo "Some checks FAILED."
|
|
332
|
+
exit 1
|
|
333
|
+
fi
|