@event4u/agent-config 9.16.0 → 9.18.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/AGENTS.md +1 -1
- package/CHANGELOG.md +80 -130
- package/README.md +1 -1
- package/dist/agent-src/commands/agent-handoff.md +100 -48
- package/dist/agent-src/commands/challenge-me/vision.md +5 -0
- package/dist/agent-src/commands/commit.md +1 -1
- package/dist/agent-src/commands/condense.md +19 -64
- package/dist/agent-src/commands/evals/agent-handoff.json +13 -1
- package/dist/agent-src/commands/evals/rule-compliance-audit.json +46 -0
- package/dist/agent-src/commands/feature/plan.md +20 -0
- package/dist/agent-src/commands/feature/roadmap.md +19 -0
- package/dist/agent-src/commands/memory/promote.md +14 -1
- package/dist/agent-src/commands/mode.md +9 -5
- package/dist/agent-src/commands/optimize/deep.md +72 -11
- package/dist/agent-src/commands/pr/create.md +29 -0
- package/dist/agent-src/commands/roadmap/create.md +29 -0
- package/dist/agent-src/commands/rule-compliance-audit.md +28 -5
- package/dist/agent-src/contexts/authority/commit-mechanics.md +5 -5
- package/dist/agent-src/contexts/communication/rules-auto/guidelines-mechanics.md +1 -0
- package/dist/agent-src/contexts/communication/rules-auto/skill-quality-mechanics.md +1 -1
- package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +6 -1
- package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +4 -1
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +27 -1
- package/dist/agent-src/contexts/execution/plan-confidence-gate.md +133 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +5 -2
- package/dist/agent-src/profiles/agency.yml +3 -3
- package/dist/agent-src/profiles/content_creator.yml +2 -2
- package/dist/agent-src/profiles/developer.yml +2 -2
- package/dist/agent-src/profiles/finance.yml +1 -1
- package/dist/agent-src/profiles/founder.yml +2 -2
- package/dist/agent-src/profiles/ops.yml +2 -2
- package/dist/agent-src/rules/active-remediation.md +2 -0
- package/dist/agent-src/rules/architecture.md +4 -2
- package/dist/agent-src/rules/augment-edit-discipline.md +2 -0
- package/dist/agent-src/rules/autonomous-execution.md +1 -1
- package/dist/agent-src/rules/brand-consistency.md +10 -62
- package/dist/agent-src/rules/brand-source-of-truth.md +62 -11
- package/dist/agent-src/rules/broken-access-control.md +4 -0
- package/dist/agent-src/rules/cli-output-handling.md +5 -0
- package/dist/agent-src/rules/code-comment-discipline.md +3 -0
- package/dist/agent-src/rules/commit-conventions.md +2 -0
- package/dist/agent-src/rules/context-hygiene.md +3 -2
- package/dist/agent-src/rules/cross-source-consistency.md +3 -0
- package/dist/agent-src/rules/design-fidelity.md +2 -0
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +2 -0
- package/dist/agent-src/rules/docker-commands.md +4 -0
- package/dist/agent-src/rules/domain-adoption-policy.md +2 -0
- package/dist/agent-src/rules/domain-safety-disclaimer.md +5 -2
- package/dist/agent-src/rules/domain-safety-pii.md +1 -1
- package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +9 -0
- package/dist/agent-src/rules/image-likeness-and-rights.md +4 -0
- package/dist/agent-src/rules/improve-before-implement.md +4 -0
- package/dist/agent-src/rules/laravel-routing.md +4 -0
- package/dist/agent-src/rules/legal-safety-floor.md +3 -0
- package/dist/agent-src/rules/lethal-trifecta-guard.md +3 -0
- package/dist/agent-src/rules/media-governance-routing.md +5 -0
- package/dist/agent-src/rules/minimal-safe-diff.md +2 -0
- package/dist/agent-src/rules/no-roadmap-references.md +2 -0
- package/dist/agent-src/rules/notes-first-reasoning.md +2 -0
- package/dist/agent-src/rules/output-discipline.md +9 -2
- package/dist/agent-src/rules/php-coding.md +2 -0
- package/dist/agent-src/rules/prefer-enums-over-literals.md +3 -0
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +5 -0
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +2 -0
- package/dist/agent-src/rules/roadmap-progress-sync.md +2 -0
- package/dist/agent-src/rules/rule-type-governance.md +2 -0
- package/dist/agent-src/rules/scale-discipline.md +3 -0
- package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +9 -2
- package/dist/agent-src/rules/senior-engineering-discipline.md +6 -0
- package/dist/agent-src/rules/skill-quality.md +2 -0
- package/dist/agent-src/rules/source-confidentiality.md +4 -0
- package/dist/agent-src/rules/source-discovery-gate.md +3 -0
- package/dist/agent-src/rules/source-of-truth.md +2 -0
- package/dist/agent-src/rules/strategy-safety-floor.md +2 -0
- package/dist/agent-src/rules/think-before-action.md +5 -0
- package/dist/agent-src/rules/token-budget-discipline.md +2 -2
- package/dist/agent-src/rules/ui-audit-gate.md +2 -0
- package/dist/agent-src/rules/user-interaction.md +3 -4
- package/dist/agent-src/skills/build-buy-partner/SKILL.md +1 -1
- package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +4 -4
- package/dist/agent-src/skills/copilot-config/SKILL.md +1 -1
- package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +7 -4
- package/dist/agent-src/skills/description-assist/SKILL.md +1 -1
- package/dist/agent-src/skills/design-intelligence/SKILL.md +6 -180
- package/dist/agent-src/skills/design-intelligence/references/context-and-registers.md +100 -0
- package/dist/agent-src/skills/design-intelligence/references/integration-mapping.md +91 -0
- package/dist/agent-src/skills/design-review/SKILL.md +4 -141
- package/dist/agent-src/skills/design-review/references/review-communication.md +92 -0
- package/dist/agent-src/skills/design-review/references/verification-automation.md +61 -0
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +8 -27
- package/dist/agent-src/skills/existing-ui-audit/references/anti-slop-cross-reference.md +31 -0
- package/dist/agent-src/skills/fe-design/SKILL.md +4 -289
- package/dist/agent-src/skills/fe-design/references/design-patterns.md +227 -0
- package/dist/agent-src/skills/fe-design/references/design-read-and-memory.md +75 -0
- package/dist/agent-src/skills/market-entry-analysis/SKILL.md +1 -1
- package/dist/agent-src/skills/persona-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/readme-reviewer/SKILL.md +2 -1
- package/dist/agent-src/skills/roadmap-management/SKILL.md +10 -0
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +12 -1
- package/dist/agent-src/skills/rule-writing/SKILL.md +4 -2
- package/dist/agent-src/skills/skill-reviewer/SKILL.md +1 -1
- package/dist/agent-src/skills/skill-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +3 -1
- package/dist/agent-src/skills/token-optimizer/SKILL.md +2 -2
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +6 -3
- package/dist/agent-src/templates/agent-settings.md +13 -15
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +6 -2
- package/dist/agent-src/templates/persona.md +2 -2
- package/dist/agent-src/templates/roadmaps.md +13 -1
- package/dist/agent-src/templates/rule.md +1 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/_fix_lane.ts +52 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +8 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/design.ts +6 -0
- package/dist/agent-src/templates/scripts/work_engine/intent/classify.ts +56 -4
- package/dist/agent-src/templates/skill.md +1 -1
- package/dist/cli/registry.js +3 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/chunk-AIIUU73N.js +2040 -0
- package/dist/cli-delegate/{chunk-ZXXJLL5K.js → chunk-BSLUHV2F.js} +127 -1487
- package/dist/cli-delegate/{chunk-H574KOUH.js → chunk-ELMFOQPW.js} +35 -1
- package/dist/cli-delegate/chunk-LF2KKJ4Q.js +183 -0
- package/dist/cli-delegate/chunk-VSYT7OHO.js +1382 -0
- package/dist/cli-delegate/chunk-XGA2NTU4.js +3727 -0
- package/dist/cli-delegate/cmd_conformance.js +4 -3
- package/dist/cli-delegate/cmd_converge.js +3 -3
- package/dist/cli-delegate/cmd_doctor.js +3 -2
- package/dist/cli-delegate/cmd_explain.js +36 -36
- package/dist/cli-delegate/cmd_export.js +4 -4
- package/dist/cli-delegate/cmd_handoff.js +1169 -0
- package/dist/cli-delegate/cmd_memory_get.js +35 -3754
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +4 -4
- package/dist/cli-delegate/cmd_route_audit.js +249 -0
- package/dist/cli-delegate/cmd_route_explain.js +285 -0
- package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
- package/dist/cli-delegate/cmd_sync.js +4 -4
- package/dist/cli-delegate/cmd_uninstall.js +4 -4
- package/dist/cli-delegate/cmd_update.js +3 -3
- package/dist/cli-delegate/cmd_upgrade.js +3 -3
- package/dist/cli-delegate/cmd_validate.js +4 -4
- package/dist/cli-delegate/cmd_versions.js +3 -3
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +84 -84
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +602 -507
- package/dist/install/install.mjs +34 -0
- package/dist/mcp/awesome-mcp-servers.row.md +1 -1
- package/dist/mcp/mcp-cloudflare-catalogue.json +2 -2
- package/dist/mcp/registry-manifest.json +4 -4
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +25 -3
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_src.js +39 -6
- package/dist/scripts/_lib/agent_src.js.map +1 -1
- package/dist/server/schemas/settings.js +25 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/guidelines/abstraction-thresholds.md +53 -0
- package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -1
- package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +7 -0
- package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +2 -2
- package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +5 -3
- package/docs/guidelines/agent-infra/size-and-scope.md +8 -2
- package/docs/guidelines/component-oriented-and-oop-development.md +11 -6
- package/docs/guidelines/docs/readme-size-and-splitting.md +5 -2
- package/llms.txt +1 -0
- package/package.json +1 -1
- package/src/agent-src/templates/scripts/work_engine/directives/ui/_fix_lane.ts +52 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +8 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/design.ts +6 -0
- package/src/agent-src/templates/scripts/work_engine/intent/classify.ts +56 -4
- package/src/config/agent-settings.template.yml +68 -0
- package/src/config/evaluator-budgets.json +8 -11
- package/src/config/gate-coverage.yml +70 -0
- package/src/scripts/_cli/cmd_explain.ts +41 -36
- package/src/scripts/_cli/cmd_handoff.ts +405 -0
- package/src/scripts/_cli/cmd_route_audit.ts +290 -0
- package/src/scripts/_cli/cmd_route_explain.ts +269 -0
- package/src/scripts/_cli/handoff_generate.ts +453 -0
- package/src/scripts/_cli/handoff_sessions.ts +435 -0
- package/src/scripts/_dispatch.bash +32 -0
- package/src/scripts/_lib/agent_src.ts +36 -6
- package/src/scripts/_lib/git_env.ts +40 -0
- package/src/scripts/_lib/md_table.ts +27 -0
- package/src/scripts/_lib/planning_settings.ts +43 -0
- package/src/scripts/_lib/release_material.ts +156 -0
- package/src/scripts/_lib/router_match.ts +301 -0
- package/src/scripts/annotate_r1_outcomes.ts +258 -0
- package/src/scripts/check_completion_review.ts +1140 -0
- package/src/scripts/check_condensation.ts +2 -1
- package/src/scripts/check_finding_dispositions.ts +278 -0
- package/src/scripts/check_pack_size.ts +4 -3
- package/src/scripts/check_references.ts +1 -0
- package/src/scripts/check_release_highlights.ts +300 -0
- package/src/scripts/check_release_pr_shape.ts +4 -0
- package/src/scripts/check_release_surface_equality.ts +132 -0
- package/src/scripts/check_reply_consistency.ts +187 -138
- package/src/scripts/compile_router.ts +20 -3
- package/src/scripts/dispatch_r2_reviewer.ts +968 -0
- package/src/scripts/eval_ui_triviality.ts +156 -0
- package/src/scripts/handoff_context_hook.ts +148 -0
- package/src/scripts/hook_manifest.yaml +17 -7
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/lint_abstraction_thresholds.ts +327 -0
- package/src/scripts/lint_framework_leakage_allowlist.json +2 -2
- package/src/scripts/lint_plan_risk_register.ts +931 -0
- package/src/scripts/lint_profile_personas.ts +153 -0
- package/src/scripts/lint_token_budget_discipline.ts +148 -0
- package/src/scripts/lint_trigger_collisions.ts +257 -0
- package/src/scripts/release.ts +156 -32
- package/src/scripts/release_drill.ts +491 -0
- package/src/scripts/router_telemetry.ts +16 -290
- package/src/scripts/schemas/command.schema.json +33 -0
- package/src/scripts/schemas/rule.schema.json +10 -0
- package/src/scripts/self_review_gate.ts +41 -3
- package/src/scripts/skill_linter.ts +3 -1
- package/src/scripts/smoke/router.sh +1 -1
- package/src/scripts/update_counts.ts +60 -12
- package/src/server/schemas/settings.ts +41 -0
- package/dist/cli-delegate/{chunk-XX6TOPD7.js → chunk-WR6GTRHJ.js} +3 -3
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* `agent-config route:explain "<prompt>" [--files a,b]` — deterministic,
|
|
4
|
+
* offline trace of which rules the router's triggers match for one prompt.
|
|
5
|
+
*
|
|
6
|
+
* The validation surface the routing-correctness mandate asks for: matched
|
|
7
|
+
* triggers, tier, injected-vs-pointer disposition, budget consumption, and
|
|
8
|
+
* rejected candidates — all from `dist/router.json` + the ONE shared matcher
|
|
9
|
+
* (`_lib/router_match.ts`, parity-by-construction with `router_telemetry`
|
|
10
|
+
* and `explain route`).
|
|
11
|
+
*
|
|
12
|
+
* Measurement level (ADR-126): this shows TRIGGER MATCHING only. Whether the
|
|
13
|
+
* host actually invokes a matched rule is a different measurement and is NOT
|
|
14
|
+
* made here — the mandatory first output line says so on every run.
|
|
15
|
+
*
|
|
16
|
+
* Exit codes: `0` at least one non-kernel rule matched, `1` nothing matched
|
|
17
|
+
* (kernel is always active, so "no match" still leaves the kernel), `2`
|
|
18
|
+
* invocation error (missing prompt, unreadable router.json).
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import * as fs from 'node:fs';
|
|
22
|
+
import * as path from 'node:path';
|
|
23
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
24
|
+
|
|
25
|
+
import {
|
|
26
|
+
match_prompt,
|
|
27
|
+
_asRuleList,
|
|
28
|
+
type Router,
|
|
29
|
+
type Rule,
|
|
30
|
+
type Trigger,
|
|
31
|
+
} from '../_lib/router_match.js';
|
|
32
|
+
import { measure, method_note } from '../_lib/token_count.js';
|
|
33
|
+
import { load_agent_settings } from '../_lib/agent_settings.js';
|
|
34
|
+
|
|
35
|
+
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
|
|
36
|
+
const ROUTER_JSON = path.join(REPO_ROOT, 'dist', 'router.json');
|
|
37
|
+
const RULES_DIST_DIR = path.join(REPO_ROOT, 'dist', 'agent-src', 'rules');
|
|
38
|
+
|
|
39
|
+
export const MEASUREMENT_HEADER =
|
|
40
|
+
'Measurement level: trigger matching only — what the host actually invokes is NOT measured here (ADR-126).';
|
|
41
|
+
|
|
42
|
+
interface RuleReport {
|
|
43
|
+
id: string;
|
|
44
|
+
tier: string;
|
|
45
|
+
matched: string[]; // "kind: value" labels
|
|
46
|
+
routes_to: string[];
|
|
47
|
+
disposition: string;
|
|
48
|
+
body_chars: number;
|
|
49
|
+
body_tokens_gpt: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface Report {
|
|
53
|
+
measurement_level: string;
|
|
54
|
+
prompt: string;
|
|
55
|
+
files: string[];
|
|
56
|
+
profile: string;
|
|
57
|
+
projection_mode: string;
|
|
58
|
+
kernel_always: string[];
|
|
59
|
+
matches: RuleReport[];
|
|
60
|
+
rejected: { reason: string; ids: string[] }[];
|
|
61
|
+
budget: { matched_chars: number; matched_tokens_gpt: number; method: string };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function _trigger_label(trigger: Trigger): string {
|
|
65
|
+
for (const kind of ['keyword', 'phrase', 'command', 'path_prefix', 'file_pattern']) {
|
|
66
|
+
if (kind in trigger) {
|
|
67
|
+
return `${kind}: ${String(trigger[kind])}`;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return `trigger: ${JSON.stringify(trigger)}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Projection mode from settings; the shipped default is eager-all. */
|
|
74
|
+
export function _projection_mode(): string {
|
|
75
|
+
try {
|
|
76
|
+
const settings = load_agent_settings({ cwd: REPO_ROOT }) as Record<string, unknown>;
|
|
77
|
+
const lp = settings['lean_projection'];
|
|
78
|
+
if (lp !== null && typeof lp === 'object' && !Array.isArray(lp)) {
|
|
79
|
+
const mode = (lp as Record<string, unknown>)['mode'];
|
|
80
|
+
if (typeof mode === 'string' && mode.trim() !== '') {
|
|
81
|
+
return mode.trim();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
} catch {
|
|
85
|
+
// settings unreadable → shipped default
|
|
86
|
+
}
|
|
87
|
+
return 'eager-all';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function _disposition(tier: string, projection_mode: string): string {
|
|
91
|
+
if (tier === 'kernel') {
|
|
92
|
+
return 'injected (kernel, always full-bodied)';
|
|
93
|
+
}
|
|
94
|
+
// Disposition is decided at projection time, not at runtime — say so
|
|
95
|
+
// instead of inventing a runtime injection the router does not perform.
|
|
96
|
+
return projection_mode === 'eager-all'
|
|
97
|
+
? `injected at projection time (${tier}, lean_projection.mode: eager-all)`
|
|
98
|
+
: `router-resolved pointer at projection time (${tier}, lean_projection.mode: ${projection_mode})`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function _rule_body_size(rule_id: string): { chars: number; tokens: number } {
|
|
102
|
+
const p = path.join(RULES_DIST_DIR, `${rule_id}.md`);
|
|
103
|
+
try {
|
|
104
|
+
const text = fs.readFileSync(p, 'utf-8');
|
|
105
|
+
const m = measure(text);
|
|
106
|
+
return { chars: m.chars, tokens: m.tokens_gpt };
|
|
107
|
+
} catch {
|
|
108
|
+
return { chars: 0, tokens: 0 };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function build_report(
|
|
113
|
+
router: Router,
|
|
114
|
+
prompt: string,
|
|
115
|
+
files: string[],
|
|
116
|
+
profile: string,
|
|
117
|
+
): Report {
|
|
118
|
+
const projection_mode = _projection_mode();
|
|
119
|
+
const result = match_prompt(router, prompt, profile, files.length > 0 ? files : null, null);
|
|
120
|
+
|
|
121
|
+
const matchedByRule = new Map<string, { tier: string; labels: string[] }>();
|
|
122
|
+
for (const mt of result.matched_triggers) {
|
|
123
|
+
const id = String(mt.rule);
|
|
124
|
+
const entry = matchedByRule.get(id) ?? { tier: mt.tier.replace('_', '-'), labels: [] };
|
|
125
|
+
entry.labels.push(_trigger_label(mt.trigger));
|
|
126
|
+
matchedByRule.set(id, entry);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const routesById = new Map<string, string[]>();
|
|
130
|
+
for (const tierKey of ['tier_1', 'tier_2'] as const) {
|
|
131
|
+
for (const rule of _asRuleList(router[tierKey])) {
|
|
132
|
+
routesById.set(String(rule['id']), ((rule['routes_to'] as unknown[]) ?? []).map(String));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const matches: RuleReport[] = [...matchedByRule.entries()]
|
|
137
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
138
|
+
.map(([id, { tier, labels }]) => {
|
|
139
|
+
const size = _rule_body_size(id);
|
|
140
|
+
return {
|
|
141
|
+
id,
|
|
142
|
+
tier,
|
|
143
|
+
matched: labels,
|
|
144
|
+
routes_to: routesById.get(id) ?? [],
|
|
145
|
+
disposition: _disposition(tier, projection_mode),
|
|
146
|
+
body_chars: size.chars,
|
|
147
|
+
body_tokens_gpt: size.tokens,
|
|
148
|
+
};
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const rejected_no_match: string[] = [];
|
|
152
|
+
for (const tierKey of ['tier_1', 'tier_2'] as const) {
|
|
153
|
+
if (tierKey === 'tier_2' && profile !== 'full') continue;
|
|
154
|
+
for (const rule of _asRuleList(router[tierKey])) {
|
|
155
|
+
const id = String(rule['id']);
|
|
156
|
+
if (!matchedByRule.has(id)) rejected_no_match.push(id);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
rejected_no_match.sort();
|
|
160
|
+
const rejected: Report['rejected'] = [
|
|
161
|
+
{ reason: 'no trigger matched', ids: rejected_no_match },
|
|
162
|
+
];
|
|
163
|
+
if (profile !== 'full') {
|
|
164
|
+
rejected.push({
|
|
165
|
+
reason: `tier-2 excluded by profile '${profile}' (tier-2 is considered under profile 'full' only)`,
|
|
166
|
+
ids: _asRuleList(router['tier_2']).map((r: Rule) => String(r['id'])).sort(),
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const kernel_always = (Array.isArray(router['kernel']) ? router['kernel'] : []).map(String);
|
|
171
|
+
const matched_chars = matches.reduce((s, m) => s + m.body_chars, 0);
|
|
172
|
+
const matched_tokens = matches.reduce((s, m) => s + m.body_tokens_gpt, 0);
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
measurement_level: MEASUREMENT_HEADER,
|
|
176
|
+
prompt,
|
|
177
|
+
files,
|
|
178
|
+
profile,
|
|
179
|
+
projection_mode,
|
|
180
|
+
kernel_always,
|
|
181
|
+
matches,
|
|
182
|
+
rejected,
|
|
183
|
+
budget: { matched_chars, matched_tokens_gpt: matched_tokens, method: method_note() },
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function render_text(report: Report): string {
|
|
188
|
+
const out: string[] = [];
|
|
189
|
+
out.push(report.measurement_level);
|
|
190
|
+
out.push('');
|
|
191
|
+
out.push(`prompt: ${JSON.stringify(report.prompt)}`);
|
|
192
|
+
if (report.files.length > 0) out.push(`files: ${report.files.join(', ')}`);
|
|
193
|
+
out.push(`profile: ${report.profile} · projection mode: ${report.projection_mode}`);
|
|
194
|
+
out.push('');
|
|
195
|
+
out.push(`kernel (always active, ${report.kernel_always.length}): ${report.kernel_always.join(', ')}`);
|
|
196
|
+
out.push('');
|
|
197
|
+
out.push(`matched rules (${report.matches.length}):`);
|
|
198
|
+
for (const m of report.matches) {
|
|
199
|
+
out.push(` · ${m.id} [${m.tier}]`);
|
|
200
|
+
for (const label of m.matched) out.push(` matched ${label}`);
|
|
201
|
+
out.push(` disposition: ${m.disposition}`);
|
|
202
|
+
if (m.routes_to.length > 0) out.push(` routes_to: ${m.routes_to.join(', ')}`);
|
|
203
|
+
out.push(` body: ${m.body_chars} chars ≈ ${m.body_tokens_gpt} GPT tokens`);
|
|
204
|
+
}
|
|
205
|
+
if (report.matches.length === 0) {
|
|
206
|
+
out.push(' · (no trigger matched — only kernel rules active)');
|
|
207
|
+
}
|
|
208
|
+
out.push('');
|
|
209
|
+
out.push(
|
|
210
|
+
`budget consumption of matched non-kernel bodies: ${report.budget.matched_chars} chars`
|
|
211
|
+
+ ` ≈ ${report.budget.matched_tokens_gpt} GPT tokens (${report.budget.method})`,
|
|
212
|
+
);
|
|
213
|
+
for (const r of report.rejected) {
|
|
214
|
+
out.push(`rejected — ${r.reason}: ${r.ids.length} rule(s)`);
|
|
215
|
+
}
|
|
216
|
+
return out.join('\n') + '\n';
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function main(argv: string[]): number {
|
|
220
|
+
const args = [...argv];
|
|
221
|
+
const as_json = args.includes('--json');
|
|
222
|
+
let files: string[] = [];
|
|
223
|
+
let profile = 'full';
|
|
224
|
+
const positional: string[] = [];
|
|
225
|
+
for (let i = 0; i < args.length; i++) {
|
|
226
|
+
const a = args[i] as string;
|
|
227
|
+
if (a === '--json') continue;
|
|
228
|
+
if (a === '--files') {
|
|
229
|
+
files = String(args[++i] ?? '').split(',').map((s) => s.trim()).filter(Boolean);
|
|
230
|
+
} else if (a.startsWith('--files=')) {
|
|
231
|
+
files = a.slice('--files='.length).split(',').map((s) => s.trim()).filter(Boolean);
|
|
232
|
+
} else if (a === '--profile') {
|
|
233
|
+
profile = String(args[++i] ?? 'full');
|
|
234
|
+
} else if (a.startsWith('--profile=')) {
|
|
235
|
+
profile = a.slice('--profile='.length);
|
|
236
|
+
} else if (a === '-h' || a === '--help') {
|
|
237
|
+
process.stdout.write(
|
|
238
|
+
'usage: agent-config route:explain "<prompt>" [--files a,b] [--profile full|balanced] [--json]\n',
|
|
239
|
+
);
|
|
240
|
+
return 0;
|
|
241
|
+
} else {
|
|
242
|
+
positional.push(a);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const prompt = positional.join(' ').trim();
|
|
246
|
+
if (!prompt) {
|
|
247
|
+
process.stderr.write('route:explain: a prompt is required\n');
|
|
248
|
+
return 2;
|
|
249
|
+
}
|
|
250
|
+
let router: Router;
|
|
251
|
+
try {
|
|
252
|
+
router = JSON.parse(fs.readFileSync(ROUTER_JSON, 'utf-8')) as Router;
|
|
253
|
+
} catch (e) {
|
|
254
|
+
process.stderr.write(`route:explain: cannot read ${ROUTER_JSON}: ${String(e)}\n`);
|
|
255
|
+
return 2;
|
|
256
|
+
}
|
|
257
|
+
const report = build_report(router, prompt, files, profile);
|
|
258
|
+
if (as_json) {
|
|
259
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
260
|
+
} else {
|
|
261
|
+
process.stdout.write(render_text(report));
|
|
262
|
+
}
|
|
263
|
+
return report.matches.length === 0 ? 1 : 0;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const _HERE = fileURLToPath(import.meta.url);
|
|
267
|
+
if (process.argv[1] && (import.meta.url === pathToFileURL(process.argv[1]).href || path.resolve(process.argv[1]) === _HERE)) {
|
|
268
|
+
process.exitCode = main(process.argv.slice(2));
|
|
269
|
+
}
|