squadrant 0.27.1 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +755 -515
- package/dist/index.js.map +1 -1
- package/dist/squadrantd.js +451 -258
- package/dist/squadrantd.js.map +1 -1
- package/package.json +1 -1
- package/plugin/skills/knowledge-extract/SKILL.md +2 -0
- package/plugin/skills/knowledge-review/SKILL.md +5 -0
- package/templates/crew.claude.md +1 -0
- package/templates/crew.generic.md +1 -0
- package/templates/crew.opencode.md +1 -0
package/dist/squadrantd.js
CHANGED
|
@@ -305,7 +305,8 @@ function validateRuleFrontmatter(fm) {
|
|
|
305
305
|
if (fm[k] !== void 0 && !isStrArr(fm[k]))
|
|
306
306
|
p.push(`${k} must be a string array`);
|
|
307
307
|
}
|
|
308
|
-
|
|
308
|
+
const mayBeSourceless = fm.status === "stale" || fm.status === "retired";
|
|
309
|
+
if (!Array.isArray(fm.sources) || fm.sources.length === 0 && !mayBeSourceless) {
|
|
309
310
|
p.push("sources must be a non-empty array");
|
|
310
311
|
} else {
|
|
311
312
|
fm.sources.forEach((s, i) => {
|
|
@@ -339,6 +340,26 @@ function validateSourceEntry(e) {
|
|
|
339
340
|
p.push("domain must be a string");
|
|
340
341
|
if (e.sensitivity !== void 0 && e.sensitivity !== "local-only")
|
|
341
342
|
p.push("sensitivity must be 'local-only' when set");
|
|
343
|
+
if (e.review !== void 0 && e.review !== "required")
|
|
344
|
+
p.push("review must be 'required' when set");
|
|
345
|
+
return p;
|
|
346
|
+
}
|
|
347
|
+
function validateErratum(e) {
|
|
348
|
+
if (!isObj(e))
|
|
349
|
+
return ["erratum must be an object"];
|
|
350
|
+
const p = [];
|
|
351
|
+
if (typeof e.id !== "string" || !RULE_ID_RE.test(e.id))
|
|
352
|
+
p.push(`id must match ${RULE_ID_RE}`);
|
|
353
|
+
for (const k of ["ref", "quote", "reason"]) {
|
|
354
|
+
if (typeof e[k] !== "string" || e[k] === "")
|
|
355
|
+
p.push(`${k} must be a non-empty string`);
|
|
356
|
+
}
|
|
357
|
+
if (e.evidence !== void 0 && !isStrArr(e.evidence))
|
|
358
|
+
p.push("evidence must be a string array");
|
|
359
|
+
for (const k of ["checked", "by", "at", "decision"]) {
|
|
360
|
+
if (e[k] !== void 0 && typeof e[k] !== "string")
|
|
361
|
+
p.push(`${k} must be a string`);
|
|
362
|
+
}
|
|
342
363
|
return p;
|
|
343
364
|
}
|
|
344
365
|
function kbConfigs(cfg) {
|
|
@@ -463,22 +484,22 @@ function defaultCmuxConfigPath() {
|
|
|
463
484
|
return join(homedir(), ".config", "cmux", "cmux.json");
|
|
464
485
|
}
|
|
465
486
|
function ensureSocketAutomation(opts = {}) {
|
|
466
|
-
const
|
|
467
|
-
if (!existsSync(
|
|
468
|
-
mkdirSync(dirname(
|
|
469
|
-
writeFileSync(
|
|
470
|
-
return { path:
|
|
487
|
+
const path43 = opts.path ?? defaultCmuxConfigPath();
|
|
488
|
+
if (!existsSync(path43)) {
|
|
489
|
+
mkdirSync(dirname(path43), { recursive: true });
|
|
490
|
+
writeFileSync(path43, MINIMAL_TEMPLATE);
|
|
491
|
+
return { path: path43, changed: true, alreadySet: false };
|
|
471
492
|
}
|
|
472
|
-
const text = readFileSync(
|
|
493
|
+
const text = readFileSync(path43, "utf-8");
|
|
473
494
|
const current = parse(text)?.automation?.socketControlMode;
|
|
474
495
|
if (current === AUTOMATION_MODE) {
|
|
475
|
-
return { path:
|
|
496
|
+
return { path: path43, changed: false, alreadySet: true };
|
|
476
497
|
}
|
|
477
498
|
const edits = modify(text, [...SOCKET_CONTROL_MODE_PATH], AUTOMATION_MODE, {
|
|
478
499
|
formattingOptions: { insertSpaces: true, tabSize: 2 }
|
|
479
500
|
});
|
|
480
|
-
writeFileSync(
|
|
481
|
-
return { path:
|
|
501
|
+
writeFileSync(path43, applyEdits(text, edits));
|
|
502
|
+
return { path: path43, changed: true, alreadySet: false };
|
|
482
503
|
}
|
|
483
504
|
var SOCKET_CONTROL_MODE_PATH, AUTOMATION_MODE, MINIMAL_TEMPLATE;
|
|
484
505
|
var init_cmux_config = __esm({
|
|
@@ -628,9 +649,9 @@ import { join as join4 } from "path";
|
|
|
628
649
|
function defaultStatePath() {
|
|
629
650
|
return join4(homedir3(), ".config", "squadrant", "state", "cmux-autoconfig.json");
|
|
630
651
|
}
|
|
631
|
-
function readState(
|
|
652
|
+
function readState(path43) {
|
|
632
653
|
try {
|
|
633
|
-
return JSON.parse(readConfigFileSync(
|
|
654
|
+
return JSON.parse(readConfigFileSync(path43));
|
|
634
655
|
} catch {
|
|
635
656
|
return {};
|
|
636
657
|
}
|
|
@@ -2577,10 +2598,10 @@ function detectForeignInstall(parsed, thisEntry, registeredEntryExists) {
|
|
|
2577
2598
|
isUpgrade: isVersionUpgrade(parsed.daemonEntry, thisEntry)
|
|
2578
2599
|
};
|
|
2579
2600
|
}
|
|
2580
|
-
function sanitizePathForPlist(
|
|
2601
|
+
function sanitizePathForPlist(path43) {
|
|
2581
2602
|
const seen = /* @__PURE__ */ new Set();
|
|
2582
2603
|
const stable = [];
|
|
2583
|
-
for (const p of
|
|
2604
|
+
for (const p of path43.split(":")) {
|
|
2584
2605
|
if (!p)
|
|
2585
2606
|
continue;
|
|
2586
2607
|
if (p.includes("/.claude/plugins/"))
|
|
@@ -5120,11 +5141,11 @@ var init_captain_record = __esm({
|
|
|
5120
5141
|
// packages/core/dist/opencode-session.js
|
|
5121
5142
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
5122
5143
|
async function listSessions(port, fetchImpl = fetch, timeoutMs = 5e3) {
|
|
5123
|
-
for (const
|
|
5144
|
+
for (const path43 of ["/session", "/api/session"]) {
|
|
5124
5145
|
const ac = new AbortController();
|
|
5125
5146
|
const t = setTimeout(() => ac.abort(), timeoutMs);
|
|
5126
5147
|
try {
|
|
5127
|
-
const res = await fetchImpl(`http://127.0.0.1:${port}${
|
|
5148
|
+
const res = await fetchImpl(`http://127.0.0.1:${port}${path43}`, { signal: ac.signal });
|
|
5128
5149
|
if (!res.ok)
|
|
5129
5150
|
continue;
|
|
5130
5151
|
const rows = await res.json();
|
|
@@ -5817,10 +5838,10 @@ function distBuiltAt() {
|
|
|
5817
5838
|
return 0;
|
|
5818
5839
|
}
|
|
5819
5840
|
}
|
|
5820
|
-
function gatherLogStats(
|
|
5841
|
+
function gatherLogStats(path43, now, windowMs) {
|
|
5821
5842
|
let sizeBytes = 0;
|
|
5822
5843
|
try {
|
|
5823
|
-
sizeBytes = statSync3(
|
|
5844
|
+
sizeBytes = statSync3(path43).size;
|
|
5824
5845
|
} catch {
|
|
5825
5846
|
return { errorCount: 0, sizeBytes: 0, windowMs };
|
|
5826
5847
|
}
|
|
@@ -5831,7 +5852,7 @@ function gatherLogStats(path42, now, windowMs) {
|
|
|
5831
5852
|
const len = sizeBytes - start;
|
|
5832
5853
|
let text = "";
|
|
5833
5854
|
try {
|
|
5834
|
-
const fd = openSync2(
|
|
5855
|
+
const fd = openSync2(path43, "r");
|
|
5835
5856
|
try {
|
|
5836
5857
|
const buf = Buffer.alloc(len);
|
|
5837
5858
|
readSync(fd, buf, 0, len, start);
|
|
@@ -8077,8 +8098,8 @@ var init_stream = __esm({
|
|
|
8077
8098
|
// packages/core/dist/router/shim.js
|
|
8078
8099
|
import { createServer as createServer3 } from "http";
|
|
8079
8100
|
import { Readable } from "stream";
|
|
8080
|
-
function joinUrl(base,
|
|
8081
|
-
return base.replace(/\/+$/, "") +
|
|
8101
|
+
function joinUrl(base, path43) {
|
|
8102
|
+
return base.replace(/\/+$/, "") + path43;
|
|
8082
8103
|
}
|
|
8083
8104
|
async function readBody(req) {
|
|
8084
8105
|
const chunks = [];
|
|
@@ -8254,8 +8275,8 @@ function createRouterShim(opts) {
|
|
|
8254
8275
|
writeJson(res, 200, { input_tokens: Math.max(1, Math.ceil(text.length / 4)) });
|
|
8255
8276
|
}
|
|
8256
8277
|
function handler(req, res) {
|
|
8257
|
-
const
|
|
8258
|
-
if (req.method === "POST" &&
|
|
8278
|
+
const path43 = pathnameOf(req.url);
|
|
8279
|
+
if (req.method === "POST" && path43 === "/v1/messages") {
|
|
8259
8280
|
void handleMessages(req, res).catch((err) => {
|
|
8260
8281
|
log(`router internal error: ${err instanceof Error ? err.message : String(err)}`);
|
|
8261
8282
|
if (!res.headersSent) {
|
|
@@ -8267,18 +8288,18 @@ function createRouterShim(opts) {
|
|
|
8267
8288
|
});
|
|
8268
8289
|
return;
|
|
8269
8290
|
}
|
|
8270
|
-
if (req.method === "POST" &&
|
|
8291
|
+
if (req.method === "POST" && path43 === "/v1/messages/count_tokens") {
|
|
8271
8292
|
void handleCountTokens(req, res).catch(() => {
|
|
8272
8293
|
if (!res.headersSent)
|
|
8273
8294
|
writeJson(res, 502, anthropicError(502, "api_error", "router internal error").body);
|
|
8274
8295
|
});
|
|
8275
8296
|
return;
|
|
8276
8297
|
}
|
|
8277
|
-
if (req.method === "GET" &&
|
|
8298
|
+
if (req.method === "GET" && path43 === "/v1/models") {
|
|
8278
8299
|
writeJson(res, 200, modelsList([...advertisedModels]));
|
|
8279
8300
|
return;
|
|
8280
8301
|
}
|
|
8281
|
-
if (req.method === "GET" &&
|
|
8302
|
+
if (req.method === "GET" && path43 === "/healthz") {
|
|
8282
8303
|
writeJson(res, 200, { ready: server?.listening === true, upstreamReachable, lastError });
|
|
8283
8304
|
return;
|
|
8284
8305
|
}
|
|
@@ -8547,11 +8568,11 @@ async function probeCaptainChannel(project, opts = {}) {
|
|
|
8547
8568
|
}
|
|
8548
8569
|
}
|
|
8549
8570
|
async function httpReachable(port, fetchImpl, timeoutMs) {
|
|
8550
|
-
for (const
|
|
8571
|
+
for (const path43 of ["/session", "/api/session"]) {
|
|
8551
8572
|
const ac = new AbortController();
|
|
8552
8573
|
const t = setTimeout(() => ac.abort(), timeoutMs);
|
|
8553
8574
|
try {
|
|
8554
|
-
const res = await fetchImpl(`http://127.0.0.1:${port}${
|
|
8575
|
+
const res = await fetchImpl(`http://127.0.0.1:${port}${path43}`, { signal: ac.signal });
|
|
8555
8576
|
if (res.ok)
|
|
8556
8577
|
return true;
|
|
8557
8578
|
} catch {
|
|
@@ -9473,6 +9494,11 @@ function expandSource(kbRoot, entry) {
|
|
|
9473
9494
|
const re = globToRegExp(abs.split(path16.sep).join("/"));
|
|
9474
9495
|
return walkFiles(root).filter((f) => re.test(f.split(path16.sep).join("/"))).sort();
|
|
9475
9496
|
}
|
|
9497
|
+
function sourceCovers(kbRoot, entry, ref) {
|
|
9498
|
+
const abs = path16.resolve(kbRoot, expandHome(entry.path));
|
|
9499
|
+
const file = fileForRef(kbRoot, ref);
|
|
9500
|
+
return /[*?]/.test(entry.path) ? globToRegExp(abs.split(path16.sep).join("/")).test(file.split(path16.sep).join("/")) : abs === file;
|
|
9501
|
+
}
|
|
9476
9502
|
function detectChange(kbRoot, file) {
|
|
9477
9503
|
const ref = refFor(kbRoot, file);
|
|
9478
9504
|
const st = fs15.statSync(file);
|
|
@@ -9569,7 +9595,7 @@ async function planIngest(kbRoot, opts) {
|
|
|
9569
9595
|
}
|
|
9570
9596
|
return plan;
|
|
9571
9597
|
}
|
|
9572
|
-
var execFileAsync, CONVERTED_DIR, DEFAULT_MAX_SECTIONS_PER_PASS, CHARS_PER_TOKEN, PASS_THROUGH, SECTION_TARGET_CHARS, markitdownConverter, expandHome, fileForRef, cacheKey, convertedFile, stampFile, sha256;
|
|
9598
|
+
var execFileAsync, CONVERTED_DIR, DEFAULT_MAX_SECTIONS_PER_PASS, CHARS_PER_TOKEN, PASS_THROUGH, SECTION_TARGET_CHARS, markitdownConverter, expandHome, fileForRef, cacheKey, convertedFile, stampFile, isGatedRef, sha256;
|
|
9573
9599
|
var init_ingest = __esm({
|
|
9574
9600
|
"packages/core/dist/knowledge/ingest.js"() {
|
|
9575
9601
|
execFileAsync = promisify2(execFile2);
|
|
@@ -9587,6 +9613,7 @@ var init_ingest = __esm({
|
|
|
9587
9613
|
cacheKey = (ref) => `${ref.replace(/[^A-Za-z0-9._-]+/g, "_")}.${crypto3.createHash("sha1").update(ref).digest("hex").slice(0, 6)}`;
|
|
9588
9614
|
convertedFile = (kbRoot, ref) => path16.join(kbRoot, CONVERTED_DIR, `${cacheKey(ref)}.md`);
|
|
9589
9615
|
stampFile = (kbRoot, ref) => path16.join(kbRoot, CONVERTED_DIR, `${cacheKey(ref)}.sha`);
|
|
9616
|
+
isGatedRef = (kbRoot, sources, ref) => sources.some((e) => e.review === "required" && sourceCovers(kbRoot, e, ref));
|
|
9590
9617
|
sha256 = (file) => crypto3.createHash("sha256").update(fs15.readFileSync(file)).digest("hex");
|
|
9591
9618
|
}
|
|
9592
9619
|
});
|
|
@@ -9779,9 +9806,14 @@ function validateKb(opts) {
|
|
|
9779
9806
|
});
|
|
9780
9807
|
}
|
|
9781
9808
|
const { hay, convertible } = cache.get(key);
|
|
9782
|
-
|
|
9809
|
+
const span = findQuote(hay, src.quote);
|
|
9810
|
+
if (span) {
|
|
9783
9811
|
verified++;
|
|
9784
|
-
|
|
9812
|
+
const active = r.status === "active" && !path17.relative(opts.rulesDir, r.file).split(path17.sep).includes(PROPOSED_DIR);
|
|
9813
|
+
const err = active ? (opts.errata ?? []).find((e) => e.ref === src.ref && ((o) => !!o && spansOverlap(o, span))(findQuote(hay, e.quote))) : void 0;
|
|
9814
|
+
if (err)
|
|
9815
|
+
checks.push({ level: "warn", message: `${r.id}: grounded in erratum ${err.id} (${err.reason}); re-check or retire it (${r.file})` });
|
|
9816
|
+
} else if (convertible)
|
|
9785
9817
|
notIngested++;
|
|
9786
9818
|
else
|
|
9787
9819
|
checks.push({ level: "fail", message: `quote not found in ${file}: ${r.id} sources[${i}] (${r.file})` });
|
|
@@ -12986,6 +13018,7 @@ var init_js_yaml = __esm({
|
|
|
12986
13018
|
// packages/core/dist/knowledge/sources.js
|
|
12987
13019
|
import fs19 from "fs";
|
|
12988
13020
|
import path19 from "path";
|
|
13021
|
+
import matter3 from "gray-matter";
|
|
12989
13022
|
function loadSources(kbRoot) {
|
|
12990
13023
|
const file = path19.join(kbRoot, "sources.yaml");
|
|
12991
13024
|
if (!fs19.existsSync(file))
|
|
@@ -13011,20 +13044,77 @@ function loadSources(kbRoot) {
|
|
|
13011
13044
|
});
|
|
13012
13045
|
return { sources, errors };
|
|
13013
13046
|
}
|
|
13047
|
+
function dropEntryBlock(text, entryPath) {
|
|
13048
|
+
const lines = text.split("\n");
|
|
13049
|
+
const q = entryPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
13050
|
+
const head = new RegExp(`^-\\s+path:\\s*(['"]?)${q}\\1\\s*(#.*)?$`);
|
|
13051
|
+
const i = lines.findIndex((l) => head.test(l));
|
|
13052
|
+
if (i < 0)
|
|
13053
|
+
return null;
|
|
13054
|
+
let j = i + 1;
|
|
13055
|
+
while (j < lines.length && /^\s+\S/.test(lines[j]))
|
|
13056
|
+
j++;
|
|
13057
|
+
return [...lines.slice(0, i), ...lines.slice(j)].join("\n");
|
|
13058
|
+
}
|
|
13059
|
+
function removeSource(kbRoot, rulesDir, entryPath, opts = {}) {
|
|
13060
|
+
const file = path19.join(kbRoot, "sources.yaml");
|
|
13061
|
+
const { sources } = loadSources(kbRoot);
|
|
13062
|
+
const entry = sources.find((s) => s.path === entryPath);
|
|
13063
|
+
if (!entry)
|
|
13064
|
+
throw new Error(`no sources.yaml entry with path '${entryPath}' (give it exactly as listed by \`knowledge sources\`)`);
|
|
13065
|
+
const edited = dropEntryBlock(fs19.readFileSync(file, "utf8"), entryPath);
|
|
13066
|
+
if (edited === null)
|
|
13067
|
+
throw new Error(`could not edit sources.yaml for '${entryPath}' (not a plain block entry); remove it by hand, then rerun to strip the refs`);
|
|
13068
|
+
const res = { dryRun: !!opts.dryRun, entryRemoved: true, stripped: [], stale: [] };
|
|
13069
|
+
const writes = [];
|
|
13070
|
+
for (const rule of loadRulesDir(rulesDir, "kb").rules) {
|
|
13071
|
+
const kept = rule.sources.filter((s) => !sourceCovers(kbRoot, entry, s.ref));
|
|
13072
|
+
if (kept.length === rule.sources.length)
|
|
13073
|
+
continue;
|
|
13074
|
+
res.stripped.push(rule.id);
|
|
13075
|
+
const parsed = matter3(fs19.readFileSync(rule.file, "utf8"), { engines: { javascript: () => {
|
|
13076
|
+
throw new Error("only YAML front matter is allowed");
|
|
13077
|
+
} } });
|
|
13078
|
+
const fm = { ...parsed.data, sources: kept };
|
|
13079
|
+
if (!kept.length) {
|
|
13080
|
+
res.stale.push(rule.id);
|
|
13081
|
+
if (fm.status === "active")
|
|
13082
|
+
fm.status = "stale";
|
|
13083
|
+
}
|
|
13084
|
+
writes.push({ file: rule.file, text: matter3.stringify(parsed.content, JSON.parse(JSON.stringify(fm))) });
|
|
13085
|
+
}
|
|
13086
|
+
res.stripped.sort();
|
|
13087
|
+
res.stale.sort();
|
|
13088
|
+
if (opts.dryRun)
|
|
13089
|
+
return res;
|
|
13090
|
+
for (const w of writes)
|
|
13091
|
+
fs19.writeFileSync(w.file, w.text);
|
|
13092
|
+
fs19.writeFileSync(file, edited);
|
|
13093
|
+
const name = opts.kbName ?? path19.basename(kbRoot);
|
|
13094
|
+
writeIndex(kbRoot, compileIndex(name, loadRulesDir(rulesDir, `kb:${name}`).rules));
|
|
13095
|
+
return res;
|
|
13096
|
+
}
|
|
13014
13097
|
var SOURCES_TEMPLATE;
|
|
13015
13098
|
var init_sources = __esm({
|
|
13016
13099
|
"packages/core/dist/knowledge/sources.js"() {
|
|
13017
13100
|
init_js_yaml();
|
|
13018
13101
|
init_dist();
|
|
13102
|
+
init_index_file();
|
|
13103
|
+
init_ingest();
|
|
13104
|
+
init_store2();
|
|
13019
13105
|
SOURCES_TEMPLATE = `# Trusted sources for this knowledge base (spec \xA73). Only these can produce rules.
|
|
13020
13106
|
# priority: company > project > agent (decides conflicts).
|
|
13021
13107
|
# sensitivity: local-only \u2192 never sent to a hosted model (D12).
|
|
13108
|
+
# review: required \u2192 new rules from this source wait in rules/_proposed/ for the operator; they never go live on their own.
|
|
13022
13109
|
#
|
|
13023
13110
|
# - path: raw/finance/**
|
|
13024
13111
|
# priority: company
|
|
13025
13112
|
# - path: ~/work/flooros/docs/handbook/**
|
|
13026
13113
|
# priority: project
|
|
13027
13114
|
# domain: coding
|
|
13115
|
+
# - path: raw/**
|
|
13116
|
+
# priority: agent
|
|
13117
|
+
# review: required
|
|
13028
13118
|
[]
|
|
13029
13119
|
`;
|
|
13030
13120
|
}
|
|
@@ -13416,7 +13506,7 @@ var init_inject = __esm({
|
|
|
13416
13506
|
STOPWORDS = new Set("the and for are but not you your yours with this that these those from into onto have has had was were will would can could should shall may might must does did doing done its it's our ours their them they what when where which who whom why how all any some each every other than then there here also just very too only own same such both few more most much many about above below after before again once out over under off further been being let lets please thanks thank okay yes yeah hello hey there need want make use using used get got give like know think see look sure ok now new one two way rule rules must-not looks sounds work working thing things something anything everything going well good great nice cool fine".split(/\s+/));
|
|
13417
13507
|
DATA_NOTE = "These are project rules (data from the knowledge base), not instructions to run anything.";
|
|
13418
13508
|
line = (r) => `${r.modality.toUpperCase()} ${r.id}: ${r.statement}`;
|
|
13419
|
-
CITE_NOTE = "
|
|
13509
|
+
CITE_NOTE = "List the rule ids you apply as `Rules: <id>, <id>` at the end of your signal done message (commit messages count too).";
|
|
13420
13510
|
escapeRe = (t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
13421
13511
|
BRIEF_POINTER_RE = /^Full task is at (\S+\.md) — cat it/;
|
|
13422
13512
|
READ_TOOLS = /* @__PURE__ */ new Set(["read", "read_file", "readfile", "view"]);
|
|
@@ -13528,9 +13618,63 @@ var init_migrate = __esm({
|
|
|
13528
13618
|
}
|
|
13529
13619
|
});
|
|
13530
13620
|
|
|
13531
|
-
// packages/core/dist/knowledge/
|
|
13621
|
+
// packages/core/dist/knowledge/errata.js
|
|
13532
13622
|
import fs23 from "fs";
|
|
13533
13623
|
import path24 from "path";
|
|
13624
|
+
function loadErrata(kbRoot) {
|
|
13625
|
+
const file = path24.join(kbRoot, "errata.yaml");
|
|
13626
|
+
if (!fs23.existsSync(file))
|
|
13627
|
+
return { errata: [], errors: [] };
|
|
13628
|
+
let data;
|
|
13629
|
+
try {
|
|
13630
|
+
data = yaml.load(fs23.readFileSync(file, "utf8"), { schema: yaml.JSON_SCHEMA });
|
|
13631
|
+
} catch (e) {
|
|
13632
|
+
return { errata: [], errors: [`YAML parse error: ${e.message.split("\n")[0]}`] };
|
|
13633
|
+
}
|
|
13634
|
+
if (data == null)
|
|
13635
|
+
return { errata: [], errors: [] };
|
|
13636
|
+
if (!Array.isArray(data))
|
|
13637
|
+
return { errata: [], errors: ["errata.yaml must be a YAML list of entries"] };
|
|
13638
|
+
const errata = [];
|
|
13639
|
+
const errors = [];
|
|
13640
|
+
data.forEach((entry, i) => {
|
|
13641
|
+
const problems = validateErratum(entry);
|
|
13642
|
+
if (problems.length)
|
|
13643
|
+
errors.push(...problems.map((p) => `entry ${i}: ${p}`));
|
|
13644
|
+
else
|
|
13645
|
+
errata.push(entry);
|
|
13646
|
+
});
|
|
13647
|
+
return { errata, errors };
|
|
13648
|
+
}
|
|
13649
|
+
function orphanedErrata(kbRoot, errata, refs) {
|
|
13650
|
+
const only = refs ? new Set(refs) : void 0;
|
|
13651
|
+
const hays = /* @__PURE__ */ new Map();
|
|
13652
|
+
const out = [];
|
|
13653
|
+
for (const e of errata) {
|
|
13654
|
+
if (only && !only.has(e.ref))
|
|
13655
|
+
continue;
|
|
13656
|
+
if (!hays.has(e.ref)) {
|
|
13657
|
+
const conv = readState2(kbRoot, e.ref) ? convertedFile(kbRoot, e.ref) : null;
|
|
13658
|
+
hays.set(e.ref, conv && fs23.existsSync(conv) ? normalizedViews(fs23.readFileSync(conv, "utf8")) : null);
|
|
13659
|
+
}
|
|
13660
|
+
const hay = hays.get(e.ref);
|
|
13661
|
+
if (hay && !findQuote(hay, e.quote))
|
|
13662
|
+
out.push({ id: e.id, ref: e.ref });
|
|
13663
|
+
}
|
|
13664
|
+
return out;
|
|
13665
|
+
}
|
|
13666
|
+
var init_errata = __esm({
|
|
13667
|
+
"packages/core/dist/knowledge/errata.js"() {
|
|
13668
|
+
init_js_yaml();
|
|
13669
|
+
init_dist();
|
|
13670
|
+
init_ingest();
|
|
13671
|
+
init_verify();
|
|
13672
|
+
}
|
|
13673
|
+
});
|
|
13674
|
+
|
|
13675
|
+
// packages/core/dist/knowledge/anchor.js
|
|
13676
|
+
import fs24 from "fs";
|
|
13677
|
+
import path25 from "path";
|
|
13534
13678
|
function* repoFiles(root) {
|
|
13535
13679
|
let count = 0;
|
|
13536
13680
|
const stack = [root];
|
|
@@ -13538,43 +13682,43 @@ function* repoFiles(root) {
|
|
|
13538
13682
|
const dir = stack.pop();
|
|
13539
13683
|
let ents;
|
|
13540
13684
|
try {
|
|
13541
|
-
ents =
|
|
13685
|
+
ents = fs24.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name < b.name ? 1 : -1);
|
|
13542
13686
|
} catch {
|
|
13543
13687
|
continue;
|
|
13544
13688
|
}
|
|
13545
13689
|
for (const ent of ents) {
|
|
13546
13690
|
if (ent.isDirectory()) {
|
|
13547
13691
|
if (!SKIP_DIRS.has(ent.name))
|
|
13548
|
-
stack.push(
|
|
13549
|
-
} else if (ent.isFile() && CODE_EXT.has(
|
|
13692
|
+
stack.push(path25.join(dir, ent.name));
|
|
13693
|
+
} else if (ent.isFile() && CODE_EXT.has(path25.extname(ent.name))) {
|
|
13550
13694
|
if (++count > MAX_FILES)
|
|
13551
13695
|
return;
|
|
13552
|
-
yield
|
|
13696
|
+
yield path25.join(dir, ent.name);
|
|
13553
13697
|
}
|
|
13554
13698
|
}
|
|
13555
13699
|
}
|
|
13556
13700
|
}
|
|
13557
13701
|
function computeAnchor(repoRoot, triggers) {
|
|
13558
13702
|
const terms2 = anchorTerms(triggers);
|
|
13559
|
-
if (!terms2.length || !
|
|
13703
|
+
if (!terms2.length || !fs24.existsSync(repoRoot))
|
|
13560
13704
|
return null;
|
|
13561
13705
|
const hits = [];
|
|
13562
13706
|
for (const file of repoFiles(repoRoot)) {
|
|
13563
13707
|
let text;
|
|
13564
13708
|
try {
|
|
13565
|
-
if (
|
|
13709
|
+
if (fs24.statSync(file).size > MAX_FILE_BYTES)
|
|
13566
13710
|
continue;
|
|
13567
|
-
text =
|
|
13711
|
+
text = fs24.readFileSync(file, "utf8");
|
|
13568
13712
|
} catch {
|
|
13569
13713
|
continue;
|
|
13570
13714
|
}
|
|
13571
|
-
const hay = `${
|
|
13715
|
+
const hay = `${path25.relative(repoRoot, file)}
|
|
13572
13716
|
${text}`.toLowerCase();
|
|
13573
13717
|
const score = terms2.filter((t) => hay.includes(t)).length;
|
|
13574
13718
|
if (!score)
|
|
13575
13719
|
continue;
|
|
13576
13720
|
const symbols2 = [...text.matchAll(SYMBOL_RE)].map((m) => m[1]).filter((s) => terms2.some((t) => s.toLowerCase().includes(t)));
|
|
13577
|
-
hits.push({ rel:
|
|
13721
|
+
hits.push({ rel: path25.relative(repoRoot, file).split(path25.sep).join("/"), score, symbols: symbols2 });
|
|
13578
13722
|
}
|
|
13579
13723
|
if (!hits.length)
|
|
13580
13724
|
return null;
|
|
@@ -13598,11 +13742,11 @@ var init_anchor = __esm({
|
|
|
13598
13742
|
});
|
|
13599
13743
|
|
|
13600
13744
|
// packages/core/dist/knowledge/extract.js
|
|
13601
|
-
import
|
|
13602
|
-
import
|
|
13603
|
-
import
|
|
13745
|
+
import fs25 from "fs";
|
|
13746
|
+
import path26 from "path";
|
|
13747
|
+
import matter4 from "gray-matter";
|
|
13604
13748
|
function serialize(fm, body) {
|
|
13605
|
-
return
|
|
13749
|
+
return matter4.stringify(body.trim() + "\n", clean(fm));
|
|
13606
13750
|
}
|
|
13607
13751
|
function validateCandidate(c) {
|
|
13608
13752
|
const p = [];
|
|
@@ -13645,9 +13789,9 @@ function upsertSource(fm, src) {
|
|
|
13645
13789
|
}
|
|
13646
13790
|
function applyCandidates(input, opts) {
|
|
13647
13791
|
const { kb, kbRoot, rulesDir } = opts;
|
|
13648
|
-
const res = { created: [], merged: [], proposed: [], superseded: [], stale: [], rejected: [], doclingFlags: [], idOverrides: [] };
|
|
13792
|
+
const res = { created: [], merged: [], proposed: [], superseded: [], stale: [], rejected: [], doclingFlags: [], idOverrides: [], orphanedErrata: [] };
|
|
13649
13793
|
const events = [];
|
|
13650
|
-
const ev2 = (event, itemId,
|
|
13794
|
+
const ev2 = (event, itemId, extra = {}) => events.push({ kb, level: "group", project: "", domain: "rules", itemId, event, ...extra });
|
|
13651
13795
|
const loaded = loadRulesDir(rulesDir, `kb:${kb}`);
|
|
13652
13796
|
const work = /* @__PURE__ */ new Map();
|
|
13653
13797
|
for (const r of loaded.rules) {
|
|
@@ -13666,13 +13810,13 @@ function applyCandidates(input, opts) {
|
|
|
13666
13810
|
}
|
|
13667
13811
|
const st = readState2(kbRoot, cand.source);
|
|
13668
13812
|
const convFile = st ? convertedFile(kbRoot, cand.source) : null;
|
|
13669
|
-
if (!st || !
|
|
13813
|
+
if (!st || !fs25.existsSync(convFile)) {
|
|
13670
13814
|
res.rejected.push({ id: cand.id, source: cand.source, reason: "unknown source (not ingested)" });
|
|
13671
13815
|
continue;
|
|
13672
13816
|
}
|
|
13673
13817
|
let hay = norm.get(cand.source);
|
|
13674
13818
|
if (!hay) {
|
|
13675
|
-
hay = normalizedViews(
|
|
13819
|
+
hay = normalizedViews(fs25.readFileSync(convFile, "utf8"));
|
|
13676
13820
|
norm.set(cand.source, hay);
|
|
13677
13821
|
}
|
|
13678
13822
|
const tot = totals.get(cand.source) ?? { total: 0, dropped: 0 };
|
|
@@ -13682,7 +13826,14 @@ function applyCandidates(input, opts) {
|
|
|
13682
13826
|
if (!offset) {
|
|
13683
13827
|
tot.dropped++;
|
|
13684
13828
|
res.rejected.push({ id: cand.id, source: cand.source, reason: "ungrounded" });
|
|
13685
|
-
ev2("item.rejected", cand.id,
|
|
13829
|
+
ev2("item.rejected", cand.id, { reason: "ungrounded" });
|
|
13830
|
+
continue;
|
|
13831
|
+
}
|
|
13832
|
+
const hit = (opts.errata ?? []).find((e) => e.ref === cand.source && ((o) => !!o && spansOverlap(o, offset))(findQuote(hay, e.quote)));
|
|
13833
|
+
if (hit) {
|
|
13834
|
+
tot.total--;
|
|
13835
|
+
res.rejected.push({ id: cand.id, source: cand.source, reason: `errata:${hit.id}` });
|
|
13836
|
+
ev2("item.rejected", cand.id, { reason: `errata:${hit.id}` });
|
|
13686
13837
|
continue;
|
|
13687
13838
|
}
|
|
13688
13839
|
let id = cand.id;
|
|
@@ -13714,7 +13865,7 @@ ${cand.rationale.trim()}` : "");
|
|
|
13714
13865
|
}
|
|
13715
13866
|
continue;
|
|
13716
13867
|
}
|
|
13717
|
-
if (!target && contradicted.length === 0) {
|
|
13868
|
+
if (!target && contradicted.length === 0 && !isGatedRef(kbRoot, opts.sources ?? [], cand.source)) {
|
|
13718
13869
|
const fm2 = {
|
|
13719
13870
|
id,
|
|
13720
13871
|
domain: cand.domain,
|
|
@@ -13727,9 +13878,9 @@ ${cand.rationale.trim()}` : "");
|
|
|
13727
13878
|
supersedes: [],
|
|
13728
13879
|
conflictsWith: []
|
|
13729
13880
|
};
|
|
13730
|
-
work.set(id, { fm: fm2, body: bodyOf(), file:
|
|
13881
|
+
work.set(id, { fm: fm2, body: bodyOf(), file: path26.join(rulesDir, cand.domain, `${id}.md`), dirty: true, isNew: true });
|
|
13731
13882
|
res.created.push(id);
|
|
13732
|
-
ev2("item.applied", id
|
|
13883
|
+
ev2("item.applied", id);
|
|
13733
13884
|
continue;
|
|
13734
13885
|
}
|
|
13735
13886
|
const fm = {
|
|
@@ -13744,26 +13895,26 @@ ${cand.rationale.trim()}` : "");
|
|
|
13744
13895
|
supersedes: [],
|
|
13745
13896
|
conflictsWith: contradicted
|
|
13746
13897
|
};
|
|
13747
|
-
const dir =
|
|
13748
|
-
const file =
|
|
13898
|
+
const dir = path26.join(rulesDir, PROPOSED_DIR);
|
|
13899
|
+
const file = path26.join(dir, `${id}@${st.sha.slice(0, SHA_LEN)}.md`);
|
|
13749
13900
|
const text = serialize(fm, bodyOf());
|
|
13750
|
-
if (
|
|
13901
|
+
if (fs25.existsSync(file) && fs25.readFileSync(file, "utf8") === text)
|
|
13751
13902
|
continue;
|
|
13752
|
-
|
|
13753
|
-
for (const other of
|
|
13754
|
-
if (!other.startsWith(`${id}@`) || !other.endsWith(".md") ||
|
|
13903
|
+
fs25.mkdirSync(dir, { recursive: true });
|
|
13904
|
+
for (const other of fs25.readdirSync(dir)) {
|
|
13905
|
+
if (!other.startsWith(`${id}@`) || !other.endsWith(".md") || path26.join(dir, other) === file)
|
|
13755
13906
|
continue;
|
|
13756
|
-
const old =
|
|
13907
|
+
const old = matter4(fs25.readFileSync(path26.join(dir, other), "utf8"));
|
|
13757
13908
|
if (!old.data.sources?.some((s) => s.ref === cand.source))
|
|
13758
13909
|
continue;
|
|
13759
|
-
|
|
13760
|
-
|
|
13910
|
+
fs25.writeFileSync(path26.join(dir, other.replace(/\.md$/, ".superseded")), matter4.stringify(old.content, { ...old.data, supersededBy: path26.basename(file) }));
|
|
13911
|
+
fs25.rmSync(path26.join(dir, other));
|
|
13761
13912
|
res.superseded.push(other.replace(/\.md$/, ""));
|
|
13762
|
-
ev2("item.superseded", id
|
|
13913
|
+
ev2("item.superseded", id);
|
|
13763
13914
|
}
|
|
13764
|
-
|
|
13915
|
+
fs25.writeFileSync(file, text);
|
|
13765
13916
|
res.proposed.push(`${id}@${st.sha.slice(0, SHA_LEN)}`);
|
|
13766
|
-
ev2("item.proposed", id
|
|
13917
|
+
ev2("item.proposed", id);
|
|
13767
13918
|
}
|
|
13768
13919
|
for (const [id, w] of work) {
|
|
13769
13920
|
if (touched.has(id) || w.fm.status !== "active" || w.isNew)
|
|
@@ -13789,11 +13940,12 @@ ${cand.rationale.trim()}` : "");
|
|
|
13789
13940
|
for (const w of work.values()) {
|
|
13790
13941
|
if (!w.dirty)
|
|
13791
13942
|
continue;
|
|
13792
|
-
|
|
13943
|
+
fs25.mkdirSync(path26.dirname(w.file), { recursive: true });
|
|
13793
13944
|
const text = serialize(w.fm, w.body);
|
|
13794
|
-
if (!
|
|
13795
|
-
|
|
13945
|
+
if (!fs25.existsSync(w.file) || fs25.readFileSync(w.file, "utf8") !== text)
|
|
13946
|
+
fs25.writeFileSync(w.file, text);
|
|
13796
13947
|
}
|
|
13948
|
+
res.orphanedErrata = orphanedErrata(kbRoot, opts.errata ?? [], totals.keys());
|
|
13797
13949
|
for (const [ref, t] of totals)
|
|
13798
13950
|
if (needsDocling(t.dropped, t.total))
|
|
13799
13951
|
res.doclingFlags.push({ ref, ...t });
|
|
@@ -13810,6 +13962,7 @@ var init_extract = __esm({
|
|
|
13810
13962
|
init_anchor();
|
|
13811
13963
|
init_index_file();
|
|
13812
13964
|
init_ingest();
|
|
13965
|
+
init_errata();
|
|
13813
13966
|
init_paths();
|
|
13814
13967
|
init_store2();
|
|
13815
13968
|
init_verify();
|
|
@@ -13826,20 +13979,20 @@ var init_extract = __esm({
|
|
|
13826
13979
|
});
|
|
13827
13980
|
|
|
13828
13981
|
// packages/core/dist/knowledge/schedule.js
|
|
13829
|
-
import
|
|
13830
|
-
import
|
|
13982
|
+
import fs26 from "fs";
|
|
13983
|
+
import path27 from "path";
|
|
13831
13984
|
function readSchedule(stateRoot) {
|
|
13832
13985
|
try {
|
|
13833
|
-
return JSON.parse(
|
|
13986
|
+
return JSON.parse(fs26.readFileSync(scheduleFile(stateRoot), "utf8"));
|
|
13834
13987
|
} catch {
|
|
13835
13988
|
return {};
|
|
13836
13989
|
}
|
|
13837
13990
|
}
|
|
13838
13991
|
function writeSchedule(stateRoot, s) {
|
|
13839
|
-
|
|
13992
|
+
fs26.mkdirSync(stateRoot, { recursive: true });
|
|
13840
13993
|
const tmp = `${scheduleFile(stateRoot)}.${process.pid}.tmp`;
|
|
13841
|
-
|
|
13842
|
-
|
|
13994
|
+
fs26.writeFileSync(tmp, JSON.stringify(s, null, 2) + "\n");
|
|
13995
|
+
fs26.renameSync(tmp, scheduleFile(stateRoot));
|
|
13843
13996
|
}
|
|
13844
13997
|
function snapshotSources(kbRoot, sources) {
|
|
13845
13998
|
const out = {};
|
|
@@ -13919,7 +14072,7 @@ async function tickKnowledgeSchedule(d) {
|
|
|
13919
14072
|
continue;
|
|
13920
14073
|
try {
|
|
13921
14074
|
const root = kbDir(d.cfg, kb);
|
|
13922
|
-
if (!
|
|
14075
|
+
if (!fs26.existsSync(root))
|
|
13923
14076
|
continue;
|
|
13924
14077
|
const { sources } = loadSources(root);
|
|
13925
14078
|
if (!sources.length)
|
|
@@ -13984,7 +14137,7 @@ var init_schedule = __esm({
|
|
|
13984
14137
|
init_sources();
|
|
13985
14138
|
RUNNING_STALE_MS = 6 * 60 * 60 * 1e3;
|
|
13986
14139
|
DAY_MS = 24 * 60 * 60 * 1e3;
|
|
13987
|
-
scheduleFile = (stateRoot) =>
|
|
14140
|
+
scheduleFile = (stateRoot) => path27.join(stateRoot, "knowledge-schedule.json");
|
|
13988
14141
|
reconcileConfig = (cfg, kb) => ({ ...DEFAULT_RECONCILE, ...kbConfigs(cfg)[kb]?.reconcile });
|
|
13989
14142
|
}
|
|
13990
14143
|
});
|
|
@@ -13992,19 +14145,19 @@ var init_schedule = __esm({
|
|
|
13992
14145
|
// packages/core/dist/knowledge/review.js
|
|
13993
14146
|
import crypto4 from "crypto";
|
|
13994
14147
|
import { execFileSync as execFileSync7 } from "child_process";
|
|
13995
|
-
import
|
|
13996
|
-
import
|
|
13997
|
-
import
|
|
14148
|
+
import fs27 from "fs";
|
|
14149
|
+
import path28 from "path";
|
|
14150
|
+
import matter5 from "gray-matter";
|
|
13998
14151
|
function readEscalations(kbRoot) {
|
|
13999
14152
|
try {
|
|
14000
|
-
return JSON.parse(
|
|
14153
|
+
return JSON.parse(fs27.readFileSync(escalationsFile(kbRoot), "utf8")).items;
|
|
14001
14154
|
} catch {
|
|
14002
14155
|
return [];
|
|
14003
14156
|
}
|
|
14004
14157
|
}
|
|
14005
14158
|
function writeEscalations(kbRoot, items) {
|
|
14006
|
-
|
|
14007
|
-
|
|
14159
|
+
fs27.mkdirSync(kbRoot, { recursive: true });
|
|
14160
|
+
fs27.writeFileSync(escalationsFile(kbRoot), JSON.stringify({ items }, null, 2) + "\n");
|
|
14008
14161
|
}
|
|
14009
14162
|
function addEscalation(kbRoot, e) {
|
|
14010
14163
|
const items = readEscalations(kbRoot);
|
|
@@ -14014,8 +14167,8 @@ function addEscalation(kbRoot, e) {
|
|
|
14014
14167
|
return true;
|
|
14015
14168
|
}
|
|
14016
14169
|
function appendVerdict(kbRoot, v2, now) {
|
|
14017
|
-
|
|
14018
|
-
|
|
14170
|
+
fs27.mkdirSync(kbRoot, { recursive: true });
|
|
14171
|
+
fs27.appendFileSync(verdictsFile(kbRoot), JSON.stringify({ ts: now.toISOString(), ...v2 }) + "\n");
|
|
14019
14172
|
}
|
|
14020
14173
|
function priorityOfRef(c, ref) {
|
|
14021
14174
|
if (ref.startsWith("agent:"))
|
|
@@ -14036,20 +14189,20 @@ function loadProposals(c) {
|
|
|
14036
14189
|
const byId = new Map(live.map((r) => [r.id, r]));
|
|
14037
14190
|
const proposals = [];
|
|
14038
14191
|
const pdirs = /* @__PURE__ */ new Set();
|
|
14039
|
-
for (const f of
|
|
14040
|
-
if (
|
|
14192
|
+
for (const f of fs27.existsSync(dir) ? walkDirs(dir) : [])
|
|
14193
|
+
if (path28.basename(f) === PROPOSED_DIR)
|
|
14041
14194
|
pdirs.add(f);
|
|
14042
14195
|
for (const pd of pdirs) {
|
|
14043
14196
|
for (const rule of loadRulesDir(pd, `kb:${c.kb}`, { includeProposed: true }).rules) {
|
|
14044
|
-
proposals.push({ key:
|
|
14197
|
+
proposals.push({ key: path28.basename(rule.file).replace(/\.md$/, ""), rule, live: byId.get(rule.id) });
|
|
14045
14198
|
}
|
|
14046
14199
|
}
|
|
14047
14200
|
return { proposals, live };
|
|
14048
14201
|
}
|
|
14049
14202
|
function walkDirs(dir, out = []) {
|
|
14050
|
-
for (const e of
|
|
14203
|
+
for (const e of fs27.readdirSync(dir, { withFileTypes: true }))
|
|
14051
14204
|
if (e.isDirectory()) {
|
|
14052
|
-
const f =
|
|
14205
|
+
const f = path28.join(dir, e.name);
|
|
14053
14206
|
out.push(f);
|
|
14054
14207
|
walkDirs(f, out);
|
|
14055
14208
|
}
|
|
@@ -14078,9 +14231,9 @@ function promoteProposal(c, p, by, justification, events) {
|
|
|
14078
14231
|
continue;
|
|
14079
14232
|
const o = readFm(other.file);
|
|
14080
14233
|
o.fm.status = "retired";
|
|
14081
|
-
|
|
14234
|
+
fs27.writeFileSync(other.file, fileText(o.fm, o.body));
|
|
14082
14235
|
retired.push(id);
|
|
14083
|
-
events.push(ev(c, "item.superseded", id
|
|
14236
|
+
events.push(ev(c, "item.superseded", id));
|
|
14084
14237
|
}
|
|
14085
14238
|
const next = { ...fm, status: "active", approvedBy: by, justification, supersedes: [.../* @__PURE__ */ new Set([...fm.supersedes ?? [], ...retired])], conflictsWith: [] };
|
|
14086
14239
|
if (p.live?.decision)
|
|
@@ -14088,17 +14241,17 @@ function promoteProposal(c, p, by, justification, events) {
|
|
|
14088
14241
|
const anchors = anchorsFor(c, { ...next, anchors: p.live?.anchors ?? fm.anchors });
|
|
14089
14242
|
if (anchors)
|
|
14090
14243
|
next.anchors = anchors;
|
|
14091
|
-
const target = p.live?.file ??
|
|
14092
|
-
|
|
14093
|
-
|
|
14094
|
-
|
|
14095
|
-
events.push(ev(c, "item.approved", next.id
|
|
14244
|
+
const target = p.live?.file ?? path28.join(dir, next.domain, `${next.id}.md`);
|
|
14245
|
+
fs27.mkdirSync(path28.dirname(target), { recursive: true });
|
|
14246
|
+
fs27.writeFileSync(target, fileText(next, body));
|
|
14247
|
+
fs27.rmSync(p.rule.file);
|
|
14248
|
+
events.push(ev(c, "item.approved", next.id), ev(c, "item.applied", next.id));
|
|
14096
14249
|
if (p.live)
|
|
14097
|
-
events.push(ev(c, "item.superseded", next.id
|
|
14250
|
+
events.push(ev(c, "item.superseded", next.id));
|
|
14098
14251
|
}
|
|
14099
14252
|
function dropProposal(c, p, events) {
|
|
14100
|
-
|
|
14101
|
-
events.push(ev(c, "item.rejected", p.rule.id,
|
|
14253
|
+
fs27.rmSync(p.rule.file);
|
|
14254
|
+
events.push(ev(c, "item.rejected", p.rule.id, { reason: "reviewer" }));
|
|
14102
14255
|
}
|
|
14103
14256
|
function mergeInto(c, p, targetId, live, events) {
|
|
14104
14257
|
const t = live.find((r) => r.id === targetId);
|
|
@@ -14108,9 +14261,9 @@ function mergeInto(c, p, targetId, live, events) {
|
|
|
14108
14261
|
for (const s of p.rule.sources)
|
|
14109
14262
|
if (!tf.fm.sources.some((x) => x.ref === s.ref))
|
|
14110
14263
|
tf.fm.sources.push(s);
|
|
14111
|
-
|
|
14112
|
-
|
|
14113
|
-
events.push(ev(c, "item.superseded", p.rule.id
|
|
14264
|
+
fs27.writeFileSync(t.file, fileText(tf.fm, tf.body));
|
|
14265
|
+
fs27.rmSync(p.rule.file);
|
|
14266
|
+
events.push(ev(c, "item.superseded", p.rule.id), ev(c, "item.applied", targetId));
|
|
14114
14267
|
return true;
|
|
14115
14268
|
}
|
|
14116
14269
|
function evaluateCodeConflict(c, rule, cc) {
|
|
@@ -14184,14 +14337,15 @@ function applyDecisions(file, c) {
|
|
|
14184
14337
|
f.fm.status = "active";
|
|
14185
14338
|
if (d.loc && f.fm.sources[0])
|
|
14186
14339
|
f.fm.sources[0].loc = d.loc;
|
|
14187
|
-
|
|
14188
|
-
|
|
14340
|
+
const noSource = !rule.sources.length;
|
|
14341
|
+
if (conf >= threshold && !d.flag && !reasons.length && !noSource) {
|
|
14342
|
+
fs27.writeFileSync(rule.file, fileText(f.fm, f.body));
|
|
14189
14343
|
res.applied.push(d.item);
|
|
14190
|
-
events.push(ev(c, "item.applied", rule.id
|
|
14344
|
+
events.push(ev(c, "item.applied", rule.id));
|
|
14191
14345
|
verdict(d, "applied", { confidence: conf });
|
|
14192
14346
|
continue;
|
|
14193
14347
|
}
|
|
14194
|
-
reasons.push(conf < threshold ? "low-confidence" : "reviewer-flagged");
|
|
14348
|
+
reasons.push(noSource ? "no-source" : conf < threshold ? "low-confidence" : "reviewer-flagged");
|
|
14195
14349
|
} else if (d.decision === "approve") {
|
|
14196
14350
|
if (strong(rule.modality))
|
|
14197
14351
|
reasons.push("retiring must/must-not");
|
|
@@ -14202,9 +14356,9 @@ function applyDecisions(file, c) {
|
|
|
14202
14356
|
if (!reasons.length) {
|
|
14203
14357
|
const f = readFm(rule.file);
|
|
14204
14358
|
f.fm.status = "retired";
|
|
14205
|
-
|
|
14359
|
+
fs27.writeFileSync(rule.file, fileText(f.fm, f.body));
|
|
14206
14360
|
res.applied.push(d.item);
|
|
14207
|
-
events.push(ev(c, "item.archived", rule.id
|
|
14361
|
+
events.push(ev(c, "item.archived", rule.id));
|
|
14208
14362
|
verdict(d, "applied", { confidence: conf });
|
|
14209
14363
|
continue;
|
|
14210
14364
|
}
|
|
@@ -14219,6 +14373,8 @@ function applyDecisions(file, c) {
|
|
|
14219
14373
|
reasons.push("reviewer-flagged");
|
|
14220
14374
|
if (conf < threshold)
|
|
14221
14375
|
reasons.push("low-confidence");
|
|
14376
|
+
if (p.rule.sources.some((s) => isGatedRef(kbRoot, c.sources, s.ref)))
|
|
14377
|
+
reasons.push("review-required");
|
|
14222
14378
|
if (d.decision === "approve") {
|
|
14223
14379
|
const myPri = priorityOfRule(c, p.rule);
|
|
14224
14380
|
const conflicted = (p.rule.conflictsWith ?? []).map((id) => live.find((r) => r.id === id)).filter((r) => !!r);
|
|
@@ -14280,7 +14436,7 @@ function applyPair(pd, c, res, threshold, events, kbRoot, now) {
|
|
|
14280
14436
|
for (const [x, y] of [[a, b], [b, a]]) {
|
|
14281
14437
|
const f = readFm(x.file);
|
|
14282
14438
|
f.fm.conflictsWith = [.../* @__PURE__ */ new Set([...f.fm.conflictsWith ?? [], y.id])];
|
|
14283
|
-
|
|
14439
|
+
fs27.writeFileSync(x.file, fileText(f.fm, f.body));
|
|
14284
14440
|
}
|
|
14285
14441
|
return;
|
|
14286
14442
|
}
|
|
@@ -14295,11 +14451,11 @@ function applyPair(pd, c, res, threshold, events, kbRoot, now) {
|
|
|
14295
14451
|
if (!kf.fm.sources.some((x) => x.ref === s.ref))
|
|
14296
14452
|
kf.fm.sources.push(s);
|
|
14297
14453
|
kf.fm.supersedes = [.../* @__PURE__ */ new Set([...kf.fm.supersedes ?? [], drop.id])];
|
|
14298
|
-
|
|
14454
|
+
fs27.writeFileSync(keep.file, fileText(kf.fm, kf.body));
|
|
14299
14455
|
const df = readFm(drop.file);
|
|
14300
14456
|
df.fm.status = "retired";
|
|
14301
|
-
|
|
14302
|
-
events.push(ev(c, "item.superseded", drop.id
|
|
14457
|
+
fs27.writeFileSync(drop.file, fileText(df.fm, df.body));
|
|
14458
|
+
events.push(ev(c, "item.superseded", drop.id), ev(c, "item.applied", keep.id));
|
|
14303
14459
|
res.applied.push(key);
|
|
14304
14460
|
}
|
|
14305
14461
|
function resolveEscalation(c, key, r, by, reason) {
|
|
@@ -14329,9 +14485,9 @@ function resolveEscalation(c, key, r, by, reason) {
|
|
|
14329
14485
|
f.fm.decision = decision;
|
|
14330
14486
|
if (r.verdict === "supersede-with-code") {
|
|
14331
14487
|
f.fm.status = "retired";
|
|
14332
|
-
events.push(ev(c, "item.superseded", rule.id
|
|
14488
|
+
events.push(ev(c, "item.superseded", rule.id));
|
|
14333
14489
|
}
|
|
14334
|
-
|
|
14490
|
+
fs27.writeFileSync(rule.file, fileText(f.fm, f.body));
|
|
14335
14491
|
return done(`${rule.id}: ${r.verdict}`);
|
|
14336
14492
|
}
|
|
14337
14493
|
if (esc.kind === "proposal") {
|
|
@@ -14348,23 +14504,26 @@ function resolveEscalation(c, key, r, by, reason) {
|
|
|
14348
14504
|
}
|
|
14349
14505
|
if (esc.kind === "stale-retire") {
|
|
14350
14506
|
const rule = live.find((x) => x.id === esc.ruleId);
|
|
14507
|
+
if (rule && r.kind !== "approve" && !rule.sources.length) {
|
|
14508
|
+
throw new Error(`Rule ${rule.id} has no source, so it cannot be kept active. Add a source to the rule (or re-extract it), or retire it with --approve.`);
|
|
14509
|
+
}
|
|
14351
14510
|
if (rule) {
|
|
14352
14511
|
const f = readFm(rule.file);
|
|
14353
14512
|
f.fm.status = r.kind === "approve" ? "retired" : "active";
|
|
14354
|
-
|
|
14355
|
-
events.push(ev(c, r.kind === "approve" ? "item.archived" : "item.applied", rule.id
|
|
14513
|
+
fs27.writeFileSync(rule.file, fileText(f.fm, f.body));
|
|
14514
|
+
events.push(ev(c, r.kind === "approve" ? "item.archived" : "item.applied", rule.id));
|
|
14356
14515
|
}
|
|
14357
14516
|
return done(`${esc.ruleId}: ${r.kind === "approve" ? "retired" : "kept"}`);
|
|
14358
14517
|
}
|
|
14359
14518
|
if (esc.kind === "override-base-changed") {
|
|
14360
|
-
const ov = esc.item &&
|
|
14519
|
+
const ov = esc.item && fs27.existsSync(esc.item) ? esc.item : void 0;
|
|
14361
14520
|
if (ov) {
|
|
14362
14521
|
if (r.kind === "reject")
|
|
14363
|
-
|
|
14522
|
+
fs27.rmSync(ov);
|
|
14364
14523
|
else {
|
|
14365
14524
|
const f = readFm(ov);
|
|
14366
14525
|
f.fm.overridesBase = esc.evidence?.docRev;
|
|
14367
|
-
|
|
14526
|
+
fs27.writeFileSync(ov, fileText(f.fm, f.body));
|
|
14368
14527
|
}
|
|
14369
14528
|
}
|
|
14370
14529
|
return done(`${esc.ruleId}: override ${r.kind === "reject" ? "dropped" : "kept"}`);
|
|
@@ -14388,11 +14547,11 @@ ${o.evidence}`).digest("hex");
|
|
|
14388
14547
|
supersedes: [],
|
|
14389
14548
|
conflictsWith: []
|
|
14390
14549
|
};
|
|
14391
|
-
const dir =
|
|
14392
|
-
|
|
14393
|
-
const file =
|
|
14394
|
-
|
|
14395
|
-
appendAudit([ev(c, "item.proposed", id
|
|
14550
|
+
const dir = path28.join(kbRulesDir(c.cfg, c.kb), PROPOSED_DIR);
|
|
14551
|
+
fs27.mkdirSync(dir, { recursive: true });
|
|
14552
|
+
const file = path28.join(dir, `${id}@${sha.slice(0, SHA_LEN2)}.md`);
|
|
14553
|
+
fs27.writeFileSync(file, fileText(fm, o.statement));
|
|
14554
|
+
appendAudit([ev(c, "item.proposed", id)], c.audit);
|
|
14396
14555
|
return file;
|
|
14397
14556
|
}
|
|
14398
14557
|
function buildReviewPacket(c) {
|
|
@@ -14432,8 +14591,8 @@ var init_review = __esm({
|
|
|
14432
14591
|
PRIORITY_RANK = { company: 3, project: 2, agent: 1 };
|
|
14433
14592
|
SHA_LEN2 = 12;
|
|
14434
14593
|
strong = (m) => m === "must" || m === "must-not";
|
|
14435
|
-
escalationsFile = (kbRoot) =>
|
|
14436
|
-
verdictsFile = (kbRoot) =>
|
|
14594
|
+
escalationsFile = (kbRoot) => path28.join(kbRoot, "escalations.json");
|
|
14595
|
+
verdictsFile = (kbRoot) => path28.join(kbRoot, "verdicts.jsonl");
|
|
14437
14596
|
needsYouCount = (kbRoot) => readEscalations(kbRoot).filter((e) => e.needsYou).length;
|
|
14438
14597
|
git = (root, args) => execFileSync7("git", ["-C", root, ...args], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
14439
14598
|
realGit = {
|
|
@@ -14454,34 +14613,34 @@ var init_review = __esm({
|
|
|
14454
14613
|
},
|
|
14455
14614
|
docDate(file) {
|
|
14456
14615
|
try {
|
|
14457
|
-
const d = git(
|
|
14616
|
+
const d = git(path28.dirname(file), ["log", "-1", "--format=%cI", "--", path28.basename(file)]);
|
|
14458
14617
|
if (d)
|
|
14459
14618
|
return d;
|
|
14460
14619
|
} catch {
|
|
14461
14620
|
}
|
|
14462
14621
|
try {
|
|
14463
|
-
return
|
|
14622
|
+
return fs27.statSync(file).mtime.toISOString();
|
|
14464
14623
|
} catch {
|
|
14465
14624
|
return null;
|
|
14466
14625
|
}
|
|
14467
14626
|
}
|
|
14468
14627
|
};
|
|
14469
14628
|
nowOf = (c) => c.now?.() ?? /* @__PURE__ */ new Date();
|
|
14470
|
-
fileText = (fm, body) =>
|
|
14629
|
+
fileText = (fm, body) => matter5.stringify(body.trim() + "\n", JSON.parse(JSON.stringify(fm)));
|
|
14471
14630
|
readFm = (file) => {
|
|
14472
|
-
const m =
|
|
14631
|
+
const m = matter5(fs27.readFileSync(file, "utf8"));
|
|
14473
14632
|
return { fm: m.data, body: m.content };
|
|
14474
14633
|
};
|
|
14475
|
-
ev = (c, event, itemId,
|
|
14634
|
+
ev = (c, event, itemId, extra = {}) => ({ kb: c.kb, level: "group", project: "", domain: "rules", itemId, event, ...extra });
|
|
14476
14635
|
docRevOf = (r) => r.sources.map((s) => `${s.ref}@${s.sha.slice(0, SHA_LEN2)}`).join(",");
|
|
14477
14636
|
}
|
|
14478
14637
|
});
|
|
14479
14638
|
|
|
14480
14639
|
// packages/core/dist/knowledge/fullpass.js
|
|
14481
14640
|
import crypto5 from "crypto";
|
|
14482
|
-
import
|
|
14483
|
-
import
|
|
14484
|
-
import
|
|
14641
|
+
import fs28 from "fs";
|
|
14642
|
+
import path29 from "path";
|
|
14643
|
+
import matter6 from "gray-matter";
|
|
14485
14644
|
function dedupPairs(rules) {
|
|
14486
14645
|
const active = rules.filter((r) => r.status === "active").sort((x, y) => x.id.localeCompare(y.id));
|
|
14487
14646
|
const out = [];
|
|
@@ -14497,12 +14656,12 @@ function dedupPairs(rules) {
|
|
|
14497
14656
|
return out.slice(0, MAX_DEDUP_PAIRS);
|
|
14498
14657
|
}
|
|
14499
14658
|
function readAuditRecords(kb, since, dir = defaultAuditDir()) {
|
|
14500
|
-
if (!
|
|
14659
|
+
if (!fs28.existsSync(dir))
|
|
14501
14660
|
return [];
|
|
14502
14661
|
const sinceMonth = since.toISOString().slice(0, 7);
|
|
14503
14662
|
const out = [];
|
|
14504
|
-
for (const f of
|
|
14505
|
-
for (const line2 of
|
|
14663
|
+
for (const f of fs28.readdirSync(dir).filter((n) => n.endsWith(".jsonl") && n.slice(0, 7) >= sinceMonth).sort()) {
|
|
14664
|
+
for (const line2 of fs28.readFileSync(path29.join(dir, f), "utf8").split("\n")) {
|
|
14506
14665
|
if (!line2.trim())
|
|
14507
14666
|
continue;
|
|
14508
14667
|
try {
|
|
@@ -14565,8 +14724,8 @@ function checkOverrides(cfg, kb) {
|
|
|
14565
14724
|
continue;
|
|
14566
14725
|
const h = baseHash(b);
|
|
14567
14726
|
if (!o.overridesBase) {
|
|
14568
|
-
const m =
|
|
14569
|
-
|
|
14727
|
+
const m = matter6(fs28.readFileSync(o.file, "utf8"));
|
|
14728
|
+
fs28.writeFileSync(o.file, matter6.stringify(m.content, { ...m.data, overridesBase: h }));
|
|
14570
14729
|
continue;
|
|
14571
14730
|
}
|
|
14572
14731
|
out.push({ project, ruleId: o.id, file: o.file, baseHash: h, changed: o.overridesBase !== h });
|
|
@@ -14609,8 +14768,8 @@ var init_fullpass = __esm({
|
|
|
14609
14768
|
});
|
|
14610
14769
|
|
|
14611
14770
|
// packages/core/dist/knowledge/scores.js
|
|
14612
|
-
import
|
|
14613
|
-
import
|
|
14771
|
+
import fs29 from "fs";
|
|
14772
|
+
import path30 from "path";
|
|
14614
14773
|
function tally(records, into = emptyTally()) {
|
|
14615
14774
|
for (const e of records) {
|
|
14616
14775
|
const domain = typeof e.domain === "string" && e.domain ? e.domain : "rules";
|
|
@@ -14619,7 +14778,7 @@ function tally(records, into = emptyTally()) {
|
|
|
14619
14778
|
d.writes++;
|
|
14620
14779
|
if (READ_EVENTS.has(e.event ?? ""))
|
|
14621
14780
|
d.reads++;
|
|
14622
|
-
if (!e.itemId)
|
|
14781
|
+
if (!e.itemId || WRITE_EVENTS.has(e.event ?? ""))
|
|
14623
14782
|
continue;
|
|
14624
14783
|
const c = into.items[`${domain}|${e.itemId}`] ??= { ...zero(), domain, itemId: e.itemId };
|
|
14625
14784
|
switch (e.event) {
|
|
@@ -14656,7 +14815,7 @@ function tally(records, into = emptyTally()) {
|
|
|
14656
14815
|
}
|
|
14657
14816
|
function parseLines(file) {
|
|
14658
14817
|
const out = [];
|
|
14659
|
-
for (const line2 of
|
|
14818
|
+
for (const line2 of fs29.readFileSync(file, "utf8").split("\n")) {
|
|
14660
14819
|
if (!line2.trim())
|
|
14661
14820
|
continue;
|
|
14662
14821
|
try {
|
|
@@ -14668,37 +14827,37 @@ function parseLines(file) {
|
|
|
14668
14827
|
}
|
|
14669
14828
|
function compactAudit(o) {
|
|
14670
14829
|
const dir = o.dir ?? defaultAuditDir();
|
|
14671
|
-
if (!
|
|
14830
|
+
if (!fs29.existsSync(dir))
|
|
14672
14831
|
return [];
|
|
14673
14832
|
const cutoffMonth = new Date(o.now.getTime() - SCORE_WINDOW_DAYS * DAY_MS3).toISOString().slice(0, 7);
|
|
14674
14833
|
const done = [];
|
|
14675
|
-
for (const f of
|
|
14834
|
+
for (const f of fs29.readdirSync(dir).sort()) {
|
|
14676
14835
|
const m = MONTH_FILE_RE.exec(f);
|
|
14677
14836
|
if (!m || m[1] >= cutoffMonth)
|
|
14678
14837
|
continue;
|
|
14679
14838
|
const [, month, machine] = m;
|
|
14680
14839
|
const byKb = /* @__PURE__ */ new Map();
|
|
14681
|
-
for (const r of parseLines(
|
|
14840
|
+
for (const r of parseLines(path30.join(dir, f)))
|
|
14682
14841
|
byKb.set(r.kb ?? "", [...byKb.get(r.kb ?? "") ?? [], r]);
|
|
14683
|
-
const statsPath =
|
|
14684
|
-
const prior =
|
|
14842
|
+
const statsPath = path30.join(dir, statsFileName(month, machine));
|
|
14843
|
+
const prior = fs29.existsSync(statsPath) ? JSON.parse(fs29.readFileSync(statsPath, "utf8")) : null;
|
|
14685
14844
|
const kbs = prior?.kbs ?? {};
|
|
14686
14845
|
for (const [kb, recs] of byKb)
|
|
14687
14846
|
kbs[kb] = tally(recs, kbs[kb]);
|
|
14688
|
-
|
|
14689
|
-
|
|
14690
|
-
|
|
14847
|
+
fs29.writeFileSync(`${statsPath}.tmp`, JSON.stringify({ month, machine, kbs }));
|
|
14848
|
+
fs29.renameSync(`${statsPath}.tmp`, statsPath);
|
|
14849
|
+
fs29.unlinkSync(path30.join(dir, f));
|
|
14691
14850
|
done.push(month);
|
|
14692
14851
|
}
|
|
14693
14852
|
return done;
|
|
14694
14853
|
}
|
|
14695
14854
|
function readCompacted(kb, dir) {
|
|
14696
14855
|
const t = emptyTally();
|
|
14697
|
-
if (!
|
|
14856
|
+
if (!fs29.existsSync(dir))
|
|
14698
14857
|
return t;
|
|
14699
|
-
for (const f of
|
|
14858
|
+
for (const f of fs29.readdirSync(dir).filter((n) => n.endsWith(".stats.json"))) {
|
|
14700
14859
|
try {
|
|
14701
|
-
const k = JSON.parse(
|
|
14860
|
+
const k = JSON.parse(fs29.readFileSync(path30.join(dir, f), "utf8")).kbs[kb];
|
|
14702
14861
|
if (k)
|
|
14703
14862
|
mergeTally(t, k);
|
|
14704
14863
|
} catch {
|
|
@@ -14748,7 +14907,7 @@ function computeScores(i) {
|
|
|
14748
14907
|
noise: w.noise,
|
|
14749
14908
|
wrong: w.wrong,
|
|
14750
14909
|
fireRate: w.surfaced,
|
|
14751
|
-
pullRate: w.shown,
|
|
14910
|
+
pullRate: w.shown + w.searched,
|
|
14752
14911
|
useRate: ratio(w.cited, w.surfaced),
|
|
14753
14912
|
noiseRate: ratio(w.noise, w.surfaced),
|
|
14754
14913
|
violationRate: ratio(w.violated, w.surfaced),
|
|
@@ -14790,21 +14949,21 @@ function computeScores(i) {
|
|
|
14790
14949
|
function scoreKb(o) {
|
|
14791
14950
|
const dir = o.auditDir ?? defaultAuditDir();
|
|
14792
14951
|
const records = [];
|
|
14793
|
-
if (
|
|
14794
|
-
for (const f of
|
|
14795
|
-
records.push(...parseLines(
|
|
14952
|
+
if (fs29.existsSync(dir)) {
|
|
14953
|
+
for (const f of fs29.readdirSync(dir).filter((n) => MONTH_FILE_RE.test(n)).sort()) {
|
|
14954
|
+
records.push(...parseLines(path30.join(dir, f)).filter((r) => r.kb === o.kb));
|
|
14796
14955
|
}
|
|
14797
14956
|
}
|
|
14798
14957
|
let verdicts = [];
|
|
14799
14958
|
try {
|
|
14800
|
-
verdicts =
|
|
14959
|
+
verdicts = fs29.readFileSync(path30.join(o.kbRoot, "verdicts.jsonl"), "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l));
|
|
14801
14960
|
} catch {
|
|
14802
14961
|
}
|
|
14803
14962
|
return computeScores({ kb: o.kb, records, now: o.now, known: o.known, compacted: readCompacted(o.kb, dir), verdicts });
|
|
14804
14963
|
}
|
|
14805
14964
|
function writeScores(kbRoot, s) {
|
|
14806
|
-
|
|
14807
|
-
|
|
14965
|
+
fs29.mkdirSync(kbRoot, { recursive: true });
|
|
14966
|
+
fs29.writeFileSync(scoresFile(kbRoot), JSON.stringify(s, null, 2) + "\n");
|
|
14808
14967
|
}
|
|
14809
14968
|
function renderScoresSection(s) {
|
|
14810
14969
|
const pct = (x) => x === null ? "n/a" : `${Math.round(x * 100)}%`;
|
|
@@ -14817,7 +14976,7 @@ function renderScoresSection(s) {
|
|
|
14817
14976
|
...used.length ? [
|
|
14818
14977
|
"| Item | Surfaced | Pulled | Cited | Use | Noise | Violated |",
|
|
14819
14978
|
"|---|---|---|---|---|---|---|",
|
|
14820
|
-
...used.map((x) => `| ${x.itemId} | ${x.surfaced} | ${x.
|
|
14979
|
+
...used.map((x) => `| ${x.itemId} | ${x.surfaced} | ${x.pullRate} | ${x.cited} | ${pct(x.useRate)} | ${pct(x.noiseRate)} | ${pct(x.violationRate)} |`)
|
|
14821
14980
|
] : ["No items surfaced."],
|
|
14822
14981
|
"",
|
|
14823
14982
|
`- Never fired (${never.length}): ${never.slice(0, 20).join(", ") || "none"}${never.length > 20 ? ", \u2026" : ""}`,
|
|
@@ -14845,13 +15004,13 @@ var init_scores = __esm({
|
|
|
14845
15004
|
MONTH_FILE_RE = /^(\d{4}-\d{2})\.(.+)\.jsonl$/;
|
|
14846
15005
|
statsFileName = (month, machine) => `${month}.${machine}.stats.json`;
|
|
14847
15006
|
ratio = (n, d) => d ? Math.round(n / d * 1e3) / 1e3 : null;
|
|
14848
|
-
scoresFile = (kbRoot) =>
|
|
15007
|
+
scoresFile = (kbRoot) => path30.join(kbRoot, "scores.json");
|
|
14849
15008
|
}
|
|
14850
15009
|
});
|
|
14851
15010
|
|
|
14852
15011
|
// packages/core/dist/knowledge/report.js
|
|
14853
|
-
import
|
|
14854
|
-
import
|
|
15012
|
+
import fs30 from "fs";
|
|
15013
|
+
import path31 from "path";
|
|
14855
15014
|
function renderReport(cfg, kb, o) {
|
|
14856
15015
|
const { rules } = loadKbRules(cfg, kb, { includeProposed: true });
|
|
14857
15016
|
const count = (s) => rules.filter((r) => r.status === s).length;
|
|
@@ -14873,6 +15032,11 @@ function renderReport(cfg, kb, o) {
|
|
|
14873
15032
|
const info = esc.filter((e) => !e.needsYou);
|
|
14874
15033
|
if (info.length)
|
|
14875
15034
|
L.push("", `## For information (${info.length})`, "", ...info.map((e) => `- **${e.key}**: ${e.explanation}`));
|
|
15035
|
+
const { errata, errors: errataErrors } = loadErrata(kbDir(cfg, kb));
|
|
15036
|
+
const orphans = orphanedErrata(kbDir(cfg, kb), errata);
|
|
15037
|
+
if (orphans.length || errataErrors.length) {
|
|
15038
|
+
L.push("", `## Errata to re-check (${orphans.length + errataErrors.length})`, "", ...orphans.map((e) => `- **${e.id}** (${e.ref}): quote no longer found in the source; the raw file changed. Re-check it in errata.yaml.`), ...errataErrors.map((e) => `- errata.yaml: ${e}`));
|
|
15039
|
+
}
|
|
14876
15040
|
if (o.full) {
|
|
14877
15041
|
const { usage: usage2, caps } = o.full;
|
|
14878
15042
|
L.push("", "## Usage (30 days)", "", `- Surfaced: ${Object.values(usage2.surfaced).reduce((a, b) => a + b, 0)} times across ${Object.keys(usage2.surfaced).length} rules.`, `- Never surfaced (re-check triggers): ${usage2.neverSurfaced.join(", ") || "none"}`, `- Noisy (narrow triggers): ${usage2.noisy.join(", ") || "none"}`, `- Violation feedback (reword): ${usage2.violated.join(", ") || "none"}`, `- Domains over cap: ${caps.map((c) => `${c.domain} (${c.count}/${c.cap})`).join(", ") || "none"}`);
|
|
@@ -14882,12 +15046,13 @@ function renderReport(cfg, kb, o) {
|
|
|
14882
15046
|
return L.join("\n") + "\n";
|
|
14883
15047
|
}
|
|
14884
15048
|
function writeReport(cfg, kb, o) {
|
|
14885
|
-
const file =
|
|
14886
|
-
|
|
15049
|
+
const file = path31.join(kbDir(cfg, kb), "REPORT.md");
|
|
15050
|
+
fs30.writeFileSync(file, renderReport(cfg, kb, o));
|
|
14887
15051
|
return file;
|
|
14888
15052
|
}
|
|
14889
15053
|
var init_report = __esm({
|
|
14890
15054
|
"packages/core/dist/knowledge/report.js"() {
|
|
15055
|
+
init_errata();
|
|
14891
15056
|
init_layers();
|
|
14892
15057
|
init_paths();
|
|
14893
15058
|
init_review();
|
|
@@ -14931,44 +15096,63 @@ var init_reconcile = __esm({
|
|
|
14931
15096
|
|
|
14932
15097
|
// packages/core/dist/knowledge/cite.js
|
|
14933
15098
|
function scanAndLogCitations(i) {
|
|
14934
|
-
|
|
14935
|
-
|
|
14936
|
-
|
|
14937
|
-
|
|
14938
|
-
|
|
14939
|
-
|
|
14940
|
-
|
|
14941
|
-
|
|
14942
|
-
|
|
14943
|
-
|
|
14944
|
-
|
|
14945
|
-
|
|
14946
|
-
|
|
14947
|
-
|
|
14948
|
-
delivered
|
|
14949
|
-
|
|
14950
|
-
|
|
14951
|
-
|
|
14952
|
-
|
|
14953
|
-
|
|
14954
|
-
|
|
14955
|
-
|
|
14956
|
-
|
|
14957
|
-
|
|
14958
|
-
|
|
14959
|
-
|
|
14960
|
-
|
|
14961
|
-
|
|
14962
|
-
|
|
15099
|
+
return scanCitations([i], i);
|
|
15100
|
+
}
|
|
15101
|
+
function scanCitations(texts, o) {
|
|
15102
|
+
if (!texts.length)
|
|
15103
|
+
return [];
|
|
15104
|
+
const now = o.sink?.now?.() ?? /* @__PURE__ */ new Date();
|
|
15105
|
+
const lookbackMs = (o.lookbackDays ?? CITE_LOOKBACK_DAYS) * DAY_MS4;
|
|
15106
|
+
const ats = texts.map((t) => (t.at ?? now).getTime());
|
|
15107
|
+
const records = readAuditRecords(void 0, new Date(Math.min(...ats) - lookbackMs), o.sink?.dir ?? defaultAuditDir()).filter((r) => r.itemId && r.project === o.project);
|
|
15108
|
+
const already = new Set(records.filter((r) => r.event === "item.cited").map((r) => `${r.ref}|${r.itemId}`));
|
|
15109
|
+
const deliveries = records.filter((r) => (r.event === "item.surfaced" || r.event === "item.shown" || r.event === "item.searched") && !(o.session && r.session && r.session !== o.session));
|
|
15110
|
+
const events = [];
|
|
15111
|
+
texts.forEach((t, n) => {
|
|
15112
|
+
const at = ats[n];
|
|
15113
|
+
const delivered = /* @__PURE__ */ new Map();
|
|
15114
|
+
for (const r of deliveries) {
|
|
15115
|
+
const ts = Date.parse(r.ts);
|
|
15116
|
+
if (ts <= at && ts >= at - lookbackMs)
|
|
15117
|
+
delivered.set(r.itemId, r);
|
|
15118
|
+
}
|
|
15119
|
+
for (const [itemId, r] of delivered) {
|
|
15120
|
+
if (already.has(`${t.ref}|${itemId}`) || !mentionsId(t.text, itemId))
|
|
15121
|
+
continue;
|
|
15122
|
+
already.add(`${t.ref}|${itemId}`);
|
|
15123
|
+
events.push({
|
|
15124
|
+
kb: String(r.kb ?? ""),
|
|
15125
|
+
level: String(r.level ?? "project"),
|
|
15126
|
+
project: o.project,
|
|
15127
|
+
domain: String(r.domain ?? "rules"),
|
|
15128
|
+
itemId,
|
|
15129
|
+
event: "item.cited",
|
|
15130
|
+
ref: t.ref,
|
|
15131
|
+
...o.agent ? { agent: o.agent } : {},
|
|
15132
|
+
...o.session ? { session: o.session } : {}
|
|
15133
|
+
});
|
|
15134
|
+
}
|
|
15135
|
+
});
|
|
15136
|
+
appendAudit(events, o.sink);
|
|
15137
|
+
return events.map((e) => e.itemId);
|
|
14963
15138
|
}
|
|
14964
15139
|
function readGitMessages(repo, since, run) {
|
|
14965
|
-
|
|
15140
|
+
return parseLog(run(["-C", repo, "log", "--all", `--since=${since.toISOString()}`, LOG_FORMAT]));
|
|
15141
|
+
}
|
|
15142
|
+
function readBranchOnlyMessages(repo, run, max = 200) {
|
|
15143
|
+
const branch = run(["-C", repo, "rev-parse", "--abbrev-ref", "HEAD"]).trim();
|
|
15144
|
+
if (!branch)
|
|
15145
|
+
return [];
|
|
15146
|
+
const own = branch === "HEAD" ? [] : [`--exclude=${branch}`];
|
|
15147
|
+
return parseLog(run(["-C", repo, "log", `--max-count=${max}`, "HEAD", "--not", ...own, "--branches", ...own.length ? [`--exclude=*/${branch}`] : [], "--remotes", LOG_FORMAT]));
|
|
15148
|
+
}
|
|
15149
|
+
function parseLog(out) {
|
|
14966
15150
|
return out.split("").filter((c) => c.trim()).map((c) => {
|
|
14967
15151
|
const [sha, at, ...rest] = c.split("");
|
|
14968
15152
|
return { sha: sha.trim(), at: new Date(at), text: rest.join("") };
|
|
14969
15153
|
});
|
|
14970
15154
|
}
|
|
14971
|
-
var DAY_MS4, CITE_LOOKBACK_DAYS, escapeRe2, mentionsId;
|
|
15155
|
+
var DAY_MS4, CITE_LOOKBACK_DAYS, escapeRe2, mentionsId, LOG_FORMAT;
|
|
14972
15156
|
var init_cite = __esm({
|
|
14973
15157
|
"packages/core/dist/knowledge/cite.js"() {
|
|
14974
15158
|
init_audit();
|
|
@@ -14977,6 +15161,7 @@ var init_cite = __esm({
|
|
|
14977
15161
|
CITE_LOOKBACK_DAYS = 7;
|
|
14978
15162
|
escapeRe2 = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
14979
15163
|
mentionsId = (text, id) => new RegExp(`(?<![\\w.-])${escapeRe2(id)}(?![\\w-])`).test(text);
|
|
15164
|
+
LOG_FORMAT = "--format=%x1e%H%x1f%cI%x1f%B";
|
|
14980
15165
|
}
|
|
14981
15166
|
});
|
|
14982
15167
|
|
|
@@ -14994,6 +15179,7 @@ var init_knowledge2 = __esm({
|
|
|
14994
15179
|
init_migrate();
|
|
14995
15180
|
init_verify();
|
|
14996
15181
|
init_ingest();
|
|
15182
|
+
init_errata();
|
|
14997
15183
|
init_anchor();
|
|
14998
15184
|
init_extract();
|
|
14999
15185
|
init_match();
|
|
@@ -15244,6 +15430,7 @@ __export(dist_exports, {
|
|
|
15244
15430
|
isDaemonSocketLive: () => isDaemonSocketLive,
|
|
15245
15431
|
isGateCacheEnabled: () => isGateCacheEnabled,
|
|
15246
15432
|
isGateSession: () => isGateSession,
|
|
15433
|
+
isGatedRef: () => isGatedRef,
|
|
15247
15434
|
isNotifyActive: () => isNotifyActive,
|
|
15248
15435
|
isOperatorInitiatedCommand: () => isOperatorInitiatedCommand,
|
|
15249
15436
|
isPendingProposalDup: () => isPendingProposalDup,
|
|
@@ -15261,6 +15448,7 @@ __export(dist_exports, {
|
|
|
15261
15448
|
launchOneWorkspace: () => launchOneWorkspace,
|
|
15262
15449
|
legacyKbDir: () => legacyKbDir,
|
|
15263
15450
|
listSessions: () => listSessions,
|
|
15451
|
+
loadErrata: () => loadErrata,
|
|
15264
15452
|
loadKbRules: () => loadKbRules,
|
|
15265
15453
|
loadPending: () => loadPending,
|
|
15266
15454
|
loadProposals: () => loadProposals,
|
|
@@ -15295,6 +15483,7 @@ __export(dist_exports, {
|
|
|
15295
15483
|
normalizedViews: () => normalizedViews,
|
|
15296
15484
|
notePaneScreen: () => notePaneScreen,
|
|
15297
15485
|
notifyToggle: () => notifyToggle,
|
|
15486
|
+
orphanedErrata: () => orphanedErrata,
|
|
15298
15487
|
parseBearer: () => parseBearer,
|
|
15299
15488
|
parseClassifierVerdict: () => parseClassifierVerdict,
|
|
15300
15489
|
parseCommand: () => parseCommand,
|
|
@@ -15319,6 +15508,7 @@ __export(dist_exports, {
|
|
|
15319
15508
|
pruneTopics: () => pruneTopics,
|
|
15320
15509
|
purgeExpiredWorkItems: () => purgeExpiredWorkItems,
|
|
15321
15510
|
readAuditRecords: () => readAuditRecords,
|
|
15511
|
+
readBranchOnlyMessages: () => readBranchOnlyMessages,
|
|
15322
15512
|
readCaptainAddress: () => readCaptainAddress,
|
|
15323
15513
|
readCursor: () => readCursor,
|
|
15324
15514
|
readEscalations: () => readEscalations,
|
|
@@ -15345,6 +15535,7 @@ __export(dist_exports, {
|
|
|
15345
15535
|
refFor: () => refFor,
|
|
15346
15536
|
releaseDaemonLock: () => releaseDaemonLock,
|
|
15347
15537
|
removeRunningMarker: () => removeRunningMarker,
|
|
15538
|
+
removeSource: () => removeSource,
|
|
15348
15539
|
renderEnvAssignments: () => renderEnvAssignments,
|
|
15349
15540
|
renderPlist: () => renderPlist,
|
|
15350
15541
|
renderReport: () => renderReport,
|
|
@@ -15407,6 +15598,7 @@ __export(dist_exports, {
|
|
|
15407
15598
|
saveSessions: () => saveSessions,
|
|
15408
15599
|
saveState: () => saveState,
|
|
15409
15600
|
scanAndLogCitations: () => scanAndLogCitations,
|
|
15601
|
+
scanCitations: () => scanCitations,
|
|
15410
15602
|
scheduleFile: () => scheduleFile,
|
|
15411
15603
|
scoreKb: () => scoreKb,
|
|
15412
15604
|
scoresFile: () => scoresFile,
|
|
@@ -15427,6 +15619,7 @@ __export(dist_exports, {
|
|
|
15427
15619
|
sideNextAutoName: () => sideNextAutoName,
|
|
15428
15620
|
sideTitleFor: () => sideTitleFor,
|
|
15429
15621
|
snapshotSources: () => snapshotSources,
|
|
15622
|
+
sourceCovers: () => sourceCovers,
|
|
15430
15623
|
spansOverlap: () => spansOverlap,
|
|
15431
15624
|
splitSections: () => splitSections,
|
|
15432
15625
|
splitStatement: () => splitStatement,
|
|
@@ -15561,7 +15754,7 @@ import { readdirSync as readdirSync4, readFileSync as readFileSync12 } from "fs"
|
|
|
15561
15754
|
import { join as join18 } from "path";
|
|
15562
15755
|
|
|
15563
15756
|
// packages/agents/dist/claude/registry.js
|
|
15564
|
-
import
|
|
15757
|
+
import fs31 from "fs";
|
|
15565
15758
|
import { join as join17 } from "path";
|
|
15566
15759
|
import { homedir as homedir7 } from "os";
|
|
15567
15760
|
var CLAUDE_SESSIONS_DIR = join17(homedir7(), ".claude", "sessions");
|
|
@@ -15606,11 +15799,11 @@ function toLifecycleSnapshot(entry, taskId, alive, now) {
|
|
|
15606
15799
|
function readClaudeStatusBySocketPath(socketPath) {
|
|
15607
15800
|
let files;
|
|
15608
15801
|
try {
|
|
15609
|
-
files =
|
|
15802
|
+
files = fs31.readdirSync(CLAUDE_SESSIONS_DIR);
|
|
15610
15803
|
} catch {
|
|
15611
15804
|
return void 0;
|
|
15612
15805
|
}
|
|
15613
|
-
const entries = parseRegistryDir(files, (name) =>
|
|
15806
|
+
const entries = parseRegistryDir(files, (name) => fs31.readFileSync(join17(CLAUDE_SESSIONS_DIR, name), "utf8"));
|
|
15614
15807
|
const entry = entries.find((e) => e.messagingSocketPath === socketPath);
|
|
15615
15808
|
if (!entry)
|
|
15616
15809
|
return void 0;
|
|
@@ -15633,38 +15826,38 @@ import { homedir as homedir8 } from "os";
|
|
|
15633
15826
|
var SQUADRANT_STATE_DIR = join19(homedir8(), ".config", "squadrant", "state");
|
|
15634
15827
|
|
|
15635
15828
|
// packages/agents/dist/drivers/launch-cmd.js
|
|
15636
|
-
import
|
|
15637
|
-
import
|
|
15829
|
+
import fs32 from "fs";
|
|
15830
|
+
import path32 from "path";
|
|
15638
15831
|
|
|
15639
15832
|
// packages/agents/dist/projection/cursor.js
|
|
15640
15833
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
15641
|
-
import
|
|
15834
|
+
import path33 from "path";
|
|
15642
15835
|
import os10 from "os";
|
|
15643
15836
|
|
|
15644
15837
|
// packages/agents/dist/projection/codex.js
|
|
15645
15838
|
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
15646
|
-
import
|
|
15839
|
+
import path34 from "path";
|
|
15647
15840
|
import os11 from "os";
|
|
15648
15841
|
|
|
15649
15842
|
// packages/agents/dist/projection/gemini.js
|
|
15650
15843
|
import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
15651
|
-
import
|
|
15844
|
+
import path35 from "path";
|
|
15652
15845
|
import os12 from "os";
|
|
15653
15846
|
|
|
15654
15847
|
// packages/agents/dist/projection/opencode.js
|
|
15655
15848
|
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
15656
|
-
import
|
|
15849
|
+
import path36 from "path";
|
|
15657
15850
|
import os13 from "os";
|
|
15658
15851
|
|
|
15659
15852
|
// packages/agents/dist/projection/opencode-skills.js
|
|
15660
|
-
import
|
|
15853
|
+
import fs33 from "fs";
|
|
15661
15854
|
import os14 from "os";
|
|
15662
|
-
import
|
|
15855
|
+
import path37 from "path";
|
|
15663
15856
|
var OPENCODE_SKILL_MARKER = ".squadrant-managed";
|
|
15664
15857
|
var MARKER_BODY = "squadrant\n";
|
|
15665
15858
|
function defaultOpencodeSkillsRoot(env = process.env) {
|
|
15666
|
-
const configHome = env.XDG_CONFIG_HOME ||
|
|
15667
|
-
return
|
|
15859
|
+
const configHome = env.XDG_CONFIG_HOME || path37.join(os14.homedir(), ".config");
|
|
15860
|
+
return path37.join(configHome, "opencode", "skills");
|
|
15668
15861
|
}
|
|
15669
15862
|
var SAFE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
15670
15863
|
function parseSkillName(raw) {
|
|
@@ -15679,62 +15872,62 @@ function parseSkillName(raw) {
|
|
|
15679
15872
|
}
|
|
15680
15873
|
function listSourceSkills(sourceSkillsDir) {
|
|
15681
15874
|
const out = /* @__PURE__ */ new Map();
|
|
15682
|
-
if (!
|
|
15875
|
+
if (!fs33.existsSync(sourceSkillsDir))
|
|
15683
15876
|
return out;
|
|
15684
|
-
for (const entry of
|
|
15877
|
+
for (const entry of fs33.readdirSync(sourceSkillsDir, { withFileTypes: true })) {
|
|
15685
15878
|
if (!entry.isDirectory())
|
|
15686
15879
|
continue;
|
|
15687
|
-
const skillPath =
|
|
15688
|
-
if (!
|
|
15880
|
+
const skillPath = path37.join(sourceSkillsDir, entry.name, "SKILL.md");
|
|
15881
|
+
if (!fs33.existsSync(skillPath))
|
|
15689
15882
|
continue;
|
|
15690
|
-
const name = parseSkillName(
|
|
15883
|
+
const name = parseSkillName(fs33.readFileSync(skillPath, "utf-8"));
|
|
15691
15884
|
if (name && SAFE_NAME.test(name))
|
|
15692
15885
|
out.set(name, skillPath);
|
|
15693
15886
|
}
|
|
15694
15887
|
return out;
|
|
15695
15888
|
}
|
|
15696
15889
|
function hasMarker(dir) {
|
|
15697
|
-
return
|
|
15890
|
+
return fs33.existsSync(path37.join(dir, OPENCODE_SKILL_MARKER));
|
|
15698
15891
|
}
|
|
15699
15892
|
function syncOpencodeSkills(opts) {
|
|
15700
15893
|
const result = { written: [], unchanged: [], removed: [], skipped: [] };
|
|
15701
15894
|
const wanted = listSourceSkills(opts.sourceSkillsDir);
|
|
15702
|
-
if (wanted.size === 0 && !
|
|
15895
|
+
if (wanted.size === 0 && !fs33.existsSync(opts.sourceSkillsDir))
|
|
15703
15896
|
return result;
|
|
15704
15897
|
if (!opts.dryRun)
|
|
15705
|
-
|
|
15898
|
+
fs33.mkdirSync(opts.skillsRoot, { recursive: true });
|
|
15706
15899
|
for (const [name, srcPath] of wanted) {
|
|
15707
|
-
const targetDir =
|
|
15708
|
-
const targetSkill =
|
|
15900
|
+
const targetDir = path37.join(opts.skillsRoot, name);
|
|
15901
|
+
const targetSkill = path37.join(targetDir, "SKILL.md");
|
|
15709
15902
|
const managed = hasMarker(targetDir);
|
|
15710
|
-
if (
|
|
15903
|
+
if (fs33.existsSync(targetSkill) && !managed) {
|
|
15711
15904
|
result.skipped.push({ name, reason: "foreign-collision" });
|
|
15712
15905
|
continue;
|
|
15713
15906
|
}
|
|
15714
|
-
const current =
|
|
15715
|
-
if (current && current.equals(
|
|
15907
|
+
const current = fs33.existsSync(targetSkill) ? fs33.readFileSync(targetSkill) : null;
|
|
15908
|
+
if (current && current.equals(fs33.readFileSync(srcPath))) {
|
|
15716
15909
|
if (!managed && !opts.dryRun) {
|
|
15717
|
-
|
|
15910
|
+
fs33.writeFileSync(path37.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
|
|
15718
15911
|
}
|
|
15719
15912
|
result.unchanged.push(name);
|
|
15720
15913
|
continue;
|
|
15721
15914
|
}
|
|
15722
15915
|
if (!opts.dryRun) {
|
|
15723
|
-
|
|
15724
|
-
|
|
15725
|
-
|
|
15916
|
+
fs33.mkdirSync(targetDir, { recursive: true });
|
|
15917
|
+
fs33.copyFileSync(srcPath, targetSkill);
|
|
15918
|
+
fs33.writeFileSync(path37.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
|
|
15726
15919
|
}
|
|
15727
15920
|
result.written.push(name);
|
|
15728
15921
|
}
|
|
15729
|
-
if (
|
|
15730
|
-
for (const entry of
|
|
15922
|
+
if (fs33.existsSync(opts.skillsRoot)) {
|
|
15923
|
+
for (const entry of fs33.readdirSync(opts.skillsRoot, { withFileTypes: true })) {
|
|
15731
15924
|
if (!entry.isDirectory() || wanted.has(entry.name))
|
|
15732
15925
|
continue;
|
|
15733
|
-
const dir =
|
|
15926
|
+
const dir = path37.join(opts.skillsRoot, entry.name);
|
|
15734
15927
|
if (!hasMarker(dir))
|
|
15735
15928
|
continue;
|
|
15736
15929
|
if (!opts.dryRun)
|
|
15737
|
-
|
|
15930
|
+
fs33.rmSync(dir, { recursive: true, force: true });
|
|
15738
15931
|
result.removed.push(entry.name);
|
|
15739
15932
|
}
|
|
15740
15933
|
}
|
|
@@ -15742,7 +15935,7 @@ function syncOpencodeSkills(opts) {
|
|
|
15742
15935
|
}
|
|
15743
15936
|
function syncShippedOpencodeSkills(opts) {
|
|
15744
15937
|
return syncOpencodeSkills({
|
|
15745
|
-
sourceSkillsDir:
|
|
15938
|
+
sourceSkillsDir: path37.join(opts.pkgRoot, "plugin", "skills"),
|
|
15746
15939
|
skillsRoot: opts.skillsRoot ?? defaultOpencodeSkillsRoot(),
|
|
15747
15940
|
dryRun: opts.dryRun
|
|
15748
15941
|
});
|
|
@@ -15750,7 +15943,7 @@ function syncShippedOpencodeSkills(opts) {
|
|
|
15750
15943
|
|
|
15751
15944
|
// packages/agents/dist/projection/claude.js
|
|
15752
15945
|
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
15753
|
-
import
|
|
15946
|
+
import path38 from "path";
|
|
15754
15947
|
import os15 from "os";
|
|
15755
15948
|
|
|
15756
15949
|
// packages/agents/dist/codex/app-server-client.js
|
|
@@ -17095,9 +17288,9 @@ var ClaudeReceiptListener = class {
|
|
|
17095
17288
|
};
|
|
17096
17289
|
|
|
17097
17290
|
// packages/agents/dist/claude/api-key-approval.js
|
|
17098
|
-
import
|
|
17291
|
+
import fs34 from "fs";
|
|
17099
17292
|
import os16 from "os";
|
|
17100
|
-
import
|
|
17293
|
+
import path39 from "path";
|
|
17101
17294
|
|
|
17102
17295
|
// packages/agents/dist/opencode/http-channel.js
|
|
17103
17296
|
init_dist2();
|
|
@@ -17189,10 +17382,10 @@ var OpencodeHttpChannel = class {
|
|
|
17189
17382
|
return cached;
|
|
17190
17383
|
const directory = this.directoryFor?.(taskId);
|
|
17191
17384
|
const createdAfterMs = this.createdAfterFor?.(taskId);
|
|
17192
|
-
for (const
|
|
17385
|
+
for (const path43 of ["/session?", "/api/session?"]) {
|
|
17193
17386
|
let res;
|
|
17194
17387
|
try {
|
|
17195
|
-
res = await this.request(`http://127.0.0.1:${port}${
|
|
17388
|
+
res = await this.request(`http://127.0.0.1:${port}${path43}`, { method: "GET" });
|
|
17196
17389
|
} catch {
|
|
17197
17390
|
return void 0;
|
|
17198
17391
|
}
|
|
@@ -17266,9 +17459,9 @@ function createOpencodeFactAdapter(deps) {
|
|
|
17266
17459
|
}
|
|
17267
17460
|
|
|
17268
17461
|
// packages/agents/dist/rules-hooks/install.js
|
|
17269
|
-
import
|
|
17462
|
+
import fs35 from "fs";
|
|
17270
17463
|
import os17 from "os";
|
|
17271
|
-
import
|
|
17464
|
+
import path40 from "path";
|
|
17272
17465
|
|
|
17273
17466
|
// packages/workspaces/dist/runtimes/cmux.js
|
|
17274
17467
|
init_dist();
|
|
@@ -18006,9 +18199,9 @@ var NotifierRegistry = class {
|
|
|
18006
18199
|
};
|
|
18007
18200
|
|
|
18008
18201
|
// packages/workspaces/dist/workspaces/obsidian.js
|
|
18009
|
-
import
|
|
18202
|
+
import fs36 from "fs/promises";
|
|
18010
18203
|
import { existsSync as existsSync11 } from "fs";
|
|
18011
|
-
import
|
|
18204
|
+
import path41 from "path";
|
|
18012
18205
|
|
|
18013
18206
|
// packages/workspaces/dist/workspaces/registry.js
|
|
18014
18207
|
init_dist();
|
|
@@ -18558,9 +18751,9 @@ function defaultListFiles(dir) {
|
|
|
18558
18751
|
return [];
|
|
18559
18752
|
}
|
|
18560
18753
|
}
|
|
18561
|
-
function defaultReadFile(
|
|
18754
|
+
function defaultReadFile(path43) {
|
|
18562
18755
|
try {
|
|
18563
|
-
return readFileSync17(
|
|
18756
|
+
return readFileSync17(path43, "utf-8");
|
|
18564
18757
|
} catch {
|
|
18565
18758
|
return void 0;
|
|
18566
18759
|
}
|
|
@@ -18940,16 +19133,16 @@ function extractDetail(sub, payload) {
|
|
|
18940
19133
|
}
|
|
18941
19134
|
return void 0;
|
|
18942
19135
|
}
|
|
18943
|
-
function defaultReadFile2(
|
|
19136
|
+
function defaultReadFile2(path43) {
|
|
18944
19137
|
try {
|
|
18945
|
-
return readFileSync18(
|
|
19138
|
+
return readFileSync18(path43, "utf-8");
|
|
18946
19139
|
} catch {
|
|
18947
19140
|
return void 0;
|
|
18948
19141
|
}
|
|
18949
19142
|
}
|
|
18950
|
-
function defaultWriteFile(
|
|
18951
|
-
mkdirSync8(
|
|
18952
|
-
writeFileSync11(
|
|
19143
|
+
function defaultWriteFile(path43, content) {
|
|
19144
|
+
mkdirSync8(path43.replace(/\/[^/]+$/, ""), { recursive: true });
|
|
19145
|
+
writeFileSync11(path43, content, "utf-8");
|
|
18953
19146
|
}
|
|
18954
19147
|
|
|
18955
19148
|
// packages/workspaces/dist/crew-pane.js
|
|
@@ -19034,9 +19227,9 @@ init_dist();
|
|
|
19034
19227
|
|
|
19035
19228
|
// packages/cli/src/lib/daemon-restart-broadcast.ts
|
|
19036
19229
|
init_dist();
|
|
19037
|
-
import
|
|
19230
|
+
import path42 from "path";
|
|
19038
19231
|
function statePath2(stateRoot) {
|
|
19039
|
-
return
|
|
19232
|
+
return path42.join(stateRoot, "daemon-restart-state.json");
|
|
19040
19233
|
}
|
|
19041
19234
|
function computeRestartSignature(version, buildMtimeMs) {
|
|
19042
19235
|
return `${version}::${buildMtimeMs}`;
|
|
@@ -19085,7 +19278,7 @@ async function maybeBroadcastDaemonRestart(opts) {
|
|
|
19085
19278
|
|
|
19086
19279
|
// packages/cli/src/lib/captain-channel-factory.ts
|
|
19087
19280
|
import { createServer as createServer4, connect as netConnect } from "net";
|
|
19088
|
-
import
|
|
19281
|
+
import fs37 from "fs";
|
|
19089
19282
|
import { join as join26 } from "path";
|
|
19090
19283
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
19091
19284
|
import chalk2 from "chalk";
|
|
@@ -19094,15 +19287,15 @@ var shared;
|
|
|
19094
19287
|
var registryEntryPath = () => join26(CLAUDE_SESSIONS_DIR, `${process.pid}.json`);
|
|
19095
19288
|
function unregisterSenderIdentity() {
|
|
19096
19289
|
try {
|
|
19097
|
-
|
|
19290
|
+
fs37.unlinkSync(registryEntryPath());
|
|
19098
19291
|
} catch {
|
|
19099
19292
|
}
|
|
19100
19293
|
}
|
|
19101
19294
|
function registerSenderIdentity(socketPath) {
|
|
19102
19295
|
try {
|
|
19103
19296
|
unregisterSenderIdentity();
|
|
19104
|
-
|
|
19105
|
-
|
|
19297
|
+
fs37.mkdirSync(CLAUDE_SESSIONS_DIR, { recursive: true });
|
|
19298
|
+
fs37.writeFileSync(
|
|
19106
19299
|
registryEntryPath(),
|
|
19107
19300
|
JSON.stringify({
|
|
19108
19301
|
pid: process.pid,
|
|
@@ -19128,7 +19321,7 @@ async function sharedReceiptListener() {
|
|
|
19128
19321
|
// must never be the reason we refuse to start.
|
|
19129
19322
|
unlinkStale: (p) => {
|
|
19130
19323
|
try {
|
|
19131
|
-
|
|
19324
|
+
fs37.unlinkSync(p);
|
|
19132
19325
|
} catch {
|
|
19133
19326
|
}
|
|
19134
19327
|
},
|
|
@@ -19153,7 +19346,7 @@ async function buildCaptainChannel() {
|
|
|
19153
19346
|
// in /tmp/x registers cwd "/private/tmp/x" on macOS, so cwd matching silently
|
|
19154
19347
|
// missed and every captain ping reported accepted-unconfirmed.
|
|
19155
19348
|
statusFor: (taskId) => readClaudeStatusBySocketPath(captainSocketPath(taskId)),
|
|
19156
|
-
wire: (p, e) => writeLine(p, e, { connect: (
|
|
19349
|
+
wire: (p, e) => writeLine(p, e, { connect: (path43) => netConnect(path43) }),
|
|
19157
19350
|
receipts,
|
|
19158
19351
|
newMsgId: () => randomUUID5(),
|
|
19159
19352
|
sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
|