Add the checker the showboat skill references, so `just check-demos` actually runs instead of pointing at non-existent tooling. - scripts/ci/check-spec-demo-anchors.sh: validates every anchored spec.md (demos-anchored: true) has a sibling demo whose proof blocks carry matching machine + human anchors and at least one evidence block per scenario; GitHub-style slug derivation; exits 0 on the no-anchored-specs-yet case - justfile: `check-demos` recipe delegating to the script (just is installed; coexists with the canonical Makefile) - showboat skill: restore `just check-demos` references now that the command works Verified: passes clean on the current tree (0 anchored specs) and correctly fails on missing demo / missing evidence fixtures.
4 KiB
Retrofit Mode
Retrofit mode rewrites an existing demo that does not yet use anchors into the anchored shape. Use it when:
- A spec gains
<!-- demos-anchored: true -->and the sibling demo already exists in the old AC-based or freeform shape. - The caller invokes showboat with an explicit "retrofit" instruction.
Anchor shape and evidence-kind rules live in anchored-mode.md — read that
first. Antipattern checklist lives in authoring-smells.md.
Retrofit Procedure
-
Read the spec — extract every
#### Scenario:heading and its WHEN/THEN/AND bullets. Compute the slug for each. -
Read the existing demo — identify what content maps to each scenario. The existing structure may be
R<n>,AC<n>, or prose headings. Match by content similarity, not by position.H2 dedup rule: If the old demo has an
## AC<n> — <heading>H2 that shadows a quoted#### Scenario: <same heading>H4 immediately below it, drop the H2. Keep only the#### Scenario:quote inside the anchor block. Rationale: the H2 is navigational scaffolding for the old AC-based format; the anchored#### Scenario:heading is the canonical proof text and already provides the same orientation.Before retrofit:
## AC1 — Config, state, and cache have distinct homes #### Scenario: Config, state, and cache have distinct homes - **WHEN** ...After retrofit:
<!-- spec-scenario: merge-pull-request#config-state-and-cache-have-distinct-homes --> **Proves:** [spec.md → Scenario: Config, state, and cache have distinct homes](./spec.md#scenario-config-state-and-cache-have-distinct-homes) #### Scenario: Config, state, and cache have distinct homes - **WHEN** ...AC numbering: Drop
AC<n>numbering entirely on retrofit. Gaps appear naturally when scenarios are inserted mid-sequence; numbered headings create false continuity. Use the scenario heading as the sole identifier. -
Rewrite stale provenance links — if the old demo has a
[openspec/changes/<old-name>]link that no longer matches the merged capability, replace the whole provenance block with a single one-liner:*Originally captured for `<old-cap>` / PR #N; merged into `<new-cap>` on YYYY-MM-DD.*Do not try to keep the old multi-field header block alive — it rots.
-
Surface test candidates — for each scenario slug, grep the following paths for test function names or filter strings that resemble the slug:
pkg/**/*_test.gooperation/**/*_test.gotest/(if present)
A candidate matches when its function name or
go test -runfilter contains any substring of the scenario slug (at least one full slug token). Report candidates to the caller before writing.If a 1:1 candidate exists: propose
evidence-kind: test-invocation. If no 1:1 exists: proposeevidence-kind: unit-test-outputwith a placeholder comment naming which assertions prove the scenario. If the scenario is CLI-observable: proposeevidence-kind: showboat-cli. -
Write the anchored demo — for each scenario in spec order:
- Emit the machine anchor, human anchor, quoted scenario block, then the evidence block chosen in step 4.
- Preserve any real captured output from the old demo when it maps cleanly to the scenario.
- Where output is stale or missing, use a placeholder:
# TODO: re-run against live instance to capture real output $ <command> <output pending>
-
Record the evidence-kind choice inline — even for
showboat-cliproofs, add<!-- evidence-kind: showboat-cli -->before the fenced block so the checker and future authors see the intent. -
Note test-split decisions — when a
unit-test-outputplaceholder is chosen instead oftest-invocation, add an inline comment explaining why (<!-- retrofitted: no 1:1 test found; unit-test-output fallback -->). -
Verify. Run
just check-demos; fix any reported errors before committing.