@event4u/agent-config 10.2.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 (69) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +110 -276
  3. package/dist/agent-src/commands/analyze/reference-repo.md +62 -0
  4. package/dist/agent-src/commands/roadmap/create.md +4 -1
  5. package/dist/agent-src/personas/advisors/first-principles.md +6 -0
  6. package/dist/agent-src/rules/active-remediation.md +53 -2
  7. package/dist/agent-src/rules/code-provenance.md +66 -4
  8. package/dist/agent-src/rules/content-quoting-floor.md +6 -0
  9. package/dist/agent-src/rules/design-fidelity.md +49 -3
  10. package/dist/agent-src/skills/design-review/references/verification-automation.md +23 -1
  11. package/dist/agent-src/skills/fe-design/SKILL.md +27 -3
  12. package/dist/agent-src/skills/judge-synthesis/SKILL.md +30 -0
  13. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +11 -0
  14. package/dist/agent-src/skills/roadmap-writing/SKILL.md +8 -8
  15. package/dist/agent-src/skills/skill-writing/SKILL.md +4 -0
  16. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  17. package/dist/agent-src/templates/persona.md +26 -0
  18. package/dist/agent-src/templates/roadmaps.md +27 -7
  19. package/dist/agent-src/templates/skill.md +35 -1
  20. package/dist/cli/commands/commands.candidates.test.js +257 -0
  21. package/dist/cli/commands/commands.candidates.test.js.map +1 -0
  22. package/dist/cli/commands/commands.js +199 -0
  23. package/dist/cli/commands/commands.js.map +1 -1
  24. package/dist/cli/main.js +1 -0
  25. package/dist/cli/main.js.map +1 -1
  26. package/dist/cli/registry.js +1 -1
  27. package/dist/cli/registry.js.map +1 -1
  28. package/dist/cli-delegate/{chunk-E4RUZKXB.js → chunk-FV34EGEX.js} +1 -1
  29. package/dist/cli-delegate/cmd_conformance.js +1 -1
  30. package/dist/cli-delegate/cmd_doctor.js +1 -1
  31. package/dist/discovery/deprecation-report.md +1 -1
  32. package/dist/discovery/discovery-manifest.json +13 -13
  33. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  34. package/dist/discovery/discovery-manifest.summary.md +1 -1
  35. package/dist/discovery/dormancy-report.md +1 -1
  36. package/dist/discovery/orphan-report.md +1 -1
  37. package/dist/discovery/packs.json +2 -2
  38. package/dist/discovery/trust-report.md +1 -1
  39. package/dist/discovery/workspaces.json +2 -2
  40. package/dist/hooks/dispatch.js +116 -24
  41. package/dist/mcp/registry-manifest.json +2 -2
  42. package/dist/mcp/server.json +2 -2
  43. package/dist/mcp/server.mjs +1 -1
  44. package/dist/router.json +1 -1
  45. package/docs/guidelines/agent-infra/active-remediation-mechanics.md +54 -0
  46. package/docs/guidelines/design-antipatterns.md +79 -10
  47. package/docs/guidelines/design-fidelity-mechanics.md +120 -2
  48. package/package.json +1 -1
  49. package/src/config/gate-coverage.yml +42 -8
  50. package/src/config/gate-violation-baselines.json +6 -0
  51. package/src/config/review-prompt-binding-baseline.json +19 -0
  52. package/src/config/rule-enforcement-baseline.json +0 -1
  53. package/src/scripts/_dispatch.bash +1 -0
  54. package/src/scripts/ai_council/clients.ts +15 -1
  55. package/src/scripts/check_ci_local_parity.ts +60 -6
  56. package/src/scripts/check_review_prompt_binding.ts +553 -0
  57. package/src/scripts/check_suppression_hygiene.ts +19 -3
  58. package/src/scripts/design_slop_rules.test.ts +37 -6
  59. package/src/scripts/design_slop_rules.ts +150 -22
  60. package/src/scripts/dispatch_r2_reviewer.ts +15 -1
  61. package/src/scripts/hooks/ui_route_nudge_hook.ts +55 -2
  62. package/src/scripts/lint_design_antipattern_parity.ts +201 -0
  63. package/src/scripts/lint_harvest_provenance.ts +483 -0
  64. package/src/scripts/lint_skill_router_head.ts +254 -0
  65. package/src/scripts/report_consultation_rate.ts +126 -1
  66. package/src/scripts/run_skill_evals.ts +10 -5
  67. package/src/scripts/schemas/persona.schema.json +8 -0
  68. package/src/scripts/schemas/provenance-harvest.schema.json +39 -0
  69. package/src/scripts/sweep_dead_scan_roots.ts +51 -0
@@ -16,9 +16,11 @@ routes_to:
16
16
  - "guideline:agent-infra/active-remediation-mechanics"
17
17
  workspaces: [engineering]
18
18
  packs: [engineering-base]
19
+ enforced_by:
20
+ - "none"
19
21
  collision_ok:
20
22
  "refactor": "an explicit clean-up/refactor ask is the remediation ladder's own trigger"
21
- # obligation: line 51
23
+ # obligation: line 31
22
24
  obligation_frequency: "per-edit"
23
25
  ---
24
26
 
@@ -34,16 +36,53 @@ SMALL + TASK-ALIGNED → FIX IT NOW, IN THE SAME CHANGE, WITH ITS TEST.
34
36
  BIGGER OR DIVERGENT → NOTE IT, FINISH THE TASK, THEN ASK — NEVER MID-FLOW.
35
37
  TOO MANY → PROPOSE ONE OR MORE SEPARATE FOLLOW-UP PRs THE USER REVIEWS.
36
38
  A LIVE SECURITY / DATA-EXPOSURE GAP IS NEVER MERELY "NOTED FOR LATER".
39
+ A NOTE IS NOT A DISCHARGE — THE DECISION IS. AN ISSUE REPORTED IN PROSE AND
40
+ NEITHER FIXED NOR PUT TO THE USER IS STILL OPEN, AND STILL YOURS.
41
+ THE ASK CARRIES CANDIDATE FIXES AND AN EXPLICIT "LEAVE IT" — NEVER A BARE FLAG.
37
42
  ```
38
43
 
39
44
  ## What to remediate
40
45
 
41
- Security gaps (broken access control, injection, secrets, missing authz — see `broken-access-control`) · missing/weak test coverage · bad code (dead code, silent error-swallow, unguarded edge cases) · **duplication** (the same or near-same logic repeated instead of one method/abstraction) · **stale version-idioms** (code written for an older language/framework version than the project actually runs).
46
+ Security gaps (broken access control, injection, secrets, missing authz — see `broken-access-control`) · missing/weak test coverage · bad code (dead code, silent error-swallow, unguarded edge cases) · **duplication** (the same or near-same logic repeated instead of one method/abstraction) · **stale version-idioms** (code written for an older language/framework version than the project actually runs) · **a failing check you already ran** (below).
47
+
48
+ ## A check you already ran is a spotted issue
49
+
50
+ A red gate, a failing test, a lint or type error — output the tooling already put
51
+ in front of you — is **spotted**, exactly like a defect read in a file, and
52
+ enters the ladder on the same terms. "It was already red before I got here"
53
+ decides *which* tier, never whether the ladder applies.
54
+
55
+ Two bounds: **only output you already have** (never an obligation to go run a
56
+ check — the remote CI stays the authoritative gate), and **ownership picks the
57
+ tier, never the silence**. Classification + worked example: the mechanics
58
+ guideline below.
42
59
 
43
60
  ## The ladder — three tiers
44
61
 
45
62
  **Fix now** — small + task-aligned; ALL five conditions hold: same request path/module · ≤ ~10 changed lines in one production file (plus its test file) · no public-API / response-shape change · no dependency bump, no migration · verification ships in the same commit. Anything outside → next tier. · **Note + ask** (batched, one numbered-options prompt after delivery) · **Follow-up PR** (many spots; creation stays permission-gated). Per-tier detail + version-gated modernization + guardrails: the mechanics guideline below.
46
63
 
64
+ ## Every noted issue ends in one of three states
65
+
66
+ **Fixed**, **decided by the user** (an explicit "leave it" is terminal and is not
67
+ raised again, per [`scope-control`](scope-control.md)), or **in front of the user
68
+ right now** as the batched ask. A line in the closing summary is none of the
69
+ three: it leaves the issue open while sounding like it was handled, and it is the
70
+ failure this rule exists to stop. An undecided item survives the turn — raised
71
+ once more at the next task boundary, never aged out. A declined batch is closed.
72
+
73
+ ## The ask carries fixes, not a flag
74
+
75
+ "There are 7 lint errors — shall I fix them?" hands the problem back untouched.
76
+ Each numbered option is a candidate the user can pick without a follow-up
77
+ question — what changes, where, roughly how large, what it costs — grouped by fix
78
+ shape rather than one per finding, with an explicit **leave it as is** last and
79
+ one recommendation line (per [`user-interaction`](user-interaction.md)).
80
+
81
+ The ask is subordinate to [`no-cheap-questions`](no-cheap-questions.md): its
82
+ Pre-Send Self-Check runs first, and a finding with no nameable benefit or no real
83
+ trade-off is dropped silently instead of becoming a question. That check forbids
84
+ a content-free ask, never the surfacing of a genuine defect.
85
+
47
86
  ## Live-security carve-out (priority)
48
87
 
49
88
  A **live cross-user / cross-tenant data exposure** (per `broken-access-control`) is not a "note for later": it is a potential GDPR-notifiable breach (Art. 33, 72 h from discovery). If it meets the fix-now bar → fix it now with its negative test. If not → **stop and surface it immediately** (a safety surface, visible even under an autonomous mandate — like the `no-pr-progress-comments` safety carve-out). Never defer it silently, never look away.
@@ -56,6 +95,16 @@ While implementing/modifying code you pass an issue outside the literal task. Al
56
95
 
57
96
  - No issue spotted. Prose/docs-only. The user fenced the scope ("just this one line").
58
97
  - The issue is the task itself — then it's just the task (no ladder needed).
98
+ - The user already decided this item (fixed later, or explicitly ignored).
99
+
100
+ ## Honest enforcement — `enforced_by: none`
101
+
102
+ The note, the ask and the user's decision are all prose, and the issue set is
103
+ whatever the agent happened to see, so no gate can tell a discharged issue from a
104
+ mentioned one. This rule ships `enforced_by: none` — the honesty boundary
105
+ [`security-sensitive-stop`](security-sensitive-stop.md) and
106
+ [`ui-audit-gate`](ui-audit-gate.md) state for their own obligations. The ladder
107
+ is the control; skipping it is caught by nothing.
59
108
 
60
109
  Body migrated to [`guideline:agent-infra/active-remediation-mechanics`](../docs/guidelines/agent-infra/active-remediation-mechanics.md) (per P4 of `road-to-kernel-and-router.md`) — per-tier fix-now/note+ask/follow-up-PR criteria, version-gated modernization, anti-nagging guardrails.
61
110
  Trigger-set above activates this routing on demand, independent of the discipline profile (ADR-110).
@@ -68,3 +117,5 @@ Trigger-set above activates this routing on demand, independent of the disciplin
68
117
  - [`source-discovery-gate`](source-discovery-gate.md) — establishing the verified project version before modernizing.
69
118
  - [`scope-control`](scope-control.md), [`commit-policy`](commit-policy.md) — PR/commit creation stays permission-gated.
70
119
  - [`improve-before-implement`](improve-before-implement.md) — the pre-work challenge (before); this is the during/after remediation.
120
+ - [`verify-before-complete`](verify-before-complete.md) — an undecided issue is unfinished work, not a caveat to report.
121
+ - [`no-cheap-questions`](no-cheap-questions.md) — the floor the batched ask clears before it is asked at all.
@@ -2,7 +2,7 @@
2
2
  type: "auto"
3
3
  tier: "2a"
4
4
  alwaysApply: false
5
- description: "Porting/adapting external code (algorithm, structure, >~10 lines) — close the source, re-derive; conscious borrows need a ledger entry + license check"
5
+ description: "Porting external code, or asserting an externally-sourced claim — close the source, re-derive; borrows need a ledger entry + license check, harvested claims an id or an own-analysis label"
6
6
  triggers:
7
7
  - keyword: "port this"
8
8
  - keyword: "adapt this"
@@ -12,6 +12,8 @@ triggers:
12
12
  - keyword: "borrow"
13
13
  - keyword: "vendored"
14
14
  - keyword: "reference implementation"
15
+ - keyword: "harvest"
16
+ - keyword: "adopt from"
15
17
  routes_to:
16
18
  - "skill:license-compliance-borrow-check"
17
19
  - "skill:license-compliance-credits"
@@ -21,7 +23,7 @@ packs: [engineering-base]
21
23
  roles: [developer, reviewer, tester, po, incident, planner]
22
24
  enforced_by:
23
25
  - "none"
24
- # obligation: line 38
26
+ # obligation: line 40
25
27
  obligation_frequency: "per-edit"
26
28
  ---
27
29
 
@@ -64,6 +66,40 @@ An **unknown** source license is never permissive-by-default. Stop and
64
66
  escalate (numbered options, per
65
67
  [`ask-when-uncertain`](ask-when-uncertain.md)) instead of guessing.
66
68
 
69
+ ## The knowledge layer — cite a harvest id, or label it own analysis
70
+
71
+ The clauses above cover borrowed **code**. The same failure has a prose half:
72
+ a comparative pass concludes "their citation registry is worth adopting", the
73
+ sentence lands in a skill, and six months later nobody can say where it came
74
+ from or whether it was ever true. An unattributed idea is not a licensing
75
+ problem, which is why it needs its own clause rather than a wider reading of
76
+ the one above — it is an **epistemic** one, and it fails silently.
77
+
78
+ ```
79
+ AN ARTEFACT ASSERTING AN EXTERNALLY-SOURCED CLAIM EITHER CITES A HARVEST ID
80
+ OR LABELS THE STATEMENT AS OWN ANALYSIS. SILENCE IS NEITHER.
81
+ ```
82
+
83
+ Fires when a skill, rule, command, guideline, or roadmap states a heuristic, a
84
+ number, or a mechanism taken from a source outside this repo. Two acceptable
85
+ discharges, and the choice is the author's:
86
+
87
+ 1. **Cite** — append `<!-- harvest:<id> -->` and add the row to
88
+ `provenance/harvests.jsonl` (shape: `provenance/README.md`). The row pins
89
+ the source to a revision, or names it opaquely when
90
+ [`source-confidentiality`](source-confidentiality.md) keeps it out of the
91
+ tracked tree.
92
+ 2. **Label** — say in the text that this is own analysis. A stated derivation
93
+ is a complete discharge; the ledger exists for what came from elsewhere.
94
+
95
+ Only `adopt` and `adapt` findings produce a row. A rejected or already-present
96
+ finding has no artefact citing it and belongs in the analysis document.
97
+
98
+ **The prose carve-out below does not reach this section.** "Prose/docs-only
99
+ edits" excuses the *code* clauses, where there is no borrowed code to record;
100
+ prose is precisely where a harvested claim lands, so excluding it here would
101
+ empty the obligation of everything it applies to.
102
+
67
103
  ## Self-interrogation clause (AUXILIARY — never a control)
68
104
 
69
105
  Before finalizing any non-trivial function, ask internally: *"Did I derive
@@ -96,16 +132,42 @@ the source and re-derive" — a pre-write reasoning step only the model
96
132
  observes — so this rule ships `enforced_by: none`, same honesty stance as
97
133
  `security-sensitive-stop` and `untrusted-input-defense`.
98
134
 
135
+ `lint_harvest_provenance.ts` stands in exactly the same relation to the
136
+ knowledge layer, and the sentence is worth repeating rather than assuming
137
+ transferred: it validates the harvest ledger's own rows and citations — schema,
138
+ uniqueness, pinning, dead rows, orphan ids — and **cannot see a claim nobody
139
+ recorded**. A harvested assertion that was never cited and never labelled
140
+ passes every gate in this repo. That is the honest coverage statement, and it
141
+ is why the discipline is the control on both layers.
142
+
99
143
  ## When NOT to fire
100
144
 
101
145
  - A well-known, unpatentable algorithm shape (a hash map, a for-loop) with
102
146
  no specific source in mind.
103
147
  - Reusing your **own** prior code within this repo.
104
- - Prose/docs/config-only edits.
148
+ - Prose/docs/config-only edits — **for the code clauses only**. The knowledge
149
+ layer fires on exactly these surfaces; see its own note above.
150
+ - Common knowledge with no nameable source, on either layer. "Indexes speed up
151
+ lookups" needs no row; a specific number, threshold, or mechanism read
152
+ somewhere does.
153
+ - **A design artifact the user handed over** — a prototype, an exported
154
+ `design.html`, a token sidecar. That is the user's own material, not
155
+ third-party external code, so adapting its markup/CSS/JS is not a borrow and
156
+ needs no ledger entry. Same carve-out
157
+ [`content-quoting-floor`](content-quoting-floor.md) makes for user-owned text.
158
+ **The carve-out is authorship, not delivery:** a vendored component or a
159
+ licensed template that merely *arrives inside* a handover stays under this
160
+ rule in full. Boundary stated from the other side in
161
+ [`design-fidelity-mechanics`](../docs/guidelines/design-fidelity-mechanics.md)
162
+ § Adopt the code.
163
+ **It exempts the code clauses only.** A claim *about* the artifact's origin —
164
+ that a pattern in it came from somewhere nameable — is a knowledge-layer
165
+ statement and takes a harvest id or an own-analysis label like any other.
105
166
 
106
167
  ## See also
107
168
 
108
169
  - [`license-compliance-borrow-check`](../skills/license-compliance-borrow-check/SKILL.md), [`license-compliance-credits`](../skills/license-compliance-credits/SKILL.md), [`license-compliance-audit`](../skills/license-compliance-audit/SKILL.md) — the borrowing / notices / on-demand-scan skill family this rule routes to.
109
- - `provenance/README.md`, `src/scripts/lint_provenance.ts`, `src/scripts/detect_target_license.ts` — the ledger, its linter, and the S1.2 policy derivation.
170
+ - `provenance/README.md`, `src/scripts/lint_provenance.ts`, `src/scripts/detect_target_license.ts` — the code ledger, its linter, and the S1.2 policy derivation.
171
+ - `provenance/harvests.jsonl`, `src/scripts/lint_harvest_provenance.ts` — the knowledge ledger and its linter. Neither is `docs/CLAIMS.md` / `check_claims.ts`, which govern public claims this package makes about **itself**; the shared vocabulary is a grep hazard, so `provenance/README.md` states the three-way split.
110
172
  - [`secret-vcs-guard`](secret-vcs-guard.md) — sibling detect → ask → act discipline for a different leak class.
111
173
  - [`ask-when-uncertain`](ask-when-uncertain.md) — the escalation shape for `conditional`/`unknown` verdicts.
@@ -82,6 +82,12 @@ does not substitute for engaging with the source.
82
82
  treating fetched content as data vs instructions; this rule governs
83
83
  how much of that data may be reproduced verbatim once it IS being
84
84
  used as source material.
85
+ - [`code-provenance`](code-provenance.md) +
86
+ [`design-fidelity-mechanics`](../docs/guidelines/design-fidelity-mechanics.md)
87
+ § Adopt the code — this rule's user-owned-text carve-out extended to
88
+ **markup**: a design artifact the user hands over is their own material, so
89
+ adapting its code is not a borrow. Third-party code arriving inside that
90
+ handover is not covered, on either side.
85
91
  - [`docs/contracts/write-engine.md`](../docs/contracts/write-engine.md) —
86
92
  ghostwriter's disclosure-footer contract; this rule's quote floor
87
93
  applies to any ghostwriter draft that cites an external source.
@@ -60,8 +60,28 @@ A PROVIDED PROTOTYPE / DESIGN SYSTEM IS THE SPEC, NOT A SUGGESTION.
60
60
  BUILD IT 1:1. NEVER SWAP FONTS, CONTROLS, COMPONENTS, LAYOUT, SPACING,
61
61
  OR COLOUR — AND NEVER OMIT OR ADD AN ELEMENT — WITHOUT EXPLICIT CONFIRMATION.
62
62
  A "BETTER IDEA" IS A PROPOSAL TO SURFACE, NEVER A CHANGE TO MAKE.
63
+ WHENEVER THE SOURCE IS REACHABLE, THE SOURCE IS THE DATA BASIS.
64
+ A SCREENSHOT IS VALIDATION, NEVER THE INPUT YOU BUILD FROM,
65
+ WHILE ANY HIGHER RUNG IS REACHABLE. WHEN THE HANDOVER *IS* AN IMAGE,
66
+ THE IMAGE IS THE SPEC AND THE 1:1 FLOOR ABOVE APPLIES TO IT UNCHANGED.
67
+ WHERE THE ARTIFACT'S OWN MARKUP / CSS / JS IS STACK-COMPATIBLE, ADAPTING
68
+ THAT CODE IS THE DEFAULT — A FROM-SCRATCH RE-DERIVATION IS A DEVIATION
69
+ AND NEEDS THE SAME CONFIRMATION AS A SWAPPED CONTROL.
63
70
  ```
64
71
 
72
+ The qualifier is load-bearing, not hedging. Unqualified, the screenshot line
73
+ contradicts this rule's own opening sentence and its § What counts as the spec,
74
+ both of which name a screenshot as a legitimate spec — and it would forbid the
75
+ image-only handover class the rule exists to govern. What it forbids is
76
+ narrower: reaching for pixels **while the code is sitting there**.
77
+
78
+ The five new lines route to
79
+ [`design-fidelity-mechanics`](../docs/guidelines/design-fidelity-mechanics.md)
80
+ § Data-basis ladder (the first three) and § Adopt the code (the last two) —
81
+ including the scope line that keeps the adopt-the-code duty from colliding with
82
+ [`code-provenance`](code-provenance.md). Read that scope line before acting on
83
+ either rule; the boundary is stated from both sides.
84
+
65
85
  ## What counts as the spec
66
86
 
67
87
  A user-provided, finished design artifact the user points at and says "match
@@ -114,6 +134,21 @@ Two further handover shapes carry the artifact without any of the above:
114
134
  conventional location for a handed-over token/component set. The prefix is the
115
135
  vendor-scoped directory, never a bare `design-system/`, which is a normal
116
136
  source folder in a large fraction of frontend repos.
137
+ - **A third-party builder's share link — UNCOVERED, deliberately.** A page built
138
+ in Lovable / v0 / bolt and handed over as a link is a finished spec, and this
139
+ rule does not route it. The obvious trigger was tried on this branch and
140
+ **withdrawn**: matching is plain substring containment, so `https://v0.dev/`
141
+ also fires on `https://v0.dev/docs`, a pricing page, or a changelog link — it
142
+ would treat every mention of the tool's own site as a spec handover. That is
143
+ the `claude.ai` failure the capability-URL entry above exists to avoid, and by
144
+ this rule's own standard it is worse than the gap it closes. The alternatives
145
+ are a bare-host keyword (broader still) or guessing each vendor's share-path
146
+ segment, and a trigger built on a guessed path is not evidence.
147
+ **What closes it:** a verified share-path segment per vendor, or a
148
+ handover-word co-occurrence the matcher cannot express today. Until then the
149
+ class needs one word in the prompt, like any other unlisted filename.
150
+ `near-bare-host-mention` in the matrix pins the bare-host direction silent so
151
+ a future attempt cannot reintroduce the broad form unnoticed.
117
152
 
118
153
  The trigger set is deliberately phrase-heavy on the German side and on
119
154
  `artifact`: a bare `artifact` keyword fires on "the CI build artifact is 40 MB".
@@ -121,9 +156,20 @@ The trigger set is deliberately phrase-heavy on the German side and on
121
156
  [`design_fidelity_routing.test.ts`](../../tests/scripts/design_fidelity_routing.test.ts)
122
157
  pins both halves — every class that must route, and the near-misses that must
123
158
  stay silent (fixture `daf-port-trigger-de`). Extending the set without adding a
124
- near-miss row there is how an over-broad trigger lands: each of the two triggers
125
- above ships with its own near-miss row (`near-claude-ai-chat-link`,
126
- `near-generic-design-system-dir`).
159
+ near-miss row there is how an over-broad trigger lands: each of the two shipped
160
+ trigger classes above carries its own near-miss row
161
+ (`near-claude-ai-chat-link`, `near-generic-design-system-dir`), and the
162
+ withdrawn builder-URL class left `near-bare-host-mention` behind so the broad
163
+ form stays pinned silent.
164
+
165
+ **The near-miss must test the direction the new trigger opens, not a direction
166
+ that was already closed.** The withdrawn class is the worked example: its first
167
+ near-miss row tested a protocol-less mention, which was silent *before* the
168
+ change and therefore could not have caught the over-broadness the change
169
+ introduced. The row that would have caught it is
170
+ `near-builder-host-non-handover-url` — a documentation URL on the same host —
171
+ and it exists only because a review asked for it after the trigger had already
172
+ shipped. Write that row first next time; it is the cheap half.
127
173
 
128
174
  Body migrated to [`guideline:design-fidelity-mechanics`](../docs/guidelines/design-fidelity-mechanics.md) (per P4 of `road-to-kernel-and-router.md`) — surgical visual edits (targeted-edit vs redesign-trigger discipline, stable anchors), asset & imagery discipline (owned-asset path, third-party delivery is self-hosted by default, real-imagery-as-proof, iconography floor, no unrequested filler), deviation-surfacing shape, failure-mode catalog, `daf-*` fixtures.
129
175
  Trigger-set above activates this routing on demand, independent of the discipline profile (ADR-110).
@@ -29,7 +29,25 @@ Don't just screenshot the default state. Capture:
29
29
 
30
30
  ### Mockup-to-code verification
31
31
 
32
- When implementing from a design mockup or screenshot:
32
+ **Branch on what the artifact actually is before you open anything.** The two
33
+ kinds carry different workflows, and running the image workflow over a code
34
+ artifact is the failure this branch exists to prevent — it rebuilds from pixels
35
+ what was handed over as source.
36
+
37
+ **Code artifact** — an HTML/JSX/Vue file, an archive, a repo, a live page whose
38
+ DOM you can reach:
39
+
40
+ 1. **Read the code** — it is the data basis (`design-fidelity-mechanics`
41
+ § Data-basis ladder, rungs 1–2). Markup, styles, scripts.
42
+ 2. **Implement** — adapting the artifact's own code where it is
43
+ stack-compatible; a from-scratch re-derivation is a deviation, not a default.
44
+ 3. **Screenshot afterwards** — for an after-the-fact visual diff only, never as
45
+ the input you built from.
46
+ 4. **Flag deviations** — including behaviour: a handler or keyframe that did not
47
+ survive is a deviation, not an implementation detail.
48
+
49
+ **Image artifact** — a PNG/JPG screenshot, a Figma export you cannot open as
50
+ source, a photograph of a whiteboard:
33
51
 
34
52
  1. **Open the mockup** — use the provided image/screenshot.
35
53
  2. **Implement** — build the UI component.
@@ -38,6 +56,10 @@ When implementing from a design mockup or screenshot:
38
56
 
39
57
  This is especially useful when the user provides a screenshot or Figma export as a reference.
40
58
 
59
+ > **Near-miss worth naming:** an HTML file *opened in a browser* is still a code
60
+ > artifact. The browser makes it look like an image; the file on disk is rung 1.
61
+ > Take the code path.
62
+
41
63
  ## Async-verifier pattern (keep the main context clean)
42
64
 
43
65
  For a review that needs browser probing, use an **async background verifier**
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  model_tier: medium
3
3
  name: fe-design
4
- description: "Frontend design heuristics — and, outside the ticket engine, the loop that applies them: audit, brief, build, review. Use when building or changing any UI, not only when planning one."
4
+ description: "Frontend design heuristics — and, outside the ticket engine, the loop that applies them: audit, brief, inventory, build, review. Use when building or changing any UI, not only when planning one."
5
5
  personas:
6
6
  - frontend-engineer
7
7
  domain: engineering
@@ -40,8 +40,32 @@ else runs the loop.
40
40
  `layout`, `components`, `states`, `microcopy`, `a11y`. `states` means all
41
41
  five of `empty`, `loading`, `error`, `success`, `disabled` — a brief missing
42
42
  one is unfinished, not concise.
43
- 3. **Build** — against the audit's primitives, in the project's stack.
44
- 4. **Review** — run [`design-review`](../design-review/SKILL.md) before calling
43
+ 3. **Inventory — only when an artifact was provided, and before you build.**
44
+ List the artifact's **interactions, keyframes, and script includes** from its
45
+ source (`design-fidelity-mechanics` § Data-basis ladder — read it, do not
46
+ look at a picture of it). Then place **every** listed item in exactly one
47
+ bucket, using the engine's own names (`apply.ts`, `COVERAGE_BUCKETS`) so the
48
+ two surfaces read the same. **Nothing enforces that they stay the same** —
49
+ this is a copied vocabulary, not a shared constant, and no test pins it;
50
+ renaming a bucket in the engine leaves this list stale and silent:
51
+
52
+ | Bucket | Meaning |
53
+ |---|---|
54
+ | `honoured` | carried over as-is |
55
+ | `translated` | carried over in a different shape (a handler became a framework binding) |
56
+ | `flagged` | **not** carried over — with the reason, in the output |
57
+
58
+ Dropping a handler stays allowed; hiding one does not. An item in no bucket
59
+ is the failure this step exists to catch — "missing JavaScript" is what it
60
+ looks like from the user's side. Inside the engine this is enforced
61
+ (`apply.ts`, `COVERAGE_BUCKETS`, an unaccounted item is a halt); out here it
62
+ is a duty you carry, and nothing checks it for you. (fixture:
63
+ `daf-adhoc-port-coverage`.)
64
+ 4. **Build** — against the audit's primitives, in the project's stack. Where the
65
+ artifact's own markup/CSS/JS is stack-compatible, adapt **that code**;
66
+ re-deriving it from scratch is a deviation needing confirmation
67
+ (`design-fidelity-mechanics` § Adopt the code).
68
+ 5. **Review** — run [`design-review`](../design-review/SKILL.md) before calling
45
69
  it done, and scope the verdict honestly: render-scoped when you can render
46
70
  it, otherwise explicitly static-scoped, naming which checks actually ran.
47
71
  "Looks good" with neither scope named is a verdict without evidence.
@@ -103,6 +103,36 @@ contested.
103
103
  Each entry carries **provenance**: which judge(s) raised it. Never merge two
104
104
  judges' findings into one unattributed line.
105
105
 
106
+ ### 4b. Mark an uncited assertion — never drop it
107
+
108
+ A panelist assertion carrying neither fresh evidence produced this run (a
109
+ `file:line`, a command's output, a diff hunk) nor a citation is **marked
110
+ `uncited`** where it appears. It still ships.
111
+
112
+ ```
113
+ FLAG THE UNCITED ASSERTION. NEVER DROP IT.
114
+ A SUPPRESSED FINDING IS INDISTINGUISHABLE FROM A FINDING NOBODY MADE.
115
+ ```
116
+
117
+ The distinction is load-bearing and it is the reason this is a marking rule
118
+ rather than a filter: an unevidenced assertion may still be the most valuable
119
+ line in the report — a judge noticing something it could not yet prove is
120
+ exactly the signal a human wants. What the reader needs is to know which
121
+ category they are reading, not to be protected from one of them.
122
+
123
+ **Drop was considered and rejected against this file.** The formulation this
124
+ was adapted from offers "drop or flag"; the drop half contradicts § 4's
125
+ Advisory tier three paragraphs up — *"Emitted in full, never elided … a finding
126
+ that reached a judge and not the reader was suppressed by the aggregator"*.
127
+ Taking it would have put two rules in one skill in direct conflict, with the
128
+ newer one silently winning. Marking satisfies the same goal (the reader can
129
+ tell evidence from assertion) at zero information cost.
130
+
131
+ Scope: this marks **panelist** assertions inside a synthesis. It does not reach
132
+ the reviewed change, and it is not the `code-provenance` knowledge-layer
133
+ obligation, which governs what a durable artefact asserts rather than what a
134
+ transient review does.
135
+
106
136
  ### 5. Overall recommendation
107
137
 
108
138
  One sentence, not a number: `block` (any worst-tier verdict), `revise` (any
@@ -31,6 +31,17 @@ Use this skill when:
31
31
  a repeated phase pattern via
32
32
  [`extract_audit_patterns.ts`](../../../scripts/extract_audit_patterns.ts)
33
33
  — the pattern's `count` ≥ 2 already satisfies the repetition gate
34
+ * A comparative analysis handed over a **`### SEED —` block** from its
35
+ `## Seeds` section ([`/analyze:reference-repo`](../../agent-src/commands/analyze/reference-repo.md)
36
+ § 6). This is an accepted intake shape: the block already carries the
37
+ proposed name, kind, target template, one-line description, and the
38
+ `Extends instead?` answer, so step 4's overlap search starts from a stated
39
+ candidate rather than a blank page — it does **not** skip that search, and a
40
+ seed whose `Extends instead?` line is missing is incomplete intake, not a
41
+ shortcut. The repetition gate is satisfied differently here: the evidence is
42
+ the anchored ADOPT/ADAPT verdict behind the seed rather than a recurrence
43
+ count — a mechanism confirmed once against a named own-repo defect is not the
44
+ one-off case the gate exists to filter.
34
45
 
35
46
  Do not use this skill when:
36
47
 
@@ -152,14 +152,14 @@ Sign-off" phases are authoring bugs; replace each with an
152
152
  agent-verifiable check (a command, a targeted test, a grep). Never
153
153
  restate run-time safety floors as steps.
154
154
 
155
- Gate-test before any checkpoint: *"Could the agent clear this with a
156
- tool or command during the run?"* Yes → step, not gate. No →
157
- structured `## Blockers` entry (§ 5b), distinguishing per rule 22:
158
- **human gate** (only a human can decide/authorize — Hard-Floor
159
- authorization, billable spend, contested decision) vs **external
160
- blocker** (agent cannot resolve but CAN probe status — CI run, package
161
- release, upstream PR; `Resolved when:` carries the probe, owner is
162
- not a human). Merge is never a completion requirement — it may appear
155
+ Gate-test — three rungs in order (rule 22 owns the detail): **1.** agent-clearable
156
+ by tool/command → step. **2.** has a technical answer a council could reach → still
157
+ a step, first action runs the council; a contested *technical* decision is never a
158
+ human gate while one is configured (`agent-config council:status`). **3.** what
159
+ survives both → `## Blockers` (§ 5b): **human gate** (only a human can
160
+ decide/authorize — Hard-Floor authorization, billable spend, or preference / risk
161
+ appetite / product intent) vs **external blocker** (agent cannot resolve but CAN
162
+ probe status — CI run, package release, upstream PR; `Resolved when:` carries the probe, owner is not a human). Merge is never a completion requirement — it may appear
163
163
  as a blocker only when later roadmap work depends on the merged state.
164
164
  `lint_roadmap_complexity` warns on human-gate patterns in every mode.
165
165
 
@@ -102,6 +102,10 @@ Do NOT create a skill or rule for:
102
102
  → See `docs/guidelines/agent-infra/size-and-scope.md` for full limits.
103
103
 
104
104
  * Target: 300–900 words. Review for split above 1200 words. Strongly consider split above 1500 words.
105
+ * Over the 400-line K6 cap → the **router-head contract** in `templates/skill.md`
106
+ applies: entry head (when-to-use · mode table · routing) plus one `tasks/` or
107
+ `references/` file per mode, and the head never inlines more than one mode's
108
+ procedure. Gated by `lint_skill_router_head` with a shrink-only allowlist.
105
109
  * If multiple workflows exist → split into multiple skills
106
110
  * If two skills overlap heavily → merge
107
111
  * If a skill becomes "read the guideline" → it lost its purpose, restore the workflow
@@ -39,7 +39,7 @@ schema_version: 1
39
39
  # CI guard: a release bump of `package.json` must update this value
40
40
  # in lockstep — see scripts/check_template_pin_drift.ts (road-to-
41
41
  # portable-runtime-and-update-check P3.3).
42
- agent_config_version: "10.2.0"
42
+ agent_config_version: "10.3.0"
43
43
 
44
44
  # --- Project identity ---
45
45
  project:
@@ -38,6 +38,32 @@ source: package
38
38
  - mode optional — advisory link to a role-contracts workflow mode
39
39
  - version required — semantic version; bump on breaking changes
40
40
  - source required — "package" for personas shipped in dist/agent-src/
41
+ - sources optional — harvest_id list this persona may cite as external
42
+ doctrine (provenance/harvests.jsonl). OMIT IT unless you mean
43
+ one of the two scoped states; absent is the normal case and
44
+ the one every existing persona is in.
45
+ -->
46
+
47
+ <!-- SOURCES — an epistemic scope, not a bibliography.
48
+
49
+ A persona declares a voice. `sources:` optionally declares what that voice is
50
+ allowed to assert as *external doctrine* — as opposed to its own reasoning,
51
+ which needs no declaration and is never restricted.
52
+
53
+ | State | Meaning |
54
+ |---|---|
55
+ | field absent | Unscoped. Today's behaviour for every persona; nothing changes. |
56
+ | `sources: []` | Explicitly asserts nothing harvested — its positions are its own. |
57
+ | `sources: [id, …]` | May cite those harvest ids as doctrine. |
58
+
59
+ Every declared id must resolve to a row in `provenance/harvests.jsonl`;
60
+ `lint_harvest_provenance` fails an id that does not. Do NOT invent a row to
61
+ populate the field — an empty ledger and an absent field is the correct
62
+ resting state, and `[]` is for a persona where the distinction is worth
63
+ stating out loud.
64
+
65
+ This does not touch the Unique-Questions heuristic. A scoped persona still
66
+ earns its place by asking what nobody else asks.
41
67
  -->
42
68
 
43
69
  # {Role name}
@@ -197,9 +197,22 @@ Templates for roadmap files stored in `agents/roadmaps/` or `{module_root}/{Modu
197
197
  "user approves", "looks good", or "sign-off".
198
198
  - A **human gate** is allowed only when only a human can **decide or
199
199
  authorize**: a Hard-Floor action (deploy, prod data/infra),
200
- billable spend, or a contested product / architecture decision.
201
- Record it as a structured `## Blockers` entry (rule 20) — never as
202
- an inline checkbox step scattered through phases.
200
+ billable spend, or a decision bound to the user's own preference,
201
+ risk appetite, or product intent.
202
+ - A **contested technical decision is not a human gate while a
203
+ council is configured.** Which design is sound, whether a contract
204
+ still holds, which of N implementations to pick — these have
205
+ technical answers, and `decision_resolution` already classes a
206
+ contract or architecture change as `medium_impact → council`
207
+ (`docs/contracts/ai-council-config.md`). Authoring them as human
208
+ gates contradicts that classification and spends the user's
209
+ attention on a question the council answers. Run it, record the
210
+ verdict in the phase, and the gate becomes a step.
211
+ `agent-config council:status` says whether one is configured —
212
+ never infer it from the project tree (`council-availability`).
213
+ Record a genuine gate as a structured `## Blockers` entry
214
+ (rule 20) — never as an inline checkbox step scattered through
215
+ phases.
203
216
  - An **external dependency is a blocker, not a human gate**, whenever
204
217
  the agent can probe its status (CI run finished, package version
205
218
  published, upstream PR merged, API reachable, DNS propagated):
@@ -216,10 +229,17 @@ Templates for roadmap files stored in `agents/roadmaps/` or `{module_root}/{Modu
216
229
  `security-sensitive-stop`, and `commit-policy` fire at run time on
217
230
  their own; an authored "STOP: confirm with user before X" duplicates
218
231
  them and only adds interruptions.
219
- Gate-test before writing any checkpoint: *"Could the agent clear this
220
- with a tool or command during the run?"* Yes → it is a step, not a
221
- gate. No → structured blocker with a decidable `Resolved when:`,
222
- owned by a human only when the blocker is a genuine human gate.
232
+ Gate-test before writing any checkpoint, asked in this order:
233
+ 1. *"Could the agent clear this with a tool or command during the
234
+ run?"* Yes → it is a step, not a gate.
235
+ 2. *"Does it have a technical answer a council could reach?"* Yes →
236
+ it is a step whose first action runs the council.
237
+ 3. Only what survives both — preference, risk appetite, product
238
+ intent, authorization, spend — becomes a structured blocker with
239
+ a decidable `Resolved when:`, owned by a human.
240
+ Stopping at question 1 is the authoring bug this ordering exists to
241
+ prevent: it sends every decision the agent cannot compute straight to
242
+ the user, including the ones the council exists to answer.
223
243
  `task lint-roadmap-complexity` warns on human-gate step patterns,
224
244
  human-gate phase headings, and human-approval exit criteria.
225
245
 
@@ -207,8 +207,42 @@ Before considering a skill complete, verify it passes all 5 checks:
207
207
  - [ ] **K3: No obvious content** — doesn't teach the model what it already knows; only project-specific conventions and non-obvious patterns
208
208
  - [ ] **K4: Has Gotcha section** — documents real failure patterns, not theoretical advice; seeded with 2-3 entries
209
209
  - [ ] **K5: Has Output format** — numbered list with 2-4 deliverables describing what the skill produces
210
- - [ ] **K6: Under 400 lines** — if larger, extract reference tables or templates into separate files in the skill folder
210
+ - [ ] **K6: Under 400 lines** — if larger, restructure as a router head per the contract below (gate: `lint_skill_router_head`)
211
211
  - [ ] **English only** — all content in English
212
212
  - [ ] **No duplication** — doesn't repeat rules or guidelines that are already enforced elsewhere
213
213
  - [ ] **No "Related skills" section for mid-tier / untiered skills** — the agent discovers them via `<available_skills>` descriptions; cross-links waste tokens. Senior-tier skills (`tier: senior`) MUST include the block per `skill-quality.md` § Senior-Tier Required Structure (linter-enforced).
214
214
 
215
+ ## The router-head contract (K6, over the cap)
216
+
217
+ A `SKILL.md` over the 400-line cap restructures instead of growing. The shape:
218
+
219
+ | Part | Holds | Budget |
220
+ |---|---|---|
221
+ | **Entry head** — `SKILL.md` | When-to-use · a mode table · the routing that picks a mode · anything true across *all* modes | the cap |
222
+ | **Mode bodies** — `tasks/*.md` or `references/*.md` in the skill folder | One file per mode: the procedure, its examples, its tables | unbudgeted |
223
+
224
+ One binding constraint on the head: **it never inlines the procedure body for
225
+ more than one mode.** A head that carries mode A in full and points at modes
226
+ B and C has not been restructured — it has been relabelled, and the next edit
227
+ will grow it back.
228
+
229
+ ### What this contract does NOT claim
230
+
231
+ It does not claim a token win. The host loads `SKILL.md` whole on trigger, and
232
+ whether it then follows a pointer into `tasks/` is host behaviour **nothing in
233
+ this tree observes**. Anyone proposing a retrofit of an existing oversized skill
234
+ on activation grounds is asserting something currently unmeasurable, and
235
+ ADR-202's lesson binds: an activation claim goes behind a measured instrument or
236
+ it is not made.
237
+
238
+ What the contract does is narrower and real: the 400-line cap was already this
239
+ repo's published position, sitting in a checklist nothing enforced. The gate
240
+ makes an existing contract true for **new** skills. Restructuring the current
241
+ offenders is a separate decision with its own evidence bar.
242
+
243
+ ### Grandfathering
244
+
245
+ `lint_skill_router_head` carries a shrink-only allowlist seeded with the skills
246
+ that already exceed the cap. Entries may be removed, never added — a new
247
+ oversized monolith fails the gate rather than joining the list.
248
+