Skip to content

AC4 arming policy: retired-filename blocks, stale-version warns (each CURRENT_VERSION bump is a measure-then-arm event) #991

Description

@hyperpolymath

standards#960's AC4 gate (scripts/check-launcher-standard-currency.sh) is
implemented + tested + — once the wiring PR lands — wired. This issue records the
arming policy: which defect class blocks, which warns, and the rule for re-measuring
before the warn tier is ever promoted.

Filed per the standing stopping rule (a new scanner finding becomes an issue with
acceptance criteria, not a merge blocker).

The gate emits two defect classes, and they have opposite volatility

class predicate volatility tier as wired
retired-filename names launcher-standard.a2ml, a file deleted upstream 2026-09-22 (#952) stable — a deleted file stays deleted; a consumer that is clean today cannot become defective without editing the citation itself fail
stale-version cites a version other than the gate's CURRENT_VERSION time-dependent — see below warn (::warning::, non-blocking)

Why stale-version cannot block today

The gate compares each citation against CURRENT_VERSION (0.4.0 at time of writing).
When the standard bumps to 0.5.0, every correctly-citing consumer flips to defect with
zero action of its own.
That is the guard-asks-a-different-question trap in its
time-delayed form: the gate asks "does this cite the newest version", while the consumer
can only answer "does this cite the version that was newest when I last touched it".

A baked-in cutoff date does not fix this. The docs-gate precedent (check-docs-presence.sh,
#505) could use a date because its missing-CONTRIBUTING population was static — the set
of defective repos only shrank. Here the population is regenerated at every version bump.

⇒ Each CURRENT_VERSION bump is a measure-then-arm event, not a date.

Blast radius as measured (2026-09-22, post-fix)

Census over the estate's consumers of the governance reusable:

distinct consumer slugs   26
with >=1 defect            3
clean                     23
slug max defects retired stale archived?
hyperpolymath/tma-mark2 7 5 2 YES (private)
metadatastician/canonical-ums 4 3 1 YES (public)
hyperpolymath/the-nash-equilibrium 4 3 1 no — live, but AC1-exempt and on the DO-NOT-MERGE list (2 corrupt remote branches)

All three pin the reusable at a SHA, not @main. The 13 @main-pinned consumers carry
zero defects.

⇒ Arming retired-filename at fail tier today reds ZERO live, mergeable consumers.
That is the evidence the fail tier rests on, and it is the number that must be re-measured
before any later promotion.

Acceptance criteria

  1. The wiring is not vacuous. A seeded retired-filename citation in a consumer's tree
    makes the quality job red; a seeded stale-version-only citation makes it green
    with a ::warning::
    . Proven by a mutant, not by reading the YAML — ::warning:: cannot
    fail a job, so a comment claiming "blocks" above a warning asserts the opposite of what
    the code does.
  2. A broken invocation fails, never warns. The gate returns rc=2 for a usage error or
    a surviving self-test mutant. The wrapper must treat rc=2 as fail. Control: invoke with
    a bogus flag and require the step to red.
  3. A vacuous pass is visible. The gate's check-launcher-standard-currency: canonical=… expected=…
    header is echoed unconditionally, so a run that scanned nothing is distinguishable from a
    run that scanned and found nothing.
  4. The re-arm rule is honoured. Before CURRENT_VERSION is bumped in the gate, the
    estate blast radius is re-measured at the new version and posted here. A bump that reds
    live consumers is a sweep-then-arm, not a bump.
  5. The stale-version tier decision is recorded here when taken — see the open question
    below — with the measurement it rests on.

⚖ Open question for the owner

Once an AC1-style sweep confirms stale-version reds 0 live consumers at the then-current
version:

  • (a) warn permanently — accept that the class can never block, because the next bump
    re-creates the population regardless of any sweep. Simplest; the gate stays informational
    for this class forever.
  • (b) warn until a sweep confirms 0, then promote to fail, and demote back to warn on each
    bump
    — blocks drift between bumps, at the cost of a measure-then-arm ritual attached to
    every CURRENT_VERSION change, and a window after each bump where the class is silent.

Both are defensible; (b) buys real enforcement between bumps but only if the demote step is
never skipped, and a skipped demote reds the whole estate. Recording the choice here rather
than leaving it to decay.

References

  • hyperpolymath/standards#960 — the parent AC set (AC4)
  • hyperpolymath/standards#983 — the gate itself (merged edac0d6a)
  • hyperpolymath/standards#990 — the false-positive cure + this wiring
  • hyperpolymath/standards#952 — the upstream deletion of launcher-standard.a2ml
  • hyperpolymath/standards#505 — the docs-gate split-tier precedent

🤖 Generated with Claude Code

https://claude.ai/code/session_01WPSJ7fBhVAMcpSffCBWUDo

Activity

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

    governancePolicy, rulesets, standards, compliance, and their enforcementtech-debtKnown shortcut, drift, or hygiene owed - includes cleanup

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions