Skip to content

The ledger records provenance nobody fills, and loses evidence to an unquoted comma #279

Description

@drevendev

Goal

Make the ledger's merge provenance real: fill the field nobody was responsible for
filling, stop rows losing their evidence to an unquoted comma, and refuse to release a
milestone on provenance that does not exist.

The mechanical half of #278. The judgement half — whether REQ-CORE-006 is satisfied by
the merged #239, and what REQ-MARKET-002's evidence should say while #270 stands — stays
there, because deciding a requirement is met is the ACCEPTOR's call, not an operator's.

Evidence

Found by the external QA voice in #278 and verified independently.

MERGE_COMMIT was blank on 11 of 23 rows, 8 of them IMPLEMENTED. The AUTHOR
cannot write it: the row lands inside its own pull request and the squash commit does
not exist until that pull request merges. AUTHOR_RUNBOOK.md therefore called the field
optional — while release_tag.py, added the day before, consumes it as authoritative
provenance. Optional and nobody's job are the same thing.

The consequence is on the release tagger itself: coverage_digest hashes
(REQ_ID, MERGE_COMMIT) pairs, so with blanks a milestone repaired at new commits
hashes identically to the one released before and the patch tag that exists for exactly
that case is never cut. Release notes rendered the blanks as an em dash.

10 of 23 rows parsed into more than the six declared fields. An unquoted comma in
EVIDENCE splits the row; csv.DictReader files the surplus under the key None,
validate() never looked at it, and every consumer read only the text before that
comma. REQ-CORE-005 lost everything after jurisdictionChanges — 620 characters of
evidence rendered as 120.

Scope

  • docs/spec/implementation_status.csv, docs/spec/IMPLEMENTATION_STATUS.md
  • scripts/implementation_status.py
  • scripts/backfill_merge_commits.py, scripts/tests/test_backfill_merge_commits.py
  • scripts/release_tag.py
  • .github/workflows/release-tag.yml
  • docs/zendev/AUTHOR_RUNBOOK.md

Non-goals

Changing any STATUS. Whether a requirement is satisfied is the ACCEPTOR's judgement
against acceptance criteria; this records only where work landed. REQ-CORE-006 stays
PARTIAL here even though #278 argues convincingly that #239 completed it.

Acceptance criteria

  1. No row that names a merged pull request lacks its merge commit, and a test asserts
    this of the repository's own ledger.
  2. implementation_status.py --check rejects a row that parses into more than six
    fields, naming the row and the reason.
  3. Every repaired row's evidence survives a parse round-trip intact.
  4. The tagger refuses to release a milestone with a blank merge commit, warning which
    requirements are missing it, rather than hashing an empty string.
  5. Backfill runs before the tagger on every push that touches the ledger, and cannot
    loop: a run that changes nothing pushes nothing.
  6. Backfill never rewrites a commit already recorded and never touches a row whose pull
    request is not merged.
  7. The runbook says the field is filled after the merge, not that it is optional.

Verification

python -m unittest discover -s scripts/tests,
python scripts/implementation_status.py --check, and
python scripts/release_tag.py --dry-run.

Activity

  1. added
    priority:highImportant and time-sensitive; schedule ahead of normal work
    type:bugVerified behavior differs from the intended contract
    area:toolingCI, scripts, guards, developer tooling
    status:in-progressClaimed work with an active branch or pull request
    policyControl-plane change: workflows, scripts, runbooks, AGENTS.md. Operator-owned, never AUTHOR.
    on Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:toolingCI, scripts, guards, developer toolingpolicyControl-plane change: workflows, scripts, runbooks, AGENTS.md. Operator-owned, never AUTHOR.priority:highImportant and time-sensitive; schedule ahead of normal worktype:bugVerified behavior differs from the intended contract

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions