Skip to content

Trace linter

scripts/trace-lint.mjs validates the whole ID graph on every push and every PR. Link rot is the killer — 80%-accurate traceability is worse than none — so it has run in CI since the first commit.

  1. A FEAT-* markdown file past proposed with zero code-tag references.
  2. A code tag whose ID doesn’t resolve to a markdown file.
  3. Any depends_on / decisions / affects / sub_feature_of / superseded_by edge pointing at a missing ID.
  4. A feature status: built whose ID doesn’t appear in both code and tests.
  5. The same ID declared more than once within a single collection.
Terminal window
pnpm trace-lint

Exit code 0 with a summary line on success; exit code 1 with one line per violation otherwise. Output is plain text, one per error.

  • Unparseable frontmatter is itself a lint error, not a silent skip.
  • Regex literals don’t count as tags — the scanner requires a full FEAT-nnnn form; FEAT-\d{4} in a pattern never matches.
  • Test detection is by path: *.test.*, *.spec.*, tests/, __tests__/.
  • The grep-based v1 is deliberate; a v2 may be SHACL over a generated graph, but a convention without a linter is a suggestion, so grep shipped first.
4 open decisions