squadrant 0.28.0 → 0.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -10428,10 +10428,34 @@ function expandSource(kbRoot, entry) {
10428
10428
  const re = globToRegExp(abs.split(path16.sep).join("/"));
10429
10429
  return walkFiles(root).filter((f) => re.test(f.split(path16.sep).join("/"))).sort();
10430
10430
  }
10431
- function sourceCovers(kbRoot, entry, ref) {
10432
- const abs = path16.resolve(kbRoot, expandHome(entry.path));
10433
- const file = fileForRef(kbRoot, ref);
10434
- return /[*?]/.test(entry.path) ? globToRegExp(abs.split(path16.sep).join("/")).test(file.split(path16.sep).join("/")) : abs === file;
10431
+ function refCandidates(kbRoot, sources, ref) {
10432
+ const asIs = path16.resolve(kbRoot, expandHome(ref));
10433
+ if (path16.isAbsolute(expandHome(ref)))
10434
+ return [asIs];
10435
+ const bases = /* @__PURE__ */ new Set([kbRoot]);
10436
+ for (const s of sources) {
10437
+ let d = path16.resolve(kbRoot, expandHome(s.path.split(/[*?[{]/)[0]));
10438
+ for (let i = 0; i < 6 && d !== path16.dirname(d); i++) {
10439
+ d = path16.dirname(d);
10440
+ bases.add(d);
10441
+ }
10442
+ }
10443
+ return [.../* @__PURE__ */ new Set([asIs, ...[...bases].map((b) => path16.join(b, ref))])];
10444
+ }
10445
+ function refPath(kbRoot, sources, ref) {
10446
+ const cands = refCandidates(kbRoot, sources, ref);
10447
+ return cands.find(isFile) ?? cands.find((f) => sources.some((e) => entryCovers(kbRoot, e, f))) ?? cands[0];
10448
+ }
10449
+ function refCanon(kbRoot, sources) {
10450
+ const memo = /* @__PURE__ */ new Map();
10451
+ return (ref) => {
10452
+ let c = memo.get(ref);
10453
+ if (c === void 0) {
10454
+ c = refFor(kbRoot, refPath(kbRoot, sources, ref));
10455
+ memo.set(ref, c);
10456
+ }
10457
+ return c;
10458
+ };
10435
10459
  }
10436
10460
  function detectChange(kbRoot, file) {
10437
10461
  const ref = refFor(kbRoot, file);
@@ -10529,7 +10553,7 @@ async function planIngest(kbRoot, opts) {
10529
10553
  }
10530
10554
  return plan;
10531
10555
  }
10532
- 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;
10556
+ var execFileAsync, CONVERTED_DIR, DEFAULT_MAX_SECTIONS_PER_PASS, CHARS_PER_TOKEN, PASS_THROUGH, SECTION_TARGET_CHARS, markitdownConverter, expandHome, cacheKey, convertedFile, stampFile, isFile, resolveSourceRef, entryCovers, sourceCovers, isGatedRef, sha256;
10533
10557
  var init_ingest = __esm({
10534
10558
  "packages/core/dist/knowledge/ingest.js"() {
10535
10559
  execFileAsync = promisify2(execFile2);
@@ -10543,11 +10567,17 @@ var init_ingest = __esm({
10543
10567
  return stdout;
10544
10568
  };
10545
10569
  expandHome = (p) => p === "~" || p.startsWith("~/") ? path16.join(os7.homedir(), p.slice(1)) : p;
10546
- fileForRef = (kbRoot, ref) => path16.resolve(kbRoot, expandHome(ref));
10547
10570
  cacheKey = (ref) => `${ref.replace(/[^A-Za-z0-9._-]+/g, "_")}.${crypto3.createHash("sha1").update(ref).digest("hex").slice(0, 6)}`;
10548
10571
  convertedFile = (kbRoot, ref) => path16.join(kbRoot, CONVERTED_DIR, `${cacheKey(ref)}.md`);
10549
10572
  stampFile = (kbRoot, ref) => path16.join(kbRoot, CONVERTED_DIR, `${cacheKey(ref)}.sha`);
10550
- isGatedRef = (kbRoot, sources, ref) => sources.some((e) => e.review === "required" && sourceCovers(kbRoot, e, ref));
10573
+ isFile = (f) => fs15.existsSync(f) && fs15.statSync(f).isFile();
10574
+ resolveSourceRef = (kbRoot, sources, ref) => refCandidates(kbRoot, sources, ref).find(isFile);
10575
+ entryCovers = (kbRoot, entry, file) => {
10576
+ const abs = path16.resolve(kbRoot, expandHome(entry.path));
10577
+ return /[*?]/.test(entry.path) ? globToRegExp(abs.split(path16.sep).join("/")).test(file.split(path16.sep).join("/")) : abs === file;
10578
+ };
10579
+ sourceCovers = (kbRoot, sources, entry, ref) => entryCovers(kbRoot, entry, refPath(kbRoot, sources, ref));
10580
+ isGatedRef = (kbRoot, sources, ref) => sources.some((e) => e.review === "required" && sourceCovers(kbRoot, sources, e, ref));
10551
10581
  sha256 = (file) => crypto3.createHash("sha256").update(fs15.readFileSync(file)).digest("hex");
10552
10582
  }
10553
10583
  });
@@ -10630,7 +10660,6 @@ var init_verify = __esm({
10630
10660
 
10631
10661
  // packages/core/dist/knowledge/store.js
10632
10662
  import fs16 from "fs";
10633
- import os8 from "os";
10634
10663
  import path17 from "path";
10635
10664
  import matter2 from "gray-matter";
10636
10665
  function duplicateIdProblem(id, ignored, used) {
@@ -10691,18 +10720,6 @@ function loadRulesDir(dir, layer, opts = {}) {
10691
10720
  }
10692
10721
  return { rules, errors };
10693
10722
  }
10694
- function resolveSourceRef(ref, kbRoot, sources) {
10695
- const bases = /* @__PURE__ */ new Set([kbRoot]);
10696
- for (const s of sources) {
10697
- let d = path17.resolve(kbRoot, expandHome2(s.path.split(/[*?[{]/)[0]));
10698
- for (let i = 0; i < 6 && d !== path17.dirname(d); i++) {
10699
- d = path17.dirname(d);
10700
- bases.add(d);
10701
- }
10702
- }
10703
- const cands = [path17.resolve(kbRoot, expandHome2(ref)), ...[...bases].map((b) => path17.join(b, ref))];
10704
- return cands.find((c) => fs16.existsSync(c) && fs16.statSync(c).isFile());
10705
- }
10706
10723
  function validateKb(opts) {
10707
10724
  const { rules, errors } = loadRulesDir(opts.rulesDir, "kb", { includeProposed: true });
10708
10725
  const checks = [];
@@ -10722,17 +10739,18 @@ function validateKb(opts) {
10722
10739
  else
10723
10740
  checks.push({ level: "ok", message: "no duplicate ids" });
10724
10741
  const cache = /* @__PURE__ */ new Map();
10742
+ const canon = refCanon(opts.kbRoot, opts.sources);
10725
10743
  let verified = 0, unresolved = 0, notIngested = 0;
10726
10744
  for (const r of rules) {
10727
10745
  r.sources.forEach((src, i) => {
10728
- const file = resolveSourceRef(src.ref, opts.kbRoot, opts.sources);
10746
+ const file = resolveSourceRef(opts.kbRoot, opts.sources, src.ref);
10729
10747
  if (!file) {
10730
10748
  unresolved++;
10731
10749
  return;
10732
10750
  }
10733
10751
  const key = `${src.ref}\0${file}`;
10734
10752
  if (!cache.has(key)) {
10735
- const conv = readState2(opts.kbRoot, src.ref) ? convertedFile(opts.kbRoot, src.ref) : null;
10753
+ const conv = readState2(opts.kbRoot, canon(src.ref)) ? convertedFile(opts.kbRoot, canon(src.ref)) : null;
10736
10754
  const cached = !!conv && fs16.existsSync(conv);
10737
10755
  cache.set(key, {
10738
10756
  hay: normalizedViews(fs16.readFileSync(cached ? conv : file, "utf8")),
@@ -10744,7 +10762,7 @@ function validateKb(opts) {
10744
10762
  if (span) {
10745
10763
  verified++;
10746
10764
  const active = r.status === "active" && !path17.relative(opts.rulesDir, r.file).split(path17.sep).includes(PROPOSED_DIR);
10747
- const err = active ? (opts.errata ?? []).find((e) => e.ref === src.ref && ((o) => !!o && spansOverlap(o, span))(findQuote(hay, e.quote))) : void 0;
10765
+ const err = active ? (opts.errata ?? []).find((e) => canon(e.ref) === canon(src.ref) && ((o) => !!o && spansOverlap(o, span))(findQuote(hay, e.quote))) : void 0;
10748
10766
  if (err)
10749
10767
  checks.push({ level: "warn", message: `${r.id}: grounded in erratum ${err.id} (${err.reason}); re-check or retire it (${r.file})` });
10750
10768
  } else if (convertible)
@@ -10767,7 +10785,7 @@ function validateKb(opts) {
10767
10785
  }
10768
10786
  return { checks, ok: !checks.some((c) => c.level === "fail") };
10769
10787
  }
10770
- var NO_JS_FRONTMATTER, expandHome2;
10788
+ var NO_JS_FRONTMATTER;
10771
10789
  var init_store2 = __esm({
10772
10790
  "packages/core/dist/knowledge/store.js"() {
10773
10791
  init_dist();
@@ -10779,7 +10797,6 @@ var init_store2 = __esm({
10779
10797
  throw new Error("only YAML front matter is allowed");
10780
10798
  } } }
10781
10799
  };
10782
- expandHome2 = (p) => p === "~" || p.startsWith("~/") ? path17.join(os8.homedir(), p.slice(1)) : p;
10783
10800
  }
10784
10801
  });
10785
10802
 
@@ -14002,7 +14019,7 @@ function removeSource(kbRoot, rulesDir, entryPath, opts = {}) {
14002
14019
  const res = { dryRun: !!opts.dryRun, entryRemoved: true, stripped: [], stale: [] };
14003
14020
  const writes = [];
14004
14021
  for (const rule2 of loadRulesDir(rulesDir, "kb").rules) {
14005
- const kept = rule2.sources.filter((s) => !sourceCovers(kbRoot, entry, s.ref));
14022
+ const kept = rule2.sources.filter((s) => !sourceCovers(kbRoot, sources, entry, s.ref));
14006
14023
  if (kept.length === rule2.sources.length)
14007
14024
  continue;
14008
14025
  res.stripped.push(rule2.id);
@@ -14123,7 +14140,7 @@ var init_match = __esm({
14123
14140
 
14124
14141
  // packages/core/dist/knowledge/audit.js
14125
14142
  import fs20 from "fs";
14126
- import os9 from "os";
14143
+ import os8 from "os";
14127
14144
  import path21 from "path";
14128
14145
  function appendAudit(events, sink = {}) {
14129
14146
  if (!events.length)
@@ -14153,8 +14170,8 @@ var AUDIT_QUERY_CHARS, defaultAuditDir, auditMachineId;
14153
14170
  var init_audit = __esm({
14154
14171
  "packages/core/dist/knowledge/audit.js"() {
14155
14172
  AUDIT_QUERY_CHARS = 200;
14156
- defaultAuditDir = () => process.env.SQUADRANT_AUDIT_DIR || path21.join(os9.homedir(), ".local", "state", "squadrant", "audit");
14157
- auditMachineId = () => os9.hostname().replace(/[^A-Za-z0-9_-]/g, "_") || "host";
14173
+ defaultAuditDir = () => process.env.SQUADRANT_AUDIT_DIR || path21.join(os8.homedir(), ".local", "state", "squadrant", "audit");
14174
+ auditMachineId = () => os8.hostname().replace(/[^A-Za-z0-9_-]/g, "_") || "host";
14158
14175
  }
14159
14176
  });
14160
14177
 
@@ -14580,18 +14597,20 @@ function loadErrata(kbRoot) {
14580
14597
  });
14581
14598
  return { errata, errors };
14582
14599
  }
14583
- function orphanedErrata(kbRoot, errata, refs) {
14584
- const only = refs ? new Set(refs) : void 0;
14600
+ function orphanedErrata(kbRoot, sources, errata, refs) {
14601
+ const canon = refCanon(kbRoot, sources);
14602
+ const only = refs ? new Set([...refs].map(canon)) : void 0;
14585
14603
  const hays = /* @__PURE__ */ new Map();
14586
14604
  const out = [];
14587
14605
  for (const e of errata) {
14588
- if (only && !only.has(e.ref))
14606
+ const ref = canon(e.ref);
14607
+ if (only && !only.has(ref))
14589
14608
  continue;
14590
- if (!hays.has(e.ref)) {
14591
- const conv = readState2(kbRoot, e.ref) ? convertedFile(kbRoot, e.ref) : null;
14592
- hays.set(e.ref, conv && fs23.existsSync(conv) ? normalizedViews(fs23.readFileSync(conv, "utf8")) : null);
14609
+ if (!hays.has(ref)) {
14610
+ const conv = readState2(kbRoot, ref) ? convertedFile(kbRoot, ref) : null;
14611
+ hays.set(ref, conv && fs23.existsSync(conv) ? normalizedViews(fs23.readFileSync(conv, "utf8")) : null);
14593
14612
  }
14594
- const hay = hays.get(e.ref);
14613
+ const hay = hays.get(ref);
14595
14614
  if (hay && !findQuote(hay, e.quote))
14596
14615
  out.push({ id: e.id, ref: e.ref });
14597
14616
  }
@@ -14608,9 +14627,31 @@ var init_errata = __esm({
14608
14627
 
14609
14628
  // packages/core/dist/knowledge/anchor.js
14610
14629
  import fs24 from "fs";
14630
+ import { execFileSync as execFileSync7 } from "child_process";
14611
14631
  import path25 from "path";
14612
- function* repoFiles(root) {
14632
+ function gitFiles(root) {
14633
+ try {
14634
+ const out = execFileSync7("git", ["ls-files", "-co", "--exclude-standard", "-z"], { cwd: root, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], maxBuffer: 64 * 1024 * 1024 });
14635
+ return out.split("\0").filter(Boolean).sort();
14636
+ } catch {
14637
+ return null;
14638
+ }
14639
+ }
14640
+ function* repoFiles(root, maxFiles) {
14613
14641
  let count = 0;
14642
+ const listed = gitFiles(root);
14643
+ if (listed) {
14644
+ for (const rel of listed) {
14645
+ if (!CODE_EXT.has(path25.extname(rel)) || rel.split("/").slice(0, -1).some((d) => SKIP_DIRS.has(d)))
14646
+ continue;
14647
+ if (++count > maxFiles) {
14648
+ console.warn(`anchor: ${root} has more than ${maxFiles} code files; anchors cover only the first ${maxFiles}`);
14649
+ return;
14650
+ }
14651
+ yield path25.join(root, rel);
14652
+ }
14653
+ return;
14654
+ }
14614
14655
  const stack = [root];
14615
14656
  while (stack.length) {
14616
14657
  const dir = stack.pop();
@@ -14625,48 +14666,60 @@ function* repoFiles(root) {
14625
14666
  if (!SKIP_DIRS.has(ent.name))
14626
14667
  stack.push(path25.join(dir, ent.name));
14627
14668
  } else if (ent.isFile() && CODE_EXT.has(path25.extname(ent.name))) {
14628
- if (++count > MAX_FILES)
14669
+ if (++count > maxFiles) {
14670
+ console.warn(`anchor: ${root} has more than ${maxFiles} code files; anchors cover only the first ${maxFiles}`);
14629
14671
  return;
14672
+ }
14630
14673
  yield path25.join(dir, ent.name);
14631
14674
  }
14632
14675
  }
14633
14676
  }
14634
14677
  }
14635
- function computeAnchor(repoRoot, triggers) {
14636
- const terms2 = anchorTerms(triggers);
14637
- if (!terms2.length || !fs24.existsSync(repoRoot))
14638
- return null;
14639
- const hits = [];
14640
- for (const file of repoFiles(repoRoot)) {
14641
- let text;
14678
+ function scanRepo(root, maxFiles) {
14679
+ const out = [];
14680
+ for (const file of repoFiles(root, maxFiles)) {
14642
14681
  try {
14643
14682
  if (fs24.statSync(file).size > MAX_FILE_BYTES)
14644
14683
  continue;
14645
- text = fs24.readFileSync(file, "utf8");
14684
+ const text = fs24.readFileSync(file, "utf8");
14685
+ const rel = path25.relative(root, file).split(path25.sep).join("/");
14686
+ out.push({ rel, text, hay: `${path25.relative(root, file)}
14687
+ ${text}`.toLowerCase() });
14646
14688
  } catch {
14647
14689
  continue;
14648
14690
  }
14649
- const hay = `${path25.relative(repoRoot, file)}
14650
- ${text}`.toLowerCase();
14691
+ }
14692
+ return out;
14693
+ }
14694
+ function computeAnchor(repoRoot, triggers, cache, maxFiles = MAX_FILES) {
14695
+ const terms2 = anchorTerms(triggers);
14696
+ if (!terms2.length || !fs24.existsSync(repoRoot))
14697
+ return null;
14698
+ let files = cache?.get(repoRoot);
14699
+ if (!files) {
14700
+ files = scanRepo(repoRoot, maxFiles);
14701
+ cache?.set(repoRoot, files);
14702
+ }
14703
+ const hits = [];
14704
+ for (const { rel, text, hay } of files) {
14651
14705
  const score = terms2.filter((t) => hay.includes(t)).length;
14652
14706
  if (!score)
14653
14707
  continue;
14654
- const symbols2 = [...text.matchAll(SYMBOL_RE)].map((m) => m[1]).filter((s) => terms2.some((t) => s.toLowerCase().includes(t)));
14655
- hits.push({ rel: path25.relative(repoRoot, file).split(path25.sep).join("/"), score, symbols: symbols2 });
14708
+ hits.push({ rel, score, text });
14656
14709
  }
14657
14710
  if (!hits.length)
14658
14711
  return null;
14659
14712
  hits.sort((a, b) => b.score - a.score || (a.rel < b.rel ? -1 : 1));
14660
14713
  const top = hits.slice(0, MAX_PATHS);
14661
- const symbols = [...new Set(top.flatMap((h) => h.symbols))].sort().slice(0, MAX_SYMBOLS);
14714
+ const symbols = [...new Set(top.flatMap((h) => [...h.text.matchAll(SYMBOL_RE)].map((m) => m[1]).filter((s) => terms2.some((t) => s.toLowerCase().includes(t)))))].sort().slice(0, MAX_SYMBOLS);
14662
14715
  return { paths: top.map((h) => h.rel).sort(), ...symbols.length ? { symbols } : {} };
14663
14716
  }
14664
14717
  var SKIP_DIRS, CODE_EXT, MAX_FILES, MAX_FILE_BYTES, MAX_PATHS, MAX_SYMBOLS, SYMBOL_RE, anchorTerms;
14665
14718
  var init_anchor = __esm({
14666
14719
  "packages/core/dist/knowledge/anchor.js"() {
14667
- SKIP_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", "dist", "build", "coverage", ".next", ".worktrees", ".planning", ".converted"]);
14720
+ SKIP_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", "dist", "build", "coverage", ".next", ".worktrees", ".planning", ".converted", ".venv", "venv", "__pycache__"]);
14668
14721
  CODE_EXT = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".go", ".rs", ".java", ".kt", ".swift", ".rb", ".php", ".cs", ".sol", ".sql", ".md"]);
14669
- MAX_FILES = 5e3;
14722
+ MAX_FILES = 2e4;
14670
14723
  MAX_FILE_BYTES = 256 * 1024;
14671
14724
  MAX_PATHS = 5;
14672
14725
  MAX_SYMBOLS = 10;
@@ -14710,8 +14763,8 @@ function validateCandidate(c) {
14710
14763
  }
14711
14764
  return p;
14712
14765
  }
14713
- function upsertSource(fm, src) {
14714
- const i = fm.sources.findIndex((s) => s.ref === src.ref);
14766
+ function upsertSource(fm, src, canon) {
14767
+ const i = fm.sources.findIndex((s) => canon(s.ref) === canon(src.ref));
14715
14768
  if (i < 0) {
14716
14769
  fm.sources.push(src);
14717
14770
  return true;
@@ -14735,7 +14788,8 @@ function applyCandidates(input, opts) {
14735
14788
  const norm = /* @__PURE__ */ new Map();
14736
14789
  const totals = /* @__PURE__ */ new Map();
14737
14790
  const touched = /* @__PURE__ */ new Set();
14738
- const complete = new Set(input.complete ?? []);
14791
+ const canon = refCanon(kbRoot, opts.sources ?? []);
14792
+ const complete = new Set((input.complete ?? []).map(canon));
14739
14793
  for (const cand of input.candidates) {
14740
14794
  const problems = validateCandidate(cand);
14741
14795
  if (problems.length) {
@@ -14763,7 +14817,7 @@ function applyCandidates(input, opts) {
14763
14817
  ev2("item.rejected", cand.id, { reason: "ungrounded" });
14764
14818
  continue;
14765
14819
  }
14766
- const hit = (opts.errata ?? []).find((e) => e.ref === cand.source && ((o) => !!o && spansOverlap(o, offset))(findQuote(hay, e.quote)));
14820
+ const hit = (opts.errata ?? []).find((e) => canon(e.ref) === canon(cand.source) && ((o) => !!o && spansOverlap(o, offset))(findQuote(hay, e.quote)));
14767
14821
  if (hit) {
14768
14822
  tot.total--;
14769
14823
  res.rejected.push({ id: cand.id, source: cand.source, reason: `errata:${hit.id}` });
@@ -14773,7 +14827,7 @@ function applyCandidates(input, opts) {
14773
14827
  let id = cand.id;
14774
14828
  for (const [wid, w] of work) {
14775
14829
  const span = (s) => s.sha === st.sha ? s.offset : findQuote(hay, s.quote) ?? s.offset;
14776
- if (w.fm.sources.some((s) => s.ref === cand.source && s.offset && ((o) => !!o && spansOverlap(o, offset))(span(s)))) {
14830
+ if (w.fm.sources.some((s) => canon(s.ref) === canon(cand.source) && s.offset && ((o) => !!o && spansOverlap(o, offset))(span(s)))) {
14777
14831
  id = wid;
14778
14832
  break;
14779
14833
  }
@@ -14788,7 +14842,7 @@ function applyCandidates(input, opts) {
14788
14842
 
14789
14843
  ${cand.rationale.trim()}` : "");
14790
14844
  if (target && contradicted.length === 0 && sameMeaning(target, cand)) {
14791
- let changed = upsertSource(target.fm, src);
14845
+ let changed = upsertSource(target.fm, src, canon);
14792
14846
  if (target.fm.status === "stale") {
14793
14847
  target.fm.status = "active";
14794
14848
  changed = true;
@@ -14839,7 +14893,7 @@ ${cand.rationale.trim()}` : "");
14839
14893
  if (!other.startsWith(`${id}@`) || !other.endsWith(".md") || path26.join(dir, other) === file)
14840
14894
  continue;
14841
14895
  const old = matter4(fs25.readFileSync(path26.join(dir, other), "utf8"));
14842
- if (!old.data.sources?.some((s) => s.ref === cand.source))
14896
+ if (!old.data.sources?.some((s) => canon(s.ref) === canon(cand.source)))
14843
14897
  continue;
14844
14898
  fs25.writeFileSync(path26.join(dir, other.replace(/\.md$/, ".superseded")), matter4.stringify(old.content, { ...old.data, supersededBy: path26.basename(file) }));
14845
14899
  fs25.rmSync(path26.join(dir, other));
@@ -14853,18 +14907,19 @@ ${cand.rationale.trim()}` : "");
14853
14907
  for (const [id, w] of work) {
14854
14908
  if (touched.has(id) || w.fm.status !== "active" || w.isNew)
14855
14909
  continue;
14856
- if (w.fm.sources.length && w.fm.sources.every((s) => complete.has(s.ref))) {
14910
+ if (w.fm.sources.length && w.fm.sources.every((s) => complete.has(canon(s.ref)))) {
14857
14911
  w.fm.status = "stale";
14858
14912
  w.dirty = true;
14859
14913
  res.stale.push(id);
14860
14914
  }
14861
14915
  }
14916
+ const anchorCache = /* @__PURE__ */ new Map();
14862
14917
  for (const w of work.values()) {
14863
14918
  if (!w.dirty || !opts.projects?.length)
14864
14919
  continue;
14865
14920
  const anchors = { ...w.fm.anchors ?? {} };
14866
14921
  for (const p of opts.projects) {
14867
- const a = computeAnchor(p.root, w.fm.triggers);
14922
+ const a = computeAnchor(p.root, w.fm.triggers, anchorCache);
14868
14923
  if (a)
14869
14924
  anchors[p.name] = a;
14870
14925
  }
@@ -14879,7 +14934,7 @@ ${cand.rationale.trim()}` : "");
14879
14934
  if (!fs25.existsSync(w.file) || fs25.readFileSync(w.file, "utf8") !== text)
14880
14935
  fs25.writeFileSync(w.file, text);
14881
14936
  }
14882
- res.orphanedErrata = orphanedErrata(kbRoot, opts.errata ?? [], totals.keys());
14937
+ res.orphanedErrata = orphanedErrata(kbRoot, opts.sources ?? [], opts.errata ?? [], totals.keys());
14883
14938
  for (const [ref, t] of totals)
14884
14939
  if (needsDocling(t.dropped, t.total))
14885
14940
  res.doclingFlags.push({ ref, ...t });
@@ -15078,7 +15133,7 @@ var init_schedule = __esm({
15078
15133
 
15079
15134
  // packages/core/dist/knowledge/review.js
15080
15135
  import crypto4 from "crypto";
15081
- import { execFileSync as execFileSync7 } from "child_process";
15136
+ import { execFileSync as execFileSync8 } from "child_process";
15082
15137
  import fs27 from "fs";
15083
15138
  import path28 from "path";
15084
15139
  import matter5 from "gray-matter";
@@ -15108,11 +15163,7 @@ function priorityOfRef(c, ref) {
15108
15163
  if (ref.startsWith("agent:"))
15109
15164
  return "agent";
15110
15165
  const root = kbDir(c.cfg, c.kb);
15111
- for (const e of c.sources)
15112
- for (const f of expandSource(root, e))
15113
- if (refFor(root, f) === ref)
15114
- return e.priority;
15115
- return "project";
15166
+ return c.sources.find((e) => sourceCovers(root, c.sources, e, ref))?.priority ?? "project";
15116
15167
  }
15117
15168
  function priorityOfRule(c, r) {
15118
15169
  return r.sources.map((s) => priorityOfRef(c, s.ref)).sort((a, b) => PRIORITY_RANK[b] - PRIORITY_RANK[a])[0] ?? "project";
@@ -15149,7 +15200,7 @@ function reindex(c) {
15149
15200
  function anchorsFor(c, fm) {
15150
15201
  const anchors = { ...fm.anchors ?? {} };
15151
15202
  for (const p of c.projects ?? []) {
15152
- const a = computeAnchor(p.root, fm.triggers);
15203
+ const a = computeAnchor(p.root, fm.triggers, c.anchorCache);
15153
15204
  if (a)
15154
15205
  anchors[p.name] = a;
15155
15206
  }
@@ -15192,8 +15243,9 @@ function mergeInto(c, p, targetId, live, events) {
15192
15243
  if (!t)
15193
15244
  return false;
15194
15245
  const tf = readFm(t.file);
15246
+ const canon = refCanon(kbDir(c.cfg, c.kb), c.sources);
15195
15247
  for (const s of p.rule.sources)
15196
- if (!tf.fm.sources.some((x) => x.ref === s.ref))
15248
+ if (!tf.fm.sources.some((x) => canon(x.ref) === canon(s.ref)))
15197
15249
  tf.fm.sources.push(s);
15198
15250
  fs27.writeFileSync(t.file, fileText(tf.fm, tf.body));
15199
15251
  fs27.rmSync(p.rule.file);
@@ -15206,7 +15258,7 @@ function evaluateCodeConflict(c, rule2, cc) {
15206
15258
  const root = proj?.root;
15207
15259
  const code = root ? g.lastCommit(root, cc.files) : null;
15208
15260
  const kbRoot = kbDir(c.cfg, c.kb);
15209
- const docDates = rule2.sources.map((s) => g.docDate(fileForRef(kbRoot, s.ref))).filter((d2) => !!d2).sort();
15261
+ const docDates = rule2.sources.map((s) => g.docDate(refPath(kbRoot, c.sources, s.ref))).filter((d2) => !!d2).sort();
15210
15262
  const docDate = docDates[docDates.length - 1];
15211
15263
  const docRev = docRevOf(rule2);
15212
15264
  const evidence = { docRev, codeRev: code?.rev ?? "unknown", files: cc.files, project: cc.project };
@@ -15228,6 +15280,7 @@ function evaluateCodeConflict(c, rule2, cc) {
15228
15280
  };
15229
15281
  }
15230
15282
  function applyDecisions(file, c) {
15283
+ c = { ...c, anchorCache: /* @__PURE__ */ new Map() };
15231
15284
  const now = nowOf(c);
15232
15285
  const kbRoot = kbDir(c.cfg, c.kb);
15233
15286
  const threshold = reconcileConfig(c.cfg, c.kb).autoApproveConfidence;
@@ -15381,8 +15434,9 @@ function applyPair(pd, c, res, threshold, events, kbRoot, now) {
15381
15434
  return;
15382
15435
  }
15383
15436
  const kf = readFm(keep.file);
15437
+ const canon = refCanon(kbRoot, c.sources);
15384
15438
  for (const s of drop.sources)
15385
- if (!kf.fm.sources.some((x) => x.ref === s.ref))
15439
+ if (!kf.fm.sources.some((x) => canon(x.ref) === canon(s.ref)))
15386
15440
  kf.fm.sources.push(s);
15387
15441
  kf.fm.supersedes = [.../* @__PURE__ */ new Set([...kf.fm.supersedes ?? [], drop.id])];
15388
15442
  fs27.writeFileSync(keep.file, fileText(kf.fm, kf.body));
@@ -15528,7 +15582,7 @@ var init_review = __esm({
15528
15582
  escalationsFile = (kbRoot) => path28.join(kbRoot, "escalations.json");
15529
15583
  verdictsFile = (kbRoot) => path28.join(kbRoot, "verdicts.jsonl");
15530
15584
  needsYouCount = (kbRoot) => readEscalations(kbRoot).filter((e) => e.needsYou).length;
15531
- git = (root, args) => execFileSync7("git", ["-C", root, ...args], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
15585
+ git = (root, args) => execFileSync8("git", ["-C", root, ...args], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
15532
15586
  realGit = {
15533
15587
  lastCommit(root, files) {
15534
15588
  try {
@@ -15967,7 +16021,7 @@ function renderReport(cfg, kb, o) {
15967
16021
  if (info.length)
15968
16022
  L.push("", `## For information (${info.length})`, "", ...info.map((e) => `- **${e.key}**: ${e.explanation}`));
15969
16023
  const { errata, errors: errataErrors } = loadErrata(kbDir(cfg, kb));
15970
- const orphans = orphanedErrata(kbDir(cfg, kb), errata);
16024
+ const orphans = orphanedErrata(kbDir(cfg, kb), loadSources(kbDir(cfg, kb)).sources, errata);
15971
16025
  if (orphans.length || errataErrors.length) {
15972
16026
  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}`));
15973
16027
  }
@@ -15989,6 +16043,7 @@ var init_report = __esm({
15989
16043
  init_errata();
15990
16044
  init_layers();
15991
16045
  init_paths();
16046
+ init_sources();
15992
16047
  init_review();
15993
16048
  init_scores();
15994
16049
  }
@@ -16324,7 +16379,6 @@ __export(dist_exports2, {
16324
16379
  extractToolPayload: () => extractToolPayload,
16325
16380
  extractUserIntentFromTranscript: () => extractUserIntentFromTranscript,
16326
16381
  fallsBackToPane: () => fallsBackToPane,
16327
- fileForRef: () => fileForRef,
16328
16382
  findCrewPane: () => findCrewPane,
16329
16383
  findLegacyKbs: () => findLegacyKbs,
16330
16384
  findLegacyOverlays: () => findLegacyOverlays,
@@ -16466,7 +16520,10 @@ __export(dist_exports2, {
16466
16520
  recoverStall: () => recoverStall,
16467
16521
  reduce: () => reduce,
16468
16522
  reduceLifecycle: () => reduceLifecycle,
16523
+ refCandidates: () => refCandidates,
16524
+ refCanon: () => refCanon,
16469
16525
  refFor: () => refFor,
16526
+ refPath: () => refPath,
16470
16527
  releaseDaemonLock: () => releaseDaemonLock,
16471
16528
  removeRunningMarker: () => removeRunningMarker,
16472
16529
  removeSource: () => removeSource,
@@ -16499,6 +16556,7 @@ __export(dist_exports2, {
16499
16556
  resolveSetupGroup: () => resolveSetupGroup,
16500
16557
  resolveSetupToken: () => resolveSetupToken,
16501
16558
  resolveSetupUserId: () => resolveSetupUserId,
16559
+ resolveSourceRef: () => resolveSourceRef,
16502
16560
  restartDaemonIfRunning: () => restartDaemonIfRunning,
16503
16561
  rotateIfNeeded: () => rotateIfNeeded,
16504
16562
  ruleAuditScope: () => ruleAuditScope,
@@ -17235,7 +17293,7 @@ var init_drivers = __esm({
17235
17293
  // packages/agents/dist/projection/cursor.js
17236
17294
  import { mkdir, readFile, writeFile } from "fs/promises";
17237
17295
  import path33 from "path";
17238
- import os10 from "os";
17296
+ import os9 from "os";
17239
17297
  function renderMdc(source) {
17240
17298
  const skillSections = source.skills.map((s) => `## Skill: ${s.name}
17241
17299
 
@@ -17283,7 +17341,7 @@ function createCursorEmitter() {
17283
17341
  if (scope === "user") {
17284
17342
  return [
17285
17343
  {
17286
- path: path33.join(os10.homedir(), ".cursor/rules/squadrant-global.mdc"),
17344
+ path: path33.join(os9.homedir(), ".cursor/rules/squadrant-global.mdc"),
17287
17345
  shared: false,
17288
17346
  format: "mdc"
17289
17347
  }
@@ -17362,7 +17420,7 @@ var init_marker = __esm({
17362
17420
  // packages/agents/dist/projection/codex.js
17363
17421
  import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
17364
17422
  import path34 from "path";
17365
- import os11 from "os";
17423
+ import os10 from "os";
17366
17424
  function renderMarkdown(source) {
17367
17425
  const skillSections = source.skills.map((s) => `## Skill: ${s.name}
17368
17426
 
@@ -17386,7 +17444,7 @@ function createCodexEmitter() {
17386
17444
  destinations(scope, projectRoot) {
17387
17445
  if (scope === "user") {
17388
17446
  return [{
17389
- path: path34.join(os11.homedir(), ".codex/AGENTS.md"),
17447
+ path: path34.join(os10.homedir(), ".codex/AGENTS.md"),
17390
17448
  shared: true,
17391
17449
  format: "markdown"
17392
17450
  }];
@@ -17434,7 +17492,7 @@ var init_codex2 = __esm({
17434
17492
  // packages/agents/dist/projection/gemini.js
17435
17493
  import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
17436
17494
  import path35 from "path";
17437
- import os12 from "os";
17495
+ import os11 from "os";
17438
17496
  function renderMarkdown2(source) {
17439
17497
  const skillSections = source.skills.map((s) => `## Skill: ${s.name}
17440
17498
 
@@ -17458,7 +17516,7 @@ function createGeminiEmitter() {
17458
17516
  destinations(scope, projectRoot) {
17459
17517
  if (scope === "user") {
17460
17518
  return [{
17461
- path: path35.join(os12.homedir(), ".gemini/GEMINI.md"),
17519
+ path: path35.join(os11.homedir(), ".gemini/GEMINI.md"),
17462
17520
  shared: true,
17463
17521
  format: "markdown"
17464
17522
  }];
@@ -17506,7 +17564,7 @@ var init_gemini2 = __esm({
17506
17564
  // packages/agents/dist/projection/opencode.js
17507
17565
  import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
17508
17566
  import path36 from "path";
17509
- import os13 from "os";
17567
+ import os12 from "os";
17510
17568
  function renderMarkdown3(source) {
17511
17569
  const skillSections = source.skills.map((s) => `## Skill: ${s.name}
17512
17570
 
@@ -17530,7 +17588,7 @@ function createOpencodeEmitter() {
17530
17588
  destinations(scope, projectRoot) {
17531
17589
  if (scope === "user") {
17532
17590
  return [{
17533
- path: path36.join(os13.homedir(), ".config", "opencode", "AGENTS.md"),
17591
+ path: path36.join(os12.homedir(), ".config", "opencode", "AGENTS.md"),
17534
17592
  shared: true,
17535
17593
  format: "markdown"
17536
17594
  }];
@@ -17577,10 +17635,10 @@ var init_opencode2 = __esm({
17577
17635
 
17578
17636
  // packages/agents/dist/projection/opencode-skills.js
17579
17637
  import fs33 from "fs";
17580
- import os14 from "os";
17638
+ import os13 from "os";
17581
17639
  import path37 from "path";
17582
17640
  function defaultOpencodeSkillsRoot(env = process.env) {
17583
- const configHome = env.XDG_CONFIG_HOME || path37.join(os14.homedir(), ".config");
17641
+ const configHome = env.XDG_CONFIG_HOME || path37.join(os13.homedir(), ".config");
17584
17642
  return path37.join(configHome, "opencode", "skills");
17585
17643
  }
17586
17644
  function parseSkillName(raw) {
@@ -17675,7 +17733,7 @@ var init_opencode_skills = __esm({
17675
17733
  // packages/agents/dist/projection/claude.js
17676
17734
  import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
17677
17735
  import path38 from "path";
17678
- import os15 from "os";
17736
+ import os14 from "os";
17679
17737
  function renderMarkdown4(source) {
17680
17738
  const skillSections = source.skills.map((s) => `## Skill: ${s.name}
17681
17739
 
@@ -17699,7 +17757,7 @@ function createClaudeEmitter() {
17699
17757
  destinations(scope, projectRoot) {
17700
17758
  if (scope === "user") {
17701
17759
  return [{
17702
- path: path38.join(os15.homedir(), ".claude/CLAUDE.md"),
17760
+ path: path38.join(os14.homedir(), ".claude/CLAUDE.md"),
17703
17761
  shared: true,
17704
17762
  format: "markdown"
17705
17763
  }];
@@ -19654,13 +19712,13 @@ var init_receipt_listener = __esm({
19654
19712
 
19655
19713
  // packages/agents/dist/claude/api-key-approval.js
19656
19714
  import fs34 from "fs";
19657
- import os16 from "os";
19715
+ import os15 from "os";
19658
19716
  import path39 from "path";
19659
19717
  function ensureClaudeApiKeyApproved(apiKey, opts = {}) {
19660
19718
  const suffix = apiKey.slice(-20);
19661
19719
  if (!suffix)
19662
19720
  return { changed: false, reason: "empty api key" };
19663
- const file = opts.claudeJsonPath ?? path39.join(os16.homedir(), ".claude.json");
19721
+ const file = opts.claudeJsonPath ?? path39.join(os15.homedir(), ".claude.json");
19664
19722
  const log = opts.log ?? (() => {
19665
19723
  });
19666
19724
  if (!fs34.existsSync(file)) {
@@ -19887,7 +19945,7 @@ var init_fact_adapter = __esm({
19887
19945
 
19888
19946
  // packages/agents/dist/rules-hooks/install.js
19889
19947
  import fs35 from "fs";
19890
- import os17 from "os";
19948
+ import os16 from "os";
19891
19949
  import path40 from "path";
19892
19950
  function readJson(file) {
19893
19951
  try {
@@ -19925,12 +19983,12 @@ function writeIfChanged(file, next, dryRun) {
19925
19983
  }
19926
19984
  function installCodexRulesHooks(opts = {}) {
19927
19985
  const env = opts.env ?? process.env;
19928
- const file = opts.target ?? path40.join(env.CODEX_HOME ?? path40.join(os17.homedir(), ".codex"), "hooks.json");
19986
+ const file = opts.target ?? path40.join(env.CODEX_HOME ?? path40.join(os16.homedir(), ".codex"), "hooks.json");
19929
19987
  const merged = mergeHooks(readJson(file), "codex", CODEX_HOOKS, opts.cli ?? "squadrant", 5);
19930
19988
  return writeIfChanged(file, JSON.stringify(merged, null, 2) + "\n", opts.dryRun);
19931
19989
  }
19932
19990
  function installGeminiRulesHooks(opts = {}) {
19933
- const file = opts.target ?? path40.join(os17.homedir(), ".gemini", "settings.json");
19991
+ const file = opts.target ?? path40.join(os16.homedir(), ".gemini", "settings.json");
19934
19992
  const merged = mergeHooks(readJson(file), "gemini", GEMINI_HOOKS, opts.cli ?? "squadrant", 5e3);
19935
19993
  return writeIfChanged(file, JSON.stringify(merged, null, 2) + "\n", opts.dryRun);
19936
19994
  }
@@ -19971,7 +20029,7 @@ export const SquadrantRules = async ({ directory }) => {
19971
20029
  }
19972
20030
  function installOpencodeRulesHooks(opts = {}) {
19973
20031
  const env = opts.env ?? process.env;
19974
- const file = opts.target ?? path40.join(env.XDG_CONFIG_HOME || path40.join(os17.homedir(), ".config"), "opencode", "plugin", "squadrant-rules.js");
20032
+ const file = opts.target ?? path40.join(env.XDG_CONFIG_HOME || path40.join(os16.homedir(), ".config"), "opencode", "plugin", "squadrant-rules.js");
19975
20033
  try {
19976
20034
  if (!fs35.readFileSync(file, "utf8").startsWith(OPENCODE_PLUGIN_MARKER))
19977
20035
  return { path: file, changed: false, skipped: "foreign-file" };
@@ -20102,12 +20160,12 @@ var init_dist3 = __esm({
20102
20160
  });
20103
20161
 
20104
20162
  // packages/workspaces/dist/runtimes/cmux.js
20105
- import { execFile as execFile3, execFileSync as execFileSync8 } from "child_process";
20163
+ import { execFile as execFile3, execFileSync as execFileSync9 } from "child_process";
20106
20164
  function isInsideCmux() {
20107
20165
  return !!process.env.CMUX_WORKSPACE_ID;
20108
20166
  }
20109
20167
  function cmuxLocal(args) {
20110
- return execFileSync8(resolveCmuxBin(), args, {
20168
+ return execFileSync9(resolveCmuxBin(), args, {
20111
20169
  encoding: "utf-8",
20112
20170
  stdio: ["ignore", "pipe", "pipe"],
20113
20171
  timeout: CMUX_TIMEOUT
@@ -20873,14 +20931,14 @@ var init_runtimes = __esm({
20873
20931
  });
20874
20932
 
20875
20933
  // packages/workspaces/dist/notifiers/cmux.js
20876
- import { execFile as execFileCb, execFileSync as execFileSync9 } from "child_process";
20934
+ import { execFile as execFileCb, execFileSync as execFileSync10 } from "child_process";
20877
20935
  import { promisify as promisify3 } from "util";
20878
20936
  function createCmuxNotifier(_scope) {
20879
20937
  return {
20880
20938
  name: "cmux",
20881
20939
  async probe() {
20882
20940
  try {
20883
- execFileSync9(resolveCmuxBin(), ["capabilities"], { encoding: "utf-8", stdio: "pipe", timeout: CMUX_TIMEOUT });
20941
+ execFileSync10(resolveCmuxBin(), ["capabilities"], { encoding: "utf-8", stdio: "pipe", timeout: CMUX_TIMEOUT });
20884
20942
  return { installed: true, reachable: true };
20885
20943
  } catch (err) {
20886
20944
  const code = err.code;
@@ -21206,9 +21264,9 @@ var init_events_bridge = __esm({
21206
21264
  });
21207
21265
 
21208
21266
  // packages/workspaces/dist/cmux-daemon/store-fingerprint.js
21209
- import { execFileSync as execFileSync10 } from "child_process";
21267
+ import { execFileSync as execFileSync11 } from "child_process";
21210
21268
  function defaultExecPs(pid) {
21211
- return execFileSync10("ps", ["-o", "command=", "-p", String(pid)], {
21269
+ return execFileSync11("ps", ["-o", "command=", "-p", String(pid)], {
21212
21270
  encoding: "utf-8",
21213
21271
  stdio: ["ignore", "pipe", "ignore"]
21214
21272
  });
@@ -22935,7 +22993,7 @@ init_dist();
22935
22993
  import { Command as Command2 } from "commander";
22936
22994
  import fs38 from "fs";
22937
22995
  import path43 from "path";
22938
- import os18 from "os";
22996
+ import os17 from "os";
22939
22997
  import readline from "readline";
22940
22998
  import chalk4 from "chalk";
22941
22999
 
@@ -23242,7 +23300,7 @@ function warnIfNoAnthropic(preset, auth) {
23242
23300
  var initCommand = new Command2("init").description("Guided first-time setup: provider, hub vault, agents, plugins, projects (re-run-safe)").option("--hub <path>", "Hub vault path", "~/squadrant-hub").option("--preset <id>", "provider preset: a|b|c (non-interactive; d accepted as a deprecated alias for c)").action(async (opts) => {
23243
23301
  const hubPath = resolveHome(opts.hub);
23244
23302
  const pkgRoot = findPackageRoot();
23245
- const configDir = path43.join(os18.homedir(), ".config", "squadrant");
23303
+ const configDir = path43.join(os17.homedir(), ".config", "squadrant");
23246
23304
  const isTTY = process.stdin.isTTY === true;
23247
23305
  console.log(chalk4.bold("\nSquadrant Init\n"));
23248
23306
  let explicitPreset;
@@ -23347,7 +23405,7 @@ var initCommand = new Command2("init").description("Guided first-time setup: pro
23347
23405
  ensureRuntimeSynced({ sourceRoot: pkgRoot, runtimeRoot: configDir });
23348
23406
  console.log(chalk4.green(` \u2714 Runtime assets synced to ${configDir}`));
23349
23407
  stepHeader(2, 5, "Agent + projection setup");
23350
- const settingsPath = path43.join(os18.homedir(), ".claude", "settings.json");
23408
+ const settingsPath = path43.join(os17.homedir(), ".claude", "settings.json");
23351
23409
  try {
23352
23410
  let settings = {};
23353
23411
  if (fs38.existsSync(settingsPath)) {
@@ -23653,9 +23711,9 @@ init_dist();
23653
23711
  import { Command as Command5 } from "commander";
23654
23712
  import { execSync as execSync9 } from "child_process";
23655
23713
  import path45 from "path";
23656
- import os19 from "os";
23714
+ import os18 from "os";
23657
23715
  import chalk7 from "chalk";
23658
- var TEMPLATES_DIR2 = path45.join(os19.homedir(), ".config", "squadrant", "templates");
23716
+ var TEMPLATES_DIR2 = path45.join(os18.homedir(), ".config", "squadrant", "templates");
23659
23717
  var TASK_PROMPTS = {
23660
23718
  briefing: "Run your daily briefing using the squadrant:command-ops skill. Read all spoke handoffs, yesterday's logs, current status; produce a concise cross-project briefing; save to {hubVault}/daily-logs/YYYY-MM-DD.md; then exit.",
23661
23719
  "learnings-review": "Run a learnings review using the squadrant:command-ops skill. Scan {spokeVault}/learnings across all projects, identify cross-project patterns, propose captured-skill or fix actions, and exit when done.",
@@ -23729,7 +23787,7 @@ init_dist3();
23729
23787
  import { Command as Command9 } from "commander";
23730
23788
  import { createConnection as createConnection4 } from "net";
23731
23789
  import { randomUUID as randomUUID5 } from "crypto";
23732
- import { execFileSync as execFileSync11, spawnSync } from "child_process";
23790
+ import { execFileSync as execFileSync12, spawnSync } from "child_process";
23733
23791
  import { homedir as homedir15 } from "os";
23734
23792
  import { join as join27 } from "path";
23735
23793
  import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync13 } from "fs";
@@ -24258,10 +24316,10 @@ function resolveApproveTarget(tasks, crew) {
24258
24316
  return matches.reduce((a, b) => (b.createdAt ?? 0) > (a.createdAt ?? 0) ? b : a);
24259
24317
  }
24260
24318
  function defaultPushBranch(cwd, branch) {
24261
- execFileSync11("git", ["-C", cwd, "push", "-u", "origin", branch], { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
24319
+ execFileSync12("git", ["-C", cwd, "push", "-u", "origin", branch], { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
24262
24320
  }
24263
24321
  function defaultCreatePr(cwd, o) {
24264
- return execFileSync11(
24322
+ return execFileSync12(
24265
24323
  "gh",
24266
24324
  ["pr", "create", "--base", o.base, "--head", o.branch, "--title", o.title, "--body", o.body],
24267
24325
  { cwd, encoding: "utf-8" }
@@ -24269,7 +24327,7 @@ function defaultCreatePr(cwd, o) {
24269
24327
  }
24270
24328
  function defaultGetCommitSubject(cwd) {
24271
24329
  try {
24272
- return execFileSync11("git", ["-C", cwd, "log", "-1", "--format=%s"], {
24330
+ return execFileSync12("git", ["-C", cwd, "log", "-1", "--format=%s"], {
24273
24331
  encoding: "utf-8",
24274
24332
  stdio: ["ignore", "pipe", "pipe"]
24275
24333
  }).trim();
@@ -24951,7 +25009,7 @@ init_dist();
24951
25009
  init_dist4();
24952
25010
  import { Command as Command11 } from "commander";
24953
25011
  import chalk12 from "chalk";
24954
- import { execFileSync as execFileSync12 } from "child_process";
25012
+ import { execFileSync as execFileSync13 } from "child_process";
24955
25013
  import readline2 from "readline";
24956
25014
  function resolveDiffTarget(tasks, crew, projectPath) {
24957
25015
  const matches = tasks.filter((t) => t.name === crew);
@@ -25022,14 +25080,14 @@ function promptLine2(question) {
25022
25080
  }
25023
25081
  function getPrDiff(projectPath, pr) {
25024
25082
  try {
25025
- return execFileSync12("gh", ["pr", "diff", pr], { cwd: projectPath, encoding: "utf-8" });
25083
+ return execFileSync13("gh", ["pr", "diff", pr], { cwd: projectPath, encoding: "utf-8" });
25026
25084
  } catch (e) {
25027
25085
  throw new Error(`Could not fetch PR #${pr} diff (gh pr diff failed): ${e.message}`);
25028
25086
  }
25029
25087
  }
25030
25088
  function getRefsDiff(projectPath, base, head) {
25031
25089
  try {
25032
- return execFileSync12("git", ["-C", projectPath, "diff", `${base}...${head}`], { encoding: "utf-8" });
25090
+ return execFileSync13("git", ["-C", projectPath, "diff", `${base}...${head}`], { encoding: "utf-8" });
25033
25091
  } catch (e) {
25034
25092
  throw new Error(`Could not diff ${base}...${head}: ${e.message}`);
25035
25093
  }
@@ -25050,7 +25108,7 @@ async function openCrewDiff(project, proj, crew, opts, runtime, workspaceId) {
25050
25108
  let opened = 0;
25051
25109
  for (const source of sources) {
25052
25110
  const statArgs = source === "staged" ? ["diff", "--stat", "--cached"] : ["diff", "--stat"];
25053
- const stat2 = execFileSync12("git", ["-C", target.cwd, ...statArgs], { encoding: "utf-8" }).trim();
25111
+ const stat2 = execFileSync13("git", ["-C", target.cwd, ...statArgs], { encoding: "utf-8" }).trim();
25054
25112
  if (!stat2) continue;
25055
25113
  await runtime.showDiff({
25056
25114
  workspaceId,
@@ -25071,7 +25129,7 @@ async function openCrewDiff(project, proj, crew, opts, runtime, workspaceId) {
25071
25129
  }
25072
25130
  return;
25073
25131
  }
25074
- const diffStat = execFileSync12(
25132
+ const diffStat = execFileSync13(
25075
25133
  "git",
25076
25134
  ["-C", target.cwd, "diff", "--stat", `${base}...HEAD`],
25077
25135
  { encoding: "utf-8" }
@@ -25120,7 +25178,7 @@ async function runDiff(project, crewArg, opts) {
25120
25178
  const base = resolveWorktreeBase(proj.path);
25121
25179
  const stats = buildCrewDiffStats(tasks, proj.path, base, (cwd, b) => {
25122
25180
  try {
25123
- return execFileSync12("git", ["-C", cwd, "diff", "--stat", `${b}...HEAD`], { encoding: "utf-8" });
25181
+ return execFileSync13("git", ["-C", cwd, "diff", "--stat", `${b}...HEAD`], { encoding: "utf-8" });
25124
25182
  } catch {
25125
25183
  return "";
25126
25184
  }
@@ -25149,9 +25207,9 @@ init_dist2();
25149
25207
  import { Command as Command12 } from "commander";
25150
25208
  import fs41 from "fs";
25151
25209
  import path46 from "path";
25152
- import os20 from "os";
25210
+ import os19 from "os";
25153
25211
  import chalk13 from "chalk";
25154
- var TEMPLATES_DIR3 = path46.join(os20.homedir(), ".config", "squadrant", "templates");
25212
+ var TEMPLATES_DIR3 = path46.join(os19.homedir(), ".config", "squadrant", "templates");
25155
25213
  async function runSideSpawn2(input) {
25156
25214
  const config = loadConfig();
25157
25215
  const proj = config.projects[input.project];
@@ -26795,10 +26853,10 @@ init_dist3();
26795
26853
  init_dist4();
26796
26854
  init_dist2();
26797
26855
  import { Command as Command14 } from "commander";
26798
- import { execSync as execSync11, execFileSync as execFileSync13 } from "child_process";
26856
+ import { execSync as execSync11, execFileSync as execFileSync14 } from "child_process";
26799
26857
  import fs43 from "fs";
26800
26858
  import path48 from "path";
26801
- import os21 from "os";
26859
+ import os20 from "os";
26802
26860
  import chalk16 from "chalk";
26803
26861
 
26804
26862
  // packages/cli/src/commands/launch-interactive.ts
@@ -26890,8 +26948,8 @@ function resolveLaunchBackend(o) {
26890
26948
  // packages/cli/src/commands/launch.ts
26891
26949
  init_dist2();
26892
26950
  var CMUX_APP = "/Applications/cmux.app";
26893
- var TEMPLATES_DIR4 = path48.join(os21.homedir(), ".config", "squadrant", "templates");
26894
- var SESSIONS_PATH2 = path48.join(os21.homedir(), ".config", "squadrant", "sessions.json");
26951
+ var TEMPLATES_DIR4 = path48.join(os20.homedir(), ".config", "squadrant", "templates");
26952
+ var SESSIONS_PATH2 = path48.join(os20.homedir(), ".config", "squadrant", "sessions.json");
26895
26953
  function shouldWireCaptainChannel(agentName, config) {
26896
26954
  return agentName === "claude" && resolveCaptainChannelMode(config.defaults) !== "off";
26897
26955
  }
@@ -26913,7 +26971,7 @@ function pickResumeSessionId(record, agentName, fresh = false) {
26913
26971
  }
26914
26972
  function isOpencodeCaptainDir(dir) {
26915
26973
  try {
26916
- execFileSync13("git", ["-C", dir, "rev-parse", "--verify", "HEAD"], { stdio: "ignore" });
26974
+ execFileSync14("git", ["-C", dir, "rev-parse", "--verify", "HEAD"], { stdio: "ignore" });
26917
26975
  return true;
26918
26976
  } catch {
26919
26977
  return false;
@@ -26988,7 +27046,7 @@ var launchCommand = new Command14("launch").description(
26988
27046
  initialPrompt = "Run your startup checklist: use the squadrant:command-ops skill, complete your daily briefing, then report ready.";
26989
27047
  }
26990
27048
  const runtime = projectName ? runtimes.forProject(projectName, config) : runtimes.global(config);
26991
- const stateRoot = path48.join(os21.homedir(), ".config", "squadrant", "state");
27049
+ const stateRoot = path48.join(os20.homedir(), ".config", "squadrant", "state");
26992
27050
  const isOpencodeCaptain = role === "captain" && agentName === "opencode" && !!projectName;
26993
27051
  if (isOpencodeCaptain && !isOpencodeCaptainDir(cwd)) {
26994
27052
  console.error(chalk16.red(`
@@ -27345,7 +27403,7 @@ Shutting down captain workspace for '${project}'...
27345
27403
  init_dist();
27346
27404
  import { Command as Command16 } from "commander";
27347
27405
  import fs44 from "fs";
27348
- import os22 from "os";
27406
+ import os21 from "os";
27349
27407
  import path49 from "path";
27350
27408
  import { fileURLToPath as fileURLToPath3 } from "url";
27351
27409
  import { execSync as execSync12 } from "child_process";
@@ -27399,7 +27457,7 @@ function buildIssueUrl(metrics, squadrantVersion) {
27399
27457
  }
27400
27458
  var feedbackCommand = new Command16("feedback").description("Open a pre-filled GitHub issue for feedback or bug reports").action(() => {
27401
27459
  const config = loadConfig();
27402
- const metricsPath = config.metrics?.path || path49.join(os22.homedir(), ".config", "squadrant", "metrics.json");
27460
+ const metricsPath = config.metrics?.path || path49.join(os21.homedir(), ".config", "squadrant", "metrics.json");
27403
27461
  const metrics = readMetrics(metricsPath);
27404
27462
  const version = readStamp(config) ?? readPkgVersion();
27405
27463
  const issueUrl = buildIssueUrl(metrics, version);
@@ -28182,7 +28240,7 @@ function readPkgVersion2() {
28182
28240
 
28183
28241
  // packages/cli/src/commands/heal.ts
28184
28242
  init_dist();
28185
- import { execFileSync as execFileSync14 } from "child_process";
28243
+ import { execFileSync as execFileSync15 } from "child_process";
28186
28244
  import { join as join32 } from "path";
28187
28245
  import { homedir as homedir17 } from "os";
28188
28246
  import { Command as Command24 } from "commander";
@@ -28391,7 +28449,7 @@ async function runHealCaptain(projects, deps) {
28391
28449
  }
28392
28450
  function kickstartDaemonForHealCaptain() {
28393
28451
  const uid = process.getuid?.() ?? 0;
28394
- execFileSync14("launchctl", ["kickstart", "-k", `gui/${uid}/${LABEL}`], { stdio: "ignore" });
28452
+ execFileSync15("launchctl", ["kickstart", "-k", `gui/${uid}/${LABEL}`], { stdio: "ignore" });
28395
28453
  }
28396
28454
  var healCommand = new Command24("heal").description("Targeted, idempotent remediation for squadrant components (daemon, health)").addHelpText("after", "\nDeferred: 'squadrant heal crew <id>' (re-attach) \u2014 see issue #100.").addCommand(
28397
28455
  new Command24("status").description("Dry-run: print unhealthy components and the exact heal command for each").option("-p, --project <project>", "scope to one project").option("--json", "output machine-readable JSON (exit 0=healthy, 1=error, 2=unhealthy)").action(async (opts) => {
@@ -28730,11 +28788,11 @@ var effortCommand = new Command29("effort").description("Get or set the crew tok
28730
28788
  init_dist();
28731
28789
  import fs48 from "fs";
28732
28790
  import path52 from "path";
28733
- import os23 from "os";
28791
+ import os22 from "os";
28734
28792
  import readline3 from "readline";
28735
28793
  import { Command as Command30 } from "commander";
28736
28794
  import chalk31 from "chalk";
28737
- var CLAUDE_PROJECTS_DIR = path52.join(os23.homedir(), ".claude", "projects");
28795
+ var CLAUDE_PROJECTS_DIR = path52.join(os22.homedir(), ".claude", "projects");
28738
28796
  function parseTranscriptLine(rawLine) {
28739
28797
  const line2 = rawLine.trim();
28740
28798
  if (!line2) return { timestamp: null, usage: null };
@@ -30003,11 +30061,11 @@ var workCommand = new Command34("work").description("Track your own in-flight wo
30003
30061
  init_dist();
30004
30062
  import { Command as Command35 } from "commander";
30005
30063
  import path57 from "path";
30006
- import os24 from "os";
30064
+ import os23 from "os";
30007
30065
 
30008
30066
  // packages/cli/src/lib/handoff-live-repo.ts
30009
30067
  init_dist();
30010
- import { execFileSync as execFileSync15 } from "child_process";
30068
+ import { execFileSync as execFileSync16 } from "child_process";
30011
30069
  import fs50 from "fs";
30012
30070
  import path55 from "path";
30013
30071
 
@@ -30086,7 +30144,7 @@ var OPEN_PR_LIMIT = 20;
30086
30144
  var RELEASE_BRANCH = "main";
30087
30145
  var defaultCommandRunner = {
30088
30146
  run(cmd, args, cwd) {
30089
- return execFileSync15(cmd, args, { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
30147
+ return execFileSync16(cmd, args, { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
30090
30148
  }
30091
30149
  };
30092
30150
  function tryRun2(runner, cmd, args, cwd) {
@@ -30415,7 +30473,7 @@ function readNewestArchivedHandoff(spokeVault, now) {
30415
30473
  }
30416
30474
 
30417
30475
  // packages/cli/src/commands/handoff.ts
30418
- var CLAUDE_MEM_DB_PATH = path57.join(os24.homedir(), ".claude-mem", "claude-mem.db");
30476
+ var CLAUDE_MEM_DB_PATH = path57.join(os23.homedir(), ".claude-mem", "claude-mem.db");
30419
30477
  async function defaultFetchTasks(project) {
30420
30478
  return await squadrantdCall({ kind: "list", project });
30421
30479
  }
@@ -30575,7 +30633,7 @@ var sessionsCommand = new Command36("sessions").description("List live agent ses
30575
30633
  init_dist();
30576
30634
  init_dist2();
30577
30635
  init_dist3();
30578
- import os25 from "os";
30636
+ import os24 from "os";
30579
30637
  import path58 from "path";
30580
30638
  import { Command as Command37 } from "commander";
30581
30639
  import chalk36 from "chalk";
@@ -30694,7 +30752,7 @@ function buildWhoamiDeps(opts = {}) {
30694
30752
  const projects = Object.fromEntries(
30695
30753
  Object.entries(config.projects).map(([n, p]) => [n, resolveHome(p.path)])
30696
30754
  );
30697
- const root = stateRoot ?? path58.join(os25.homedir(), ".config", "squadrant", "state");
30755
+ const root = stateRoot ?? path58.join(os24.homedir(), ".config", "squadrant", "state");
30698
30756
  const store = createStore(root);
30699
30757
  const merged = {
30700
30758
  env: process.env,
@@ -30747,7 +30805,7 @@ var whoamiCommand = new Command37("whoami").description("Show the agent session
30747
30805
  init_dist();
30748
30806
  init_dist2();
30749
30807
  import fs54 from "fs";
30750
- import os26 from "os";
30808
+ import os25 from "os";
30751
30809
  import path59 from "path";
30752
30810
  import readline4 from "readline/promises";
30753
30811
  import { spawnSync as spawnSync2 } from "child_process";
@@ -31103,7 +31161,7 @@ knowledgeCommand.command("review <kb>").description("Escalations for the operato
31103
31161
  for (const x of r.skipped) console.log(chalk38.red(` \u2718 ${x.item}: ${x.reason}`));
31104
31162
  return;
31105
31163
  }
31106
- const by = os26.userInfo().username;
31164
+ const by = os25.userInfo().username;
31107
31165
  const resolution = () => o.keepDoc ? { kind: "verdict", verdict: "keep-doc" } : o.supersedeWithCode ? { kind: "verdict", verdict: "supersede-with-code" } : o.approve ? { kind: "approve" } : o.reject ? { kind: "reject" } : null;
31108
31166
  if (o.resolve) {
31109
31167
  const r = resolution();