@event4u/agent-config 9.22.0 → 9.23.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 (85) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +69 -256
  3. package/README.md +1 -1
  4. package/dist/agent-src/commands/optimize/deep.md +13 -0
  5. package/dist/agent-src/contexts/execution/cheap-question-mechanics.md +12 -2
  6. package/dist/agent-src/contexts/execution/mandated-lines.md +180 -0
  7. package/dist/agent-src/rules/context-hygiene.md +17 -0
  8. package/dist/agent-src/rules/downstream-changes.md +26 -0
  9. package/dist/agent-src/rules/think-before-action.md +25 -0
  10. package/dist/agent-src/rules/token-budget-discipline.md +46 -3
  11. package/dist/agent-src/rules/token-efficiency.md +13 -0
  12. package/dist/agent-src/rules/ui-audit-gate.md +33 -2
  13. package/dist/agent-src/skills/adversarial-review/SKILL.md +18 -4
  14. package/dist/agent-src/skills/decision-review/SKILL.md +49 -0
  15. package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +5 -1
  16. package/dist/agent-src/skills/judge-bug-hunter/SKILL.md +16 -0
  17. package/dist/agent-src/skills/judge-synthesis/SKILL.md +14 -1
  18. package/dist/agent-src/skills/rule-writing/SKILL.md +33 -0
  19. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +31 -0
  20. package/dist/agent-src/skills/skill-reviewer/SKILL.md +1 -1
  21. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  22. package/dist/cli/registry.js +1 -0
  23. package/dist/cli/registry.js.map +1 -1
  24. package/dist/cli-delegate/chunk-DVRS2KVR.js +4602 -0
  25. package/dist/cli-delegate/{chunk-ELMFOQPW.js → chunk-SJQMJI7M.js} +8 -4597
  26. package/dist/cli-delegate/cmd_export.js +2 -1
  27. package/dist/cli-delegate/cmd_prune.js +2 -1
  28. package/dist/cli-delegate/cmd_settings_migrate.js +2 -1
  29. package/dist/cli-delegate/cmd_settings_set.js +3370 -0
  30. package/dist/cli-delegate/cmd_sync.js +2 -1
  31. package/dist/cli-delegate/cmd_uninstall.js +2 -1
  32. package/dist/cli-delegate/cmd_validate.js +2 -1
  33. package/dist/discovery/deprecation-report.md +1 -1
  34. package/dist/discovery/discovery-manifest.json +17 -17
  35. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  36. package/dist/discovery/discovery-manifest.summary.md +1 -1
  37. package/dist/discovery/orphan-report.md +1 -1
  38. package/dist/discovery/packs.json +2 -2
  39. package/dist/discovery/trust-report.md +1 -1
  40. package/dist/discovery/workspaces.json +2 -2
  41. package/dist/hooks/dispatch.js +79 -1
  42. package/dist/mcp/registry-manifest.json +2 -2
  43. package/dist/mcp/server.json +2 -2
  44. package/dist/scripts/condense.js +47 -2
  45. package/dist/scripts/condense.js.map +1 -1
  46. package/dist/server/routes/settings.js +82 -0
  47. package/dist/server/routes/settings.js.map +1 -1
  48. package/dist/shared/settingsClasses.js +191 -0
  49. package/dist/shared/settingsClasses.js.map +1 -0
  50. package/docs/contracts/settings-classes.md +342 -0
  51. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +23 -2
  52. package/docs/guidelines/agent-infra/false-green.md +187 -0
  53. package/docs/guidelines/agent-infra/gate-authoring.md +177 -0
  54. package/package.json +3 -1
  55. package/src/config/ci-local-parity.yml +12 -0
  56. package/src/config/evaluator-budgets.json +4 -4
  57. package/src/config/gate-coverage.yml +54 -12
  58. package/src/config/gate-violation-baselines.json +6 -0
  59. package/src/config/pack-size-budget.json +4 -3
  60. package/src/scripts/_cli/cmd_settings_set.ts +509 -0
  61. package/src/scripts/_dispatch.bash +16 -0
  62. package/src/scripts/_lib/gate_ledger.ts +295 -0
  63. package/src/scripts/_lib/gate_result.ts +101 -0
  64. package/src/scripts/_lib/gate_self_test.ts +129 -0
  65. package/src/scripts/_lib/measured_render.ts +97 -0
  66. package/src/scripts/_lib/ratchet_base_ref.ts +373 -0
  67. package/src/scripts/check_gate_completeness.ts +244 -0
  68. package/src/scripts/check_gate_coverage.ts +35 -6
  69. package/src/scripts/check_references.ts +125 -15
  70. package/src/scripts/check_review_dispositions.ts +14 -1
  71. package/src/scripts/check_suppression_hygiene.ts +503 -0
  72. package/src/scripts/condense.ts +47 -2
  73. package/src/scripts/hook_manifest.yaml +23 -0
  74. package/src/scripts/hooks/dispatch_hook.ts +65 -1
  75. package/src/scripts/hooks/host_semantics.ts +140 -0
  76. package/src/scripts/lint_framework_leakage.ts +147 -15
  77. package/src/scripts/lint_mandated_lines.ts +339 -0
  78. package/src/scripts/lint_roadmap_complexity.ts +102 -11
  79. package/src/scripts/lint_roadmap_family_cap.ts +191 -0
  80. package/src/scripts/lint_settings_classes.ts +397 -0
  81. package/src/scripts/lint_token_budget_discipline.ts +109 -1
  82. package/src/scripts/report_imperative_density.ts +229 -0
  83. package/src/scripts/verify_physical_move.ts +10 -1
  84. package/src/server/io/yamlIO.ts +173 -0
  85. package/src/shared/settingsClasses.ts +235 -0
@@ -0,0 +1,180 @@
1
+ # Mandated Lines — the forced artifact at the decision point
2
+
3
+ Shared contract for the small closed set of **verbatim lines the run must emit
4
+ at a decision point**, and for the pre-send sweep that catches an owed line that
5
+ went missing. Routed from the rule that owns each decision point rather than
6
+ restated in each.
7
+
8
+ **Routing status, stated because a claimed edge that does not exist is worse
9
+ than a missing one.** Two rules link here today:
10
+ [`think-before-action`](../../rules/think-before-action.md) (the intent line)
11
+ and [`downstream-changes`](../../rules/downstream-changes.md) (the sibling
12
+ search). The authorization and commit lines belong to
13
+ [`non-destructive-by-default`](../../rules/non-destructive-by-default.md) and
14
+ [`commit-policy`](../../rules/commit-policy.md) — both **kernel** rules, whose
15
+ edits require their own pull request and a 24-hour soak under
16
+ [`scope-control`](../../rules/scope-control.md). Those two edges are therefore
17
+ deliberately absent from this change rather than smuggled into it, and until
18
+ they land those two lines are carried by this contract alone.
19
+
20
+ ## Why a line and not a rule
21
+
22
+ An external source published the A/B of one obligation in three forms. Absent:
23
+ **0 of 4** runs surfaced a planted contradiction. Added as mid-list prose:
24
+ **1 of 4**, scoring *below* the no-instruction control. Converted into a
25
+ mandated verbatim line the run must emit *before* the behaviour-changing edit,
26
+ paired with a mechanical sweep for owed-but-missing lines: **4 of 4**. The rule
27
+ text did not change. Only its form did.
28
+
29
+ This suite has three recorded honest nulls on *reminder-shaped* interventions —
30
+ a decay-triggered restate, a reminder-injection experiment measuring zero delta,
31
+ a recursive-verification null. Those stand. This is a different mechanism: an
32
+ artifact the run must **produce**, not a reminder it must **receive**, with an
33
+ opposite measured result and its failing baseline published first. That is the
34
+ mechanism-match test in [`decision-revisit-gate`](../../rules/decision-revisit-gate.md),
35
+ passed rather than dodged.
36
+
37
+ ```
38
+ A MANDATED LINE IS EMITTED AT THE DECISION POINT, BEFORE THE ACTION —
39
+ NEVER AS A TRAILING CHECKLIST THAT PROVES THE ACTION HAPPENED.
40
+ A LINE THAT IS OWED AND MISSING IS AN INCOMPLETE REPLY.
41
+ A LINE THAT IS NOT OWED IS NOT EMITTED. SILENCE IS THE DEFAULT.
42
+ ```
43
+
44
+ ## The five lines
45
+
46
+ Each is bound to a **decision point**, not to a topic. One sentence each.
47
+
48
+ ### 1. Intent — before a behaviour-changing edit
49
+
50
+ Three slots: **what the code does · what the failing check expects · what the
51
+ specification says.**
52
+
53
+ > Intent: `parseDate` returns null on an empty string · the failing test expects
54
+ > a thrown `RangeError` · the spec says empty input is a caller error.
55
+
56
+ The load-bearing consequence, and the whole reason the line has three slots
57
+ rather than one: **when the three disagree, the disagreement is the finding and
58
+ the edit does not proceed.** A line that reads the same three ways is a line
59
+ that was written after deciding.
60
+
61
+ ### 2. Authorization — before an irreversible outward action
62
+
63
+ Carries **the user's own words**, quoted. Two denials are explicit:
64
+
65
+ - **Documentation is not authorization.** A roadmap step, a command file, or a
66
+ prior turn's plan describing the action is not the user asking for it.
67
+ - **Completing the task is not authorization.** Reaching the point where the
68
+ action would be natural is not permission to take it.
69
+
70
+ > Authorization: "push it and open the PR" (this turn) — covers this push and
71
+ > this PR, not the follow-up fix.
72
+
73
+ Fires for the [`non-destructive-by-default`](../../rules/non-destructive-by-default.md)
74
+ Hard-Floor set: push, deploy, prod-trunk merge, prod data or infra, bulk
75
+ destructive, and any irreversible external action (send · publish · post ·
76
+ purchase · submit).
77
+
78
+ ### 3. Commit — before a commit
79
+
80
+ Three slots: **the authorization and its exact scope · that the staged set
81
+ matches the intended edit · that nothing unintended is staged.**
82
+
83
+ > Commit: authorized "commit this now" (this turn), scope = the parser fix ·
84
+ > staged set is the 2 files that fix names · nothing else staged.
85
+
86
+ This is the mandated-artifact form of an obligation
87
+ [`commit-policy`](../../rules/commit-policy.md) already carries as prose, and it
88
+ is the fifth line rather than a variant of the authorization line because its
89
+ failure mode is different: the authorization line asks *may I*, the commit line
90
+ asks *is what I am about to record what I meant to record*. A commit with a
91
+ stray file is authorized and still wrong.
92
+
93
+ ### 4. Pending — when a prescribed follow-up was deliberately not taken
94
+
95
+ > Pending: the negative test for the tenant path is not written — the fixture
96
+ > needs a second tenant and I did not create one.
97
+
98
+ Unlike the other four this line gates nothing. It is a **disclosure**
99
+ obligation: it makes a deliberate skip visible to the human who reviews the
100
+ work, and it exists because this suite's work lands through reviewed pull
101
+ requests, so the line has a recipient. A skip nobody was told about is
102
+ indistinguishable from a step that was forgotten.
103
+
104
+ ### 5. Sibling search — after a defect fix
105
+
106
+ Names **the exact wrong construct searched for, and the count found.**
107
+
108
+ > Sibling search: grepped `JSON.parse(` without a try — 3 sites, 2 fixed, 1 in
109
+ > a test fixture and left.
110
+
111
+ A defect found in one place is presumed to recur until searched. The count is
112
+ part of the line because "I checked" is not a finding and zero is a real answer.
113
+
114
+ ## The pre-send sweep
115
+
116
+ Before a reply that claims completion, check each line above against what the
117
+ run **actually did**, and add any that is owed and missing.
118
+
119
+ - Fire only when something is owed. A reply owing nothing passes untouched, and
120
+ no line is emitted to prove the sweep ran.
121
+ - This is the same shape as the existing
122
+ [`roadmap-progress-sync`](../../rules/roadmap-progress-sync.md) and
123
+ [`no-cheap-questions`](../../rules/no-cheap-questions.md) pre-send checks — a
124
+ step in an existing sequence, not a new mechanism.
125
+ - The sweep is a backstop for a line that should already have been emitted at
126
+ its decision point. A reply where every owed line first appears in the sweep
127
+ is a reply that took the actions before thinking about them, and the sweep
128
+ cannot repair that — it can only surface it.
129
+
130
+ ## Brevity — how these avoid becoming ceremony
131
+
132
+ This suite's [`direct-answers`](../../rules/direct-answers.md) Iron Law 3 treats
133
+ long replies as a failure mode, and its anti-ceremony discipline says not to
134
+ invent receipts solely to prove execution. Five mandated lines are in real
135
+ tension with both. Three constraints resolve it, and they are part of the
136
+ contract:
137
+
138
+ 1. **One sentence per line.** A line that needs a paragraph is a line whose
139
+ decision was not made.
140
+ 2. **Emitted at the decision point, never as a trailing checklist.** The
141
+ measured 4-of-4 result came from a line emitted *before* the action. A
142
+ checklist at the end of a reply is the ceremony shape, and it also loses the
143
+ only property that made the mechanism work — that writing it can still stop
144
+ the action.
145
+ 3. **Two or more owed lines merge into one block, in execution order**, with
146
+ minimal labels — one interruption rather than five.
147
+
148
+ ```
149
+ Intent (parser.ts): returns null on empty · test expects RangeError · spec says caller error
150
+ Sibling search: grepped `JSON.parse(` without a try — 3 sites, 2 fixed, 1 test fixture left
151
+ Commit: authorized "commit this" (this turn), scope = parser fix · 2 files staged · nothing else
152
+ ```
153
+
154
+ ## Honest scope — what this does not claim
155
+
156
+ **Enforced by:** partially. `src/scripts/lint_mandated_lines.ts` is the
157
+ deterministic half and it checks only what a **run report** can be checked for:
158
+ a report claiming a behaviour change carries an intent line, and a report
159
+ describing an outward action carries an authorization line. It cannot check that
160
+ the line was emitted *before* the action rather than reconstructed after, and it
161
+ cannot check that the three intent slots were honestly filled. Those are
162
+ model-carried, and saying so here is cheaper than discovering it later.
163
+
164
+ **The transfer risk, stated.** The 4-of-4 measurement came from one source on
165
+ one task family — contradiction detection. This suite's work is largely
166
+ construction, where there may be no planted contradiction to surface, and the
167
+ mechanism could reduce to ceremony without anyone noticing.
168
+
169
+ **The cheap observation that would detect it:** track how often an emitted
170
+ intent line has its three slots **disagree**. If disagreements are effectively
171
+ never found, the line is decorating decisions already made and the set should
172
+ shrink. If disagreements are found and the edit is then revised or stopped, the
173
+ mechanism is doing the thing it was adopted for. That observation costs one
174
+ counter and is the first thing to look at before adding a sixth line.
175
+
176
+ ## See also
177
+
178
+ - [`docs/contracts/settings-classes.md`](../../../docs/contracts/settings-classes.md) — a sibling contract in the same shape: prose that a gate reads.
179
+ - [`verify-before-complete`](../../rules/verify-before-complete.md) — the evidence gate the pre-send sweep runs beside.
180
+ - `src/scripts/lint_mandated_lines.ts` — the deterministic half.
@@ -56,6 +56,8 @@ When **3 consecutive attempts** at the same task fail (code fix, test fix, confi
56
56
 
57
57
  Calling the **same tool** more than **2 times in a row** with similar parameters = loop.
58
58
  **Immediate action:** 1. STOP all tool calls. 2. Do the task directly. 3. Can't proceed → ask the user.
59
+
60
+ **"Similar parameters" is the load-bearing word — an enumerated set is not a loop.** Walking N *declared, distinct* targets (a downstream-caller sweep per [`downstream-changes`](downstream-changes.md), an override chain, the members of a grep result) is one operation whose parameters differ every call. Counting it as N repetitions makes `downstream-changes`' "find **ALL** callers, tests, imports" unsatisfiable — it cannot be done in two calls. The loop this detects is *repetition without new information*: same target, same parameters, hoping for a different answer. Mirrors the same carve-out in [`token-efficiency`](token-efficiency.md).
59
61
  `sequentialthinking` is especially prone to loops: at most **once** per task, NEVER for simple file operations, command execution, or straightforward edits.
60
62
 
61
63
  ## Read-Loop Detection — the 15 / 25 rule
@@ -72,6 +74,21 @@ EVERY TURN MUST EDIT, RUN, OR ASK.
72
74
 
73
75
  **25-min abort (5 read-only turns) — STOP and ask** with the abort block (template in the mechanics guideline). Non-bypassable: an autonomous mandate does **not** lift the abort — it is the safety net that protects autonomy from becoming a token sink.
74
76
 
77
+ ### Declared read protocol — the cap goes UP, never off
78
+
79
+ A mandated analysis/audit/review protocol is exactly the case that legitimately needs *more* reads, not fewer — an 8-turn evidence sweep is the protocol working, not a loop. Capping a declared protocol tighter than an undeclared one is backwards. So:
80
+
81
+ - **Undeclared reading keeps 3-warn / 5-abort.** Unchanged.
82
+ - **A declared protocol raises the abort to 8 read-only turns** — and never suspends it. "Non-bypassable" narrows to **no *silent* bypass**: a declared protocol is not silent.
83
+
84
+ A declaration is only valid when it states, before the reading starts, all three of:
85
+
86
+ 1. **the analysis goal**, falsifiably ("map every call chain that writes to the audit table" — not "understand the code");
87
+ 2. **the expected read count**;
88
+ 3. **the output shape** the reads feed (a table, an evidence report, a decision).
89
+
90
+ Free-text intent is not a declaration — the three fields exist so that "declared protocol: I need to read things" cannot buy the higher cap. Exceeding the declared count by more than 2 is itself the violation: stop, surface what the extra reads were for, and ask.
91
+
75
92
  Body migrated to [`guideline:agent-infra/context-hygiene-mechanics`](../docs/guidelines/agent-infra/context-hygiene-mechanics.md) (per P4 of `road-to-kernel-and-router.md`) — the freshness-suggestion template, the read-loop self-check + abort block, the state-dump format + `/agent-handoff` pointer, the Augment ignored-skills recovery flow, and the Copilot no-hook fallback (manual `context_hygiene_hook` refresh).
76
93
  Trigger-set above activates this routing on demand, independent of the discipline profile (ADR-110).
77
94
 
@@ -47,6 +47,32 @@ After editing any file, search for **all** of these:
47
47
  | **Routes** | Search `routes/` for controller references | Update after controller rename/move |
48
48
  | **Documentation** | Search `agents/`, `docs/`, `README`, examples for references | Update the doc that **describes** the changed surface — see Doc-Impact below |
49
49
 
50
+ ## Defect-pattern search — one instance is a sample, not the population
51
+
52
+ ```
53
+ A DEFECT FOUND IN ONE PLACE IS PRESUMED TO RECUR UNTIL SEARCHED.
54
+ NAME THE EXACT WRONG CONSTRUCT. SEARCH THE TREE. REPORT THE COUNT AND THE FILES.
55
+ "I FIXED IT" WITHOUT A COUNT IS A FIX OF ONE INSTANCE, NOT OF THE DEFECT.
56
+ ```
57
+
58
+ After fixing a defect, before claiming the fix is complete: write down the
59
+ **exact wrong construct** — the literal pattern, not a description of it — grep
60
+ the tree for it, and report **how many sites matched and which**. Zero is a real
61
+ answer and is worth reporting; it is the difference between "this was unique"
62
+ and "I did not look".
63
+
64
+ The own-orphan sweep above greps identifiers your diff *stopped referencing*.
65
+ This greps for the **defect itself**, which nothing else does — the two run over
66
+ different sets and neither substitutes for the other.
67
+
68
+ Emit the finding as the sibling-search mandated line
69
+ ([`mandated-lines`](../contexts/execution/mandated-lines.md) § 5), which is
70
+ where its shape and the reason it carries a count are specified.
71
+
72
+ **When NOT to fire:** the defect is in code the diff created this turn (there is
73
+ no population to search), or the construct is one the language makes impossible
74
+ to express twice.
75
+
50
76
  ## Doc-Impact — docs follow code (same change)
51
77
 
52
78
  ```
@@ -45,6 +45,31 @@ NO BLIND TRIAL-AND-ERROR. MAX 2 RETRIES PER APPROACH.
45
45
  - Do NOT modify code you do not fully understand — read it, trace the flow, then change it.
46
46
  - Multiple valid frameworks/patterns coexist (Tailwind + Flux, multiple form libs, competing state stores) → do NOT pick one silently — ask. See [`no blind implementation`](../docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md#2-no-blind-implementation).
47
47
 
48
+ ## The intent line, before a behaviour-changing edit
49
+
50
+ Before an edit that changes behaviour, emit the **intent line**: what the code
51
+ does · what the failing check expects · what the specification says. When the
52
+ three disagree, the disagreement is the finding and the edit does not proceed.
53
+ Shape, the other four mandated lines, and the pre-send sweep:
54
+ [`mandated-lines`](../contexts/execution/mandated-lines.md).
55
+
56
+ ## Where the answer lives — and saying so when it lives nowhere
57
+
58
+ Route by **where the answer actually is**: the code, a config, a live probe, a
59
+ doc, the user. When the answer exists only in your own inference — nothing to
60
+ open, nothing to run, nobody to ask — **say that**, in the report, in one clause.
61
+
62
+ ```
63
+ AN INFERENCE DRESSED IN PROCESS IS INDISTINGUISHABLE FROM A LOOKUP.
64
+ NAME THE DETOUR. A SILENT DETOUR READS AS A SKIPPED STEP.
65
+ ```
66
+
67
+ This rule and its neighbours say *be rigorous* often enough that the costume
68
+ version — narrating a thorough-sounding procedure over a guess — is a live risk
69
+ here specifically. The cost of naming it is one clause; the cost of not naming
70
+ it is that a reader cannot tell a verified fact from a confident one, which is
71
+ the property the whole evidence discipline exists to protect.
72
+
48
73
  ## Mechanics — workflow, minimum read set, verify-with-real-tools, no blind retries
49
74
 
50
75
  The five-step Understand → Analyze → Plan → Implement → Verify workflow, the minimum read set (symbol, callers, tests, abstractions, data), the memory-consult step, the verification matrix, the output-reduction patterns, the no-blind-retries protocol, and the "open files are context, not intent" clause all live in [`contexts/communication/rules-auto/think-before-action-mechanics.md`](../contexts/communication/rules-auto/think-before-action-mechanics.md). The rule above is the obligation surface; the mechanics file is the lookup material.
@@ -28,7 +28,7 @@ TO THE FULL FRUGALITY CANON (telegraph-speak, thin-projector).
28
28
  |---|---|---|---|---|
29
29
  | `lean` | No explicit key = lean | Full condensation | May be trimmed | < 500 tokens |
30
30
  | `standard` | — | Balanced condensation | Not trimmed if priority ≥ 60 | 500–2000 tokens |
31
- | `rich` | Must be declared + justified | **Exempt** | **Never trimmed** | 2000–5000 tokens |
31
+ | `rich` | Must be declared + justified | **Exempt** | **Never trimmed** | 2000–3500 tokens |
32
32
 
33
33
  Read `tokens.rich_skills` from `.agent-settings.yml` (default `on`) to determine
34
34
  whether rich skills may load in full. If `off`, treat them as
@@ -82,7 +82,7 @@ THE BUDGET LINE IS AN INPUT TO THE DECISION, NEVER THE DECISION ITSELF.
82
82
  The 15 % rich-skill cap, the lean/standard/rich size targets, and every
83
83
  telegraph-speak / thin-projector trim point are cost controls, not
84
84
  capability ceilings. When a proposed change is blocked *purely* because
85
- it would cross one of these lines — a skill needs more than 5000 tokens
85
+ it would cross one of these lines — a skill needs more than 3500 tokens
86
86
  to stay useful, a rule's condensed form loses a worked example the
87
87
  frugality canon would otherwise trim — do not silently reject it.
88
88
  Surface the trade-off instead: the estimated token delta, and the
@@ -107,10 +107,53 @@ These skills are approved `rich` by this roadmap's council:
107
107
  | `accessibility-auditor` | WCAG criteria are non-negotiable detail; every criterion has a testable condition + failure mode; compression loses the test procedures |
108
108
  | `design-system-capture` (Phase 6) | Writes + maintains DESIGN.md + PRODUCT.md; needs full templates + worked examples to generate useful artifacts |
109
109
 
110
+ ## Rich artifacts lead with a non-negotiable band
111
+
112
+ ```
113
+ A RICH-CLASS ARTIFACT OPENS WITH THE SECTION THAT OUTRANKS THE REST OF ITS
114
+ OWN DOCUMENT, THEN THE REASONING LAYER.
115
+ A LONG REFERENCE READ PARTIALLY MUST LOSE THE REASONING, NEVER THE OBLIGATION.
116
+ ```
117
+
118
+ The `rich` exemption buys length, and length buys the risk that a reader stops
119
+ early. Ordering is the mitigation available at authoring time: put the
120
+ load-bearing fraction first, so a partial read loses the part that was
121
+ explanation rather than the part that was binding.
122
+
123
+ This is a **precedence claim inside one document**, not a claim over other
124
+ artifacts — a rich skill's leading band outranks that skill's own later
125
+ sections and nothing else. Cross-artifact precedence is the authority index's
126
+ job.
127
+
128
+ It mitigates partial reading. It does **not** answer whether the artifact should
129
+ be shorter — that is the ceiling, gated below, and the two controls are
130
+ independent: an artifact can sit comfortably under the ceiling and still bury
131
+ its obligation on line 300.
132
+
133
+ ## The size band is measured, and only its ceiling is gated
134
+
135
+ The `rich` band is **2,000–3,500 tokens** ([ADR-217](../docs/decisions/ADR-217-rich-class-band-measured-and-enforced.md)).
136
+ It was 2,000–5,000 and enforced by nothing until that record: measured with the
137
+ exact BPE tokenizer, the largest rich artifact in the tree is 3,331 tokens, so
138
+ the old ceiling described no artifact that existed. An unused permission costs
139
+ nothing until someone uses it.
140
+
141
+ `lint_token_budget_discipline.ts` gates the **ceiling** and publishes every rich
142
+ artifact's size on the green path. It does **not** gate the floor, and that is a
143
+ finding rather than an omission: running the check once surfaced a 1,931-token
144
+ skill legitimately holding the class, because `rich` buys exemption from
145
+ condensation — a claim about what compression would *lose*, not about file size.
146
+ The published study supplies a degradation threshold, which is a ceiling.
147
+ Nothing measures a minimum.
148
+
149
+ Measurement is exact where `js-tiktoken` resolves and the character proxy where
150
+ it does not; the gate says which, and a proxy reading within its own error
151
+ margin of the ceiling is reported **unresolved** rather than classified.
152
+
110
153
  ## Governed by
111
154
 
112
155
  - `tokens.rich_skills` setting in `.agent-settings.yml` (consumer override)
113
- - `lint_token_budget_discipline.ts` (cap + justification CI check)
156
+ - `lint_token_budget_discipline.ts` (cap + justification + ceiling CI check)
114
157
  - the telegraph-speak rule, where enabled (amended to except rich-tagged skills)
115
158
 
116
159
  ## See also
@@ -26,6 +26,19 @@ NEVER CALL THE SAME TOOL >2 TIMES IN A ROW WITH SIMILAR PARAMETERS.
26
26
  IF YOU CATCH YOURSELF REPEATING → STOP, RETHINK, ASK.
27
27
  ```
28
28
 
29
+ ## Enumerated file sets are ONE operation, not N repetitions
30
+
31
+ The same-tool ceiling counts *repetition without new information* — the loop where the agent re-runs a tool because it did not learn from the last result. Reading N **declared, enumerated** files is the opposite: each read returns different content and the set was known before the first call. Counting it as N repetitions puts this rule in direct conflict with [`downstream-changes`](downstream-changes.md) ("find **ALL** callers, tests, imports") and with [`source-discovery-gate`](source-discovery-gate.md), which cannot be satisfied in two calls.
32
+
33
+ Exempt — the file set is enumerated **before** the first read and each read is a distinct member:
34
+
35
+ - an override / settings-resolution chain (project → user → global);
36
+ - a downstream-caller sweep after a rename or signature change;
37
+ - the members of a directory listing or grep result being opened in turn;
38
+ - a declared read protocol under [`context-hygiene`](context-hygiene.md).
39
+
40
+ Not exempt, and still the failure this rule exists to catch: re-reading the *same* file hoping for a different answer, re-running a failing command unchanged, or widening a grep by one word at a time instead of thinking. The discriminator is **did the previous call change what I know** — not the tool name.
41
+
29
42
  ## Fresh Output Over Memory
30
43
 
31
44
  When a tool returns a value (branch name, file path, PR number), use that EXACT value in subsequent API calls. NEVER substitute a value from earlier in the conversation. Context decay causes silent mismatches — fresh output is the only source of truth.
@@ -46,12 +46,43 @@ EXISTING-UI-AUDIT RUNS FIRST. ALWAYS.
46
46
 
47
47
  `null` or `{}` is **not** findings; empty dict is rejected on purpose.
48
48
 
49
- ## Allow-list — `ui-trivial`
49
+ ## Allow-list — `ui-trivial`, decidable from the diff alone
50
50
 
51
51
  Skip only when **all** hold:
52
52
 
53
- - `directive_set == "ui-trivial"`.
54
53
  - ≤ 1 file, ≤ 5 changed lines, no new component, no new state.
54
+ - Inside the work engine, `directive_set == "ui-trivial"` — the dispatcher
55
+ states it directly. Outside it, the same four conditions are read **off the
56
+ diff**, which is observable without any dispatcher state.
57
+
58
+ The `directive_set` check used to be an additional *requirement* rather than
59
+ the dispatcher's way of stating the same fact. That made the escape hatch
60
+ dispatcher-only, and with `state.ui_audit` also dispatcher-only the gate could
61
+ be neither satisfied nor skipped in a plain chat session — the only
62
+ rule-conform action left was "write no UI". A gate whose sole compliant path is
63
+ inaction is not a gate.
64
+
65
+ ## Honest scope — what this rule does NOT enforce in a chat session
66
+
67
+ ```
68
+ OUTSIDE THE WORK ENGINE, THE AUDIT OBLIGATION IS MODEL-CARRIED.
69
+ NEVER CLAIM THE AUDIT RAN AS IF IT WERE VERIFIED.
70
+ ```
71
+
72
+ `state.ui_audit` exists only inside the work-engine dispatcher, so only there
73
+ is "the audit ran" a *checked* fact. A chat session cannot verify it: "I ran
74
+ `existing-ui-audit` first" is self-report, and self-report is not enforcement —
75
+ the same honesty boundary `security-sensitive-stop` and
76
+ `untrusted-input-defense` state for their own obligations. So this rule ships
77
+ `enforced_by: none` outside the dispatcher, deliberately, rather than pretending
78
+ a satisfiable-by-assertion condition is a gate.
79
+
80
+ What that leaves, and it is the useful part: run
81
+ [`existing-ui-audit`](../skills/existing-ui-audit/SKILL.md) before adding a
82
+ component because reuse beats duplication — not because a check will catch you.
83
+ Full enforcement requires the dispatcher (or the `frontend-design` pack once
84
+ pack-scoped rule projection is enabled; that flip is a maintainer decision,
85
+ never an automated one).
55
86
 
56
87
  ## Failure modes
57
88
 
@@ -37,7 +37,7 @@ sums ("attack the winner, using the losing options' strongest criteria")
37
37
  1. **Inspect the artifact** — Read the plan, diff, or draft you are about to critique; note its scope, assumptions, and the explicit asks before attacking.
38
38
  2. **Attack** — Run Step 1 below as the grumpy senior engineer.
39
39
  3. **Defend** — Run Step 2 as the balanced engineer; classify each criticism as must-fix / defer / reject.
40
- 4. **Revise** — Run Step 3 to fold valid fixes back in and surface only the trade-offs the user needs to decide.
40
+ 4. **Revise** — Run Step 3 to fold valid fixes back in, then report every criticism with its disposition. Deciding which trade-offs matter is the user's pass, not this step's.
41
41
 
42
42
  ### Step 1: Attack (Grumpy Senior Engineer)
43
43
 
@@ -64,8 +64,19 @@ Counter the criticism fairly:
64
64
  - Move deferred concerns to "Open Questions" or "Known Limitations".
65
65
  - Present the improved version to the user.
66
66
 
67
- **Do this internally** — the user sees the improved result, not the raw debate.
68
- Only surface trade-offs or concerns that need the user's input.
67
+ **Debate internally, report completely.** The user sees the improved result
68
+ rather than the blow-by-blow — but every criticism raised reaches the report
69
+ with its disposition (must-fix / deferred / rejected, each with one line of
70
+ reason). Do not decide on the user's behalf which concerns were worth their
71
+ attention.
72
+
73
+ This clause used to read *"surface only the trade-offs that need the user's
74
+ input"*, and that is the pre-filter defect: an instruction to report a subset is
75
+ followed literally — the review finds the defects, then withholds the ones it
76
+ judged unimportant, and the loss is invisible because the withheld set leaves no
77
+ trace. It matters here more than anywhere: `self_review_gate.ts` loads this file
78
+ as the system prompt for the package's own CI self-review, so a suppression
79
+ clause here suppresses findings on every pull request.
69
80
 
70
81
  ## Context-specific attack questions
71
82
 
@@ -148,7 +159,10 @@ triggers it. See [`rdp-gate`](../../contexts/execution/rdp-gate.md) (L12).
148
159
  ## Output format
149
160
 
150
161
  1. Improved plan/code incorporating adversarial findings
151
- 2. Risk summary — top concerns discovered and how they were addressed
162
+ 2. **Every criticism raised**, each with severity and disposition (must-fix /
163
+ deferred / rejected) and one line of reason. Not "top concerns" — a summary
164
+ that keeps only the highlights is the pre-filter defect wearing an
165
+ editor's hat.
152
166
  3. Remaining open risks (if any) with severity rating
153
167
 
154
168
  ## Gotcha
@@ -173,6 +173,55 @@ strengthening evidence.
173
173
  `skipped` (stale — age > `review_after_days`), surface them to
174
174
  the user; do not silently use stale entries as if they were current.
175
175
 
176
+ ## Removal is a disposition — a rule the agent keeps failing gets teeth or gets deleted
177
+
178
+ ```
179
+ A RULE THE AGENT CONSISTENTLY FAILS TO FOLLOW GETS STRUCTURAL ENFORCEMENT
180
+ OR DELETION. NEVER A LOUDER RESTATEMENT.
181
+ ASK WHAT CAN BE REMOVED AS DELIBERATELY AS WHAT SHOULD BE ADDED.
182
+ ```
183
+
184
+ Ratchets in this tree move one way. Counts go up, gates accumulate, and nothing
185
+ retires an artifact — so the default response to non-adherence has been to say
186
+ it again, harder. That is the one response the evidence rules out: an obligation
187
+ that did not change behaviour as prose does not change it as louder prose. The
188
+ fork is **enforcement or deletion**, and both are real options.
189
+
190
+ **Non-adherence is the trigger, not low frequency.** A rule that rarely fires is
191
+ not a rule that fails. A floor is working precisely when nothing crosses it, and
192
+ deleting it because it has been quiet removes the thing that was holding.
193
+
194
+ ### The simplify signals
195
+
196
+ Any of these is a reason to open the question. None of them is on its own a
197
+ verdict:
198
+
199
+ - a section that has not been relevant across many sessions;
200
+ - a rule derived from a **single unvalidated observation**;
201
+ - a workflow that is consistently shortcut in practice;
202
+ - sections that are loaded every run and never acted on;
203
+ - two rules that contradict each other;
204
+ - complexity added for a case that has never triggered.
205
+
206
+ Note that *never relevant*, *single unvalidated observation*, and *never acted
207
+ on* are listed separately on purpose. They look alike and they are not: the
208
+ first is about scope, the second about evidence, the third about attention.
209
+
210
+ ### Escalation, and its counterpart
211
+
212
+ ```
213
+ A THIRD RECURRENCE OF THE SAME VIOLATION CLASS CONVERTS AN OBSERVATION
214
+ INTO A DETERMINISTIC GATE.
215
+ A REVIEW FINDING NEVER SILENTLY BECOMES A HARD GATE.
216
+ ESCALATE AT A STATED THRESHOLD, NEVER SILENTLY.
217
+ ```
218
+
219
+ Both halves are load-bearing and they come from sources that disagree. The
220
+ threshold stops a recurring defect from being re-observed forever; the
221
+ counterpart stops a single reviewer's opinion from quietly becoming law. Between
222
+ them, the only legitimate path from *noticed* to *enforced* is a stated count
223
+ reached in the open.
224
+
176
225
  ## Decision-revisit gate — mechanics (migrated from the `decision-revisit-gate` rule)
177
226
 
178
227
  Body of [`decision-revisit-gate`](../../rules/decision-revisit-gate.md)
@@ -101,7 +101,11 @@ Before finalising:
101
101
  2. No dimension was penalised for length or word count.
102
102
  3. N/A credit was granted only where the schema allows it.
103
103
  4. The verdict follows the ratio thresholds above, not intuition.
104
- 5. Top gaps are the highest-weight missing dimensions — not every minor gap.
104
+ 5. The **Dimensions block lists every dimension**, scored, with no omissions —
105
+ that is the complete emission and it is not optional. **Top gaps** is a
106
+ ranked summary layered over it, so it names the highest-weight misses rather
107
+ than repeating the block. Shortening the block itself is the pre-filter
108
+ defect; shortening the summary is what a summary is.
105
109
 
106
110
  ## Output format
107
111
 
@@ -121,11 +121,24 @@ Issues (if revise/reject):
121
121
  Trigger: <concrete input/condition>
122
122
  Expected: <what should happen>
123
123
  🟡 ...
124
+
125
+ Rejected candidates (if the devil's-advocate pass killed any):
126
+ 🔴→drop path/to/file.ext:LINE — <the finding> · refuted by: <guard clause
127
+ upstream | framework default | unreachable input | …>
124
128
  ```
125
129
 
126
130
  Severity: 🔴 crash or incorrect result / 🟡 edge case unhandled but
127
131
  graceful / 🟢 defensive-coding suggestion.
128
132
 
133
+ **A killed 🔴 is demoted, never deleted.** This judge runs a refutation pass on
134
+ every 🔴 and used to leave no trace of what it killed — the one judge with a
135
+ refutation step and no demotion bucket, where `code-review`, `security-audit`,
136
+ `bug-analyzer`, and the adversarial council all pair theirs with one. The
137
+ asymmetry matters because refutation is a judgement: a reviewer who was wrong to
138
+ refute leaves the reader no way to notice. Confidence is what the row carries;
139
+ severity is what it keeps — a 🔴 refuted on a guess is still a 🔴 somebody should
140
+ look at.
141
+
129
142
  Required fields (ordered):
130
143
 
131
144
  1. **Judge** and **Model** — skill name and resolved judge model
@@ -133,6 +146,9 @@ Required fields (ordered):
133
146
  3. **Verdict** — `apply`, `revise`, or `reject`
134
147
  4. **Issues** — every finding cites file:line and concrete trigger;
135
148
  omit only when verdict is `apply`
149
+ 5. **Rejected candidates** — every finding the refutation pass killed, with what
150
+ refuted it. Omit the section only when the pass killed nothing; never omit it
151
+ because the kills seemed obvious.
136
152
 
137
153
  If a finding needs runtime confirmation, note it as a follow-up for
138
154
  the implementer with the concrete probe — backend: `curl` or
@@ -63,6 +63,15 @@ finding count. Preserve each
63
63
  judge's own verdict word (do not normalise away `breached` into `reject`); add a
64
64
  severity tier (worst/mid/clean) only as a sort key.
65
65
 
66
+ **A sort key, never a filter.** Severity orders the synthesis; it never decides
67
+ what enters it. Dropping a judge's low-severity finding during synthesis
68
+ reproduces the pre-filter defect one layer up — the finding was found, the
69
+ reviewer reported it, and the aggregator withheld it. Filtering is the
70
+ consumer's pass, after the ledger is whole. Output shape, the separate
71
+ `Confidence` field, and the preserve-an-unverified-S0 rule are specified once in
72
+ [`adversarial-review-protocol`](../../../docs/contracts/adversarial-review-protocol.md)
73
+ § 3.
74
+
66
75
  ### 2. Find consensus (highest confidence)
67
76
 
68
77
  A finding flagged by **≥2 judges** (same file:line / same dimension / same
@@ -85,7 +94,11 @@ contested.
85
94
  - **Must-fix** — every finding from a worst-tier verdict (`reject` / `incomplete`
86
95
  / `breached`) + every consensus finding at the highest severity.
87
96
  - **Should-fix** — mid-tier (`revise` / `partial`) findings.
88
- - **Advisory** — single-judge low-severity suggestions.
97
+ - **Advisory** — single-judge low-severity suggestions. **Emitted in full,
98
+ never elided.** This is the tier with no downstream consumer, which makes it
99
+ the one where quiet dropping costs nothing visible — and that is exactly why
100
+ it is stated: a finding that reached a judge and not the reader was suppressed
101
+ by the aggregator, whatever the tier was called.
89
102
 
90
103
  Each entry carries **provenance**: which judge(s) raised it. Never merge two
91
104
  judges' findings into one unattributed line.
@@ -203,6 +203,39 @@ See § 3b above for the load-bearing distinction between `load_context:`
203
203
  (logical, rewritten), `triggers[].path_prefix:` (literal, verbatim),
204
204
  and body links (relative `../../docs/...`, rewriter handles depth).
205
205
 
206
+ ## Required: name the primary bias this rule overrides
207
+
208
+ ```
209
+ EVERY RULE STATES, IN ONE SENTENCE, THE MODEL'S WRONG DEFAULT IT EXISTS TO
210
+ OVERRIDE. NOT THE HISTORY. NOT THE RATIONALE. THE TENDENCY.
211
+ A RULE THAT CANNOT NAME ONE IS A RULE WITH NO OBSERVED FAILURE BEHIND IT.
212
+ ```
213
+
214
+ One sentence, near the top, in the shape *"left alone, the model
215
+ &lt;does the wrong thing&gt;"*:
216
+
217
+ - ✅ "Left alone, the model treats a question as an instruction and starts
218
+ building."
219
+ - ✅ "Left alone, the model reports the happy path it just made pass and calls
220
+ the change finished."
221
+ - ❌ "This rule exists because a session in June went badly." — backstory.
222
+ - ❌ "Correctness matters." — a value, not a tendency.
223
+ - ❌ "Agents sometimes make mistakes." — true of everything, discriminates
224
+ nothing.
225
+
226
+ **Why this field and not a longer rationale.** It is the discriminator the
227
+ mechanism-must-match-an-observed-failure-mode discipline wants at *authoring*
228
+ time: a rule whose bias sentence is a plausible generality is a rule aimed at
229
+ nothing in particular, and that is visible in one line where it is invisible in
230
+ three paragraphs. The field is also the input to the removal question later —
231
+ `decision-review` asks whether the agent still exhibits the named tendency, and
232
+ that question cannot be asked of a rule that never named one.
233
+
234
+ **Retrofit is opportunistic, never a sweep.** Add the sentence when you touch a
235
+ rule for another reason. A batch edit across the rule set trips the
236
+ kernel-prefix byte-stability gate, and that gate is right to fire — the kernel
237
+ prefix is pinned deliberately.
238
+
206
239
  ## Output format
207
240
 
208
241
  1. Complete rule file at `src/rules/{name}.md`