@event4u/agent-config 12.0.0 → 13.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +273 -0
- package/README.md +1 -1
- package/agents/templates/.ai-council.yml.example +46 -3
- package/dist/agent-src/commands/cost/report.md +23 -0
- package/dist/agent-src/contexts/execution/subagent-routing.md +148 -33
- package/dist/agent-src/contexts/model-recommendations.md +6 -4
- package/dist/agent-src/contexts/subagent-configuration.md +69 -7
- package/dist/agent-src/rules/autonomous-execution.md +1 -1
- package/dist/agent-src/rules/design-fidelity.md +1 -1
- package/dist/agent-src/rules/design-review-after-ui-write.md +10 -5
- package/dist/agent-src/rules/evaluator-independence.md +27 -5
- package/dist/agent-src/rules/git-history-discipline.md +5 -1
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -0
- package/dist/agent-src/rules/missing-skill-recovery.md +89 -0
- package/dist/agent-src/rules/ui-audit-gate.md +9 -4
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +33 -0
- package/dist/agent-src/scripts/roadmap_gates.ts +30 -2
- package/dist/agent-src/scripts/update_roadmap_progress.ts +47 -1
- package/dist/agent-src/skills/authz-review/SKILL.md +4 -0
- package/dist/agent-src/skills/design-system-capture/SKILL.md +4 -0
- package/dist/agent-src/skills/design-system-capture/references/snapshot-preference-order.md +77 -0
- package/dist/agent-src/skills/merge-conflicts/SKILL.md +4 -0
- package/dist/agent-src/skills/prompt-optimizer/SKILL.md +17 -1
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +11 -11
- package/dist/agent-src/skills/systematic-debugging/SKILL.md +4 -0
- package/dist/agent-src/skills/threat-modeling/SKILL.md +3 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +41 -3
- package/dist/cli/registry.js +1 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/{chunk-NN4KW4HZ.js → chunk-3B72LSZL.js} +123 -2338
- package/dist/cli-delegate/{chunk-55WZN5VF.js → chunk-EVTY7ISR.js} +2 -2
- package/dist/cli-delegate/chunk-N7FEST6D.js +3895 -0
- package/dist/cli-delegate/{chunk-L565YFXH.js → chunk-XURJ4AQC.js} +566 -298
- package/dist/cli-delegate/cmd_conformance.js +4 -4
- package/dist/cli-delegate/cmd_doctor.js +2 -2
- package/dist/cli-delegate/cmd_export.js +2 -2
- package/dist/cli-delegate/cmd_handoff.js +1 -1
- package/dist/cli-delegate/cmd_prune.js +2 -2
- package/dist/cli-delegate/cmd_settings_migrate.js +2 -2
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +2 -2
- package/dist/cli-delegate/cmd_uninstall.js +2 -2
- package/dist/cli-delegate/cmd_validate.js +2 -2
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +44 -23
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +6 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +5 -4
- package/dist/hooks/dispatch.js +10625 -8541
- package/dist/install/install.mjs +754 -484
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1302 -167
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/model_tier.js +9 -0
- package/dist/scripts/_lib/model_tier.js.map +1 -1
- package/dist/scripts/condense.js +50 -0
- package/dist/scripts/condense.js.map +1 -1
- package/dist/server/schemas/settings.js +2 -2
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/MIGRATION.md +20 -1
- package/docs/guidelines/design-fidelity-mechanics.md +21 -0
- package/docs/guidelines/design-handover-extraction.md +87 -0
- package/docs/guidelines/prompt-templates.md +24 -1
- package/package.json +1 -1
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +33 -0
- package/src/agent-src/scripts/roadmap_gates.ts +30 -2
- package/src/agent-src/scripts/update_roadmap_progress.ts +47 -1
- package/src/config/evaluator-budgets.json +9 -8
- package/src/config/gate-coverage.yml +63 -11
- package/src/config/gate-violation-baselines.json +12 -0
- package/src/config/hook-token-budget.json +15 -2
- package/src/config/preamble-payload-budget.json +28 -0
- package/src/scripts/_dispatch.bash +10 -0
- package/src/scripts/_lib/bench_ab_complexity.ts +439 -0
- package/src/scripts/_lib/bench_ab_safety_tier.ts +142 -0
- package/src/scripts/_lib/bench_ab_scoring_v2.ts +28 -3
- package/src/scripts/_lib/bench_ab_search_adherence.ts +423 -0
- package/src/scripts/_lib/bench_ab_size_claim.ts +206 -0
- package/src/scripts/_lib/bench_ab_workspace.ts +111 -0
- package/src/scripts/_lib/git_common_dir.ts +173 -0
- package/src/scripts/_lib/model_tier.ts +9 -0
- package/src/scripts/_lib/release_highlights.ts +108 -7
- package/src/scripts/_lib/skill_catalogue.ts +1115 -0
- package/src/scripts/_lib/tier_budget_routing.ts +31 -331
- package/src/scripts/ai_council/clients.ts +197 -18
- package/src/scripts/ai_council/config.ts +16 -1
- package/src/scripts/ai_council/low_impact.ts +14 -1
- package/src/scripts/ai_council/orchestrator.ts +14 -1
- package/src/scripts/ai_council/transport_resolver.ts +32 -2
- package/src/scripts/bench_ab_v2_complexity.ts +252 -0
- package/src/scripts/bench_ab_v2_run.ts +3 -42
- package/src/scripts/bench_ab_v2_safety.ts +296 -0
- package/src/scripts/bench_ab_v2_search.ts +343 -0
- package/src/scripts/bench_ab_v2_stats.ts +191 -0
- package/src/scripts/build_archive_index.ts +383 -0
- package/src/scripts/capture_skill_catalogue.ts +279 -317
- package/src/scripts/check_branch_freshness.ts +7 -1
- package/src/scripts/check_release_published.ts +6 -2
- package/src/scripts/check_release_trunk_sync.ts +18 -2
- package/src/scripts/check_source_size_budget.ts +428 -0
- package/src/scripts/check_suppression_hygiene.ts +5 -1
- package/src/scripts/condense.ts +50 -1
- package/src/scripts/cost/backfill_rates.mjs +298 -0
- package/src/scripts/cost/budget.mjs +12 -32
- package/src/scripts/cost_summary.ts +25 -0
- package/src/scripts/dispatch_r2_reviewer.ts +15 -5
- package/src/scripts/evidence_report.ts +15 -4
- package/src/scripts/external_sources_denylist.json +1 -0
- package/src/scripts/hook_manifest.yaml +75 -15
- package/src/scripts/hooks/concern_registry.ts +4 -0
- package/src/scripts/hooks/orchestration_record_hook.ts +21 -0
- package/src/scripts/hooks/skill_route_hook.ts +226 -0
- package/src/scripts/hooks/tool_result_bytes_hook.ts +219 -0
- package/src/scripts/hooks/ui_route_nudge_hook.ts +6 -3
- package/src/scripts/hot_context_hook.ts +13 -1
- package/src/scripts/install.ts +129 -0
- package/src/scripts/janitor.ts +77 -2
- package/src/scripts/lint_design_antipattern_parity.ts +40 -6
- package/src/scripts/lint_harvest_provenance.ts +35 -1
- package/src/scripts/lint_plan_risk_register.ts +22 -9
- package/src/scripts/lint_roadmap_blockers.ts +109 -6
- package/src/scripts/lint_rule_skill_pack_reach.ts +43 -0
- package/src/scripts/lint_scheduled_deprecations.ts +738 -0
- package/src/scripts/lint_skill_router_head.ts +21 -0
- package/src/scripts/mcp_server/consumer_tool_catalog.json +26 -3
- package/src/scripts/mcp_server/tool_catalog_source.ts +6 -24
- package/src/scripts/mcp_server/tools.ts +87 -0
- package/src/scripts/migration_status.ts +17 -1
- package/src/scripts/probe_review_binding_drift.ts +731 -0
- package/src/scripts/release.ts +100 -6
- package/src/scripts/routing_doctor.ts +50 -13
- package/src/scripts/schemas/command.schema.json +3 -3
- package/src/scripts/schemas/skill.schema.json +20 -2
- package/src/scripts/schemas/subagent.schema.json +2 -2
- package/src/scripts/session_eol_report.ts +81 -0
- package/src/scripts/trigger_coverage.ts +224 -3
- package/src/scripts/workspace_doctor.ts +464 -0
- package/src/scripts/worktree_cleanup_check.ts +2 -1
- package/src/server/schemas/settings.ts +2 -2
- package/dist/cli-delegate/chunk-AYKQGIBG.js +0 -1594
- package/src/config/budget-routing.json +0 -7
|
@@ -8,8 +8,10 @@ provider's model or billing rule.
|
|
|
8
8
|
|
|
9
9
|
## Inputs
|
|
10
10
|
|
|
11
|
-
- The sub-task's declared `model_tier` (`lite | medium | high |
|
|
12
|
-
per [`model-recommendations`](../model-recommendations.md)).
|
|
11
|
+
- The sub-task's declared `model_tier` (`lite | medium | high | frontier |
|
|
12
|
+
inherit`, per [`model-recommendations`](../model-recommendations.md)).
|
|
13
|
+
`frontier` (ADR-232) is declarable and opt-in; it is never the resolution of
|
|
14
|
+
`inherit` — see the top-band invariant below.
|
|
13
15
|
- `subagents.downshift`, `subagents.quota_arbitrage`, `subagents.model_map`
|
|
14
16
|
(see [`auto-orchestration-activation`](auto-orchestration-activation.md)).
|
|
15
17
|
- The host-capability manifest's `separate_quota_pool`
|
|
@@ -27,43 +29,154 @@ THE SAME MINUS THE QUOTA WIN.
|
|
|
27
29
|
1. **Downshift off** (`downshift: false`) → every sub-task runs on the session
|
|
28
30
|
tier. No routing change.
|
|
29
31
|
2. **Downshift on** → a sub-task runs on its declared tier; an `inherit` task
|
|
30
|
-
runs on the session tier
|
|
31
|
-
`model_map`; an empty entry means "use
|
|
32
|
-
baked-in provider model name.
|
|
32
|
+
runs on the session tier, **bounded by the top-band invariant below**. The
|
|
33
|
+
tier resolves to a model alias via `model_map`; an empty entry means "use
|
|
34
|
+
the tier's runtime default" — never a baked-in provider model name.
|
|
33
35
|
3. **Quota arbitrage** → prefer the **separate** quota pool for the sub-task
|
|
34
36
|
**only when** `subagents.quota_arbitrage == true` **and**
|
|
35
37
|
`manifest.separate_quota_pool == true`. Otherwise the shared pool is used and
|
|
36
38
|
the tier/model choice is unchanged. This is the only place the
|
|
37
39
|
"Sonnet-has-its-own-allowance" idea lives, and it lives as a runtime-detected
|
|
38
40
|
flag, never as portable prose.
|
|
39
|
-
4. **Budget routing
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
`
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
41
|
+
4. **Budget routing — ARCHIVED 2026-08-16, there is no fourth step.** This
|
|
42
|
+
position used to describe a budget relation applied after the tier resolves
|
|
43
|
+
per 1–3: cheapest classifier-adequate tier WITH available budget, an atomic
|
|
44
|
+
pre-dispatch reserve, a cool-down on quota errors. None of it exists any
|
|
45
|
+
more. A converged AI-council verdict (anthropic + openai, 2 of 2) archived
|
|
46
|
+
`pickTier` and the permit lifecycle, because the `routing_switch` they
|
|
47
|
+
required lost its only source when `subagents.budget_routing` was deliberately
|
|
48
|
+
deleted by always-on orchestration — so wiring meant inventing a replacement
|
|
49
|
+
for a removed category — and because `session_tier` sits non-null in 0 of 327
|
|
50
|
+
records, leaving the saving unmeasurable in principle. Migration record and
|
|
51
|
+
the union revisit-if:
|
|
52
|
+
[`budget-routing` contract](../../../../docs/contracts/budget-routing.md).
|
|
53
|
+
**Tier resolution therefore ends at step 3.** What survives of the module is
|
|
54
|
+
`TIER_ORDER` and `readCooldowns`, read by `routing:doctor` as a diagnostic —
|
|
55
|
+
monitoring, not routing, and note that nothing writes the cool-down file any
|
|
56
|
+
more, which is why the doctor reports that state as *unavailable, no
|
|
57
|
+
producer* rather than as a measured "not cooling".
|
|
58
|
+
|
|
59
|
+
### The top-band invariant (binding)
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
UNDER A TOP-BAND SESSION, `inherit` RESOLVES TO AT MOST `high`.
|
|
63
|
+
A SLICE THAT GENUINELY NEEDS THE SESSION'S OWN BAND DECLARES IT.
|
|
64
|
+
ONE TOP-BAND CONTEXT PER TASK — THE ORCHESTRATOR'S. NEVER A SECOND BY DEFAULT.
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Read as one line: an undeclared slice under a top-band session runs at most
|
|
68
|
+
`high`, never the session's own band.
|
|
69
|
+
|
|
70
|
+
`inherit` means *model-agnostic*, not *whatever the session happens to cost*.
|
|
71
|
+
Left unbounded it is the one declaration that silently buys the most expensive
|
|
72
|
+
band available, for exactly the slices whose authors judged the model choice
|
|
73
|
+
not to matter — the weakest possible reason to spend the most.
|
|
74
|
+
|
|
75
|
+
**The clamp is `high`, not the top mapped tier, and the distinction is not
|
|
76
|
+
cosmetic.** ADR-232 added `frontier` to the tier→model map, so the top *mapped*
|
|
77
|
+
rung is now `frontier`; clamping there would clamp nothing. The bound is the
|
|
78
|
+
top **generally-recommended** band, which is what
|
|
79
|
+
[`model-recommendations`](../model-recommendations.md) already states from the
|
|
80
|
+
other side — its `frontier` row reads *"Never the resolution of `inherit`"*.
|
|
81
|
+
This clause is that same rule written where the resolution actually happens.
|
|
82
|
+
|
|
83
|
+
Consequences, stated so the cost stays visible rather than removed:
|
|
84
|
+
|
|
85
|
+
- A slice that needs `frontier` **declares `model_tier: frontier`** — a value
|
|
86
|
+
§ Inputs above lists as declarable, precisely so this escape hatch is legal
|
|
87
|
+
rather than instructed-but-forbidden. The declaration is the whole point:
|
|
88
|
+
the spend becomes an authored decision with a name on it instead of a
|
|
89
|
+
default nobody chose.
|
|
90
|
+
- The clamp changes only the **undeclared** case. Every explicit
|
|
91
|
+
`model_tier:` is honoured verbatim, upward included.
|
|
92
|
+
- A session running *below* `high` is untouched — `inherit` still resolves to
|
|
93
|
+
the session tier. "At most" is a ceiling, never a floor, and this clause
|
|
94
|
+
never promotes a slice.
|
|
95
|
+
- A **declared `frontier` implementer** keeps its band, and its judge is
|
|
96
|
+
governed by [`subagent-configuration`](../subagent-configuration.md)
|
|
97
|
+
§ The judge cap — which handles that case explicitly rather than leaving
|
|
98
|
+
the reviewer weaker than the author.
|
|
99
|
+
|
|
100
|
+
**Honest scope.** This is a policy clause in a context file, so it binds the
|
|
101
|
+
agent that reads it and nothing else; no gate re-derives an `inherit`
|
|
102
|
+
resolution at dispatch time. `enforced_by: none`, deliberately — the same
|
|
103
|
+
boundary the safety-floor rules state for their own obligations.
|
|
104
|
+
|
|
105
|
+
### The non-escalation floor (binding)
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
A SLICE WHOSE DISPATCH OVERHEAD EXCEEDS THE SAVING FROM DOWNSHIFTING
|
|
109
|
+
STAYS IN-SESSION. SPLITTING WORK WHOSE OVERHEAD EATS ITS OWN SAVING
|
|
110
|
+
IS THE ANTI-GOAL, NOT THE MECHANISM WORKING.
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Every dispatch pays a fixed cost the in-session path does not: the slice's
|
|
114
|
+
prompt is re-sent to a fresh context, the return is read back, and the
|
|
115
|
+
orchestrator verifies it. Below some slice size that overhead exceeds
|
|
116
|
+
whatever the cheaper tier saved, and the delegation is a net loss dressed as
|
|
117
|
+
an optimisation.
|
|
118
|
+
|
|
119
|
+
**The floor is a rule, not a number — and the reason is measured, not
|
|
120
|
+
assumed.** The step that authored this clause expected the same-band spawn
|
|
121
|
+
distribution to supply the number. It cannot, and the corpus says so
|
|
122
|
+
precisely. Over the full 327-record `orchestration` corpus (2026-07 plus
|
|
123
|
+
2026-08):
|
|
124
|
+
|
|
125
|
+
| Field the saving model needs | Non-null records |
|
|
126
|
+
|---|---:|
|
|
127
|
+
| `dispatch_tokens` | 40 |
|
|
128
|
+
| `tier_chosen` | 1 |
|
|
129
|
+
| `session_tier` | **0** |
|
|
130
|
+
|
|
131
|
+
The three must co-occur on one dispatch to model a reduction, so the usable
|
|
132
|
+
intersection is **zero**. This is not a small sample — it is an empty one, and
|
|
133
|
+
`orchestration_savings_report.ts` already prints exactly that conclusion
|
|
134
|
+
(`MODELED cost reduction: n/a (needs dispatch_tokens + session_tier +
|
|
135
|
+
tier_chosen on a dispatch)`). `token_delta` does not rescue it: the hook
|
|
136
|
+
writes it as a constant `0` with provenance `estimated`, deliberately, because
|
|
137
|
+
no in-session counterfactual exists on disk to difference against.
|
|
138
|
+
|
|
139
|
+
So the floor binds as a judgement with a named direction rather than a
|
|
140
|
+
threshold:
|
|
141
|
+
|
|
142
|
+
- **Default to in-session** when the slice is small enough that stating it
|
|
143
|
+
costs about as much as doing it — a single-file edit, one grep, one
|
|
144
|
+
question with a known answer.
|
|
145
|
+
- **Delegate** when the slice carries its own reading (a file set to sweep, an
|
|
146
|
+
independent verification, a search whose output you do not want in context)
|
|
147
|
+
— there the returned conclusion is the saving, and it is not in tokens.
|
|
148
|
+
- **Never delegate to hit a target.** A dispatch count is not an outcome.
|
|
149
|
+
|
|
150
|
+
*Revisit-if:* a single dispatch record carries `dispatch_tokens`,
|
|
151
|
+
`session_tier` and `tier_chosen` together. At that point the floor is
|
|
152
|
+
computable and this clause should be replaced by the number, not amended
|
|
153
|
+
toward it. Filling `session_tier` is the blocking gap — it exists in the
|
|
154
|
+
schema and on the manual `orchestration_record` CLI path (`--session-tier`),
|
|
155
|
+
and the hook that produced all 327 records never sets it.
|
|
59
156
|
|
|
60
157
|
**Cache trade-off (road-to-cache-economy Phase 4).** A tier downshift changes
|
|
61
|
-
the sub-task's model, and the prompt cache is keyed by `(model, prefix)
|
|
62
|
-
a downshifted leg forfeits its model-scoped cache reads AND
|
|
63
|
-
shared prefix into two caches (downshifted legs vs.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
158
|
+
the sub-task's model, and the prompt cache is keyed by `(model, prefix)`. The
|
|
159
|
+
concern was that a downshifted leg forfeits its model-scoped cache reads AND
|
|
160
|
+
splits a cohort's shared prefix into two caches (downshifted legs vs.
|
|
161
|
+
session-tier legs).
|
|
162
|
+
|
|
163
|
+
**Measured 2026-08-16 —
|
|
164
|
+
[`downshift-vs-cache.md`](../../../../agents/evidence/analysis/downshift-vs-cache.md),
|
|
165
|
+
611 subagent legs / 16,612 calls.** The first half does not hold: a subagent
|
|
166
|
+
leg's **first call realizes 2.8 % cache read**, so it starts cold and does not
|
|
167
|
+
inherit the session's cache — a downshift forfeits a cache the leg never had.
|
|
168
|
+
The cache is not lost, it is created on the other model and then read for the
|
|
169
|
+
rest of the leg (median 18 calls per leg, ~96.9 % read share). The second half
|
|
170
|
+
is **not measured** — nothing sizes cohort prefix sharing — but it is bounded
|
|
171
|
+
above: prefix splitting is a write-side cost, and writes are **3.1 %** of
|
|
172
|
+
subagent billable input against a 96.9 % read surface. Even attributing every
|
|
173
|
+
write to splitting, the two sit about an order of magnitude apart, in favour of
|
|
174
|
+
the downshift, so the direction does not depend on the unmeasured fraction.
|
|
175
|
+
|
|
176
|
+
This resolves the direction; it does not license downshifting as a target. The
|
|
177
|
+
cold start is paid per leg regardless of tier, which is precisely what the
|
|
178
|
+
non-escalation floor above bounds. Analogous downgrade/cache coupling on the
|
|
179
|
+
council side: see
|
|
67
180
|
[`docs/contracts/ai-council-config.md`](../../../../docs/contracts/ai-council-config.md)
|
|
68
181
|
§ `model_downgrade` for the analogous downgrade/cache coupling this suite
|
|
69
182
|
already ships on the council side.
|
|
@@ -80,8 +193,10 @@ rule, or context asserts "model X is free".
|
|
|
80
193
|
[`src/scripts/_lib/subagent_routing.ts`](../../../../src/scripts/_lib/subagent_routing.ts)
|
|
81
194
|
(`resolveSubagentRouting`), covered by
|
|
82
195
|
[`tests/scripts/_lib_subagent_routing.test.ts`](../../../../tests/scripts/_lib_subagent_routing.test.ts).
|
|
83
|
-
|
|
84
|
-
|
|
196
|
+
Tier vocabulary + cool-down state:
|
|
197
|
+
[`src/scripts/_lib/tier_budget_routing.ts`](../../../../src/scripts/_lib/tier_budget_routing.ts)
|
|
198
|
+
(`TIER_ORDER`, `readCooldowns` — the budget decision layer that used to live
|
|
199
|
+
there is archived, see step 4), covered by
|
|
85
200
|
[`tests/scripts/tier_budget_routing.test.ts`](../../../../tests/scripts/tier_budget_routing.test.ts);
|
|
86
201
|
live state: `agent-config routing:doctor` (orchestration section).
|
|
87
202
|
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
# Model Recommendations
|
|
2
2
|
|
|
3
3
|
Loaded by the `model-recommendation` rule. Expresses recommendations as
|
|
4
|
-
**vendor-neutral capability tiers** (`lite | medium | high
|
|
5
|
-
vendor model names. Each agent resolves a
|
|
6
|
-
band; the package's only tier→model mapping
|
|
7
|
-
(`high→opus`, `medium→sonnet`,
|
|
4
|
+
**vendor-neutral capability tiers** (`lite | medium | high | frontier`,
|
|
5
|
+
ADR-035 as amended by ADR-232), never vendor model names. Each agent resolves a
|
|
6
|
+
tier to its own best model in that band; the package's only tier→model mapping
|
|
7
|
+
is the Claude generator's (`frontier→fable`, `high→opus`, `medium→sonnet`,
|
|
8
|
+
`lite→haiku`).
|
|
8
9
|
|
|
9
10
|
## Tier Profiles
|
|
10
11
|
|
|
11
12
|
| Tier | Band | Claude resolution | Use for |
|
|
12
13
|
|---|---|---|---|
|
|
14
|
+
| `frontier` | above the strongest generally-recommended band | Fable | **Opt-in, expected to stay rare.** Declare it only where the work genuinely needs capability beyond `high` — the point of the band is that such work *says so* rather than inheriting the session's model silently. Never the resolution of `inherit` |
|
|
13
15
|
| `high` | strongest reasoning | Opus | Architecture, refactoring, complex debugging, code review, design decisions, multi-file changes, large-scale analysis / research / planning |
|
|
14
16
|
| `medium` | balanced daily | Sonnet (latest) | Daily coding, known-cause bug fixes, tests, single-layer features, quality checks, config, documentation, implementation after a `high`-tier plan |
|
|
15
17
|
| `lite` | fastest / cheapest | Haiku | Trivial mechanical edits — formatting, one-line config, rote renames, boilerplate stamping |
|
|
@@ -15,21 +15,83 @@ Loaded by the `subagent-orchestration` skill and the `/do-and-judge`,
|
|
|
15
15
|
## Model tier ladder
|
|
16
16
|
|
|
17
17
|
The "one tier up" fallback walks this ladder. Session model is the
|
|
18
|
-
starting point; judge picks the tier above.
|
|
18
|
+
starting point; judge picks the tier above. The ladder is written in
|
|
19
|
+
**bands**, not vendor models — the package keeps exactly one tier→model
|
|
20
|
+
mapping and it lives in
|
|
21
|
+
[`model-recommendations`](model-recommendations.md) (ADR-035 § 3). A
|
|
22
|
+
second per-vendor ladder here would be the two-clocks drift ADR-232 was
|
|
23
|
+
careful not to create.
|
|
19
24
|
|
|
20
25
|
```
|
|
21
|
-
|
|
26
|
+
lite → medium → high
|
|
22
27
|
```
|
|
23
28
|
|
|
24
|
-
If the session runs
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
If the session runs at **`high`**, judge stays at `high`. If the session
|
|
30
|
+
runs at **`medium`**, judge defaults to `high`. If the session runs at
|
|
31
|
+
**`lite`**, judge defaults to `medium`.
|
|
32
|
+
|
|
33
|
+
### The judge cap (binding)
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
THE ONE-TIER-UP ESCALATION STOPS AT `high` — IT NEVER CLIMBS INTO `frontier`.
|
|
37
|
+
A JUDGE IS NEVER BELOW ITS OWN IMPLEMENTER: A DECLARED `frontier`
|
|
38
|
+
IMPLEMENTER KEEPS A `frontier` JUDGE.
|
|
39
|
+
A SATURATED LADDER ESCALATES CROSS-VENDOR VIA THE COUNCIL —
|
|
40
|
+
NEVER INTO A SECOND SAME-VENDOR TOP-BAND AGENT.
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Two clauses that are easy to collapse into one and must not be. The cap
|
|
44
|
+
binds the **escalation**, not the floor:
|
|
45
|
+
|
|
46
|
+
| Implementer band | Judge band | Why |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| `lite` | `medium` | one tier up |
|
|
49
|
+
| `medium` | `high` | one tier up |
|
|
50
|
+
| `high` | `high` | escalation capped — never climbs into `frontier` |
|
|
51
|
+
| `frontier` | **`frontier`** | the floor wins: a judge is never below its author |
|
|
52
|
+
|
|
53
|
+
`frontier` (ADR-232) sits above `high` in the vocabulary, so a naive
|
|
54
|
+
"one tier up" would resolve a `high` implementer's judge to `frontier`
|
|
55
|
+
and buy the most expensive band available for every verification pass.
|
|
56
|
+
The cap forecloses that — `frontier` is opt-in by declaration only.
|
|
57
|
+
|
|
58
|
+
**But the cap must not invert the ladder it protects.** Reading it as a
|
|
59
|
+
flat ceiling would give a declared `frontier` implementer a `high`
|
|
60
|
+
judge, i.e. a reviewer strictly *weaker* than the author — worse than
|
|
61
|
+
the same-band case the one-tier-up rule exists to avoid, and a direct
|
|
62
|
+
contradiction of "never downshifts its judge below what the verify
|
|
63
|
+
contract requires" below. So `frontier` reaches the judge only where
|
|
64
|
+
the implementer already declared it, never by escalation from `high`.
|
|
65
|
+
|
|
66
|
+
**What to do when the ladder saturates.** At `high` and at `frontier`
|
|
67
|
+
the judge is same-band — the reviewer is no stronger than the author,
|
|
68
|
+
which is the condition the one-tier-up rule existed to avoid. The
|
|
69
|
+
answer is *different vendor*, not *bigger model*:
|
|
70
|
+
|
|
71
|
+
- Route the saturation case through
|
|
72
|
+
[`ai-council`](../skills/ai-council/SKILL.md), which polls models
|
|
73
|
+
outside the host session (Anthropic + OpenAI) and is therefore
|
|
74
|
+
genuinely independent of the implementer's framing.
|
|
75
|
+
- This is the escalation **instead of** a second top-band context, not
|
|
76
|
+
in addition to one. Two same-vendor top-band agents on one task cost
|
|
77
|
+
twice and correlate their blind spots; a second vendor costs less and
|
|
78
|
+
disagrees for real reasons.
|
|
79
|
+
- Cost boundary unchanged: the council is a network call and is
|
|
80
|
+
therefore never automatic. It is what the saturation case escalates
|
|
81
|
+
*to* when a second opinion is wanted, not a step every `high` task
|
|
82
|
+
takes ([`ai-council`](../skills/ai-council/SKILL.md) § Do NOT use).
|
|
83
|
+
|
|
84
|
+
**Honest scope.** This is policy prose in a context file — it binds the
|
|
85
|
+
agent that reads it and no gate re-derives a judge tier at dispatch
|
|
86
|
+
time. `enforced_by: none`, stated rather than implied.
|
|
27
87
|
|
|
28
88
|
**Downshift never touches the judge.** When cost-aware routing runs an
|
|
29
89
|
implementer on a downshifted tier (per the category → tier defaults in
|
|
30
90
|
[`model-recommendations § Subagent Category → Tier Defaults`](model-recommendations.md)),
|
|
31
|
-
the judge still resolves one tier above the IMPLEMENTER's resolved tier
|
|
32
|
-
|
|
91
|
+
the judge still resolves one tier above the IMPLEMENTER's resolved tier,
|
|
92
|
+
**with the escalation capped at `high` per the judge cap above** — so a
|
|
93
|
+
`lite` implementer gets at least a `medium` judge, and no *downshifted*
|
|
94
|
+
implementer escalates its judge into `frontier`. Downshifting an
|
|
33
95
|
implementer never downshifts its judge below what the verify contract
|
|
34
96
|
requires, and a judge is never `lite`.
|
|
35
97
|
|
|
@@ -67,7 +67,7 @@ ALLOWLIST > 20 ENTRIES IN ONE SESSION = THE LINTER IS WRONG.
|
|
|
67
67
|
STOP. PROPOSE LINTER REDESIGN OR REMOVAL. DO NOT EXPAND THE ALLOWLIST FURTHER.
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
Crossing 20 entries counts as the 3rd validation-target failure — fix the tool shape, not the list. Enforced at tool-call time by the `block-config-weakening` PreToolUse guard (`src/scripts/hooks/block_config_weakening.ts`) **on the
|
|
70
|
+
Crossing 20 entries counts as the 3rd validation-target failure — fix the tool shape, not the list. Enforced at tool-call time by the `block-config-weakening` PreToolUse guard (`src/scripts/hooks/block_config_weakening.ts`) **on `claude`, the one host that both binds `pre_tool_use` and honours a deny**: it counts allowlist entries added per session, warns from 5, and blocks past 20. It is *bound* on augment and cowork as well, and ignored there — `host_semantics.ts` verifies claude alone, and both trampolines discard dispatcher output and `exit 0` unconditionally. Everywhere else the cap is model-carried and "enforced at tool-call time" is not a claim this rule can make. **Corrected 2026-08-17 in both directions:** this sentence used to certify augment, claude and cowork as the enforcing set (an over-claim of two hosts) and to explain the rest with "the guard has nowhere to bind" (false for cursor, cline and gemini, whose native pre-tool events `native_event_aliases` already maps onto `pre_tool_use` — unbound, not unbindable; only windsurf and copilot have no pre-tool surface). The four states are tabulated once in [`hook-architecture-v1 § Which hosts carry pre_tool_use`](../docs/contracts/hook-architecture-v1.md). Run `agent-config hooks:status` to see which slots are bound on the host you are actually on — the sibling rules `git-history-discipline` and `evaluator-independence` qualify the identical slot, and an unqualified claim here would read as a guarantee the manifest does not give. Baselines and budget thresholds warn only — a rising count there may be a legitimate ratchet reset, which the edit alone cannot distinguish. Verify with the narrowest tool that proves the target green (a single `curl` / Playwright spec for HTTP/UI, the test runner with a `--filter`, an `xdebug` step-through) — never a meta-pipeline as per-iteration probe. Failed-attempt detail, suppression-sweep equivalents, probe-efficiency detail, and adaptive effort & stop (RDP): [`autonomy-mechanics § Validation-loop budget`](../contexts/execution/autonomy-mechanics.md).
|
|
71
71
|
|
|
72
72
|
Body migrated to `contexts/execution/autonomy-mechanics.md` (per P4 of `road-to-kernel-and-router.md`) — opt-in detection summary, task-scope shapes table, N=3 mechanics, allowlist-antipattern detail, probe efficiency, adaptive effort (RDP).
|
|
73
73
|
Trigger-set above activates this routing on demand, independent of the discipline profile (ADR-110).
|
|
@@ -171,7 +171,7 @@ introduced. The row that would have caught it is
|
|
|
171
171
|
and it exists only because a review asked for it after the trigger had already
|
|
172
172
|
shipped. Write that row first next time; it is the cheap half.
|
|
173
173
|
|
|
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.
|
|
174
|
+
Body migrated to [`guideline:design-fidelity-mechanics`](../docs/guidelines/design-fidelity-mechanics.md) (per P4 of `road-to-kernel-and-router.md`) — URL / live-page handover (extraction into the `design-system.json` contract before the first UI write, the retrieval order, the lock boundary), 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.
|
|
175
175
|
Trigger-set above activates this routing on demand, independent of the discipline profile (ADR-110).
|
|
176
176
|
|
|
177
177
|
## See also
|
|
@@ -114,11 +114,16 @@ still have no runtime consumer. A test — not a code path — keeps the two fro
|
|
|
114
114
|
drifting: `ui_rule_triggers.test.ts` asserts every `file_pattern` declared here
|
|
115
115
|
is accepted by that predicate.
|
|
116
116
|
|
|
117
|
-
Warn-only, capped at two nudges per session, default-OFF, bound only
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
117
|
+
Warn-only, capped at two nudges per session, default-OFF, and bound only in the
|
|
118
|
+
three `platforms:` rows that carry a `pre_tool_use` key — augment, claude,
|
|
119
|
+
cowork (**clarified 2026-08-17**: "hosts carrying a slot" read as a host
|
|
120
|
+
property and is a manifest one; three further hosts alias a native pre-tool
|
|
121
|
+
event with no binding, and only claude honours a deny — see
|
|
122
|
+
[`hook-architecture-v1 § Which hosts carry pre_tool_use`](../docs/contracts/hook-architecture-v1.md)).
|
|
123
|
+
The verdict is unchanged either way: a nudge that can be ignored is not
|
|
124
|
+
enforcement, so `enforced_by:` stays `none` — it moves the day a mechanism can
|
|
125
|
+
refuse, not the day a reminder appears. `agent-config hooks:status` answers
|
|
126
|
+
whether the concern is bound on the host you are actually on.
|
|
122
127
|
|
|
123
128
|
What that leaves, and it is the useful part: the write side now has a named
|
|
124
129
|
obligation and a route to the skill that discharges it, where before it had
|
|
@@ -95,13 +95,35 @@ Three limits, stated because they were measured. The pre-loaded-verdict list is
|
|
|
95
95
|
a **phrase list**, so a paraphrase evades it — it catches recurrences of known
|
|
96
96
|
steering wording, not steering as such. The turn boundary is the
|
|
97
97
|
authorization ledger's `detected_at` stamp, because the envelope carries no turn
|
|
98
|
-
id; with no ledger yet, the counter falls back to session scope. And the
|
|
99
|
-
|
|
100
|
-
claude, cowork
|
|
101
|
-
|
|
102
|
-
frequency join in `check_enforcement_coverage.ts` reports exactly that set, and
|
|
98
|
+
id; with no ledger yet, the counter falls back to session scope. And the guard
|
|
99
|
+
does not deny everywhere it exists: `pre_tool_use` is **bound** on three hosts —
|
|
100
|
+
augment, claude, cowork — and only `claude` honours the deny. Everywhere else,
|
|
101
|
+
augment and cowork included, items 1 and 4 join 2 and 3 as model-carried.
|
|
103
102
|
`agent-config hooks:status` answers it for the host you are on right now.
|
|
104
103
|
|
|
104
|
+
**Corrected 2026-08-17 — this paragraph was wrong on both sides of the line it
|
|
105
|
+
drew.** It said `pre_tool_use` "exists on three hosts" and that the guard has
|
|
106
|
+
"nowhere to bind" on the other five. Neither half survived a re-read of the
|
|
107
|
+
tree. **Downward:** the manifest's own `native_event_aliases` table already maps
|
|
108
|
+
`preToolUse` (cursor), `PreToolUse` (cline) and `BeforeTool` (gemini) onto
|
|
109
|
+
`pre_tool_use`, so there the guard is **unbound, not unbindable**; only windsurf
|
|
110
|
+
and copilot carry no pre-tool surface at all. **Upward, and worse:**
|
|
111
|
+
`host_semantics.ts` certifies **claude alone**, and the augment and cowork
|
|
112
|
+
trampolines discard dispatcher output and `exit 0` unconditionally — so on two
|
|
113
|
+
of the three "enforcing" hosts this guard runs and is then ignored. Nor may the
|
|
114
|
+
inverse be asserted downward: nothing records whether an unbound host's
|
|
115
|
+
pre-tool event can *deny*, and `severity: blocking` is a property of the concern
|
|
116
|
+
rather than of the host. The four states are tabulated once in
|
|
117
|
+
[`hook-architecture-v1 § Which hosts carry pre_tool_use`](../docs/contracts/hook-architecture-v1.md).
|
|
118
|
+
|
|
119
|
+
Stated at this length because this rule exists over a case where a process that
|
|
120
|
+
*looked* followed produced fabricated evidence. An unbacked reason for a real
|
|
121
|
+
gap and an unmeasured claim of enforcement are the same failure in a smaller
|
|
122
|
+
font, and this paragraph had shipped one of each. Note also what the frequency
|
|
123
|
+
join actually reports: `check_enforcement_coverage.ts` skips `fallback_only`
|
|
124
|
+
platforms, so its gap set is **four** — cursor, cline, windsurf, gemini — never
|
|
125
|
+
copilot, which is excluded by declaration rather than measured as a gap.
|
|
126
|
+
|
|
105
127
|
Items 2 and 3 — an honestly chosen scope, and recording the prompt with the
|
|
106
128
|
verdict — are **not** enforced by anything. A narrowed scope is not decidable
|
|
107
129
|
from the prompt alone, and no validator reads the artefacts a verdict lands in.
|
|
@@ -84,4 +84,8 @@ Trigger-set above activates this routing on demand, independent of the disciplin
|
|
|
84
84
|
- [`commit-policy`](commit-policy.md) — commits are the user's call; rewriting them is a stronger version of the same restriction.
|
|
85
85
|
- [`token-efficiency`](token-efficiency.md) — Iron Law on burning the user's tokens for cosmetic gain.
|
|
86
86
|
- [`skill:git-workflow`](../skills/git-workflow/SKILL.md) — Safe Squash-After-Push protocol and Divergent-State Recovery decision tree.
|
|
87
|
-
- `git … --no-verify` / `core.hooksPath` overrides — deterministically blocked by the `block-no-verify` PreToolUse guard (`src/scripts/hooks/block_no_verify.ts`, registered in `hook_manifest.yaml`) **on the
|
|
87
|
+
- `git … --no-verify` / `core.hooksPath` overrides — deterministically blocked by the `block-no-verify` PreToolUse guard (`src/scripts/hooks/block_no_verify.ts`, registered in `hook_manifest.yaml`) **on `claude`, the one host that both binds `pre_tool_use` and honours a deny**. It is *bound* on augment and cowork too, and ignored there. Everywhere else the Iron Laws above are model-carried and "deterministically blocked" is not a claim this rule can make. To check the host you are on rather than trusting this sentence, run `agent-config hooks:status`.
|
|
88
|
+
|
|
89
|
+
**Corrected 2026-08-17, in both directions, because this line was wrong on each side.** It read "the guard has nowhere to bind" on cursor, cline, windsurf, gemini and copilot — refuted for three of the five by the manifest's own `native_event_aliases` table, which already maps `preToolUse`, `PreToolUse` and `BeforeTool` onto `pre_tool_use`: there the guard is **unbound, not unbindable**, and only windsurf and copilot carry no pre-tool surface. And it certified augment, claude and cowork as the enforcing set — `host_semantics.ts` verifies **claude alone**, while the augment and cowork trampolines discard dispatcher output and `exit 0` unconditionally, so a guard bound there runs and is then ignored. Both halves are the same failure: a host-capability claim this tree never established. The four states are tabulated once in [`hook-architecture-v1 § Which hosts carry pre_tool_use`](../docs/contracts/hook-architecture-v1.md).
|
|
90
|
+
|
|
91
|
+
The frequency join in `check_enforcement_coverage.ts` reports this obligation uncovered on **four** platforms — cursor, cline, windsurf, gemini. It skips `fallback_only` platforms before computing, so copilot never appears in its output and must not be quoted as if it did; copilot is uncovered for the separate reason that it has no hook surface at all.
|
|
@@ -4,6 +4,7 @@ tier: "1"
|
|
|
4
4
|
description: "Writing/upstreaming low-impact-decisions corpus entries — non-bypassable privacy floor"
|
|
5
5
|
triggers:
|
|
6
6
|
- path_prefix: "agents/decisions/low-impact-decisions"
|
|
7
|
+
- path_prefix: "data/low-impact-decisions-seed"
|
|
7
8
|
- keyword: "low-impact-decisions"
|
|
8
9
|
- keyword: "low-impact corpus"
|
|
9
10
|
- keyword: "learn-low-impact"
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: "auto"
|
|
3
|
+
tier: "2a"
|
|
4
|
+
description: "A skill exists in the tree but not in the host's catalogue — ask for it by TASK via suggest_skill_for_task, never conclude it does not exist"
|
|
5
|
+
triggers:
|
|
6
|
+
- phrase: "skill not found"
|
|
7
|
+
- phrase: "no such skill"
|
|
8
|
+
- phrase: "skill does not exist"
|
|
9
|
+
- phrase: "kein passendes skill"
|
|
10
|
+
- phrase: "which skill"
|
|
11
|
+
- phrase: "welches skill"
|
|
12
|
+
applies_to_user_types:
|
|
13
|
+
- "developer"
|
|
14
|
+
- "maintainer"
|
|
15
|
+
self_contained: true
|
|
16
|
+
workspaces: [engineering]
|
|
17
|
+
packs: [meta]
|
|
18
|
+
# obligation: line 41
|
|
19
|
+
obligation_frequency: "per-turn"
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
# Missing-Skill Recovery
|
|
23
|
+
|
|
24
|
+
The catalogue a host shows you is not the catalogue that exists. Hosts truncate,
|
|
25
|
+
and at least one truncates hard: measured 2026-08-16 on a default install, the
|
|
26
|
+
host published its own budget event stating it had stripped every description
|
|
27
|
+
and dropped **402 entries** from the model-visible skills list
|
|
28
|
+
(`agents/evidence/analysis/scoped-projection-host-delivery.md`). Scoping the
|
|
29
|
+
projection moved that to 330 and stripped the descriptions anyway.
|
|
30
|
+
|
|
31
|
+
402 is the **host's own count against the host's own denominator**, which is not
|
|
32
|
+
this package's: the same install projects 297 skills, so the figure is a
|
|
33
|
+
magnitude, never a subtraction anyone can perform. What it establishes is that
|
|
34
|
+
most of the catalogue is not model-visible — which is all this rule needs.
|
|
35
|
+
|
|
36
|
+
So "I do not see a skill for this" is evidence about the **delivery**, never
|
|
37
|
+
about the tree.
|
|
38
|
+
|
|
39
|
+
## The Iron Law
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
A SKILL MISSING FROM THE HOST CATALOGUE IS NOT A SKILL THAT DOES NOT EXIST.
|
|
43
|
+
NEVER CONCLUDE "NO SKILL COVERS THIS" FROM THE LIST YOU WERE SHOWN.
|
|
44
|
+
ASK BY TASK — `suggest_skill_for_task` RANKS THE TREE, NOT THE CATALOGUE.
|
|
45
|
+
NEVER REBUILD A CAPABILITY BECAUSE ITS SKILL WAS NOT DELIVERED.
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## What to do
|
|
49
|
+
|
|
50
|
+
1. **Ask by task, not by name.** A name you cannot see is a name you cannot
|
|
51
|
+
type; a task description always works. The `suggest_skill_for_task` MCP tool
|
|
52
|
+
ranks `SKILL.md` frontmatter over the source tree and returns names, scores
|
|
53
|
+
and personas — no bodies, so a wrong rank costs one read.
|
|
54
|
+
2. **Open the winner and check it yourself.** The ranker is deterministic
|
|
55
|
+
keyword scoring, not judgement. A high score is a pointer, not a verdict.
|
|
56
|
+
3. **Say which source answered.** "The catalogue had no entry, the ranker
|
|
57
|
+
found `X`" is a different claim from "there is no skill for this", and a
|
|
58
|
+
reader cannot reconstruct which one you meant from silence.
|
|
59
|
+
4. **If nothing scores, say that** — and proceed without a skill rather than
|
|
60
|
+
inventing one. A ranked empty list and an unreachable catalogue are
|
|
61
|
+
different answers; the tool distinguishes them (`status: no_catalogue`) and
|
|
62
|
+
so should you.
|
|
63
|
+
|
|
64
|
+
## When NOT to fire
|
|
65
|
+
|
|
66
|
+
- The skill you need was delivered and is in front of you. This rule is for the
|
|
67
|
+
gap, not for routine skill selection.
|
|
68
|
+
- The task genuinely has no skill and you already checked by task. Checking
|
|
69
|
+
twice is the loop, not the discipline.
|
|
70
|
+
- A host that delivers its catalogue whole — the rule costs nothing there and
|
|
71
|
+
simply never has a gap to close.
|
|
72
|
+
|
|
73
|
+
## Honest enforcement — `enforced_by: none`
|
|
74
|
+
|
|
75
|
+
Nothing can observe an agent concluding "no skill exists". The `skill-route`
|
|
76
|
+
concern injects ranked pointers on `user_prompt_submit` when its floor is
|
|
77
|
+
cleared, which covers the prompts where the ranker is confident and by
|
|
78
|
+
construction covers no others: it is silent on ~86 % of prompts by design. This
|
|
79
|
+
rule is the model-carried half for the rest, and it is stated as such rather
|
|
80
|
+
than implied to be caught by the concern.
|
|
81
|
+
|
|
82
|
+
## See also
|
|
83
|
+
|
|
84
|
+
- [`code-intelligence`](../skills/code-intelligence/SKILL.md) — the same
|
|
85
|
+
shape for source code: query the index first, fall back, name the source.
|
|
86
|
+
- [`external-code-graph-interop`](external-code-graph-interop.md) — its rule-side
|
|
87
|
+
twin, and the model this rule's trigger set follows.
|
|
88
|
+
- `src/scripts/skill_tools/score_skill_relevance.ts` — the ranker itself, and
|
|
89
|
+
the one place its scoring is defined.
|
|
@@ -121,10 +121,15 @@ every `file_pattern` declared here is accepted by that predicate. The predicate
|
|
|
121
121
|
is deliberately wider (it also covers `.css`, `.scss`, `.astro`), because a
|
|
122
122
|
measurement denominator and a routing trigger are not the same population.
|
|
123
123
|
|
|
124
|
-
Warn-only, capped at two per session, default-OFF, bound only
|
|
125
|
-
`
|
|
126
|
-
|
|
127
|
-
|
|
124
|
+
Warn-only, capped at two per session, default-OFF, and bound only in the three
|
|
125
|
+
`platforms:` rows that carry a `pre_tool_use` key — augment, claude, cowork
|
|
126
|
+
(**clarified 2026-08-17**: "where a slot exists" read as a host property, and it
|
|
127
|
+
is a manifest one; three further hosts alias a native pre-tool event without a
|
|
128
|
+
binding, and only claude honours a deny at all — the four states are tabulated
|
|
129
|
+
in [`hook-architecture-v1 § Which hosts carry pre_tool_use`](../docs/contracts/hook-architecture-v1.md)).
|
|
130
|
+
None of that changes the verdict here: a reminder that can be ignored is not a
|
|
131
|
+
gate, so `enforced_by:` stays `none`. Run `agent-config hooks:status` for the
|
|
132
|
+
host you are on rather than trusting this sentence.
|
|
128
133
|
|
|
129
134
|
## Failure modes
|
|
130
135
|
|
|
@@ -403,6 +403,38 @@ function _regen_dashboard(root: string, dry_run: boolean): void {
|
|
|
403
403
|
}
|
|
404
404
|
}
|
|
405
405
|
|
|
406
|
+
/**
|
|
407
|
+
* Rebuild the archive index after a move, when the builder is present.
|
|
408
|
+
*
|
|
409
|
+
* The sweep is the one operation that changes what `agents/roadmaps/archive/`
|
|
410
|
+
* contains, so it is the one operation that can leave the generated index
|
|
411
|
+
* stale — and the drift gate on that index runs in the same PR the sweep runs
|
|
412
|
+
* in. Regenerating here keeps the two from disagreeing by construction rather
|
|
413
|
+
* than by remembering.
|
|
414
|
+
*
|
|
415
|
+
* `build_archive_index` is package-internal (`src/scripts/`), while this sweep
|
|
416
|
+
* is projected into consumer installs that carry no such script. Absent
|
|
417
|
+
* builder → nothing to regenerate, and that is a normal consumer state, not a
|
|
418
|
+
* failure. The spawn is best-effort for the same reason `_regen_dashboard` is:
|
|
419
|
+
* a sweep that archived correctly must not report failure because a
|
|
420
|
+
* regeneration could not run.
|
|
421
|
+
*/
|
|
422
|
+
function _regen_archive_index(root: string, dry_run: boolean): void {
|
|
423
|
+
if (dry_run) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
const script = path.join(root, 'src', 'scripts', 'build_archive_index.ts');
|
|
427
|
+
if (!_isFile(script)) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
_runTwin(root, script);
|
|
431
|
+
for (const rel of ['agents/roadmaps/archive/INDEX.md', 'agents/roadmaps/archive/index.json']) {
|
|
432
|
+
if (_isFile(path.join(root, rel))) {
|
|
433
|
+
_run(['git', 'add', '--', rel], root);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
406
438
|
/** Spawn the dashboard generator twin (tsx) with cwd=root, mirroring `[sys.executable, script]`. */
|
|
407
439
|
function _runTwin(root: string, script: string): void {
|
|
408
440
|
// Python uses `sys.executable` — the interpreter already running this
|
|
@@ -491,6 +523,7 @@ function main(argv?: readonly string[]): number {
|
|
|
491
523
|
return 0;
|
|
492
524
|
}
|
|
493
525
|
_regen_dashboard(root, ns.dry_run);
|
|
526
|
+
_regen_archive_index(root, ns.dry_run);
|
|
494
527
|
const verb = ns.dry_run ? 'Would archive' : 'Archived';
|
|
495
528
|
for (const rec of archived) {
|
|
496
529
|
process.stdout.write(
|