Audit: Plan references in source¶
What we check¶
Every reference to a plan file (PLAN-*.md) written into source code
or configuration must resolve in the repository it is written in, or
else be an absolute URL.
Since 2026-09-24 the plan-references-in-code shared block (see the
push-audit audit) says what code may cite at all:
the reasoning behind a line belongs in its comment, not behind a
pointer to the plan that produced it, and a plan link survives only
for work that is not built yet -- "deferred; see
docs/plans/PLAN-session-001-feedback.md". This audit is the
mechanical half for the links that remain: whatever a comment still
points at has to be there when a reader follows it.
Nothing renders these pointers. A markdown link in docs/ breaks
visibly and docs-external-links audits it; a path inside a //
comment or a YAML key is inert text no renderer resolves. So a renamed
or archived plan rots the pointer silently, and the first person to
notice is someone who went looking for the plan and did not find it
-- at which point the comment is worse than none, because it asserts
a record exists.
The check runs git ls-files, skips markdown files (they are
docs-external-links' scope), files under a plans directory in
docs/, and files over 2 MB, and resolves each PLAN-<name>.md it
finds in what remains:
- Path-qualified references (
docs/plans/PLAN-foo.md) resolve as written, from the repository root and then fromdocs/. The second position exists for mkdocs navigation, which addresses pages relative to the documentation root. - Bare filenames (
PLAN-foo.md) match any markdown file underdocs/plans/at any depth, so a plan archived intodocs/plans/completed/still resolves. A bare filename names no directory, so there is no path for it to be wrong about.
Three shapes are not flagged:
- Absolute URLs. Text matching a
scheme://URL is removed before scanning. A plan in another repository cannot resolve locally and should be written ashttps://github.com/<org>/<repo>/blob/<default-branch>/docs/plans/PLAN-foo.md-- the same ruledocs-external-linksandreadme-absolute-linksapply, for the same reason: a reference read somewhere other than where it lives has to be absolute. PLAN-TEMPLATE.md. Not a plan but the template plans are written from, living at the repository root and held there by theplan-templateaudit.- Lines carrying
audit-ok: plan-reference, for the rare line where aPLAN-*.mdstring is not a pointer -- a filename pattern in a linter config, a fixture naming a plan that deliberately does not exist.
A plans directory is skipped because it is the record of how the
software was built, and citing plans is its job. The case that forced
the rule was client-python-k3s, whose push-audit phase keeps the diffs
it reviewed in docs/plans/audit/diffs/: those diffs quote every plan
path they touched, including plans renamed since and plans in other
repositories, and rewriting them so the pointers resolve would falsify
the record. The scope is the one plan-phase-references exempts -- a
plans/ directory under docs/ at any depth -- so the two agree on
what a plans directory is. A plans/ directory elsewhere, such as a
package in the code, is source and is scanned.
Test suites are scanned like any other source: a test file carries
prose pointers too and they rot the same way -- instar's
tests/test_adversarial.py cites a plan that no longer exists, in its
module docstring -- so skipping files for having "test" in the name
would hide exactly the finding this audit is for. A suite whose plan
paths genuinely are all fixtures carries audit-ok:
plan-reference-file once near the top with a sentence saying why. That
exempts the whole file, prose included, so prefer the per-line form.
A repository with no plan references outside markdown is N/A.
This audit composes with plan-phase-references, which governs what
documentation prose may cite, plan-history-in-source, which reads
the same files for the phase, decision and step numbers code should
not cite at all, and plan-index, which governs whether a plan is
registered. This one governs only whether a pointer written in code
still lands on a file.
Template¶
No template. Fix each reference at its source:
- the plan moved to
docs/plans/completed/-- update the path, or drop to the bare filename, which resolves either way; - the plan was renamed -- update the name;
- the plan lives in another repository -- rewrite it as an absolute
https://github.com/...URL; - the plan never existed, or the reference is not a pointer -- delete
it, or mark the line
audit-ok: plan-reference; - the whole file is fixtures rather than pointers -- mark it once with
audit-ok: plan-reference-file, and say why.
Deleting a pointer is not a fix on its own where the comment leaned
on it: write the reasoning the plan held into the comment, then drop
the pointer. That is also the right fix for a pointer that does
resolve but cites work already built -- plan-references-in-code
asks for it, though this audit does not flag it.
Projects¶
Per-project compliance for this criterion is regenerated on every run of the consistency audit: see the compliance page.