@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
|
@@ -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 (
|
|
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 {
|