@massu/core 2.5.3 → 2.5.5
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/CHANGELOG.md +56 -0
- package/dist/cli.js +436 -365
- package/dist/hooks/auto-learning-pipeline.js +26 -2
- package/dist/hooks/classify-failure.js +26 -2
- package/dist/hooks/cost-tracker.js +26 -2
- package/dist/hooks/fix-detector.js +26 -2
- package/dist/hooks/incident-pipeline.js +26 -2
- package/dist/hooks/intent-suggester.js +26 -2
- package/dist/hooks/memory-recall.js +26 -2
- package/dist/hooks/post-edit-context.js +26 -2
- package/dist/hooks/post-tool-use.js +26 -2
- package/dist/hooks/pre-compact.js +26 -2
- package/dist/hooks/pre-delete-check.js +26 -2
- package/dist/hooks/pre-tool-use-gate.js +26 -2
- package/dist/hooks/quality-event.js +26 -2
- package/dist/hooks/rule-enforcement-pipeline.js +26 -2
- package/dist/hooks/security-gate.js +26 -2
- package/dist/hooks/session-end.js +633 -313
- package/dist/hooks/session-start.js +26 -2
- package/dist/hooks/user-prompt.js +26 -2
- package/docs/SECURITY.md +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -421,12 +421,12 @@ function runRebuild(pkgDir, abiFrom, abiTo, start) {
|
|
|
421
421
|
}
|
|
422
422
|
const prebuildBin = resolveLocalBin(pkgDir, "prebuild-install");
|
|
423
423
|
if (prebuildBin) {
|
|
424
|
-
const
|
|
424
|
+
const r3 = spawnSync2(process.execPath, [prebuildBin], {
|
|
425
425
|
cwd: pkgDir,
|
|
426
426
|
encoding: "utf-8",
|
|
427
427
|
timeout: 12e4
|
|
428
428
|
});
|
|
429
|
-
if (
|
|
429
|
+
if (r3.status === 0) {
|
|
430
430
|
const res2 = { healed: true, method: "prebuild-install", abiFrom, abiTo, durationMs: Date.now() - start };
|
|
431
431
|
recordHealEvent({ phase: "success", reason: "abi-mismatch", ...res2 });
|
|
432
432
|
return res2;
|
|
@@ -434,12 +434,12 @@ function runRebuild(pkgDir, abiFrom, abiTo, start) {
|
|
|
434
434
|
}
|
|
435
435
|
const gypBin = resolveNodeGypBin();
|
|
436
436
|
if (gypBin && hasCompiler()) {
|
|
437
|
-
const
|
|
437
|
+
const r3 = spawnSync2(process.execPath, [gypBin, "rebuild", "--release"], {
|
|
438
438
|
cwd: pkgDir,
|
|
439
439
|
encoding: "utf-8",
|
|
440
440
|
timeout: 3e5
|
|
441
441
|
});
|
|
442
|
-
if (
|
|
442
|
+
if (r3.status === 0) {
|
|
443
443
|
const res2 = { healed: true, method: "node-gyp", abiFrom, abiTo, durationMs: Date.now() - start };
|
|
444
444
|
recordHealEvent({ phase: "success", reason: "abi-mismatch", ...res2 });
|
|
445
445
|
return res2;
|
|
@@ -518,8 +518,8 @@ function resolveNodeGypBin() {
|
|
|
518
518
|
function hasCompiler() {
|
|
519
519
|
for (const cc of ["cc", "clang", "gcc"]) {
|
|
520
520
|
try {
|
|
521
|
-
const
|
|
522
|
-
if (
|
|
521
|
+
const r3 = spawnSync2(cc, ["--version"], { encoding: "utf-8", timeout: 5e3 });
|
|
522
|
+
if (r3.status === 0) return true;
|
|
523
523
|
} catch {
|
|
524
524
|
}
|
|
525
525
|
}
|
|
@@ -593,10 +593,10 @@ function openNodeSqlite(dbPath, opts) {
|
|
|
593
593
|
const st = raw.prepare(sql);
|
|
594
594
|
return {
|
|
595
595
|
run: (...p19) => {
|
|
596
|
-
const
|
|
596
|
+
const r3 = st.run(...p19);
|
|
597
597
|
return {
|
|
598
|
-
changes: typeof
|
|
599
|
-
lastInsertRowid:
|
|
598
|
+
changes: typeof r3.changes === "bigint" ? Number(r3.changes) : r3.changes,
|
|
599
|
+
lastInsertRowid: r3.lastInsertRowid
|
|
600
600
|
};
|
|
601
601
|
},
|
|
602
602
|
get: (...p19) => plainRow(st.get(...p19)),
|
|
@@ -1170,7 +1170,8 @@ var init_config = __esm({
|
|
|
1170
1170
|
input_per_million: z2.number(),
|
|
1171
1171
|
output_per_million: z2.number(),
|
|
1172
1172
|
cache_read_per_million: z2.number().optional(),
|
|
1173
|
-
cache_write_per_million: z2.number().optional()
|
|
1173
|
+
cache_write_per_million: z2.number().optional(),
|
|
1174
|
+
cache_write_1h_per_million: z2.number().optional()
|
|
1174
1175
|
});
|
|
1175
1176
|
AnalyticsConfigSchema = z2.object({
|
|
1176
1177
|
quality: z2.object({
|
|
@@ -1793,7 +1794,7 @@ function tableExists(db, table) {
|
|
|
1793
1794
|
}
|
|
1794
1795
|
function columns(db, table) {
|
|
1795
1796
|
const rows = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
1796
|
-
return new Set(rows.map((
|
|
1797
|
+
return new Set(rows.map((r3) => r3.name));
|
|
1797
1798
|
}
|
|
1798
1799
|
function migrateRuleDelivery(db) {
|
|
1799
1800
|
const ADDITIONS = [
|
|
@@ -1814,8 +1815,8 @@ function migrateRuleDelivery(db) {
|
|
|
1814
1815
|
function undeliveredSnapshot(db) {
|
|
1815
1816
|
const count = (t2) => {
|
|
1816
1817
|
if (!tableExists(db, t2)) return 0;
|
|
1817
|
-
const
|
|
1818
|
-
return
|
|
1818
|
+
const r3 = db.prepare(`SELECT COUNT(*) AS n FROM ${t2}`).get();
|
|
1819
|
+
return r3.n;
|
|
1819
1820
|
};
|
|
1820
1821
|
const promotions = count("team_promotion_outbound");
|
|
1821
1822
|
const revocations = count("team_revocation_outbound");
|
|
@@ -1825,9 +1826,9 @@ function undeliveredSnapshot(db) {
|
|
|
1825
1826
|
for (const t2 of RULE_OUTBOUND_TABLES) {
|
|
1826
1827
|
if (!tableExists(db, t2)) continue;
|
|
1827
1828
|
if (!columns(db, t2).has("attempts")) continue;
|
|
1828
|
-
const
|
|
1829
|
-
if (
|
|
1830
|
-
if (
|
|
1829
|
+
const r3 = db.prepare(`SELECT MAX(attempts) AS a, MIN(created_at) AS c FROM ${t2}`).get();
|
|
1830
|
+
if (r3.a !== null && r3.a > maxAttempts) maxAttempts = r3.a;
|
|
1831
|
+
if (r3.c !== null && (oldest === null || r3.c < oldest)) oldest = r3.c;
|
|
1831
1832
|
}
|
|
1832
1833
|
return {
|
|
1833
1834
|
promotions,
|
|
@@ -1918,9 +1919,9 @@ function setCandidateStatus(db, promptHash, status, destination) {
|
|
|
1918
1919
|
}
|
|
1919
1920
|
function getCandidate(db, promptHash) {
|
|
1920
1921
|
ensureRuleCandidatesTable(db);
|
|
1921
|
-
const
|
|
1922
|
-
if (!
|
|
1923
|
-
return { ...
|
|
1922
|
+
const r3 = db.prepare("SELECT * FROM rule_candidates WHERE prompt_hash = ?").get(promptHash);
|
|
1923
|
+
if (!r3) return null;
|
|
1924
|
+
return { ...r3, payload: safeParse(r3.payload_json) };
|
|
1924
1925
|
}
|
|
1925
1926
|
function safeParse(raw) {
|
|
1926
1927
|
try {
|
|
@@ -2138,11 +2139,11 @@ function getActiveEmbedModel() {
|
|
|
2138
2139
|
}
|
|
2139
2140
|
function loadEmbedSettings() {
|
|
2140
2141
|
try {
|
|
2141
|
-
const
|
|
2142
|
+
const r3 = getConfig().memory?.recall;
|
|
2142
2143
|
return {
|
|
2143
|
-
enabled:
|
|
2144
|
-
endpoint:
|
|
2145
|
-
model:
|
|
2144
|
+
enabled: r3?.embedEnabled ?? true,
|
|
2145
|
+
endpoint: r3?.embedEndpoint,
|
|
2146
|
+
model: r3?.embedModel
|
|
2146
2147
|
};
|
|
2147
2148
|
} catch {
|
|
2148
2149
|
return { enabled: true };
|
|
@@ -2416,13 +2417,13 @@ async function runEmbedSweep(db, cfg, opts = {}) {
|
|
|
2416
2417
|
break;
|
|
2417
2418
|
}
|
|
2418
2419
|
const units = [];
|
|
2419
|
-
for (const
|
|
2420
|
+
for (const r3 of rows) {
|
|
2420
2421
|
if (cfg.chunked) {
|
|
2421
|
-
const parts = chunkForEmbedding(
|
|
2422
|
+
const parts = chunkForEmbedding(r3.text);
|
|
2422
2423
|
if (parts.length === 0) continue;
|
|
2423
|
-
parts.forEach((text18, chunkIx) => units.push({ id:
|
|
2424
|
+
parts.forEach((text18, chunkIx) => units.push({ id: r3.id, chunkIx, text: text18 }));
|
|
2424
2425
|
} else {
|
|
2425
|
-
units.push({ id:
|
|
2426
|
+
units.push({ id: r3.id, chunkIx: 0, text: r3.text });
|
|
2426
2427
|
}
|
|
2427
2428
|
}
|
|
2428
2429
|
const vecs = await embedBatch(units.map((u2) => u2.text));
|
|
@@ -2541,6 +2542,7 @@ __export(memory_db_exports, {
|
|
|
2541
2542
|
pruneToolCostEvents: () => pruneToolCostEvents,
|
|
2542
2543
|
recordRecallHits: () => recordRecallHits,
|
|
2543
2544
|
recordTelemetry: () => recordTelemetry,
|
|
2545
|
+
releaseMetaLease: () => releaseMetaLease,
|
|
2544
2546
|
removePendingSync: () => removePendingSync,
|
|
2545
2547
|
sanitizeFts5Query: () => sanitizeFts5Query,
|
|
2546
2548
|
sanitizeFts5QueryOr: () => sanitizeFts5QueryOr,
|
|
@@ -2549,6 +2551,7 @@ __export(memory_db_exports, {
|
|
|
2549
2551
|
searchObservations: () => searchObservations,
|
|
2550
2552
|
setLastProcessedLine: () => setLastProcessedLine,
|
|
2551
2553
|
setMemoryMeta: () => setMemoryMeta,
|
|
2554
|
+
tryAcquireMetaLease: () => tryAcquireMetaLease,
|
|
2552
2555
|
upsertObservationEmbedding: () => upsertObservationEmbedding,
|
|
2553
2556
|
usageWarmupElapsed: () => usageWarmupElapsed
|
|
2554
2557
|
});
|
|
@@ -3054,6 +3057,15 @@ function initMemorySchema(db) {
|
|
|
3054
3057
|
);
|
|
3055
3058
|
CREATE INDEX IF NOT EXISTS idx_sc_session ON session_costs(session_id);
|
|
3056
3059
|
`);
|
|
3060
|
+
const costCols = db.prepare(`PRAGMA table_info(session_costs)`).all();
|
|
3061
|
+
const addCostCol = (name, ddl) => {
|
|
3062
|
+
if (!costCols.some((c2) => c2.name === name)) db.exec(`ALTER TABLE session_costs ADD COLUMN ${ddl}`);
|
|
3063
|
+
};
|
|
3064
|
+
addCostCol("cost_status", `cost_status TEXT NOT NULL DEFAULT 'unknown'`);
|
|
3065
|
+
addCostCol("unpriced_models", `unpriced_models TEXT NOT NULL DEFAULT ''`);
|
|
3066
|
+
addCostCol("priced_responses", `priced_responses INTEGER NOT NULL DEFAULT 0`);
|
|
3067
|
+
addCostCol("unpriced_responses", `unpriced_responses INTEGER NOT NULL DEFAULT 0`);
|
|
3068
|
+
addCostCol("pricing_version", `pricing_version INTEGER NOT NULL DEFAULT 0`);
|
|
3057
3069
|
db.exec(`
|
|
3058
3070
|
CREATE TABLE IF NOT EXISTS feature_costs (
|
|
3059
3071
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -3483,6 +3495,18 @@ function getMemoryMeta(db, key) {
|
|
|
3483
3495
|
function setMemoryMeta(db, key, value) {
|
|
3484
3496
|
db.prepare("INSERT OR REPLACE INTO memory_meta (key, value) VALUES (?, ?)").run(key, value);
|
|
3485
3497
|
}
|
|
3498
|
+
function tryAcquireMetaLease(db, key, ttlSec, nowSec = Math.floor(Date.now() / 1e3)) {
|
|
3499
|
+
const r3 = db.prepare(
|
|
3500
|
+
`INSERT INTO memory_meta (key, value) VALUES (?, ?)
|
|
3501
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value
|
|
3502
|
+
WHERE memory_meta.value = ''
|
|
3503
|
+
OR CAST(substr(memory_meta.value, instr(memory_meta.value, ':') + 1) AS INTEGER) <= ?`
|
|
3504
|
+
).run(key, `${process.pid}:${nowSec + ttlSec}`, nowSec);
|
|
3505
|
+
return Number(r3.changes) === 1;
|
|
3506
|
+
}
|
|
3507
|
+
function releaseMetaLease(db, key) {
|
|
3508
|
+
db.prepare(`UPDATE memory_meta SET value = '' WHERE key = ? AND value LIKE ?`).run(key, `${process.pid}:%`);
|
|
3509
|
+
}
|
|
3486
3510
|
function upsertObservationEmbedding(db, observationId, vec, modelId, dim) {
|
|
3487
3511
|
db.prepare(
|
|
3488
3512
|
`INSERT OR REPLACE INTO observation_embeddings (observation_id, model_id, dim, vec, created_at)
|
|
@@ -3524,7 +3548,7 @@ async function embedMissingObservations(db, opts = {}) {
|
|
|
3524
3548
|
)
|
|
3525
3549
|
ORDER BY o.id LIMIT ?`
|
|
3526
3550
|
).all(cursor, batchSize);
|
|
3527
|
-
return rows.map((
|
|
3551
|
+
return rows.map((r3) => ({ id: r3.id, text: observationEmbedText(r3.title, r3.detail) }));
|
|
3528
3552
|
}
|
|
3529
3553
|
},
|
|
3530
3554
|
opts
|
|
@@ -3612,9 +3636,9 @@ function rescueLearningFromStalePayloads(db, stale) {
|
|
|
3612
3636
|
rescued++;
|
|
3613
3637
|
}
|
|
3614
3638
|
const revocations = Array.isArray(payload.rule_revocations) ? payload.rule_revocations : [];
|
|
3615
|
-
for (const
|
|
3616
|
-
if (typeof
|
|
3617
|
-
enqueueTeamRevocation(db,
|
|
3639
|
+
for (const r3 of revocations) {
|
|
3640
|
+
if (typeof r3?.prompt_hash === "string") {
|
|
3641
|
+
enqueueTeamRevocation(db, r3.prompt_hash);
|
|
3618
3642
|
rescued++;
|
|
3619
3643
|
}
|
|
3620
3644
|
}
|
|
@@ -4351,7 +4375,7 @@ var init_memory_db = __esm({
|
|
|
4351
4375
|
init_rule_candidate_store();
|
|
4352
4376
|
init_hook_failure_signal();
|
|
4353
4377
|
init_memory_embed_sweep();
|
|
4354
|
-
MEMORY_SCHEMA_VERSION =
|
|
4378
|
+
MEMORY_SCHEMA_VERSION = 2;
|
|
4355
4379
|
TOOL_COST_EVENTS_RETENTION_DAYS = 90;
|
|
4356
4380
|
MAX_DRAFT_TEXT_LEN = 16384;
|
|
4357
4381
|
FUNNEL_EVENT_OUTBOX_CAP = 2e4;
|
|
@@ -5831,7 +5855,7 @@ var init_install_commands = __esm({
|
|
|
5831
5855
|
});
|
|
5832
5856
|
|
|
5833
5857
|
// src/lib/hook-timeouts.ts
|
|
5834
|
-
var HOOK_TIMEOUTS;
|
|
5858
|
+
var HOOK_TIMEOUTS, BACKGROUND_HOOKS;
|
|
5835
5859
|
var init_hook_timeouts = __esm({
|
|
5836
5860
|
"src/lib/hook-timeouts.ts"() {
|
|
5837
5861
|
"use strict";
|
|
@@ -5865,6 +5889,7 @@ var init_hook_timeouts = __esm({
|
|
|
5865
5889
|
// always fails open on its own terms before the platform kills it.
|
|
5866
5890
|
"memory-recall": 10
|
|
5867
5891
|
};
|
|
5892
|
+
BACKGROUND_HOOKS = /* @__PURE__ */ new Set(["session-end"]);
|
|
5868
5893
|
}
|
|
5869
5894
|
});
|
|
5870
5895
|
|
|
@@ -6583,13 +6608,13 @@ var init_package_detector = __esm({
|
|
|
6583
6608
|
// src/detect/framework-detector.ts
|
|
6584
6609
|
function matchRule(rules, language, kind, deps) {
|
|
6585
6610
|
let best = null;
|
|
6586
|
-
for (const
|
|
6587
|
-
if (
|
|
6588
|
-
if (
|
|
6589
|
-
if (!deps.has(
|
|
6590
|
-
const pr =
|
|
6611
|
+
for (const r3 of rules) {
|
|
6612
|
+
if (r3.language !== language) continue;
|
|
6613
|
+
if (r3.kind !== kind) continue;
|
|
6614
|
+
if (!deps.has(r3.keyword.toLowerCase())) continue;
|
|
6615
|
+
const pr = r3.priority ?? 0;
|
|
6591
6616
|
if (!best || pr > best.priority) {
|
|
6592
|
-
best = { value:
|
|
6617
|
+
best = { value: r3.value, priority: pr };
|
|
6593
6618
|
}
|
|
6594
6619
|
}
|
|
6595
6620
|
return best;
|
|
@@ -15121,12 +15146,12 @@ async function introspectAsync(detection, projectRoot) {
|
|
|
15121
15146
|
}
|
|
15122
15147
|
return out;
|
|
15123
15148
|
}
|
|
15124
|
-
function serializeAdapterBlock(
|
|
15125
|
-
const block = { ...
|
|
15126
|
-
if (Object.keys(
|
|
15127
|
-
block._provenance =
|
|
15149
|
+
function serializeAdapterBlock(r3) {
|
|
15150
|
+
const block = { ...r3.conventions };
|
|
15151
|
+
if (Object.keys(r3._provenance).length > 0) {
|
|
15152
|
+
block._provenance = r3._provenance;
|
|
15128
15153
|
}
|
|
15129
|
-
block._confidence =
|
|
15154
|
+
block._confidence = r3.confidence;
|
|
15130
15155
|
return block;
|
|
15131
15156
|
}
|
|
15132
15157
|
var FIRST_PARTY_ADAPTERS;
|
|
@@ -16058,7 +16083,7 @@ var init_dist2 = __esm({
|
|
|
16058
16083
|
}
|
|
16059
16084
|
};
|
|
16060
16085
|
k2 = (s) => {
|
|
16061
|
-
const { cursor: n, options: t2, style: i } = s,
|
|
16086
|
+
const { cursor: n, options: t2, style: i } = s, r3 = s.maxItems ?? Number.POSITIVE_INFINITY, c2 = Math.max(process.stdout.rows - 4, 0), o = Math.min(c2, Math.max(r3, 5));
|
|
16062
16087
|
let l2 = 0;
|
|
16063
16088
|
n >= l2 + o - 3 ? l2 = Math.max(Math.min(n - o + 3, t2.length - o), 0) : n < l2 + 2 && (l2 = Math.max(n - 2, 0));
|
|
16064
16089
|
const $2 = o < t2.length && l2 > 0, d2 = o < t2.length && l2 + o < t2.length;
|
|
@@ -16114,12 +16139,12 @@ ${import_picocolors2.default.cyan(m2)}
|
|
|
16114
16139
|
return new fD({ active: n, inactive: t2, initialValue: s.initialValue ?? true, render() {
|
|
16115
16140
|
const i = `${import_picocolors2.default.gray(a)}
|
|
16116
16141
|
${y2(this.state)} ${s.message}
|
|
16117
|
-
`,
|
|
16142
|
+
`, r3 = this.value ? n : t2;
|
|
16118
16143
|
switch (this.state) {
|
|
16119
16144
|
case "submit":
|
|
16120
|
-
return `${i}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.dim(
|
|
16145
|
+
return `${i}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.dim(r3)}`;
|
|
16121
16146
|
case "cancel":
|
|
16122
|
-
return `${i}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(
|
|
16147
|
+
return `${i}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r3))}
|
|
16123
16148
|
${import_picocolors2.default.gray(a)}`;
|
|
16124
16149
|
default:
|
|
16125
16150
|
return `${i}${import_picocolors2.default.cyan(a)} ${this.value ? `${import_picocolors2.default.green(j2)} ${n}` : `${import_picocolors2.default.dim(R2)} ${import_picocolors2.default.dim(n)}`} ${import_picocolors2.default.dim("/")} ${this.value ? `${import_picocolors2.default.dim(R2)} ${import_picocolors2.default.dim(t2)}` : `${import_picocolors2.default.green(j2)} ${t2}`}
|
|
@@ -16130,16 +16155,16 @@ ${import_picocolors2.default.cyan(m2)}
|
|
|
16130
16155
|
};
|
|
16131
16156
|
de = (s) => {
|
|
16132
16157
|
const n = (t2, i) => {
|
|
16133
|
-
const
|
|
16158
|
+
const r3 = t2.label ?? String(t2.value);
|
|
16134
16159
|
switch (i) {
|
|
16135
16160
|
case "selected":
|
|
16136
|
-
return `${import_picocolors2.default.dim(
|
|
16161
|
+
return `${import_picocolors2.default.dim(r3)}`;
|
|
16137
16162
|
case "active":
|
|
16138
|
-
return `${import_picocolors2.default.green(j2)} ${
|
|
16163
|
+
return `${import_picocolors2.default.green(j2)} ${r3} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}`;
|
|
16139
16164
|
case "cancelled":
|
|
16140
|
-
return `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(
|
|
16165
|
+
return `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r3))}`;
|
|
16141
16166
|
default:
|
|
16142
|
-
return `${import_picocolors2.default.dim(R2)} ${import_picocolors2.default.dim(
|
|
16167
|
+
return `${import_picocolors2.default.dim(R2)} ${import_picocolors2.default.dim(r3)}`;
|
|
16143
16168
|
}
|
|
16144
16169
|
};
|
|
16145
16170
|
return new jD({ options: s.options, initialValue: s.initialValue, render() {
|
|
@@ -16153,7 +16178,7 @@ ${y2(this.state)} ${s.message}
|
|
|
16153
16178
|
return `${t2}${import_picocolors2.default.gray(a)} ${n(this.options[this.cursor], "cancelled")}
|
|
16154
16179
|
${import_picocolors2.default.gray(a)}`;
|
|
16155
16180
|
default:
|
|
16156
|
-
return `${t2}${import_picocolors2.default.cyan(a)} ${k2({ cursor: this.cursor, options: this.options, maxItems: s.maxItems, style: (i,
|
|
16181
|
+
return `${t2}${import_picocolors2.default.cyan(a)} ${k2({ cursor: this.cursor, options: this.options, maxItems: s.maxItems, style: (i, r3) => n(i, r3 ? "active" : "inactive") }).join(`
|
|
16157
16182
|
${import_picocolors2.default.cyan(a)} `)}
|
|
16158
16183
|
${import_picocolors2.default.cyan(m2)}
|
|
16159
16184
|
`;
|
|
@@ -16162,8 +16187,8 @@ ${import_picocolors2.default.cyan(m2)}
|
|
|
16162
16187
|
};
|
|
16163
16188
|
he = (s) => {
|
|
16164
16189
|
const n = (t2, i = "inactive") => {
|
|
16165
|
-
const
|
|
16166
|
-
return i === "selected" ? `${import_picocolors2.default.dim(
|
|
16190
|
+
const r3 = t2.label ?? String(t2.value);
|
|
16191
|
+
return i === "selected" ? `${import_picocolors2.default.dim(r3)}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r3))}` : i === "active" ? `${import_picocolors2.default.bgCyan(import_picocolors2.default.gray(` ${t2.value} `))} ${r3} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}` : `${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(` ${t2.value} `)))} ${r3} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}`;
|
|
16167
16192
|
};
|
|
16168
16193
|
return new OD({ options: s.options, initialValue: s.initialValue, render() {
|
|
16169
16194
|
const t2 = `${import_picocolors2.default.gray(a)}
|
|
@@ -16176,7 +16201,7 @@ ${y2(this.state)} ${s.message}
|
|
|
16176
16201
|
return `${t2}${import_picocolors2.default.gray(a)} ${n(this.options[0], "cancelled")}
|
|
16177
16202
|
${import_picocolors2.default.gray(a)}`;
|
|
16178
16203
|
default:
|
|
16179
|
-
return `${t2}${import_picocolors2.default.cyan(a)} ${this.options.map((i,
|
|
16204
|
+
return `${t2}${import_picocolors2.default.cyan(a)} ${this.options.map((i, r3) => n(i, r3 === this.cursor ? "active" : "inactive")).join(`
|
|
16180
16205
|
${import_picocolors2.default.cyan(a)} `)}
|
|
16181
16206
|
${import_picocolors2.default.cyan(m2)}
|
|
16182
16207
|
`;
|
|
@@ -16185,8 +16210,8 @@ ${import_picocolors2.default.cyan(m2)}
|
|
|
16185
16210
|
};
|
|
16186
16211
|
pe = (s) => {
|
|
16187
16212
|
const n = (t2, i) => {
|
|
16188
|
-
const
|
|
16189
|
-
return i === "active" ? `${import_picocolors2.default.cyan(V2)} ${
|
|
16213
|
+
const r3 = t2.label ?? String(t2.value);
|
|
16214
|
+
return i === "active" ? `${import_picocolors2.default.cyan(V2)} ${r3} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}` : i === "selected" ? `${import_picocolors2.default.green(M2)} ${import_picocolors2.default.dim(r3)}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r3))}` : i === "active-selected" ? `${import_picocolors2.default.green(M2)} ${r3} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}` : i === "submitted" ? `${import_picocolors2.default.dim(r3)}` : `${import_picocolors2.default.dim(G2)} ${import_picocolors2.default.dim(r3)}`;
|
|
16190
16215
|
};
|
|
16191
16216
|
return new wD({ options: s.options, initialValues: s.initialValues, required: s.required ?? true, cursorAt: s.cursorAt, validate(t2) {
|
|
16192
16217
|
if (this.required && t2.length === 0) return `Please select at least one option.
|
|
@@ -16194,25 +16219,25 @@ ${import_picocolors2.default.reset(import_picocolors2.default.dim(`Press ${impor
|
|
|
16194
16219
|
}, render() {
|
|
16195
16220
|
const t2 = `${import_picocolors2.default.gray(a)}
|
|
16196
16221
|
${y2(this.state)} ${s.message}
|
|
16197
|
-
`, i = (
|
|
16198
|
-
const o = this.value.includes(
|
|
16199
|
-
return c2 && o ? n(
|
|
16222
|
+
`, i = (r3, c2) => {
|
|
16223
|
+
const o = this.value.includes(r3.value);
|
|
16224
|
+
return c2 && o ? n(r3, "active-selected") : o ? n(r3, "selected") : n(r3, c2 ? "active" : "inactive");
|
|
16200
16225
|
};
|
|
16201
16226
|
switch (this.state) {
|
|
16202
16227
|
case "submit":
|
|
16203
|
-
return `${t2}${import_picocolors2.default.gray(a)} ${this.options.filter(({ value:
|
|
16228
|
+
return `${t2}${import_picocolors2.default.gray(a)} ${this.options.filter(({ value: r3 }) => this.value.includes(r3)).map((r3) => n(r3, "submitted")).join(import_picocolors2.default.dim(", ")) || import_picocolors2.default.dim("none")}`;
|
|
16204
16229
|
case "cancel": {
|
|
16205
|
-
const
|
|
16206
|
-
return `${t2}${import_picocolors2.default.gray(a)} ${
|
|
16230
|
+
const r3 = this.options.filter(({ value: c2 }) => this.value.includes(c2)).map((c2) => n(c2, "cancelled")).join(import_picocolors2.default.dim(", "));
|
|
16231
|
+
return `${t2}${import_picocolors2.default.gray(a)} ${r3.trim() ? `${r3}
|
|
16207
16232
|
${import_picocolors2.default.gray(a)}` : ""}`;
|
|
16208
16233
|
}
|
|
16209
16234
|
case "error": {
|
|
16210
|
-
const
|
|
16235
|
+
const r3 = this.error.split(`
|
|
16211
16236
|
`).map((c2, o) => o === 0 ? `${import_picocolors2.default.yellow(m2)} ${import_picocolors2.default.yellow(c2)}` : ` ${c2}`).join(`
|
|
16212
16237
|
`);
|
|
16213
16238
|
return `${t2 + import_picocolors2.default.yellow(a)} ${k2({ options: this.options, cursor: this.cursor, maxItems: s.maxItems, style: i }).join(`
|
|
16214
16239
|
${import_picocolors2.default.yellow(a)} `)}
|
|
16215
|
-
${
|
|
16240
|
+
${r3}
|
|
16216
16241
|
`;
|
|
16217
16242
|
}
|
|
16218
16243
|
default:
|
|
@@ -16224,8 +16249,8 @@ ${import_picocolors2.default.cyan(m2)}
|
|
|
16224
16249
|
} }).prompt();
|
|
16225
16250
|
};
|
|
16226
16251
|
ge = (s) => {
|
|
16227
|
-
const n = (t2, i,
|
|
16228
|
-
const c2 = t2.label ?? String(t2.value), o = typeof t2.group == "string", l2 = o && (
|
|
16252
|
+
const n = (t2, i, r3 = []) => {
|
|
16253
|
+
const c2 = t2.label ?? String(t2.value), o = typeof t2.group == "string", l2 = o && (r3[r3.indexOf(t2) + 1] ?? { group: true }), $2 = o && l2.group === true, d2 = o ? `${$2 ? m2 : a} ` : "";
|
|
16229
16254
|
return i === "active" ? `${import_picocolors2.default.dim(d2)}${import_picocolors2.default.cyan(V2)} ${c2} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}` : i === "group-active" ? `${d2}${import_picocolors2.default.cyan(V2)} ${import_picocolors2.default.dim(c2)}` : i === "group-active-selected" ? `${d2}${import_picocolors2.default.green(M2)} ${import_picocolors2.default.dim(c2)}` : i === "selected" ? `${import_picocolors2.default.dim(d2)}${import_picocolors2.default.green(M2)} ${import_picocolors2.default.dim(c2)}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(c2))}` : i === "active-selected" ? `${import_picocolors2.default.dim(d2)}${import_picocolors2.default.green(M2)} ${c2} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}` : i === "submitted" ? `${import_picocolors2.default.dim(c2)}` : `${import_picocolors2.default.dim(d2)}${import_picocolors2.default.dim(G2)} ${import_picocolors2.default.dim(c2)}`;
|
|
16230
16255
|
};
|
|
16231
16256
|
return new dD({ options: s.options, initialValues: s.initialValues, required: s.required ?? true, cursorAt: s.cursorAt, validate(t2) {
|
|
@@ -16239,25 +16264,25 @@ ${y2(this.state)} ${s.message}
|
|
|
16239
16264
|
case "submit":
|
|
16240
16265
|
return `${t2}${import_picocolors2.default.gray(a)} ${this.options.filter(({ value: i }) => this.value.includes(i)).map((i) => n(i, "submitted")).join(import_picocolors2.default.dim(", "))}`;
|
|
16241
16266
|
case "cancel": {
|
|
16242
|
-
const i = this.options.filter(({ value:
|
|
16267
|
+
const i = this.options.filter(({ value: r3 }) => this.value.includes(r3)).map((r3) => n(r3, "cancelled")).join(import_picocolors2.default.dim(", "));
|
|
16243
16268
|
return `${t2}${import_picocolors2.default.gray(a)} ${i.trim() ? `${i}
|
|
16244
16269
|
${import_picocolors2.default.gray(a)}` : ""}`;
|
|
16245
16270
|
}
|
|
16246
16271
|
case "error": {
|
|
16247
16272
|
const i = this.error.split(`
|
|
16248
|
-
`).map((
|
|
16273
|
+
`).map((r3, c2) => c2 === 0 ? `${import_picocolors2.default.yellow(m2)} ${import_picocolors2.default.yellow(r3)}` : ` ${r3}`).join(`
|
|
16249
16274
|
`);
|
|
16250
|
-
return `${t2}${import_picocolors2.default.yellow(a)} ${this.options.map((
|
|
16251
|
-
const l2 = this.value.includes(
|
|
16252
|
-
return !$2 && typeof
|
|
16275
|
+
return `${t2}${import_picocolors2.default.yellow(a)} ${this.options.map((r3, c2, o) => {
|
|
16276
|
+
const l2 = this.value.includes(r3.value) || r3.group === true && this.isGroupSelected(`${r3.value}`), $2 = c2 === this.cursor;
|
|
16277
|
+
return !$2 && typeof r3.group == "string" && this.options[this.cursor].value === r3.group ? n(r3, l2 ? "group-active-selected" : "group-active", o) : $2 && l2 ? n(r3, "active-selected", o) : l2 ? n(r3, "selected", o) : n(r3, $2 ? "active" : "inactive", o);
|
|
16253
16278
|
}).join(`
|
|
16254
16279
|
${import_picocolors2.default.yellow(a)} `)}
|
|
16255
16280
|
${i}
|
|
16256
16281
|
`;
|
|
16257
16282
|
}
|
|
16258
16283
|
default:
|
|
16259
|
-
return `${t2}${import_picocolors2.default.cyan(a)} ${this.options.map((i,
|
|
16260
|
-
const o = this.value.includes(i.value) || i.group === true && this.isGroupSelected(`${i.value}`), l2 =
|
|
16284
|
+
return `${t2}${import_picocolors2.default.cyan(a)} ${this.options.map((i, r3, c2) => {
|
|
16285
|
+
const o = this.value.includes(i.value) || i.group === true && this.isGroupSelected(`${i.value}`), l2 = r3 === this.cursor;
|
|
16261
16286
|
return !l2 && typeof i.group == "string" && this.options[this.cursor].value === i.group ? n(i, o ? "group-active-selected" : "group-active", c2) : l2 && o ? n(i, "active-selected", c2) : o ? n(i, "selected", c2) : n(i, l2 ? "active" : "inactive", c2);
|
|
16262
16287
|
}).join(`
|
|
16263
16288
|
${import_picocolors2.default.cyan(a)} `)}
|
|
@@ -16270,15 +16295,15 @@ ${import_picocolors2.default.cyan(m2)}
|
|
|
16270
16295
|
const t2 = `
|
|
16271
16296
|
${s}
|
|
16272
16297
|
`.split(`
|
|
16273
|
-
`), i = T2(n).length,
|
|
16298
|
+
`), i = T2(n).length, r3 = Math.max(t2.reduce((o, l2) => {
|
|
16274
16299
|
const $2 = T2(l2);
|
|
16275
16300
|
return $2.length > o ? $2.length : o;
|
|
16276
|
-
}, 0), i) + 2, c2 = t2.map((o) => `${import_picocolors2.default.gray(a)} ${import_picocolors2.default.dim(o)}${" ".repeat(
|
|
16301
|
+
}, 0), i) + 2, c2 = t2.map((o) => `${import_picocolors2.default.gray(a)} ${import_picocolors2.default.dim(o)}${" ".repeat(r3 - T2(o).length)}${import_picocolors2.default.gray(a)}`).join(`
|
|
16277
16302
|
`);
|
|
16278
16303
|
process.stdout.write(`${import_picocolors2.default.gray(a)}
|
|
16279
|
-
${import_picocolors2.default.green(S2)} ${import_picocolors2.default.reset(n)} ${import_picocolors2.default.gray(N2.repeat(Math.max(
|
|
16304
|
+
${import_picocolors2.default.green(S2)} ${import_picocolors2.default.reset(n)} ${import_picocolors2.default.gray(N2.repeat(Math.max(r3 - i - 1, 1)) + re)}
|
|
16280
16305
|
${c2}
|
|
16281
|
-
${import_picocolors2.default.gray(ie + N2.repeat(
|
|
16306
|
+
${import_picocolors2.default.gray(ie + N2.repeat(r3 + 2) + ne)}
|
|
16282
16307
|
`);
|
|
16283
16308
|
};
|
|
16284
16309
|
ve = (s = "") => {
|
|
@@ -16299,9 +16324,9 @@ ${import_picocolors2.default.gray(m2)} ${s}
|
|
|
16299
16324
|
v2 = { message: (s = "", { symbol: n = import_picocolors2.default.gray(a) } = {}) => {
|
|
16300
16325
|
const t2 = [`${import_picocolors2.default.gray(a)}`];
|
|
16301
16326
|
if (s) {
|
|
16302
|
-
const [i, ...
|
|
16327
|
+
const [i, ...r3] = s.split(`
|
|
16303
16328
|
`);
|
|
16304
|
-
t2.push(`${n} ${i}`, ...
|
|
16329
|
+
t2.push(`${n} ${i}`, ...r3.map((c2) => `${import_picocolors2.default.gray(a)} ${c2}`));
|
|
16305
16330
|
}
|
|
16306
16331
|
process.stdout.write(`${t2.join(`
|
|
16307
16332
|
`)}
|
|
@@ -16321,7 +16346,7 @@ ${import_picocolors2.default.gray(m2)} ${s}
|
|
|
16321
16346
|
} };
|
|
16322
16347
|
L2 = () => {
|
|
16323
16348
|
const s = E ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"], n = E ? 80 : 120, t2 = process.env.CI === "true";
|
|
16324
|
-
let i,
|
|
16349
|
+
let i, r3, c2 = false, o = "", l2;
|
|
16325
16350
|
const $2 = (h2) => {
|
|
16326
16351
|
const g2 = h2 > 1 ? "Something went wrong" : "Canceled";
|
|
16327
16352
|
c2 && P2(g2, h2);
|
|
@@ -16340,14 +16365,14 @@ ${import_picocolors2.default.gray(m2)} ${s}
|
|
|
16340
16365
|
c2 = true, i = cD(), o = x2(h2), process.stdout.write(`${import_picocolors2.default.gray(a)}
|
|
16341
16366
|
`);
|
|
16342
16367
|
let g2 = 0, f2 = 0;
|
|
16343
|
-
b2(),
|
|
16368
|
+
b2(), r3 = setInterval(() => {
|
|
16344
16369
|
if (t2 && o === l2) return;
|
|
16345
16370
|
I2(), l2 = o;
|
|
16346
16371
|
const W2 = import_picocolors2.default.magenta(s[g2]), _2 = t2 ? "..." : ".".repeat(Math.floor(f2)).slice(0, 3);
|
|
16347
16372
|
process.stdout.write(`${W2} ${o}${_2}`), g2 = g2 + 1 < s.length ? g2 + 1 : 0, f2 = f2 < s.length ? f2 + 0.125 : 0;
|
|
16348
16373
|
}, n);
|
|
16349
16374
|
}, P2 = (h2 = "", g2 = 0) => {
|
|
16350
|
-
c2 = false, clearInterval(
|
|
16375
|
+
c2 = false, clearInterval(r3), I2();
|
|
16351
16376
|
const f2 = g2 === 0 ? import_picocolors2.default.green(S2) : g2 === 1 ? import_picocolors2.default.red(A2) : import_picocolors2.default.red(B);
|
|
16352
16377
|
o = x2(h2 ?? o), process.stdout.write(`${f2} ${o}
|
|
16353
16378
|
`), C(), i();
|
|
@@ -16358,15 +16383,15 @@ ${import_picocolors2.default.gray(m2)} ${s}
|
|
|
16358
16383
|
};
|
|
16359
16384
|
be = async (s, n) => {
|
|
16360
16385
|
const t2 = {}, i = Object.keys(s);
|
|
16361
|
-
for (const
|
|
16362
|
-
const c2 = s[
|
|
16386
|
+
for (const r3 of i) {
|
|
16387
|
+
const c2 = s[r3], o = await c2({ results: t2 })?.catch((l2) => {
|
|
16363
16388
|
throw l2;
|
|
16364
16389
|
});
|
|
16365
16390
|
if (typeof n?.onCancel == "function" && BD(o)) {
|
|
16366
|
-
t2[
|
|
16391
|
+
t2[r3] = "canceled", n.onCancel({ results: t2 });
|
|
16367
16392
|
continue;
|
|
16368
16393
|
}
|
|
16369
|
-
t2[
|
|
16394
|
+
t2[r3] = o;
|
|
16370
16395
|
}
|
|
16371
16396
|
return t2;
|
|
16372
16397
|
};
|
|
@@ -16901,10 +16926,10 @@ function validateWrittenConfig(configPath, projectRoot, checkPaths = true) {
|
|
|
16901
16926
|
}
|
|
16902
16927
|
const mRoots = cfg.paths.monorepo_roots;
|
|
16903
16928
|
if (Array.isArray(mRoots)) {
|
|
16904
|
-
for (const
|
|
16905
|
-
if (typeof
|
|
16906
|
-
if (!existsSync21(resolve12(projectRoot,
|
|
16907
|
-
return `paths.monorepo_roots '${
|
|
16929
|
+
for (const r3 of mRoots) {
|
|
16930
|
+
if (typeof r3 !== "string" || r3 === ".") continue;
|
|
16931
|
+
if (!existsSync21(resolve12(projectRoot, r3))) {
|
|
16932
|
+
return `paths.monorepo_roots '${r3}' does not exist on disk`;
|
|
16908
16933
|
}
|
|
16909
16934
|
}
|
|
16910
16935
|
}
|
|
@@ -17121,13 +17146,18 @@ function hookCmd(version, hookName, shim) {
|
|
|
17121
17146
|
function getHookTimeout(name) {
|
|
17122
17147
|
return HOOK_TIMEOUTS[name] ?? 5;
|
|
17123
17148
|
}
|
|
17149
|
+
function hookEntry(version, name, shim) {
|
|
17150
|
+
const entry = { type: "command", command: hookCmd(version, name, shim), timeout: getHookTimeout(name) };
|
|
17151
|
+
if (BACKGROUND_HOOKS.has(name)) entry.async = true;
|
|
17152
|
+
return entry;
|
|
17153
|
+
}
|
|
17124
17154
|
function buildHooksConfig(_hooksDir, shim = resolveMassuShim()) {
|
|
17125
17155
|
const version = getInstallerVersion();
|
|
17126
17156
|
return {
|
|
17127
17157
|
SessionStart: [
|
|
17128
17158
|
{
|
|
17129
17159
|
hooks: [
|
|
17130
|
-
|
|
17160
|
+
hookEntry(version, "session-start", shim)
|
|
17131
17161
|
]
|
|
17132
17162
|
}
|
|
17133
17163
|
],
|
|
@@ -17142,26 +17172,26 @@ function buildHooksConfig(_hooksDir, shim = resolveMassuShim()) {
|
|
|
17142
17172
|
{
|
|
17143
17173
|
matcher: "Bash|Write|Edit",
|
|
17144
17174
|
hooks: [
|
|
17145
|
-
|
|
17175
|
+
hookEntry(version, "pre-tool-use-gate", shim)
|
|
17146
17176
|
]
|
|
17147
17177
|
}
|
|
17148
17178
|
],
|
|
17149
17179
|
PostToolUse: [
|
|
17150
17180
|
{
|
|
17151
17181
|
hooks: [
|
|
17152
|
-
|
|
17153
|
-
|
|
17154
|
-
|
|
17182
|
+
hookEntry(version, "post-tool-use", shim),
|
|
17183
|
+
hookEntry(version, "quality-event", shim),
|
|
17184
|
+
hookEntry(version, "cost-tracker", shim)
|
|
17155
17185
|
]
|
|
17156
17186
|
},
|
|
17157
17187
|
{
|
|
17158
17188
|
matcher: "Edit|Write",
|
|
17159
17189
|
hooks: [
|
|
17160
|
-
|
|
17190
|
+
hookEntry(version, "post-edit-context", shim),
|
|
17161
17191
|
// Auto-learning pipeline — classifies failures and detects fixes on
|
|
17162
17192
|
// file changes. See Phase 5-6 of the autodetect plan.
|
|
17163
|
-
|
|
17164
|
-
|
|
17193
|
+
hookEntry(version, "fix-detector", shim),
|
|
17194
|
+
hookEntry(version, "classify-failure", shim)
|
|
17165
17195
|
]
|
|
17166
17196
|
},
|
|
17167
17197
|
{
|
|
@@ -17169,35 +17199,35 @@ function buildHooksConfig(_hooksDir, shim = resolveMassuShim()) {
|
|
|
17169
17199
|
hooks: [
|
|
17170
17200
|
// Incident + rule enforcement pipelines fire on Write-only (incidents
|
|
17171
17201
|
// are authored as .md files; rules are enforced after new-file drops).
|
|
17172
|
-
|
|
17173
|
-
|
|
17202
|
+
hookEntry(version, "incident-pipeline", shim),
|
|
17203
|
+
hookEntry(version, "rule-enforcement-pipeline", shim)
|
|
17174
17204
|
]
|
|
17175
17205
|
}
|
|
17176
17206
|
],
|
|
17177
17207
|
Stop: [
|
|
17178
17208
|
{
|
|
17179
17209
|
hooks: [
|
|
17180
|
-
|
|
17210
|
+
hookEntry(version, "session-end", shim),
|
|
17181
17211
|
// Session-end auto-learning aggregation (failure-class roll-up).
|
|
17182
|
-
|
|
17212
|
+
hookEntry(version, "auto-learning-pipeline", shim)
|
|
17183
17213
|
]
|
|
17184
17214
|
}
|
|
17185
17215
|
],
|
|
17186
17216
|
PreCompact: [
|
|
17187
17217
|
{
|
|
17188
17218
|
hooks: [
|
|
17189
|
-
|
|
17219
|
+
hookEntry(version, "pre-compact", shim)
|
|
17190
17220
|
]
|
|
17191
17221
|
}
|
|
17192
17222
|
],
|
|
17193
17223
|
UserPromptSubmit: [
|
|
17194
17224
|
{
|
|
17195
17225
|
hooks: [
|
|
17196
|
-
|
|
17197
|
-
|
|
17226
|
+
hookEntry(version, "user-prompt", shim),
|
|
17227
|
+
hookEntry(version, "intent-suggester", shim),
|
|
17198
17228
|
// plan-living-memory-slice-1 P3-002: automatic relevant-recall.
|
|
17199
17229
|
// Injects a compact "🧠 Relevant memory" block; fails open (empty).
|
|
17200
|
-
|
|
17230
|
+
hookEntry(version, "memory-recall", shim)
|
|
17201
17231
|
]
|
|
17202
17232
|
}
|
|
17203
17233
|
]
|
|
@@ -20165,7 +20195,7 @@ async function embedMissingChunks(db, opts = {}) {
|
|
|
20165
20195
|
)
|
|
20166
20196
|
ORDER BY c.id LIMIT ?`
|
|
20167
20197
|
).all(cursor, batchSize);
|
|
20168
|
-
return rows.map((
|
|
20198
|
+
return rows.map((r3) => ({ id: r3.id, text: chunkEmbedText(r3.heading, r3.content) }));
|
|
20169
20199
|
}
|
|
20170
20200
|
},
|
|
20171
20201
|
opts
|
|
@@ -21285,7 +21315,7 @@ function buildIndexLines(db, memoryDir, planned, config) {
|
|
|
21285
21315
|
ORDER BY o.importance DESC, o.created_at_epoch DESC
|
|
21286
21316
|
LIMIT ?`
|
|
21287
21317
|
).all(config.indexMaxLines + planned.length);
|
|
21288
|
-
const byPath = new Map(rows.map((
|
|
21318
|
+
const byPath = new Map(rows.map((r3) => [r3.rel_path.toLowerCase(), r3]));
|
|
21289
21319
|
for (const p19 of planned) {
|
|
21290
21320
|
byPath.set(p19.relPath.toLowerCase(), {
|
|
21291
21321
|
rel_path: p19.relPath,
|
|
@@ -21294,11 +21324,11 @@ function buildIndexLines(db, memoryDir, planned, config) {
|
|
|
21294
21324
|
created_at_epoch: 0
|
|
21295
21325
|
});
|
|
21296
21326
|
}
|
|
21297
|
-
const live = [...byPath.values()].filter((
|
|
21327
|
+
const live = [...byPath.values()].filter((r3) => !isTombstoned(memoryDir, r3.rel_path));
|
|
21298
21328
|
const ranked = live.sort(
|
|
21299
21329
|
(a2, b2) => b2.importance - a2.importance || b2.created_at_epoch - a2.created_at_epoch
|
|
21300
21330
|
);
|
|
21301
|
-
return ranked.slice(0, config.indexMaxLines).map((
|
|
21331
|
+
return ranked.slice(0, config.indexMaxLines).map((r3) => `- [${oneLine(r3.name)}](${r3.rel_path}) \u2014 learned by Massu`);
|
|
21302
21332
|
}
|
|
21303
21333
|
function oneLine(s) {
|
|
21304
21334
|
return s.replace(/[\r\n]+/g, " ").slice(0, 120);
|
|
@@ -21494,14 +21524,14 @@ function memoryRestore(memoryDir, opts = {}) {
|
|
|
21494
21524
|
return { exitCode: 1, output: "No backups exist yet. Nothing to restore." };
|
|
21495
21525
|
}
|
|
21496
21526
|
try {
|
|
21497
|
-
const
|
|
21527
|
+
const r3 = restoreBackup(memoryDir, { ...opts, home });
|
|
21498
21528
|
const lines = [
|
|
21499
|
-
|
|
21529
|
+
r3.dryRun ? `--dry-run: would restore ${r3.wouldRestore.length} file(s) from ${r3.stamp}. Nothing changed.` : `Restored ${r3.filesRestored} file(s) from ${r3.stamp}.`
|
|
21500
21530
|
];
|
|
21501
|
-
for (const f2 of
|
|
21502
|
-
if (
|
|
21531
|
+
for (const f2 of r3.wouldRestore) lines.push(` ${f2}`);
|
|
21532
|
+
if (r3.presentButNotInBackup.length > 0) {
|
|
21503
21533
|
lines.push("", "These files exist now but are NOT in the backup. Massu left them alone:");
|
|
21504
|
-
for (const f2 of
|
|
21534
|
+
for (const f2 of r3.presentButNotInBackup) lines.push(` ${f2}`);
|
|
21505
21535
|
}
|
|
21506
21536
|
return { exitCode: 0, output: lines.join("\n") };
|
|
21507
21537
|
} catch (err) {
|
|
@@ -21535,8 +21565,8 @@ function loadRenderCandidates(db) {
|
|
|
21535
21565
|
ORDER BY importance DESC, created_at_epoch DESC
|
|
21536
21566
|
LIMIT ${CANDIDATE_WINDOW}`
|
|
21537
21567
|
).all(cfg.renderMinImportance, ...RENDERABLE_MEMORY_TYPES);
|
|
21538
|
-
const reingest = rows.filter((
|
|
21539
|
-
const kept = rows.filter((
|
|
21568
|
+
const reingest = rows.filter((r3) => r3.title.startsWith("[memory-file]"));
|
|
21569
|
+
const kept = rows.filter((r3) => !r3.title.startsWith("[memory-file]"));
|
|
21540
21570
|
const excluded = reingest.length ? [{ reason: EXCLUSION_MEMORY_FILE_REINGEST, count: reingest.length }] : [];
|
|
21541
21571
|
const ledger = {
|
|
21542
21572
|
population,
|
|
@@ -21553,13 +21583,13 @@ function loadRenderCandidates(db) {
|
|
|
21553
21583
|
}
|
|
21554
21584
|
return {
|
|
21555
21585
|
ledger,
|
|
21556
|
-
candidates: kept.map((
|
|
21557
|
-
observationId:
|
|
21558
|
-
name:
|
|
21559
|
-
title:
|
|
21560
|
-
body:
|
|
21561
|
-
importance:
|
|
21562
|
-
origin:
|
|
21586
|
+
candidates: kept.map((r3) => ({
|
|
21587
|
+
observationId: r3.id,
|
|
21588
|
+
name: r3.title,
|
|
21589
|
+
title: r3.title,
|
|
21590
|
+
body: r3.detail ?? "",
|
|
21591
|
+
importance: r3.importance,
|
|
21592
|
+
origin: r3.origin
|
|
21563
21593
|
}))
|
|
21564
21594
|
};
|
|
21565
21595
|
}
|
|
@@ -21742,8 +21772,8 @@ async function runMemoryRenderCli(sub, args2) {
|
|
|
21742
21772
|
}
|
|
21743
21773
|
if (result.refusals.length > 0) {
|
|
21744
21774
|
lines.push("", `${result.refusals.length} memory/memories REFUSED:`);
|
|
21745
|
-
for (const
|
|
21746
|
-
lines.push(` ${
|
|
21775
|
+
for (const r3 of result.refusals) {
|
|
21776
|
+
lines.push(` ${r3.name}: ${r3.reason}${r3.detail ? ` (${r3.detail})` : ""}`);
|
|
21747
21777
|
}
|
|
21748
21778
|
}
|
|
21749
21779
|
lines.push("", `Bytes written: ${result.bytesWritten} (a dry run always writes 0).`);
|
|
@@ -21765,7 +21795,7 @@ async function runMemoryRenderCli(sub, args2) {
|
|
|
21765
21795
|
"",
|
|
21766
21796
|
"Sample (first 10):"
|
|
21767
21797
|
];
|
|
21768
|
-
for (const
|
|
21798
|
+
for (const r3 of sampleNoise2(db, 10)) lines.push(` [${r3.reason}] id=${r3.id} ${r3.type}: ${r3.title.slice(0, 60)}`);
|
|
21769
21799
|
if (apply) {
|
|
21770
21800
|
const result = pruneNoiseObservations2(db, { dryRun: false });
|
|
21771
21801
|
lines.push("", `Expired ${result.expired} row(s) (CR-61: expired, NOT deleted; still asOf-queryable).`);
|
|
@@ -21859,12 +21889,12 @@ function readReposRegistry(home = homedir13()) {
|
|
|
21859
21889
|
try {
|
|
21860
21890
|
const parsed = JSON.parse(readFileSync29(p19, "utf-8"));
|
|
21861
21891
|
if (!parsed || typeof parsed !== "object") return emptyRegistry();
|
|
21862
|
-
const
|
|
21863
|
-
if (!Array.isArray(
|
|
21864
|
-
const repos =
|
|
21892
|
+
const r3 = parsed;
|
|
21893
|
+
if (!Array.isArray(r3.repos)) return emptyRegistry();
|
|
21894
|
+
const repos = r3.repos.filter(
|
|
21865
21895
|
(e2) => !!e2 && typeof e2 === "object" && typeof e2.repo_id === "string" && typeof e2.label === "string"
|
|
21866
21896
|
);
|
|
21867
|
-
return { version: typeof
|
|
21897
|
+
return { version: typeof r3.version === "number" ? r3.version : REPOS_REGISTRY_VERSION, repos };
|
|
21868
21898
|
} catch {
|
|
21869
21899
|
return emptyRegistry();
|
|
21870
21900
|
}
|
|
@@ -22038,7 +22068,7 @@ function acceptSharedMemory(db, recordHash, opts = {}) {
|
|
|
22038
22068
|
const verdict = verifyLocalShareEnvelope(env, pinned, home);
|
|
22039
22069
|
if (verdict.kind !== "valid") return refuse(db, recordHash, `reverify_${verdict.kind}`);
|
|
22040
22070
|
if (!hasSignedLoadBearingKeys(env)) return refuse(db, recordHash, "unsigned_field");
|
|
22041
|
-
const signed = parseRecords(env.records_json).find((
|
|
22071
|
+
const signed = parseRecords(env.records_json).find((r3) => r3.record_hash === recordHash);
|
|
22042
22072
|
if (!signed) return refuse(db, recordHash, "not_in_signed_records");
|
|
22043
22073
|
if (hashSharedMemoryRecord(stripHash(signed)) !== recordHash) {
|
|
22044
22074
|
return refuse(db, recordHash, "record_hash_mismatch");
|
|
@@ -22134,20 +22164,20 @@ function listPendingSharedMemories(db, opts = {}) {
|
|
|
22134
22164
|
LIMIT 500`
|
|
22135
22165
|
).all();
|
|
22136
22166
|
const out = [];
|
|
22137
|
-
for (const
|
|
22167
|
+
for (const r3 of rows) {
|
|
22138
22168
|
let rec = null;
|
|
22139
22169
|
let valid = false;
|
|
22140
22170
|
try {
|
|
22141
|
-
rec = JSON.parse(
|
|
22142
|
-
const env = JSON.parse(
|
|
22143
|
-
const pinned = getSharedPin(db,
|
|
22171
|
+
rec = JSON.parse(r3.record_json);
|
|
22172
|
+
const env = JSON.parse(r3.envelope_raw);
|
|
22173
|
+
const pinned = getSharedPin(db, r3.origin_repo_id);
|
|
22144
22174
|
valid = !!pinned && verifyLocalShareEnvelope(env, pinned, home).kind === "valid";
|
|
22145
22175
|
} catch {
|
|
22146
22176
|
}
|
|
22147
22177
|
out.push({
|
|
22148
|
-
record_hash:
|
|
22149
|
-
origin_repo_label: deriveRepoLabel(
|
|
22150
|
-
received_at_epoch:
|
|
22178
|
+
record_hash: r3.record_hash,
|
|
22179
|
+
origin_repo_label: deriveRepoLabel(r3.origin_repo_label),
|
|
22180
|
+
received_at_epoch: r3.received_at_epoch,
|
|
22151
22181
|
type: rec?.type ?? "unknown",
|
|
22152
22182
|
title: sanitizeCrossRepoTitle(rec?.title ?? ""),
|
|
22153
22183
|
detail: sanitizeCrossRepoBody(rec?.detail ?? ""),
|
|
@@ -22168,14 +22198,14 @@ function parseRecords(json) {
|
|
|
22168
22198
|
return [];
|
|
22169
22199
|
}
|
|
22170
22200
|
}
|
|
22171
|
-
function stripHash(
|
|
22201
|
+
function stripHash(r3) {
|
|
22172
22202
|
return {
|
|
22173
|
-
type:
|
|
22174
|
-
title:
|
|
22175
|
-
detail:
|
|
22176
|
-
importance:
|
|
22177
|
-
created_at_epoch:
|
|
22178
|
-
superseded_by_hash:
|
|
22203
|
+
type: r3.type,
|
|
22204
|
+
title: r3.title,
|
|
22205
|
+
detail: r3.detail,
|
|
22206
|
+
importance: r3.importance,
|
|
22207
|
+
created_at_epoch: r3.created_at_epoch,
|
|
22208
|
+
superseded_by_hash: r3.superseded_by_hash
|
|
22179
22209
|
};
|
|
22180
22210
|
}
|
|
22181
22211
|
function clampImportance(n) {
|
|
@@ -22902,40 +22932,40 @@ function validateCandidatePayload(raw) {
|
|
|
22902
22932
|
if (!raw || typeof raw !== "object") {
|
|
22903
22933
|
throw new CandidatePayloadValidationError("payload is not an object");
|
|
22904
22934
|
}
|
|
22905
|
-
const
|
|
22906
|
-
if (typeof
|
|
22935
|
+
const r3 = raw;
|
|
22936
|
+
if (typeof r3.prompt !== "string" || r3.prompt.length === 0) {
|
|
22907
22937
|
throw new CandidatePayloadValidationError("prompt must be a non-empty string");
|
|
22908
22938
|
}
|
|
22909
|
-
if (typeof
|
|
22939
|
+
if (typeof r3.prompt_hash !== "string" || !/^[a-f0-9]{16}$/.test(r3.prompt_hash)) {
|
|
22910
22940
|
throw new CandidatePayloadValidationError("prompt_hash must be 16 hex chars");
|
|
22911
22941
|
}
|
|
22912
|
-
if (typeof
|
|
22942
|
+
if (typeof r3.score !== "number" || r3.score < -200 || r3.score > 200 || !Number.isFinite(r3.score)) {
|
|
22913
22943
|
throw new CandidatePayloadValidationError("score must be a finite number in [-200, 200]");
|
|
22914
22944
|
}
|
|
22915
|
-
if (!Array.isArray(
|
|
22945
|
+
if (!Array.isArray(r3.signals)) {
|
|
22916
22946
|
throw new CandidatePayloadValidationError("signals must be an array");
|
|
22917
22947
|
}
|
|
22918
|
-
for (const s of
|
|
22948
|
+
for (const s of r3.signals) {
|
|
22919
22949
|
if (!s || typeof s !== "object") throw new CandidatePayloadValidationError("signal entry not an object");
|
|
22920
22950
|
const sig = s;
|
|
22921
22951
|
if (typeof sig.name !== "string") throw new CandidatePayloadValidationError("signal.name must be a string");
|
|
22922
22952
|
if (typeof sig.baseWeight !== "number") throw new CandidatePayloadValidationError("signal.baseWeight must be a number");
|
|
22923
22953
|
if (typeof sig.applied !== "number") throw new CandidatePayloadValidationError("signal.applied must be a number");
|
|
22924
22954
|
}
|
|
22925
|
-
if (!Array.isArray(
|
|
22955
|
+
if (!Array.isArray(r3.prior_turn_files)) {
|
|
22926
22956
|
throw new CandidatePayloadValidationError("prior_turn_files must be an array");
|
|
22927
22957
|
}
|
|
22928
|
-
if (typeof
|
|
22958
|
+
if (typeof r3.timestamp !== "string") {
|
|
22929
22959
|
throw new CandidatePayloadValidationError("timestamp must be a string");
|
|
22930
22960
|
}
|
|
22931
|
-
if (typeof
|
|
22961
|
+
if (typeof r3.session_id !== "string") {
|
|
22932
22962
|
throw new CandidatePayloadValidationError("session_id must be a string");
|
|
22933
22963
|
}
|
|
22934
|
-
if (
|
|
22935
|
-
if (!
|
|
22964
|
+
if (r3.provenance !== void 0) {
|
|
22965
|
+
if (!r3.provenance || typeof r3.provenance !== "object") {
|
|
22936
22966
|
throw new CandidatePayloadValidationError("provenance must be an object when present");
|
|
22937
22967
|
}
|
|
22938
|
-
const p19 =
|
|
22968
|
+
const p19 = r3.provenance;
|
|
22939
22969
|
const origin = p19.origin;
|
|
22940
22970
|
const isTeamOrPack = origin === "team" || origin === "pack";
|
|
22941
22971
|
const isRepo = typeof origin === "string" && isCrossRepoOrigin(origin);
|
|
@@ -22960,17 +22990,17 @@ function validateCandidatePayload(raw) {
|
|
|
22960
22990
|
if (p19.apply_mac !== void 0 && typeof p19.apply_mac !== "string") {
|
|
22961
22991
|
throw new CandidatePayloadValidationError("provenance.apply_mac, when present, must be a string");
|
|
22962
22992
|
}
|
|
22963
|
-
if (!isRuleDestination(
|
|
22993
|
+
if (!isRuleDestination(r3.destination)) {
|
|
22964
22994
|
throw new CandidatePayloadValidationError("provenance-bearing candidate must declare a valid destination");
|
|
22965
22995
|
}
|
|
22966
|
-
if (
|
|
22996
|
+
if (r3.draft_text !== void 0 && typeof r3.draft_text !== "string") {
|
|
22967
22997
|
throw new CandidatePayloadValidationError("draft_text must be a string when present");
|
|
22968
22998
|
}
|
|
22969
22999
|
}
|
|
22970
|
-
} else if (
|
|
23000
|
+
} else if (r3.destination !== void 0 && !isRuleDestination(r3.destination)) {
|
|
22971
23001
|
throw new CandidatePayloadValidationError("destination, when present, must be a valid RuleDestination");
|
|
22972
23002
|
}
|
|
22973
|
-
return
|
|
23003
|
+
return r3;
|
|
22974
23004
|
}
|
|
22975
23005
|
async function applyRuleCandidate(db, opts) {
|
|
22976
23006
|
const ent = await assertAutoLearningEntitled();
|
|
@@ -23325,8 +23355,8 @@ function dismissRuleCandidate(db, opts) {
|
|
|
23325
23355
|
`);
|
|
23326
23356
|
for (const sig of candidate.signals) {
|
|
23327
23357
|
if (sig.baseWeight <= 0) continue;
|
|
23328
|
-
const
|
|
23329
|
-
blacklistUpdates +=
|
|
23358
|
+
const r3 = upsert.run(sig.name);
|
|
23359
|
+
blacklistUpdates += r3.changes;
|
|
23330
23360
|
}
|
|
23331
23361
|
const entry = {
|
|
23332
23362
|
eventType: "rule_dismissed",
|
|
@@ -23758,27 +23788,27 @@ function validateRulePackRule(rule) {
|
|
|
23758
23788
|
if (typeof rule !== "object" || rule === null || Array.isArray(rule)) {
|
|
23759
23789
|
return { valid: false, errors: ["rule must be a non-null object"], requiresHardened: false };
|
|
23760
23790
|
}
|
|
23761
|
-
const
|
|
23762
|
-
if (!isNonEmptyString(
|
|
23791
|
+
const r3 = rule;
|
|
23792
|
+
if (!isNonEmptyString(r3.title)) {
|
|
23763
23793
|
errors.push("missing required field: title");
|
|
23764
23794
|
}
|
|
23765
|
-
if (!isNonEmptyString(
|
|
23795
|
+
if (!isNonEmptyString(r3.description)) {
|
|
23766
23796
|
errors.push("missing required field: description");
|
|
23767
23797
|
}
|
|
23768
|
-
if (!isNonEmptyString(
|
|
23798
|
+
if (!isNonEmptyString(r3.severity)) {
|
|
23769
23799
|
errors.push("missing required field: severity");
|
|
23770
23800
|
}
|
|
23771
|
-
const destinationKnown = isRuleDestination2(
|
|
23801
|
+
const destinationKnown = isRuleDestination2(r3.destination);
|
|
23772
23802
|
if (!destinationKnown) {
|
|
23773
23803
|
errors.push(
|
|
23774
|
-
`invalid destination: ${JSON.stringify(
|
|
23804
|
+
`invalid destination: ${JSON.stringify(r3.destination)} is not a known RuleDestination (one of ${RULE_DESTINATIONS.join(", ")})`
|
|
23775
23805
|
);
|
|
23776
23806
|
}
|
|
23777
23807
|
if (destinationKnown) {
|
|
23778
|
-
const destination =
|
|
23779
|
-
const hasPattern = isNonEmptyString(
|
|
23780
|
-
const hasCheck = isNonEmptyString(
|
|
23781
|
-
const hasTextBody = isNonEmptyString(
|
|
23808
|
+
const destination = r3.destination;
|
|
23809
|
+
const hasPattern = isNonEmptyString(r3.pattern);
|
|
23810
|
+
const hasCheck = isNonEmptyString(r3.check);
|
|
23811
|
+
const hasTextBody = isNonEmptyString(r3.description);
|
|
23782
23812
|
switch (destination) {
|
|
23783
23813
|
case "pattern-scanner":
|
|
23784
23814
|
if (!hasPattern && !hasCheck) {
|
|
@@ -23804,7 +23834,7 @@ function validateRulePackRule(rule) {
|
|
|
23804
23834
|
break;
|
|
23805
23835
|
}
|
|
23806
23836
|
}
|
|
23807
|
-
const requiresHardened = destinationKnown && isExecutableDestination(
|
|
23837
|
+
const requiresHardened = destinationKnown && isExecutableDestination(r3.destination);
|
|
23808
23838
|
return { valid: errors.length === 0, errors, requiresHardened };
|
|
23809
23839
|
}
|
|
23810
23840
|
var RULE_DESTINATIONS;
|
|
@@ -23916,8 +23946,8 @@ function countUntrusted(envelope) {
|
|
|
23916
23946
|
}
|
|
23917
23947
|
function isValidInstalledPack(p19) {
|
|
23918
23948
|
if (!p19 || typeof p19 !== "object") return false;
|
|
23919
|
-
const
|
|
23920
|
-
return typeof
|
|
23949
|
+
const r3 = p19;
|
|
23950
|
+
return typeof r3.slug === "string" && r3.slug.length > 0 && Array.isArray(r3.rules);
|
|
23921
23951
|
}
|
|
23922
23952
|
function packRulePromptHash(slug, rule) {
|
|
23923
23953
|
const { createHash: createHash17 } = __require("node:crypto");
|
|
@@ -24403,14 +24433,14 @@ function collectObservations(memDb, queryText, pool, nowMs, loadVec, modelId, di
|
|
|
24403
24433
|
WHERE observations_fts MATCH ?${bm25Temporal ? ` AND ${bm25Temporal}` : ""}
|
|
24404
24434
|
ORDER BY rank LIMIT ?`
|
|
24405
24435
|
).all(sanitizeFts5QueryOr(queryText), pool);
|
|
24406
|
-
rows.forEach((
|
|
24407
|
-
map.set(
|
|
24408
|
-
id:
|
|
24436
|
+
rows.forEach((r3, i) => {
|
|
24437
|
+
map.set(r3.id, {
|
|
24438
|
+
id: r3.id,
|
|
24409
24439
|
source: "observation",
|
|
24410
|
-
title:
|
|
24411
|
-
snippet: snippetOf(
|
|
24412
|
-
importance:
|
|
24413
|
-
ageDays: ageDaysFrom(
|
|
24440
|
+
title: r3.title,
|
|
24441
|
+
snippet: snippetOf(r3.detail ?? r3.title),
|
|
24442
|
+
importance: r3.importance,
|
|
24443
|
+
ageDays: ageDaysFrom(r3.created_at_epoch * 1e3, nowMs),
|
|
24414
24444
|
bm25Order: i,
|
|
24415
24445
|
vecs: []
|
|
24416
24446
|
});
|
|
@@ -24421,15 +24451,15 @@ function collectObservations(memDb, queryText, pool, nowMs, loadVec, modelId, di
|
|
|
24421
24451
|
`SELECT id, title, detail, importance, created_at_epoch
|
|
24422
24452
|
FROM observations${plainTemporal ? ` WHERE ${plainTemporal}` : ""} ORDER BY created_at_epoch DESC LIMIT ?`
|
|
24423
24453
|
).all(pool);
|
|
24424
|
-
for (const
|
|
24425
|
-
if (!map.has(
|
|
24426
|
-
map.set(
|
|
24427
|
-
id:
|
|
24454
|
+
for (const r3 of recent) {
|
|
24455
|
+
if (!map.has(r3.id)) {
|
|
24456
|
+
map.set(r3.id, {
|
|
24457
|
+
id: r3.id,
|
|
24428
24458
|
source: "observation",
|
|
24429
|
-
title:
|
|
24430
|
-
snippet: snippetOf(
|
|
24431
|
-
importance:
|
|
24432
|
-
ageDays: ageDaysFrom(
|
|
24459
|
+
title: r3.title,
|
|
24460
|
+
snippet: snippetOf(r3.detail ?? r3.title),
|
|
24461
|
+
importance: r3.importance,
|
|
24462
|
+
ageDays: ageDaysFrom(r3.created_at_epoch * 1e3, nowMs),
|
|
24433
24463
|
bm25Order: null,
|
|
24434
24464
|
vecs: []
|
|
24435
24465
|
});
|
|
@@ -24469,14 +24499,14 @@ function collectLikeSource(db, source, cfg, queryText, pool, nowMs) {
|
|
|
24469
24499
|
FROM ${cfg.table} WHERE (${likeClause})${cfg.temporalClause ? ` AND ${cfg.temporalClause}` : ""}
|
|
24470
24500
|
ORDER BY ${cfg.createdCol} DESC LIMIT ?`
|
|
24471
24501
|
).all(...params, pool);
|
|
24472
|
-
rows.forEach((
|
|
24473
|
-
map.set(
|
|
24474
|
-
id:
|
|
24502
|
+
rows.forEach((r3, i) => {
|
|
24503
|
+
map.set(r3.id, {
|
|
24504
|
+
id: r3.id,
|
|
24475
24505
|
source,
|
|
24476
|
-
title:
|
|
24477
|
-
snippet: snippetOf(
|
|
24506
|
+
title: r3.title,
|
|
24507
|
+
snippet: snippetOf(r3.snippet ?? r3.title),
|
|
24478
24508
|
importance: 3,
|
|
24479
|
-
ageDays: ageExpr(
|
|
24509
|
+
ageDays: ageExpr(r3.created),
|
|
24480
24510
|
bm25Order: i,
|
|
24481
24511
|
vecs: []
|
|
24482
24512
|
});
|
|
@@ -24489,15 +24519,15 @@ function collectLikeSource(db, source, cfg, queryText, pool, nowMs) {
|
|
|
24489
24519
|
${cfg.snippetCol} AS snippet, ${cfg.createdCol} AS created
|
|
24490
24520
|
FROM ${cfg.table}${cfg.temporalClause ? ` WHERE ${cfg.temporalClause}` : ""} ORDER BY ${cfg.createdCol} DESC LIMIT ?`
|
|
24491
24521
|
).all(pool);
|
|
24492
|
-
for (const
|
|
24493
|
-
if (!map.has(
|
|
24494
|
-
map.set(
|
|
24495
|
-
id:
|
|
24522
|
+
for (const r3 of recent) {
|
|
24523
|
+
if (!map.has(r3.id)) {
|
|
24524
|
+
map.set(r3.id, {
|
|
24525
|
+
id: r3.id,
|
|
24496
24526
|
source,
|
|
24497
|
-
title:
|
|
24498
|
-
snippet: snippetOf(
|
|
24527
|
+
title: r3.title,
|
|
24528
|
+
snippet: snippetOf(r3.snippet ?? r3.title),
|
|
24499
24529
|
importance: 3,
|
|
24500
|
-
ageDays: ageExpr(
|
|
24530
|
+
ageDays: ageExpr(r3.created),
|
|
24501
24531
|
bm25Order: null,
|
|
24502
24532
|
vecs: []
|
|
24503
24533
|
});
|
|
@@ -24517,14 +24547,14 @@ function collectKnowledgeChunks(knowledgeDb, queryText, pool, nowMs, loadVec, mo
|
|
|
24517
24547
|
WHERE knowledge_fts MATCH ?
|
|
24518
24548
|
ORDER BY rank LIMIT ?`
|
|
24519
24549
|
).all(sanitizeFts5QueryOr(queryText), pool);
|
|
24520
|
-
rows.forEach((
|
|
24521
|
-
map.set(
|
|
24522
|
-
id:
|
|
24550
|
+
rows.forEach((r3, i) => {
|
|
24551
|
+
map.set(r3.id, {
|
|
24552
|
+
id: r3.id,
|
|
24523
24553
|
source: "knowledge_chunk",
|
|
24524
|
-
title:
|
|
24525
|
-
snippet: snippetOf(
|
|
24554
|
+
title: r3.heading || snippetOf(r3.content, 60),
|
|
24555
|
+
snippet: snippetOf(r3.content),
|
|
24526
24556
|
importance: 3,
|
|
24527
|
-
ageDays: ageDaysFrom((
|
|
24557
|
+
ageDays: ageDaysFrom((r3.epoch ?? 0) * 1e3, nowMs),
|
|
24528
24558
|
bm25Order: i,
|
|
24529
24559
|
vecs: []
|
|
24530
24560
|
});
|
|
@@ -24556,9 +24586,9 @@ function loadEmbeddings(db, table, idCol, ids, modelId, dim, assign) {
|
|
|
24556
24586
|
WHERE ${idCol} IN (${placeholders}) AND model_id = ? AND dim = ?
|
|
24557
24587
|
LIMIT ?`
|
|
24558
24588
|
).all(...ids, modelId, dim, ids.length);
|
|
24559
|
-
for (const
|
|
24560
|
-
const v3 = blobToFloat32(
|
|
24561
|
-
if (v3 && v3.length === dim) assign(
|
|
24589
|
+
for (const r3 of rows) {
|
|
24590
|
+
const v3 = blobToFloat32(r3.vec);
|
|
24591
|
+
if (v3 && v3.length === dim) assign(r3.id, v3);
|
|
24562
24592
|
}
|
|
24563
24593
|
} catch {
|
|
24564
24594
|
}
|
|
@@ -24668,17 +24698,17 @@ function hybridSearch(memDb, knowledgeDb, opts) {
|
|
|
24668
24698
|
ageDays: c2.ageDays
|
|
24669
24699
|
};
|
|
24670
24700
|
});
|
|
24671
|
-
const top = ranked.filter((
|
|
24701
|
+
const top = ranked.filter((r3) => r3.score >= minScore).sort((a2, b2) => b2.score - a2.score || a2.ageDays - b2.ageDays).slice(0, limit);
|
|
24672
24702
|
if (includeSuperseded && opts.asOf == null) {
|
|
24673
|
-
for (const
|
|
24674
|
-
const table =
|
|
24703
|
+
for (const r3 of top) {
|
|
24704
|
+
const table = r3.source === "observation" ? "observations" : r3.source === "architecture_decision" ? "architecture_decisions" : null;
|
|
24675
24705
|
if (!table) continue;
|
|
24676
24706
|
try {
|
|
24677
|
-
const row = memDb.prepare(`SELECT valid_to, superseded_by, expired_at_epoch FROM ${table} WHERE id = ?`).get(
|
|
24707
|
+
const row = memDb.prepare(`SELECT valid_to, superseded_by, expired_at_epoch FROM ${table} WHERE id = ?`).get(r3.id);
|
|
24678
24708
|
if (row && row.expired_at_epoch != null) {
|
|
24679
24709
|
const when = row.valid_to ? row.valid_to.slice(0, 10) : "an earlier date";
|
|
24680
24710
|
const by = row.superseded_by != null ? ` by #${row.superseded_by}` : "";
|
|
24681
|
-
|
|
24711
|
+
r3.snippet = `(superseded on ${when}${by}) ${r3.snippet}`;
|
|
24682
24712
|
}
|
|
24683
24713
|
} catch {
|
|
24684
24714
|
}
|
|
@@ -24808,11 +24838,11 @@ async function supersedeIfContradicted(memDb, knowledgeDb, args2) {
|
|
|
24808
24838
|
candidatePool: 20
|
|
24809
24839
|
});
|
|
24810
24840
|
const scored = [];
|
|
24811
|
-
for (const
|
|
24812
|
-
if (
|
|
24841
|
+
for (const r3 of results) {
|
|
24842
|
+
if (r3.id === args2.newId) continue;
|
|
24813
24843
|
if (Date.now() - start > cfg.budgetMs) break;
|
|
24814
|
-
const vec = await candidateVec(memDb, args2.source,
|
|
24815
|
-
if (vec) scored.push({ id:
|
|
24844
|
+
const vec = await candidateVec(memDb, args2.source, r3.id);
|
|
24845
|
+
if (vec) scored.push({ id: r3.id, source: args2.source, cosine: cosineSim(queryVec, vec) });
|
|
24816
24846
|
}
|
|
24817
24847
|
let verdict = null;
|
|
24818
24848
|
if (cfg.judgeEndpoint && Date.now() - start < cfg.budgetMs) {
|
|
@@ -24871,17 +24901,11 @@ function emptyResult() {
|
|
|
24871
24901
|
};
|
|
24872
24902
|
}
|
|
24873
24903
|
function acquireLease(db, now, ttlSec) {
|
|
24874
|
-
|
|
24875
|
-
if (raw) {
|
|
24876
|
-
const expiry = Number(raw.split(":")[1]);
|
|
24877
|
-
if (Number.isFinite(expiry) && expiry > now) return false;
|
|
24878
|
-
}
|
|
24879
|
-
setMemoryMeta(db, LEASE_KEY, `${process.pid}:${now + ttlSec}`);
|
|
24880
|
-
return true;
|
|
24904
|
+
return tryAcquireMetaLease(db, LEASE_KEY, ttlSec, now);
|
|
24881
24905
|
}
|
|
24882
24906
|
function releaseLease(db) {
|
|
24883
24907
|
try {
|
|
24884
|
-
|
|
24908
|
+
releaseMetaLease(db, LEASE_KEY);
|
|
24885
24909
|
} catch {
|
|
24886
24910
|
}
|
|
24887
24911
|
}
|
|
@@ -24900,19 +24924,19 @@ async function stageDedupe(db, cfg, deadline, now) {
|
|
|
24900
24924
|
return 0;
|
|
24901
24925
|
}
|
|
24902
24926
|
let deduped = 0;
|
|
24903
|
-
for (const
|
|
24927
|
+
for (const r3 of rows) {
|
|
24904
24928
|
if (Date.now() > deadline) break;
|
|
24905
|
-
const live = db.prepare(`SELECT expired_at FROM observations WHERE id = ?`).get(
|
|
24929
|
+
const live = db.prepare(`SELECT expired_at FROM observations WHERE id = ?`).get(r3.id);
|
|
24906
24930
|
if (!live || live.expired_at != null) continue;
|
|
24907
24931
|
const res = await supersedeIfContradicted(db, null, {
|
|
24908
|
-
text: `${
|
|
24909
|
-
${
|
|
24932
|
+
text: `${r3.title}
|
|
24933
|
+
${r3.detail ?? ""}`.trim(),
|
|
24910
24934
|
source: "observation",
|
|
24911
|
-
newId:
|
|
24935
|
+
newId: r3.id,
|
|
24912
24936
|
nowEpochSec: now
|
|
24913
24937
|
});
|
|
24914
24938
|
if (res.superseded != null) deduped++;
|
|
24915
|
-
setMemoryMeta(db, DEDUPE_CURSOR, String(
|
|
24939
|
+
setMemoryMeta(db, DEDUPE_CURSOR, String(r3.id));
|
|
24916
24940
|
}
|
|
24917
24941
|
return deduped;
|
|
24918
24942
|
}
|
|
@@ -24990,11 +25014,11 @@ async function stagePromote(db, cfg, projectRoot, deadline, now, dryRun) {
|
|
|
24990
25014
|
).all(MAX_ROWS_PER_STAGE);
|
|
24991
25015
|
if (rows.length === 0) return { promoted: 0, refusedByTier: 0, embedderUnavailable: false };
|
|
24992
25016
|
const vecs = /* @__PURE__ */ new Map();
|
|
24993
|
-
for (const
|
|
25017
|
+
for (const r3 of rows) {
|
|
24994
25018
|
if (Date.now() > deadline) break;
|
|
24995
|
-
const v3 = await embed(`${
|
|
24996
|
-
${
|
|
24997
|
-
if (v3) vecs.set(
|
|
25019
|
+
const v3 = await embed(`${r3.title}
|
|
25020
|
+
${r3.detail ?? ""}`.trim());
|
|
25021
|
+
if (v3) vecs.set(r3.id, v3);
|
|
24998
25022
|
}
|
|
24999
25023
|
if (vecs.size === 0) {
|
|
25000
25024
|
return { promoted: 0, refusedByTier: 0, embedderUnavailable: true };
|
|
@@ -25002,13 +25026,13 @@ ${r2.detail ?? ""}`.trim());
|
|
|
25002
25026
|
const CLUSTER_THRESHOLD = 0.8;
|
|
25003
25027
|
const used = /* @__PURE__ */ new Set();
|
|
25004
25028
|
const clusters = [];
|
|
25005
|
-
for (const
|
|
25006
|
-
if (used.has(
|
|
25007
|
-
const cluster = [
|
|
25008
|
-
used.add(
|
|
25029
|
+
for (const r3 of rows) {
|
|
25030
|
+
if (used.has(r3.id) || !vecs.has(r3.id)) continue;
|
|
25031
|
+
const cluster = [r3];
|
|
25032
|
+
used.add(r3.id);
|
|
25009
25033
|
for (const other of rows) {
|
|
25010
25034
|
if (used.has(other.id) || !vecs.has(other.id)) continue;
|
|
25011
|
-
if (cosineSim(vecs.get(
|
|
25035
|
+
if (cosineSim(vecs.get(r3.id), vecs.get(other.id)) >= CLUSTER_THRESHOLD) {
|
|
25012
25036
|
cluster.push(other);
|
|
25013
25037
|
used.add(other.id);
|
|
25014
25038
|
}
|
|
@@ -25107,14 +25131,14 @@ function stageReweight(db, cfg, now) {
|
|
|
25107
25131
|
ON CONFLICT(source, record_id) DO UPDATE SET last_reweight_epoch = excluded.last_reweight_epoch`
|
|
25108
25132
|
);
|
|
25109
25133
|
const tx = db.transaction(() => {
|
|
25110
|
-
for (const
|
|
25111
|
-
bump.run(
|
|
25112
|
-
mark.run(
|
|
25134
|
+
for (const r3 of promote) {
|
|
25135
|
+
bump.run(r3.id);
|
|
25136
|
+
mark.run(r3.id, now);
|
|
25113
25137
|
changed++;
|
|
25114
25138
|
}
|
|
25115
|
-
for (const
|
|
25116
|
-
drop.run(
|
|
25117
|
-
mark.run(
|
|
25139
|
+
for (const r3 of demote) {
|
|
25140
|
+
drop.run(r3.id);
|
|
25141
|
+
mark.run(r3.id, now);
|
|
25118
25142
|
changed++;
|
|
25119
25143
|
}
|
|
25120
25144
|
});
|
|
@@ -28060,8 +28084,8 @@ async function runAdaptersList(_args) {
|
|
|
28060
28084
|
`);
|
|
28061
28085
|
}
|
|
28062
28086
|
} else {
|
|
28063
|
-
for (const
|
|
28064
|
-
process.stderr.write(`[manifest] ${
|
|
28087
|
+
for (const r3 of manifestResult.reasons) {
|
|
28088
|
+
process.stderr.write(`[manifest] ${r3}
|
|
28065
28089
|
`);
|
|
28066
28090
|
}
|
|
28067
28091
|
}
|
|
@@ -28980,9 +29004,9 @@ var init_security_utils = __esm({
|
|
|
28980
29004
|
|
|
28981
29005
|
// src/rules.ts
|
|
28982
29006
|
function getPatternRules() {
|
|
28983
|
-
return getConfig().rules.map((
|
|
28984
|
-
match:
|
|
28985
|
-
rules:
|
|
29007
|
+
return getConfig().rules.map((r3) => ({
|
|
29008
|
+
match: r3.pattern,
|
|
29009
|
+
rules: r3.rules
|
|
28986
29010
|
}));
|
|
28987
29011
|
}
|
|
28988
29012
|
function matchRules(filePath) {
|
|
@@ -31244,8 +31268,8 @@ function handleSearch(args2, db) {
|
|
|
31244
31268
|
const lines = [`## Search Results for "${query}" (${results.length} matches)`, ""];
|
|
31245
31269
|
lines.push("| ID | Type | Title | Date | Importance |");
|
|
31246
31270
|
lines.push("|----|------|-------|------|------------|");
|
|
31247
|
-
for (const
|
|
31248
|
-
lines.push(`| ${
|
|
31271
|
+
for (const r3 of results) {
|
|
31272
|
+
lines.push(`| ${r3.id} | ${r3.type} | ${r3.title.slice(0, 80)} | ${r3.created_at.split("T")[0]} | ${r3.importance} |`);
|
|
31249
31273
|
}
|
|
31250
31274
|
lines.push("");
|
|
31251
31275
|
lines.push(`Use ${p3("memory_detail")} with IDs for full details.`);
|
|
@@ -31678,9 +31702,9 @@ function handleDocsAudit(args2) {
|
|
|
31678
31702
|
}
|
|
31679
31703
|
}
|
|
31680
31704
|
}
|
|
31681
|
-
const staleCount = results.filter((
|
|
31682
|
-
const newCount = results.filter((
|
|
31683
|
-
const okCount = results.filter((
|
|
31705
|
+
const staleCount = results.filter((r3) => r3.status === "STALE").length;
|
|
31706
|
+
const newCount = results.filter((r3) => r3.status === "NEW").length;
|
|
31707
|
+
const okCount = results.filter((r3) => r3.status === "OK").length;
|
|
31684
31708
|
const report = {
|
|
31685
31709
|
affectedPages: results,
|
|
31686
31710
|
summary: `${results.length} pages checked: ${staleCount} STALE, ${newCount} NEW, ${okCount} OK. ${staleCount + newCount > 0 ? `${staleCount + newCount} pages need updates.` : "All docs are current."}`
|
|
@@ -31932,8 +31956,8 @@ function handlePromptAnalysis(args2, db) {
|
|
|
31932
31956
|
const lines = [`## Prompt Search: "${query}" (${results.length} results)`, ""];
|
|
31933
31957
|
lines.push("| Session | Turn | Prompt (truncated) | Tools | Response Tokens | Date |");
|
|
31934
31958
|
lines.push("|---------|------|--------------------|-------|-----------------|------|");
|
|
31935
|
-
for (const
|
|
31936
|
-
lines.push(`| ${
|
|
31959
|
+
for (const r3 of results) {
|
|
31960
|
+
lines.push(`| ${r3.session_id.slice(0, 8)}... | ${r3.turn_number} | ${r3.user_prompt.slice(0, 60).replace(/\|/g, "\\|")} | ${r3.tool_call_count} | ${r3.response_tokens ?? "-"} | ${r3.created_at.split("T")[0]} |`);
|
|
31937
31961
|
}
|
|
31938
31962
|
return text4(lines.join("\n"));
|
|
31939
31963
|
}
|
|
@@ -33373,12 +33397,49 @@ var init_analytics = __esm({
|
|
|
33373
33397
|
}
|
|
33374
33398
|
});
|
|
33375
33399
|
|
|
33400
|
+
// src/model-pricing.ts
|
|
33401
|
+
var PRICE_TABLE_SOURCE, PRICE_TABLE_AS_OF, r2, US, BUILT_IN_PRICES;
|
|
33402
|
+
var init_model_pricing = __esm({
|
|
33403
|
+
"src/model-pricing.ts"() {
|
|
33404
|
+
"use strict";
|
|
33405
|
+
PRICE_TABLE_SOURCE = "https://platform.claude.com/docs/en/about-claude/pricing";
|
|
33406
|
+
PRICE_TABLE_AS_OF = "2026-11-09";
|
|
33407
|
+
r2 = (input, cacheWrite5m, cacheWrite1h, cacheRead, output) => ({ input, cacheWrite5m, cacheWrite1h, cacheRead, output });
|
|
33408
|
+
US = 1.1;
|
|
33409
|
+
BUILT_IN_PRICES = {
|
|
33410
|
+
"claude-fable-5-1": { ...r2(10, 12.5, 20, 0.25, 50), usGeoMultiplier: US },
|
|
33411
|
+
"claude-mythos-5-1": { ...r2(10, 12.5, 20, 0.25, 50), usGeoMultiplier: US },
|
|
33412
|
+
"claude-fable-5": { ...r2(10, 12.5, 20, 1, 50), usGeoMultiplier: US },
|
|
33413
|
+
"claude-mythos-5": { ...r2(10, 12.5, 20, 1, 50), usGeoMultiplier: US },
|
|
33414
|
+
"claude-opus-5-5": { ...r2(4, 5, 8, 0.2, 20), fast: { input: 8, output: 40 }, usGeoMultiplier: US },
|
|
33415
|
+
"claude-opus-5": { ...r2(5, 6.25, 10, 0.5, 25), fast: { input: 10, output: 50 }, usGeoMultiplier: US },
|
|
33416
|
+
"claude-opus-4-8": { ...r2(5, 6.25, 10, 0.5, 25), fast: { input: 10, output: 50 }, usGeoMultiplier: US },
|
|
33417
|
+
"claude-opus-4-7": { ...r2(5, 6.25, 10, 0.5, 25), usGeoMultiplier: US },
|
|
33418
|
+
"claude-opus-4-6": { ...r2(5, 6.25, 10, 0.5, 25), usGeoMultiplier: US },
|
|
33419
|
+
"claude-opus-4-5": r2(5, 6.25, 10, 0.5, 25),
|
|
33420
|
+
"claude-opus-4-1": r2(15, 18.75, 30, 1.5, 75),
|
|
33421
|
+
"claude-opus-4": r2(15, 18.75, 30, 1.5, 75),
|
|
33422
|
+
"claude-sonnet-5-5": { ...r2(2, 2.5, 4, 0.1, 10), usGeoMultiplier: US },
|
|
33423
|
+
"claude-sonnet-5": { ...r2(2, 2.5, 4, 0.2, 10), usGeoMultiplier: US },
|
|
33424
|
+
"claude-sonnet-4-6": { ...r2(3, 3.75, 6, 0.3, 15), usGeoMultiplier: US },
|
|
33425
|
+
"claude-sonnet-4-5": r2(3, 3.75, 6, 0.3, 15),
|
|
33426
|
+
"claude-sonnet-4": r2(3, 3.75, 6, 0.3, 15),
|
|
33427
|
+
"claude-haiku-5-5": {
|
|
33428
|
+
...r2(0.1, 0.125, 0.2, 0.01, 0.5),
|
|
33429
|
+
longPrompt: { overTokens: 1e5, rates: r2(0.5, 0.625, 1, 0.05, 2.5) },
|
|
33430
|
+
usGeoMultiplier: US
|
|
33431
|
+
},
|
|
33432
|
+
"claude-haiku-4-5": r2(1, 1.25, 2, 0.1, 5)
|
|
33433
|
+
};
|
|
33434
|
+
}
|
|
33435
|
+
});
|
|
33436
|
+
|
|
33376
33437
|
// src/cost-tracker.ts
|
|
33377
33438
|
function p8(baseName) {
|
|
33378
33439
|
return `${getConfig().toolPrefix}_${baseName}`;
|
|
33379
33440
|
}
|
|
33380
|
-
function
|
|
33381
|
-
return getConfig().analytics?.cost?.
|
|
33441
|
+
function getCurrency() {
|
|
33442
|
+
return getConfig().analytics?.cost?.currency ?? "USD";
|
|
33382
33443
|
}
|
|
33383
33444
|
function getCostToolDefinitions() {
|
|
33384
33445
|
return [
|
|
@@ -33452,25 +33513,31 @@ function handleCostSession(args2, db) {
|
|
|
33452
33513
|
if (!cost) {
|
|
33453
33514
|
return text7(`No cost data found for session ${sessionId}. Cost data is recorded automatically when sessions end via the session-end hook. If the session is still active, data will appear after it completes. Try: ${p8("cost_trend")} { days: 30 } to see aggregate cost data instead.`);
|
|
33454
33515
|
}
|
|
33455
|
-
const
|
|
33456
|
-
const
|
|
33457
|
-
const
|
|
33458
|
-
const outputCost = cost.output_tokens / 1e6 * mp.output_per_million;
|
|
33459
|
-
const cacheReadCost = cost.cache_read_tokens / 1e6 * (mp.cache_read_per_million ?? 0);
|
|
33460
|
-
const cacheWriteCost = cost.cache_write_tokens / 1e6 * (mp.cache_write_per_million ?? 0);
|
|
33516
|
+
const status = cost.cost_status ?? "unknown";
|
|
33517
|
+
const dollars = cost.estimated_cost_usd;
|
|
33518
|
+
const headline = status === "unknown" ? "unknown" : `$${dollars.toFixed(4)}${status === "partial" ? " (partial, see below)" : ""}`;
|
|
33461
33519
|
const lines = [
|
|
33462
|
-
`## Session Cost:
|
|
33463
|
-
`Model: ${cost.model}`,
|
|
33520
|
+
`## Session Cost: ${headline}`,
|
|
33521
|
+
`Model: ${cost.model ?? "unknown"}`,
|
|
33464
33522
|
"",
|
|
33465
33523
|
"### Token Usage",
|
|
33466
|
-
`| Type | Tokens
|
|
33467
|
-
|
|
33468
|
-
`| Input | ${cost.input_tokens.toLocaleString()}
|
|
33469
|
-
`| Output | ${cost.output_tokens.toLocaleString()}
|
|
33470
|
-
`| Cache Read | ${cost.cache_read_tokens.toLocaleString()}
|
|
33471
|
-
`| Cache Write | ${cost.cache_write_tokens.toLocaleString()}
|
|
33472
|
-
`| **Total** | ${cost.total_tokens.toLocaleString()}
|
|
33524
|
+
`| Type | Tokens |`,
|
|
33525
|
+
`|------|--------|`,
|
|
33526
|
+
`| Input | ${cost.input_tokens.toLocaleString()} |`,
|
|
33527
|
+
`| Output | ${cost.output_tokens.toLocaleString()} |`,
|
|
33528
|
+
`| Cache Read | ${cost.cache_read_tokens.toLocaleString()} |`,
|
|
33529
|
+
`| Cache Write | ${cost.cache_write_tokens.toLocaleString()} |`,
|
|
33530
|
+
`| **Total** | ${cost.total_tokens.toLocaleString()} |`,
|
|
33531
|
+
"",
|
|
33532
|
+
`Responses priced: ${cost.priced_responses ?? 0}; without a price: ${cost.unpriced_responses ?? 0}.`
|
|
33473
33533
|
];
|
|
33534
|
+
if (status === "unknown" && !cost.unpriced_responses) {
|
|
33535
|
+
lines.push("No transcript was available to price this session.");
|
|
33536
|
+
}
|
|
33537
|
+
if (cost.unpriced_models) {
|
|
33538
|
+
lines.push(`No price known for: ${cost.unpriced_models}. Add it under analytics.cost.models in massu.config.yaml.`);
|
|
33539
|
+
}
|
|
33540
|
+
lines.push(`Prices: ${PRICE_TABLE_SOURCE} as of ${PRICE_TABLE_AS_OF} (${getCurrency()}).`);
|
|
33474
33541
|
return text7(lines.join("\n"));
|
|
33475
33542
|
}
|
|
33476
33543
|
function handleCostTrend(args2, db) {
|
|
@@ -33481,17 +33548,21 @@ function handleCostTrend(args2, db) {
|
|
|
33481
33548
|
}
|
|
33482
33549
|
const sql = groupBy === "week" ? `SELECT strftime('%Y-W%W', created_at) as period,
|
|
33483
33550
|
COUNT(*) as sessions,
|
|
33484
|
-
SUM(estimated_cost_usd) as total_cost,
|
|
33551
|
+
SUM(CASE WHEN cost_status = 'unknown' THEN 0 ELSE estimated_cost_usd END) as total_cost,
|
|
33485
33552
|
SUM(total_tokens) as total_tokens,
|
|
33486
|
-
|
|
33553
|
+
SUM(CASE WHEN cost_status = 'priced' THEN 1 ELSE 0 END) as priced_sessions,
|
|
33554
|
+
SUM(CASE WHEN cost_status = 'partial' THEN 1 ELSE 0 END) as partial_sessions,
|
|
33555
|
+
SUM(CASE WHEN cost_status = 'unknown' THEN 1 ELSE 0 END) as unknown_sessions
|
|
33487
33556
|
FROM session_costs
|
|
33488
33557
|
WHERE created_at >= datetime('now', ?)
|
|
33489
33558
|
GROUP BY period
|
|
33490
33559
|
ORDER BY period ASC` : `SELECT strftime('%Y-%m-%d', created_at) as period,
|
|
33491
33560
|
COUNT(*) as sessions,
|
|
33492
|
-
SUM(estimated_cost_usd) as total_cost,
|
|
33561
|
+
SUM(CASE WHEN cost_status = 'unknown' THEN 0 ELSE estimated_cost_usd END) as total_cost,
|
|
33493
33562
|
SUM(total_tokens) as total_tokens,
|
|
33494
|
-
|
|
33563
|
+
SUM(CASE WHEN cost_status = 'priced' THEN 1 ELSE 0 END) as priced_sessions,
|
|
33564
|
+
SUM(CASE WHEN cost_status = 'partial' THEN 1 ELSE 0 END) as partial_sessions,
|
|
33565
|
+
SUM(CASE WHEN cost_status = 'unknown' THEN 1 ELSE 0 END) as unknown_sessions
|
|
33495
33566
|
FROM session_costs
|
|
33496
33567
|
WHERE created_at >= datetime('now', ?)
|
|
33497
33568
|
GROUP BY period
|
|
@@ -33500,22 +33571,28 @@ function handleCostTrend(args2, db) {
|
|
|
33500
33571
|
if (rows.length === 0) {
|
|
33501
33572
|
return text7(`No cost data found in the last ${days} days. Cost tracking records token usage automatically at session end via hooks. Ensure session-end hooks are configured in your settings. Try: ${p8("cost_session")} { session_id: "..." } to check a specific session.`);
|
|
33502
33573
|
}
|
|
33503
|
-
const
|
|
33504
|
-
const
|
|
33574
|
+
const sum = (k3) => rows.reduce((acc, r3) => acc + (r3[k3] ?? 0), 0);
|
|
33575
|
+
const totalCost = sum("total_cost");
|
|
33576
|
+
const totalSessions = sum("sessions");
|
|
33577
|
+
const known = sum("priced_sessions") + sum("partial_sessions");
|
|
33578
|
+
const unknown = sum("unknown_sessions");
|
|
33579
|
+
const partial = sum("partial_sessions");
|
|
33505
33580
|
const lines = [
|
|
33506
33581
|
`## Cost Trend (${days} days)`,
|
|
33507
|
-
`Total: $${totalCost.toFixed(2)} across ${totalSessions}
|
|
33508
|
-
`Average per session: $${(totalCost /
|
|
33582
|
+
`Total: $${totalCost.toFixed(2)} across ${known} priced session(s)` + (unknown ? `; ${unknown} session(s) of ${totalSessions} have unknown cost and are NOT in this total` : ""),
|
|
33583
|
+
known ? `Average per priced session: $${(totalCost / known).toFixed(4)}` : "No session has a known cost in this window."
|
|
33584
|
+
];
|
|
33585
|
+
if (partial) lines.push(`${partial} session(s) are partial: a model they used has no price, so they are under-counted.`);
|
|
33586
|
+
lines.push(
|
|
33509
33587
|
"",
|
|
33510
33588
|
`### By ${groupBy === "week" ? "Week" : "Day"}`,
|
|
33511
|
-
`| Period | Sessions | Cost |
|
|
33512
|
-
|
|
33513
|
-
|
|
33589
|
+
`| Period | Sessions | Cost | Unknown |`,
|
|
33590
|
+
`|--------|----------|------|---------|`
|
|
33591
|
+
);
|
|
33514
33592
|
for (const row of rows) {
|
|
33515
|
-
lines.push(
|
|
33516
|
-
`| ${row.period} | ${row.sessions} | $${row.total_cost.toFixed(2)} | $${row.avg_cost.toFixed(4)} |`
|
|
33517
|
-
);
|
|
33593
|
+
lines.push(`| ${row.period} | ${row.sessions} | $${row.total_cost.toFixed(2)} | ${row.unknown_sessions} |`);
|
|
33518
33594
|
}
|
|
33595
|
+
lines.push("", `Prices: ${PRICE_TABLE_SOURCE} as of ${PRICE_TABLE_AS_OF} (${getCurrency()}).`);
|
|
33519
33596
|
return text7(lines.join("\n"));
|
|
33520
33597
|
}
|
|
33521
33598
|
function handleCostFeature(args2, db) {
|
|
@@ -33530,7 +33607,7 @@ function handleCostFeature(args2, db) {
|
|
|
33530
33607
|
if (rows.length === 0) {
|
|
33531
33608
|
return text7(`No feature cost data found in the last ${days} days. Feature costs are attributed automatically when sessions work on registered features. Ensure features are registered, then costs are tracked per-session. Try: ${p8("cost_trend")} { days: 30 } for session-level cost trends instead.`);
|
|
33532
33609
|
}
|
|
33533
|
-
const totalCost = rows.reduce((sum,
|
|
33610
|
+
const totalCost = rows.reduce((sum, r3) => sum + r3.total_cost, 0);
|
|
33534
33611
|
const lines = [
|
|
33535
33612
|
`## Feature Cost Attribution (${days} days)`,
|
|
33536
33613
|
`Total: $${totalCost.toFixed(2)} across ${rows.length} features`,
|
|
@@ -33549,18 +33626,12 @@ function handleCostFeature(args2, db) {
|
|
|
33549
33626
|
function text7(content) {
|
|
33550
33627
|
return { content: [{ type: "text", text: content }] };
|
|
33551
33628
|
}
|
|
33552
|
-
var
|
|
33629
|
+
var COST_BASE_NAMES;
|
|
33553
33630
|
var init_cost_tracker = __esm({
|
|
33554
33631
|
"src/cost-tracker.ts"() {
|
|
33555
33632
|
"use strict";
|
|
33556
33633
|
init_config();
|
|
33557
|
-
|
|
33558
|
-
"claude-opus-4-6": { input_per_million: 15, output_per_million: 75, cache_read_per_million: 1.5, cache_write_per_million: 18.75 },
|
|
33559
|
-
"claude-sonnet-4-6": { input_per_million: 3, output_per_million: 15, cache_read_per_million: 0.3, cache_write_per_million: 3.75 },
|
|
33560
|
-
"claude-sonnet-4-5": { input_per_million: 3, output_per_million: 15, cache_read_per_million: 0.3, cache_write_per_million: 3.75 },
|
|
33561
|
-
"claude-haiku-4-5-20251001": { input_per_million: 0.8, output_per_million: 4, cache_read_per_million: 0.08, cache_write_per_million: 1 },
|
|
33562
|
-
"default": { input_per_million: 3, output_per_million: 15, cache_read_per_million: 0.3, cache_write_per_million: 3.75 }
|
|
33563
|
-
};
|
|
33634
|
+
init_model_pricing();
|
|
33564
33635
|
COST_BASE_NAMES = /* @__PURE__ */ new Set(["cost_session", "cost_trend", "cost_feature"]);
|
|
33565
33636
|
}
|
|
33566
33637
|
});
|
|
@@ -33973,8 +34044,8 @@ function handleValidationReport(args2, db) {
|
|
|
33973
34044
|
if (results.length === 0) {
|
|
33974
34045
|
return text9(`No validation results found in the last ${days} days. Run ${p10("validation_check")} { file: "src/path/to/file.ts" } on specific files to generate validation data, or try a longer time range with { days: 90 }.`);
|
|
33975
34046
|
}
|
|
33976
|
-
const passedCount = results.filter((
|
|
33977
|
-
const failedCount = results.filter((
|
|
34047
|
+
const passedCount = results.filter((r3) => r3.passed === 1).length;
|
|
34048
|
+
const failedCount = results.filter((r3) => r3.passed === 0).length;
|
|
33978
34049
|
const lines = [
|
|
33979
34050
|
`## Validation Report (${days} days)`,
|
|
33980
34051
|
`Files validated: ${results.length}`,
|
|
@@ -33985,11 +34056,11 @@ function handleValidationReport(args2, db) {
|
|
|
33985
34056
|
"| File | Rules Violated | Date |",
|
|
33986
34057
|
"|------|----------------|------|"
|
|
33987
34058
|
];
|
|
33988
|
-
const failedResults = results.filter((
|
|
33989
|
-
for (const
|
|
33990
|
-
const filename =
|
|
33991
|
-
const rules =
|
|
33992
|
-
lines.push(`| ${filename} | ${rules.slice(0, 60)} | ${
|
|
34059
|
+
const failedResults = results.filter((r3) => r3.passed === 0);
|
|
34060
|
+
for (const r3 of failedResults.slice(0, 30)) {
|
|
34061
|
+
const filename = r3.file_path.split("/").pop();
|
|
34062
|
+
const rules = r3.rules_violated ?? "-";
|
|
34063
|
+
lines.push(`| ${filename} | ${rules.slice(0, 60)} | ${r3.created_at.slice(0, 10)} |`);
|
|
33993
34064
|
}
|
|
33994
34065
|
if (failedResults.length > 30) {
|
|
33995
34066
|
lines.push(`... and ${failedResults.length - 30} more`);
|
|
@@ -34918,9 +34989,9 @@ function handleTeamSearch(args2, db) {
|
|
|
34918
34989
|
"| Developer | Type | Summary | Module | Date |",
|
|
34919
34990
|
"|-----------|------|---------|--------|------|"
|
|
34920
34991
|
];
|
|
34921
|
-
for (const
|
|
34992
|
+
for (const r3 of results) {
|
|
34922
34993
|
lines.push(
|
|
34923
|
-
`| ${
|
|
34994
|
+
`| ${r3.developer_id} | ${r3.observation_type} | ${r3.summary.slice(0, 60)} | ${r3.module ?? "-"} | ${r3.created_at.split("T")[0]} |`
|
|
34924
34995
|
);
|
|
34925
34996
|
}
|
|
34926
34997
|
return text13(lines.join("\n"));
|
|
@@ -36013,10 +36084,10 @@ function handleSearch3(db, args2) {
|
|
|
36013
36084
|
} else {
|
|
36014
36085
|
lines.push(`Found ${results.length} result(s):`);
|
|
36015
36086
|
lines.push("");
|
|
36016
|
-
for (const
|
|
36017
|
-
const preview =
|
|
36018
|
-
lines.push(`### ${
|
|
36019
|
-
lines.push(`**File**: ${claudeDir}/${
|
|
36087
|
+
for (const r3 of results) {
|
|
36088
|
+
const preview = r3.content.length > 500 ? r3.content.substring(0, 500) + "..." : r3.content;
|
|
36089
|
+
lines.push(`### ${r3.heading || r3.title} [${r3.chunk_type}]`);
|
|
36090
|
+
lines.push(`**File**: ${claudeDir}/${r3.file_path} | **Category**: ${r3.category}`);
|
|
36020
36091
|
lines.push("");
|
|
36021
36092
|
lines.push(preview);
|
|
36022
36093
|
lines.push("");
|
|
@@ -36250,11 +36321,11 @@ function handlePattern(db, args2) {
|
|
|
36250
36321
|
LIMIT 10
|
|
36251
36322
|
`).all(sanitizeFts5Query(topic), ...docIds);
|
|
36252
36323
|
if (topicResults.length > 0) {
|
|
36253
|
-
for (const
|
|
36254
|
-
lines.push(`### ${
|
|
36255
|
-
lines.push(`*Source: ${claudeDir}/${
|
|
36324
|
+
for (const r3 of topicResults) {
|
|
36325
|
+
lines.push(`### ${r3.heading || "(section)"} [${r3.chunk_type}]`);
|
|
36326
|
+
lines.push(`*Source: ${claudeDir}/${r3.file_path}*`);
|
|
36256
36327
|
lines.push("");
|
|
36257
|
-
lines.push(
|
|
36328
|
+
lines.push(r3.content.length > 800 ? r3.content.substring(0, 800) + "..." : r3.content);
|
|
36258
36329
|
lines.push("");
|
|
36259
36330
|
lines.push("---");
|
|
36260
36331
|
lines.push("");
|
|
@@ -36298,8 +36369,8 @@ function handlePattern(db, args2) {
|
|
|
36298
36369
|
if (ftsResults.length > 0) {
|
|
36299
36370
|
lines.push("### Broad Search Results");
|
|
36300
36371
|
lines.push("");
|
|
36301
|
-
for (const
|
|
36302
|
-
lines.push(`- **${
|
|
36372
|
+
for (const r3 of ftsResults) {
|
|
36373
|
+
lines.push(`- **${r3.heading || "(section)"}** (${claudeDir}/${r3.file_path}): ${r3.content.substring(0, 200)}...`);
|
|
36303
36374
|
}
|
|
36304
36375
|
}
|
|
36305
36376
|
} catch {
|
|
@@ -36447,9 +36518,9 @@ function handleCommand(db, args2) {
|
|
|
36447
36518
|
`).all(`%${keyword}%`, `%${keyword}%`);
|
|
36448
36519
|
lines.push(`## Commands matching "${keyword}" (${results.length} found)`);
|
|
36449
36520
|
lines.push("");
|
|
36450
|
-
for (const
|
|
36451
|
-
const preview =
|
|
36452
|
-
lines.push(`- **${
|
|
36521
|
+
for (const r3 of results) {
|
|
36522
|
+
const preview = r3.content.substring(0, 200).replace(/\n/g, " ");
|
|
36523
|
+
lines.push(`- **${r3.heading}** (${claudeDir}/${r3.file_path}): ${preview}...`);
|
|
36453
36524
|
}
|
|
36454
36525
|
} else {
|
|
36455
36526
|
const commands = db.prepare(`
|
|
@@ -36534,8 +36605,8 @@ function handlePlan(db, args2) {
|
|
|
36534
36605
|
`).all(`%${basename12(file)}%`);
|
|
36535
36606
|
lines.push(`## Plans referencing \`${file}\` (${results.length} found)`);
|
|
36536
36607
|
lines.push("");
|
|
36537
|
-
for (const
|
|
36538
|
-
lines.push(`- **${
|
|
36608
|
+
for (const r3 of results) {
|
|
36609
|
+
lines.push(`- **${r3.title}** (${r3.file_path})`);
|
|
36539
36610
|
}
|
|
36540
36611
|
} else if (keyword) {
|
|
36541
36612
|
try {
|
|
@@ -36550,8 +36621,8 @@ function handlePlan(db, args2) {
|
|
|
36550
36621
|
`).all(sanitizeFts5Query(keyword));
|
|
36551
36622
|
lines.push(`## Plans matching "${keyword}" (${results.length} found)`);
|
|
36552
36623
|
lines.push("");
|
|
36553
|
-
for (const
|
|
36554
|
-
lines.push(`- **${
|
|
36624
|
+
for (const r3 of results) {
|
|
36625
|
+
lines.push(`- **${r3.title}** (${r3.file_path})`);
|
|
36555
36626
|
}
|
|
36556
36627
|
} catch {
|
|
36557
36628
|
lines.push(`FTS search error for "${keyword}". Try simpler terms.`);
|
|
@@ -36744,7 +36815,7 @@ function handleEffectiveness2(db, args2) {
|
|
|
36744
36815
|
}
|
|
36745
36816
|
if (ruleId || mode === "detail") {
|
|
36746
36817
|
const targetRule = ruleId || "";
|
|
36747
|
-
const rule = allRules.find((
|
|
36818
|
+
const rule = allRules.find((r3) => r3.rule_id === targetRule);
|
|
36748
36819
|
if (!rule) {
|
|
36749
36820
|
return text15(`Rule ${targetRule} not found.`);
|
|
36750
36821
|
}
|
|
@@ -36767,10 +36838,10 @@ function handleEffectiveness2(db, args2) {
|
|
|
36767
36838
|
lines.push(`| Linked Corrections | ${correctionEdges.cnt} |`);
|
|
36768
36839
|
lines.push(`| Effectiveness Score | ${violations === 0 ? "HIGH (never violated)" : violations < 3 ? "MEDIUM" : "LOW (frequently violated)"} |`);
|
|
36769
36840
|
} else {
|
|
36770
|
-
const rulesWithCounts = allRules.map((
|
|
36771
|
-
...
|
|
36772
|
-
violations: violationCounts.get(
|
|
36773
|
-
last_at: lastViolated.get(
|
|
36841
|
+
const rulesWithCounts = allRules.map((r3) => ({
|
|
36842
|
+
...r3,
|
|
36843
|
+
violations: violationCounts.get(r3.rule_id) || 0,
|
|
36844
|
+
last_at: lastViolated.get(r3.rule_id) || "Never"
|
|
36774
36845
|
}));
|
|
36775
36846
|
if (mode === "most_violated") {
|
|
36776
36847
|
rulesWithCounts.sort((a2, b2) => b2.violations - a2.violations);
|
|
@@ -36786,9 +36857,9 @@ function handleEffectiveness2(db, args2) {
|
|
|
36786
36857
|
lines.push("");
|
|
36787
36858
|
lines.push(`| Rule | Text | Violations | Last Violated |`);
|
|
36788
36859
|
lines.push(`|------|------|------------|---------------|`);
|
|
36789
|
-
for (const
|
|
36790
|
-
const ruleText =
|
|
36791
|
-
lines.push(`| ${
|
|
36860
|
+
for (const r3 of rulesWithCounts.slice(0, topN)) {
|
|
36861
|
+
const ruleText = r3.rule_text.length > 40 ? r3.rule_text.substring(0, 40) + "..." : r3.rule_text;
|
|
36862
|
+
lines.push(`| ${r3.rule_id} | ${ruleText} | ${r3.violations} | ${r3.last_at} |`);
|
|
36792
36863
|
}
|
|
36793
36864
|
}
|
|
36794
36865
|
return text15(lines.join("\n"));
|
|
@@ -37085,21 +37156,21 @@ function handlePyRoutes(args2, dataDb) {
|
|
|
37085
37156
|
const routes = dataDb.prepare(query).all(...params);
|
|
37086
37157
|
if (args2.uncoupled) {
|
|
37087
37158
|
const callerCountStmt = dataDb.prepare(`SELECT COUNT(*) as cnt FROM ${t("py_route_callers")} WHERE route_id = ?`);
|
|
37088
|
-
const uncoupledRoutes = routes.filter((
|
|
37089
|
-
const callers = callerCountStmt.get(
|
|
37159
|
+
const uncoupledRoutes = routes.filter((r3) => {
|
|
37160
|
+
const callers = callerCountStmt.get(r3.id).cnt;
|
|
37090
37161
|
return callers === 0;
|
|
37091
37162
|
});
|
|
37092
37163
|
lines.push(`## Uncoupled Routes (${uncoupledRoutes.length} with no frontend callers)`);
|
|
37093
|
-
for (const
|
|
37094
|
-
lines.push(`- ${
|
|
37164
|
+
for (const r3 of uncoupledRoutes) {
|
|
37165
|
+
lines.push(`- ${r3.method} ${r3.path} \u2192 ${r3.function_name} (${r3.file}:${r3.line})`);
|
|
37095
37166
|
}
|
|
37096
37167
|
} else {
|
|
37097
37168
|
lines.push(`## Python Routes (${routes.length} found)`);
|
|
37098
|
-
for (const
|
|
37099
|
-
const auth =
|
|
37100
|
-
const deps = safeParseArray(
|
|
37101
|
-
lines.push(`- ${
|
|
37102
|
-
if (
|
|
37169
|
+
for (const r3 of routes) {
|
|
37170
|
+
const auth = r3.is_authenticated ? "" : " [UNAUTH]";
|
|
37171
|
+
const deps = safeParseArray(r3.dependencies);
|
|
37172
|
+
lines.push(`- ${r3.method} ${r3.path} \u2192 ${r3.function_name} (${r3.file}:${r3.line})${auth}`);
|
|
37173
|
+
if (r3.response_model) lines.push(` Response: ${r3.response_model}`);
|
|
37103
37174
|
if (deps.length > 0) lines.push(` Depends: ${deps.join(", ")}`);
|
|
37104
37175
|
}
|
|
37105
37176
|
}
|
|
@@ -37301,8 +37372,8 @@ function handlePyImpact(args2, dataDb) {
|
|
|
37301
37372
|
if (routes.length > 0) {
|
|
37302
37373
|
lines.push(`
|
|
37303
37374
|
### Routes Defined (${routes.length})`);
|
|
37304
|
-
for (const
|
|
37305
|
-
lines.push(`- ${
|
|
37375
|
+
for (const r3 of routes) {
|
|
37376
|
+
lines.push(`- ${r3.method} ${r3.path} \u2192 ${r3.function_name}`);
|
|
37306
37377
|
}
|
|
37307
37378
|
}
|
|
37308
37379
|
const models = dataDb.prepare(
|
|
@@ -37320,7 +37391,7 @@ function handlePyImpact(args2, dataDb) {
|
|
|
37320
37391
|
const placeholders = routeIds.map(() => "?").join(",");
|
|
37321
37392
|
const callers = dataDb.prepare(
|
|
37322
37393
|
`SELECT DISTINCT frontend_file FROM ${t("py_route_callers")} WHERE route_id IN (${placeholders}) LIMIT 100000`
|
|
37323
|
-
).all(...routeIds.map((
|
|
37394
|
+
).all(...routeIds.map((r3) => r3.id));
|
|
37324
37395
|
if (callers.length > 0) {
|
|
37325
37396
|
lines.push(`
|
|
37326
37397
|
### Frontend Callers (${callers.length} files)`);
|
|
@@ -37363,8 +37434,8 @@ function handlePyContext(args2, dataDb) {
|
|
|
37363
37434
|
const routes = dataDb.prepare(`SELECT method, path, function_name, line FROM ${t("py_routes")} WHERE file = ? LIMIT 10000`).all(file);
|
|
37364
37435
|
if (routes.length > 0) {
|
|
37365
37436
|
lines.push("\n### Routes");
|
|
37366
|
-
for (const
|
|
37367
|
-
lines.push(`- ${
|
|
37437
|
+
for (const r3 of routes) {
|
|
37438
|
+
lines.push(`- ${r3.method} ${r3.path} \u2192 ${r3.function_name} (L${r3.line})`);
|
|
37368
37439
|
}
|
|
37369
37440
|
}
|
|
37370
37441
|
const models = dataDb.prepare(`SELECT class_name, table_name, line FROM ${t("py_models")} WHERE file = ? LIMIT 10000`).all(file);
|
|
@@ -37375,8 +37446,8 @@ function handlePyContext(args2, dataDb) {
|
|
|
37375
37446
|
}
|
|
37376
37447
|
}
|
|
37377
37448
|
const rules = config.rules || [];
|
|
37378
|
-
const matchingRules = rules.filter((
|
|
37379
|
-
const pattern =
|
|
37449
|
+
const matchingRules = rules.filter((r3) => {
|
|
37450
|
+
const pattern = r3.pattern;
|
|
37380
37451
|
if (pattern === "**") return true;
|
|
37381
37452
|
if (pattern.includes("**/*.py")) return file.endsWith(".py");
|
|
37382
37453
|
return file.includes(pattern.replace(/\*\*/g, ""));
|
|
@@ -37384,8 +37455,8 @@ function handlePyContext(args2, dataDb) {
|
|
|
37384
37455
|
if (matchingRules.length > 0) {
|
|
37385
37456
|
lines.push("\n### Applicable Rules");
|
|
37386
37457
|
for (const rule of matchingRules) {
|
|
37387
|
-
for (const
|
|
37388
|
-
lines.push(`- ${
|
|
37458
|
+
for (const r3 of rule.rules) {
|
|
37459
|
+
lines.push(`- ${r3}`);
|
|
37389
37460
|
}
|
|
37390
37461
|
}
|
|
37391
37462
|
}
|
|
@@ -37791,8 +37862,8 @@ function handleContext(file, dataDb, codegraphDb) {
|
|
|
37791
37862
|
lines.push("## Applicable Rules");
|
|
37792
37863
|
for (const rule of rules) {
|
|
37793
37864
|
const severity = rule.severity ? `[${rule.severity}]` : "";
|
|
37794
|
-
for (const
|
|
37795
|
-
lines.push(`- ${severity} ${
|
|
37865
|
+
for (const r3 of rule.rules) {
|
|
37866
|
+
lines.push(`- ${severity} ${r3}`);
|
|
37796
37867
|
}
|
|
37797
37868
|
if (rule.patternFile) {
|
|
37798
37869
|
lines.push(` See: .claude/${rule.patternFile}`);
|
|
@@ -37880,7 +37951,7 @@ function handleContext(file, dataDb, codegraphDb) {
|
|
|
37880
37951
|
WHERE kf.content MATCH ? AND kc.chunk_type = 'rule'
|
|
37881
37952
|
LIMIT 8
|
|
37882
37953
|
`).all(ftsQuery);
|
|
37883
|
-
ftsRuleIds = ftsResults.map((
|
|
37954
|
+
ftsRuleIds = ftsResults.map((r3) => r3.rule_id).filter((id) => id.startsWith("CR-"));
|
|
37884
37955
|
} catch {
|
|
37885
37956
|
}
|
|
37886
37957
|
}
|
|
@@ -38234,7 +38305,7 @@ function handleDomains(args2, dataDb, codegraphDb) {
|
|
|
38234
38305
|
}
|
|
38235
38306
|
lines.push("");
|
|
38236
38307
|
lines.push(`### Routers (${files.routers.length})`);
|
|
38237
|
-
for (const
|
|
38308
|
+
for (const r3 of files.routers) lines.push(`- ${r3}`);
|
|
38238
38309
|
lines.push("");
|
|
38239
38310
|
lines.push(`### Pages (${files.pages.length})`);
|
|
38240
38311
|
for (const p19 of files.pages) lines.push(`- ${p19}`);
|
|
@@ -39324,8 +39395,8 @@ function winManagerDirs(env) {
|
|
|
39324
39395
|
function windowsAllowlistRoots(env) {
|
|
39325
39396
|
const d2 = winManagerDirs(env);
|
|
39326
39397
|
const roots = [];
|
|
39327
|
-
for (const
|
|
39328
|
-
if (
|
|
39398
|
+
for (const r3 of [d2.userprofile, d2.nvmHome, d2.nvmSymlink, d2.fnmDir, d2.voltaHome, d2.localappdata]) {
|
|
39399
|
+
if (r3) roots.push(r3);
|
|
39329
39400
|
}
|
|
39330
39401
|
roots.push("C:\\Program Files\\nodejs", "C:\\Program Files (x86)\\nodejs");
|
|
39331
39402
|
return roots;
|