Skip to content

Commit 6d649f0

Browse files
authored
Merge pull request #126 from clkao/spacedock-ensign/limit-fo-checklist-to-three-items
Cap FO-built dispatch checklists at ≤ 3 linchpin items
2 parents 6b8456b + b6d5ae0 commit 6d649f0

3 files changed

Lines changed: 71 additions & 0 deletions

File tree

docs/plans/limit-fo-checklist-to-three-items.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,43 @@ Audited recent FO-built checklists (median 10, max 11 items) against the 3-item
231231
3. **Write refined ACs + test plan + concrete override path — DONE.** ACs restructured to AC-1 (mechanism enforcement with three-case unit test), AC-2 (shared-core prose with static-grep test), AC-3 (preamble line with unit test), AC-4 (commission SKILL.md doc with static-grep test), AC-5 (one live sanity dispatch), AC-6 (`make test-static` green). Test plan: ~$1-2 total, mostly static tests; single live dispatch for AC-5. Override path finalized as `dispatch.checklist.max-items` nested under `dispatch` in workflow README frontmatter; precedence and invalid-value handling specified.
232232

233233

234+
## Stage Report (implementation)
235+
236+
### Summary
237+
Added a short paragraph under step 2 of the Dispatch section in `skills/first-officer/references/first-officer-shared-core.md` articulating the <= 3 linchpin cap (upper bound, not target) and the excluded boilerplate (read entity body, commit before signaling, write stage report). Added one static test `test_first_officer_shared_core_caps_checklist_at_three_linchpin_items` in `tests/test_agent_content.py` that greps the Dispatch section for the linchpin framing, the "at most 3" cap phrasing, the "upper bound, not a target" clarification, a boilerplate item name, and the "MUST NOT appear in the checklist" exclusion. Scope kept narrow per the Cycle 1 amendment: no `claude-team build` changes, no workflow README changes, no commission skill changes.
238+
239+
### Checklist
240+
241+
1. **Add prose paragraph to shared-core near line 60 — DONE.** Edited `skills/first-officer/references/first-officer-shared-core.md` to add the paragraph under step 2 of the Dispatch section (now at line 62). Covers the three required points: (a) `<=` 3 cap as upper bound with "0, 1, 2, or 3 items are all valid; do not pad to reach 3"; (b) linchpin framing ("linchpins — the few signals … that demonstrate this dispatch's job is done well"); (c) excluded boilerplate ("read the entity body, commit before signaling complete, and write a stage report … MUST NOT appear in the checklist"). Grep evidence:
242+
```
243+
$ grep -n -E "linchpin|at most 3|upper bound|read the entity body|commit before signaling|write a stage report" skills/first-officer/references/first-officer-shared-core.md
244+
62: Checklist items are linchpins — the few signals (at most 3) that demonstrate this dispatch's job is done well. The cap is an upper bound, not a target: 0, 1, 2, or 3 items are all valid; do not pad to reach 3. This is not a work-breakdown. The ensign already knows how to read the entity body, commit before signaling complete, and write a stage report; those are covered by structural conventions and MUST NOT appear in the checklist. Name what separates a good outcome from a ceremonial one.
245+
```
246+
247+
2. **Add static test asserting prose presence — DONE.** Added `test_first_officer_shared_core_caps_checklist_at_three_linchpin_items` to `tests/test_agent_content.py` (existing home for grep-based shared-core assertions; no separate `test_static_guardrails.py` exists). The test extracts the `## Dispatch` section with the existing `section_text` helper and asserts five regex/substring matches: (a) "linchpin" framing, (b) the `<=` 3 / "at most 3" cap, (c) the "upper bound, not a target" / "do not pad" clarification, (d) at least one excluded-boilerplate phrase, (e) the "MUST NOT appear in the checklist" exclusion. Test output:
248+
```
249+
$ uv run pytest tests/test_agent_content.py::test_first_officer_shared_core_caps_checklist_at_three_linchpin_items -v
250+
tests/test_agent_content.py::test_first_officer_shared_core_caps_checklist_at_three_linchpin_items PASSED [100%]
251+
============================== 1 passed in 0.05s ===============================
252+
```
253+
254+
3. **Run `make test-static`, confirm green with count >= 439 — DONE.** Baseline before change was 439 passing; after change 440 passing (baseline + 1 new test), 22 deselected. Output tail:
255+
```
256+
440 passed, 22 deselected, 10 subtests passed in 20.14s
257+
```
258+
Single commit to follow with both changes on branch `spacedock-ensign/limit-fo-checklist-to-three-items`.
259+
260+
### Feedback Cycles — Cycle 1 (team-lead amendment during implementation)
261+
262+
Team-lead requested a forward-compatibility amendment to keep #193's per-dispatch vs. entity-level framing aligned. Two narrow changes, same file/same test/same scope:
263+
264+
1. **Prose lead rewritten.** The paragraph now opens with "The dispatch checklist is a **per-dispatch, stage-level** list of linchpin signals — at most 3 items — that demonstrate this specific dispatch's job is done well. It is distinct from entity-level acceptance criteria." Remaining sentences (0/1/2/3 valid, don't pad, boilerplate excluded, MUST NOT appear) unchanged.
265+
2. **Test assertion added.** `test_first_officer_shared_core_caps_checklist_at_three_linchpin_items` now greps the Dispatch section for `per-dispatch|stage-level` (case-insensitive) in addition to the previous five assertions. The test continues to pass.
266+
267+
Grep evidence after amendment:
268+
```
269+
$ grep -n -E "per-dispatch|stage-level|linchpin" skills/first-officer/references/first-officer-shared-core.md
270+
62: The dispatch checklist is a **per-dispatch, stage-level** list of linchpin signals — at most 3 items — that demonstrate this specific dispatch's job is done well. It is distinct from entity-level acceptance criteria. ...
271+
```
272+
273+
`make test-static` re-run after amendment: 440 passed, 22 deselected.

skills/first-officer/references/first-officer-shared-core.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ For each entity reported by `status --next`:
5858

5959
1. Read the entity file and the target stage definition.
6060
2. Build a numbered checklist from stage outputs and entity acceptance criteria.
61+
62+
The dispatch checklist is a **per-dispatch, stage-level** list of linchpin signals — at most 3 items — that demonstrate this specific dispatch's job is done well. It is distinct from entity-level acceptance criteria. The cap is an upper bound, not a target: 0, 1, 2, or 3 items are all valid; do not pad to reach 3. This is not a work-breakdown. The ensign already knows how to read the entity body, commit before signaling complete, and write a stage report; those are covered by structural conventions and MUST NOT appear in the checklist. Name what separates a good outcome from a ceremonial one.
6163
3. Check for obvious conflicts if multiple worktree stages would touch overlapping files.
6264
4. Determine `dispatch_agent_id` from the stage `agent:` property. Default to `ensign` when absent.
6365
5. Update main-branch frontmatter for dispatch:

tests/test_agent_content.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,35 @@ def test_shared_core_grep_over_read_discipline_for_entity_body():
638638
assert "field: old -> new" in discipline
639639

640640

641+
def test_first_officer_shared_core_caps_checklist_at_three_linchpin_items():
642+
"""#192: FO-built checklists are capped at <= 3 linchpin items; boilerplate excluded."""
643+
text = read_text("skills/first-officer/references/first-officer-shared-core.md")
644+
dispatch_section = section_text(text, "## Dispatch", (r"^## ",))
645+
646+
assert re.search(r"per-dispatch|stage-level", dispatch_section, re.IGNORECASE), (
647+
"Dispatch section must frame the checklist as per-dispatch / stage-level"
648+
)
649+
assert "linchpin" in dispatch_section.lower(), (
650+
"Dispatch section must frame checklist items as linchpins"
651+
)
652+
assert re.search(r"at most 3|\u2264\s*3|<=\s*3", dispatch_section), (
653+
"Dispatch section must state the <= 3 checklist cap"
654+
)
655+
assert re.search(r"upper bound, not a target|do not pad", dispatch_section, re.IGNORECASE), (
656+
"Dispatch section must clarify the cap is an upper bound, not a target"
657+
)
658+
assert re.search(
659+
r"read the entity body|commit before signaling|write a stage report",
660+
dispatch_section,
661+
re.IGNORECASE,
662+
), (
663+
"Dispatch section must name at least one excluded boilerplate item"
664+
)
665+
assert re.search(r"MUST NOT appear in the checklist", dispatch_section), (
666+
"Dispatch section must explicitly exclude boilerplate from the checklist"
667+
)
668+
669+
641670
def test_claude_runtime_points_to_shared_core_entity_body_inspection_rule():
642671
"""AC-2 (#159): the Claude runtime adapter carries a short pointer to the shared-core rule."""
643672
text = read_text("skills/first-officer/references/claude-first-officer-runtime.md")

0 commit comments

Comments
 (0)