@event4u/agent-config 9.17.0 → 9.18.1
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 +122 -171
- package/dist/agent-src/commands/challenge-me/vision.md +5 -0
- 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/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/execution/plan-confidence-gate.md +133 -0
- package/dist/agent-src/rules/active-remediation.md +2 -0
- package/dist/agent-src/rules/architecture.md +2 -0
- package/dist/agent-src/rules/augment-edit-discipline.md +2 -0
- 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/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/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/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/ui-audit-gate.md +2 -0
- 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/roadmap-management/SKILL.md +10 -0
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +12 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +12 -0
- 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/cli/registry.js +2 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/chunk-AIIUU73N.js +2040 -0
- package/dist/cli-delegate/{chunk-IMSXPRVH.js → chunk-ELMFOQPW.js} +11 -0
- package/dist/cli-delegate/chunk-LF2KKJ4Q.js +183 -0
- package/dist/cli-delegate/cmd_explain.js +36 -36
- package/dist/cli-delegate/cmd_export.js +1 -1
- package/dist/cli-delegate/cmd_handoff.js +203 -2228
- package/dist/cli-delegate/cmd_prune.js +1 -1
- 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 +1 -1
- package/dist/cli-delegate/cmd_sync.js +1 -1
- package/dist/cli-delegate/cmd_uninstall.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +57 -57
- 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/install/install.mjs +11 -0
- package/dist/mcp/registry-manifest.json +1 -1
- package/dist/mcp/server.json +2 -2
- package/dist/router.json +1 -1
- package/dist/server/schemas/settings.js +12 -0
- package/dist/server/schemas/settings.js.map +1 -1
- 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 +46 -0
- package/src/config/evaluator-budgets.json +3 -3
- package/src/config/gate-coverage.yml +44 -0
- package/src/scripts/_cli/cmd_explain.ts +41 -36
- package/src/scripts/_cli/cmd_route_audit.ts +290 -0
- package/src/scripts/_cli/cmd_route_explain.ts +269 -0
- package/src/scripts/_dispatch.bash +23 -0
- 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_highlights.ts +279 -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 +1322 -0
- package/src/scripts/check_release_highlights.ts +60 -152
- package/src/scripts/compile_router.ts +20 -3
- package/src/scripts/dispatch_r2_reviewer.ts +969 -0
- package/src/scripts/eval_ui_triviality.ts +156 -0
- package/src/scripts/lint_abstraction_thresholds.ts +3 -1
- package/src/scripts/lint_plan_risk_register.ts +931 -0
- package/src/scripts/lint_trigger_collisions.ts +257 -0
- package/src/scripts/release.ts +47 -13
- package/src/scripts/router_telemetry.ts +16 -290
- package/src/scripts/schemas/rule.schema.json +10 -0
- package/src/server/schemas/settings.ts +18 -0
|
@@ -1,7 +1,7 @@
|
|
|
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-
|
|
4
|
+
} from "./chunk-ELMFOQPW.js";
|
|
5
5
|
import "./chunk-WR6GTRHJ.js";
|
|
6
6
|
import "./chunk-BKO2AZ7Z.js";
|
|
7
7
|
import {
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
match_prompt
|
|
5
|
+
} from "./chunk-LF2KKJ4Q.js";
|
|
6
|
+
import {
|
|
7
|
+
read_entries
|
|
8
|
+
} from "./chunk-AIIUU73N.js";
|
|
9
|
+
import "./chunk-XGA2NTU4.js";
|
|
10
|
+
import {
|
|
11
|
+
load_agent_settings
|
|
12
|
+
} from "./chunk-HJ6DAJHR.js";
|
|
13
|
+
import "./chunk-NDJLNC6Q.js";
|
|
14
|
+
import "./chunk-OY53J6II.js";
|
|
15
|
+
import "./chunk-J55WI3RR.js";
|
|
16
|
+
|
|
17
|
+
// src/scripts/_cli/cmd_route_audit.ts
|
|
18
|
+
import * as crypto from "node:crypto";
|
|
19
|
+
import * as fs from "node:fs";
|
|
20
|
+
import * as path from "node:path";
|
|
21
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
22
|
+
var REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
|
|
23
|
+
var ROUTER_JSON = path.join(REPO_ROOT, "dist", "router.json");
|
|
24
|
+
var RECORDER_REL = "agents/runtime/state/routing-telemetry.jsonl";
|
|
25
|
+
var RULE_TRIPS_REL = "agents/runtime/state/rule-trips.json";
|
|
26
|
+
var RECORD_SCHEMA_VERSION = 1;
|
|
27
|
+
var MEASUREMENT_HEADER = "Measurement level: trigger matching only \u2014 what the host actually invokes is NOT measured here (ADR-126).";
|
|
28
|
+
var PREREG_AUTHORITY_LINE = "Resolver authority: internal/bench/layer1-resolver-PREREG.md \u2014 this corpus feeds its P2 condition as a side effect; nothing here revives a resolver.";
|
|
29
|
+
function recorder_path() {
|
|
30
|
+
return process.env["AGENT_ROUTING_TELEMETRY_FILE"] ?? path.join(REPO_ROOT, RECORDER_REL);
|
|
31
|
+
}
|
|
32
|
+
function recorder_enabled() {
|
|
33
|
+
try {
|
|
34
|
+
const settings = load_agent_settings({ cwd: REPO_ROOT });
|
|
35
|
+
const t = settings["telemetry"];
|
|
36
|
+
if (t === null || typeof t !== "object" || Array.isArray(t)) return false;
|
|
37
|
+
const rr = t["routing_recorder"];
|
|
38
|
+
if (rr === null || typeof rr !== "object" || Array.isArray(rr)) return false;
|
|
39
|
+
const enabled = rr["enabled"];
|
|
40
|
+
return enabled === true || enabled === "true" || enabled === "on" || enabled === "yes";
|
|
41
|
+
} catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function _trigger_label(trigger) {
|
|
46
|
+
for (const kind of ["keyword", "phrase", "command", "path_prefix", "file_pattern"]) {
|
|
47
|
+
if (kind in trigger) return `${kind}: ${String(trigger[kind])}`;
|
|
48
|
+
}
|
|
49
|
+
return JSON.stringify(trigger);
|
|
50
|
+
}
|
|
51
|
+
function audit_prompts(router, prompts) {
|
|
52
|
+
return prompts.map((prompt) => {
|
|
53
|
+
const result = match_prompt(router, prompt, "full", null, null);
|
|
54
|
+
const byRule = /* @__PURE__ */ new Map();
|
|
55
|
+
for (const mt of result.matched_triggers) {
|
|
56
|
+
const id = String(mt.rule);
|
|
57
|
+
const entry = byRule.get(id) ?? { tier: mt.tier.replace("_", "-"), triggers: [] };
|
|
58
|
+
entry.triggers.push(_trigger_label(mt.trigger));
|
|
59
|
+
byRule.set(id, entry);
|
|
60
|
+
}
|
|
61
|
+
const matched = [...byRule.entries()].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([rule, v]) => ({ rule, tier: v.tier, triggers: v.triggers }));
|
|
62
|
+
return { prompt, matched };
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function load_user_prompts(last, history_path) {
|
|
66
|
+
let entries = [];
|
|
67
|
+
try {
|
|
68
|
+
entries = read_entries({ path: history_path ?? null });
|
|
69
|
+
} catch {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
const prompts = [];
|
|
73
|
+
for (const e of entries) {
|
|
74
|
+
if (e === null || typeof e !== "object") continue;
|
|
75
|
+
if (e.t !== "user" || typeof e.text !== "string") continue;
|
|
76
|
+
const text = e.text.trim();
|
|
77
|
+
if (text === "" || text.startsWith("<") || text.startsWith("Caveat:")) continue;
|
|
78
|
+
prompts.push(text);
|
|
79
|
+
}
|
|
80
|
+
return prompts.slice(-last);
|
|
81
|
+
}
|
|
82
|
+
function _load_trips() {
|
|
83
|
+
try {
|
|
84
|
+
return JSON.parse(fs.readFileSync(path.join(REPO_ROOT, RULE_TRIPS_REL), "utf-8"));
|
|
85
|
+
} catch {
|
|
86
|
+
return {};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function build_records(audits, now_iso) {
|
|
90
|
+
const trips = _load_trips();
|
|
91
|
+
return audits.map((a) => {
|
|
92
|
+
const enforcement_trips = {};
|
|
93
|
+
for (const m of a.matched) {
|
|
94
|
+
const concern = trips.concerns?.[m.rule];
|
|
95
|
+
if (concern) {
|
|
96
|
+
enforcement_trips[m.rule] = { block: concern.block ?? 0, warn: concern.warn ?? 0 };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
schema_version: RECORD_SCHEMA_VERSION,
|
|
101
|
+
ts: now_iso,
|
|
102
|
+
prompt_sha16: crypto.createHash("sha256").update(a.prompt).digest("hex").slice(0, 16),
|
|
103
|
+
matched: a.matched,
|
|
104
|
+
enforcement_trips
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
function append_records(records, target) {
|
|
109
|
+
if (process.env["AGENT_CONFIG_REPLAY"] === "1") return 0;
|
|
110
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
111
|
+
const fd = fs.openSync(target, "a", 420);
|
|
112
|
+
try {
|
|
113
|
+
for (const r of records) fs.writeSync(fd, JSON.stringify(r) + "\n");
|
|
114
|
+
fs.fsyncSync(fd);
|
|
115
|
+
} finally {
|
|
116
|
+
fs.closeSync(fd);
|
|
117
|
+
}
|
|
118
|
+
return records.length;
|
|
119
|
+
}
|
|
120
|
+
function render_weekly(target, now) {
|
|
121
|
+
let lines = [];
|
|
122
|
+
try {
|
|
123
|
+
lines = fs.readFileSync(target, "utf-8").split("\n").filter(Boolean);
|
|
124
|
+
} catch {
|
|
125
|
+
lines = [];
|
|
126
|
+
}
|
|
127
|
+
const cutoff = now.getTime() - 7 * 24 * 60 * 60 * 1e3;
|
|
128
|
+
const perRule = /* @__PURE__ */ new Map();
|
|
129
|
+
let inWindow = 0;
|
|
130
|
+
for (const line of lines) {
|
|
131
|
+
let rec;
|
|
132
|
+
try {
|
|
133
|
+
rec = JSON.parse(line);
|
|
134
|
+
} catch {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const ts = Date.parse(rec.ts ?? "");
|
|
138
|
+
if (Number.isNaN(ts) || ts < cutoff) continue;
|
|
139
|
+
inWindow += 1;
|
|
140
|
+
for (const m of rec.matched ?? []) {
|
|
141
|
+
perRule.set(m.rule, (perRule.get(m.rule) ?? 0) + 1);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const out = [MEASUREMENT_HEADER, ""];
|
|
145
|
+
out.push(`routing recorder \u2014 rolling 7-day window (${inWindow} recorded prompt(s))`);
|
|
146
|
+
if (inWindow === 0) {
|
|
147
|
+
out.push(" (no records in the window \u2014 enable telemetry.routing_recorder and run `route:audit --record`)");
|
|
148
|
+
} else {
|
|
149
|
+
const rows = [...perRule.entries()].sort((a, b) => b[1] - a[1] || (a[0] < b[0] ? -1 : 1));
|
|
150
|
+
for (const [rule, n] of rows) out.push(` ${String(n).padStart(4)} \xD7 ${rule}`);
|
|
151
|
+
}
|
|
152
|
+
out.push("");
|
|
153
|
+
out.push(PREREG_AUTHORITY_LINE);
|
|
154
|
+
return { text: out.join("\n") + "\n", records: inWindow };
|
|
155
|
+
}
|
|
156
|
+
function main(argv) {
|
|
157
|
+
const args = [...argv];
|
|
158
|
+
const as_json = args.includes("--json");
|
|
159
|
+
const weekly = args.includes("--weekly");
|
|
160
|
+
const record = args.includes("--record");
|
|
161
|
+
let last = 10;
|
|
162
|
+
for (let i = 0; i < args.length; i++) {
|
|
163
|
+
const a = args[i];
|
|
164
|
+
if (a === "--last") last = Number(args[++i] ?? "10") || 10;
|
|
165
|
+
else if (a.startsWith("--last=")) last = Number(a.slice("--last=".length)) || 10;
|
|
166
|
+
else if (a === "-h" || a === "--help") {
|
|
167
|
+
process.stdout.write("usage: agent-config route:audit [--last N] [--record] [--weekly] [--json]\n");
|
|
168
|
+
return 0;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (weekly) {
|
|
172
|
+
const { text, records } = render_weekly(recorder_path(), /* @__PURE__ */ new Date());
|
|
173
|
+
process.stdout.write(text);
|
|
174
|
+
return records === 0 ? 1 : 0;
|
|
175
|
+
}
|
|
176
|
+
let router;
|
|
177
|
+
try {
|
|
178
|
+
router = JSON.parse(fs.readFileSync(ROUTER_JSON, "utf-8"));
|
|
179
|
+
} catch (e) {
|
|
180
|
+
process.stderr.write(`route:audit: cannot read ${ROUTER_JSON}: ${String(e)}
|
|
181
|
+
`);
|
|
182
|
+
return 2;
|
|
183
|
+
}
|
|
184
|
+
const prompts = load_user_prompts(last);
|
|
185
|
+
if (prompts.length === 0) {
|
|
186
|
+
process.stdout.write(MEASUREMENT_HEADER + "\n\n");
|
|
187
|
+
process.stdout.write("no user prompts found in the chat-history log \u2014 nothing to audit\n");
|
|
188
|
+
return 1;
|
|
189
|
+
}
|
|
190
|
+
const audits = audit_prompts(router, prompts);
|
|
191
|
+
let recorded = 0;
|
|
192
|
+
let recorder_note = "";
|
|
193
|
+
if (record) {
|
|
194
|
+
if (recorder_enabled()) {
|
|
195
|
+
recorded = append_records(build_records(audits, (/* @__PURE__ */ new Date()).toISOString()), recorder_path());
|
|
196
|
+
recorder_note = `recorded ${recorded} prompt(s) to ${RECORDER_REL}`;
|
|
197
|
+
} else {
|
|
198
|
+
recorder_note = "recorder disabled (telemetry.routing_recorder.enabled is off \u2014 default) \u2014 nothing written";
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (as_json) {
|
|
202
|
+
process.stdout.write(
|
|
203
|
+
JSON.stringify(
|
|
204
|
+
{ measurement_level: MEASUREMENT_HEADER, audited: audits.length, recorded, prompts: audits },
|
|
205
|
+
null,
|
|
206
|
+
2
|
|
207
|
+
) + "\n"
|
|
208
|
+
);
|
|
209
|
+
return 0;
|
|
210
|
+
}
|
|
211
|
+
const out = [MEASUREMENT_HEADER, ""];
|
|
212
|
+
out.push(`audited the last ${audits.length} user prompt(s) \u2014 matched rules per prompt`);
|
|
213
|
+
out.push("(should-have-matched is the reviewer's judgment over this table, not a computed verdict)");
|
|
214
|
+
out.push("");
|
|
215
|
+
audits.forEach((a, i) => {
|
|
216
|
+
const shown = a.prompt.length > 100 ? a.prompt.slice(0, 97) + "..." : a.prompt;
|
|
217
|
+
out.push(`${String(i + 1).padStart(3)}. ${JSON.stringify(shown)}`);
|
|
218
|
+
if (a.matched.length === 0) {
|
|
219
|
+
out.push(" \u2192 (no trigger matched \u2014 kernel only)");
|
|
220
|
+
} else {
|
|
221
|
+
for (const m of a.matched) {
|
|
222
|
+
out.push(` \u2192 ${m.rule} [${m.tier}] (${m.triggers.join(" \xB7 ")})`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
if (recorder_note) {
|
|
227
|
+
out.push("");
|
|
228
|
+
out.push(recorder_note);
|
|
229
|
+
}
|
|
230
|
+
process.stdout.write(out.join("\n") + "\n");
|
|
231
|
+
return 0;
|
|
232
|
+
}
|
|
233
|
+
var _HERE = fileURLToPath(import.meta.url);
|
|
234
|
+
if (process.argv[1] && (import.meta.url === pathToFileURL(process.argv[1]).href || path.resolve(process.argv[1]) === _HERE)) {
|
|
235
|
+
process.exitCode = main(process.argv.slice(2));
|
|
236
|
+
}
|
|
237
|
+
export {
|
|
238
|
+
MEASUREMENT_HEADER,
|
|
239
|
+
PREREG_AUTHORITY_LINE,
|
|
240
|
+
RECORDER_REL,
|
|
241
|
+
RECORD_SCHEMA_VERSION,
|
|
242
|
+
append_records,
|
|
243
|
+
audit_prompts,
|
|
244
|
+
build_records,
|
|
245
|
+
load_user_prompts,
|
|
246
|
+
main,
|
|
247
|
+
recorder_enabled,
|
|
248
|
+
render_weekly
|
|
249
|
+
};
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
_asRuleList,
|
|
5
|
+
match_prompt
|
|
6
|
+
} from "./chunk-LF2KKJ4Q.js";
|
|
7
|
+
import {
|
|
8
|
+
load_agent_settings
|
|
9
|
+
} from "./chunk-HJ6DAJHR.js";
|
|
10
|
+
import "./chunk-NDJLNC6Q.js";
|
|
11
|
+
import "./chunk-J55WI3RR.js";
|
|
12
|
+
|
|
13
|
+
// src/scripts/_cli/cmd_route_explain.ts
|
|
14
|
+
import * as fs from "node:fs";
|
|
15
|
+
import * as path from "node:path";
|
|
16
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
17
|
+
|
|
18
|
+
// src/scripts/_lib/token_count.ts
|
|
19
|
+
import { createRequire } from "node:module";
|
|
20
|
+
var _GPT_CHARS_PER_TOKEN = 4;
|
|
21
|
+
var _CLAUDE_CHARS_PER_TOKEN = 3.6;
|
|
22
|
+
var _TIKTOKEN_ENCODING = "cl100k_base";
|
|
23
|
+
function _loadEncoder() {
|
|
24
|
+
try {
|
|
25
|
+
const require2 = createRequire(import.meta.url);
|
|
26
|
+
const mod = require2("js-tiktoken");
|
|
27
|
+
return mod.getEncoding(_TIKTOKEN_ENCODING);
|
|
28
|
+
} catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
var _ENCODER = _loadEncoder();
|
|
33
|
+
var TIKTOKEN_AVAILABLE = _ENCODER !== null;
|
|
34
|
+
var TokenCount = class {
|
|
35
|
+
tokens;
|
|
36
|
+
exact;
|
|
37
|
+
constructor(tokens, exact) {
|
|
38
|
+
this.tokens = tokens;
|
|
39
|
+
this.exact = exact;
|
|
40
|
+
Object.freeze(this);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
function _len(text) {
|
|
44
|
+
let count = 0;
|
|
45
|
+
for (const _ch of text) count += 1;
|
|
46
|
+
return count;
|
|
47
|
+
}
|
|
48
|
+
function _python_round(x) {
|
|
49
|
+
const floor = Math.floor(x);
|
|
50
|
+
const diff = x - floor;
|
|
51
|
+
if (diff > 0.5) return floor + 1;
|
|
52
|
+
if (diff < 0.5) return floor;
|
|
53
|
+
return floor % 2 === 0 ? floor : floor + 1;
|
|
54
|
+
}
|
|
55
|
+
function _py_float_repr(x) {
|
|
56
|
+
return Number.isInteger(x) ? `${x}.0` : `${x}`;
|
|
57
|
+
}
|
|
58
|
+
function gpt_tokens(text) {
|
|
59
|
+
if (_ENCODER !== null) {
|
|
60
|
+
return new TokenCount(_ENCODER.encode(text).length, true);
|
|
61
|
+
}
|
|
62
|
+
return gpt_tokens_proxy(text);
|
|
63
|
+
}
|
|
64
|
+
function gpt_tokens_proxy(text) {
|
|
65
|
+
return new TokenCount(_python_round(_len(text) / _GPT_CHARS_PER_TOKEN), false);
|
|
66
|
+
}
|
|
67
|
+
function claude_tokens(text) {
|
|
68
|
+
return new TokenCount(
|
|
69
|
+
_python_round(_len(text) / _CLAUDE_CHARS_PER_TOKEN),
|
|
70
|
+
false
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
function measure(text) {
|
|
74
|
+
const g = gpt_tokens(text);
|
|
75
|
+
const c = claude_tokens(text);
|
|
76
|
+
return {
|
|
77
|
+
chars: _len(text),
|
|
78
|
+
tokens_gpt: g.tokens,
|
|
79
|
+
tokens_gpt_exact: g.exact,
|
|
80
|
+
tokens_claude: c.tokens,
|
|
81
|
+
tokens_claude_exact: c.exact
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function method_note_proxy() {
|
|
85
|
+
return `tokens_gpt: proxy (chars/${_py_float_repr(_GPT_CHARS_PER_TOKEN)}, tiktoken not installed); tokens_claude: proxy (chars/${_py_float_repr(_CLAUDE_CHARS_PER_TOKEN)})`;
|
|
86
|
+
}
|
|
87
|
+
function method_note() {
|
|
88
|
+
if (TIKTOKEN_AVAILABLE) {
|
|
89
|
+
return `tokens_gpt: exact (tiktoken ${_TIKTOKEN_ENCODING}); tokens_claude: proxy (chars/${_py_float_repr(_CLAUDE_CHARS_PER_TOKEN)})`;
|
|
90
|
+
}
|
|
91
|
+
return method_note_proxy();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// src/scripts/_cli/cmd_route_explain.ts
|
|
95
|
+
var REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
|
|
96
|
+
var ROUTER_JSON = path.join(REPO_ROOT, "dist", "router.json");
|
|
97
|
+
var RULES_DIST_DIR = path.join(REPO_ROOT, "dist", "agent-src", "rules");
|
|
98
|
+
var MEASUREMENT_HEADER = "Measurement level: trigger matching only \u2014 what the host actually invokes is NOT measured here (ADR-126).";
|
|
99
|
+
function _trigger_label(trigger) {
|
|
100
|
+
for (const kind of ["keyword", "phrase", "command", "path_prefix", "file_pattern"]) {
|
|
101
|
+
if (kind in trigger) {
|
|
102
|
+
return `${kind}: ${String(trigger[kind])}`;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return `trigger: ${JSON.stringify(trigger)}`;
|
|
106
|
+
}
|
|
107
|
+
function _projection_mode() {
|
|
108
|
+
try {
|
|
109
|
+
const settings = load_agent_settings({ cwd: REPO_ROOT });
|
|
110
|
+
const lp = settings["lean_projection"];
|
|
111
|
+
if (lp !== null && typeof lp === "object" && !Array.isArray(lp)) {
|
|
112
|
+
const mode = lp["mode"];
|
|
113
|
+
if (typeof mode === "string" && mode.trim() !== "") {
|
|
114
|
+
return mode.trim();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
} catch {
|
|
118
|
+
}
|
|
119
|
+
return "eager-all";
|
|
120
|
+
}
|
|
121
|
+
function _disposition(tier, projection_mode) {
|
|
122
|
+
if (tier === "kernel") {
|
|
123
|
+
return "injected (kernel, always full-bodied)";
|
|
124
|
+
}
|
|
125
|
+
return projection_mode === "eager-all" ? `injected at projection time (${tier}, lean_projection.mode: eager-all)` : `router-resolved pointer at projection time (${tier}, lean_projection.mode: ${projection_mode})`;
|
|
126
|
+
}
|
|
127
|
+
function _rule_body_size(rule_id) {
|
|
128
|
+
const p = path.join(RULES_DIST_DIR, `${rule_id}.md`);
|
|
129
|
+
try {
|
|
130
|
+
const text = fs.readFileSync(p, "utf-8");
|
|
131
|
+
const m = measure(text);
|
|
132
|
+
return { chars: m.chars, tokens: m.tokens_gpt };
|
|
133
|
+
} catch {
|
|
134
|
+
return { chars: 0, tokens: 0 };
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function build_report(router, prompt, files, profile) {
|
|
138
|
+
const projection_mode = _projection_mode();
|
|
139
|
+
const result = match_prompt(router, prompt, profile, files.length > 0 ? files : null, null);
|
|
140
|
+
const matchedByRule = /* @__PURE__ */ new Map();
|
|
141
|
+
for (const mt of result.matched_triggers) {
|
|
142
|
+
const id = String(mt.rule);
|
|
143
|
+
const entry = matchedByRule.get(id) ?? { tier: mt.tier.replace("_", "-"), labels: [] };
|
|
144
|
+
entry.labels.push(_trigger_label(mt.trigger));
|
|
145
|
+
matchedByRule.set(id, entry);
|
|
146
|
+
}
|
|
147
|
+
const routesById = /* @__PURE__ */ new Map();
|
|
148
|
+
for (const tierKey of ["tier_1", "tier_2"]) {
|
|
149
|
+
for (const rule of _asRuleList(router[tierKey])) {
|
|
150
|
+
routesById.set(String(rule["id"]), (rule["routes_to"] ?? []).map(String));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const matches = [...matchedByRule.entries()].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([id, { tier, labels }]) => {
|
|
154
|
+
const size = _rule_body_size(id);
|
|
155
|
+
return {
|
|
156
|
+
id,
|
|
157
|
+
tier,
|
|
158
|
+
matched: labels,
|
|
159
|
+
routes_to: routesById.get(id) ?? [],
|
|
160
|
+
disposition: _disposition(tier, projection_mode),
|
|
161
|
+
body_chars: size.chars,
|
|
162
|
+
body_tokens_gpt: size.tokens
|
|
163
|
+
};
|
|
164
|
+
});
|
|
165
|
+
const rejected_no_match = [];
|
|
166
|
+
for (const tierKey of ["tier_1", "tier_2"]) {
|
|
167
|
+
if (tierKey === "tier_2" && profile !== "full") continue;
|
|
168
|
+
for (const rule of _asRuleList(router[tierKey])) {
|
|
169
|
+
const id = String(rule["id"]);
|
|
170
|
+
if (!matchedByRule.has(id)) rejected_no_match.push(id);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
rejected_no_match.sort();
|
|
174
|
+
const rejected = [
|
|
175
|
+
{ reason: "no trigger matched", ids: rejected_no_match }
|
|
176
|
+
];
|
|
177
|
+
if (profile !== "full") {
|
|
178
|
+
rejected.push({
|
|
179
|
+
reason: `tier-2 excluded by profile '${profile}' (tier-2 is considered under profile 'full' only)`,
|
|
180
|
+
ids: _asRuleList(router["tier_2"]).map((r) => String(r["id"])).sort()
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
const kernel_always = (Array.isArray(router["kernel"]) ? router["kernel"] : []).map(String);
|
|
184
|
+
const matched_chars = matches.reduce((s, m) => s + m.body_chars, 0);
|
|
185
|
+
const matched_tokens = matches.reduce((s, m) => s + m.body_tokens_gpt, 0);
|
|
186
|
+
return {
|
|
187
|
+
measurement_level: MEASUREMENT_HEADER,
|
|
188
|
+
prompt,
|
|
189
|
+
files,
|
|
190
|
+
profile,
|
|
191
|
+
projection_mode,
|
|
192
|
+
kernel_always,
|
|
193
|
+
matches,
|
|
194
|
+
rejected,
|
|
195
|
+
budget: { matched_chars, matched_tokens_gpt: matched_tokens, method: method_note() }
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function render_text(report) {
|
|
199
|
+
const out = [];
|
|
200
|
+
out.push(report.measurement_level);
|
|
201
|
+
out.push("");
|
|
202
|
+
out.push(`prompt: ${JSON.stringify(report.prompt)}`);
|
|
203
|
+
if (report.files.length > 0) out.push(`files: ${report.files.join(", ")}`);
|
|
204
|
+
out.push(`profile: ${report.profile} \xB7 projection mode: ${report.projection_mode}`);
|
|
205
|
+
out.push("");
|
|
206
|
+
out.push(`kernel (always active, ${report.kernel_always.length}): ${report.kernel_always.join(", ")}`);
|
|
207
|
+
out.push("");
|
|
208
|
+
out.push(`matched rules (${report.matches.length}):`);
|
|
209
|
+
for (const m of report.matches) {
|
|
210
|
+
out.push(` \xB7 ${m.id} [${m.tier}]`);
|
|
211
|
+
for (const label of m.matched) out.push(` matched ${label}`);
|
|
212
|
+
out.push(` disposition: ${m.disposition}`);
|
|
213
|
+
if (m.routes_to.length > 0) out.push(` routes_to: ${m.routes_to.join(", ")}`);
|
|
214
|
+
out.push(` body: ${m.body_chars} chars \u2248 ${m.body_tokens_gpt} GPT tokens`);
|
|
215
|
+
}
|
|
216
|
+
if (report.matches.length === 0) {
|
|
217
|
+
out.push(" \xB7 (no trigger matched \u2014 only kernel rules active)");
|
|
218
|
+
}
|
|
219
|
+
out.push("");
|
|
220
|
+
out.push(
|
|
221
|
+
`budget consumption of matched non-kernel bodies: ${report.budget.matched_chars} chars \u2248 ${report.budget.matched_tokens_gpt} GPT tokens (${report.budget.method})`
|
|
222
|
+
);
|
|
223
|
+
for (const r of report.rejected) {
|
|
224
|
+
out.push(`rejected \u2014 ${r.reason}: ${r.ids.length} rule(s)`);
|
|
225
|
+
}
|
|
226
|
+
return out.join("\n") + "\n";
|
|
227
|
+
}
|
|
228
|
+
function main(argv) {
|
|
229
|
+
const args = [...argv];
|
|
230
|
+
const as_json = args.includes("--json");
|
|
231
|
+
let files = [];
|
|
232
|
+
let profile = "full";
|
|
233
|
+
const positional = [];
|
|
234
|
+
for (let i = 0; i < args.length; i++) {
|
|
235
|
+
const a = args[i];
|
|
236
|
+
if (a === "--json") continue;
|
|
237
|
+
if (a === "--files") {
|
|
238
|
+
files = String(args[++i] ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
239
|
+
} else if (a.startsWith("--files=")) {
|
|
240
|
+
files = a.slice("--files=".length).split(",").map((s) => s.trim()).filter(Boolean);
|
|
241
|
+
} else if (a === "--profile") {
|
|
242
|
+
profile = String(args[++i] ?? "full");
|
|
243
|
+
} else if (a.startsWith("--profile=")) {
|
|
244
|
+
profile = a.slice("--profile=".length);
|
|
245
|
+
} else if (a === "-h" || a === "--help") {
|
|
246
|
+
process.stdout.write(
|
|
247
|
+
'usage: agent-config route:explain "<prompt>" [--files a,b] [--profile full|balanced] [--json]\n'
|
|
248
|
+
);
|
|
249
|
+
return 0;
|
|
250
|
+
} else {
|
|
251
|
+
positional.push(a);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
const prompt = positional.join(" ").trim();
|
|
255
|
+
if (!prompt) {
|
|
256
|
+
process.stderr.write("route:explain: a prompt is required\n");
|
|
257
|
+
return 2;
|
|
258
|
+
}
|
|
259
|
+
let router;
|
|
260
|
+
try {
|
|
261
|
+
router = JSON.parse(fs.readFileSync(ROUTER_JSON, "utf-8"));
|
|
262
|
+
} catch (e) {
|
|
263
|
+
process.stderr.write(`route:explain: cannot read ${ROUTER_JSON}: ${String(e)}
|
|
264
|
+
`);
|
|
265
|
+
return 2;
|
|
266
|
+
}
|
|
267
|
+
const report = build_report(router, prompt, files, profile);
|
|
268
|
+
if (as_json) {
|
|
269
|
+
process.stdout.write(JSON.stringify(report, null, 2) + "\n");
|
|
270
|
+
} else {
|
|
271
|
+
process.stdout.write(render_text(report));
|
|
272
|
+
}
|
|
273
|
+
return report.matches.length === 0 ? 1 : 0;
|
|
274
|
+
}
|
|
275
|
+
var _HERE = fileURLToPath(import.meta.url);
|
|
276
|
+
if (process.argv[1] && (import.meta.url === pathToFileURL(process.argv[1]).href || path.resolve(process.argv[1]) === _HERE)) {
|
|
277
|
+
process.exitCode = main(process.argv.slice(2));
|
|
278
|
+
}
|
|
279
|
+
export {
|
|
280
|
+
MEASUREMENT_HEADER,
|
|
281
|
+
_projection_mode,
|
|
282
|
+
build_report,
|
|
283
|
+
main,
|
|
284
|
+
render_text
|
|
285
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
main
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ELMFOQPW.js";
|
|
5
5
|
import "./chunk-WR6GTRHJ.js";
|
|
6
6
|
import "./chunk-BKO2AZ7Z.js";
|
|
7
7
|
import {
|
|
@@ -3,7 +3,7 @@ import { createRequire as __acCreateRequire } from 'node:module'; const require
|
|
|
3
3
|
import {
|
|
4
4
|
PROJECT_BRIDGE_MARKERS,
|
|
5
5
|
USER_SCOPE_PATHS
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-ELMFOQPW.js";
|
|
7
7
|
import "./chunk-WR6GTRHJ.js";
|
|
8
8
|
import "./chunk-BKO2AZ7Z.js";
|
|
9
9
|
import {
|