Skip to content

Remove SPECS.md and rationalize its ADR migration into co-located contracts #163

Description

@atqamz

Problem

SPECS.md began as a design and implementation plan. The implementation has landed, but the 2,831-line file remains a second description of nearly the entire program. It duplicates command behavior, schemas, state transitions, output examples, implementation details, contributor rules, and historical rationale that already have or should have an owner closer to the code.

Issue #159 proposed shrinking SPECS.md to contract and moving rationale into ADRs. PR #162 shows why that split is an intermediate state rather than the final information architecture:

  • SPECS.md falls from 2,831 to 2,579 lines, only 9 percent by line count.
  • 26 ADRs plus an index add 1,872 lines.
  • The PR as a whole adds 2,335 lines and deletes 692, a net increase of 1,643 lines.
  • Contract sections gain Why: links into ADRs, while ADRs link back into SPECS.md, so understanding one behavior crosses more files.
  • Neither the SPECS.md contract nor the new links are enforced by the build or tests; the PR test plan treats the documentation checks as manual.
  • Some ADRs preserve incident-level implementation history rather than a durable architectural boundary.

The problem is not only that rationale and contract share one file. The problem is that a monolithic prose specification duplicates executable behavior and has no single subsystem owner. Splitting that prose into a large contract plus many records increases navigation, maintenance, and drift surfaces.

This issue supersedes #159 as the final structure. If #162 lands, treat its reduced SPECS.md and ADR set as migration input: preserve its useful analysis, then rationalize both rather than assuming all newly created files are permanent. Sequence this work after #162 so the migration is performed once against the merged state.

Decision

Remove SPECS.md completely. Do not replace it with another monolithic specification or a generated copy of the CLI. Audit and restructure the ADRs introduced by #162 as part of the same migration.

A contract belongs beside the mechanism that enforces it:

Information Authoritative home
Commands, flags, defaults, arguments, and user-facing errors Cobra help text plus command tests
Exit codes and error kinds cmd/root.go, focused package/command tests, and concise user documentation where needed
TOON and JSON output shapes internal/axi, golden/contract tests, and command help
Database schema and migration rules internal/store schema/migrations and migration tests
Brief, backlog, report-channel, and other file formats Owning package documentation, parsers/writers, fixtures, and format tests
Watcher state transitions and persistence invariants internal/watcher code and focused state-transition tests
Harness capabilities and launch behavior internal/harness, shared fake behavior, and harness tests
Observed contracts of external tools internal/faketool/FIDELITY.md and tests/contract
Fleet-home agent workflow internal/agentsmd generated template and its tests
Contributor-wide policy AGENTS.md or CONTRIBUTING.md, whichever owns the audience
Installation and operator workflows README and command help
Durable architectural decisions that remain useful A small ADR only when it records a stable boundary and materially rejected alternatives

Executable artifacts win whenever prose disagrees. A contract that matters must have a test at the closest practical boundary; prose alone must not be the only enforcement mechanism.

SPECS.md migration

Inventory the merged SPECS.md section by section and give every span one disposition before deleting it:

  1. Already represented and enforced: delete the duplicate prose.
  2. Durable contract without a sufficient owner: move the minimum statement to the owning package/help surface and add or strengthen a focused test.
  3. Contributor or user guidance: move a concise version to AGENTS.md, CONTRIBUTING.md, README, or command help.
  4. Durable architectural rationale: retain only if a future contributor could reasonably reverse a still-important boundary without it; keep or write one focused ADR.
  5. Shipped plan, stale example, implementation narration, incident history, rejected pre-release scope, or duplicated generated content: delete. Git and closed issues already preserve history.

Record the disposition in the implementing PR description or a temporary review checklist, not in a permanent replacement ledger.

Then remove every reference to SPECS.md from README, AGENTS.md, CONTRIBUTING.md, Go comments, tests, generated fleet-home instructions, fidelity documentation, and retained ADRs. Repoint only references that still add value; delete comments whose only purpose was to cite the monolith.

ADR restructuring after #162

Review every ADR introduced by #162 independently. Give each one exactly one disposition:

  1. Keep: it records a durable architectural boundary, realistic rejected alternatives, and consequences not adequately expressed by tests or local documentation. Tighten it so it does not restate implementation details.
  2. Merge: two or more records are facets of one stable decision and are more understandable together. Merge around the boundary, not merely around a shared subsystem.
  3. Relocate: its useful content is actually an invariant, external-tool observation, contributor rule, or user workflow. Move the minimum content to the owning test, FIDELITY.md, AGENTS.md, CONTRIBUTING.md, README, or command help, then delete the ADR.
  4. Delete: it mainly narrates an incident, repeats current code, preserves rejected pre-release scope, or is already recoverable from its issue and PR history.

Do not merge all records into a large replacement design history. A smaller ADR set is a result of applying the bar, not a numeric target. Update docs/adr/README.md to describe only the retained collection and remove its dependency on SPECS.md.

ADR bar

An ADR must describe a durable architectural decision, identify a realistic alternative a future change might reintroduce, and remain useful without narrating individual bugs or restating current implementation details.

Prefer the issue or PR that made a local implementation decision as its historical record. Prefer a focused invariant test when the important fact is what must continue to hold. Prefer FIDELITY.md when the fact belongs to an external tool rather than to Secondhand architecture.

Non-goals

  • Generating Markdown from Cobra solely to replace SPECS.md. hand --help is already the command reference.
  • Copying every deleted example into README or package comments.
  • Preserving prose merely because removing it feels risky or because docs: separate specification contracts from rationale #162 created a file for it.
  • Combining the new ADRs into one large replacement for SPECS.md.
  • Reorganizing unrelated production code.

Acceptance criteria

  • This work starts from the merged result of docs: separate specification contracts from rationale #162, if docs: separate specification contracts from rationale #162 lands.
  • SPECS.md is deleted.
  • rg "SPECS\.md" returns no tracked references, including under docs/adr/.
  • Every ADR introduced by docs: separate specification contracts from rationale #162 has a recorded keep, merge, relocate, or delete disposition in the implementing PR.
  • Every retained ADR passes the narrow ADR bar, contains no duplicated behavioral contract, and links directly to relevant code, tests, issues, or PRs where useful.
  • docs/adr/README.md describes the final retained collection without acting as a replacement specification.
  • No new monolithic specification, contract ledger, exhaustive generated CLI reference, or monolithic ADR replaces SPECS.md.
  • Each retained behavioral contract has a clearly named owner beside its implementation and a focused test where practical.
  • User-facing workflows remain discoverable through README and hand --help.
  • Contributor-wide rules remain discoverable through AGENTS.md and CONTRIBUTING.md.
  • External-tool fidelity remains documented and checked through internal/faketool/FIDELITY.md and make contract.
  • The implementing PR explains the disposition of every merged SPECS.md section and every ADR created by docs: separate specification contracts from rationale #162.
  • make lint, go build ./..., go test -race ./..., the e2e suite, and make contract pass.
  • A fresh fleet home generated by hand init contains no stale reference to SPECS.md.

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentation

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions