@event4u/agent-config 9.18.0 → 9.19.0

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.
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Bootstrap shim for the event4u agent-config suite. This plugin ships ONLY the dispatcher hooks plus one install-pointer skill — ALL content (skills, rules, commands) is installed via `npx -y @event4u/agent-config init`, which writes the file projection AND registers the same hooks in ~/.claude/settings.json. DEPRECATED as a content channel; kept so the marketplace listing stays discoverable and existing installs keep working hooks.",
9
- "version": "9.18.0",
9
+ "version": "9.19.0",
10
10
  "keywords": [
11
11
  "agent-config",
12
12
  "skills",
package/CHANGELOG.md CHANGED
@@ -82,6 +82,29 @@ Entry-shape contract: [`docs/contracts/CHANGELOG-conventions.md`](docs/contracts
82
82
 
83
83
  ### Fixed
84
84
 
85
+ - **Every release PR was red on its first run — the generator and the
86
+ highlight gate contradicted each other.** `release.ts` wrote `_none_` into
87
+ all five curated-head fields; `check_release_highlights` (added 2026-08-03)
88
+ fails a `_none_` the release span contradicts. Because every release of this
89
+ package touches `src/rules/` or `src/scripts/schemas/`, "Behaviour changes"
90
+ is *always* substantiated, so the gate reliably red-flagged the generator's
91
+ own default — 9.17.0 (run 30871194277) and 9.18.0 (run 30909511315) both
92
+ failed on that one step, and each release had to be unblocked by hand.
93
+ - The span → category classifier now lives once, in
94
+ `src/scripts/_lib/release_highlights.ts`, and is shared by the generator
95
+ and the gate; the two duplicated label lists are gone with it.
96
+ - `release.ts` **pre-fills** each substantiated label with the deriving
97
+ reason plus its citing SHAs (capped at 6, remainder stated, never silently
98
+ truncated). `_none_` is now a fallback for labels the span does not
99
+ substantiate, not a blanket default — so the tool no longer asserts five
100
+ things it never checked.
101
+ - The gate keeps full teeth for the failure it was actually built for: a
102
+ **human** editing a substantiated line back down to `_none_`, which is what
103
+ produced the false 9.13.0 and 9.14.0 heads. An unrewritten auto-derived
104
+ line is advisory (a prose gap, not a false claim) and never blocks.
105
+ - Derivation is best-effort in the generator: a git failure degrades to the
106
+ `_none_` skeleton with a warning instead of aborting a release.
107
+
85
108
  - **`/team delegate` double gate is now enforced in code, not only in prose**
86
109
  (team mode stays default-off; closing `road-to-team-mode`). The gate on the
87
110
  only write-access wrapper existed as agent-followed instructions in the
@@ -271,6 +294,72 @@ Entry-shape contract: [`docs/contracts/CHANGELOG-conventions.md`](docs/contracts
271
294
  > that forces a new era split (`# Era: 9.19.x`, etc.) — see
272
295
  > [`docs/contracts/CHANGELOG-conventions.md § Era splits`](docs/contracts/CHANGELOG-conventions.md).
273
296
 
297
+ ## [9.19.0](https://github.com/event4u-app/agent-config/compare/9.18.1...9.19.0) (2026-08-04)
298
+
299
+ ### Release highlights
300
+
301
+ <!-- Curated head: fill before merge, keep it under 10 lines, and leave `_none_` where it is genuinely the answer. The generated log below is unchanged. -->
302
+ - **Behaviour changes:** _none_
303
+ - **Default changes + migration:** _none_
304
+ - **Security and correctness:** _none_
305
+ - **Honest nulls:** _auto-derived, rewrite before merge:_ commits carrying an honest-null marker in 1c744c3.
306
+ - **Known limitations:** _none_
307
+
308
+ ### Features
309
+
310
+ * **gate-coverage:** ratchet the unhardened-gate count, armed at 189 and able to fail ([5d1564f](https://github.com/event4u-app/agent-config/commit/5d1564fe0dcbeb340c97f33a29245a54c43a8591))
311
+ * **gate-coverage:** publish the asserted count from five gates, 17 -> 22 covered ([d228aa5](https://github.com/event4u-app/agent-config/commit/d228aa5cb5019dffe11c0e4606644630450d0816))
312
+
313
+ ### Bug Fixes
314
+
315
+ * **roadmap:** repair the archived roadmap's own relative link ([ac85f3a](https://github.com/event4u-app/agent-config/commit/ac85f3a0fdefbbed74c50cc7049c5ffc72b408a8))
316
+ * **census:** make the scan-scope census reproducible, and regenerate it ([1e539ee](https://github.com/event4u-app/agent-config/commit/1e539ee96efc1807663342e084c2a0e666eaf9bc))
317
+ * **lint_handoffs:** stop the CI invocation resolving --quiet as the scan root ([6994781](https://github.com/event4u-app/agent-config/commit/6994781875f8d1d2feab6012ac7704e04232447e))
318
+ * **gates:** name the fence hole, drop the dead sort ([16dace4](https://github.com/event4u-app/agent-config/commit/16dace44b7d468aaba95abf16ec79d65d9862db8))
319
+
320
+ ### Documentation
321
+
322
+ * **roadmap:** close road-to-gates-that-can-fail, re-charter the adoption gap ([34ff10c](https://github.com/event4u-app/agent-config/commit/34ff10c0748ea7e1c4cfdb99f423c35bba1c9a98))
323
+ * **claims:** register the exit-2 rate alarm in the Stage-A protocol ([4653841](https://github.com/event4u-app/agent-config/commit/46538415f7a59993aef7575f32cc84582a03126f))
324
+ * **review:** unsteered post-merge blind pass — 5 findings, 1 critical ([1c744c3](https://github.com/event4u-app/agent-config/commit/1c744c395f8d1bb727be946f459ce5a498320b5d))
325
+
326
+ ### Chores
327
+
328
+ * **census:** regenerate after merging origin/main ([239f141](https://github.com/event4u-app/agent-config/commit/239f1413b950455efbe379976ea34a67ff02d380))
329
+
330
+ Tests: 10972 (+9 since 9.18.1)
331
+
332
+ ## [9.18.1](https://github.com/event4u-app/agent-config/compare/9.18.0...9.18.1) (2026-08-04)
333
+
334
+ ### Release highlights
335
+
336
+ <!-- Curated head: fill before merge, keep it under 10 lines, and leave `_none_` where it is genuinely the answer. The generated log below is unchanged. -->
337
+ - **Behaviour changes:** the release generator pre-fills the curated head from the release span instead of writing `_none_` into all five fields (8fe60e9, 2f23d6b) — `_none_` now means "the span substantiates nothing", so a reader can trust it; review-gate scope classification changed, with IaC and extensionless build files counting as code and a findings row required to be exactly six cells (6c5f0f5).
338
+ - **Default changes + migration:** _none_
339
+ - **Security and correctness:** two more fail-open routes in the review-gate fence parser are closed — an unterminated fence no longer swallows the rest of a findings artefact (55dc01d) and a bare fence never delimits a region (9937ad9, the fourth such route); both previously let a truncated artefact read as clean.
340
+ - **Honest nulls:** the honest-null recorded against 6c6fc15a9 in the 9.18.0 notes was **false** — the real binding review is restored (d56c0be), so treat that 9.18.0 line as withdrawn. Rounds 6 to 8 of the R2 review closed 7 findings and deferred 10, with 0 critical or high (7a0f7b3, 39f071f, 70bb89f).
341
+ - **Known limitations:** the head pre-fill matches an `honest-null` literal anywhere in a commit body, so a commit *about* the mechanism gets cited as one — it did here, for 2f23d6b, and a human dropped it. The derived line is a draft, never a claim; the gate blocks only a `_none_` the span contradicts and never judges a filled field.
342
+
343
+ ### Bug Fixes
344
+
345
+ * **release:** derive the head in --dry-run too, so the preview matches ([2f23d6b](https://github.com/event4u-app/agent-config/commit/2f23d6bb963577af5741951962b48e556e5a3e97))
346
+ * **release:** stop the generator writing a `_none_` the gate rejects ([8fe60e9](https://github.com/event4u-app/agent-config/commit/8fe60e9aba5192c07f8e33bc6ce1747a77e82922))
347
+ * **gates:** a bare fence never delimits a region — close the fourth fail-open route ([9937ad9](https://github.com/event4u-app/agent-config/commit/9937ad9b75f60bffd4ad42f2a830589bd4be7e5c))
348
+ * **gates:** an unterminated fence must not swallow the rest of a findings artefact ([55dc01d](https://github.com/event4u-app/agent-config/commit/55dc01d1fd3c8dbf44dd04fa7b3f41e3f4bc39bb))
349
+ * **gates:** IaC and extensionless build files are code; a row is exactly six cells ([6c5f0f5](https://github.com/event4u-app/agent-config/commit/6c5f0f5999b8a421cf765269a8da8b780465dc98))
350
+
351
+ ### Documentation
352
+
353
+ * **review:** close round 8 — 1 fixed, 4 deferred, 0 critical ([70bb89f](https://github.com/event4u-app/agent-config/commit/70bb89f2820f4c5a5a26cd25f5db2daa53b08e5e))
354
+ * **review:** close round 7 — 2 fixed, 3 deferred, 0 critical/high ([39f071f](https://github.com/event4u-app/agent-config/commit/39f071fad58dc2c5cb9e6ec87e8e37b79085db2f))
355
+ * **gates:** in-place re-binding is the normal fix-pass path (2.1/2.5/2.7) ([1f7d140](https://github.com/event4u-app/agent-config/commit/1f7d1404c4bc63e87d4b46f91d52f81f2ae51f7b))
356
+ * **review:** round-7 R2 findings — 2 medium, 3 low, 0 critical/high ([2bd3eda](https://github.com/event4u-app/agent-config/commit/2bd3edad82ff69700f62c4d16c93f38a484e5e08))
357
+ * **review:** close round 6 — 4 fixed, 3 deferred, 0 critical/high ([7a0f7b3](https://github.com/event4u-app/agent-config/commit/7a0f7b33aed30921f2404ae1955a8e5aa76dde9b))
358
+ * **gates:** two claims corrected to match the code (round-6 lows) ([0f5d43a](https://github.com/event4u-app/agent-config/commit/0f5d43a17be245b034287b0f486839fb156f8b86))
359
+ * **review:** restore the real binding review — 6c6fc15a9's honest-null was false ([d56c0be](https://github.com/event4u-app/agent-config/commit/d56c0be63f6782183737ab50256401ab52a1f38f))
360
+
361
+ Tests: 10963 (+19 since 9.18.0)
362
+
274
363
  ## [9.18.0](https://github.com/event4u-app/agent-config/compare/9.17.0...9.18.0) (2026-08-04)
275
364
 
276
365
  ### Release highlights
@@ -39,7 +39,7 @@ schema_version: 1
39
39
  # CI guard: a release bump of `package.json` must update this value
40
40
  # in lockstep — see scripts/check_template_pin_drift.ts (road-to-
41
41
  # portable-runtime-and-update-check P3.3).
42
- agent_config_version: "9.18.0"
42
+ agent_config_version: "9.19.0"
43
43
 
44
44
  # --- Project identity ---
45
45
  project:
@@ -1,6 +1,6 @@
1
1
  # Discovery — Deprecation Report
2
2
 
3
- - Generated: `2026-08-04T14:13:41Z`
3
+ - Generated: `2026-08-04T16:08:00Z`
4
4
  - Deprecated artefacts: **0**
5
5
 
6
6
  _None. Tree is clean._
@@ -14402,7 +14402,7 @@
14402
14402
  "reason": "scaffold template for ticket-bundle tickets (ADR-101); carries no runtime frontmatter — emit-tickets fills it in per ticket"
14403
14403
  }
14404
14404
  ],
14405
- "generated_at": "2026-08-04T14:13:41Z",
14405
+ "generated_at": "2026-08-04T16:08:00Z",
14406
14406
  "packs": [
14407
14407
  {
14408
14408
  "artefact_count": 117,
@@ -1 +1 @@
1
- 4a7dadd2d33fe1127bfd31cb3bdf58c83d3609c17b740e06e8666569b760cf65 discovery-manifest.json
1
+ 771e350a2329d84c1a47378ed09ebeed75e5ada993d722cfc079b3f5befec595 discovery-manifest.json
@@ -1,6 +1,6 @@
1
1
  # Discovery Manifest — Summary
2
2
 
3
- - Generated: `2026-08-04T14:13:41Z`
3
+ - Generated: `2026-08-04T16:08:00Z`
4
4
  - Scanner: `c24312e116f8`
5
5
  - Artefacts: **594**
6
6
  - Unassigned: **0**
@@ -1,6 +1,6 @@
1
1
  # Discovery — Orphan Report
2
2
 
3
- - Generated: `2026-08-04T14:13:41Z`
3
+ - Generated: `2026-08-04T16:08:00Z`
4
4
  - Orphan artefacts: **0**
5
5
 
6
6
  > An orphan is an artefact whose declared pack has no other members.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "checksum": "sha256:d766f7f17140ce6b648e68821c9403c0bf478609a1ea925e85501c5994002a05",
3
- "generated_at": "2026-08-04T14:13:41Z",
3
+ "generated_at": "2026-08-04T16:08:00Z",
4
4
  "packs": [
5
5
  {
6
6
  "always_on": false,
@@ -1,6 +1,6 @@
1
1
  # Discovery — Trust Report
2
2
 
3
- - Generated: `2026-08-04T14:13:41Z`
3
+ - Generated: `2026-08-04T16:08:00Z`
4
4
  - Workspaces tracked: **10**
5
5
  - Human-review-required artefacts: **3**
6
6
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "checksum": "sha256:d766f7f17140ce6b648e68821c9403c0bf478609a1ea925e85501c5994002a05",
3
- "generated_at": "2026-08-04T14:13:41Z",
3
+ "generated_at": "2026-08-04T16:08:00Z",
4
4
  "scanner_version": "c24312e116f8",
5
5
  "workspaces": [
6
6
  {
@@ -9,7 +9,7 @@
9
9
  "homepage": "https://event4u-app.github.io/agent-config",
10
10
  "name": "@event4u/agent-config",
11
11
  "repository": "https://github.com/event4u-app/agent-config",
12
- "version": "9.18.0"
12
+ "version": "9.19.0"
13
13
  },
14
14
  "registries": [
15
15
  {
@@ -9,12 +9,12 @@
9
9
  "transport": {
10
10
  "type": "stdio"
11
11
  },
12
- "version": "9.18.0"
12
+ "version": "9.19.0"
13
13
  }
14
14
  ],
15
15
  "repository": {
16
16
  "source": "github",
17
17
  "url": "https://github.com/event4u-app/agent-config"
18
18
  },
19
- "version": "9.18.0"
19
+ "version": "9.19.0"
20
20
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@event4u/agent-config",
3
3
  "mcpName": "io.github.event4u-app/agent-config",
4
- "version": "9.18.0",
4
+ "version": "9.19.0",
5
5
  "description": "Governed skills, rules and commands for AI coding tools (Claude Code, Cursor, Windsurf, Copilot) — every claim machine-checked, including \"zero runtime daemon\".",
6
6
  "license": "MIT",
7
7
  "private": false,
@@ -40,25 +40,43 @@
40
40
  # visible, or it repeats the sin it exists to catch.
41
41
  # canary optional mutation recipe (Phase 7) — see CANARY below
42
42
  #
43
- # COVERAGE — THE HONEST DENOMINATOR (measured 2026-08-02)
44
- # ------------------------------------------------------
45
- # 211 `lint_*` / `check_*` / `audit_*` scripts live under `src/scripts/`.
46
- # **8 of them emit the machine-readable `scanned: <N>` line under their
47
- # CI-identical argv, and all 8 are listed below.** The manifest is therefore
48
- # complete with respect to its own contract, and covers ~4 % of the gate
49
- # population.
43
+ # COVERAGE — THE HONEST DENOMINATOR (re-measured 2026-08-04)
44
+ # ----------------------------------------------------------
45
+ # 223 `lint_*` / `check_*` / `audit_*` scripts live under `src/scripts/`
46
+ # (the count is computed, not asserted — `check_gate_coverage.count_gate_scripts`).
47
+ # **22 of them emit the machine-readable `scanned: <N>` line under their
48
+ # CI-identical argv, and all 22 are listed below.** The manifest is therefore
49
+ # complete with respect to its own contract, and covers ~10 % of the population.
50
50
  #
51
- # The other ~203 are NOT covered, for one reason: rule 1. They print their count
51
+ # The previous revision of this header claimed "8 of 211". Both halves had
52
+ # drifted: entries were added without the header following, and the population
53
+ # grew by 12. Numbers written in prose beside a mechanism that can compute them
54
+ # is how a denominator goes stale — the population figure now comes from the
55
+ # function, and the honest-denominator test bounds the drift.
56
+ #
57
+ # The other ~201 are NOT covered, for one reason: rule 1. They print their count
52
58
  # in prose ("111 file(s) scanned", "0 declarer(s)") or not at all, and a guard
53
59
  # that parses prose is the fragile thing being replaced. Padding this list with
54
60
  # them would manufacture exactly the false green the file exists to prevent.
55
61
  #
56
- # Closing the gap is one line per gate, not a new mechanism: a gate that already
57
- # computes its count for `_lib/scan_scope.assertScanned` need only also write
58
- # `scanned: <N>`. Seven gates are one line away today — they call `assertScanned`
59
- # / `assertWatchlistResolves` with a real count in hand: `audit_skill_overlap`,
60
- # `check_iron_law_prominence`, `check_safety_floor_untouched`, `lint_handoffs`,
61
- # `lint_namespace`, `lint_artefact_frontmatter`, `skill_linter` (listed).
62
+ # THE "SEVEN GATES ONE LINE AWAY" NOTE IS DISCHARGED (2026-08-04). It named
63
+ # `audit_skill_overlap`, `check_iron_law_prominence`, `check_safety_floor_untouched`,
64
+ # `lint_handoffs`, `lint_namespace`, `lint_artefact_frontmatter`, `skill_linter`.
65
+ # Five are now converted and listed below; `skill_linter` was already listed when
66
+ # the note was written. `check_safety_floor_untouched` is deliberately NOT
67
+ # converted: it is the one watch-list gate, so its "count" is the size of a fixed
68
+ # guard list (4), not a corpus. A floor under a constant can never trip — that is
69
+ # the false-count shape Phase 2 of the roadmap repaired, and re-introducing it
70
+ # here to raise a coverage number would be the manufactured green this file
71
+ # exists to prevent. It stays unlisted, named, with the reason.
72
+ #
73
+ # What remains is NOT one line per gate. For the ~201 the count would have to be
74
+ # INVENTED (what is this gate's unit?) rather than published, and that judgement
75
+ # is per-gate. It is tracked as a vulnerability ratchet — `gate-hardening:
76
+ # unhardened-scan-scope` in src/config/gate-violation-baselines.json, which fails
77
+ # on a RISE and targets 0 — and charter-owned by
78
+ # `agents/roadmaps/road-to-gate-hardening-adoption.md`.
79
+ #
62
80
  # `tests/scripts/check_gate_coverage.test.ts` fails the build the moment a gate
63
81
  # starts emitting the line without being registered here, so the list cannot
64
82
  # silently fall behind again (that omission is exactly how `check_site_links`
@@ -329,8 +347,12 @@ gates:
329
347
  Gate R2 (docs/contracts/plan-review-gates.md § 2). HONEST LIMIT, stated
330
348
  because a floor that cannot fail is exactly the false green this file
331
349
  exists to prevent: scanned = artefacts inspected + 1 for the diff
332
- evaluation, so it is >= 1 by construction and `min_scanned: 1` can never
333
- trip. NOTHING ELSE TRIPS EITHER DURING THE ADVISORY WINDOW. The argv above
350
+ evaluation, so on any run that REACHES the count `min_scanned: 1` cannot
351
+ trip. It is not unreachable in principle — a moved reviews root exits
352
+ before the inventory and reports `scanned: 0`, which the guard does read —
353
+ but that path is the dead-scope violation below, so the floor never adds
354
+ anything the assertion does not already catch.
355
+ NOTHING TRIPS AT ALL DURING THE ADVISORY WINDOW. The argv above
334
356
  mirrors the CI invocation, and under `--advisory` every violation kind —
335
357
  dead-scan-scope included — is printed as a warning and the exit code is 0.
336
358
  So for the duration of the Stage-A window this entry proves only that the
@@ -342,3 +364,64 @@ gates:
342
364
  from the CI invocation; nothing else changes at that switch. The entry
343
365
  stays registered so the guard reports this gate rather than skipping it
344
366
  silently.
367
+
368
+ # ---------------------------------------------------------------------------
369
+ # The five below close the gap this header named: they already called
370
+ # `_lib/scan_scope.assertScanned` with a real count and only had to PRINT it.
371
+ # The published number is not agent-derived — it is byte-identical to the value
372
+ # the gate's own dead-scope assertion already gates a red exit on, so there is
373
+ # no fresh judgement about "what a unit is" and no room for a count that drifts
374
+ # from what the gate inspected. That property is what made them convertible
375
+ # without per-gate adjudication; gates whose count would have to be INVENTED
376
+ # are deliberately NOT in this batch — see road-to-gate-hardening-adoption.
377
+ # Floors are ~87 % of the measured baseline: room for legitimate deletions,
378
+ # far above a collapse (rule 3).
379
+ # ---------------------------------------------------------------------------
380
+
381
+ - id: lint_handoffs
382
+ argv: ["--quiet"]
383
+ min_scanned: 250
384
+ corpus: "src/skills/*/SKILL.md (288 at baseline)"
385
+ status: enforced
386
+ note: >
387
+ The argv here is load-bearing, not decoration. Taskfile injects `--quiet`
388
+ (QUIET_FLAG) and this gate read `args[0]` as a positional path, so the CI
389
+ invocation resolved `--quiet` as its skills root, scanned 0 and exited 2 —
390
+ red in `task lint-handoffs`, green when probed bare. Fixed by filtering
391
+ flag-shaped args before the positional read. Registering it under the REAL
392
+ argv is what keeps that regression caught: a bare-probe entry would have
393
+ gone on passing over the broken invocation.
394
+
395
+ - id: lint_namespace
396
+ argv: ["--quiet"]
397
+ min_scanned: 540
398
+ corpus: "names across src/rules + src/skills + src/agent-src + src/domains/**/command.md (621 at baseline)"
399
+ status: enforced
400
+ note: >
401
+ Counts NAMES, not files — the scan-scope census counts files under the same
402
+ roots, so the two artefacts legitimately report different numbers here.
403
+
404
+ - id: lint_artefact_frontmatter
405
+ argv: ["--quiet"]
406
+ min_scanned: 540
407
+ corpus: "artefacts carrying frontmatter across the discovery roots (619 at baseline)"
408
+ status: enforced
409
+
410
+ - id: audit_skill_overlap
411
+ argv: ["--quiet", "--print-table", "--strict"]
412
+ min_scanned: 250
413
+ corpus: "src/skills/*/SKILL.md compared pairwise (288 at baseline)"
414
+ status: enforced
415
+ note: >
416
+ `--strict` is part of the CI invocation and can exit non-zero on a real
417
+ overlap finding. The guard reads the count independently of the exit code —
418
+ coverage and verdict are different questions.
419
+
420
+ - id: check_iron_law_prominence
421
+ argv: ["--quiet"]
422
+ min_scanned: 90
423
+ corpus: "src/rules/*.md (111 at baseline)"
424
+ status: enforced
425
+ note: >
426
+ Emits on stderr, not stdout: `--format json` owns this gate's stdout and a
427
+ count written there would corrupt the payload. The guard reads both streams.
@@ -1,6 +1,11 @@
1
1
  {
2
2
  "$comment": "Violation ratchet for gates whose dead scan root was repaired. A repair REVEALS pre-existing debt; it does not create it. Each entry records the count revealed at repair time — the gate fails only when its count RISES. Lowering a count is a normal commit; raising one is a defect. Entries expire: a baseline that has not dropped within 56 days of `landed` (or of `reaffirmed.date`) fails its gate, because a number that never moves is suppression with extra steps. Mechanism + rationale: src/scripts/_lib/gate_baseline.ts. Decision: AI council 2026-08-02, roadmap road-to-gates-that-can-fail blocker `dead-gate-finding-triage`.",
3
3
  "gates": {
4
+ "gate-hardening:unhardened-scan-scope": {
5
+ "count": 189,
6
+ "landed": "2026-08-04",
7
+ "note": "Gate scripts under src/scripts (population 223, the lint_/check_/audit_ prefix set) that neither route through _lib/scan_scope nor emit the machine-readable 'scanned:' line — the gates that can still report success over a moved or empty root without saying so. This is a VULNERABILITY count, not a coverage percentage: it measures how much of the original defect class is still reachable, it RISES whenever a new gate is written without a scope assertion, and its target is 0. That direction is the whole point — an adoption-reach metric ('hardened gates must increase') can never regress and would be threshold-lowering wearing a ratchet's clothes (AI council 2026-08-04, anthropic/claude-sonnet-4-5 + openai/gpt-4o, convergent on scope decomposition plus this discriminator). Clearing it is the charter of road-to-gate-hardening-adoption; the 56-day non-stagnation clause applies unchanged, so a number that never drops fails this gate rather than hardening into configuration. NEW ENTRY, not a raised threshold: this records newly-measured pre-existing exposure at first measurement — nothing was loosened."
8
+ },
4
9
  "check_no_new_legacy_path:hardcoded-scan-roots": {
5
10
  "count": 51,
6
11
  "landed": "2026-08-02",