@gluecharm-lab/easyspecs-cli 0.0.25 → 0.0.27
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/README.md +1 -1
- package/commands.md +10 -1
- package/dist/main.cjs +496 -187
- 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
|
|
@@ -13192,7 +13192,7 @@ function createFileBackedWorkspaceState(repoRoot) {
|
|
|
13192
13192
|
}
|
|
13193
13193
|
|
|
13194
13194
|
// src/pipelines/synthesis/synthesisPipeline.ts
|
|
13195
|
-
var
|
|
13195
|
+
var fs37 = __toESM(require("fs"));
|
|
13196
13196
|
var path32 = __toESM(require("path"));
|
|
13197
13197
|
|
|
13198
13198
|
// src/analysis/analysisDynamicTestSteps.ts
|
|
@@ -20320,14 +20320,304 @@ function nextAdaptiveMaxAfterCpuSample(p) {
|
|
|
20320
20320
|
if (p.activeRunningCount < 1 || !Number.isFinite(p.ratio) || p.ratio <= threshold) {
|
|
20321
20321
|
return { adaptiveMax: p.priorAdaptiveMax, changed: false };
|
|
20322
20322
|
}
|
|
20323
|
-
const
|
|
20324
|
-
const
|
|
20323
|
+
const stepDown = Math.max(1, p.priorAdaptiveMax - 1);
|
|
20324
|
+
const backpressure = p.activeRunningCount <= 1 ? stepDown : Math.max(1, p.activeRunningCount - 1);
|
|
20325
|
+
const next = Math.min(p.priorAdaptiveMax, stepDown, backpressure);
|
|
20325
20326
|
if (next < p.priorAdaptiveMax) {
|
|
20326
20327
|
return { adaptiveMax: next, changed: true };
|
|
20327
20328
|
}
|
|
20328
20329
|
return { adaptiveMax: p.priorAdaptiveMax, changed: false };
|
|
20329
20330
|
}
|
|
20330
20331
|
|
|
20332
|
+
// src/hostPoolPeriodicDiagnostics.ts
|
|
20333
|
+
var fs36 = __toESM(require("fs"));
|
|
20334
|
+
var DEFAULT_HOST_POOL_INTERVAL_MS = 45e3;
|
|
20335
|
+
var MAX_ADVICE_TEXT_CHARS = 400;
|
|
20336
|
+
var MAX_FD_ENUM = 4096;
|
|
20337
|
+
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.";
|
|
20338
|
+
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.";
|
|
20339
|
+
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.";
|
|
20340
|
+
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.";
|
|
20341
|
+
function hintSchedulerFromSnapshot(s) {
|
|
20342
|
+
const p = s.load1PerCpu;
|
|
20343
|
+
if (p === null || !Number.isFinite(p)) {
|
|
20344
|
+
return "UNK";
|
|
20345
|
+
}
|
|
20346
|
+
if (p >= 1.25) {
|
|
20347
|
+
return "KO";
|
|
20348
|
+
}
|
|
20349
|
+
if (p < 1) {
|
|
20350
|
+
return "OK";
|
|
20351
|
+
}
|
|
20352
|
+
return "UNK";
|
|
20353
|
+
}
|
|
20354
|
+
function hintMemoryFrom(platform, s, swap) {
|
|
20355
|
+
const total = s.hostRamTotalB;
|
|
20356
|
+
if (total <= 0) {
|
|
20357
|
+
return "UNK";
|
|
20358
|
+
}
|
|
20359
|
+
const freeRatio = s.hostRamFreeB / total;
|
|
20360
|
+
let ram;
|
|
20361
|
+
if (freeRatio < 0.07) {
|
|
20362
|
+
ram = "KO";
|
|
20363
|
+
} else if (freeRatio < 0.1) {
|
|
20364
|
+
ram = "UNK";
|
|
20365
|
+
} else {
|
|
20366
|
+
ram = "OK";
|
|
20367
|
+
}
|
|
20368
|
+
let swapH = "OK";
|
|
20369
|
+
if (platform === "linux" && swap !== null && swap.swapTotalB > 0) {
|
|
20370
|
+
const sf = swap.swapFreeB / swap.swapTotalB;
|
|
20371
|
+
if (sf < 0.08) {
|
|
20372
|
+
swapH = "KO";
|
|
20373
|
+
} else if (sf < 0.15) {
|
|
20374
|
+
swapH = "UNK";
|
|
20375
|
+
} else {
|
|
20376
|
+
swapH = "OK";
|
|
20377
|
+
}
|
|
20378
|
+
}
|
|
20379
|
+
if (ram === "KO" || swapH === "KO") {
|
|
20380
|
+
return "KO";
|
|
20381
|
+
}
|
|
20382
|
+
if (ram === "UNK" || swapH === "UNK") {
|
|
20383
|
+
return "UNK";
|
|
20384
|
+
}
|
|
20385
|
+
return "OK";
|
|
20386
|
+
}
|
|
20387
|
+
function hintLimitsFrom(sample) {
|
|
20388
|
+
if (sample === null) {
|
|
20389
|
+
return "UNK";
|
|
20390
|
+
}
|
|
20391
|
+
if (sample.truncated) {
|
|
20392
|
+
return "UNK";
|
|
20393
|
+
}
|
|
20394
|
+
const ratios = [];
|
|
20395
|
+
if (sample.fdRatio !== null && Number.isFinite(sample.fdRatio)) {
|
|
20396
|
+
ratios.push(sample.fdRatio);
|
|
20397
|
+
}
|
|
20398
|
+
if (sample.procRatio !== null && Number.isFinite(sample.procRatio)) {
|
|
20399
|
+
ratios.push(sample.procRatio);
|
|
20400
|
+
}
|
|
20401
|
+
if (ratios.length === 0) {
|
|
20402
|
+
return "UNK";
|
|
20403
|
+
}
|
|
20404
|
+
if (ratios.some((r) => r >= 0.85)) {
|
|
20405
|
+
return "KO";
|
|
20406
|
+
}
|
|
20407
|
+
if (ratios.every((r) => r < 0.75)) {
|
|
20408
|
+
return "OK";
|
|
20409
|
+
}
|
|
20410
|
+
return "UNK";
|
|
20411
|
+
}
|
|
20412
|
+
function hintIoFrom(prev, curr) {
|
|
20413
|
+
if (prev === null || curr === null) {
|
|
20414
|
+
return "UNK";
|
|
20415
|
+
}
|
|
20416
|
+
const dTotal = curr.total - prev.total;
|
|
20417
|
+
const dIo = curr.iowait - prev.iowait;
|
|
20418
|
+
if (dTotal <= 0 || !Number.isFinite(dTotal) || !Number.isFinite(dIo)) {
|
|
20419
|
+
return "UNK";
|
|
20420
|
+
}
|
|
20421
|
+
const share = dIo / dTotal;
|
|
20422
|
+
if (!Number.isFinite(share)) {
|
|
20423
|
+
return "UNK";
|
|
20424
|
+
}
|
|
20425
|
+
if (share >= 0.22) {
|
|
20426
|
+
return "KO";
|
|
20427
|
+
}
|
|
20428
|
+
if (share <= 0.12) {
|
|
20429
|
+
return "OK";
|
|
20430
|
+
}
|
|
20431
|
+
return "UNK";
|
|
20432
|
+
}
|
|
20433
|
+
function computeHostPoolHints(input) {
|
|
20434
|
+
return {
|
|
20435
|
+
hintScheduler: hintSchedulerFromSnapshot(input.snapshot),
|
|
20436
|
+
hintMemory: hintMemoryFrom(input.platform, input.snapshot, input.swap),
|
|
20437
|
+
hintLimits: hintLimitsFrom(input.limits),
|
|
20438
|
+
hintIo: hintIoFrom(input.prevStat, input.currStat)
|
|
20439
|
+
};
|
|
20440
|
+
}
|
|
20441
|
+
function tryReadLinuxSwapBytesFromMeminfo(readFileSyncImpl = fs36.readFileSync) {
|
|
20442
|
+
let raw;
|
|
20443
|
+
try {
|
|
20444
|
+
raw = readFileSyncImpl("/proc/meminfo", { encoding: "utf8", flag: "r" });
|
|
20445
|
+
} catch {
|
|
20446
|
+
return null;
|
|
20447
|
+
}
|
|
20448
|
+
let swapTotalKb = null;
|
|
20449
|
+
let swapFreeKb = null;
|
|
20450
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
20451
|
+
const tm = /^\s*SwapTotal:\s+(\d+)\s+kB/i.exec(line);
|
|
20452
|
+
if (tm) {
|
|
20453
|
+
swapTotalKb = Number(tm[1]);
|
|
20454
|
+
}
|
|
20455
|
+
const fm = /^\s*SwapFree:\s+(\d+)\s+kB/i.exec(line);
|
|
20456
|
+
if (fm) {
|
|
20457
|
+
swapFreeKb = Number(fm[1]);
|
|
20458
|
+
}
|
|
20459
|
+
}
|
|
20460
|
+
if (swapTotalKb === null || swapFreeKb === null || !Number.isFinite(swapTotalKb) || !Number.isFinite(swapFreeKb) || swapTotalKb < 0 || swapFreeKb < 0) {
|
|
20461
|
+
return null;
|
|
20462
|
+
}
|
|
20463
|
+
return {
|
|
20464
|
+
swapTotalB: Math.floor(swapTotalKb * 1024),
|
|
20465
|
+
swapFreeB: Math.floor(swapFreeKb * 1024)
|
|
20466
|
+
};
|
|
20467
|
+
}
|
|
20468
|
+
function tryReadLinuxAggregateCpuJiffies(readFileSyncImpl = fs36.readFileSync) {
|
|
20469
|
+
let raw;
|
|
20470
|
+
try {
|
|
20471
|
+
raw = readFileSyncImpl("/proc/stat", { encoding: "utf8", flag: "r" });
|
|
20472
|
+
} catch {
|
|
20473
|
+
return null;
|
|
20474
|
+
}
|
|
20475
|
+
const firstLine = raw.split(/\r?\n/)[0] ?? "";
|
|
20476
|
+
return parseLinuxAggregateCpuLine(firstLine);
|
|
20477
|
+
}
|
|
20478
|
+
function parseLinuxAggregateCpuLine(line) {
|
|
20479
|
+
const t = line.trim();
|
|
20480
|
+
if (!t.startsWith("cpu") || /^cpu\d/.test(t)) {
|
|
20481
|
+
return null;
|
|
20482
|
+
}
|
|
20483
|
+
const parts = t.split(/\s+/);
|
|
20484
|
+
if (parts.length < 6 || parts[0] !== "cpu") {
|
|
20485
|
+
return null;
|
|
20486
|
+
}
|
|
20487
|
+
const nums = [];
|
|
20488
|
+
for (let i = 1; i < parts.length; i++) {
|
|
20489
|
+
const n = Number(parts[i]);
|
|
20490
|
+
if (!Number.isFinite(n) || n < 0) {
|
|
20491
|
+
return null;
|
|
20492
|
+
}
|
|
20493
|
+
nums.push(Math.floor(n));
|
|
20494
|
+
}
|
|
20495
|
+
const total = nums.reduce((a, b) => a + b, 0);
|
|
20496
|
+
const iowait = nums.length >= 5 ? nums[4] : 0;
|
|
20497
|
+
return { total, iowait };
|
|
20498
|
+
}
|
|
20499
|
+
function parseProcSelfLimitsSoft(content, label) {
|
|
20500
|
+
const re = label === "Max open files" ? /^\s*Max open files\s+(\d+)\s+(\d+)/m : /^\s*Max processes\s+(\d+)\s+(\d+)/m;
|
|
20501
|
+
const m = re.exec(content);
|
|
20502
|
+
if (!m) {
|
|
20503
|
+
return null;
|
|
20504
|
+
}
|
|
20505
|
+
const soft = Number(m[1]);
|
|
20506
|
+
return Number.isFinite(soft) && soft > 0 ? soft : null;
|
|
20507
|
+
}
|
|
20508
|
+
function parseProcSelfStatusThreads(content) {
|
|
20509
|
+
const m = /^\s*Threads:\s*(\d+)/m.exec(content);
|
|
20510
|
+
if (!m) {
|
|
20511
|
+
return null;
|
|
20512
|
+
}
|
|
20513
|
+
const n = Number(m[1]);
|
|
20514
|
+
return Number.isFinite(n) && n >= 0 ? n : null;
|
|
20515
|
+
}
|
|
20516
|
+
function trySampleLinuxLimits(platform, readFileSyncImpl = fs36.readFileSync, readdirSyncImpl = fs36.readdirSync) {
|
|
20517
|
+
if (platform !== "linux") {
|
|
20518
|
+
return null;
|
|
20519
|
+
}
|
|
20520
|
+
let limitsRaw;
|
|
20521
|
+
let statusRaw;
|
|
20522
|
+
try {
|
|
20523
|
+
limitsRaw = readFileSyncImpl("/proc/self/limits", { encoding: "utf8", flag: "r" });
|
|
20524
|
+
statusRaw = readFileSyncImpl("/proc/self/status", { encoding: "utf8", flag: "r" });
|
|
20525
|
+
} catch {
|
|
20526
|
+
return null;
|
|
20527
|
+
}
|
|
20528
|
+
const nofileSoft = parseProcSelfLimitsSoft(limitsRaw, "Max open files");
|
|
20529
|
+
const nprocSoft = parseProcSelfLimitsSoft(limitsRaw, "Max processes");
|
|
20530
|
+
const threads = parseProcSelfStatusThreads(statusRaw);
|
|
20531
|
+
let fdCount = 0;
|
|
20532
|
+
let truncated = false;
|
|
20533
|
+
try {
|
|
20534
|
+
const names = readdirSyncImpl("/proc/self/fd");
|
|
20535
|
+
truncated = names.length > MAX_FD_ENUM;
|
|
20536
|
+
fdCount = Math.min(names.length, MAX_FD_ENUM);
|
|
20537
|
+
} catch {
|
|
20538
|
+
return { fdRatio: null, procRatio: null, truncated: true };
|
|
20539
|
+
}
|
|
20540
|
+
const fdRatio = nofileSoft !== null && nofileSoft > 0 ? Math.min(1, fdCount / nofileSoft) : null;
|
|
20541
|
+
const procRatio = nprocSoft !== null && nprocSoft > 0 && threads !== null ? Math.min(1, threads / nprocSoft) : null;
|
|
20542
|
+
return { fdRatio, procRatio, truncated };
|
|
20543
|
+
}
|
|
20544
|
+
function formatHostPoolPeriodicLine(params) {
|
|
20545
|
+
const s = params.snapshot;
|
|
20546
|
+
const load1Str = s.load1 === null ? "unknown" : String(s.load1);
|
|
20547
|
+
const perCpuStr = s.load1PerCpu === null ? "unknown" : String(s.load1PerCpu);
|
|
20548
|
+
const swapPart = params.swap !== null ? ` swapTotalB=${String(params.swap.swapTotalB)} swapFreeB=${String(params.swap.swapFreeB)}` : "";
|
|
20549
|
+
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}`;
|
|
20550
|
+
}
|
|
20551
|
+
function anyKo(h) {
|
|
20552
|
+
return h.hintMemory === "KO" || h.hintScheduler === "KO" || h.hintIo === "KO" || h.hintLimits === "KO";
|
|
20553
|
+
}
|
|
20554
|
+
function formatHostPoolRecLine(hints) {
|
|
20555
|
+
if (!anyKo(hints)) {
|
|
20556
|
+
return "[host-pool-rec] kind=none";
|
|
20557
|
+
}
|
|
20558
|
+
const parts = [];
|
|
20559
|
+
if (hints.hintMemory === "KO") {
|
|
20560
|
+
parts.push(TEMPLATE_MEMORY_KO);
|
|
20561
|
+
}
|
|
20562
|
+
if (hints.hintScheduler === "KO") {
|
|
20563
|
+
parts.push(TEMPLATE_SCHEDULER_KO);
|
|
20564
|
+
}
|
|
20565
|
+
if (hints.hintIo === "KO") {
|
|
20566
|
+
parts.push(TEMPLATE_IO_KO);
|
|
20567
|
+
}
|
|
20568
|
+
if (hints.hintLimits === "KO") {
|
|
20569
|
+
parts.push(TEMPLATE_LIMITS_KO);
|
|
20570
|
+
}
|
|
20571
|
+
let text = parts.join(" | ");
|
|
20572
|
+
if (text.length > MAX_ADVICE_TEXT_CHARS) {
|
|
20573
|
+
text = `${text.slice(0, MAX_ADVICE_TEXT_CHARS - 2)} \u2026`;
|
|
20574
|
+
}
|
|
20575
|
+
return `[host-pool-rec] kind=advice text=${text}`;
|
|
20576
|
+
}
|
|
20577
|
+
function createHostPoolTick(deps) {
|
|
20578
|
+
const platform = deps.platform ?? process.platform;
|
|
20579
|
+
const collect = deps.collectHostSnapshotFn ?? collectHostSnapshot;
|
|
20580
|
+
const readFs = deps.readFileSyncFn ?? fs36.readFileSync;
|
|
20581
|
+
const readDir = deps.readdirSyncFn ?? fs36.readdirSync;
|
|
20582
|
+
return () => {
|
|
20583
|
+
const { active, staticMaxConcurrentAi, adaptiveMaxConcurrentAi } = deps.getPoolState();
|
|
20584
|
+
if (active < 1) {
|
|
20585
|
+
return;
|
|
20586
|
+
}
|
|
20587
|
+
const snapshot = collect();
|
|
20588
|
+
let swap = null;
|
|
20589
|
+
let currStat = null;
|
|
20590
|
+
let limits = null;
|
|
20591
|
+
if (platform === "linux") {
|
|
20592
|
+
swap = tryReadLinuxSwapBytesFromMeminfo(readFs);
|
|
20593
|
+
currStat = tryReadLinuxAggregateCpuJiffies(readFs);
|
|
20594
|
+
limits = trySampleLinuxLimits(platform, readFs, readDir);
|
|
20595
|
+
}
|
|
20596
|
+
const hints = computeHostPoolHints({
|
|
20597
|
+
platform,
|
|
20598
|
+
snapshot,
|
|
20599
|
+
swap,
|
|
20600
|
+
limits,
|
|
20601
|
+
prevStat: deps.prevProcStatRef.current,
|
|
20602
|
+
currStat
|
|
20603
|
+
});
|
|
20604
|
+
const metrics = formatHostPoolPeriodicLine({
|
|
20605
|
+
activeWorkstations: active,
|
|
20606
|
+
staticMaxConcurrentAi,
|
|
20607
|
+
adaptiveMaxConcurrentAi,
|
|
20608
|
+
snapshot,
|
|
20609
|
+
hints,
|
|
20610
|
+
swap
|
|
20611
|
+
});
|
|
20612
|
+
const rec = formatHostPoolRecLine(hints);
|
|
20613
|
+
deps.log(metrics);
|
|
20614
|
+
deps.log(rec);
|
|
20615
|
+
if (platform === "linux" && currStat !== null) {
|
|
20616
|
+
deps.prevProcStatRef.current = currStat;
|
|
20617
|
+
}
|
|
20618
|
+
};
|
|
20619
|
+
}
|
|
20620
|
+
|
|
20331
20621
|
// src/pipelines/synthesis/synthesisPipeline.ts
|
|
20332
20622
|
var FE = /^FE-\d+$/;
|
|
20333
20623
|
var UC = /^UC-\d+$/;
|
|
@@ -20340,7 +20630,7 @@ function stripBom2(s) {
|
|
|
20340
20630
|
}
|
|
20341
20631
|
function readJson4(filePath) {
|
|
20342
20632
|
try {
|
|
20343
|
-
const raw = stripBom2(
|
|
20633
|
+
const raw = stripBom2(fs37.readFileSync(filePath, "utf-8"));
|
|
20344
20634
|
return JSON.parse(raw);
|
|
20345
20635
|
} catch {
|
|
20346
20636
|
return null;
|
|
@@ -20435,7 +20725,7 @@ function featureDetailTarget(contextDir2, code, name, slug) {
|
|
|
20435
20725
|
displayName: "Feature detail",
|
|
20436
20726
|
outputBasename: basename17,
|
|
20437
20727
|
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).`,
|
|
20438
|
-
exists:
|
|
20728
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20439
20729
|
};
|
|
20440
20730
|
}
|
|
20441
20731
|
function viewDetailTarget(row2, contextDir2) {
|
|
@@ -20446,7 +20736,7 @@ function viewDetailTarget(row2, contextDir2) {
|
|
|
20446
20736
|
displayName: "View detail",
|
|
20447
20737
|
outputBasename: basename17,
|
|
20448
20738
|
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.`,
|
|
20449
|
-
exists:
|
|
20739
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20450
20740
|
};
|
|
20451
20741
|
}
|
|
20452
20742
|
function interactionDetailTarget(viewCode, ix, contextDir2) {
|
|
@@ -20457,7 +20747,7 @@ function interactionDetailTarget(viewCode, ix, contextDir2) {
|
|
|
20457
20747
|
displayName: "Interaction detail",
|
|
20458
20748
|
outputBasename: basename17,
|
|
20459
20749
|
taskDescription: `Document interaction **${ix.code}** (**${ix.name}**) on view **${viewCode}** per \`.gluecharm/context/experiences-list.json\`.`,
|
|
20460
|
-
exists:
|
|
20750
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20461
20751
|
};
|
|
20462
20752
|
}
|
|
20463
20753
|
function serviceDetailTarget(row2, contextDir2) {
|
|
@@ -20468,7 +20758,7 @@ function serviceDetailTarget(row2, contextDir2) {
|
|
|
20468
20758
|
displayName: "Service detail",
|
|
20469
20759
|
outputBasename: basename17,
|
|
20470
20760
|
taskDescription: `Describe service **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/services-list.json\`: responsibilities, consumers, errors, integration points.`,
|
|
20471
|
-
exists:
|
|
20761
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20472
20762
|
};
|
|
20473
20763
|
}
|
|
20474
20764
|
function methodDetailTarget(svc, m, contextDir2) {
|
|
@@ -20479,7 +20769,7 @@ function methodDetailTarget(svc, m, contextDir2) {
|
|
|
20479
20769
|
displayName: "Method detail",
|
|
20480
20770
|
outputBasename: basename17,
|
|
20481
20771
|
taskDescription: `Document method **${m.code}** (**${m.name}**) on service **${svc.code}** per \`.gluecharm/context/services-list.json\`.`,
|
|
20482
|
-
exists:
|
|
20772
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20483
20773
|
};
|
|
20484
20774
|
}
|
|
20485
20775
|
function entityDetailTarget(dmCode, ename, slug, contextDir2) {
|
|
@@ -20490,7 +20780,7 @@ function entityDetailTarget(dmCode, ename, slug, contextDir2) {
|
|
|
20490
20780
|
displayName: "Entity detail",
|
|
20491
20781
|
outputBasename: basename17,
|
|
20492
20782
|
taskDescription: `Describe entity **${dmCode}** (**${ename}**, slug **${slug}**) per \`.gluecharm/context/data-model-list.json\`: lifecycle, invariants, storage, ORM/schema mapping.`,
|
|
20493
|
-
exists:
|
|
20783
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20494
20784
|
};
|
|
20495
20785
|
}
|
|
20496
20786
|
function fieldDetailTarget(dmCode, fdCode, fname, fSlug, contextDir2) {
|
|
@@ -20501,7 +20791,7 @@ function fieldDetailTarget(dmCode, fdCode, fname, fSlug, contextDir2) {
|
|
|
20501
20791
|
displayName: "Field detail",
|
|
20502
20792
|
outputBasename: basename17,
|
|
20503
20793
|
taskDescription: `Document field **${fdCode}** (**${fname}**) on entity **${dmCode}** per \`.gluecharm/context/${dmCode}-fields-list.json\`. Cite types and constraints with file and line.`,
|
|
20504
|
-
exists:
|
|
20794
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20505
20795
|
};
|
|
20506
20796
|
}
|
|
20507
20797
|
function toolDetailTarget(row2, contextDir2) {
|
|
@@ -20512,7 +20802,7 @@ function toolDetailTarget(row2, contextDir2) {
|
|
|
20512
20802
|
displayName: "Tool detail",
|
|
20513
20803
|
outputBasename: basename17,
|
|
20514
20804
|
taskDescription: `Describe tool **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/tech-stack-list.json\`: role, version hints, configuration, boundaries.`,
|
|
20515
|
-
exists:
|
|
20805
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20516
20806
|
};
|
|
20517
20807
|
}
|
|
20518
20808
|
function useCaseDetailTarget(feCode, ucCode, ucName, ucSlug, contextDir2) {
|
|
@@ -20525,7 +20815,7 @@ function useCaseDetailTarget(feCode, ucCode, ucName, ucSlug, contextDir2) {
|
|
|
20525
20815
|
taskDescription: `Document use case **${ucCode}** (**${ucName}**) under feature **${feCode}** per \`.gluecharm/context/${feCode}-use-cases-list.json\`. Do not change stable codes.
|
|
20526
20816
|
|
|
20527
20817
|
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.`,
|
|
20528
|
-
exists:
|
|
20818
|
+
exists: fs37.existsSync(path32.join(contextDir2, ucBase)) && fs37.statSync(path32.join(contextDir2, ucBase)).size > 0
|
|
20529
20819
|
};
|
|
20530
20820
|
}
|
|
20531
20821
|
function scenarioDetailTarget(feCode, ucCode, scCode, scName, contextDir2) {
|
|
@@ -20536,7 +20826,7 @@ function scenarioDetailTarget(feCode, ucCode, scCode, scName, contextDir2) {
|
|
|
20536
20826
|
displayName: "Scenario detail",
|
|
20537
20827
|
outputBasename: basename17,
|
|
20538
20828
|
taskDescription: `Document scenario **${scCode}** (**${scName}**) for **${feCode}** / **${ucCode}** per \`.gluecharm/context/${feCode}_${ucCode}-scenarios-list.json\`. Cite steps with file and line where possible.`,
|
|
20539
|
-
exists:
|
|
20829
|
+
exists: fs37.existsSync(path32.join(contextDir2, basename17)) && fs37.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20540
20830
|
};
|
|
20541
20831
|
}
|
|
20542
20832
|
function parentsDone(item, byId) {
|
|
@@ -21096,6 +21386,20 @@ async function drainWorkstationPool(p) {
|
|
|
21096
21386
|
const intervalMs = p.__testOnlyCpuPressureIntervalMs ?? 3e4;
|
|
21097
21387
|
pressureInterval = setInterval(() => applyCpuPressure(), intervalMs);
|
|
21098
21388
|
}
|
|
21389
|
+
const hostPoolPrevStat = { current: null };
|
|
21390
|
+
const hostPoolTick = createHostPoolTick({
|
|
21391
|
+
log,
|
|
21392
|
+
getPoolState: () => ({
|
|
21393
|
+
active,
|
|
21394
|
+
staticMaxConcurrentAi: staticMaxC,
|
|
21395
|
+
adaptiveMaxConcurrentAi: adaptiveMax
|
|
21396
|
+
}),
|
|
21397
|
+
prevProcStatRef: hostPoolPrevStat
|
|
21398
|
+
});
|
|
21399
|
+
const hostPoolIntervalMs = p.__testOnlyHostPoolIntervalMs ?? DEFAULT_HOST_POOL_INTERVAL_MS;
|
|
21400
|
+
const hostPoolInterval = setInterval(() => {
|
|
21401
|
+
hostPoolTick();
|
|
21402
|
+
}, hostPoolIntervalMs);
|
|
21099
21403
|
try {
|
|
21100
21404
|
while (true) {
|
|
21101
21405
|
while (fifo.length > 0 && active < currentCap() && !abortSignal?.aborted) {
|
|
@@ -21126,6 +21430,7 @@ async function drainWorkstationPool(p) {
|
|
|
21126
21430
|
if (pressureInterval) {
|
|
21127
21431
|
clearInterval(pressureInterval);
|
|
21128
21432
|
}
|
|
21433
|
+
clearInterval(hostPoolInterval);
|
|
21129
21434
|
if (poolAbortListenerRegistered && abortSignal) {
|
|
21130
21435
|
abortSignal.removeEventListener("abort", onPipelineAbort);
|
|
21131
21436
|
}
|
|
@@ -21165,7 +21470,7 @@ async function runSynthesisPipelineDrainFromPreparedWorktree(storageContext, rep
|
|
|
21165
21470
|
offlineLearnAfterSameSessionTrace: getAceOfflineLearnAfterSameSessionTrace(handle.path)
|
|
21166
21471
|
};
|
|
21167
21472
|
const contextDir2 = path32.join(handle.path, ".gluecharm", "context");
|
|
21168
|
-
|
|
21473
|
+
fs37.mkdirSync(contextDir2, { recursive: true });
|
|
21169
21474
|
const initialItems = buildRootItems();
|
|
21170
21475
|
await startArtefactRun(storageContext, repoRoot, handle.path, initialItems);
|
|
21171
21476
|
await cb.onBootstrapReady?.({ worktreeRoot: handle.path, contextDir: contextDir2 });
|
|
@@ -21266,27 +21571,27 @@ async function runSynthesisPipeline(storageContext, repoRoot, workspaceLabel, ex
|
|
|
21266
21571
|
}
|
|
21267
21572
|
|
|
21268
21573
|
// src/workspaceContextPromote.ts
|
|
21269
|
-
var
|
|
21574
|
+
var fs38 = __toESM(require("fs"));
|
|
21270
21575
|
var path33 = __toESM(require("path"));
|
|
21271
21576
|
function promoteContextDirectoryToWorkspaceFs(sourceContextDir, workspaceRootFs) {
|
|
21272
21577
|
const dest = path33.join(workspaceRootFs, ".gluecharm", "context");
|
|
21273
|
-
|
|
21274
|
-
|
|
21578
|
+
fs38.mkdirSync(path33.join(workspaceRootFs, ".gluecharm"), { recursive: true });
|
|
21579
|
+
fs38.mkdirSync(dest, { recursive: true });
|
|
21275
21580
|
let names;
|
|
21276
21581
|
try {
|
|
21277
|
-
names =
|
|
21582
|
+
names = fs38.readdirSync(sourceContextDir);
|
|
21278
21583
|
} catch {
|
|
21279
21584
|
return { filesCopied: 0 };
|
|
21280
21585
|
}
|
|
21281
21586
|
let filesCopied = 0;
|
|
21282
21587
|
for (const name of names) {
|
|
21283
21588
|
const srcPath = path33.join(sourceContextDir, name);
|
|
21284
|
-
if (!
|
|
21589
|
+
if (!fs38.statSync(srcPath).isFile()) {
|
|
21285
21590
|
continue;
|
|
21286
21591
|
}
|
|
21287
|
-
const buf =
|
|
21592
|
+
const buf = fs38.readFileSync(srcPath);
|
|
21288
21593
|
const target = path33.join(dest, name);
|
|
21289
|
-
|
|
21594
|
+
fs38.writeFileSync(target, buf);
|
|
21290
21595
|
filesCopied += 1;
|
|
21291
21596
|
}
|
|
21292
21597
|
return { filesCopied };
|
|
@@ -21946,7 +22251,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21946
22251
|
}
|
|
21947
22252
|
|
|
21948
22253
|
// src/factory/generateContextFactoryHeadlessHost.ts
|
|
21949
|
-
var
|
|
22254
|
+
var fs47 = __toESM(require("node:fs"));
|
|
21950
22255
|
var path43 = __toESM(require("node:path"));
|
|
21951
22256
|
|
|
21952
22257
|
// src/stores/pipelineRunStore.ts
|
|
@@ -22047,11 +22352,11 @@ async function noteAgentsMaterialized(context) {
|
|
|
22047
22352
|
}
|
|
22048
22353
|
|
|
22049
22354
|
// src/pipelines/remediation/missingWorkstations.ts
|
|
22050
|
-
var
|
|
22355
|
+
var fs40 = __toESM(require("fs"));
|
|
22051
22356
|
var path35 = __toESM(require("path"));
|
|
22052
22357
|
|
|
22053
22358
|
// src/analysis/analysisDetailMarkdownDiscovery.ts
|
|
22054
|
-
var
|
|
22359
|
+
var fs39 = __toESM(require("fs"));
|
|
22055
22360
|
var path34 = __toESM(require("path"));
|
|
22056
22361
|
var SLUG4 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
22057
22362
|
var FE2 = /^FE-\d+$/;
|
|
@@ -22073,7 +22378,7 @@ var STEM_TO_AGENT = {
|
|
|
22073
22378
|
};
|
|
22074
22379
|
function readJson5(filePath) {
|
|
22075
22380
|
try {
|
|
22076
|
-
let raw =
|
|
22381
|
+
let raw = fs39.readFileSync(filePath, "utf-8");
|
|
22077
22382
|
if (raw.length > 0 && raw.charCodeAt(0) === 65279) {
|
|
22078
22383
|
raw = raw.slice(1);
|
|
22079
22384
|
}
|
|
@@ -22341,7 +22646,7 @@ function fileAndValidationFromKind(kind) {
|
|
|
22341
22646
|
function classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeRoot) {
|
|
22342
22647
|
const abs = path35.join(contextDir2, row2.relativePath);
|
|
22343
22648
|
try {
|
|
22344
|
-
const st =
|
|
22649
|
+
const st = fs40.statSync(abs);
|
|
22345
22650
|
if (!st.isFile()) {
|
|
22346
22651
|
return { kind: "absent", detail: "Path exists but is not a regular file." };
|
|
22347
22652
|
}
|
|
@@ -22379,7 +22684,7 @@ function classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeR
|
|
|
22379
22684
|
};
|
|
22380
22685
|
}
|
|
22381
22686
|
const schemaAbs = path35.join(worktreeRoot, ".opencode", "schemas", "context-lists", schemaBn);
|
|
22382
|
-
if (!
|
|
22687
|
+
if (!fs40.existsSync(schemaAbs)) {
|
|
22383
22688
|
return {
|
|
22384
22689
|
kind: "invalid",
|
|
22385
22690
|
detail: `Schema not found (${schemaBn}). Run **Materialize agents** on this checkout.`
|
|
@@ -22615,7 +22920,7 @@ function listMissingWorkstations(contextDir2, worktreeRoot, snapshot) {
|
|
|
22615
22920
|
}
|
|
22616
22921
|
}
|
|
22617
22922
|
}
|
|
22618
|
-
if (!
|
|
22923
|
+
if (!fs40.existsSync(contextDir2)) {
|
|
22619
22924
|
return [...map.values()].sort((a, b) => a.key.localeCompare(b.key));
|
|
22620
22925
|
}
|
|
22621
22926
|
const dynamic = discoverDynamicAnalysisTestSteps(contextDir2);
|
|
@@ -22796,11 +23101,11 @@ async function runRemediationPipelineMissingPass(p) {
|
|
|
22796
23101
|
|
|
22797
23102
|
// src/pipelines/coverage/coveragePipeline.ts
|
|
22798
23103
|
var import_child_process5 = require("child_process");
|
|
22799
|
-
var
|
|
23104
|
+
var fs42 = __toESM(require("fs"));
|
|
22800
23105
|
var path38 = __toESM(require("path"));
|
|
22801
23106
|
|
|
22802
23107
|
// src/analysis/coverageReferenceValidationSchemaValidate.ts
|
|
22803
|
-
var
|
|
23108
|
+
var fs41 = __toESM(require("fs"));
|
|
22804
23109
|
var path37 = __toESM(require("path"));
|
|
22805
23110
|
var import__5 = __toESM(require__());
|
|
22806
23111
|
function stripUtf8Bom4(s) {
|
|
@@ -22830,7 +23135,7 @@ function getValidate() {
|
|
|
22830
23135
|
return compiledValidate;
|
|
22831
23136
|
}
|
|
22832
23137
|
const schemaPath = bundledCoverageReferenceValidationSchemaPath();
|
|
22833
|
-
const schemaRaw = stripUtf8Bom4(
|
|
23138
|
+
const schemaRaw = stripUtf8Bom4(fs41.readFileSync(schemaPath, "utf-8"));
|
|
22834
23139
|
const schema = JSON.parse(schemaRaw);
|
|
22835
23140
|
const ajv2 = new import__5.default({ allErrors: true, strict: false });
|
|
22836
23141
|
compiledValidate = ajv2.compile(schema);
|
|
@@ -22846,7 +23151,7 @@ function validateCoverageReferenceValidationData(data) {
|
|
|
22846
23151
|
function readAndValidateCoverageReferenceValidationFile(jsonAbsolutePath) {
|
|
22847
23152
|
let raw;
|
|
22848
23153
|
try {
|
|
22849
|
-
raw = stripUtf8Bom4(
|
|
23154
|
+
raw = stripUtf8Bom4(fs41.readFileSync(jsonAbsolutePath, "utf-8"));
|
|
22850
23155
|
} catch (e) {
|
|
22851
23156
|
return {
|
|
22852
23157
|
ok: false,
|
|
@@ -22888,7 +23193,7 @@ var DEFAULT_IGNORE_DIR_BASENAMES = [
|
|
|
22888
23193
|
var GIT_LS_FILES_MAX_BUFFER = 64 * 1024 * 1024;
|
|
22889
23194
|
function tryLoadGitNonIgnoredPathSet(repositoryRootAbs) {
|
|
22890
23195
|
const root = path38.resolve(repositoryRootAbs);
|
|
22891
|
-
if (!
|
|
23196
|
+
if (!fs42.existsSync(path38.join(root, ".git"))) {
|
|
22892
23197
|
return null;
|
|
22893
23198
|
}
|
|
22894
23199
|
const env = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
@@ -23043,7 +23348,7 @@ function extractEvidenceIndexPathCitations(body) {
|
|
|
23043
23348
|
function listContextFilesRecursive(dir, acc) {
|
|
23044
23349
|
let entries;
|
|
23045
23350
|
try {
|
|
23046
|
-
entries =
|
|
23351
|
+
entries = fs42.readdirSync(dir, { withFileTypes: true });
|
|
23047
23352
|
} catch {
|
|
23048
23353
|
return;
|
|
23049
23354
|
}
|
|
@@ -23061,7 +23366,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
23061
23366
|
const walk = (dir) => {
|
|
23062
23367
|
let entries;
|
|
23063
23368
|
try {
|
|
23064
|
-
entries =
|
|
23369
|
+
entries = fs42.readdirSync(dir, { withFileTypes: true });
|
|
23065
23370
|
} catch {
|
|
23066
23371
|
return;
|
|
23067
23372
|
}
|
|
@@ -23091,7 +23396,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
23091
23396
|
}
|
|
23092
23397
|
let st;
|
|
23093
23398
|
try {
|
|
23094
|
-
st =
|
|
23399
|
+
st = fs42.statSync(full);
|
|
23095
23400
|
} catch {
|
|
23096
23401
|
continue;
|
|
23097
23402
|
}
|
|
@@ -23101,7 +23406,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
23101
23406
|
}
|
|
23102
23407
|
let buf;
|
|
23103
23408
|
try {
|
|
23104
|
-
buf =
|
|
23409
|
+
buf = fs42.readFileSync(full);
|
|
23105
23410
|
} catch {
|
|
23106
23411
|
excludedOut.push({ path: rel, reason: "read error" });
|
|
23107
23412
|
continue;
|
|
@@ -23121,7 +23426,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
23121
23426
|
}
|
|
23122
23427
|
function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings) {
|
|
23123
23428
|
const references = [];
|
|
23124
|
-
if (!
|
|
23429
|
+
if (!fs42.existsSync(contextDirAbs)) {
|
|
23125
23430
|
warnings.push(`Context directory missing: ${contextDirAbs}`);
|
|
23126
23431
|
return references;
|
|
23127
23432
|
}
|
|
@@ -23137,7 +23442,7 @@ function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings
|
|
|
23137
23442
|
}
|
|
23138
23443
|
let raw;
|
|
23139
23444
|
try {
|
|
23140
|
-
raw =
|
|
23445
|
+
raw = fs42.readFileSync(abs, "utf-8");
|
|
23141
23446
|
} catch (e) {
|
|
23142
23447
|
warnings.push(`Skip JSON (read error): ${sourceArtefact} \u2014 ${e instanceof Error ? e.message : String(e)}`);
|
|
23143
23448
|
continue;
|
|
@@ -23168,7 +23473,7 @@ function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings
|
|
|
23168
23473
|
if (ext === ".md") {
|
|
23169
23474
|
let text;
|
|
23170
23475
|
try {
|
|
23171
|
-
const buf =
|
|
23476
|
+
const buf = fs42.readFileSync(abs);
|
|
23172
23477
|
text = decodeBufferForLineCount(buf);
|
|
23173
23478
|
} catch (e) {
|
|
23174
23479
|
warnings.push(`Skip markdown (read/decode error): ${sourceArtefact} \u2014 ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -23225,7 +23530,7 @@ function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirA
|
|
|
23225
23530
|
}
|
|
23226
23531
|
const excludedFiles = [];
|
|
23227
23532
|
const gitNonIgnoredPaths = tryLoadGitNonIgnoredPathSet(repoRoot);
|
|
23228
|
-
if (
|
|
23533
|
+
if (fs42.existsSync(path38.join(repoRoot, ".git")) && gitNonIgnoredPaths === null) {
|
|
23229
23534
|
warnings.push(
|
|
23230
23535
|
"Repository has .git but git ls-files failed or git is unavailable; .gitignore / exclude-standard not applied."
|
|
23231
23536
|
);
|
|
@@ -23276,10 +23581,10 @@ function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirA
|
|
|
23276
23581
|
function runCoveragePipeline(opts) {
|
|
23277
23582
|
const repoRoot = path38.resolve(opts.repositoryRootAbs);
|
|
23278
23583
|
const contextDir2 = path38.resolve(opts.contextDirAbs);
|
|
23279
|
-
if (!
|
|
23584
|
+
if (!fs42.existsSync(repoRoot)) {
|
|
23280
23585
|
return { ok: false, error: `Repository root does not exist: ${repoRoot}` };
|
|
23281
23586
|
}
|
|
23282
|
-
if (!
|
|
23587
|
+
if (!fs42.existsSync(contextDir2)) {
|
|
23283
23588
|
return {
|
|
23284
23589
|
ok: false,
|
|
23285
23590
|
error: `Missing .gluecharm/context: ${contextDir2}`
|
|
@@ -23301,7 +23606,7 @@ ${schemaCheck.errors.join("\n")}`,
|
|
|
23301
23606
|
if (opts.write) {
|
|
23302
23607
|
try {
|
|
23303
23608
|
const payload = stableStringifyCoverageDocument(document);
|
|
23304
|
-
|
|
23609
|
+
fs42.writeFileSync(outPath, payload, "utf-8");
|
|
23305
23610
|
} catch (e) {
|
|
23306
23611
|
return {
|
|
23307
23612
|
ok: false,
|
|
@@ -23315,11 +23620,11 @@ ${schemaCheck.errors.join("\n")}`,
|
|
|
23315
23620
|
|
|
23316
23621
|
// src/pipelines/remediation/zeroReferenceWorkstationChain.ts
|
|
23317
23622
|
var crypto = __toESM(require("crypto"));
|
|
23318
|
-
var
|
|
23623
|
+
var fs44 = __toESM(require("fs"));
|
|
23319
23624
|
var path40 = __toESM(require("path"));
|
|
23320
23625
|
|
|
23321
23626
|
// src/analysis/zeroReferenceRemediationSchemaValidate.ts
|
|
23322
|
-
var
|
|
23627
|
+
var fs43 = __toESM(require("fs"));
|
|
23323
23628
|
var path39 = __toESM(require("path"));
|
|
23324
23629
|
var import__6 = __toESM(require__());
|
|
23325
23630
|
function stripUtf8Bom5(s) {
|
|
@@ -23341,7 +23646,7 @@ function formatAjvErrors6(errors) {
|
|
|
23341
23646
|
var ajv = new import__6.default({ allErrors: true, strict: false });
|
|
23342
23647
|
function compileSchema(basename17) {
|
|
23343
23648
|
const schemaPath = path39.join(schemasDir(), basename17);
|
|
23344
|
-
const schemaRaw = stripUtf8Bom5(
|
|
23649
|
+
const schemaRaw = stripUtf8Bom5(fs43.readFileSync(schemaPath, "utf-8"));
|
|
23345
23650
|
const schema = JSON.parse(schemaRaw);
|
|
23346
23651
|
return ajv.compile(schema);
|
|
23347
23652
|
}
|
|
@@ -23385,7 +23690,7 @@ var ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS = 5;
|
|
|
23385
23690
|
var ZERO_REF_STAGING_FILE_PREVIEW_MAX_CHARS = 6e3;
|
|
23386
23691
|
function readStagingOutputPreview(outAbs) {
|
|
23387
23692
|
try {
|
|
23388
|
-
const s =
|
|
23693
|
+
const s = fs44.readFileSync(outAbs, "utf-8");
|
|
23389
23694
|
if (s.length <= ZERO_REF_STAGING_FILE_PREVIEW_MAX_CHARS) {
|
|
23390
23695
|
return s;
|
|
23391
23696
|
}
|
|
@@ -23668,14 +23973,14 @@ function readNonReferencedFilesFromRepositoryRoot(repositoryRootAbs) {
|
|
|
23668
23973
|
return { ok: true, paths, ...generatedAt ? { generatedAt } : {} };
|
|
23669
23974
|
}
|
|
23670
23975
|
function readOrInitRoutingDoc(routingAbs, coverageReferenceGeneratedAt) {
|
|
23671
|
-
if (!
|
|
23976
|
+
if (!fs44.existsSync(routingAbs)) {
|
|
23672
23977
|
return {
|
|
23673
23978
|
schemaVersion: ROUTING_SCHEMA_VERSION,
|
|
23674
23979
|
...coverageReferenceGeneratedAt ? { coverageReferenceGeneratedAt } : {},
|
|
23675
23980
|
records: {}
|
|
23676
23981
|
};
|
|
23677
23982
|
}
|
|
23678
|
-
const raw =
|
|
23983
|
+
const raw = fs44.readFileSync(routingAbs, "utf-8");
|
|
23679
23984
|
const data = JSON.parse(raw);
|
|
23680
23985
|
if (!data.records || typeof data.records !== "object") {
|
|
23681
23986
|
return {
|
|
@@ -23687,10 +23992,10 @@ function readOrInitRoutingDoc(routingAbs, coverageReferenceGeneratedAt) {
|
|
|
23687
23992
|
return data;
|
|
23688
23993
|
}
|
|
23689
23994
|
function readOrInitTriageDoc(triageAbs) {
|
|
23690
|
-
if (!
|
|
23995
|
+
if (!fs44.existsSync(triageAbs)) {
|
|
23691
23996
|
return { schemaVersion: TRIAGE_SCHEMA_VERSION, records: {} };
|
|
23692
23997
|
}
|
|
23693
|
-
const raw =
|
|
23998
|
+
const raw = fs44.readFileSync(triageAbs, "utf-8");
|
|
23694
23999
|
const data = JSON.parse(raw);
|
|
23695
24000
|
if (!data.records || typeof data.records !== "object") {
|
|
23696
24001
|
return { schemaVersion: TRIAGE_SCHEMA_VERSION, records: {} };
|
|
@@ -23741,7 +24046,7 @@ function lineCountRepoFile(worktreeRootAbs, relPosix) {
|
|
|
23741
24046
|
const abs = path40.join(worktreeRootAbs, ...relPosix.split("/"));
|
|
23742
24047
|
let buf;
|
|
23743
24048
|
try {
|
|
23744
|
-
buf =
|
|
24049
|
+
buf = fs44.readFileSync(abs);
|
|
23745
24050
|
} catch {
|
|
23746
24051
|
return 1;
|
|
23747
24052
|
}
|
|
@@ -23795,7 +24100,7 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23795
24100
|
const cfg = LIST_MERGE_CFG[input.listKind];
|
|
23796
24101
|
const listPath = path40.join(input.contextDirAbs, cfg.listBasename);
|
|
23797
24102
|
const schemaPath = path40.join(resolveContextListSchemasDir(), cfg.schemaBasename);
|
|
23798
|
-
if (!
|
|
24103
|
+
if (!fs44.existsSync(listPath)) {
|
|
23799
24104
|
return {
|
|
23800
24105
|
ok: false,
|
|
23801
24106
|
message: `${cfg.listBasename} not found \u2014 run coordination step ${LIST_STEP_HINT[input.listKind]} first.`
|
|
@@ -23806,7 +24111,7 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23806
24111
|
return withCoordinationListFileLock(listPath, {}, async () => {
|
|
23807
24112
|
let raw;
|
|
23808
24113
|
try {
|
|
23809
|
-
raw =
|
|
24114
|
+
raw = fs44.readFileSync(listPath, "utf-8");
|
|
23810
24115
|
} catch (e) {
|
|
23811
24116
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
23812
24117
|
}
|
|
@@ -23874,7 +24179,7 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23874
24179
|
});
|
|
23875
24180
|
const tmp = `${listPath}.tmp.${process.pid}`;
|
|
23876
24181
|
try {
|
|
23877
|
-
|
|
24182
|
+
fs44.writeFileSync(tmp, `${JSON.stringify(doc, null, 2)}
|
|
23878
24183
|
`, "utf-8");
|
|
23879
24184
|
} catch (e) {
|
|
23880
24185
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
@@ -23882,13 +24187,13 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23882
24187
|
const v = validateCoordinationListJson(tmp, schemaPath);
|
|
23883
24188
|
if (!v.ok) {
|
|
23884
24189
|
try {
|
|
23885
|
-
|
|
24190
|
+
fs44.unlinkSync(tmp);
|
|
23886
24191
|
} catch {
|
|
23887
24192
|
}
|
|
23888
24193
|
return { ok: false, message: `${cfg.listBasename} validation failed: ${JSON.stringify(v.failure)}` };
|
|
23889
24194
|
}
|
|
23890
24195
|
try {
|
|
23891
|
-
|
|
24196
|
+
fs44.renameSync(tmp, listPath);
|
|
23892
24197
|
} catch (e) {
|
|
23893
24198
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
23894
24199
|
}
|
|
@@ -23898,9 +24203,9 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23898
24203
|
}
|
|
23899
24204
|
async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, workspaceLabel) {
|
|
23900
24205
|
const outAbs = stagingPathForTarget(contextDirAbs, "classifier", targetFilePathPosix);
|
|
23901
|
-
|
|
24206
|
+
fs44.mkdirSync(path40.dirname(outAbs), { recursive: true });
|
|
23902
24207
|
const runDir = path40.join(common.worktreeRoot, ".opencode", "_run");
|
|
23903
|
-
|
|
24208
|
+
fs44.mkdirSync(runDir, { recursive: true });
|
|
23904
24209
|
const outputBasename = path40.basename(outAbs);
|
|
23905
24210
|
const listTaskDescription = [
|
|
23906
24211
|
`Target file (repo-relative, POSIX): **${targetFilePathPosix}**`,
|
|
@@ -23938,7 +24243,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
|
|
|
23938
24243
|
...repairAppendix ? { repairAppendix } : {}
|
|
23939
24244
|
});
|
|
23940
24245
|
const promptPath = path40.join(runDir, `zero-ref-classify-a${attempt}-${Date.now()}.prompt.txt`);
|
|
23941
|
-
|
|
24246
|
+
fs44.writeFileSync(promptPath, body, "utf-8");
|
|
23942
24247
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
23943
24248
|
promptFile: promptPath,
|
|
23944
24249
|
agentId: ZERO_REF_CLASSIFY_AGENT_STEM,
|
|
@@ -23965,7 +24270,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
|
|
|
23965
24270
|
const canRetry = attempt < ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS - 1;
|
|
23966
24271
|
let st;
|
|
23967
24272
|
try {
|
|
23968
|
-
st =
|
|
24273
|
+
st = fs44.statSync(outAbs);
|
|
23969
24274
|
} catch {
|
|
23970
24275
|
st = void 0;
|
|
23971
24276
|
}
|
|
@@ -23987,7 +24292,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
|
|
|
23987
24292
|
}
|
|
23988
24293
|
let parsed;
|
|
23989
24294
|
try {
|
|
23990
|
-
parsed = JSON.parse(
|
|
24295
|
+
parsed = JSON.parse(fs44.readFileSync(outAbs, "utf-8"));
|
|
23991
24296
|
} catch (e) {
|
|
23992
24297
|
const msg = e instanceof Error ? e.message : String(e);
|
|
23993
24298
|
lastFailureMessage = `Classifier output not valid JSON: ${msg}`;
|
|
@@ -24072,7 +24377,7 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
|
|
|
24072
24377
|
const mdAbs = path40.join(contextDirAbs, mdBasename);
|
|
24073
24378
|
const agentStem = which === "project" ? ZERO_REF_ADD_REF_PROJECT_AGENT_STEM : ZERO_REF_ADD_REF_ARCH_AGENT_STEM;
|
|
24074
24379
|
const runDir = path40.join(common.worktreeRoot, ".opencode", "_run");
|
|
24075
|
-
|
|
24380
|
+
fs44.mkdirSync(runDir, { recursive: true });
|
|
24076
24381
|
const lines = [
|
|
24077
24382
|
`# SRS-30 \u2014 Add reference to ${mdBasename}`,
|
|
24078
24383
|
``,
|
|
@@ -24088,7 +24393,7 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
|
|
|
24088
24393
|
`- Do not remove unrelated content; append or extend the most appropriate section.`
|
|
24089
24394
|
];
|
|
24090
24395
|
const promptPath = path40.join(runDir, `zero-ref-md-${which}-${Date.now()}.prompt.txt`);
|
|
24091
|
-
|
|
24396
|
+
fs44.writeFileSync(promptPath, lines.join("\n"), "utf-8");
|
|
24092
24397
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
24093
24398
|
promptFile: promptPath,
|
|
24094
24399
|
agentId: agentStem,
|
|
@@ -24115,9 +24420,9 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
|
|
|
24115
24420
|
async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathPosix, routingSummary, workspaceLabel, triageScope) {
|
|
24116
24421
|
const meta = TRIAGE_SCOPE_META[triageScope];
|
|
24117
24422
|
const outAbs = stagingPathForTarget(contextDirAbs, "triage", targetFilePathPosix);
|
|
24118
|
-
|
|
24423
|
+
fs44.mkdirSync(path40.dirname(outAbs), { recursive: true });
|
|
24119
24424
|
const runDir = path40.join(common.worktreeRoot, ".opencode", "_run");
|
|
24120
|
-
|
|
24425
|
+
fs44.mkdirSync(runDir, { recursive: true });
|
|
24121
24426
|
const outputBasename = path40.basename(outAbs);
|
|
24122
24427
|
const listTaskDescription = [
|
|
24123
24428
|
`Target file: **${targetFilePathPosix}** (${workspaceLabel})`,
|
|
@@ -24149,7 +24454,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
24149
24454
|
...repairAppendix ? { repairAppendix } : {}
|
|
24150
24455
|
});
|
|
24151
24456
|
const promptPath = path40.join(runDir, `zero-ref-triage-a${attempt}-${Date.now()}.prompt.txt`);
|
|
24152
|
-
|
|
24457
|
+
fs44.writeFileSync(promptPath, body, "utf-8");
|
|
24153
24458
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
24154
24459
|
promptFile: promptPath,
|
|
24155
24460
|
agentId: ZERO_REF_TRIAGE_COORD_AGENT_STEM,
|
|
@@ -24176,7 +24481,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
24176
24481
|
const canRetry = attempt < ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS - 1;
|
|
24177
24482
|
let st;
|
|
24178
24483
|
try {
|
|
24179
|
-
st =
|
|
24484
|
+
st = fs44.statSync(outAbs);
|
|
24180
24485
|
} catch {
|
|
24181
24486
|
st = void 0;
|
|
24182
24487
|
}
|
|
@@ -24198,7 +24503,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
24198
24503
|
}
|
|
24199
24504
|
let parsed;
|
|
24200
24505
|
try {
|
|
24201
|
-
parsed = JSON.parse(
|
|
24506
|
+
parsed = JSON.parse(fs44.readFileSync(outAbs, "utf-8"));
|
|
24202
24507
|
} catch (e) {
|
|
24203
24508
|
const msg = e instanceof Error ? e.message : String(e);
|
|
24204
24509
|
lastFailureMessage = `Triage output not valid JSON: ${msg}`;
|
|
@@ -24254,7 +24559,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
24254
24559
|
return { ok: false, message: lastFailureMessage, stagingPath: outAbs };
|
|
24255
24560
|
}
|
|
24256
24561
|
try {
|
|
24257
|
-
|
|
24562
|
+
fs44.writeFileSync(outAbs, `${JSON.stringify(parsed, null, 2)}
|
|
24258
24563
|
`, "utf-8");
|
|
24259
24564
|
} catch {
|
|
24260
24565
|
}
|
|
@@ -24272,7 +24577,7 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
24272
24577
|
}
|
|
24273
24578
|
let stagingParsed;
|
|
24274
24579
|
try {
|
|
24275
|
-
stagingParsed = JSON.parse(
|
|
24580
|
+
stagingParsed = JSON.parse(fs44.readFileSync(cr.stagingPath, "utf-8"));
|
|
24276
24581
|
} catch (e) {
|
|
24277
24582
|
return { ok: false, message: String(e) };
|
|
24278
24583
|
}
|
|
@@ -24288,8 +24593,8 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
24288
24593
|
if (!s.ok) {
|
|
24289
24594
|
throw new Error(s.errors.join("; "));
|
|
24290
24595
|
}
|
|
24291
|
-
|
|
24292
|
-
|
|
24596
|
+
fs44.mkdirSync(path40.dirname(routingAbs), { recursive: true });
|
|
24597
|
+
fs44.writeFileSync(routingAbs, s.json, "utf-8");
|
|
24293
24598
|
});
|
|
24294
24599
|
const routing = stagingParsed.routing;
|
|
24295
24600
|
const routingSummary = typeof stagingParsed.projectRelationSummary === "string" ? stagingParsed.projectRelationSummary : "";
|
|
@@ -24320,7 +24625,7 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
24320
24625
|
}
|
|
24321
24626
|
let triageParsed;
|
|
24322
24627
|
try {
|
|
24323
|
-
triageParsed = JSON.parse(
|
|
24628
|
+
triageParsed = JSON.parse(fs44.readFileSync(tr.stagingPath, "utf-8"));
|
|
24324
24629
|
} catch (e) {
|
|
24325
24630
|
return { ok: false, message: String(e) };
|
|
24326
24631
|
}
|
|
@@ -24337,8 +24642,8 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
24337
24642
|
if (!s.ok) {
|
|
24338
24643
|
throw new Error(s.errors.join("; "));
|
|
24339
24644
|
}
|
|
24340
|
-
|
|
24341
|
-
|
|
24645
|
+
fs44.mkdirSync(path40.dirname(triageAbs), { recursive: true });
|
|
24646
|
+
fs44.writeFileSync(triageAbs, s.json, "utf-8");
|
|
24342
24647
|
});
|
|
24343
24648
|
const decision = triageParsed.decision;
|
|
24344
24649
|
if (decision === "new_item" || decision === "enrich_existing") {
|
|
@@ -24426,7 +24731,7 @@ async function runRemediationPipelineZeroRefPass(p) {
|
|
|
24426
24731
|
}
|
|
24427
24732
|
|
|
24428
24733
|
// src/pipelines/coverage/coverageExecutionReport.ts
|
|
24429
|
-
var
|
|
24734
|
+
var fs45 = __toESM(require("fs"));
|
|
24430
24735
|
var path41 = __toESM(require("path"));
|
|
24431
24736
|
var REFERENCE_COVERAGE_EXECUTION_REPORT_BASENAME = "reference-coverage-execution-report.md";
|
|
24432
24737
|
function inlineMdText(s) {
|
|
@@ -24523,7 +24828,7 @@ function collectNoActionRowsFromRoutingDoc(doc) {
|
|
|
24523
24828
|
return rows;
|
|
24524
24829
|
}
|
|
24525
24830
|
function readRoutingDocFromDisk(routingAbs) {
|
|
24526
|
-
if (!
|
|
24831
|
+
if (!fs45.existsSync(routingAbs)) {
|
|
24527
24832
|
return {
|
|
24528
24833
|
ok: true,
|
|
24529
24834
|
doc: { schemaVersion: "1", records: {} }
|
|
@@ -24531,7 +24836,7 @@ function readRoutingDocFromDisk(routingAbs) {
|
|
|
24531
24836
|
}
|
|
24532
24837
|
let raw;
|
|
24533
24838
|
try {
|
|
24534
|
-
raw =
|
|
24839
|
+
raw = fs45.readFileSync(routingAbs, "utf-8");
|
|
24535
24840
|
} catch (e) {
|
|
24536
24841
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
24537
24842
|
}
|
|
@@ -24571,20 +24876,20 @@ async function runCoverageExecutionReport(p) {
|
|
|
24571
24876
|
}
|
|
24572
24877
|
let previous;
|
|
24573
24878
|
try {
|
|
24574
|
-
if (
|
|
24575
|
-
previous =
|
|
24879
|
+
if (fs45.existsSync(outAbs)) {
|
|
24880
|
+
previous = fs45.readFileSync(outAbs, "utf-8");
|
|
24576
24881
|
}
|
|
24577
24882
|
} catch {
|
|
24578
24883
|
previous = void 0;
|
|
24579
24884
|
}
|
|
24580
24885
|
try {
|
|
24581
|
-
|
|
24582
|
-
|
|
24886
|
+
fs45.mkdirSync(path41.dirname(outAbs), { recursive: true });
|
|
24887
|
+
fs45.writeFileSync(outAbs, md, "utf-8");
|
|
24583
24888
|
} catch (e) {
|
|
24584
24889
|
const msg = e instanceof Error ? e.message : String(e);
|
|
24585
24890
|
if (previous !== void 0) {
|
|
24586
24891
|
try {
|
|
24587
|
-
|
|
24892
|
+
fs45.writeFileSync(outAbs, previous, "utf-8");
|
|
24588
24893
|
} catch {
|
|
24589
24894
|
}
|
|
24590
24895
|
}
|
|
@@ -24595,7 +24900,7 @@ async function runCoverageExecutionReport(p) {
|
|
|
24595
24900
|
}
|
|
24596
24901
|
|
|
24597
24902
|
// src/gluecharm/minimalGluecharmLayout.ts
|
|
24598
|
-
var
|
|
24903
|
+
var fs46 = __toESM(require("node:fs"));
|
|
24599
24904
|
var path42 = __toESM(require("node:path"));
|
|
24600
24905
|
var MINIMAL_GLUECHARM_RELATIVE_DIRS = [
|
|
24601
24906
|
[".gluecharm", "docs", "srs"],
|
|
@@ -24608,7 +24913,7 @@ function ensureMinimalGluecharmLayoutNode(repoRootAbs) {
|
|
|
24608
24913
|
for (const segments of MINIMAL_GLUECHARM_RELATIVE_DIRS) {
|
|
24609
24914
|
const dir = path42.join(root, ...segments);
|
|
24610
24915
|
try {
|
|
24611
|
-
|
|
24916
|
+
fs46.mkdirSync(dir, { recursive: true });
|
|
24612
24917
|
} catch (e) {
|
|
24613
24918
|
const err = e;
|
|
24614
24919
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -24990,13 +25295,13 @@ function buildFactoryDepsHeadless(input) {
|
|
|
24990
25295
|
},
|
|
24991
25296
|
runPrepareAnalysisWorktree: async (resume) => {
|
|
24992
25297
|
if (resume) {
|
|
24993
|
-
if (adHocWorktree &&
|
|
25298
|
+
if (adHocWorktree && fs47.existsSync(path43.join(adHocWorktree.path, ".git"))) {
|
|
24994
25299
|
return { ok: true };
|
|
24995
25300
|
}
|
|
24996
25301
|
const snap = readAnalysisWorkspaceSnapshot(storageContext);
|
|
24997
25302
|
const wtPath = snap?.adHocWorktreePath?.trim();
|
|
24998
25303
|
const repo = snap?.adHocRepositoryRoot?.trim() || repoRoot;
|
|
24999
|
-
if (wtPath &&
|
|
25304
|
+
if (wtPath && fs47.existsSync(path43.join(wtPath, ".git"))) {
|
|
25000
25305
|
adHocWorktree = attachWorktreeHandle(wtPath, repo);
|
|
25001
25306
|
macroSourceBranch = snap?.adHocSourceBranchAtCreation;
|
|
25002
25307
|
macroFinalize = () => {
|
|
@@ -25221,7 +25526,7 @@ function stderrLinesForFactoryFailures(failures, exitCode) {
|
|
|
25221
25526
|
var path48 = __toESM(require("node:path"));
|
|
25222
25527
|
|
|
25223
25528
|
// src/factory/updateContext/updateContextBaseline.ts
|
|
25224
|
-
var
|
|
25529
|
+
var fs48 = __toESM(require("node:fs"));
|
|
25225
25530
|
var path44 = __toESM(require("node:path"));
|
|
25226
25531
|
function isValidIso(s) {
|
|
25227
25532
|
const t = Date.parse(s);
|
|
@@ -25232,7 +25537,7 @@ function maxMtimeRegularFilesUnderDir(dirAbs) {
|
|
|
25232
25537
|
const walk = (d) => {
|
|
25233
25538
|
let entries;
|
|
25234
25539
|
try {
|
|
25235
|
-
entries =
|
|
25540
|
+
entries = fs48.readdirSync(d, { withFileTypes: true });
|
|
25236
25541
|
} catch {
|
|
25237
25542
|
return;
|
|
25238
25543
|
}
|
|
@@ -25242,7 +25547,7 @@ function maxMtimeRegularFilesUnderDir(dirAbs) {
|
|
|
25242
25547
|
walk(p);
|
|
25243
25548
|
} else if (e.isFile()) {
|
|
25244
25549
|
try {
|
|
25245
|
-
const st =
|
|
25550
|
+
const st = fs48.statSync(p);
|
|
25246
25551
|
const m = st.mtimeMs;
|
|
25247
25552
|
if (best === null || m > best) {
|
|
25248
25553
|
best = m;
|
|
@@ -25264,7 +25569,7 @@ function resolveUpdateContextBaseline(repoRootAbs, repoConfig) {
|
|
|
25264
25569
|
return { baselineIsoUtc: new Date(last).toISOString(), source: "lastRunAt" };
|
|
25265
25570
|
}
|
|
25266
25571
|
const ctxDir = path44.join(repoRootAbs, ".gluecharm", "context");
|
|
25267
|
-
if (!
|
|
25572
|
+
if (!fs48.existsSync(ctxDir)) {
|
|
25268
25573
|
return null;
|
|
25269
25574
|
}
|
|
25270
25575
|
const maxMs = maxMtimeRegularFilesUnderDir(ctxDir);
|
|
@@ -25287,7 +25592,7 @@ function persistUpdateContextLastRunAt(repoRootAbs, isoUtc) {
|
|
|
25287
25592
|
|
|
25288
25593
|
// src/factory/updateContext/updateContextGitWindow.ts
|
|
25289
25594
|
var import_node_child_process3 = require("node:child_process");
|
|
25290
|
-
var
|
|
25595
|
+
var fs49 = __toESM(require("node:fs"));
|
|
25291
25596
|
var path45 = __toESM(require("node:path"));
|
|
25292
25597
|
var GIT_ENV = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
25293
25598
|
function gitLines(repoRootAbs, args) {
|
|
@@ -25313,7 +25618,7 @@ function parseGitLogIso(line) {
|
|
|
25313
25618
|
}
|
|
25314
25619
|
function discoverCommitWindowAndTouchedPaths(repoRootAbs, baselineIsoUtc) {
|
|
25315
25620
|
const root = path45.resolve(repoRootAbs);
|
|
25316
|
-
if (!
|
|
25621
|
+
if (!fs49.existsSync(path45.join(root, ".git"))) {
|
|
25317
25622
|
return { ok: false, error: "Not a git repository (missing .git)." };
|
|
25318
25623
|
}
|
|
25319
25624
|
const baselineMs = Date.parse(baselineIsoUtc);
|
|
@@ -25378,7 +25683,7 @@ function filterPathsExistingInWorktree(worktreeRootAbs, pathsPosix) {
|
|
|
25378
25683
|
const rel = p.replace(/\\/g, "/");
|
|
25379
25684
|
const abs = path45.join(root, ...rel.split("/"));
|
|
25380
25685
|
try {
|
|
25381
|
-
if (
|
|
25686
|
+
if (fs49.existsSync(abs) && fs49.statSync(abs).isFile()) {
|
|
25382
25687
|
out.push(rel);
|
|
25383
25688
|
}
|
|
25384
25689
|
} catch {
|
|
@@ -25388,7 +25693,7 @@ function filterPathsExistingInWorktree(worktreeRootAbs, pathsPosix) {
|
|
|
25388
25693
|
}
|
|
25389
25694
|
|
|
25390
25695
|
// src/factory/updateContext/updateContextReport.ts
|
|
25391
|
-
var
|
|
25696
|
+
var fs50 = __toESM(require("node:fs"));
|
|
25392
25697
|
var path46 = __toESM(require("node:path"));
|
|
25393
25698
|
var CHANGES_SINCE_DATE_BASENAME = "changes-since-date.md";
|
|
25394
25699
|
function renderChangesSinceDateMarkdown(p) {
|
|
@@ -25430,9 +25735,9 @@ function renderChangesSinceDateMarkdown(p) {
|
|
|
25430
25735
|
}
|
|
25431
25736
|
function writeChangesSinceDateReport(contextDirAbs, body) {
|
|
25432
25737
|
try {
|
|
25433
|
-
|
|
25738
|
+
fs50.mkdirSync(contextDirAbs, { recursive: true });
|
|
25434
25739
|
const target = path46.join(contextDirAbs, CHANGES_SINCE_DATE_BASENAME);
|
|
25435
|
-
|
|
25740
|
+
fs50.writeFileSync(target, body, "utf-8");
|
|
25436
25741
|
return { ok: true };
|
|
25437
25742
|
} catch (e) {
|
|
25438
25743
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
@@ -25440,13 +25745,13 @@ function writeChangesSinceDateReport(contextDirAbs, body) {
|
|
|
25440
25745
|
}
|
|
25441
25746
|
|
|
25442
25747
|
// src/factory/updateContext/updateContextSeedCheck.ts
|
|
25443
|
-
var
|
|
25748
|
+
var fs51 = __toESM(require("node:fs"));
|
|
25444
25749
|
var path47 = __toESM(require("node:path"));
|
|
25445
25750
|
var INDEX_BASENAME = "index-application-context.json";
|
|
25446
25751
|
var CHANGES_REPORT = "changes-since-date.md";
|
|
25447
25752
|
function tryParseJsonFile(abs) {
|
|
25448
25753
|
try {
|
|
25449
|
-
const raw =
|
|
25754
|
+
const raw = fs51.readFileSync(abs, "utf-8");
|
|
25450
25755
|
JSON.parse(raw);
|
|
25451
25756
|
return true;
|
|
25452
25757
|
} catch {
|
|
@@ -25454,16 +25759,16 @@ function tryParseJsonFile(abs) {
|
|
|
25454
25759
|
}
|
|
25455
25760
|
}
|
|
25456
25761
|
function isWorktreeContextSeeded(contextDirAbs) {
|
|
25457
|
-
if (!
|
|
25762
|
+
if (!fs51.existsSync(contextDirAbs)) {
|
|
25458
25763
|
return false;
|
|
25459
25764
|
}
|
|
25460
25765
|
const indexAbs = path47.join(contextDirAbs, INDEX_BASENAME);
|
|
25461
|
-
if (
|
|
25766
|
+
if (fs51.existsSync(indexAbs) && fs51.statSync(indexAbs).isFile() && tryParseJsonFile(indexAbs)) {
|
|
25462
25767
|
return true;
|
|
25463
25768
|
}
|
|
25464
25769
|
let names;
|
|
25465
25770
|
try {
|
|
25466
|
-
names =
|
|
25771
|
+
names = fs51.readdirSync(contextDirAbs);
|
|
25467
25772
|
} catch {
|
|
25468
25773
|
return false;
|
|
25469
25774
|
}
|
|
@@ -25477,7 +25782,7 @@ function isWorktreeContextSeeded(contextDirAbs) {
|
|
|
25477
25782
|
}
|
|
25478
25783
|
const p = path47.join(contextDirAbs, name);
|
|
25479
25784
|
try {
|
|
25480
|
-
if (
|
|
25785
|
+
if (fs51.statSync(p).isFile()) {
|
|
25481
25786
|
distinct.add(name);
|
|
25482
25787
|
}
|
|
25483
25788
|
} catch {
|
|
@@ -25779,11 +26084,11 @@ async function runUpdateContextFactory(deps) {
|
|
|
25779
26084
|
}
|
|
25780
26085
|
|
|
25781
26086
|
// src/factory/contextDrift/runContextDriftFactory.ts
|
|
25782
|
-
var
|
|
26087
|
+
var fs57 = __toESM(require("node:fs"));
|
|
25783
26088
|
var path53 = __toESM(require("node:path"));
|
|
25784
26089
|
|
|
25785
26090
|
// src/factory/contextDrift/contextDriftManifest.ts
|
|
25786
|
-
var
|
|
26091
|
+
var fs52 = __toESM(require("node:fs"));
|
|
25787
26092
|
var path49 = __toESM(require("node:path"));
|
|
25788
26093
|
var MAX_REFERENCE_BYTES = 256 * 1024;
|
|
25789
26094
|
var MAX_EVIDENCE_FILES = 300;
|
|
@@ -25792,7 +26097,7 @@ var MAX_EXCERPT = 4e3;
|
|
|
25792
26097
|
function readFileLimited(abs, maxBytes) {
|
|
25793
26098
|
let buf;
|
|
25794
26099
|
try {
|
|
25795
|
-
buf =
|
|
26100
|
+
buf = fs52.readFileSync(abs);
|
|
25796
26101
|
} catch {
|
|
25797
26102
|
return { text: "", truncated: false };
|
|
25798
26103
|
}
|
|
@@ -25805,14 +26110,14 @@ function collectEvidencePaths(repoRoot) {
|
|
|
25805
26110
|
const roots = ["src", "test", "tests", "packages", ".gluecharm", "scripts"];
|
|
25806
26111
|
for (const rel of roots) {
|
|
25807
26112
|
const abs = path49.join(repoRoot, rel);
|
|
25808
|
-
if (!
|
|
26113
|
+
if (!fs52.existsSync(abs)) {
|
|
25809
26114
|
continue;
|
|
25810
26115
|
}
|
|
25811
26116
|
walkFiles(abs, repoRoot, out, 0);
|
|
25812
26117
|
}
|
|
25813
26118
|
for (const leaf of ["package.json", "tsconfig.json"]) {
|
|
25814
26119
|
const abs = path49.join(repoRoot, leaf);
|
|
25815
|
-
if (
|
|
26120
|
+
if (fs52.existsSync(abs) && fs52.statSync(abs).isFile()) {
|
|
25816
26121
|
const r = path49.relative(repoRoot, abs).split(path49.sep).join("/");
|
|
25817
26122
|
out.push(r);
|
|
25818
26123
|
}
|
|
@@ -25830,7 +26135,7 @@ function walkFiles(dir, repoRoot, out, depth) {
|
|
|
25830
26135
|
}
|
|
25831
26136
|
let entries;
|
|
25832
26137
|
try {
|
|
25833
|
-
entries =
|
|
26138
|
+
entries = fs52.readdirSync(dir, { withFileTypes: true });
|
|
25834
26139
|
} catch {
|
|
25835
26140
|
return;
|
|
25836
26141
|
}
|
|
@@ -25867,7 +26172,7 @@ function buildComparisonManifest(args) {
|
|
|
25867
26172
|
const evidenceFiles = [];
|
|
25868
26173
|
for (const rel of evidencePathsTrimmed) {
|
|
25869
26174
|
const abs = path49.join(args.worktreeRoot, ...rel.split("/"));
|
|
25870
|
-
const st =
|
|
26175
|
+
const st = fs52.existsSync(abs) ? fs52.statSync(abs) : null;
|
|
25871
26176
|
const size = st && st.isFile() ? st.size : 0;
|
|
25872
26177
|
const { text, truncated } = readFileLimited(abs, MAX_EVIDENCE_READ);
|
|
25873
26178
|
const excerpt = truncated ? `${text.slice(0, MAX_EXCERPT)}
|
|
@@ -25889,7 +26194,7 @@ function buildComparisonManifest(args) {
|
|
|
25889
26194
|
}
|
|
25890
26195
|
|
|
25891
26196
|
// src/factory/contextDrift/contextDriftAgent.ts
|
|
25892
|
-
var
|
|
26197
|
+
var fs53 = __toESM(require("node:fs"));
|
|
25893
26198
|
var path50 = __toESM(require("node:path"));
|
|
25894
26199
|
|
|
25895
26200
|
// src/factory/contextDrift/contextDriftPayload.ts
|
|
@@ -26036,16 +26341,16 @@ function buildDriftPrompt(args) {
|
|
|
26036
26341
|
}
|
|
26037
26342
|
async function runDriftComparisonOpenCode(args) {
|
|
26038
26343
|
const runDir = path50.join(args.worktreeRoot, ".opencode", "_run");
|
|
26039
|
-
|
|
26344
|
+
fs53.mkdirSync(runDir, { recursive: true });
|
|
26040
26345
|
const manifestPath = path50.join(runDir, "context-drift-manifest.json");
|
|
26041
26346
|
const outputPath = path50.join(runDir, "context-drift-payload.json");
|
|
26042
|
-
|
|
26347
|
+
fs53.writeFileSync(manifestPath, `${JSON.stringify(args.manifestObject, null, 2)}
|
|
26043
26348
|
`, "utf8");
|
|
26044
|
-
if (
|
|
26045
|
-
|
|
26349
|
+
if (fs53.existsSync(outputPath)) {
|
|
26350
|
+
fs53.unlinkSync(outputPath);
|
|
26046
26351
|
}
|
|
26047
26352
|
const promptPath = path50.join(runDir, `context-drift-${Date.now()}.prompt.txt`);
|
|
26048
|
-
|
|
26353
|
+
fs53.writeFileSync(
|
|
26049
26354
|
promptPath,
|
|
26050
26355
|
buildDriftPrompt({
|
|
26051
26356
|
worktreeRoot: args.worktreeRoot,
|
|
@@ -26087,7 +26392,7 @@ async function runDriftComparisonOpenCode(args) {
|
|
|
26087
26392
|
}
|
|
26088
26393
|
let raw;
|
|
26089
26394
|
try {
|
|
26090
|
-
const txt =
|
|
26395
|
+
const txt = fs53.readFileSync(outputPath, "utf8");
|
|
26091
26396
|
raw = JSON.parse(txt);
|
|
26092
26397
|
} catch (e) {
|
|
26093
26398
|
return {
|
|
@@ -26104,7 +26409,7 @@ async function runDriftComparisonOpenCode(args) {
|
|
|
26104
26409
|
|
|
26105
26410
|
// src/factory/contextDrift/contextDriftPaths.ts
|
|
26106
26411
|
var crypto2 = __toESM(require("node:crypto"));
|
|
26107
|
-
var
|
|
26412
|
+
var fs54 = __toESM(require("node:fs"));
|
|
26108
26413
|
var path51 = __toESM(require("node:path"));
|
|
26109
26414
|
var DRIFT_CONTEXT_SUBDIR = path51.join(".gluecharm", "context", "drift");
|
|
26110
26415
|
function sanitizeSlug(raw) {
|
|
@@ -26143,7 +26448,7 @@ function maybeDedupeSlug(slug, referenceRelPosix) {
|
|
|
26143
26448
|
function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
26144
26449
|
let st;
|
|
26145
26450
|
try {
|
|
26146
|
-
st =
|
|
26451
|
+
st = fs54.statSync(referenceAbsInWorktree);
|
|
26147
26452
|
} catch {
|
|
26148
26453
|
return { ok: false, error: `Reference path not found in analysis worktree: ${referenceAbsInWorktree}` };
|
|
26149
26454
|
}
|
|
@@ -26164,7 +26469,7 @@ function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
|
26164
26469
|
}
|
|
26165
26470
|
let entries;
|
|
26166
26471
|
try {
|
|
26167
|
-
entries =
|
|
26472
|
+
entries = fs54.readdirSync(dir, { withFileTypes: true });
|
|
26168
26473
|
} catch {
|
|
26169
26474
|
return;
|
|
26170
26475
|
}
|
|
@@ -26189,7 +26494,7 @@ function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
|
26189
26494
|
}
|
|
26190
26495
|
function pickReferenceRootDocument(args) {
|
|
26191
26496
|
if (args.indexOverrideAbs) {
|
|
26192
|
-
if (!
|
|
26497
|
+
if (!fs54.existsSync(args.indexOverrideAbs) || !args.indexOverrideAbs.endsWith(".md")) {
|
|
26193
26498
|
return { ok: false, error: "--index must point to an existing .md file under the repo." };
|
|
26194
26499
|
}
|
|
26195
26500
|
return { ok: true, path: args.indexOverrideAbs };
|
|
@@ -26200,7 +26505,7 @@ function pickReferenceRootDocument(args) {
|
|
|
26200
26505
|
const dir = args.referenceAbsInWorktree;
|
|
26201
26506
|
for (const name of ["index.md", "README.md"]) {
|
|
26202
26507
|
const p = path51.join(dir, name);
|
|
26203
|
-
if (
|
|
26508
|
+
if (fs54.existsSync(p) && fs54.statSync(p).isFile()) {
|
|
26204
26509
|
return { ok: true, path: p };
|
|
26205
26510
|
}
|
|
26206
26511
|
}
|
|
@@ -26217,13 +26522,13 @@ function toPosixPath(p) {
|
|
|
26217
26522
|
}
|
|
26218
26523
|
|
|
26219
26524
|
// src/factory/contextDrift/contextDriftIndex.ts
|
|
26220
|
-
var
|
|
26525
|
+
var fs55 = __toESM(require("node:fs"));
|
|
26221
26526
|
var START = "<!-- easyspecs-drift-links:start -->";
|
|
26222
26527
|
var END = "<!-- easyspecs-drift-links:end -->";
|
|
26223
26528
|
function patchReferenceIndexWithDriftLink(args) {
|
|
26224
26529
|
let body;
|
|
26225
26530
|
try {
|
|
26226
|
-
body =
|
|
26531
|
+
body = fs55.readFileSync(args.referenceRootAbsolute, "utf8");
|
|
26227
26532
|
} catch (e) {
|
|
26228
26533
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
26229
26534
|
}
|
|
@@ -26244,7 +26549,7 @@ ${block}
|
|
|
26244
26549
|
`;
|
|
26245
26550
|
}
|
|
26246
26551
|
try {
|
|
26247
|
-
|
|
26552
|
+
fs55.writeFileSync(args.referenceRootAbsolute, next, "utf8");
|
|
26248
26553
|
} catch (e) {
|
|
26249
26554
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
26250
26555
|
}
|
|
@@ -26255,13 +26560,13 @@ function escapeRe(s) {
|
|
|
26255
26560
|
}
|
|
26256
26561
|
|
|
26257
26562
|
// src/factory/contextDrift/contextDriftPromote.ts
|
|
26258
|
-
var
|
|
26563
|
+
var fs56 = __toESM(require("node:fs"));
|
|
26259
26564
|
var path52 = __toESM(require("node:path"));
|
|
26260
26565
|
function copyWorktreeFileToWorkspace(args) {
|
|
26261
26566
|
const src = path52.join(args.worktreeRoot, ...args.relativePosix.split("/"));
|
|
26262
26567
|
const dest = path52.join(args.workspaceRoot, ...args.relativePosix.split("/"));
|
|
26263
|
-
|
|
26264
|
-
|
|
26568
|
+
fs56.mkdirSync(path52.dirname(dest), { recursive: true });
|
|
26569
|
+
fs56.copyFileSync(src, dest);
|
|
26265
26570
|
}
|
|
26266
26571
|
|
|
26267
26572
|
// src/factory/contextDrift/runContextDriftFactory.ts
|
|
@@ -26280,7 +26585,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26280
26585
|
};
|
|
26281
26586
|
}
|
|
26282
26587
|
const refAbsWorkspace = resolved.abs;
|
|
26283
|
-
if (!
|
|
26588
|
+
if (!fs57.existsSync(refAbsWorkspace)) {
|
|
26284
26589
|
return {
|
|
26285
26590
|
exitOk: false,
|
|
26286
26591
|
ok: false,
|
|
@@ -26293,7 +26598,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26293
26598
|
let indexOverrideAbsWorkspace;
|
|
26294
26599
|
if (deps.indexOverrideArg?.trim()) {
|
|
26295
26600
|
const ir = resolveInsideRepo(deps.repoRootAbs, deps.indexOverrideArg.trim());
|
|
26296
|
-
if (!ir.ok || !
|
|
26601
|
+
if (!ir.ok || !fs57.existsSync(ir.abs)) {
|
|
26297
26602
|
return {
|
|
26298
26603
|
exitOk: false,
|
|
26299
26604
|
ok: false,
|
|
@@ -26311,7 +26616,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26311
26616
|
ok: true,
|
|
26312
26617
|
code: "DRY_RUN",
|
|
26313
26618
|
...baseMeta,
|
|
26314
|
-
referenceRootDocument: toPosixPath(path53.relative(deps.repoRootAbs, refAbsWorkspace)) + (
|
|
26619
|
+
referenceRootDocument: toPosixPath(path53.relative(deps.repoRootAbs, refAbsWorkspace)) + (fs57.statSync(refAbsWorkspace).isDirectory() ? "/" : ""),
|
|
26315
26620
|
driftReportPath: null,
|
|
26316
26621
|
analysisWorktreeRoot: "",
|
|
26317
26622
|
promoted: false,
|
|
@@ -26380,7 +26685,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26380
26685
|
}
|
|
26381
26686
|
const indexWt = indexOverrideAbsWorkspace ? path53.join(wt, ...path53.relative(deps.repoRootAbs, indexOverrideAbsWorkspace).split(path53.sep)) : void 0;
|
|
26382
26687
|
const rootPick = pickReferenceRootDocument({
|
|
26383
|
-
referencePathIsFile:
|
|
26688
|
+
referencePathIsFile: fs57.statSync(refAbsWt).isFile(),
|
|
26384
26689
|
referenceAbsInWorktree: refAbsWt,
|
|
26385
26690
|
bundleFiles: bundle.bundleFiles,
|
|
26386
26691
|
indexOverrideAbs: indexWt
|
|
@@ -26407,7 +26712,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26407
26712
|
slug = maybeDedupeSlug(slug, refRel);
|
|
26408
26713
|
const driftBase = driftFilename(slug, runDate);
|
|
26409
26714
|
const driftDirWt = path53.join(wt, DRIFT_CONTEXT_SUBDIR);
|
|
26410
|
-
|
|
26715
|
+
fs57.mkdirSync(driftDirWt, { recursive: true });
|
|
26411
26716
|
const driftAbsWt = path53.join(driftDirWt, driftBase);
|
|
26412
26717
|
let payload;
|
|
26413
26718
|
if (deps.testOnlyFixturePayload) {
|
|
@@ -26444,7 +26749,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26444
26749
|
manifestTruncation: manifest.truncation
|
|
26445
26750
|
});
|
|
26446
26751
|
try {
|
|
26447
|
-
|
|
26752
|
+
fs57.writeFileSync(driftAbsWt, md, "utf8");
|
|
26448
26753
|
} catch (e) {
|
|
26449
26754
|
finalizeWt?.();
|
|
26450
26755
|
return {
|
|
@@ -26523,7 +26828,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26523
26828
|
}
|
|
26524
26829
|
|
|
26525
26830
|
// src/analysis/coordinationDuplicatesDiagnosis.ts
|
|
26526
|
-
var
|
|
26831
|
+
var fs58 = __toESM(require("fs"));
|
|
26527
26832
|
var path54 = __toESM(require("path"));
|
|
26528
26833
|
var import__7 = __toESM(require__());
|
|
26529
26834
|
var COORDINATION_DUPLICATES_REPORT_BASENAME = "coordination-duplicates-report.json";
|
|
@@ -26560,11 +26865,11 @@ function looksLikeCoordinationDetailMarkdownBasename(basename17) {
|
|
|
26560
26865
|
}
|
|
26561
26866
|
function loadRawFeatureRows(contextDirAbs) {
|
|
26562
26867
|
const p = path54.join(contextDirAbs, "features-list.json");
|
|
26563
|
-
if (!
|
|
26868
|
+
if (!fs58.existsSync(p)) {
|
|
26564
26869
|
return [];
|
|
26565
26870
|
}
|
|
26566
26871
|
try {
|
|
26567
|
-
const raw = stripUtf8Bom6(
|
|
26872
|
+
const raw = stripUtf8Bom6(fs58.readFileSync(p, "utf-8"));
|
|
26568
26873
|
const doc = JSON.parse(raw);
|
|
26569
26874
|
return Array.isArray(doc.features) ? doc.features : [];
|
|
26570
26875
|
} catch {
|
|
@@ -26599,7 +26904,7 @@ function findOrphanCoordinationMarkdown(contextDirAbs) {
|
|
|
26599
26904
|
const featureRows = loadRawFeatureRows(contextDirAbs);
|
|
26600
26905
|
let dirents;
|
|
26601
26906
|
try {
|
|
26602
|
-
dirents =
|
|
26907
|
+
dirents = fs58.readdirSync(contextDirAbs, { withFileTypes: true });
|
|
26603
26908
|
} catch {
|
|
26604
26909
|
return [];
|
|
26605
26910
|
}
|
|
@@ -26853,13 +27158,13 @@ function buildCoordinationDuplicatesReport(input) {
|
|
|
26853
27158
|
const duplicateGroups = [];
|
|
26854
27159
|
for (const entry of COORDINATION_LIST_SCAN_ENTRIES) {
|
|
26855
27160
|
const filePath = path54.join(input.contextDirAbsolute, entry.basename);
|
|
26856
|
-
if (!
|
|
27161
|
+
if (!fs58.existsSync(filePath)) {
|
|
26857
27162
|
lists.push({ basename: entry.basename, status: "missing" });
|
|
26858
27163
|
continue;
|
|
26859
27164
|
}
|
|
26860
27165
|
let raw;
|
|
26861
27166
|
try {
|
|
26862
|
-
raw = stripUtf8Bom6(
|
|
27167
|
+
raw = stripUtf8Bom6(fs58.readFileSync(filePath, "utf-8"));
|
|
26863
27168
|
} catch (e) {
|
|
26864
27169
|
lists.push({
|
|
26865
27170
|
basename: entry.basename,
|
|
@@ -26908,7 +27213,7 @@ function validateReportData(data) {
|
|
|
26908
27213
|
if (!validateReportCompiled) {
|
|
26909
27214
|
const ajv2 = new import__7.default({ allErrors: true, strict: false });
|
|
26910
27215
|
const schemaPath = path54.join(resolveContextListSchemasDir(), "coordination-duplicates-report.schema.json");
|
|
26911
|
-
const schemaRaw = stripUtf8Bom6(
|
|
27216
|
+
const schemaRaw = stripUtf8Bom6(fs58.readFileSync(schemaPath, "utf-8"));
|
|
26912
27217
|
validateReportCompiled = ajv2.compile(JSON.parse(schemaRaw));
|
|
26913
27218
|
}
|
|
26914
27219
|
if (validateReportCompiled(data)) {
|
|
@@ -26931,15 +27236,15 @@ function runCoordinationDuplicatesDiagnosis(input) {
|
|
|
26931
27236
|
`;
|
|
26932
27237
|
const tmp = `${outPath}.tmp.${process.pid}`;
|
|
26933
27238
|
try {
|
|
26934
|
-
|
|
27239
|
+
fs58.writeFileSync(tmp, payload, "utf-8");
|
|
26935
27240
|
} catch (e) {
|
|
26936
27241
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
26937
27242
|
}
|
|
26938
27243
|
try {
|
|
26939
|
-
|
|
27244
|
+
fs58.renameSync(tmp, outPath);
|
|
26940
27245
|
} catch (e) {
|
|
26941
27246
|
try {
|
|
26942
|
-
|
|
27247
|
+
fs58.unlinkSync(tmp);
|
|
26943
27248
|
} catch {
|
|
26944
27249
|
}
|
|
26945
27250
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
@@ -26973,7 +27278,7 @@ function runCoordinationDuplicatesDiagnosis(input) {
|
|
|
26973
27278
|
}
|
|
26974
27279
|
|
|
26975
27280
|
// src/pipelines/download/downloadPipeline.ts
|
|
26976
|
-
var
|
|
27281
|
+
var fs59 = __toESM(require("node:fs"));
|
|
26977
27282
|
var path55 = __toESM(require("node:path"));
|
|
26978
27283
|
var SRS_DISCOVERY_BATCH_GET_CHUNK_SIZE = 200;
|
|
26979
27284
|
function isRecord7(v) {
|
|
@@ -27079,19 +27384,19 @@ function chunkIds(ids, size) {
|
|
|
27079
27384
|
return out;
|
|
27080
27385
|
}
|
|
27081
27386
|
function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
27082
|
-
if (!
|
|
27387
|
+
if (!fs59.existsSync(contextDirAbs) || !fs59.statSync(contextDirAbs).isDirectory()) {
|
|
27083
27388
|
return { filesRemoved: 0 };
|
|
27084
27389
|
}
|
|
27085
27390
|
const preserveAbs = path55.resolve(contextDirAbs, UPLOAD_TARGET_FILENAME);
|
|
27086
27391
|
const preserveSet = /* @__PURE__ */ new Set();
|
|
27087
|
-
if (
|
|
27392
|
+
if (fs59.existsSync(preserveAbs) && fs59.statSync(preserveAbs).isFile()) {
|
|
27088
27393
|
preserveSet.add(preserveAbs);
|
|
27089
27394
|
}
|
|
27090
27395
|
let filesRemoved = 0;
|
|
27091
27396
|
const walkRm = (dir) => {
|
|
27092
27397
|
let entries;
|
|
27093
27398
|
try {
|
|
27094
|
-
entries =
|
|
27399
|
+
entries = fs59.readdirSync(dir, { withFileTypes: true });
|
|
27095
27400
|
} catch {
|
|
27096
27401
|
return;
|
|
27097
27402
|
}
|
|
@@ -27100,7 +27405,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
|
27100
27405
|
if (e.isDirectory()) {
|
|
27101
27406
|
walkRm(full);
|
|
27102
27407
|
try {
|
|
27103
|
-
|
|
27408
|
+
fs59.rmdirSync(full);
|
|
27104
27409
|
} catch {
|
|
27105
27410
|
}
|
|
27106
27411
|
} else if (e.isFile()) {
|
|
@@ -27109,7 +27414,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
|
27109
27414
|
continue;
|
|
27110
27415
|
}
|
|
27111
27416
|
try {
|
|
27112
|
-
|
|
27417
|
+
fs59.unlinkSync(abs);
|
|
27113
27418
|
filesRemoved += 1;
|
|
27114
27419
|
} catch {
|
|
27115
27420
|
}
|
|
@@ -27188,15 +27493,15 @@ async function runDownloadPipeline(opts) {
|
|
|
27188
27493
|
failed.push({ id, name, message: "Unsafe or invalid name for local path." });
|
|
27189
27494
|
continue;
|
|
27190
27495
|
}
|
|
27191
|
-
|
|
27192
|
-
const exists =
|
|
27496
|
+
fs59.mkdirSync(path55.dirname(outAbs), { recursive: true });
|
|
27497
|
+
const exists = fs59.existsSync(outAbs);
|
|
27193
27498
|
if (exists && !opts.force && !opts.replaceFromCloud) {
|
|
27194
27499
|
skipped += 1;
|
|
27195
27500
|
log?.(`[pipeline:download] skip existing ${name} (use --force to overwrite).`);
|
|
27196
27501
|
continue;
|
|
27197
27502
|
}
|
|
27198
27503
|
try {
|
|
27199
|
-
|
|
27504
|
+
fs59.writeFileSync(outAbs, bodyText, "utf8");
|
|
27200
27505
|
downloaded += 1;
|
|
27201
27506
|
succeededIds[outAbs] = id;
|
|
27202
27507
|
} catch (e) {
|
|
@@ -27367,7 +27672,7 @@ function createAuthenticatedRequestJson(deps) {
|
|
|
27367
27672
|
}
|
|
27368
27673
|
|
|
27369
27674
|
// src/cli/cliSession.ts
|
|
27370
|
-
var
|
|
27675
|
+
var fs60 = __toESM(require("node:fs"));
|
|
27371
27676
|
var os6 = __toESM(require("node:os"));
|
|
27372
27677
|
var path56 = __toESM(require("node:path"));
|
|
27373
27678
|
function defaultSessionPath() {
|
|
@@ -27412,10 +27717,10 @@ function effectiveCliSessionPath() {
|
|
|
27412
27717
|
function readCliSession() {
|
|
27413
27718
|
const p = effectiveCliSessionPath();
|
|
27414
27719
|
try {
|
|
27415
|
-
if (!
|
|
27720
|
+
if (!fs60.existsSync(p)) {
|
|
27416
27721
|
return void 0;
|
|
27417
27722
|
}
|
|
27418
|
-
const j = JSON.parse(
|
|
27723
|
+
const j = JSON.parse(fs60.readFileSync(p, "utf8"));
|
|
27419
27724
|
const apiBaseUrl = typeof j.apiBaseUrl === "string" ? j.apiBaseUrl.trim() : "";
|
|
27420
27725
|
const accessToken = typeof j.accessToken === "string" ? j.accessToken : "";
|
|
27421
27726
|
const refreshToken = typeof j.refreshToken === "string" ? j.refreshToken : "";
|
|
@@ -27429,20 +27734,20 @@ function readCliSession() {
|
|
|
27429
27734
|
}
|
|
27430
27735
|
function writeCliSession(s) {
|
|
27431
27736
|
const p = effectiveCliSessionPath();
|
|
27432
|
-
|
|
27433
|
-
|
|
27737
|
+
fs60.mkdirSync(path56.dirname(p), { recursive: true });
|
|
27738
|
+
fs60.writeFileSync(p, `${JSON.stringify(s, null, 2)}
|
|
27434
27739
|
`, "utf8");
|
|
27435
27740
|
}
|
|
27436
27741
|
function clearCliSession() {
|
|
27437
27742
|
const p = effectiveCliSessionPath();
|
|
27438
27743
|
try {
|
|
27439
|
-
|
|
27744
|
+
fs60.unlinkSync(p);
|
|
27440
27745
|
} catch {
|
|
27441
27746
|
}
|
|
27442
27747
|
}
|
|
27443
27748
|
|
|
27444
27749
|
// src/analysis/acePendingTraces.ts
|
|
27445
|
-
var
|
|
27750
|
+
var fs61 = __toESM(require("fs"));
|
|
27446
27751
|
var path57 = __toESM(require("path"));
|
|
27447
27752
|
function normalizeAceTraceRelativePath(rel) {
|
|
27448
27753
|
return rel.split(/[/\\]/).join("/");
|
|
@@ -27450,12 +27755,12 @@ function normalizeAceTraceRelativePath(rel) {
|
|
|
27450
27755
|
function readCompletedTraceRelativePaths(contextDir2) {
|
|
27451
27756
|
const set = /* @__PURE__ */ new Set();
|
|
27452
27757
|
const jsonlPath = aceConsolidatedSessionsJsonlPath(contextDir2);
|
|
27453
|
-
if (!
|
|
27758
|
+
if (!fs61.existsSync(jsonlPath)) {
|
|
27454
27759
|
return set;
|
|
27455
27760
|
}
|
|
27456
27761
|
let raw;
|
|
27457
27762
|
try {
|
|
27458
|
-
raw =
|
|
27763
|
+
raw = fs61.readFileSync(jsonlPath, "utf8");
|
|
27459
27764
|
} catch {
|
|
27460
27765
|
return set;
|
|
27461
27766
|
}
|
|
@@ -27486,7 +27791,7 @@ function readCompletedTraceRelativePaths(contextDir2) {
|
|
|
27486
27791
|
}
|
|
27487
27792
|
function listPendingAceTraceFiles(contextDir2, worktreeRoot) {
|
|
27488
27793
|
const traceSchema = opencodeAceSchemaPath(worktreeRoot, ACE_SCHEMA_TRACE);
|
|
27489
|
-
if (!
|
|
27794
|
+
if (!fs61.existsSync(traceSchema)) {
|
|
27490
27795
|
return [];
|
|
27491
27796
|
}
|
|
27492
27797
|
const completed = readCompletedTraceRelativePaths(contextDir2);
|
|
@@ -27790,7 +28095,9 @@ var TAG_SGR = {
|
|
|
27790
28095
|
"zero-ref": "\x1B[91m",
|
|
27791
28096
|
ace: "\x1B[95m",
|
|
27792
28097
|
cli: "\x1B[90m",
|
|
27793
|
-
EasySpecs: "\x1B[93m"
|
|
28098
|
+
EasySpecs: "\x1B[93m",
|
|
28099
|
+
"host-pool": "\x1B[36m",
|
|
28100
|
+
"host-pool-rec": "\x1B[90m"
|
|
27794
28101
|
};
|
|
27795
28102
|
function tagOpenSgr(tag) {
|
|
27796
28103
|
const direct = TAG_SGR[tag];
|
|
@@ -27831,7 +28138,7 @@ function phaseFamilyForTag(tag) {
|
|
|
27831
28138
|
if (tag.startsWith("pipeline:")) {
|
|
27832
28139
|
return "meta";
|
|
27833
28140
|
}
|
|
27834
|
-
if (tag === "pool" || tag === "queue" || tag === "worktree" || tag === "context") {
|
|
28141
|
+
if (tag === "pool" || tag === "queue" || tag === "worktree" || tag === "context" || tag === "host-pool" || tag === "host-pool-rec") {
|
|
27835
28142
|
return "orch";
|
|
27836
28143
|
}
|
|
27837
28144
|
if (Object.prototype.hasOwnProperty.call(TAG_SGR, tag)) {
|
|
@@ -28090,7 +28397,7 @@ function formatCliStderrLine(line, useAnsi) {
|
|
|
28090
28397
|
}
|
|
28091
28398
|
|
|
28092
28399
|
// src/cli/main.ts
|
|
28093
|
-
var PKG_VERSION = "0.0.
|
|
28400
|
+
var PKG_VERSION = "0.0.27";
|
|
28094
28401
|
function isNonEmptyFactoryFailureArray(x) {
|
|
28095
28402
|
if (!Array.isArray(x) || x.length === 0) {
|
|
28096
28403
|
return false;
|
|
@@ -28222,7 +28529,7 @@ function resolveAnalysisRoot(repoRoot, rootKind, worktreePath) {
|
|
|
28222
28529
|
return repoRoot;
|
|
28223
28530
|
}
|
|
28224
28531
|
const wt = worktreePath?.trim();
|
|
28225
|
-
if (wt &&
|
|
28532
|
+
if (wt && fs62.existsSync(path59.join(wt, ".git"))) {
|
|
28226
28533
|
return path59.resolve(wt);
|
|
28227
28534
|
}
|
|
28228
28535
|
throw new Error("worktree mode requires --worktree <path> to an existing analysis checkout.");
|
|
@@ -28231,14 +28538,14 @@ function resolveAdHocCheckoutRoot(_repoRoot, storage, worktreeFlag) {
|
|
|
28231
28538
|
const w = worktreeFlag?.trim();
|
|
28232
28539
|
if (w) {
|
|
28233
28540
|
const abs = path59.resolve(w);
|
|
28234
|
-
if (
|
|
28541
|
+
if (fs62.existsSync(path59.join(abs, ".git"))) {
|
|
28235
28542
|
return abs;
|
|
28236
28543
|
}
|
|
28237
28544
|
throw new Error(`Invalid --worktree (not a git checkout): ${abs}`);
|
|
28238
28545
|
}
|
|
28239
28546
|
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
28240
28547
|
const p = snap?.adHocWorktreePath?.trim();
|
|
28241
|
-
if (p &&
|
|
28548
|
+
if (p && fs62.existsSync(path59.join(p, ".git"))) {
|
|
28242
28549
|
return p;
|
|
28243
28550
|
}
|
|
28244
28551
|
throw new Error("No analysis checkout: run `easyspecs-cli run synthesis` first or pass `--worktree <path>`.");
|
|
@@ -28561,13 +28868,14 @@ async function main() {
|
|
|
28561
28868
|
process.exit(ExitCode.usage);
|
|
28562
28869
|
}
|
|
28563
28870
|
const agentsDir = resolveOpenCodeAgentsDir(repoRoot, repoConfig);
|
|
28564
|
-
const agentsOk =
|
|
28871
|
+
const agentsOk = fs62.existsSync(agentsDir);
|
|
28565
28872
|
const oc = getOpenCodeReadiness({
|
|
28566
28873
|
executable: merged.openCodeExecutable,
|
|
28567
28874
|
skipCredentialsCheck: merged.openCodeSkipCredentialsCheck,
|
|
28568
28875
|
providerEnvFromConfig: merged.openCodeChildEnv
|
|
28569
28876
|
});
|
|
28570
28877
|
const lines = [
|
|
28878
|
+
`cliVersion=${PKG_VERSION}`,
|
|
28571
28879
|
`repoRoot=${repoRoot}`,
|
|
28572
28880
|
`apiBaseUrl=${apiResolved || "(empty \u2014 stub auth only)"}`,
|
|
28573
28881
|
`opencode installed=${String(oc.installed)} credentialsReady=${String(oc.credentialsReady)}`,
|
|
@@ -28587,6 +28895,7 @@ async function main() {
|
|
|
28587
28895
|
const envelope = { ok: true };
|
|
28588
28896
|
if (modes.readiness) {
|
|
28589
28897
|
envelope.lines = lines;
|
|
28898
|
+
envelope.cliVersion = PKG_VERSION;
|
|
28590
28899
|
}
|
|
28591
28900
|
if (modes.inspectConfig) {
|
|
28592
28901
|
envelope.config = inspectPayload;
|
|
@@ -29075,7 +29384,7 @@ async function main() {
|
|
|
29075
29384
|
const wt = snap?.adHocWorktreePath?.trim();
|
|
29076
29385
|
if (wt) {
|
|
29077
29386
|
const sourceCtx = path59.join(wt, ".gluecharm", "context");
|
|
29078
|
-
if (
|
|
29387
|
+
if (fs62.existsSync(sourceCtx)) {
|
|
29079
29388
|
const n = promoteContextDirectoryToWorkspaceFs(sourceCtx, repoRoot);
|
|
29080
29389
|
logErr(flags, `[pipeline:analysis] promoted ${String(n.filesCopied)} file(s) \u2192 ${repoRoot}`);
|
|
29081
29390
|
} else {
|
|
@@ -29245,12 +29554,12 @@ async function main() {
|
|
|
29245
29554
|
if (pos[1] === "republish") {
|
|
29246
29555
|
const fromCfg = repoConfig.easyspecs?.upload?.contextDirectory?.trim();
|
|
29247
29556
|
const resolvedOverride = fromCfg && fromCfg.length > 0 ? path59.isAbsolute(fromCfg) ? path59.normalize(fromCfg) : path59.resolve(repoRoot, fromCfg) : "";
|
|
29248
|
-
if (resolvedOverride &&
|
|
29557
|
+
if (resolvedOverride && fs62.existsSync(path59.join(resolvedOverride, ".."))) {
|
|
29249
29558
|
ctxDir = resolvedOverride;
|
|
29250
29559
|
} else {
|
|
29251
29560
|
const storage = createFileBackedWorkspaceState(repoRoot);
|
|
29252
29561
|
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
29253
|
-
const wt = snap?.adHocWorktreePath &&
|
|
29562
|
+
const wt = snap?.adHocWorktreePath && fs62.existsSync(path59.join(snap.adHocWorktreePath, ".gluecharm", "context")) ? path59.join(snap.adHocWorktreePath, ".gluecharm", "context") : "";
|
|
29254
29563
|
if (!wt) {
|
|
29255
29564
|
finish(ExitCode.misconfiguration, {
|
|
29256
29565
|
ok: false,
|
|
@@ -29368,16 +29677,16 @@ async function main() {
|
|
|
29368
29677
|
}
|
|
29369
29678
|
if (pos[0] === "ace" && pos[1] === "clear") {
|
|
29370
29679
|
const learnings = path59.join(repoRoot, ".gluecharm", "context", "learnings");
|
|
29371
|
-
if (!
|
|
29680
|
+
if (!fs62.existsSync(learnings)) {
|
|
29372
29681
|
finish(ExitCode.ok, { ok: true, message: "nothing to clear" });
|
|
29373
29682
|
}
|
|
29374
|
-
|
|
29683
|
+
fs62.rmSync(learnings, { recursive: true, force: true });
|
|
29375
29684
|
finish(ExitCode.ok, { ok: true, message: `cleared ${learnings}` });
|
|
29376
29685
|
}
|
|
29377
29686
|
if (pos[0] === "ace" && pos[1] === "learn") {
|
|
29378
29687
|
requireOpenCode(merged, flags);
|
|
29379
29688
|
const { worktree } = parseWorktreeFlag(pos.slice(2));
|
|
29380
|
-
const root = worktree &&
|
|
29689
|
+
const root = worktree && fs62.existsSync(path59.join(worktree, ".opencode", "schemas", "ace")) ? worktree : repoRoot;
|
|
29381
29690
|
const contextDir2 = path59.join(root, ".gluecharm", "context");
|
|
29382
29691
|
const traces = listAceTraceFiles(contextDir2);
|
|
29383
29692
|
if (traces.length === 0) {
|
|
@@ -29402,7 +29711,7 @@ async function main() {
|
|
|
29402
29711
|
if (pos[0] === "ace" && pos[1] === "auto-learn") {
|
|
29403
29712
|
requireOpenCode(merged, flags);
|
|
29404
29713
|
const { worktree } = parseWorktreeFlag(pos.slice(2));
|
|
29405
|
-
const root = worktree &&
|
|
29714
|
+
const root = worktree && fs62.existsSync(path59.join(worktree, ".git")) ? worktree : repoRoot;
|
|
29406
29715
|
const contextDir2 = path59.join(root, ".gluecharm", "context");
|
|
29407
29716
|
const pending = listPendingAceTraceFiles(contextDir2, root);
|
|
29408
29717
|
if (pending.length === 0) {
|