Symptom
/planning:interview Step 3's mandatory register gate (scripts/check-open-questions.sh) exits 2 (ungradeable) on a correctly filled ledger:
error: the register section holds no question rows in: .work/<topic>/interview-checklist.md
registered=0 open=0 deferred=0 blocked=0 withdrawn=0 answered=0 brief=unchecked status=ungradeable
exit=2
The ledger had seven correctly shaped rows. Exit 2 halts per the skill's own contract, so the interview cannot lock its contract until the operator diagnoses a plugin-internal problem mid-session.
Root cause
extract_section() returns the body of the first heading matching the pattern and stops at the next heading of any level. skills/interview/templates/checklist.md ships its own instructional section titled exactly ## Open-question register, and the skill instructs the operator to copy that template into the memory slice and maintain the live register inside it. Every copied ledger therefore holds two headings with that name. The gate binds to the instructional one, whose fenced example rows do not parse as register rows, and reports registered=0.
Two further defects found while fixing it:
- The template's register section carries a fenced bash block whose
# Step 3, ... comment line matched the heading regex and terminated the section, hiding any row written after it.
- The row loop skipped every row after an unterminated fence as documentation, so an open row behind a stray fence graded clean (exit 0).
Reproduction
- Run
/planning:interview on any topic with two or more open questions.
- Copy
skills/interview/templates/checklist.md to <memory_dir>/<topic>/interview-checklist.md as instructed.
- Append a
## Open-question register section with valid rows.
bash scripts/check-open-questions.sh --ledger <that file> exits 2 with registered=0.
Fix
PR #4065: duplicate matching headings make the gate exit 2 naming every candidate line rather than silently binding first or last; heading detection and section extraction are fence-aware; an unterminated fence exits 2; diagnostics name the bound heading and its line number.
Deferred: marking the live register with a structural sentinel pair so identification does not depend on a heading that documentation naturally repeats. That changes the template and skill contract, not only the script.
Origin: handoff-inbox item 20260907-104819-planning-interview-register-gate-heading-shadowing, observed at planning 0.39.0 during a live interview run.
Symptom
/planning:interviewStep 3's mandatory register gate (scripts/check-open-questions.sh) exits 2 (ungradeable) on a correctly filled ledger:The ledger had seven correctly shaped rows. Exit 2 halts per the skill's own contract, so the interview cannot lock its contract until the operator diagnoses a plugin-internal problem mid-session.
Root cause
extract_section()returns the body of the first heading matching the pattern and stops at the next heading of any level.skills/interview/templates/checklist.mdships its own instructional section titled exactly## Open-question register, and the skill instructs the operator to copy that template into the memory slice and maintain the live register inside it. Every copied ledger therefore holds two headings with that name. The gate binds to the instructional one, whose fenced example rows do not parse as register rows, and reportsregistered=0.Two further defects found while fixing it:
# Step 3, ...comment line matched the heading regex and terminated the section, hiding any row written after it.Reproduction
/planning:interviewon any topic with two or more open questions.skills/interview/templates/checklist.mdto<memory_dir>/<topic>/interview-checklist.mdas instructed.## Open-question registersection with valid rows.bash scripts/check-open-questions.sh --ledger <that file>exits 2 withregistered=0.Fix
PR #4065: duplicate matching headings make the gate exit 2 naming every candidate line rather than silently binding first or last; heading detection and section extraction are fence-aware; an unterminated fence exits 2; diagnostics name the bound heading and its line number.
Deferred: marking the live register with a structural sentinel pair so identification does not depend on a heading that documentation naturally repeats. That changes the template and skill contract, not only the script.
Origin: handoff-inbox item
20260907-104819-planning-interview-register-gate-heading-shadowing, observed at planning 0.39.0 during a live interview run.