Skip to content

fix(principles): enforce last-revised discipline + backfill stale dates - #38

Merged
brettdavies merged 2 commits into
devfrom
fix/principle-last-revised-discipline
May 28, 2026
Merged

brettdavies merged 2 commits into
devfrom
fix/principle-last-revised-discipline

Conversation

@brettdavies

Copy link
Copy Markdown
Owner

Summary

Tightens the principle last-revised rule so any frontmatter mutation stamps today's date, adds scripts/check-last-revised.mjs to enforce the rule at pre-push and PR CI (with a --fix flag), and backfills seven principle files whose dates had drifted because the old rule's "prose-only" carve-out was ambiguous enough to skip applicability-shape migrations and summary rewrites.

Audit found one file (p3) where the discipline was followed correctly. Six files were off by 1 to 15 days; the worst cases were p2 and p8 (PR #34 conditional-applicability migration) and p5/p7 (summary rewrites in #25/#22). The backfill diff touches only last-revised, so it does not trigger the new check, because the rule fires on frontmatter-sans-date deltas and the backfill leaves frontmatter-sans-date unchanged.

Changelog

Changed

  • last-revised discipline tightened: any frontmatter mutation (summary rewrites, applicability shape migrations, tier changes, requirement add/remove, status flips, reordering) stamps today's date. Prose-only edits below the closing --- fence remain exempt. Enforced by scripts/check-last-revised.mjs at pre-push and PR CI.

Fixed

  • Backfilled last-revised on p1, p2, p4, p5, p6, p7, p8 to match each file's most recent substantive frontmatter change. p3 was already correct.

Linked check review

no check changes needed: this PR is governance + tooling only and does not alter any MUST/SHOULD/MAY tier, requirement ID, or applicability shape. anc's vendored spec/ will pick up the corrected dates on its next sync.

Human reviewer

Reviewer: @brettdavies

AI disclosure

Audit, script, tests, hook wiring, CI workflow, and PR body authored by Claude (claude-opus-4-7) under human direction. Human reviewed the design decision to compare last-revised against today's date rather than against the base ref, and approved the backfill date choices.

Tighten the AGENTS.md rule so any frontmatter mutation (summary rewrites, applicability shape migrations, tier changes, requirement add/remove, status flips, reordering) stamps today's date on `last-revised`. Prose-only edits below the closing `---` fence remain exempt.

Add `scripts/check-last-revised.mjs` to enforce the rule. The checker reads the principles diff against a base ref (default `origin/dev`), detects substantive frontmatter mutations, and asserts `last-revised` equals today's local date. A `--fix` flag auto-stamps today on every violating file. `CHECK_LR_TODAY=YYYY-MM-DD` overrides "today" for deterministic tests.

Wire the checker into `scripts/hooks/pre-push` and add a PR-time CI workflow (`.github/workflows/check-last-revised.yml`) so the discipline holds at both the local-push and merge-gate boundaries. Tests live in `scripts/test-check-last-revised.mjs` and cover the eight branches of the state machine, including `--fix` rewrites and the prose-only no-op.

Closes the gap PR #34 exposed: an applicability-shape migration counted as "prose-only" under the old rule wording and slipped past review without a date bump.

## Changelog

### Changed

- `last-revised` discipline tightened: any frontmatter mutation stamps today's date, enforced by `scripts/check-last-revised.mjs` at pre-push and PR CI. The previous rule exempted "prose-only" edits ambiguously; the new wording explicitly scopes "prose-only" to body content below the closing frontmatter fence.
Audit of `git log` against principles/p*.md frontmatter found seven files where `last-revised` did not reflect the latest substantive frontmatter change. Six were off by 1 to 15 days; one (p3) was already correct.

Backfilled dates use the commit date of each principle's most recent substantive frontmatter change, not today, because the canonical record for those changes is already in `git log` and the principles shipped to consumers (anc's vendored `spec/`) under those dates.

The backfill diff touches only `last-revised`, so it does not itself trigger the discipline check landing in the same PR (which fires only when frontmatter-sans-date differs from base).

| Principle | Old        | New        | Source                          |
|-----------|------------|------------|---------------------------------|
| p1        | 2026-05-06 | 2026-05-07 | #25 v0.4.0 (off-by-one)         |
| p2        | 2026-05-06 | 2026-05-21 | #34 conditional applicability   |
| p4        | 2026-05-06 | 2026-05-07 | #25 v0.4.0 (off-by-one)         |
| p5        | 2026-04-22 | 2026-05-07 | #25 v0.4.0 (summary rewrite)    |
| p6        | 2026-05-06 | 2026-05-07 | #25 v0.4.0 (off-by-one)         |
| p7        | 2026-04-22 | 2026-05-07 | #22 v0.3.1 (summary rewrite)    |
| p8        | 2026-05-06 | 2026-05-21 | #34 conditional applicability   |
@brettdavies
brettdavies merged commit 1fb49fe into dev May 28, 2026
1 check passed
@brettdavies
brettdavies deleted the fix/principle-last-revised-discipline branch May 28, 2026 01:29
brettdavies added a commit that referenced this pull request May 30, 2026
## Summary

Add four domain terms to the brand Vale vocabulary: `backfill`,
`backfilled`, `consequent`, `consequents`. Both pairs surfaced as
Vale.Spelling findings during the v0.5.0 CHANGELOG scrub. Both already
appear in PR-body prose: "Backfilled" in PR #38's `last-revised` cleanup
bullet, "consequent's" in PR #34's antecedent-status propagation table
description. Vocab gap, not a typo on either side.

## Changelog

## Linked audit review

no audit changes needed. Vocab-only update with no `requirements[]`
impact.

## Human reviewer

**Reviewer:** @brettdavies

## AI disclosure

Edit, alphabetic placement, commit, and PR-body authoring performed by
Claude (Opus 4.7) under direct supervision; word selection was
human-flagged during the v0.5.0 release scrub.
brettdavies added a commit that referenced this pull request May 30, 2026
…dit rename (#44)

## Summary

v0.5.0 of the agent-native CLI standard. Two principles gain normative
content: p3 acquires a universal `--version` MUST plus a short-alias
SHOULD; p8's machine-checkable applicability gains a typed `{kind:
conditional, antecedent: {audit_id: <id>}}` shape that supersedes the
prose-only `{if: <reason>}` form (p2 migrates as well). The standard's
conformance vocabulary renames from `check` to `audit` across principle
prose, the `audit_id` frontmatter field, and the `anc audit` subcommand.
A leaderboard scoring formula lands in `principles/scoring.md` with a
binary-behavior, credit-weighted ratio plus four cohort bands (Exemplary
/ Strong / Solid / Qualified) and a 70% eligibility floor. Governance
gains the three-tier contribution framework (Signal / Proposal / Code),
the `last-revised` discipline check now stamps any frontmatter mutation,
and `RELEASES.md` splits into a runbook plus a companion rationale doc.

## Changelog

### Added

- Three-tier contribution framework (Signal / Proposal / Code) in
`CONTRIBUTING.md` with a "Where to file what" routing table covering all
four repos by @brettdavies in
[#30](#30)
- `00-blank.yml` issue template, sort-prefixed to the top of the picker,
with an agent-facing footer redirecting to structured templates
- Fourth `contact_link` in `.github/ISSUE_TEMPLATE/config.yml` routing
skill-bundle issues to the bundle repo
- `p3-must-version` (universal MUST): top-level `--version` prints a
non-empty version line and exits 0. by @brettdavies in
[#33](#33)
- `p3-should-version-short` (universal SHOULD): a short alias (`-V` per
clap default; `-v` per Node/npm/Bun/Yarn/Make convention; `-version` per
Go's `flag` package) accompanies `--version`. Any of the three forms is
sufficient.
- Conditional applicability shape `{kind: conditional, antecedent:
{check_id: <id>}}` for machine-checkable conditionals. The `check_id` is
a verifier identifier, not a requirement `id`; the v1 schema is
single-antecedent only, with compound antecedents (`op`/`checks`)
deferred to v2 and rejected by the validator. by @brettdavies in
[#34](#34)
- Antecedent-status propagation table mapping the antecedent's status
(under the 7-status taxonomy: `pass`, `warn`, `fail`, `opt_out`, `n_a`,
`skip`, `error`) to the consequent's emission, including the inheritance
rules for `skip` and `error`.
- Add `principles/scoring.md` defining the leaderboard scoring formula:
a binary-behavior, credit-weighted ratio with `opt_out` counted and
`n_a`/`skip`/`error` excluded, plus four badge cohort bands. by
@brettdavies in
[#39](#39)

### Changed

- Issue template `grade-a-cli.yml` renamed to `grading-finding.yml`,
with `name`, `description`, and `labels` updated to match the actual
purpose by @brettdavies in
[#30](#30)
- `RELEASES.md` reduced from runbook-plus-rationale (339 lines) to
runbook-only (201 lines), cross-linking the new rationale doc
- `AGENTS.md` updated from three-repo to four-repo ecosystem; template
references updated
- `scripts/prose-check.sh` default `LANGUAGETOOL_URL` is now
`http://languagetool:8081` (service-name default; consumers override via
env var)
- Migrate p2 (`p2-must-schema-print`, `p2-should-schema-file`) and p8
(`p8-must-bundle-install`, `p8-may-install-all`, `p8-may-bundle-update`)
applicability from `{if: <reason>}` to the new shape. Antecedent for p2
is `p2-json-output`; for p8 is `p8-bundle-exists`. No tier changes. by
@brettdavies in
[#34](#34)
- `last-revised` discipline tightened: any frontmatter mutation (summary
rewrites, applicability shape migrations, tier changes, requirement
add/remove, status flips, reordering) stamps today's date. Prose-only
edits below the closing `---` fence remain exempt. Enforced by
`scripts/check-last-revised.mjs` at pre-push and PR CI. by @brettdavies
in [#38](#38)
- Lower the badge eligibility floor from 80% to 70%. by @brettdavies in
[#39](#39)
- Replace the badge's three-color threshold with four cohort bands
(Exemplary >= 85, Strong 80-84, Solid 75-79, Qualified 70-74).
- Rename the conditional-antecedent frontmatter field `check_id` to
`audit_id`. This is a breaking change to the principle-frontmatter
shape: consumers that parse `applicability.antecedent` read `audit_id`
instead of `check_id`. by @brettdavies in
[#40](#40)
- Rename the standard's conformance vocabulary from `check` to `audit`
(the `anc audit` subcommand, "audit IDs", "auditor") across principle
prose and governance docs.

### Fixed

- Backfilled `last-revised` on p1, p2, p4, p5, p6, p7, p8 to match each
file's most recent substantive frontmatter change. p3 was already
correct. by @brettdavies in
[#38](#38)
- The `last-revised` discipline check runs only on PRs targeting `dev`,
so release PRs to `main` no longer fail it for principles revised on an
earlier day. by @brettdavies in
[#41](#41)

### Removed

- `docs/architecture/languagetool-deployment.md` (deployment knowledge
compounded into the shared `solutions-docs` repo as
`self-hosted-languagetool-for-prose-check-stacks-2026-05-20.md`) by
@brettdavies in
[#30](#30)

## Linked audit review

no audit changes needed — the `anc` repo is pinned at vendored spec
v0.4.0 and re-vendors on the v0.5.0 tag; a verifier for
`p3-must-version` (the only new MUST) is a downstream follow-up, not a
spec-release blocker.

## Human reviewer

**Reviewer:** @brettdavies

## AI disclosure

Cherry-pick assembly, conflict resolution, CHANGELOG generation, and
PR-body drafting performed by Claude (Opus 4.7) under direct
supervision; all normative principle content and PR-body Changelog
bullets originate from human-authored upstream PR bodies.
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