@event4u/agent-config 12.1.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 +151 -0
- package/README.md +1 -1
- 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/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/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/update_roadmap_progress.ts +17 -2
- 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 +4 -4
- 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/cli-delegate/{chunk-O52B4F5S.js → chunk-3B72LSZL.js} +1 -1
- package/dist/cli-delegate/{chunk-55WZN5VF.js → chunk-EVTY7ISR.js} +2 -2
- package/dist/cli-delegate/{chunk-K34QTSD5.js → chunk-N7FEST6D.js} +17 -17
- package/dist/cli-delegate/{chunk-LKZ5DOYW.js → chunk-XURJ4AQC.js} +11 -3
- package/dist/cli-delegate/cmd_conformance.js +2 -2
- 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 +43 -22
- 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 +936 -346
- package/dist/install/install.mjs +12 -4
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1192 -160
- package/dist/router.json +1 -1
- package/dist/server/schemas/settings.js +2 -2
- package/dist/server/schemas/settings.js.map +1 -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/update_roadmap_progress.ts +17 -2
- package/src/config/evaluator-budgets.json +5 -4
- package/src/config/gate-coverage.yml +33 -11
- package/src/config/gate-violation-baselines.json +9 -3
- package/src/config/hook-token-budget.json +8 -1
- 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/skill_catalogue.ts +258 -5
- package/src/scripts/_lib/tier_budget_routing.ts +31 -331
- package/src/scripts/ai_council/clients.ts +21 -21
- 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 +107 -2
- package/src/scripts/check_source_size_budget.ts +428 -0
- package/src/scripts/check_suppression_hygiene.ts +5 -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/external_sources_denylist.json +1 -0
- package/src/scripts/hook_manifest.yaml +28 -2
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/skill_route_hook.ts +226 -0
- package/src/scripts/hooks/ui_route_nudge_hook.ts +6 -3
- package/src/scripts/lint_design_antipattern_parity.ts +40 -6
- package/src/scripts/lint_harvest_provenance.ts +35 -1
- package/src/scripts/lint_rule_skill_pack_reach.ts +43 -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/release.ts +5 -5
- package/src/scripts/routing_doctor.ts +50 -13
- package/src/scripts/schemas/command.schema.json +1 -1
- package/src/scripts/schemas/skill.schema.json +18 -1
- package/src/scripts/trigger_coverage.ts +224 -3
- package/src/server/schemas/settings.ts +2 -2
- package/src/config/budget-routing.json +0 -7
|
@@ -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.
|
|
@@ -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(
|
|
@@ -380,8 +380,23 @@ function _stripFencedCode(text: string): string {
|
|
|
380
380
|
return text.replace(FENCED_CODE_RE, (m) => '\n'.repeat(_splitlines(m).length));
|
|
381
381
|
}
|
|
382
382
|
|
|
383
|
-
|
|
384
|
-
|
|
383
|
+
/**
|
|
384
|
+
* Terminator for a blocker field's continuation lines — ANY `- **Label:**`
|
|
385
|
+
* bullet, not a closed list of known labels.
|
|
386
|
+
*
|
|
387
|
+
* It used to enumerate eight names, which silently diverged from the contract
|
|
388
|
+
* the two call sites below already document ("up to the next `- **Field:**`
|
|
389
|
+
* marker"): a bullet whose label was not on the list did not terminate, so the
|
|
390
|
+
* PREVIOUS field kept absorbing it and the dashboard rendered the two as one
|
|
391
|
+
* run-on sentence. Measured when `- **Options:**` and `- **Side finding:**`
|
|
392
|
+
* first appeared in a blocker — a reader saw the side finding as part of
|
|
393
|
+
* `Resolved when`, i.e. the generator changed what a field meant.
|
|
394
|
+
*
|
|
395
|
+
* A closed list is the wrong shape for a terminator: every future field name
|
|
396
|
+
* would have to be added here to avoid corrupting the field above it, and the
|
|
397
|
+
* failure is silent in generated output nobody edits by hand.
|
|
398
|
+
*/
|
|
399
|
+
const BLOCKER_FIELD_RE = /^-[ \t]*\*\*[^*]+:\*\*/;
|
|
385
400
|
|
|
386
401
|
/** Strip an inline `<!-- comment -->` and trim. */
|
|
387
402
|
function _stripComment(s: string): string {
|
|
@@ -306,6 +306,10 @@ handoff shape emitted alongside `design-system.json`
|
|
|
306
306
|
— when the artifact is a mock — an explicit "prototype, not production code"
|
|
307
307
|
warning so a consumer never ships the reference verbatim.
|
|
308
308
|
|
|
309
|
+
**What to capture FROM** a running project: sources first, SSR fetch second,
|
|
310
|
+
rendered snapshot only with consumer tooling; record the git SHA. Rationale:
|
|
311
|
+
[snapshot preference order](references/snapshot-preference-order.md).
|
|
312
|
+
|
|
309
313
|
## Gotcha
|
|
310
314
|
|
|
311
315
|
- **Over-writing instead of diff-updating** — the most common failure.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Snapshot preference order — what to capture a design system FROM
|
|
2
|
+
|
|
3
|
+
When a design system has to be captured out of a running project — for a
|
|
4
|
+
handoff, an external design pass, or a reference bundle — there is more than one
|
|
5
|
+
thing you could point at, and they are not equally good. This is the preference
|
|
6
|
+
order, highest fidelity per unit of effort first.
|
|
7
|
+
|
|
8
|
+
**Take the first level the project supports. Do not skip down the list for
|
|
9
|
+
convenience, and do not skip UP it for thoroughness** — Level C is additional
|
|
10
|
+
evidence, never a replacement for Level A.
|
|
11
|
+
|
|
12
|
+
## Level A — source-level (always available, the default)
|
|
13
|
+
|
|
14
|
+
The involved component sources, plus the token layer (DTCG / CSS custom
|
|
15
|
+
properties), plus the page composition that assembles them.
|
|
16
|
+
|
|
17
|
+
**Why this is the default and not the fallback**, which is the part that reads
|
|
18
|
+
backwards until you have seen the alternative: in a component project, a
|
|
19
|
+
rendered DOM dump is *worse* input than the sources it came from. Hydrated
|
|
20
|
+
markup is utility-class soup with the component boundaries erased — the very
|
|
21
|
+
structure a design system is made of is the structure rendering destroys. A
|
|
22
|
+
reader (human or tool) reworks clean sources far better than expanded markup.
|
|
23
|
+
|
|
24
|
+
Level A needs no dev server, no browser, and no network. It is available in a
|
|
25
|
+
bare checkout, which is why it is also the only level that always works.
|
|
26
|
+
|
|
27
|
+
## Level B — SSR fetch (no browser)
|
|
28
|
+
|
|
29
|
+
When the stack renders server-side and a dev server is running, an ordinary
|
|
30
|
+
HTTP fetch of the rendered page.
|
|
31
|
+
|
|
32
|
+
Use it to answer what Level A cannot: what the composition actually resolves to
|
|
33
|
+
for a given route — conditional branches taken, data-dependent states, the real
|
|
34
|
+
class strings after server-side composition. Zero browser dependency, so it
|
|
35
|
+
stays cheap.
|
|
36
|
+
|
|
37
|
+
Level B **supplements** Level A. Capturing B alone leaves you with the soup
|
|
38
|
+
problem above and no component boundaries.
|
|
39
|
+
|
|
40
|
+
## Level C — rendered snapshot (consumer tooling only)
|
|
41
|
+
|
|
42
|
+
If the project already carries a browser-automation tool, or a DevTools bridge
|
|
43
|
+
is available in the session, additionally capture a screenshot plus a
|
|
44
|
+
computed-style extract as visual ground truth.
|
|
45
|
+
|
|
46
|
+
**Capability-detect, never hard-depend.** Level C is available when the consumer
|
|
47
|
+
already has the tooling; it is never a reason to install a browser stack, add a
|
|
48
|
+
dependency, or fail a capture. A project without it captures at A (and B where
|
|
49
|
+
applicable) and says so.
|
|
50
|
+
|
|
51
|
+
Of the two artefacts, **the screenshot is the valuable part** — it is the only
|
|
52
|
+
one that records what a person actually sees. The DOM dump is supplementary and
|
|
53
|
+
carries the erasure problem Level A exists to avoid.
|
|
54
|
+
|
|
55
|
+
## Every snapshot records the source revision
|
|
56
|
+
|
|
57
|
+
Whatever level was captured, record the git SHA the capture was taken at.
|
|
58
|
+
|
|
59
|
+
This is the anchor that makes a return leg possible: without it, reworked output
|
|
60
|
+
cannot be diffed against what was sent, and a capture from an unknown state is
|
|
61
|
+
evidence about nothing in particular. It costs one line and it is the difference
|
|
62
|
+
between a snapshot and a screenshot.
|
|
63
|
+
|
|
64
|
+
## State the level in the output
|
|
65
|
+
|
|
66
|
+
A capture says which level it reached and why it stopped there — "Level A + B;
|
|
67
|
+
no browser tooling detected, so no visual ground truth". A consumer reading the
|
|
68
|
+
bundle can then tell *absent because unavailable* from *absent because
|
|
69
|
+
overlooked*, which is the same distinction the extraction floor draws for
|
|
70
|
+
not-extractable values.
|
|
71
|
+
|
|
72
|
+
## See also
|
|
73
|
+
|
|
74
|
+
- [`design-system-json.md`](design-system-json.md) — the import contract the
|
|
75
|
+
captured artefact is emitted against.
|
|
76
|
+
- [`../SKILL.md`](../SKILL.md) § Design-system extraction floor — what a
|
|
77
|
+
complete extraction carries once the source has been chosen.
|
|
@@ -89,6 +89,18 @@ Apply the table above. State: *"Running in BASIC — say `DETAIL` to switch."* (
|
|
|
89
89
|
|
|
90
90
|
Identify each slot in the rough prompt: intent · entities · output shape · constraints · target AI · tone · audience. List every missing slot. Check for ambiguity, unstated assumptions, and contradictory requirements.
|
|
91
91
|
|
|
92
|
+
#### 3b. De-inflate before you sharpen
|
|
93
|
+
|
|
94
|
+
Diagnose asks what is *missing*. The de-inflation pass asks what must **go** — because sharpening a premise the target model will confabulate around makes the output worse, not better. Strip exactly these three, and nothing else:
|
|
95
|
+
|
|
96
|
+
| Pattern | What it looks like | What it costs |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| **Grandiose persona** | "You are the world's foremost / legendary / 10× expert in X" | Tokens without behaviour change — a superlative is not a constraint, and the model cannot act on it |
|
|
99
|
+
| **Presupposed canon** | "Apply the 7 laws of X", "use the standard X framework" for a body of knowledge that may not exist | The model invents a canon to satisfy the presupposition, and the confabulation reads as authority |
|
|
100
|
+
| **Scope stuffing** | One prompt demanding analysis *and* strategy *and* copy *and* a checklist | An answer to a question nobody asked, at the cost of the one that was |
|
|
101
|
+
|
|
102
|
+
Strip only these three. Anything else the author wrote is a requirement, not inflation — see § Gotcha for the failure mode on both sides. A stripped persona is replaced by the concrete role the task actually needs ("a senior X" is a role; "the world's foremost X" is decoration), and a presupposed canon becomes a question in DETAIL mode or a stated assumption in BASIC. **This is own analysis, not adopted material** — the three patterns are named here rather than cited from an external collection.
|
|
103
|
+
|
|
92
104
|
### 4a. BASIC path
|
|
93
105
|
|
|
94
106
|
Fill missing slots with safe defaults (general audience, neutral tone, the named AI or "any modern LLM"). Skip to step 5.
|
|
@@ -120,7 +132,11 @@ Format per § Output format. Do **not** execute the optimized prompt yourself un
|
|
|
120
132
|
- The model tends to over-engineer BASIC mode — for a one-line ask, the optimized prompt should still be short. No 800-word system prompts for "help with my resume".
|
|
121
133
|
- Don't drift into German welcome text. The optimized prompt mirrors the user's source-language preference; the skill's own scaffolding stays English (per `language-and-tone` for `.md`).
|
|
122
134
|
- The model tends to **mix languages** in the optimized prompt when the user wrote in German but named an English-speaking target audience — pick one language for the whole optimized prompt body (default: source-language of the rough prompt unless the user explicitly named the target audience's language).
|
|
123
|
-
- The model tends to
|
|
135
|
+
- The model tends to **polish a grandiose persona instead of removing it** — "you are the world's foremost expert in X" gets tightened into a better-written superlative. It is decoration either way: replace it with the concrete role the task needs, or drop it.
|
|
136
|
+
- The model tends to **preserve a presupposed canon while sharpening around it** — asked to improve "apply the 7 laws of X", it produces a cleaner prompt that still presupposes seven laws, and the target model then invents them. Turn the presupposition into a DETAIL question or a stated BASIC assumption; never carry it through polished.
|
|
137
|
+
- The model tends to **keep every demand in a scope-stuffed prompt** because each one came from the author — four deliverables in one prompt produce four shallow answers. Name the primary deliverable, and surface the rest as a numbered option rather than silently answering all of them.
|
|
138
|
+
- The model tends to **over-apply de-inflation once it has the concept** — stripping a constraint the author meant, because it read as verbose. Exactly three patterns are strippable (§ 3b); everything else the author wrote is a requirement. Removing a requirement is the worse failure of the two, and it is silent.
|
|
139
|
+
- The model tends to inherit upstream dogma that "only 5 techniques are safe" (few-shot, role, structured-output, constraint-based, chain-of-thought). That claim travels with an external prompt-collection and is **rejected here** — CO-STAR, RISEN, CRISPE, ReAct, and the image-AI templates land in [`docs/guidelines/prompt-templates.md`](../../../docs/guidelines/prompt-templates.md) and are first-class. Pick by request type, not by upstream whitelist.
|
|
124
140
|
|
|
125
141
|
## Do NOT
|
|
126
142
|
|
|
@@ -393,8 +393,8 @@ to every roadmap you author.
|
|
|
393
393
|
reads as open questions. For source-derived/contested plans, council
|
|
394
394
|
*first* (§ 8.B), then author the verdicts.
|
|
395
395
|
|
|
396
|
-
## Examples
|
|
396
|
+
## Examples & the "already tried?" check
|
|
397
397
|
|
|
398
|
-
Browse `agents/roadmaps/` (active set)
|
|
399
|
-
|
|
400
|
-
|
|
398
|
+
Browse `agents/roadmaps/` (active set) for canonical structural / tactical examples. For closed
|
|
399
|
+
work — and for every already-tried / closed / refuted question — read the generated `INDEX.md` in
|
|
400
|
+
`agents/roadmaps/archive/` first; open an archived file only for a row it marks `not-extractable`.
|
|
@@ -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: "
|
|
42
|
+
agent_config_version: "13.0.0"
|
|
43
43
|
|
|
44
44
|
# --- Project identity ---
|
|
45
45
|
project:
|
|
@@ -4111,13 +4111,13 @@ var settingsSchema = external_exports.object({
|
|
|
4111
4111
|
),
|
|
4112
4112
|
per_tier: external_exports.object({
|
|
4113
4113
|
cheap: external_exports.number().min(0).nullable().default(null).describe(
|
|
4114
|
-
"USD ceiling for the cheap model tier
|
|
4114
|
+
"USD ceiling for the cheap model tier. Budget-aware delegation was ARCHIVED 2026-08-16 (docs/contracts/budget-routing.md), so no code routes on this today; the cap is still summed and reported by `budget.mjs tier`. null = no separate tier cap; global ceilings still apply."
|
|
4115
4115
|
),
|
|
4116
4116
|
medium: external_exports.number().min(0).nullable().default(null).describe(
|
|
4117
4117
|
"USD ceiling for the medium model tier. null = no separate tier cap."
|
|
4118
4118
|
),
|
|
4119
4119
|
strong: external_exports.number().min(0).nullable().default(null).describe(
|
|
4120
|
-
"USD ceiling for the strong model tier. null = no separate tier cap
|
|
4120
|
+
"USD ceiling for the strong model tier. null = no separate tier cap. The never-block-to-save-money relation this used to describe went with the archived budget-routing layer (docs/contracts/budget-routing.md); nothing routes between tiers today."
|
|
4121
4121
|
)
|
|
4122
4122
|
}).default({ cheap: null, medium: null, strong: null })
|
|
4123
4123
|
}),
|
|
@@ -1451,23 +1451,23 @@ var AnthropicCliClient = class extends CliClient {
|
|
|
1451
1451
|
// documented "disable all tools" value.
|
|
1452
1452
|
//
|
|
1453
1453
|
// It also repairs a live failure, which is how the grant was found
|
|
1454
|
-
// rather than reasoned about.
|
|
1455
|
-
//
|
|
1456
|
-
//
|
|
1457
|
-
//
|
|
1458
|
-
//
|
|
1459
|
-
// In this package that overflowed the model's context window
|
|
1460
|
-
// outright: `is_error: true`, `"the request is ~214331 tokens
|
|
1454
|
+
// rather than reasoned about. AT THE TIME (2026-08-12) the spawn
|
|
1455
|
+
// inherited the caller's cwd, so invoking the council from inside a
|
|
1456
|
+
// repository made the child load that project's own instructions AND
|
|
1457
|
+
// every tool definition. In this package that overflowed the context
|
|
1458
|
+
// window outright: `is_error: true`, `"the request is ~214331 tokens
|
|
1461
1459
|
// (limit 200000) … the rest is system prompt, tool definitions"`,
|
|
1462
|
-
// exit 1, empty stderr —
|
|
1463
|
-
//
|
|
1464
|
-
//
|
|
1465
|
-
// returns the worktree call to exit 0.
|
|
1460
|
+
// exit 1, empty stderr — the member reported unavailable with no
|
|
1461
|
+
// diagnosable cause. Identical call from `/tmp` exit 0, from the
|
|
1462
|
+
// worktree exit 1, and this one flag returns the worktree to exit 0.
|
|
1466
1463
|
//
|
|
1467
|
-
//
|
|
1468
|
-
//
|
|
1469
|
-
//
|
|
1470
|
-
//
|
|
1464
|
+
// TENSE CORRECTED 2026-08-16. This block read "`_runSubprocess` sets
|
|
1465
|
+
// none, deliberately" and "dropping the tools RATHER THAN
|
|
1466
|
+
// neutralising the cwd" — both false since `_runSubprocess` set
|
|
1467
|
+
// `cwd: os.tmpdir()` for a DIFFERENT contamination (a member
|
|
1468
|
+
// answering this repo's `end-review-nudge`). Two repairs, one
|
|
1469
|
+
// cause, neither aware of the other, so a reader here concluded
|
|
1470
|
+
// the cwd is inherited. Both are live; this flag bounds what a member may DO.
|
|
1471
1471
|
"--tools",
|
|
1472
1472
|
"",
|
|
1473
1473
|
"--append-system-prompt",
|
|
@@ -1557,7 +1557,7 @@ var OpenAICliClient = class extends CliClient {
|
|
|
1557
1557
|
if (measuredOn === void 0) return null;
|
|
1558
1558
|
return {
|
|
1559
1559
|
code: "model_unsupported_on_transport",
|
|
1560
|
-
detail: `openai member pins model \`${this.model}\`, which the codex CLI (subscription transport) refused when measured on ${measuredOn}: "The '${this.model}' model is not supported when using Codex with a ChatGPT account." The CLI publishes no list of models it DOES accept, so there is no supported set to offer here \u2014 the one configuration measured to work is no pin at all. Fix:
|
|
1560
|
+
detail: `openai member pins model \`${this.model}\`, which the codex CLI (subscription transport) refused when measured on ${measuredOn}: "The '${this.model}' model is not supported when using Codex with a ChatGPT account." The CLI publishes no list of models it DOES accept, so there is no supported set to offer here \u2014 the one configuration measured to work is no pin at all. Fix: set \`model: codex-default\` on the openai member. Do NOT delete the \`model:\` line \u2014 an enabled member with no model fails config load, so that takes EVERY provider to NOT CONFIGURED. A pin is reachable only on the API transport.`
|
|
1561
1561
|
};
|
|
1562
1562
|
}
|
|
1563
1563
|
/**
|
|
@@ -1672,7 +1672,7 @@ var OpenAICliClient = class extends CliClient {
|
|
|
1672
1672
|
// needs and neither of which the error code carries.
|
|
1673
1673
|
detail: failure.slice(0, 400),
|
|
1674
1674
|
...unsupported ? {
|
|
1675
|
-
hint: "the codex subscription transport serves no explicitly pinned model measured so far \u2014
|
|
1675
|
+
hint: "the codex subscription transport serves no explicitly pinned model measured so far \u2014 set `model: codex-default` on the openai member; deleting the line fails config load"
|
|
1676
1676
|
} : {}
|
|
1677
1677
|
}
|
|
1678
1678
|
});
|
|
@@ -2,7 +2,7 @@ import { createRequire as __acCreateRequire } from 'node:module'; const require
|
|
|
2
2
|
import {
|
|
3
3
|
ZodFirstPartyTypeKind,
|
|
4
4
|
settingsSchema
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-EVTY7ISR.js";
|
|
6
6
|
import {
|
|
7
7
|
main
|
|
8
8
|
} from "./chunk-PPQO4NGR.js";
|
|
@@ -705,14 +705,22 @@ function measureCatalogueVolume(host, root) {
|
|
|
705
705
|
descriptionBytes: skills.reduce((sum, e) => sum + Buffer.byteLength(e.description), 0)
|
|
706
706
|
};
|
|
707
707
|
}
|
|
708
|
+
function _supersedes(candidate, incumbent) {
|
|
709
|
+
if (candidate.observed_at !== incumbent.observed_at) {
|
|
710
|
+
return candidate.observed_at > incumbent.observed_at;
|
|
711
|
+
}
|
|
712
|
+
return (candidate.dropped_count ?? 0) > (incumbent.dropped_count ?? 0);
|
|
713
|
+
}
|
|
708
714
|
function knownHostLimits(records) {
|
|
709
715
|
const out = /* @__PURE__ */ new Map();
|
|
716
|
+
const chosen = /* @__PURE__ */ new Map();
|
|
710
717
|
for (const record of records) {
|
|
711
718
|
if (truncationModeOf(record) !== "budget-strip-and-drop") continue;
|
|
712
719
|
if (typeof record.dropped_count !== "number") continue;
|
|
713
720
|
if (record.dropped_count <= 0) continue;
|
|
714
|
-
const previous =
|
|
715
|
-
if (previous !== void 0 && previous
|
|
721
|
+
const previous = chosen.get(record.host);
|
|
722
|
+
if (previous !== void 0 && !_supersedes(record, previous)) continue;
|
|
723
|
+
chosen.set(record.host, record);
|
|
716
724
|
out.set(record.host, {
|
|
717
725
|
host: record.host,
|
|
718
726
|
droppedEntries: record.dropped_count,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
frontmatterPaths,
|
|
23
23
|
proseEqual,
|
|
24
24
|
splitFrontmatter
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-3B72LSZL.js";
|
|
26
26
|
import "./chunk-FTAISGDQ.js";
|
|
27
27
|
import {
|
|
28
28
|
atomic_write_json,
|
|
@@ -33,7 +33,7 @@ import "./chunk-Q26HT4QT.js";
|
|
|
33
33
|
import {
|
|
34
34
|
projectStoreSlug,
|
|
35
35
|
resolveSessionRole
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-N7FEST6D.js";
|
|
37
37
|
import "./chunk-PZWRPRWP.js";
|
|
38
38
|
import "./chunk-M2DPGFZ4.js";
|
|
39
39
|
import {
|
|
@@ -66,11 +66,11 @@ import {
|
|
|
66
66
|
_wizard_state_path,
|
|
67
67
|
main,
|
|
68
68
|
shutilWhich
|
|
69
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-3B72LSZL.js";
|
|
70
70
|
import "./chunk-FTAISGDQ.js";
|
|
71
71
|
import "./chunk-EJITJBJX.js";
|
|
72
72
|
import "./chunk-Q26HT4QT.js";
|
|
73
|
-
import "./chunk-
|
|
73
|
+
import "./chunk-N7FEST6D.js";
|
|
74
74
|
import "./chunk-PZWRPRWP.js";
|
|
75
75
|
import "./chunk-M2DPGFZ4.js";
|
|
76
76
|
import "./chunk-63WSP6YZ.js";
|
|
@@ -9,8 +9,8 @@ import {
|
|
|
9
9
|
KIRO_MARKER,
|
|
10
10
|
ROOCODE_MARKER,
|
|
11
11
|
ZED_MARKER
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-XURJ4AQC.js";
|
|
13
|
+
import "./chunk-EVTY7ISR.js";
|
|
14
14
|
import "./chunk-PPQO4NGR.js";
|
|
15
15
|
import "./chunk-BKO2AZ7Z.js";
|
|
16
16
|
import "./chunk-63WSP6YZ.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
PROJECT_BRIDGE_MARKERS
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-XURJ4AQC.js";
|
|
5
|
+
import "./chunk-EVTY7ISR.js";
|
|
6
6
|
import "./chunk-PPQO4NGR.js";
|
|
7
7
|
import "./chunk-BKO2AZ7Z.js";
|
|
8
8
|
import {
|