squadrant 0.16.0 → 0.16.2
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 +228 -150
- package/dist/index.js.map +1 -1
- package/dist/squadrantd.js +55 -41
- package/dist/squadrantd.js.map +1 -1
- package/package.json +3 -2
- package/plugin/skills/captain-ops/SKILL.md +1 -1
- package/scripts/heavy-lock.mjs +129 -0
package/dist/index.js
CHANGED
|
@@ -744,6 +744,7 @@ var init_update_check = __esm({
|
|
|
744
744
|
|
|
745
745
|
// packages/shared/dist/lib/git-worktree.js
|
|
746
746
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
747
|
+
import fs4 from "fs";
|
|
747
748
|
import path4 from "path";
|
|
748
749
|
function worktreePath(repoRoot, worktreeDir, project, name) {
|
|
749
750
|
return path4.resolve(repoRoot, worktreeDir, `${project}-${name}`);
|
|
@@ -751,6 +752,18 @@ function worktreePath(repoRoot, worktreeDir, project, name) {
|
|
|
751
752
|
function crewBranch(name) {
|
|
752
753
|
return `crew/${name}`;
|
|
753
754
|
}
|
|
755
|
+
function ensureSpotlightExcluded(repoRoot, worktreeDir) {
|
|
756
|
+
if (process.platform !== "darwin")
|
|
757
|
+
return;
|
|
758
|
+
try {
|
|
759
|
+
const dir = path4.resolve(repoRoot, worktreeDir);
|
|
760
|
+
fs4.mkdirSync(dir, { recursive: true });
|
|
761
|
+
const marker = path4.join(dir, ".metadata_never_index");
|
|
762
|
+
if (!fs4.existsSync(marker))
|
|
763
|
+
fs4.writeFileSync(marker, "");
|
|
764
|
+
} catch {
|
|
765
|
+
}
|
|
766
|
+
}
|
|
754
767
|
function resolveWorktreeBase(repoRoot, fallback = "develop") {
|
|
755
768
|
try {
|
|
756
769
|
const ref = execFileSync2("git", ["-C", repoRoot, "symbolic-ref", "refs/remotes/origin/HEAD"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
@@ -763,6 +776,7 @@ function resolveWorktreeBase(repoRoot, fallback = "develop") {
|
|
|
763
776
|
return fallback;
|
|
764
777
|
}
|
|
765
778
|
function addWorktree(spec) {
|
|
779
|
+
ensureSpotlightExcluded(spec.repoRoot, spec.worktreeDir);
|
|
766
780
|
const originalBranch = crewBranch(spec.name);
|
|
767
781
|
let targetName = spec.name;
|
|
768
782
|
let targetBranch = originalBranch;
|
|
@@ -798,8 +812,25 @@ function addWorktree(spec) {
|
|
|
798
812
|
}
|
|
799
813
|
const wt = worktreePath(spec.repoRoot, spec.worktreeDir, spec.project, targetName);
|
|
800
814
|
execFileSync2("git", ["-C", spec.repoRoot, "worktree", "add", wt, "-b", targetBranch, spec.base], { stdio: "pipe" });
|
|
815
|
+
installWorktreeDependencies(wt);
|
|
801
816
|
return wt;
|
|
802
817
|
}
|
|
818
|
+
function installWorktreeDependencies(wt) {
|
|
819
|
+
if (!fs4.existsSync(path4.join(wt, "package.json")))
|
|
820
|
+
return;
|
|
821
|
+
if (fs4.existsSync(path4.join(wt, "pnpm-lock.yaml"))) {
|
|
822
|
+
execFileSync2("pnpm", ["-C", wt, "install", "--frozen-lockfile"], { stdio: "pipe" });
|
|
823
|
+
} else if (fs4.existsSync(path4.join(wt, "yarn.lock"))) {
|
|
824
|
+
execFileSync2("yarn", ["install", "--frozen-lockfile"], { cwd: wt, stdio: "pipe" });
|
|
825
|
+
} else if (fs4.existsSync(path4.join(wt, "package-lock.json"))) {
|
|
826
|
+
execFileSync2("npm", ["ci"], { cwd: wt, stdio: "pipe" });
|
|
827
|
+
} else if (fs4.existsSync(path4.join(wt, "bun.lockb"))) {
|
|
828
|
+
execFileSync2("bun", ["install", "--frozen-lockfile"], { cwd: wt, stdio: "pipe" });
|
|
829
|
+
} else {
|
|
830
|
+
process.stderr.write(`worktree ${wt}: package.json present but no lockfile \u2014 dependencies not installed; local typechecks/tests may resolve against the main checkout instead of this worktree.
|
|
831
|
+
`);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
803
834
|
function removeWorktree(repoRoot, wtPath) {
|
|
804
835
|
try {
|
|
805
836
|
execFileSync2("git", ["-C", repoRoot, "worktree", "remove", wtPath], { stdio: "pipe" });
|
|
@@ -813,7 +844,7 @@ var init_git_worktree = __esm({
|
|
|
813
844
|
});
|
|
814
845
|
|
|
815
846
|
// packages/shared/dist/lib/resolve-text-input.js
|
|
816
|
-
import
|
|
847
|
+
import fs5 from "fs";
|
|
817
848
|
async function readAllStdin() {
|
|
818
849
|
const chunks = [];
|
|
819
850
|
for await (const chunk of process.stdin) {
|
|
@@ -825,7 +856,7 @@ function flagName(label) {
|
|
|
825
856
|
return label === "task" ? "--task-file" : "--message-file";
|
|
826
857
|
}
|
|
827
858
|
async function resolveTextInput(opts, deps) {
|
|
828
|
-
const readFile6 = deps?.readFile ?? ((p) =>
|
|
859
|
+
const readFile6 = deps?.readFile ?? ((p) => fs5.readFileSync(p, "utf8"));
|
|
829
860
|
const readStdin3 = deps?.readStdin ?? readAllStdin;
|
|
830
861
|
if (opts.filePath) {
|
|
831
862
|
if (opts.filePath === "-") {
|
|
@@ -853,19 +884,19 @@ var init_resolve_text_input = __esm({
|
|
|
853
884
|
});
|
|
854
885
|
|
|
855
886
|
// packages/shared/dist/lib/runtime-sync.js
|
|
856
|
-
import
|
|
887
|
+
import fs6 from "fs";
|
|
857
888
|
import path5 from "path";
|
|
858
889
|
function copyIfDifferent(src, dest) {
|
|
859
|
-
if (
|
|
860
|
-
if (
|
|
890
|
+
if (fs6.existsSync(dest)) {
|
|
891
|
+
if (fs6.readFileSync(src).equals(fs6.readFileSync(dest)))
|
|
861
892
|
return false;
|
|
862
893
|
}
|
|
863
|
-
|
|
894
|
+
fs6.copyFileSync(src, dest);
|
|
864
895
|
return true;
|
|
865
896
|
}
|
|
866
897
|
function mirrorDir(src, dest) {
|
|
867
|
-
|
|
868
|
-
const srcEntries =
|
|
898
|
+
fs6.mkdirSync(dest, { recursive: true });
|
|
899
|
+
const srcEntries = fs6.readdirSync(src, { withFileTypes: true });
|
|
869
900
|
const srcNames = new Set(srcEntries.map((e) => e.name));
|
|
870
901
|
for (const entry of srcEntries) {
|
|
871
902
|
const srcPath = path5.join(src, entry.name);
|
|
@@ -876,25 +907,25 @@ function mirrorDir(src, dest) {
|
|
|
876
907
|
copyIfDifferent(srcPath, destPath);
|
|
877
908
|
}
|
|
878
909
|
}
|
|
879
|
-
for (const entry of
|
|
910
|
+
for (const entry of fs6.readdirSync(dest, { withFileTypes: true })) {
|
|
880
911
|
if (!srcNames.has(entry.name)) {
|
|
881
|
-
|
|
912
|
+
fs6.rmSync(path5.join(dest, entry.name), { recursive: true, force: true });
|
|
882
913
|
}
|
|
883
914
|
}
|
|
884
915
|
}
|
|
885
916
|
function mirrorFlat(src, dest, match, chmod) {
|
|
886
|
-
|
|
887
|
-
const matched =
|
|
917
|
+
fs6.mkdirSync(dest, { recursive: true });
|
|
918
|
+
const matched = fs6.readdirSync(src, { withFileTypes: true }).filter((e) => e.isFile() && match.test(e.name)).map((e) => e.name);
|
|
888
919
|
const matchedSet = new Set(matched);
|
|
889
920
|
for (const name of matched) {
|
|
890
921
|
const destPath = path5.join(dest, name);
|
|
891
922
|
const copied = copyIfDifferent(path5.join(src, name), destPath);
|
|
892
923
|
if (copied && chmod !== void 0)
|
|
893
|
-
|
|
924
|
+
fs6.chmodSync(destPath, chmod);
|
|
894
925
|
}
|
|
895
|
-
for (const entry of
|
|
926
|
+
for (const entry of fs6.readdirSync(dest, { withFileTypes: true })) {
|
|
896
927
|
if (!matchedSet.has(entry.name)) {
|
|
897
|
-
|
|
928
|
+
fs6.rmSync(path5.join(dest, entry.name), { recursive: true, force: true });
|
|
898
929
|
}
|
|
899
930
|
}
|
|
900
931
|
}
|
|
@@ -903,7 +934,7 @@ function ensureRuntimeSynced(opts) {
|
|
|
903
934
|
for (const t of targets) {
|
|
904
935
|
const srcDir = path5.join(opts.sourceRoot, t.srcRel);
|
|
905
936
|
try {
|
|
906
|
-
if (!
|
|
937
|
+
if (!fs6.existsSync(srcDir))
|
|
907
938
|
continue;
|
|
908
939
|
const destDir = path5.join(opts.runtimeRoot, t.name);
|
|
909
940
|
if (t.mode === "tree") {
|
|
@@ -969,7 +1000,7 @@ var init_tool_compat = __esm({
|
|
|
969
1000
|
});
|
|
970
1001
|
|
|
971
1002
|
// packages/shared/dist/lib/canonical-source.js
|
|
972
|
-
import
|
|
1003
|
+
import fs7 from "fs";
|
|
973
1004
|
import path6 from "path";
|
|
974
1005
|
function parseSkill(raw) {
|
|
975
1006
|
const match = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
|
@@ -1011,7 +1042,7 @@ async function readSkills(driver, skillsDir) {
|
|
|
1011
1042
|
function readRoleTemplates(opts) {
|
|
1012
1043
|
if (!opts.pkgRoot)
|
|
1013
1044
|
return "";
|
|
1014
|
-
const reader = opts.readFile ?? ((p) =>
|
|
1045
|
+
const reader = opts.readFile ?? ((p) => fs7.readFileSync(p, "utf-8"));
|
|
1015
1046
|
const sections = [];
|
|
1016
1047
|
for (const { file, heading } of ROLE_TEMPLATES) {
|
|
1017
1048
|
const full = path6.join(opts.pkgRoot, "templates", file);
|
|
@@ -1051,7 +1082,7 @@ var init_canonical_source = __esm({
|
|
|
1051
1082
|
|
|
1052
1083
|
// packages/shared/dist/lib/daily-logs.js
|
|
1053
1084
|
import { execSync } from "child_process";
|
|
1054
|
-
import
|
|
1085
|
+
import fs8 from "fs";
|
|
1055
1086
|
import path7 from "path";
|
|
1056
1087
|
import matter from "gray-matter";
|
|
1057
1088
|
function iso(d) {
|
|
@@ -1104,7 +1135,7 @@ function getGitCommits(projectPath, dateStr) {
|
|
|
1104
1135
|
}
|
|
1105
1136
|
function getGitCommitsInRange(projectPath, since, until) {
|
|
1106
1137
|
const resolved = resolveHome(projectPath);
|
|
1107
|
-
if (!
|
|
1138
|
+
if (!fs8.existsSync(path7.join(resolved, ".git")))
|
|
1108
1139
|
return [];
|
|
1109
1140
|
const untilArg = until ? ` --until="${until}"` : "";
|
|
1110
1141
|
try {
|
|
@@ -1118,7 +1149,7 @@ function getGitCommitsInRange(projectPath, since, until) {
|
|
|
1118
1149
|
}
|
|
1119
1150
|
function getMergedPRsInRange(projectPath, since, until) {
|
|
1120
1151
|
const resolved = resolveHome(projectPath);
|
|
1121
|
-
if (!
|
|
1152
|
+
if (!fs8.existsSync(path7.join(resolved, ".git")))
|
|
1122
1153
|
return [];
|
|
1123
1154
|
const untilArg = until ? ` --until="${until}"` : "";
|
|
1124
1155
|
try {
|
|
@@ -1830,7 +1861,7 @@ var init_reduce = __esm({
|
|
|
1830
1861
|
});
|
|
1831
1862
|
|
|
1832
1863
|
// packages/core/dist/mailbox.js
|
|
1833
|
-
import { promises as
|
|
1864
|
+
import { promises as fs9 } from "fs";
|
|
1834
1865
|
import { join as join5 } from "path";
|
|
1835
1866
|
import { randomUUID } from "crypto";
|
|
1836
1867
|
function inboxDir(stateRoot) {
|
|
@@ -1847,7 +1878,7 @@ async function listRotatedOldestFirst(stateRoot, project) {
|
|
|
1847
1878
|
const dir = inboxDir(stateRoot);
|
|
1848
1879
|
let entries;
|
|
1849
1880
|
try {
|
|
1850
|
-
entries = await
|
|
1881
|
+
entries = await fs9.readdir(dir);
|
|
1851
1882
|
} catch {
|
|
1852
1883
|
return [];
|
|
1853
1884
|
}
|
|
@@ -1856,7 +1887,7 @@ async function listRotatedOldestFirst(stateRoot, project) {
|
|
|
1856
1887
|
}
|
|
1857
1888
|
async function readMaxSeqFromFile(file) {
|
|
1858
1889
|
try {
|
|
1859
|
-
const buf = await
|
|
1890
|
+
const buf = await fs9.readFile(file, "utf-8");
|
|
1860
1891
|
if (!buf.trim())
|
|
1861
1892
|
return 0;
|
|
1862
1893
|
const lines = buf.trim().split("\n");
|
|
@@ -1897,12 +1928,12 @@ function withProjectLock(project, fn) {
|
|
|
1897
1928
|
function appendEntry(stateRoot, project, build) {
|
|
1898
1929
|
return withProjectLock(project, async () => {
|
|
1899
1930
|
const dir = inboxDir(stateRoot);
|
|
1900
|
-
await
|
|
1931
|
+
await fs9.mkdir(dir, { recursive: true });
|
|
1901
1932
|
const file = logPath(stateRoot, project);
|
|
1902
1933
|
const lastSeq = await readMaxSeq(stateRoot, project);
|
|
1903
1934
|
const seq = lastSeq + 1;
|
|
1904
1935
|
const entry = build(seq);
|
|
1905
|
-
await
|
|
1936
|
+
await fs9.appendFile(file, JSON.stringify(entry) + "\n", { encoding: "utf-8" });
|
|
1906
1937
|
return seq;
|
|
1907
1938
|
});
|
|
1908
1939
|
}
|
|
@@ -1919,7 +1950,7 @@ async function appendToMailbox(opts) {
|
|
|
1919
1950
|
}));
|
|
1920
1951
|
}
|
|
1921
1952
|
async function appendCaptainMessage(opts) {
|
|
1922
|
-
|
|
1953
|
+
return appendEntry(opts.stateRoot, opts.project, (seq) => ({
|
|
1923
1954
|
seq,
|
|
1924
1955
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1925
1956
|
kind: "captain.message",
|
|
@@ -1933,7 +1964,7 @@ function cursorPath(stateRoot, project, subscriber) {
|
|
|
1933
1964
|
async function readCursor(opts) {
|
|
1934
1965
|
let buf;
|
|
1935
1966
|
try {
|
|
1936
|
-
buf = await
|
|
1967
|
+
buf = await fs9.readFile(cursorPath(opts.stateRoot, opts.project, opts.subscriber), "utf-8");
|
|
1937
1968
|
} catch (e) {
|
|
1938
1969
|
if (e.code === "ENOENT")
|
|
1939
1970
|
return null;
|
|
@@ -1947,8 +1978,20 @@ async function readCursor(opts) {
|
|
|
1947
1978
|
return null;
|
|
1948
1979
|
}
|
|
1949
1980
|
}
|
|
1981
|
+
async function waitForCaptainDelivery(opts) {
|
|
1982
|
+
const subscriber = opts.subscriber ?? "captain";
|
|
1983
|
+
const deadline = Date.now() + opts.timeoutMs;
|
|
1984
|
+
for (; ; ) {
|
|
1985
|
+
const cursor = await readCursor({ stateRoot: opts.stateRoot, project: opts.project, subscriber });
|
|
1986
|
+
if (cursor && cursor.lastAckedSeq >= opts.seq)
|
|
1987
|
+
return true;
|
|
1988
|
+
if (Date.now() >= deadline)
|
|
1989
|
+
return false;
|
|
1990
|
+
await new Promise((r) => setTimeout(r, opts.pollMs));
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1950
1993
|
async function writeCursor(opts) {
|
|
1951
|
-
await
|
|
1994
|
+
await fs9.mkdir(inboxDir(opts.stateRoot), { recursive: true });
|
|
1952
1995
|
const dest = cursorPath(opts.stateRoot, opts.project, opts.subscriber);
|
|
1953
1996
|
const tmp = `${dest}.${process.pid}.${randomUUID()}.tmp`;
|
|
1954
1997
|
const data = {
|
|
@@ -1956,7 +1999,7 @@ async function writeCursor(opts) {
|
|
|
1956
1999
|
subscriber: opts.subscriber,
|
|
1957
2000
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1958
2001
|
};
|
|
1959
|
-
const handle = await
|
|
2002
|
+
const handle = await fs9.open(tmp, "w");
|
|
1960
2003
|
try {
|
|
1961
2004
|
await handle.writeFile(JSON.stringify(data), { encoding: "utf-8" });
|
|
1962
2005
|
await handle.sync();
|
|
@@ -1964,9 +2007,9 @@ async function writeCursor(opts) {
|
|
|
1964
2007
|
await handle.close();
|
|
1965
2008
|
}
|
|
1966
2009
|
try {
|
|
1967
|
-
await
|
|
2010
|
+
await fs9.rename(tmp, dest);
|
|
1968
2011
|
} catch (e) {
|
|
1969
|
-
await
|
|
2012
|
+
await fs9.unlink(tmp).catch(() => {
|
|
1970
2013
|
});
|
|
1971
2014
|
throw e;
|
|
1972
2015
|
}
|
|
@@ -1977,7 +2020,7 @@ async function* readFromCursor(opts) {
|
|
|
1977
2020
|
for (const file of files) {
|
|
1978
2021
|
let buf;
|
|
1979
2022
|
try {
|
|
1980
|
-
buf = await
|
|
2023
|
+
buf = await fs9.readFile(file, "utf-8");
|
|
1981
2024
|
} catch (e) {
|
|
1982
2025
|
if (e.code === "ENOENT")
|
|
1983
2026
|
continue;
|
|
@@ -2003,7 +2046,7 @@ async function mailboxStats(stateRoot, project) {
|
|
|
2003
2046
|
let sizeBytes = 0;
|
|
2004
2047
|
for (const f of [file, ...rotated]) {
|
|
2005
2048
|
try {
|
|
2006
|
-
sizeBytes += (await
|
|
2049
|
+
sizeBytes += (await fs9.stat(f)).size;
|
|
2007
2050
|
} catch (e) {
|
|
2008
2051
|
if (e.code !== "ENOENT")
|
|
2009
2052
|
throw e;
|
|
@@ -2019,7 +2062,7 @@ async function mailboxStats(stateRoot, project) {
|
|
|
2019
2062
|
}
|
|
2020
2063
|
async function oldestEntryAgeMs(file) {
|
|
2021
2064
|
try {
|
|
2022
|
-
const buf = await
|
|
2065
|
+
const buf = await fs9.readFile(file, "utf-8");
|
|
2023
2066
|
const firstLine2 = buf.split("\n").find((l) => l.trim());
|
|
2024
2067
|
if (!firstLine2)
|
|
2025
2068
|
return 0;
|
|
@@ -2034,7 +2077,7 @@ async function rotateIfNeeded(opts) {
|
|
|
2034
2077
|
const file = logPath(opts.stateRoot, opts.project);
|
|
2035
2078
|
let size = 0;
|
|
2036
2079
|
try {
|
|
2037
|
-
size = (await
|
|
2080
|
+
size = (await fs9.stat(file)).size;
|
|
2038
2081
|
} catch (e) {
|
|
2039
2082
|
if (e.code === "ENOENT")
|
|
2040
2083
|
return { rotated: false };
|
|
@@ -2050,22 +2093,22 @@ async function rotateIfNeeded(opts) {
|
|
|
2050
2093
|
const dst = `${file}.${n + 1}`;
|
|
2051
2094
|
if (n + 1 > opts.keepCount) {
|
|
2052
2095
|
try {
|
|
2053
|
-
await
|
|
2096
|
+
await fs9.unlink(src);
|
|
2054
2097
|
} catch (e) {
|
|
2055
2098
|
if (e.code !== "ENOENT")
|
|
2056
2099
|
throw e;
|
|
2057
2100
|
}
|
|
2058
2101
|
} else {
|
|
2059
2102
|
try {
|
|
2060
|
-
await
|
|
2103
|
+
await fs9.rename(src, dst);
|
|
2061
2104
|
} catch (e) {
|
|
2062
2105
|
if (e.code !== "ENOENT")
|
|
2063
2106
|
throw e;
|
|
2064
2107
|
}
|
|
2065
2108
|
}
|
|
2066
2109
|
}
|
|
2067
|
-
await
|
|
2068
|
-
await
|
|
2110
|
+
await fs9.rename(file, `${file}.1`);
|
|
2111
|
+
await fs9.writeFile(file, "", { encoding: "utf-8" });
|
|
2069
2112
|
return { rotated: true, from: file, to: `${file}.1` };
|
|
2070
2113
|
});
|
|
2071
2114
|
}
|
|
@@ -2358,6 +2401,9 @@ function reconcileLiveness(prev, next) {
|
|
|
2358
2401
|
}
|
|
2359
2402
|
if (next.startedAt >= prev.startedAt || next.lastState === "end")
|
|
2360
2403
|
return next;
|
|
2404
|
+
const prevAlive = prev.lastState === "start" && prev.pidAlive;
|
|
2405
|
+
if (!prevAlive && next.lastState === "start" && next.pidAlive)
|
|
2406
|
+
return next;
|
|
2361
2407
|
return prev;
|
|
2362
2408
|
}
|
|
2363
2409
|
var CREW_STALE_MS, CREW_GONE_MS, TERMINAL;
|
|
@@ -3363,9 +3409,15 @@ async function runLivenessTick(deps) {
|
|
|
3363
3409
|
return;
|
|
3364
3410
|
}
|
|
3365
3411
|
const seen = /* @__PURE__ */ new Set();
|
|
3412
|
+
const knownCaptainSessions = /* @__PURE__ */ new Map();
|
|
3413
|
+
for (const e of deps.registry.all()) {
|
|
3414
|
+
if (e.role === "captain")
|
|
3415
|
+
knownCaptainSessions.set(e.sessionId, e.project);
|
|
3416
|
+
}
|
|
3366
3417
|
const byProject = /* @__PURE__ */ new Map();
|
|
3367
3418
|
for (const r of records) {
|
|
3368
|
-
|
|
3419
|
+
const role = r.role === "captain" || knownCaptainSessions.get(r.sessionId) === r.project ? "captain" : r.role;
|
|
3420
|
+
if (role !== "captain")
|
|
3369
3421
|
continue;
|
|
3370
3422
|
let arr = byProject.get(r.project);
|
|
3371
3423
|
if (!arr) {
|
|
@@ -3397,10 +3449,14 @@ async function runLivenessTick(deps) {
|
|
|
3397
3449
|
logEntry(deps.log, project, deps.registry.get(project));
|
|
3398
3450
|
}
|
|
3399
3451
|
for (const e of deps.registry.all()) {
|
|
3400
|
-
if (e.role
|
|
3401
|
-
|
|
3402
|
-
|
|
3452
|
+
if (e.role !== "captain" || e.lastState !== "start" || seen.has(e.project))
|
|
3453
|
+
continue;
|
|
3454
|
+
if (e.pid == null || deps.isPidAlive(e.pid)) {
|
|
3455
|
+
deps.log?.(`[${e.role}/runtime] ${e.project} pid=${e.pid} missing from snapshot but not confirmed dead \u2014 leaving alive`);
|
|
3456
|
+
continue;
|
|
3403
3457
|
}
|
|
3458
|
+
deps.registry.markEnded(e.project, now);
|
|
3459
|
+
logEntry(deps.log, e.project, deps.registry.get(e.project));
|
|
3404
3460
|
}
|
|
3405
3461
|
if (deps.reap) {
|
|
3406
3462
|
for (const e of deps.registry.all()) {
|
|
@@ -3994,35 +4050,35 @@ var init_start = __esm({
|
|
|
3994
4050
|
|
|
3995
4051
|
// packages/core/dist/session-freshness.js
|
|
3996
4052
|
import crypto from "crypto";
|
|
3997
|
-
import
|
|
4053
|
+
import fs10 from "fs";
|
|
3998
4054
|
import path8 from "path";
|
|
3999
4055
|
function loadSessions(sessionsPath) {
|
|
4000
4056
|
try {
|
|
4001
|
-
return JSON.parse(
|
|
4057
|
+
return JSON.parse(fs10.readFileSync(sessionsPath, "utf-8"));
|
|
4002
4058
|
} catch {
|
|
4003
4059
|
return { workspaces: {} };
|
|
4004
4060
|
}
|
|
4005
4061
|
}
|
|
4006
4062
|
function saveSessions(sessionsPath, sessions) {
|
|
4007
4063
|
const dir = path8.dirname(sessionsPath);
|
|
4008
|
-
|
|
4009
|
-
|
|
4064
|
+
fs10.mkdirSync(dir, { recursive: true });
|
|
4065
|
+
fs10.writeFileSync(sessionsPath, JSON.stringify(sessions, null, 2) + "\n");
|
|
4010
4066
|
}
|
|
4011
4067
|
function computeTemplateHash(role, templatesDir) {
|
|
4012
4068
|
const hash = crypto.createHash("sha256");
|
|
4013
4069
|
const roleFile = path8.join(templatesDir, `${role}.claude.md`);
|
|
4014
4070
|
const legacyRoleFile = path8.join(templatesDir, `${role}.CLAUDE.md`);
|
|
4015
|
-
if (
|
|
4016
|
-
hash.update(
|
|
4017
|
-
} else if (
|
|
4018
|
-
hash.update(
|
|
4071
|
+
if (fs10.existsSync(roleFile)) {
|
|
4072
|
+
hash.update(fs10.readFileSync(roleFile, "utf-8"));
|
|
4073
|
+
} else if (fs10.existsSync(legacyRoleFile)) {
|
|
4074
|
+
hash.update(fs10.readFileSync(legacyRoleFile, "utf-8"));
|
|
4019
4075
|
}
|
|
4020
4076
|
const pluginSkillsDir = path8.join(templatesDir, "..", "plugin", "skills");
|
|
4021
|
-
if (
|
|
4022
|
-
for (const skill of
|
|
4077
|
+
if (fs10.existsSync(pluginSkillsDir)) {
|
|
4078
|
+
for (const skill of fs10.readdirSync(pluginSkillsDir).sort()) {
|
|
4023
4079
|
const skillFile = path8.join(pluginSkillsDir, skill, "SKILL.md");
|
|
4024
|
-
if (
|
|
4025
|
-
hash.update(
|
|
4080
|
+
if (fs10.existsSync(skillFile)) {
|
|
4081
|
+
hash.update(fs10.readFileSync(skillFile, "utf-8"));
|
|
4026
4082
|
}
|
|
4027
4083
|
}
|
|
4028
4084
|
}
|
|
@@ -4086,6 +4142,9 @@ function shellQuote(p) {
|
|
|
4086
4142
|
function titleFor(project, name) {
|
|
4087
4143
|
return `\u{1F527} ${project}:${name}`;
|
|
4088
4144
|
}
|
|
4145
|
+
function niceCrewCommand(cmd) {
|
|
4146
|
+
return `nice -n ${CREW_NICE_LEVEL} ${cmd}`;
|
|
4147
|
+
}
|
|
4089
4148
|
function isCrewTitle(project, title) {
|
|
4090
4149
|
return title.startsWith(`\u{1F527} ${project}:`);
|
|
4091
4150
|
}
|
|
@@ -4104,8 +4163,10 @@ function nextAutoName(existingTitles, project) {
|
|
|
4104
4163
|
i++;
|
|
4105
4164
|
return `crew-${i}`;
|
|
4106
4165
|
}
|
|
4166
|
+
var CREW_NICE_LEVEL;
|
|
4107
4167
|
var init_crew_protocol = __esm({
|
|
4108
4168
|
"packages/core/dist/crew-protocol.js"() {
|
|
4169
|
+
CREW_NICE_LEVEL = 10;
|
|
4109
4170
|
}
|
|
4110
4171
|
});
|
|
4111
4172
|
|
|
@@ -4431,7 +4492,7 @@ var init_format = __esm({
|
|
|
4431
4492
|
});
|
|
4432
4493
|
|
|
4433
4494
|
// packages/core/dist/telegram/state.js
|
|
4434
|
-
import
|
|
4495
|
+
import fs11 from "fs";
|
|
4435
4496
|
import path9 from "path";
|
|
4436
4497
|
function statePath(stateRoot) {
|
|
4437
4498
|
return path9.join(stateRoot, "telegram-state.json");
|
|
@@ -4441,7 +4502,7 @@ function topicKey(project, scope = "project") {
|
|
|
4441
4502
|
}
|
|
4442
4503
|
function loadState(stateRoot) {
|
|
4443
4504
|
try {
|
|
4444
|
-
const raw =
|
|
4505
|
+
const raw = fs11.readFileSync(statePath(stateRoot), "utf-8");
|
|
4445
4506
|
const data = JSON.parse(raw);
|
|
4446
4507
|
const result = {
|
|
4447
4508
|
offset: typeof data.offset === "number" ? data.offset : 0,
|
|
@@ -4456,8 +4517,8 @@ function loadState(stateRoot) {
|
|
|
4456
4517
|
}
|
|
4457
4518
|
}
|
|
4458
4519
|
function saveState(stateRoot, s) {
|
|
4459
|
-
|
|
4460
|
-
|
|
4520
|
+
fs11.mkdirSync(stateRoot, { recursive: true });
|
|
4521
|
+
fs11.writeFileSync(statePath(stateRoot), JSON.stringify(s, null, 2) + "\n");
|
|
4461
4522
|
}
|
|
4462
4523
|
function setTopic(stateRoot, project, topicId, scope = "project") {
|
|
4463
4524
|
const s = loadState(stateRoot);
|
|
@@ -5063,7 +5124,7 @@ var init_restart_daemon = __esm({
|
|
|
5063
5124
|
});
|
|
5064
5125
|
|
|
5065
5126
|
// packages/core/dist/telegram/setup.js
|
|
5066
|
-
import
|
|
5127
|
+
import fs12 from "fs";
|
|
5067
5128
|
function resolveSetupGroup(existingSupergroupId, opts) {
|
|
5068
5129
|
if (existingSupergroupId !== void 0 && !opts.redetect)
|
|
5069
5130
|
return "reuse";
|
|
@@ -5114,7 +5175,7 @@ function writeTelegramConfig(configPath, opts) {
|
|
|
5114
5175
|
let config;
|
|
5115
5176
|
let raw = null;
|
|
5116
5177
|
try {
|
|
5117
|
-
raw =
|
|
5178
|
+
raw = fs12.readFileSync(configPath, "utf-8");
|
|
5118
5179
|
} catch (err) {
|
|
5119
5180
|
if (err.code !== "ENOENT") {
|
|
5120
5181
|
throw new Error(`refusing to overwrite unreadable config at ${configPath}: ${String(err)}`);
|
|
@@ -5142,7 +5203,7 @@ function writeTelegramConfig(configPath, opts) {
|
|
|
5142
5203
|
if (remoteControl !== void 0)
|
|
5143
5204
|
next.remoteControl = remoteControl;
|
|
5144
5205
|
config.telegram = next;
|
|
5145
|
-
|
|
5206
|
+
fs12.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
5146
5207
|
}
|
|
5147
5208
|
var init_setup = __esm({
|
|
5148
5209
|
"packages/core/dist/telegram/setup.js"() {
|
|
@@ -5470,7 +5531,7 @@ var init_launch_workspace = __esm({
|
|
|
5470
5531
|
});
|
|
5471
5532
|
|
|
5472
5533
|
// packages/core/dist/side-session.js
|
|
5473
|
-
import
|
|
5534
|
+
import fs13 from "fs";
|
|
5474
5535
|
function sideTitleFor(project, name) {
|
|
5475
5536
|
return `\u{1F5D2} ${project}:${name}`;
|
|
5476
5537
|
}
|
|
@@ -5572,7 +5633,7 @@ async function runSideClose(runtime, workspaceId, project, name, projPath, workt
|
|
|
5572
5633
|
await runtime.closePane(pane);
|
|
5573
5634
|
if (projPath) {
|
|
5574
5635
|
const wtPath = worktreePath(projPath, worktreeDir, project, name);
|
|
5575
|
-
if (
|
|
5636
|
+
if (fs13.existsSync(wtPath)) {
|
|
5576
5637
|
try {
|
|
5577
5638
|
removeWorktree(projPath, wtPath);
|
|
5578
5639
|
} catch (e) {
|
|
@@ -5592,7 +5653,7 @@ var init_side_session = __esm({
|
|
|
5592
5653
|
});
|
|
5593
5654
|
|
|
5594
5655
|
// packages/core/dist/crew-spawn.js
|
|
5595
|
-
import
|
|
5656
|
+
import fs14 from "fs";
|
|
5596
5657
|
import os5 from "os";
|
|
5597
5658
|
import path11 from "path";
|
|
5598
5659
|
async function listCrewPanes(runtime, workspaceId, project) {
|
|
@@ -5660,7 +5721,7 @@ async function runCrewSpawn(input, config, deps) {
|
|
|
5660
5721
|
if (input.taskFile && input.taskFile !== "-" && !input.shared) {
|
|
5661
5722
|
const absTaskFile = path11.resolve(input.taskFile);
|
|
5662
5723
|
const basename = path11.basename(absTaskFile);
|
|
5663
|
-
|
|
5724
|
+
fs14.copyFileSync(absTaskFile, path11.join(spawnCwd, basename));
|
|
5664
5725
|
firstTurnTask = `Read ./${basename} to get your task brief, then execute it.`;
|
|
5665
5726
|
}
|
|
5666
5727
|
const route = !input.agentExplicit && !input.model ? resolveCrewRoute(input.task, config) : null;
|
|
@@ -5674,7 +5735,7 @@ async function runCrewSpawn(input, config, deps) {
|
|
|
5674
5735
|
}
|
|
5675
5736
|
if (agentName === "codex") {
|
|
5676
5737
|
const codexRoleFile = path11.join(TEMPLATES_DIR, `crew.${agent.templateSuffix}.md`);
|
|
5677
|
-
const roleInstructions =
|
|
5738
|
+
const roleInstructions = fs14.existsSync(codexRoleFile) ? fs14.readFileSync(codexRoleFile, "utf8") : void 0;
|
|
5678
5739
|
return runCodexInteractiveSpawn({
|
|
5679
5740
|
project: input.project,
|
|
5680
5741
|
task: input.task,
|
|
@@ -5725,7 +5786,7 @@ async function runCrewSpawn(input, config, deps) {
|
|
|
5725
5786
|
const title2 = titleFor(input.project, name);
|
|
5726
5787
|
const pane2 = await deps.runtime.newPane({ workspaceId: captain.id, direction: direction2, title: title2 });
|
|
5727
5788
|
const envPrefix = `SQUADRANT_CREW_TASK_ID=${rec.id} SQUADRANT_CREW_PROJECT=${input.project}`;
|
|
5728
|
-
await deps.runtime.sendToPane(pane2, `cd ${shellQuote(spawnCwd)} && ${envPrefix} ${cliCommand2}`);
|
|
5789
|
+
await deps.runtime.sendToPane(pane2, `cd ${shellQuote(spawnCwd)} && ${envPrefix} ${niceCrewCommand(cliCommand2)}`);
|
|
5729
5790
|
const preLaunchScreen = await deps.runtime.readPaneScreen(pane2) ?? "";
|
|
5730
5791
|
const claudeResult = await deps.sendFirstTurn(pane2, `${firstTurnTask}
|
|
5731
5792
|
|
|
@@ -5773,7 +5834,7 @@ ${buildCompletionProtocol(rec.id, input.project)}`, preLaunchScreen);
|
|
|
5773
5834
|
const title2 = titleFor(input.project, name);
|
|
5774
5835
|
const pane2 = await deps.runtime.newPane({ workspaceId: captain.id, direction: direction2, title: title2 });
|
|
5775
5836
|
const envPrefix = `SQUADRANT_CREW_TASK_ID=${rec.id} SQUADRANT_CREW_PROJECT=${input.project}`;
|
|
5776
|
-
await deps.runtime.sendToPane(pane2, `cd ${shellQuote(spawnCwd)} && ${envPrefix} OPENCODE_CONFIG=${opencodeConfigPath} ${cliCommand2}`);
|
|
5837
|
+
await deps.runtime.sendToPane(pane2, `cd ${shellQuote(spawnCwd)} && ${envPrefix} OPENCODE_CONFIG=${opencodeConfigPath} ${niceCrewCommand(cliCommand2)}`);
|
|
5777
5838
|
const preLaunchScreen = await deps.runtime.readPaneScreen(pane2) ?? "";
|
|
5778
5839
|
const opencodeResult = await deps.sendFirstTurn(pane2, `${firstTurnTask}
|
|
5779
5840
|
|
|
@@ -5808,7 +5869,7 @@ ${buildCompletionProtocol(rec.id, input.project)}`, preLaunchScreen, {
|
|
|
5808
5869
|
const direction = input.direction ?? "tab";
|
|
5809
5870
|
const title = titleFor(input.project, name);
|
|
5810
5871
|
const pane = await deps.runtime.newPane({ workspaceId: captain.id, direction, title });
|
|
5811
|
-
await deps.runtime.sendToPane(pane, cliCommand);
|
|
5872
|
+
await deps.runtime.sendToPane(pane, niceCrewCommand(cliCommand));
|
|
5812
5873
|
if (interactive) {
|
|
5813
5874
|
const preLaunchScreen = await deps.runtime.readPaneScreen(pane) ?? "";
|
|
5814
5875
|
const genericResult = await deps.sendFirstTurn(pane, firstTurnTask, preLaunchScreen);
|
|
@@ -5846,8 +5907,7 @@ async function runCrewSend(project, name, message, runtime, workspaceId, deps) {
|
|
|
5846
5907
|
throw new Error(blockedByModalMessage());
|
|
5847
5908
|
}
|
|
5848
5909
|
if (!delivered) {
|
|
5849
|
-
|
|
5850
|
-
`);
|
|
5910
|
+
throw new Error(`Message not delivered to crew '${name}' \u2014 the paste/submit could not be confirmed. Re-send with 'squadrant crew send ${project} ${name}'.`);
|
|
5851
5911
|
}
|
|
5852
5912
|
}
|
|
5853
5913
|
async function runCrewRead(project, name, runtime, workspaceId) {
|
|
@@ -6040,6 +6100,7 @@ __export(dist_exports2, {
|
|
|
6040
6100
|
maskToken: () => maskToken,
|
|
6041
6101
|
nameFromTitle: () => nameFromTitle,
|
|
6042
6102
|
nextAutoName: () => nextAutoName,
|
|
6103
|
+
niceCrewCommand: () => niceCrewCommand,
|
|
6043
6104
|
notifyToggle: () => notifyToggle,
|
|
6044
6105
|
parseCommand: () => parseCommand,
|
|
6045
6106
|
parseNotifyPref: () => parseNotifyPref,
|
|
@@ -6107,6 +6168,7 @@ __export(dist_exports2, {
|
|
|
6107
6168
|
topicKey: () => topicKey,
|
|
6108
6169
|
topicName: () => topicName,
|
|
6109
6170
|
tryAcquireDaemonLock: () => tryAcquireDaemonLock,
|
|
6171
|
+
waitForCaptainDelivery: () => waitForCaptainDelivery,
|
|
6110
6172
|
waitForWarmup: () => waitForWarmup,
|
|
6111
6173
|
writeCursor: () => writeCursor,
|
|
6112
6174
|
writeTelegramConfig: () => writeTelegramConfig
|
|
@@ -6745,7 +6807,7 @@ var init_notifiers = __esm({
|
|
|
6745
6807
|
});
|
|
6746
6808
|
|
|
6747
6809
|
// packages/workspaces/dist/workspaces/obsidian.js
|
|
6748
|
-
import
|
|
6810
|
+
import fs15 from "fs/promises";
|
|
6749
6811
|
import { existsSync as existsSync9 } from "fs";
|
|
6750
6812
|
import path12 from "path";
|
|
6751
6813
|
function resolveInRoot(root, relative) {
|
|
@@ -6770,16 +6832,16 @@ function createObsidianDriver(scope) {
|
|
|
6770
6832
|
};
|
|
6771
6833
|
},
|
|
6772
6834
|
async read(rel) {
|
|
6773
|
-
return
|
|
6835
|
+
return fs15.readFile(resolveInRoot(root, rel), "utf-8");
|
|
6774
6836
|
},
|
|
6775
6837
|
async write(rel, content) {
|
|
6776
6838
|
const abs = resolveInRoot(root, rel);
|
|
6777
|
-
await
|
|
6778
|
-
await
|
|
6839
|
+
await fs15.mkdir(path12.dirname(abs), { recursive: true });
|
|
6840
|
+
await fs15.writeFile(abs, content);
|
|
6779
6841
|
},
|
|
6780
6842
|
async exists(rel) {
|
|
6781
6843
|
try {
|
|
6782
|
-
await
|
|
6844
|
+
await fs15.access(resolveInRoot(root, rel));
|
|
6783
6845
|
return true;
|
|
6784
6846
|
} catch {
|
|
6785
6847
|
return false;
|
|
@@ -6787,13 +6849,13 @@ function createObsidianDriver(scope) {
|
|
|
6787
6849
|
},
|
|
6788
6850
|
async list(rel) {
|
|
6789
6851
|
try {
|
|
6790
|
-
return await
|
|
6852
|
+
return await fs15.readdir(resolveInRoot(root, rel));
|
|
6791
6853
|
} catch {
|
|
6792
6854
|
return [];
|
|
6793
6855
|
}
|
|
6794
6856
|
},
|
|
6795
6857
|
async mkdir(rel) {
|
|
6796
|
-
await
|
|
6858
|
+
await fs15.mkdir(resolveInRoot(root, rel), { recursive: true });
|
|
6797
6859
|
}
|
|
6798
6860
|
};
|
|
6799
6861
|
}
|
|
@@ -8018,7 +8080,7 @@ var init_registry4 = __esm({
|
|
|
8018
8080
|
});
|
|
8019
8081
|
|
|
8020
8082
|
// packages/agents/dist/drivers/launch-cmd.js
|
|
8021
|
-
import
|
|
8083
|
+
import fs16 from "fs";
|
|
8022
8084
|
import path13 from "path";
|
|
8023
8085
|
function buildAgentCmd(agentName, registry, role, fresh, permissionMode, model, templatesDir) {
|
|
8024
8086
|
const driver = registry.getDriver(agentName);
|
|
@@ -8037,12 +8099,12 @@ function buildAgentCmd(agentName, registry, role, fresh, permissionMode, model,
|
|
|
8037
8099
|
if (templatesDir) {
|
|
8038
8100
|
const roleFile2 = path13.join(templatesDir, `${role}.claude.md`);
|
|
8039
8101
|
const legacyRoleFile = path13.join(templatesDir, `${role}.CLAUDE.md`);
|
|
8040
|
-
const actualRoleFile =
|
|
8102
|
+
const actualRoleFile = fs16.existsSync(roleFile2) ? roleFile2 : fs16.existsSync(legacyRoleFile) ? legacyRoleFile : null;
|
|
8041
8103
|
if (actualRoleFile) {
|
|
8042
8104
|
cmd += ` --append-system-prompt-file ${actualRoleFile}`;
|
|
8043
8105
|
}
|
|
8044
8106
|
const pluginDir = path13.join(templatesDir, "..", "plugin");
|
|
8045
|
-
if (
|
|
8107
|
+
if (fs16.existsSync(pluginDir)) {
|
|
8046
8108
|
cmd += ` --plugin-dir ${pluginDir}`;
|
|
8047
8109
|
}
|
|
8048
8110
|
}
|
|
@@ -8055,7 +8117,7 @@ function buildAgentCmd(agentName, registry, role, fresh, permissionMode, model,
|
|
|
8055
8117
|
role,
|
|
8056
8118
|
model,
|
|
8057
8119
|
autoApprove: true,
|
|
8058
|
-
promptFile: roleFile &&
|
|
8120
|
+
promptFile: roleFile && fs16.existsSync(roleFile) ? roleFile : void 0
|
|
8059
8121
|
});
|
|
8060
8122
|
}
|
|
8061
8123
|
var init_launch_cmd = __esm({
|
|
@@ -9819,7 +9881,7 @@ init_dist();
|
|
|
9819
9881
|
init_dist3();
|
|
9820
9882
|
import { Command } from "commander";
|
|
9821
9883
|
import { execSync as execSync8 } from "child_process";
|
|
9822
|
-
import
|
|
9884
|
+
import fs17 from "fs";
|
|
9823
9885
|
import { stat } from "fs/promises";
|
|
9824
9886
|
import path18 from "path";
|
|
9825
9887
|
import chalk3 from "chalk";
|
|
@@ -9924,7 +9986,7 @@ function settingsHaveAgentTeams() {
|
|
|
9924
9986
|
try {
|
|
9925
9987
|
const home = process.env.HOME || "";
|
|
9926
9988
|
const settings = JSON.parse(
|
|
9927
|
-
|
|
9989
|
+
fs17.readFileSync(`${home}/.claude/settings.json`, "utf-8")
|
|
9928
9990
|
);
|
|
9929
9991
|
return settings?.env?.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS === "1";
|
|
9930
9992
|
} catch {
|
|
@@ -9935,7 +9997,7 @@ function pluginInstalled(pluginKey) {
|
|
|
9935
9997
|
try {
|
|
9936
9998
|
const home = process.env.HOME || "";
|
|
9937
9999
|
const plugins = JSON.parse(
|
|
9938
|
-
|
|
10000
|
+
fs17.readFileSync(
|
|
9939
10001
|
`${home}/.claude/plugins/installed_plugins.json`,
|
|
9940
10002
|
"utf-8"
|
|
9941
10003
|
)
|
|
@@ -9980,7 +10042,7 @@ var doctorCommand = new Command("doctor").description("Check system health and p
|
|
|
9980
10042
|
));
|
|
9981
10043
|
results.push(check(
|
|
9982
10044
|
"Obsidian installed",
|
|
9983
|
-
commandExists("obsidian") ||
|
|
10045
|
+
commandExists("obsidian") || fs17.existsSync("/Applications/Obsidian.app"),
|
|
9984
10046
|
"Install from: https://obsidian.md"
|
|
9985
10047
|
));
|
|
9986
10048
|
results.push(check(
|
|
@@ -10087,7 +10149,7 @@ var doctorCommand = new Command("doctor").description("Check system health and p
|
|
|
10087
10149
|
results.push(
|
|
10088
10150
|
check(
|
|
10089
10151
|
"Squadrant config exists",
|
|
10090
|
-
|
|
10152
|
+
fs17.existsSync(
|
|
10091
10153
|
process.env.SQUADRANT_CONFIG || `${process.env.HOME}/.config/squadrant/config.json`
|
|
10092
10154
|
),
|
|
10093
10155
|
"Run: squadrant init"
|
|
@@ -10161,7 +10223,7 @@ init_dist();
|
|
|
10161
10223
|
init_dist3();
|
|
10162
10224
|
init_dist();
|
|
10163
10225
|
import { Command as Command2 } from "commander";
|
|
10164
|
-
import
|
|
10226
|
+
import fs18 from "fs";
|
|
10165
10227
|
import path19 from "path";
|
|
10166
10228
|
import os10 from "os";
|
|
10167
10229
|
import readline from "readline";
|
|
@@ -10318,20 +10380,20 @@ init_dist4();
|
|
|
10318
10380
|
function findPackageRoot() {
|
|
10319
10381
|
let dir = path19.dirname(new URL(import.meta.url).pathname);
|
|
10320
10382
|
while (dir !== "/") {
|
|
10321
|
-
if (
|
|
10383
|
+
if (fs18.existsSync(path19.join(dir, "package.json"))) return dir;
|
|
10322
10384
|
dir = path19.dirname(dir);
|
|
10323
10385
|
}
|
|
10324
10386
|
return process.cwd();
|
|
10325
10387
|
}
|
|
10326
10388
|
function copyDirRecursive(src, dest) {
|
|
10327
|
-
|
|
10328
|
-
for (const entry of
|
|
10389
|
+
fs18.mkdirSync(dest, { recursive: true });
|
|
10390
|
+
for (const entry of fs18.readdirSync(src, { withFileTypes: true })) {
|
|
10329
10391
|
const srcPath = path19.join(src, entry.name);
|
|
10330
10392
|
const destPath = path19.join(dest, entry.name);
|
|
10331
10393
|
if (entry.isDirectory()) {
|
|
10332
10394
|
copyDirRecursive(srcPath, destPath);
|
|
10333
10395
|
} else {
|
|
10334
|
-
|
|
10396
|
+
fs18.copyFileSync(srcPath, destPath);
|
|
10335
10397
|
}
|
|
10336
10398
|
}
|
|
10337
10399
|
}
|
|
@@ -10377,8 +10439,8 @@ var initCommand = new Command2("init").description("Guided first-time setup: hub
|
|
|
10377
10439
|
}
|
|
10378
10440
|
const wsRegistry = new WorkspaceRegistry({ obsidian: createObsidianDriver });
|
|
10379
10441
|
try {
|
|
10380
|
-
if (
|
|
10381
|
-
const existing = JSON.parse(
|
|
10442
|
+
if (fs18.existsSync(DEFAULT_CONFIG_PATH)) {
|
|
10443
|
+
const existing = JSON.parse(fs18.readFileSync(DEFAULT_CONFIG_PATH, "utf-8"));
|
|
10382
10444
|
wsRegistry.get(existing.workspace ?? "obsidian");
|
|
10383
10445
|
}
|
|
10384
10446
|
} catch (err) {
|
|
@@ -10386,7 +10448,7 @@ var initCommand = new Command2("init").description("Guided first-time setup: hub
|
|
|
10386
10448
|
return;
|
|
10387
10449
|
}
|
|
10388
10450
|
stepHeader(1, 5, "Hub vault");
|
|
10389
|
-
if (
|
|
10451
|
+
if (fs18.existsSync(DEFAULT_CONFIG_PATH)) {
|
|
10390
10452
|
console.log(chalk4.yellow(" \u26A0 Config already exists, skipping creation"));
|
|
10391
10453
|
} else {
|
|
10392
10454
|
const config = getDefaultConfig();
|
|
@@ -10395,36 +10457,36 @@ var initCommand = new Command2("init").description("Guided first-time setup: hub
|
|
|
10395
10457
|
console.log(chalk4.green(` \u2714 Config created at ${DEFAULT_CONFIG_PATH}`));
|
|
10396
10458
|
}
|
|
10397
10459
|
const hubTemplate = path19.join(pkgRoot, "obsidian", "hub");
|
|
10398
|
-
if (
|
|
10460
|
+
if (fs18.existsSync(hubPath)) {
|
|
10399
10461
|
console.log(chalk4.yellow(` \u26A0 Hub vault already exists at ${hubPath}`));
|
|
10400
|
-
} else if (
|
|
10462
|
+
} else if (fs18.existsSync(hubTemplate)) {
|
|
10401
10463
|
copyDirRecursive(hubTemplate, hubPath);
|
|
10402
10464
|
console.log(chalk4.green(` \u2714 Hub vault scaffolded at ${hubPath}`));
|
|
10403
10465
|
} else {
|
|
10404
|
-
|
|
10466
|
+
fs18.mkdirSync(hubPath, { recursive: true });
|
|
10405
10467
|
console.log(chalk4.yellow(` \u26A0 Hub template not found; created empty directory at ${hubPath}`));
|
|
10406
10468
|
}
|
|
10407
10469
|
const hubDashboardSrc = path19.join(pkgRoot, "obsidian", "hub", "dashboard.md");
|
|
10408
10470
|
const hubDashboardDest = path19.join(hubPath, "dashboard.md");
|
|
10409
|
-
if (
|
|
10410
|
-
|
|
10471
|
+
if (fs18.existsSync(hubDashboardSrc)) {
|
|
10472
|
+
fs18.copyFileSync(hubDashboardSrc, hubDashboardDest);
|
|
10411
10473
|
console.log(chalk4.green(` \u2714 Dashboard refreshed`));
|
|
10412
10474
|
}
|
|
10413
|
-
|
|
10475
|
+
fs18.mkdirSync(path19.join(hubPath, "projects"), { recursive: true });
|
|
10414
10476
|
ensureRuntimeSynced({ sourceRoot: pkgRoot, runtimeRoot: configDir });
|
|
10415
10477
|
console.log(chalk4.green(` \u2714 Runtime assets synced to ${configDir}`));
|
|
10416
10478
|
stepHeader(2, 5, "Agent + projection setup");
|
|
10417
10479
|
const settingsPath = path19.join(os10.homedir(), ".claude", "settings.json");
|
|
10418
10480
|
try {
|
|
10419
10481
|
let settings = {};
|
|
10420
|
-
if (
|
|
10421
|
-
settings = JSON.parse(
|
|
10482
|
+
if (fs18.existsSync(settingsPath)) {
|
|
10483
|
+
settings = JSON.parse(fs18.readFileSync(settingsPath, "utf-8"));
|
|
10422
10484
|
}
|
|
10423
10485
|
const env = settings.env || {};
|
|
10424
10486
|
if (env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS !== "1") {
|
|
10425
10487
|
settings.env = { ...env, CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: "1" };
|
|
10426
|
-
|
|
10427
|
-
|
|
10488
|
+
fs18.mkdirSync(path19.dirname(settingsPath), { recursive: true });
|
|
10489
|
+
fs18.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
10428
10490
|
console.log(chalk4.green(" \u2714 Agent Teams enabled in ~/.claude/settings.json"));
|
|
10429
10491
|
} else {
|
|
10430
10492
|
console.log(chalk4.green(" \u2714 Agent Teams already enabled"));
|
|
@@ -10504,7 +10566,7 @@ var initCommand = new Command2("init").description("Guided first-time setup: hub
|
|
|
10504
10566
|
init_dist();
|
|
10505
10567
|
init_dist2();
|
|
10506
10568
|
import { Command as Command3 } from "commander";
|
|
10507
|
-
import
|
|
10569
|
+
import fs19 from "fs";
|
|
10508
10570
|
import path20 from "path";
|
|
10509
10571
|
import chalk5 from "chalk";
|
|
10510
10572
|
function restartAfterProjectsAdd(opts) {
|
|
@@ -10519,20 +10581,20 @@ function restartAfterProjectsAdd(opts) {
|
|
|
10519
10581
|
function findPackageRoot2() {
|
|
10520
10582
|
let dir = path20.dirname(new URL(import.meta.url).pathname);
|
|
10521
10583
|
while (dir !== "/") {
|
|
10522
|
-
if (
|
|
10584
|
+
if (fs19.existsSync(path20.join(dir, "package.json"))) return dir;
|
|
10523
10585
|
dir = path20.dirname(dir);
|
|
10524
10586
|
}
|
|
10525
10587
|
return process.cwd();
|
|
10526
10588
|
}
|
|
10527
10589
|
function copyDirRecursive2(src, dest) {
|
|
10528
|
-
|
|
10529
|
-
for (const entry of
|
|
10590
|
+
fs19.mkdirSync(dest, { recursive: true });
|
|
10591
|
+
for (const entry of fs19.readdirSync(src, { withFileTypes: true })) {
|
|
10530
10592
|
const srcPath = path20.join(src, entry.name);
|
|
10531
10593
|
const destPath = path20.join(dest, entry.name);
|
|
10532
10594
|
if (entry.isDirectory()) {
|
|
10533
10595
|
copyDirRecursive2(srcPath, destPath);
|
|
10534
10596
|
} else {
|
|
10535
|
-
|
|
10597
|
+
fs19.copyFileSync(srcPath, destPath);
|
|
10536
10598
|
}
|
|
10537
10599
|
}
|
|
10538
10600
|
}
|
|
@@ -10568,7 +10630,7 @@ var addCmd = new Command3("add").description("Register a project").argument("<na
|
|
|
10568
10630
|
process.exit(1);
|
|
10569
10631
|
}
|
|
10570
10632
|
const resolvedPath = resolveHome(projectPath);
|
|
10571
|
-
if (!
|
|
10633
|
+
if (!fs19.existsSync(path20.join(resolvedPath, ".git"))) {
|
|
10572
10634
|
console.log(chalk5.yellow(`
|
|
10573
10635
|
\u26A0 No .git found at ${resolvedPath}. Make sure this is the project root, not a parent directory.
|
|
10574
10636
|
`));
|
|
@@ -10637,19 +10699,19 @@ var addCmd = new Command3("add").description("Register a project").argument("<na
|
|
|
10637
10699
|
restartAfterProjectsAdd({ noRestart: opts.restart === false });
|
|
10638
10700
|
const pkgRoot = findPackageRoot2();
|
|
10639
10701
|
const spokeTemplate = path20.join(pkgRoot, "obsidian", "spoke");
|
|
10640
|
-
if (
|
|
10702
|
+
if (fs19.existsSync(spokeVault)) {
|
|
10641
10703
|
console.log(chalk5.yellow(` \u26A0 Spoke vault already exists at ${spokeVault}, skipping scaffold`));
|
|
10642
|
-
} else if (
|
|
10704
|
+
} else if (fs19.existsSync(spokeTemplate)) {
|
|
10643
10705
|
copyDirRecursive2(spokeTemplate, spokeVault);
|
|
10644
10706
|
const statusPath = path20.join(spokeVault, "status.md");
|
|
10645
|
-
if (
|
|
10646
|
-
const content =
|
|
10707
|
+
if (fs19.existsSync(statusPath)) {
|
|
10708
|
+
const content = fs19.readFileSync(statusPath, "utf-8");
|
|
10647
10709
|
const updated = content.replace(/^project: unnamed/m, `project: ${name}`);
|
|
10648
|
-
|
|
10710
|
+
fs19.writeFileSync(statusPath, updated);
|
|
10649
10711
|
}
|
|
10650
10712
|
console.log(chalk5.green(` \u2714 Spoke vault scaffolded at ${spokeVault}`));
|
|
10651
10713
|
} else {
|
|
10652
|
-
|
|
10714
|
+
fs19.mkdirSync(spokeVault, { recursive: true });
|
|
10653
10715
|
console.log(chalk5.yellow(` \u26A0 Spoke template not found; created empty dir at ${spokeVault}`));
|
|
10654
10716
|
}
|
|
10655
10717
|
console.log("");
|
|
@@ -11506,7 +11568,7 @@ init_dist3();
|
|
|
11506
11568
|
init_dist();
|
|
11507
11569
|
init_dist2();
|
|
11508
11570
|
import { Command as Command10 } from "commander";
|
|
11509
|
-
import
|
|
11571
|
+
import fs20 from "fs";
|
|
11510
11572
|
import path22 from "path";
|
|
11511
11573
|
import os12 from "os";
|
|
11512
11574
|
import chalk10 from "chalk";
|
|
@@ -11542,7 +11604,7 @@ async function runSideSpawn2(input) {
|
|
|
11542
11604
|
prompt: input.topic,
|
|
11543
11605
|
workdir: spawnCwd,
|
|
11544
11606
|
role: "side",
|
|
11545
|
-
promptFile:
|
|
11607
|
+
promptFile: fs20.existsSync(promptFile) ? promptFile : void 0,
|
|
11546
11608
|
interactive: true,
|
|
11547
11609
|
permissionMode: config.defaults.permissions?.crew ?? "auto",
|
|
11548
11610
|
...sideModel ? { model: sideModel } : {}
|
|
@@ -11806,7 +11868,7 @@ function renderDashboard(rows, opts) {
|
|
|
11806
11868
|
|
|
11807
11869
|
// packages/web/dist/sync-hub.js
|
|
11808
11870
|
init_dist();
|
|
11809
|
-
import
|
|
11871
|
+
import fs21 from "fs";
|
|
11810
11872
|
import path23 from "path";
|
|
11811
11873
|
function buildMirrorMarkdown(s) {
|
|
11812
11874
|
const fenced = "```";
|
|
@@ -11833,8 +11895,8 @@ function buildMirrorMarkdown(s) {
|
|
|
11833
11895
|
function syncHub(deps) {
|
|
11834
11896
|
if (!deps.config.hubVault)
|
|
11835
11897
|
return [];
|
|
11836
|
-
const writeFile5 = deps.writeFile ?? ((p, c) =>
|
|
11837
|
-
const mkdir5 = deps.mkdir ?? ((p) =>
|
|
11898
|
+
const writeFile5 = deps.writeFile ?? ((p, c) => fs21.writeFileSync(p, c));
|
|
11899
|
+
const mkdir5 = deps.mkdir ?? ((p) => fs21.mkdirSync(p, { recursive: true }));
|
|
11838
11900
|
const projectsDir = path23.join(resolveHome(deps.config.hubVault), "projects");
|
|
11839
11901
|
mkdir5(projectsDir);
|
|
11840
11902
|
const out = [];
|
|
@@ -12966,7 +13028,7 @@ init_dist3();
|
|
|
12966
13028
|
init_dist2();
|
|
12967
13029
|
import { Command as Command12 } from "commander";
|
|
12968
13030
|
import { execSync as execSync11 } from "child_process";
|
|
12969
|
-
import
|
|
13031
|
+
import fs22 from "fs";
|
|
12970
13032
|
import path24 from "path";
|
|
12971
13033
|
import os13 from "os";
|
|
12972
13034
|
import chalk13 from "chalk";
|
|
@@ -13119,12 +13181,12 @@ var launchCommand = new Command12("launch").description(
|
|
|
13119
13181
|
}
|
|
13120
13182
|
if (opts.all) {
|
|
13121
13183
|
const hubPath = resolveHome(config.hubVault);
|
|
13122
|
-
|
|
13184
|
+
fs22.mkdirSync(hubPath, { recursive: true });
|
|
13123
13185
|
console.log(chalk13.bold("\nLaunching all captain workspaces\n"));
|
|
13124
13186
|
for (const [name, proj] of Object.entries(config.projects)) {
|
|
13125
13187
|
const projPath = resolveHome(proj.path);
|
|
13126
13188
|
const spokePath = resolveHome(proj.spokeVault);
|
|
13127
|
-
if (!
|
|
13189
|
+
if (!fs22.existsSync(spokePath)) {
|
|
13128
13190
|
const spokeDriver = new WorkspaceRegistry({ obsidian: createObsidianDriver }).forProject(name, config);
|
|
13129
13191
|
await ensureSpokeLayout(spokeDriver);
|
|
13130
13192
|
console.log(chalk13.cyan(` \u2714 Created spoke vault at ${spokePath}`));
|
|
@@ -13162,7 +13224,7 @@ Launching ${selected.length} captain workspace(s) in parallel
|
|
|
13162
13224
|
const proj = config.projects[name];
|
|
13163
13225
|
const projPath = resolveHome(proj.path);
|
|
13164
13226
|
const spokePath = resolveHome(proj.spokeVault);
|
|
13165
|
-
if (!
|
|
13227
|
+
if (!fs22.existsSync(spokePath)) {
|
|
13166
13228
|
const spokeDriver = new WorkspaceRegistry({ obsidian: createObsidianDriver }).forProject(name, config);
|
|
13167
13229
|
await ensureSpokeLayout(spokeDriver);
|
|
13168
13230
|
console.log(chalk13.cyan(` \u2714 Created spoke vault at ${spokePath}`));
|
|
@@ -13186,7 +13248,7 @@ Launching ${selected.length} captain workspace(s) in parallel
|
|
|
13186
13248
|
const proj = config.projects[project];
|
|
13187
13249
|
const projPath = resolveHome(proj.path);
|
|
13188
13250
|
const spokePath = resolveHome(proj.spokeVault);
|
|
13189
|
-
if (!
|
|
13251
|
+
if (!fs22.existsSync(spokePath)) {
|
|
13190
13252
|
const spokeDriver = new WorkspaceRegistry({ obsidian: createObsidianDriver }).forProject(project, config);
|
|
13191
13253
|
await ensureSpokeLayout(spokeDriver);
|
|
13192
13254
|
console.log(chalk13.cyan(` \u2714 Created spoke vault at ${spokePath}`));
|
|
@@ -13322,7 +13384,7 @@ Shutting down captain workspace for '${project}'...
|
|
|
13322
13384
|
// packages/cli/src/commands/feedback.ts
|
|
13323
13385
|
init_dist();
|
|
13324
13386
|
import { Command as Command14 } from "commander";
|
|
13325
|
-
import
|
|
13387
|
+
import fs23 from "fs";
|
|
13326
13388
|
import os14 from "os";
|
|
13327
13389
|
import path25 from "path";
|
|
13328
13390
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -13332,14 +13394,14 @@ var REPO_URL = "https://github.com/tu11aa/squadrant";
|
|
|
13332
13394
|
function readPkgVersion() {
|
|
13333
13395
|
try {
|
|
13334
13396
|
const pkgPath = path25.join(path25.dirname(fileURLToPath3(import.meta.url)), "..", "package.json");
|
|
13335
|
-
return JSON.parse(
|
|
13397
|
+
return JSON.parse(fs23.readFileSync(pkgPath, "utf-8")).version ?? "unknown";
|
|
13336
13398
|
} catch {
|
|
13337
13399
|
return "unknown";
|
|
13338
13400
|
}
|
|
13339
13401
|
}
|
|
13340
13402
|
function readMetrics(metricsPath) {
|
|
13341
13403
|
try {
|
|
13342
|
-
return JSON.parse(
|
|
13404
|
+
return JSON.parse(fs23.readFileSync(metricsPath, "utf-8"));
|
|
13343
13405
|
} catch {
|
|
13344
13406
|
return {};
|
|
13345
13407
|
}
|
|
@@ -13399,7 +13461,7 @@ init_dist();
|
|
|
13399
13461
|
init_dist();
|
|
13400
13462
|
init_dist3();
|
|
13401
13463
|
import { Command as Command15 } from "commander";
|
|
13402
|
-
import
|
|
13464
|
+
import fs24 from "fs";
|
|
13403
13465
|
import path26 from "path";
|
|
13404
13466
|
import chalk16 from "chalk";
|
|
13405
13467
|
import matter3 from "gray-matter";
|
|
@@ -13411,9 +13473,9 @@ async function getProjectStandup(name, project, dateStr, registry, config) {
|
|
|
13411
13473
|
const spokeVault = resolveHome(project.spokeVault);
|
|
13412
13474
|
const statusFile = path26.join(spokeVault, "status.md");
|
|
13413
13475
|
let status = {};
|
|
13414
|
-
if (
|
|
13476
|
+
if (fs24.existsSync(statusFile)) {
|
|
13415
13477
|
try {
|
|
13416
|
-
status = matter3(
|
|
13478
|
+
status = matter3(fs24.readFileSync(statusFile, "utf-8")).data;
|
|
13417
13479
|
} catch {
|
|
13418
13480
|
}
|
|
13419
13481
|
}
|
|
@@ -13531,15 +13593,15 @@ init_dist();
|
|
|
13531
13593
|
init_dist();
|
|
13532
13594
|
init_dist3();
|
|
13533
13595
|
import { Command as Command16 } from "commander";
|
|
13534
|
-
import
|
|
13596
|
+
import fs25 from "fs";
|
|
13535
13597
|
import path27 from "path";
|
|
13536
13598
|
import chalk17 from "chalk";
|
|
13537
13599
|
import matter4 from "gray-matter";
|
|
13538
13600
|
function readStatus(spokeVault) {
|
|
13539
13601
|
const statusFile = path27.join(spokeVault, "status.md");
|
|
13540
|
-
if (!
|
|
13602
|
+
if (!fs25.existsSync(statusFile)) return {};
|
|
13541
13603
|
try {
|
|
13542
|
-
return matter4(
|
|
13604
|
+
return matter4(fs25.readFileSync(statusFile, "utf-8")).data;
|
|
13543
13605
|
} catch {
|
|
13544
13606
|
return {};
|
|
13545
13607
|
}
|
|
@@ -13730,7 +13792,9 @@ runtimeCommand.command("status").description("Print 'running' or 'stopped' for a
|
|
|
13730
13792
|
process.exit(2);
|
|
13731
13793
|
}
|
|
13732
13794
|
});
|
|
13733
|
-
|
|
13795
|
+
var SEND_CONFIRM_TIMEOUT_MS = 15e3;
|
|
13796
|
+
var SEND_CONFIRM_POLL_MS = 500;
|
|
13797
|
+
async function runRuntimeSend(arg1, arg2, opts, confirmOpts) {
|
|
13734
13798
|
const config = loadConfig();
|
|
13735
13799
|
const registry = buildRegistry();
|
|
13736
13800
|
if (opts.command && arg2 !== void 0) {
|
|
@@ -13740,7 +13804,7 @@ async function runRuntimeSend(arg1, arg2, opts) {
|
|
|
13740
13804
|
const message = opts.command ? arg1 : arg2;
|
|
13741
13805
|
if (!message) throw new Error("Message is required");
|
|
13742
13806
|
const { requireDaemon: requireDaemon2 } = await Promise.resolve().then(() => (init_require_daemon(), require_daemon_exports));
|
|
13743
|
-
const { appendCaptainMessage: appendCaptainMessage2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports2));
|
|
13807
|
+
const { appendCaptainMessage: appendCaptainMessage2, waitForCaptainDelivery: waitForCaptainDelivery2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports2));
|
|
13744
13808
|
await requireDaemon2();
|
|
13745
13809
|
const resolved = resolveTarget(registry, config, target, !!opts.command);
|
|
13746
13810
|
await needRef(resolved);
|
|
@@ -13748,16 +13812,30 @@ async function runRuntimeSend(arg1, arg2, opts) {
|
|
|
13748
13812
|
const { join: join30, dirname: dirname10 } = await import("path");
|
|
13749
13813
|
const { DEFAULT_CONFIG_PATH: DEFAULT_CONFIG_PATH2 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
|
|
13750
13814
|
const stateRoot = join30(dirname10(DEFAULT_CONFIG_PATH2), "state");
|
|
13751
|
-
await appendCaptainMessage2({
|
|
13815
|
+
const seq = await appendCaptainMessage2({
|
|
13752
13816
|
stateRoot,
|
|
13753
13817
|
project: finalProject,
|
|
13754
13818
|
text: message,
|
|
13755
13819
|
source: "cli"
|
|
13756
13820
|
});
|
|
13821
|
+
const timeoutMs = confirmOpts?.timeoutMs ?? SEND_CONFIRM_TIMEOUT_MS;
|
|
13822
|
+
const delivered = await waitForCaptainDelivery2({
|
|
13823
|
+
stateRoot,
|
|
13824
|
+
project: finalProject,
|
|
13825
|
+
seq,
|
|
13826
|
+
timeoutMs,
|
|
13827
|
+
pollMs: confirmOpts?.pollMs ?? SEND_CONFIRM_POLL_MS
|
|
13828
|
+
});
|
|
13829
|
+
if (!delivered) {
|
|
13830
|
+
throw new Error(
|
|
13831
|
+
`Message queued for '${finalProject}' (seq=${seq}) but delivery was not confirmed within ${Math.round(timeoutMs / 1e3)}s. It may still be pending \u2014 check with 'squadrant runtime read-screen ${finalProject}${opts.command ? " --command" : ""}'.`
|
|
13832
|
+
);
|
|
13833
|
+
}
|
|
13757
13834
|
}
|
|
13758
13835
|
runtimeCommand.command("send").description("Send a message to a target workspace AND commit with Enter. With --command, the first positional is the message.").argument("<arg1>", "Project name, or the message when --command is used").argument("[arg2]", "Message (when target is a project). Omit when using --command.").option("--command", "Target the command workspace").action(async (arg1, arg2, opts) => {
|
|
13759
13836
|
try {
|
|
13760
13837
|
await runRuntimeSend(arg1, arg2, opts);
|
|
13838
|
+
console.log(chalk18.green("\u2714 Delivered (confirmed)"));
|
|
13761
13839
|
} catch (err) {
|
|
13762
13840
|
console.error(chalk18.red(err.message));
|
|
13763
13841
|
process.exit(1);
|
|
@@ -13956,7 +14034,7 @@ init_dist3();
|
|
|
13956
14034
|
init_dist();
|
|
13957
14035
|
import { Command as Command20 } from "commander";
|
|
13958
14036
|
import chalk21 from "chalk";
|
|
13959
|
-
import
|
|
14037
|
+
import fs26 from "fs";
|
|
13960
14038
|
import path28 from "path";
|
|
13961
14039
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
13962
14040
|
function parseScope(v) {
|
|
@@ -13968,7 +14046,7 @@ function parseScope(v) {
|
|
|
13968
14046
|
function findPackageRoot3() {
|
|
13969
14047
|
let dir = path28.dirname(fileURLToPath4(import.meta.url));
|
|
13970
14048
|
while (dir !== "/" && dir !== "") {
|
|
13971
|
-
if (
|
|
14049
|
+
if (fs26.existsSync(path28.join(dir, "package.json"))) return dir;
|
|
13972
14050
|
dir = path28.dirname(dir);
|
|
13973
14051
|
}
|
|
13974
14052
|
return process.cwd();
|
|
@@ -14164,12 +14242,12 @@ init_dist();
|
|
|
14164
14242
|
init_dist();
|
|
14165
14243
|
init_dist2();
|
|
14166
14244
|
import { Command as Command22 } from "commander";
|
|
14167
|
-
import
|
|
14245
|
+
import fs27 from "fs";
|
|
14168
14246
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
14169
14247
|
import { dirname as dirname6, join as join25 } from "path";
|
|
14170
14248
|
import chalk22 from "chalk";
|
|
14171
14249
|
function runConfigCheck(opts) {
|
|
14172
|
-
const raw = JSON.parse(
|
|
14250
|
+
const raw = JSON.parse(fs27.readFileSync(opts.configPath, "utf-8"));
|
|
14173
14251
|
const def = getDefaultConfig();
|
|
14174
14252
|
const items = detectDrift(raw, def);
|
|
14175
14253
|
let working = raw;
|
|
@@ -14186,7 +14264,7 @@ function runConfigCheck(opts) {
|
|
|
14186
14264
|
stamped = true;
|
|
14187
14265
|
}
|
|
14188
14266
|
if (opts.fix || opts.accept || stamped) {
|
|
14189
|
-
|
|
14267
|
+
fs27.writeFileSync(opts.configPath, JSON.stringify(working, null, 2) + "\n");
|
|
14190
14268
|
}
|
|
14191
14269
|
return { items, applied, remaining, stamped };
|
|
14192
14270
|
}
|
|
@@ -14257,7 +14335,7 @@ function printItems(items) {
|
|
|
14257
14335
|
var configCommand = new Command22("config").description("Inspect and reconcile squadrant config");
|
|
14258
14336
|
configCommand.command("check").description("Detect config drift vs the current default schema").option("--fix", "Apply the safe tier (add missing, remove deprecated)", false).option("--accept", "Stamp the current version without changing config (dismiss advisories)", false).option("--json", "Output drift items as JSON", false).action((opts) => {
|
|
14259
14337
|
const pkgVersion = readPkgVersion2();
|
|
14260
|
-
if (!
|
|
14338
|
+
if (!fs27.existsSync(DEFAULT_CONFIG_PATH)) {
|
|
14261
14339
|
console.log(chalk22.yellow("No config found \u2014 run `squadrant init` first."));
|
|
14262
14340
|
return;
|
|
14263
14341
|
}
|
|
@@ -14303,7 +14381,7 @@ configCommand.command("set").description("Write a config value by dotted key (e.
|
|
|
14303
14381
|
});
|
|
14304
14382
|
function readPkgVersion2() {
|
|
14305
14383
|
const pkgPath = join25(dirname6(fileURLToPath5(import.meta.url)), "..", "package.json");
|
|
14306
|
-
return JSON.parse(
|
|
14384
|
+
return JSON.parse(fs27.readFileSync(pkgPath, "utf-8")).version;
|
|
14307
14385
|
}
|
|
14308
14386
|
|
|
14309
14387
|
// packages/cli/src/commands/heal.ts
|
|
@@ -14543,7 +14621,7 @@ var cmuxCommand = new Command27("cmux").description("cmux integration helpers").
|
|
|
14543
14621
|
// packages/cli/src/commands/effort.ts
|
|
14544
14622
|
init_dist();
|
|
14545
14623
|
init_dist2();
|
|
14546
|
-
import
|
|
14624
|
+
import fs28 from "fs";
|
|
14547
14625
|
import path29 from "path";
|
|
14548
14626
|
import { Command as Command28 } from "commander";
|
|
14549
14627
|
import chalk28 from "chalk";
|
|
@@ -14571,7 +14649,7 @@ function runEffortSet(value, configPath = DEFAULT_CONFIG_PATH) {
|
|
|
14571
14649
|
}
|
|
14572
14650
|
function canonical(p) {
|
|
14573
14651
|
try {
|
|
14574
|
-
return
|
|
14652
|
+
return fs28.realpathSync(p);
|
|
14575
14653
|
} catch {
|
|
14576
14654
|
return path29.resolve(p);
|
|
14577
14655
|
}
|