Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions docs/plans/limit-fo-checklist-to-three-items.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,43 @@ Audited recent FO-built checklists (median 10, max 11 items) against the 3-item
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.


## Stage Report (implementation)

### Summary
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.

### Checklist

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:
```
$ 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
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.
```

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:
```
$ uv run pytest tests/test_agent_content.py::test_first_officer_shared_core_caps_checklist_at_three_linchpin_items -v
tests/test_agent_content.py::test_first_officer_shared_core_caps_checklist_at_three_linchpin_items PASSED [100%]
============================== 1 passed in 0.05s ===============================
```

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:
```
440 passed, 22 deselected, 10 subtests passed in 20.14s
```
Single commit to follow with both changes on branch `spacedock-ensign/limit-fo-checklist-to-three-items`.

### Feedback Cycles — Cycle 1 (team-lead amendment during implementation)

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:

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.
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.

Grep evidence after amendment:
```
$ grep -n -E "per-dispatch|stage-level|linchpin" skills/first-officer/references/first-officer-shared-core.md
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. ...
```

`make test-static` re-run after amendment: 440 passed, 22 deselected.
2 changes: 2 additions & 0 deletions skills/first-officer/references/first-officer-shared-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ For each entity reported by `status --next`:

1. Read the entity file and the target stage definition.
2. Build a numbered checklist from stage outputs and entity acceptance criteria.

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.
3. Check for obvious conflicts if multiple worktree stages would touch overlapping files.
4. Determine `dispatch_agent_id` from the stage `agent:` property. Default to `ensign` when absent.
5. Update main-branch frontmatter for dispatch:
Expand Down
29 changes: 29 additions & 0 deletions tests/test_agent_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,35 @@ def test_shared_core_grep_over_read_discipline_for_entity_body():
assert "field: old -> new" in discipline


def test_first_officer_shared_core_caps_checklist_at_three_linchpin_items():
"""#192: FO-built checklists are capped at <= 3 linchpin items; boilerplate excluded."""
text = read_text("skills/first-officer/references/first-officer-shared-core.md")
dispatch_section = section_text(text, "## Dispatch", (r"^## ",))

assert re.search(r"per-dispatch|stage-level", dispatch_section, re.IGNORECASE), (
"Dispatch section must frame the checklist as per-dispatch / stage-level"
)
assert "linchpin" in dispatch_section.lower(), (
"Dispatch section must frame checklist items as linchpins"
)
assert re.search(r"at most 3|\u2264\s*3|<=\s*3", dispatch_section), (
"Dispatch section must state the <= 3 checklist cap"
)
assert re.search(r"upper bound, not a target|do not pad", dispatch_section, re.IGNORECASE), (
"Dispatch section must clarify the cap is an upper bound, not a target"
)
assert re.search(
r"read the entity body|commit before signaling|write a stage report",
dispatch_section,
re.IGNORECASE,
), (
"Dispatch section must name at least one excluded boilerplate item"
)
assert re.search(r"MUST NOT appear in the checklist", dispatch_section), (
"Dispatch section must explicitly exclude boilerplate from the checklist"
)


def test_claude_runtime_points_to_shared_core_entity_body_inspection_rule():
"""AC-2 (#159): the Claude runtime adapter carries a short pointer to the shared-core rule."""
text = read_text("skills/first-officer/references/claude-first-officer-runtime.md")
Expand Down
Loading