Skip to content

docs: enforce the DECISIONS.md narrative log, backfill iters 15-23 - #88

Open
drdgreed wants to merge 4 commits into
mainfrom
docs/enforce-decisions-log
Open

docs: enforce the DECISIONS.md narrative log, backfill iters 15-23#88
drdgreed wants to merge 4 commits into
mainfrom
docs/enforce-decisions-log

Conversation

@drdgreed

@drdgreed drdgreed commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Item #9why the discipline lapsed, then the fix. It required correcting something I told you.

I was wrong: verdict recording never lapsed

I reported "DECISIONS.md has zero entries for chg-19 through chg-31 — 13 changes of governance debt." I got that by grepping DECISIONS.md for chg-N strings.

35 verdicts are recorded — in the manifests, structured and CI-validated:

iter-16 → chg-19, chg-20 keep      iter-19 → chg-25 improve
iter-17 → chg-21/22/23 keep        iter-20 → chg-29 rollback
iter-18 → chg-24 keep              iter-21 → chg-30 keep

What actually lapsed: the narrative layer, twice

Record Enforcement State
harness/manifests/iter-N.json schema + validator + required CI check + PR-template field complete through iter-24
docs/DECISIONS.md prose — nothing dead at iter-14
docs/ITERATIONS.md prose — nothing dead at iter-7

Two causes. Enforcement asymmetry — the third time this session (P-014, P-016, and now this): what isn't checked doesn't happen. And redundancy without a decision — the manifest schema grew a verdicts[] array that absorbed most of DECISIONS.md's job, so the prose stopped being the path of least resistance. Nobody decided to retire it.

CLAUDE.md step 5 still pointed at the unenforced artifact, which is exactly why my audit of that instruction produced a false alarm.

The fix (your call: keep + enforce)

  • test_decisions_log_coverage.py — every manifest needs a matching ## iter-N — section. Watched failing on 9 missing iterations, green after. Asserts coverage, not quality — stated in the docstring rather than implied. Includes a denominator check, because a coverage gate that enumerates nothing passes vacuously.
  • Backfilled iters 15–23. Entries for 15–18 are marked "(Reconstructed from the manifest)" — I didn't do that work and am writing from the record. Silently uniform prose would imply a provenance consistency that doesn't exist.
  • CLAUDE.md step 5 now names both artifacts with their different jobs, and records why the second decayed.

Two stale claims I'd made and hadn't fixed

  • The enforcement block still said enforce_admins is false with the admin bypass live. I closed it on 2026-08-01 and didn't update the doc. Now recorded as closed — with the two gaps that remain true: no required PR review (a single author can self-merge on green CI) and strict: false (a branch can merge against a stale base).
  • The scope-guard section said five call sites; chg-32 made it six.

Both are the drift this file's own header warns about. I introduced both and am fixing them a PR late.

Left open deliberately

ITERATIONS.md gets a status banner saying it's stalled and not currently required — but revive-or-retire is your decision, not a test's. Its role overlaps DECISIONS.md almost entirely, so retiring is defensible; reviving means committing to a third enforced artifact.

make test-all1044 passed.

🤖 Generated with Claude Code

https://claude.ai/code/session_019UrGtq26sBHzoQZkm9M27A

PACCA kept three overlapping records of the same work. Only one was enforced,
and the other two died — DECISIONS.md at iter-14 (2026-07-26), ITERATIONS.md at
iter-7 (2026-05-31), while the manifests ran to iter-24.

The cause was not neglect. The manifest has a JSON schema, a validator, a
required CI check and a PR-template field demanding its path; the prose logs had
none of that. Add that the manifest schema grew a verdicts[] array which
absorbed most of what DECISIONS.md was for, and the prose stopped being the path
of least resistance. Nobody decided to retire it. This is AGENT_LESSONS P-014
and P-016 arriving a third time: what is not checked does not happen, and "try
harder" is not a fix.

David's call: keep and enforce. This is the gate.

Two things it deliberately does NOT do. It asserts coverage, not quality — it
cannot tell whether an entry says anything useful, only that the iteration was
not skipped, and the docstring says so rather than implying more. And it does
not cover ITERATIONS.md, which is 17 iterations behind and overlaps DECISIONS.md
almost entirely; revive-or-retire is a decision, not a test's to make.

Includes a denominator check (P-016): a coverage gate that enumerates nothing
passes vacuously and looks identical to one that passes honestly.

The matcher accepts two heading shapes. iter-1 predates the convention and is
titled "## chg-1 (iter-1) — ...". Normalising it would break an existing anchor
for no gain, so the test accommodates the document rather than the document
being rewritten to satisfy the test.
…ries

Restores what the manifests structurally cannot hold: why an iteration was
shaped as it was, what an unexplained red test meant, and what the evaluation
could not establish.

Entries for iters 15-18 are marked "(Reconstructed from the manifest)" in the
text. That boundary is explicit on purpose — I did not do that work and am
writing from the record, so a reader can weigh those differently from iters
19-23, which are first-hand. Silently uniform prose would have implied a
consistency of provenance that does not exist.

The narrative each entry carries, rather than restating its manifest:

  iter-15  a `str` return type cannot express "this worked, but not how you
           think" — the shape shared with iter-14
  iter-16  all three defects found by adversarial validation, not by the suite;
           the origin of P-009
  iter-17  the third in-flight state the spec did not name; the origin of P-013
  iter-18  a metric that moves without the system moving is not a measurement
  iter-19  moving a check from a judge to a matcher changes what the check
           MEANS; and counting unique ids is not counting cases
  iter-20  the first ROLLBACK, and why the measurement change that preceded it
           is what invalidated it
  iter-21  the aggregate was unchanged at 85.7% while two cases moved in
           opposite directions — the total would have shown the fix doing
           nothing
  iter-22  the harness supplied what production did not, so the golden set
           could never have found the gap
  iter-23  an expectation coupled to three open defects, pinned so repairing
           them is loud
…stale

Step 5 said "Record a verdict in docs/DECISIONS.md" and named only the artifact
that had no enforcement. That is why my own audit of this instruction produced a
false alarm: grepping DECISIONS.md for chg-N found nothing for chg-19..chg-34
and I reported 13 changes of governance debt. Wrong — 35 verdicts were recorded,
in the manifests, structured and CI-validated. Verdict recording never lapsed;
the NARRATIVE layer did.

Step 5 now names both, with their different jobs: the manifest verdicts[] array
as structured SSOT (schema-validated by the required validate-manifests check),
and DECISIONS.md for what a schema cannot hold (now gated by
test_decisions_log_coverage.py). It also records WHY the second decayed —
enforcement asymmetry, not neglect — so the next reader understands the rule
rather than just obeying it.

Two corrections to claims this file made that my own work invalidated:

- The enforcement block still said enforce_admins is false and described the
  admin bypass as live. I enabled it on 2026-08-01 and did not update the doc.
  Now records the bypass as CLOSED, and keeps the two residual gaps that remain
  true: no required PR review (a single author can self-merge on green CI), and
  strict=false (a branch can merge against a stale base).

- The scope-guard section said five call sites. chg-32 added a sixth,
  db.read_prior_denials — the first READ in the prior-auth scope and the first
  guarded call touching rows outside the current request. Now six, with that
  distinction noted.

Both are exactly the drift the file's own header warns about: "If you find a
claim here that the code contradicts, the code wins — fix the doc in the same
PR." I introduced both and am fixing them a PR late.
… dates imply it

ITERATIONS.md last moved 2026-05-31 at iter-7, seventeen iterations ago, while
presenting itself as a current per-iteration record. A reader had to notice the
dates to learn otherwise.

The banner says where the live record is (DECISIONS.md plus the manifests, both
now enforced) and states plainly that this file is not currently required. It
does NOT decide revive-or-retire: its role overlaps DECISIONS.md almost
entirely, so retiring it is defensible and reviving it means committing to a
third enforced artifact. That is David's call, recorded as open rather than
silently answered by leaving the file to rot.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant