Adopting without a rewrite
Adopt a spec framework on the next ticket, on the smallest subset that answers your failure, in files your team can read without the tool, and plan for a network that will not let you install it.
Adopt on the next ticket, not on the backlog
The rewrite instinct waits until everything has a spec. But nobody reads a spec for code that already works, and the first evidence arrives a week later. Put the next ticket through the framework and leave the rest alone. Five tickets give you five real artifacts, an opinion you can defend, and something for the two-week signal from Lessons 1 and 2 to count.
Map what exists before you write anything new
The one exception is a map the machine writes, and only LID writes one.
OpenSpec's specs cover only the change in hand, so it needs no map.
LID's /arrow-maintenance:map-codebase reverse-engineers an existing codebase's design
tree for you to reconcile. On the build machine (LID 831c1959, 2026-09-22) it wrote thirteen
documents carrying 63 EARS requirement IDs and changed no source or test file; the skill's own
instructions did not load in that run, so the tree is LID-shaped rather than LID-generated.
Fix its wrong inferences before you cite its IDs in code.
BMAD's specs cover only the change in hand, so it needs no map.
The subset you keep
Adoptions die in a framework's long tail. Write your subset down, because the default is all of it.
OpenSpec: the change folder, the three delta headers a first change needs (## ADDED
Requirements, ## MODIFIED Requirements, ## REMOVED
Requirements), and /opsx:propose, /opsx:apply and
/opsx:archive. Its other commands and the inspection CLI can wait.
LID: EARS requirements with semantic IDs and their [x],
[ ] and [D] status markers (implemented, gap, deferred), and a
// @spec line comment on the topmost function that owns the behavior. Save the
drift audit, /arrow-maintenance:arrow-maintenance, for before a review relies on
the map's IDs.
BMAD: SPEC.md, stories.yaml and one file per
story, the ready-for-dev status, /bmad-build, and
bmad-code-review for repairs. The rest of the 29 skills, sprint planning included,
wait for epic-sized work.
What survives a locked-down network
Your track's “Network blocked?” box in Exercise 1 shows what survives when the install source is blocked.
OpenSpec comes from the public npm registry and needs Node 20.19.0 or higher. Its
tarball installs only if npm reaches a local mirror, because the /opsx commands call
the openspec CLI before they write anything.
Turn OpenSpec's telemetry off:
openspec config set telemetry.enabled false
LID comes from a plugin marketplace on GitHub. It runs from the vendored plugins with
--plugin-dir.
BMAD comes from the public npm registry and needs Node 20.12 or later and
uv with Python 3.11 or later, which uv downloads itself when the network allows;
bmad-build and bmad-build-auto halt without uv. Its files
copy in, but behind a blocked network uv and its Python must already be installed.
The lasting answer is a mirror: pin a version, mirror it, upgrade on purpose.
The artifacts have to be readable without the tool
All three store specs as plain text, Markdown plus BMAD's stories.yaml, so a
reviewer without the tool can read them in a pull request, and adoption stays reversible. Test
one artifact from your Exercise 2 run: if a reviewer new to the framework could not approve or
reject it, the tool's vocabulary is now part of every review.
Committing it: the team file and your file
Commit the framework's own files: openspec/ plus the commands and skills
openspec init wrote under .claude/.
Commit the framework's own files: LID's docs/ tree. LID's plugins stay at
user scope, one install per teammate.
Commit the framework's own files: _bmad/, its skills under
.claude/skills/ and the spec folders under
_bmad-output/implementation-artifacts/.
BMAD has its own personal file: _bmad/config.user.toml holds your install
answers, and the installer writes your system username there and into two
config.yaml files. Check all three before the first commit, and keep
config.user.toml out, like the settings.local.json below.
Commit .claude/settings.json too, with the permission rules the framework's
commands need. “Yes, and don't ask again” on a shell command saves its rule to the
personal .claude/settings.local.json, which takes precedence, so a command that runs
unprompted for you may be allowed nowhere else until its rule moves into the committed
file.
Keeping CLAUDE.md from growing
A framework can write into CLAUDE.md, which loads into every session and is paid
for on every turn. On the build machine (OpenSpec 1.13.1, BMAD
6.12.0, 2026-09-22) OpenSpec and BMAD left it untouched, and LID's /arrow-maintenance:map-codebase run appended a
29-line ## LID section.
A line @path/to/import inside CLAUDE.md pulls in another file, so a
framework's directives can live in their own file, deletable in one edit.
Imported files load at launch too, so that changes organization, not cost. It also fails LID:
update-lid looks for its directives and ## LID block in
AGENTS.md if it exists, otherwise in CLAUDE.md itself, and writes back
what it misses, so on the LID track the block stays in whichever of the two your project uses.
From inside day3-work, compare the shipped file with yours:
wc -l ../sandbox/swift/CLAUDE.md CLAUDE.md
wc -l ../sandbox/kotlin/CLAUDE.md CLAUDE.md
If your CLAUDE.md line counts more than the shipped file's, the framework owes
the difference under Day
2's net-zero line cap.
Only if your CLAUDE.md contains @ imports, add each imported file
to the command, for example for a line @docs/framework-directives.md:
wc -l ../sandbox/swift/CLAUDE.md CLAUDE.md docs/framework-directives.md
wc -l ../sandbox/kotlin/CLAUDE.md CLAUDE.md docs/framework-directives.md
Then compare the shipped file's count with the sum of your files' counts. Skip wc's
total line: it adds the shipped file in too.
When not to adopt
The biggest case: a module with no tests, like a payments module with no XCTest target or only a flaky Gradle UI test. Every framework here assumes a sensor that can tell the agent it is wrong; without one, it files specs nobody can check.
Adopt a test suite first. A team norm: no framework goes on a module until its tests can fail for the reason the spec cares about.
Skip the framework, too, for a one-off script or throwaway code, where nobody will read the spec again, and on a team that merges without review, where nobody reads it the first time.
Quick check
Your framework appends a dozen lines of directives to CLAUDE.md. What do
you do with them, and why does it matter more than it looks?
Move them into their own file and pull it in with @path/to/import, so they are
readable in one place and removable in one edit, unless the framework reads them back from
CLAUDE.md, as LID's update-lid does. That alone saves nothing: CLAUDE.md
and the files it imports load into every session, and you pay for them on every turn. Day 2's
net-zero line cap applies across both files.
You are told to adopt a spec framework on a module that has no tests. What do you do first, and what is the reasoning?
Write the tests first. Every framework assumes something that can tell the agent it got it wrong; with no failing command available, the acceptance criteria cannot fail, and the framework produces documents instead of checks.
Sources
Framework documentation accessed 2026-09-22; Claude Code documentation accessed 2026-09-22 and 2026-09-23. Versions pinned for Day 3: OpenSpec 1.13.1, LID commit 831c1959, BMAD 6.12.0. Entries marked observed were recorded on the build machine on 2026-09-22 in scratch copies of the Swift lane.
lid-08,lid-09,lid-obs-02—/arrow-maintenance:map-codebasefor an existing codebase, the/arrow-maintenance:arrow-maintenancedrift audit, from the LID repository; observed: the plugins installed at user scope on the build machine.lid-11,lid-12,lid-13— the// @specline comment, the[x],[ ]and[D]status markers, and the semantic ID shape, from the LID repository'sAGENTS.md.lid-obs-05,lid-obs-06,lid-obs-07— observed: the map wrote thirteen documents carrying 63 EARS IDs and no source or test change, and appended a 29-line## LIDsection toCLAUDE.md; in that run the skill's own body did not load.lid-obs-10— observed: with the marketplace plugins disabled, starting Claude Code with--plugin-dirpointing at the vendored LID plugins made their commands resolve.- Where
update-lidlooks for LID's directives and## LIDblock (AGENTS.mdif it exists, otherwiseCLAUDE.md) and what it writes back when they are missing — LID's own text at commit 831c1959, in this course's snapshot atday-3-choose-your-adventure/starter/vendored/lid-831c1959/lid/plugins/linked-intent-dev/skills/update-lid/SKILL.md. openspec-01— the npm install command, from OpenSpec installation;openspec-03— the Node 20.19.0 floor, from the npm registry entry.openspec-08,openspec-09,openspec-10,openspec-18— propose, apply, archive and the inspection commands, from OpenSpec getting started.openspec-13,openspec-14,openspec-15— the three delta headers, from OpenSpec concepts.- The
openspeccalls in/opsx:propose(allowed-tools: Bash(openspec:*), step 2'sopenspec context --jsonand its stop on failure), from the vendoredday-3-choose-your-adventure/starter/vendored/openspec-1.13.1/project-files/.claude/commands/opsx/propose.mdat OpenSpec 1.13.1. openspec-19— the telemetry opt-out, from the OpenSpec repository.openspec-obs-02,openspec-obs-03— observed:openspec initwrote anopenspec/folder and twelve files under.claude/and leftCLAUDE.mdunmodified.bmad-01,bmad-05— the install command and the Node 20.12 floor, from BMAD installation.bmad-06,bmad-11,bmad-18—uvwith Python 3.11 or later is required, andbmad-buildandbmad-build-autohalt without it; the sprint-planning, build, code-review chain; the config layering that includes_bmad/config.user.toml, from the BMAD changelog (v6.11.0).bmad-obs-02— observed: the installer's welcome text saysuvprovisions the Python interpreter itself.- What
bmad-sprint-planningreads (the epic files) and how/bmad-buildtakes aready-for-devspec to implementation and then its own review — BMAD 6.12.0's own skill text, in this course's snapshot atday-3-choose-your-adventure/starter/vendored/bmad-6.12.0/project-files/.claude/skills/(bmad-sprint-planning/SKILL.md,bmad-sprint-planning/references/generate-tracking.md,bmad-build/step-01-clarify-and-route.md). _bmad/config.user.tomlas the personal install-answers file and the username in three files — the file headers of_bmad/config.tomland_bmad/config.user.tomland the notes inSNAPSHOT.md, in this course's snapshot atday-3-choose-your-adventure/starter/vendored/bmad-6.12.0/.bmad-12,bmad-13— the frontmatter status values and theSPEC.md,stories.yamland per-story layout, from BMAD autonomous development loops.bmad-obs-05,bmad-obs-06,bmad-obs-11— observed: a default 6.12.0 install wrote_bmad/and 29 skills and leftCLAUDE.mdunmodified, and the build skill wrote its spec folder under_bmad-output/implementation-artifacts/.cc-core-12,cc-core-15,cc-core-40— the@path/to/importsyntax, path-scoped rule files under.claude/rules/, and imports loading at launch, from Memory.cc-core-36—CLAUDE.mdfiles loaded at startup, from Context window.cc-core-23,enterprise-11— the shared and personal settings files and their precedence, from Settings.cc-core-39— where “Yes, and don't ask again” saves a rule, from Permissions.cc-core-32— Claude Code 2.1.280, from the Claude Code changelog.