Run Change C through your track
By the end you will have driven one brief through your framework's own artifacts, commands and implementation, and graded the result with an acceptance suite it never saw.
This continues Exercise 1's
day3-work. Starting here? Run the setup block, then your track's install-and-init
steps there.
Setup
Quit Claude Code and paste one block from the course root (cd .. first if you are
in the copy). It keeps an existing day3-work, adds the brief and the cycle fixture,
and leaves you inside it, where every later command runs.
mkdir -p work
{ [ -d day3-work ] || cp -R sandbox/swift day3-work; } && cd day3-work
cp ../day-3-choose-your-adventure/starter/change-c-brief.md .
cp ../day-3-choose-your-adventure/starter/fixtures/cycle-config.tsv Tests/LedgerKitTests/Fixtures/
{ [ -f ../work/map.md ] || cp ../day-3-choose-your-adventure/starter/map-template.md ../work/map.md; }
ls change-c-brief.md Tests/LedgerKitTests/Fixtures/
The fixtures folder lists cycle-config.tsv.
mkdir -p work
{ [ -d day3-work ] || cp -R sandbox/kotlin day3-work; } && cd day3-work
cp ../day-3-choose-your-adventure/starter/change-c-brief.md .
cp ../day-3-choose-your-adventure/starter/fixtures/cycle-config.tsv src/test/resources/
{ [ -f ../work/map.md ] || cp ../day-3-choose-your-adventure/starter/map-template.md ../work/map.md; }
ls change-c-brief.md src/test/resources/
src/test/resources/ lists cycle-config.tsv.
Start claude there, with a second terminal tab for shell commands. In default
mode Claude Code asks before each edit and command; approving is not steering.
The brief pins the type names and entry point, so a test against them compiles, and nothing else: no acceptance criteria, two unmarked ambiguities.
Note the time: 25 minutes to the checkpoint in step 6, reading the brief included; then implementing takes about 10 on OpenSpec, 17 on LID and 20 on BMAD, whose build reviews its diff with three subagents; then 8 to grade. That is 43, 50 or 53 of the 55; the rest is reading this page and its reveals.
Steps
-
Read the brief before typing anything. In
../work/ambiguities.md, list every place two reasonable engineers would build different things. -
Confirm the suite is green, as in Exercise 1.
Swift laneswift testTest Suite 'All tests' passed at …. Executed 34 tests, with 1 test skipped and 0 failures (0 unexpected) in … (…) secondsKotlin lane./gradlew testBUILD SUCCESSFUL in …Gradle prints no count; read it from the report:
cat build/test-results/test/TEST-*.xml | grep -c '<testcase ' grep -o 'skipped="[0-9]*"' build/test-results/test/TEST-ledgerkit.KnownIssueTest.xmlIt prints
85, thenskipped="1". -
Start planning with your tab's prompt, pasted whole: whether the framework reads the file is part of the test.
-
When the planning output appears (some commands,
/opsx:proposeamong them, write several files at once), mark each item on your list: asked, recorded as an open question, or silently chosen; the third is what matters. Then send:Do not change any code yet. List every behaviour in the brief that you had to decide without the brief telling you, one line each, with the decision you made and the file where that decision is now written down. If a decision is only in this conversation and not in a file, say so explicitly for that line. -
Resolve each ambiguity in the framework's own artifact (your tab names it), not in chat:
/clearempties the conversation, and a decision kept there goes with it. Then send:I have written my decisions into <the file your tab names>. Re-read it from disk, treat those open questions as closed, and continue to your next step without changing them. Do not write any code yet. -
Checkpoint at 25 minutes. If planning is unfinished, quit Claude Code, copy in your track's reference planning artifacts (made by its workflow on the build machine) with your tab's lines, restart
claude, and continue at step 7. Taking it is not failing. -
Run your tab's implementation prompt. Do not hand-edit source while it runs.
-
Run your lane's suite. If anything is red, send your tab's repair prompt with the failing output in place of
<paste>, and re-run until green. The count now includes your framework's own tests: it is grading itself.Swift laneswift testKotlin lane./gradlew test -
Copy in the acceptance suite, outside
day3-workuntil now and the same for every track, then run the self-check.Swift lanecp ../day-3-choose-your-adventure/starter/acceptance/ChangeCAcceptanceTests.swift Tests/LedgerKitTests/ ls Tests/LedgerKitTests/Kotlin lanecp ../day-3-choose-your-adventure/starter/acceptance/ChangeCAcceptanceTest.kt src/test/kotlin/ ls src/test/kotlin/ -
Check the bounds: the known-issue run, then a diff against the shipped lane. Below, the reference implementation stands in.
Swift laneLEDGER_RUN_KNOWN_ISSUES=1 swift test diff -rq -x .build -x build -x .gradle -x .kotlin ../sandbox/swift .Known-issue run:
…/Tests/LedgerKitTests/KnownIssueTests.swift:35: error: -[LedgerKitTests.KnownIssueTests testLEDGER7_JPYRendersWithTwoDecimalPlaces] : XCTAssertEqual failed: ("-¥1,280.00") is not equal to ("-¥128,000") - LEDGER-7: LK-014 (JPY) rendered the wrong amount. expected: -¥128,000 actual: -¥1,280.00 … Executed … tests, with 1 failure (0 unexpected) in … (…) secondsDiff:
Only in ./Sources/LedgerKit: StatementPeriods.swift Only in ./Tests/LedgerKitTests: ChangeCAcceptanceTests.swift Only in ./Tests/LedgerKitTests/Fixtures: cycle-config.tsv Only in .: change-c-brief.mdKotlin laneLEDGER_RUN_KNOWN_ISSUES=1 ./gradlew test diff -rq -x .build -x build -x .gradle -x .kotlin ../sandbox/kotlin .Known-issue run:
KnownIssueTest > LEDGER-7 the JPY row renders with decimal places it should not have() FAILED org.opentest4j.AssertionFailedError: … ==> expected: <-¥128,000> but was: <-¥1,280.00> … … tests completed, 1 failed … BUILD FAILED in …Diff:
Only in .: change-c-brief.md Only in ./src/main/kotlin/ledgerkit: StatementPeriods.kt Only in ./src/test/kotlin: ChangeCAcceptanceTest.kt Only in ./src/test/resources: cycle-config.tsvOne failure, the JPY case. Read the diff as in Exercise 1: every line must be in your source or test folders, the brief, or your map's list, and no
differline may nameMoneyorLedgerFilter. Your diff will be longer than the four lines above: your track adds its own folders (on OpenSpec,openspec/and.claude/) and its own test file; those are in your map's list. -
Under
## Change C notesin../work/map.md, write three lines: which ambiguity your framework caught, which one it chose without asking, and which file the resolution ended up in.
Your track
OpenSpec: plan (step 3)
/opsx:propose Statement periods for LedgerKit. The full brief is in change-c-brief.md in this project folder — read that file, do not work from this sentence. Produce the proposal and the delta specs for this change, plus whatever design note and task list your workflow normally produces. Do not write implementation code in this step. Where the brief leaves a behaviour genuinely undetermined, do not ask me before creating the change or choose for me: record it under a heading "Open questions", still write the design note and task list, mark each task that depends on an open question blocked, and stop. Keep every code change inside Sources/LedgerKit/ and Tests/LedgerKitTests/ on the Swift lane, or src/main/kotlin/ and src/test/kotlin/ on the Kotlin lane.
/opsx:propose writes every artifact under openspec/changes/ and stops on the open
questions.
Where a decision lives (step 5)
In the delta spec: a ### Requirement: under ## ADDED
Requirements, pinned by a #### Scenario:. The build run also recorded
each decision in proposal.md, but the delta spec is the copy
/opsx:apply implements. Validate by the name openspec list
shows:
openspec list
openspec validate <name>
On the build machine (1.13.1, 2026-09-22): Change 'add-statement-periods' is
valid.
Checkpoint (step 6)
Move any change of your own out first:
mv openspec/changes/<your-change> ../work/
cp -R ../day-3-choose-your-adventure/starter/checkpoints/openspec/changes/. openspec/changes/
Its tasks and design assume Swift; paste this under # Tasks in
openspec/changes/add-statement-periods/tasks.md:
Kotlin lane: this checkout is the Kotlin lane, and this line overrides every Swift path and command in these tasks and in design.md. Code goes in src/main/kotlin/ledgerkit/, tests in src/test/kotlin/, fixtures in src/test/resources/, and ./gradlew test replaces swift build and swift test.
Implement (step 7)
Send /opsx:apply with the change name openspec list shows
(after the checkpoint, add-statement-periods) and your bounds:
/opsx:apply <name> Work this change's task list. Implement only what the delta specs describe. Stay inside Sources/LedgerKit/ and Tests/LedgerKitTests/ on the Swift lane, or src/main/kotlin/ and src/test/kotlin/ on the Kotlin lane, and stop when the task list is complete. Do not use git in this folder: where a task runs git, run diff -rq -x .build -x build -x .gradle -x .kotlin ../sandbox/swift . (on the Kotlin lane, ../sandbox/kotlin) instead.
Repair (step 8)
/opsx:apply again, then:
The test suite is red. Here is the failing output, verbatim: <paste>. Fix it by working the task list and the delta specs — if the delta spec is what is wrong, change the delta spec first and then the code. Do not edit the tests to make them pass.
What OpenSpec produced on the build run: the proposal and the delta spec
OpenSpec 1.13.1, 2026-09-22, in a fresh copy of the Swift lane, handed the planning
prompt above. The full folder is
../day-3-choose-your-adventure/starter/checkpoints/openspec/.
openspec/changes/add-statement-periods/proposal.md
openspec/changes/add-statement-periods/design.md
openspec/changes/add-statement-periods/tasks.md
openspec/changes/add-statement-periods/.openspec.yaml
openspec/changes/add-statement-periods/specs/statement-cycle/spec.md
openspec/changes/add-statement-periods/specs/statement-periods/spec.md
It stopped on four open questions with the dependent tasks blocked. After the answers were folded back in, the proposal's last section reads, headings only:
## Decisions on what the brief left open
### OQ-1. Placement date: the posted date
### OQ-2. Short months: clamp the start day to the month's last day
### OQ-3. Rule combination: single rule only
### OQ-4. Malformed table rows: skip the row
The first requirement of specs/statement-periods/spec.md, with its first
scenario:
### Requirement: A transaction is placed by its posted date
The date that decides which period a transaction belongs to SHALL be the UTC
calendar date of its `postedAt`, the same date the existing day grouping uses.
The authorized date SHALL never decide membership. This applies to every
status: a pending or declined transaction is placed by its `postedAt` like any
other.
#### Scenario: Fixture row LK-015 is placed by its posted date
- **WHEN** the twenty transactions of `transactions.tsv` are grouped with the
`standard` cycle from the shipped cycle table
- **THEN** `LK-015` (authorized `2026-03-04`, posted `2026-03-05`) is in the
period starting `2026-03-05` and ending `2026-04-04`, not in the period
ending `2026-03-04`
LID: plan (step 3)
Describe the change: the ## LID block Exercise 1 added to
CLAUDE.md sends it down the arrow through the linked-intent-dev
skill (/linked-intent-dev:update-lid is for drift and mode changes). Paste as an
ordinary message:
Statement periods for LedgerKit. The full brief is in change-c-brief.md in this project folder — read that file, do not work from this message. This module already has a design tree from Exercise 1, so extend it rather than proposing a new architecture. Give the new EARS requirements the prefix LK-PERIOD. Stop for my review at the end of each phase. Where the brief leaves a behaviour genuinely undetermined, raise it rather than choosing for me.
The skill stops for approval after each phase: high-level design, low-level design, EARS requirements, edge audit, tests. Read each, then send:
Approved. Continue to the next phase.
Where a decision lives (step 5)
Before requirements exist, in the leaf's design doc under Decisions & Alternatives;
after, in the LK-PERIOD requirement it cascades to
(docs/intent/<segment>/<segment>-specs.md), one EARS sentence per
decision.
Checkpoint (step 6)
Move any leaf of your own out first, and delete any LK-PERIOD segment it
added to docs/arrows/index.yaml:
mv docs/intent/<your-leaf> ../work/
cp -R ../day-3-choose-your-adventure/starter/checkpoints/lid/docs/intent/statement-period docs/intent/
Then copy in the arrow doc and make by hand the three edits
../day-3-choose-your-adventure/starter/checkpoints/lid/CHECKPOINT.md lists, in
docs/arrows/index.yaml, docs/high-level-design.md and
CLAUDE.md, which a copy would overwrite. The overlay snippet comes in both
shapes an index.yaml can have; match yours.
Implement (step 7)
At the stop before tests (after the checkpoint, as your first message), send:
Continue down the arrow: write the tests for the LK-PERIOD requirements first, then the code, and annotate each with // @spec and its requirement ID on the topmost function that owns the behaviour. Keep code and tests inside Sources/LedgerKit/ and Tests/LedgerKitTests/ on the Swift lane; on the Kotlin lane, in src/main/kotlin/ledgerkit/ and src/test/kotlin/, in place of any Swift file the design names. Do not change any requirement to match code you have already written — if the code cannot satisfy a requirement, stop and tell me which one.
Each annotation is // @spec and comma-separated IDs, each a design-tree path
plus a number. List them:
grep -rn '@spec LK-PERIOD' Sources Tests
grep -rn '@spec LK-PERIOD' src
Repair (step 8)
The test suite is red. Here is the failing output, verbatim: <paste>. Decide first whether the failure means the code is wrong or the requirement is wrong. If the requirement is wrong, fix the low-level design and cascade downstream; if the code is wrong, fix the code and leave the requirement alone. Tell me which of the two you concluded and which artifact you changed. Do not edit the tests to make them pass.
What LID produced on the build run: the design addition and the LK-PERIOD block
LID at commit 831c1959, 2026-09-22, in a fresh copy of the Swift lane with the design
tree already mapped. That run could not stop for a person at its phase boundaries, so it
was handed the planning prompt plus the answers to the two ambiguities up front. It was
started as /linked-intent-dev:update-lid with the prompt as its argument; the
plain-message start this tab uses was not run on the build machine, so your run is the
first observation of it. This is
what it produced, not a fixed file list; the files are in
../day-3-choose-your-adventure/starter/checkpoints/lid/.
docs/high-level-design.md the new leaf added to the high-level design
docs/intent/statement-period/statement-period-design.md the low-level design addition
docs/intent/statement-period/statement-period-specs.md 22 EARS requirements, LK-PERIOD-001..022
docs/arrows/index.yaml a new LK-PERIOD segment
CLAUDE.md PERIOD added to the leaf list
The design doc's sections run Purpose, Scope, Design, Interfaces, Decisions & Alternatives, Open Questions & Future Decisions, and Verification. Two of the requirements:
**LK-PERIOD-008** When a calendar month has fewer days than the cycle's
start day, the statement-period grouping shall open that month's period on
the last day of that month, and shall leave every other month's opening
day unchanged (a start day of 31 opens the February 2026 period on
2026-02-28 and the March 2026 period on 2026-03-31).
Verified by: (no test yet).
**LK-PERIOD-013** The statement-period grouping shall place each
transaction in the period whose `start` and `end` days, both inclusive,
contain the transaction's `postedDay` (the UTC calendar day of
`postedAt`), and shall never use `authorizedDay` to decide membership
(fixture row `LK-015`, authorized 2026-03-04 and posted 2026-03-05,
belongs on a start-day-5 cycle to the period that opens on 2026-03-05).
Verified by: (no test yet).
Every requirement reads (no test yet): the arrow had reached requirements
and not tests. The run also reported three sibling documents from the mapping as stale
rather than editing them, because a sibling is not downstream on the arrow.
BMAD: plan (step 3)
/bmad-build Statement periods for LedgerKit. The full brief is in change-c-brief.md in this project folder — read that file, do not work from this sentence. Ask your clarifying questions before you plan, and show me the plan for approval before you implement anything. Where the brief leaves a behaviour genuinely undetermined, ask rather than choosing for me. Keep every code change inside Sources/LedgerKit/ and Tests/LedgerKitTests/ on the Swift lane, or src/main/kotlin/ and src/test/kotlin/ on the Kotlin lane.
/bmad-build opens with a uv run command naming _bmad/scripts/render_skill.py: approve it.
Without uv, or with that command refused, it halts.
Where a decision lives (step 5)
In the spec /bmad-build writes under
_bmad-output/implementation-artifacts/: by its step-01 text one
spec-<slug>.md; on the build machine,
statement-periods/SPEC.md. Answer its Open Questions there, as decisions inside its
<frozen-after-approval> block.
Checkpoint (step 6)
Move any spec of your own out first. cp -R into a missing folder renames the
copy, so mkdir comes first:
mv _bmad-output/implementation-artifacts/<your spec file or folder> ../work/
mkdir -p _bmad-output/implementation-artifacts
cp -R ../day-3-choose-your-adventure/starter/checkpoints/bmad/statement-periods _bmad-output/implementation-artifacts/
The implementing subagent reads only the spec, so in the frozen block of
statement-periods/SPEC.md cut or a Kotlin lane and its
parenthesis from Never: and add under Always:
- This repository is the Kotlin lane, and this line overrides every Swift name, path and command in this spec: use the brief's Kotlin block, code in src/main/kotlin/ledgerkit/, tests in src/test/kotlin/, fixtures in src/test/resources/, and run ./gradlew test.
Implement (step 7)
After reviewing its plan:
Approved — build the plan you just showed me. Implement only what the spec describes, keep every change inside Sources/LedgerKit/ and Tests/LedgerKitTests/ on the Swift lane, or src/main/kotlin/ and src/test/kotlin/ on the Kotlin lane, and stop when the spec's status reaches done. Do not use git in this folder: wherever your workflow needs a diff, use the output of diff -ruN -x .build -x build -x .gradle -x .kotlin -x _bmad -x _bmad-output -x .claude ../sandbox/swift . (on the Kotlin lane, ../sandbox/kotlin) as the provided diff, and do not commit.
After the checkpoint, hand /bmad-build the spec; at
ready-for-dev it goes straight to implementation:
/bmad-build _bmad-output/implementation-artifacts/statement-periods/SPEC.md Implement this spec. Implement only what the spec describes, keep every change inside Sources/LedgerKit/ and Tests/LedgerKitTests/ on the Swift lane, or src/main/kotlin/ and src/test/kotlin/ on the Kotlin lane, and stop when the spec's status reaches done. Do not use git in this folder: wherever your workflow needs a diff, use the output of diff -ruN -x .build -x build -x .gradle -x .kotlin -x _bmad -x _bmad-output -x .claude ../sandbox/swift . (on the Kotlin lane, ../sandbox/kotlin) as the provided diff, and do not commit.
No git: in a clone of the course, git reports on the whole course.
Repair (step 8)
BMAD's phase-4 chain runs bmad-sprint-planning,
bmad-build, bmad-code-review; your repair prompt re-enters it at the
review.
The test suite is red. Here is the failing output, verbatim: <paste>. Re-enter at bmad-code-review for the spec or story that owns this behaviour, then bmad-build to apply the fix. Do not edit the tests to make them pass, and tell me which one you reopened. Do not use git in this folder: wherever your workflow needs a diff, use the output of diff -ruN -x .build -x build -x .gradle -x .kotlin -x _bmad -x _bmad-output -x .claude ../sandbox/swift . (on the Kotlin lane, ../sandbox/kotlin) as the provided diff, and do not commit.
What BMAD produced on the build run: SPEC.md and stories.yaml
BMAD 6.12.0, 2026-09-22, in a fresh copy of the Swift lane, handed the planning prompt
above and told to halt after planning. That run could not answer in conversation, so it wrote its five clarifying
questions into the spec; the answers were then folded in by a second pass. This is what
it produced, not a fixed file list; the folder is
../day-3-choose-your-adventure/starter/checkpoints/bmad/.
_bmad-output/implementation-artifacts/statement-periods/SPEC.md
_bmad-output/implementation-artifacts/statement-periods/stories.yaml
_bmad-output/implementation-artifacts/statement-periods/stories/1-parse-cycle-configuration.md
_bmad-output/implementation-artifacts/statement-periods/stories/2-group-into-statement-periods.md
The frontmatter of SPEC.md, which goes on to a frozen decision block, a
25-row edge-case matrix, tasks and acceptance criteria:
---
title: 'Statement periods'
type: 'feature'
created: '2026-09-22'
status: 'ready-for-dev'
route: 'dispatch'
review_loop_iteration: 0
context:
- '{project-root}/change-c-brief.md'
---
stories.yaml, whole:
# Story set for SPEC.md (statement periods). Execution order is list order.
# The five planning questions were answered on 2026-09-22; the decisions live
# under "Decided" in the SPEC.md frozen block. Both stories are unblocked.
- id: "1"
title: Parse a cycle configuration from TSV
description: >-
Add CycleRule and StatementCycle with parse(tsv:named:) as fixed in
change-c-brief.md, covering every "parse" row of the SPEC.md matrix. A
malformed row is skipped; nil only when no usable row carries the name.
spec_checkpoint: true
invoke_dev_with: >-
Read the Decided list in the SPEC.md frozen block first; the frozen block
is locked and settles every parse row. Hand-rolled parsing only.
- id: "2"
title: Group transactions into statement periods
description: >-
Add StatementPeriod and StatementPeriods.periods(for:cycle:), placing by
posted day, newest period first, contiguous, empty middle periods
included, short months clamped, one governing rule per list, covering
every grouping row of the SPEC.md matrix. Depends on story 1.
spec_checkpoint: true
invoke_dev_with: >-
Read the Decided list in the SPEC.md frozen block first; membership is by
posted day, a missing start day clamps to the month's last day, and one
rule governs the whole list. Reuse UTCDay and ISO8601.daysSinceEpoch from
Transaction.swift for all date arithmetic.
If you see something else instead
Likely wrong turns
- The acceptance suite does not compile: a type is named differently from the brief, or
missing. Rename through the framework's artifact, never
the acceptance file. With no Change C:
Swift lane
…/Tests/LedgerKitTests/ChangeCAcceptanceTests.swift:109:23: error: cannot find 'StatementPeriods' in scopeKotlin lanee: …/src/test/kotlin/ChangeCAcceptanceTest.kt:29:38 Unresolved reference 'StatementCycle'. - Red only in
testAuthorizedVsPostedMembershiportestFebruaryCycleStart: your framework read an ambiguity the other way. Record it for step 11, then change the decision in the artifact and repair. cycle-config.tsv is not on the test classpath - copy it into src/test/resources/means the setup's fixture line did not run.error: PCH was compiled with module cache path '…/sandbox/swift/.build/…'means the copy brought a build folder along; runrm -rf .buildand test again.- To start over, use the reset below; it spares
../work/, so move your planning folder there first to keep it.
Self-check
The acceptance suite decides it
Run it after step 9 and any repair.
swift test 2>&1 | grep -A1 -e "Test Suite 'ChangeCAcceptanceTests' [pf]" -e "Test Suite 'All tests' [pf]"
With the reference implementation in place it printed:
Test Suite 'ChangeCAcceptanceTests' passed at ….
Executed 6 tests, with 0 failures (0 unexpected) in … (…) seconds
--
Test Suite 'All tests' passed at ….
Executed … tests, with 1 test skipped and 0 failures (0 unexpected) in … (…) seconds
Pass is both suites passed. failed on either is a red test; no
output means no compile.
./gradlew test
grep -o 'tests="[0-9]*" skipped="[0-9]*" failures="[0-9]*" errors="[0-9]*"' build/test-results/test/TEST-ledgerkit.ChangeCAcceptanceTest.xml
With the reference implementation in place the grep printed:
tests="6" skipped="0" failures="0" errors="0"
Pass is BUILD SUCCESSFUL in … from the first command and exactly that line
from the second. After BUILD FAILED with e: lines, the report is
left over from an earlier run.
Done when: the six acceptance tests pass in a green
suite, the known-issue run fails on JPY alone, the diff shows nothing out of bounds, decisions
live in artifacts, and your three lines sit under ## Change C notes in
../work/map.md.
Reference answers
The two deliberate ambiguities, and which track surfaced them on the build run
First: whether a transaction belongs to a period by its authorized date or its posted
date. The brief says the two are often different days and never says which one counts.
Fixture row LK-015, authorized 2026-03-04 and posted 2026-03-05, lands in
different periods under the standard cycle depending on the answer.
testAuthorizedVsPostedMembership holds one reading.
Second: what a cycle that starts on day 31 does in February. The brief allows any start day
from the 1st to the 31st, and the cycle table your setup copied in carries a
month-end configuration on the 31st.
testFebruaryCycleStart holds one reading.
On the build machine on 2026-09-22, one run per track: OpenSpec found both unprompted,
recorded them as blocking open questions without recommending an answer, named
LK-015 and the month-end configuration as its evidence, and refused
to implement. BMAD found both among five clarifying questions, each with options and a
recommendation. LID was handed both answers in its prompt because that run could not stop for
a person, so it turned them into requirements rather than questions, and its finding of them is
the least independently shown of the three. None of the three chose silently. That is one
observation on one machine on one date, not a property of the frameworks: your run is the
evidence for your card in Exercise 3.
Reset
Quit Claude Code, then from inside day3-work run your lane's line. It replaces the
copy with a fresh one and leaves you inside it; sandbox/ and ../work/
are untouched.
cd .. && rm -rf day3-work && cp -R sandbox/swift day3-work && cd day3-work
cd .. && rm -rf day3-work && cp -R sandbox/kotlin day3-work && cd day3-work
Then paste this page's setup lines after cd day3-work and redo your track's
install-and-init steps from Exercise 1. OpenSpec on your PATH and the LID plugins at user scope
survive; BMAD lives in the project, so rerun its installer. Do not reset at the end:
Exercise 3 continues in this day3-work.
Sources
openspec-08,openspec-09,openspec-18—/opsx:propose <feature description>,/opsx:apply,openspec listandopenspec validate, from OpenSpec's getting-started guide.openspec-13,openspec-16,openspec-17—## ADDED Requirements,### Requirement:and#### Scenario:, from OpenSpec's concepts page.openspec-01— the npm install command, from OpenSpec installation.openspec-04— version 1.13.1, from the OpenSpec latest release.lid-06—/linked-intent-dev:update-lidreconciles drift or changes mode, from the LID repository.lid-11,lid-13— the// @specannotation and the semantic ID shape, from LID's AGENTS.md.lid-25— commit 831c1959, from the LID commit history.bmad-06—bmad-buildhalts withoutuv, from the BMAD changelog (v6.11.0).bmad-07—/bmad-buildfollowed by what you want built, from BMAD's Build your first change.bmad-11— the phase-4 chain, from the BMAD changelog.cc-core-07— default mode asks before edits and commands, from Permission modes;cc-core-19—/clearempties the conversation, from Commands.- From the pinned snapshots under
../day-3-choose-your-adventure/starter/vendored/: thelinked-intent-devskill's phases and its stop after each one (lid-831c1959,skills/linked-intent-dev/SKILL.md);/opsx:applyselecting a named change and working its task list (openspec-1.13.1,.claude/commands/opsx/apply.md); thebmad-buildskill's openinguv runcommand and halt, itsspec-<slug>.mdfile name and route from aready-for-devspec to implementation, Open Questions answered into the frozen block, an implementing subagent that reads only the spec, and three reviewer subagents (bmad-6.12.0,.claude/skills/bmad-build/:SKILL.md,step-01-clarify-and-route.md,step-02-plan.md,step-03-implement.md,customize.toml). The Swift paths and the Kotlin-lane lines the Kotlin notes replace are in the checkpoints'tasks.md,design.mdandSPEC.md. - Observed on the build machine on 2026-09-22, one scratch copy of the Swift lane per
track:
openspec-obs-06(openspec validateoutput),openspec-obs-07(the change folder),openspec-obs-08(both ambiguities found),lid-obs-02(the LID plugins installed at user scope),lid-obs-05(the## LIDblock, its paths and its arrow rule),lid-obs-08(cascade stops at a sibling),bmad-obs-01(version 6.12.0),bmad-obs-05(the install writes into the project),bmad-obs-10(no skill starts without itsuvcommand),bmad-obs-11(the spec folder). The planning runs behind every reveal are described in each track'sCHECKPOINT.mdunder../day-3-choose-your-adventure/starter/checkpoints/. - The quoted test and diff output was recorded on this machine on 2026-09-23 in a fresh copy made by this page's setup block, one run per lane; where it says so, with the reference Change C implementation copied in to stand for a framework's result.