@event4u/agent-config 9.23.0 → 9.25.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +82 -0
- package/README.md +2 -2
- package/dist/agent-src/commands/agent-handoff.md +10 -3
- package/dist/agent-src/commands/analyze/conformance.md +182 -0
- package/dist/agent-src/commands/analyze/inbox.md +221 -0
- package/dist/agent-src/commands/analyze.md +4 -3
- package/dist/agent-src/commands/pr/create.md +6 -6
- package/dist/agent-src/rules/context-hygiene.md +3 -0
- package/dist/agent-src/rules/decision-revisit-gate.md +2 -0
- package/dist/agent-src/rules/evaluator-independence.md +105 -0
- package/dist/agent-src/rules/session-canary.md +13 -1
- package/dist/agent-src/rules/user-interaction.md +22 -0
- package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +1 -1
- package/dist/agent-src/skills/rule-writing/SKILL.md +45 -0
- package/dist/agent-src/skills/skill-writing/SKILL.md +114 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli/registry.js +1 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +96 -22
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -4
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +11 -8
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +9 -6
- package/dist/hooks/dispatch.js +1026 -328
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/router.json +1 -1
- package/package.json +1 -1
- package/src/config/evaluator-budgets.json +68 -68
- package/src/config/gate-coverage.yml +103 -5
- package/src/config/gate-violation-baselines.json +11 -6
- package/src/scripts/_dispatch.bash +12 -0
- package/src/scripts/before_complete_hook.ts +127 -5
- package/src/scripts/check_depth_budget.ts +295 -0
- package/src/scripts/conformance_scan.ts +392 -0
- package/src/scripts/git_authorization_hook.ts +263 -0
- package/src/scripts/hook_manifest.yaml +50 -9
- package/src/scripts/hooks/block_unauthorized_git.ts +254 -0
- package/src/scripts/hooks/concern_registry.ts +8 -0
- package/src/scripts/hooks/evidence_independence.ts +334 -0
- package/src/scripts/language_mirror_hook.ts +267 -0
- package/src/scripts/lint_decision_impact.ts +246 -0
- package/src/scripts/lint_example_fences.ts +609 -0
- package/src/scripts/lint_rule_interactions.ts +90 -0
- package/src/scripts/lint_rule_migration_ledger.ts +480 -0
- package/src/scripts/lint_skill_descriptions.ts +86 -2
- package/src/scripts/measure_rule_absoluta.ts +231 -0
- package/src/scripts/schemas/rule.schema.json +10 -0
|
@@ -42,11 +42,11 @@
|
|
|
42
42
|
#
|
|
43
43
|
# COVERAGE — THE HONEST DENOMINATOR (re-measured 2026-08-05)
|
|
44
44
|
# ----------------------------------------------------------
|
|
45
|
-
#
|
|
45
|
+
# 240 `lint_*` / `check_*` / `audit_*` scripts live under `src/scripts/`
|
|
46
46
|
# (the count is computed, not asserted — `check_gate_coverage.count_gate_scripts`).
|
|
47
|
-
# **
|
|
48
|
-
# CI-identical argv, and all
|
|
49
|
-
# complete with respect to its own contract, and covers ~
|
|
47
|
+
# **31 of them emit the machine-readable `scanned: <N>` line under their
|
|
48
|
+
# CI-identical argv, and all 31 are listed below.** The manifest is therefore
|
|
49
|
+
# complete with respect to its own contract, and covers ~13 % of the population.
|
|
50
50
|
#
|
|
51
51
|
# Two revisions of this header have now gone stale the same way. It claimed
|
|
52
52
|
# "8 of 211", then "22 of 223" while 26 entries were listed. Both halves drift
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
# stays a manual count until something computes it too. If you add an entry,
|
|
58
58
|
# the two numbers in the paragraph above are part of the diff.
|
|
59
59
|
#
|
|
60
|
-
# The other ~
|
|
60
|
+
# The other ~209 are NOT covered, for one reason: rule 1. They print their count
|
|
61
61
|
# in prose ("111 file(s) scanned", "0 declarer(s)") or not at all, and a guard
|
|
62
62
|
# that parses prose is the fragile thing being replaced. Padding this list with
|
|
63
63
|
# them would manufacture exactly the false green the file exists to prevent.
|
|
@@ -501,3 +501,101 @@ gates:
|
|
|
501
501
|
create-only by design. Discrimination is proven instead by the gate's own
|
|
502
502
|
`--self-test`, which drives the real binary through six rejecting cases
|
|
503
503
|
including the dead-scan-root one.
|
|
504
|
+
|
|
505
|
+
- id: lint_example_fences
|
|
506
|
+
argv: ["--strict"]
|
|
507
|
+
min_scanned: 450
|
|
508
|
+
corpus: "authored markdown whose fenced blocks are code the reader copies — src/rules/*.md, src/skills/*/SKILL.md, docs/guidelines/**/*.md (503 at baseline)"
|
|
509
|
+
status: enforced
|
|
510
|
+
canary:
|
|
511
|
+
class: undetected-antipattern
|
|
512
|
+
path: docs/guidelines/zz-canary-example-fence.md
|
|
513
|
+
content: |
|
|
514
|
+
# Canary
|
|
515
|
+
|
|
516
|
+
Planted canary: a fenced example teaching the render sink the
|
|
517
|
+
`frontend-render-security` rule forbids three paragraphs away.
|
|
518
|
+
|
|
519
|
+
```js
|
|
520
|
+
el.innerHTML = untrustedUserBio;
|
|
521
|
+
```
|
|
522
|
+
note: >
|
|
523
|
+
Registered STRICT on day one, which is the opposite of the advisory
|
|
524
|
+
landing its roadmap step planned for — because the classification that
|
|
525
|
+
step demands came back **zero hits over all 503 files**, and an advisory
|
|
526
|
+
gate over an empty violation set is a gate that can only ever be ignored.
|
|
527
|
+
The zero is verified rather than assumed: every raw occurrence of the
|
|
528
|
+
eight registry tokens in the tree is prose forbidding the pattern, a table
|
|
529
|
+
row, or an `rg` search string inside a shell fence, and a liveness probe
|
|
530
|
+
that injected a violation INTO a real corpus file fired while the
|
|
531
|
+
untouched original stayed clean. Floor at 450 against a live 503 leaves
|
|
532
|
+
room for skill retirement without redding the change that retires one.
|
|
533
|
+
|
|
534
|
+
- id: check_depth_budget
|
|
535
|
+
argv: []
|
|
536
|
+
min_scanned: 140
|
|
537
|
+
corpus: "on-demand depth files — src/agent-src/contexts/**/*.md + docs/guidelines/**/*.md (161 at baseline)"
|
|
538
|
+
status: enforced
|
|
539
|
+
canary:
|
|
540
|
+
class: budget-blind
|
|
541
|
+
path: docs/guidelines/zz-canary-depth-budget.md
|
|
542
|
+
content: |
|
|
543
|
+
# Canary
|
|
544
|
+
|
|
545
|
+
Planted canary: a depth file over the 16,000-char ceiling, which must
|
|
546
|
+
make the shrink-only ratchet red as the fifth violation.
|
|
547
|
+
|
|
548
|
+
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
549
|
+
note: >
|
|
550
|
+
The ratchet baseline is 4, so this gate is green on the current tree and
|
|
551
|
+
reds on a FIFTH over-ceiling depth file. Both halves are proven rather
|
|
552
|
+
than assumed: planting a 16,100-char file took it to exit 1 and removing
|
|
553
|
+
the file took it back to exit 0. Floor at 140 against a live 161 leaves
|
|
554
|
+
room for consolidating reference documents — which is the direction this
|
|
555
|
+
ratchet is meant to push — without redding the change that consolidates.
|
|
556
|
+
|
|
557
|
+
- id: lint_rule_migration_ledger
|
|
558
|
+
argv: ["--quiet"]
|
|
559
|
+
min_scanned: 35
|
|
560
|
+
corpus: "rules whose body was migrated out to a skill, guideline, context or contract (44 at baseline)"
|
|
561
|
+
status: enforced
|
|
562
|
+
canary:
|
|
563
|
+
class: unledgered-migration
|
|
564
|
+
path: src/rules/zz-canary-migrated-rule.md
|
|
565
|
+
content: |
|
|
566
|
+
---
|
|
567
|
+
type: auto
|
|
568
|
+
description: "Planted canary rule whose body was migrated out with no ledger behind it."
|
|
569
|
+
---
|
|
570
|
+
|
|
571
|
+
# Canary
|
|
572
|
+
|
|
573
|
+
Body migrated to `skill:docker`.
|
|
574
|
+
note: >
|
|
575
|
+
The canary plants a rule carrying a migration pointer and no ledger, which
|
|
576
|
+
is the defect the gate exists for — a lossy transform with no record.
|
|
577
|
+
Floor at 35 against a live 44 leaves room for a rule un-migrating (its
|
|
578
|
+
body coming back) without redding the change that does it.
|
|
579
|
+
|
|
580
|
+
- id: lint_decision_impact
|
|
581
|
+
argv: ["--quiet"]
|
|
582
|
+
min_scanned: 90
|
|
583
|
+
corpus: "src/rules/*.md frontmatters (111 at baseline)"
|
|
584
|
+
status: enforced
|
|
585
|
+
canary:
|
|
586
|
+
class: unevidenced-removal-class
|
|
587
|
+
path: src/rules/zz-canary-decision-impact.md
|
|
588
|
+
content: |
|
|
589
|
+
---
|
|
590
|
+
type: auto
|
|
591
|
+
description: "Planted canary claiming the removal-permitting class with no evidence behind it."
|
|
592
|
+
decision_impact: already-complied-with
|
|
593
|
+
---
|
|
594
|
+
|
|
595
|
+
# Canary
|
|
596
|
+
note: >
|
|
597
|
+
Verified-empty by design: 111 rules read, 0 classified, because the field
|
|
598
|
+
is optional and backfill is opportunistic (a 111-rule batch trips
|
|
599
|
+
check_kernel_prefix_stability). The canary is what distinguishes that from
|
|
600
|
+
a gate scanning nothing — it plants the removal-permitting class with no
|
|
601
|
+
evidence and the gate reds.
|
|
@@ -1,31 +1,36 @@
|
|
|
1
1
|
{
|
|
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
|
|
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 \u2014 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
4
|
"check_no_new_legacy_path:hardcoded-scan-roots": {
|
|
5
5
|
"count": 49,
|
|
6
6
|
"landed": "2026-08-04",
|
|
7
|
-
"note": "Lines under src/scripts/**/*.{ts,mts,mjs} that pass the retired `.agent-src.uncondensed` directory into `path.join(...)`
|
|
7
|
+
"note": "Lines under src/scripts/**/*.{ts,mts,mjs} that pass the retired `.agent-src.uncondensed` directory into `path.join(...)` \u2014 a filesystem path CONSTRUCTED against the tree ADR-051 abandoned, which is the exact shape of all 14 dead gates. Deliberately narrow so the number is signal, not noise: 236 raw mentions under src/scripts \u2192 147 string-literal lines \u2192 67 path-constructing lines when the pass was written, after exempting src/scripts/_lib/agent_src.ts (the shared resolver, whose job IS owning the constant \u2014 gates that route through it survived the move). Detectors holding the literal as data to match, strip, or print are not counted, and no prose, docs, tests or fixtures are read: that full-tree shape was measured at 44 files / 213 hits and rejected as the wrong lint (see the note in check_no_new_legacy_path.ts::find_offenders). Recorded at 58 rather than 67 because Phase 1's scan-root repairs were landing on this branch while the pass was being written and had already removed 9 \u2014 a baseline above the truth silently permits new violations. This count goes to ZERO as the remaining repairs land; every repair is a lowering commit. Lowered 56\u219251 by the road-to-renewal-foundation Phase 1 dead-root sweep (check_always_budget, check_portability, check_references, lint_framework_leakage, lint_agents_md). Lowered 51\u219249 by the gate-hardening adoption PR: skill_collision_clusters and skill_overlap were repointed at the live skills tree via the shared resolver \u2014 two gates that had been reading the retired container and scoring 0 of 288 skills."
|
|
8
8
|
},
|
|
9
9
|
"audit_user_type_axis": {
|
|
10
10
|
"count": 1,
|
|
11
11
|
"landed": "2026-08-02",
|
|
12
|
-
"note": "One orphan user-type value: `legal`. Five legal-review-prep skills (contract-review, dpa-review, nda-triage, legal-intake-triage, legal-practice-profile) declare `recommended_for_user_types: [legal]`, but there is no `user-types/legal.yml`
|
|
12
|
+
"note": "One orphan user-type value: `legal`. Five legal-review-prep skills (contract-review, dpa-review, nda-triage, legal-intake-triage, legal-practice-profile) declare `recommended_for_user_types: [legal]`, but there is no `user-types/legal.yml` \u2014 the pack shipped an axis value with no user-type definition behind it, and the dead scan root hid it (the audit reported used=0 orphans=0 while reading zero skills; it now reads 288 and reports used=8). Clearing this entry is a product call, not a copy edit: either author `user-types/legal.yml` (tagline, recommended packs, install-path hint) or drop `legal` from those five skills. Not decided here because both options change shipped pack behaviour."
|
|
13
13
|
},
|
|
14
14
|
"lint_handoffs": {
|
|
15
15
|
"count": 18,
|
|
16
16
|
"landed": "2026-08-02",
|
|
17
|
-
"note": "All 18 are `handoff_tier_mismatch`: a senior-tier skill links to a peer whose frontmatter carries no `tier` (reported as tier='unset')
|
|
17
|
+
"note": "All 18 are `handoff_tier_mismatch`: a senior-tier skill links to a peer whose frontmatter carries no `tier` (reported as tier='unset') \u2014 e.g. build-buy-partner \u2192 adr-create, customer-research \u2192 po-discovery, gated-reach \u2192 threat-modeling. This is a tier-metadata backfill backlog on the LINKED-TO skills, not a broken link. The one genuinely dangling link revealed by the same repair (competitive-positioning \u2192 a non-existent ../analyze-reference-repo/SKILL.md; it is a command, not a skill) was FIXED in the repairing commit rather than baselined. Clearing this entry means backfilling `tier` on the linked-to skills, or deciding that `tier: unset` on a link target is not a violation and narrowing the rule."
|
|
18
18
|
},
|
|
19
19
|
"lint_pack_boundaries": {
|
|
20
20
|
"count": 337,
|
|
21
21
|
"landed": "2026-08-02",
|
|
22
|
-
"note": "Markdown links between source artefacts that cross a pack boundary the source pack's `requires` graph does not reach
|
|
22
|
+
"note": "Markdown links between source artefacts that cross a pack boundary the source pack's `requires` graph does not reach \u2014 revealed when the scan root moved off the deleted packages/ tree to the live corpus (0 -> 753 artefacts scanned). 82 distinct pack pairs across 131 source files; largest single class is engineering-base -> meta (73), skills in a consumer-installable pack citing this package's own maintenance skills. Each is a link that dangles for a consumer who installs the source pack without the target's. Judged real drift rather than an over-strict gate because it is long-tailed \u2014 top bucket 22%, no single systematic cause \u2014 unlike the lint_artefact_frontmatter case, where one required shape had 0-of-288 adoption. Fix per finding: add the edge to packs.yml requires, retarget the link, or move the artefact."
|
|
23
23
|
},
|
|
24
24
|
"check_gate_completeness": {
|
|
25
25
|
"count": 217,
|
|
26
26
|
"landed": "2026-08-05",
|
|
27
|
-
"note": "Ledger adoption ratchet. 217 of 221 CI-registered gates do not yet carry per-target completeness accounting (`_lib/gate_ledger.ts`) or a `// ledger-exempt:` marker. This is deliberately NOT a sweep: road-to-skill-ecosystem-gate-integrity Phase 1 adopts exactly three gates (lint_framework_leakage, check_references, lint_roadmap_complexity) plus the checker itself to prove the interface, and the remainder migrates as gates are touched. Shrink-only from here
|
|
27
|
+
"note": "Ledger adoption ratchet. 217 of 221 CI-registered gates do not yet carry per-target completeness accounting (`_lib/gate_ledger.ts`) or a `// ledger-exempt:` marker. This is deliberately NOT a sweep: road-to-skill-ecosystem-gate-integrity Phase 1 adopts exactly three gates (lint_framework_leakage, check_references, lint_roadmap_complexity) plus the checker itself to prove the interface, and the remainder migrates as gates are touched. Shrink-only from here \u2014 the number may not grow, so a NEW gate must adopt or exempt.",
|
|
28
28
|
"falsifier": "./scripts-run src/scripts/check_gate_completeness"
|
|
29
|
+
},
|
|
30
|
+
"check_depth_budget": {
|
|
31
|
+
"count": 4,
|
|
32
|
+
"landed": "2026-08-06",
|
|
33
|
+
"note": "Four depth files exceed the 16,000-char per-file ceiling: rule-body-migration-inventory.md (23,782), design-antipatterns.md (20,707), roadmap-process-loop.md (20,360), orchestration-telemetry.md (16,155). Recorded rather than fixed because splitting four large reference documents is unrelated to the change that introduced the ceiling, and a gate that lands as four instant blockers is the shape this repository has already recorded as a failure. Shrink-only from here: a FIFTH over-ceiling file reds. roadmap-process-loop.md is the file that motivated the gate \u2014 it states 'Size budget: <= 4,000 chars' in its own header and is 5x over it, which is what a declared budget with nothing measuring it decays into. The ceiling is a GROWTH RATCHET, not a measured quality threshold: the 7,308-trajectory study behind the 3,500-token skill ceiling (ADR-217) was taken on procedural always-co-loaded skills, and this layer is declarative and loaded one or two files at a time. Replace the number when someone measures comprehension on THIS layer."
|
|
29
34
|
}
|
|
30
35
|
}
|
|
31
36
|
}
|
|
@@ -124,6 +124,7 @@ Tier 1 — power-user (release shape, audit, migration):
|
|
|
124
124
|
user-authored files; persists standing consent
|
|
125
125
|
(install.auto_converge) on first use.
|
|
126
126
|
Flags: --dry-run | --yes
|
|
127
|
+
conformance:behavior Replay local transcripts through the mechanised conformance checks
|
|
127
128
|
conformance Consumer conformance contract: doctor --ci +
|
|
128
129
|
installed-and-firing checks. Exits non-zero on
|
|
129
130
|
a failed check.
|
|
@@ -1219,6 +1220,16 @@ cmd_analyze_session() {
|
|
|
1219
1220
|
exec_ts "$PACKAGE_ROOT/src/scripts/_cli/cmd_analyze_session.ts" "$@"
|
|
1220
1221
|
}
|
|
1221
1222
|
|
|
1223
|
+
# `agent-config conformance:behavior` — replay the local transcript store
|
|
1224
|
+
# through the four MECHANISED conformance checks (language pin, git
|
|
1225
|
+
# authorization, vacuous evidence, evidence steering). Report, not gate:
|
|
1226
|
+
# exit 0 unless the store is unreadable. See src/scripts/conformance_scan.ts.
|
|
1227
|
+
cmd_conformance_behavior() {
|
|
1228
|
+
local script
|
|
1229
|
+
script="$(resolve_script "src/scripts/conformance_scan.ts" "dist/agent-src/scripts/conformance_scan.ts")"
|
|
1230
|
+
exec_ts "$script" "$@"
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1222
1233
|
# `agent-config handoff` — pick a recent session, generate a deterministic
|
|
1223
1234
|
# handoff into agents/runtime/state/handoff-context.md, optionally --launch a
|
|
1224
1235
|
# fresh host session. See scripts/_cli/cmd_handoff.ts.
|
|
@@ -1240,6 +1251,7 @@ main() {
|
|
|
1240
1251
|
graph-explain) cmd_graph_explain "$@" ;;
|
|
1241
1252
|
benchmark) cmd_benchmark "$@" ;;
|
|
1242
1253
|
code-graph) cmd_code_graph "$@" ;;
|
|
1254
|
+
conformance:behavior) cmd_conformance_behavior "$@" ;;
|
|
1243
1255
|
roadmap:progress) cmd_roadmap_progress "$@" ;;
|
|
1244
1256
|
roadmap:progress-check) cmd_roadmap_progress_check "$@" ;;
|
|
1245
1257
|
roadmap:archive) cmd_roadmap_archive "$@" ;;
|
|
@@ -111,6 +111,8 @@ function _empty_state(): StateDict {
|
|
|
111
111
|
verifications_this_session: 0,
|
|
112
112
|
last_stop_at: null,
|
|
113
113
|
verified_this_turn: false,
|
|
114
|
+
ci_saw_pending: false,
|
|
115
|
+
nonevidence_this_turn: 0,
|
|
114
116
|
checked_at: _now(),
|
|
115
117
|
};
|
|
116
118
|
}
|
|
@@ -163,7 +165,94 @@ function _extract_command(payload: StateDict): [string | null, string | null] {
|
|
|
163
165
|
}
|
|
164
166
|
|
|
165
167
|
function _is_verification(command: string): boolean {
|
|
166
|
-
|
|
168
|
+
// CI polls join the verification set here (they did not match the local
|
|
169
|
+
// runner pattern). A settled green CI run IS evidence — but only once the
|
|
170
|
+
// settle is genuine, which is what the FC-3b guard below decides. Before this
|
|
171
|
+
// change a CI poll counted for nothing at all, so nothing observed the
|
|
172
|
+
// difference between "settled" and "never started".
|
|
173
|
+
return _VERIFICATION_RE.test(command) || isCiPoll(command);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Non-vacuity guard (conformance audit 2026-08-06, failure class FC-3b).
|
|
178
|
+
*
|
|
179
|
+
* The measured failure: a CI poll landing in the gap between `git push` and
|
|
180
|
+
* GitHub registering the checks returned `0 pass / 0 fail`, so the agent's exit
|
|
181
|
+
* condition `pending == 0` was TRIVIALLY satisfied and "CI settled" was reported
|
|
182
|
+
* twice — on a run that had not started. The verification *command* ran, so the
|
|
183
|
+
* evidence gate felt satisfied. Nothing checked that its output said anything.
|
|
184
|
+
*
|
|
185
|
+
* A result set of size zero is not evidence. `∀x ∈ ∅` is vacuously true, and
|
|
186
|
+
* that is a logic error rather than a judgement call, which is why it is gated
|
|
187
|
+
* here rather than described in a rule.
|
|
188
|
+
*/
|
|
189
|
+
const _VACUOUS_PATTERNS: readonly RegExp[] = [
|
|
190
|
+
// gh pr checks / gh run — no checks registered at all.
|
|
191
|
+
/\b0\s+(?:checks?|runs?)\b/i,
|
|
192
|
+
// Test runners reporting an empty run.
|
|
193
|
+
/\bno tests? (?:ran|found|to run|were run)\b/i,
|
|
194
|
+
/\bNo test files found\b/i,
|
|
195
|
+
/\b0\s+pass(?:ed|ing)?\b[\s,|·]*\b0\s+fail(?:ed|ing|ures)?\b/i,
|
|
196
|
+
/\bTests?\s+0\s+passed\b/i,
|
|
197
|
+
/\bRan 0 tests?\b/i,
|
|
198
|
+
// Linters / scanners with an empty target set.
|
|
199
|
+
/\bno files? (?:matched|to (?:lint|check|scan)|found)\b/i,
|
|
200
|
+
/\b0\s+files?\s+(?:checked|scanned|linted)\b/i,
|
|
201
|
+
/\bnothing to check\b/i,
|
|
202
|
+
];
|
|
203
|
+
|
|
204
|
+
/** True when a verification command's output proves nothing because it covered nothing. */
|
|
205
|
+
export function isVacuousOutput(output: string): boolean {
|
|
206
|
+
const text = output.trim();
|
|
207
|
+
if (!text) {
|
|
208
|
+
// A verification command that printed nothing at all is not evidence either.
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
return _VACUOUS_PATTERNS.some((re) => re.test(text));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** Commands that poll CI state rather than produce a local result. */
|
|
215
|
+
const _CI_POLL_RE = /\bgh\s+(?:pr\s+checks|run\s+(?:watch|list|view))\b/i;
|
|
216
|
+
|
|
217
|
+
export function isCiPoll(command: string): boolean {
|
|
218
|
+
return _CI_POLL_RE.test(command);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Read a pending-check count out of a CI poll's output. Returns null when the
|
|
223
|
+
* shape is unrecognised — an unknown shape must not be read as "settled".
|
|
224
|
+
*/
|
|
225
|
+
export function pendingCount(output: string): number | null {
|
|
226
|
+
const m = /(\d+)\s+(?:checks? )?pending\b/i.exec(output) ?? /\bpending[:=]\s*(\d+)/i.exec(output);
|
|
227
|
+
if (m?.[1] !== undefined) {
|
|
228
|
+
return Number(m[1]);
|
|
229
|
+
}
|
|
230
|
+
// `gh pr checks` prints one row per check; count the in-progress markers.
|
|
231
|
+
const rows = output.match(/^\S.*\b(pending|in_progress|queued)\b/gim);
|
|
232
|
+
return rows ? rows.length : null;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Extract a tool's textual output from a post-tool payload.
|
|
237
|
+
*
|
|
238
|
+
* Returns `null` when the payload carries NO output field at all — which is not
|
|
239
|
+
* the same fact as "the command produced no output". Several platforms do not
|
|
240
|
+
* surface tool output on this event, and treating their silence as a vacuous
|
|
241
|
+
* result would turn the guard into a blanket regression that stops counting
|
|
242
|
+
* every verification everywhere. The guard only fires where it can actually
|
|
243
|
+
* read a result.
|
|
244
|
+
*/
|
|
245
|
+
function _extract_output(payload: StateDict): string | null {
|
|
246
|
+
for (const key of ["tool_response", "toolResponse", "output", "stdout", "result"]) {
|
|
247
|
+
const v = payload[key];
|
|
248
|
+
if (typeof v === "string") {
|
|
249
|
+
return v;
|
|
250
|
+
}
|
|
251
|
+
if (v !== null && typeof v === "object") {
|
|
252
|
+
return JSON.stringify(v);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return null;
|
|
167
256
|
}
|
|
168
257
|
|
|
169
258
|
function _reset_turn(state: StateDict, session_id: string): StateDict {
|
|
@@ -171,6 +260,10 @@ function _reset_turn(state: StateDict, session_id: string): StateDict {
|
|
|
171
260
|
state["turn_started_at"] = _now();
|
|
172
261
|
state["verifications_this_turn"] = 0;
|
|
173
262
|
state["verified_this_turn"] = false;
|
|
263
|
+
// FC-3b turn-scoped counters: a CI settle must be witnessed within the same
|
|
264
|
+
// turn that claims it, so the in-flight observation does not survive a turn.
|
|
265
|
+
state["ci_saw_pending"] = false;
|
|
266
|
+
state["nonevidence_this_turn"] = 0;
|
|
174
267
|
return state;
|
|
175
268
|
}
|
|
176
269
|
|
|
@@ -205,16 +298,45 @@ function _update(state: StateDict, event: string, envelope: StateDict): StateDic
|
|
|
205
298
|
} else if (event === "post_tool_use") {
|
|
206
299
|
const [tool, cmd] = _extract_command(pl);
|
|
207
300
|
if (cmd && _is_verification(cmd)) {
|
|
301
|
+
const output = _extract_output(pl);
|
|
302
|
+
// No readable output → the guard has nothing to judge, so behaviour is
|
|
303
|
+
// exactly what it was before FC-3b landed.
|
|
304
|
+
const vacuous = output !== null && isVacuousOutput(output);
|
|
305
|
+
|
|
306
|
+
// A CI poll is evidence of a SETTLE only when this turn has already seen
|
|
307
|
+
// the run in flight. Polling once and reading `pending == 0` off a run
|
|
308
|
+
// that never registered is the measured FC-3b failure. With no readable
|
|
309
|
+
// output a poll counts for nothing — which is also its pre-FC-3b
|
|
310
|
+
// behaviour, since CI polls were not in the verification set at all.
|
|
311
|
+
let counts = !vacuous;
|
|
312
|
+
if (isCiPoll(cmd)) {
|
|
313
|
+
const pending = output === null ? null : pendingCount(output);
|
|
314
|
+
if (pending !== null && pending > 0) {
|
|
315
|
+
state["ci_saw_pending"] = true;
|
|
316
|
+
counts = false; // running, not settled
|
|
317
|
+
} else if (pending === 0) {
|
|
318
|
+
counts = !vacuous && state["ci_saw_pending"] === true;
|
|
319
|
+
} else {
|
|
320
|
+
counts = false; // unrecognised or unreadable — never read as settled
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
208
324
|
state["last_verification"] = {
|
|
209
325
|
command: cmd.slice(0, 512),
|
|
210
326
|
tool,
|
|
211
327
|
at: _now(),
|
|
212
328
|
platform: (envelope["platform"] || "") as unknown,
|
|
329
|
+
vacuous,
|
|
330
|
+
counted: counts,
|
|
213
331
|
};
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
332
|
+
if (counts) {
|
|
333
|
+
state["verifications_this_turn"] = _asInt(state["verifications_this_turn"]) + 1;
|
|
334
|
+
state["verifications_this_session"] =
|
|
335
|
+
_asInt(state["verifications_this_session"]) + 1;
|
|
336
|
+
state["verified_this_turn"] = true;
|
|
337
|
+
} else {
|
|
338
|
+
state["nonevidence_this_turn"] = _asInt(state["nonevidence_this_turn"]) + 1;
|
|
339
|
+
}
|
|
218
340
|
}
|
|
219
341
|
} else if (event === "stop") {
|
|
220
342
|
state["last_stop_at"] = _now();
|