Skip to content

Commit 712d39b

Browse files
author
Rubiczhang
committed
fix(bitlesson): require init template file and add tests
1 parent 2cdcfff commit 712d39b

2 files changed

Lines changed: 68 additions & 37 deletions

File tree

scripts/bitlesson-init.sh

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ Behavior:
1111
- Default bitlesson-relpath: bitlesson.md
1212
- Creates <project-root>/<bitlesson-relpath> from template if missing
1313
- Does not overwrite existing file
14-
- Falls back to inline template if --template does not exist
1514
- Prints the resolved bitlesson file path to stdout on success
1615
USAGE_EOF
1716
}
@@ -63,6 +62,11 @@ if [[ ! -d "$PROJECT_ROOT" ]]; then
6362
exit 1
6463
fi
6564

65+
if [[ ! -f "$TEMPLATE_PATH" ]]; then
66+
echo "Error: --template must be an existing file: $TEMPLATE_PATH" >&2
67+
exit 1
68+
fi
69+
6670
PROJECT_ROOT_ABS="$(cd "$PROJECT_ROOT" && pwd -P)"
6771
BITLESSON_FILE="$PROJECT_ROOT_ABS/$BITLESSON_RELPATH"
6872

@@ -73,35 +77,7 @@ fi
7377

7478
if [[ ! -f "$BITLESSON_FILE" ]]; then
7579
mkdir -p "$(dirname "$BITLESSON_FILE")"
76-
if [[ -f "$TEMPLATE_PATH" ]]; then
77-
cp "$TEMPLATE_PATH" "$BITLESSON_FILE"
78-
else
79-
cat > "$BITLESSON_FILE" << 'BITLESSON_EOF'
80-
# BitLesson Knowledge Base
81-
82-
This file is project-specific. Keep entries precise and reusable for future rounds.
83-
84-
## Entry Template (Strict)
85-
86-
Use this exact field order for every entry:
87-
88-
```markdown
89-
## Lesson: <unique-id>
90-
Lesson ID: <BL-YYYYMMDD-short-name>
91-
Scope: <component/subsystem/files>
92-
Problem Description: <specific failure mode with trigger conditions>
93-
Root Cause: <direct technical cause>
94-
Solution: <exact fix that resolved the problem>
95-
Constraints: <limits, assumptions, non-goals>
96-
Validation Evidence: <tests/commands/logs/PR evidence>
97-
Source Rounds: <round numbers where problem appeared and was solved>
98-
```
99-
100-
## Entries
101-
102-
<!-- Add lessons below using the strict template. -->
103-
BITLESSON_EOF
104-
fi
80+
cp "$TEMPLATE_PATH" "$BITLESSON_FILE"
10581
fi
10682

10783
printf '%s\n' "$BITLESSON_FILE"

tests/test-bitlesson-workflow.sh

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ source "$SCRIPT_DIR/test-helpers.sh"
1919
SETUP_SCRIPT="$PROJECT_ROOT/scripts/setup-rlcr-loop.sh"
2020
STOP_HOOK="$PROJECT_ROOT/hooks/loop-codex-stop-hook.sh"
2121
BITLESSON_TEMPLATE_FILE="$PROJECT_ROOT/templates/bitlesson.md"
22+
BITLESSON_INIT_SCRIPT="$PROJECT_ROOT/scripts/bitlesson-init.sh"
23+
BITLESSON_VALIDATE_DELTA_SCRIPT="$PROJECT_ROOT/scripts/bitlesson-validate-delta.sh"
24+
BITLESSON_SELECT_SCRIPT="$PROJECT_ROOT/scripts/bitlesson-select.sh"
2225

2326
echo "=========================================="
2427
echo "BitLesson Workflow Tests"
@@ -96,10 +99,62 @@ else
9699
fi
97100

98101
# ========================================
99-
# Test 2: Setup initializes project-level bitlesson and round-0 requirements
102+
# Test 2: Extracted BitLesson scripts exist and validate inputs
100103
# ========================================
101104

105+
if [[ -f "$BITLESSON_INIT_SCRIPT" && -x "$BITLESSON_INIT_SCRIPT" ]]; then
106+
pass "bitlesson-init.sh exists and is executable"
107+
else
108+
fail "bitlesson-init.sh exists and is executable" "executable script" "missing or not executable"
109+
fi
110+
111+
if [[ -f "$BITLESSON_VALIDATE_DELTA_SCRIPT" && -x "$BITLESSON_VALIDATE_DELTA_SCRIPT" ]]; then
112+
pass "bitlesson-validate-delta.sh exists and is executable"
113+
else
114+
fail "bitlesson-validate-delta.sh exists and is executable" "executable script" "missing or not executable"
115+
fi
116+
117+
if [[ -f "$BITLESSON_SELECT_SCRIPT" && -x "$BITLESSON_SELECT_SCRIPT" ]]; then
118+
pass "bitlesson-select.sh exists and is executable"
119+
else
120+
fail "bitlesson-select.sh exists and is executable" "executable script" "missing or not executable"
121+
fi
122+
102123
setup_test_dir
124+
mkdir -p "$TEST_DIR/init-project"
125+
126+
set +e
127+
bash "$BITLESSON_INIT_SCRIPT" --project-root "$TEST_DIR/init-project" --template "$TEST_DIR/does-not-exist.md" > /dev/null 2>&1
128+
INIT_BAD_TEMPLATE_EXIT=$?
129+
set -e
130+
131+
if [[ "$INIT_BAD_TEMPLATE_EXIT" -ne 0 ]] && [[ ! -f "$TEST_DIR/init-project/bitlesson.md" ]]; then
132+
pass "bitlesson-init.sh errors when template file is missing"
133+
else
134+
fail "bitlesson-init.sh errors when template file is missing" "non-zero exit and no file created" "exit=$INIT_BAD_TEMPLATE_EXIT"
135+
fi
136+
137+
bash "$BITLESSON_INIT_SCRIPT" --project-root "$TEST_DIR/init-project" --template "$BITLESSON_TEMPLATE_FILE" > /dev/null 2>&1
138+
139+
if [[ -f "$TEST_DIR/init-project/bitlesson.md" ]]; then
140+
pass "bitlesson-init.sh creates bitlesson.md from template when missing"
141+
else
142+
fail "bitlesson-init.sh creates bitlesson.md from template when missing" "bitlesson.md created" "not found"
143+
fi
144+
145+
echo "SENTINEL" > "$TEST_DIR/init-project/bitlesson.md"
146+
bash "$BITLESSON_INIT_SCRIPT" --project-root "$TEST_DIR/init-project" --template "$BITLESSON_TEMPLATE_FILE" > /dev/null 2>&1
147+
148+
if grep -q "SENTINEL" "$TEST_DIR/init-project/bitlesson.md"; then
149+
pass "bitlesson-init.sh does not overwrite an existing bitlesson.md"
150+
else
151+
fail "bitlesson-init.sh does not overwrite an existing bitlesson.md" "SENTINEL preserved" "template content overwritten"
152+
fi
153+
154+
# ========================================
155+
# Test 3: Setup initializes project-level bitlesson and round-0 requirements
156+
# ========================================
157+
103158
init_test_git_repo "$TEST_DIR/project"
104159
mkdir -p "$TEST_DIR/project/plans" "$TEST_DIR/project/bin"
105160
cat > "$TEST_DIR/project/plans/plan.md" << 'EOF'
@@ -167,7 +222,7 @@ else
167222
fi
168223

169224
# ========================================
170-
# Test 3: Team/worktree templates enforce selector constraints
225+
# Test 4: Team/worktree templates enforce selector constraints
171226
# ========================================
172227

173228
for template in \
@@ -185,7 +240,7 @@ do
185240
done
186241

187242
# ========================================
188-
# Test 4: Next-round prompt keeps BitLesson requirements
243+
# Test 5: Next-round prompt keeps BitLesson requirements
189244
# ========================================
190245

191246
# Add one concrete lesson entry so Action:none in later round remains valid.
@@ -236,7 +291,7 @@ else
236291
fi
237292

238293
# ========================================
239-
# Test 5: Stop hook blocks Action:add when lesson IDs are not in bitlesson.md
294+
# Test 6: Stop hook blocks Action:add when lesson IDs are not in bitlesson.md
240295
# ========================================
241296

242297
cat > "$LOOP_DIR/round-2-summary.md" << 'EOF'
@@ -258,7 +313,7 @@ else
258313
fi
259314

260315
# ========================================
261-
# Test 6: Stop hook blocks when BitLesson Delta is missing
316+
# Test 7: Stop hook blocks when BitLesson Delta is missing
262317
# ========================================
263318

264319
cat > "$LOOP_DIR/round-2-summary.md" << 'EOF'
@@ -275,7 +330,7 @@ else
275330
fi
276331

277332
# ========================================
278-
# Test 7: Stop hook allows round>0 Action:none by default when bitlesson has no concrete entries
333+
# Test 8: Stop hook allows round>0 Action:none by default when bitlesson has no concrete entries
279334
# ========================================
280335

281336
cp "$BITLESSON_TEMPLATE_FILE" "$TEST_DIR/project/bitlesson.md"
@@ -301,7 +356,7 @@ else
301356
fi
302357

303358
# ========================================
304-
# Test 8: Strict mode blocks round>0 Action:none when bitlesson has no concrete entries
359+
# Test 9: Strict mode blocks round>0 Action:none when bitlesson has no concrete entries
305360
# ========================================
306361

307362
sed -i 's/^bitlesson_allow_empty_none: true$/bitlesson_allow_empty_none: false/' "$STATE_FILE"

0 commit comments

Comments
 (0)