@gluecharm-lab/easyspecs-cli 0.0.26 → 0.0.28
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/commands.md +14 -3
- package/dist/main.cjs +497 -193
- package/dist/main.cjs.map +4 -4
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -960,7 +960,7 @@ var require_command = __commonJS({
|
|
|
960
960
|
var EventEmitter = require("node:events").EventEmitter;
|
|
961
961
|
var childProcess = require("node:child_process");
|
|
962
962
|
var path60 = require("node:path");
|
|
963
|
-
var
|
|
963
|
+
var fs63 = require("node:fs");
|
|
964
964
|
var process2 = require("node:process");
|
|
965
965
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
966
966
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -1893,10 +1893,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1893
1893
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1894
1894
|
function findFile(baseDir, baseName) {
|
|
1895
1895
|
const localBin = path60.resolve(baseDir, baseName);
|
|
1896
|
-
if (
|
|
1896
|
+
if (fs63.existsSync(localBin)) return localBin;
|
|
1897
1897
|
if (sourceExt.includes(path60.extname(baseName))) return void 0;
|
|
1898
1898
|
const foundExt = sourceExt.find(
|
|
1899
|
-
(ext) =>
|
|
1899
|
+
(ext) => fs63.existsSync(`${localBin}${ext}`)
|
|
1900
1900
|
);
|
|
1901
1901
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1902
1902
|
return void 0;
|
|
@@ -1908,7 +1908,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1908
1908
|
if (this._scriptPath) {
|
|
1909
1909
|
let resolvedScriptPath;
|
|
1910
1910
|
try {
|
|
1911
|
-
resolvedScriptPath =
|
|
1911
|
+
resolvedScriptPath = fs63.realpathSync(this._scriptPath);
|
|
1912
1912
|
} catch (err) {
|
|
1913
1913
|
resolvedScriptPath = this._scriptPath;
|
|
1914
1914
|
}
|
|
@@ -10622,12 +10622,12 @@ var require_dist = __commonJS({
|
|
|
10622
10622
|
throw new Error(`Unknown format "${name}"`);
|
|
10623
10623
|
return f;
|
|
10624
10624
|
};
|
|
10625
|
-
function addFormats2(ajv2, list,
|
|
10625
|
+
function addFormats2(ajv2, list, fs63, exportName) {
|
|
10626
10626
|
var _a;
|
|
10627
10627
|
var _b;
|
|
10628
10628
|
(_a = (_b = ajv2.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
10629
10629
|
for (const f of list)
|
|
10630
|
-
ajv2.addFormat(f,
|
|
10630
|
+
ajv2.addFormat(f, fs63[f]);
|
|
10631
10631
|
}
|
|
10632
10632
|
module2.exports = exports2 = formatsPlugin;
|
|
10633
10633
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -10636,7 +10636,7 @@ var require_dist = __commonJS({
|
|
|
10636
10636
|
});
|
|
10637
10637
|
|
|
10638
10638
|
// src/cli/main.ts
|
|
10639
|
-
var
|
|
10639
|
+
var fs62 = __toESM(require("node:fs"));
|
|
10640
10640
|
var path59 = __toESM(require("node:path"));
|
|
10641
10641
|
|
|
10642
10642
|
// src/cli/exitCodes.ts
|
|
@@ -10707,7 +10707,7 @@ function createEasyspecsCliProgram() {
|
|
|
10707
10707
|
program2.command("help").description("Show help");
|
|
10708
10708
|
program2.command("version").description("Print CLI version");
|
|
10709
10709
|
const workstation = program2.command("workstation").description("Host inventory for AI workstation sizing");
|
|
10710
|
-
workstation.command("info").description("Print CPU, RAM, and SRS-
|
|
10710
|
+
workstation.command("info").description("Print CPU, RAM, and SRS-69 N_sys (macOS and Linux only; use global --json)").allowUnknownOption(false);
|
|
10711
10711
|
program2.command("doctor").description("Check readiness and/or inspect configuration").option("--readiness", "Print readiness summary (default)").option("--inspect-config", "Print redacted merged configuration");
|
|
10712
10712
|
const auth = program2.command("auth").description("Authentication");
|
|
10713
10713
|
auth.command("login").description("Log in").option("--email <email>", "Email address").option("--password <password>", "Password").option("--session-path <path>", "Session JSON path override for this run").option("--ci", "Use easyspecs.auth.ciLogin from config when argv credentials are omitted");
|
|
@@ -11245,6 +11245,8 @@ var import_node_child_process2 = require("node:child_process");
|
|
|
11245
11245
|
var ABSOLUTE_MAX_CONCURRENT_AI = 64;
|
|
11246
11246
|
|
|
11247
11247
|
// src/config/machineConcurrentAiFromHost.ts
|
|
11248
|
+
var AGENTS_PER_PHYSICAL_CORE = 1;
|
|
11249
|
+
var RAM_GIB_PER_AGENT = 8;
|
|
11248
11250
|
function clampProductConcurrentLimits(n) {
|
|
11249
11251
|
if (!Number.isFinite(n)) {
|
|
11250
11252
|
return DEFAULT_MAX_CONCURRENT_AI;
|
|
@@ -11261,13 +11263,9 @@ function machineConcurrentAiCapFromHost(profile) {
|
|
|
11261
11263
|
if (!Number.isFinite(rGib) || rGib <= 0) {
|
|
11262
11264
|
return 1;
|
|
11263
11265
|
}
|
|
11264
|
-
|
|
11265
|
-
|
|
11266
|
-
|
|
11267
|
-
} else {
|
|
11268
|
-
nCpuFloat = 100 + 8.5 * (p - 11);
|
|
11269
|
-
}
|
|
11270
|
-
const ramFactor = Math.min(1, rGib / (4 * p));
|
|
11266
|
+
const nCpuFloat = AGENTS_PER_PHYSICAL_CORE * p;
|
|
11267
|
+
const ramRefGib = RAM_GIB_PER_AGENT * p;
|
|
11268
|
+
const ramFactor = Math.min(1, rGib / ramRefGib);
|
|
11271
11269
|
const nFloat = nCpuFloat * ramFactor;
|
|
11272
11270
|
const rounded = Math.round(nFloat);
|
|
11273
11271
|
return Math.max(1, rounded);
|
|
@@ -13192,7 +13190,7 @@ function createFileBackedWorkspaceState(repoRoot) {
|
|
|
13192
13190
|
}
|
|
13193
13191
|
|
|
13194
13192
|
// src/pipelines/synthesis/synthesisPipeline.ts
|
|
13195
|
-
var
|
|
13193
|
+
var fs37 = __toESM(require("fs"));
|
|
13196
13194
|
var path32 = __toESM(require("path"));
|
|
13197
13195
|
|
|
13198
13196
|
// src/analysis/analysisDynamicTestSteps.ts
|
|
@@ -20329,6 +20327,295 @@ function nextAdaptiveMaxAfterCpuSample(p) {
|
|
|
20329
20327
|
return { adaptiveMax: p.priorAdaptiveMax, changed: false };
|
|
20330
20328
|
}
|
|
20331
20329
|
|
|
20330
|
+
// src/hostPoolPeriodicDiagnostics.ts
|
|
20331
|
+
var fs36 = __toESM(require("fs"));
|
|
20332
|
+
var DEFAULT_HOST_POOL_INTERVAL_MS = 45e3;
|
|
20333
|
+
var MAX_ADVICE_TEXT_CHARS = 400;
|
|
20334
|
+
var MAX_FD_ENUM = 4096;
|
|
20335
|
+
var TEMPLATE_MEMORY_KO = "Low free RAM or swap in this worker: lower easyspecs.workstations.maxConcurrentAi (or host concurrency cap), raise Celery worker or container memory if you can, and verify with vmstat or cgroup memory stats.";
|
|
20336
|
+
var TEMPLATE_SCHEDULER_KO = "High load vs CPUs in this worker: lower easyspecs.workstations.maxConcurrentAi and watch earlier [pool] lines for adaptive cap changes; if load stays high while only this task runs, check worker CPU limits or VM CPU steal.";
|
|
20337
|
+
var TEMPLATE_IO_KO = "Elevated I/O wait (Linux /proc delta): check disk saturation with iostat or vmstat; fewer easyspecs concurrent agents help; on a host dedicated to this task, inspect storage latency, disk quotas, or shared volume contention.";
|
|
20338
|
+
var TEMPLATE_LIMITS_KO = "This Node process is near soft FD/process/thread limits: raise ulimit or prlimit for the Celery worker process, or lower easyspecs.workstations.maxConcurrentAi; confirm with /proc/self/limits.";
|
|
20339
|
+
function hintSchedulerFromSnapshot(s) {
|
|
20340
|
+
const p = s.load1PerCpu;
|
|
20341
|
+
if (p === null || !Number.isFinite(p)) {
|
|
20342
|
+
return "UNK";
|
|
20343
|
+
}
|
|
20344
|
+
if (p >= 1.25) {
|
|
20345
|
+
return "KO";
|
|
20346
|
+
}
|
|
20347
|
+
if (p < 1) {
|
|
20348
|
+
return "OK";
|
|
20349
|
+
}
|
|
20350
|
+
return "UNK";
|
|
20351
|
+
}
|
|
20352
|
+
function hintMemoryFrom(platform, s, swap) {
|
|
20353
|
+
const total = s.hostRamTotalB;
|
|
20354
|
+
if (total <= 0) {
|
|
20355
|
+
return "UNK";
|
|
20356
|
+
}
|
|
20357
|
+
const freeRatio = s.hostRamFreeB / total;
|
|
20358
|
+
let ram;
|
|
20359
|
+
if (freeRatio < 0.07) {
|
|
20360
|
+
ram = "KO";
|
|
20361
|
+
} else if (freeRatio < 0.1) {
|
|
20362
|
+
ram = "UNK";
|
|
20363
|
+
} else {
|
|
20364
|
+
ram = "OK";
|
|
20365
|
+
}
|
|
20366
|
+
let swapH = "OK";
|
|
20367
|
+
if (platform === "linux" && swap !== null && swap.swapTotalB > 0) {
|
|
20368
|
+
const sf = swap.swapFreeB / swap.swapTotalB;
|
|
20369
|
+
if (sf < 0.08) {
|
|
20370
|
+
swapH = "KO";
|
|
20371
|
+
} else if (sf < 0.15) {
|
|
20372
|
+
swapH = "UNK";
|
|
20373
|
+
} else {
|
|
20374
|
+
swapH = "OK";
|
|
20375
|
+
}
|
|
20376
|
+
}
|
|
20377
|
+
if (ram === "KO" || swapH === "KO") {
|
|
20378
|
+
return "KO";
|
|
20379
|
+
}
|
|
20380
|
+
if (ram === "UNK" || swapH === "UNK") {
|
|
20381
|
+
return "UNK";
|
|
20382
|
+
}
|
|
20383
|
+
return "OK";
|
|
20384
|
+
}
|
|
20385
|
+
function hintLimitsFrom(sample) {
|
|
20386
|
+
if (sample === null) {
|
|
20387
|
+
return "UNK";
|
|
20388
|
+
}
|
|
20389
|
+
if (sample.truncated) {
|
|
20390
|
+
return "UNK";
|
|
20391
|
+
}
|
|
20392
|
+
const ratios = [];
|
|
20393
|
+
if (sample.fdRatio !== null && Number.isFinite(sample.fdRatio)) {
|
|
20394
|
+
ratios.push(sample.fdRatio);
|
|
20395
|
+
}
|
|
20396
|
+
if (sample.procRatio !== null && Number.isFinite(sample.procRatio)) {
|
|
20397
|
+
ratios.push(sample.procRatio);
|
|
20398
|
+
}
|
|
20399
|
+
if (ratios.length === 0) {
|
|
20400
|
+
return "UNK";
|
|
20401
|
+
}
|
|
20402
|
+
if (ratios.some((r) => r >= 0.85)) {
|
|
20403
|
+
return "KO";
|
|
20404
|
+
}
|
|
20405
|
+
if (ratios.every((r) => r < 0.75)) {
|
|
20406
|
+
return "OK";
|
|
20407
|
+
}
|
|
20408
|
+
return "UNK";
|
|
20409
|
+
}
|
|
20410
|
+
function hintIoFrom(prev, curr) {
|
|
20411
|
+
if (prev === null || curr === null) {
|
|
20412
|
+
return "UNK";
|
|
20413
|
+
}
|
|
20414
|
+
const dTotal = curr.total - prev.total;
|
|
20415
|
+
const dIo = curr.iowait - prev.iowait;
|
|
20416
|
+
if (dTotal <= 0 || !Number.isFinite(dTotal) || !Number.isFinite(dIo)) {
|
|
20417
|
+
return "UNK";
|
|
20418
|
+
}
|
|
20419
|
+
const share = dIo / dTotal;
|
|
20420
|
+
if (!Number.isFinite(share)) {
|
|
20421
|
+
return "UNK";
|
|
20422
|
+
}
|
|
20423
|
+
if (share >= 0.22) {
|
|
20424
|
+
return "KO";
|
|
20425
|
+
}
|
|
20426
|
+
if (share <= 0.12) {
|
|
20427
|
+
return "OK";
|
|
20428
|
+
}
|
|
20429
|
+
return "UNK";
|
|
20430
|
+
}
|
|
20431
|
+
function computeHostPoolHints(input) {
|
|
20432
|
+
return {
|
|
20433
|
+
hintScheduler: hintSchedulerFromSnapshot(input.snapshot),
|
|
20434
|
+
hintMemory: hintMemoryFrom(input.platform, input.snapshot, input.swap),
|
|
20435
|
+
hintLimits: hintLimitsFrom(input.limits),
|
|
20436
|
+
hintIo: hintIoFrom(input.prevStat, input.currStat)
|
|
20437
|
+
};
|
|
20438
|
+
}
|
|
20439
|
+
function tryReadLinuxSwapBytesFromMeminfo(readFileSyncImpl = fs36.readFileSync) {
|
|
20440
|
+
let raw;
|
|
20441
|
+
try {
|
|
20442
|
+
raw = readFileSyncImpl("/proc/meminfo", { encoding: "utf8", flag: "r" });
|
|
20443
|
+
} catch {
|
|
20444
|
+
return null;
|
|
20445
|
+
}
|
|
20446
|
+
let swapTotalKb = null;
|
|
20447
|
+
let swapFreeKb = null;
|
|
20448
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
20449
|
+
const tm = /^\s*SwapTotal:\s+(\d+)\s+kB/i.exec(line);
|
|
20450
|
+
if (tm) {
|
|
20451
|
+
swapTotalKb = Number(tm[1]);
|
|
20452
|
+
}
|
|
20453
|
+
const fm = /^\s*SwapFree:\s+(\d+)\s+kB/i.exec(line);
|
|
20454
|
+
if (fm) {
|
|
20455
|
+
swapFreeKb = Number(fm[1]);
|
|
20456
|
+
}
|
|
20457
|
+
}
|
|
20458
|
+
if (swapTotalKb === null || swapFreeKb === null || !Number.isFinite(swapTotalKb) || !Number.isFinite(swapFreeKb) || swapTotalKb < 0 || swapFreeKb < 0) {
|
|
20459
|
+
return null;
|
|
20460
|
+
}
|
|
20461
|
+
return {
|
|
20462
|
+
swapTotalB: Math.floor(swapTotalKb * 1024),
|
|
20463
|
+
swapFreeB: Math.floor(swapFreeKb * 1024)
|
|
20464
|
+
};
|
|
20465
|
+
}
|
|
20466
|
+
function tryReadLinuxAggregateCpuJiffies(readFileSyncImpl = fs36.readFileSync) {
|
|
20467
|
+
let raw;
|
|
20468
|
+
try {
|
|
20469
|
+
raw = readFileSyncImpl("/proc/stat", { encoding: "utf8", flag: "r" });
|
|
20470
|
+
} catch {
|
|
20471
|
+
return null;
|
|
20472
|
+
}
|
|
20473
|
+
const firstLine = raw.split(/\r?\n/)[0] ?? "";
|
|
20474
|
+
return parseLinuxAggregateCpuLine(firstLine);
|
|
20475
|
+
}
|
|
20476
|
+
function parseLinuxAggregateCpuLine(line) {
|
|
20477
|
+
const t = line.trim();
|
|
20478
|
+
if (!t.startsWith("cpu") || /^cpu\d/.test(t)) {
|
|
20479
|
+
return null;
|
|
20480
|
+
}
|
|
20481
|
+
const parts = t.split(/\s+/);
|
|
20482
|
+
if (parts.length < 6 || parts[0] !== "cpu") {
|
|
20483
|
+
return null;
|
|
20484
|
+
}
|
|
20485
|
+
const nums = [];
|
|
20486
|
+
for (let i = 1; i < parts.length; i++) {
|
|
20487
|
+
const n = Number(parts[i]);
|
|
20488
|
+
if (!Number.isFinite(n) || n < 0) {
|
|
20489
|
+
return null;
|
|
20490
|
+
}
|
|
20491
|
+
nums.push(Math.floor(n));
|
|
20492
|
+
}
|
|
20493
|
+
const total = nums.reduce((a, b) => a + b, 0);
|
|
20494
|
+
const iowait = nums.length >= 5 ? nums[4] : 0;
|
|
20495
|
+
return { total, iowait };
|
|
20496
|
+
}
|
|
20497
|
+
function parseProcSelfLimitsSoft(content, label) {
|
|
20498
|
+
const re = label === "Max open files" ? /^\s*Max open files\s+(\d+)\s+(\d+)/m : /^\s*Max processes\s+(\d+)\s+(\d+)/m;
|
|
20499
|
+
const m = re.exec(content);
|
|
20500
|
+
if (!m) {
|
|
20501
|
+
return null;
|
|
20502
|
+
}
|
|
20503
|
+
const soft = Number(m[1]);
|
|
20504
|
+
return Number.isFinite(soft) && soft > 0 ? soft : null;
|
|
20505
|
+
}
|
|
20506
|
+
function parseProcSelfStatusThreads(content) {
|
|
20507
|
+
const m = /^\s*Threads:\s*(\d+)/m.exec(content);
|
|
20508
|
+
if (!m) {
|
|
20509
|
+
return null;
|
|
20510
|
+
}
|
|
20511
|
+
const n = Number(m[1]);
|
|
20512
|
+
return Number.isFinite(n) && n >= 0 ? n : null;
|
|
20513
|
+
}
|
|
20514
|
+
function trySampleLinuxLimits(platform, readFileSyncImpl = fs36.readFileSync, readdirSyncImpl = fs36.readdirSync) {
|
|
20515
|
+
if (platform !== "linux") {
|
|
20516
|
+
return null;
|
|
20517
|
+
}
|
|
20518
|
+
let limitsRaw;
|
|
20519
|
+
let statusRaw;
|
|
20520
|
+
try {
|
|
20521
|
+
limitsRaw = readFileSyncImpl("/proc/self/limits", { encoding: "utf8", flag: "r" });
|
|
20522
|
+
statusRaw = readFileSyncImpl("/proc/self/status", { encoding: "utf8", flag: "r" });
|
|
20523
|
+
} catch {
|
|
20524
|
+
return null;
|
|
20525
|
+
}
|
|
20526
|
+
const nofileSoft = parseProcSelfLimitsSoft(limitsRaw, "Max open files");
|
|
20527
|
+
const nprocSoft = parseProcSelfLimitsSoft(limitsRaw, "Max processes");
|
|
20528
|
+
const threads = parseProcSelfStatusThreads(statusRaw);
|
|
20529
|
+
let fdCount = 0;
|
|
20530
|
+
let truncated = false;
|
|
20531
|
+
try {
|
|
20532
|
+
const names = readdirSyncImpl("/proc/self/fd");
|
|
20533
|
+
truncated = names.length > MAX_FD_ENUM;
|
|
20534
|
+
fdCount = Math.min(names.length, MAX_FD_ENUM);
|
|
20535
|
+
} catch {
|
|
20536
|
+
return { fdRatio: null, procRatio: null, truncated: true };
|
|
20537
|
+
}
|
|
20538
|
+
const fdRatio = nofileSoft !== null && nofileSoft > 0 ? Math.min(1, fdCount / nofileSoft) : null;
|
|
20539
|
+
const procRatio = nprocSoft !== null && nprocSoft > 0 && threads !== null ? Math.min(1, threads / nprocSoft) : null;
|
|
20540
|
+
return { fdRatio, procRatio, truncated };
|
|
20541
|
+
}
|
|
20542
|
+
function formatHostPoolPeriodicLine(params) {
|
|
20543
|
+
const s = params.snapshot;
|
|
20544
|
+
const load1Str = s.load1 === null ? "unknown" : String(s.load1);
|
|
20545
|
+
const perCpuStr = s.load1PerCpu === null ? "unknown" : String(s.load1PerCpu);
|
|
20546
|
+
const swapPart = params.swap !== null ? ` swapTotalB=${String(params.swap.swapTotalB)} swapFreeB=${String(params.swap.swapFreeB)}` : "";
|
|
20547
|
+
return `[host-pool] activeWorkstations=${String(params.activeWorkstations)} staticMaxConcurrentAi=${String(params.staticMaxConcurrentAi)} adaptiveMaxConcurrentAi=${String(params.adaptiveMaxConcurrentAi)} hostRamTotalB=${String(s.hostRamTotalB)} hostRamFreeB=${String(s.hostRamFreeB)} hostRamUsedB=${String(s.hostRamUsedB)} cpusLogical=${String(s.cpusLogical)} load1=${load1Str} load1PerCpu=${perCpuStr}${swapPart} hintScheduler=${params.hints.hintScheduler} hintMemory=${params.hints.hintMemory} hintLimits=${params.hints.hintLimits} hintIo=${params.hints.hintIo}`;
|
|
20548
|
+
}
|
|
20549
|
+
function anyKo(h) {
|
|
20550
|
+
return h.hintMemory === "KO" || h.hintScheduler === "KO" || h.hintIo === "KO" || h.hintLimits === "KO";
|
|
20551
|
+
}
|
|
20552
|
+
function formatHostPoolRecLine(hints) {
|
|
20553
|
+
if (!anyKo(hints)) {
|
|
20554
|
+
return "[host-pool-rec] kind=none";
|
|
20555
|
+
}
|
|
20556
|
+
const parts = [];
|
|
20557
|
+
if (hints.hintMemory === "KO") {
|
|
20558
|
+
parts.push(TEMPLATE_MEMORY_KO);
|
|
20559
|
+
}
|
|
20560
|
+
if (hints.hintScheduler === "KO") {
|
|
20561
|
+
parts.push(TEMPLATE_SCHEDULER_KO);
|
|
20562
|
+
}
|
|
20563
|
+
if (hints.hintIo === "KO") {
|
|
20564
|
+
parts.push(TEMPLATE_IO_KO);
|
|
20565
|
+
}
|
|
20566
|
+
if (hints.hintLimits === "KO") {
|
|
20567
|
+
parts.push(TEMPLATE_LIMITS_KO);
|
|
20568
|
+
}
|
|
20569
|
+
let text = parts.join(" | ");
|
|
20570
|
+
if (text.length > MAX_ADVICE_TEXT_CHARS) {
|
|
20571
|
+
text = `${text.slice(0, MAX_ADVICE_TEXT_CHARS - 2)} \u2026`;
|
|
20572
|
+
}
|
|
20573
|
+
return `[host-pool-rec] kind=advice text=${text}`;
|
|
20574
|
+
}
|
|
20575
|
+
function createHostPoolTick(deps) {
|
|
20576
|
+
const platform = deps.platform ?? process.platform;
|
|
20577
|
+
const collect = deps.collectHostSnapshotFn ?? collectHostSnapshot;
|
|
20578
|
+
const readFs = deps.readFileSyncFn ?? fs36.readFileSync;
|
|
20579
|
+
const readDir = deps.readdirSyncFn ?? fs36.readdirSync;
|
|
20580
|
+
return () => {
|
|
20581
|
+
const { active, staticMaxConcurrentAi, adaptiveMaxConcurrentAi } = deps.getPoolState();
|
|
20582
|
+
if (active < 1) {
|
|
20583
|
+
return;
|
|
20584
|
+
}
|
|
20585
|
+
const snapshot = collect();
|
|
20586
|
+
let swap = null;
|
|
20587
|
+
let currStat = null;
|
|
20588
|
+
let limits = null;
|
|
20589
|
+
if (platform === "linux") {
|
|
20590
|
+
swap = tryReadLinuxSwapBytesFromMeminfo(readFs);
|
|
20591
|
+
currStat = tryReadLinuxAggregateCpuJiffies(readFs);
|
|
20592
|
+
limits = trySampleLinuxLimits(platform, readFs, readDir);
|
|
20593
|
+
}
|
|
20594
|
+
const hints = computeHostPoolHints({
|
|
20595
|
+
platform,
|
|
20596
|
+
snapshot,
|
|
20597
|
+
swap,
|
|
20598
|
+
limits,
|
|
20599
|
+
prevStat: deps.prevProcStatRef.current,
|
|
20600
|
+
currStat
|
|
20601
|
+
});
|
|
20602
|
+
const metrics = formatHostPoolPeriodicLine({
|
|
20603
|
+
activeWorkstations: active,
|
|
20604
|
+
staticMaxConcurrentAi,
|
|
20605
|
+
adaptiveMaxConcurrentAi,
|
|
20606
|
+
snapshot,
|
|
20607
|
+
hints,
|
|
20608
|
+
swap
|
|
20609
|
+
});
|
|
20610
|
+
const rec = formatHostPoolRecLine(hints);
|
|
20611
|
+
deps.log(metrics);
|
|
20612
|
+
deps.log(rec);
|
|
20613
|
+
if (platform === "linux" && currStat !== null) {
|
|
20614
|
+
deps.prevProcStatRef.current = currStat;
|
|
20615
|
+
}
|
|
20616
|
+
};
|
|
20617
|
+
}
|
|
20618
|
+
|
|
20332
20619
|
// src/pipelines/synthesis/synthesisPipeline.ts
|
|
20333
20620
|
var FE = /^FE-\d+$/;
|
|
20334
20621
|
var UC = /^UC-\d+$/;
|
|
@@ -20341,7 +20628,7 @@ function stripBom2(s) {
|
|
|
20341
20628
|
}
|
|
20342
20629
|
function readJson4(filePath) {
|
|
20343
20630
|
try {
|
|
20344
|
-
const raw = stripBom2(
|
|
20631
|
+
const raw = stripBom2(fs37.readFileSync(filePath, "utf-8"));
|
|
20345
20632
|
return JSON.parse(raw);
|
|
20346
20633
|
} catch {
|
|
20347
20634
|
return null;
|
|
@@ -20436,7 +20723,7 @@ function featureDetailTarget(contextDir2, code, name, slug) {
|
|
|
20436
20723
|
displayName: "Feature detail",
|
|
20437
20724
|
outputBasename: basename17,
|
|
20438
20725
|
taskDescription: `Document feature **${code}** (**${name}**, slug **${slug}**) per \`.gluecharm/context/features-list.json\`: scope, behaviour, main dependencies, entry points, and links to code under the worktree. Write exactly one markdown file at the output path; cite substantive claims with file and line (or range).`,
|
|
20439
|
-
exists:
|
|
20726
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20440
20727
|
};
|
|
20441
20728
|
}
|
|
20442
20729
|
function viewDetailTarget(row2, contextDir2) {
|
|
@@ -20447,7 +20734,7 @@ function viewDetailTarget(row2, contextDir2) {
|
|
|
20447
20734
|
displayName: "View detail",
|
|
20448
20735
|
outputBasename: basename17,
|
|
20449
20736
|
taskDescription: `Describe view **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/experiences-list.json\`: purpose, layout, controls, navigation, data shown; ground in components and routes.`,
|
|
20450
|
-
exists:
|
|
20737
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20451
20738
|
};
|
|
20452
20739
|
}
|
|
20453
20740
|
function interactionDetailTarget(viewCode, ix, contextDir2) {
|
|
@@ -20458,7 +20745,7 @@ function interactionDetailTarget(viewCode, ix, contextDir2) {
|
|
|
20458
20745
|
displayName: "Interaction detail",
|
|
20459
20746
|
outputBasename: basename17,
|
|
20460
20747
|
taskDescription: `Document interaction **${ix.code}** (**${ix.name}**) on view **${viewCode}** per \`.gluecharm/context/experiences-list.json\`.`,
|
|
20461
|
-
exists:
|
|
20748
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20462
20749
|
};
|
|
20463
20750
|
}
|
|
20464
20751
|
function serviceDetailTarget(row2, contextDir2) {
|
|
@@ -20469,7 +20756,7 @@ function serviceDetailTarget(row2, contextDir2) {
|
|
|
20469
20756
|
displayName: "Service detail",
|
|
20470
20757
|
outputBasename: basename17,
|
|
20471
20758
|
taskDescription: `Describe service **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/services-list.json\`: responsibilities, consumers, errors, integration points.`,
|
|
20472
|
-
exists:
|
|
20759
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20473
20760
|
};
|
|
20474
20761
|
}
|
|
20475
20762
|
function methodDetailTarget(svc, m, contextDir2) {
|
|
@@ -20480,7 +20767,7 @@ function methodDetailTarget(svc, m, contextDir2) {
|
|
|
20480
20767
|
displayName: "Method detail",
|
|
20481
20768
|
outputBasename: basename17,
|
|
20482
20769
|
taskDescription: `Document method **${m.code}** (**${m.name}**) on service **${svc.code}** per \`.gluecharm/context/services-list.json\`.`,
|
|
20483
|
-
exists:
|
|
20770
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20484
20771
|
};
|
|
20485
20772
|
}
|
|
20486
20773
|
function entityDetailTarget(dmCode, ename, slug, contextDir2) {
|
|
@@ -20491,7 +20778,7 @@ function entityDetailTarget(dmCode, ename, slug, contextDir2) {
|
|
|
20491
20778
|
displayName: "Entity detail",
|
|
20492
20779
|
outputBasename: basename17,
|
|
20493
20780
|
taskDescription: `Describe entity **${dmCode}** (**${ename}**, slug **${slug}**) per \`.gluecharm/context/data-model-list.json\`: lifecycle, invariants, storage, ORM/schema mapping.`,
|
|
20494
|
-
exists:
|
|
20781
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20495
20782
|
};
|
|
20496
20783
|
}
|
|
20497
20784
|
function fieldDetailTarget(dmCode, fdCode, fname, fSlug, contextDir2) {
|
|
@@ -20502,7 +20789,7 @@ function fieldDetailTarget(dmCode, fdCode, fname, fSlug, contextDir2) {
|
|
|
20502
20789
|
displayName: "Field detail",
|
|
20503
20790
|
outputBasename: basename17,
|
|
20504
20791
|
taskDescription: `Document field **${fdCode}** (**${fname}**) on entity **${dmCode}** per \`.gluecharm/context/${dmCode}-fields-list.json\`. Cite types and constraints with file and line.`,
|
|
20505
|
-
exists:
|
|
20792
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20506
20793
|
};
|
|
20507
20794
|
}
|
|
20508
20795
|
function toolDetailTarget(row2, contextDir2) {
|
|
@@ -20513,7 +20800,7 @@ function toolDetailTarget(row2, contextDir2) {
|
|
|
20513
20800
|
displayName: "Tool detail",
|
|
20514
20801
|
outputBasename: basename17,
|
|
20515
20802
|
taskDescription: `Describe tool **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/tech-stack-list.json\`: role, version hints, configuration, boundaries.`,
|
|
20516
|
-
exists:
|
|
20803
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20517
20804
|
};
|
|
20518
20805
|
}
|
|
20519
20806
|
function useCaseDetailTarget(feCode, ucCode, ucName, ucSlug, contextDir2) {
|
|
@@ -20526,7 +20813,7 @@ function useCaseDetailTarget(feCode, ucCode, ucName, ucSlug, contextDir2) {
|
|
|
20526
20813
|
taskDescription: `Document use case **${ucCode}** (**${ucName}**) under feature **${feCode}** per \`.gluecharm/context/${feCode}-use-cases-list.json\`. Do not change stable codes.
|
|
20527
20814
|
|
|
20528
20815
|
Follow bundled agent **agent-md-use-case-detail**: include **## Data inputs and validation** (concrete fields, mandatory vs optional, rules, failure behaviour). **## Code flow** must trace **implementation order** (entrypoint \u2192 validation \u2192 business rules \u2192 persistence \u2192 response) with **real** symbols and files\u2014not generic \u201Cuser does X\u201D. Add a **Mermaid** fenced diagram under Code flow when there are **two or more** implementation stages. **## Evidence index** must cite **each major stage** (validation, persistence, response), not only the outer entrypoint.`,
|
|
20529
|
-
exists:
|
|
20816
|
+
exists: fs37.existsSync(path32.join(contextDir2, ucBase)) && fs37.statSync(path32.join(contextDir2, ucBase)).size > 0
|
|
20530
20817
|
};
|
|
20531
20818
|
}
|
|
20532
20819
|
function scenarioDetailTarget(feCode, ucCode, scCode, scName, contextDir2) {
|
|
@@ -20537,7 +20824,7 @@ function scenarioDetailTarget(feCode, ucCode, scCode, scName, contextDir2) {
|
|
|
20537
20824
|
displayName: "Scenario detail",
|
|
20538
20825
|
outputBasename: basename17,
|
|
20539
20826
|
taskDescription: `Document scenario **${scCode}** (**${scName}**) for **${feCode}** / **${ucCode}** per \`.gluecharm/context/${feCode}_${ucCode}-scenarios-list.json\`. Cite steps with file and line where possible.`,
|
|
20540
|
-
exists:
|
|
20827
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20541
20828
|
};
|
|
20542
20829
|
}
|
|
20543
20830
|
function parentsDone(item, byId) {
|
|
@@ -21097,6 +21384,20 @@ async function drainWorkstationPool(p) {
|
|
|
21097
21384
|
const intervalMs = p.__testOnlyCpuPressureIntervalMs ?? 3e4;
|
|
21098
21385
|
pressureInterval = setInterval(() => applyCpuPressure(), intervalMs);
|
|
21099
21386
|
}
|
|
21387
|
+
const hostPoolPrevStat = { current: null };
|
|
21388
|
+
const hostPoolTick = createHostPoolTick({
|
|
21389
|
+
log,
|
|
21390
|
+
getPoolState: () => ({
|
|
21391
|
+
active,
|
|
21392
|
+
staticMaxConcurrentAi: staticMaxC,
|
|
21393
|
+
adaptiveMaxConcurrentAi: adaptiveMax
|
|
21394
|
+
}),
|
|
21395
|
+
prevProcStatRef: hostPoolPrevStat
|
|
21396
|
+
});
|
|
21397
|
+
const hostPoolIntervalMs = p.__testOnlyHostPoolIntervalMs ?? DEFAULT_HOST_POOL_INTERVAL_MS;
|
|
21398
|
+
const hostPoolInterval = setInterval(() => {
|
|
21399
|
+
hostPoolTick();
|
|
21400
|
+
}, hostPoolIntervalMs);
|
|
21100
21401
|
try {
|
|
21101
21402
|
while (true) {
|
|
21102
21403
|
while (fifo.length > 0 && active < currentCap() && !abortSignal?.aborted) {
|
|
@@ -21127,6 +21428,7 @@ async function drainWorkstationPool(p) {
|
|
|
21127
21428
|
if (pressureInterval) {
|
|
21128
21429
|
clearInterval(pressureInterval);
|
|
21129
21430
|
}
|
|
21431
|
+
clearInterval(hostPoolInterval);
|
|
21130
21432
|
if (poolAbortListenerRegistered && abortSignal) {
|
|
21131
21433
|
abortSignal.removeEventListener("abort", onPipelineAbort);
|
|
21132
21434
|
}
|
|
@@ -21166,7 +21468,7 @@ async function runSynthesisPipelineDrainFromPreparedWorktree(storageContext, rep
|
|
|
21166
21468
|
offlineLearnAfterSameSessionTrace: getAceOfflineLearnAfterSameSessionTrace(handle.path)
|
|
21167
21469
|
};
|
|
21168
21470
|
const contextDir2 = path32.join(handle.path, ".gluecharm", "context");
|
|
21169
|
-
|
|
21471
|
+
fs37.mkdirSync(contextDir2, { recursive: true });
|
|
21170
21472
|
const initialItems = buildRootItems();
|
|
21171
21473
|
await startArtefactRun(storageContext, repoRoot, handle.path, initialItems);
|
|
21172
21474
|
await cb.onBootstrapReady?.({ worktreeRoot: handle.path, contextDir: contextDir2 });
|
|
@@ -21267,27 +21569,27 @@ async function runSynthesisPipeline(storageContext, repoRoot, workspaceLabel, ex
|
|
|
21267
21569
|
}
|
|
21268
21570
|
|
|
21269
21571
|
// src/workspaceContextPromote.ts
|
|
21270
|
-
var
|
|
21572
|
+
var fs38 = __toESM(require("fs"));
|
|
21271
21573
|
var path33 = __toESM(require("path"));
|
|
21272
21574
|
function promoteContextDirectoryToWorkspaceFs(sourceContextDir, workspaceRootFs) {
|
|
21273
21575
|
const dest = path33.join(workspaceRootFs, ".gluecharm", "context");
|
|
21274
|
-
|
|
21275
|
-
|
|
21576
|
+
fs38.mkdirSync(path33.join(workspaceRootFs, ".gluecharm"), { recursive: true });
|
|
21577
|
+
fs38.mkdirSync(dest, { recursive: true });
|
|
21276
21578
|
let names;
|
|
21277
21579
|
try {
|
|
21278
|
-
names =
|
|
21580
|
+
names = fs38.readdirSync(sourceContextDir);
|
|
21279
21581
|
} catch {
|
|
21280
21582
|
return { filesCopied: 0 };
|
|
21281
21583
|
}
|
|
21282
21584
|
let filesCopied = 0;
|
|
21283
21585
|
for (const name of names) {
|
|
21284
21586
|
const srcPath = path33.join(sourceContextDir, name);
|
|
21285
|
-
if (!
|
|
21587
|
+
if (!fs38.statSync(srcPath).isFile()) {
|
|
21286
21588
|
continue;
|
|
21287
21589
|
}
|
|
21288
|
-
const buf =
|
|
21590
|
+
const buf = fs38.readFileSync(srcPath);
|
|
21289
21591
|
const target = path33.join(dest, name);
|
|
21290
|
-
|
|
21592
|
+
fs38.writeFileSync(target, buf);
|
|
21291
21593
|
filesCopied += 1;
|
|
21292
21594
|
}
|
|
21293
21595
|
return { filesCopied };
|
|
@@ -21947,7 +22249,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21947
22249
|
}
|
|
21948
22250
|
|
|
21949
22251
|
// src/factory/generateContextFactoryHeadlessHost.ts
|
|
21950
|
-
var
|
|
22252
|
+
var fs47 = __toESM(require("node:fs"));
|
|
21951
22253
|
var path43 = __toESM(require("node:path"));
|
|
21952
22254
|
|
|
21953
22255
|
// src/stores/pipelineRunStore.ts
|
|
@@ -22048,11 +22350,11 @@ async function noteAgentsMaterialized(context) {
|
|
|
22048
22350
|
}
|
|
22049
22351
|
|
|
22050
22352
|
// src/pipelines/remediation/missingWorkstations.ts
|
|
22051
|
-
var
|
|
22353
|
+
var fs40 = __toESM(require("fs"));
|
|
22052
22354
|
var path35 = __toESM(require("path"));
|
|
22053
22355
|
|
|
22054
22356
|
// src/analysis/analysisDetailMarkdownDiscovery.ts
|
|
22055
|
-
var
|
|
22357
|
+
var fs39 = __toESM(require("fs"));
|
|
22056
22358
|
var path34 = __toESM(require("path"));
|
|
22057
22359
|
var SLUG4 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
22058
22360
|
var FE2 = /^FE-\d+$/;
|
|
@@ -22074,7 +22376,7 @@ var STEM_TO_AGENT = {
|
|
|
22074
22376
|
};
|
|
22075
22377
|
function readJson5(filePath) {
|
|
22076
22378
|
try {
|
|
22077
|
-
let raw =
|
|
22379
|
+
let raw = fs39.readFileSync(filePath, "utf-8");
|
|
22078
22380
|
if (raw.length > 0 && raw.charCodeAt(0) === 65279) {
|
|
22079
22381
|
raw = raw.slice(1);
|
|
22080
22382
|
}
|
|
@@ -22342,7 +22644,7 @@ function fileAndValidationFromKind(kind) {
|
|
|
22342
22644
|
function classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeRoot) {
|
|
22343
22645
|
const abs = path35.join(contextDir2, row2.relativePath);
|
|
22344
22646
|
try {
|
|
22345
|
-
const st =
|
|
22647
|
+
const st = fs40.statSync(abs);
|
|
22346
22648
|
if (!st.isFile()) {
|
|
22347
22649
|
return { kind: "absent", detail: "Path exists but is not a regular file." };
|
|
22348
22650
|
}
|
|
@@ -22380,7 +22682,7 @@ function classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeR
|
|
|
22380
22682
|
};
|
|
22381
22683
|
}
|
|
22382
22684
|
const schemaAbs = path35.join(worktreeRoot, ".opencode", "schemas", "context-lists", schemaBn);
|
|
22383
|
-
if (!
|
|
22685
|
+
if (!fs40.existsSync(schemaAbs)) {
|
|
22384
22686
|
return {
|
|
22385
22687
|
kind: "invalid",
|
|
22386
22688
|
detail: `Schema not found (${schemaBn}). Run **Materialize agents** on this checkout.`
|
|
@@ -22616,7 +22918,7 @@ function listMissingWorkstations(contextDir2, worktreeRoot, snapshot) {
|
|
|
22616
22918
|
}
|
|
22617
22919
|
}
|
|
22618
22920
|
}
|
|
22619
|
-
if (!
|
|
22921
|
+
if (!fs40.existsSync(contextDir2)) {
|
|
22620
22922
|
return [...map.values()].sort((a, b) => a.key.localeCompare(b.key));
|
|
22621
22923
|
}
|
|
22622
22924
|
const dynamic = discoverDynamicAnalysisTestSteps(contextDir2);
|
|
@@ -22797,11 +23099,11 @@ async function runRemediationPipelineMissingPass(p) {
|
|
|
22797
23099
|
|
|
22798
23100
|
// src/pipelines/coverage/coveragePipeline.ts
|
|
22799
23101
|
var import_child_process5 = require("child_process");
|
|
22800
|
-
var
|
|
23102
|
+
var fs42 = __toESM(require("fs"));
|
|
22801
23103
|
var path38 = __toESM(require("path"));
|
|
22802
23104
|
|
|
22803
23105
|
// src/analysis/coverageReferenceValidationSchemaValidate.ts
|
|
22804
|
-
var
|
|
23106
|
+
var fs41 = __toESM(require("fs"));
|
|
22805
23107
|
var path37 = __toESM(require("path"));
|
|
22806
23108
|
var import__5 = __toESM(require__());
|
|
22807
23109
|
function stripUtf8Bom4(s) {
|
|
@@ -22831,7 +23133,7 @@ function getValidate() {
|
|
|
22831
23133
|
return compiledValidate;
|
|
22832
23134
|
}
|
|
22833
23135
|
const schemaPath = bundledCoverageReferenceValidationSchemaPath();
|
|
22834
|
-
const schemaRaw = stripUtf8Bom4(
|
|
23136
|
+
const schemaRaw = stripUtf8Bom4(fs41.readFileSync(schemaPath, "utf-8"));
|
|
22835
23137
|
const schema = JSON.parse(schemaRaw);
|
|
22836
23138
|
const ajv2 = new import__5.default({ allErrors: true, strict: false });
|
|
22837
23139
|
compiledValidate = ajv2.compile(schema);
|
|
@@ -22847,7 +23149,7 @@ function validateCoverageReferenceValidationData(data) {
|
|
|
22847
23149
|
function readAndValidateCoverageReferenceValidationFile(jsonAbsolutePath) {
|
|
22848
23150
|
let raw;
|
|
22849
23151
|
try {
|
|
22850
|
-
raw = stripUtf8Bom4(
|
|
23152
|
+
raw = stripUtf8Bom4(fs41.readFileSync(jsonAbsolutePath, "utf-8"));
|
|
22851
23153
|
} catch (e) {
|
|
22852
23154
|
return {
|
|
22853
23155
|
ok: false,
|
|
@@ -22889,7 +23191,7 @@ var DEFAULT_IGNORE_DIR_BASENAMES = [
|
|
|
22889
23191
|
var GIT_LS_FILES_MAX_BUFFER = 64 * 1024 * 1024;
|
|
22890
23192
|
function tryLoadGitNonIgnoredPathSet(repositoryRootAbs) {
|
|
22891
23193
|
const root = path38.resolve(repositoryRootAbs);
|
|
22892
|
-
if (!
|
|
23194
|
+
if (!fs42.existsSync(path38.join(root, ".git"))) {
|
|
22893
23195
|
return null;
|
|
22894
23196
|
}
|
|
22895
23197
|
const env = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
@@ -23044,7 +23346,7 @@ function extractEvidenceIndexPathCitations(body) {
|
|
|
23044
23346
|
function listContextFilesRecursive(dir, acc) {
|
|
23045
23347
|
let entries;
|
|
23046
23348
|
try {
|
|
23047
|
-
entries =
|
|
23349
|
+
entries = fs42.readdirSync(dir, { withFileTypes: true });
|
|
23048
23350
|
} catch {
|
|
23049
23351
|
return;
|
|
23050
23352
|
}
|
|
@@ -23062,7 +23364,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
23062
23364
|
const walk = (dir) => {
|
|
23063
23365
|
let entries;
|
|
23064
23366
|
try {
|
|
23065
|
-
entries =
|
|
23367
|
+
entries = fs42.readdirSync(dir, { withFileTypes: true });
|
|
23066
23368
|
} catch {
|
|
23067
23369
|
return;
|
|
23068
23370
|
}
|
|
@@ -23092,7 +23394,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
23092
23394
|
}
|
|
23093
23395
|
let st;
|
|
23094
23396
|
try {
|
|
23095
|
-
st =
|
|
23397
|
+
st = fs42.statSync(full);
|
|
23096
23398
|
} catch {
|
|
23097
23399
|
continue;
|
|
23098
23400
|
}
|
|
@@ -23102,7 +23404,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
23102
23404
|
}
|
|
23103
23405
|
let buf;
|
|
23104
23406
|
try {
|
|
23105
|
-
buf =
|
|
23407
|
+
buf = fs42.readFileSync(full);
|
|
23106
23408
|
} catch {
|
|
23107
23409
|
excludedOut.push({ path: rel, reason: "read error" });
|
|
23108
23410
|
continue;
|
|
@@ -23122,7 +23424,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
23122
23424
|
}
|
|
23123
23425
|
function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings) {
|
|
23124
23426
|
const references = [];
|
|
23125
|
-
if (!
|
|
23427
|
+
if (!fs42.existsSync(contextDirAbs)) {
|
|
23126
23428
|
warnings.push(`Context directory missing: ${contextDirAbs}`);
|
|
23127
23429
|
return references;
|
|
23128
23430
|
}
|
|
@@ -23138,7 +23440,7 @@ function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings
|
|
|
23138
23440
|
}
|
|
23139
23441
|
let raw;
|
|
23140
23442
|
try {
|
|
23141
|
-
raw =
|
|
23443
|
+
raw = fs42.readFileSync(abs, "utf-8");
|
|
23142
23444
|
} catch (e) {
|
|
23143
23445
|
warnings.push(`Skip JSON (read error): ${sourceArtefact} \u2014 ${e instanceof Error ? e.message : String(e)}`);
|
|
23144
23446
|
continue;
|
|
@@ -23169,7 +23471,7 @@ function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings
|
|
|
23169
23471
|
if (ext === ".md") {
|
|
23170
23472
|
let text;
|
|
23171
23473
|
try {
|
|
23172
|
-
const buf =
|
|
23474
|
+
const buf = fs42.readFileSync(abs);
|
|
23173
23475
|
text = decodeBufferForLineCount(buf);
|
|
23174
23476
|
} catch (e) {
|
|
23175
23477
|
warnings.push(`Skip markdown (read/decode error): ${sourceArtefact} \u2014 ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -23226,7 +23528,7 @@ function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirA
|
|
|
23226
23528
|
}
|
|
23227
23529
|
const excludedFiles = [];
|
|
23228
23530
|
const gitNonIgnoredPaths = tryLoadGitNonIgnoredPathSet(repoRoot);
|
|
23229
|
-
if (
|
|
23531
|
+
if (fs42.existsSync(path38.join(repoRoot, ".git")) && gitNonIgnoredPaths === null) {
|
|
23230
23532
|
warnings.push(
|
|
23231
23533
|
"Repository has .git but git ls-files failed or git is unavailable; .gitignore / exclude-standard not applied."
|
|
23232
23534
|
);
|
|
@@ -23277,10 +23579,10 @@ function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirA
|
|
|
23277
23579
|
function runCoveragePipeline(opts) {
|
|
23278
23580
|
const repoRoot = path38.resolve(opts.repositoryRootAbs);
|
|
23279
23581
|
const contextDir2 = path38.resolve(opts.contextDirAbs);
|
|
23280
|
-
if (!
|
|
23582
|
+
if (!fs42.existsSync(repoRoot)) {
|
|
23281
23583
|
return { ok: false, error: `Repository root does not exist: ${repoRoot}` };
|
|
23282
23584
|
}
|
|
23283
|
-
if (!
|
|
23585
|
+
if (!fs42.existsSync(contextDir2)) {
|
|
23284
23586
|
return {
|
|
23285
23587
|
ok: false,
|
|
23286
23588
|
error: `Missing .gluecharm/context: ${contextDir2}`
|
|
@@ -23302,7 +23604,7 @@ ${schemaCheck.errors.join("\n")}`,
|
|
|
23302
23604
|
if (opts.write) {
|
|
23303
23605
|
try {
|
|
23304
23606
|
const payload = stableStringifyCoverageDocument(document);
|
|
23305
|
-
|
|
23607
|
+
fs42.writeFileSync(outPath, payload, "utf-8");
|
|
23306
23608
|
} catch (e) {
|
|
23307
23609
|
return {
|
|
23308
23610
|
ok: false,
|
|
@@ -23316,11 +23618,11 @@ ${schemaCheck.errors.join("\n")}`,
|
|
|
23316
23618
|
|
|
23317
23619
|
// src/pipelines/remediation/zeroReferenceWorkstationChain.ts
|
|
23318
23620
|
var crypto = __toESM(require("crypto"));
|
|
23319
|
-
var
|
|
23621
|
+
var fs44 = __toESM(require("fs"));
|
|
23320
23622
|
var path40 = __toESM(require("path"));
|
|
23321
23623
|
|
|
23322
23624
|
// src/analysis/zeroReferenceRemediationSchemaValidate.ts
|
|
23323
|
-
var
|
|
23625
|
+
var fs43 = __toESM(require("fs"));
|
|
23324
23626
|
var path39 = __toESM(require("path"));
|
|
23325
23627
|
var import__6 = __toESM(require__());
|
|
23326
23628
|
function stripUtf8Bom5(s) {
|
|
@@ -23342,7 +23644,7 @@ function formatAjvErrors6(errors) {
|
|
|
23342
23644
|
var ajv = new import__6.default({ allErrors: true, strict: false });
|
|
23343
23645
|
function compileSchema(basename17) {
|
|
23344
23646
|
const schemaPath = path39.join(schemasDir(), basename17);
|
|
23345
|
-
const schemaRaw = stripUtf8Bom5(
|
|
23647
|
+
const schemaRaw = stripUtf8Bom5(fs43.readFileSync(schemaPath, "utf-8"));
|
|
23346
23648
|
const schema = JSON.parse(schemaRaw);
|
|
23347
23649
|
return ajv.compile(schema);
|
|
23348
23650
|
}
|
|
@@ -23386,7 +23688,7 @@ var ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS = 5;
|
|
|
23386
23688
|
var ZERO_REF_STAGING_FILE_PREVIEW_MAX_CHARS = 6e3;
|
|
23387
23689
|
function readStagingOutputPreview(outAbs) {
|
|
23388
23690
|
try {
|
|
23389
|
-
const s =
|
|
23691
|
+
const s = fs44.readFileSync(outAbs, "utf-8");
|
|
23390
23692
|
if (s.length <= ZERO_REF_STAGING_FILE_PREVIEW_MAX_CHARS) {
|
|
23391
23693
|
return s;
|
|
23392
23694
|
}
|
|
@@ -23669,14 +23971,14 @@ function readNonReferencedFilesFromRepositoryRoot(repositoryRootAbs) {
|
|
|
23669
23971
|
return { ok: true, paths, ...generatedAt ? { generatedAt } : {} };
|
|
23670
23972
|
}
|
|
23671
23973
|
function readOrInitRoutingDoc(routingAbs, coverageReferenceGeneratedAt) {
|
|
23672
|
-
if (!
|
|
23974
|
+
if (!fs44.existsSync(routingAbs)) {
|
|
23673
23975
|
return {
|
|
23674
23976
|
schemaVersion: ROUTING_SCHEMA_VERSION,
|
|
23675
23977
|
...coverageReferenceGeneratedAt ? { coverageReferenceGeneratedAt } : {},
|
|
23676
23978
|
records: {}
|
|
23677
23979
|
};
|
|
23678
23980
|
}
|
|
23679
|
-
const raw =
|
|
23981
|
+
const raw = fs44.readFileSync(routingAbs, "utf-8");
|
|
23680
23982
|
const data = JSON.parse(raw);
|
|
23681
23983
|
if (!data.records || typeof data.records !== "object") {
|
|
23682
23984
|
return {
|
|
@@ -23688,10 +23990,10 @@ function readOrInitRoutingDoc(routingAbs, coverageReferenceGeneratedAt) {
|
|
|
23688
23990
|
return data;
|
|
23689
23991
|
}
|
|
23690
23992
|
function readOrInitTriageDoc(triageAbs) {
|
|
23691
|
-
if (!
|
|
23993
|
+
if (!fs44.existsSync(triageAbs)) {
|
|
23692
23994
|
return { schemaVersion: TRIAGE_SCHEMA_VERSION, records: {} };
|
|
23693
23995
|
}
|
|
23694
|
-
const raw =
|
|
23996
|
+
const raw = fs44.readFileSync(triageAbs, "utf-8");
|
|
23695
23997
|
const data = JSON.parse(raw);
|
|
23696
23998
|
if (!data.records || typeof data.records !== "object") {
|
|
23697
23999
|
return { schemaVersion: TRIAGE_SCHEMA_VERSION, records: {} };
|
|
@@ -23742,7 +24044,7 @@ function lineCountRepoFile(worktreeRootAbs, relPosix) {
|
|
|
23742
24044
|
const abs = path40.join(worktreeRootAbs, ...relPosix.split("/"));
|
|
23743
24045
|
let buf;
|
|
23744
24046
|
try {
|
|
23745
|
-
buf =
|
|
24047
|
+
buf = fs44.readFileSync(abs);
|
|
23746
24048
|
} catch {
|
|
23747
24049
|
return 1;
|
|
23748
24050
|
}
|
|
@@ -23796,7 +24098,7 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23796
24098
|
const cfg = LIST_MERGE_CFG[input.listKind];
|
|
23797
24099
|
const listPath = path40.join(input.contextDirAbs, cfg.listBasename);
|
|
23798
24100
|
const schemaPath = path40.join(resolveContextListSchemasDir(), cfg.schemaBasename);
|
|
23799
|
-
if (!
|
|
24101
|
+
if (!fs44.existsSync(listPath)) {
|
|
23800
24102
|
return {
|
|
23801
24103
|
ok: false,
|
|
23802
24104
|
message: `${cfg.listBasename} not found \u2014 run coordination step ${LIST_STEP_HINT[input.listKind]} first.`
|
|
@@ -23807,7 +24109,7 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23807
24109
|
return withCoordinationListFileLock(listPath, {}, async () => {
|
|
23808
24110
|
let raw;
|
|
23809
24111
|
try {
|
|
23810
|
-
raw =
|
|
24112
|
+
raw = fs44.readFileSync(listPath, "utf-8");
|
|
23811
24113
|
} catch (e) {
|
|
23812
24114
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
23813
24115
|
}
|
|
@@ -23875,7 +24177,7 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23875
24177
|
});
|
|
23876
24178
|
const tmp = `${listPath}.tmp.${process.pid}`;
|
|
23877
24179
|
try {
|
|
23878
|
-
|
|
24180
|
+
fs44.writeFileSync(tmp, `${JSON.stringify(doc, null, 2)}
|
|
23879
24181
|
`, "utf-8");
|
|
23880
24182
|
} catch (e) {
|
|
23881
24183
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
@@ -23883,13 +24185,13 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23883
24185
|
const v = validateCoordinationListJson(tmp, schemaPath);
|
|
23884
24186
|
if (!v.ok) {
|
|
23885
24187
|
try {
|
|
23886
|
-
|
|
24188
|
+
fs44.unlinkSync(tmp);
|
|
23887
24189
|
} catch {
|
|
23888
24190
|
}
|
|
23889
24191
|
return { ok: false, message: `${cfg.listBasename} validation failed: ${JSON.stringify(v.failure)}` };
|
|
23890
24192
|
}
|
|
23891
24193
|
try {
|
|
23892
|
-
|
|
24194
|
+
fs44.renameSync(tmp, listPath);
|
|
23893
24195
|
} catch (e) {
|
|
23894
24196
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
23895
24197
|
}
|
|
@@ -23899,9 +24201,9 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23899
24201
|
}
|
|
23900
24202
|
async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, workspaceLabel) {
|
|
23901
24203
|
const outAbs = stagingPathForTarget(contextDirAbs, "classifier", targetFilePathPosix);
|
|
23902
|
-
|
|
24204
|
+
fs44.mkdirSync(path40.dirname(outAbs), { recursive: true });
|
|
23903
24205
|
const runDir = path40.join(common.worktreeRoot, ".opencode", "_run");
|
|
23904
|
-
|
|
24206
|
+
fs44.mkdirSync(runDir, { recursive: true });
|
|
23905
24207
|
const outputBasename = path40.basename(outAbs);
|
|
23906
24208
|
const listTaskDescription = [
|
|
23907
24209
|
`Target file (repo-relative, POSIX): **${targetFilePathPosix}**`,
|
|
@@ -23939,7 +24241,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
|
|
|
23939
24241
|
...repairAppendix ? { repairAppendix } : {}
|
|
23940
24242
|
});
|
|
23941
24243
|
const promptPath = path40.join(runDir, `zero-ref-classify-a${attempt}-${Date.now()}.prompt.txt`);
|
|
23942
|
-
|
|
24244
|
+
fs44.writeFileSync(promptPath, body, "utf-8");
|
|
23943
24245
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
23944
24246
|
promptFile: promptPath,
|
|
23945
24247
|
agentId: ZERO_REF_CLASSIFY_AGENT_STEM,
|
|
@@ -23966,7 +24268,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
|
|
|
23966
24268
|
const canRetry = attempt < ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS - 1;
|
|
23967
24269
|
let st;
|
|
23968
24270
|
try {
|
|
23969
|
-
st =
|
|
24271
|
+
st = fs44.statSync(outAbs);
|
|
23970
24272
|
} catch {
|
|
23971
24273
|
st = void 0;
|
|
23972
24274
|
}
|
|
@@ -23988,7 +24290,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
|
|
|
23988
24290
|
}
|
|
23989
24291
|
let parsed;
|
|
23990
24292
|
try {
|
|
23991
|
-
parsed = JSON.parse(
|
|
24293
|
+
parsed = JSON.parse(fs44.readFileSync(outAbs, "utf-8"));
|
|
23992
24294
|
} catch (e) {
|
|
23993
24295
|
const msg = e instanceof Error ? e.message : String(e);
|
|
23994
24296
|
lastFailureMessage = `Classifier output not valid JSON: ${msg}`;
|
|
@@ -24073,7 +24375,7 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
|
|
|
24073
24375
|
const mdAbs = path40.join(contextDirAbs, mdBasename);
|
|
24074
24376
|
const agentStem = which === "project" ? ZERO_REF_ADD_REF_PROJECT_AGENT_STEM : ZERO_REF_ADD_REF_ARCH_AGENT_STEM;
|
|
24075
24377
|
const runDir = path40.join(common.worktreeRoot, ".opencode", "_run");
|
|
24076
|
-
|
|
24378
|
+
fs44.mkdirSync(runDir, { recursive: true });
|
|
24077
24379
|
const lines = [
|
|
24078
24380
|
`# SRS-30 \u2014 Add reference to ${mdBasename}`,
|
|
24079
24381
|
``,
|
|
@@ -24089,7 +24391,7 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
|
|
|
24089
24391
|
`- Do not remove unrelated content; append or extend the most appropriate section.`
|
|
24090
24392
|
];
|
|
24091
24393
|
const promptPath = path40.join(runDir, `zero-ref-md-${which}-${Date.now()}.prompt.txt`);
|
|
24092
|
-
|
|
24394
|
+
fs44.writeFileSync(promptPath, lines.join("\n"), "utf-8");
|
|
24093
24395
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
24094
24396
|
promptFile: promptPath,
|
|
24095
24397
|
agentId: agentStem,
|
|
@@ -24116,9 +24418,9 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
|
|
|
24116
24418
|
async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathPosix, routingSummary, workspaceLabel, triageScope) {
|
|
24117
24419
|
const meta = TRIAGE_SCOPE_META[triageScope];
|
|
24118
24420
|
const outAbs = stagingPathForTarget(contextDirAbs, "triage", targetFilePathPosix);
|
|
24119
|
-
|
|
24421
|
+
fs44.mkdirSync(path40.dirname(outAbs), { recursive: true });
|
|
24120
24422
|
const runDir = path40.join(common.worktreeRoot, ".opencode", "_run");
|
|
24121
|
-
|
|
24423
|
+
fs44.mkdirSync(runDir, { recursive: true });
|
|
24122
24424
|
const outputBasename = path40.basename(outAbs);
|
|
24123
24425
|
const listTaskDescription = [
|
|
24124
24426
|
`Target file: **${targetFilePathPosix}** (${workspaceLabel})`,
|
|
@@ -24150,7 +24452,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
24150
24452
|
...repairAppendix ? { repairAppendix } : {}
|
|
24151
24453
|
});
|
|
24152
24454
|
const promptPath = path40.join(runDir, `zero-ref-triage-a${attempt}-${Date.now()}.prompt.txt`);
|
|
24153
|
-
|
|
24455
|
+
fs44.writeFileSync(promptPath, body, "utf-8");
|
|
24154
24456
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
24155
24457
|
promptFile: promptPath,
|
|
24156
24458
|
agentId: ZERO_REF_TRIAGE_COORD_AGENT_STEM,
|
|
@@ -24177,7 +24479,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
24177
24479
|
const canRetry = attempt < ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS - 1;
|
|
24178
24480
|
let st;
|
|
24179
24481
|
try {
|
|
24180
|
-
st =
|
|
24482
|
+
st = fs44.statSync(outAbs);
|
|
24181
24483
|
} catch {
|
|
24182
24484
|
st = void 0;
|
|
24183
24485
|
}
|
|
@@ -24199,7 +24501,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
24199
24501
|
}
|
|
24200
24502
|
let parsed;
|
|
24201
24503
|
try {
|
|
24202
|
-
parsed = JSON.parse(
|
|
24504
|
+
parsed = JSON.parse(fs44.readFileSync(outAbs, "utf-8"));
|
|
24203
24505
|
} catch (e) {
|
|
24204
24506
|
const msg = e instanceof Error ? e.message : String(e);
|
|
24205
24507
|
lastFailureMessage = `Triage output not valid JSON: ${msg}`;
|
|
@@ -24255,7 +24557,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
24255
24557
|
return { ok: false, message: lastFailureMessage, stagingPath: outAbs };
|
|
24256
24558
|
}
|
|
24257
24559
|
try {
|
|
24258
|
-
|
|
24560
|
+
fs44.writeFileSync(outAbs, `${JSON.stringify(parsed, null, 2)}
|
|
24259
24561
|
`, "utf-8");
|
|
24260
24562
|
} catch {
|
|
24261
24563
|
}
|
|
@@ -24273,7 +24575,7 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
24273
24575
|
}
|
|
24274
24576
|
let stagingParsed;
|
|
24275
24577
|
try {
|
|
24276
|
-
stagingParsed = JSON.parse(
|
|
24578
|
+
stagingParsed = JSON.parse(fs44.readFileSync(cr.stagingPath, "utf-8"));
|
|
24277
24579
|
} catch (e) {
|
|
24278
24580
|
return { ok: false, message: String(e) };
|
|
24279
24581
|
}
|
|
@@ -24289,8 +24591,8 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
24289
24591
|
if (!s.ok) {
|
|
24290
24592
|
throw new Error(s.errors.join("; "));
|
|
24291
24593
|
}
|
|
24292
|
-
|
|
24293
|
-
|
|
24594
|
+
fs44.mkdirSync(path40.dirname(routingAbs), { recursive: true });
|
|
24595
|
+
fs44.writeFileSync(routingAbs, s.json, "utf-8");
|
|
24294
24596
|
});
|
|
24295
24597
|
const routing = stagingParsed.routing;
|
|
24296
24598
|
const routingSummary = typeof stagingParsed.projectRelationSummary === "string" ? stagingParsed.projectRelationSummary : "";
|
|
@@ -24321,7 +24623,7 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
24321
24623
|
}
|
|
24322
24624
|
let triageParsed;
|
|
24323
24625
|
try {
|
|
24324
|
-
triageParsed = JSON.parse(
|
|
24626
|
+
triageParsed = JSON.parse(fs44.readFileSync(tr.stagingPath, "utf-8"));
|
|
24325
24627
|
} catch (e) {
|
|
24326
24628
|
return { ok: false, message: String(e) };
|
|
24327
24629
|
}
|
|
@@ -24338,8 +24640,8 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
24338
24640
|
if (!s.ok) {
|
|
24339
24641
|
throw new Error(s.errors.join("; "));
|
|
24340
24642
|
}
|
|
24341
|
-
|
|
24342
|
-
|
|
24643
|
+
fs44.mkdirSync(path40.dirname(triageAbs), { recursive: true });
|
|
24644
|
+
fs44.writeFileSync(triageAbs, s.json, "utf-8");
|
|
24343
24645
|
});
|
|
24344
24646
|
const decision = triageParsed.decision;
|
|
24345
24647
|
if (decision === "new_item" || decision === "enrich_existing") {
|
|
@@ -24427,7 +24729,7 @@ async function runRemediationPipelineZeroRefPass(p) {
|
|
|
24427
24729
|
}
|
|
24428
24730
|
|
|
24429
24731
|
// src/pipelines/coverage/coverageExecutionReport.ts
|
|
24430
|
-
var
|
|
24732
|
+
var fs45 = __toESM(require("fs"));
|
|
24431
24733
|
var path41 = __toESM(require("path"));
|
|
24432
24734
|
var REFERENCE_COVERAGE_EXECUTION_REPORT_BASENAME = "reference-coverage-execution-report.md";
|
|
24433
24735
|
function inlineMdText(s) {
|
|
@@ -24524,7 +24826,7 @@ function collectNoActionRowsFromRoutingDoc(doc) {
|
|
|
24524
24826
|
return rows;
|
|
24525
24827
|
}
|
|
24526
24828
|
function readRoutingDocFromDisk(routingAbs) {
|
|
24527
|
-
if (!
|
|
24829
|
+
if (!fs45.existsSync(routingAbs)) {
|
|
24528
24830
|
return {
|
|
24529
24831
|
ok: true,
|
|
24530
24832
|
doc: { schemaVersion: "1", records: {} }
|
|
@@ -24532,7 +24834,7 @@ function readRoutingDocFromDisk(routingAbs) {
|
|
|
24532
24834
|
}
|
|
24533
24835
|
let raw;
|
|
24534
24836
|
try {
|
|
24535
|
-
raw =
|
|
24837
|
+
raw = fs45.readFileSync(routingAbs, "utf-8");
|
|
24536
24838
|
} catch (e) {
|
|
24537
24839
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
24538
24840
|
}
|
|
@@ -24572,20 +24874,20 @@ async function runCoverageExecutionReport(p) {
|
|
|
24572
24874
|
}
|
|
24573
24875
|
let previous;
|
|
24574
24876
|
try {
|
|
24575
|
-
if (
|
|
24576
|
-
previous =
|
|
24877
|
+
if (fs45.existsSync(outAbs)) {
|
|
24878
|
+
previous = fs45.readFileSync(outAbs, "utf-8");
|
|
24577
24879
|
}
|
|
24578
24880
|
} catch {
|
|
24579
24881
|
previous = void 0;
|
|
24580
24882
|
}
|
|
24581
24883
|
try {
|
|
24582
|
-
|
|
24583
|
-
|
|
24884
|
+
fs45.mkdirSync(path41.dirname(outAbs), { recursive: true });
|
|
24885
|
+
fs45.writeFileSync(outAbs, md, "utf-8");
|
|
24584
24886
|
} catch (e) {
|
|
24585
24887
|
const msg = e instanceof Error ? e.message : String(e);
|
|
24586
24888
|
if (previous !== void 0) {
|
|
24587
24889
|
try {
|
|
24588
|
-
|
|
24890
|
+
fs45.writeFileSync(outAbs, previous, "utf-8");
|
|
24589
24891
|
} catch {
|
|
24590
24892
|
}
|
|
24591
24893
|
}
|
|
@@ -24596,7 +24898,7 @@ async function runCoverageExecutionReport(p) {
|
|
|
24596
24898
|
}
|
|
24597
24899
|
|
|
24598
24900
|
// src/gluecharm/minimalGluecharmLayout.ts
|
|
24599
|
-
var
|
|
24901
|
+
var fs46 = __toESM(require("node:fs"));
|
|
24600
24902
|
var path42 = __toESM(require("node:path"));
|
|
24601
24903
|
var MINIMAL_GLUECHARM_RELATIVE_DIRS = [
|
|
24602
24904
|
[".gluecharm", "docs", "srs"],
|
|
@@ -24609,7 +24911,7 @@ function ensureMinimalGluecharmLayoutNode(repoRootAbs) {
|
|
|
24609
24911
|
for (const segments of MINIMAL_GLUECHARM_RELATIVE_DIRS) {
|
|
24610
24912
|
const dir = path42.join(root, ...segments);
|
|
24611
24913
|
try {
|
|
24612
|
-
|
|
24914
|
+
fs46.mkdirSync(dir, { recursive: true });
|
|
24613
24915
|
} catch (e) {
|
|
24614
24916
|
const err = e;
|
|
24615
24917
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -24991,13 +25293,13 @@ function buildFactoryDepsHeadless(input) {
|
|
|
24991
25293
|
},
|
|
24992
25294
|
runPrepareAnalysisWorktree: async (resume) => {
|
|
24993
25295
|
if (resume) {
|
|
24994
|
-
if (adHocWorktree &&
|
|
25296
|
+
if (adHocWorktree && fs47.existsSync(path43.join(adHocWorktree.path, ".git"))) {
|
|
24995
25297
|
return { ok: true };
|
|
24996
25298
|
}
|
|
24997
25299
|
const snap = readAnalysisWorkspaceSnapshot(storageContext);
|
|
24998
25300
|
const wtPath = snap?.adHocWorktreePath?.trim();
|
|
24999
25301
|
const repo = snap?.adHocRepositoryRoot?.trim() || repoRoot;
|
|
25000
|
-
if (wtPath &&
|
|
25302
|
+
if (wtPath && fs47.existsSync(path43.join(wtPath, ".git"))) {
|
|
25001
25303
|
adHocWorktree = attachWorktreeHandle(wtPath, repo);
|
|
25002
25304
|
macroSourceBranch = snap?.adHocSourceBranchAtCreation;
|
|
25003
25305
|
macroFinalize = () => {
|
|
@@ -25222,7 +25524,7 @@ function stderrLinesForFactoryFailures(failures, exitCode) {
|
|
|
25222
25524
|
var path48 = __toESM(require("node:path"));
|
|
25223
25525
|
|
|
25224
25526
|
// src/factory/updateContext/updateContextBaseline.ts
|
|
25225
|
-
var
|
|
25527
|
+
var fs48 = __toESM(require("node:fs"));
|
|
25226
25528
|
var path44 = __toESM(require("node:path"));
|
|
25227
25529
|
function isValidIso(s) {
|
|
25228
25530
|
const t = Date.parse(s);
|
|
@@ -25233,7 +25535,7 @@ function maxMtimeRegularFilesUnderDir(dirAbs) {
|
|
|
25233
25535
|
const walk = (d) => {
|
|
25234
25536
|
let entries;
|
|
25235
25537
|
try {
|
|
25236
|
-
entries =
|
|
25538
|
+
entries = fs48.readdirSync(d, { withFileTypes: true });
|
|
25237
25539
|
} catch {
|
|
25238
25540
|
return;
|
|
25239
25541
|
}
|
|
@@ -25243,7 +25545,7 @@ function maxMtimeRegularFilesUnderDir(dirAbs) {
|
|
|
25243
25545
|
walk(p);
|
|
25244
25546
|
} else if (e.isFile()) {
|
|
25245
25547
|
try {
|
|
25246
|
-
const st =
|
|
25548
|
+
const st = fs48.statSync(p);
|
|
25247
25549
|
const m = st.mtimeMs;
|
|
25248
25550
|
if (best === null || m > best) {
|
|
25249
25551
|
best = m;
|
|
@@ -25265,7 +25567,7 @@ function resolveUpdateContextBaseline(repoRootAbs, repoConfig) {
|
|
|
25265
25567
|
return { baselineIsoUtc: new Date(last).toISOString(), source: "lastRunAt" };
|
|
25266
25568
|
}
|
|
25267
25569
|
const ctxDir = path44.join(repoRootAbs, ".gluecharm", "context");
|
|
25268
|
-
if (!
|
|
25570
|
+
if (!fs48.existsSync(ctxDir)) {
|
|
25269
25571
|
return null;
|
|
25270
25572
|
}
|
|
25271
25573
|
const maxMs = maxMtimeRegularFilesUnderDir(ctxDir);
|
|
@@ -25288,7 +25590,7 @@ function persistUpdateContextLastRunAt(repoRootAbs, isoUtc) {
|
|
|
25288
25590
|
|
|
25289
25591
|
// src/factory/updateContext/updateContextGitWindow.ts
|
|
25290
25592
|
var import_node_child_process3 = require("node:child_process");
|
|
25291
|
-
var
|
|
25593
|
+
var fs49 = __toESM(require("node:fs"));
|
|
25292
25594
|
var path45 = __toESM(require("node:path"));
|
|
25293
25595
|
var GIT_ENV = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
25294
25596
|
function gitLines(repoRootAbs, args) {
|
|
@@ -25314,7 +25616,7 @@ function parseGitLogIso(line) {
|
|
|
25314
25616
|
}
|
|
25315
25617
|
function discoverCommitWindowAndTouchedPaths(repoRootAbs, baselineIsoUtc) {
|
|
25316
25618
|
const root = path45.resolve(repoRootAbs);
|
|
25317
|
-
if (!
|
|
25619
|
+
if (!fs49.existsSync(path45.join(root, ".git"))) {
|
|
25318
25620
|
return { ok: false, error: "Not a git repository (missing .git)." };
|
|
25319
25621
|
}
|
|
25320
25622
|
const baselineMs = Date.parse(baselineIsoUtc);
|
|
@@ -25379,7 +25681,7 @@ function filterPathsExistingInWorktree(worktreeRootAbs, pathsPosix) {
|
|
|
25379
25681
|
const rel = p.replace(/\\/g, "/");
|
|
25380
25682
|
const abs = path45.join(root, ...rel.split("/"));
|
|
25381
25683
|
try {
|
|
25382
|
-
if (
|
|
25684
|
+
if (fs49.existsSync(abs) && fs49.statSync(abs).isFile()) {
|
|
25383
25685
|
out.push(rel);
|
|
25384
25686
|
}
|
|
25385
25687
|
} catch {
|
|
@@ -25389,7 +25691,7 @@ function filterPathsExistingInWorktree(worktreeRootAbs, pathsPosix) {
|
|
|
25389
25691
|
}
|
|
25390
25692
|
|
|
25391
25693
|
// src/factory/updateContext/updateContextReport.ts
|
|
25392
|
-
var
|
|
25694
|
+
var fs50 = __toESM(require("node:fs"));
|
|
25393
25695
|
var path46 = __toESM(require("node:path"));
|
|
25394
25696
|
var CHANGES_SINCE_DATE_BASENAME = "changes-since-date.md";
|
|
25395
25697
|
function renderChangesSinceDateMarkdown(p) {
|
|
@@ -25431,9 +25733,9 @@ function renderChangesSinceDateMarkdown(p) {
|
|
|
25431
25733
|
}
|
|
25432
25734
|
function writeChangesSinceDateReport(contextDirAbs, body) {
|
|
25433
25735
|
try {
|
|
25434
|
-
|
|
25736
|
+
fs50.mkdirSync(contextDirAbs, { recursive: true });
|
|
25435
25737
|
const target = path46.join(contextDirAbs, CHANGES_SINCE_DATE_BASENAME);
|
|
25436
|
-
|
|
25738
|
+
fs50.writeFileSync(target, body, "utf-8");
|
|
25437
25739
|
return { ok: true };
|
|
25438
25740
|
} catch (e) {
|
|
25439
25741
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
@@ -25441,13 +25743,13 @@ function writeChangesSinceDateReport(contextDirAbs, body) {
|
|
|
25441
25743
|
}
|
|
25442
25744
|
|
|
25443
25745
|
// src/factory/updateContext/updateContextSeedCheck.ts
|
|
25444
|
-
var
|
|
25746
|
+
var fs51 = __toESM(require("node:fs"));
|
|
25445
25747
|
var path47 = __toESM(require("node:path"));
|
|
25446
25748
|
var INDEX_BASENAME = "index-application-context.json";
|
|
25447
25749
|
var CHANGES_REPORT = "changes-since-date.md";
|
|
25448
25750
|
function tryParseJsonFile(abs) {
|
|
25449
25751
|
try {
|
|
25450
|
-
const raw =
|
|
25752
|
+
const raw = fs51.readFileSync(abs, "utf-8");
|
|
25451
25753
|
JSON.parse(raw);
|
|
25452
25754
|
return true;
|
|
25453
25755
|
} catch {
|
|
@@ -25455,16 +25757,16 @@ function tryParseJsonFile(abs) {
|
|
|
25455
25757
|
}
|
|
25456
25758
|
}
|
|
25457
25759
|
function isWorktreeContextSeeded(contextDirAbs) {
|
|
25458
|
-
if (!
|
|
25760
|
+
if (!fs51.existsSync(contextDirAbs)) {
|
|
25459
25761
|
return false;
|
|
25460
25762
|
}
|
|
25461
25763
|
const indexAbs = path47.join(contextDirAbs, INDEX_BASENAME);
|
|
25462
|
-
if (
|
|
25764
|
+
if (fs51.existsSync(indexAbs) && fs51.statSync(indexAbs).isFile() && tryParseJsonFile(indexAbs)) {
|
|
25463
25765
|
return true;
|
|
25464
25766
|
}
|
|
25465
25767
|
let names;
|
|
25466
25768
|
try {
|
|
25467
|
-
names =
|
|
25769
|
+
names = fs51.readdirSync(contextDirAbs);
|
|
25468
25770
|
} catch {
|
|
25469
25771
|
return false;
|
|
25470
25772
|
}
|
|
@@ -25478,7 +25780,7 @@ function isWorktreeContextSeeded(contextDirAbs) {
|
|
|
25478
25780
|
}
|
|
25479
25781
|
const p = path47.join(contextDirAbs, name);
|
|
25480
25782
|
try {
|
|
25481
|
-
if (
|
|
25783
|
+
if (fs51.statSync(p).isFile()) {
|
|
25482
25784
|
distinct.add(name);
|
|
25483
25785
|
}
|
|
25484
25786
|
} catch {
|
|
@@ -25780,11 +26082,11 @@ async function runUpdateContextFactory(deps) {
|
|
|
25780
26082
|
}
|
|
25781
26083
|
|
|
25782
26084
|
// src/factory/contextDrift/runContextDriftFactory.ts
|
|
25783
|
-
var
|
|
26085
|
+
var fs57 = __toESM(require("node:fs"));
|
|
25784
26086
|
var path53 = __toESM(require("node:path"));
|
|
25785
26087
|
|
|
25786
26088
|
// src/factory/contextDrift/contextDriftManifest.ts
|
|
25787
|
-
var
|
|
26089
|
+
var fs52 = __toESM(require("node:fs"));
|
|
25788
26090
|
var path49 = __toESM(require("node:path"));
|
|
25789
26091
|
var MAX_REFERENCE_BYTES = 256 * 1024;
|
|
25790
26092
|
var MAX_EVIDENCE_FILES = 300;
|
|
@@ -25793,7 +26095,7 @@ var MAX_EXCERPT = 4e3;
|
|
|
25793
26095
|
function readFileLimited(abs, maxBytes) {
|
|
25794
26096
|
let buf;
|
|
25795
26097
|
try {
|
|
25796
|
-
buf =
|
|
26098
|
+
buf = fs52.readFileSync(abs);
|
|
25797
26099
|
} catch {
|
|
25798
26100
|
return { text: "", truncated: false };
|
|
25799
26101
|
}
|
|
@@ -25806,14 +26108,14 @@ function collectEvidencePaths(repoRoot) {
|
|
|
25806
26108
|
const roots = ["src", "test", "tests", "packages", ".gluecharm", "scripts"];
|
|
25807
26109
|
for (const rel of roots) {
|
|
25808
26110
|
const abs = path49.join(repoRoot, rel);
|
|
25809
|
-
if (!
|
|
26111
|
+
if (!fs52.existsSync(abs)) {
|
|
25810
26112
|
continue;
|
|
25811
26113
|
}
|
|
25812
26114
|
walkFiles(abs, repoRoot, out, 0);
|
|
25813
26115
|
}
|
|
25814
26116
|
for (const leaf of ["package.json", "tsconfig.json"]) {
|
|
25815
26117
|
const abs = path49.join(repoRoot, leaf);
|
|
25816
|
-
if (
|
|
26118
|
+
if (fs52.existsSync(abs) && fs52.statSync(abs).isFile()) {
|
|
25817
26119
|
const r = path49.relative(repoRoot, abs).split(path49.sep).join("/");
|
|
25818
26120
|
out.push(r);
|
|
25819
26121
|
}
|
|
@@ -25831,7 +26133,7 @@ function walkFiles(dir, repoRoot, out, depth) {
|
|
|
25831
26133
|
}
|
|
25832
26134
|
let entries;
|
|
25833
26135
|
try {
|
|
25834
|
-
entries =
|
|
26136
|
+
entries = fs52.readdirSync(dir, { withFileTypes: true });
|
|
25835
26137
|
} catch {
|
|
25836
26138
|
return;
|
|
25837
26139
|
}
|
|
@@ -25868,7 +26170,7 @@ function buildComparisonManifest(args) {
|
|
|
25868
26170
|
const evidenceFiles = [];
|
|
25869
26171
|
for (const rel of evidencePathsTrimmed) {
|
|
25870
26172
|
const abs = path49.join(args.worktreeRoot, ...rel.split("/"));
|
|
25871
|
-
const st =
|
|
26173
|
+
const st = fs52.existsSync(abs) ? fs52.statSync(abs) : null;
|
|
25872
26174
|
const size = st && st.isFile() ? st.size : 0;
|
|
25873
26175
|
const { text, truncated } = readFileLimited(abs, MAX_EVIDENCE_READ);
|
|
25874
26176
|
const excerpt = truncated ? `${text.slice(0, MAX_EXCERPT)}
|
|
@@ -25890,7 +26192,7 @@ function buildComparisonManifest(args) {
|
|
|
25890
26192
|
}
|
|
25891
26193
|
|
|
25892
26194
|
// src/factory/contextDrift/contextDriftAgent.ts
|
|
25893
|
-
var
|
|
26195
|
+
var fs53 = __toESM(require("node:fs"));
|
|
25894
26196
|
var path50 = __toESM(require("node:path"));
|
|
25895
26197
|
|
|
25896
26198
|
// src/factory/contextDrift/contextDriftPayload.ts
|
|
@@ -26037,16 +26339,16 @@ function buildDriftPrompt(args) {
|
|
|
26037
26339
|
}
|
|
26038
26340
|
async function runDriftComparisonOpenCode(args) {
|
|
26039
26341
|
const runDir = path50.join(args.worktreeRoot, ".opencode", "_run");
|
|
26040
|
-
|
|
26342
|
+
fs53.mkdirSync(runDir, { recursive: true });
|
|
26041
26343
|
const manifestPath = path50.join(runDir, "context-drift-manifest.json");
|
|
26042
26344
|
const outputPath = path50.join(runDir, "context-drift-payload.json");
|
|
26043
|
-
|
|
26345
|
+
fs53.writeFileSync(manifestPath, `${JSON.stringify(args.manifestObject, null, 2)}
|
|
26044
26346
|
`, "utf8");
|
|
26045
|
-
if (
|
|
26046
|
-
|
|
26347
|
+
if (fs53.existsSync(outputPath)) {
|
|
26348
|
+
fs53.unlinkSync(outputPath);
|
|
26047
26349
|
}
|
|
26048
26350
|
const promptPath = path50.join(runDir, `context-drift-${Date.now()}.prompt.txt`);
|
|
26049
|
-
|
|
26351
|
+
fs53.writeFileSync(
|
|
26050
26352
|
promptPath,
|
|
26051
26353
|
buildDriftPrompt({
|
|
26052
26354
|
worktreeRoot: args.worktreeRoot,
|
|
@@ -26088,7 +26390,7 @@ async function runDriftComparisonOpenCode(args) {
|
|
|
26088
26390
|
}
|
|
26089
26391
|
let raw;
|
|
26090
26392
|
try {
|
|
26091
|
-
const txt =
|
|
26393
|
+
const txt = fs53.readFileSync(outputPath, "utf8");
|
|
26092
26394
|
raw = JSON.parse(txt);
|
|
26093
26395
|
} catch (e) {
|
|
26094
26396
|
return {
|
|
@@ -26105,7 +26407,7 @@ async function runDriftComparisonOpenCode(args) {
|
|
|
26105
26407
|
|
|
26106
26408
|
// src/factory/contextDrift/contextDriftPaths.ts
|
|
26107
26409
|
var crypto2 = __toESM(require("node:crypto"));
|
|
26108
|
-
var
|
|
26410
|
+
var fs54 = __toESM(require("node:fs"));
|
|
26109
26411
|
var path51 = __toESM(require("node:path"));
|
|
26110
26412
|
var DRIFT_CONTEXT_SUBDIR = path51.join(".gluecharm", "context", "drift");
|
|
26111
26413
|
function sanitizeSlug(raw) {
|
|
@@ -26144,7 +26446,7 @@ function maybeDedupeSlug(slug, referenceRelPosix) {
|
|
|
26144
26446
|
function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
26145
26447
|
let st;
|
|
26146
26448
|
try {
|
|
26147
|
-
st =
|
|
26449
|
+
st = fs54.statSync(referenceAbsInWorktree);
|
|
26148
26450
|
} catch {
|
|
26149
26451
|
return { ok: false, error: `Reference path not found in analysis worktree: ${referenceAbsInWorktree}` };
|
|
26150
26452
|
}
|
|
@@ -26165,7 +26467,7 @@ function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
|
26165
26467
|
}
|
|
26166
26468
|
let entries;
|
|
26167
26469
|
try {
|
|
26168
|
-
entries =
|
|
26470
|
+
entries = fs54.readdirSync(dir, { withFileTypes: true });
|
|
26169
26471
|
} catch {
|
|
26170
26472
|
return;
|
|
26171
26473
|
}
|
|
@@ -26190,7 +26492,7 @@ function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
|
26190
26492
|
}
|
|
26191
26493
|
function pickReferenceRootDocument(args) {
|
|
26192
26494
|
if (args.indexOverrideAbs) {
|
|
26193
|
-
if (!
|
|
26495
|
+
if (!fs54.existsSync(args.indexOverrideAbs) || !args.indexOverrideAbs.endsWith(".md")) {
|
|
26194
26496
|
return { ok: false, error: "--index must point to an existing .md file under the repo." };
|
|
26195
26497
|
}
|
|
26196
26498
|
return { ok: true, path: args.indexOverrideAbs };
|
|
@@ -26201,7 +26503,7 @@ function pickReferenceRootDocument(args) {
|
|
|
26201
26503
|
const dir = args.referenceAbsInWorktree;
|
|
26202
26504
|
for (const name of ["index.md", "README.md"]) {
|
|
26203
26505
|
const p = path51.join(dir, name);
|
|
26204
|
-
if (
|
|
26506
|
+
if (fs54.existsSync(p) && fs54.statSync(p).isFile()) {
|
|
26205
26507
|
return { ok: true, path: p };
|
|
26206
26508
|
}
|
|
26207
26509
|
}
|
|
@@ -26218,13 +26520,13 @@ function toPosixPath(p) {
|
|
|
26218
26520
|
}
|
|
26219
26521
|
|
|
26220
26522
|
// src/factory/contextDrift/contextDriftIndex.ts
|
|
26221
|
-
var
|
|
26523
|
+
var fs55 = __toESM(require("node:fs"));
|
|
26222
26524
|
var START = "<!-- easyspecs-drift-links:start -->";
|
|
26223
26525
|
var END = "<!-- easyspecs-drift-links:end -->";
|
|
26224
26526
|
function patchReferenceIndexWithDriftLink(args) {
|
|
26225
26527
|
let body;
|
|
26226
26528
|
try {
|
|
26227
|
-
body =
|
|
26529
|
+
body = fs55.readFileSync(args.referenceRootAbsolute, "utf8");
|
|
26228
26530
|
} catch (e) {
|
|
26229
26531
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
26230
26532
|
}
|
|
@@ -26245,7 +26547,7 @@ ${block}
|
|
|
26245
26547
|
`;
|
|
26246
26548
|
}
|
|
26247
26549
|
try {
|
|
26248
|
-
|
|
26550
|
+
fs55.writeFileSync(args.referenceRootAbsolute, next, "utf8");
|
|
26249
26551
|
} catch (e) {
|
|
26250
26552
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
26251
26553
|
}
|
|
@@ -26256,13 +26558,13 @@ function escapeRe(s) {
|
|
|
26256
26558
|
}
|
|
26257
26559
|
|
|
26258
26560
|
// src/factory/contextDrift/contextDriftPromote.ts
|
|
26259
|
-
var
|
|
26561
|
+
var fs56 = __toESM(require("node:fs"));
|
|
26260
26562
|
var path52 = __toESM(require("node:path"));
|
|
26261
26563
|
function copyWorktreeFileToWorkspace(args) {
|
|
26262
26564
|
const src = path52.join(args.worktreeRoot, ...args.relativePosix.split("/"));
|
|
26263
26565
|
const dest = path52.join(args.workspaceRoot, ...args.relativePosix.split("/"));
|
|
26264
|
-
|
|
26265
|
-
|
|
26566
|
+
fs56.mkdirSync(path52.dirname(dest), { recursive: true });
|
|
26567
|
+
fs56.copyFileSync(src, dest);
|
|
26266
26568
|
}
|
|
26267
26569
|
|
|
26268
26570
|
// src/factory/contextDrift/runContextDriftFactory.ts
|
|
@@ -26281,7 +26583,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26281
26583
|
};
|
|
26282
26584
|
}
|
|
26283
26585
|
const refAbsWorkspace = resolved.abs;
|
|
26284
|
-
if (!
|
|
26586
|
+
if (!fs57.existsSync(refAbsWorkspace)) {
|
|
26285
26587
|
return {
|
|
26286
26588
|
exitOk: false,
|
|
26287
26589
|
ok: false,
|
|
@@ -26294,7 +26596,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26294
26596
|
let indexOverrideAbsWorkspace;
|
|
26295
26597
|
if (deps.indexOverrideArg?.trim()) {
|
|
26296
26598
|
const ir = resolveInsideRepo(deps.repoRootAbs, deps.indexOverrideArg.trim());
|
|
26297
|
-
if (!ir.ok || !
|
|
26599
|
+
if (!ir.ok || !fs57.existsSync(ir.abs)) {
|
|
26298
26600
|
return {
|
|
26299
26601
|
exitOk: false,
|
|
26300
26602
|
ok: false,
|
|
@@ -26312,7 +26614,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26312
26614
|
ok: true,
|
|
26313
26615
|
code: "DRY_RUN",
|
|
26314
26616
|
...baseMeta,
|
|
26315
|
-
referenceRootDocument: toPosixPath(path53.relative(deps.repoRootAbs, refAbsWorkspace)) + (
|
|
26617
|
+
referenceRootDocument: toPosixPath(path53.relative(deps.repoRootAbs, refAbsWorkspace)) + (fs57.statSync(refAbsWorkspace).isDirectory() ? "/" : ""),
|
|
26316
26618
|
driftReportPath: null,
|
|
26317
26619
|
analysisWorktreeRoot: "",
|
|
26318
26620
|
promoted: false,
|
|
@@ -26381,7 +26683,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26381
26683
|
}
|
|
26382
26684
|
const indexWt = indexOverrideAbsWorkspace ? path53.join(wt, ...path53.relative(deps.repoRootAbs, indexOverrideAbsWorkspace).split(path53.sep)) : void 0;
|
|
26383
26685
|
const rootPick = pickReferenceRootDocument({
|
|
26384
|
-
referencePathIsFile:
|
|
26686
|
+
referencePathIsFile: fs57.statSync(refAbsWt).isFile(),
|
|
26385
26687
|
referenceAbsInWorktree: refAbsWt,
|
|
26386
26688
|
bundleFiles: bundle.bundleFiles,
|
|
26387
26689
|
indexOverrideAbs: indexWt
|
|
@@ -26408,7 +26710,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26408
26710
|
slug = maybeDedupeSlug(slug, refRel);
|
|
26409
26711
|
const driftBase = driftFilename(slug, runDate);
|
|
26410
26712
|
const driftDirWt = path53.join(wt, DRIFT_CONTEXT_SUBDIR);
|
|
26411
|
-
|
|
26713
|
+
fs57.mkdirSync(driftDirWt, { recursive: true });
|
|
26412
26714
|
const driftAbsWt = path53.join(driftDirWt, driftBase);
|
|
26413
26715
|
let payload;
|
|
26414
26716
|
if (deps.testOnlyFixturePayload) {
|
|
@@ -26445,7 +26747,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26445
26747
|
manifestTruncation: manifest.truncation
|
|
26446
26748
|
});
|
|
26447
26749
|
try {
|
|
26448
|
-
|
|
26750
|
+
fs57.writeFileSync(driftAbsWt, md, "utf8");
|
|
26449
26751
|
} catch (e) {
|
|
26450
26752
|
finalizeWt?.();
|
|
26451
26753
|
return {
|
|
@@ -26524,7 +26826,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26524
26826
|
}
|
|
26525
26827
|
|
|
26526
26828
|
// src/analysis/coordinationDuplicatesDiagnosis.ts
|
|
26527
|
-
var
|
|
26829
|
+
var fs58 = __toESM(require("fs"));
|
|
26528
26830
|
var path54 = __toESM(require("path"));
|
|
26529
26831
|
var import__7 = __toESM(require__());
|
|
26530
26832
|
var COORDINATION_DUPLICATES_REPORT_BASENAME = "coordination-duplicates-report.json";
|
|
@@ -26561,11 +26863,11 @@ function looksLikeCoordinationDetailMarkdownBasename(basename17) {
|
|
|
26561
26863
|
}
|
|
26562
26864
|
function loadRawFeatureRows(contextDirAbs) {
|
|
26563
26865
|
const p = path54.join(contextDirAbs, "features-list.json");
|
|
26564
|
-
if (!
|
|
26866
|
+
if (!fs58.existsSync(p)) {
|
|
26565
26867
|
return [];
|
|
26566
26868
|
}
|
|
26567
26869
|
try {
|
|
26568
|
-
const raw = stripUtf8Bom6(
|
|
26870
|
+
const raw = stripUtf8Bom6(fs58.readFileSync(p, "utf-8"));
|
|
26569
26871
|
const doc = JSON.parse(raw);
|
|
26570
26872
|
return Array.isArray(doc.features) ? doc.features : [];
|
|
26571
26873
|
} catch {
|
|
@@ -26600,7 +26902,7 @@ function findOrphanCoordinationMarkdown(contextDirAbs) {
|
|
|
26600
26902
|
const featureRows = loadRawFeatureRows(contextDirAbs);
|
|
26601
26903
|
let dirents;
|
|
26602
26904
|
try {
|
|
26603
|
-
dirents =
|
|
26905
|
+
dirents = fs58.readdirSync(contextDirAbs, { withFileTypes: true });
|
|
26604
26906
|
} catch {
|
|
26605
26907
|
return [];
|
|
26606
26908
|
}
|
|
@@ -26854,13 +27156,13 @@ function buildCoordinationDuplicatesReport(input) {
|
|
|
26854
27156
|
const duplicateGroups = [];
|
|
26855
27157
|
for (const entry of COORDINATION_LIST_SCAN_ENTRIES) {
|
|
26856
27158
|
const filePath = path54.join(input.contextDirAbsolute, entry.basename);
|
|
26857
|
-
if (!
|
|
27159
|
+
if (!fs58.existsSync(filePath)) {
|
|
26858
27160
|
lists.push({ basename: entry.basename, status: "missing" });
|
|
26859
27161
|
continue;
|
|
26860
27162
|
}
|
|
26861
27163
|
let raw;
|
|
26862
27164
|
try {
|
|
26863
|
-
raw = stripUtf8Bom6(
|
|
27165
|
+
raw = stripUtf8Bom6(fs58.readFileSync(filePath, "utf-8"));
|
|
26864
27166
|
} catch (e) {
|
|
26865
27167
|
lists.push({
|
|
26866
27168
|
basename: entry.basename,
|
|
@@ -26909,7 +27211,7 @@ function validateReportData(data) {
|
|
|
26909
27211
|
if (!validateReportCompiled) {
|
|
26910
27212
|
const ajv2 = new import__7.default({ allErrors: true, strict: false });
|
|
26911
27213
|
const schemaPath = path54.join(resolveContextListSchemasDir(), "coordination-duplicates-report.schema.json");
|
|
26912
|
-
const schemaRaw = stripUtf8Bom6(
|
|
27214
|
+
const schemaRaw = stripUtf8Bom6(fs58.readFileSync(schemaPath, "utf-8"));
|
|
26913
27215
|
validateReportCompiled = ajv2.compile(JSON.parse(schemaRaw));
|
|
26914
27216
|
}
|
|
26915
27217
|
if (validateReportCompiled(data)) {
|
|
@@ -26932,15 +27234,15 @@ function runCoordinationDuplicatesDiagnosis(input) {
|
|
|
26932
27234
|
`;
|
|
26933
27235
|
const tmp = `${outPath}.tmp.${process.pid}`;
|
|
26934
27236
|
try {
|
|
26935
|
-
|
|
27237
|
+
fs58.writeFileSync(tmp, payload, "utf-8");
|
|
26936
27238
|
} catch (e) {
|
|
26937
27239
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
26938
27240
|
}
|
|
26939
27241
|
try {
|
|
26940
|
-
|
|
27242
|
+
fs58.renameSync(tmp, outPath);
|
|
26941
27243
|
} catch (e) {
|
|
26942
27244
|
try {
|
|
26943
|
-
|
|
27245
|
+
fs58.unlinkSync(tmp);
|
|
26944
27246
|
} catch {
|
|
26945
27247
|
}
|
|
26946
27248
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
@@ -26974,7 +27276,7 @@ function runCoordinationDuplicatesDiagnosis(input) {
|
|
|
26974
27276
|
}
|
|
26975
27277
|
|
|
26976
27278
|
// src/pipelines/download/downloadPipeline.ts
|
|
26977
|
-
var
|
|
27279
|
+
var fs59 = __toESM(require("node:fs"));
|
|
26978
27280
|
var path55 = __toESM(require("node:path"));
|
|
26979
27281
|
var SRS_DISCOVERY_BATCH_GET_CHUNK_SIZE = 200;
|
|
26980
27282
|
function isRecord7(v) {
|
|
@@ -27080,19 +27382,19 @@ function chunkIds(ids, size) {
|
|
|
27080
27382
|
return out;
|
|
27081
27383
|
}
|
|
27082
27384
|
function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
27083
|
-
if (!
|
|
27385
|
+
if (!fs59.existsSync(contextDirAbs) || !fs59.statSync(contextDirAbs).isDirectory()) {
|
|
27084
27386
|
return { filesRemoved: 0 };
|
|
27085
27387
|
}
|
|
27086
27388
|
const preserveAbs = path55.resolve(contextDirAbs, UPLOAD_TARGET_FILENAME);
|
|
27087
27389
|
const preserveSet = /* @__PURE__ */ new Set();
|
|
27088
|
-
if (
|
|
27390
|
+
if (fs59.existsSync(preserveAbs) && fs59.statSync(preserveAbs).isFile()) {
|
|
27089
27391
|
preserveSet.add(preserveAbs);
|
|
27090
27392
|
}
|
|
27091
27393
|
let filesRemoved = 0;
|
|
27092
27394
|
const walkRm = (dir) => {
|
|
27093
27395
|
let entries;
|
|
27094
27396
|
try {
|
|
27095
|
-
entries =
|
|
27397
|
+
entries = fs59.readdirSync(dir, { withFileTypes: true });
|
|
27096
27398
|
} catch {
|
|
27097
27399
|
return;
|
|
27098
27400
|
}
|
|
@@ -27101,7 +27403,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
|
27101
27403
|
if (e.isDirectory()) {
|
|
27102
27404
|
walkRm(full);
|
|
27103
27405
|
try {
|
|
27104
|
-
|
|
27406
|
+
fs59.rmdirSync(full);
|
|
27105
27407
|
} catch {
|
|
27106
27408
|
}
|
|
27107
27409
|
} else if (e.isFile()) {
|
|
@@ -27110,7 +27412,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
|
27110
27412
|
continue;
|
|
27111
27413
|
}
|
|
27112
27414
|
try {
|
|
27113
|
-
|
|
27415
|
+
fs59.unlinkSync(abs);
|
|
27114
27416
|
filesRemoved += 1;
|
|
27115
27417
|
} catch {
|
|
27116
27418
|
}
|
|
@@ -27189,15 +27491,15 @@ async function runDownloadPipeline(opts) {
|
|
|
27189
27491
|
failed.push({ id, name, message: "Unsafe or invalid name for local path." });
|
|
27190
27492
|
continue;
|
|
27191
27493
|
}
|
|
27192
|
-
|
|
27193
|
-
const exists =
|
|
27494
|
+
fs59.mkdirSync(path55.dirname(outAbs), { recursive: true });
|
|
27495
|
+
const exists = fs59.existsSync(outAbs);
|
|
27194
27496
|
if (exists && !opts.force && !opts.replaceFromCloud) {
|
|
27195
27497
|
skipped += 1;
|
|
27196
27498
|
log?.(`[pipeline:download] skip existing ${name} (use --force to overwrite).`);
|
|
27197
27499
|
continue;
|
|
27198
27500
|
}
|
|
27199
27501
|
try {
|
|
27200
|
-
|
|
27502
|
+
fs59.writeFileSync(outAbs, bodyText, "utf8");
|
|
27201
27503
|
downloaded += 1;
|
|
27202
27504
|
succeededIds[outAbs] = id;
|
|
27203
27505
|
} catch (e) {
|
|
@@ -27368,7 +27670,7 @@ function createAuthenticatedRequestJson(deps) {
|
|
|
27368
27670
|
}
|
|
27369
27671
|
|
|
27370
27672
|
// src/cli/cliSession.ts
|
|
27371
|
-
var
|
|
27673
|
+
var fs60 = __toESM(require("node:fs"));
|
|
27372
27674
|
var os6 = __toESM(require("node:os"));
|
|
27373
27675
|
var path56 = __toESM(require("node:path"));
|
|
27374
27676
|
function defaultSessionPath() {
|
|
@@ -27413,10 +27715,10 @@ function effectiveCliSessionPath() {
|
|
|
27413
27715
|
function readCliSession() {
|
|
27414
27716
|
const p = effectiveCliSessionPath();
|
|
27415
27717
|
try {
|
|
27416
|
-
if (!
|
|
27718
|
+
if (!fs60.existsSync(p)) {
|
|
27417
27719
|
return void 0;
|
|
27418
27720
|
}
|
|
27419
|
-
const j = JSON.parse(
|
|
27721
|
+
const j = JSON.parse(fs60.readFileSync(p, "utf8"));
|
|
27420
27722
|
const apiBaseUrl = typeof j.apiBaseUrl === "string" ? j.apiBaseUrl.trim() : "";
|
|
27421
27723
|
const accessToken = typeof j.accessToken === "string" ? j.accessToken : "";
|
|
27422
27724
|
const refreshToken = typeof j.refreshToken === "string" ? j.refreshToken : "";
|
|
@@ -27430,20 +27732,20 @@ function readCliSession() {
|
|
|
27430
27732
|
}
|
|
27431
27733
|
function writeCliSession(s) {
|
|
27432
27734
|
const p = effectiveCliSessionPath();
|
|
27433
|
-
|
|
27434
|
-
|
|
27735
|
+
fs60.mkdirSync(path56.dirname(p), { recursive: true });
|
|
27736
|
+
fs60.writeFileSync(p, `${JSON.stringify(s, null, 2)}
|
|
27435
27737
|
`, "utf8");
|
|
27436
27738
|
}
|
|
27437
27739
|
function clearCliSession() {
|
|
27438
27740
|
const p = effectiveCliSessionPath();
|
|
27439
27741
|
try {
|
|
27440
|
-
|
|
27742
|
+
fs60.unlinkSync(p);
|
|
27441
27743
|
} catch {
|
|
27442
27744
|
}
|
|
27443
27745
|
}
|
|
27444
27746
|
|
|
27445
27747
|
// src/analysis/acePendingTraces.ts
|
|
27446
|
-
var
|
|
27748
|
+
var fs61 = __toESM(require("fs"));
|
|
27447
27749
|
var path57 = __toESM(require("path"));
|
|
27448
27750
|
function normalizeAceTraceRelativePath(rel) {
|
|
27449
27751
|
return rel.split(/[/\\]/).join("/");
|
|
@@ -27451,12 +27753,12 @@ function normalizeAceTraceRelativePath(rel) {
|
|
|
27451
27753
|
function readCompletedTraceRelativePaths(contextDir2) {
|
|
27452
27754
|
const set = /* @__PURE__ */ new Set();
|
|
27453
27755
|
const jsonlPath = aceConsolidatedSessionsJsonlPath(contextDir2);
|
|
27454
|
-
if (!
|
|
27756
|
+
if (!fs61.existsSync(jsonlPath)) {
|
|
27455
27757
|
return set;
|
|
27456
27758
|
}
|
|
27457
27759
|
let raw;
|
|
27458
27760
|
try {
|
|
27459
|
-
raw =
|
|
27761
|
+
raw = fs61.readFileSync(jsonlPath, "utf8");
|
|
27460
27762
|
} catch {
|
|
27461
27763
|
return set;
|
|
27462
27764
|
}
|
|
@@ -27487,7 +27789,7 @@ function readCompletedTraceRelativePaths(contextDir2) {
|
|
|
27487
27789
|
}
|
|
27488
27790
|
function listPendingAceTraceFiles(contextDir2, worktreeRoot) {
|
|
27489
27791
|
const traceSchema = opencodeAceSchemaPath(worktreeRoot, ACE_SCHEMA_TRACE);
|
|
27490
|
-
if (!
|
|
27792
|
+
if (!fs61.existsSync(traceSchema)) {
|
|
27491
27793
|
return [];
|
|
27492
27794
|
}
|
|
27493
27795
|
const completed = readCompletedTraceRelativePaths(contextDir2);
|
|
@@ -27791,7 +28093,9 @@ var TAG_SGR = {
|
|
|
27791
28093
|
"zero-ref": "\x1B[91m",
|
|
27792
28094
|
ace: "\x1B[95m",
|
|
27793
28095
|
cli: "\x1B[90m",
|
|
27794
|
-
EasySpecs: "\x1B[93m"
|
|
28096
|
+
EasySpecs: "\x1B[93m",
|
|
28097
|
+
"host-pool": "\x1B[36m",
|
|
28098
|
+
"host-pool-rec": "\x1B[90m"
|
|
27795
28099
|
};
|
|
27796
28100
|
function tagOpenSgr(tag) {
|
|
27797
28101
|
const direct = TAG_SGR[tag];
|
|
@@ -27832,7 +28136,7 @@ function phaseFamilyForTag(tag) {
|
|
|
27832
28136
|
if (tag.startsWith("pipeline:")) {
|
|
27833
28137
|
return "meta";
|
|
27834
28138
|
}
|
|
27835
|
-
if (tag === "pool" || tag === "queue" || tag === "worktree" || tag === "context") {
|
|
28139
|
+
if (tag === "pool" || tag === "queue" || tag === "worktree" || tag === "context" || tag === "host-pool" || tag === "host-pool-rec") {
|
|
27836
28140
|
return "orch";
|
|
27837
28141
|
}
|
|
27838
28142
|
if (Object.prototype.hasOwnProperty.call(TAG_SGR, tag)) {
|
|
@@ -28091,7 +28395,7 @@ function formatCliStderrLine(line, useAnsi) {
|
|
|
28091
28395
|
}
|
|
28092
28396
|
|
|
28093
28397
|
// src/cli/main.ts
|
|
28094
|
-
var PKG_VERSION = "0.0.
|
|
28398
|
+
var PKG_VERSION = "0.0.28";
|
|
28095
28399
|
function isNonEmptyFactoryFailureArray(x) {
|
|
28096
28400
|
if (!Array.isArray(x) || x.length === 0) {
|
|
28097
28401
|
return false;
|
|
@@ -28223,7 +28527,7 @@ function resolveAnalysisRoot(repoRoot, rootKind, worktreePath) {
|
|
|
28223
28527
|
return repoRoot;
|
|
28224
28528
|
}
|
|
28225
28529
|
const wt = worktreePath?.trim();
|
|
28226
|
-
if (wt &&
|
|
28530
|
+
if (wt && fs62.existsSync(path59.join(wt, ".git"))) {
|
|
28227
28531
|
return path59.resolve(wt);
|
|
28228
28532
|
}
|
|
28229
28533
|
throw new Error("worktree mode requires --worktree <path> to an existing analysis checkout.");
|
|
@@ -28232,14 +28536,14 @@ function resolveAdHocCheckoutRoot(_repoRoot, storage, worktreeFlag) {
|
|
|
28232
28536
|
const w = worktreeFlag?.trim();
|
|
28233
28537
|
if (w) {
|
|
28234
28538
|
const abs = path59.resolve(w);
|
|
28235
|
-
if (
|
|
28539
|
+
if (fs62.existsSync(path59.join(abs, ".git"))) {
|
|
28236
28540
|
return abs;
|
|
28237
28541
|
}
|
|
28238
28542
|
throw new Error(`Invalid --worktree (not a git checkout): ${abs}`);
|
|
28239
28543
|
}
|
|
28240
28544
|
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
28241
28545
|
const p = snap?.adHocWorktreePath?.trim();
|
|
28242
|
-
if (p &&
|
|
28546
|
+
if (p && fs62.existsSync(path59.join(p, ".git"))) {
|
|
28243
28547
|
return p;
|
|
28244
28548
|
}
|
|
28245
28549
|
throw new Error("No analysis checkout: run `easyspecs-cli run synthesis` first or pass `--worktree <path>`.");
|
|
@@ -28562,7 +28866,7 @@ async function main() {
|
|
|
28562
28866
|
process.exit(ExitCode.usage);
|
|
28563
28867
|
}
|
|
28564
28868
|
const agentsDir = resolveOpenCodeAgentsDir(repoRoot, repoConfig);
|
|
28565
|
-
const agentsOk =
|
|
28869
|
+
const agentsOk = fs62.existsSync(agentsDir);
|
|
28566
28870
|
const oc = getOpenCodeReadiness({
|
|
28567
28871
|
executable: merged.openCodeExecutable,
|
|
28568
28872
|
skipCredentialsCheck: merged.openCodeSkipCredentialsCheck,
|
|
@@ -29078,7 +29382,7 @@ async function main() {
|
|
|
29078
29382
|
const wt = snap?.adHocWorktreePath?.trim();
|
|
29079
29383
|
if (wt) {
|
|
29080
29384
|
const sourceCtx = path59.join(wt, ".gluecharm", "context");
|
|
29081
|
-
if (
|
|
29385
|
+
if (fs62.existsSync(sourceCtx)) {
|
|
29082
29386
|
const n = promoteContextDirectoryToWorkspaceFs(sourceCtx, repoRoot);
|
|
29083
29387
|
logErr(flags, `[pipeline:analysis] promoted ${String(n.filesCopied)} file(s) \u2192 ${repoRoot}`);
|
|
29084
29388
|
} else {
|
|
@@ -29248,12 +29552,12 @@ async function main() {
|
|
|
29248
29552
|
if (pos[1] === "republish") {
|
|
29249
29553
|
const fromCfg = repoConfig.easyspecs?.upload?.contextDirectory?.trim();
|
|
29250
29554
|
const resolvedOverride = fromCfg && fromCfg.length > 0 ? path59.isAbsolute(fromCfg) ? path59.normalize(fromCfg) : path59.resolve(repoRoot, fromCfg) : "";
|
|
29251
|
-
if (resolvedOverride &&
|
|
29555
|
+
if (resolvedOverride && fs62.existsSync(path59.join(resolvedOverride, ".."))) {
|
|
29252
29556
|
ctxDir = resolvedOverride;
|
|
29253
29557
|
} else {
|
|
29254
29558
|
const storage = createFileBackedWorkspaceState(repoRoot);
|
|
29255
29559
|
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
29256
|
-
const wt = snap?.adHocWorktreePath &&
|
|
29560
|
+
const wt = snap?.adHocWorktreePath && fs62.existsSync(path59.join(snap.adHocWorktreePath, ".gluecharm", "context")) ? path59.join(snap.adHocWorktreePath, ".gluecharm", "context") : "";
|
|
29257
29561
|
if (!wt) {
|
|
29258
29562
|
finish(ExitCode.misconfiguration, {
|
|
29259
29563
|
ok: false,
|
|
@@ -29371,16 +29675,16 @@ async function main() {
|
|
|
29371
29675
|
}
|
|
29372
29676
|
if (pos[0] === "ace" && pos[1] === "clear") {
|
|
29373
29677
|
const learnings = path59.join(repoRoot, ".gluecharm", "context", "learnings");
|
|
29374
|
-
if (!
|
|
29678
|
+
if (!fs62.existsSync(learnings)) {
|
|
29375
29679
|
finish(ExitCode.ok, { ok: true, message: "nothing to clear" });
|
|
29376
29680
|
}
|
|
29377
|
-
|
|
29681
|
+
fs62.rmSync(learnings, { recursive: true, force: true });
|
|
29378
29682
|
finish(ExitCode.ok, { ok: true, message: `cleared ${learnings}` });
|
|
29379
29683
|
}
|
|
29380
29684
|
if (pos[0] === "ace" && pos[1] === "learn") {
|
|
29381
29685
|
requireOpenCode(merged, flags);
|
|
29382
29686
|
const { worktree } = parseWorktreeFlag(pos.slice(2));
|
|
29383
|
-
const root = worktree &&
|
|
29687
|
+
const root = worktree && fs62.existsSync(path59.join(worktree, ".opencode", "schemas", "ace")) ? worktree : repoRoot;
|
|
29384
29688
|
const contextDir2 = path59.join(root, ".gluecharm", "context");
|
|
29385
29689
|
const traces = listAceTraceFiles(contextDir2);
|
|
29386
29690
|
if (traces.length === 0) {
|
|
@@ -29405,7 +29709,7 @@ async function main() {
|
|
|
29405
29709
|
if (pos[0] === "ace" && pos[1] === "auto-learn") {
|
|
29406
29710
|
requireOpenCode(merged, flags);
|
|
29407
29711
|
const { worktree } = parseWorktreeFlag(pos.slice(2));
|
|
29408
|
-
const root = worktree &&
|
|
29712
|
+
const root = worktree && fs62.existsSync(path59.join(worktree, ".git")) ? worktree : repoRoot;
|
|
29409
29713
|
const contextDir2 = path59.join(root, ".gluecharm", "context");
|
|
29410
29714
|
const pending = listPendingAceTraceFiles(contextDir2, root);
|
|
29411
29715
|
if (pending.length === 0) {
|