@event4u/agent-config 10.1.0 → 10.3.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.
Files changed (158) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +110 -167
  3. package/README.md +1 -1
  4. package/dist/agent-src/commands/analyze/reference-repo.md +62 -0
  5. package/dist/agent-src/commands/roadmap/create.md +4 -1
  6. package/dist/agent-src/commands/roadmap/next.md +38 -0
  7. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +22 -1
  8. package/dist/agent-src/contexts/contracts/frugality-charter.md +1 -1
  9. package/dist/agent-src/personas/advisors/first-principles.md +6 -0
  10. package/dist/agent-src/rules/active-remediation.md +53 -2
  11. package/dist/agent-src/rules/code-provenance.md +66 -4
  12. package/dist/agent-src/rules/content-quoting-floor.md +6 -0
  13. package/dist/agent-src/rules/context-hygiene.md +39 -0
  14. package/dist/agent-src/rules/design-fidelity.md +49 -3
  15. package/dist/agent-src/rules/token-budget-discipline.md +3 -2
  16. package/dist/agent-src/rules/token-efficiency.md +22 -0
  17. package/dist/agent-src/skills/ai-council/SKILL.md +28 -6
  18. package/dist/agent-src/skills/condense-memory/SKILL.md +1 -1
  19. package/dist/agent-src/skills/design-review/references/verification-automation.md +23 -1
  20. package/dist/agent-src/skills/fe-design/SKILL.md +27 -3
  21. package/dist/agent-src/skills/judge-synthesis/SKILL.md +30 -0
  22. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +11 -0
  23. package/dist/agent-src/skills/roadmap-writing/SKILL.md +9 -9
  24. package/dist/agent-src/skills/skill-writing/SKILL.md +4 -0
  25. package/dist/agent-src/skills/token-optimizer/SKILL.md +5 -1
  26. package/dist/agent-src/templates/agent-settings.md +12 -28
  27. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +2 -2
  28. package/dist/agent-src/templates/persona.md +26 -0
  29. package/dist/agent-src/templates/roadmaps.md +27 -7
  30. package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -1
  31. package/dist/agent-src/templates/skill.md +35 -1
  32. package/dist/cli/commands/commands.candidates.test.js +257 -0
  33. package/dist/cli/commands/commands.candidates.test.js.map +1 -0
  34. package/dist/cli/commands/commands.js +199 -0
  35. package/dist/cli/commands/commands.js.map +1 -1
  36. package/dist/cli/main.js +1 -0
  37. package/dist/cli/main.js.map +1 -1
  38. package/dist/cli/registry.js +2 -2
  39. package/dist/cli/registry.js.map +1 -1
  40. package/dist/cli-delegate/{chunk-3JUTT26I.js → chunk-6ENSXSBW.js} +1 -1
  41. package/dist/cli-delegate/{chunk-TVGXH7VA.js → chunk-6LOPHJLD.js} +1 -1
  42. package/dist/cli-delegate/{chunk-XT2YTJCZ.js → chunk-AYKQGIBG.js} +4 -0
  43. package/dist/cli-delegate/{chunk-HJSKTMIF.js → chunk-BV3WR67D.js} +3 -19
  44. package/dist/cli-delegate/{chunk-HTIU3W56.js → chunk-BWMXLD4B.js} +6 -2
  45. package/dist/cli-delegate/{chunk-2H5SE7DU.js → chunk-FV34EGEX.js} +166 -39
  46. package/dist/cli-delegate/{chunk-XTC5ARB6.js → chunk-IR3IVRVC.js} +7 -2
  47. package/dist/cli-delegate/{chunk-LRXJK6GN.js → chunk-JMQZ7MM5.js} +1 -1
  48. package/dist/cli-delegate/{chunk-NX5AXSLD.js → chunk-X3VOARZD.js} +3 -3
  49. package/dist/cli-delegate/cmd_analyze_session.js +1 -1
  50. package/dist/cli-delegate/cmd_brand_status.js +1 -1
  51. package/dist/cli-delegate/cmd_conformance.js +881 -204
  52. package/dist/cli-delegate/cmd_doctor.js +3 -3
  53. package/dist/cli-delegate/cmd_explain.js +2 -2
  54. package/dist/cli-delegate/cmd_export.js +4 -4
  55. package/dist/cli-delegate/cmd_handoff.js +6 -5
  56. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  57. package/dist/cli-delegate/cmd_migrate.js +2 -2
  58. package/dist/cli-delegate/cmd_packs_active.js +2 -2
  59. package/dist/cli-delegate/cmd_prune.js +4 -4
  60. package/dist/cli-delegate/cmd_route_audit.js +2 -2
  61. package/dist/cli-delegate/cmd_route_explain.js +1 -1
  62. package/dist/cli-delegate/cmd_session_recycle.js +44 -9
  63. package/dist/cli-delegate/cmd_settings_get.js +2 -2
  64. package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
  65. package/dist/cli-delegate/cmd_settings_set.js +2 -2
  66. package/dist/cli-delegate/cmd_sync.js +4 -4
  67. package/dist/cli-delegate/cmd_uninstall.js +4 -4
  68. package/dist/cli-delegate/cmd_update.js +1 -1
  69. package/dist/cli-delegate/cmd_upgrade.js +1 -1
  70. package/dist/cli-delegate/cmd_validate.js +4 -4
  71. package/dist/cli-delegate/cmd_versions.js +1 -1
  72. package/dist/discovery/deprecation-report.md +1 -1
  73. package/dist/discovery/discovery-manifest.json +21 -21
  74. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  75. package/dist/discovery/discovery-manifest.summary.md +1 -1
  76. package/dist/discovery/dormancy-report.md +1 -1
  77. package/dist/discovery/orphan-report.md +1 -1
  78. package/dist/discovery/packs.json +2 -2
  79. package/dist/discovery/trust-report.md +1 -1
  80. package/dist/discovery/workspaces.json +2 -2
  81. package/dist/hooks/dispatch.js +204 -44
  82. package/dist/install/install.mjs +9 -21
  83. package/dist/mcp/registry-manifest.json +2 -2
  84. package/dist/mcp/server.json +2 -2
  85. package/dist/mcp/server.mjs +1337 -490
  86. package/dist/router.json +1 -1
  87. package/dist/scripts/_lib/agent_settings.js +25 -2
  88. package/dist/scripts/_lib/agent_settings.js.map +1 -1
  89. package/dist/scripts/_lib/compile_time_toggles.js +4 -3
  90. package/dist/scripts/_lib/compile_time_toggles.js.map +1 -1
  91. package/dist/server/io/yamlIO.js +0 -2
  92. package/dist/server/io/yamlIO.js.map +1 -1
  93. package/dist/server/schemas/settings.js +3 -9
  94. package/dist/server/schemas/settings.js.map +1 -1
  95. package/dist/shared/settingsClasses.js +64 -2
  96. package/dist/shared/settingsClasses.js.map +1 -1
  97. package/dist/ui/assets/{index-B5qGYOJo.js → index-5fXOHoVh.js} +2 -2
  98. package/dist/ui/assets/index-5fXOHoVh.js.map +1 -0
  99. package/dist/ui/index.html +1 -1
  100. package/docs/contracts/settings-classes.md +307 -145
  101. package/docs/guidelines/agent-infra/active-remediation-mechanics.md +54 -0
  102. package/docs/guidelines/agent-infra/layered-settings.md +1 -2
  103. package/docs/guidelines/agent-infra/symptom-driven-harvest-loop.md +104 -0
  104. package/docs/guidelines/design-antipatterns.md +79 -10
  105. package/docs/guidelines/design-fidelity-mechanics.md +120 -2
  106. package/package.json +1 -1
  107. package/src/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -1
  108. package/src/config/agent-settings.template.yml +12 -30
  109. package/src/config/gate-coverage.yml +42 -8
  110. package/src/config/gate-violation-baselines.json +15 -3
  111. package/src/config/profiles/balanced.ini +0 -2
  112. package/src/config/profiles/full.ini +1 -3
  113. package/src/config/profiles/minimal.ini +0 -2
  114. package/src/config/review-prompt-binding-baseline.json +19 -0
  115. package/src/config/rule-enforcement-baseline.json +0 -1
  116. package/src/scripts/_cli/cmd_session_recycle.ts +66 -9
  117. package/src/scripts/_cli/handoff_sessions.ts +3 -2
  118. package/src/scripts/_dispatch.bash +1 -0
  119. package/src/scripts/_lib/agent_settings.ts +25 -2
  120. package/src/scripts/_lib/bench_telegraph.ts +1 -1
  121. package/src/scripts/_lib/cc_transcript.ts +25 -0
  122. package/src/scripts/_lib/compile_time_toggles.ts +4 -3
  123. package/src/scripts/ai_council/clients.ts +243 -34
  124. package/src/scripts/cache_realization_report.ts +3 -2
  125. package/src/scripts/check_ci_local_parity.ts +60 -6
  126. package/src/scripts/check_review_prompt_binding.ts +553 -0
  127. package/src/scripts/check_rule_projection_integrity.ts +3 -1
  128. package/src/scripts/check_suppression_hygiene.ts +19 -3
  129. package/src/scripts/conformance_scan.ts +282 -9
  130. package/src/scripts/cost/track.mjs +10 -4
  131. package/src/scripts/council_cli.ts +33 -3
  132. package/src/scripts/design_slop_rules.test.ts +37 -6
  133. package/src/scripts/design_slop_rules.ts +150 -22
  134. package/src/scripts/dispatch_r2_reviewer.ts +15 -1
  135. package/src/scripts/external_sources_denylist.json +3 -1
  136. package/src/scripts/hook_manifest.yaml +17 -6
  137. package/src/scripts/hooks/block_unauthorized_git.ts +54 -8
  138. package/src/scripts/hooks/delegation_nudge_hook.ts +33 -8
  139. package/src/scripts/hooks/evidence_independence.ts +61 -9
  140. package/src/scripts/hooks/session_eol_hook.ts +123 -3
  141. package/src/scripts/hooks/turn_end_gate_hook.ts +31 -0
  142. package/src/scripts/hooks/ui_route_nudge_hook.ts +55 -2
  143. package/src/scripts/lint_design_antipattern_parity.ts +201 -0
  144. package/src/scripts/lint_harvest_provenance.ts +483 -0
  145. package/src/scripts/lint_settings_classes.ts +273 -11
  146. package/src/scripts/lint_skill_router_head.ts +254 -0
  147. package/src/scripts/lint_symptom_intake.ts +241 -0
  148. package/src/scripts/report_consultation_rate.ts +128 -2
  149. package/src/scripts/report_skill_activation.ts +6 -4
  150. package/src/scripts/report_skill_obligation_violations.ts +2 -1
  151. package/src/scripts/run_skill_evals.ts +10 -5
  152. package/src/scripts/schemas/persona.schema.json +8 -0
  153. package/src/scripts/schemas/provenance-harvest.schema.json +39 -0
  154. package/src/scripts/sweep_dead_scan_roots.ts +51 -0
  155. package/src/server/io/yamlIO.ts +0 -2
  156. package/src/server/schemas/settings.ts +3 -19
  157. package/src/shared/settingsClasses.ts +93 -2
  158. package/dist/ui/assets/index-B5qGYOJo.js.map +0 -1
@@ -22,10 +22,64 @@ Under those constraints the fix is auditable in the same diff and is *not* scope
22
22
 
23
23
  Bigger, or diverges from the task → do **not** refactor inline, do **not** interrupt the flow. Note the site (file:line + the issue). Surface the batch as **one** numbered-options prompt (per `user-interaction`, one recommendation line) **after the task is delivered** — or mid-work only when the flow makes it natural. Each option must carry a real trade-off (`no-cheap-questions`). Refactor only on an explicit yes, as a separate scoped change (`scope-control`, `downstream-changes`).
24
24
 
25
+ #### Option anatomy — a pickable fix, not a yes/no
26
+
27
+ The user should be able to answer with one number and get a change they can predict. Each numbered option therefore names four things, in a line or two:
28
+
29
+ 1. **What changes** — the concrete edit, in the vocabulary of the code ("replace the three `array()` literals with `[]`", not "clean up the file").
30
+ 2. **Where** — file, or the group of files if the option covers a batch.
31
+ 3. **How large** — line count or an honest size class, so the user can weigh it without opening the diff.
32
+ 4. **What it costs** — the risk, the review burden, or the reason it was not simply done inline.
33
+
34
+ Group findings by **fix shape**, never one option per finding: seven lint errors that are three `no-unused-vars`, three `prefer-const` and one genuine type hole are three options, not seven. The final option is always an explicit **leave it as is** — its absence is what turns a menu into pressure. One recommendation line under the block names your pick (`user-interaction` Iron Law 1).
35
+
36
+ #### Carry-over — undecided is not finished
37
+
38
+ An item the user has not answered stays live: raise it once more at the next natural task boundary, in the same batched form. Two bounds keep that from becoming nagging:
39
+
40
+ - **A decline is terminal.** An explicit "leave it" / "ignore" closes the item for the task; re-raising it is the re-ask `scope-control` § Decline = silence forbids.
41
+ - **Once per boundary, not once per reply.** The batch is a task-close artifact. Repeating it between steps is the continuation prompt `no-cheap-questions` Iron Law 4 forbids.
42
+
25
43
  ### Propose a follow-up PR (many spots)
26
44
 
27
45
  When the issues are too many to fold in without blowing the current diff's scope, propose **one or more separate follow-up PRs** (or a roadmap under `agents/roadmaps/`, using the shared-prefix convention) so the user reviews the changes before merge. Creating the PR/roadmap is **permission-gated** — propose, get a yes, then create (`scope-control`, `commit-policy`).
28
46
 
47
+ ## Observed failing checks — classifying the red you already have
48
+
49
+ The rule puts a check result you have already seen into the same ladder as a defect you read in a file. Running a command, reading seven errors, and walking past them is not scoping the work — it is looking away.
50
+
51
+ The rule's two bounds, in full:
52
+
53
+ - **Only output you already have.** The clause never obliges a check run; it fires on a result already in front of you. What runs locally stays the user's call — this package records "no proactive quality tools, remote CI gates only" as a standing preference — and the remote CI remains the authoritative gate. An obligation to *hunt* for red would contradict that outright; an obligation not to walk past red you already read does not.
54
+ - **Ownership picks the tier, never the silence.** Caused by your diff → it is the task. Pre-existing and inside the fix-now bar → fix it. Pre-existing and wider, or many, or unrelated → note + ask, or a follow-up PR. There is no seventh option called "mention it in the closing summary" — that line reads as a status report and closes nothing.
55
+
56
+ Classification is the whole of the work, and it runs on two axes:
57
+
58
+ | | Inside the fix-now bar | Outside it |
59
+ |---|---|---|
60
+ | **Caused by this diff** | Fix it — it is the task, not remediation. | Fix it; a diff you cannot make green is not deliverable. Blocked → surface it as a blocker, never as a caveat. |
61
+ | **Pre-existing** | Fix it with the work, and say in the commit body that it was pre-existing. | Note + ask with candidate fixes, or a follow-up PR when the batch is large. |
62
+
63
+ Two failure shapes this table exists to name:
64
+
65
+ - **"Not mine, so not mentioned."** Pre-existing red is the most common thing an agent walks past, because `minimal-safe-diff` reads like permission to ignore it. It is not: that rule bounds the *diff*, this one bounds the *silence*. The two are satisfied together by noting the finding and asking, which changes no line of code.
66
+ - **"Mine, so quietly worked around."** A gate that goes green because the check was narrowed, an assertion loosened, or a file excluded is a defect with a green light on top. Route it through the ladder as an issue, and say what was narrowed.
67
+
68
+ ### Worked example — a red gate seen mid-task
69
+
70
+ > `task check` fails; the lint step reports 7 errors, all pre-existing on `main`, in files this branch does not touch.
71
+
72
+ Wrong, and the canonical shape of it: finish the task, and close with *"the only thing still open is the lint finding — 7 errors on main, which makes `task check` unusable as a chain"*. The sentence is accurate, the issue is named, and nothing about it is decided — the next session inherits it verbatim.
73
+
74
+ Right: the errors are pre-existing, outside the fix-now bar (unrelated files, more than ~10 lines), so they are **note + ask** — after the task is delivered, one block:
75
+
76
+ 1. Fix the 3 `no-unused-vars` in `src/a.ts`, `src/b.ts` — ~6 lines, mechanical, ships in this PR.
77
+ 2. Fix all 7 in a separate follow-up PR — keeps this diff single-purpose; needs a branch (permission-gated).
78
+ 3. Suppress the two in generated output with a scoped ignore, fix the rest — smallest green path, adds a suppression to review.
79
+ 4. Leave as is — `task check` stays unusable as a chain until someone else picks it up.
80
+
81
+ One recommendation line names the pick. Whatever the user answers, the item is closed. If they answer nothing, it is raised once at the next task boundary — not carried silently into a third session.
82
+
29
83
  ## Version-gated modernization
30
84
 
31
85
  Update stale idioms to the version the project **actually runs** — but only when that version is **verified**:
@@ -18,7 +18,7 @@ on user request.
18
18
  | File | Git | Scope | Owner | Example values |
19
19
  |---|---|---|---|---|
20
20
  | `.agent-project-settings.yml` | **committed** | team / repo | lead maintainer | `project.stack`, `quality.php.tools`, `memory.dogfood` |
21
- | `~/.event4u/agent-config/agent-settings.yml` | **n/a** (outside repo) | individual developer · cross-project | individual | `name`, `ide`, `rule_loading_tier`, `personal.bot_icon`, `personal.autonomy`, `telegraph.speak_scope` (legacy `~/.config/agent-config/agent-settings.yml` read as fallback) |
21
+ | `~/.event4u/agent-config/agent-settings.yml` | **n/a** (outside repo) | individual developer · cross-project | individual | `name`, `ide`, `rule_loading_tier`, `personal.bot_icon`, `personal.autonomy`, `memory.cadence` (legacy `~/.config/agent-config/agent-settings.yml` read as fallback) |
22
22
  | `agents/settings/.agent-settings.yml` | **gitignored** | individual developer · this project | individual | `personal.ide`, `personal.user_name`, `subagents.max_parallel`, `onboarding.onboarded` |
23
23
 
24
24
  > **Canonical location (ADR-038):** the developer file lives in the settings
@@ -61,7 +61,6 @@ ide
61
61
  rule_loading_tier
62
62
  personal.bot_icon
63
63
  personal.autonomy
64
- telegraph.speak_scope
65
64
  ```
66
65
 
67
66
  Loader contract:
@@ -0,0 +1,104 @@
1
+ # Symptom-driven harvest loop
2
+
3
+ > The procedure that turns an **operator's production symptom** into a roadmap
4
+ > this repository can execute. It is the inverse of the source-driven harvest:
5
+ > that one starts from external material pushed onto the repo and asks what is
6
+ > worth adopting; this one starts from a failure someone hit in production and
7
+ > pulls external material in **per confirmed defect**.
8
+ >
9
+ > Body of `road-to-symptom-driven-harvest-loop` Phase 2. It lives here rather
10
+ > than inline in [`roadmap-writing`](../../../src/skills/roadmap-writing/SKILL.md)
11
+ > because that skill is already ~4.8k tokens — well past the 3,500-token band —
12
+ > and a procedure needed a few times a quarter should not be paid for on every
13
+ > roadmap-authoring turn. The skill carries the pointer.
14
+
15
+ ## When this applies
16
+
17
+ An operator reports a failure in their own words — "runs never end", "the agent
18
+ screenshots instead of reading the code" — rather than a defect with a file and
19
+ a line. File it first under [`agents/tickets/symptoms/`](../../../agents/tickets/symptoms/README.md);
20
+ that entry is what this loop resolves.
21
+
22
+ Not this loop: a defect already traced to a file (that is a roadmap item), a
23
+ feature request (roadmap or ticket), or external material arriving unprompted
24
+ (the source-driven harvest family).
25
+
26
+ ## The four steps
27
+
28
+ **1. Confirm against the live tree, at a pinned commit, before any external
29
+ search.** One `file:line` per claim, and the pin recorded next to it. The
30
+ ordering is the load-bearing part: searching externally first produces a plan
31
+ about the ecosystem's problems rather than this tree's, and every subsequent
32
+ round inherits that frame. A symptom that does not reproduce as a confirmed
33
+ defect gets a `null:` block and stops here — that is a result.
34
+
35
+ **2. Triangulate externally, per confirmed defect, never additively.** For each
36
+ defect, and only for each defect: the host tool's own issue tracker, its official
37
+ docs **fetched fresh**, and practitioner reports. Inverted form throughout — the
38
+ defect is the anchor, the source is drawn in to explain or bound it. A source
39
+ that matches no confirmed defect is not evidence for this roadmap; note it and
40
+ drop it.
41
+
42
+ **3. Iterate at least two further rounds, each stating its delta.** A round that
43
+ changes nothing ends the loop early and says so. This is the step that is
44
+ skipped under time pressure and the step that pays: on the first run of this
45
+ loop, round 2 refuted a standing repo blocker from the official payload spec,
46
+ imported a constraint that reshaped a whole phase from "block on invalid" to
47
+ "command-hook, disk-fallback, block-once", and round 3 found a reopen-clause
48
+ deadlock that was the *only* argument for reopening cancelled work at all. A
49
+ one-pass version would have shipped a roadmap re-proposing cancelled items with
50
+ no reopening argument and a mechanism the host would have broken.
51
+
52
+ **4. Emit with a symptom→defect map and per-phase falsifiers.** The map is the
53
+ artifact the operator can read: their words in one column, confirmed defects with
54
+ anchors in the next, owning phase in the third. Every phase carries the
55
+ measurement that would delete it.
56
+
57
+ ## Step 5, added by the first three runs: re-verify at adoption
58
+
59
+ A roadmap drafted at a pin and adopted later is a **snapshot of an opinion about
60
+ a tree that has since moved**. Before adopting, re-verify every repo claim at the
61
+ current tip and record the deltas.
62
+
63
+ This is not ceremony. Adopting the first three runs of this loop, 81 commits
64
+ past their shared pin, re-verification found 32 of 36 claims still true — and:
65
+
66
+ - one defect had **fixed itself** (a function measured as having zero production
67
+ callers had acquired one), which deleted a roadmap step before anyone built it;
68
+ - one claim was **wrong at the pin too** (a count stated as six where the tree
69
+ binds seven), which no amount of re-reading the draft would have surfaced;
70
+ - three anchors had **drifted** to new line numbers while their content held;
71
+ - one cross-cutting conflict was invisible until two drafts were read together
72
+ (a proposed "adopt the artifact's code" duty against an existing
73
+ `NEVER ADOPT EXTERNAL CODE VERBATIM` Iron Law).
74
+
75
+ The cheapest of those to find was the already-fixed one, and it was worth the
76
+ most: an item prevented costs nothing to maintain.
77
+
78
+ ## Worked example — why round 2 is mandatory
79
+
80
+ `hook_manifest.yaml` carried a comment stating that in-process subagents "inherit
81
+ the host process env and cannot be marked per-spawn", and that comment had stood
82
+ for months as a recorded blocker on a whole design axis. It was true about the
83
+ mechanism it named — the env var — and false about the conclusion.
84
+
85
+ Round 2 fetched the host's current payload specification, which states that tool
86
+ events inside a subagent carry `agent_id` and `agent_type` precisely so
87
+ subagent calls can be distinguished from main-thread ones. The env cannot mark a
88
+ spawn; the payload already did. One fetch refuted a months-old blocker, and the
89
+ axis it had closed reopened.
90
+
91
+ The general shape: **a repo comment records what was tried, not what is
92
+ possible.** Round 1 finds the comment and believes it, because it is this tree's
93
+ own evidence. Only an external round can date it.
94
+
95
+ ## See also
96
+
97
+ - [`roadmap-writing`](../../../src/skills/roadmap-writing/SKILL.md) — the authoring
98
+ skill this procedure extends; it owns phases, falsifiers, and the output format.
99
+ - [`agents/tickets/symptoms/README.md`](../../../agents/tickets/symptoms/README.md) —
100
+ the intake convention and the two resolution blocks.
101
+ - [`source-discovery-gate`](../../../src/rules/source-discovery-gate.md) — the
102
+ no-structural-claim-without-evidence rule step 1 is an application of.
103
+ - [`external-reference-deep-dive`](../../../src/rules/external-reference-deep-dive.md) —
104
+ how to read a named external source properly in step 2.
@@ -36,16 +36,17 @@ The stack-specific bans live in the apply skills and link back here by entry ID.
36
36
  The objective floors are cited from the linter, never re-eyeballed by an agent.
37
37
 
38
38
  **Deterministic detector backing** (`lint_design_slop`, dependency-free, zero
39
- runtime token cost): a pattern-detectable subset of these entries now has a
40
- deterministic rule that `design-review` cites instead of re-deriving — `V1`,
41
- `V3`, `V6`, `C2`, `C5`, `T4`, `T6`, `T7`, `L4`, `L8`, `M2`, `M4`, `CP1`, `CP2`,
42
- `CP5`, plus the **Consistency Locks & layout caps** `V8`, `C6`, `L9`, `L10`
43
- (rule ids `slop-<id>-*`, registry in `src/scripts/design_slop_rules.ts`). These
44
- are **flags / rebuttable presumptions**, never hard blocks — a consumer
45
- `DESIGN.md` that declares the pattern as intentional suppresses the flag. The
46
- entries needing structural or aesthetic judgment (e.g. `T3` icon-tile stack,
47
- `L2` three-identical-card grid, `V2` glassmorphism intent, `C7` theme-inversion)
48
- stay agent-judgment-only and are deliberately **not** in the detector.
39
+ runtime token cost): a pattern-detectable subset of these entries has a
40
+ deterministic rule that `design-review` cites instead of re-deriving (rule ids
41
+ `slop-<id>-*`, registry in `src/scripts/design_slop_rules.ts`). These are
42
+ **flags / rebuttable presumptions**, never hard blocks — a consumer `DESIGN.md`
43
+ that declares the pattern as intentional suppresses the flag.
44
+
45
+ Which entries those are is **not** enumerated here. The enumeration lives in
46
+ [§ Detector status](#detector-status) below, where every entry carries exactly
47
+ one status and `lint_design_antipattern_parity` checks the `backed` rows against
48
+ the registry on every run. A second hand-maintained list in this paragraph is
49
+ precisely the drift the gate exists to prevent, so there is only one.
49
50
 
50
51
  ## Current-generation tells (generation-dated — review 2026-Q4)
51
52
 
@@ -195,6 +196,74 @@ possible but deferred until a real incident.
195
196
 
196
197
  ---
197
198
 
199
+ ## Detector status
200
+
201
+ Every catalog entry above carries exactly one status. This table is the single
202
+ enumeration of what the deterministic detector covers, and
203
+ `src/scripts/lint_design_antipattern_parity.ts` checks it on every CI run: a
204
+ `backed` row whose id is not in the registry fails, a registry rule whose
205
+ `catalogId` is not `backed` here fails, and an entry missing from this table
206
+ fails. `Q*` floors are excluded — they are owned by `lint_design_quality` and
207
+ are listed in § Quality floors.
208
+
209
+ | Status | Meaning |
210
+ |---|---|
211
+ | `backed` | a deterministic rule exists in `design_slop_rules.ts` |
212
+ | `floor` | measurable and enforced, but as a `Q*` objective floor in `lint_design_quality`, not as an aesthetic tell |
213
+ | `judgment-only` | needs structural or aesthetic judgment a text pass cannot make; `design-review` decides it |
214
+ | `deferred` | pattern-detectable but a design-system opinion rather than a floor; deliberately not shipped |
215
+ | `candidate` | a numeric threshold stated in the entry, not yet detected — a status that must resolve to `backed` or `judgment-only`, never persist |
216
+
217
+ | Entry | Status | Note |
218
+ |---|---|---|
219
+ | V1 | backed | |
220
+ | V2 | judgment-only | decoration-vs-intent is the tell; a text pass cannot read intent |
221
+ | V3 | backed | |
222
+ | V4 | backed | |
223
+ | V5 | judgment-only | icon register collision is a visual-style comparison |
224
+ | V6 | backed | |
225
+ | V7 | judgment-only | DOM-structure nesting depth, measured too false-positive-prone |
226
+ | V8 | backed | |
227
+ | C1 | judgment-only | the tell is the combination *as the primary scheme*; which colours are primary is a judgment |
228
+ | C2 | backed | |
229
+ | C3 | backed | |
230
+ | C4 | floor | WCAG contrast, Q1 |
231
+ | C5 | backed | |
232
+ | C6 | judgment-only | demoted 2026-08-13 at M1 = 4 of 32 clean files; the rule counted every saturated hue, so one accent plus a semantic danger colour reached its threshold — which is correct design, not the tell this entry describes |
233
+ | C7 | judgment-only | theme inversion may be deliberate emphasis |
234
+ | T1 | judgment-only | requires comparing optical weight across the document |
235
+ | T2 | judgment-only | requires knowing which element is the hero |
236
+ | T3 | judgment-only | icon-tile stack; DOM-structure analysis, too false-positive-prone |
237
+ | T4 | backed | |
238
+ | T5 | judgment-only | copy phrase-list; that mechanism is council-rejected |
239
+ | T6 | backed | |
240
+ | T7 | backed | |
241
+ | T8 | deferred | typeface count is a design-system opinion, not a floor |
242
+ | T9 | backed | |
243
+ | T10 | backed | |
244
+ | L1 | judgment-only | composite structural template |
245
+ | L2 | judgment-only | three-identical-card grid; DOM-structure analysis |
246
+ | L3 | deferred | spacing-multiple uniformity is a design-system opinion |
247
+ | L4 | backed | |
248
+ | L5 | floor | line length, Q3 |
249
+ | L6 | judgment-only | requires an ancestor relation a flat text pass cannot establish |
250
+ | L7 | judgment-only | requires a render |
251
+ | L8 | backed | |
252
+ | L9 | backed | |
253
+ | L10 | backed | |
254
+ | M1 | backed | |
255
+ | M2 | backed | |
256
+ | M3 | backed | |
257
+ | M4 | backed | |
258
+ | M5 | floor | reduced-motion alternative, Q4 |
259
+ | CP1 | backed | |
260
+ | CP2 | backed | |
261
+ | CP3 | judgment-only | copy phrase-list; that mechanism is council-rejected |
262
+ | CP4 | judgment-only | copy phrase-list; that mechanism is council-rejected |
263
+ | CP5 | backed | |
264
+
265
+ ---
266
+
198
267
  ## The AI-slop originality self-test
199
268
 
200
269
  Before finalizing any UI design, run this two-tier check:
@@ -4,6 +4,102 @@
4
4
 
5
5
  _Origin: migrated from `src/rules/design-fidelity.md` per the P4 pattern of `road-to-kernel-and-router.md`. The Iron Law, the `design.fidelity_mode` strictness table, and the fire/not-fire scope stay in the rule; this file carries the illustrative depth._
6
6
 
7
+ ## Data-basis ladder
8
+
9
+ ```
10
+ WHENEVER SOURCE IS REACHABLE, THE SOURCE IS THE DATA BASIS.
11
+ A SCREENSHOT IS VALIDATION, NEVER THE INPUT YOU BUILD FROM,
12
+ WHILE ANY HIGHER RUNG IS REACHABLE.
13
+ ```
14
+
15
+ Four rungs, highest first. Take the highest one you can reach; a lower rung is
16
+ a fallback you name, not a preference you exercise.
17
+
18
+ | # | Rung | What it is | When it is the right rung |
19
+ |---|---|---|---|
20
+ | 1 | **Provided source files** | The artifact itself — an archive, an attached `design.html`, a token sidecar, a repo the user pointed at | Whenever the user handed something over. Read it *before* the first write. |
21
+ | 2 | **Source read through any channel** | The same code reached indirectly — a repository read, or DOM / stylesheets / scripts pulled through the user's own connected browser tools | The artifact is live rather than attached (a URL, a staging page, a preview build) |
22
+ | 3 | **Structured snapshot** | An accessibility tree or equivalent structured dump — text, roles, hierarchy, no pixels | Source is genuinely unreachable, but structure is not |
23
+ | 4 | **Screenshot** | Rendered pixels | Nothing above is reachable, **or** the thing being checked only exists once rendered |
24
+
25
+ **What rung 4 is legitimately for**, and this is not a grudging exception:
26
+ visual validation after building, layout collisions, contrast as actually
27
+ rendered, and content that only exists dynamically. The failure this ladder
28
+ names is not *using* a screenshot — it is using one **as the data basis while
29
+ rung 1 or 2 was sitting right there**, which is how a port ends up with the
30
+ right colours and none of the behaviour.
31
+
32
+ **The ladder governs where data comes from, never whether defects may be
33
+ fixed.** Reading the source and improving it is allowed and often correct;
34
+ reading the source is what makes an improvement a decision rather than a guess.
35
+
36
+ Two consequences worth stating because they are the ones agents get backwards:
37
+
38
+ - **A rendered HTML file is still a code artifact.** Opening it in a browser
39
+ does not demote it to rung 4; the file is still rung 1. What the browser adds
40
+ is validation, not input.
41
+ - **Degrading is honest, silence is not.** When you build from rung 3 or 4, say
42
+ which rung you used and why the higher ones were unreachable. An unscoped
43
+ "matches the design" over a screenshot-derived build is a verdict without
44
+ evidence (`design-review` § verdict scoping).
45
+
46
+ Regression witness: `daf-source-over-screenshot`.
47
+
48
+ ## Adopt the code — re-derivation is a deviation
49
+
50
+ Where the artifact's own markup, CSS, or JS is stack-compatible, **adapting that
51
+ code is the default**. Writing an equivalent from scratch is a **deviation** and
52
+ carries the same obligation as a swapped control: surface it, get confirmation,
53
+ do not just do it.
54
+
55
+ Stack translation is not re-derivation. Porting the artifact's structure into
56
+ Blade, JSX or a template language translates *that* structure — it does not
57
+ license a new one. If your output's element tree cannot be walked next to the
58
+ artifact's, you re-derived.
59
+
60
+ Why this needs saying at all: the visible half of a port (colours, type,
61
+ spacing) is what a reviewer checks, and it survives a from-scratch rewrite. The
62
+ half that does not survive is the behaviour — event handlers, keyframes, ARIA
63
+ wiring, focus order — and its absence is invisible in a screenshot comparison.
64
+ "HTML not adopted, worse markup written from scratch, missing JavaScript" is one
65
+ failure, not three.
66
+
67
+ ### The scope line — where `code-provenance` ends and this begins
68
+
69
+ ```
70
+ A USER-SUPPLIED DESIGN ARTIFACT IS THE USER'S OWN MATERIAL, NOT THIRD-PARTY
71
+ EXTERNAL CODE. ADOPTING IT IS NOT A BORROW.
72
+ THIRD-PARTY CODE THAT MERELY ARRIVES THROUGH A HANDOVER STAYS UNDER
73
+ `code-provenance` IN FULL.
74
+ ```
75
+
76
+ Without this line the two rules contradict each other on the same act:
77
+ [`code-provenance`](../../src/rules/code-provenance.md) opens with `NEVER ADOPT
78
+ EXTERNAL CODE VERBATIM` and routes any conscious borrow through a licence check
79
+ plus a ledger entry, while the duty above says adapt the artifact's code.
80
+ Whichever the agent followed, it would be violating a rule, and no gate can
81
+ arbitrate between two Iron Laws.
82
+
83
+ The resolution weakens neither, and it is not new: it is the carve-out
84
+ [`content-quoting-floor`](../../src/rules/content-quoting-floor.md) already
85
+ makes for user-owned text — *"content the user wrote, pasted, or explicitly
86
+ authorized for verbatim use is not an external source"*. A design artifact the
87
+ user hands over is that same category, in markup.
88
+
89
+ **What stays under `code-provenance` in full**, so the carve-out cannot be read
90
+ as a hole:
91
+
92
+ - A vendored component, a licensed template, or a third-party library that
93
+ happens to be *inside* the handover. Arriving through a design handover
94
+ changes nothing about its licence.
95
+ - Code the artifact itself borrowed from somewhere identifiable.
96
+ - Anything you reach for *beyond* the artifact while implementing it.
97
+
98
+ The discriminator is authorship, not delivery: did the user hand you their own
99
+ material, or did they hand you a container with someone else's material in it?
100
+
101
+ Regression witness: `daf-rederive-is-deviation`.
102
+
7
103
  ## Surgical visual edits
8
104
 
9
105
  A request to change one visual thing — a colour, a label, a single element — is
@@ -64,7 +160,8 @@ brand evidence**. The design-surface instance of the no-invented-facts floor.
64
160
  ## Provided-artifact precedence
65
161
 
66
162
  ```
67
- PROVIDED ARTIFACT > ANTI-SLOP > HOUSE TASTE.
163
+ PROVIDED ARTIFACT > ANTI-SLOP > HOUSE TASTE
164
+ > ANY GENERATIVE DESIGN-SYSTEM TOOLING, FIRST- OR THIRD-PARTY.
68
165
  THE EXEMPTION COVERS ONLY DECISIONS THE ARTIFACT ACTUALLY COVERS.
69
166
  IT NEVER COVERS GENERATIVE WORK IN THE SAME RUN.
70
167
  ```
@@ -94,6 +191,23 @@ nothing acts on them.
94
191
  the consumer's own brand (`brand-source-of-truth`). Artifact-vs-brand
95
192
  conflicts are surfaced, never merged.
96
193
 
194
+ ### The precedence chain's fourth member, and why it is not obvious
195
+
196
+ A generative design-system
197
+ skill — this suite's own or a third party's installed beside it — can carry an
198
+ instruction of the shape *"always generate a design system first"*. On a
199
+ greenfield brief that is right. On a **port** it is the same error the anti-slop
200
+ catalog makes: it argues the agent out of a decision the user already made, and
201
+ it does so from a step that runs *before* the artifact is even read, so nothing
202
+ downstream ever gets the chance to override it. A generative step's output may
203
+ inform decisions the artifact leaves open — states it never showed, a breakpoint
204
+ it never specified — and nothing more. It never re-opens a decision the artifact
205
+ carries.
206
+
207
+ This is a precedence clause, not a ban: the generative tooling stays correct
208
+ where it was already correct. What it loses is the authority to run *instead of*
209
+ reading a supplied artifact.
210
+
97
211
  **The mechanical half.** A review finding carries `artifact_covered: true`, and
98
212
  the polish gate drops those from the round-driving set *before* the ceiling
99
213
  check, so a port cannot burn its two rounds on findings it was never allowed to
@@ -125,7 +239,11 @@ labelled "not wired yet" note beats an invented redesign.
125
239
 
126
240
  Behavioral baseline: the `daf-*` fixtures named above (edit preservation,
127
241
  unwanted variations, redesign trigger, missing asset, external asset URL,
128
- invented screenshot).
242
+ invented screenshot), plus the port family this guideline governs —
243
+ `daf-source-over-screenshot` (data basis), `daf-adhoc-port-coverage` (loss
244
+ reporting outside the engine), `daf-rederive-is-deviation` (adopt the code),
245
+ and `daf-handoff-bundle`, the bundle shape where a token sidecar makes
246
+ "honoured the contract" and "eyeballed the CSS" produce different artefacts.
129
247
 
130
248
  ## See also
131
249
 
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": "10.1.0",
4
+ "version": "10.3.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,
@@ -210,7 +210,6 @@ export const MERGEABLE_KEYS: readonly string[] = [
210
210
  'memory.cadence',
211
211
  'personal.bot_icon',
212
212
  'personal.autonomy',
213
- 'telegraph.speak_scope',
214
213
  // Knowledge-card global cross-project sharing is a USER-GLOBAL setting
215
214
  // (ADR-100 / road-to-structure-grounding-v2). Whitelisted so the
216
215
  // ~/.event4u/agent-config/agent-settings.yml values are honoured.
@@ -166,33 +166,25 @@ lean_projection:
166
166
 
167
167
  # --- Telegraph condensation (output-side) ---
168
168
  #
169
- # speak_scope: off | prose_only | aggressive (QUOTE the value — bare `off` is a
170
- # YAML 1.1 boolean, not the string)
171
- #
172
- # `off` is the shipped default per docs/adrs/telegraph/0001-default-off-until-bench.md
173
- # (Status: accepted) and docs/contracts/condensation-default-kill-criterion.md.
169
+ # `speak: false` is the shipped default per
170
+ # docs/adrs/telegraph/0001-default-off-until-bench.md (Status: accepted) and
171
+ # docs/contracts/condensation-default-kill-criterion.md.
174
172
  # Reason it is off: the only output-side bench (telegraph-v1, n=10, 2026-05-16)
175
173
  # measured median vs_terse -9.27% (API counts) / -5.47% (exact cl100k_base
176
174
  # re-analysis) — telegraph emits MORE tokens than a plain "be terse" instruction.
177
175
  # The kill-criterion table therefore lands on "criterion not met — defer" and the
178
176
  # telemetry multiplier stays suspended (0.9155 < 1.0).
179
177
  #
180
- # NOTE: `speak_scope: off` disables the BEHAVIOUR but not the COST — the projector
181
- # gates this rule on `telegraph.speak`, never on speak_scope, so under
182
- # `lean_projection.mode: eager-all` the ~982-token body still ships every session.
183
- # Set `speak: false` for zero-cost dormancy.
184
- #
185
178
  # Stated explicitly here because until 2026-07-29 this default existed only in
186
- # prose — and two prose sources disagreed (the rule said prose_only, the accepted
187
- # ADR said off). Do not flip without a passing output-side bench.
179
+ # prose — and two prose sources disagreed. Do not flip without a passing
180
+ # output-side bench.
188
181
  telegraph:
189
182
  # speak: false = DORMANT (the shipped default per docs/adrs/telegraph/0002).
190
183
  # The rule is omitted from dist/router.json entirely, so its ~982-token body
191
- # never ships. This — not speak_scope — is the lever that stops the cost:
192
- # compile_router gates on `speak` and never reads speak_scope.
184
+ # never ships. This is the only lever that stops the cost: compile_router
185
+ # gates on `speak` and on nothing else.
193
186
  # Set true only after an output-side bench clears the kill-criterion bar.
194
187
  speak: false
195
- speak_scope: "off"
196
188
 
197
189
  # --- Token-rich skills governance ---
198
190
  #
@@ -420,14 +412,6 @@ chat_history:
420
412
  # per_tool = one entry per tool call (most verbose)
421
413
  frequency: __CHAT_HISTORY_FREQUENCY__
422
414
 
423
- # Max file size in KB before overflow handling kicks in (integer)
424
- max_size_kb: __CHAT_HISTORY_MAX_SIZE_KB__
425
-
426
- # Overflow behavior
427
- # rotate = drop oldest entries to stay under max_size_kb
428
- # condense = mark for summarization on the next agent turn
429
- on_overflow: __CHAT_HISTORY_ON_OVERFLOW__
430
-
431
415
  # Per-entry-type text-length caps (chars). 0 = verbatim, no slice.
432
416
  # N > 0 = collapse whitespace, slice to N chars, append " … [+K chars]"
433
417
  # so the log self-reports truncation. Defaults match the hardcoded
@@ -656,12 +640,6 @@ quality:
656
640
  # gates delegated to remote CI", never claim an unrun pipeline passed.
657
641
  local_auto_run: false
658
642
 
659
- # Wait for remote CI to finish on the PR / pipeline (true, false)
660
- # true = after push, poll GitHub check-runs / pipeline status and
661
- # report green / red before handing back
662
- # false = push and hand back immediately; user inspects CI
663
- # themselves (default — saves agent runtime and tokens)
664
- wait_for_remote_ci: false
665
643
 
666
644
  # --- Design fidelity ---
667
645
  #
@@ -744,6 +722,11 @@ screenshots:
744
722
  # ship-and-hope. Illustrative / no-data screenshots (diagrams, logos,
745
723
  # placeholder-only UI) may embed with a stated justification.
746
724
  # off = no data-bearing gate (legacy; the anonymization taxonomy still applies).
725
+ #
726
+ # NOTE: nothing reads this key yet — the gate it names is unconditional prose in
727
+ # `doc-screenshot-hygiene`. Kept rather than deleted so the missing reader is a
728
+ # visible gap instead of a silently unguarded action; see settings-classes.md
729
+ # § The six unread keys for the disagreement about which repair is right.
747
730
  data_bearing_gate: "on"
748
731
 
749
732
  code_style:
@@ -1365,7 +1348,6 @@ explain:
1365
1348
  # rule refuses every legal-review-prep skill until `acknowledged: true`.
1366
1349
  legal_review_prep:
1367
1350
  acknowledged: false
1368
- consented_at: ""
1369
1351
  # Gate legal work-product behind a multi-model council / deep-research pass
1370
1352
  # (defense-in-depth + audit trail; fail-closed). Off lets single-model legal
1371
1353
  # output through — not recommended for this high-risk pack.
@@ -40,16 +40,29 @@
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 (re-measured 2026-08-10)
43
+ # COVERAGE — THE HONEST DENOMINATOR (re-measured 2026-08-13)
44
44
  # ----------------------------------------------------------
45
- # 251 `lint_*` / `check_*` / `audit_*` scripts live under `src/scripts/`
45
+ # 257 `lint_*` / `check_*` / `audit_*` scripts live under `src/scripts/`
46
46
  # (the count is computed, not asserted — `check_gate_coverage.count_gate_scripts`).
47
- # **33 of them emit the machine-readable `scanned: <N>` line under their
48
- # CI-identical argv, and all 33 are listed below.** The manifest is therefore
49
- # complete with respect to its own contract, and covers ~13 % of the population.
50
- # (The 2026-08-05 reading said "32 … and all 31 are listed": the two halves of
51
- # one sentence disagreed by one, which is the drift this paragraph exists to
52
- # make visible. Both are recounted above, not adjusted toward each other.)
47
+ # **35 of them emit the machine-readable `scanned: <N>` line under their
48
+ # CI-identical argv, and all 35 are listed below.** The manifest is therefore
49
+ # complete with respect to its own contract, and covers ~14 % of the population.
50
+ # (The 2026-08-05 reading said "32 … and all 31 are listed"; the 2026-08-10
51
+ # reading said "33 … and all 33" while 34 entries were listed. Both halves are
52
+ # RECOUNTED here: 257 is what `count_gate_scripts()` returns on the tree that
53
+ # carries this change, and 35 is the entries counted directly. It read 255 while
54
+ # this change was being written and 257 after `main` merged in two further gate
55
+ # scripts — re-measured at the merge rather than left at the earlier reading,
56
+ # which is the same discipline the note below records failing.)
57
+ #
58
+ # A 2026-08-13 revision of this paragraph first wrote 256, derived as "255 before
59
+ # this change plus the one it adds" — inside the sentence claiming to have
60
+ # recounted. It was wrong twice over: 255 was already the reading WITH the new
61
+ # script present, and arithmetic on the previous prose is the exact move this
62
+ # paragraph forbids. Recorded rather than quietly corrected, because a
63
+ # denominator that goes stale by being adjusted is the failure documented here
64
+ # twice before, and the third instance is the one that shows the note is not
65
+ # enough on its own.
53
66
  #
54
67
  # Two revisions of this header have now gone stale the same way. It claimed
55
68
  # "8 of 211", then "22 of 223" while 26 entries were listed. Both halves drift
@@ -677,6 +690,27 @@ gates:
677
690
  a gate scanning nothing — it plants the removal-permitting class with no
678
691
  evidence and the gate reds.
679
692
 
693
+ - id: check_review_prompt_binding
694
+ argv: []
695
+ min_scanned: 15
696
+ corpus: "agents/evidence/reviews/<slug>.review-input/prompt.md paired with a prompt_hash in <slug>.findings.md (19 at baseline)"
697
+ status: enforced
698
+ canary:
699
+ class: unbound-review-prompt
700
+ path: agents/evidence/reviews/zcs-closure.review-input/prompt.md
701
+ content: |
702
+ Planted canary: a reviewer prompt whose sha256 cannot equal the
703
+ prompt_hash recorded in zcs-closure.findings.md.
704
+ note: >
705
+ The plant needs a slug that already carries a `prompt_hash` but no committed
706
+ package — a brand-new `zz-canary` slug is skipped, not caught, because an
707
+ artefact without a package is deliberately out of scope. `zcs-closure` is a
708
+ closed round, so it will not gain a real package and the plant cannot
709
+ collide with one. The two planted failures the roadmap asked for (a one-byte
710
+ prompt edit, a pre-loaded verdict) are pinned in
711
+ tests/scripts/check_review_prompt_binding.test.ts, which is where the
712
+ two-file plants this single-file recipe cannot express are exercised.
713
+
680
714
  - id: check_corpus_staleness
681
715
  argv: ["--quiet", "--today", "2026-08-06"]
682
716
  min_scanned: 5