@gluecharm-lab/easyspecs-cli 0.0.24 → 0.0.26
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 +21 -2
- package/dist/main.cjs +960 -425
- package/dist/main.cjs.map +4 -4
- package/error-code.md +2 -0
- 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 fs62 = 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 (fs62.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) => fs62.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 = fs62.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, fs62, 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, fs62[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 fs61 = __toESM(require("node:fs"));
|
|
10640
10640
|
var path59 = __toESM(require("node:path"));
|
|
10641
10641
|
|
|
10642
10642
|
// src/cli/exitCodes.ts
|
|
@@ -10706,6 +10706,8 @@ function createEasyspecsCliProgram() {
|
|
|
10706
10706
|
program2.option("--cwd <dir>", "Repository root (default: current directory)").option("--ci", "Non-interactive; fail fast if configuration is missing").option("--json", "Print one JSON summary line on stdout").option("--verbose", "Extra stderr logging").option("--config <path>", "Configuration file path (accepted; currently unused)").option("--api-base-url <url>", "System Manager API origin (overrides config)").option("--session-path <file>", "Session JSON for this run (overrides config)").option("--environment <environment>", "Effective deployment (alias: --env)").option("--env <environment>", "Alias for --environment").option("--promote", "After run synthesis: force context promotion when config would disable it").option("--no-promote", "After run synthesis or analysis: skip copying .gluecharm/context into repo for this run");
|
|
10707
10707
|
program2.command("help").description("Show help");
|
|
10708
10708
|
program2.command("version").description("Print CLI version");
|
|
10709
|
+
const workstation = program2.command("workstation").description("Host inventory for AI workstation sizing");
|
|
10710
|
+
workstation.command("info").description("Print CPU, RAM, and SRS-64 N_sys (macOS and Linux only; use global --json)").allowUnknownOption(false);
|
|
10709
10711
|
program2.command("doctor").description("Check readiness and/or inspect configuration").option("--readiness", "Print readiness summary (default)").option("--inspect-config", "Print redacted merged configuration");
|
|
10710
10712
|
const auth = program2.command("auth").description("Authentication");
|
|
10711
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");
|
|
@@ -11234,6 +11236,159 @@ function getDefaultEasyspecsConfig() {
|
|
|
11234
11236
|
};
|
|
11235
11237
|
}
|
|
11236
11238
|
|
|
11239
|
+
// src/config/machineConcurrentAiFromHost.ts
|
|
11240
|
+
var fs3 = __toESM(require("node:fs"));
|
|
11241
|
+
var os = __toESM(require("node:os"));
|
|
11242
|
+
var import_node_child_process2 = require("node:child_process");
|
|
11243
|
+
|
|
11244
|
+
// src/config/effectiveMaxConcurrentAi.ts
|
|
11245
|
+
var ABSOLUTE_MAX_CONCURRENT_AI = 64;
|
|
11246
|
+
|
|
11247
|
+
// src/config/machineConcurrentAiFromHost.ts
|
|
11248
|
+
function clampProductConcurrentLimits(n) {
|
|
11249
|
+
if (!Number.isFinite(n)) {
|
|
11250
|
+
return DEFAULT_MAX_CONCURRENT_AI;
|
|
11251
|
+
}
|
|
11252
|
+
return Math.min(ABSOLUTE_MAX_CONCURRENT_AI, Math.max(1, Math.floor(n)));
|
|
11253
|
+
}
|
|
11254
|
+
function machineConcurrentAiCapFromHost(profile) {
|
|
11255
|
+
const memBytes = Number.isFinite(profile.totalMemBytes) && profile.totalMemBytes > 0 ? profile.totalMemBytes : 0;
|
|
11256
|
+
const rGib = memBytes / 2 ** 30;
|
|
11257
|
+
let p = Math.floor(profile.cpusForCap);
|
|
11258
|
+
if (!Number.isFinite(p) || p < 1) {
|
|
11259
|
+
p = 1;
|
|
11260
|
+
}
|
|
11261
|
+
if (!Number.isFinite(rGib) || rGib <= 0) {
|
|
11262
|
+
return 1;
|
|
11263
|
+
}
|
|
11264
|
+
let nCpuFloat;
|
|
11265
|
+
if (p <= 11) {
|
|
11266
|
+
nCpuFloat = 15 + 8.5 * (p - 1);
|
|
11267
|
+
} else {
|
|
11268
|
+
nCpuFloat = 100 + 8.5 * (p - 11);
|
|
11269
|
+
}
|
|
11270
|
+
const ramFactor = Math.min(1, rGib / (4 * p));
|
|
11271
|
+
const nFloat = nCpuFloat * ramFactor;
|
|
11272
|
+
const rounded = Math.round(nFloat);
|
|
11273
|
+
return Math.max(1, rounded);
|
|
11274
|
+
}
|
|
11275
|
+
function hostHardMaxFromHost(profile) {
|
|
11276
|
+
const nSys = machineConcurrentAiCapFromHost(profile);
|
|
11277
|
+
return Math.min(64, Math.max(1, nSys));
|
|
11278
|
+
}
|
|
11279
|
+
function resolveStaticEffectiveMaxConcurrentAi(params) {
|
|
11280
|
+
const requestedSanitized = clampProductConcurrentLimits(Number(params.requested));
|
|
11281
|
+
let nSys;
|
|
11282
|
+
let hostHardMax;
|
|
11283
|
+
if (params.hostHardMaxOverride !== void 0) {
|
|
11284
|
+
hostHardMax = clampProductConcurrentLimits(params.hostHardMaxOverride);
|
|
11285
|
+
nSys = params.hostProfile ? machineConcurrentAiCapFromHost(params.hostProfile) : hostHardMax;
|
|
11286
|
+
} else {
|
|
11287
|
+
const profile = params.hostProfile ?? collectHostMachineProfile();
|
|
11288
|
+
nSys = machineConcurrentAiCapFromHost(profile);
|
|
11289
|
+
hostHardMax = hostHardMaxFromHost(profile);
|
|
11290
|
+
}
|
|
11291
|
+
if (params.applyHostConcurrencyCap === false) {
|
|
11292
|
+
return {
|
|
11293
|
+
staticEffective: requestedSanitized,
|
|
11294
|
+
hostHardMax,
|
|
11295
|
+
nSys,
|
|
11296
|
+
requestedSanitized,
|
|
11297
|
+
cappedByHost: false
|
|
11298
|
+
};
|
|
11299
|
+
}
|
|
11300
|
+
const staticEffective = clampProductConcurrentLimits(Math.min(requestedSanitized, hostHardMax));
|
|
11301
|
+
const cappedByHost = requestedSanitized > hostHardMax;
|
|
11302
|
+
return { staticEffective, hostHardMax, nSys, requestedSanitized, cappedByHost };
|
|
11303
|
+
}
|
|
11304
|
+
function formatMaxConcurrentAiOverCapWarning(p) {
|
|
11305
|
+
return `[EasySpecs] easyspecs.workstations.maxConcurrentAi (${String(p.requested)}) exceeds this host's hostHardMax (${String(p.hostHardMax)}). Using effective concurrency ${String(p.effective)}.`;
|
|
11306
|
+
}
|
|
11307
|
+
function tryReadDarwinPhysicalCpus() {
|
|
11308
|
+
if (process.platform !== "darwin") {
|
|
11309
|
+
return void 0;
|
|
11310
|
+
}
|
|
11311
|
+
try {
|
|
11312
|
+
const out = (0, import_node_child_process2.execFileSync)("/usr/sbin/sysctl", ["-n", "hw.physicalcpu"], {
|
|
11313
|
+
encoding: "utf8",
|
|
11314
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
11315
|
+
timeout: 2e3
|
|
11316
|
+
}).trim();
|
|
11317
|
+
const n = parseInt(out, 10);
|
|
11318
|
+
if (Number.isFinite(n) && n > 0) {
|
|
11319
|
+
return n;
|
|
11320
|
+
}
|
|
11321
|
+
} catch {
|
|
11322
|
+
}
|
|
11323
|
+
return void 0;
|
|
11324
|
+
}
|
|
11325
|
+
function tryReadLinuxPhysicalCpus() {
|
|
11326
|
+
if (process.platform !== "linux") {
|
|
11327
|
+
return void 0;
|
|
11328
|
+
}
|
|
11329
|
+
try {
|
|
11330
|
+
const raw = fs3.readFileSync("/proc/cpuinfo", "utf8");
|
|
11331
|
+
const chunks = raw.split(/\n(?=^processor\s*:)/m);
|
|
11332
|
+
const pairs = /* @__PURE__ */ new Set();
|
|
11333
|
+
for (const chunk of chunks) {
|
|
11334
|
+
if (!/^processor\s*:/m.test(chunk.trim())) {
|
|
11335
|
+
continue;
|
|
11336
|
+
}
|
|
11337
|
+
let physicalId;
|
|
11338
|
+
let coreId;
|
|
11339
|
+
for (const line of chunk.split("\n")) {
|
|
11340
|
+
const t = line.trim();
|
|
11341
|
+
const mPhy = /^physical id\s*:\s*(\d+)\s*$/i.exec(t);
|
|
11342
|
+
if (mPhy) {
|
|
11343
|
+
physicalId = mPhy[1];
|
|
11344
|
+
}
|
|
11345
|
+
const mCore = /^core id\s*:\s*(\d+)\s*$/i.exec(t);
|
|
11346
|
+
if (mCore) {
|
|
11347
|
+
coreId = mCore[1];
|
|
11348
|
+
}
|
|
11349
|
+
}
|
|
11350
|
+
if (physicalId !== void 0 && coreId !== void 0) {
|
|
11351
|
+
pairs.add(`${physicalId}:${coreId}`);
|
|
11352
|
+
}
|
|
11353
|
+
}
|
|
11354
|
+
if (pairs.size > 0) {
|
|
11355
|
+
return pairs.size;
|
|
11356
|
+
}
|
|
11357
|
+
} catch {
|
|
11358
|
+
}
|
|
11359
|
+
return void 0;
|
|
11360
|
+
}
|
|
11361
|
+
function collectHostMachineProfile() {
|
|
11362
|
+
const platform = process.platform;
|
|
11363
|
+
const totalMemBytes = os.totalmem();
|
|
11364
|
+
const logical = Math.max(1, os.cpus()?.length ?? 1);
|
|
11365
|
+
if (platform === "darwin") {
|
|
11366
|
+
const phy = tryReadDarwinPhysicalCpus();
|
|
11367
|
+
if (phy !== void 0) {
|
|
11368
|
+
return {
|
|
11369
|
+
cpusForCap: phy,
|
|
11370
|
+
cpusForCapSource: "physical",
|
|
11371
|
+
totalMemBytes,
|
|
11372
|
+
platform
|
|
11373
|
+
};
|
|
11374
|
+
}
|
|
11375
|
+
return { cpusForCap: logical, cpusForCapSource: "logical_fallback", totalMemBytes, platform };
|
|
11376
|
+
}
|
|
11377
|
+
if (platform === "linux") {
|
|
11378
|
+
const phy = tryReadLinuxPhysicalCpus();
|
|
11379
|
+
if (phy !== void 0) {
|
|
11380
|
+
return {
|
|
11381
|
+
cpusForCap: phy,
|
|
11382
|
+
cpusForCapSource: "physical",
|
|
11383
|
+
totalMemBytes,
|
|
11384
|
+
platform
|
|
11385
|
+
};
|
|
11386
|
+
}
|
|
11387
|
+
return { cpusForCap: logical, cpusForCapSource: "logical_fallback", totalMemBytes, platform };
|
|
11388
|
+
}
|
|
11389
|
+
return { cpusForCap: logical, cpusForCapSource: "logical_fallback", totalMemBytes, platform };
|
|
11390
|
+
}
|
|
11391
|
+
|
|
11237
11392
|
// src/config/openCodeProviderEnv.ts
|
|
11238
11393
|
var path3 = __toESM(require("node:path"));
|
|
11239
11394
|
var PROVIDER_TO_ENV = {
|
|
@@ -11340,6 +11495,8 @@ function getEasyspecsMergedConfigValue(es, fullKey) {
|
|
|
11340
11495
|
return es.orchestration?.synthesisRemediationShareBackoff;
|
|
11341
11496
|
case "easyspecs.workstations.maxConcurrentAi":
|
|
11342
11497
|
return es.workstations?.maxConcurrentAi;
|
|
11498
|
+
case "easyspecs.workstations.applyHostConcurrencyCap":
|
|
11499
|
+
return es.workstations?.applyHostConcurrencyCap;
|
|
11343
11500
|
case "easyspecs.analysis.maxConcurrentOpenCodeAgents":
|
|
11344
11501
|
return es.analysis?.maxConcurrentOpenCodeAgents;
|
|
11345
11502
|
case "easyspecs.workstations.openCodeArgv":
|
|
@@ -11409,7 +11566,24 @@ function mergeEasyspecsCliSettings(cfg, overrides = {}) {
|
|
|
11409
11566
|
const listJsonSchemaRepairAttempts = rt?.coordinationRepairs?.listJsonSchemaRepairAttempts ?? readEasyspecsMergedSetting(cfg.easyspecs, "easyspecs.workstations.coordinationListRepairAttempts") ?? 1;
|
|
11410
11567
|
const markdownEvidenceRepairAttempts = rt?.coordinationRepairs?.markdownEvidenceRepairAttempts ?? readEasyspecsMergedSetting(cfg.easyspecs, "easyspecs.workstations.detailMarkdownRepairAttempts") ?? 2;
|
|
11411
11568
|
const markdownOpenQuestionIterations = rt?.coordinationRepairs?.markdownOpenQuestionIterations ?? readEasyspecsMergedSetting(cfg.easyspecs, "easyspecs.workstations.openQuestionIterations") ?? 5;
|
|
11412
|
-
const
|
|
11569
|
+
const requestedPool = overrides.maxConcurrentOpenCodeAgents ?? readEasyspecsMergedSetting(cfg.easyspecs, "easyspecs.workstations.maxConcurrentAi") ?? rt?.pool?.maxConcurrentAgents ?? DEFAULT_MAX_CONCURRENT_AI;
|
|
11570
|
+
const applyHostCap = readEasyspecsMergedSetting(cfg.easyspecs, "easyspecs.workstations.applyHostConcurrencyCap") !== false;
|
|
11571
|
+
const hostProfile = overrides.__testOnlyHostProfile ?? collectHostMachineProfile();
|
|
11572
|
+
const resolved = resolveStaticEffectiveMaxConcurrentAi({
|
|
11573
|
+
requested: requestedPool,
|
|
11574
|
+
applyHostConcurrencyCap: applyHostCap,
|
|
11575
|
+
hostProfile
|
|
11576
|
+
});
|
|
11577
|
+
const maxConcurrentOpenCodeAgents = resolved.staticEffective;
|
|
11578
|
+
if (resolved.cappedByHost) {
|
|
11579
|
+
const msg = formatMaxConcurrentAiOverCapWarning({
|
|
11580
|
+
requested: resolved.requestedSanitized,
|
|
11581
|
+
hostHardMax: resolved.hostHardMax,
|
|
11582
|
+
effective: resolved.staticEffective
|
|
11583
|
+
});
|
|
11584
|
+
process.stderr.write(`${msg}
|
|
11585
|
+
`);
|
|
11586
|
+
}
|
|
11413
11587
|
const promoteContextToWorkspace = overrides.promote === false ? false : overrides.promote === true ? true : analysis.promoteContextToWorkspace !== false;
|
|
11414
11588
|
let maxOuter = overrides.maxOuterIterationsPerPhase ?? readEasyspecsMergedSetting(cfg.easyspecs, "easyspecs.factory.maxOuterIterationsPerPipeline") ?? orch.maxOuterIterationsPerPhase ?? 0;
|
|
11415
11589
|
if (ci && maxOuter === 0) {
|
|
@@ -11464,27 +11638,27 @@ function redactMergedCliSettingsForDump(merged) {
|
|
|
11464
11638
|
}
|
|
11465
11639
|
|
|
11466
11640
|
// src/config/easyspecsConfigFile.ts
|
|
11467
|
-
var
|
|
11641
|
+
var fs7 = __toESM(require("node:fs"));
|
|
11468
11642
|
var path7 = __toESM(require("node:path"));
|
|
11469
11643
|
|
|
11470
11644
|
// src/easySpecsWorkspaceSettingsCore.ts
|
|
11471
|
-
var
|
|
11645
|
+
var fs5 = __toESM(require("node:fs"));
|
|
11472
11646
|
var path5 = __toESM(require("node:path"));
|
|
11473
11647
|
|
|
11474
11648
|
// src/analysis/easySpecsWorktreeMarker.ts
|
|
11475
|
-
var
|
|
11649
|
+
var fs4 = __toESM(require("fs"));
|
|
11476
11650
|
var path4 = __toESM(require("path"));
|
|
11477
11651
|
var EASYSPECS_LOCAL_DIR = ".easyspecs";
|
|
11478
11652
|
var EASYSPECS_WORKTREE_MARKER_REL = path4.join(EASYSPECS_LOCAL_DIR, "analysis-worktree.json");
|
|
11479
11653
|
var MARKER_KIND = "easyspecs-analysis-worktree";
|
|
11480
11654
|
function writeAnalysisWorktreeMarker(worktreeRoot, repositoryRoot) {
|
|
11481
11655
|
const dir = path4.join(worktreeRoot, EASYSPECS_LOCAL_DIR);
|
|
11482
|
-
|
|
11656
|
+
fs4.mkdirSync(dir, { recursive: true });
|
|
11483
11657
|
const payload = {
|
|
11484
11658
|
kind: MARKER_KIND,
|
|
11485
11659
|
repositoryRoot: path4.resolve(repositoryRoot)
|
|
11486
11660
|
};
|
|
11487
|
-
|
|
11661
|
+
fs4.writeFileSync(path4.join(dir, "analysis-worktree.json"), `${JSON.stringify(payload)}
|
|
11488
11662
|
`, "utf-8");
|
|
11489
11663
|
}
|
|
11490
11664
|
|
|
@@ -11500,7 +11674,7 @@ function readAceEnabledFromEasySpecsSettingsFile(workspaceRootFsPath) {
|
|
|
11500
11674
|
const filePath = path5.join(workspaceRootFsPath, EASYSPECS_WORKSPACE_DIR, EASYSPECS_SETTINGS_JSON);
|
|
11501
11675
|
let raw;
|
|
11502
11676
|
try {
|
|
11503
|
-
raw =
|
|
11677
|
+
raw = fs5.readFileSync(filePath, "utf8");
|
|
11504
11678
|
} catch {
|
|
11505
11679
|
return void 0;
|
|
11506
11680
|
}
|
|
@@ -11520,7 +11694,7 @@ function readAceOfflineLearnAfterSameSessionTraceFromEasySpecsSettingsFile(works
|
|
|
11520
11694
|
const filePath = path5.join(workspaceRootFsPath, EASYSPECS_WORKSPACE_DIR, EASYSPECS_SETTINGS_JSON);
|
|
11521
11695
|
let raw;
|
|
11522
11696
|
try {
|
|
11523
|
-
raw =
|
|
11697
|
+
raw = fs5.readFileSync(filePath, "utf8");
|
|
11524
11698
|
} catch {
|
|
11525
11699
|
return void 0;
|
|
11526
11700
|
}
|
|
@@ -11538,7 +11712,7 @@ function readAceOfflineLearnAfterSameSessionTraceFromEasySpecsSettingsFile(works
|
|
|
11538
11712
|
}
|
|
11539
11713
|
|
|
11540
11714
|
// src/config/validateEasyspecsConfigSrs46.ts
|
|
11541
|
-
var
|
|
11715
|
+
var fs6 = __toESM(require("node:fs"));
|
|
11542
11716
|
var path6 = __toESM(require("node:path"));
|
|
11543
11717
|
var import__ = __toESM(require__());
|
|
11544
11718
|
var import_ajv_formats = __toESM(require_dist());
|
|
@@ -11553,14 +11727,14 @@ function resolveSrs46ConfigSchemaPath() {
|
|
|
11553
11727
|
path6.join(__dirname, "..", "..", "..", SCHEMA_REL_REPO)
|
|
11554
11728
|
];
|
|
11555
11729
|
for (const p of candidates) {
|
|
11556
|
-
if (
|
|
11730
|
+
if (fs6.existsSync(p)) {
|
|
11557
11731
|
return path6.normalize(p);
|
|
11558
11732
|
}
|
|
11559
11733
|
}
|
|
11560
11734
|
let dir = __dirname;
|
|
11561
11735
|
for (let i = 0; i < 14; i += 1) {
|
|
11562
11736
|
const p = path6.join(dir, SCHEMA_REL_REPO);
|
|
11563
|
-
if (
|
|
11737
|
+
if (fs6.existsSync(p)) {
|
|
11564
11738
|
return path6.normalize(p);
|
|
11565
11739
|
}
|
|
11566
11740
|
const parent = path6.dirname(dir);
|
|
@@ -11575,7 +11749,7 @@ function resolveSrs46ConfigSchemaPath() {
|
|
|
11575
11749
|
}
|
|
11576
11750
|
function loadSchemaObject() {
|
|
11577
11751
|
const schemaPath = resolveSrs46ConfigSchemaPath();
|
|
11578
|
-
const raw =
|
|
11752
|
+
const raw = fs6.readFileSync(schemaPath, "utf8");
|
|
11579
11753
|
return JSON.parse(raw);
|
|
11580
11754
|
}
|
|
11581
11755
|
var EasyspecsConfigSchemaError = class extends Error {
|
|
@@ -11647,7 +11821,7 @@ function parseEasyspecsConfigJson(raw, filePath) {
|
|
|
11647
11821
|
}
|
|
11648
11822
|
function readEasyspecsConfig(repoRoot) {
|
|
11649
11823
|
const p = easyspecsConfigPath(repoRoot);
|
|
11650
|
-
const raw =
|
|
11824
|
+
const raw = fs7.readFileSync(p, "utf8");
|
|
11651
11825
|
return parseEasyspecsConfigJson(raw, p);
|
|
11652
11826
|
}
|
|
11653
11827
|
function cliJsonFileToConfigPartial(legacy) {
|
|
@@ -11690,17 +11864,17 @@ function cliJsonFileToConfigPartial(legacy) {
|
|
|
11690
11864
|
}
|
|
11691
11865
|
function atomicWriteFile(targetPath, contents) {
|
|
11692
11866
|
const dir = path7.dirname(targetPath);
|
|
11693
|
-
|
|
11867
|
+
fs7.mkdirSync(dir, { recursive: true });
|
|
11694
11868
|
const tmp = path7.join(dir, `.${path7.basename(targetPath)}.${process.pid}.${Date.now()}.tmp`);
|
|
11695
|
-
|
|
11696
|
-
|
|
11869
|
+
fs7.writeFileSync(tmp, contents, "utf8");
|
|
11870
|
+
fs7.renameSync(tmp, targetPath);
|
|
11697
11871
|
}
|
|
11698
11872
|
function buildFreshEasyspecsConfigFromLegacy(repoRoot, warnMigration) {
|
|
11699
11873
|
let base = getDefaultEasyspecsConfig();
|
|
11700
11874
|
const legacyPath = easyspecsLegacyCliJsonPath(repoRoot);
|
|
11701
|
-
if (
|
|
11875
|
+
if (fs7.existsSync(legacyPath)) {
|
|
11702
11876
|
try {
|
|
11703
|
-
const rawLegacy =
|
|
11877
|
+
const rawLegacy = fs7.readFileSync(legacyPath, "utf8");
|
|
11704
11878
|
const legacyParsed = JSON.parse(rawLegacy);
|
|
11705
11879
|
base = mergeEasyspecsConfigDefaults(base, cliJsonFileToConfigPartial(legacyParsed));
|
|
11706
11880
|
warnMigration?.(`Imported settings from ${LEGACY_CLI_JSON} into ${CONFIG_BASENAME} (SRS-43 migration).`);
|
|
@@ -11709,9 +11883,9 @@ function buildFreshEasyspecsConfigFromLegacy(repoRoot, warnMigration) {
|
|
|
11709
11883
|
}
|
|
11710
11884
|
}
|
|
11711
11885
|
const settingsLegacyPath = easyspecsLegacySettingsJsonPath(repoRoot);
|
|
11712
|
-
if (
|
|
11886
|
+
if (fs7.existsSync(settingsLegacyPath)) {
|
|
11713
11887
|
try {
|
|
11714
|
-
const rawS =
|
|
11888
|
+
const rawS = fs7.readFileSync(settingsLegacyPath, "utf8");
|
|
11715
11889
|
const leg = JSON.parse(rawS);
|
|
11716
11890
|
const ace = {};
|
|
11717
11891
|
if (Object.prototype.hasOwnProperty.call(leg, EASYSPECS_SETTINGS_ACE_KEY)) {
|
|
@@ -11740,7 +11914,7 @@ function buildFreshEasyspecsConfigFromLegacy(repoRoot, warnMigration) {
|
|
|
11740
11914
|
}
|
|
11741
11915
|
function initEasyspecsConfigFile(repoRoot, opts) {
|
|
11742
11916
|
const configPath = easyspecsConfigPath(repoRoot);
|
|
11743
|
-
const existed =
|
|
11917
|
+
const existed = fs7.existsSync(configPath);
|
|
11744
11918
|
if (existed && !opts.overwrite) {
|
|
11745
11919
|
return { outcome: "unchanged", path: configPath, config: readEasyspecsConfig(repoRoot) };
|
|
11746
11920
|
}
|
|
@@ -11756,14 +11930,14 @@ function initEasyspecsConfigFile(repoRoot, opts) {
|
|
|
11756
11930
|
function ensureEasyspecsConfig(repoRoot, opts) {
|
|
11757
11931
|
const configPath = easyspecsConfigPath(repoRoot);
|
|
11758
11932
|
const legacyPath = easyspecsLegacyCliJsonPath(repoRoot);
|
|
11759
|
-
if (
|
|
11760
|
-
if (
|
|
11933
|
+
if (fs7.existsSync(configPath)) {
|
|
11934
|
+
if (fs7.existsSync(legacyPath)) {
|
|
11761
11935
|
opts.warnMigration?.(
|
|
11762
11936
|
`${legacyPath} is deprecated alongside ${configPath}; prefer editing ${CONFIG_BASENAME} only.`
|
|
11763
11937
|
);
|
|
11764
11938
|
}
|
|
11765
11939
|
const settingsLegacy = easyspecsLegacySettingsJsonPath(repoRoot);
|
|
11766
|
-
if (
|
|
11940
|
+
if (fs7.existsSync(settingsLegacy)) {
|
|
11767
11941
|
opts.warnMigration?.(
|
|
11768
11942
|
`${settingsLegacy} is deprecated; use easyspecs.analysis.ace in ${CONFIG_BASENAME} (see USER-MANUAL-SRS-35).`
|
|
11769
11943
|
);
|
|
@@ -11785,7 +11959,7 @@ function syncDefaultGitRemoteUrlIfEmpty(repoRoot, cfg, opts) {
|
|
|
11785
11959
|
return cfg;
|
|
11786
11960
|
}
|
|
11787
11961
|
const configPath = easyspecsConfigPath(repoRoot);
|
|
11788
|
-
if (!
|
|
11962
|
+
if (!fs7.existsSync(configPath)) {
|
|
11789
11963
|
return cfg;
|
|
11790
11964
|
}
|
|
11791
11965
|
const gitRoot = findGitRepoRoot(repoRoot) ?? repoRoot;
|
|
@@ -11797,7 +11971,7 @@ function syncDefaultGitRemoteUrlIfEmpty(repoRoot, cfg, opts) {
|
|
|
11797
11971
|
}
|
|
11798
11972
|
function updateEasyspecsConfig(repoRoot, patch, opts) {
|
|
11799
11973
|
const configPath = easyspecsConfigPath(repoRoot);
|
|
11800
|
-
const base =
|
|
11974
|
+
const base = fs7.existsSync(configPath) ? readEasyspecsConfig(repoRoot) : buildFreshEasyspecsConfigFromLegacy(repoRoot, opts?.warnMigration);
|
|
11801
11975
|
const merged = mergeEasyspecsConfigDefaults(base, patch);
|
|
11802
11976
|
assertEasyspecsConfigValidatesSrs46Schema(merged, configPath);
|
|
11803
11977
|
atomicWriteFile(configPath, `${JSON.stringify(merged, null, 2)}
|
|
@@ -11806,7 +11980,7 @@ function updateEasyspecsConfig(repoRoot, patch, opts) {
|
|
|
11806
11980
|
}
|
|
11807
11981
|
|
|
11808
11982
|
// src/pipelines/upload/uploadPipeline.ts
|
|
11809
|
-
var
|
|
11983
|
+
var fs12 = __toESM(require("node:fs"));
|
|
11810
11984
|
var path12 = __toESM(require("node:path"));
|
|
11811
11985
|
var import_node_crypto = require("node:crypto");
|
|
11812
11986
|
|
|
@@ -11896,24 +12070,24 @@ function toAuthErrorMessage(error, fallback) {
|
|
|
11896
12070
|
}
|
|
11897
12071
|
|
|
11898
12072
|
// src/analysis/contextSrsDiscoveryIdMap.ts
|
|
11899
|
-
var
|
|
12073
|
+
var fs11 = __toESM(require("node:fs"));
|
|
11900
12074
|
var path11 = __toESM(require("node:path"));
|
|
11901
12075
|
|
|
11902
12076
|
// src/analysis/indexApplicationContextMergeUploadIds.ts
|
|
11903
|
-
var
|
|
12077
|
+
var fs10 = __toESM(require("node:fs"));
|
|
11904
12078
|
var path10 = __toESM(require("node:path"));
|
|
11905
12079
|
|
|
11906
12080
|
// src/indexApplicationContextValidate.ts
|
|
11907
12081
|
var import__2 = __toESM(require__());
|
|
11908
|
-
var
|
|
12082
|
+
var fs9 = __toESM(require("fs"));
|
|
11909
12083
|
var path9 = __toESM(require("path"));
|
|
11910
12084
|
|
|
11911
12085
|
// src/shared/repoResourcesRoot.ts
|
|
11912
|
-
var
|
|
12086
|
+
var fs8 = __toESM(require("node:fs"));
|
|
11913
12087
|
var path8 = __toESM(require("node:path"));
|
|
11914
12088
|
var CONTEXT_LIST_MARKER = path8.join("schemas", "context-lists", "zero-reference-classifier-record.schema.json");
|
|
11915
12089
|
function hasMarker(resourcesRoot) {
|
|
11916
|
-
return
|
|
12090
|
+
return fs8.existsSync(path8.join(resourcesRoot, CONTEXT_LIST_MARKER));
|
|
11917
12091
|
}
|
|
11918
12092
|
function resolveRepoResourcesRoot() {
|
|
11919
12093
|
const candidates = [path8.join(__dirname, "..", "resources"), path8.join(__dirname, "..", "..", "resources")];
|
|
@@ -11943,7 +12117,7 @@ function getValidator(schemaPath) {
|
|
|
11943
12117
|
const abs = path9.resolve(schemaPath);
|
|
11944
12118
|
let v = validators.get(abs);
|
|
11945
12119
|
if (!v) {
|
|
11946
|
-
const raw =
|
|
12120
|
+
const raw = fs9.readFileSync(abs, "utf-8");
|
|
11947
12121
|
const schema = JSON.parse(raw);
|
|
11948
12122
|
const ajv2 = new import__2.default({ allErrors: true, strict: false });
|
|
11949
12123
|
v = ajv2.compile(schema);
|
|
@@ -12028,12 +12202,12 @@ function mergeUploadIdsIntoIndexDocument(doc, contextDir2, succeededIds) {
|
|
|
12028
12202
|
function atomicWriteJson(targetPath, doc) {
|
|
12029
12203
|
const tmp = `${targetPath}.${process.pid}.tmp`;
|
|
12030
12204
|
try {
|
|
12031
|
-
|
|
12205
|
+
fs10.writeFileSync(tmp, `${JSON.stringify(doc, null, 2)}
|
|
12032
12206
|
`, "utf-8");
|
|
12033
|
-
|
|
12207
|
+
fs10.renameSync(tmp, targetPath);
|
|
12034
12208
|
} catch (e) {
|
|
12035
12209
|
try {
|
|
12036
|
-
|
|
12210
|
+
fs10.unlinkSync(tmp);
|
|
12037
12211
|
} catch {
|
|
12038
12212
|
}
|
|
12039
12213
|
throw e;
|
|
@@ -12042,12 +12216,12 @@ function atomicWriteJson(targetPath, doc) {
|
|
|
12042
12216
|
function mergeUploadIdsIntoIndexOnDisk(contextDir2, succeededIds, options) {
|
|
12043
12217
|
const schemaPath = options?.schemaPath ?? getDefaultIndexSchemaPath();
|
|
12044
12218
|
const target = path10.join(contextDir2, INDEX_APPLICATION_CONTEXT_BASENAME);
|
|
12045
|
-
if (!
|
|
12219
|
+
if (!fs10.existsSync(target)) {
|
|
12046
12220
|
return { ok: true };
|
|
12047
12221
|
}
|
|
12048
12222
|
let raw;
|
|
12049
12223
|
try {
|
|
12050
|
-
raw =
|
|
12224
|
+
raw = fs10.readFileSync(target, "utf-8");
|
|
12051
12225
|
} catch (e) {
|
|
12052
12226
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
12053
12227
|
}
|
|
@@ -12096,11 +12270,11 @@ function isRecord2(v) {
|
|
|
12096
12270
|
return Boolean(v) && typeof v === "object" && !Array.isArray(v);
|
|
12097
12271
|
}
|
|
12098
12272
|
function loadSrsDiscoveryIdMapFromContextDir(contextDir2, log) {
|
|
12099
|
-
if (!contextDir2 || !
|
|
12273
|
+
if (!contextDir2 || !fs11.existsSync(contextDir2) || !fs11.statSync(contextDir2).isDirectory()) {
|
|
12100
12274
|
return {};
|
|
12101
12275
|
}
|
|
12102
12276
|
const indexPath = path11.join(contextDir2, INDEX_APPLICATION_CONTEXT_BASENAME);
|
|
12103
|
-
if (!
|
|
12277
|
+
if (!fs11.existsSync(indexPath)) {
|
|
12104
12278
|
log?.(
|
|
12105
12279
|
`[pipeline:upload] No local ${INDEX_APPLICATION_CONTEXT_BASENAME} \u2014 id map empty; uploads use create (new UUID) until the index exists.`
|
|
12106
12280
|
);
|
|
@@ -12108,7 +12282,7 @@ function loadSrsDiscoveryIdMapFromContextDir(contextDir2, log) {
|
|
|
12108
12282
|
}
|
|
12109
12283
|
let raw;
|
|
12110
12284
|
try {
|
|
12111
|
-
raw =
|
|
12285
|
+
raw = fs11.readFileSync(indexPath, "utf8");
|
|
12112
12286
|
} catch (e) {
|
|
12113
12287
|
log?.(`[pipeline:upload] Could not read index file \u2014 ${e instanceof Error ? e.message : String(e)}`);
|
|
12114
12288
|
return {};
|
|
@@ -12322,14 +12496,14 @@ async function fetchApplicationCloudContextAnalysisStatus(requestJson, applicati
|
|
|
12322
12496
|
return { contextAnalyzedInCloud: parsed.contextAnalyzedInCloud, contextAnalyzedInCloudAt };
|
|
12323
12497
|
}
|
|
12324
12498
|
function listContextFilesForUpload(contextDir2, excludeBasenames = /* @__PURE__ */ new Set()) {
|
|
12325
|
-
if (!
|
|
12499
|
+
if (!fs12.existsSync(contextDir2) || !fs12.statSync(contextDir2).isDirectory()) {
|
|
12326
12500
|
return [];
|
|
12327
12501
|
}
|
|
12328
12502
|
const out = [];
|
|
12329
12503
|
const walk = (dir) => {
|
|
12330
12504
|
let entries;
|
|
12331
12505
|
try {
|
|
12332
|
-
entries =
|
|
12506
|
+
entries = fs12.readdirSync(dir, { withFileTypes: true });
|
|
12333
12507
|
} catch {
|
|
12334
12508
|
return;
|
|
12335
12509
|
}
|
|
@@ -12513,7 +12687,7 @@ async function runParallelSinglesIntoAccum(requestJson, applicationId, paths, on
|
|
|
12513
12687
|
const basename17 = path12.basename(absPath);
|
|
12514
12688
|
let content;
|
|
12515
12689
|
try {
|
|
12516
|
-
content =
|
|
12690
|
+
content = fs12.readFileSync(absPath, "utf8");
|
|
12517
12691
|
} catch (e) {
|
|
12518
12692
|
const msg = errorMessage(e);
|
|
12519
12693
|
logSrs13Failure(log, `read file file=${basename17}`, msg);
|
|
@@ -12620,7 +12794,7 @@ async function executeContextSrsDiscoveryUploadPhase(filePaths, phaseOpts, accum
|
|
|
12620
12794
|
const basename17 = path12.basename(absPath);
|
|
12621
12795
|
let content;
|
|
12622
12796
|
try {
|
|
12623
|
-
content =
|
|
12797
|
+
content = fs12.readFileSync(absPath, "utf8");
|
|
12624
12798
|
} catch (e) {
|
|
12625
12799
|
const msg = errorMessage(e);
|
|
12626
12800
|
logSrs13Failure(log, `read file file=${basename17}`, msg);
|
|
@@ -12645,7 +12819,7 @@ async function executeContextSrsDiscoveryUploadPhase(filePaths, phaseOpts, accum
|
|
|
12645
12819
|
const bn = path12.basename(onlyPath);
|
|
12646
12820
|
let singleContent;
|
|
12647
12821
|
try {
|
|
12648
|
-
singleContent =
|
|
12822
|
+
singleContent = fs12.readFileSync(onlyPath, "utf8");
|
|
12649
12823
|
} catch (e) {
|
|
12650
12824
|
const msg = errorMessage(e);
|
|
12651
12825
|
logSrs13Failure(log, `read file file=${bn}`, msg);
|
|
@@ -12786,6 +12960,73 @@ async function runUploadPipeline(opts) {
|
|
|
12786
12960
|
return { succeeded, failed, succeededIds };
|
|
12787
12961
|
}
|
|
12788
12962
|
|
|
12963
|
+
// src/cli/formatCliThrownUnknown.ts
|
|
12964
|
+
var MAX_ERROR_MESSAGE_LEN = 1200;
|
|
12965
|
+
var MAX_JSON_SNAPSHOT_LEN = 600;
|
|
12966
|
+
function isHttpApiErrorLike(e) {
|
|
12967
|
+
if (!e || typeof e !== "object" || Array.isArray(e)) {
|
|
12968
|
+
return false;
|
|
12969
|
+
}
|
|
12970
|
+
const o = e;
|
|
12971
|
+
if (typeof o.message !== "string" || o.message.trim().length === 0) {
|
|
12972
|
+
return false;
|
|
12973
|
+
}
|
|
12974
|
+
if (typeof o.status !== "number" || !Number.isFinite(o.status)) {
|
|
12975
|
+
return false;
|
|
12976
|
+
}
|
|
12977
|
+
return true;
|
|
12978
|
+
}
|
|
12979
|
+
function formatCliThrownUnknown(e, fallback = "Unknown error") {
|
|
12980
|
+
if (e == null) {
|
|
12981
|
+
return fallback;
|
|
12982
|
+
}
|
|
12983
|
+
if (isHttpApiErrorLike(e)) {
|
|
12984
|
+
return toAuthErrorMessage(e, fallback);
|
|
12985
|
+
}
|
|
12986
|
+
if (e instanceof Error) {
|
|
12987
|
+
const m = e.message.trim();
|
|
12988
|
+
if (m.length === 0) {
|
|
12989
|
+
return fallback;
|
|
12990
|
+
}
|
|
12991
|
+
return m.length > MAX_ERROR_MESSAGE_LEN ? `${m.slice(0, MAX_ERROR_MESSAGE_LEN)}\u2026` : m;
|
|
12992
|
+
}
|
|
12993
|
+
if (typeof e === "string") {
|
|
12994
|
+
const t = e.trim();
|
|
12995
|
+
return t.length > 0 ? t : fallback;
|
|
12996
|
+
}
|
|
12997
|
+
if (typeof e === "number" || typeof e === "boolean" || typeof e === "bigint") {
|
|
12998
|
+
return String(e);
|
|
12999
|
+
}
|
|
13000
|
+
if (typeof e === "object") {
|
|
13001
|
+
try {
|
|
13002
|
+
const s = JSON.stringify(e);
|
|
13003
|
+
if (s.length === 0) {
|
|
13004
|
+
return fallback;
|
|
13005
|
+
}
|
|
13006
|
+
return s.length > MAX_JSON_SNAPSHOT_LEN ? `${s.slice(0, MAX_JSON_SNAPSHOT_LEN - 1)}\u2026` : s;
|
|
13007
|
+
} catch {
|
|
13008
|
+
return fallback;
|
|
13009
|
+
}
|
|
13010
|
+
}
|
|
13011
|
+
return fallback;
|
|
13012
|
+
}
|
|
13013
|
+
function exitCodeForThrownHttpApiError(e) {
|
|
13014
|
+
if (!isHttpApiErrorLike(e)) {
|
|
13015
|
+
return void 0;
|
|
13016
|
+
}
|
|
13017
|
+
const { status } = e;
|
|
13018
|
+
if (status === 401) {
|
|
13019
|
+
return ExitCode.auth;
|
|
13020
|
+
}
|
|
13021
|
+
if (status === 0) {
|
|
13022
|
+
return ExitCode.misconfiguration;
|
|
13023
|
+
}
|
|
13024
|
+
if (status >= 400 && status <= 599 && status !== 401) {
|
|
13025
|
+
return ExitCode.upload;
|
|
13026
|
+
}
|
|
13027
|
+
return void 0;
|
|
13028
|
+
}
|
|
13029
|
+
|
|
12789
13030
|
// src/cli/cloudContextUploadCli.ts
|
|
12790
13031
|
function buildUploadPrimaryJsonSrs46(args) {
|
|
12791
13032
|
const out = {
|
|
@@ -12805,7 +13046,7 @@ async function fetchUploadCloudContextStatusWithR8Policy(args) {
|
|
|
12805
13046
|
timeoutMs: args.timeoutMs
|
|
12806
13047
|
});
|
|
12807
13048
|
} catch (e) {
|
|
12808
|
-
const msg =
|
|
13049
|
+
const msg = formatCliThrownUnknown(e);
|
|
12809
13050
|
return {
|
|
12810
13051
|
contextAnalyzedInCloud: false,
|
|
12811
13052
|
contextAnalyzedInCloudAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -12842,7 +13083,7 @@ function redactEasyspecsConfigRootForDump(cfg) {
|
|
|
12842
13083
|
}
|
|
12843
13084
|
|
|
12844
13085
|
// src/cli/cliFileWorkspaceState.ts
|
|
12845
|
-
var
|
|
13086
|
+
var fs13 = __toESM(require("node:fs"));
|
|
12846
13087
|
var path13 = __toESM(require("node:path"));
|
|
12847
13088
|
|
|
12848
13089
|
// src/srs53PersistedStateMigration.ts
|
|
@@ -12912,20 +13153,20 @@ function applySrs53PersistedStateMigrationInPlace(m) {
|
|
|
12912
13153
|
function createFileBackedWorkspaceState(repoRoot) {
|
|
12913
13154
|
const dir = path13.join(repoRoot, ".gluecharm", "logs");
|
|
12914
13155
|
const file = path13.join(dir, "easyspecs-cli-workspace-state.json");
|
|
12915
|
-
|
|
13156
|
+
fs13.mkdirSync(dir, { recursive: true });
|
|
12916
13157
|
const load = () => {
|
|
12917
13158
|
try {
|
|
12918
|
-
if (!
|
|
13159
|
+
if (!fs13.existsSync(file)) {
|
|
12919
13160
|
return {};
|
|
12920
13161
|
}
|
|
12921
|
-
const j = JSON.parse(
|
|
13162
|
+
const j = JSON.parse(fs13.readFileSync(file, "utf8"));
|
|
12922
13163
|
return typeof j === "object" && j !== null && !Array.isArray(j) ? j : {};
|
|
12923
13164
|
} catch {
|
|
12924
13165
|
return {};
|
|
12925
13166
|
}
|
|
12926
13167
|
};
|
|
12927
13168
|
const save = (m) => {
|
|
12928
|
-
|
|
13169
|
+
fs13.writeFileSync(file, `${JSON.stringify(m, null, 2)}
|
|
12929
13170
|
`, "utf8");
|
|
12930
13171
|
};
|
|
12931
13172
|
const m0 = load();
|
|
@@ -12951,11 +13192,11 @@ function createFileBackedWorkspaceState(repoRoot) {
|
|
|
12951
13192
|
}
|
|
12952
13193
|
|
|
12953
13194
|
// src/pipelines/synthesis/synthesisPipeline.ts
|
|
12954
|
-
var
|
|
13195
|
+
var fs36 = __toESM(require("fs"));
|
|
12955
13196
|
var path32 = __toESM(require("path"));
|
|
12956
13197
|
|
|
12957
13198
|
// src/analysis/analysisDynamicTestSteps.ts
|
|
12958
|
-
var
|
|
13199
|
+
var fs14 = __toESM(require("fs"));
|
|
12959
13200
|
var path14 = __toESM(require("path"));
|
|
12960
13201
|
var FE_CODE = /^FE-\d+$/;
|
|
12961
13202
|
var UC_CODE = /^UC-\d+$/;
|
|
@@ -12965,7 +13206,7 @@ function stripUtf8Bom(s) {
|
|
|
12965
13206
|
}
|
|
12966
13207
|
function readJson(filePath) {
|
|
12967
13208
|
try {
|
|
12968
|
-
const raw = stripUtf8Bom(
|
|
13209
|
+
const raw = stripUtf8Bom(fs14.readFileSync(filePath, "utf-8"));
|
|
12969
13210
|
return JSON.parse(raw);
|
|
12970
13211
|
} catch {
|
|
12971
13212
|
return null;
|
|
@@ -13087,7 +13328,7 @@ function safeFeatureName(v) {
|
|
|
13087
13328
|
}
|
|
13088
13329
|
function nonEmptyContextFile(absolutePath) {
|
|
13089
13330
|
try {
|
|
13090
|
-
const st =
|
|
13331
|
+
const st = fs14.statSync(absolutePath);
|
|
13091
13332
|
return st.isFile() && st.size > 0;
|
|
13092
13333
|
} catch {
|
|
13093
13334
|
return false;
|
|
@@ -13160,7 +13401,7 @@ function discoverDynamicAnalysisTestSteps(contextDir2) {
|
|
|
13160
13401
|
});
|
|
13161
13402
|
}
|
|
13162
13403
|
}
|
|
13163
|
-
const entityFieldsEmptyHint = !
|
|
13404
|
+
const entityFieldsEmptyHint = !fs14.existsSync(dmPath) || dmData === null ? "No data-model-list.json yet \u2014 run the data model list step after Materialize agents." : entityFieldsRuns.length === 0 ? "data-model-list.json has no valid DM-nn rows \u2014 run the data model step or edit that file." : "";
|
|
13164
13405
|
const expPath = path14.join(contextDir2, "experiences-list.json");
|
|
13165
13406
|
const expFileData = readJson(expPath);
|
|
13166
13407
|
const expTreeRows = discoverExperienceTreeRows(contextDir2);
|
|
@@ -13176,7 +13417,7 @@ function discoverDynamicAnalysisTestSteps(contextDir2) {
|
|
|
13176
13417
|
detailExists: nonEmptyContextFile(path14.join(contextDir2, `${row2.code}_${ix.code}-${ix.slug}.md`))
|
|
13177
13418
|
}))
|
|
13178
13419
|
}));
|
|
13179
|
-
const experienceEmptyHint = !
|
|
13420
|
+
const experienceEmptyHint = !fs14.existsSync(expPath) || expFileData === null ? "No experiences-list.json yet \u2014 run the experiences list step after Materialize agents." : experienceViewRuns.length === 0 ? "experiences-list.json has no valid XP-* views with resolvable URL-safe slugs (check code/slug fields and JSON syntax, including UTF-8 BOM)." : "";
|
|
13180
13421
|
const svcPath = path14.join(contextDir2, "services-list.json");
|
|
13181
13422
|
const svcFileData = readJson(svcPath);
|
|
13182
13423
|
const svcTreeRows = discoverServiceTreeRows(contextDir2);
|
|
@@ -13192,7 +13433,7 @@ function discoverDynamicAnalysisTestSteps(contextDir2) {
|
|
|
13192
13433
|
detailExists: nonEmptyContextFile(path14.join(contextDir2, `${row2.code}_${m.code}-${m.slug}.md`))
|
|
13193
13434
|
}))
|
|
13194
13435
|
}));
|
|
13195
|
-
const servicesEmptyHint = !
|
|
13436
|
+
const servicesEmptyHint = !fs14.existsSync(svcPath) || svcFileData === null ? "No services-list.json yet \u2014 run the services list step after Materialize agents." : serviceRuns.length === 0 ? "services-list.json has no valid SV-* services with resolvable URL-safe slugs (check code/slug fields and JSON syntax, including UTF-8 BOM)." : "";
|
|
13196
13437
|
const tsListPath = path14.join(contextDir2, "tech-stack-list.json");
|
|
13197
13438
|
const tsListFileData = readJson(tsListPath);
|
|
13198
13439
|
const toolTreeRows = discoverTechStackToolRows(contextDir2);
|
|
@@ -13202,8 +13443,8 @@ function discoverDynamicAnalysisTestSteps(contextDir2) {
|
|
|
13202
13443
|
slug: row2.slug,
|
|
13203
13444
|
toolDetailExists: nonEmptyContextFile(path14.join(contextDir2, `${row2.code}-${row2.slug}.md`))
|
|
13204
13445
|
}));
|
|
13205
|
-
const techStackEmptyHint = !
|
|
13206
|
-
const useCaseEmptyHint = !
|
|
13446
|
+
const techStackEmptyHint = !fs14.existsSync(tsListPath) || tsListFileData === null ? "No tech-stack-list.json yet \u2014 run the tech stack list step after Materialize agents." : techStackToolRuns.length === 0 ? "tech-stack-list.json has no valid TS-* tools with resolvable URL-safe slugs (check code/slug fields and JSON syntax, including UTF-8 BOM)." : "";
|
|
13447
|
+
const useCaseEmptyHint = !fs14.existsSync(featuresPath) || featuresData === null ? "No features-list.json yet \u2014 run step 3 (features list) after Materialize agents." : useCaseRuns.length === 0 ? "features-list.json has no valid FE-nn rows \u2014 run step 3 or edit that file." : "";
|
|
13207
13448
|
const scenarioEmptyHint = scenarioRuns.length === 0 ? useCaseRuns.length === 0 ? "Scenario runs appear after features exist and per-feature use-case lists define UC rows." : "Run a per-feature use case list (above) or add UC rows to each FE-nn-use-cases-list.json." : "";
|
|
13208
13449
|
return {
|
|
13209
13450
|
staticOutputs,
|
|
@@ -13223,11 +13464,11 @@ function discoverDynamicAnalysisTestSteps(contextDir2) {
|
|
|
13223
13464
|
}
|
|
13224
13465
|
|
|
13225
13466
|
// src/analysis/materializeOpenCodeAgents.ts
|
|
13226
|
-
var
|
|
13467
|
+
var fs17 = __toESM(require("fs"));
|
|
13227
13468
|
var path17 = __toESM(require("path"));
|
|
13228
13469
|
|
|
13229
13470
|
// src/analysis/applyAceMaterializedAgents.ts
|
|
13230
|
-
var
|
|
13471
|
+
var fs16 = __toESM(require("fs"));
|
|
13231
13472
|
var path16 = __toESM(require("path"));
|
|
13232
13473
|
|
|
13233
13474
|
// src/analysis/acePaths.ts
|
|
@@ -13282,7 +13523,7 @@ function opencodeAceSchemaPath(worktreeRoot, basename17) {
|
|
|
13282
13523
|
}
|
|
13283
13524
|
|
|
13284
13525
|
// src/analysis/aceJsonValidate.ts
|
|
13285
|
-
var
|
|
13526
|
+
var fs15 = __toESM(require("fs"));
|
|
13286
13527
|
var import__3 = __toESM(require__());
|
|
13287
13528
|
function stripUtf8Bom2(s) {
|
|
13288
13529
|
return s.length > 0 && s.charCodeAt(0) === 65279 ? s.slice(1) : s;
|
|
@@ -13300,7 +13541,7 @@ function formatAjvErrors3(errors) {
|
|
|
13300
13541
|
function validateAceJsonFile(jsonAbsolutePath, schemaAbsolutePath) {
|
|
13301
13542
|
let raw;
|
|
13302
13543
|
try {
|
|
13303
|
-
raw = stripUtf8Bom2(
|
|
13544
|
+
raw = stripUtf8Bom2(fs15.readFileSync(jsonAbsolutePath, "utf-8"));
|
|
13304
13545
|
} catch (e) {
|
|
13305
13546
|
return { ok: false, kind: "read", message: e instanceof Error ? e.message : String(e) };
|
|
13306
13547
|
}
|
|
@@ -13388,7 +13629,7 @@ function balancedJsonObjectFrom(s, start) {
|
|
|
13388
13629
|
function validateAceJsonValue(data, schemaAbsolutePath) {
|
|
13389
13630
|
let schemaRaw;
|
|
13390
13631
|
try {
|
|
13391
|
-
schemaRaw = stripUtf8Bom2(
|
|
13632
|
+
schemaRaw = stripUtf8Bom2(fs15.readFileSync(schemaAbsolutePath, "utf-8"));
|
|
13392
13633
|
} catch (e) {
|
|
13393
13634
|
return { ok: false, kind: "read", message: `Schema read failed: ${e instanceof Error ? e.message : String(e)}` };
|
|
13394
13635
|
}
|
|
@@ -13483,16 +13724,16 @@ function applyAceToMaterializedAgents(worktreeRoot, options) {
|
|
|
13483
13724
|
return;
|
|
13484
13725
|
}
|
|
13485
13726
|
const agentsDir = path16.join(worktreeRoot, ".opencode", "agents");
|
|
13486
|
-
if (!
|
|
13727
|
+
if (!fs16.existsSync(agentsDir) || !fs16.statSync(agentsDir).isDirectory()) {
|
|
13487
13728
|
log(`[ace] skip apply \u2014 missing agents dir: ${agentsDir}`);
|
|
13488
13729
|
return;
|
|
13489
13730
|
}
|
|
13490
13731
|
const contextDir2 = gluecharmContextDir(worktreeRoot);
|
|
13491
13732
|
const learningsRoot = aceLearningsRoot(contextDir2);
|
|
13492
|
-
|
|
13733
|
+
fs16.mkdirSync(learningsRoot, { recursive: true });
|
|
13493
13734
|
const playbookSchema = opencodeAceSchemaPath(worktreeRoot, ACE_SCHEMA_PLAYBOOK);
|
|
13494
13735
|
const overlaySchema = opencodeAceSchemaPath(worktreeRoot, ACE_SCHEMA_OVERLAY);
|
|
13495
|
-
const entries =
|
|
13736
|
+
const entries = fs16.readdirSync(agentsDir, { withFileTypes: true });
|
|
13496
13737
|
for (const e of entries) {
|
|
13497
13738
|
if (!e.isFile() || !e.name.endsWith(".md") || e.name === "README.md") {
|
|
13498
13739
|
continue;
|
|
@@ -13501,7 +13742,7 @@ function applyAceToMaterializedAgents(worktreeRoot, options) {
|
|
|
13501
13742
|
const agentPath = path16.join(agentsDir, e.name);
|
|
13502
13743
|
let raw;
|
|
13503
13744
|
try {
|
|
13504
|
-
raw =
|
|
13745
|
+
raw = fs16.readFileSync(agentPath, "utf-8");
|
|
13505
13746
|
} catch (err) {
|
|
13506
13747
|
log(`[ace] skip ${stem} \u2014 read failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
13507
13748
|
continue;
|
|
@@ -13514,7 +13755,7 @@ function applyAceToMaterializedAgents(worktreeRoot, options) {
|
|
|
13514
13755
|
const pbPath = acePlaybookPath(contextDir2, stem);
|
|
13515
13756
|
const ovPath = aceOverlayPath(contextDir2, stem);
|
|
13516
13757
|
let playbookDoc;
|
|
13517
|
-
if (
|
|
13758
|
+
if (fs16.existsSync(pbPath)) {
|
|
13518
13759
|
const v = validateAceJsonFile(pbPath, playbookSchema);
|
|
13519
13760
|
if (v.ok) {
|
|
13520
13761
|
const d = v.data;
|
|
@@ -13529,7 +13770,7 @@ ${v.errorsText.slice(0, 500)}` : ""}`
|
|
|
13529
13770
|
}
|
|
13530
13771
|
}
|
|
13531
13772
|
let overlayDoc;
|
|
13532
|
-
if (
|
|
13773
|
+
if (fs16.existsSync(ovPath)) {
|
|
13533
13774
|
const v = validateAceJsonFile(ovPath, overlaySchema);
|
|
13534
13775
|
if (v.ok) {
|
|
13535
13776
|
overlayDoc = v.data;
|
|
@@ -13560,7 +13801,7 @@ ${extra}
|
|
|
13560
13801
|
|
|
13561
13802
|
${extra}
|
|
13562
13803
|
`;
|
|
13563
|
-
|
|
13804
|
+
fs16.writeFileSync(agentPath, out, "utf-8");
|
|
13564
13805
|
log(`[ace] merged playbook/overlay into materialized agent: ${e.name}`);
|
|
13565
13806
|
}
|
|
13566
13807
|
}
|
|
@@ -13622,9 +13863,9 @@ function ensureAnalysisOpenCodePermissionsConfig(analysisCheckoutRoot, projectCo
|
|
|
13622
13863
|
};
|
|
13623
13864
|
const configPath = path17.join(root, "opencode.json");
|
|
13624
13865
|
let cfg = {};
|
|
13625
|
-
if (
|
|
13866
|
+
if (fs17.existsSync(configPath)) {
|
|
13626
13867
|
try {
|
|
13627
|
-
const raw =
|
|
13868
|
+
const raw = fs17.readFileSync(configPath, "utf-8");
|
|
13628
13869
|
const parsed = JSON.parse(raw);
|
|
13629
13870
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
13630
13871
|
cfg = { ...parsed };
|
|
@@ -13647,27 +13888,27 @@ function ensureAnalysisOpenCodePermissionsConfig(analysisCheckoutRoot, projectCo
|
|
|
13647
13888
|
if (projectConfigOverlay && Object.keys(projectConfigOverlay).length > 0) {
|
|
13648
13889
|
cfg = mergeDeepUnknown(cfg, projectConfigOverlay);
|
|
13649
13890
|
}
|
|
13650
|
-
|
|
13891
|
+
fs17.writeFileSync(configPath, `${JSON.stringify(cfg, null, 2)}
|
|
13651
13892
|
`, "utf-8");
|
|
13652
13893
|
}
|
|
13653
13894
|
function copyRecursive(src, dest) {
|
|
13654
|
-
|
|
13655
|
-
const entries =
|
|
13895
|
+
fs17.mkdirSync(dest, { recursive: true });
|
|
13896
|
+
const entries = fs17.readdirSync(src, { withFileTypes: true });
|
|
13656
13897
|
for (const e of entries) {
|
|
13657
13898
|
const s = path17.join(src, e.name);
|
|
13658
13899
|
const d = path17.join(dest, e.name);
|
|
13659
13900
|
if (e.isDirectory()) {
|
|
13660
13901
|
copyRecursive(s, d);
|
|
13661
13902
|
} else {
|
|
13662
|
-
|
|
13903
|
+
fs17.copyFileSync(s, d);
|
|
13663
13904
|
}
|
|
13664
13905
|
}
|
|
13665
13906
|
}
|
|
13666
13907
|
function materializeOpenCodeAgents(extensionResourcesAgents, analysisCheckoutRoot, projectConfigOverlay) {
|
|
13667
13908
|
const dest = path17.join(analysisCheckoutRoot, ".opencode", "agents");
|
|
13668
|
-
if (!
|
|
13669
|
-
|
|
13670
|
-
|
|
13909
|
+
if (!fs17.existsSync(extensionResourcesAgents)) {
|
|
13910
|
+
fs17.mkdirSync(dest, { recursive: true });
|
|
13911
|
+
fs17.writeFileSync(
|
|
13671
13912
|
path17.join(dest, "README.md"),
|
|
13672
13913
|
"# OpenCode agents\n\nPlaceholder: add agent configs here. Bundled folder was missing at materialize time.\n",
|
|
13673
13914
|
"utf-8"
|
|
@@ -13677,12 +13918,12 @@ function materializeOpenCodeAgents(extensionResourcesAgents, analysisCheckoutRoo
|
|
|
13677
13918
|
}
|
|
13678
13919
|
copyRecursive(extensionResourcesAgents, dest);
|
|
13679
13920
|
const schemasSrc = path17.join(path17.dirname(extensionResourcesAgents), "schemas", "context-lists");
|
|
13680
|
-
if (
|
|
13921
|
+
if (fs17.existsSync(schemasSrc)) {
|
|
13681
13922
|
const schemasDest = path17.join(analysisCheckoutRoot, ".opencode", "schemas", "context-lists");
|
|
13682
13923
|
copyRecursive(schemasSrc, schemasDest);
|
|
13683
13924
|
}
|
|
13684
13925
|
const aceSchemasSrc = path17.join(path17.dirname(extensionResourcesAgents), "schemas", "ace");
|
|
13685
|
-
if (
|
|
13926
|
+
if (fs17.existsSync(aceSchemasSrc)) {
|
|
13686
13927
|
const aceSchemasDest = path17.join(analysisCheckoutRoot, ".opencode", "schemas", "ace");
|
|
13687
13928
|
copyRecursive(aceSchemasSrc, aceSchemasDest);
|
|
13688
13929
|
}
|
|
@@ -13694,7 +13935,7 @@ function materializeOpenCodeAgentsWithAce(extensionResourcesAgents, analysisChec
|
|
|
13694
13935
|
}
|
|
13695
13936
|
|
|
13696
13937
|
// src/workstations/aiWorkstation.ts
|
|
13697
|
-
var
|
|
13938
|
+
var fs30 = __toESM(require("fs"));
|
|
13698
13939
|
var path26 = __toESM(require("path"));
|
|
13699
13940
|
|
|
13700
13941
|
// src/analysis/promptTemplates.ts
|
|
@@ -13846,12 +14087,11 @@ function synthesisStepLabel(step, ctx) {
|
|
|
13846
14087
|
}
|
|
13847
14088
|
|
|
13848
14089
|
// src/analysis/aceTracePhase.ts
|
|
13849
|
-
var
|
|
14090
|
+
var fs23 = __toESM(require("fs"));
|
|
13850
14091
|
var path21 = __toESM(require("path"));
|
|
13851
14092
|
|
|
13852
14093
|
// src/opencodeCli.ts
|
|
13853
|
-
var
|
|
13854
|
-
var import_node_events = require("node:events");
|
|
14094
|
+
var import_child_process2 = require("child_process");
|
|
13855
14095
|
|
|
13856
14096
|
// src/analysis/openCodeSessionStewardship.ts
|
|
13857
14097
|
var TITLE_MAX_LEN = 80;
|
|
@@ -13975,8 +14215,140 @@ function logOpenCodeSessionFollowUpStart(diagnosticLog, p) {
|
|
|
13975
14215
|
);
|
|
13976
14216
|
}
|
|
13977
14217
|
|
|
14218
|
+
// src/opencodeSpawnDiagnostics.ts
|
|
14219
|
+
var import_child_process = require("child_process");
|
|
14220
|
+
var fs18 = __toESM(require("fs"));
|
|
14221
|
+
var os2 = __toESM(require("os"));
|
|
14222
|
+
function defaultCpusLogical() {
|
|
14223
|
+
const ap = os2.availableParallelism?.();
|
|
14224
|
+
if (typeof ap === "number" && Number.isFinite(ap) && ap >= 1) {
|
|
14225
|
+
return ap;
|
|
14226
|
+
}
|
|
14227
|
+
const n = os2.cpus()?.length ?? 1;
|
|
14228
|
+
return Math.max(1, n);
|
|
14229
|
+
}
|
|
14230
|
+
function collectHostSnapshot(deps) {
|
|
14231
|
+
const totalmem3 = deps?.totalmem ?? (() => os2.totalmem());
|
|
14232
|
+
const freemem2 = deps?.freemem ?? (() => os2.freemem());
|
|
14233
|
+
const loadavg3 = deps?.loadavg ?? (() => os2.loadavg());
|
|
14234
|
+
const cpusLogicalFn = deps?.cpusLogical ?? defaultCpusLogical;
|
|
14235
|
+
const total = Math.max(0, Math.floor(totalmem3()));
|
|
14236
|
+
const free = Math.max(0, Math.floor(freemem2()));
|
|
14237
|
+
const used = Math.max(0, total - free);
|
|
14238
|
+
const cpusLogical = Math.max(1, Math.floor(cpusLogicalFn()));
|
|
14239
|
+
const la = loadavg3();
|
|
14240
|
+
const raw = Array.isArray(la) && la.length > 0 ? la[0] : NaN;
|
|
14241
|
+
const load1 = Number.isFinite(raw) && raw >= 0 ? raw : null;
|
|
14242
|
+
const load1PerCpu = load1 === null ? null : load1 / cpusLogical;
|
|
14243
|
+
return {
|
|
14244
|
+
hostRamTotalB: total,
|
|
14245
|
+
hostRamFreeB: free,
|
|
14246
|
+
hostRamUsedB: used,
|
|
14247
|
+
load1,
|
|
14248
|
+
cpusLogical,
|
|
14249
|
+
load1PerCpu
|
|
14250
|
+
};
|
|
14251
|
+
}
|
|
14252
|
+
function formatHostSnapshotLine(procTag, childPid, s) {
|
|
14253
|
+
const load1Str = s.load1 === null ? "unknown" : String(s.load1);
|
|
14254
|
+
const perCpuStr = s.load1PerCpu === null ? "unknown" : String(s.load1PerCpu);
|
|
14255
|
+
return `${procTag} scope=host childPid=${childPid} hostRamTotalB=${s.hostRamTotalB} hostRamFreeB=${s.hostRamFreeB} hostRamUsedB=${s.hostRamUsedB} load1=${load1Str} cpusLogical=${s.cpusLogical} load1PerCpu=${perCpuStr}`;
|
|
14256
|
+
}
|
|
14257
|
+
function parseVmRssKilobytesFromProcStatus(content) {
|
|
14258
|
+
for (const line of content.split(/\r?\n/)) {
|
|
14259
|
+
const m = /^\s*VmRSS:\s*(\d+)\s*kB/i.exec(line);
|
|
14260
|
+
if (m) {
|
|
14261
|
+
const kb = Number(m[1]);
|
|
14262
|
+
return Number.isFinite(kb) && kb >= 0 ? kb : null;
|
|
14263
|
+
}
|
|
14264
|
+
}
|
|
14265
|
+
return null;
|
|
14266
|
+
}
|
|
14267
|
+
function parsePsRssDarwinKilobytes(stdout) {
|
|
14268
|
+
const t = stdout.trim();
|
|
14269
|
+
if (!t) {
|
|
14270
|
+
return null;
|
|
14271
|
+
}
|
|
14272
|
+
const first = t.split(/\s+/)[0] ?? "";
|
|
14273
|
+
const n = Number(first);
|
|
14274
|
+
if (!Number.isFinite(n) || n < 0) {
|
|
14275
|
+
return null;
|
|
14276
|
+
}
|
|
14277
|
+
return n;
|
|
14278
|
+
}
|
|
14279
|
+
function readLinuxPidRssBytes(pid) {
|
|
14280
|
+
const path60 = `/proc/${pid}/status`;
|
|
14281
|
+
try {
|
|
14282
|
+
const content = fs18.readFileSync(path60, "utf8");
|
|
14283
|
+
const kb = parseVmRssKilobytesFromProcStatus(content);
|
|
14284
|
+
if (kb === null) {
|
|
14285
|
+
return { kind: "unknown", reason: "VmRSS_missing" };
|
|
14286
|
+
}
|
|
14287
|
+
return { kind: "ok", bytes: Math.floor(kb * 1024) };
|
|
14288
|
+
} catch (e) {
|
|
14289
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
14290
|
+
return { kind: "unknown", reason: truncateReason(msg) };
|
|
14291
|
+
}
|
|
14292
|
+
}
|
|
14293
|
+
function readDarwinPidRssBytes(pid) {
|
|
14294
|
+
try {
|
|
14295
|
+
const out = (0, import_child_process.execFileSync)("ps", ["-o", "rss=", "-p", String(pid)], {
|
|
14296
|
+
encoding: "utf8",
|
|
14297
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
14298
|
+
maxBuffer: 64 * 1024
|
|
14299
|
+
});
|
|
14300
|
+
const kb = parsePsRssDarwinKilobytes(out);
|
|
14301
|
+
if (kb === null) {
|
|
14302
|
+
return { kind: "unknown", reason: "ps_parse" };
|
|
14303
|
+
}
|
|
14304
|
+
return { kind: "ok", bytes: Math.floor(kb * 1024) };
|
|
14305
|
+
} catch (e) {
|
|
14306
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
14307
|
+
return { kind: "unknown", reason: truncateReason(msg) };
|
|
14308
|
+
}
|
|
14309
|
+
}
|
|
14310
|
+
var MAX_RSS_REASON = 48;
|
|
14311
|
+
function truncateReason(s) {
|
|
14312
|
+
const one = s.replace(/\s+/g, " ").trim();
|
|
14313
|
+
if (one.length <= MAX_RSS_REASON) {
|
|
14314
|
+
return one;
|
|
14315
|
+
}
|
|
14316
|
+
return `${one.slice(0, MAX_RSS_REASON - 3)}...`;
|
|
14317
|
+
}
|
|
14318
|
+
function readProcessRssBytes(pid) {
|
|
14319
|
+
if (!Number.isFinite(pid) || pid <= 0) {
|
|
14320
|
+
return { kind: "unknown", reason: "bad_pid" };
|
|
14321
|
+
}
|
|
14322
|
+
const plat = process.platform;
|
|
14323
|
+
if (plat === "linux") {
|
|
14324
|
+
return readLinuxPidRssBytes(pid);
|
|
14325
|
+
}
|
|
14326
|
+
if (plat === "darwin") {
|
|
14327
|
+
return readDarwinPidRssBytes(pid);
|
|
14328
|
+
}
|
|
14329
|
+
return { kind: "unknown", reason: "platform" };
|
|
14330
|
+
}
|
|
14331
|
+
function formatChildResourceLine(procTag, childPid, childCpuMs, rss) {
|
|
14332
|
+
const cpu = Math.max(0, Math.round(childCpuMs));
|
|
14333
|
+
if (rss.kind === "ok") {
|
|
14334
|
+
return `${procTag} scope=child childPid=${childPid} childCpuMs=${cpu} childRssBytes=${rss.bytes}`;
|
|
14335
|
+
}
|
|
14336
|
+
const esc = rss.reason.replace(/\\/g, "\\\\").replace(/\s+/g, " ");
|
|
14337
|
+
return `${procTag} scope=child childPid=${childPid} childCpuMs=${cpu} childRssBytes=unknown rssErr=${esc}`;
|
|
14338
|
+
}
|
|
14339
|
+
function childCpuTimeMsFromUsageDelta(delta) {
|
|
14340
|
+
const us = Math.max(0, delta.user) + Math.max(0, delta.system);
|
|
14341
|
+
return Math.round(us / 1e3);
|
|
14342
|
+
}
|
|
14343
|
+
function subprocessCpuUsage(proc, previous) {
|
|
14344
|
+
const p = proc;
|
|
14345
|
+
if (typeof p.cpuUsage !== "function") {
|
|
14346
|
+
return { user: 0, system: 0 };
|
|
14347
|
+
}
|
|
14348
|
+
return previous === void 0 ? p.cpuUsage() : p.cpuUsage(previous);
|
|
14349
|
+
}
|
|
14350
|
+
|
|
13978
14351
|
// src/opencodeCli.ts
|
|
13979
|
-
var SHARED_OPEN_CODE_ABORT_LISTENER_BUDGET = 512;
|
|
13980
14352
|
var USE_SHELL = process.platform === "win32";
|
|
13981
14353
|
function resolveExecutable(executable) {
|
|
13982
14354
|
const t = executable?.trim();
|
|
@@ -13984,7 +14356,7 @@ function resolveExecutable(executable) {
|
|
|
13984
14356
|
}
|
|
13985
14357
|
function spawnCliSync(executable, args, cwd, timeoutMs, env) {
|
|
13986
14358
|
const mergedEnv = env ? { ...process.env, ...env } : process.env;
|
|
13987
|
-
return (0,
|
|
14359
|
+
return (0, import_child_process2.spawnSync)(executable, args, {
|
|
13988
14360
|
encoding: "utf-8",
|
|
13989
14361
|
cwd,
|
|
13990
14362
|
shell: USE_SHELL,
|
|
@@ -14101,12 +14473,36 @@ function runOpenCodeAgent(cwd, args, options) {
|
|
|
14101
14473
|
return;
|
|
14102
14474
|
}
|
|
14103
14475
|
const spawnEnv = options?.childEnv && Object.keys(options.childEnv).length > 0 ? { ...process.env, ...options.childEnv } : process.env;
|
|
14104
|
-
const child = (0,
|
|
14476
|
+
const child = (0, import_child_process2.spawn)(cmd, args, {
|
|
14105
14477
|
cwd,
|
|
14106
14478
|
shell: USE_SHELL,
|
|
14107
14479
|
env: spawnEnv,
|
|
14108
14480
|
stdio: ["ignore", "pipe", "pipe"]
|
|
14109
14481
|
});
|
|
14482
|
+
let childResourceLogged = false;
|
|
14483
|
+
let cpuBaseline;
|
|
14484
|
+
const tryEmitChildResourceDiag = () => {
|
|
14485
|
+
if (childResourceLogged || !log) {
|
|
14486
|
+
return;
|
|
14487
|
+
}
|
|
14488
|
+
if (typeof child.pid !== "number" || child.pid <= 0 || !cpuBaseline) {
|
|
14489
|
+
return;
|
|
14490
|
+
}
|
|
14491
|
+
childResourceLogged = true;
|
|
14492
|
+
let delta;
|
|
14493
|
+
try {
|
|
14494
|
+
delta = subprocessCpuUsage(child, cpuBaseline);
|
|
14495
|
+
} catch {
|
|
14496
|
+
delta = { user: 0, system: 0 };
|
|
14497
|
+
}
|
|
14498
|
+
const cpuMs = childCpuTimeMsFromUsageDelta(delta);
|
|
14499
|
+
const rss = readProcessRssBytes(child.pid);
|
|
14500
|
+
log(formatChildResourceLine(procTag, child.pid, cpuMs, rss));
|
|
14501
|
+
};
|
|
14502
|
+
if (log && typeof child.pid === "number" && child.pid > 0) {
|
|
14503
|
+
log(formatHostSnapshotLine(procTag, child.pid, collectHostSnapshot()));
|
|
14504
|
+
cpuBaseline = subprocessCpuUsage(child);
|
|
14505
|
+
}
|
|
14110
14506
|
options?.onAgentLaunched?.();
|
|
14111
14507
|
let stdout = "";
|
|
14112
14508
|
let stderr = "";
|
|
@@ -14164,6 +14560,7 @@ ${truncateForDiag(outBody, DIAG_STDOUT_MAX)}`);
|
|
|
14164
14560
|
return;
|
|
14165
14561
|
}
|
|
14166
14562
|
settled = true;
|
|
14563
|
+
tryEmitChildResourceDiag();
|
|
14167
14564
|
if (diag) {
|
|
14168
14565
|
finishDiag(diag.label, diag.code, diag.dumpStreams);
|
|
14169
14566
|
}
|
|
@@ -14177,9 +14574,6 @@ ${truncateForDiag(outBody, DIAG_STDOUT_MAX)}`);
|
|
|
14177
14574
|
}
|
|
14178
14575
|
};
|
|
14179
14576
|
if (sig) {
|
|
14180
|
-
if ((0, import_node_events.getMaxListeners)(sig) < SHARED_OPEN_CODE_ABORT_LISTENER_BUDGET) {
|
|
14181
|
-
(0, import_node_events.setMaxListeners)(SHARED_OPEN_CODE_ABORT_LISTENER_BUDGET, sig);
|
|
14182
|
-
}
|
|
14183
14577
|
onAbort = () => {
|
|
14184
14578
|
child.kill("SIGTERM");
|
|
14185
14579
|
settle(
|
|
@@ -14245,7 +14639,7 @@ ${truncateForDiag(outBody, DIAG_STDOUT_MAX)}`);
|
|
|
14245
14639
|
}
|
|
14246
14640
|
|
|
14247
14641
|
// src/analysis/aceTraceNormalize.ts
|
|
14248
|
-
var
|
|
14642
|
+
var fs19 = __toESM(require("fs"));
|
|
14249
14643
|
var ACE_VERSION = "1.0.0-draft";
|
|
14250
14644
|
var REASONING_PHASES = /* @__PURE__ */ new Set([
|
|
14251
14645
|
"explore",
|
|
@@ -14390,7 +14784,7 @@ function sanitizePlaybookHooks(input) {
|
|
|
14390
14784
|
function rewriteAceTraceFileWithCanonicalEnvelope(traceAbsolutePath, canonical, diagnosticLog) {
|
|
14391
14785
|
let raw;
|
|
14392
14786
|
try {
|
|
14393
|
-
raw =
|
|
14787
|
+
raw = fs19.readFileSync(traceAbsolutePath, "utf-8");
|
|
14394
14788
|
} catch (e) {
|
|
14395
14789
|
diagnosticLog?.(`[ace] trace normalize read failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
14396
14790
|
return false;
|
|
@@ -14435,7 +14829,7 @@ function rewriteAceTraceFileWithCanonicalEnvelope(traceAbsolutePath, canonical,
|
|
|
14435
14829
|
doc.playbookHooks = hooks;
|
|
14436
14830
|
}
|
|
14437
14831
|
try {
|
|
14438
|
-
|
|
14832
|
+
fs19.writeFileSync(traceAbsolutePath, `${JSON.stringify(doc, null, 2)}
|
|
14439
14833
|
`, "utf-8");
|
|
14440
14834
|
} catch (e) {
|
|
14441
14835
|
diagnosticLog?.(`[ace] trace normalize write failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -14446,15 +14840,15 @@ function rewriteAceTraceFileWithCanonicalEnvelope(traceAbsolutePath, canonical,
|
|
|
14446
14840
|
}
|
|
14447
14841
|
|
|
14448
14842
|
// src/analysis/aceOfflineLearn.ts
|
|
14449
|
-
var
|
|
14843
|
+
var fs22 = __toESM(require("fs"));
|
|
14450
14844
|
var path20 = __toESM(require("path"));
|
|
14451
14845
|
|
|
14452
14846
|
// src/analysis/aceCuratorApplier.ts
|
|
14453
|
-
var
|
|
14847
|
+
var fs20 = __toESM(require("fs"));
|
|
14454
14848
|
var path18 = __toESM(require("path"));
|
|
14455
14849
|
function writeJson(pathAbs, obj) {
|
|
14456
|
-
|
|
14457
|
-
|
|
14850
|
+
fs20.mkdirSync(path18.dirname(pathAbs), { recursive: true });
|
|
14851
|
+
fs20.writeFileSync(pathAbs, `${JSON.stringify(obj, null, 2)}
|
|
14458
14852
|
`, "utf-8");
|
|
14459
14853
|
}
|
|
14460
14854
|
function emptyPlaybook(agentStem) {
|
|
@@ -14480,7 +14874,7 @@ function applyAceCuratorDeltaFile(worktreeRoot, deltaAbsolutePath, log) {
|
|
|
14480
14874
|
const pbPath = acePlaybookPath(contextDir2, agentStem);
|
|
14481
14875
|
const ovPath = aceOverlayPath(contextDir2, agentStem);
|
|
14482
14876
|
let playbook;
|
|
14483
|
-
if (
|
|
14877
|
+
if (fs20.existsSync(pbPath)) {
|
|
14484
14878
|
const pv = validateAceJsonFile(pbPath, playbookSchema);
|
|
14485
14879
|
if (!pv.ok) {
|
|
14486
14880
|
return { ok: false, message: `Existing playbook invalid: ${pv.message}` };
|
|
@@ -14490,7 +14884,7 @@ function applyAceCuratorDeltaFile(worktreeRoot, deltaAbsolutePath, log) {
|
|
|
14490
14884
|
playbook = emptyPlaybook(agentStem);
|
|
14491
14885
|
}
|
|
14492
14886
|
let overlay;
|
|
14493
|
-
if (
|
|
14887
|
+
if (fs20.existsSync(ovPath)) {
|
|
14494
14888
|
const ov = validateAceJsonFile(ovPath, overlaySchema);
|
|
14495
14889
|
if (!ov.ok) {
|
|
14496
14890
|
return { ok: false, message: `Existing overlay invalid: ${ov.message}` };
|
|
@@ -14568,7 +14962,7 @@ function applyAceCuratorDeltaFile(worktreeRoot, deltaAbsolutePath, log) {
|
|
|
14568
14962
|
}
|
|
14569
14963
|
|
|
14570
14964
|
// src/analysis/aceOfflineLearnFallbacks.ts
|
|
14571
|
-
var
|
|
14965
|
+
var fs21 = __toESM(require("fs"));
|
|
14572
14966
|
var path19 = __toESM(require("path"));
|
|
14573
14967
|
var ACE_VERSION2 = "1.0.0-draft";
|
|
14574
14968
|
function buildEmptyReflectorLessons(traceRelativePath, sessionRunId) {
|
|
@@ -14593,8 +14987,8 @@ function buildEmptyCuratorDelta(agentStem, lessonsRelativePath) {
|
|
|
14593
14987
|
function appendAceConsolidatedSessionRecord(contextDir2, record, diagnosticLog) {
|
|
14594
14988
|
const abs = aceConsolidatedSessionsJsonlPath(contextDir2);
|
|
14595
14989
|
const rel = path19.relative(contextDir2, abs).split(path19.sep).join("/");
|
|
14596
|
-
|
|
14597
|
-
|
|
14990
|
+
fs21.mkdirSync(aceLearningsRoot(contextDir2), { recursive: true });
|
|
14991
|
+
fs21.appendFileSync(abs, `${JSON.stringify(record)}
|
|
14598
14992
|
`, "utf-8");
|
|
14599
14993
|
diagnosticLog?.(`[ace] consolidated session record appended \u2014 ${rel}`);
|
|
14600
14994
|
}
|
|
@@ -14616,7 +15010,7 @@ function safeRunIdSegment(runId) {
|
|
|
14616
15010
|
}
|
|
14617
15011
|
function readHead(p, max) {
|
|
14618
15012
|
try {
|
|
14619
|
-
const raw =
|
|
15013
|
+
const raw = fs22.readFileSync(p, "utf-8");
|
|
14620
15014
|
return raw.length <= max ? raw : `${raw.slice(0, max)}
|
|
14621
15015
|
\u2026 (truncated)`;
|
|
14622
15016
|
} catch {
|
|
@@ -14625,12 +15019,12 @@ function readHead(p, max) {
|
|
|
14625
15019
|
}
|
|
14626
15020
|
function listAceTraceFiles(contextDir2) {
|
|
14627
15021
|
const root = path20.join(aceLearningsRoot(contextDir2), "traces");
|
|
14628
|
-
if (!
|
|
15022
|
+
if (!fs22.existsSync(root)) {
|
|
14629
15023
|
return [];
|
|
14630
15024
|
}
|
|
14631
15025
|
const out = [];
|
|
14632
15026
|
const walk = (dir) => {
|
|
14633
|
-
for (const e of
|
|
15027
|
+
for (const e of fs22.readdirSync(dir, { withFileTypes: true })) {
|
|
14634
15028
|
const full = path20.join(dir, e.name);
|
|
14635
15029
|
if (e.isDirectory()) {
|
|
14636
15030
|
walk(full);
|
|
@@ -14658,14 +15052,14 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14658
15052
|
const traceRel = path20.relative(contextDir2, traceAbsolutePath).split(path20.sep).join("/");
|
|
14659
15053
|
const lessonsAbs = aceReflectionPath(contextDir2, agentStem, safeId);
|
|
14660
15054
|
const deltaAbs = aceCurationPath(contextDir2, agentStem, safeId);
|
|
14661
|
-
|
|
14662
|
-
|
|
15055
|
+
fs22.mkdirSync(path20.dirname(lessonsAbs), { recursive: true });
|
|
15056
|
+
fs22.mkdirSync(path20.dirname(deltaAbs), { recursive: true });
|
|
14663
15057
|
const pbPath = path20.join(aceLearningsRoot(contextDir2), `${agentStem}.json`);
|
|
14664
15058
|
const ovPath = path20.join(aceLearningsRoot(contextDir2), "overlays", `${agentStem}.json`);
|
|
14665
|
-
const pbExcerpt =
|
|
14666
|
-
const ovExcerpt =
|
|
15059
|
+
const pbExcerpt = fs22.existsSync(pbPath) ? readHead(pbPath, 6e3) : "(no playbook yet)";
|
|
15060
|
+
const ovExcerpt = fs22.existsSync(ovPath) ? readHead(ovPath, 4e3) : "(no overlay yet)";
|
|
14667
15061
|
const runDir = path20.join(opts.worktreeRoot, ".opencode", "_run");
|
|
14668
|
-
|
|
15062
|
+
fs22.mkdirSync(runDir, { recursive: true });
|
|
14669
15063
|
let reflectorUsedEmptyFallback = false;
|
|
14670
15064
|
let curatorUsedEmptyFallback = false;
|
|
14671
15065
|
const reflectPrompt = [
|
|
@@ -14684,7 +15078,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14684
15078
|
"Schema: `aceSchemaVersion` **1.0.0-draft**, `sourceTrace`, `lessons` (see ace-reflector-lessons schema)."
|
|
14685
15079
|
].join("\n");
|
|
14686
15080
|
const reflectPromptPath = path20.join(runDir, `ace-reflect-${safeId}-${Date.now()}.prompt.txt`);
|
|
14687
|
-
|
|
15081
|
+
fs22.writeFileSync(reflectPromptPath, reflectPrompt, "utf-8");
|
|
14688
15082
|
const reflectVars = {
|
|
14689
15083
|
promptFile: reflectPromptPath,
|
|
14690
15084
|
agentId: ACE_REFLECTOR_AGENT_STEM,
|
|
@@ -14716,11 +15110,11 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14716
15110
|
if (!rCli.ok) {
|
|
14717
15111
|
return { ok: false, message: `[ace] reflector OpenCode failed: ${rCli.message}` };
|
|
14718
15112
|
}
|
|
14719
|
-
if (!
|
|
15113
|
+
if (!fs22.existsSync(lessonsAbs)) {
|
|
14720
15114
|
const recovered = extractJsonObjectWithTopLevelKeys(rCli.message, ["aceSchemaVersion", "sourceTrace", "lessons"]);
|
|
14721
15115
|
if (recovered) {
|
|
14722
15116
|
try {
|
|
14723
|
-
|
|
15117
|
+
fs22.writeFileSync(lessonsAbs, `${recovered}
|
|
14724
15118
|
`, "utf-8");
|
|
14725
15119
|
opts.diagnosticLog?.(`[ace] reflector recovered from OpenCode stdout/stderr \u2192 ${lessonsAbs}`);
|
|
14726
15120
|
} catch (e) {
|
|
@@ -14730,7 +15124,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14730
15124
|
}
|
|
14731
15125
|
}
|
|
14732
15126
|
}
|
|
14733
|
-
if (!
|
|
15127
|
+
if (!fs22.existsSync(lessonsAbs)) {
|
|
14734
15128
|
return { ok: false, message: `[ace] reflector output missing: ${lessonsAbs}` };
|
|
14735
15129
|
}
|
|
14736
15130
|
let lv = validateAceJsonFile(lessonsAbs, reflectorSchema);
|
|
@@ -14742,7 +15136,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14742
15136
|
]);
|
|
14743
15137
|
if (recoveredAgain) {
|
|
14744
15138
|
try {
|
|
14745
|
-
|
|
15139
|
+
fs22.writeFileSync(lessonsAbs, `${recoveredAgain}
|
|
14746
15140
|
`, "utf-8");
|
|
14747
15141
|
opts.diagnosticLog?.(`[ace] reflector re-recovered from CLI output after schema failure \u2192 ${lessonsAbs}`);
|
|
14748
15142
|
lv = validateAceJsonFile(lessonsAbs, reflectorSchema);
|
|
@@ -14756,7 +15150,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14756
15150
|
if (!lv.ok) {
|
|
14757
15151
|
const hint = lv.message.length > 220 ? `${lv.message.slice(0, 220)}\u2026` : lv.message;
|
|
14758
15152
|
opts.diagnosticLog?.(`[ace] reflector lessons failed schema \u2014 writing valid empty lessons \u2014 ${hint}`);
|
|
14759
|
-
|
|
15153
|
+
fs22.writeFileSync(
|
|
14760
15154
|
lessonsAbs,
|
|
14761
15155
|
`${JSON.stringify(buildEmptyReflectorLessons(traceRel, runId), null, 2)}
|
|
14762
15156
|
`,
|
|
@@ -14803,7 +15197,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14803
15197
|
"Schema: `aceSchemaVersion` **1.0.0-draft**, `agentStem`, `sourceLessons`, `operations` (see ace-curator-delta schema)."
|
|
14804
15198
|
].join("\n");
|
|
14805
15199
|
const curPromptPath = path20.join(runDir, `ace-curate-${safeId}-${Date.now()}.prompt.txt`);
|
|
14806
|
-
|
|
15200
|
+
fs22.writeFileSync(curPromptPath, curPrompt, "utf-8");
|
|
14807
15201
|
const curVars = {
|
|
14808
15202
|
promptFile: curPromptPath,
|
|
14809
15203
|
agentId: ACE_CURATOR_AGENT_STEM,
|
|
@@ -14834,7 +15228,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14834
15228
|
if (!cCli.ok) {
|
|
14835
15229
|
return { ok: false, message: `[ace] curator OpenCode failed: ${cCli.message}` };
|
|
14836
15230
|
}
|
|
14837
|
-
if (!
|
|
15231
|
+
if (!fs22.existsSync(deltaAbs)) {
|
|
14838
15232
|
const recovered = extractJsonObjectWithTopLevelKeys(cCli.message, [
|
|
14839
15233
|
"aceSchemaVersion",
|
|
14840
15234
|
"agentStem",
|
|
@@ -14843,7 +15237,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14843
15237
|
]);
|
|
14844
15238
|
if (recovered) {
|
|
14845
15239
|
try {
|
|
14846
|
-
|
|
15240
|
+
fs22.writeFileSync(deltaAbs, `${recovered}
|
|
14847
15241
|
`, "utf-8");
|
|
14848
15242
|
opts.diagnosticLog?.(`[ace] curator recovered from OpenCode stdout/stderr \u2192 ${deltaAbs}`);
|
|
14849
15243
|
} catch (e) {
|
|
@@ -14853,7 +15247,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14853
15247
|
}
|
|
14854
15248
|
}
|
|
14855
15249
|
}
|
|
14856
|
-
if (!
|
|
15250
|
+
if (!fs22.existsSync(deltaAbs)) {
|
|
14857
15251
|
return { ok: false, message: `[ace] curator output missing: ${deltaAbs}` };
|
|
14858
15252
|
}
|
|
14859
15253
|
let dv = validateAceJsonFile(deltaAbs, curatorSchema);
|
|
@@ -14866,7 +15260,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14866
15260
|
]);
|
|
14867
15261
|
if (recoveredCur) {
|
|
14868
15262
|
try {
|
|
14869
|
-
|
|
15263
|
+
fs22.writeFileSync(deltaAbs, `${recoveredCur}
|
|
14870
15264
|
`, "utf-8");
|
|
14871
15265
|
opts.diagnosticLog?.(`[ace] curator re-recovered from CLI output after schema failure \u2192 ${deltaAbs}`);
|
|
14872
15266
|
dv = validateAceJsonFile(deltaAbs, curatorSchema);
|
|
@@ -14880,7 +15274,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14880
15274
|
if (!dv.ok) {
|
|
14881
15275
|
const hint = dv.message.length > 220 ? `${dv.message.slice(0, 220)}\u2026` : dv.message;
|
|
14882
15276
|
opts.diagnosticLog?.(`[ace] curator delta failed schema \u2014 writing valid empty operations \u2014 ${hint}`);
|
|
14883
|
-
|
|
15277
|
+
fs22.writeFileSync(
|
|
14884
15278
|
deltaAbs,
|
|
14885
15279
|
`${JSON.stringify(buildEmptyCuratorDelta(agentStem, lessonsRel), null, 2)}
|
|
14886
15280
|
`,
|
|
@@ -14899,9 +15293,9 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14899
15293
|
let lessonCount = 0;
|
|
14900
15294
|
let curatorOperationCount = 0;
|
|
14901
15295
|
try {
|
|
14902
|
-
const lessonsDoc = JSON.parse(
|
|
15296
|
+
const lessonsDoc = JSON.parse(fs22.readFileSync(lessonsAbs, "utf-8"));
|
|
14903
15297
|
lessonCount = Array.isArray(lessonsDoc.lessons) ? lessonsDoc.lessons.length : 0;
|
|
14904
|
-
const deltaDoc = JSON.parse(
|
|
15298
|
+
const deltaDoc = JSON.parse(fs22.readFileSync(deltaAbs, "utf-8"));
|
|
14905
15299
|
curatorOperationCount = Array.isArray(deltaDoc.operations) ? deltaDoc.operations.length : 0;
|
|
14906
15300
|
} catch {
|
|
14907
15301
|
}
|
|
@@ -14960,9 +15354,9 @@ async function runAceTracePhase(params) {
|
|
|
14960
15354
|
const contextDir2 = gluecharmContextDir(params.worktreeRoot);
|
|
14961
15355
|
const traceStem = aceTraceFileRunStem(params.artefactRunId, params.followUpSessionId);
|
|
14962
15356
|
const traceAbs = aceTracePath(contextDir2, params.producerAgentStem, traceStem);
|
|
14963
|
-
|
|
15357
|
+
fs23.mkdirSync(path21.dirname(traceAbs), { recursive: true });
|
|
14964
15358
|
const schemaAbs = opencodeAceSchemaPath(params.worktreeRoot, ACE_SCHEMA_TRACE);
|
|
14965
|
-
if (!
|
|
15359
|
+
if (!fs23.existsSync(schemaAbs)) {
|
|
14966
15360
|
const msg = `[ace] trace skipped \u2014 schema missing: ${schemaAbs}`;
|
|
14967
15361
|
params.diagnosticLog?.(msg);
|
|
14968
15362
|
return { ok: false, message: msg };
|
|
@@ -15011,9 +15405,9 @@ async function runAceTracePhase(params) {
|
|
|
15011
15405
|
`Use only evidence from this session's transcript and tool history.`
|
|
15012
15406
|
].join("\n");
|
|
15013
15407
|
const runDir = path21.join(params.worktreeRoot, ".opencode", "_run");
|
|
15014
|
-
|
|
15408
|
+
fs23.mkdirSync(runDir, { recursive: true });
|
|
15015
15409
|
const promptPath = path21.join(runDir, `ace-trace-${traceStem}-${Date.now()}.prompt.txt`);
|
|
15016
|
-
|
|
15410
|
+
fs23.writeFileSync(promptPath, promptBody, "utf-8");
|
|
15017
15411
|
const vars = {
|
|
15018
15412
|
promptFile: promptPath,
|
|
15019
15413
|
agentId: ACE_TRACE_RECORDER_AGENT_STEM,
|
|
@@ -15037,7 +15431,7 @@ async function runAceTracePhase(params) {
|
|
|
15037
15431
|
if (!cli.ok) {
|
|
15038
15432
|
return { ok: false, message: `[ace] trace OpenCode failed: ${cli.message}` };
|
|
15039
15433
|
}
|
|
15040
|
-
if (!
|
|
15434
|
+
if (!fs23.existsSync(traceAbs)) {
|
|
15041
15435
|
const recovered = extractJsonObjectWithTopLevelKeys(cli.message, [
|
|
15042
15436
|
"aceSchemaVersion",
|
|
15043
15437
|
"sessionMeta",
|
|
@@ -15045,7 +15439,7 @@ async function runAceTracePhase(params) {
|
|
|
15045
15439
|
]);
|
|
15046
15440
|
if (recovered) {
|
|
15047
15441
|
try {
|
|
15048
|
-
|
|
15442
|
+
fs23.writeFileSync(traceAbs, `${recovered}
|
|
15049
15443
|
`, "utf-8");
|
|
15050
15444
|
params.diagnosticLog?.(`[ace] trace recovered from OpenCode stdout/stderr \u2192 ${traceAbs}`);
|
|
15051
15445
|
} catch (e) {
|
|
@@ -15055,7 +15449,7 @@ async function runAceTracePhase(params) {
|
|
|
15055
15449
|
}
|
|
15056
15450
|
}
|
|
15057
15451
|
}
|
|
15058
|
-
if (!
|
|
15452
|
+
if (!fs23.existsSync(traceAbs)) {
|
|
15059
15453
|
const msg = `[ace] trace file missing after run: ${traceAbs}`;
|
|
15060
15454
|
params.diagnosticLog?.(msg);
|
|
15061
15455
|
return { ok: false, message: msg };
|
|
@@ -15087,7 +15481,7 @@ async function runAceTracePhase(params) {
|
|
|
15087
15481
|
return { ok: false, message: msg };
|
|
15088
15482
|
}
|
|
15089
15483
|
try {
|
|
15090
|
-
const rawAlign =
|
|
15484
|
+
const rawAlign = fs23.readFileSync(traceAbs, "utf-8");
|
|
15091
15485
|
const docAlign = JSON.parse(rawAlign);
|
|
15092
15486
|
const smRun = docAlign.sessionMeta?.runId;
|
|
15093
15487
|
if (typeof smRun !== "string" || smRun !== traceStem) {
|
|
@@ -15143,7 +15537,7 @@ async function runAceTracePhase(params) {
|
|
|
15143
15537
|
}
|
|
15144
15538
|
|
|
15145
15539
|
// src/analysis/coordinationListJsonValidate.ts
|
|
15146
|
-
var
|
|
15540
|
+
var fs24 = __toESM(require("fs"));
|
|
15147
15541
|
var import__4 = __toESM(require__());
|
|
15148
15542
|
function stripUtf8Bom3(s) {
|
|
15149
15543
|
return s.length > 0 && s.charCodeAt(0) === 65279 ? s.slice(1) : s;
|
|
@@ -15207,7 +15601,7 @@ function formatAjvErrors4(errors) {
|
|
|
15207
15601
|
function validateCoordinationListJson(jsonAbsolutePath, schemaAbsolutePath) {
|
|
15208
15602
|
let raw;
|
|
15209
15603
|
try {
|
|
15210
|
-
raw = stripUtf8Bom3(
|
|
15604
|
+
raw = stripUtf8Bom3(fs24.readFileSync(jsonAbsolutePath, "utf-8"));
|
|
15211
15605
|
} catch (e) {
|
|
15212
15606
|
return {
|
|
15213
15607
|
ok: false,
|
|
@@ -15223,7 +15617,7 @@ function validateCoordinationListJson(jsonAbsolutePath, schemaAbsolutePath) {
|
|
|
15223
15617
|
}
|
|
15224
15618
|
let schemaRaw;
|
|
15225
15619
|
try {
|
|
15226
|
-
schemaRaw = stripUtf8Bom3(
|
|
15620
|
+
schemaRaw = stripUtf8Bom3(fs24.readFileSync(schemaAbsolutePath, "utf-8"));
|
|
15227
15621
|
} catch (e) {
|
|
15228
15622
|
return {
|
|
15229
15623
|
ok: false,
|
|
@@ -15284,7 +15678,7 @@ function validateCoordinationListJson(jsonAbsolutePath, schemaAbsolutePath) {
|
|
|
15284
15678
|
var FILE_PREVIEW_MAX = 4e3;
|
|
15285
15679
|
function readCoordinationJsonPreview(jsonAbsolutePath) {
|
|
15286
15680
|
try {
|
|
15287
|
-
const raw = stripUtf8Bom3(
|
|
15681
|
+
const raw = stripUtf8Bom3(fs24.readFileSync(jsonAbsolutePath, "utf-8"));
|
|
15288
15682
|
return raw.length <= FILE_PREVIEW_MAX ? raw : `${raw.slice(0, FILE_PREVIEW_MAX)}
|
|
15289
15683
|
|
|
15290
15684
|
\u2026 (truncated)`;
|
|
@@ -15360,12 +15754,12 @@ function formatCoordinationJsonRepairAppendix(outputBasename, failure, rawFilePr
|
|
|
15360
15754
|
}
|
|
15361
15755
|
|
|
15362
15756
|
// src/analysis/coordinationListStableWrite.ts
|
|
15363
|
-
var
|
|
15757
|
+
var fs26 = __toESM(require("fs"));
|
|
15364
15758
|
var path23 = __toESM(require("path"));
|
|
15365
15759
|
|
|
15366
15760
|
// src/analysis/coordinationListFileLock.ts
|
|
15367
|
-
var
|
|
15368
|
-
var
|
|
15761
|
+
var fs25 = __toESM(require("fs"));
|
|
15762
|
+
var os3 = __toESM(require("os"));
|
|
15369
15763
|
var path22 = __toESM(require("path"));
|
|
15370
15764
|
var DEFAULT_COORDINATION_LIST_LOCK_TIMEOUT_MS = 12e4;
|
|
15371
15765
|
var DEFAULT_COORDINATION_LIST_LOCK_STALE_MS = 30 * 60 * 1e3;
|
|
@@ -15385,7 +15779,7 @@ function lockPathForList(listJsonAbsolutePath) {
|
|
|
15385
15779
|
}
|
|
15386
15780
|
function tryReadLockBody(lockAbs) {
|
|
15387
15781
|
try {
|
|
15388
|
-
const raw =
|
|
15782
|
+
const raw = fs25.readFileSync(lockAbs, "utf-8");
|
|
15389
15783
|
const j = JSON.parse(raw);
|
|
15390
15784
|
if (typeof j.pid === "number" && typeof j.createdAt === "string") {
|
|
15391
15785
|
return j;
|
|
@@ -15397,7 +15791,7 @@ function tryReadLockBody(lockAbs) {
|
|
|
15397
15791
|
function tryRemoveStaleLock(lockAbs, staleMs, diagnosticLog) {
|
|
15398
15792
|
let st;
|
|
15399
15793
|
try {
|
|
15400
|
-
st =
|
|
15794
|
+
st = fs25.statSync(lockAbs);
|
|
15401
15795
|
} catch {
|
|
15402
15796
|
return false;
|
|
15403
15797
|
}
|
|
@@ -15412,7 +15806,7 @@ function tryRemoveStaleLock(lockAbs, staleMs, diagnosticLog) {
|
|
|
15412
15806
|
return false;
|
|
15413
15807
|
}
|
|
15414
15808
|
try {
|
|
15415
|
-
|
|
15809
|
+
fs25.unlinkSync(lockAbs);
|
|
15416
15810
|
diagnosticLog?.(`[coord-lock] removed stale lock ${lockAbs} (age ${Math.round(age)} ms)`);
|
|
15417
15811
|
return true;
|
|
15418
15812
|
} catch {
|
|
@@ -15429,11 +15823,11 @@ async function withCoordinationListFileLock(listJsonAbsolutePath, options, fn) {
|
|
|
15429
15823
|
while (!acquired && Date.now() < deadline) {
|
|
15430
15824
|
const body = {
|
|
15431
15825
|
pid: process.pid,
|
|
15432
|
-
host:
|
|
15826
|
+
host: os3.hostname(),
|
|
15433
15827
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
15434
15828
|
};
|
|
15435
15829
|
try {
|
|
15436
|
-
|
|
15830
|
+
fs25.writeFileSync(lockAbs, `${JSON.stringify(body, null, 0)}
|
|
15437
15831
|
`, { encoding: "utf-8", flag: "wx" });
|
|
15438
15832
|
acquired = true;
|
|
15439
15833
|
diagnosticLog?.(`[coord-lock] acquired ${path22.basename(lockAbs)}`);
|
|
@@ -15457,7 +15851,7 @@ async function withCoordinationListFileLock(listJsonAbsolutePath, options, fn) {
|
|
|
15457
15851
|
return await fn();
|
|
15458
15852
|
} finally {
|
|
15459
15853
|
try {
|
|
15460
|
-
|
|
15854
|
+
fs25.unlinkSync(lockAbs);
|
|
15461
15855
|
diagnosticLog?.(`[coord-lock] released ${path22.basename(lockAbs)}`);
|
|
15462
15856
|
} catch {
|
|
15463
15857
|
}
|
|
@@ -15831,13 +16225,13 @@ function buildCascadePathsForDroppedCodes(listBasename, droppedCodes, contextDir
|
|
|
15831
16225
|
const paths = [];
|
|
15832
16226
|
const tryPush = (p) => {
|
|
15833
16227
|
const abs = path23.join(contextDirAbs, p);
|
|
15834
|
-
if (
|
|
16228
|
+
if (fs26.existsSync(abs)) {
|
|
15835
16229
|
paths.push(abs);
|
|
15836
16230
|
}
|
|
15837
16231
|
};
|
|
15838
16232
|
const listDir = () => {
|
|
15839
16233
|
try {
|
|
15840
|
-
return
|
|
16234
|
+
return fs26.readdirSync(contextDirAbs);
|
|
15841
16235
|
} catch {
|
|
15842
16236
|
return [];
|
|
15843
16237
|
}
|
|
@@ -16038,7 +16432,7 @@ async function finalizeCoordinationListWrite(p) {
|
|
|
16038
16432
|
async () => {
|
|
16039
16433
|
let agentRaw;
|
|
16040
16434
|
try {
|
|
16041
|
-
agentRaw =
|
|
16435
|
+
agentRaw = fs26.readFileSync(p.listJsonAbsolutePath, "utf-8");
|
|
16042
16436
|
} catch (e) {
|
|
16043
16437
|
return { ok: false, message: `SRS-50 re-read failed: ${e instanceof Error ? e.message : String(e)}` };
|
|
16044
16438
|
}
|
|
@@ -16066,7 +16460,7 @@ async function finalizeCoordinationListWrite(p) {
|
|
|
16066
16460
|
p.diagnosticLog?.(formatStableWriteDiagnosticLine(p.listBasename, m.diff));
|
|
16067
16461
|
const tmp = `${p.listJsonAbsolutePath}.tmp.${process.pid}`;
|
|
16068
16462
|
try {
|
|
16069
|
-
|
|
16463
|
+
fs26.writeFileSync(tmp, `${JSON.stringify(m.merged, null, 2)}
|
|
16070
16464
|
`, "utf-8");
|
|
16071
16465
|
} catch (e) {
|
|
16072
16466
|
return { ok: false, message: `SRS-50 temp write failed: ${e instanceof Error ? e.message : String(e)}` };
|
|
@@ -16074,14 +16468,14 @@ async function finalizeCoordinationListWrite(p) {
|
|
|
16074
16468
|
const v = validateCoordinationListJson(tmp, p.schemaAbsolutePath);
|
|
16075
16469
|
if (!v.ok) {
|
|
16076
16470
|
try {
|
|
16077
|
-
|
|
16471
|
+
fs26.unlinkSync(tmp);
|
|
16078
16472
|
} catch {
|
|
16079
16473
|
}
|
|
16080
16474
|
const detail = v.failure.kind === "schema" ? v.failure.errorsText : v.failure.kind === "parse" ? v.failure.message : v.failure.message;
|
|
16081
16475
|
return { ok: false, message: `SRS-50 merged output failed schema: ${detail}` };
|
|
16082
16476
|
}
|
|
16083
16477
|
try {
|
|
16084
|
-
|
|
16478
|
+
fs26.renameSync(tmp, p.listJsonAbsolutePath);
|
|
16085
16479
|
} catch (e) {
|
|
16086
16480
|
return { ok: false, message: `SRS-50 rename failed: ${e instanceof Error ? e.message : String(e)}` };
|
|
16087
16481
|
}
|
|
@@ -16151,7 +16545,7 @@ function allocateNextListRowCode(input) {
|
|
|
16151
16545
|
}
|
|
16152
16546
|
let names = [];
|
|
16153
16547
|
try {
|
|
16154
|
-
names =
|
|
16548
|
+
names = fs26.readdirSync(contextDirAbs);
|
|
16155
16549
|
} catch {
|
|
16156
16550
|
names = [];
|
|
16157
16551
|
}
|
|
@@ -16194,7 +16588,7 @@ function allocateNextListRowCode(input) {
|
|
|
16194
16588
|
}
|
|
16195
16589
|
|
|
16196
16590
|
// src/analysis/markdownEvidenceIndexValidate.ts
|
|
16197
|
-
var
|
|
16591
|
+
var fs27 = __toESM(require("fs"));
|
|
16198
16592
|
var EVIDENCE_HEADING = "## Evidence index";
|
|
16199
16593
|
function evidenceIndexMentionsReadmeMd(body) {
|
|
16200
16594
|
const re = /README\.md/gi;
|
|
@@ -16322,7 +16716,7 @@ function markdownEvidenceValidationPasses(content) {
|
|
|
16322
16716
|
function validateMarkdownEvidenceIndexFile(absolutePath) {
|
|
16323
16717
|
let text;
|
|
16324
16718
|
try {
|
|
16325
|
-
const buf =
|
|
16719
|
+
const buf = fs27.readFileSync(absolutePath);
|
|
16326
16720
|
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
16327
16721
|
text = decoder.decode(buf);
|
|
16328
16722
|
} catch (e) {
|
|
@@ -16363,7 +16757,7 @@ function formatMarkdownEvidenceRepairAppendix(outputFileAbsolute, kind = "empty"
|
|
|
16363
16757
|
}
|
|
16364
16758
|
|
|
16365
16759
|
// src/analysis/openQuestionResolution.ts
|
|
16366
|
-
var
|
|
16760
|
+
var fs28 = __toESM(require("fs"));
|
|
16367
16761
|
var path24 = __toESM(require("path"));
|
|
16368
16762
|
var OPEN_QUESTION_RESOLUTION_JSON_BASENAME = "open-question-resolution.json";
|
|
16369
16763
|
function openQuestionResolutionJsonAbsolute(worktreeRoot) {
|
|
@@ -16402,10 +16796,10 @@ function parseOpenQuestionResolutionJsonText(raw) {
|
|
|
16402
16796
|
function readOpenQuestionResolutionFile(worktreeRoot) {
|
|
16403
16797
|
const p = openQuestionResolutionJsonAbsolute(worktreeRoot);
|
|
16404
16798
|
try {
|
|
16405
|
-
if (!
|
|
16799
|
+
if (!fs28.existsSync(p)) {
|
|
16406
16800
|
return { ok: false, error: `Missing resolution file: ${p}` };
|
|
16407
16801
|
}
|
|
16408
|
-
const raw =
|
|
16802
|
+
const raw = fs28.readFileSync(p, "utf-8");
|
|
16409
16803
|
return parseOpenQuestionResolutionJsonText(raw);
|
|
16410
16804
|
} catch (e) {
|
|
16411
16805
|
const m = e instanceof Error ? e.message : String(e);
|
|
@@ -16415,15 +16809,15 @@ function readOpenQuestionResolutionFile(worktreeRoot) {
|
|
|
16415
16809
|
function deleteOpenQuestionResolutionFile(worktreeRoot) {
|
|
16416
16810
|
try {
|
|
16417
16811
|
const p = openQuestionResolutionJsonAbsolute(worktreeRoot);
|
|
16418
|
-
if (
|
|
16419
|
-
|
|
16812
|
+
if (fs28.existsSync(p)) {
|
|
16813
|
+
fs28.unlinkSync(p);
|
|
16420
16814
|
}
|
|
16421
16815
|
} catch {
|
|
16422
16816
|
}
|
|
16423
16817
|
}
|
|
16424
16818
|
|
|
16425
16819
|
// src/analysis/openQuestionsSectionValidate.ts
|
|
16426
|
-
var
|
|
16820
|
+
var fs29 = __toESM(require("fs"));
|
|
16427
16821
|
var path25 = __toESM(require("path"));
|
|
16428
16822
|
var CANONICAL_NORMALIZED = "open questions";
|
|
16429
16823
|
function normalizeOpenQuestionsHeadingTitle(raw) {
|
|
@@ -16556,7 +16950,7 @@ function validateOpenQuestionsSectionFile(absolutePath, scope) {
|
|
|
16556
16950
|
}
|
|
16557
16951
|
let text;
|
|
16558
16952
|
try {
|
|
16559
|
-
const buf =
|
|
16953
|
+
const buf = fs29.readFileSync(absolutePath);
|
|
16560
16954
|
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
16561
16955
|
text = decoder.decode(buf);
|
|
16562
16956
|
} catch (e) {
|
|
@@ -17111,7 +17505,7 @@ function clampMarkdownOpenQuestionIterations(raw) {
|
|
|
17111
17505
|
}
|
|
17112
17506
|
function getExpectedOutputArtefactStatus(absolutePath) {
|
|
17113
17507
|
try {
|
|
17114
|
-
const st =
|
|
17508
|
+
const st = fs30.statSync(absolutePath);
|
|
17115
17509
|
if (!st.isFile()) {
|
|
17116
17510
|
return { generated: false, reason: "not_a_file" };
|
|
17117
17511
|
}
|
|
@@ -17210,7 +17604,7 @@ function outputPaths(step, worktreeRoot, listTarget) {
|
|
|
17210
17604
|
}
|
|
17211
17605
|
async function runOpenQuestionResolutionWorkstation(opts) {
|
|
17212
17606
|
const runDir = path26.join(opts.worktreeRoot, ".opencode", "_run");
|
|
17213
|
-
|
|
17607
|
+
fs30.mkdirSync(runDir, { recursive: true });
|
|
17214
17608
|
const resolutionJsonAbsolute = openQuestionResolutionJsonAbsolute(opts.worktreeRoot);
|
|
17215
17609
|
const body = fillResolveOpenQuestionPrompt({
|
|
17216
17610
|
worktreeRoot: opts.worktreeRoot,
|
|
@@ -17220,7 +17614,7 @@ async function runOpenQuestionResolutionWorkstation(opts) {
|
|
|
17220
17614
|
resolutionJsonAbsolute
|
|
17221
17615
|
});
|
|
17222
17616
|
const promptPath = path26.join(runDir, `resolve-open-question-${Date.now()}.prompt.txt`);
|
|
17223
|
-
|
|
17617
|
+
fs30.writeFileSync(promptPath, body, "utf-8");
|
|
17224
17618
|
const vars = {
|
|
17225
17619
|
promptFile: promptPath,
|
|
17226
17620
|
agentId: RESOLVE_OPEN_QUESTION_AGENT_STEM,
|
|
@@ -17284,7 +17678,7 @@ ${cli.message}`,
|
|
|
17284
17678
|
}
|
|
17285
17679
|
async function runOpenCodeMarkdownEvidenceRepairLoop(input) {
|
|
17286
17680
|
const totalMarkdownRuns = 1 + input.maxMarkdownEvidenceRepairs;
|
|
17287
|
-
|
|
17681
|
+
fs30.mkdirSync(input.runDir, { recursive: true });
|
|
17288
17682
|
let attemptIndex = 0;
|
|
17289
17683
|
let capturedProducerSessionId;
|
|
17290
17684
|
const repair = await runWorkstationRepairLoop({
|
|
@@ -17307,7 +17701,7 @@ async function runOpenCodeMarkdownEvidenceRepairLoop(input) {
|
|
|
17307
17701
|
const idx = attemptIndex;
|
|
17308
17702
|
const promptPath = input.promptPathForAttempt(idx);
|
|
17309
17703
|
attemptIndex += 1;
|
|
17310
|
-
|
|
17704
|
+
fs30.writeFileSync(promptPath, body, "utf-8");
|
|
17311
17705
|
const vars = input.argvVarsForPrompt(promptPath);
|
|
17312
17706
|
const expanded = expandArgvTemplate3(input.argvTemplate, vars);
|
|
17313
17707
|
const followUpSessionId = input.resolveFollowUpSessionId({
|
|
@@ -17799,7 +18193,7 @@ async function runCoordinationListWorkstation(opts) {
|
|
|
17799
18193
|
let schemaAbsoluteForList;
|
|
17800
18194
|
if (effectiveListSchemaFile) {
|
|
17801
18195
|
schemaAbsoluteForList = schemaRef(opts.worktreeRoot, effectiveListSchemaFile);
|
|
17802
|
-
if (!
|
|
18196
|
+
if (!fs30.existsSync(schemaAbsoluteForList)) {
|
|
17803
18197
|
return {
|
|
17804
18198
|
ok: false,
|
|
17805
18199
|
message: `JSON Schema not found: ${schemaAbsoluteForList}
|
|
@@ -17812,11 +18206,11 @@ Run **Materialize agents** first (copies list schemas into this folder\u2019s \`
|
|
|
17812
18206
|
}
|
|
17813
18207
|
if (opts.step === "reviewExperiencesList" && effectiveListSchemaFile) {
|
|
17814
18208
|
const schemaAbs = schemaRef(opts.worktreeRoot, effectiveListSchemaFile);
|
|
17815
|
-
if (
|
|
18209
|
+
if (fs30.existsSync(outputFileAbsolute)) {
|
|
17816
18210
|
const v = validateCoordinationListJson(outputFileAbsolute, schemaAbs);
|
|
17817
18211
|
if (v.ok) {
|
|
17818
18212
|
try {
|
|
17819
|
-
const raw =
|
|
18213
|
+
const raw = fs30.readFileSync(outputFileAbsolute, "utf-8");
|
|
17820
18214
|
const data = JSON.parse(raw);
|
|
17821
18215
|
if (Array.isArray(data.views) && data.views.length === 0) {
|
|
17822
18216
|
return {
|
|
@@ -17832,9 +18226,9 @@ Run **Materialize agents** first (copies list schemas into this folder\u2019s \`
|
|
|
17832
18226
|
}
|
|
17833
18227
|
}
|
|
17834
18228
|
}
|
|
17835
|
-
|
|
18229
|
+
fs30.mkdirSync(path26.dirname(outputFileAbsolute), { recursive: true });
|
|
17836
18230
|
const runDir = path26.join(opts.worktreeRoot, ".opencode", "_run");
|
|
17837
|
-
|
|
18231
|
+
fs30.mkdirSync(runDir, { recursive: true });
|
|
17838
18232
|
const scopeSuffix = (opts.step === "listUseCases" || opts.step === "reviewUseCasesList") && opts.listTarget?.featureCode ? `-${opts.listTarget.featureCode}` : (opts.step === "listScenarios" || opts.step === "reviewScenariosList") && opts.listTarget?.featureCode && opts.listTarget?.useCaseCode ? `-${opts.listTarget.featureCode}_${opts.listTarget.useCaseCode}` : (opts.step === "listEntityFields" || opts.step === "reviewEntityFieldsList") && opts.listTarget?.entityCode ? `-${opts.listTarget.entityCode}` : "";
|
|
17839
18233
|
const rawRepair = opts.listJsonSchemaRepairAttempts;
|
|
17840
18234
|
let maxRepairAttempts = rawRepair === void 0 ? 1 : Math.floor(Number(rawRepair));
|
|
@@ -17853,8 +18247,8 @@ Run **Materialize agents** first (copies list schemas into this folder\u2019s \`
|
|
|
17853
18247
|
let preImageDocForStableWrite = {};
|
|
17854
18248
|
if (effectiveListSchemaFile && schemaAbsoluteForList && shouldApplyStableMergeForCoordinationBasename(outputBasename)) {
|
|
17855
18249
|
try {
|
|
17856
|
-
if (
|
|
17857
|
-
preImageDocForStableWrite = JSON.parse(
|
|
18250
|
+
if (fs30.existsSync(outputFileAbsolute)) {
|
|
18251
|
+
preImageDocForStableWrite = JSON.parse(fs30.readFileSync(outputFileAbsolute, "utf-8"));
|
|
17858
18252
|
}
|
|
17859
18253
|
} catch {
|
|
17860
18254
|
preImageDocForStableWrite = {};
|
|
@@ -18043,7 +18437,7 @@ Run **Materialize agents** first (copies list schemas into this folder\u2019s \`
|
|
|
18043
18437
|
);
|
|
18044
18438
|
const promptPath = path26.join(runDir, `${opts.step}${scopeSuffix}-a${attempt}-${Date.now()}.prompt.txt`);
|
|
18045
18439
|
lastPromptPath = promptPath;
|
|
18046
|
-
|
|
18440
|
+
fs30.writeFileSync(promptPath, body, "utf-8");
|
|
18047
18441
|
const vars = {
|
|
18048
18442
|
promptFile: promptPath,
|
|
18049
18443
|
agentId: STEP_OPEN_CODE_AGENT_IDS[opts.step],
|
|
@@ -18283,9 +18677,9 @@ async function runDetailMarkdownWorkstation(opts) {
|
|
|
18283
18677
|
}
|
|
18284
18678
|
maxMarkdownEvidenceRepairs = Math.min(5, Math.max(0, maxMarkdownEvidenceRepairs));
|
|
18285
18679
|
const totalMarkdownRuns = 1 + maxMarkdownEvidenceRepairs;
|
|
18286
|
-
|
|
18680
|
+
fs30.mkdirSync(path26.dirname(outputFileAbsolute), { recursive: true });
|
|
18287
18681
|
const runDir = path26.join(opts.worktreeRoot, ".opencode", "_run");
|
|
18288
|
-
|
|
18682
|
+
fs30.mkdirSync(runDir, { recursive: true });
|
|
18289
18683
|
const safeStem = opts.target.outputBasename.replace(/[^A-Za-z0-9_.-]+/g, "_").slice(0, 120);
|
|
18290
18684
|
let lastPromptPath = "";
|
|
18291
18685
|
let lastCliMessage = "";
|
|
@@ -18527,18 +18921,18 @@ Expected output: ${outputFileAbsolute}`;
|
|
|
18527
18921
|
}
|
|
18528
18922
|
|
|
18529
18923
|
// src/analysis/worktreeManager.ts
|
|
18530
|
-
var
|
|
18531
|
-
var
|
|
18532
|
-
var
|
|
18924
|
+
var import_child_process4 = require("child_process");
|
|
18925
|
+
var fs31 = __toESM(require("fs"));
|
|
18926
|
+
var os4 = __toESM(require("os"));
|
|
18533
18927
|
var path27 = __toESM(require("path"));
|
|
18534
18928
|
|
|
18535
18929
|
// src/analysis/gitWorktreeStaleRecovery.ts
|
|
18536
|
-
var
|
|
18930
|
+
var import_child_process3 = require("child_process");
|
|
18537
18931
|
function isMissingRegisteredWorktreeError(combinedStderrStdout) {
|
|
18538
18932
|
return /missing but already registered worktree/i.test(combinedStderrStdout);
|
|
18539
18933
|
}
|
|
18540
18934
|
function gitWorktreePruneSync(repoRoot) {
|
|
18541
|
-
const r = (0,
|
|
18935
|
+
const r = (0, import_child_process3.spawnSync)("git", ["worktree", "prune"], {
|
|
18542
18936
|
cwd: repoRoot,
|
|
18543
18937
|
encoding: "utf-8",
|
|
18544
18938
|
timeout: 6e4
|
|
@@ -18559,7 +18953,7 @@ function maxEasyspecsWorktreeIndex(parentDir) {
|
|
|
18559
18953
|
let max = 0;
|
|
18560
18954
|
let entries;
|
|
18561
18955
|
try {
|
|
18562
|
-
entries =
|
|
18956
|
+
entries = fs31.readdirSync(parentDir, { withFileTypes: true });
|
|
18563
18957
|
} catch {
|
|
18564
18958
|
return 0;
|
|
18565
18959
|
}
|
|
@@ -18582,19 +18976,19 @@ function formatEasyspecsWorktreeFolderName(index) {
|
|
|
18582
18976
|
return `easyspecs-${String(index).padStart(3, "0")}`;
|
|
18583
18977
|
}
|
|
18584
18978
|
function allocateEasyspecsWorktreePath(parentDir) {
|
|
18585
|
-
|
|
18979
|
+
fs31.mkdirSync(parentDir, { recursive: true });
|
|
18586
18980
|
const start = maxEasyspecsWorktreeIndex(parentDir);
|
|
18587
18981
|
for (let i = start + 1; i < start + 1e4; i++) {
|
|
18588
18982
|
const name = formatEasyspecsWorktreeFolderName(i);
|
|
18589
18983
|
const wt = path27.join(parentDir, name);
|
|
18590
|
-
if (!
|
|
18984
|
+
if (!fs31.existsSync(wt)) {
|
|
18591
18985
|
return wt;
|
|
18592
18986
|
}
|
|
18593
18987
|
}
|
|
18594
18988
|
return null;
|
|
18595
18989
|
}
|
|
18596
18990
|
function readHeadBranchShort(repoRoot) {
|
|
18597
|
-
const r = (0,
|
|
18991
|
+
const r = (0, import_child_process4.spawnSync)("git", ["symbolic-ref", "--short", "-q", "HEAD"], {
|
|
18598
18992
|
cwd: repoRoot,
|
|
18599
18993
|
encoding: "utf-8",
|
|
18600
18994
|
timeout: 3e4
|
|
@@ -18612,20 +19006,20 @@ function attachWorktreeHandle(worktreePath, repositoryRoot) {
|
|
|
18612
19006
|
path: wt,
|
|
18613
19007
|
repoRoot: repo,
|
|
18614
19008
|
remove() {
|
|
18615
|
-
(0,
|
|
19009
|
+
(0, import_child_process4.spawnSync)("git", ["worktree", "remove", "--force", wt], {
|
|
18616
19010
|
cwd: repo,
|
|
18617
19011
|
encoding: "utf-8",
|
|
18618
19012
|
timeout: 6e4
|
|
18619
19013
|
});
|
|
18620
19014
|
try {
|
|
18621
|
-
|
|
19015
|
+
fs31.rmSync(wt, { recursive: true, force: true });
|
|
18622
19016
|
} catch {
|
|
18623
19017
|
}
|
|
18624
19018
|
}
|
|
18625
19019
|
};
|
|
18626
19020
|
}
|
|
18627
19021
|
function createAnalysisWorktree(repoRoot, options) {
|
|
18628
|
-
const parent = path27.join(
|
|
19022
|
+
const parent = path27.join(os4.tmpdir(), "easyspecs-analysis");
|
|
18629
19023
|
const wt = allocateEasyspecsWorktreePath(parent);
|
|
18630
19024
|
if (!wt) {
|
|
18631
19025
|
return {
|
|
@@ -18635,7 +19029,7 @@ function createAnalysisWorktree(repoRoot, options) {
|
|
|
18635
19029
|
}
|
|
18636
19030
|
const sourceBranchAtCreation = readHeadBranchShort(repoRoot);
|
|
18637
19031
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
18638
|
-
const r = (0,
|
|
19032
|
+
const r = (0, import_child_process4.spawnSync)("git", ["worktree", "add", "--detach", wt, "HEAD"], {
|
|
18639
19033
|
cwd: repoRoot,
|
|
18640
19034
|
encoding: "utf-8",
|
|
18641
19035
|
timeout: 12e4
|
|
@@ -18753,7 +19147,7 @@ function noteOpenCodeAgentLaunched() {
|
|
|
18753
19147
|
}
|
|
18754
19148
|
|
|
18755
19149
|
// src/contextIndexAssembler.ts
|
|
18756
|
-
var
|
|
19150
|
+
var fs32 = __toESM(require("fs"));
|
|
18757
19151
|
var path28 = __toESM(require("path"));
|
|
18758
19152
|
|
|
18759
19153
|
// src/srsModel.ts
|
|
@@ -18788,7 +19182,7 @@ function tryAttachMarkdown(node, contextDir2, relativePath) {
|
|
|
18788
19182
|
}
|
|
18789
19183
|
const full = path28.join(contextDir2, norm);
|
|
18790
19184
|
try {
|
|
18791
|
-
if (!
|
|
19185
|
+
if (!fs32.existsSync(full) || !fs32.statSync(full).isFile()) {
|
|
18792
19186
|
return false;
|
|
18793
19187
|
}
|
|
18794
19188
|
} catch {
|
|
@@ -18846,10 +19240,10 @@ function mergePersistedIndexUploadMetadata(previous, next) {
|
|
|
18846
19240
|
function tryReadExistingIndexForMerge(contextDir2) {
|
|
18847
19241
|
const p = path28.join(contextDir2, "index-application-context.json");
|
|
18848
19242
|
try {
|
|
18849
|
-
if (!
|
|
19243
|
+
if (!fs32.existsSync(p)) {
|
|
18850
19244
|
return null;
|
|
18851
19245
|
}
|
|
18852
|
-
const j = JSON.parse(
|
|
19246
|
+
const j = JSON.parse(fs32.readFileSync(p, "utf8"));
|
|
18853
19247
|
if (j && typeof j === "object" && j.kind === APPLICATION_CONTEXT_KIND) {
|
|
18854
19248
|
return j;
|
|
18855
19249
|
}
|
|
@@ -19004,7 +19398,7 @@ function applyDetailMarkdownToDocument(doc, contextDir2) {
|
|
|
19004
19398
|
}
|
|
19005
19399
|
function readJson2(filePath) {
|
|
19006
19400
|
try {
|
|
19007
|
-
const raw =
|
|
19401
|
+
const raw = fs32.readFileSync(filePath, "utf-8");
|
|
19008
19402
|
return JSON.parse(raw);
|
|
19009
19403
|
} catch {
|
|
19010
19404
|
return null;
|
|
@@ -19184,11 +19578,11 @@ function writeIndexApplicationContext(contextDir2, title, options) {
|
|
|
19184
19578
|
const target = path28.join(contextDir2, "index-application-context.json");
|
|
19185
19579
|
const tmp = `${target}.${process.pid}.tmp`;
|
|
19186
19580
|
try {
|
|
19187
|
-
|
|
19188
|
-
|
|
19581
|
+
fs32.writeFileSync(tmp, JSON.stringify(doc, null, 2), "utf-8");
|
|
19582
|
+
fs32.renameSync(tmp, target);
|
|
19189
19583
|
} catch (e) {
|
|
19190
19584
|
try {
|
|
19191
|
-
|
|
19585
|
+
fs32.unlinkSync(tmp);
|
|
19192
19586
|
} catch {
|
|
19193
19587
|
}
|
|
19194
19588
|
throw e;
|
|
@@ -19197,7 +19591,7 @@ function writeIndexApplicationContext(contextDir2, title, options) {
|
|
|
19197
19591
|
}
|
|
19198
19592
|
|
|
19199
19593
|
// src/pipelines/linkMapping/linkMappingPipeline.ts
|
|
19200
|
-
var
|
|
19594
|
+
var fs33 = __toESM(require("node:fs"));
|
|
19201
19595
|
var path29 = __toESM(require("node:path"));
|
|
19202
19596
|
var SLUG2 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
19203
19597
|
function safeStr2(v) {
|
|
@@ -19222,7 +19616,7 @@ function slugOrFallback2(row2) {
|
|
|
19222
19616
|
}
|
|
19223
19617
|
function readJson3(filePath) {
|
|
19224
19618
|
try {
|
|
19225
|
-
const raw =
|
|
19619
|
+
const raw = fs33.readFileSync(filePath, "utf-8");
|
|
19226
19620
|
return JSON.parse(raw);
|
|
19227
19621
|
} catch {
|
|
19228
19622
|
return null;
|
|
@@ -19254,7 +19648,7 @@ function existsContextFile(contextDir2, rel) {
|
|
|
19254
19648
|
}
|
|
19255
19649
|
const full = path29.join(contextDir2, norm);
|
|
19256
19650
|
try {
|
|
19257
|
-
return
|
|
19651
|
+
return fs33.existsSync(full) && fs33.statSync(full).isFile();
|
|
19258
19652
|
} catch {
|
|
19259
19653
|
return false;
|
|
19260
19654
|
}
|
|
@@ -19351,7 +19745,7 @@ ${lines.join("\n")}
|
|
|
19351
19745
|
function collectMarkdownFilesRecursive(dir, acc) {
|
|
19352
19746
|
let entries;
|
|
19353
19747
|
try {
|
|
19354
|
-
entries =
|
|
19748
|
+
entries = fs33.readdirSync(dir, { withFileTypes: true });
|
|
19355
19749
|
} catch {
|
|
19356
19750
|
return;
|
|
19357
19751
|
}
|
|
@@ -19372,7 +19766,7 @@ function validateEasyspecsNavLinksInContext(contextDirAbs) {
|
|
|
19372
19766
|
for (const abs of mdFiles) {
|
|
19373
19767
|
let raw;
|
|
19374
19768
|
try {
|
|
19375
|
-
raw =
|
|
19769
|
+
raw = fs33.readFileSync(abs, "utf8");
|
|
19376
19770
|
} catch {
|
|
19377
19771
|
continue;
|
|
19378
19772
|
}
|
|
@@ -19398,7 +19792,7 @@ function validateEasyspecsNavLinksInContext(contextDirAbs) {
|
|
|
19398
19792
|
}
|
|
19399
19793
|
const target = path29.normalize(path29.join(path29.dirname(abs), href));
|
|
19400
19794
|
try {
|
|
19401
|
-
if (!
|
|
19795
|
+
if (!fs33.existsSync(target) || !fs33.statSync(target).isFile()) {
|
|
19402
19796
|
broken.push(`${path29.relative(contextDirAbs, abs)} \u2192 ${href}`);
|
|
19403
19797
|
}
|
|
19404
19798
|
} catch {
|
|
@@ -19424,7 +19818,7 @@ function validateEasyspecsNavLinksInContext(contextDirAbs) {
|
|
|
19424
19818
|
}
|
|
19425
19819
|
const target = path29.normalize(path29.join(path29.dirname(abs), href));
|
|
19426
19820
|
try {
|
|
19427
|
-
if (!
|
|
19821
|
+
if (!fs33.existsSync(target) || !fs33.statSync(target).isFile()) {
|
|
19428
19822
|
broken.push(`${path29.relative(contextDirAbs, abs)} \u2192 ${href}`);
|
|
19429
19823
|
}
|
|
19430
19824
|
} catch {
|
|
@@ -19632,7 +20026,7 @@ function renderProjectMdSections(contextDir2) {
|
|
|
19632
20026
|
}
|
|
19633
20027
|
}
|
|
19634
20028
|
const dmListPath = path29.join(contextDir2, "data-model-list.json");
|
|
19635
|
-
if (dmLines.length === 0 &&
|
|
20029
|
+
if (dmLines.length === 0 && fs33.existsSync(dmListPath)) {
|
|
19636
20030
|
dmLines.push(bulletLink("Data model registry (JSON)", "./data-model-list.json"));
|
|
19637
20031
|
}
|
|
19638
20032
|
chunks.push("### Data model", "", dmLines.length ? dmLines.join("\n") : NONE_LINE, "");
|
|
@@ -19640,23 +20034,23 @@ function renderProjectMdSections(contextDir2) {
|
|
|
19640
20034
|
}
|
|
19641
20035
|
function patchOneFile(contextDir2, basename17, innerChildren, innerParents, opts) {
|
|
19642
20036
|
const abs = path29.join(contextDir2, basename17);
|
|
19643
|
-
if (!
|
|
20037
|
+
if (!fs33.existsSync(abs)) {
|
|
19644
20038
|
return;
|
|
19645
20039
|
}
|
|
19646
20040
|
let body;
|
|
19647
20041
|
try {
|
|
19648
|
-
body =
|
|
20042
|
+
body = fs33.readFileSync(abs, "utf8");
|
|
19649
20043
|
} catch (e) {
|
|
19650
20044
|
opts.log?.(`[pipeline:link-mapping] skip read ${basename17}: ${e instanceof Error ? e.message : String(e)}`);
|
|
19651
20045
|
return;
|
|
19652
20046
|
}
|
|
19653
20047
|
let next = replaceOrAppendRegion(body, NAV_CHILDREN_START, NAV_CHILDREN_END, innerChildren);
|
|
19654
20048
|
next = replaceOrAppendRegion(next, NAV_PARENTS_START, NAV_PARENTS_END, innerParents);
|
|
19655
|
-
|
|
20049
|
+
fs33.writeFileSync(abs, next, "utf8");
|
|
19656
20050
|
}
|
|
19657
20051
|
function runLinkMappingPipeline(contextDirAbs, opts = {}) {
|
|
19658
20052
|
const contextDir2 = path29.resolve(contextDirAbs);
|
|
19659
|
-
if (!
|
|
20053
|
+
if (!fs33.existsSync(contextDir2) || !fs33.statSync(contextDir2).isDirectory()) {
|
|
19660
20054
|
return { ok: false, error: `Context directory does not exist: ${contextDir2}` };
|
|
19661
20055
|
}
|
|
19662
20056
|
const edges = buildNavEdges(contextDir2);
|
|
@@ -19684,7 +20078,7 @@ function runLinkMappingPipeline(contextDirAbs, opts = {}) {
|
|
|
19684
20078
|
continue;
|
|
19685
20079
|
}
|
|
19686
20080
|
const abs = path29.join(contextDir2, basename17);
|
|
19687
|
-
if (!
|
|
20081
|
+
if (!fs33.existsSync(abs)) {
|
|
19688
20082
|
continue;
|
|
19689
20083
|
}
|
|
19690
20084
|
const childRows = edges.children.get(basename17) ?? [];
|
|
@@ -19718,15 +20112,15 @@ var path30 = __toESM(require("node:path"));
|
|
|
19718
20112
|
var vscode2 = __toESM(require_vscode_stub());
|
|
19719
20113
|
|
|
19720
20114
|
// src/config/easyspecsAceConfigRead.ts
|
|
19721
|
-
var
|
|
20115
|
+
var fs34 = __toESM(require("node:fs"));
|
|
19722
20116
|
function readRawConfigJson(repoRoot) {
|
|
19723
20117
|
const p = easyspecsConfigPath(repoRoot);
|
|
19724
|
-
if (!
|
|
20118
|
+
if (!fs34.existsSync(p)) {
|
|
19725
20119
|
return void 0;
|
|
19726
20120
|
}
|
|
19727
20121
|
let raw;
|
|
19728
20122
|
try {
|
|
19729
|
-
raw =
|
|
20123
|
+
raw = fs34.readFileSync(p, "utf8");
|
|
19730
20124
|
} catch {
|
|
19731
20125
|
return void 0;
|
|
19732
20126
|
}
|
|
@@ -19862,7 +20256,7 @@ function getAceOfflineLearnAfterSameSessionTrace(analysisCheckoutRoot) {
|
|
|
19862
20256
|
}
|
|
19863
20257
|
|
|
19864
20258
|
// src/analysis/repoSurfaceAssessment.ts
|
|
19865
|
-
var
|
|
20259
|
+
var fs35 = __toESM(require("fs"));
|
|
19866
20260
|
var path31 = __toESM(require("path"));
|
|
19867
20261
|
var REPO_SURFACE_SCAN_BASENAME = "repo-surface-scan.json";
|
|
19868
20262
|
function stripBom(s) {
|
|
@@ -19871,7 +20265,7 @@ function stripBom(s) {
|
|
|
19871
20265
|
function readRepoSurfaceAssessment(contextDir2) {
|
|
19872
20266
|
const p = path31.join(contextDir2, REPO_SURFACE_SCAN_BASENAME);
|
|
19873
20267
|
try {
|
|
19874
|
-
const raw = stripBom(
|
|
20268
|
+
const raw = stripBom(fs35.readFileSync(p, "utf-8"));
|
|
19875
20269
|
const data = JSON.parse(raw);
|
|
19876
20270
|
if (!data || typeof data !== "object") {
|
|
19877
20271
|
return null;
|
|
@@ -19892,8 +20286,8 @@ function readRepoSurfaceAssessment(contextDir2) {
|
|
|
19892
20286
|
}
|
|
19893
20287
|
function writeEmptyExperiencesListJson(contextDir2) {
|
|
19894
20288
|
const p = path31.join(contextDir2, "experiences-list.json");
|
|
19895
|
-
|
|
19896
|
-
|
|
20289
|
+
fs35.mkdirSync(path31.dirname(p), { recursive: true });
|
|
20290
|
+
fs35.writeFileSync(
|
|
19897
20291
|
p,
|
|
19898
20292
|
`${JSON.stringify(
|
|
19899
20293
|
{
|
|
@@ -19909,6 +20303,32 @@ function writeEmptyExperiencesListJson(contextDir2) {
|
|
|
19909
20303
|
);
|
|
19910
20304
|
}
|
|
19911
20305
|
|
|
20306
|
+
// src/config/cpuPressureSample.ts
|
|
20307
|
+
var os5 = __toESM(require("node:os"));
|
|
20308
|
+
function createDefaultCpuPressureSampler() {
|
|
20309
|
+
const n = Math.max(1, os5.cpus()?.length ?? 1);
|
|
20310
|
+
return () => {
|
|
20311
|
+
const [l1] = os5.loadavg();
|
|
20312
|
+
if (!Number.isFinite(l1) || l1 <= 0) {
|
|
20313
|
+
return 0;
|
|
20314
|
+
}
|
|
20315
|
+
return Math.min(1, l1 / n);
|
|
20316
|
+
};
|
|
20317
|
+
}
|
|
20318
|
+
function nextAdaptiveMaxAfterCpuSample(p) {
|
|
20319
|
+
const threshold = p.threshold ?? 0.96;
|
|
20320
|
+
if (p.activeRunningCount < 1 || !Number.isFinite(p.ratio) || p.ratio <= threshold) {
|
|
20321
|
+
return { adaptiveMax: p.priorAdaptiveMax, changed: false };
|
|
20322
|
+
}
|
|
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);
|
|
20326
|
+
if (next < p.priorAdaptiveMax) {
|
|
20327
|
+
return { adaptiveMax: next, changed: true };
|
|
20328
|
+
}
|
|
20329
|
+
return { adaptiveMax: p.priorAdaptiveMax, changed: false };
|
|
20330
|
+
}
|
|
20331
|
+
|
|
19912
20332
|
// src/pipelines/synthesis/synthesisPipeline.ts
|
|
19913
20333
|
var FE = /^FE-\d+$/;
|
|
19914
20334
|
var UC = /^UC-\d+$/;
|
|
@@ -19921,7 +20341,7 @@ function stripBom2(s) {
|
|
|
19921
20341
|
}
|
|
19922
20342
|
function readJson4(filePath) {
|
|
19923
20343
|
try {
|
|
19924
|
-
const raw = stripBom2(
|
|
20344
|
+
const raw = stripBom2(fs36.readFileSync(filePath, "utf-8"));
|
|
19925
20345
|
return JSON.parse(raw);
|
|
19926
20346
|
} catch {
|
|
19927
20347
|
return null;
|
|
@@ -20016,7 +20436,7 @@ function featureDetailTarget(contextDir2, code, name, slug) {
|
|
|
20016
20436
|
displayName: "Feature detail",
|
|
20017
20437
|
outputBasename: basename17,
|
|
20018
20438
|
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).`,
|
|
20019
|
-
exists:
|
|
20439
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20020
20440
|
};
|
|
20021
20441
|
}
|
|
20022
20442
|
function viewDetailTarget(row2, contextDir2) {
|
|
@@ -20027,7 +20447,7 @@ function viewDetailTarget(row2, contextDir2) {
|
|
|
20027
20447
|
displayName: "View detail",
|
|
20028
20448
|
outputBasename: basename17,
|
|
20029
20449
|
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.`,
|
|
20030
|
-
exists:
|
|
20450
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20031
20451
|
};
|
|
20032
20452
|
}
|
|
20033
20453
|
function interactionDetailTarget(viewCode, ix, contextDir2) {
|
|
@@ -20038,7 +20458,7 @@ function interactionDetailTarget(viewCode, ix, contextDir2) {
|
|
|
20038
20458
|
displayName: "Interaction detail",
|
|
20039
20459
|
outputBasename: basename17,
|
|
20040
20460
|
taskDescription: `Document interaction **${ix.code}** (**${ix.name}**) on view **${viewCode}** per \`.gluecharm/context/experiences-list.json\`.`,
|
|
20041
|
-
exists:
|
|
20461
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20042
20462
|
};
|
|
20043
20463
|
}
|
|
20044
20464
|
function serviceDetailTarget(row2, contextDir2) {
|
|
@@ -20049,7 +20469,7 @@ function serviceDetailTarget(row2, contextDir2) {
|
|
|
20049
20469
|
displayName: "Service detail",
|
|
20050
20470
|
outputBasename: basename17,
|
|
20051
20471
|
taskDescription: `Describe service **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/services-list.json\`: responsibilities, consumers, errors, integration points.`,
|
|
20052
|
-
exists:
|
|
20472
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20053
20473
|
};
|
|
20054
20474
|
}
|
|
20055
20475
|
function methodDetailTarget(svc, m, contextDir2) {
|
|
@@ -20060,7 +20480,7 @@ function methodDetailTarget(svc, m, contextDir2) {
|
|
|
20060
20480
|
displayName: "Method detail",
|
|
20061
20481
|
outputBasename: basename17,
|
|
20062
20482
|
taskDescription: `Document method **${m.code}** (**${m.name}**) on service **${svc.code}** per \`.gluecharm/context/services-list.json\`.`,
|
|
20063
|
-
exists:
|
|
20483
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20064
20484
|
};
|
|
20065
20485
|
}
|
|
20066
20486
|
function entityDetailTarget(dmCode, ename, slug, contextDir2) {
|
|
@@ -20071,7 +20491,7 @@ function entityDetailTarget(dmCode, ename, slug, contextDir2) {
|
|
|
20071
20491
|
displayName: "Entity detail",
|
|
20072
20492
|
outputBasename: basename17,
|
|
20073
20493
|
taskDescription: `Describe entity **${dmCode}** (**${ename}**, slug **${slug}**) per \`.gluecharm/context/data-model-list.json\`: lifecycle, invariants, storage, ORM/schema mapping.`,
|
|
20074
|
-
exists:
|
|
20494
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20075
20495
|
};
|
|
20076
20496
|
}
|
|
20077
20497
|
function fieldDetailTarget(dmCode, fdCode, fname, fSlug, contextDir2) {
|
|
@@ -20082,7 +20502,7 @@ function fieldDetailTarget(dmCode, fdCode, fname, fSlug, contextDir2) {
|
|
|
20082
20502
|
displayName: "Field detail",
|
|
20083
20503
|
outputBasename: basename17,
|
|
20084
20504
|
taskDescription: `Document field **${fdCode}** (**${fname}**) on entity **${dmCode}** per \`.gluecharm/context/${dmCode}-fields-list.json\`. Cite types and constraints with file and line.`,
|
|
20085
|
-
exists:
|
|
20505
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20086
20506
|
};
|
|
20087
20507
|
}
|
|
20088
20508
|
function toolDetailTarget(row2, contextDir2) {
|
|
@@ -20093,7 +20513,7 @@ function toolDetailTarget(row2, contextDir2) {
|
|
|
20093
20513
|
displayName: "Tool detail",
|
|
20094
20514
|
outputBasename: basename17,
|
|
20095
20515
|
taskDescription: `Describe tool **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/tech-stack-list.json\`: role, version hints, configuration, boundaries.`,
|
|
20096
|
-
exists:
|
|
20516
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20097
20517
|
};
|
|
20098
20518
|
}
|
|
20099
20519
|
function useCaseDetailTarget(feCode, ucCode, ucName, ucSlug, contextDir2) {
|
|
@@ -20106,7 +20526,7 @@ function useCaseDetailTarget(feCode, ucCode, ucName, ucSlug, contextDir2) {
|
|
|
20106
20526
|
taskDescription: `Document use case **${ucCode}** (**${ucName}**) under feature **${feCode}** per \`.gluecharm/context/${feCode}-use-cases-list.json\`. Do not change stable codes.
|
|
20107
20527
|
|
|
20108
20528
|
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.`,
|
|
20109
|
-
exists:
|
|
20529
|
+
exists: fs36.existsSync(path32.join(contextDir2, ucBase)) && fs36.statSync(path32.join(contextDir2, ucBase)).size > 0
|
|
20110
20530
|
};
|
|
20111
20531
|
}
|
|
20112
20532
|
function scenarioDetailTarget(feCode, ucCode, scCode, scName, contextDir2) {
|
|
@@ -20117,7 +20537,7 @@ function scenarioDetailTarget(feCode, ucCode, scCode, scName, contextDir2) {
|
|
|
20117
20537
|
displayName: "Scenario detail",
|
|
20118
20538
|
outputBasename: basename17,
|
|
20119
20539
|
taskDescription: `Document scenario **${scCode}** (**${scName}**) for **${feCode}** / **${ucCode}** per \`.gluecharm/context/${feCode}_${ucCode}-scenarios-list.json\`. Cite steps with file and line where possible.`,
|
|
20120
|
-
exists:
|
|
20540
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20121
20541
|
};
|
|
20122
20542
|
}
|
|
20123
20543
|
function parentsDone(item, byId) {
|
|
@@ -20536,8 +20956,29 @@ async function runWorkstationWithOuterAttempts(item, worktreeRoot, workspaceLabe
|
|
|
20536
20956
|
};
|
|
20537
20957
|
}
|
|
20538
20958
|
async function drainWorkstationPool(p) {
|
|
20539
|
-
const maxC = clampConcurrency(p.oc.maxConcurrentOpenCodeAgents);
|
|
20540
20959
|
const { storageContext, worktreeRoot, workspaceLabel, contextDir: contextDir2, byId, fifo, oc, log, abortSignal } = p;
|
|
20960
|
+
const staticMaxC = clampConcurrency(p.oc.maxConcurrentOpenCodeAgents);
|
|
20961
|
+
const throttle = p.enableCpuAdaptiveThrottle !== false;
|
|
20962
|
+
let adaptiveMax = staticMaxC;
|
|
20963
|
+
const sample = p.cpuPressureSampler ?? (throttle ? createDefaultCpuPressureSampler() : () => 0);
|
|
20964
|
+
const applyCpuPressure = () => {
|
|
20965
|
+
if (!throttle || active < 1) {
|
|
20966
|
+
return;
|
|
20967
|
+
}
|
|
20968
|
+
const ratio = sample();
|
|
20969
|
+
const { adaptiveMax: next, changed } = nextAdaptiveMaxAfterCpuSample({
|
|
20970
|
+
ratio,
|
|
20971
|
+
activeRunningCount: active,
|
|
20972
|
+
priorAdaptiveMax: adaptiveMax
|
|
20973
|
+
});
|
|
20974
|
+
if (changed) {
|
|
20975
|
+
adaptiveMax = next;
|
|
20976
|
+
log(
|
|
20977
|
+
`[pool] cpu pressure ratio=${ratio.toFixed(3)} active=${String(active)} adaptiveMaxConcurrentAi=${String(adaptiveMax)}`
|
|
20978
|
+
);
|
|
20979
|
+
}
|
|
20980
|
+
};
|
|
20981
|
+
const currentCap = () => Math.min(staticMaxC, adaptiveMax);
|
|
20541
20982
|
const artefactRunId = readArtefactRunSnapshot(storageContext)?.runId ?? "unknown-run";
|
|
20542
20983
|
let active = 0;
|
|
20543
20984
|
let wake;
|
|
@@ -20593,9 +21034,10 @@ async function drainWorkstationPool(p) {
|
|
|
20593
21034
|
pump();
|
|
20594
21035
|
return;
|
|
20595
21036
|
}
|
|
21037
|
+
applyCpuPressure();
|
|
20596
21038
|
item.status = "running";
|
|
20597
21039
|
await persist();
|
|
20598
|
-
log(`[pool] start ${id} (active ${active}/${
|
|
21040
|
+
log(`[pool] start ${id} (active ${active}/${currentCap()})`);
|
|
20599
21041
|
const r = await runWorkstationWithOuterAttempts(
|
|
20600
21042
|
item,
|
|
20601
21043
|
worktreeRoot,
|
|
@@ -20650,9 +21092,14 @@ async function drainWorkstationPool(p) {
|
|
|
20650
21092
|
await p.onItemComplete?.(id);
|
|
20651
21093
|
pump();
|
|
20652
21094
|
};
|
|
21095
|
+
let pressureInterval;
|
|
21096
|
+
if (throttle) {
|
|
21097
|
+
const intervalMs = p.__testOnlyCpuPressureIntervalMs ?? 3e4;
|
|
21098
|
+
pressureInterval = setInterval(() => applyCpuPressure(), intervalMs);
|
|
21099
|
+
}
|
|
20653
21100
|
try {
|
|
20654
21101
|
while (true) {
|
|
20655
|
-
while (fifo.length > 0 && active <
|
|
21102
|
+
while (fifo.length > 0 && active < currentCap() && !abortSignal?.aborted) {
|
|
20656
21103
|
const id = fifo.shift();
|
|
20657
21104
|
const it = byId.get(id);
|
|
20658
21105
|
if (!it || it.status !== "pending" || !parentsDone(it, byId)) {
|
|
@@ -20672,11 +21119,14 @@ async function drainWorkstationPool(p) {
|
|
|
20672
21119
|
await waitTurn();
|
|
20673
21120
|
continue;
|
|
20674
21121
|
}
|
|
20675
|
-
if (fifo.length === 0 || active >=
|
|
21122
|
+
if (fifo.length === 0 || active >= currentCap()) {
|
|
20676
21123
|
await waitTurn();
|
|
20677
21124
|
}
|
|
20678
21125
|
}
|
|
20679
21126
|
} finally {
|
|
21127
|
+
if (pressureInterval) {
|
|
21128
|
+
clearInterval(pressureInterval);
|
|
21129
|
+
}
|
|
20680
21130
|
if (poolAbortListenerRegistered && abortSignal) {
|
|
20681
21131
|
abortSignal.removeEventListener("abort", onPipelineAbort);
|
|
20682
21132
|
}
|
|
@@ -20716,7 +21166,7 @@ async function runSynthesisPipelineDrainFromPreparedWorktree(storageContext, rep
|
|
|
20716
21166
|
offlineLearnAfterSameSessionTrace: getAceOfflineLearnAfterSameSessionTrace(handle.path)
|
|
20717
21167
|
};
|
|
20718
21168
|
const contextDir2 = path32.join(handle.path, ".gluecharm", "context");
|
|
20719
|
-
|
|
21169
|
+
fs36.mkdirSync(contextDir2, { recursive: true });
|
|
20720
21170
|
const initialItems = buildRootItems();
|
|
20721
21171
|
await startArtefactRun(storageContext, repoRoot, handle.path, initialItems);
|
|
20722
21172
|
await cb.onBootstrapReady?.({ worktreeRoot: handle.path, contextDir: contextDir2 });
|
|
@@ -20817,27 +21267,27 @@ async function runSynthesisPipeline(storageContext, repoRoot, workspaceLabel, ex
|
|
|
20817
21267
|
}
|
|
20818
21268
|
|
|
20819
21269
|
// src/workspaceContextPromote.ts
|
|
20820
|
-
var
|
|
21270
|
+
var fs37 = __toESM(require("fs"));
|
|
20821
21271
|
var path33 = __toESM(require("path"));
|
|
20822
21272
|
function promoteContextDirectoryToWorkspaceFs(sourceContextDir, workspaceRootFs) {
|
|
20823
21273
|
const dest = path33.join(workspaceRootFs, ".gluecharm", "context");
|
|
20824
|
-
|
|
20825
|
-
|
|
21274
|
+
fs37.mkdirSync(path33.join(workspaceRootFs, ".gluecharm"), { recursive: true });
|
|
21275
|
+
fs37.mkdirSync(dest, { recursive: true });
|
|
20826
21276
|
let names;
|
|
20827
21277
|
try {
|
|
20828
|
-
names =
|
|
21278
|
+
names = fs37.readdirSync(sourceContextDir);
|
|
20829
21279
|
} catch {
|
|
20830
21280
|
return { filesCopied: 0 };
|
|
20831
21281
|
}
|
|
20832
21282
|
let filesCopied = 0;
|
|
20833
21283
|
for (const name of names) {
|
|
20834
21284
|
const srcPath = path33.join(sourceContextDir, name);
|
|
20835
|
-
if (!
|
|
21285
|
+
if (!fs37.statSync(srcPath).isFile()) {
|
|
20836
21286
|
continue;
|
|
20837
21287
|
}
|
|
20838
|
-
const buf =
|
|
21288
|
+
const buf = fs37.readFileSync(srcPath);
|
|
20839
21289
|
const target = path33.join(dest, name);
|
|
20840
|
-
|
|
21290
|
+
fs37.writeFileSync(target, buf);
|
|
20841
21291
|
filesCopied += 1;
|
|
20842
21292
|
}
|
|
20843
21293
|
return { filesCopied };
|
|
@@ -21497,7 +21947,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21497
21947
|
}
|
|
21498
21948
|
|
|
21499
21949
|
// src/factory/generateContextFactoryHeadlessHost.ts
|
|
21500
|
-
var
|
|
21950
|
+
var fs46 = __toESM(require("node:fs"));
|
|
21501
21951
|
var path43 = __toESM(require("node:path"));
|
|
21502
21952
|
|
|
21503
21953
|
// src/stores/pipelineRunStore.ts
|
|
@@ -21598,11 +22048,11 @@ async function noteAgentsMaterialized(context) {
|
|
|
21598
22048
|
}
|
|
21599
22049
|
|
|
21600
22050
|
// src/pipelines/remediation/missingWorkstations.ts
|
|
21601
|
-
var
|
|
22051
|
+
var fs39 = __toESM(require("fs"));
|
|
21602
22052
|
var path35 = __toESM(require("path"));
|
|
21603
22053
|
|
|
21604
22054
|
// src/analysis/analysisDetailMarkdownDiscovery.ts
|
|
21605
|
-
var
|
|
22055
|
+
var fs38 = __toESM(require("fs"));
|
|
21606
22056
|
var path34 = __toESM(require("path"));
|
|
21607
22057
|
var SLUG4 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
21608
22058
|
var FE2 = /^FE-\d+$/;
|
|
@@ -21624,7 +22074,7 @@ var STEM_TO_AGENT = {
|
|
|
21624
22074
|
};
|
|
21625
22075
|
function readJson5(filePath) {
|
|
21626
22076
|
try {
|
|
21627
|
-
let raw =
|
|
22077
|
+
let raw = fs38.readFileSync(filePath, "utf-8");
|
|
21628
22078
|
if (raw.length > 0 && raw.charCodeAt(0) === 65279) {
|
|
21629
22079
|
raw = raw.slice(1);
|
|
21630
22080
|
}
|
|
@@ -21892,7 +22342,7 @@ function fileAndValidationFromKind(kind) {
|
|
|
21892
22342
|
function classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeRoot) {
|
|
21893
22343
|
const abs = path35.join(contextDir2, row2.relativePath);
|
|
21894
22344
|
try {
|
|
21895
|
-
const st =
|
|
22345
|
+
const st = fs39.statSync(abs);
|
|
21896
22346
|
if (!st.isFile()) {
|
|
21897
22347
|
return { kind: "absent", detail: "Path exists but is not a regular file." };
|
|
21898
22348
|
}
|
|
@@ -21930,7 +22380,7 @@ function classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeR
|
|
|
21930
22380
|
};
|
|
21931
22381
|
}
|
|
21932
22382
|
const schemaAbs = path35.join(worktreeRoot, ".opencode", "schemas", "context-lists", schemaBn);
|
|
21933
|
-
if (!
|
|
22383
|
+
if (!fs39.existsSync(schemaAbs)) {
|
|
21934
22384
|
return {
|
|
21935
22385
|
kind: "invalid",
|
|
21936
22386
|
detail: `Schema not found (${schemaBn}). Run **Materialize agents** on this checkout.`
|
|
@@ -22166,7 +22616,7 @@ function listMissingWorkstations(contextDir2, worktreeRoot, snapshot) {
|
|
|
22166
22616
|
}
|
|
22167
22617
|
}
|
|
22168
22618
|
}
|
|
22169
|
-
if (!
|
|
22619
|
+
if (!fs39.existsSync(contextDir2)) {
|
|
22170
22620
|
return [...map.values()].sort((a, b) => a.key.localeCompare(b.key));
|
|
22171
22621
|
}
|
|
22172
22622
|
const dynamic = discoverDynamicAnalysisTestSteps(contextDir2);
|
|
@@ -22346,12 +22796,12 @@ async function runRemediationPipelineMissingPass(p) {
|
|
|
22346
22796
|
}
|
|
22347
22797
|
|
|
22348
22798
|
// src/pipelines/coverage/coveragePipeline.ts
|
|
22349
|
-
var
|
|
22350
|
-
var
|
|
22799
|
+
var import_child_process5 = require("child_process");
|
|
22800
|
+
var fs41 = __toESM(require("fs"));
|
|
22351
22801
|
var path38 = __toESM(require("path"));
|
|
22352
22802
|
|
|
22353
22803
|
// src/analysis/coverageReferenceValidationSchemaValidate.ts
|
|
22354
|
-
var
|
|
22804
|
+
var fs40 = __toESM(require("fs"));
|
|
22355
22805
|
var path37 = __toESM(require("path"));
|
|
22356
22806
|
var import__5 = __toESM(require__());
|
|
22357
22807
|
function stripUtf8Bom4(s) {
|
|
@@ -22381,7 +22831,7 @@ function getValidate() {
|
|
|
22381
22831
|
return compiledValidate;
|
|
22382
22832
|
}
|
|
22383
22833
|
const schemaPath = bundledCoverageReferenceValidationSchemaPath();
|
|
22384
|
-
const schemaRaw = stripUtf8Bom4(
|
|
22834
|
+
const schemaRaw = stripUtf8Bom4(fs40.readFileSync(schemaPath, "utf-8"));
|
|
22385
22835
|
const schema = JSON.parse(schemaRaw);
|
|
22386
22836
|
const ajv2 = new import__5.default({ allErrors: true, strict: false });
|
|
22387
22837
|
compiledValidate = ajv2.compile(schema);
|
|
@@ -22397,7 +22847,7 @@ function validateCoverageReferenceValidationData(data) {
|
|
|
22397
22847
|
function readAndValidateCoverageReferenceValidationFile(jsonAbsolutePath) {
|
|
22398
22848
|
let raw;
|
|
22399
22849
|
try {
|
|
22400
|
-
raw = stripUtf8Bom4(
|
|
22850
|
+
raw = stripUtf8Bom4(fs40.readFileSync(jsonAbsolutePath, "utf-8"));
|
|
22401
22851
|
} catch (e) {
|
|
22402
22852
|
return {
|
|
22403
22853
|
ok: false,
|
|
@@ -22439,7 +22889,7 @@ var DEFAULT_IGNORE_DIR_BASENAMES = [
|
|
|
22439
22889
|
var GIT_LS_FILES_MAX_BUFFER = 64 * 1024 * 1024;
|
|
22440
22890
|
function tryLoadGitNonIgnoredPathSet(repositoryRootAbs) {
|
|
22441
22891
|
const root = path38.resolve(repositoryRootAbs);
|
|
22442
|
-
if (!
|
|
22892
|
+
if (!fs41.existsSync(path38.join(root, ".git"))) {
|
|
22443
22893
|
return null;
|
|
22444
22894
|
}
|
|
22445
22895
|
const env = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
@@ -22450,8 +22900,8 @@ function tryLoadGitNonIgnoredPathSet(repositoryRootAbs) {
|
|
|
22450
22900
|
env
|
|
22451
22901
|
};
|
|
22452
22902
|
try {
|
|
22453
|
-
const tracked = (0,
|
|
22454
|
-
const others = (0,
|
|
22903
|
+
const tracked = (0, import_child_process5.execFileSync)("git", ["-c", "core.quotepath=false", "ls-files", "-z"], opts);
|
|
22904
|
+
const others = (0, import_child_process5.execFileSync)(
|
|
22455
22905
|
"git",
|
|
22456
22906
|
["-c", "core.quotepath=false", "ls-files", "-z", "--others", "--exclude-standard"],
|
|
22457
22907
|
opts
|
|
@@ -22594,7 +23044,7 @@ function extractEvidenceIndexPathCitations(body) {
|
|
|
22594
23044
|
function listContextFilesRecursive(dir, acc) {
|
|
22595
23045
|
let entries;
|
|
22596
23046
|
try {
|
|
22597
|
-
entries =
|
|
23047
|
+
entries = fs41.readdirSync(dir, { withFileTypes: true });
|
|
22598
23048
|
} catch {
|
|
22599
23049
|
return;
|
|
22600
23050
|
}
|
|
@@ -22612,7 +23062,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
22612
23062
|
const walk = (dir) => {
|
|
22613
23063
|
let entries;
|
|
22614
23064
|
try {
|
|
22615
|
-
entries =
|
|
23065
|
+
entries = fs41.readdirSync(dir, { withFileTypes: true });
|
|
22616
23066
|
} catch {
|
|
22617
23067
|
return;
|
|
22618
23068
|
}
|
|
@@ -22642,7 +23092,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
22642
23092
|
}
|
|
22643
23093
|
let st;
|
|
22644
23094
|
try {
|
|
22645
|
-
st =
|
|
23095
|
+
st = fs41.statSync(full);
|
|
22646
23096
|
} catch {
|
|
22647
23097
|
continue;
|
|
22648
23098
|
}
|
|
@@ -22652,7 +23102,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
22652
23102
|
}
|
|
22653
23103
|
let buf;
|
|
22654
23104
|
try {
|
|
22655
|
-
buf =
|
|
23105
|
+
buf = fs41.readFileSync(full);
|
|
22656
23106
|
} catch {
|
|
22657
23107
|
excludedOut.push({ path: rel, reason: "read error" });
|
|
22658
23108
|
continue;
|
|
@@ -22672,7 +23122,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
22672
23122
|
}
|
|
22673
23123
|
function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings) {
|
|
22674
23124
|
const references = [];
|
|
22675
|
-
if (!
|
|
23125
|
+
if (!fs41.existsSync(contextDirAbs)) {
|
|
22676
23126
|
warnings.push(`Context directory missing: ${contextDirAbs}`);
|
|
22677
23127
|
return references;
|
|
22678
23128
|
}
|
|
@@ -22688,7 +23138,7 @@ function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings
|
|
|
22688
23138
|
}
|
|
22689
23139
|
let raw;
|
|
22690
23140
|
try {
|
|
22691
|
-
raw =
|
|
23141
|
+
raw = fs41.readFileSync(abs, "utf-8");
|
|
22692
23142
|
} catch (e) {
|
|
22693
23143
|
warnings.push(`Skip JSON (read error): ${sourceArtefact} \u2014 ${e instanceof Error ? e.message : String(e)}`);
|
|
22694
23144
|
continue;
|
|
@@ -22719,7 +23169,7 @@ function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings
|
|
|
22719
23169
|
if (ext === ".md") {
|
|
22720
23170
|
let text;
|
|
22721
23171
|
try {
|
|
22722
|
-
const buf =
|
|
23172
|
+
const buf = fs41.readFileSync(abs);
|
|
22723
23173
|
text = decodeBufferForLineCount(buf);
|
|
22724
23174
|
} catch (e) {
|
|
22725
23175
|
warnings.push(`Skip markdown (read/decode error): ${sourceArtefact} \u2014 ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -22776,7 +23226,7 @@ function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirA
|
|
|
22776
23226
|
}
|
|
22777
23227
|
const excludedFiles = [];
|
|
22778
23228
|
const gitNonIgnoredPaths = tryLoadGitNonIgnoredPathSet(repoRoot);
|
|
22779
|
-
if (
|
|
23229
|
+
if (fs41.existsSync(path38.join(repoRoot, ".git")) && gitNonIgnoredPaths === null) {
|
|
22780
23230
|
warnings.push(
|
|
22781
23231
|
"Repository has .git but git ls-files failed or git is unavailable; .gitignore / exclude-standard not applied."
|
|
22782
23232
|
);
|
|
@@ -22827,10 +23277,10 @@ function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirA
|
|
|
22827
23277
|
function runCoveragePipeline(opts) {
|
|
22828
23278
|
const repoRoot = path38.resolve(opts.repositoryRootAbs);
|
|
22829
23279
|
const contextDir2 = path38.resolve(opts.contextDirAbs);
|
|
22830
|
-
if (!
|
|
23280
|
+
if (!fs41.existsSync(repoRoot)) {
|
|
22831
23281
|
return { ok: false, error: `Repository root does not exist: ${repoRoot}` };
|
|
22832
23282
|
}
|
|
22833
|
-
if (!
|
|
23283
|
+
if (!fs41.existsSync(contextDir2)) {
|
|
22834
23284
|
return {
|
|
22835
23285
|
ok: false,
|
|
22836
23286
|
error: `Missing .gluecharm/context: ${contextDir2}`
|
|
@@ -22852,7 +23302,7 @@ ${schemaCheck.errors.join("\n")}`,
|
|
|
22852
23302
|
if (opts.write) {
|
|
22853
23303
|
try {
|
|
22854
23304
|
const payload = stableStringifyCoverageDocument(document);
|
|
22855
|
-
|
|
23305
|
+
fs41.writeFileSync(outPath, payload, "utf-8");
|
|
22856
23306
|
} catch (e) {
|
|
22857
23307
|
return {
|
|
22858
23308
|
ok: false,
|
|
@@ -22866,11 +23316,11 @@ ${schemaCheck.errors.join("\n")}`,
|
|
|
22866
23316
|
|
|
22867
23317
|
// src/pipelines/remediation/zeroReferenceWorkstationChain.ts
|
|
22868
23318
|
var crypto = __toESM(require("crypto"));
|
|
22869
|
-
var
|
|
23319
|
+
var fs43 = __toESM(require("fs"));
|
|
22870
23320
|
var path40 = __toESM(require("path"));
|
|
22871
23321
|
|
|
22872
23322
|
// src/analysis/zeroReferenceRemediationSchemaValidate.ts
|
|
22873
|
-
var
|
|
23323
|
+
var fs42 = __toESM(require("fs"));
|
|
22874
23324
|
var path39 = __toESM(require("path"));
|
|
22875
23325
|
var import__6 = __toESM(require__());
|
|
22876
23326
|
function stripUtf8Bom5(s) {
|
|
@@ -22892,7 +23342,7 @@ function formatAjvErrors6(errors) {
|
|
|
22892
23342
|
var ajv = new import__6.default({ allErrors: true, strict: false });
|
|
22893
23343
|
function compileSchema(basename17) {
|
|
22894
23344
|
const schemaPath = path39.join(schemasDir(), basename17);
|
|
22895
|
-
const schemaRaw = stripUtf8Bom5(
|
|
23345
|
+
const schemaRaw = stripUtf8Bom5(fs42.readFileSync(schemaPath, "utf-8"));
|
|
22896
23346
|
const schema = JSON.parse(schemaRaw);
|
|
22897
23347
|
return ajv.compile(schema);
|
|
22898
23348
|
}
|
|
@@ -22936,7 +23386,7 @@ var ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS = 5;
|
|
|
22936
23386
|
var ZERO_REF_STAGING_FILE_PREVIEW_MAX_CHARS = 6e3;
|
|
22937
23387
|
function readStagingOutputPreview(outAbs) {
|
|
22938
23388
|
try {
|
|
22939
|
-
const s =
|
|
23389
|
+
const s = fs43.readFileSync(outAbs, "utf-8");
|
|
22940
23390
|
if (s.length <= ZERO_REF_STAGING_FILE_PREVIEW_MAX_CHARS) {
|
|
22941
23391
|
return s;
|
|
22942
23392
|
}
|
|
@@ -23219,14 +23669,14 @@ function readNonReferencedFilesFromRepositoryRoot(repositoryRootAbs) {
|
|
|
23219
23669
|
return { ok: true, paths, ...generatedAt ? { generatedAt } : {} };
|
|
23220
23670
|
}
|
|
23221
23671
|
function readOrInitRoutingDoc(routingAbs, coverageReferenceGeneratedAt) {
|
|
23222
|
-
if (!
|
|
23672
|
+
if (!fs43.existsSync(routingAbs)) {
|
|
23223
23673
|
return {
|
|
23224
23674
|
schemaVersion: ROUTING_SCHEMA_VERSION,
|
|
23225
23675
|
...coverageReferenceGeneratedAt ? { coverageReferenceGeneratedAt } : {},
|
|
23226
23676
|
records: {}
|
|
23227
23677
|
};
|
|
23228
23678
|
}
|
|
23229
|
-
const raw =
|
|
23679
|
+
const raw = fs43.readFileSync(routingAbs, "utf-8");
|
|
23230
23680
|
const data = JSON.parse(raw);
|
|
23231
23681
|
if (!data.records || typeof data.records !== "object") {
|
|
23232
23682
|
return {
|
|
@@ -23238,10 +23688,10 @@ function readOrInitRoutingDoc(routingAbs, coverageReferenceGeneratedAt) {
|
|
|
23238
23688
|
return data;
|
|
23239
23689
|
}
|
|
23240
23690
|
function readOrInitTriageDoc(triageAbs) {
|
|
23241
|
-
if (!
|
|
23691
|
+
if (!fs43.existsSync(triageAbs)) {
|
|
23242
23692
|
return { schemaVersion: TRIAGE_SCHEMA_VERSION, records: {} };
|
|
23243
23693
|
}
|
|
23244
|
-
const raw =
|
|
23694
|
+
const raw = fs43.readFileSync(triageAbs, "utf-8");
|
|
23245
23695
|
const data = JSON.parse(raw);
|
|
23246
23696
|
if (!data.records || typeof data.records !== "object") {
|
|
23247
23697
|
return { schemaVersion: TRIAGE_SCHEMA_VERSION, records: {} };
|
|
@@ -23292,7 +23742,7 @@ function lineCountRepoFile(worktreeRootAbs, relPosix) {
|
|
|
23292
23742
|
const abs = path40.join(worktreeRootAbs, ...relPosix.split("/"));
|
|
23293
23743
|
let buf;
|
|
23294
23744
|
try {
|
|
23295
|
-
buf =
|
|
23745
|
+
buf = fs43.readFileSync(abs);
|
|
23296
23746
|
} catch {
|
|
23297
23747
|
return 1;
|
|
23298
23748
|
}
|
|
@@ -23346,7 +23796,7 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23346
23796
|
const cfg = LIST_MERGE_CFG[input.listKind];
|
|
23347
23797
|
const listPath = path40.join(input.contextDirAbs, cfg.listBasename);
|
|
23348
23798
|
const schemaPath = path40.join(resolveContextListSchemasDir(), cfg.schemaBasename);
|
|
23349
|
-
if (!
|
|
23799
|
+
if (!fs43.existsSync(listPath)) {
|
|
23350
23800
|
return {
|
|
23351
23801
|
ok: false,
|
|
23352
23802
|
message: `${cfg.listBasename} not found \u2014 run coordination step ${LIST_STEP_HINT[input.listKind]} first.`
|
|
@@ -23357,7 +23807,7 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23357
23807
|
return withCoordinationListFileLock(listPath, {}, async () => {
|
|
23358
23808
|
let raw;
|
|
23359
23809
|
try {
|
|
23360
|
-
raw =
|
|
23810
|
+
raw = fs43.readFileSync(listPath, "utf-8");
|
|
23361
23811
|
} catch (e) {
|
|
23362
23812
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
23363
23813
|
}
|
|
@@ -23425,7 +23875,7 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23425
23875
|
});
|
|
23426
23876
|
const tmp = `${listPath}.tmp.${process.pid}`;
|
|
23427
23877
|
try {
|
|
23428
|
-
|
|
23878
|
+
fs43.writeFileSync(tmp, `${JSON.stringify(doc, null, 2)}
|
|
23429
23879
|
`, "utf-8");
|
|
23430
23880
|
} catch (e) {
|
|
23431
23881
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
@@ -23433,13 +23883,13 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23433
23883
|
const v = validateCoordinationListJson(tmp, schemaPath);
|
|
23434
23884
|
if (!v.ok) {
|
|
23435
23885
|
try {
|
|
23436
|
-
|
|
23886
|
+
fs43.unlinkSync(tmp);
|
|
23437
23887
|
} catch {
|
|
23438
23888
|
}
|
|
23439
23889
|
return { ok: false, message: `${cfg.listBasename} validation failed: ${JSON.stringify(v.failure)}` };
|
|
23440
23890
|
}
|
|
23441
23891
|
try {
|
|
23442
|
-
|
|
23892
|
+
fs43.renameSync(tmp, listPath);
|
|
23443
23893
|
} catch (e) {
|
|
23444
23894
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
23445
23895
|
}
|
|
@@ -23449,9 +23899,9 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23449
23899
|
}
|
|
23450
23900
|
async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, workspaceLabel) {
|
|
23451
23901
|
const outAbs = stagingPathForTarget(contextDirAbs, "classifier", targetFilePathPosix);
|
|
23452
|
-
|
|
23902
|
+
fs43.mkdirSync(path40.dirname(outAbs), { recursive: true });
|
|
23453
23903
|
const runDir = path40.join(common.worktreeRoot, ".opencode", "_run");
|
|
23454
|
-
|
|
23904
|
+
fs43.mkdirSync(runDir, { recursive: true });
|
|
23455
23905
|
const outputBasename = path40.basename(outAbs);
|
|
23456
23906
|
const listTaskDescription = [
|
|
23457
23907
|
`Target file (repo-relative, POSIX): **${targetFilePathPosix}**`,
|
|
@@ -23489,7 +23939,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
|
|
|
23489
23939
|
...repairAppendix ? { repairAppendix } : {}
|
|
23490
23940
|
});
|
|
23491
23941
|
const promptPath = path40.join(runDir, `zero-ref-classify-a${attempt}-${Date.now()}.prompt.txt`);
|
|
23492
|
-
|
|
23942
|
+
fs43.writeFileSync(promptPath, body, "utf-8");
|
|
23493
23943
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
23494
23944
|
promptFile: promptPath,
|
|
23495
23945
|
agentId: ZERO_REF_CLASSIFY_AGENT_STEM,
|
|
@@ -23516,7 +23966,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
|
|
|
23516
23966
|
const canRetry = attempt < ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS - 1;
|
|
23517
23967
|
let st;
|
|
23518
23968
|
try {
|
|
23519
|
-
st =
|
|
23969
|
+
st = fs43.statSync(outAbs);
|
|
23520
23970
|
} catch {
|
|
23521
23971
|
st = void 0;
|
|
23522
23972
|
}
|
|
@@ -23538,7 +23988,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
|
|
|
23538
23988
|
}
|
|
23539
23989
|
let parsed;
|
|
23540
23990
|
try {
|
|
23541
|
-
parsed = JSON.parse(
|
|
23991
|
+
parsed = JSON.parse(fs43.readFileSync(outAbs, "utf-8"));
|
|
23542
23992
|
} catch (e) {
|
|
23543
23993
|
const msg = e instanceof Error ? e.message : String(e);
|
|
23544
23994
|
lastFailureMessage = `Classifier output not valid JSON: ${msg}`;
|
|
@@ -23623,7 +24073,7 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
|
|
|
23623
24073
|
const mdAbs = path40.join(contextDirAbs, mdBasename);
|
|
23624
24074
|
const agentStem = which === "project" ? ZERO_REF_ADD_REF_PROJECT_AGENT_STEM : ZERO_REF_ADD_REF_ARCH_AGENT_STEM;
|
|
23625
24075
|
const runDir = path40.join(common.worktreeRoot, ".opencode", "_run");
|
|
23626
|
-
|
|
24076
|
+
fs43.mkdirSync(runDir, { recursive: true });
|
|
23627
24077
|
const lines = [
|
|
23628
24078
|
`# SRS-30 \u2014 Add reference to ${mdBasename}`,
|
|
23629
24079
|
``,
|
|
@@ -23639,7 +24089,7 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
|
|
|
23639
24089
|
`- Do not remove unrelated content; append or extend the most appropriate section.`
|
|
23640
24090
|
];
|
|
23641
24091
|
const promptPath = path40.join(runDir, `zero-ref-md-${which}-${Date.now()}.prompt.txt`);
|
|
23642
|
-
|
|
24092
|
+
fs43.writeFileSync(promptPath, lines.join("\n"), "utf-8");
|
|
23643
24093
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
23644
24094
|
promptFile: promptPath,
|
|
23645
24095
|
agentId: agentStem,
|
|
@@ -23666,9 +24116,9 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
|
|
|
23666
24116
|
async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathPosix, routingSummary, workspaceLabel, triageScope) {
|
|
23667
24117
|
const meta = TRIAGE_SCOPE_META[triageScope];
|
|
23668
24118
|
const outAbs = stagingPathForTarget(contextDirAbs, "triage", targetFilePathPosix);
|
|
23669
|
-
|
|
24119
|
+
fs43.mkdirSync(path40.dirname(outAbs), { recursive: true });
|
|
23670
24120
|
const runDir = path40.join(common.worktreeRoot, ".opencode", "_run");
|
|
23671
|
-
|
|
24121
|
+
fs43.mkdirSync(runDir, { recursive: true });
|
|
23672
24122
|
const outputBasename = path40.basename(outAbs);
|
|
23673
24123
|
const listTaskDescription = [
|
|
23674
24124
|
`Target file: **${targetFilePathPosix}** (${workspaceLabel})`,
|
|
@@ -23700,7 +24150,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
23700
24150
|
...repairAppendix ? { repairAppendix } : {}
|
|
23701
24151
|
});
|
|
23702
24152
|
const promptPath = path40.join(runDir, `zero-ref-triage-a${attempt}-${Date.now()}.prompt.txt`);
|
|
23703
|
-
|
|
24153
|
+
fs43.writeFileSync(promptPath, body, "utf-8");
|
|
23704
24154
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
23705
24155
|
promptFile: promptPath,
|
|
23706
24156
|
agentId: ZERO_REF_TRIAGE_COORD_AGENT_STEM,
|
|
@@ -23727,7 +24177,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
23727
24177
|
const canRetry = attempt < ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS - 1;
|
|
23728
24178
|
let st;
|
|
23729
24179
|
try {
|
|
23730
|
-
st =
|
|
24180
|
+
st = fs43.statSync(outAbs);
|
|
23731
24181
|
} catch {
|
|
23732
24182
|
st = void 0;
|
|
23733
24183
|
}
|
|
@@ -23749,7 +24199,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
23749
24199
|
}
|
|
23750
24200
|
let parsed;
|
|
23751
24201
|
try {
|
|
23752
|
-
parsed = JSON.parse(
|
|
24202
|
+
parsed = JSON.parse(fs43.readFileSync(outAbs, "utf-8"));
|
|
23753
24203
|
} catch (e) {
|
|
23754
24204
|
const msg = e instanceof Error ? e.message : String(e);
|
|
23755
24205
|
lastFailureMessage = `Triage output not valid JSON: ${msg}`;
|
|
@@ -23805,7 +24255,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
23805
24255
|
return { ok: false, message: lastFailureMessage, stagingPath: outAbs };
|
|
23806
24256
|
}
|
|
23807
24257
|
try {
|
|
23808
|
-
|
|
24258
|
+
fs43.writeFileSync(outAbs, `${JSON.stringify(parsed, null, 2)}
|
|
23809
24259
|
`, "utf-8");
|
|
23810
24260
|
} catch {
|
|
23811
24261
|
}
|
|
@@ -23823,7 +24273,7 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
23823
24273
|
}
|
|
23824
24274
|
let stagingParsed;
|
|
23825
24275
|
try {
|
|
23826
|
-
stagingParsed = JSON.parse(
|
|
24276
|
+
stagingParsed = JSON.parse(fs43.readFileSync(cr.stagingPath, "utf-8"));
|
|
23827
24277
|
} catch (e) {
|
|
23828
24278
|
return { ok: false, message: String(e) };
|
|
23829
24279
|
}
|
|
@@ -23839,8 +24289,8 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
23839
24289
|
if (!s.ok) {
|
|
23840
24290
|
throw new Error(s.errors.join("; "));
|
|
23841
24291
|
}
|
|
23842
|
-
|
|
23843
|
-
|
|
24292
|
+
fs43.mkdirSync(path40.dirname(routingAbs), { recursive: true });
|
|
24293
|
+
fs43.writeFileSync(routingAbs, s.json, "utf-8");
|
|
23844
24294
|
});
|
|
23845
24295
|
const routing = stagingParsed.routing;
|
|
23846
24296
|
const routingSummary = typeof stagingParsed.projectRelationSummary === "string" ? stagingParsed.projectRelationSummary : "";
|
|
@@ -23871,7 +24321,7 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
23871
24321
|
}
|
|
23872
24322
|
let triageParsed;
|
|
23873
24323
|
try {
|
|
23874
|
-
triageParsed = JSON.parse(
|
|
24324
|
+
triageParsed = JSON.parse(fs43.readFileSync(tr.stagingPath, "utf-8"));
|
|
23875
24325
|
} catch (e) {
|
|
23876
24326
|
return { ok: false, message: String(e) };
|
|
23877
24327
|
}
|
|
@@ -23888,8 +24338,8 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
23888
24338
|
if (!s.ok) {
|
|
23889
24339
|
throw new Error(s.errors.join("; "));
|
|
23890
24340
|
}
|
|
23891
|
-
|
|
23892
|
-
|
|
24341
|
+
fs43.mkdirSync(path40.dirname(triageAbs), { recursive: true });
|
|
24342
|
+
fs43.writeFileSync(triageAbs, s.json, "utf-8");
|
|
23893
24343
|
});
|
|
23894
24344
|
const decision = triageParsed.decision;
|
|
23895
24345
|
if (decision === "new_item" || decision === "enrich_existing") {
|
|
@@ -23977,7 +24427,7 @@ async function runRemediationPipelineZeroRefPass(p) {
|
|
|
23977
24427
|
}
|
|
23978
24428
|
|
|
23979
24429
|
// src/pipelines/coverage/coverageExecutionReport.ts
|
|
23980
|
-
var
|
|
24430
|
+
var fs44 = __toESM(require("fs"));
|
|
23981
24431
|
var path41 = __toESM(require("path"));
|
|
23982
24432
|
var REFERENCE_COVERAGE_EXECUTION_REPORT_BASENAME = "reference-coverage-execution-report.md";
|
|
23983
24433
|
function inlineMdText(s) {
|
|
@@ -24074,7 +24524,7 @@ function collectNoActionRowsFromRoutingDoc(doc) {
|
|
|
24074
24524
|
return rows;
|
|
24075
24525
|
}
|
|
24076
24526
|
function readRoutingDocFromDisk(routingAbs) {
|
|
24077
|
-
if (!
|
|
24527
|
+
if (!fs44.existsSync(routingAbs)) {
|
|
24078
24528
|
return {
|
|
24079
24529
|
ok: true,
|
|
24080
24530
|
doc: { schemaVersion: "1", records: {} }
|
|
@@ -24082,7 +24532,7 @@ function readRoutingDocFromDisk(routingAbs) {
|
|
|
24082
24532
|
}
|
|
24083
24533
|
let raw;
|
|
24084
24534
|
try {
|
|
24085
|
-
raw =
|
|
24535
|
+
raw = fs44.readFileSync(routingAbs, "utf-8");
|
|
24086
24536
|
} catch (e) {
|
|
24087
24537
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
24088
24538
|
}
|
|
@@ -24122,20 +24572,20 @@ async function runCoverageExecutionReport(p) {
|
|
|
24122
24572
|
}
|
|
24123
24573
|
let previous;
|
|
24124
24574
|
try {
|
|
24125
|
-
if (
|
|
24126
|
-
previous =
|
|
24575
|
+
if (fs44.existsSync(outAbs)) {
|
|
24576
|
+
previous = fs44.readFileSync(outAbs, "utf-8");
|
|
24127
24577
|
}
|
|
24128
24578
|
} catch {
|
|
24129
24579
|
previous = void 0;
|
|
24130
24580
|
}
|
|
24131
24581
|
try {
|
|
24132
|
-
|
|
24133
|
-
|
|
24582
|
+
fs44.mkdirSync(path41.dirname(outAbs), { recursive: true });
|
|
24583
|
+
fs44.writeFileSync(outAbs, md, "utf-8");
|
|
24134
24584
|
} catch (e) {
|
|
24135
24585
|
const msg = e instanceof Error ? e.message : String(e);
|
|
24136
24586
|
if (previous !== void 0) {
|
|
24137
24587
|
try {
|
|
24138
|
-
|
|
24588
|
+
fs44.writeFileSync(outAbs, previous, "utf-8");
|
|
24139
24589
|
} catch {
|
|
24140
24590
|
}
|
|
24141
24591
|
}
|
|
@@ -24146,7 +24596,7 @@ async function runCoverageExecutionReport(p) {
|
|
|
24146
24596
|
}
|
|
24147
24597
|
|
|
24148
24598
|
// src/gluecharm/minimalGluecharmLayout.ts
|
|
24149
|
-
var
|
|
24599
|
+
var fs45 = __toESM(require("node:fs"));
|
|
24150
24600
|
var path42 = __toESM(require("node:path"));
|
|
24151
24601
|
var MINIMAL_GLUECHARM_RELATIVE_DIRS = [
|
|
24152
24602
|
[".gluecharm", "docs", "srs"],
|
|
@@ -24159,7 +24609,7 @@ function ensureMinimalGluecharmLayoutNode(repoRootAbs) {
|
|
|
24159
24609
|
for (const segments of MINIMAL_GLUECHARM_RELATIVE_DIRS) {
|
|
24160
24610
|
const dir = path42.join(root, ...segments);
|
|
24161
24611
|
try {
|
|
24162
|
-
|
|
24612
|
+
fs45.mkdirSync(dir, { recursive: true });
|
|
24163
24613
|
} catch (e) {
|
|
24164
24614
|
const err = e;
|
|
24165
24615
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -24541,13 +24991,13 @@ function buildFactoryDepsHeadless(input) {
|
|
|
24541
24991
|
},
|
|
24542
24992
|
runPrepareAnalysisWorktree: async (resume) => {
|
|
24543
24993
|
if (resume) {
|
|
24544
|
-
if (adHocWorktree &&
|
|
24994
|
+
if (adHocWorktree && fs46.existsSync(path43.join(adHocWorktree.path, ".git"))) {
|
|
24545
24995
|
return { ok: true };
|
|
24546
24996
|
}
|
|
24547
24997
|
const snap = readAnalysisWorkspaceSnapshot(storageContext);
|
|
24548
24998
|
const wtPath = snap?.adHocWorktreePath?.trim();
|
|
24549
24999
|
const repo = snap?.adHocRepositoryRoot?.trim() || repoRoot;
|
|
24550
|
-
if (wtPath &&
|
|
25000
|
+
if (wtPath && fs46.existsSync(path43.join(wtPath, ".git"))) {
|
|
24551
25001
|
adHocWorktree = attachWorktreeHandle(wtPath, repo);
|
|
24552
25002
|
macroSourceBranch = snap?.adHocSourceBranchAtCreation;
|
|
24553
25003
|
macroFinalize = () => {
|
|
@@ -24772,7 +25222,7 @@ function stderrLinesForFactoryFailures(failures, exitCode) {
|
|
|
24772
25222
|
var path48 = __toESM(require("node:path"));
|
|
24773
25223
|
|
|
24774
25224
|
// src/factory/updateContext/updateContextBaseline.ts
|
|
24775
|
-
var
|
|
25225
|
+
var fs47 = __toESM(require("node:fs"));
|
|
24776
25226
|
var path44 = __toESM(require("node:path"));
|
|
24777
25227
|
function isValidIso(s) {
|
|
24778
25228
|
const t = Date.parse(s);
|
|
@@ -24783,7 +25233,7 @@ function maxMtimeRegularFilesUnderDir(dirAbs) {
|
|
|
24783
25233
|
const walk = (d) => {
|
|
24784
25234
|
let entries;
|
|
24785
25235
|
try {
|
|
24786
|
-
entries =
|
|
25236
|
+
entries = fs47.readdirSync(d, { withFileTypes: true });
|
|
24787
25237
|
} catch {
|
|
24788
25238
|
return;
|
|
24789
25239
|
}
|
|
@@ -24793,7 +25243,7 @@ function maxMtimeRegularFilesUnderDir(dirAbs) {
|
|
|
24793
25243
|
walk(p);
|
|
24794
25244
|
} else if (e.isFile()) {
|
|
24795
25245
|
try {
|
|
24796
|
-
const st =
|
|
25246
|
+
const st = fs47.statSync(p);
|
|
24797
25247
|
const m = st.mtimeMs;
|
|
24798
25248
|
if (best === null || m > best) {
|
|
24799
25249
|
best = m;
|
|
@@ -24815,7 +25265,7 @@ function resolveUpdateContextBaseline(repoRootAbs, repoConfig) {
|
|
|
24815
25265
|
return { baselineIsoUtc: new Date(last).toISOString(), source: "lastRunAt" };
|
|
24816
25266
|
}
|
|
24817
25267
|
const ctxDir = path44.join(repoRootAbs, ".gluecharm", "context");
|
|
24818
|
-
if (!
|
|
25268
|
+
if (!fs47.existsSync(ctxDir)) {
|
|
24819
25269
|
return null;
|
|
24820
25270
|
}
|
|
24821
25271
|
const maxMs = maxMtimeRegularFilesUnderDir(ctxDir);
|
|
@@ -24837,12 +25287,12 @@ function persistUpdateContextLastRunAt(repoRootAbs, isoUtc) {
|
|
|
24837
25287
|
}
|
|
24838
25288
|
|
|
24839
25289
|
// src/factory/updateContext/updateContextGitWindow.ts
|
|
24840
|
-
var
|
|
24841
|
-
var
|
|
25290
|
+
var import_node_child_process3 = require("node:child_process");
|
|
25291
|
+
var fs48 = __toESM(require("node:fs"));
|
|
24842
25292
|
var path45 = __toESM(require("node:path"));
|
|
24843
25293
|
var GIT_ENV = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
24844
25294
|
function gitLines(repoRootAbs, args) {
|
|
24845
|
-
const r = (0,
|
|
25295
|
+
const r = (0, import_node_child_process3.execFileSync)("git", ["-c", "core.quotepath=false", ...args], {
|
|
24846
25296
|
cwd: repoRootAbs,
|
|
24847
25297
|
encoding: "utf-8",
|
|
24848
25298
|
env: GIT_ENV,
|
|
@@ -24864,7 +25314,7 @@ function parseGitLogIso(line) {
|
|
|
24864
25314
|
}
|
|
24865
25315
|
function discoverCommitWindowAndTouchedPaths(repoRootAbs, baselineIsoUtc) {
|
|
24866
25316
|
const root = path45.resolve(repoRootAbs);
|
|
24867
|
-
if (!
|
|
25317
|
+
if (!fs48.existsSync(path45.join(root, ".git"))) {
|
|
24868
25318
|
return { ok: false, error: "Not a git repository (missing .git)." };
|
|
24869
25319
|
}
|
|
24870
25320
|
const baselineMs = Date.parse(baselineIsoUtc);
|
|
@@ -24929,7 +25379,7 @@ function filterPathsExistingInWorktree(worktreeRootAbs, pathsPosix) {
|
|
|
24929
25379
|
const rel = p.replace(/\\/g, "/");
|
|
24930
25380
|
const abs = path45.join(root, ...rel.split("/"));
|
|
24931
25381
|
try {
|
|
24932
|
-
if (
|
|
25382
|
+
if (fs48.existsSync(abs) && fs48.statSync(abs).isFile()) {
|
|
24933
25383
|
out.push(rel);
|
|
24934
25384
|
}
|
|
24935
25385
|
} catch {
|
|
@@ -24939,7 +25389,7 @@ function filterPathsExistingInWorktree(worktreeRootAbs, pathsPosix) {
|
|
|
24939
25389
|
}
|
|
24940
25390
|
|
|
24941
25391
|
// src/factory/updateContext/updateContextReport.ts
|
|
24942
|
-
var
|
|
25392
|
+
var fs49 = __toESM(require("node:fs"));
|
|
24943
25393
|
var path46 = __toESM(require("node:path"));
|
|
24944
25394
|
var CHANGES_SINCE_DATE_BASENAME = "changes-since-date.md";
|
|
24945
25395
|
function renderChangesSinceDateMarkdown(p) {
|
|
@@ -24981,9 +25431,9 @@ function renderChangesSinceDateMarkdown(p) {
|
|
|
24981
25431
|
}
|
|
24982
25432
|
function writeChangesSinceDateReport(contextDirAbs, body) {
|
|
24983
25433
|
try {
|
|
24984
|
-
|
|
25434
|
+
fs49.mkdirSync(contextDirAbs, { recursive: true });
|
|
24985
25435
|
const target = path46.join(contextDirAbs, CHANGES_SINCE_DATE_BASENAME);
|
|
24986
|
-
|
|
25436
|
+
fs49.writeFileSync(target, body, "utf-8");
|
|
24987
25437
|
return { ok: true };
|
|
24988
25438
|
} catch (e) {
|
|
24989
25439
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
@@ -24991,13 +25441,13 @@ function writeChangesSinceDateReport(contextDirAbs, body) {
|
|
|
24991
25441
|
}
|
|
24992
25442
|
|
|
24993
25443
|
// src/factory/updateContext/updateContextSeedCheck.ts
|
|
24994
|
-
var
|
|
25444
|
+
var fs50 = __toESM(require("node:fs"));
|
|
24995
25445
|
var path47 = __toESM(require("node:path"));
|
|
24996
25446
|
var INDEX_BASENAME = "index-application-context.json";
|
|
24997
25447
|
var CHANGES_REPORT = "changes-since-date.md";
|
|
24998
25448
|
function tryParseJsonFile(abs) {
|
|
24999
25449
|
try {
|
|
25000
|
-
const raw =
|
|
25450
|
+
const raw = fs50.readFileSync(abs, "utf-8");
|
|
25001
25451
|
JSON.parse(raw);
|
|
25002
25452
|
return true;
|
|
25003
25453
|
} catch {
|
|
@@ -25005,16 +25455,16 @@ function tryParseJsonFile(abs) {
|
|
|
25005
25455
|
}
|
|
25006
25456
|
}
|
|
25007
25457
|
function isWorktreeContextSeeded(contextDirAbs) {
|
|
25008
|
-
if (!
|
|
25458
|
+
if (!fs50.existsSync(contextDirAbs)) {
|
|
25009
25459
|
return false;
|
|
25010
25460
|
}
|
|
25011
25461
|
const indexAbs = path47.join(contextDirAbs, INDEX_BASENAME);
|
|
25012
|
-
if (
|
|
25462
|
+
if (fs50.existsSync(indexAbs) && fs50.statSync(indexAbs).isFile() && tryParseJsonFile(indexAbs)) {
|
|
25013
25463
|
return true;
|
|
25014
25464
|
}
|
|
25015
25465
|
let names;
|
|
25016
25466
|
try {
|
|
25017
|
-
names =
|
|
25467
|
+
names = fs50.readdirSync(contextDirAbs);
|
|
25018
25468
|
} catch {
|
|
25019
25469
|
return false;
|
|
25020
25470
|
}
|
|
@@ -25028,7 +25478,7 @@ function isWorktreeContextSeeded(contextDirAbs) {
|
|
|
25028
25478
|
}
|
|
25029
25479
|
const p = path47.join(contextDirAbs, name);
|
|
25030
25480
|
try {
|
|
25031
|
-
if (
|
|
25481
|
+
if (fs50.statSync(p).isFile()) {
|
|
25032
25482
|
distinct.add(name);
|
|
25033
25483
|
}
|
|
25034
25484
|
} catch {
|
|
@@ -25330,11 +25780,11 @@ async function runUpdateContextFactory(deps) {
|
|
|
25330
25780
|
}
|
|
25331
25781
|
|
|
25332
25782
|
// src/factory/contextDrift/runContextDriftFactory.ts
|
|
25333
|
-
var
|
|
25783
|
+
var fs56 = __toESM(require("node:fs"));
|
|
25334
25784
|
var path53 = __toESM(require("node:path"));
|
|
25335
25785
|
|
|
25336
25786
|
// src/factory/contextDrift/contextDriftManifest.ts
|
|
25337
|
-
var
|
|
25787
|
+
var fs51 = __toESM(require("node:fs"));
|
|
25338
25788
|
var path49 = __toESM(require("node:path"));
|
|
25339
25789
|
var MAX_REFERENCE_BYTES = 256 * 1024;
|
|
25340
25790
|
var MAX_EVIDENCE_FILES = 300;
|
|
@@ -25343,7 +25793,7 @@ var MAX_EXCERPT = 4e3;
|
|
|
25343
25793
|
function readFileLimited(abs, maxBytes) {
|
|
25344
25794
|
let buf;
|
|
25345
25795
|
try {
|
|
25346
|
-
buf =
|
|
25796
|
+
buf = fs51.readFileSync(abs);
|
|
25347
25797
|
} catch {
|
|
25348
25798
|
return { text: "", truncated: false };
|
|
25349
25799
|
}
|
|
@@ -25356,14 +25806,14 @@ function collectEvidencePaths(repoRoot) {
|
|
|
25356
25806
|
const roots = ["src", "test", "tests", "packages", ".gluecharm", "scripts"];
|
|
25357
25807
|
for (const rel of roots) {
|
|
25358
25808
|
const abs = path49.join(repoRoot, rel);
|
|
25359
|
-
if (!
|
|
25809
|
+
if (!fs51.existsSync(abs)) {
|
|
25360
25810
|
continue;
|
|
25361
25811
|
}
|
|
25362
25812
|
walkFiles(abs, repoRoot, out, 0);
|
|
25363
25813
|
}
|
|
25364
25814
|
for (const leaf of ["package.json", "tsconfig.json"]) {
|
|
25365
25815
|
const abs = path49.join(repoRoot, leaf);
|
|
25366
|
-
if (
|
|
25816
|
+
if (fs51.existsSync(abs) && fs51.statSync(abs).isFile()) {
|
|
25367
25817
|
const r = path49.relative(repoRoot, abs).split(path49.sep).join("/");
|
|
25368
25818
|
out.push(r);
|
|
25369
25819
|
}
|
|
@@ -25381,7 +25831,7 @@ function walkFiles(dir, repoRoot, out, depth) {
|
|
|
25381
25831
|
}
|
|
25382
25832
|
let entries;
|
|
25383
25833
|
try {
|
|
25384
|
-
entries =
|
|
25834
|
+
entries = fs51.readdirSync(dir, { withFileTypes: true });
|
|
25385
25835
|
} catch {
|
|
25386
25836
|
return;
|
|
25387
25837
|
}
|
|
@@ -25418,7 +25868,7 @@ function buildComparisonManifest(args) {
|
|
|
25418
25868
|
const evidenceFiles = [];
|
|
25419
25869
|
for (const rel of evidencePathsTrimmed) {
|
|
25420
25870
|
const abs = path49.join(args.worktreeRoot, ...rel.split("/"));
|
|
25421
|
-
const st =
|
|
25871
|
+
const st = fs51.existsSync(abs) ? fs51.statSync(abs) : null;
|
|
25422
25872
|
const size = st && st.isFile() ? st.size : 0;
|
|
25423
25873
|
const { text, truncated } = readFileLimited(abs, MAX_EVIDENCE_READ);
|
|
25424
25874
|
const excerpt = truncated ? `${text.slice(0, MAX_EXCERPT)}
|
|
@@ -25440,7 +25890,7 @@ function buildComparisonManifest(args) {
|
|
|
25440
25890
|
}
|
|
25441
25891
|
|
|
25442
25892
|
// src/factory/contextDrift/contextDriftAgent.ts
|
|
25443
|
-
var
|
|
25893
|
+
var fs52 = __toESM(require("node:fs"));
|
|
25444
25894
|
var path50 = __toESM(require("node:path"));
|
|
25445
25895
|
|
|
25446
25896
|
// src/factory/contextDrift/contextDriftPayload.ts
|
|
@@ -25587,16 +26037,16 @@ function buildDriftPrompt(args) {
|
|
|
25587
26037
|
}
|
|
25588
26038
|
async function runDriftComparisonOpenCode(args) {
|
|
25589
26039
|
const runDir = path50.join(args.worktreeRoot, ".opencode", "_run");
|
|
25590
|
-
|
|
26040
|
+
fs52.mkdirSync(runDir, { recursive: true });
|
|
25591
26041
|
const manifestPath = path50.join(runDir, "context-drift-manifest.json");
|
|
25592
26042
|
const outputPath = path50.join(runDir, "context-drift-payload.json");
|
|
25593
|
-
|
|
26043
|
+
fs52.writeFileSync(manifestPath, `${JSON.stringify(args.manifestObject, null, 2)}
|
|
25594
26044
|
`, "utf8");
|
|
25595
|
-
if (
|
|
25596
|
-
|
|
26045
|
+
if (fs52.existsSync(outputPath)) {
|
|
26046
|
+
fs52.unlinkSync(outputPath);
|
|
25597
26047
|
}
|
|
25598
26048
|
const promptPath = path50.join(runDir, `context-drift-${Date.now()}.prompt.txt`);
|
|
25599
|
-
|
|
26049
|
+
fs52.writeFileSync(
|
|
25600
26050
|
promptPath,
|
|
25601
26051
|
buildDriftPrompt({
|
|
25602
26052
|
worktreeRoot: args.worktreeRoot,
|
|
@@ -25638,7 +26088,7 @@ async function runDriftComparisonOpenCode(args) {
|
|
|
25638
26088
|
}
|
|
25639
26089
|
let raw;
|
|
25640
26090
|
try {
|
|
25641
|
-
const txt =
|
|
26091
|
+
const txt = fs52.readFileSync(outputPath, "utf8");
|
|
25642
26092
|
raw = JSON.parse(txt);
|
|
25643
26093
|
} catch (e) {
|
|
25644
26094
|
return {
|
|
@@ -25655,7 +26105,7 @@ async function runDriftComparisonOpenCode(args) {
|
|
|
25655
26105
|
|
|
25656
26106
|
// src/factory/contextDrift/contextDriftPaths.ts
|
|
25657
26107
|
var crypto2 = __toESM(require("node:crypto"));
|
|
25658
|
-
var
|
|
26108
|
+
var fs53 = __toESM(require("node:fs"));
|
|
25659
26109
|
var path51 = __toESM(require("node:path"));
|
|
25660
26110
|
var DRIFT_CONTEXT_SUBDIR = path51.join(".gluecharm", "context", "drift");
|
|
25661
26111
|
function sanitizeSlug(raw) {
|
|
@@ -25694,7 +26144,7 @@ function maybeDedupeSlug(slug, referenceRelPosix) {
|
|
|
25694
26144
|
function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
25695
26145
|
let st;
|
|
25696
26146
|
try {
|
|
25697
|
-
st =
|
|
26147
|
+
st = fs53.statSync(referenceAbsInWorktree);
|
|
25698
26148
|
} catch {
|
|
25699
26149
|
return { ok: false, error: `Reference path not found in analysis worktree: ${referenceAbsInWorktree}` };
|
|
25700
26150
|
}
|
|
@@ -25715,7 +26165,7 @@ function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
|
25715
26165
|
}
|
|
25716
26166
|
let entries;
|
|
25717
26167
|
try {
|
|
25718
|
-
entries =
|
|
26168
|
+
entries = fs53.readdirSync(dir, { withFileTypes: true });
|
|
25719
26169
|
} catch {
|
|
25720
26170
|
return;
|
|
25721
26171
|
}
|
|
@@ -25740,7 +26190,7 @@ function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
|
25740
26190
|
}
|
|
25741
26191
|
function pickReferenceRootDocument(args) {
|
|
25742
26192
|
if (args.indexOverrideAbs) {
|
|
25743
|
-
if (!
|
|
26193
|
+
if (!fs53.existsSync(args.indexOverrideAbs) || !args.indexOverrideAbs.endsWith(".md")) {
|
|
25744
26194
|
return { ok: false, error: "--index must point to an existing .md file under the repo." };
|
|
25745
26195
|
}
|
|
25746
26196
|
return { ok: true, path: args.indexOverrideAbs };
|
|
@@ -25751,7 +26201,7 @@ function pickReferenceRootDocument(args) {
|
|
|
25751
26201
|
const dir = args.referenceAbsInWorktree;
|
|
25752
26202
|
for (const name of ["index.md", "README.md"]) {
|
|
25753
26203
|
const p = path51.join(dir, name);
|
|
25754
|
-
if (
|
|
26204
|
+
if (fs53.existsSync(p) && fs53.statSync(p).isFile()) {
|
|
25755
26205
|
return { ok: true, path: p };
|
|
25756
26206
|
}
|
|
25757
26207
|
}
|
|
@@ -25768,13 +26218,13 @@ function toPosixPath(p) {
|
|
|
25768
26218
|
}
|
|
25769
26219
|
|
|
25770
26220
|
// src/factory/contextDrift/contextDriftIndex.ts
|
|
25771
|
-
var
|
|
26221
|
+
var fs54 = __toESM(require("node:fs"));
|
|
25772
26222
|
var START = "<!-- easyspecs-drift-links:start -->";
|
|
25773
26223
|
var END = "<!-- easyspecs-drift-links:end -->";
|
|
25774
26224
|
function patchReferenceIndexWithDriftLink(args) {
|
|
25775
26225
|
let body;
|
|
25776
26226
|
try {
|
|
25777
|
-
body =
|
|
26227
|
+
body = fs54.readFileSync(args.referenceRootAbsolute, "utf8");
|
|
25778
26228
|
} catch (e) {
|
|
25779
26229
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
25780
26230
|
}
|
|
@@ -25795,7 +26245,7 @@ ${block}
|
|
|
25795
26245
|
`;
|
|
25796
26246
|
}
|
|
25797
26247
|
try {
|
|
25798
|
-
|
|
26248
|
+
fs54.writeFileSync(args.referenceRootAbsolute, next, "utf8");
|
|
25799
26249
|
} catch (e) {
|
|
25800
26250
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
25801
26251
|
}
|
|
@@ -25806,13 +26256,13 @@ function escapeRe(s) {
|
|
|
25806
26256
|
}
|
|
25807
26257
|
|
|
25808
26258
|
// src/factory/contextDrift/contextDriftPromote.ts
|
|
25809
|
-
var
|
|
26259
|
+
var fs55 = __toESM(require("node:fs"));
|
|
25810
26260
|
var path52 = __toESM(require("node:path"));
|
|
25811
26261
|
function copyWorktreeFileToWorkspace(args) {
|
|
25812
26262
|
const src = path52.join(args.worktreeRoot, ...args.relativePosix.split("/"));
|
|
25813
26263
|
const dest = path52.join(args.workspaceRoot, ...args.relativePosix.split("/"));
|
|
25814
|
-
|
|
25815
|
-
|
|
26264
|
+
fs55.mkdirSync(path52.dirname(dest), { recursive: true });
|
|
26265
|
+
fs55.copyFileSync(src, dest);
|
|
25816
26266
|
}
|
|
25817
26267
|
|
|
25818
26268
|
// src/factory/contextDrift/runContextDriftFactory.ts
|
|
@@ -25831,7 +26281,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25831
26281
|
};
|
|
25832
26282
|
}
|
|
25833
26283
|
const refAbsWorkspace = resolved.abs;
|
|
25834
|
-
if (!
|
|
26284
|
+
if (!fs56.existsSync(refAbsWorkspace)) {
|
|
25835
26285
|
return {
|
|
25836
26286
|
exitOk: false,
|
|
25837
26287
|
ok: false,
|
|
@@ -25844,7 +26294,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25844
26294
|
let indexOverrideAbsWorkspace;
|
|
25845
26295
|
if (deps.indexOverrideArg?.trim()) {
|
|
25846
26296
|
const ir = resolveInsideRepo(deps.repoRootAbs, deps.indexOverrideArg.trim());
|
|
25847
|
-
if (!ir.ok || !
|
|
26297
|
+
if (!ir.ok || !fs56.existsSync(ir.abs)) {
|
|
25848
26298
|
return {
|
|
25849
26299
|
exitOk: false,
|
|
25850
26300
|
ok: false,
|
|
@@ -25862,7 +26312,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25862
26312
|
ok: true,
|
|
25863
26313
|
code: "DRY_RUN",
|
|
25864
26314
|
...baseMeta,
|
|
25865
|
-
referenceRootDocument: toPosixPath(path53.relative(deps.repoRootAbs, refAbsWorkspace)) + (
|
|
26315
|
+
referenceRootDocument: toPosixPath(path53.relative(deps.repoRootAbs, refAbsWorkspace)) + (fs56.statSync(refAbsWorkspace).isDirectory() ? "/" : ""),
|
|
25866
26316
|
driftReportPath: null,
|
|
25867
26317
|
analysisWorktreeRoot: "",
|
|
25868
26318
|
promoted: false,
|
|
@@ -25931,7 +26381,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25931
26381
|
}
|
|
25932
26382
|
const indexWt = indexOverrideAbsWorkspace ? path53.join(wt, ...path53.relative(deps.repoRootAbs, indexOverrideAbsWorkspace).split(path53.sep)) : void 0;
|
|
25933
26383
|
const rootPick = pickReferenceRootDocument({
|
|
25934
|
-
referencePathIsFile:
|
|
26384
|
+
referencePathIsFile: fs56.statSync(refAbsWt).isFile(),
|
|
25935
26385
|
referenceAbsInWorktree: refAbsWt,
|
|
25936
26386
|
bundleFiles: bundle.bundleFiles,
|
|
25937
26387
|
indexOverrideAbs: indexWt
|
|
@@ -25958,7 +26408,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25958
26408
|
slug = maybeDedupeSlug(slug, refRel);
|
|
25959
26409
|
const driftBase = driftFilename(slug, runDate);
|
|
25960
26410
|
const driftDirWt = path53.join(wt, DRIFT_CONTEXT_SUBDIR);
|
|
25961
|
-
|
|
26411
|
+
fs56.mkdirSync(driftDirWt, { recursive: true });
|
|
25962
26412
|
const driftAbsWt = path53.join(driftDirWt, driftBase);
|
|
25963
26413
|
let payload;
|
|
25964
26414
|
if (deps.testOnlyFixturePayload) {
|
|
@@ -25995,7 +26445,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25995
26445
|
manifestTruncation: manifest.truncation
|
|
25996
26446
|
});
|
|
25997
26447
|
try {
|
|
25998
|
-
|
|
26448
|
+
fs56.writeFileSync(driftAbsWt, md, "utf8");
|
|
25999
26449
|
} catch (e) {
|
|
26000
26450
|
finalizeWt?.();
|
|
26001
26451
|
return {
|
|
@@ -26074,7 +26524,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26074
26524
|
}
|
|
26075
26525
|
|
|
26076
26526
|
// src/analysis/coordinationDuplicatesDiagnosis.ts
|
|
26077
|
-
var
|
|
26527
|
+
var fs57 = __toESM(require("fs"));
|
|
26078
26528
|
var path54 = __toESM(require("path"));
|
|
26079
26529
|
var import__7 = __toESM(require__());
|
|
26080
26530
|
var COORDINATION_DUPLICATES_REPORT_BASENAME = "coordination-duplicates-report.json";
|
|
@@ -26111,11 +26561,11 @@ function looksLikeCoordinationDetailMarkdownBasename(basename17) {
|
|
|
26111
26561
|
}
|
|
26112
26562
|
function loadRawFeatureRows(contextDirAbs) {
|
|
26113
26563
|
const p = path54.join(contextDirAbs, "features-list.json");
|
|
26114
|
-
if (!
|
|
26564
|
+
if (!fs57.existsSync(p)) {
|
|
26115
26565
|
return [];
|
|
26116
26566
|
}
|
|
26117
26567
|
try {
|
|
26118
|
-
const raw = stripUtf8Bom6(
|
|
26568
|
+
const raw = stripUtf8Bom6(fs57.readFileSync(p, "utf-8"));
|
|
26119
26569
|
const doc = JSON.parse(raw);
|
|
26120
26570
|
return Array.isArray(doc.features) ? doc.features : [];
|
|
26121
26571
|
} catch {
|
|
@@ -26150,7 +26600,7 @@ function findOrphanCoordinationMarkdown(contextDirAbs) {
|
|
|
26150
26600
|
const featureRows = loadRawFeatureRows(contextDirAbs);
|
|
26151
26601
|
let dirents;
|
|
26152
26602
|
try {
|
|
26153
|
-
dirents =
|
|
26603
|
+
dirents = fs57.readdirSync(contextDirAbs, { withFileTypes: true });
|
|
26154
26604
|
} catch {
|
|
26155
26605
|
return [];
|
|
26156
26606
|
}
|
|
@@ -26404,13 +26854,13 @@ function buildCoordinationDuplicatesReport(input) {
|
|
|
26404
26854
|
const duplicateGroups = [];
|
|
26405
26855
|
for (const entry of COORDINATION_LIST_SCAN_ENTRIES) {
|
|
26406
26856
|
const filePath = path54.join(input.contextDirAbsolute, entry.basename);
|
|
26407
|
-
if (!
|
|
26857
|
+
if (!fs57.existsSync(filePath)) {
|
|
26408
26858
|
lists.push({ basename: entry.basename, status: "missing" });
|
|
26409
26859
|
continue;
|
|
26410
26860
|
}
|
|
26411
26861
|
let raw;
|
|
26412
26862
|
try {
|
|
26413
|
-
raw = stripUtf8Bom6(
|
|
26863
|
+
raw = stripUtf8Bom6(fs57.readFileSync(filePath, "utf-8"));
|
|
26414
26864
|
} catch (e) {
|
|
26415
26865
|
lists.push({
|
|
26416
26866
|
basename: entry.basename,
|
|
@@ -26459,7 +26909,7 @@ function validateReportData(data) {
|
|
|
26459
26909
|
if (!validateReportCompiled) {
|
|
26460
26910
|
const ajv2 = new import__7.default({ allErrors: true, strict: false });
|
|
26461
26911
|
const schemaPath = path54.join(resolveContextListSchemasDir(), "coordination-duplicates-report.schema.json");
|
|
26462
|
-
const schemaRaw = stripUtf8Bom6(
|
|
26912
|
+
const schemaRaw = stripUtf8Bom6(fs57.readFileSync(schemaPath, "utf-8"));
|
|
26463
26913
|
validateReportCompiled = ajv2.compile(JSON.parse(schemaRaw));
|
|
26464
26914
|
}
|
|
26465
26915
|
if (validateReportCompiled(data)) {
|
|
@@ -26482,15 +26932,15 @@ function runCoordinationDuplicatesDiagnosis(input) {
|
|
|
26482
26932
|
`;
|
|
26483
26933
|
const tmp = `${outPath}.tmp.${process.pid}`;
|
|
26484
26934
|
try {
|
|
26485
|
-
|
|
26935
|
+
fs57.writeFileSync(tmp, payload, "utf-8");
|
|
26486
26936
|
} catch (e) {
|
|
26487
26937
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
26488
26938
|
}
|
|
26489
26939
|
try {
|
|
26490
|
-
|
|
26940
|
+
fs57.renameSync(tmp, outPath);
|
|
26491
26941
|
} catch (e) {
|
|
26492
26942
|
try {
|
|
26493
|
-
|
|
26943
|
+
fs57.unlinkSync(tmp);
|
|
26494
26944
|
} catch {
|
|
26495
26945
|
}
|
|
26496
26946
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
@@ -26524,7 +26974,7 @@ function runCoordinationDuplicatesDiagnosis(input) {
|
|
|
26524
26974
|
}
|
|
26525
26975
|
|
|
26526
26976
|
// src/pipelines/download/downloadPipeline.ts
|
|
26527
|
-
var
|
|
26977
|
+
var fs58 = __toESM(require("node:fs"));
|
|
26528
26978
|
var path55 = __toESM(require("node:path"));
|
|
26529
26979
|
var SRS_DISCOVERY_BATCH_GET_CHUNK_SIZE = 200;
|
|
26530
26980
|
function isRecord7(v) {
|
|
@@ -26630,19 +27080,19 @@ function chunkIds(ids, size) {
|
|
|
26630
27080
|
return out;
|
|
26631
27081
|
}
|
|
26632
27082
|
function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
26633
|
-
if (!
|
|
27083
|
+
if (!fs58.existsSync(contextDirAbs) || !fs58.statSync(contextDirAbs).isDirectory()) {
|
|
26634
27084
|
return { filesRemoved: 0 };
|
|
26635
27085
|
}
|
|
26636
27086
|
const preserveAbs = path55.resolve(contextDirAbs, UPLOAD_TARGET_FILENAME);
|
|
26637
27087
|
const preserveSet = /* @__PURE__ */ new Set();
|
|
26638
|
-
if (
|
|
27088
|
+
if (fs58.existsSync(preserveAbs) && fs58.statSync(preserveAbs).isFile()) {
|
|
26639
27089
|
preserveSet.add(preserveAbs);
|
|
26640
27090
|
}
|
|
26641
27091
|
let filesRemoved = 0;
|
|
26642
27092
|
const walkRm = (dir) => {
|
|
26643
27093
|
let entries;
|
|
26644
27094
|
try {
|
|
26645
|
-
entries =
|
|
27095
|
+
entries = fs58.readdirSync(dir, { withFileTypes: true });
|
|
26646
27096
|
} catch {
|
|
26647
27097
|
return;
|
|
26648
27098
|
}
|
|
@@ -26651,7 +27101,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
|
26651
27101
|
if (e.isDirectory()) {
|
|
26652
27102
|
walkRm(full);
|
|
26653
27103
|
try {
|
|
26654
|
-
|
|
27104
|
+
fs58.rmdirSync(full);
|
|
26655
27105
|
} catch {
|
|
26656
27106
|
}
|
|
26657
27107
|
} else if (e.isFile()) {
|
|
@@ -26660,7 +27110,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
|
26660
27110
|
continue;
|
|
26661
27111
|
}
|
|
26662
27112
|
try {
|
|
26663
|
-
|
|
27113
|
+
fs58.unlinkSync(abs);
|
|
26664
27114
|
filesRemoved += 1;
|
|
26665
27115
|
} catch {
|
|
26666
27116
|
}
|
|
@@ -26739,15 +27189,15 @@ async function runDownloadPipeline(opts) {
|
|
|
26739
27189
|
failed.push({ id, name, message: "Unsafe or invalid name for local path." });
|
|
26740
27190
|
continue;
|
|
26741
27191
|
}
|
|
26742
|
-
|
|
26743
|
-
const exists =
|
|
27192
|
+
fs58.mkdirSync(path55.dirname(outAbs), { recursive: true });
|
|
27193
|
+
const exists = fs58.existsSync(outAbs);
|
|
26744
27194
|
if (exists && !opts.force && !opts.replaceFromCloud) {
|
|
26745
27195
|
skipped += 1;
|
|
26746
27196
|
log?.(`[pipeline:download] skip existing ${name} (use --force to overwrite).`);
|
|
26747
27197
|
continue;
|
|
26748
27198
|
}
|
|
26749
27199
|
try {
|
|
26750
|
-
|
|
27200
|
+
fs58.writeFileSync(outAbs, bodyText, "utf8");
|
|
26751
27201
|
downloaded += 1;
|
|
26752
27202
|
succeededIds[outAbs] = id;
|
|
26753
27203
|
} catch (e) {
|
|
@@ -26918,11 +27368,11 @@ function createAuthenticatedRequestJson(deps) {
|
|
|
26918
27368
|
}
|
|
26919
27369
|
|
|
26920
27370
|
// src/cli/cliSession.ts
|
|
26921
|
-
var
|
|
26922
|
-
var
|
|
27371
|
+
var fs59 = __toESM(require("node:fs"));
|
|
27372
|
+
var os6 = __toESM(require("node:os"));
|
|
26923
27373
|
var path56 = __toESM(require("node:path"));
|
|
26924
27374
|
function defaultSessionPath() {
|
|
26925
|
-
return path56.join(
|
|
27375
|
+
return path56.join(os6.homedir(), ".easyspecs", "cli-session.json");
|
|
26926
27376
|
}
|
|
26927
27377
|
var configSessionPath;
|
|
26928
27378
|
function setCliSessionPathFromConfig(absPath) {
|
|
@@ -26963,10 +27413,10 @@ function effectiveCliSessionPath() {
|
|
|
26963
27413
|
function readCliSession() {
|
|
26964
27414
|
const p = effectiveCliSessionPath();
|
|
26965
27415
|
try {
|
|
26966
|
-
if (!
|
|
27416
|
+
if (!fs59.existsSync(p)) {
|
|
26967
27417
|
return void 0;
|
|
26968
27418
|
}
|
|
26969
|
-
const j = JSON.parse(
|
|
27419
|
+
const j = JSON.parse(fs59.readFileSync(p, "utf8"));
|
|
26970
27420
|
const apiBaseUrl = typeof j.apiBaseUrl === "string" ? j.apiBaseUrl.trim() : "";
|
|
26971
27421
|
const accessToken = typeof j.accessToken === "string" ? j.accessToken : "";
|
|
26972
27422
|
const refreshToken = typeof j.refreshToken === "string" ? j.refreshToken : "";
|
|
@@ -26980,20 +27430,20 @@ function readCliSession() {
|
|
|
26980
27430
|
}
|
|
26981
27431
|
function writeCliSession(s) {
|
|
26982
27432
|
const p = effectiveCliSessionPath();
|
|
26983
|
-
|
|
26984
|
-
|
|
27433
|
+
fs59.mkdirSync(path56.dirname(p), { recursive: true });
|
|
27434
|
+
fs59.writeFileSync(p, `${JSON.stringify(s, null, 2)}
|
|
26985
27435
|
`, "utf8");
|
|
26986
27436
|
}
|
|
26987
27437
|
function clearCliSession() {
|
|
26988
27438
|
const p = effectiveCliSessionPath();
|
|
26989
27439
|
try {
|
|
26990
|
-
|
|
27440
|
+
fs59.unlinkSync(p);
|
|
26991
27441
|
} catch {
|
|
26992
27442
|
}
|
|
26993
27443
|
}
|
|
26994
27444
|
|
|
26995
27445
|
// src/analysis/acePendingTraces.ts
|
|
26996
|
-
var
|
|
27446
|
+
var fs60 = __toESM(require("fs"));
|
|
26997
27447
|
var path57 = __toESM(require("path"));
|
|
26998
27448
|
function normalizeAceTraceRelativePath(rel) {
|
|
26999
27449
|
return rel.split(/[/\\]/).join("/");
|
|
@@ -27001,12 +27451,12 @@ function normalizeAceTraceRelativePath(rel) {
|
|
|
27001
27451
|
function readCompletedTraceRelativePaths(contextDir2) {
|
|
27002
27452
|
const set = /* @__PURE__ */ new Set();
|
|
27003
27453
|
const jsonlPath = aceConsolidatedSessionsJsonlPath(contextDir2);
|
|
27004
|
-
if (!
|
|
27454
|
+
if (!fs60.existsSync(jsonlPath)) {
|
|
27005
27455
|
return set;
|
|
27006
27456
|
}
|
|
27007
27457
|
let raw;
|
|
27008
27458
|
try {
|
|
27009
|
-
raw =
|
|
27459
|
+
raw = fs60.readFileSync(jsonlPath, "utf8");
|
|
27010
27460
|
} catch {
|
|
27011
27461
|
return set;
|
|
27012
27462
|
}
|
|
@@ -27037,7 +27487,7 @@ function readCompletedTraceRelativePaths(contextDir2) {
|
|
|
27037
27487
|
}
|
|
27038
27488
|
function listPendingAceTraceFiles(contextDir2, worktreeRoot) {
|
|
27039
27489
|
const traceSchema = opencodeAceSchemaPath(worktreeRoot, ACE_SCHEMA_TRACE);
|
|
27040
|
-
if (!
|
|
27490
|
+
if (!fs60.existsSync(traceSchema)) {
|
|
27041
27491
|
return [];
|
|
27042
27492
|
}
|
|
27043
27493
|
const completed = readCompletedTraceRelativePaths(contextDir2);
|
|
@@ -27067,11 +27517,32 @@ function clampConcurrency2(n) {
|
|
|
27067
27517
|
return Math.min(64, Math.max(1, Math.floor(n)));
|
|
27068
27518
|
}
|
|
27069
27519
|
async function runAceAutoLearnPool(p) {
|
|
27070
|
-
const
|
|
27520
|
+
const staticMaxC = clampConcurrency2(p.maxConcurrentOpenCodeAgents);
|
|
27521
|
+
const throttle = p.enableCpuAdaptiveThrottle !== false;
|
|
27522
|
+
let adaptiveMax = staticMaxC;
|
|
27523
|
+
const sample = p.cpuPressureSampler ?? (throttle ? createDefaultCpuPressureSampler() : () => 0);
|
|
27071
27524
|
const contextDir2 = gluecharmContextDir(p.baseOpts.worktreeRoot);
|
|
27072
27525
|
const runner = p.runOfflineLearn ?? runAceOfflineLearnFromTrace;
|
|
27073
27526
|
const fifo = [...p.traceAbsolutePaths];
|
|
27074
27527
|
let active = 0;
|
|
27528
|
+
const applyCpuPressure = () => {
|
|
27529
|
+
if (!throttle || active < 1) {
|
|
27530
|
+
return;
|
|
27531
|
+
}
|
|
27532
|
+
const ratio = sample();
|
|
27533
|
+
const { adaptiveMax: next, changed } = nextAdaptiveMaxAfterCpuSample({
|
|
27534
|
+
ratio,
|
|
27535
|
+
activeRunningCount: active,
|
|
27536
|
+
priorAdaptiveMax: adaptiveMax
|
|
27537
|
+
});
|
|
27538
|
+
if (changed) {
|
|
27539
|
+
adaptiveMax = next;
|
|
27540
|
+
p.log?.(
|
|
27541
|
+
`[ace] cpu pressure ratio=${ratio.toFixed(3)} active=${String(active)} adaptiveMaxConcurrentAi=${String(adaptiveMax)}`
|
|
27542
|
+
);
|
|
27543
|
+
}
|
|
27544
|
+
};
|
|
27545
|
+
const currentCap = () => Math.min(staticMaxC, adaptiveMax);
|
|
27075
27546
|
let wake;
|
|
27076
27547
|
const waitTurn = () => new Promise((resolve20) => {
|
|
27077
27548
|
wake = resolve20;
|
|
@@ -27103,8 +27574,9 @@ async function runAceAutoLearnPool(p) {
|
|
|
27103
27574
|
pump();
|
|
27104
27575
|
return;
|
|
27105
27576
|
}
|
|
27577
|
+
applyCpuPressure();
|
|
27106
27578
|
const rel = traceRel(traceAbs);
|
|
27107
|
-
p.log?.(`[ace] ace auto-learn: start ${rel} (active ${active}/${
|
|
27579
|
+
p.log?.(`[ace] ace auto-learn: start ${rel} (active ${active}/${currentCap()})`);
|
|
27108
27580
|
await p.onItemStart?.(rel);
|
|
27109
27581
|
const r = await runner(traceAbs, { ...p.baseOpts, abortSignal });
|
|
27110
27582
|
if (r.ok) {
|
|
@@ -27118,9 +27590,14 @@ async function runAceAutoLearnPool(p) {
|
|
|
27118
27590
|
p.log?.(`[ace] ace auto-learn: finished ${rel} ok=${r.ok}`);
|
|
27119
27591
|
pump();
|
|
27120
27592
|
};
|
|
27593
|
+
let pressureInterval;
|
|
27594
|
+
if (throttle) {
|
|
27595
|
+
const intervalMs = p.__testOnlyCpuPressureIntervalMs ?? 3e4;
|
|
27596
|
+
pressureInterval = setInterval(() => applyCpuPressure(), intervalMs);
|
|
27597
|
+
}
|
|
27121
27598
|
try {
|
|
27122
27599
|
while (true) {
|
|
27123
|
-
while (fifo.length > 0 && active <
|
|
27600
|
+
while (fifo.length > 0 && active < currentCap() && !abortSignal?.aborted) {
|
|
27124
27601
|
const traceAbs = fifo.shift();
|
|
27125
27602
|
active += 1;
|
|
27126
27603
|
void runOne(traceAbs);
|
|
@@ -27136,11 +27613,14 @@ async function runAceAutoLearnPool(p) {
|
|
|
27136
27613
|
await waitTurn();
|
|
27137
27614
|
continue;
|
|
27138
27615
|
}
|
|
27139
|
-
if (fifo.length === 0 || active >=
|
|
27616
|
+
if (fifo.length === 0 || active >= currentCap()) {
|
|
27140
27617
|
await waitTurn();
|
|
27141
27618
|
}
|
|
27142
27619
|
}
|
|
27143
27620
|
} finally {
|
|
27621
|
+
if (pressureInterval) {
|
|
27622
|
+
clearInterval(pressureInterval);
|
|
27623
|
+
}
|
|
27144
27624
|
if (poolAbortListenerRegistered && abortSignal) {
|
|
27145
27625
|
abortSignal.removeEventListener("abort", onPipelineAbort);
|
|
27146
27626
|
}
|
|
@@ -27611,7 +28091,7 @@ function formatCliStderrLine(line, useAnsi) {
|
|
|
27611
28091
|
}
|
|
27612
28092
|
|
|
27613
28093
|
// src/cli/main.ts
|
|
27614
|
-
var PKG_VERSION = "0.0.
|
|
28094
|
+
var PKG_VERSION = "0.0.26";
|
|
27615
28095
|
function isNonEmptyFactoryFailureArray(x) {
|
|
27616
28096
|
if (!Array.isArray(x) || x.length === 0) {
|
|
27617
28097
|
return false;
|
|
@@ -27743,7 +28223,7 @@ function resolveAnalysisRoot(repoRoot, rootKind, worktreePath) {
|
|
|
27743
28223
|
return repoRoot;
|
|
27744
28224
|
}
|
|
27745
28225
|
const wt = worktreePath?.trim();
|
|
27746
|
-
if (wt &&
|
|
28226
|
+
if (wt && fs61.existsSync(path59.join(wt, ".git"))) {
|
|
27747
28227
|
return path59.resolve(wt);
|
|
27748
28228
|
}
|
|
27749
28229
|
throw new Error("worktree mode requires --worktree <path> to an existing analysis checkout.");
|
|
@@ -27752,14 +28232,14 @@ function resolveAdHocCheckoutRoot(_repoRoot, storage, worktreeFlag) {
|
|
|
27752
28232
|
const w = worktreeFlag?.trim();
|
|
27753
28233
|
if (w) {
|
|
27754
28234
|
const abs = path59.resolve(w);
|
|
27755
|
-
if (
|
|
28235
|
+
if (fs61.existsSync(path59.join(abs, ".git"))) {
|
|
27756
28236
|
return abs;
|
|
27757
28237
|
}
|
|
27758
28238
|
throw new Error(`Invalid --worktree (not a git checkout): ${abs}`);
|
|
27759
28239
|
}
|
|
27760
28240
|
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
27761
28241
|
const p = snap?.adHocWorktreePath?.trim();
|
|
27762
|
-
if (p &&
|
|
28242
|
+
if (p && fs61.existsSync(path59.join(p, ".git"))) {
|
|
27763
28243
|
return p;
|
|
27764
28244
|
}
|
|
27765
28245
|
throw new Error("No analysis checkout: run `easyspecs-cli run synthesis` first or pass `--worktree <path>`.");
|
|
@@ -27824,7 +28304,7 @@ async function main() {
|
|
|
27824
28304
|
try {
|
|
27825
28305
|
parsed = parseCliWithCommander(process.argv.slice(2));
|
|
27826
28306
|
} catch (e) {
|
|
27827
|
-
console.error(
|
|
28307
|
+
console.error(formatCliThrownUnknown(e));
|
|
27828
28308
|
logExitCodeSummary(ExitCode.usage);
|
|
27829
28309
|
process.exit(ExitCode.usage);
|
|
27830
28310
|
}
|
|
@@ -27841,6 +28321,58 @@ async function main() {
|
|
|
27841
28321
|
const repoRoot = resolveRepoRoot(flags);
|
|
27842
28322
|
setAceCliHeadlessMode(true);
|
|
27843
28323
|
setAceCliWorkspaceRoot(repoRoot);
|
|
28324
|
+
if (positionals[0] === "workstation" && positionals[1] === "info") {
|
|
28325
|
+
const tail = positionals.slice(2);
|
|
28326
|
+
const wantJson = flags.json || tail.includes("--json");
|
|
28327
|
+
const unknown = tail.filter((t) => t !== "--json");
|
|
28328
|
+
if (unknown.length > 0) {
|
|
28329
|
+
logErr(flags, "Usage: easyspecs-cli [--json] workstation info");
|
|
28330
|
+
logExitCodeSummary(ExitCode.usage, flags);
|
|
28331
|
+
process.exit(ExitCode.usage);
|
|
28332
|
+
}
|
|
28333
|
+
const plat = process.platform;
|
|
28334
|
+
if (plat !== "darwin" && plat !== "linux") {
|
|
28335
|
+
if (!wantJson) {
|
|
28336
|
+
logErr(
|
|
28337
|
+
flags,
|
|
28338
|
+
`[EasySpecs] workstation info is only supported on macOS and Linux (unsupported platform: ${plat}).`
|
|
28339
|
+
);
|
|
28340
|
+
}
|
|
28341
|
+
logExitCodeSummary(ExitCode.misconfiguration, flags);
|
|
28342
|
+
process.exit(ExitCode.misconfiguration);
|
|
28343
|
+
}
|
|
28344
|
+
const profile = collectHostMachineProfile();
|
|
28345
|
+
const nSys = machineConcurrentAiCapFromHost(profile);
|
|
28346
|
+
const hostHardMaxConcurrentAi = hostHardMaxFromHost(profile);
|
|
28347
|
+
const physicalCpus = profile.cpusForCapSource === "physical" ? profile.cpusForCap : null;
|
|
28348
|
+
const totalMemBytes = Math.max(0, Math.floor(profile.totalMemBytes));
|
|
28349
|
+
if (wantJson) {
|
|
28350
|
+
printJsonLine({
|
|
28351
|
+
command: "workstation info",
|
|
28352
|
+
durationMs: Date.now() - t0,
|
|
28353
|
+
ok: true,
|
|
28354
|
+
platform: profile.platform,
|
|
28355
|
+
totalMemBytes,
|
|
28356
|
+
cpusForCap: profile.cpusForCap,
|
|
28357
|
+
cpusForCapSource: profile.cpusForCapSource,
|
|
28358
|
+
physicalCpus,
|
|
28359
|
+
maxSystemConcurrentAiWorkstations: nSys,
|
|
28360
|
+
hostHardMaxConcurrentAi
|
|
28361
|
+
});
|
|
28362
|
+
} else {
|
|
28363
|
+
const gib = totalMemBytes / 2 ** 30;
|
|
28364
|
+
console.log(
|
|
28365
|
+
[
|
|
28366
|
+
`platform=${profile.platform}`,
|
|
28367
|
+
`cpusForCap=${String(profile.cpusForCap)} (${profile.cpusForCapSource})`,
|
|
28368
|
+
`totalMem=${gib.toFixed(2)} GiB (${String(totalMemBytes)} bytes)`,
|
|
28369
|
+
`N_sys (maxSystemConcurrentAiWorkstations)=${String(nSys)}`,
|
|
28370
|
+
`hostHardMaxConcurrentAi (min(N_sys,64))=${String(hostHardMaxConcurrentAi)}`
|
|
28371
|
+
].join("\n")
|
|
28372
|
+
);
|
|
28373
|
+
}
|
|
28374
|
+
process.exit(ExitCode.ok);
|
|
28375
|
+
}
|
|
27844
28376
|
if (positionals[0] === "config" && positionals[1] === "init") {
|
|
27845
28377
|
const tail = positionals.slice(2);
|
|
27846
28378
|
const overwrite = tail.includes("--overwrite");
|
|
@@ -28024,19 +28556,20 @@ async function main() {
|
|
|
28024
28556
|
try {
|
|
28025
28557
|
modes = parseDoctorFlags(pos.slice(1));
|
|
28026
28558
|
} catch (e) {
|
|
28027
|
-
logErr(flags,
|
|
28559
|
+
logErr(flags, formatCliThrownUnknown(e));
|
|
28028
28560
|
logErr(flags, "Usage: easyspecs-cli doctor [--readiness] [--inspect-config]");
|
|
28029
28561
|
logExitCodeSummary(ExitCode.usage, flags);
|
|
28030
28562
|
process.exit(ExitCode.usage);
|
|
28031
28563
|
}
|
|
28032
28564
|
const agentsDir = resolveOpenCodeAgentsDir(repoRoot, repoConfig);
|
|
28033
|
-
const agentsOk =
|
|
28565
|
+
const agentsOk = fs61.existsSync(agentsDir);
|
|
28034
28566
|
const oc = getOpenCodeReadiness({
|
|
28035
28567
|
executable: merged.openCodeExecutable,
|
|
28036
28568
|
skipCredentialsCheck: merged.openCodeSkipCredentialsCheck,
|
|
28037
28569
|
providerEnvFromConfig: merged.openCodeChildEnv
|
|
28038
28570
|
});
|
|
28039
28571
|
const lines = [
|
|
28572
|
+
`cliVersion=${PKG_VERSION}`,
|
|
28040
28573
|
`repoRoot=${repoRoot}`,
|
|
28041
28574
|
`apiBaseUrl=${apiResolved || "(empty \u2014 stub auth only)"}`,
|
|
28042
28575
|
`opencode installed=${String(oc.installed)} credentialsReady=${String(oc.credentialsReady)}`,
|
|
@@ -28056,6 +28589,7 @@ async function main() {
|
|
|
28056
28589
|
const envelope = { ok: true };
|
|
28057
28590
|
if (modes.readiness) {
|
|
28058
28591
|
envelope.lines = lines;
|
|
28592
|
+
envelope.cliVersion = PKG_VERSION;
|
|
28059
28593
|
}
|
|
28060
28594
|
if (modes.inspectConfig) {
|
|
28061
28595
|
envelope.config = inspectPayload;
|
|
@@ -28090,7 +28624,7 @@ async function main() {
|
|
|
28090
28624
|
tailForCreds = extracted.rest;
|
|
28091
28625
|
sessionPathRaw = extracted.sessionPath;
|
|
28092
28626
|
} catch (e) {
|
|
28093
|
-
logErr(flags,
|
|
28627
|
+
logErr(flags, formatCliThrownUnknown(e));
|
|
28094
28628
|
logExitCodeSummary(ExitCode.usage, flags);
|
|
28095
28629
|
process.exit(ExitCode.usage);
|
|
28096
28630
|
}
|
|
@@ -28544,7 +29078,7 @@ async function main() {
|
|
|
28544
29078
|
const wt = snap?.adHocWorktreePath?.trim();
|
|
28545
29079
|
if (wt) {
|
|
28546
29080
|
const sourceCtx = path59.join(wt, ".gluecharm", "context");
|
|
28547
|
-
if (
|
|
29081
|
+
if (fs61.existsSync(sourceCtx)) {
|
|
28548
29082
|
const n = promoteContextDirectoryToWorkspaceFs(sourceCtx, repoRoot);
|
|
28549
29083
|
logErr(flags, `[pipeline:analysis] promoted ${String(n.filesCopied)} file(s) \u2192 ${repoRoot}`);
|
|
28550
29084
|
} else {
|
|
@@ -28696,8 +29230,8 @@ async function main() {
|
|
|
28696
29230
|
...flags.verbose && failCount > 0 ? { failures: result.failed } : {}
|
|
28697
29231
|
});
|
|
28698
29232
|
} catch (e) {
|
|
28699
|
-
const msg =
|
|
28700
|
-
finish(ExitCode.internal, { ok: false, error: msg });
|
|
29233
|
+
const msg = formatCliThrownUnknown(e);
|
|
29234
|
+
finish(exitCodeForThrownHttpApiError(e) ?? ExitCode.internal, { ok: false, error: msg });
|
|
28701
29235
|
}
|
|
28702
29236
|
}
|
|
28703
29237
|
if (pos[0] === "upload" && (pos[1] === "context" || pos[1] === "republish")) {
|
|
@@ -28714,12 +29248,12 @@ async function main() {
|
|
|
28714
29248
|
if (pos[1] === "republish") {
|
|
28715
29249
|
const fromCfg = repoConfig.easyspecs?.upload?.contextDirectory?.trim();
|
|
28716
29250
|
const resolvedOverride = fromCfg && fromCfg.length > 0 ? path59.isAbsolute(fromCfg) ? path59.normalize(fromCfg) : path59.resolve(repoRoot, fromCfg) : "";
|
|
28717
|
-
if (resolvedOverride &&
|
|
29251
|
+
if (resolvedOverride && fs61.existsSync(path59.join(resolvedOverride, ".."))) {
|
|
28718
29252
|
ctxDir = resolvedOverride;
|
|
28719
29253
|
} else {
|
|
28720
29254
|
const storage = createFileBackedWorkspaceState(repoRoot);
|
|
28721
29255
|
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
28722
|
-
const wt = snap?.adHocWorktreePath &&
|
|
29256
|
+
const wt = snap?.adHocWorktreePath && fs61.existsSync(path59.join(snap.adHocWorktreePath, ".gluecharm", "context")) ? path59.join(snap.adHocWorktreePath, ".gluecharm", "context") : "";
|
|
28723
29257
|
if (!wt) {
|
|
28724
29258
|
finish(ExitCode.misconfiguration, {
|
|
28725
29259
|
ok: false,
|
|
@@ -28837,16 +29371,16 @@ async function main() {
|
|
|
28837
29371
|
}
|
|
28838
29372
|
if (pos[0] === "ace" && pos[1] === "clear") {
|
|
28839
29373
|
const learnings = path59.join(repoRoot, ".gluecharm", "context", "learnings");
|
|
28840
|
-
if (!
|
|
29374
|
+
if (!fs61.existsSync(learnings)) {
|
|
28841
29375
|
finish(ExitCode.ok, { ok: true, message: "nothing to clear" });
|
|
28842
29376
|
}
|
|
28843
|
-
|
|
29377
|
+
fs61.rmSync(learnings, { recursive: true, force: true });
|
|
28844
29378
|
finish(ExitCode.ok, { ok: true, message: `cleared ${learnings}` });
|
|
28845
29379
|
}
|
|
28846
29380
|
if (pos[0] === "ace" && pos[1] === "learn") {
|
|
28847
29381
|
requireOpenCode(merged, flags);
|
|
28848
29382
|
const { worktree } = parseWorktreeFlag(pos.slice(2));
|
|
28849
|
-
const root = worktree &&
|
|
29383
|
+
const root = worktree && fs61.existsSync(path59.join(worktree, ".opencode", "schemas", "ace")) ? worktree : repoRoot;
|
|
28850
29384
|
const contextDir2 = path59.join(root, ".gluecharm", "context");
|
|
28851
29385
|
const traces = listAceTraceFiles(contextDir2);
|
|
28852
29386
|
if (traces.length === 0) {
|
|
@@ -28871,7 +29405,7 @@ async function main() {
|
|
|
28871
29405
|
if (pos[0] === "ace" && pos[1] === "auto-learn") {
|
|
28872
29406
|
requireOpenCode(merged, flags);
|
|
28873
29407
|
const { worktree } = parseWorktreeFlag(pos.slice(2));
|
|
28874
|
-
const root = worktree &&
|
|
29408
|
+
const root = worktree && fs61.existsSync(path59.join(worktree, ".git")) ? worktree : repoRoot;
|
|
28875
29409
|
const contextDir2 = path59.join(root, ".gluecharm", "context");
|
|
28876
29410
|
const pending = listPendingAceTraceFiles(contextDir2, root);
|
|
28877
29411
|
if (pending.length === 0) {
|
|
@@ -28914,9 +29448,10 @@ async function main() {
|
|
|
28914
29448
|
}
|
|
28915
29449
|
process.exit(ExitCode.misconfiguration);
|
|
28916
29450
|
}
|
|
28917
|
-
const msg =
|
|
29451
|
+
const msg = formatCliThrownUnknown(e);
|
|
29452
|
+
const exitFromApi = exitCodeForThrownHttpApiError(e);
|
|
28918
29453
|
logErr(flags, msg);
|
|
28919
|
-
finish(ExitCode.internal, { ok: false, error: msg });
|
|
29454
|
+
finish(exitFromApi ?? ExitCode.internal, { ok: false, error: msg });
|
|
28920
29455
|
}
|
|
28921
29456
|
}
|
|
28922
29457
|
void main();
|