instar 1.3.1076 → 1.3.1077
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data/standards-registry.md +4 -4
- package/dist/data/standards-registry.meta.json +2 -2
- package/package.json +1 -1
- package/scripts/standards-coverage.mjs +12 -5
- package/src/data/builtin-manifest.json +2 -2
- package/src/data/standards-registry.md +4 -4
- package/src/data/standards-registry.meta.json +2 -2
- package/upgrades/1.3.1077.md +45 -0
- package/upgrades/side-effects/standards-enforced-ratio-floor.md +89 -0
|
@@ -147,7 +147,7 @@ The Root says *enforce behavior in structure, not willpower.* This family is **w
|
|
|
147
147
|
|
|
148
148
|
### Quantitative Claims Must Bind a Subject
|
|
149
149
|
**Rule.** A verifier may compare a number only after binding both the measurement and the subject being measured. A shared unit or relation word is not semantic identity: “30 minutes in an offline-test window,” “one minute of detection latency,” “two hours remaining on the migration ETA,” and “two hours remaining in this session” are four different claims. A detector that sees only `duration + elapsed/remaining/in` and silently assumes “session clock” is a keyword classifier, not verification.
|
|
150
|
-
**In practice.** Cheap deterministic extraction may nominate a structurally anchored measurement, but competing local subjects must DROP the candidate toward pass-through. Positive verification requires an explicit subject binding or an intentionally documented unqualified default backed by the caller’s typed context. Both sides are pinned together in one decision table: real elapsed/remaining/percent session-clock claims still reach the live clock, while test windows, latencies, queues, timeouts, outages, and task ETAs do not. New quantitative verifiers must carry the same paired boundary tests; a positive-only regex fixture is incomplete.
|
|
150
|
+
**In practice.** Cheap deterministic extraction may nominate a structurally anchored measurement, but competing local subjects must DROP the candidate toward pass-through. Positive verification requires an explicit subject binding or an intentionally documented unqualified default backed by the caller’s typed context. Both sides are pinned together in one decision table: real elapsed/remaining/percent session-clock claims still reach the live clock, while test windows, latencies, queues, timeouts, outages, and task ETAs do not. New quantitative verifiers must carry the same paired boundary tests; a positive-only regex fixture is incomplete. The first verifier and its paired decision table are `src/core/time-claim.ts`.
|
|
151
151
|
**Earned from.** 2026-07-23 (Echo topic 29723): TIME_CLAIM twice interrupted correct messages and required audited overrides because it treated an offline-test-window duration and detection latency as claims about the active session clock. The earlier punctuation fix had even documented “CI queue” as an accepted false positive, exposing the missing subject-binding review.
|
|
152
152
|
**Traces to the goal.** Verification that checks the wrong subject manufactures contradictions instead of preventing them. A coherent agent must know what a number is about before declaring it true or false.
|
|
153
153
|
|
|
@@ -417,7 +417,7 @@ The Root says *enforce behavior in structure, not willpower.* This family is **w
|
|
|
417
417
|
|
|
418
418
|
### Migration Parity
|
|
419
419
|
**Rule.** Any change to agent-installed files (hooks, config defaults, CLAUDE.md template, built-in skills) must reach *existing* agents through the update path — not only new agents via `init`.
|
|
420
|
-
**In practice.** Hook-template changes get a `migrateSettings()` patch (the migration surface is `src/core/PostUpdateMigrator.ts`); config defaults get existence-checked additions; built-in hooks are *always overwritten* on migration; every migration is idempotent.
|
|
420
|
+
**In practice.** Hook-template changes get a `migrateSettings()` patch (the migration surface is `src/core/PostUpdateMigrator.ts`; the binding gate is `tests/integration/migration-guarantee.test.ts`, which runs eight committed pre-migration agent shapes through both code paths and asserts zero job loss and zero schedule drift, and which `scripts/protect-migration-guarantee.js` refuses to let a commit delete); config defaults get existence-checked additions; built-in hooks are *always overwritten* on migration; every migration is idempotent.
|
|
421
421
|
**Earned from.** The zombie-cleanup-kills-active-sessions bug (deployed agents ran stale config that killed live sessions) and the hook-event-reporter ESM bug (install-if-missing left ESM-host agents stuck on a broken CJS hook). A feature that only works for new agents is a broken feature.
|
|
422
422
|
**Traces to the goal.** Agents evolve *in place*. Evolution that doesn't reach the already-deployed self isn't evolution.
|
|
423
423
|
|
|
@@ -586,7 +586,7 @@ that reset-safe posture must be explicit and tested rather than assumed.
|
|
|
586
586
|
|
|
587
587
|
### No Deferrals
|
|
588
588
|
**Rule.** Ship complete features and fixes. A deferral requires a same-PR tracked commitment with active follow-through — never an orphaned "later" note.
|
|
589
|
-
**In practice.** "Tactical now + the rest later" without owned follow-through is how regressions recur. Default to comprehensive.
|
|
589
|
+
**In practice.** "Tactical now + the rest later" without owned follow-through is how regressions recur. Default to comprehensive. Enforced by the orphan-deferral step in `scripts/instar-dev-precommit.js`: a spec carrying deferral language must track each instance with an explicit marker or a frontmatter field, and the commit is refused otherwise (the override is an env var and is logged).
|
|
590
590
|
**Earned from.** A PR that deferred "lifeline auto-restart on server upgrade" — and that exact gap produced a regression two days later.
|
|
591
591
|
**Traces to the goal.** Coherence over time means today's shortcut doesn't become next week's outage.
|
|
592
592
|
|
|
@@ -599,7 +599,7 @@ that reset-safe posture must be explicit and tested rather than assumed.
|
|
|
599
599
|
|
|
600
600
|
### A Dark Feature Guards Nothing
|
|
601
601
|
**Rule.** When an incident or a path analysis shows that a **load-bearing path depends on a feature that ships dark, disabled, or dry-run**, that is a forced decision point: **graduate it, or record explicit operator acceptance of the manual fallback**. A safety automation that exists only dark is, for the fleet, prose — the fleet's real posture is the DARK posture. Corollary: every postmortem must answer, as a mandatory section, *"which dark features would have prevented or shortened this incident?"*
|
|
602
|
-
**In practice.** The guards inventory carries a **dark-but-load-bearing** classification, so an off feature that a critical path depends on ALERTS instead of sitting quiet among the legitimately-dark (this is what separates it from the plain `dark-default` class, which is normal and silent); graduation pressure rides the *Maturation Path* track; acceptance of a manual fallback is a recorded decision with an owner, not a shrug. The classification and its three arms (`loadBearingGap` / `loadBearingSoaking` / `loadBearingAccepted`) live in `src/monitoring/guardPostureView.ts`; the recorded acceptance is `POST /guards/:key/accept-fallback`.
|
|
602
|
+
**In practice.** The guards inventory carries a **dark-but-load-bearing** classification, so an off feature that a critical path depends on ALERTS instead of sitting quiet among the legitimately-dark (this is what separates it from the plain `dark-default` class, which is normal and silent); graduation pressure rides the *Maturation Path* track; acceptance of a manual fallback is a recorded decision with an owner, not a shrug. The classification and its three arms (`loadBearingGap` / `loadBearingSoaking` / `loadBearingAccepted`) live in `src/monitoring/guardPostureView.ts`; the ALERT the rule demands is raised by `src/monitoring/probes/GuardPostureProbe.ts` (classification and alerting are deliberately separate — `/guards` still classifies when the probe's alert is rolled back); the recorded acceptance is `POST /guards/:key/accept-fallback`.
|
|
603
603
|
**Earned from.** The 2026-07-01 mesh incident response was manual operator surgery at every step — and the damning part is that automation for nearly every step EXISTED in code and shipped dark: poll-follows-lease (dry-run), stale-holder takeover, solo-captain hold, pin persistence across lease handover. Walk the incident asking "what did our self-healing actually do?" and the answer is: nothing, because none of it was on. The framework *believed* it had self-healing; the fleet had prose (`docs/postmortems/2026-07-01-silent-telegram-message-loss.md`).
|
|
604
604
|
**Traces to the goal.** Self-healing that isn't enabled isn't self-healing. A coherent self-evolving agent must not confuse the capabilities it HAS with the capabilities it has WRITTEN — this is *Documentation IS Being*'s hard edge: if the doc says "self-healing mesh" and the flags say dark, the doc is describing a fiction.
|
|
605
605
|
**Applied through.** The dark-but-load-bearing classification in the guards inventory (G3 of the postmortem project, upstream); the mandatory postmortem question; *Maturation Path* graduation pressure; the first applied case is poll-follows-lease (decision D3, ratified topic 29836): graduate the smallest captain-hand-back automation rather than accept manual captain flips forever. (Proposed by Echo from the 2026-07-01 postmortem; ratified by Justin 2026-07-01, topic 29836.)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"sha256": "
|
|
2
|
+
"sha256": "7ccfbb251e6935ace35ca3fa778061692ba1aa3854444ad6b5ce7b085322ca9e",
|
|
3
3
|
"articleCount": 82,
|
|
4
4
|
"generatedFrom": "docs/STANDARDS-REGISTRY.md",
|
|
5
|
-
"packageVersion": "1.3.
|
|
5
|
+
"packageVersion": "1.3.1077"
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -57,11 +57,18 @@ const numEnv = (env, def) => {
|
|
|
57
57
|
return v !== undefined && v !== '' && Number.isFinite(Number(v)) ? Number(v) : def;
|
|
58
58
|
};
|
|
59
59
|
const FLOORS = {
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
|
|
60
|
+
// Started at 0 ("starts loose", the docs-coverage rationale) while the gap closed.
|
|
61
|
+
// Ratcheted to 0.64 on 2026-07-30: the documented-only set shrank 34 -> 24 that day
|
|
62
|
+
// (ten standards whose guards already existed gained resolvable citations). THIS
|
|
63
|
+
// script measures 0.6543; note the library (StandardsEnforcementAuditor, which the
|
|
64
|
+
// /conformance route serves) measures 0.6585 over 82 standards where this parser
|
|
65
|
+
// counts 81 — a known one-article discrepancy between two implementations of the
|
|
66
|
+
// same measure, recorded rather than averaged away. The floor is set against THIS
|
|
67
|
+
// script's number, since this script is what CI runs, with roughly one standard of
|
|
68
|
+
// headroom so a single unguarded addition surfaces as a real signal rather than
|
|
69
|
+
// tripping the build on rounding. It cannot fail a build that does not regress.
|
|
70
|
+
// Ratchet upward again (a visible PR diff) as the documented-only set shrinks.
|
|
71
|
+
enforcedRatio: numEnv('STANDARDS_ENFORCED_RATIO_FLOOR', 0.64),
|
|
65
72
|
// Zero tolerance: a standard must NEVER cite a guard that doesn't exist.
|
|
66
73
|
danglingCeiling: numEnv('STANDARDS_DANGLING_CEILING', 0),
|
|
67
74
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-07-
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-07-30T22:59:41.738Z",
|
|
5
|
+
"instarVersion": "1.3.1077",
|
|
6
6
|
"entryCount": 202,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -147,7 +147,7 @@ The Root says *enforce behavior in structure, not willpower.* This family is **w
|
|
|
147
147
|
|
|
148
148
|
### Quantitative Claims Must Bind a Subject
|
|
149
149
|
**Rule.** A verifier may compare a number only after binding both the measurement and the subject being measured. A shared unit or relation word is not semantic identity: “30 minutes in an offline-test window,” “one minute of detection latency,” “two hours remaining on the migration ETA,” and “two hours remaining in this session” are four different claims. A detector that sees only `duration + elapsed/remaining/in` and silently assumes “session clock” is a keyword classifier, not verification.
|
|
150
|
-
**In practice.** Cheap deterministic extraction may nominate a structurally anchored measurement, but competing local subjects must DROP the candidate toward pass-through. Positive verification requires an explicit subject binding or an intentionally documented unqualified default backed by the caller’s typed context. Both sides are pinned together in one decision table: real elapsed/remaining/percent session-clock claims still reach the live clock, while test windows, latencies, queues, timeouts, outages, and task ETAs do not. New quantitative verifiers must carry the same paired boundary tests; a positive-only regex fixture is incomplete.
|
|
150
|
+
**In practice.** Cheap deterministic extraction may nominate a structurally anchored measurement, but competing local subjects must DROP the candidate toward pass-through. Positive verification requires an explicit subject binding or an intentionally documented unqualified default backed by the caller’s typed context. Both sides are pinned together in one decision table: real elapsed/remaining/percent session-clock claims still reach the live clock, while test windows, latencies, queues, timeouts, outages, and task ETAs do not. New quantitative verifiers must carry the same paired boundary tests; a positive-only regex fixture is incomplete. The first verifier and its paired decision table are `src/core/time-claim.ts`.
|
|
151
151
|
**Earned from.** 2026-07-23 (Echo topic 29723): TIME_CLAIM twice interrupted correct messages and required audited overrides because it treated an offline-test-window duration and detection latency as claims about the active session clock. The earlier punctuation fix had even documented “CI queue” as an accepted false positive, exposing the missing subject-binding review.
|
|
152
152
|
**Traces to the goal.** Verification that checks the wrong subject manufactures contradictions instead of preventing them. A coherent agent must know what a number is about before declaring it true or false.
|
|
153
153
|
|
|
@@ -417,7 +417,7 @@ The Root says *enforce behavior in structure, not willpower.* This family is **w
|
|
|
417
417
|
|
|
418
418
|
### Migration Parity
|
|
419
419
|
**Rule.** Any change to agent-installed files (hooks, config defaults, CLAUDE.md template, built-in skills) must reach *existing* agents through the update path — not only new agents via `init`.
|
|
420
|
-
**In practice.** Hook-template changes get a `migrateSettings()` patch (the migration surface is `src/core/PostUpdateMigrator.ts`); config defaults get existence-checked additions; built-in hooks are *always overwritten* on migration; every migration is idempotent.
|
|
420
|
+
**In practice.** Hook-template changes get a `migrateSettings()` patch (the migration surface is `src/core/PostUpdateMigrator.ts`; the binding gate is `tests/integration/migration-guarantee.test.ts`, which runs eight committed pre-migration agent shapes through both code paths and asserts zero job loss and zero schedule drift, and which `scripts/protect-migration-guarantee.js` refuses to let a commit delete); config defaults get existence-checked additions; built-in hooks are *always overwritten* on migration; every migration is idempotent.
|
|
421
421
|
**Earned from.** The zombie-cleanup-kills-active-sessions bug (deployed agents ran stale config that killed live sessions) and the hook-event-reporter ESM bug (install-if-missing left ESM-host agents stuck on a broken CJS hook). A feature that only works for new agents is a broken feature.
|
|
422
422
|
**Traces to the goal.** Agents evolve *in place*. Evolution that doesn't reach the already-deployed self isn't evolution.
|
|
423
423
|
|
|
@@ -586,7 +586,7 @@ that reset-safe posture must be explicit and tested rather than assumed.
|
|
|
586
586
|
|
|
587
587
|
### No Deferrals
|
|
588
588
|
**Rule.** Ship complete features and fixes. A deferral requires a same-PR tracked commitment with active follow-through — never an orphaned "later" note.
|
|
589
|
-
**In practice.** "Tactical now + the rest later" without owned follow-through is how regressions recur. Default to comprehensive.
|
|
589
|
+
**In practice.** "Tactical now + the rest later" without owned follow-through is how regressions recur. Default to comprehensive. Enforced by the orphan-deferral step in `scripts/instar-dev-precommit.js`: a spec carrying deferral language must track each instance with an explicit marker or a frontmatter field, and the commit is refused otherwise (the override is an env var and is logged).
|
|
590
590
|
**Earned from.** A PR that deferred "lifeline auto-restart on server upgrade" — and that exact gap produced a regression two days later.
|
|
591
591
|
**Traces to the goal.** Coherence over time means today's shortcut doesn't become next week's outage.
|
|
592
592
|
|
|
@@ -599,7 +599,7 @@ that reset-safe posture must be explicit and tested rather than assumed.
|
|
|
599
599
|
|
|
600
600
|
### A Dark Feature Guards Nothing
|
|
601
601
|
**Rule.** When an incident or a path analysis shows that a **load-bearing path depends on a feature that ships dark, disabled, or dry-run**, that is a forced decision point: **graduate it, or record explicit operator acceptance of the manual fallback**. A safety automation that exists only dark is, for the fleet, prose — the fleet's real posture is the DARK posture. Corollary: every postmortem must answer, as a mandatory section, *"which dark features would have prevented or shortened this incident?"*
|
|
602
|
-
**In practice.** The guards inventory carries a **dark-but-load-bearing** classification, so an off feature that a critical path depends on ALERTS instead of sitting quiet among the legitimately-dark (this is what separates it from the plain `dark-default` class, which is normal and silent); graduation pressure rides the *Maturation Path* track; acceptance of a manual fallback is a recorded decision with an owner, not a shrug. The classification and its three arms (`loadBearingGap` / `loadBearingSoaking` / `loadBearingAccepted`) live in `src/monitoring/guardPostureView.ts`; the recorded acceptance is `POST /guards/:key/accept-fallback`.
|
|
602
|
+
**In practice.** The guards inventory carries a **dark-but-load-bearing** classification, so an off feature that a critical path depends on ALERTS instead of sitting quiet among the legitimately-dark (this is what separates it from the plain `dark-default` class, which is normal and silent); graduation pressure rides the *Maturation Path* track; acceptance of a manual fallback is a recorded decision with an owner, not a shrug. The classification and its three arms (`loadBearingGap` / `loadBearingSoaking` / `loadBearingAccepted`) live in `src/monitoring/guardPostureView.ts`; the ALERT the rule demands is raised by `src/monitoring/probes/GuardPostureProbe.ts` (classification and alerting are deliberately separate — `/guards` still classifies when the probe's alert is rolled back); the recorded acceptance is `POST /guards/:key/accept-fallback`.
|
|
603
603
|
**Earned from.** The 2026-07-01 mesh incident response was manual operator surgery at every step — and the damning part is that automation for nearly every step EXISTED in code and shipped dark: poll-follows-lease (dry-run), stale-holder takeover, solo-captain hold, pin persistence across lease handover. Walk the incident asking "what did our self-healing actually do?" and the answer is: nothing, because none of it was on. The framework *believed* it had self-healing; the fleet had prose (`docs/postmortems/2026-07-01-silent-telegram-message-loss.md`).
|
|
604
604
|
**Traces to the goal.** Self-healing that isn't enabled isn't self-healing. A coherent self-evolving agent must not confuse the capabilities it HAS with the capabilities it has WRITTEN — this is *Documentation IS Being*'s hard edge: if the doc says "self-healing mesh" and the flags say dark, the doc is describing a fiction.
|
|
605
605
|
**Applied through.** The dark-but-load-bearing classification in the guards inventory (G3 of the postmortem project, upstream); the mandatory postmortem question; *Maturation Path* graduation pressure; the first applied case is poll-follows-lease (decision D3, ratified topic 29836): graduate the smallest captain-hand-back automation rather than accept manual captain flips forever. (Proposed by Echo from the 2026-07-01 postmortem; ratified by Justin 2026-07-01, topic 29836.)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"sha256": "
|
|
2
|
+
"sha256": "7ccfbb251e6935ace35ca3fa778061692ba1aa3854444ad6b5ce7b085322ca9e",
|
|
3
3
|
"articleCount": 82,
|
|
4
4
|
"generatedFrom": "docs/STANDARDS-REGISTRY.md",
|
|
5
|
-
"packageVersion": "1.3.
|
|
5
|
+
"packageVersion": "1.3.1077"
|
|
6
6
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
The CI standards-coverage check now enforces a floor on the **enforced-ratio**, not only on dangling guard
|
|
9
|
+
references. `FLOORS.enforcedRatio` moves from `0` to `0.64` in `scripts/standards-coverage.mjs`.
|
|
10
|
+
|
|
11
|
+
Previously the ratio was computed and printed on every build with a floor of `0`, so a regression from the
|
|
12
|
+
current level all the way back to the original one would still have passed. The dangling ceiling already had
|
|
13
|
+
teeth at zero; the ratio did not.
|
|
14
|
+
|
|
15
|
+
This is the maintenance action the script's own comment asks for — *"Ratchet this upward (a visible PR diff)
|
|
16
|
+
as the documented-only set shrinks"* — taken after the documented-only set shrank from 34 standards to 24.
|
|
17
|
+
|
|
18
|
+
## What to Tell Your User
|
|
19
|
+
|
|
20
|
+
Nothing — this is a CI-only maintenance change with no runtime, route, config or agent-visible surface. A
|
|
21
|
+
deployed agent never executes this script.
|
|
22
|
+
|
|
23
|
+
The one case where it becomes visible is a future pull request that adds a constitutional standard without a
|
|
24
|
+
resolvable guard citation, or removes a guard file a standard cites: that build now fails with a message
|
|
25
|
+
naming both the floor and the measured ratio. That failure is the intended signal.
|
|
26
|
+
|
|
27
|
+
Rolling it back needs no code change: an environment setting that already exists can put the floor back to
|
|
28
|
+
zero in the build configuration.
|
|
29
|
+
|
|
30
|
+
## Summary of New Capabilities
|
|
31
|
+
|
|
32
|
+
No new capability. An existing gate stops being toothless on one of the two measures it already reports.
|
|
33
|
+
|
|
34
|
+
## Evidence
|
|
35
|
+
|
|
36
|
+
- The repository measures **0.6543** against the new **0.64** floor, so no build that does not regress can
|
|
37
|
+
fail. Verified by running `node scripts/standards-coverage.mjs --check` → exit 0.
|
|
38
|
+
- Verified the ratchet **bites** rather than only passes: `STANDARDS_ENFORCED_RATIO_FLOOR=0.99` → exit 1,
|
|
39
|
+
`STANDARDS_ENFORCED_RATIO_FLOOR=0.64` → exit 0.
|
|
40
|
+
- `tests/unit/standards-coverage-ratchet.test.ts` already covers the floor-regression and dangling-ceiling
|
|
41
|
+
failure paths and reads the committed constant, so it exercises this value rather than a copy.
|
|
42
|
+
- Noted while choosing the value: this script measures **0.6543 over 81 standards** where
|
|
43
|
+
`StandardsEnforcementAuditor` measures **0.6585 over 82**, over the same registry file. The floor is set
|
|
44
|
+
against this script's number because this script is what CI runs; the discrepancy is recorded in the code
|
|
45
|
+
comment rather than averaged away.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Side-Effects Review — ratchet the standards enforced-ratio floor 0 → 0.64
|
|
2
|
+
|
|
3
|
+
**Parent standard:** Structure beats Willpower (the constitution's root) — a measurement nobody can regress
|
|
4
|
+
is worth more than a measurement someone must remember to check.
|
|
5
|
+
**Files:** `scripts/standards-coverage.mjs` (one constant + its comment).
|
|
6
|
+
**Not a feature.** No flag, no route, no config key, no migration. A committed floor moves.
|
|
7
|
+
|
|
8
|
+
## What changed
|
|
9
|
+
|
|
10
|
+
`FLOORS.enforcedRatio` default: `0` → `0.64`. The surrounding comment is rewritten to record why, what the
|
|
11
|
+
measured value was, and the cross-implementation discrepancy found while choosing it.
|
|
12
|
+
|
|
13
|
+
This is the action the script's own comment asks the next person to take: *"Ratchet this upward (a visible
|
|
14
|
+
PR diff) as the documented-only set shrinks."* It shrank **34 → 24** on 2026-07-30, as ten standards whose
|
|
15
|
+
guards already existed gained resolvable citations (#1762–#1766, #1769, #1771–#1773).
|
|
16
|
+
|
|
17
|
+
## Blast radius
|
|
18
|
+
|
|
19
|
+
**Exactly one consumer.** `FLOORS` is read only by this script's own `--check`, which runs as the
|
|
20
|
+
`standards-coverage` job in `ci.yml`. Nothing else imports it; no route, no runtime path, no agent behaviour
|
|
21
|
+
reads it. A fleet agent never executes this file.
|
|
22
|
+
|
|
23
|
+
**It cannot fail a build that does not regress.** The repository measures **0.6543** today against a
|
|
24
|
+
**0.64** floor. Every build whose ratio is at or above today's level passes exactly as before. The only
|
|
25
|
+
builds it can newly fail are those that *lower* the ratio — which is the entire purpose.
|
|
26
|
+
|
|
27
|
+
**What it will newly fail, stated plainly so it is not a surprise:** a PR that adds a constitutional standard
|
|
28
|
+
without a resolvable guard citation, or removes a guard file a standard cites, far enough to drop the ratio
|
|
29
|
+
below 0.64. On today's 81-standard denominator that is roughly one standard of headroom. **That failure is
|
|
30
|
+
the intended signal, not a false positive** — and the message names the floor and the measured value, so the
|
|
31
|
+
author sees immediately what happened.
|
|
32
|
+
|
|
33
|
+
**The dangling ceiling is untouched** (still zero, still enforced). This change adds teeth to the ratio only.
|
|
34
|
+
|
|
35
|
+
## The margin, and the discrepancy that set it
|
|
36
|
+
|
|
37
|
+
I first chose **0.65**, taken from `StandardsEnforcementAuditor.computeCoverage` reporting **0.6585 over 82
|
|
38
|
+
standards**. Running the real script showed it reports **0.6543 over 81** — over the *same* registry file.
|
|
39
|
+
Two implementations of the same measure disagree by one article.
|
|
40
|
+
|
|
41
|
+
I did not average them or pick the flattering one. The floor is set against **this script's** number,
|
|
42
|
+
because this script is what CI executes, with roughly one standard of headroom rather than the 0.0043
|
|
43
|
+
(about a third of a standard) that 0.65 would have left. **The discrepancy is recorded in the code comment
|
|
44
|
+
rather than resolved**, because resolving it is a separate piece of work and hiding it would make a future
|
|
45
|
+
reader trust two numbers that do not agree.
|
|
46
|
+
|
|
47
|
+
## Rollback
|
|
48
|
+
|
|
49
|
+
Three levers, cheapest first:
|
|
50
|
+
1. `STANDARDS_ENFORCED_RATIO_FLOOR=0` in the CI job — the env override already exists and needs no code
|
|
51
|
+
change.
|
|
52
|
+
2. Revert the constant to `0`.
|
|
53
|
+
3. Revert the commit.
|
|
54
|
+
|
|
55
|
+
No state is written, no migration runs, nothing persists. Rollback is instantaneous and total.
|
|
56
|
+
|
|
57
|
+
## Verification
|
|
58
|
+
|
|
59
|
+
**Proven to fail, not merely to pass** — a guard nobody has watched fail is not a guard:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
STANDARDS_ENFORCED_RATIO_FLOOR=0.99 node scripts/standards-coverage.mjs --check → exit 1
|
|
63
|
+
STANDARDS_ENFORCED_RATIO_FLOOR=0.64 node scripts/standards-coverage.mjs --check → exit 0
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The existing `tests/unit/standards-coverage-ratchet.test.ts` already covers the floor-regression and
|
|
67
|
+
dangling-ceiling failure paths against a temp fixture, and it reads the floor from the committed constant —
|
|
68
|
+
so it exercises this value rather than a hardcoded copy.
|
|
69
|
+
|
|
70
|
+
## Multi-machine posture
|
|
71
|
+
|
|
72
|
+
**Not applicable — machine-local by construction.** This is a CI script executed by GitHub Actions on a
|
|
73
|
+
checkout. It reads no agent state, contacts no peer, and is never run by a deployed agent.
|
|
74
|
+
|
|
75
|
+
## Signal vs. authority
|
|
76
|
+
|
|
77
|
+
The script is **authority** by design: it fails a build. That authority already existed for the dangling
|
|
78
|
+
ceiling; this change extends it to the ratio, where it was previously advisory-by-accident (floored at 0, so
|
|
79
|
+
computed and reported but never binding). No new *kind* of authority is introduced — an existing gate stops
|
|
80
|
+
being toothless on one of its two measures.
|
|
81
|
+
|
|
82
|
+
## What this does NOT claim
|
|
83
|
+
|
|
84
|
+
- **Not** that 0.64 is the right long-term floor. It is today's measured level minus headroom, and the
|
|
85
|
+
comment says to ratchet it again as the gap closes.
|
|
86
|
+
- **Not** that the ratio measures enforcement quality. It measures that *a guard of the declared shape
|
|
87
|
+
exists and is named* — the auditor says so itself. This change locks in a bookkeeping level, not a safety
|
|
88
|
+
level.
|
|
89
|
+
- **Not** a fix for the 81-vs-82 discrepancy, which is recorded and left open.
|