Field guide + executed inert lineage lab

When a specification changes, what becomes stale?

A specification is useful only if a later change can answer a practical question: which downstream artifacts can still be trusted? A plan, task list, and check suite may all look complete while describing the previous requirement.

This guide includes an original zero-network simulator. It uses invented artifacts and does not run Spec Kit, OpenSpec, cc-sdd, a coding agent, or an implementation. Its result demonstrates one declared lineage policy—not product behavior or improved software quality.

The useful distinction is authority over time

An issue or prompt can describe intent. A persisted specification adds an addressable revision that other artifacts can cite. That creates a lineage question whenever the specification changes:

  1. What is the authoritative requirement revision?
  2. Which plan was derived from it?
  3. Which tasks were derived from that plan?
  4. Which checks still cover the current requirement?
  5. Where must a human stop and review before work resumes?

GitHub Spec Kit explicitly leaves persistence and mutation policy to the team, describing flow-back, flow-forward, and living-spec approaches. OpenSpec documents proposals and delta specs that are later archived into current specs. cc-sdd describes specs as boundary and revalidation units. Those are documented models, not evidence that any was run here.

A synthetic requirement change

The fixture starts with spec-1@1. Its plan cites that revision; tasks cite the plan; checks cite both the original spec and tasks. The invented change adds an explicit empty-state requirement and advances the spec to revision 2.

The simulator walks declared dependencies. It marks the plan stale because it cites spec-1@1, then marks tasks and checks stale transitively. It emits a rebuild order, proposed next revision identifiers, and three review stops. Those proposed revisions are not executed or reviewed rebuilds. Passing the simulator means only that this small manifest is internally consistent.

This differs from the plan-contract mutation lab: that lab rejects unsafe edits inside one plan. This lab asks what an approved requirement change invalidates across several derived artifacts.

Run the inert lab

Prerequisite: Node.js 24 or newer. Download the files together, rename the script from .txt to .mjs, and run:

node spec-lineage-lab.mjs spec-lineage.synthetic.json result.json

The script uses Node.js built-ins, makes no network request, and refuses to overwrite evidence. Repository tests run it twice in isolated paths and require byte-identical results. They also mutate dependency declarations and reject unknown fields, invalid revisions, and changes that do not bind the current spec.

Reader action: declare the invalidation rule before the change

For a real project, record the persistence policy beside the artifacts. Require each derived artifact to cite the exact revision it used. When a requirement changes, traverse those citations before editing code. Review the changed requirement, regenerate or reconcile derived work according to the declared policy, then rerun checks that bind the new revision.

Do not silently update version labels to make the graph green. A refreshed citation without a reviewed derivation is false lineage.

Primary sources:

No upstream repository was installed or executed. Current documentation informed the comparison; the simulator, fixture, worksheet, conclusions, and limitations are original to this guide.

Continue

Keep reading

Plan contract mutation lab →

All library entries →