squadrant 0.26.0 → 0.26.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 +198 -54
- package/dist/index.js.map +1 -1
- package/dist/squadrantd.js +113 -19
- package/dist/squadrantd.js.map +1 -1
- package/package.json +1 -1
- package/plugin/skills/captain-ops/SKILL.md +5 -0
- package/plugin/skills/rules-ops/SKILL.md +56 -0
- package/templates/captain.claude.md +1 -0
- package/templates/captain.generic.md +4 -0
- package/templates/crew.claude.md +4 -0
- package/templates/crew.generic.md +4 -0
- package/templates/crew.opencode.md +4 -0
package/dist/index.js
CHANGED
|
@@ -10216,8 +10216,12 @@ var init_paths = __esm({
|
|
|
10216
10216
|
|
|
10217
10217
|
// packages/core/dist/knowledge/store.js
|
|
10218
10218
|
import fs15 from "fs";
|
|
10219
|
+
import os7 from "os";
|
|
10219
10220
|
import path15 from "path";
|
|
10220
10221
|
import matter2 from "gray-matter";
|
|
10222
|
+
function duplicateIdProblem(id, ignored, used) {
|
|
10223
|
+
return `duplicate id ${id}: ${ignored} is ignored, ${used} is used (live files win over _proposed, then path order). Fix: rename the id in one file, or delete or move one of them.`;
|
|
10224
|
+
}
|
|
10221
10225
|
function splitStatement(body) {
|
|
10222
10226
|
const first = body.trim().split(/\n\s*\n/)[0] ?? "";
|
|
10223
10227
|
return first.replace(/\s+/g, " ").trim();
|
|
@@ -10262,7 +10266,7 @@ function loadRulesDir(dir, layer, opts = {}) {
|
|
|
10262
10266
|
const fm = parsed.data;
|
|
10263
10267
|
const prior = seen.get(fm.id);
|
|
10264
10268
|
if (prior) {
|
|
10265
|
-
errors.push({ file, problems: [
|
|
10269
|
+
errors.push({ file, problems: [duplicateIdProblem(fm.id, file, prior)] });
|
|
10266
10270
|
continue;
|
|
10267
10271
|
}
|
|
10268
10272
|
seen.set(fm.id, file);
|
|
@@ -10270,7 +10274,65 @@ function loadRulesDir(dir, layer, opts = {}) {
|
|
|
10270
10274
|
}
|
|
10271
10275
|
return { rules, errors };
|
|
10272
10276
|
}
|
|
10273
|
-
|
|
10277
|
+
function resolveSourceRef(ref, kbRoot, sources) {
|
|
10278
|
+
const bases = /* @__PURE__ */ new Set([kbRoot]);
|
|
10279
|
+
for (const s of sources) {
|
|
10280
|
+
let d = path15.resolve(kbRoot, expandHome(s.path.split(/[*?[{]/)[0]));
|
|
10281
|
+
for (let i = 0; i < 6 && d !== path15.dirname(d); i++) {
|
|
10282
|
+
d = path15.dirname(d);
|
|
10283
|
+
bases.add(d);
|
|
10284
|
+
}
|
|
10285
|
+
}
|
|
10286
|
+
const cands = [path15.resolve(kbRoot, expandHome(ref)), ...[...bases].map((b) => path15.join(b, ref))];
|
|
10287
|
+
return cands.find((c) => fs15.existsSync(c) && fs15.statSync(c).isFile());
|
|
10288
|
+
}
|
|
10289
|
+
function validateKb(opts) {
|
|
10290
|
+
const { rules, errors } = loadRulesDir(opts.rulesDir, "kb", { includeProposed: true });
|
|
10291
|
+
const checks = [];
|
|
10292
|
+
const dups = errors.filter((e) => e.problems.some((p) => p.startsWith("duplicate id")));
|
|
10293
|
+
const invalid = errors.filter((e) => !dups.includes(e));
|
|
10294
|
+
const proposed = rules.filter((r) => path15.relative(opts.rulesDir, r.file).split(path15.sep).includes(PROPOSED_DIR)).length;
|
|
10295
|
+
checks.push({ level: "ok", message: `${rules.length + errors.length} rule files read (${rules.length - proposed} live, ${proposed} proposed parsed OK)` });
|
|
10296
|
+
if (invalid.length)
|
|
10297
|
+
for (const e of invalid)
|
|
10298
|
+
checks.push({ level: "fail", message: `invalid ${e.file}: ${e.problems.join("; ")}` });
|
|
10299
|
+
else
|
|
10300
|
+
checks.push({ level: "ok", message: "no invalid rule files" });
|
|
10301
|
+
if (dups.length)
|
|
10302
|
+
for (const e of dups)
|
|
10303
|
+
checks.push({ level: "fail", message: e.problems.join("; ") });
|
|
10304
|
+
else
|
|
10305
|
+
checks.push({ level: "ok", message: "no duplicate ids" });
|
|
10306
|
+
const cache = /* @__PURE__ */ new Map();
|
|
10307
|
+
let verified = 0, unresolved = 0;
|
|
10308
|
+
for (const r of rules) {
|
|
10309
|
+
r.sources.forEach((src, i) => {
|
|
10310
|
+
const file = resolveSourceRef(src.ref, opts.kbRoot, opts.sources);
|
|
10311
|
+
if (!file) {
|
|
10312
|
+
unresolved++;
|
|
10313
|
+
return;
|
|
10314
|
+
}
|
|
10315
|
+
if (!cache.has(file))
|
|
10316
|
+
cache.set(file, fs15.readFileSync(file, "utf8"));
|
|
10317
|
+
if (cache.get(file).includes(src.quote))
|
|
10318
|
+
verified++;
|
|
10319
|
+
else
|
|
10320
|
+
checks.push({ level: "fail", message: `quote not found in ${file}: ${r.id} sources[${i}] (${r.file})` });
|
|
10321
|
+
});
|
|
10322
|
+
}
|
|
10323
|
+
if (!checks.some((c) => c.message.startsWith("quote not found")))
|
|
10324
|
+
checks.push({ level: "ok", message: `${verified} source quotes found in their source files` });
|
|
10325
|
+
if (unresolved)
|
|
10326
|
+
checks.push({ level: "skip", message: `${unresolved} source refs not resolvable on this machine, quote not checked` });
|
|
10327
|
+
if (opts.domains) {
|
|
10328
|
+
for (const r of rules) {
|
|
10329
|
+
if (!opts.domains.includes(r.domain))
|
|
10330
|
+
checks.push({ level: "warn", message: `${r.id}: domain '${r.domain}' not in allowed domains [${opts.domains.join(", ")}] (${r.file})` });
|
|
10331
|
+
}
|
|
10332
|
+
}
|
|
10333
|
+
return { checks, ok: !checks.some((c) => c.level === "fail") };
|
|
10334
|
+
}
|
|
10335
|
+
var NO_JS_FRONTMATTER, expandHome;
|
|
10274
10336
|
var init_store2 = __esm({
|
|
10275
10337
|
"packages/core/dist/knowledge/store.js"() {
|
|
10276
10338
|
init_dist();
|
|
@@ -10280,6 +10342,7 @@ var init_store2 = __esm({
|
|
|
10280
10342
|
throw new Error("only YAML front matter is allowed");
|
|
10281
10343
|
} } }
|
|
10282
10344
|
};
|
|
10345
|
+
expandHome = (p) => p === "~" || p.startsWith("~/") ? path15.join(os7.homedir(), p.slice(1)) : p;
|
|
10283
10346
|
}
|
|
10284
10347
|
});
|
|
10285
10348
|
|
|
@@ -10368,7 +10431,7 @@ var init_index_file = __esm({
|
|
|
10368
10431
|
|
|
10369
10432
|
// packages/core/dist/knowledge/search.js
|
|
10370
10433
|
function searchRules(rules, query, opts = {}) {
|
|
10371
|
-
const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
10434
|
+
const terms = [...new Set(query.toLowerCase().split(/\s+/).filter(Boolean))];
|
|
10372
10435
|
if (terms.length === 0)
|
|
10373
10436
|
return [];
|
|
10374
10437
|
const statuses = opts.statuses ?? DEFAULT_SEARCH_STATUSES;
|
|
@@ -10380,30 +10443,45 @@ function searchRules(rules, query, opts = {}) {
|
|
|
10380
10443
|
const expanded = lower(rule2.triggers?.expanded);
|
|
10381
10444
|
const when = (rule2.triggers?.when ?? "").toLowerCase();
|
|
10382
10445
|
const statement = rule2.statement.toLowerCase();
|
|
10446
|
+
const rationale = rationaleOf(rule2);
|
|
10383
10447
|
const id = rule2.id.toLowerCase();
|
|
10384
10448
|
let score = 0;
|
|
10449
|
+
let matched = 0;
|
|
10450
|
+
let curated = false;
|
|
10385
10451
|
for (const t of terms) {
|
|
10452
|
+
let s = 0;
|
|
10386
10453
|
if (id.includes(t))
|
|
10387
|
-
|
|
10454
|
+
s += 3;
|
|
10455
|
+
if (keywords.includes(t) || expanded.includes(t))
|
|
10456
|
+
curated = true;
|
|
10388
10457
|
if (keywords.includes(t))
|
|
10389
|
-
|
|
10458
|
+
s += 3;
|
|
10390
10459
|
if (expanded.includes(t))
|
|
10391
|
-
|
|
10460
|
+
s += 3;
|
|
10392
10461
|
if (when.includes(t))
|
|
10393
|
-
|
|
10462
|
+
s += 2;
|
|
10394
10463
|
if (statement.includes(t))
|
|
10395
|
-
|
|
10464
|
+
s += 2;
|
|
10465
|
+
if (rationale.includes(t))
|
|
10466
|
+
s += 1;
|
|
10467
|
+
if (s > 0) {
|
|
10468
|
+
matched++;
|
|
10469
|
+
score += s;
|
|
10470
|
+
}
|
|
10396
10471
|
}
|
|
10397
10472
|
if (score > 0)
|
|
10398
|
-
hits.push({ rule: rule2, score });
|
|
10473
|
+
hits.push({ rule: rule2, score, matched, curated });
|
|
10399
10474
|
}
|
|
10400
|
-
|
|
10475
|
+
const strong = terms.length >= 2 ? hits.filter((h) => h.matched >= 2 || h.curated) : hits;
|
|
10476
|
+
const out = strong.length ? strong : hits;
|
|
10477
|
+
return out.sort((a, b) => b.score - a.score || a.rule.id.localeCompare(b.rule.id));
|
|
10401
10478
|
}
|
|
10402
|
-
var DEFAULT_SEARCH_STATUSES, lower;
|
|
10479
|
+
var DEFAULT_SEARCH_STATUSES, lower, rationaleOf;
|
|
10403
10480
|
var init_search = __esm({
|
|
10404
10481
|
"packages/core/dist/knowledge/search.js"() {
|
|
10405
10482
|
DEFAULT_SEARCH_STATUSES = ["active", "stale"];
|
|
10406
10483
|
lower = (xs) => (xs ?? []).map((x) => x.toLowerCase());
|
|
10484
|
+
rationaleOf = (rule2) => rule2.body.slice(rule2.statement.length).toLowerCase();
|
|
10407
10485
|
}
|
|
10408
10486
|
});
|
|
10409
10487
|
|
|
@@ -13626,6 +13704,7 @@ __export(dist_exports2, {
|
|
|
13626
13704
|
discoverCaptainSurface: () => discoverCaptainSurface,
|
|
13627
13705
|
discoverLiveOpencodeServer: () => discoverLiveOpencodeServer,
|
|
13628
13706
|
dispatchToSibling: () => dispatchToSibling,
|
|
13707
|
+
duplicateIdProblem: () => duplicateIdProblem,
|
|
13629
13708
|
encodeFrame: () => encodeFrame,
|
|
13630
13709
|
encodeMsg: () => encodeMsg,
|
|
13631
13710
|
ensureDaemon: () => ensureDaemon,
|
|
@@ -13813,6 +13892,7 @@ __export(dist_exports2, {
|
|
|
13813
13892
|
topicName: () => topicName,
|
|
13814
13893
|
tryAcquireDaemonLock: () => tryAcquireDaemonLock,
|
|
13815
13894
|
usageFromJson: () => usageFromJson,
|
|
13895
|
+
validateKb: () => validateKb,
|
|
13816
13896
|
waitForCaptainDelivery: () => waitForCaptainDelivery,
|
|
13817
13897
|
waitForWarmup: () => waitForWarmup,
|
|
13818
13898
|
writeCaptainAddress: () => writeCaptainAddress,
|
|
@@ -14464,7 +14544,7 @@ var init_drivers = __esm({
|
|
|
14464
14544
|
// packages/agents/dist/projection/cursor.js
|
|
14465
14545
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
14466
14546
|
import path19 from "path";
|
|
14467
|
-
import
|
|
14547
|
+
import os8 from "os";
|
|
14468
14548
|
function renderMdc(source) {
|
|
14469
14549
|
const skillSections = source.skills.map((s) => `## Skill: ${s.name}
|
|
14470
14550
|
|
|
@@ -14512,7 +14592,7 @@ function createCursorEmitter() {
|
|
|
14512
14592
|
if (scope === "user") {
|
|
14513
14593
|
return [
|
|
14514
14594
|
{
|
|
14515
|
-
path: path19.join(
|
|
14595
|
+
path: path19.join(os8.homedir(), ".cursor/rules/squadrant-global.mdc"),
|
|
14516
14596
|
shared: false,
|
|
14517
14597
|
format: "mdc"
|
|
14518
14598
|
}
|
|
@@ -14591,7 +14671,7 @@ var init_marker = __esm({
|
|
|
14591
14671
|
// packages/agents/dist/projection/codex.js
|
|
14592
14672
|
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
14593
14673
|
import path20 from "path";
|
|
14594
|
-
import
|
|
14674
|
+
import os9 from "os";
|
|
14595
14675
|
function renderMarkdown(source) {
|
|
14596
14676
|
const skillSections = source.skills.map((s) => `## Skill: ${s.name}
|
|
14597
14677
|
|
|
@@ -14615,7 +14695,7 @@ function createCodexEmitter() {
|
|
|
14615
14695
|
destinations(scope, projectRoot) {
|
|
14616
14696
|
if (scope === "user") {
|
|
14617
14697
|
return [{
|
|
14618
|
-
path: path20.join(
|
|
14698
|
+
path: path20.join(os9.homedir(), ".codex/AGENTS.md"),
|
|
14619
14699
|
shared: true,
|
|
14620
14700
|
format: "markdown"
|
|
14621
14701
|
}];
|
|
@@ -14663,7 +14743,7 @@ var init_codex2 = __esm({
|
|
|
14663
14743
|
// packages/agents/dist/projection/gemini.js
|
|
14664
14744
|
import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
14665
14745
|
import path21 from "path";
|
|
14666
|
-
import
|
|
14746
|
+
import os10 from "os";
|
|
14667
14747
|
function renderMarkdown2(source) {
|
|
14668
14748
|
const skillSections = source.skills.map((s) => `## Skill: ${s.name}
|
|
14669
14749
|
|
|
@@ -14687,7 +14767,7 @@ function createGeminiEmitter() {
|
|
|
14687
14767
|
destinations(scope, projectRoot) {
|
|
14688
14768
|
if (scope === "user") {
|
|
14689
14769
|
return [{
|
|
14690
|
-
path: path21.join(
|
|
14770
|
+
path: path21.join(os10.homedir(), ".gemini/GEMINI.md"),
|
|
14691
14771
|
shared: true,
|
|
14692
14772
|
format: "markdown"
|
|
14693
14773
|
}];
|
|
@@ -14735,7 +14815,7 @@ var init_gemini2 = __esm({
|
|
|
14735
14815
|
// packages/agents/dist/projection/opencode.js
|
|
14736
14816
|
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
14737
14817
|
import path22 from "path";
|
|
14738
|
-
import
|
|
14818
|
+
import os11 from "os";
|
|
14739
14819
|
function renderMarkdown3(source) {
|
|
14740
14820
|
const skillSections = source.skills.map((s) => `## Skill: ${s.name}
|
|
14741
14821
|
|
|
@@ -14759,7 +14839,7 @@ function createOpencodeEmitter() {
|
|
|
14759
14839
|
destinations(scope, projectRoot) {
|
|
14760
14840
|
if (scope === "user") {
|
|
14761
14841
|
return [{
|
|
14762
|
-
path: path22.join(
|
|
14842
|
+
path: path22.join(os11.homedir(), ".config", "opencode", "AGENTS.md"),
|
|
14763
14843
|
shared: true,
|
|
14764
14844
|
format: "markdown"
|
|
14765
14845
|
}];
|
|
@@ -14806,10 +14886,10 @@ var init_opencode2 = __esm({
|
|
|
14806
14886
|
|
|
14807
14887
|
// packages/agents/dist/projection/opencode-skills.js
|
|
14808
14888
|
import fs21 from "fs";
|
|
14809
|
-
import
|
|
14889
|
+
import os12 from "os";
|
|
14810
14890
|
import path23 from "path";
|
|
14811
14891
|
function defaultOpencodeSkillsRoot(env = process.env) {
|
|
14812
|
-
const configHome = env.XDG_CONFIG_HOME || path23.join(
|
|
14892
|
+
const configHome = env.XDG_CONFIG_HOME || path23.join(os12.homedir(), ".config");
|
|
14813
14893
|
return path23.join(configHome, "opencode", "skills");
|
|
14814
14894
|
}
|
|
14815
14895
|
function parseSkillName(raw) {
|
|
@@ -14904,7 +14984,7 @@ var init_opencode_skills = __esm({
|
|
|
14904
14984
|
// packages/agents/dist/projection/claude.js
|
|
14905
14985
|
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
14906
14986
|
import path24 from "path";
|
|
14907
|
-
import
|
|
14987
|
+
import os13 from "os";
|
|
14908
14988
|
function renderMarkdown4(source) {
|
|
14909
14989
|
const skillSections = source.skills.map((s) => `## Skill: ${s.name}
|
|
14910
14990
|
|
|
@@ -14928,7 +15008,7 @@ function createClaudeEmitter() {
|
|
|
14928
15008
|
destinations(scope, projectRoot) {
|
|
14929
15009
|
if (scope === "user") {
|
|
14930
15010
|
return [{
|
|
14931
|
-
path: path24.join(
|
|
15011
|
+
path: path24.join(os13.homedir(), ".claude/CLAUDE.md"),
|
|
14932
15012
|
shared: true,
|
|
14933
15013
|
format: "markdown"
|
|
14934
15014
|
}];
|
|
@@ -16883,13 +16963,13 @@ var init_receipt_listener = __esm({
|
|
|
16883
16963
|
|
|
16884
16964
|
// packages/agents/dist/claude/api-key-approval.js
|
|
16885
16965
|
import fs22 from "fs";
|
|
16886
|
-
import
|
|
16966
|
+
import os14 from "os";
|
|
16887
16967
|
import path25 from "path";
|
|
16888
16968
|
function ensureClaudeApiKeyApproved(apiKey, opts = {}) {
|
|
16889
16969
|
const suffix = apiKey.slice(-20);
|
|
16890
16970
|
if (!suffix)
|
|
16891
16971
|
return { changed: false, reason: "empty api key" };
|
|
16892
|
-
const file = opts.claudeJsonPath ?? path25.join(
|
|
16972
|
+
const file = opts.claudeJsonPath ?? path25.join(os14.homedir(), ".claude.json");
|
|
16893
16973
|
const log = opts.log ?? (() => {
|
|
16894
16974
|
});
|
|
16895
16975
|
if (!fs22.existsSync(file)) {
|
|
@@ -19483,6 +19563,20 @@ var init_runtime2 = __esm({
|
|
|
19483
19563
|
}
|
|
19484
19564
|
});
|
|
19485
19565
|
|
|
19566
|
+
// packages/cli/src/lib/suppress-sqlite-warning.ts
|
|
19567
|
+
function isSqliteExperimentalWarning(warning, type2) {
|
|
19568
|
+
const name = typeof warning === "object" && warning !== null ? warning.name : typeof type2 === "string" ? type2 : void 0;
|
|
19569
|
+
const message = typeof warning === "string" ? warning : warning?.message;
|
|
19570
|
+
return name === "ExperimentalWarning" && typeof message === "string" && /SQLite is an experimental feature/i.test(message);
|
|
19571
|
+
}
|
|
19572
|
+
var original = process.emitWarning.bind(process);
|
|
19573
|
+
process.emitWarning = ((warning, ...rest) => {
|
|
19574
|
+
const first = rest[0];
|
|
19575
|
+
const type2 = typeof first === "string" ? first : first?.type;
|
|
19576
|
+
if (isSqliteExperimentalWarning(warning, type2)) return;
|
|
19577
|
+
original(warning, ...rest);
|
|
19578
|
+
});
|
|
19579
|
+
|
|
19486
19580
|
// packages/cli/src/index.ts
|
|
19487
19581
|
init_dist();
|
|
19488
19582
|
init_dist2();
|
|
@@ -19931,7 +20025,7 @@ init_dist();
|
|
|
19931
20025
|
import { Command as Command2 } from "commander";
|
|
19932
20026
|
import fs25 from "fs";
|
|
19933
20027
|
import path28 from "path";
|
|
19934
|
-
import
|
|
20028
|
+
import os15 from "os";
|
|
19935
20029
|
import readline from "readline";
|
|
19936
20030
|
import chalk4 from "chalk";
|
|
19937
20031
|
|
|
@@ -20238,7 +20332,7 @@ function warnIfNoAnthropic(preset, auth) {
|
|
|
20238
20332
|
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) => {
|
|
20239
20333
|
const hubPath = resolveHome(opts.hub);
|
|
20240
20334
|
const pkgRoot = findPackageRoot();
|
|
20241
|
-
const configDir = path28.join(
|
|
20335
|
+
const configDir = path28.join(os15.homedir(), ".config", "squadrant");
|
|
20242
20336
|
const isTTY = process.stdin.isTTY === true;
|
|
20243
20337
|
console.log(chalk4.bold("\nSquadrant Init\n"));
|
|
20244
20338
|
let explicitPreset;
|
|
@@ -20343,7 +20437,7 @@ var initCommand = new Command2("init").description("Guided first-time setup: pro
|
|
|
20343
20437
|
ensureRuntimeSynced({ sourceRoot: pkgRoot, runtimeRoot: configDir });
|
|
20344
20438
|
console.log(chalk4.green(` \u2714 Runtime assets synced to ${configDir}`));
|
|
20345
20439
|
stepHeader(2, 5, "Agent + projection setup");
|
|
20346
|
-
const settingsPath = path28.join(
|
|
20440
|
+
const settingsPath = path28.join(os15.homedir(), ".claude", "settings.json");
|
|
20347
20441
|
try {
|
|
20348
20442
|
let settings = {};
|
|
20349
20443
|
if (fs25.existsSync(settingsPath)) {
|
|
@@ -20649,9 +20743,9 @@ init_dist();
|
|
|
20649
20743
|
import { Command as Command5 } from "commander";
|
|
20650
20744
|
import { execSync as execSync9 } from "child_process";
|
|
20651
20745
|
import path30 from "path";
|
|
20652
|
-
import
|
|
20746
|
+
import os16 from "os";
|
|
20653
20747
|
import chalk7 from "chalk";
|
|
20654
|
-
var TEMPLATES_DIR2 = path30.join(
|
|
20748
|
+
var TEMPLATES_DIR2 = path30.join(os16.homedir(), ".config", "squadrant", "templates");
|
|
20655
20749
|
var TASK_PROMPTS = {
|
|
20656
20750
|
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.",
|
|
20657
20751
|
"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.",
|
|
@@ -21982,9 +22076,9 @@ init_dist2();
|
|
|
21982
22076
|
import { Command as Command12 } from "commander";
|
|
21983
22077
|
import fs27 from "fs";
|
|
21984
22078
|
import path31 from "path";
|
|
21985
|
-
import
|
|
22079
|
+
import os17 from "os";
|
|
21986
22080
|
import chalk12 from "chalk";
|
|
21987
|
-
var TEMPLATES_DIR3 = path31.join(
|
|
22081
|
+
var TEMPLATES_DIR3 = path31.join(os17.homedir(), ".config", "squadrant", "templates");
|
|
21988
22082
|
async function runSideSpawn2(input) {
|
|
21989
22083
|
const config = loadConfig();
|
|
21990
22084
|
const proj = config.projects[input.project];
|
|
@@ -23631,7 +23725,7 @@ import { Command as Command14 } from "commander";
|
|
|
23631
23725
|
import { execSync as execSync11, execFileSync as execFileSync11 } from "child_process";
|
|
23632
23726
|
import fs29 from "fs";
|
|
23633
23727
|
import path33 from "path";
|
|
23634
|
-
import
|
|
23728
|
+
import os18 from "os";
|
|
23635
23729
|
import chalk15 from "chalk";
|
|
23636
23730
|
|
|
23637
23731
|
// packages/cli/src/commands/launch-interactive.ts
|
|
@@ -23723,8 +23817,8 @@ function resolveLaunchBackend(o) {
|
|
|
23723
23817
|
// packages/cli/src/commands/launch.ts
|
|
23724
23818
|
init_dist2();
|
|
23725
23819
|
var CMUX_APP = "/Applications/cmux.app";
|
|
23726
|
-
var TEMPLATES_DIR4 = path33.join(
|
|
23727
|
-
var SESSIONS_PATH2 = path33.join(
|
|
23820
|
+
var TEMPLATES_DIR4 = path33.join(os18.homedir(), ".config", "squadrant", "templates");
|
|
23821
|
+
var SESSIONS_PATH2 = path33.join(os18.homedir(), ".config", "squadrant", "sessions.json");
|
|
23728
23822
|
function shouldWireCaptainChannel(agentName, config) {
|
|
23729
23823
|
return agentName === "claude" && resolveCaptainChannelMode(config.defaults) !== "off";
|
|
23730
23824
|
}
|
|
@@ -23821,7 +23915,7 @@ var launchCommand = new Command14("launch").description(
|
|
|
23821
23915
|
initialPrompt = "Run your startup checklist: use the squadrant:command-ops skill, complete your daily briefing, then report ready.";
|
|
23822
23916
|
}
|
|
23823
23917
|
const runtime = projectName ? runtimes.forProject(projectName, config) : runtimes.global(config);
|
|
23824
|
-
const stateRoot = path33.join(
|
|
23918
|
+
const stateRoot = path33.join(os18.homedir(), ".config", "squadrant", "state");
|
|
23825
23919
|
const isOpencodeCaptain = role === "captain" && agentName === "opencode" && !!projectName;
|
|
23826
23920
|
if (isOpencodeCaptain && !isOpencodeCaptainDir(cwd)) {
|
|
23827
23921
|
console.error(chalk15.red(`
|
|
@@ -24178,7 +24272,7 @@ Shutting down captain workspace for '${project}'...
|
|
|
24178
24272
|
init_dist();
|
|
24179
24273
|
import { Command as Command16 } from "commander";
|
|
24180
24274
|
import fs30 from "fs";
|
|
24181
|
-
import
|
|
24275
|
+
import os19 from "os";
|
|
24182
24276
|
import path34 from "path";
|
|
24183
24277
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
24184
24278
|
import { execSync as execSync12 } from "child_process";
|
|
@@ -24232,7 +24326,7 @@ function buildIssueUrl(metrics, squadrantVersion) {
|
|
|
24232
24326
|
}
|
|
24233
24327
|
var feedbackCommand = new Command16("feedback").description("Open a pre-filled GitHub issue for feedback or bug reports").action(() => {
|
|
24234
24328
|
const config = loadConfig();
|
|
24235
|
-
const metricsPath = config.metrics?.path || path34.join(
|
|
24329
|
+
const metricsPath = config.metrics?.path || path34.join(os19.homedir(), ".config", "squadrant", "metrics.json");
|
|
24236
24330
|
const metrics = readMetrics(metricsPath);
|
|
24237
24331
|
const version = readStamp(config) ?? readPkgVersion();
|
|
24238
24332
|
const issueUrl = buildIssueUrl(metrics, version);
|
|
@@ -25638,11 +25732,11 @@ var effortCommand = new Command29("effort").description("Get or set the crew tok
|
|
|
25638
25732
|
init_dist();
|
|
25639
25733
|
import fs35 from "fs";
|
|
25640
25734
|
import path37 from "path";
|
|
25641
|
-
import
|
|
25735
|
+
import os20 from "os";
|
|
25642
25736
|
import readline3 from "readline";
|
|
25643
25737
|
import { Command as Command30 } from "commander";
|
|
25644
25738
|
import chalk31 from "chalk";
|
|
25645
|
-
var CLAUDE_PROJECTS_DIR = path37.join(
|
|
25739
|
+
var CLAUDE_PROJECTS_DIR = path37.join(os20.homedir(), ".claude", "projects");
|
|
25646
25740
|
function parseTranscriptLine(rawLine) {
|
|
25647
25741
|
const line = rawLine.trim();
|
|
25648
25742
|
if (!line) return { timestamp: null, usage: null };
|
|
@@ -26846,7 +26940,7 @@ var workCommand = new Command34("work").description("Track your own in-flight wo
|
|
|
26846
26940
|
init_dist();
|
|
26847
26941
|
import { Command as Command35 } from "commander";
|
|
26848
26942
|
import path42 from "path";
|
|
26849
|
-
import
|
|
26943
|
+
import os21 from "os";
|
|
26850
26944
|
|
|
26851
26945
|
// packages/cli/src/lib/handoff-live-repo.ts
|
|
26852
26946
|
init_dist();
|
|
@@ -27258,7 +27352,7 @@ function readNewestArchivedHandoff(spokeVault, now) {
|
|
|
27258
27352
|
}
|
|
27259
27353
|
|
|
27260
27354
|
// packages/cli/src/commands/handoff.ts
|
|
27261
|
-
var CLAUDE_MEM_DB_PATH = path42.join(
|
|
27355
|
+
var CLAUDE_MEM_DB_PATH = path42.join(os21.homedir(), ".claude-mem", "claude-mem.db");
|
|
27262
27356
|
async function defaultFetchTasks(project) {
|
|
27263
27357
|
return await squadrantdCall({ kind: "list", project });
|
|
27264
27358
|
}
|
|
@@ -27418,7 +27512,7 @@ var sessionsCommand = new Command36("sessions").description("List live agent ses
|
|
|
27418
27512
|
init_dist();
|
|
27419
27513
|
init_dist2();
|
|
27420
27514
|
init_dist3();
|
|
27421
|
-
import
|
|
27515
|
+
import os22 from "os";
|
|
27422
27516
|
import path43 from "path";
|
|
27423
27517
|
import { Command as Command37 } from "commander";
|
|
27424
27518
|
import chalk36 from "chalk";
|
|
@@ -27537,7 +27631,7 @@ function buildWhoamiDeps(opts = {}) {
|
|
|
27537
27631
|
const projects = Object.fromEntries(
|
|
27538
27632
|
Object.entries(config.projects).map(([n, p]) => [n, resolveHome(p.path)])
|
|
27539
27633
|
);
|
|
27540
|
-
const root = stateRoot ?? path43.join(
|
|
27634
|
+
const root = stateRoot ?? path43.join(os22.homedir(), ".config", "squadrant", "state");
|
|
27541
27635
|
const store = createStore(root);
|
|
27542
27636
|
const merged = {
|
|
27543
27637
|
env: process.env,
|
|
@@ -27668,13 +27762,33 @@ function runKnowledgeReindex(kb, configPath = DEFAULT_CONFIG_PATH) {
|
|
|
27668
27762
|
const cfg = loadConfig(configPath);
|
|
27669
27763
|
const hub = resolveHome(cfg.hubVault);
|
|
27670
27764
|
if (!fs41.existsSync(kbDir(hub, kb))) throw new Error(`Knowledge base '${kb}' does not exist. Run: squadrant knowledge init ${kb}`);
|
|
27671
|
-
const { rules, errors } = loadKbRules(cfg, kb);
|
|
27672
|
-
const
|
|
27673
|
-
|
|
27765
|
+
const { rules: all, errors } = loadKbRules(cfg, kb, { includeProposed: true });
|
|
27766
|
+
const proposedRoot = path44.join(kbRulesDir(hub, kb), PROPOSED_DIR) + path44.sep;
|
|
27767
|
+
const live = all.filter((r) => !r.file.startsWith(proposedRoot));
|
|
27768
|
+
const file = writeIndex(hub, kb, compileIndex(kb, live));
|
|
27769
|
+
return { file, count: live.length, proposed: all.length - live.length, errors: errors.length, invalid: errors };
|
|
27770
|
+
}
|
|
27771
|
+
function runKnowledgeValidate(kb, configPath = DEFAULT_CONFIG_PATH) {
|
|
27772
|
+
assertKbName(kb);
|
|
27773
|
+
const cfg = loadConfig(configPath);
|
|
27774
|
+
const hub = resolveHome(cfg.hubVault);
|
|
27775
|
+
if (!fs41.existsSync(kbDir(hub, kb))) throw new Error(`Knowledge base '${kb}' does not exist. Run: squadrant knowledge init ${kb}`);
|
|
27776
|
+
const { sources, errors } = loadSources(hub, kb);
|
|
27777
|
+
const res = validateKb({ rulesDir: kbRulesDir(hub, kb), kbRoot: kbDir(hub, kb), sources, domains: cfg.knowledge?.[kb]?.domains });
|
|
27778
|
+
const srcChecks = errors.map((e) => ({ level: "fail", message: `sources.yaml: ${e}` }));
|
|
27779
|
+
return { checks: [...srcChecks, ...res.checks], ok: res.ok && !errors.length };
|
|
27674
27780
|
}
|
|
27675
27781
|
knowledgeCommand.command("reindex <kb>").description("Recompile index.json from the KB's rule files").action((kb) => {
|
|
27676
27782
|
const r = runKnowledgeReindex(kb);
|
|
27677
|
-
console.log(`${r.file}: ${r.count}
|
|
27783
|
+
console.log(`${r.file}: ${r.count} active${r.proposed ? ` (+${r.proposed} proposed)` : ""}${r.errors ? chalk37.red(`, ${r.errors} invalid files skipped`) : ""}`);
|
|
27784
|
+
for (const e of r.invalid) console.log(chalk37.red(` \u2718 ${e.file}: ${e.problems.join("; ")}`));
|
|
27785
|
+
});
|
|
27786
|
+
knowledgeCommand.command("validate <kb>").description("CI-style check: invalid files, duplicate ids, quotes present in sources; exits non-zero on failure").action((kb) => {
|
|
27787
|
+
const { checks, ok: ok2 } = runKnowledgeValidate(kb);
|
|
27788
|
+
const mark2 = { ok: chalk37.green("\u2714"), fail: chalk37.red("\u2718"), warn: chalk37.yellow("!"), skip: chalk37.dim("-") };
|
|
27789
|
+
for (const c of checks) console.log(`${mark2[c.level]} ${c.message}`);
|
|
27790
|
+
console.log(ok2 ? chalk37.green("valid") : chalk37.red("invalid"));
|
|
27791
|
+
if (!ok2) process.exitCode = 1;
|
|
27678
27792
|
});
|
|
27679
27793
|
|
|
27680
27794
|
// packages/cli/src/commands/rules.ts
|
|
@@ -27682,6 +27796,7 @@ init_dist();
|
|
|
27682
27796
|
init_dist2();
|
|
27683
27797
|
import { Command as Command39 } from "commander";
|
|
27684
27798
|
import chalk38 from "chalk";
|
|
27799
|
+
var DEFAULT_SEARCH_LIMIT = 5;
|
|
27685
27800
|
function resolveRulesProject(cfg, opts) {
|
|
27686
27801
|
const env = opts.env ?? process.env;
|
|
27687
27802
|
const name = opts.project ?? env.SQUADRANT_CREW_PROJECT ?? detectCurrentProject(cfg, opts.cwd ?? process.cwd());
|
|
@@ -27697,6 +27812,32 @@ function formatRule(rule2) {
|
|
|
27697
27812
|
` source: ${src}`
|
|
27698
27813
|
].join("\n");
|
|
27699
27814
|
}
|
|
27815
|
+
function formatBrief(rule2) {
|
|
27816
|
+
return `${rule2.modality.toUpperCase()} ${rule2.id}: ${rule2.statement}`;
|
|
27817
|
+
}
|
|
27818
|
+
function parseLimit(raw) {
|
|
27819
|
+
if (raw === void 0) return DEFAULT_SEARCH_LIMIT;
|
|
27820
|
+
const n = Number(raw);
|
|
27821
|
+
if (!Number.isInteger(n) || n < 1) throw new Error(`--limit must be a positive integer, got '${raw}'`);
|
|
27822
|
+
return n;
|
|
27823
|
+
}
|
|
27824
|
+
function renderSearch(hits, opts) {
|
|
27825
|
+
if (!hits.length) return ["(no matching rules)"];
|
|
27826
|
+
const limit = parseLimit(opts.limit);
|
|
27827
|
+
const shown = hits.slice(0, limit);
|
|
27828
|
+
const lines = shown.map((h) => opts.idsOnly ? h.rule.id : opts.brief ? `[${h.score}] ${formatBrief(h.rule)}` : `${formatRule(h.rule)}
|
|
27829
|
+
score: ${h.score}
|
|
27830
|
+
`);
|
|
27831
|
+
const more = hits.length - shown.length;
|
|
27832
|
+
if (more > 0) lines.push(`(+${more} more; use --limit)`);
|
|
27833
|
+
return lines;
|
|
27834
|
+
}
|
|
27835
|
+
function renderList2(rules, opts) {
|
|
27836
|
+
if (!rules.length) return ["(no rules)"];
|
|
27837
|
+
const sorted = [...rules].sort((a, b) => a.id.localeCompare(b.id));
|
|
27838
|
+
return sorted.map((r) => opts.brief ? formatBrief(r) : `${formatBrief(r)}
|
|
27839
|
+
${r.status} \xB7 ${r.layer}`);
|
|
27840
|
+
}
|
|
27700
27841
|
function loadFor(opts, configPath) {
|
|
27701
27842
|
const cfg = loadConfig(configPath);
|
|
27702
27843
|
const project = resolveRulesProject(cfg, opts);
|
|
@@ -27709,6 +27850,10 @@ function runRulesSearch(query, opts, configPath = DEFAULT_CONFIG_PATH) {
|
|
|
27709
27850
|
const rules = loadFor(opts, configPath);
|
|
27710
27851
|
return searchRules(rules, query, { statuses: opts.all ? [...RULE_STATUSES] : DEFAULT_SEARCH_STATUSES });
|
|
27711
27852
|
}
|
|
27853
|
+
function runRulesList(opts, configPath = DEFAULT_CONFIG_PATH) {
|
|
27854
|
+
const statuses = opts.all ? RULE_STATUSES : DEFAULT_SEARCH_STATUSES;
|
|
27855
|
+
return loadFor(opts, configPath).filter((r) => statuses.includes(r.status));
|
|
27856
|
+
}
|
|
27712
27857
|
function runRulesShow(id, opts, configPath = DEFAULT_CONFIG_PATH) {
|
|
27713
27858
|
const rules = loadFor(opts, configPath);
|
|
27714
27859
|
const statuses = opts.all ? RULE_STATUSES : DEFAULT_SEARCH_STATUSES;
|
|
@@ -27717,13 +27862,12 @@ function runRulesShow(id, opts, configPath = DEFAULT_CONFIG_PATH) {
|
|
|
27717
27862
|
return rule2;
|
|
27718
27863
|
}
|
|
27719
27864
|
var rulesCommand = new Command39("rules").description("Look up rules from subscribed knowledge bases (#893)");
|
|
27720
|
-
rulesCommand.command("search <query...>").description("Search rules by keyword").option("--project <name>", "project (default: from cwd or SQUADRANT_CREW_PROJECT)").option("--all", "include proposed and retired rules").action((query, opts) => {
|
|
27865
|
+
rulesCommand.command("search <query...>").description("Search rules by keyword (ranked; best match first)").option("--project <name>", "project (default: from cwd or SQUADRANT_CREW_PROJECT)").option("--all", "include proposed and retired rules").option("--limit <n>", `max results (default ${DEFAULT_SEARCH_LIMIT})`).option("--brief", "one line per rule: [score] MODALITY id: statement").option("--ids-only", "print only rule ids").action((query, opts) => {
|
|
27721
27866
|
const hits = runRulesSearch(query.join(" "), opts);
|
|
27722
|
-
|
|
27723
|
-
|
|
27724
|
-
|
|
27725
|
-
|
|
27726
|
-
for (const h of hits) console.log(formatRule(h.rule) + "\n");
|
|
27867
|
+
for (const line of renderSearch(hits, opts)) console.log(line);
|
|
27868
|
+
});
|
|
27869
|
+
rulesCommand.command("list").description("List every resolved rule for the project").option("--project <name>", "project (default: from cwd or SQUADRANT_CREW_PROJECT)").option("--all", "include proposed and retired rules").option("--brief", "one line per rule: MODALITY id: statement").action((opts) => {
|
|
27870
|
+
for (const line of renderList2(runRulesList(opts), opts)) console.log(line);
|
|
27727
27871
|
});
|
|
27728
27872
|
rulesCommand.command("show <ids...>").description("Show one or more rules in full").option("--project <name>", "project (default: from cwd or SQUADRANT_CREW_PROJECT)").option("--all", "include proposed and retired rules").action((ids, opts) => {
|
|
27729
27873
|
for (const id of ids) {
|