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
- 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.
- 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.
- 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.
- 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.
- 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
standards#960's AC4 gate (scripts/check-launcher-standard-currency.sh) isimplemented+tested+ — once the wiring PR lands —wired. This issue records thearming 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
retired-filenamelauncher-standard.a2ml, a file deleted upstream 2026-09-22 (#952)stale-versionCURRENT_VERSION::warning::, non-blocking)Why
stale-versioncannot block todayThe gate compares each citation against
CURRENT_VERSION(0.4.0at 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_VERSIONbump 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:
hyperpolymath/tma-mark2metadatastician/canonical-umshyperpolymath/the-nash-equilibriumAll three pin the reusable at a SHA, not
@main. The 13@main-pinned consumers carryzero defects.
⇒ Arming
retired-filenameat 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
retired-filenamecitation in a consumer's treemakes the
qualityjob red; a seededstale-version-only citation makes it greenwith a
::warning::. Proven by a mutant, not by reading the YAML —::warning::cannotfail a job, so a comment claiming "blocks" above a warning asserts the opposite of what
the code does.
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.
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.
CURRENT_VERSIONis bumped in the gate, theestate 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.
stale-versiontier decision is recorded here when taken — see the open questionbelow — with the measurement it rests on.
⚖ Open question for the owner
Once an AC1-style sweep confirms
stale-versionreds 0 live consumers at the then-currentversion:
re-creates the population regardless of any sweep. Simplest; the gate stays informational
for this class forever.
bump — blocks drift between bumps, at the cost of a measure-then-arm ritual attached to
every
CURRENT_VERSIONchange, 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 (mergededac0d6a)hyperpolymath/standards#990— the false-positive cure + this wiringhyperpolymath/standards#952— the upstream deletion oflauncher-standard.a2mlhyperpolymath/standards#505— the docs-gate split-tier precedent🤖 Generated with Claude Code
https://claude.ai/code/session_01WPSJ7fBhVAMcpSffCBWUDo