@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.
Files changed (148) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +273 -0
  3. package/README.md +1 -1
  4. package/agents/templates/.ai-council.yml.example +46 -3
  5. package/dist/agent-src/commands/cost/report.md +23 -0
  6. package/dist/agent-src/contexts/execution/subagent-routing.md +148 -33
  7. package/dist/agent-src/contexts/model-recommendations.md +6 -4
  8. package/dist/agent-src/contexts/subagent-configuration.md +69 -7
  9. package/dist/agent-src/rules/autonomous-execution.md +1 -1
  10. package/dist/agent-src/rules/design-fidelity.md +1 -1
  11. package/dist/agent-src/rules/design-review-after-ui-write.md +10 -5
  12. package/dist/agent-src/rules/evaluator-independence.md +27 -5
  13. package/dist/agent-src/rules/git-history-discipline.md +5 -1
  14. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -0
  15. package/dist/agent-src/rules/missing-skill-recovery.md +89 -0
  16. package/dist/agent-src/rules/ui-audit-gate.md +9 -4
  17. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +33 -0
  18. package/dist/agent-src/scripts/roadmap_gates.ts +30 -2
  19. package/dist/agent-src/scripts/update_roadmap_progress.ts +47 -1
  20. package/dist/agent-src/skills/authz-review/SKILL.md +4 -0
  21. package/dist/agent-src/skills/design-system-capture/SKILL.md +4 -0
  22. package/dist/agent-src/skills/design-system-capture/references/snapshot-preference-order.md +77 -0
  23. package/dist/agent-src/skills/merge-conflicts/SKILL.md +4 -0
  24. package/dist/agent-src/skills/prompt-optimizer/SKILL.md +17 -1
  25. package/dist/agent-src/skills/roadmap-writing/SKILL.md +11 -11
  26. package/dist/agent-src/skills/systematic-debugging/SKILL.md +4 -0
  27. package/dist/agent-src/skills/threat-modeling/SKILL.md +3 -0
  28. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  29. package/dist/agent-src/templates/roadmaps.md +41 -3
  30. package/dist/cli/registry.js +1 -0
  31. package/dist/cli/registry.js.map +1 -1
  32. package/dist/cli-delegate/{chunk-NN4KW4HZ.js → chunk-3B72LSZL.js} +123 -2338
  33. package/dist/cli-delegate/{chunk-55WZN5VF.js → chunk-EVTY7ISR.js} +2 -2
  34. package/dist/cli-delegate/chunk-N7FEST6D.js +3895 -0
  35. package/dist/cli-delegate/{chunk-L565YFXH.js → chunk-XURJ4AQC.js} +566 -298
  36. package/dist/cli-delegate/cmd_conformance.js +4 -4
  37. package/dist/cli-delegate/cmd_doctor.js +2 -2
  38. package/dist/cli-delegate/cmd_export.js +2 -2
  39. package/dist/cli-delegate/cmd_handoff.js +1 -1
  40. package/dist/cli-delegate/cmd_prune.js +2 -2
  41. package/dist/cli-delegate/cmd_settings_migrate.js +2 -2
  42. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  43. package/dist/cli-delegate/cmd_sync.js +2 -2
  44. package/dist/cli-delegate/cmd_uninstall.js +2 -2
  45. package/dist/cli-delegate/cmd_validate.js +2 -2
  46. package/dist/discovery/deprecation-report.md +1 -1
  47. package/dist/discovery/discovery-manifest.json +44 -23
  48. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  49. package/dist/discovery/discovery-manifest.summary.md +3 -3
  50. package/dist/discovery/dormancy-report.md +1 -1
  51. package/dist/discovery/orphan-report.md +1 -1
  52. package/dist/discovery/packs.json +6 -5
  53. package/dist/discovery/trust-report.md +2 -2
  54. package/dist/discovery/workspaces.json +5 -4
  55. package/dist/hooks/dispatch.js +10625 -8541
  56. package/dist/install/install.mjs +754 -484
  57. package/dist/mcp/registry-manifest.json +3 -3
  58. package/dist/mcp/server.json +2 -2
  59. package/dist/mcp/server.mjs +1302 -167
  60. package/dist/router.json +1 -1
  61. package/dist/scripts/_lib/model_tier.js +9 -0
  62. package/dist/scripts/_lib/model_tier.js.map +1 -1
  63. package/dist/scripts/condense.js +50 -0
  64. package/dist/scripts/condense.js.map +1 -1
  65. package/dist/server/schemas/settings.js +2 -2
  66. package/dist/server/schemas/settings.js.map +1 -1
  67. package/docs/MIGRATION.md +20 -1
  68. package/docs/guidelines/design-fidelity-mechanics.md +21 -0
  69. package/docs/guidelines/design-handover-extraction.md +87 -0
  70. package/docs/guidelines/prompt-templates.md +24 -1
  71. package/package.json +1 -1
  72. package/src/agent-src/scripts/archive_completed_roadmaps.ts +33 -0
  73. package/src/agent-src/scripts/roadmap_gates.ts +30 -2
  74. package/src/agent-src/scripts/update_roadmap_progress.ts +47 -1
  75. package/src/config/evaluator-budgets.json +9 -8
  76. package/src/config/gate-coverage.yml +63 -11
  77. package/src/config/gate-violation-baselines.json +12 -0
  78. package/src/config/hook-token-budget.json +15 -2
  79. package/src/config/preamble-payload-budget.json +28 -0
  80. package/src/scripts/_dispatch.bash +10 -0
  81. package/src/scripts/_lib/bench_ab_complexity.ts +439 -0
  82. package/src/scripts/_lib/bench_ab_safety_tier.ts +142 -0
  83. package/src/scripts/_lib/bench_ab_scoring_v2.ts +28 -3
  84. package/src/scripts/_lib/bench_ab_search_adherence.ts +423 -0
  85. package/src/scripts/_lib/bench_ab_size_claim.ts +206 -0
  86. package/src/scripts/_lib/bench_ab_workspace.ts +111 -0
  87. package/src/scripts/_lib/git_common_dir.ts +173 -0
  88. package/src/scripts/_lib/model_tier.ts +9 -0
  89. package/src/scripts/_lib/release_highlights.ts +108 -7
  90. package/src/scripts/_lib/skill_catalogue.ts +1115 -0
  91. package/src/scripts/_lib/tier_budget_routing.ts +31 -331
  92. package/src/scripts/ai_council/clients.ts +197 -18
  93. package/src/scripts/ai_council/config.ts +16 -1
  94. package/src/scripts/ai_council/low_impact.ts +14 -1
  95. package/src/scripts/ai_council/orchestrator.ts +14 -1
  96. package/src/scripts/ai_council/transport_resolver.ts +32 -2
  97. package/src/scripts/bench_ab_v2_complexity.ts +252 -0
  98. package/src/scripts/bench_ab_v2_run.ts +3 -42
  99. package/src/scripts/bench_ab_v2_safety.ts +296 -0
  100. package/src/scripts/bench_ab_v2_search.ts +343 -0
  101. package/src/scripts/bench_ab_v2_stats.ts +191 -0
  102. package/src/scripts/build_archive_index.ts +383 -0
  103. package/src/scripts/capture_skill_catalogue.ts +279 -317
  104. package/src/scripts/check_branch_freshness.ts +7 -1
  105. package/src/scripts/check_release_published.ts +6 -2
  106. package/src/scripts/check_release_trunk_sync.ts +18 -2
  107. package/src/scripts/check_source_size_budget.ts +428 -0
  108. package/src/scripts/check_suppression_hygiene.ts +5 -1
  109. package/src/scripts/condense.ts +50 -1
  110. package/src/scripts/cost/backfill_rates.mjs +298 -0
  111. package/src/scripts/cost/budget.mjs +12 -32
  112. package/src/scripts/cost_summary.ts +25 -0
  113. package/src/scripts/dispatch_r2_reviewer.ts +15 -5
  114. package/src/scripts/evidence_report.ts +15 -4
  115. package/src/scripts/external_sources_denylist.json +1 -0
  116. package/src/scripts/hook_manifest.yaml +75 -15
  117. package/src/scripts/hooks/concern_registry.ts +4 -0
  118. package/src/scripts/hooks/orchestration_record_hook.ts +21 -0
  119. package/src/scripts/hooks/skill_route_hook.ts +226 -0
  120. package/src/scripts/hooks/tool_result_bytes_hook.ts +219 -0
  121. package/src/scripts/hooks/ui_route_nudge_hook.ts +6 -3
  122. package/src/scripts/hot_context_hook.ts +13 -1
  123. package/src/scripts/install.ts +129 -0
  124. package/src/scripts/janitor.ts +77 -2
  125. package/src/scripts/lint_design_antipattern_parity.ts +40 -6
  126. package/src/scripts/lint_harvest_provenance.ts +35 -1
  127. package/src/scripts/lint_plan_risk_register.ts +22 -9
  128. package/src/scripts/lint_roadmap_blockers.ts +109 -6
  129. package/src/scripts/lint_rule_skill_pack_reach.ts +43 -0
  130. package/src/scripts/lint_scheduled_deprecations.ts +738 -0
  131. package/src/scripts/lint_skill_router_head.ts +21 -0
  132. package/src/scripts/mcp_server/consumer_tool_catalog.json +26 -3
  133. package/src/scripts/mcp_server/tool_catalog_source.ts +6 -24
  134. package/src/scripts/mcp_server/tools.ts +87 -0
  135. package/src/scripts/migration_status.ts +17 -1
  136. package/src/scripts/probe_review_binding_drift.ts +731 -0
  137. package/src/scripts/release.ts +100 -6
  138. package/src/scripts/routing_doctor.ts +50 -13
  139. package/src/scripts/schemas/command.schema.json +3 -3
  140. package/src/scripts/schemas/skill.schema.json +20 -2
  141. package/src/scripts/schemas/subagent.schema.json +2 -2
  142. package/src/scripts/session_eol_report.ts +81 -0
  143. package/src/scripts/trigger_coverage.ts +224 -3
  144. package/src/scripts/workspace_doctor.ts +464 -0
  145. package/src/scripts/worktree_cleanup_check.ts +2 -1
  146. package/src/server/schemas/settings.ts +2 -2
  147. package/dist/cli-delegate/chunk-AYKQGIBG.js +0 -1594
  148. package/src/config/budget-routing.json +0 -7
@@ -40,6 +40,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
40
40
  import { parse as parseYaml } from 'yaml';
41
41
 
42
42
  import { keyword_matches_anchored } from './router_telemetry.js';
43
+ import { match_prompt, type Router as MatchRouter } from './_lib/router_match.js';
43
44
 
44
45
  const _HERE = fileURLToPath(import.meta.url);
45
46
 
@@ -48,6 +49,11 @@ export const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..');
48
49
  export const ROUTER = path.join(REPO_ROOT, 'dist', 'router.json');
49
50
  export const CORPUS = path.join(REPO_ROOT, 'tests', 'eval', 'trigger-coverage.yaml');
50
51
 
52
+ /** Skill tree the `skill` scope reads `triggers:` frontmatter from. */
53
+ export const SKILLS_DIR = path.join(REPO_ROOT, 'src', 'skills');
54
+ /** The matrix corpus the unintended-activation census is defined over. */
55
+ export const MATRIX_DIR = path.join(REPO_ROOT, 'tests', 'eval', 'routing-matrix');
56
+
51
57
  type Router = {
52
58
  kernel?: string[];
53
59
  tier_1?: Array<{ id: string; triggers?: Array<Record<string, string>> }>;
@@ -100,6 +106,168 @@ export function fired_rules(prompt: string, router: Router): Set<string> {
100
106
  return fired;
101
107
  }
102
108
 
109
+ /* ------------------------------------------------------------------ *
110
+ * The SKILL scope.
111
+ *
112
+ * It reuses `match_prompt` from `_lib/router_match.ts` — the same matcher the
113
+ * rule scope's census runs on — by handing it a router-SHAPED view of the
114
+ * skill catalogue. Forking the matcher would let the two scopes disagree about
115
+ * what "fires" means, which is the exact drift the shared helper exists to
116
+ * prevent.
117
+ *
118
+ * WHAT THIS SCOPE CANNOT REGRESS, stated because the roadmap's own risk
119
+ * register assumed otherwise. Risk 2 reads "the corpus counts activations
120
+ * across the whole router, so a skill-side tranche can regress a rule-side
121
+ * number". Verified against the tree: `compile_router.ts` contains zero
122
+ * references to skills, and `dist/router.json` carries exactly
123
+ * `kernel` + `tier_1` + `tier_2` rule entries. Skill triggers are compiled
124
+ * into nothing and are matched here over a SEPARATE catalogue, so the rule-side
125
+ * 433 census is structurally untouched by any skill tranche. The risk it names
126
+ * is real for a shared router and does not exist in this one — which makes the
127
+ * skill-side count below a NEW number needing its own ceiling, not a threat to
128
+ * the old one.
129
+ * ------------------------------------------------------------------ */
130
+
131
+ /** One skill that declares activation triggers. */
132
+ export interface SkillTriggerEntry {
133
+ id: string;
134
+ triggers: Array<Record<string, string>>;
135
+ }
136
+
137
+ /** `triggers:` list items from a SKILL.md frontmatter block. */
138
+ function _parseTriggerBlock(frontmatter: string): Array<Record<string, string>> {
139
+ const out: Array<Record<string, string>> = [];
140
+ const lines = frontmatter.split('\n');
141
+ let inside = false;
142
+ for (const line of lines) {
143
+ if (/^triggers:\s*$/.test(line)) {
144
+ inside = true;
145
+ continue;
146
+ }
147
+ if (inside && /^\S/.test(line)) break; // next top-level key ends the block
148
+ if (!inside) continue;
149
+ const item = /^\s*-\s*(keyword|phrase|file_pattern|path_prefix|command):\s*(.+?)\s*$/.exec(line);
150
+ if (item) {
151
+ out.push({ [item[1]!]: item[2]!.replace(/^["']|["']$/g, '') });
152
+ }
153
+ }
154
+ return out;
155
+ }
156
+
157
+ /** Every skill under `skillsDir` that declares a non-empty `triggers:` list. */
158
+ export function loadSkillTriggers(skillsDir: string): SkillTriggerEntry[] {
159
+ let names: string[];
160
+ try {
161
+ names = fs.readdirSync(skillsDir);
162
+ } catch {
163
+ return [];
164
+ }
165
+ const out: SkillTriggerEntry[] = [];
166
+ for (const name of names.sort()) {
167
+ const file = path.join(skillsDir, name, 'SKILL.md');
168
+ let content: string;
169
+ try {
170
+ content = fs.readFileSync(file, 'utf-8');
171
+ } catch {
172
+ continue;
173
+ }
174
+ if (!content.startsWith('---')) continue;
175
+ const end = content.indexOf('\n---', 3);
176
+ if (end === -1) continue;
177
+ const triggers = _parseTriggerBlock(content.slice(3, end));
178
+ if (triggers.length > 0) out.push({ id: name, triggers });
179
+ }
180
+ return out;
181
+ }
182
+
183
+ /**
184
+ * Every prompt in the matrix corpus, positives and near-misses alike.
185
+ *
186
+ * Parsed with the YAML reader this module already imports, not with a
187
+ * line regex. A regex anchored on `- prompt: "…"` silently drops any entry
188
+ * written unquoted or in single quotes, and a corpus that shrinks without
189
+ * saying so moves every rate computed against it — the denominator would
190
+ * change while the number kept its old name.
191
+ */
192
+ export function loadMatrixPrompts(matrixDir: string): string[] {
193
+ let files: string[];
194
+ try {
195
+ files = fs.readdirSync(matrixDir).filter((n) => n.endsWith('.yaml')).sort();
196
+ } catch {
197
+ return [];
198
+ }
199
+ const out: string[] = [];
200
+ for (const f of files) {
201
+ let doc: unknown;
202
+ try {
203
+ doc = parseYaml(fs.readFileSync(path.join(matrixDir, f), 'utf-8'), { version: '1.1' });
204
+ } catch {
205
+ continue; // an unparseable corpus file is skipped, never guessed at
206
+ }
207
+ if (typeof doc !== 'object' || doc === null) continue;
208
+ const record = doc as Record<string, unknown>;
209
+ for (const section of ['positives', 'near_misses']) {
210
+ const entries = record[section];
211
+ if (!Array.isArray(entries)) continue;
212
+ for (const raw of entries) {
213
+ const prompt = (raw as Record<string, unknown> | null)?.['prompt'];
214
+ if (typeof prompt === 'string' && prompt.trim() !== '') out.push(prompt);
215
+ }
216
+ }
217
+ }
218
+ return out;
219
+ }
220
+
221
+ export interface SkillScopeReport {
222
+ /** Skills declaring at least one trigger. Zero on the day the schema ships. */
223
+ skills_with_triggers: number;
224
+ prompts: number;
225
+ /** Total (prompt, skill) activations — the skill-side census. */
226
+ activations: number;
227
+ /** Prompts that activated at least one skill. */
228
+ prompts_activating: number;
229
+ /** Per-skill activation counts, descending then by id. */
230
+ histogram: Array<[string, number]>;
231
+ }
232
+
233
+ /**
234
+ * Run the skill catalogue over the matrix corpus with the shared matcher.
235
+ *
236
+ * `tier_2` is the carrier for the router-shaped view purely because
237
+ * `match_prompt` reads its rule lists from `tier_1`/`tier_2`; skills have no
238
+ * tier and none is implied by the placement.
239
+ */
240
+ export function runSkillScope(
241
+ entries: readonly SkillTriggerEntry[],
242
+ prompts: readonly string[],
243
+ ): SkillScopeReport {
244
+ // `kernel: []` is load-bearing: `match_prompt` appends every kernel id to
245
+ // `activated_rules` unconditionally, so a non-empty kernel here would count
246
+ // rule activations as skill ones on every prompt.
247
+ const view = { kernel: [], tier_1: [], tier_2: entries } as unknown as MatchRouter;
248
+ const histogram: Record<string, number> = {};
249
+ let activations = 0;
250
+ let promptsActivating = 0;
251
+ for (const prompt of prompts) {
252
+ const result = match_prompt(view, prompt, 'full', null, null);
253
+ const ids = result.activated_rules.map((a) => String(a.rule));
254
+ if (ids.length > 0) promptsActivating += 1;
255
+ for (const id of ids) {
256
+ histogram[id] = (histogram[id] ?? 0) + 1;
257
+ activations += 1;
258
+ }
259
+ }
260
+ return {
261
+ skills_with_triggers: entries.length,
262
+ prompts: prompts.length,
263
+ activations,
264
+ prompts_activating: promptsActivating,
265
+ histogram: Object.entries(histogram).sort((a, b) =>
266
+ b[1] !== a[1] ? b[1] - a[1] : a[0] < b[0] ? -1 : 1,
267
+ ),
268
+ };
269
+ }
270
+
103
271
  export function run(corpus: Case[], router: Router): [CaseResult[], number] {
104
272
  const results: CaseResult[] = [];
105
273
  let misses = 0;
@@ -168,23 +336,76 @@ function _jsonDumps(obj: unknown): string {
168
336
 
169
337
  interface ParsedArgs {
170
338
  json: boolean;
339
+ /** `rule` keeps the pinned byte-identical contract; `skill` is additive. */
340
+ scope: 'rule' | 'skill';
171
341
  }
172
342
 
173
343
  function parse_args(argv: string[]): ParsedArgs {
174
- const out: ParsedArgs = { json: false };
175
- for (const a of argv) {
344
+ const out: ParsedArgs = { json: false, scope: 'rule' };
345
+ for (let i = 0; i < argv.length; i += 1) {
346
+ const a = argv[i]!;
176
347
  if (a === '--json') {
177
348
  out.json = true;
349
+ } else if (a === '--scope') {
350
+ const v = argv[i + 1];
351
+ if (v !== 'rule' && v !== 'skill') {
352
+ process.stderr.write(`error: --scope must be rule or skill, got: ${v ?? '(missing)'}\n`);
353
+ process.exit(2);
354
+ }
355
+ out.scope = v;
356
+ i += 1;
178
357
  } else if (a === '-h' || a === '--help') {
179
- process.stdout.write('usage: trigger_coverage [-h] [--json]\n');
358
+ process.stdout.write('usage: trigger_coverage [-h] [--json] [--scope rule|skill]\n');
180
359
  process.exit(0);
181
360
  }
182
361
  }
183
362
  return out;
184
363
  }
185
364
 
365
+ /**
366
+ * `--scope skill` — report only, never a gate.
367
+ *
368
+ * Exit 0 regardless of the count: no ceiling is committed here. The skill-side
369
+ * census is a NEW number (see the scope's header note on why the rule-side 433
370
+ * is structurally out of reach), and this package does not commit a threshold
371
+ * before it has a reading. A tranche is judged against a published baseline in
372
+ * its own change, not against a number invented on the day the instrument
373
+ * shipped.
374
+ */
375
+ function runSkillScopeCli(json: boolean): number {
376
+ const report = runSkillScope(loadSkillTriggers(SKILLS_DIR), loadMatrixPrompts(MATRIX_DIR));
377
+ if (json) {
378
+ process.stdout.write(_jsonDumps(report) + '\n');
379
+ return 0;
380
+ }
381
+ process.stdout.write(
382
+ `skill trigger coverage over ${report.prompts} matrix prompts\n` +
383
+ ` skills declaring triggers: ${report.skills_with_triggers}\n` +
384
+ ` activations: ${report.activations}\n` +
385
+ ` prompts activating ≥1: ${report.prompts_activating}\n`,
386
+ );
387
+ if (report.skills_with_triggers === 0) {
388
+ process.stdout.write(
389
+ '\nNo skill declares a trigger yet. That is the schema landing empty of\n' +
390
+ 'adopters, not a failure: the capability is declarable before anything\n' +
391
+ 'declares it, so a seeded tranche is measurable before it is written.\n',
392
+ );
393
+ return 0;
394
+ }
395
+ process.stdout.write('\nper skill:\n');
396
+ for (const [id, n] of report.histogram) {
397
+ process.stdout.write(` ${String(n).padStart(4)} ${id}\n`);
398
+ }
399
+ process.stdout.write(
400
+ '\nReport only — no ceiling is enforced here. The rule-side 433 census is a\n' +
401
+ 'different catalogue and cannot move from this scope.\n',
402
+ );
403
+ return 0;
404
+ }
405
+
186
406
  export function main(argv: string[] | null = null): number {
187
407
  const args = parse_args(argv ?? process.argv.slice(2));
408
+ if (args.scope === 'skill') return runSkillScopeCli(args.json);
188
409
 
189
410
  let isFile = false;
190
411
  try {