@gluecharm-lab/easyspecs-cli 0.0.23 → 0.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/commands.md +20 -1
- package/dist/main.cjs +1006 -453
- 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,11 +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
|
|
14094
|
+
var import_child_process2 = require("child_process");
|
|
13854
14095
|
|
|
13855
14096
|
// src/analysis/openCodeSessionStewardship.ts
|
|
13856
14097
|
var TITLE_MAX_LEN = 80;
|
|
@@ -13974,6 +14215,139 @@ function logOpenCodeSessionFollowUpStart(diagnosticLog, p) {
|
|
|
13974
14215
|
);
|
|
13975
14216
|
}
|
|
13976
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
|
+
|
|
13977
14351
|
// src/opencodeCli.ts
|
|
13978
14352
|
var USE_SHELL = process.platform === "win32";
|
|
13979
14353
|
function resolveExecutable(executable) {
|
|
@@ -13982,7 +14356,7 @@ function resolveExecutable(executable) {
|
|
|
13982
14356
|
}
|
|
13983
14357
|
function spawnCliSync(executable, args, cwd, timeoutMs, env) {
|
|
13984
14358
|
const mergedEnv = env ? { ...process.env, ...env } : process.env;
|
|
13985
|
-
return (0,
|
|
14359
|
+
return (0, import_child_process2.spawnSync)(executable, args, {
|
|
13986
14360
|
encoding: "utf-8",
|
|
13987
14361
|
cwd,
|
|
13988
14362
|
shell: USE_SHELL,
|
|
@@ -14099,12 +14473,36 @@ function runOpenCodeAgent(cwd, args, options) {
|
|
|
14099
14473
|
return;
|
|
14100
14474
|
}
|
|
14101
14475
|
const spawnEnv = options?.childEnv && Object.keys(options.childEnv).length > 0 ? { ...process.env, ...options.childEnv } : process.env;
|
|
14102
|
-
const child = (0,
|
|
14476
|
+
const child = (0, import_child_process2.spawn)(cmd, args, {
|
|
14103
14477
|
cwd,
|
|
14104
14478
|
shell: USE_SHELL,
|
|
14105
14479
|
env: spawnEnv,
|
|
14106
14480
|
stdio: ["ignore", "pipe", "pipe"]
|
|
14107
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
|
+
}
|
|
14108
14506
|
options?.onAgentLaunched?.();
|
|
14109
14507
|
let stdout = "";
|
|
14110
14508
|
let stderr = "";
|
|
@@ -14162,6 +14560,7 @@ ${truncateForDiag(outBody, DIAG_STDOUT_MAX)}`);
|
|
|
14162
14560
|
return;
|
|
14163
14561
|
}
|
|
14164
14562
|
settled = true;
|
|
14563
|
+
tryEmitChildResourceDiag();
|
|
14165
14564
|
if (diag) {
|
|
14166
14565
|
finishDiag(diag.label, diag.code, diag.dumpStreams);
|
|
14167
14566
|
}
|
|
@@ -14240,7 +14639,7 @@ ${truncateForDiag(outBody, DIAG_STDOUT_MAX)}`);
|
|
|
14240
14639
|
}
|
|
14241
14640
|
|
|
14242
14641
|
// src/analysis/aceTraceNormalize.ts
|
|
14243
|
-
var
|
|
14642
|
+
var fs19 = __toESM(require("fs"));
|
|
14244
14643
|
var ACE_VERSION = "1.0.0-draft";
|
|
14245
14644
|
var REASONING_PHASES = /* @__PURE__ */ new Set([
|
|
14246
14645
|
"explore",
|
|
@@ -14385,7 +14784,7 @@ function sanitizePlaybookHooks(input) {
|
|
|
14385
14784
|
function rewriteAceTraceFileWithCanonicalEnvelope(traceAbsolutePath, canonical, diagnosticLog) {
|
|
14386
14785
|
let raw;
|
|
14387
14786
|
try {
|
|
14388
|
-
raw =
|
|
14787
|
+
raw = fs19.readFileSync(traceAbsolutePath, "utf-8");
|
|
14389
14788
|
} catch (e) {
|
|
14390
14789
|
diagnosticLog?.(`[ace] trace normalize read failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
14391
14790
|
return false;
|
|
@@ -14430,7 +14829,7 @@ function rewriteAceTraceFileWithCanonicalEnvelope(traceAbsolutePath, canonical,
|
|
|
14430
14829
|
doc.playbookHooks = hooks;
|
|
14431
14830
|
}
|
|
14432
14831
|
try {
|
|
14433
|
-
|
|
14832
|
+
fs19.writeFileSync(traceAbsolutePath, `${JSON.stringify(doc, null, 2)}
|
|
14434
14833
|
`, "utf-8");
|
|
14435
14834
|
} catch (e) {
|
|
14436
14835
|
diagnosticLog?.(`[ace] trace normalize write failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -14441,15 +14840,15 @@ function rewriteAceTraceFileWithCanonicalEnvelope(traceAbsolutePath, canonical,
|
|
|
14441
14840
|
}
|
|
14442
14841
|
|
|
14443
14842
|
// src/analysis/aceOfflineLearn.ts
|
|
14444
|
-
var
|
|
14843
|
+
var fs22 = __toESM(require("fs"));
|
|
14445
14844
|
var path20 = __toESM(require("path"));
|
|
14446
14845
|
|
|
14447
14846
|
// src/analysis/aceCuratorApplier.ts
|
|
14448
|
-
var
|
|
14847
|
+
var fs20 = __toESM(require("fs"));
|
|
14449
14848
|
var path18 = __toESM(require("path"));
|
|
14450
14849
|
function writeJson(pathAbs, obj) {
|
|
14451
|
-
|
|
14452
|
-
|
|
14850
|
+
fs20.mkdirSync(path18.dirname(pathAbs), { recursive: true });
|
|
14851
|
+
fs20.writeFileSync(pathAbs, `${JSON.stringify(obj, null, 2)}
|
|
14453
14852
|
`, "utf-8");
|
|
14454
14853
|
}
|
|
14455
14854
|
function emptyPlaybook(agentStem) {
|
|
@@ -14475,7 +14874,7 @@ function applyAceCuratorDeltaFile(worktreeRoot, deltaAbsolutePath, log) {
|
|
|
14475
14874
|
const pbPath = acePlaybookPath(contextDir2, agentStem);
|
|
14476
14875
|
const ovPath = aceOverlayPath(contextDir2, agentStem);
|
|
14477
14876
|
let playbook;
|
|
14478
|
-
if (
|
|
14877
|
+
if (fs20.existsSync(pbPath)) {
|
|
14479
14878
|
const pv = validateAceJsonFile(pbPath, playbookSchema);
|
|
14480
14879
|
if (!pv.ok) {
|
|
14481
14880
|
return { ok: false, message: `Existing playbook invalid: ${pv.message}` };
|
|
@@ -14485,7 +14884,7 @@ function applyAceCuratorDeltaFile(worktreeRoot, deltaAbsolutePath, log) {
|
|
|
14485
14884
|
playbook = emptyPlaybook(agentStem);
|
|
14486
14885
|
}
|
|
14487
14886
|
let overlay;
|
|
14488
|
-
if (
|
|
14887
|
+
if (fs20.existsSync(ovPath)) {
|
|
14489
14888
|
const ov = validateAceJsonFile(ovPath, overlaySchema);
|
|
14490
14889
|
if (!ov.ok) {
|
|
14491
14890
|
return { ok: false, message: `Existing overlay invalid: ${ov.message}` };
|
|
@@ -14563,7 +14962,7 @@ function applyAceCuratorDeltaFile(worktreeRoot, deltaAbsolutePath, log) {
|
|
|
14563
14962
|
}
|
|
14564
14963
|
|
|
14565
14964
|
// src/analysis/aceOfflineLearnFallbacks.ts
|
|
14566
|
-
var
|
|
14965
|
+
var fs21 = __toESM(require("fs"));
|
|
14567
14966
|
var path19 = __toESM(require("path"));
|
|
14568
14967
|
var ACE_VERSION2 = "1.0.0-draft";
|
|
14569
14968
|
function buildEmptyReflectorLessons(traceRelativePath, sessionRunId) {
|
|
@@ -14588,8 +14987,8 @@ function buildEmptyCuratorDelta(agentStem, lessonsRelativePath) {
|
|
|
14588
14987
|
function appendAceConsolidatedSessionRecord(contextDir2, record, diagnosticLog) {
|
|
14589
14988
|
const abs = aceConsolidatedSessionsJsonlPath(contextDir2);
|
|
14590
14989
|
const rel = path19.relative(contextDir2, abs).split(path19.sep).join("/");
|
|
14591
|
-
|
|
14592
|
-
|
|
14990
|
+
fs21.mkdirSync(aceLearningsRoot(contextDir2), { recursive: true });
|
|
14991
|
+
fs21.appendFileSync(abs, `${JSON.stringify(record)}
|
|
14593
14992
|
`, "utf-8");
|
|
14594
14993
|
diagnosticLog?.(`[ace] consolidated session record appended \u2014 ${rel}`);
|
|
14595
14994
|
}
|
|
@@ -14611,7 +15010,7 @@ function safeRunIdSegment(runId) {
|
|
|
14611
15010
|
}
|
|
14612
15011
|
function readHead(p, max) {
|
|
14613
15012
|
try {
|
|
14614
|
-
const raw =
|
|
15013
|
+
const raw = fs22.readFileSync(p, "utf-8");
|
|
14615
15014
|
return raw.length <= max ? raw : `${raw.slice(0, max)}
|
|
14616
15015
|
\u2026 (truncated)`;
|
|
14617
15016
|
} catch {
|
|
@@ -14620,12 +15019,12 @@ function readHead(p, max) {
|
|
|
14620
15019
|
}
|
|
14621
15020
|
function listAceTraceFiles(contextDir2) {
|
|
14622
15021
|
const root = path20.join(aceLearningsRoot(contextDir2), "traces");
|
|
14623
|
-
if (!
|
|
15022
|
+
if (!fs22.existsSync(root)) {
|
|
14624
15023
|
return [];
|
|
14625
15024
|
}
|
|
14626
15025
|
const out = [];
|
|
14627
15026
|
const walk = (dir) => {
|
|
14628
|
-
for (const e of
|
|
15027
|
+
for (const e of fs22.readdirSync(dir, { withFileTypes: true })) {
|
|
14629
15028
|
const full = path20.join(dir, e.name);
|
|
14630
15029
|
if (e.isDirectory()) {
|
|
14631
15030
|
walk(full);
|
|
@@ -14653,14 +15052,14 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14653
15052
|
const traceRel = path20.relative(contextDir2, traceAbsolutePath).split(path20.sep).join("/");
|
|
14654
15053
|
const lessonsAbs = aceReflectionPath(contextDir2, agentStem, safeId);
|
|
14655
15054
|
const deltaAbs = aceCurationPath(contextDir2, agentStem, safeId);
|
|
14656
|
-
|
|
14657
|
-
|
|
15055
|
+
fs22.mkdirSync(path20.dirname(lessonsAbs), { recursive: true });
|
|
15056
|
+
fs22.mkdirSync(path20.dirname(deltaAbs), { recursive: true });
|
|
14658
15057
|
const pbPath = path20.join(aceLearningsRoot(contextDir2), `${agentStem}.json`);
|
|
14659
15058
|
const ovPath = path20.join(aceLearningsRoot(contextDir2), "overlays", `${agentStem}.json`);
|
|
14660
|
-
const pbExcerpt =
|
|
14661
|
-
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)";
|
|
14662
15061
|
const runDir = path20.join(opts.worktreeRoot, ".opencode", "_run");
|
|
14663
|
-
|
|
15062
|
+
fs22.mkdirSync(runDir, { recursive: true });
|
|
14664
15063
|
let reflectorUsedEmptyFallback = false;
|
|
14665
15064
|
let curatorUsedEmptyFallback = false;
|
|
14666
15065
|
const reflectPrompt = [
|
|
@@ -14679,7 +15078,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14679
15078
|
"Schema: `aceSchemaVersion` **1.0.0-draft**, `sourceTrace`, `lessons` (see ace-reflector-lessons schema)."
|
|
14680
15079
|
].join("\n");
|
|
14681
15080
|
const reflectPromptPath = path20.join(runDir, `ace-reflect-${safeId}-${Date.now()}.prompt.txt`);
|
|
14682
|
-
|
|
15081
|
+
fs22.writeFileSync(reflectPromptPath, reflectPrompt, "utf-8");
|
|
14683
15082
|
const reflectVars = {
|
|
14684
15083
|
promptFile: reflectPromptPath,
|
|
14685
15084
|
agentId: ACE_REFLECTOR_AGENT_STEM,
|
|
@@ -14711,11 +15110,11 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14711
15110
|
if (!rCli.ok) {
|
|
14712
15111
|
return { ok: false, message: `[ace] reflector OpenCode failed: ${rCli.message}` };
|
|
14713
15112
|
}
|
|
14714
|
-
if (!
|
|
15113
|
+
if (!fs22.existsSync(lessonsAbs)) {
|
|
14715
15114
|
const recovered = extractJsonObjectWithTopLevelKeys(rCli.message, ["aceSchemaVersion", "sourceTrace", "lessons"]);
|
|
14716
15115
|
if (recovered) {
|
|
14717
15116
|
try {
|
|
14718
|
-
|
|
15117
|
+
fs22.writeFileSync(lessonsAbs, `${recovered}
|
|
14719
15118
|
`, "utf-8");
|
|
14720
15119
|
opts.diagnosticLog?.(`[ace] reflector recovered from OpenCode stdout/stderr \u2192 ${lessonsAbs}`);
|
|
14721
15120
|
} catch (e) {
|
|
@@ -14725,7 +15124,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14725
15124
|
}
|
|
14726
15125
|
}
|
|
14727
15126
|
}
|
|
14728
|
-
if (!
|
|
15127
|
+
if (!fs22.existsSync(lessonsAbs)) {
|
|
14729
15128
|
return { ok: false, message: `[ace] reflector output missing: ${lessonsAbs}` };
|
|
14730
15129
|
}
|
|
14731
15130
|
let lv = validateAceJsonFile(lessonsAbs, reflectorSchema);
|
|
@@ -14737,7 +15136,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14737
15136
|
]);
|
|
14738
15137
|
if (recoveredAgain) {
|
|
14739
15138
|
try {
|
|
14740
|
-
|
|
15139
|
+
fs22.writeFileSync(lessonsAbs, `${recoveredAgain}
|
|
14741
15140
|
`, "utf-8");
|
|
14742
15141
|
opts.diagnosticLog?.(`[ace] reflector re-recovered from CLI output after schema failure \u2192 ${lessonsAbs}`);
|
|
14743
15142
|
lv = validateAceJsonFile(lessonsAbs, reflectorSchema);
|
|
@@ -14751,7 +15150,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14751
15150
|
if (!lv.ok) {
|
|
14752
15151
|
const hint = lv.message.length > 220 ? `${lv.message.slice(0, 220)}\u2026` : lv.message;
|
|
14753
15152
|
opts.diagnosticLog?.(`[ace] reflector lessons failed schema \u2014 writing valid empty lessons \u2014 ${hint}`);
|
|
14754
|
-
|
|
15153
|
+
fs22.writeFileSync(
|
|
14755
15154
|
lessonsAbs,
|
|
14756
15155
|
`${JSON.stringify(buildEmptyReflectorLessons(traceRel, runId), null, 2)}
|
|
14757
15156
|
`,
|
|
@@ -14798,7 +15197,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14798
15197
|
"Schema: `aceSchemaVersion` **1.0.0-draft**, `agentStem`, `sourceLessons`, `operations` (see ace-curator-delta schema)."
|
|
14799
15198
|
].join("\n");
|
|
14800
15199
|
const curPromptPath = path20.join(runDir, `ace-curate-${safeId}-${Date.now()}.prompt.txt`);
|
|
14801
|
-
|
|
15200
|
+
fs22.writeFileSync(curPromptPath, curPrompt, "utf-8");
|
|
14802
15201
|
const curVars = {
|
|
14803
15202
|
promptFile: curPromptPath,
|
|
14804
15203
|
agentId: ACE_CURATOR_AGENT_STEM,
|
|
@@ -14829,7 +15228,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14829
15228
|
if (!cCli.ok) {
|
|
14830
15229
|
return { ok: false, message: `[ace] curator OpenCode failed: ${cCli.message}` };
|
|
14831
15230
|
}
|
|
14832
|
-
if (!
|
|
15231
|
+
if (!fs22.existsSync(deltaAbs)) {
|
|
14833
15232
|
const recovered = extractJsonObjectWithTopLevelKeys(cCli.message, [
|
|
14834
15233
|
"aceSchemaVersion",
|
|
14835
15234
|
"agentStem",
|
|
@@ -14838,7 +15237,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14838
15237
|
]);
|
|
14839
15238
|
if (recovered) {
|
|
14840
15239
|
try {
|
|
14841
|
-
|
|
15240
|
+
fs22.writeFileSync(deltaAbs, `${recovered}
|
|
14842
15241
|
`, "utf-8");
|
|
14843
15242
|
opts.diagnosticLog?.(`[ace] curator recovered from OpenCode stdout/stderr \u2192 ${deltaAbs}`);
|
|
14844
15243
|
} catch (e) {
|
|
@@ -14848,7 +15247,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14848
15247
|
}
|
|
14849
15248
|
}
|
|
14850
15249
|
}
|
|
14851
|
-
if (!
|
|
15250
|
+
if (!fs22.existsSync(deltaAbs)) {
|
|
14852
15251
|
return { ok: false, message: `[ace] curator output missing: ${deltaAbs}` };
|
|
14853
15252
|
}
|
|
14854
15253
|
let dv = validateAceJsonFile(deltaAbs, curatorSchema);
|
|
@@ -14861,7 +15260,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14861
15260
|
]);
|
|
14862
15261
|
if (recoveredCur) {
|
|
14863
15262
|
try {
|
|
14864
|
-
|
|
15263
|
+
fs22.writeFileSync(deltaAbs, `${recoveredCur}
|
|
14865
15264
|
`, "utf-8");
|
|
14866
15265
|
opts.diagnosticLog?.(`[ace] curator re-recovered from CLI output after schema failure \u2192 ${deltaAbs}`);
|
|
14867
15266
|
dv = validateAceJsonFile(deltaAbs, curatorSchema);
|
|
@@ -14875,7 +15274,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14875
15274
|
if (!dv.ok) {
|
|
14876
15275
|
const hint = dv.message.length > 220 ? `${dv.message.slice(0, 220)}\u2026` : dv.message;
|
|
14877
15276
|
opts.diagnosticLog?.(`[ace] curator delta failed schema \u2014 writing valid empty operations \u2014 ${hint}`);
|
|
14878
|
-
|
|
15277
|
+
fs22.writeFileSync(
|
|
14879
15278
|
deltaAbs,
|
|
14880
15279
|
`${JSON.stringify(buildEmptyCuratorDelta(agentStem, lessonsRel), null, 2)}
|
|
14881
15280
|
`,
|
|
@@ -14894,9 +15293,9 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
|
|
|
14894
15293
|
let lessonCount = 0;
|
|
14895
15294
|
let curatorOperationCount = 0;
|
|
14896
15295
|
try {
|
|
14897
|
-
const lessonsDoc = JSON.parse(
|
|
15296
|
+
const lessonsDoc = JSON.parse(fs22.readFileSync(lessonsAbs, "utf-8"));
|
|
14898
15297
|
lessonCount = Array.isArray(lessonsDoc.lessons) ? lessonsDoc.lessons.length : 0;
|
|
14899
|
-
const deltaDoc = JSON.parse(
|
|
15298
|
+
const deltaDoc = JSON.parse(fs22.readFileSync(deltaAbs, "utf-8"));
|
|
14900
15299
|
curatorOperationCount = Array.isArray(deltaDoc.operations) ? deltaDoc.operations.length : 0;
|
|
14901
15300
|
} catch {
|
|
14902
15301
|
}
|
|
@@ -14955,9 +15354,9 @@ async function runAceTracePhase(params) {
|
|
|
14955
15354
|
const contextDir2 = gluecharmContextDir(params.worktreeRoot);
|
|
14956
15355
|
const traceStem = aceTraceFileRunStem(params.artefactRunId, params.followUpSessionId);
|
|
14957
15356
|
const traceAbs = aceTracePath(contextDir2, params.producerAgentStem, traceStem);
|
|
14958
|
-
|
|
15357
|
+
fs23.mkdirSync(path21.dirname(traceAbs), { recursive: true });
|
|
14959
15358
|
const schemaAbs = opencodeAceSchemaPath(params.worktreeRoot, ACE_SCHEMA_TRACE);
|
|
14960
|
-
if (!
|
|
15359
|
+
if (!fs23.existsSync(schemaAbs)) {
|
|
14961
15360
|
const msg = `[ace] trace skipped \u2014 schema missing: ${schemaAbs}`;
|
|
14962
15361
|
params.diagnosticLog?.(msg);
|
|
14963
15362
|
return { ok: false, message: msg };
|
|
@@ -15006,9 +15405,9 @@ async function runAceTracePhase(params) {
|
|
|
15006
15405
|
`Use only evidence from this session's transcript and tool history.`
|
|
15007
15406
|
].join("\n");
|
|
15008
15407
|
const runDir = path21.join(params.worktreeRoot, ".opencode", "_run");
|
|
15009
|
-
|
|
15408
|
+
fs23.mkdirSync(runDir, { recursive: true });
|
|
15010
15409
|
const promptPath = path21.join(runDir, `ace-trace-${traceStem}-${Date.now()}.prompt.txt`);
|
|
15011
|
-
|
|
15410
|
+
fs23.writeFileSync(promptPath, promptBody, "utf-8");
|
|
15012
15411
|
const vars = {
|
|
15013
15412
|
promptFile: promptPath,
|
|
15014
15413
|
agentId: ACE_TRACE_RECORDER_AGENT_STEM,
|
|
@@ -15032,7 +15431,7 @@ async function runAceTracePhase(params) {
|
|
|
15032
15431
|
if (!cli.ok) {
|
|
15033
15432
|
return { ok: false, message: `[ace] trace OpenCode failed: ${cli.message}` };
|
|
15034
15433
|
}
|
|
15035
|
-
if (!
|
|
15434
|
+
if (!fs23.existsSync(traceAbs)) {
|
|
15036
15435
|
const recovered = extractJsonObjectWithTopLevelKeys(cli.message, [
|
|
15037
15436
|
"aceSchemaVersion",
|
|
15038
15437
|
"sessionMeta",
|
|
@@ -15040,7 +15439,7 @@ async function runAceTracePhase(params) {
|
|
|
15040
15439
|
]);
|
|
15041
15440
|
if (recovered) {
|
|
15042
15441
|
try {
|
|
15043
|
-
|
|
15442
|
+
fs23.writeFileSync(traceAbs, `${recovered}
|
|
15044
15443
|
`, "utf-8");
|
|
15045
15444
|
params.diagnosticLog?.(`[ace] trace recovered from OpenCode stdout/stderr \u2192 ${traceAbs}`);
|
|
15046
15445
|
} catch (e) {
|
|
@@ -15050,7 +15449,7 @@ async function runAceTracePhase(params) {
|
|
|
15050
15449
|
}
|
|
15051
15450
|
}
|
|
15052
15451
|
}
|
|
15053
|
-
if (!
|
|
15452
|
+
if (!fs23.existsSync(traceAbs)) {
|
|
15054
15453
|
const msg = `[ace] trace file missing after run: ${traceAbs}`;
|
|
15055
15454
|
params.diagnosticLog?.(msg);
|
|
15056
15455
|
return { ok: false, message: msg };
|
|
@@ -15082,7 +15481,7 @@ async function runAceTracePhase(params) {
|
|
|
15082
15481
|
return { ok: false, message: msg };
|
|
15083
15482
|
}
|
|
15084
15483
|
try {
|
|
15085
|
-
const rawAlign =
|
|
15484
|
+
const rawAlign = fs23.readFileSync(traceAbs, "utf-8");
|
|
15086
15485
|
const docAlign = JSON.parse(rawAlign);
|
|
15087
15486
|
const smRun = docAlign.sessionMeta?.runId;
|
|
15088
15487
|
if (typeof smRun !== "string" || smRun !== traceStem) {
|
|
@@ -15138,7 +15537,7 @@ async function runAceTracePhase(params) {
|
|
|
15138
15537
|
}
|
|
15139
15538
|
|
|
15140
15539
|
// src/analysis/coordinationListJsonValidate.ts
|
|
15141
|
-
var
|
|
15540
|
+
var fs24 = __toESM(require("fs"));
|
|
15142
15541
|
var import__4 = __toESM(require__());
|
|
15143
15542
|
function stripUtf8Bom3(s) {
|
|
15144
15543
|
return s.length > 0 && s.charCodeAt(0) === 65279 ? s.slice(1) : s;
|
|
@@ -15202,7 +15601,7 @@ function formatAjvErrors4(errors) {
|
|
|
15202
15601
|
function validateCoordinationListJson(jsonAbsolutePath, schemaAbsolutePath) {
|
|
15203
15602
|
let raw;
|
|
15204
15603
|
try {
|
|
15205
|
-
raw = stripUtf8Bom3(
|
|
15604
|
+
raw = stripUtf8Bom3(fs24.readFileSync(jsonAbsolutePath, "utf-8"));
|
|
15206
15605
|
} catch (e) {
|
|
15207
15606
|
return {
|
|
15208
15607
|
ok: false,
|
|
@@ -15218,7 +15617,7 @@ function validateCoordinationListJson(jsonAbsolutePath, schemaAbsolutePath) {
|
|
|
15218
15617
|
}
|
|
15219
15618
|
let schemaRaw;
|
|
15220
15619
|
try {
|
|
15221
|
-
schemaRaw = stripUtf8Bom3(
|
|
15620
|
+
schemaRaw = stripUtf8Bom3(fs24.readFileSync(schemaAbsolutePath, "utf-8"));
|
|
15222
15621
|
} catch (e) {
|
|
15223
15622
|
return {
|
|
15224
15623
|
ok: false,
|
|
@@ -15279,7 +15678,7 @@ function validateCoordinationListJson(jsonAbsolutePath, schemaAbsolutePath) {
|
|
|
15279
15678
|
var FILE_PREVIEW_MAX = 4e3;
|
|
15280
15679
|
function readCoordinationJsonPreview(jsonAbsolutePath) {
|
|
15281
15680
|
try {
|
|
15282
|
-
const raw = stripUtf8Bom3(
|
|
15681
|
+
const raw = stripUtf8Bom3(fs24.readFileSync(jsonAbsolutePath, "utf-8"));
|
|
15283
15682
|
return raw.length <= FILE_PREVIEW_MAX ? raw : `${raw.slice(0, FILE_PREVIEW_MAX)}
|
|
15284
15683
|
|
|
15285
15684
|
\u2026 (truncated)`;
|
|
@@ -15355,12 +15754,12 @@ function formatCoordinationJsonRepairAppendix(outputBasename, failure, rawFilePr
|
|
|
15355
15754
|
}
|
|
15356
15755
|
|
|
15357
15756
|
// src/analysis/coordinationListStableWrite.ts
|
|
15358
|
-
var
|
|
15757
|
+
var fs26 = __toESM(require("fs"));
|
|
15359
15758
|
var path23 = __toESM(require("path"));
|
|
15360
15759
|
|
|
15361
15760
|
// src/analysis/coordinationListFileLock.ts
|
|
15362
|
-
var
|
|
15363
|
-
var
|
|
15761
|
+
var fs25 = __toESM(require("fs"));
|
|
15762
|
+
var os3 = __toESM(require("os"));
|
|
15364
15763
|
var path22 = __toESM(require("path"));
|
|
15365
15764
|
var DEFAULT_COORDINATION_LIST_LOCK_TIMEOUT_MS = 12e4;
|
|
15366
15765
|
var DEFAULT_COORDINATION_LIST_LOCK_STALE_MS = 30 * 60 * 1e3;
|
|
@@ -15380,7 +15779,7 @@ function lockPathForList(listJsonAbsolutePath) {
|
|
|
15380
15779
|
}
|
|
15381
15780
|
function tryReadLockBody(lockAbs) {
|
|
15382
15781
|
try {
|
|
15383
|
-
const raw =
|
|
15782
|
+
const raw = fs25.readFileSync(lockAbs, "utf-8");
|
|
15384
15783
|
const j = JSON.parse(raw);
|
|
15385
15784
|
if (typeof j.pid === "number" && typeof j.createdAt === "string") {
|
|
15386
15785
|
return j;
|
|
@@ -15392,7 +15791,7 @@ function tryReadLockBody(lockAbs) {
|
|
|
15392
15791
|
function tryRemoveStaleLock(lockAbs, staleMs, diagnosticLog) {
|
|
15393
15792
|
let st;
|
|
15394
15793
|
try {
|
|
15395
|
-
st =
|
|
15794
|
+
st = fs25.statSync(lockAbs);
|
|
15396
15795
|
} catch {
|
|
15397
15796
|
return false;
|
|
15398
15797
|
}
|
|
@@ -15407,7 +15806,7 @@ function tryRemoveStaleLock(lockAbs, staleMs, diagnosticLog) {
|
|
|
15407
15806
|
return false;
|
|
15408
15807
|
}
|
|
15409
15808
|
try {
|
|
15410
|
-
|
|
15809
|
+
fs25.unlinkSync(lockAbs);
|
|
15411
15810
|
diagnosticLog?.(`[coord-lock] removed stale lock ${lockAbs} (age ${Math.round(age)} ms)`);
|
|
15412
15811
|
return true;
|
|
15413
15812
|
} catch {
|
|
@@ -15424,11 +15823,11 @@ async function withCoordinationListFileLock(listJsonAbsolutePath, options, fn) {
|
|
|
15424
15823
|
while (!acquired && Date.now() < deadline) {
|
|
15425
15824
|
const body = {
|
|
15426
15825
|
pid: process.pid,
|
|
15427
|
-
host:
|
|
15826
|
+
host: os3.hostname(),
|
|
15428
15827
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
15429
15828
|
};
|
|
15430
15829
|
try {
|
|
15431
|
-
|
|
15830
|
+
fs25.writeFileSync(lockAbs, `${JSON.stringify(body, null, 0)}
|
|
15432
15831
|
`, { encoding: "utf-8", flag: "wx" });
|
|
15433
15832
|
acquired = true;
|
|
15434
15833
|
diagnosticLog?.(`[coord-lock] acquired ${path22.basename(lockAbs)}`);
|
|
@@ -15452,7 +15851,7 @@ async function withCoordinationListFileLock(listJsonAbsolutePath, options, fn) {
|
|
|
15452
15851
|
return await fn();
|
|
15453
15852
|
} finally {
|
|
15454
15853
|
try {
|
|
15455
|
-
|
|
15854
|
+
fs25.unlinkSync(lockAbs);
|
|
15456
15855
|
diagnosticLog?.(`[coord-lock] released ${path22.basename(lockAbs)}`);
|
|
15457
15856
|
} catch {
|
|
15458
15857
|
}
|
|
@@ -15826,13 +16225,13 @@ function buildCascadePathsForDroppedCodes(listBasename, droppedCodes, contextDir
|
|
|
15826
16225
|
const paths = [];
|
|
15827
16226
|
const tryPush = (p) => {
|
|
15828
16227
|
const abs = path23.join(contextDirAbs, p);
|
|
15829
|
-
if (
|
|
16228
|
+
if (fs26.existsSync(abs)) {
|
|
15830
16229
|
paths.push(abs);
|
|
15831
16230
|
}
|
|
15832
16231
|
};
|
|
15833
16232
|
const listDir = () => {
|
|
15834
16233
|
try {
|
|
15835
|
-
return
|
|
16234
|
+
return fs26.readdirSync(contextDirAbs);
|
|
15836
16235
|
} catch {
|
|
15837
16236
|
return [];
|
|
15838
16237
|
}
|
|
@@ -16033,7 +16432,7 @@ async function finalizeCoordinationListWrite(p) {
|
|
|
16033
16432
|
async () => {
|
|
16034
16433
|
let agentRaw;
|
|
16035
16434
|
try {
|
|
16036
|
-
agentRaw =
|
|
16435
|
+
agentRaw = fs26.readFileSync(p.listJsonAbsolutePath, "utf-8");
|
|
16037
16436
|
} catch (e) {
|
|
16038
16437
|
return { ok: false, message: `SRS-50 re-read failed: ${e instanceof Error ? e.message : String(e)}` };
|
|
16039
16438
|
}
|
|
@@ -16061,7 +16460,7 @@ async function finalizeCoordinationListWrite(p) {
|
|
|
16061
16460
|
p.diagnosticLog?.(formatStableWriteDiagnosticLine(p.listBasename, m.diff));
|
|
16062
16461
|
const tmp = `${p.listJsonAbsolutePath}.tmp.${process.pid}`;
|
|
16063
16462
|
try {
|
|
16064
|
-
|
|
16463
|
+
fs26.writeFileSync(tmp, `${JSON.stringify(m.merged, null, 2)}
|
|
16065
16464
|
`, "utf-8");
|
|
16066
16465
|
} catch (e) {
|
|
16067
16466
|
return { ok: false, message: `SRS-50 temp write failed: ${e instanceof Error ? e.message : String(e)}` };
|
|
@@ -16069,14 +16468,14 @@ async function finalizeCoordinationListWrite(p) {
|
|
|
16069
16468
|
const v = validateCoordinationListJson(tmp, p.schemaAbsolutePath);
|
|
16070
16469
|
if (!v.ok) {
|
|
16071
16470
|
try {
|
|
16072
|
-
|
|
16471
|
+
fs26.unlinkSync(tmp);
|
|
16073
16472
|
} catch {
|
|
16074
16473
|
}
|
|
16075
16474
|
const detail = v.failure.kind === "schema" ? v.failure.errorsText : v.failure.kind === "parse" ? v.failure.message : v.failure.message;
|
|
16076
16475
|
return { ok: false, message: `SRS-50 merged output failed schema: ${detail}` };
|
|
16077
16476
|
}
|
|
16078
16477
|
try {
|
|
16079
|
-
|
|
16478
|
+
fs26.renameSync(tmp, p.listJsonAbsolutePath);
|
|
16080
16479
|
} catch (e) {
|
|
16081
16480
|
return { ok: false, message: `SRS-50 rename failed: ${e instanceof Error ? e.message : String(e)}` };
|
|
16082
16481
|
}
|
|
@@ -16146,7 +16545,7 @@ function allocateNextListRowCode(input) {
|
|
|
16146
16545
|
}
|
|
16147
16546
|
let names = [];
|
|
16148
16547
|
try {
|
|
16149
|
-
names =
|
|
16548
|
+
names = fs26.readdirSync(contextDirAbs);
|
|
16150
16549
|
} catch {
|
|
16151
16550
|
names = [];
|
|
16152
16551
|
}
|
|
@@ -16189,7 +16588,7 @@ function allocateNextListRowCode(input) {
|
|
|
16189
16588
|
}
|
|
16190
16589
|
|
|
16191
16590
|
// src/analysis/markdownEvidenceIndexValidate.ts
|
|
16192
|
-
var
|
|
16591
|
+
var fs27 = __toESM(require("fs"));
|
|
16193
16592
|
var EVIDENCE_HEADING = "## Evidence index";
|
|
16194
16593
|
function evidenceIndexMentionsReadmeMd(body) {
|
|
16195
16594
|
const re = /README\.md/gi;
|
|
@@ -16317,7 +16716,7 @@ function markdownEvidenceValidationPasses(content) {
|
|
|
16317
16716
|
function validateMarkdownEvidenceIndexFile(absolutePath) {
|
|
16318
16717
|
let text;
|
|
16319
16718
|
try {
|
|
16320
|
-
const buf =
|
|
16719
|
+
const buf = fs27.readFileSync(absolutePath);
|
|
16321
16720
|
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
16322
16721
|
text = decoder.decode(buf);
|
|
16323
16722
|
} catch (e) {
|
|
@@ -16358,7 +16757,7 @@ function formatMarkdownEvidenceRepairAppendix(outputFileAbsolute, kind = "empty"
|
|
|
16358
16757
|
}
|
|
16359
16758
|
|
|
16360
16759
|
// src/analysis/openQuestionResolution.ts
|
|
16361
|
-
var
|
|
16760
|
+
var fs28 = __toESM(require("fs"));
|
|
16362
16761
|
var path24 = __toESM(require("path"));
|
|
16363
16762
|
var OPEN_QUESTION_RESOLUTION_JSON_BASENAME = "open-question-resolution.json";
|
|
16364
16763
|
function openQuestionResolutionJsonAbsolute(worktreeRoot) {
|
|
@@ -16397,10 +16796,10 @@ function parseOpenQuestionResolutionJsonText(raw) {
|
|
|
16397
16796
|
function readOpenQuestionResolutionFile(worktreeRoot) {
|
|
16398
16797
|
const p = openQuestionResolutionJsonAbsolute(worktreeRoot);
|
|
16399
16798
|
try {
|
|
16400
|
-
if (!
|
|
16799
|
+
if (!fs28.existsSync(p)) {
|
|
16401
16800
|
return { ok: false, error: `Missing resolution file: ${p}` };
|
|
16402
16801
|
}
|
|
16403
|
-
const raw =
|
|
16802
|
+
const raw = fs28.readFileSync(p, "utf-8");
|
|
16404
16803
|
return parseOpenQuestionResolutionJsonText(raw);
|
|
16405
16804
|
} catch (e) {
|
|
16406
16805
|
const m = e instanceof Error ? e.message : String(e);
|
|
@@ -16410,15 +16809,15 @@ function readOpenQuestionResolutionFile(worktreeRoot) {
|
|
|
16410
16809
|
function deleteOpenQuestionResolutionFile(worktreeRoot) {
|
|
16411
16810
|
try {
|
|
16412
16811
|
const p = openQuestionResolutionJsonAbsolute(worktreeRoot);
|
|
16413
|
-
if (
|
|
16414
|
-
|
|
16812
|
+
if (fs28.existsSync(p)) {
|
|
16813
|
+
fs28.unlinkSync(p);
|
|
16415
16814
|
}
|
|
16416
16815
|
} catch {
|
|
16417
16816
|
}
|
|
16418
16817
|
}
|
|
16419
16818
|
|
|
16420
16819
|
// src/analysis/openQuestionsSectionValidate.ts
|
|
16421
|
-
var
|
|
16820
|
+
var fs29 = __toESM(require("fs"));
|
|
16422
16821
|
var path25 = __toESM(require("path"));
|
|
16423
16822
|
var CANONICAL_NORMALIZED = "open questions";
|
|
16424
16823
|
function normalizeOpenQuestionsHeadingTitle(raw) {
|
|
@@ -16551,7 +16950,7 @@ function validateOpenQuestionsSectionFile(absolutePath, scope) {
|
|
|
16551
16950
|
}
|
|
16552
16951
|
let text;
|
|
16553
16952
|
try {
|
|
16554
|
-
const buf =
|
|
16953
|
+
const buf = fs29.readFileSync(absolutePath);
|
|
16555
16954
|
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
16556
16955
|
text = decoder.decode(buf);
|
|
16557
16956
|
} catch (e) {
|
|
@@ -17106,7 +17505,7 @@ function clampMarkdownOpenQuestionIterations(raw) {
|
|
|
17106
17505
|
}
|
|
17107
17506
|
function getExpectedOutputArtefactStatus(absolutePath) {
|
|
17108
17507
|
try {
|
|
17109
|
-
const st =
|
|
17508
|
+
const st = fs30.statSync(absolutePath);
|
|
17110
17509
|
if (!st.isFile()) {
|
|
17111
17510
|
return { generated: false, reason: "not_a_file" };
|
|
17112
17511
|
}
|
|
@@ -17205,7 +17604,7 @@ function outputPaths(step, worktreeRoot, listTarget) {
|
|
|
17205
17604
|
}
|
|
17206
17605
|
async function runOpenQuestionResolutionWorkstation(opts) {
|
|
17207
17606
|
const runDir = path26.join(opts.worktreeRoot, ".opencode", "_run");
|
|
17208
|
-
|
|
17607
|
+
fs30.mkdirSync(runDir, { recursive: true });
|
|
17209
17608
|
const resolutionJsonAbsolute = openQuestionResolutionJsonAbsolute(opts.worktreeRoot);
|
|
17210
17609
|
const body = fillResolveOpenQuestionPrompt({
|
|
17211
17610
|
worktreeRoot: opts.worktreeRoot,
|
|
@@ -17215,7 +17614,7 @@ async function runOpenQuestionResolutionWorkstation(opts) {
|
|
|
17215
17614
|
resolutionJsonAbsolute
|
|
17216
17615
|
});
|
|
17217
17616
|
const promptPath = path26.join(runDir, `resolve-open-question-${Date.now()}.prompt.txt`);
|
|
17218
|
-
|
|
17617
|
+
fs30.writeFileSync(promptPath, body, "utf-8");
|
|
17219
17618
|
const vars = {
|
|
17220
17619
|
promptFile: promptPath,
|
|
17221
17620
|
agentId: RESOLVE_OPEN_QUESTION_AGENT_STEM,
|
|
@@ -17279,7 +17678,7 @@ ${cli.message}`,
|
|
|
17279
17678
|
}
|
|
17280
17679
|
async function runOpenCodeMarkdownEvidenceRepairLoop(input) {
|
|
17281
17680
|
const totalMarkdownRuns = 1 + input.maxMarkdownEvidenceRepairs;
|
|
17282
|
-
|
|
17681
|
+
fs30.mkdirSync(input.runDir, { recursive: true });
|
|
17283
17682
|
let attemptIndex = 0;
|
|
17284
17683
|
let capturedProducerSessionId;
|
|
17285
17684
|
const repair = await runWorkstationRepairLoop({
|
|
@@ -17302,7 +17701,7 @@ async function runOpenCodeMarkdownEvidenceRepairLoop(input) {
|
|
|
17302
17701
|
const idx = attemptIndex;
|
|
17303
17702
|
const promptPath = input.promptPathForAttempt(idx);
|
|
17304
17703
|
attemptIndex += 1;
|
|
17305
|
-
|
|
17704
|
+
fs30.writeFileSync(promptPath, body, "utf-8");
|
|
17306
17705
|
const vars = input.argvVarsForPrompt(promptPath);
|
|
17307
17706
|
const expanded = expandArgvTemplate3(input.argvTemplate, vars);
|
|
17308
17707
|
const followUpSessionId = input.resolveFollowUpSessionId({
|
|
@@ -17794,7 +18193,7 @@ async function runCoordinationListWorkstation(opts) {
|
|
|
17794
18193
|
let schemaAbsoluteForList;
|
|
17795
18194
|
if (effectiveListSchemaFile) {
|
|
17796
18195
|
schemaAbsoluteForList = schemaRef(opts.worktreeRoot, effectiveListSchemaFile);
|
|
17797
|
-
if (!
|
|
18196
|
+
if (!fs30.existsSync(schemaAbsoluteForList)) {
|
|
17798
18197
|
return {
|
|
17799
18198
|
ok: false,
|
|
17800
18199
|
message: `JSON Schema not found: ${schemaAbsoluteForList}
|
|
@@ -17807,11 +18206,11 @@ Run **Materialize agents** first (copies list schemas into this folder\u2019s \`
|
|
|
17807
18206
|
}
|
|
17808
18207
|
if (opts.step === "reviewExperiencesList" && effectiveListSchemaFile) {
|
|
17809
18208
|
const schemaAbs = schemaRef(opts.worktreeRoot, effectiveListSchemaFile);
|
|
17810
|
-
if (
|
|
18209
|
+
if (fs30.existsSync(outputFileAbsolute)) {
|
|
17811
18210
|
const v = validateCoordinationListJson(outputFileAbsolute, schemaAbs);
|
|
17812
18211
|
if (v.ok) {
|
|
17813
18212
|
try {
|
|
17814
|
-
const raw =
|
|
18213
|
+
const raw = fs30.readFileSync(outputFileAbsolute, "utf-8");
|
|
17815
18214
|
const data = JSON.parse(raw);
|
|
17816
18215
|
if (Array.isArray(data.views) && data.views.length === 0) {
|
|
17817
18216
|
return {
|
|
@@ -17827,9 +18226,9 @@ Run **Materialize agents** first (copies list schemas into this folder\u2019s \`
|
|
|
17827
18226
|
}
|
|
17828
18227
|
}
|
|
17829
18228
|
}
|
|
17830
|
-
|
|
18229
|
+
fs30.mkdirSync(path26.dirname(outputFileAbsolute), { recursive: true });
|
|
17831
18230
|
const runDir = path26.join(opts.worktreeRoot, ".opencode", "_run");
|
|
17832
|
-
|
|
18231
|
+
fs30.mkdirSync(runDir, { recursive: true });
|
|
17833
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}` : "";
|
|
17834
18233
|
const rawRepair = opts.listJsonSchemaRepairAttempts;
|
|
17835
18234
|
let maxRepairAttempts = rawRepair === void 0 ? 1 : Math.floor(Number(rawRepair));
|
|
@@ -17848,8 +18247,8 @@ Run **Materialize agents** first (copies list schemas into this folder\u2019s \`
|
|
|
17848
18247
|
let preImageDocForStableWrite = {};
|
|
17849
18248
|
if (effectiveListSchemaFile && schemaAbsoluteForList && shouldApplyStableMergeForCoordinationBasename(outputBasename)) {
|
|
17850
18249
|
try {
|
|
17851
|
-
if (
|
|
17852
|
-
preImageDocForStableWrite = JSON.parse(
|
|
18250
|
+
if (fs30.existsSync(outputFileAbsolute)) {
|
|
18251
|
+
preImageDocForStableWrite = JSON.parse(fs30.readFileSync(outputFileAbsolute, "utf-8"));
|
|
17853
18252
|
}
|
|
17854
18253
|
} catch {
|
|
17855
18254
|
preImageDocForStableWrite = {};
|
|
@@ -18038,7 +18437,7 @@ Run **Materialize agents** first (copies list schemas into this folder\u2019s \`
|
|
|
18038
18437
|
);
|
|
18039
18438
|
const promptPath = path26.join(runDir, `${opts.step}${scopeSuffix}-a${attempt}-${Date.now()}.prompt.txt`);
|
|
18040
18439
|
lastPromptPath = promptPath;
|
|
18041
|
-
|
|
18440
|
+
fs30.writeFileSync(promptPath, body, "utf-8");
|
|
18042
18441
|
const vars = {
|
|
18043
18442
|
promptFile: promptPath,
|
|
18044
18443
|
agentId: STEP_OPEN_CODE_AGENT_IDS[opts.step],
|
|
@@ -18278,9 +18677,9 @@ async function runDetailMarkdownWorkstation(opts) {
|
|
|
18278
18677
|
}
|
|
18279
18678
|
maxMarkdownEvidenceRepairs = Math.min(5, Math.max(0, maxMarkdownEvidenceRepairs));
|
|
18280
18679
|
const totalMarkdownRuns = 1 + maxMarkdownEvidenceRepairs;
|
|
18281
|
-
|
|
18680
|
+
fs30.mkdirSync(path26.dirname(outputFileAbsolute), { recursive: true });
|
|
18282
18681
|
const runDir = path26.join(opts.worktreeRoot, ".opencode", "_run");
|
|
18283
|
-
|
|
18682
|
+
fs30.mkdirSync(runDir, { recursive: true });
|
|
18284
18683
|
const safeStem = opts.target.outputBasename.replace(/[^A-Za-z0-9_.-]+/g, "_").slice(0, 120);
|
|
18285
18684
|
let lastPromptPath = "";
|
|
18286
18685
|
let lastCliMessage = "";
|
|
@@ -18522,18 +18921,18 @@ Expected output: ${outputFileAbsolute}`;
|
|
|
18522
18921
|
}
|
|
18523
18922
|
|
|
18524
18923
|
// src/analysis/worktreeManager.ts
|
|
18525
|
-
var
|
|
18526
|
-
var
|
|
18527
|
-
var
|
|
18924
|
+
var import_child_process4 = require("child_process");
|
|
18925
|
+
var fs31 = __toESM(require("fs"));
|
|
18926
|
+
var os4 = __toESM(require("os"));
|
|
18528
18927
|
var path27 = __toESM(require("path"));
|
|
18529
18928
|
|
|
18530
18929
|
// src/analysis/gitWorktreeStaleRecovery.ts
|
|
18531
|
-
var
|
|
18930
|
+
var import_child_process3 = require("child_process");
|
|
18532
18931
|
function isMissingRegisteredWorktreeError(combinedStderrStdout) {
|
|
18533
18932
|
return /missing but already registered worktree/i.test(combinedStderrStdout);
|
|
18534
18933
|
}
|
|
18535
18934
|
function gitWorktreePruneSync(repoRoot) {
|
|
18536
|
-
const r = (0,
|
|
18935
|
+
const r = (0, import_child_process3.spawnSync)("git", ["worktree", "prune"], {
|
|
18537
18936
|
cwd: repoRoot,
|
|
18538
18937
|
encoding: "utf-8",
|
|
18539
18938
|
timeout: 6e4
|
|
@@ -18554,7 +18953,7 @@ function maxEasyspecsWorktreeIndex(parentDir) {
|
|
|
18554
18953
|
let max = 0;
|
|
18555
18954
|
let entries;
|
|
18556
18955
|
try {
|
|
18557
|
-
entries =
|
|
18956
|
+
entries = fs31.readdirSync(parentDir, { withFileTypes: true });
|
|
18558
18957
|
} catch {
|
|
18559
18958
|
return 0;
|
|
18560
18959
|
}
|
|
@@ -18577,19 +18976,19 @@ function formatEasyspecsWorktreeFolderName(index) {
|
|
|
18577
18976
|
return `easyspecs-${String(index).padStart(3, "0")}`;
|
|
18578
18977
|
}
|
|
18579
18978
|
function allocateEasyspecsWorktreePath(parentDir) {
|
|
18580
|
-
|
|
18979
|
+
fs31.mkdirSync(parentDir, { recursive: true });
|
|
18581
18980
|
const start = maxEasyspecsWorktreeIndex(parentDir);
|
|
18582
18981
|
for (let i = start + 1; i < start + 1e4; i++) {
|
|
18583
18982
|
const name = formatEasyspecsWorktreeFolderName(i);
|
|
18584
18983
|
const wt = path27.join(parentDir, name);
|
|
18585
|
-
if (!
|
|
18984
|
+
if (!fs31.existsSync(wt)) {
|
|
18586
18985
|
return wt;
|
|
18587
18986
|
}
|
|
18588
18987
|
}
|
|
18589
18988
|
return null;
|
|
18590
18989
|
}
|
|
18591
18990
|
function readHeadBranchShort(repoRoot) {
|
|
18592
|
-
const r = (0,
|
|
18991
|
+
const r = (0, import_child_process4.spawnSync)("git", ["symbolic-ref", "--short", "-q", "HEAD"], {
|
|
18593
18992
|
cwd: repoRoot,
|
|
18594
18993
|
encoding: "utf-8",
|
|
18595
18994
|
timeout: 3e4
|
|
@@ -18607,20 +19006,20 @@ function attachWorktreeHandle(worktreePath, repositoryRoot) {
|
|
|
18607
19006
|
path: wt,
|
|
18608
19007
|
repoRoot: repo,
|
|
18609
19008
|
remove() {
|
|
18610
|
-
(0,
|
|
19009
|
+
(0, import_child_process4.spawnSync)("git", ["worktree", "remove", "--force", wt], {
|
|
18611
19010
|
cwd: repo,
|
|
18612
19011
|
encoding: "utf-8",
|
|
18613
19012
|
timeout: 6e4
|
|
18614
19013
|
});
|
|
18615
19014
|
try {
|
|
18616
|
-
|
|
19015
|
+
fs31.rmSync(wt, { recursive: true, force: true });
|
|
18617
19016
|
} catch {
|
|
18618
19017
|
}
|
|
18619
19018
|
}
|
|
18620
19019
|
};
|
|
18621
19020
|
}
|
|
18622
19021
|
function createAnalysisWorktree(repoRoot, options) {
|
|
18623
|
-
const parent = path27.join(
|
|
19022
|
+
const parent = path27.join(os4.tmpdir(), "easyspecs-analysis");
|
|
18624
19023
|
const wt = allocateEasyspecsWorktreePath(parent);
|
|
18625
19024
|
if (!wt) {
|
|
18626
19025
|
return {
|
|
@@ -18630,7 +19029,7 @@ function createAnalysisWorktree(repoRoot, options) {
|
|
|
18630
19029
|
}
|
|
18631
19030
|
const sourceBranchAtCreation = readHeadBranchShort(repoRoot);
|
|
18632
19031
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
18633
|
-
const r = (0,
|
|
19032
|
+
const r = (0, import_child_process4.spawnSync)("git", ["worktree", "add", "--detach", wt, "HEAD"], {
|
|
18634
19033
|
cwd: repoRoot,
|
|
18635
19034
|
encoding: "utf-8",
|
|
18636
19035
|
timeout: 12e4
|
|
@@ -18748,7 +19147,7 @@ function noteOpenCodeAgentLaunched() {
|
|
|
18748
19147
|
}
|
|
18749
19148
|
|
|
18750
19149
|
// src/contextIndexAssembler.ts
|
|
18751
|
-
var
|
|
19150
|
+
var fs32 = __toESM(require("fs"));
|
|
18752
19151
|
var path28 = __toESM(require("path"));
|
|
18753
19152
|
|
|
18754
19153
|
// src/srsModel.ts
|
|
@@ -18783,7 +19182,7 @@ function tryAttachMarkdown(node, contextDir2, relativePath) {
|
|
|
18783
19182
|
}
|
|
18784
19183
|
const full = path28.join(contextDir2, norm);
|
|
18785
19184
|
try {
|
|
18786
|
-
if (!
|
|
19185
|
+
if (!fs32.existsSync(full) || !fs32.statSync(full).isFile()) {
|
|
18787
19186
|
return false;
|
|
18788
19187
|
}
|
|
18789
19188
|
} catch {
|
|
@@ -18841,10 +19240,10 @@ function mergePersistedIndexUploadMetadata(previous, next) {
|
|
|
18841
19240
|
function tryReadExistingIndexForMerge(contextDir2) {
|
|
18842
19241
|
const p = path28.join(contextDir2, "index-application-context.json");
|
|
18843
19242
|
try {
|
|
18844
|
-
if (!
|
|
19243
|
+
if (!fs32.existsSync(p)) {
|
|
18845
19244
|
return null;
|
|
18846
19245
|
}
|
|
18847
|
-
const j = JSON.parse(
|
|
19246
|
+
const j = JSON.parse(fs32.readFileSync(p, "utf8"));
|
|
18848
19247
|
if (j && typeof j === "object" && j.kind === APPLICATION_CONTEXT_KIND) {
|
|
18849
19248
|
return j;
|
|
18850
19249
|
}
|
|
@@ -18999,7 +19398,7 @@ function applyDetailMarkdownToDocument(doc, contextDir2) {
|
|
|
18999
19398
|
}
|
|
19000
19399
|
function readJson2(filePath) {
|
|
19001
19400
|
try {
|
|
19002
|
-
const raw =
|
|
19401
|
+
const raw = fs32.readFileSync(filePath, "utf-8");
|
|
19003
19402
|
return JSON.parse(raw);
|
|
19004
19403
|
} catch {
|
|
19005
19404
|
return null;
|
|
@@ -19179,11 +19578,11 @@ function writeIndexApplicationContext(contextDir2, title, options) {
|
|
|
19179
19578
|
const target = path28.join(contextDir2, "index-application-context.json");
|
|
19180
19579
|
const tmp = `${target}.${process.pid}.tmp`;
|
|
19181
19580
|
try {
|
|
19182
|
-
|
|
19183
|
-
|
|
19581
|
+
fs32.writeFileSync(tmp, JSON.stringify(doc, null, 2), "utf-8");
|
|
19582
|
+
fs32.renameSync(tmp, target);
|
|
19184
19583
|
} catch (e) {
|
|
19185
19584
|
try {
|
|
19186
|
-
|
|
19585
|
+
fs32.unlinkSync(tmp);
|
|
19187
19586
|
} catch {
|
|
19188
19587
|
}
|
|
19189
19588
|
throw e;
|
|
@@ -19192,7 +19591,7 @@ function writeIndexApplicationContext(contextDir2, title, options) {
|
|
|
19192
19591
|
}
|
|
19193
19592
|
|
|
19194
19593
|
// src/pipelines/linkMapping/linkMappingPipeline.ts
|
|
19195
|
-
var
|
|
19594
|
+
var fs33 = __toESM(require("node:fs"));
|
|
19196
19595
|
var path29 = __toESM(require("node:path"));
|
|
19197
19596
|
var SLUG2 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
19198
19597
|
function safeStr2(v) {
|
|
@@ -19217,7 +19616,7 @@ function slugOrFallback2(row2) {
|
|
|
19217
19616
|
}
|
|
19218
19617
|
function readJson3(filePath) {
|
|
19219
19618
|
try {
|
|
19220
|
-
const raw =
|
|
19619
|
+
const raw = fs33.readFileSync(filePath, "utf-8");
|
|
19221
19620
|
return JSON.parse(raw);
|
|
19222
19621
|
} catch {
|
|
19223
19622
|
return null;
|
|
@@ -19249,7 +19648,7 @@ function existsContextFile(contextDir2, rel) {
|
|
|
19249
19648
|
}
|
|
19250
19649
|
const full = path29.join(contextDir2, norm);
|
|
19251
19650
|
try {
|
|
19252
|
-
return
|
|
19651
|
+
return fs33.existsSync(full) && fs33.statSync(full).isFile();
|
|
19253
19652
|
} catch {
|
|
19254
19653
|
return false;
|
|
19255
19654
|
}
|
|
@@ -19346,7 +19745,7 @@ ${lines.join("\n")}
|
|
|
19346
19745
|
function collectMarkdownFilesRecursive(dir, acc) {
|
|
19347
19746
|
let entries;
|
|
19348
19747
|
try {
|
|
19349
|
-
entries =
|
|
19748
|
+
entries = fs33.readdirSync(dir, { withFileTypes: true });
|
|
19350
19749
|
} catch {
|
|
19351
19750
|
return;
|
|
19352
19751
|
}
|
|
@@ -19367,7 +19766,7 @@ function validateEasyspecsNavLinksInContext(contextDirAbs) {
|
|
|
19367
19766
|
for (const abs of mdFiles) {
|
|
19368
19767
|
let raw;
|
|
19369
19768
|
try {
|
|
19370
|
-
raw =
|
|
19769
|
+
raw = fs33.readFileSync(abs, "utf8");
|
|
19371
19770
|
} catch {
|
|
19372
19771
|
continue;
|
|
19373
19772
|
}
|
|
@@ -19393,7 +19792,7 @@ function validateEasyspecsNavLinksInContext(contextDirAbs) {
|
|
|
19393
19792
|
}
|
|
19394
19793
|
const target = path29.normalize(path29.join(path29.dirname(abs), href));
|
|
19395
19794
|
try {
|
|
19396
|
-
if (!
|
|
19795
|
+
if (!fs33.existsSync(target) || !fs33.statSync(target).isFile()) {
|
|
19397
19796
|
broken.push(`${path29.relative(contextDirAbs, abs)} \u2192 ${href}`);
|
|
19398
19797
|
}
|
|
19399
19798
|
} catch {
|
|
@@ -19419,7 +19818,7 @@ function validateEasyspecsNavLinksInContext(contextDirAbs) {
|
|
|
19419
19818
|
}
|
|
19420
19819
|
const target = path29.normalize(path29.join(path29.dirname(abs), href));
|
|
19421
19820
|
try {
|
|
19422
|
-
if (!
|
|
19821
|
+
if (!fs33.existsSync(target) || !fs33.statSync(target).isFile()) {
|
|
19423
19822
|
broken.push(`${path29.relative(contextDirAbs, abs)} \u2192 ${href}`);
|
|
19424
19823
|
}
|
|
19425
19824
|
} catch {
|
|
@@ -19627,7 +20026,7 @@ function renderProjectMdSections(contextDir2) {
|
|
|
19627
20026
|
}
|
|
19628
20027
|
}
|
|
19629
20028
|
const dmListPath = path29.join(contextDir2, "data-model-list.json");
|
|
19630
|
-
if (dmLines.length === 0 &&
|
|
20029
|
+
if (dmLines.length === 0 && fs33.existsSync(dmListPath)) {
|
|
19631
20030
|
dmLines.push(bulletLink("Data model registry (JSON)", "./data-model-list.json"));
|
|
19632
20031
|
}
|
|
19633
20032
|
chunks.push("### Data model", "", dmLines.length ? dmLines.join("\n") : NONE_LINE, "");
|
|
@@ -19635,23 +20034,23 @@ function renderProjectMdSections(contextDir2) {
|
|
|
19635
20034
|
}
|
|
19636
20035
|
function patchOneFile(contextDir2, basename17, innerChildren, innerParents, opts) {
|
|
19637
20036
|
const abs = path29.join(contextDir2, basename17);
|
|
19638
|
-
if (!
|
|
20037
|
+
if (!fs33.existsSync(abs)) {
|
|
19639
20038
|
return;
|
|
19640
20039
|
}
|
|
19641
20040
|
let body;
|
|
19642
20041
|
try {
|
|
19643
|
-
body =
|
|
20042
|
+
body = fs33.readFileSync(abs, "utf8");
|
|
19644
20043
|
} catch (e) {
|
|
19645
20044
|
opts.log?.(`[pipeline:link-mapping] skip read ${basename17}: ${e instanceof Error ? e.message : String(e)}`);
|
|
19646
20045
|
return;
|
|
19647
20046
|
}
|
|
19648
20047
|
let next = replaceOrAppendRegion(body, NAV_CHILDREN_START, NAV_CHILDREN_END, innerChildren);
|
|
19649
20048
|
next = replaceOrAppendRegion(next, NAV_PARENTS_START, NAV_PARENTS_END, innerParents);
|
|
19650
|
-
|
|
20049
|
+
fs33.writeFileSync(abs, next, "utf8");
|
|
19651
20050
|
}
|
|
19652
20051
|
function runLinkMappingPipeline(contextDirAbs, opts = {}) {
|
|
19653
20052
|
const contextDir2 = path29.resolve(contextDirAbs);
|
|
19654
|
-
if (!
|
|
20053
|
+
if (!fs33.existsSync(contextDir2) || !fs33.statSync(contextDir2).isDirectory()) {
|
|
19655
20054
|
return { ok: false, error: `Context directory does not exist: ${contextDir2}` };
|
|
19656
20055
|
}
|
|
19657
20056
|
const edges = buildNavEdges(contextDir2);
|
|
@@ -19679,7 +20078,7 @@ function runLinkMappingPipeline(contextDirAbs, opts = {}) {
|
|
|
19679
20078
|
continue;
|
|
19680
20079
|
}
|
|
19681
20080
|
const abs = path29.join(contextDir2, basename17);
|
|
19682
|
-
if (!
|
|
20081
|
+
if (!fs33.existsSync(abs)) {
|
|
19683
20082
|
continue;
|
|
19684
20083
|
}
|
|
19685
20084
|
const childRows = edges.children.get(basename17) ?? [];
|
|
@@ -19713,15 +20112,15 @@ var path30 = __toESM(require("node:path"));
|
|
|
19713
20112
|
var vscode2 = __toESM(require_vscode_stub());
|
|
19714
20113
|
|
|
19715
20114
|
// src/config/easyspecsAceConfigRead.ts
|
|
19716
|
-
var
|
|
20115
|
+
var fs34 = __toESM(require("node:fs"));
|
|
19717
20116
|
function readRawConfigJson(repoRoot) {
|
|
19718
20117
|
const p = easyspecsConfigPath(repoRoot);
|
|
19719
|
-
if (!
|
|
20118
|
+
if (!fs34.existsSync(p)) {
|
|
19720
20119
|
return void 0;
|
|
19721
20120
|
}
|
|
19722
20121
|
let raw;
|
|
19723
20122
|
try {
|
|
19724
|
-
raw =
|
|
20123
|
+
raw = fs34.readFileSync(p, "utf8");
|
|
19725
20124
|
} catch {
|
|
19726
20125
|
return void 0;
|
|
19727
20126
|
}
|
|
@@ -19857,7 +20256,7 @@ function getAceOfflineLearnAfterSameSessionTrace(analysisCheckoutRoot) {
|
|
|
19857
20256
|
}
|
|
19858
20257
|
|
|
19859
20258
|
// src/analysis/repoSurfaceAssessment.ts
|
|
19860
|
-
var
|
|
20259
|
+
var fs35 = __toESM(require("fs"));
|
|
19861
20260
|
var path31 = __toESM(require("path"));
|
|
19862
20261
|
var REPO_SURFACE_SCAN_BASENAME = "repo-surface-scan.json";
|
|
19863
20262
|
function stripBom(s) {
|
|
@@ -19866,7 +20265,7 @@ function stripBom(s) {
|
|
|
19866
20265
|
function readRepoSurfaceAssessment(contextDir2) {
|
|
19867
20266
|
const p = path31.join(contextDir2, REPO_SURFACE_SCAN_BASENAME);
|
|
19868
20267
|
try {
|
|
19869
|
-
const raw = stripBom(
|
|
20268
|
+
const raw = stripBom(fs35.readFileSync(p, "utf-8"));
|
|
19870
20269
|
const data = JSON.parse(raw);
|
|
19871
20270
|
if (!data || typeof data !== "object") {
|
|
19872
20271
|
return null;
|
|
@@ -19887,8 +20286,8 @@ function readRepoSurfaceAssessment(contextDir2) {
|
|
|
19887
20286
|
}
|
|
19888
20287
|
function writeEmptyExperiencesListJson(contextDir2) {
|
|
19889
20288
|
const p = path31.join(contextDir2, "experiences-list.json");
|
|
19890
|
-
|
|
19891
|
-
|
|
20289
|
+
fs35.mkdirSync(path31.dirname(p), { recursive: true });
|
|
20290
|
+
fs35.writeFileSync(
|
|
19892
20291
|
p,
|
|
19893
20292
|
`${JSON.stringify(
|
|
19894
20293
|
{
|
|
@@ -19904,6 +20303,31 @@ function writeEmptyExperiencesListJson(contextDir2) {
|
|
|
19904
20303
|
);
|
|
19905
20304
|
}
|
|
19906
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 candidate = Math.max(1, p.activeRunningCount - 1);
|
|
20324
|
+
const next = Math.min(p.priorAdaptiveMax, candidate);
|
|
20325
|
+
if (next < p.priorAdaptiveMax) {
|
|
20326
|
+
return { adaptiveMax: next, changed: true };
|
|
20327
|
+
}
|
|
20328
|
+
return { adaptiveMax: p.priorAdaptiveMax, changed: false };
|
|
20329
|
+
}
|
|
20330
|
+
|
|
19907
20331
|
// src/pipelines/synthesis/synthesisPipeline.ts
|
|
19908
20332
|
var FE = /^FE-\d+$/;
|
|
19909
20333
|
var UC = /^UC-\d+$/;
|
|
@@ -19916,7 +20340,7 @@ function stripBom2(s) {
|
|
|
19916
20340
|
}
|
|
19917
20341
|
function readJson4(filePath) {
|
|
19918
20342
|
try {
|
|
19919
|
-
const raw = stripBom2(
|
|
20343
|
+
const raw = stripBom2(fs36.readFileSync(filePath, "utf-8"));
|
|
19920
20344
|
return JSON.parse(raw);
|
|
19921
20345
|
} catch {
|
|
19922
20346
|
return null;
|
|
@@ -20011,7 +20435,7 @@ function featureDetailTarget(contextDir2, code, name, slug) {
|
|
|
20011
20435
|
displayName: "Feature detail",
|
|
20012
20436
|
outputBasename: basename17,
|
|
20013
20437
|
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).`,
|
|
20014
|
-
exists:
|
|
20438
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20015
20439
|
};
|
|
20016
20440
|
}
|
|
20017
20441
|
function viewDetailTarget(row2, contextDir2) {
|
|
@@ -20022,7 +20446,7 @@ function viewDetailTarget(row2, contextDir2) {
|
|
|
20022
20446
|
displayName: "View detail",
|
|
20023
20447
|
outputBasename: basename17,
|
|
20024
20448
|
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.`,
|
|
20025
|
-
exists:
|
|
20449
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20026
20450
|
};
|
|
20027
20451
|
}
|
|
20028
20452
|
function interactionDetailTarget(viewCode, ix, contextDir2) {
|
|
@@ -20033,7 +20457,7 @@ function interactionDetailTarget(viewCode, ix, contextDir2) {
|
|
|
20033
20457
|
displayName: "Interaction detail",
|
|
20034
20458
|
outputBasename: basename17,
|
|
20035
20459
|
taskDescription: `Document interaction **${ix.code}** (**${ix.name}**) on view **${viewCode}** per \`.gluecharm/context/experiences-list.json\`.`,
|
|
20036
|
-
exists:
|
|
20460
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20037
20461
|
};
|
|
20038
20462
|
}
|
|
20039
20463
|
function serviceDetailTarget(row2, contextDir2) {
|
|
@@ -20044,7 +20468,7 @@ function serviceDetailTarget(row2, contextDir2) {
|
|
|
20044
20468
|
displayName: "Service detail",
|
|
20045
20469
|
outputBasename: basename17,
|
|
20046
20470
|
taskDescription: `Describe service **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/services-list.json\`: responsibilities, consumers, errors, integration points.`,
|
|
20047
|
-
exists:
|
|
20471
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20048
20472
|
};
|
|
20049
20473
|
}
|
|
20050
20474
|
function methodDetailTarget(svc, m, contextDir2) {
|
|
@@ -20055,7 +20479,7 @@ function methodDetailTarget(svc, m, contextDir2) {
|
|
|
20055
20479
|
displayName: "Method detail",
|
|
20056
20480
|
outputBasename: basename17,
|
|
20057
20481
|
taskDescription: `Document method **${m.code}** (**${m.name}**) on service **${svc.code}** per \`.gluecharm/context/services-list.json\`.`,
|
|
20058
|
-
exists:
|
|
20482
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20059
20483
|
};
|
|
20060
20484
|
}
|
|
20061
20485
|
function entityDetailTarget(dmCode, ename, slug, contextDir2) {
|
|
@@ -20066,7 +20490,7 @@ function entityDetailTarget(dmCode, ename, slug, contextDir2) {
|
|
|
20066
20490
|
displayName: "Entity detail",
|
|
20067
20491
|
outputBasename: basename17,
|
|
20068
20492
|
taskDescription: `Describe entity **${dmCode}** (**${ename}**, slug **${slug}**) per \`.gluecharm/context/data-model-list.json\`: lifecycle, invariants, storage, ORM/schema mapping.`,
|
|
20069
|
-
exists:
|
|
20493
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20070
20494
|
};
|
|
20071
20495
|
}
|
|
20072
20496
|
function fieldDetailTarget(dmCode, fdCode, fname, fSlug, contextDir2) {
|
|
@@ -20077,7 +20501,7 @@ function fieldDetailTarget(dmCode, fdCode, fname, fSlug, contextDir2) {
|
|
|
20077
20501
|
displayName: "Field detail",
|
|
20078
20502
|
outputBasename: basename17,
|
|
20079
20503
|
taskDescription: `Document field **${fdCode}** (**${fname}**) on entity **${dmCode}** per \`.gluecharm/context/${dmCode}-fields-list.json\`. Cite types and constraints with file and line.`,
|
|
20080
|
-
exists:
|
|
20504
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20081
20505
|
};
|
|
20082
20506
|
}
|
|
20083
20507
|
function toolDetailTarget(row2, contextDir2) {
|
|
@@ -20088,7 +20512,7 @@ function toolDetailTarget(row2, contextDir2) {
|
|
|
20088
20512
|
displayName: "Tool detail",
|
|
20089
20513
|
outputBasename: basename17,
|
|
20090
20514
|
taskDescription: `Describe tool **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/tech-stack-list.json\`: role, version hints, configuration, boundaries.`,
|
|
20091
|
-
exists:
|
|
20515
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20092
20516
|
};
|
|
20093
20517
|
}
|
|
20094
20518
|
function useCaseDetailTarget(feCode, ucCode, ucName, ucSlug, contextDir2) {
|
|
@@ -20101,7 +20525,7 @@ function useCaseDetailTarget(feCode, ucCode, ucName, ucSlug, contextDir2) {
|
|
|
20101
20525
|
taskDescription: `Document use case **${ucCode}** (**${ucName}**) under feature **${feCode}** per \`.gluecharm/context/${feCode}-use-cases-list.json\`. Do not change stable codes.
|
|
20102
20526
|
|
|
20103
20527
|
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.`,
|
|
20104
|
-
exists:
|
|
20528
|
+
exists: fs36.existsSync(path32.join(contextDir2, ucBase)) && fs36.statSync(path32.join(contextDir2, ucBase)).size > 0
|
|
20105
20529
|
};
|
|
20106
20530
|
}
|
|
20107
20531
|
function scenarioDetailTarget(feCode, ucCode, scCode, scName, contextDir2) {
|
|
@@ -20112,7 +20536,7 @@ function scenarioDetailTarget(feCode, ucCode, scCode, scName, contextDir2) {
|
|
|
20112
20536
|
displayName: "Scenario detail",
|
|
20113
20537
|
outputBasename: basename17,
|
|
20114
20538
|
taskDescription: `Document scenario **${scCode}** (**${scName}**) for **${feCode}** / **${ucCode}** per \`.gluecharm/context/${feCode}_${ucCode}-scenarios-list.json\`. Cite steps with file and line where possible.`,
|
|
20115
|
-
exists:
|
|
20539
|
+
exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20116
20540
|
};
|
|
20117
20541
|
}
|
|
20118
20542
|
function parentsDone(item, byId) {
|
|
@@ -20531,8 +20955,29 @@ async function runWorkstationWithOuterAttempts(item, worktreeRoot, workspaceLabe
|
|
|
20531
20955
|
};
|
|
20532
20956
|
}
|
|
20533
20957
|
async function drainWorkstationPool(p) {
|
|
20534
|
-
const maxC = clampConcurrency(p.oc.maxConcurrentOpenCodeAgents);
|
|
20535
20958
|
const { storageContext, worktreeRoot, workspaceLabel, contextDir: contextDir2, byId, fifo, oc, log, abortSignal } = p;
|
|
20959
|
+
const staticMaxC = clampConcurrency(p.oc.maxConcurrentOpenCodeAgents);
|
|
20960
|
+
const throttle = p.enableCpuAdaptiveThrottle !== false;
|
|
20961
|
+
let adaptiveMax = staticMaxC;
|
|
20962
|
+
const sample = p.cpuPressureSampler ?? (throttle ? createDefaultCpuPressureSampler() : () => 0);
|
|
20963
|
+
const applyCpuPressure = () => {
|
|
20964
|
+
if (!throttle || active < 1) {
|
|
20965
|
+
return;
|
|
20966
|
+
}
|
|
20967
|
+
const ratio = sample();
|
|
20968
|
+
const { adaptiveMax: next, changed } = nextAdaptiveMaxAfterCpuSample({
|
|
20969
|
+
ratio,
|
|
20970
|
+
activeRunningCount: active,
|
|
20971
|
+
priorAdaptiveMax: adaptiveMax
|
|
20972
|
+
});
|
|
20973
|
+
if (changed) {
|
|
20974
|
+
adaptiveMax = next;
|
|
20975
|
+
log(
|
|
20976
|
+
`[pool] cpu pressure ratio=${ratio.toFixed(3)} active=${String(active)} adaptiveMaxConcurrentAi=${String(adaptiveMax)}`
|
|
20977
|
+
);
|
|
20978
|
+
}
|
|
20979
|
+
};
|
|
20980
|
+
const currentCap = () => Math.min(staticMaxC, adaptiveMax);
|
|
20536
20981
|
const artefactRunId = readArtefactRunSnapshot(storageContext)?.runId ?? "unknown-run";
|
|
20537
20982
|
let active = 0;
|
|
20538
20983
|
let wake;
|
|
@@ -20567,11 +21012,13 @@ async function drainWorkstationPool(p) {
|
|
|
20567
21012
|
void persist();
|
|
20568
21013
|
pump();
|
|
20569
21014
|
};
|
|
21015
|
+
let poolAbortListenerRegistered = false;
|
|
20570
21016
|
if (abortSignal) {
|
|
20571
21017
|
if (abortSignal.aborted) {
|
|
20572
21018
|
onPipelineAbort();
|
|
20573
21019
|
} else {
|
|
20574
|
-
abortSignal.addEventListener("abort", onPipelineAbort
|
|
21020
|
+
abortSignal.addEventListener("abort", onPipelineAbort);
|
|
21021
|
+
poolAbortListenerRegistered = true;
|
|
20575
21022
|
}
|
|
20576
21023
|
}
|
|
20577
21024
|
const runOne = async (id) => {
|
|
@@ -20586,9 +21033,10 @@ async function drainWorkstationPool(p) {
|
|
|
20586
21033
|
pump();
|
|
20587
21034
|
return;
|
|
20588
21035
|
}
|
|
21036
|
+
applyCpuPressure();
|
|
20589
21037
|
item.status = "running";
|
|
20590
21038
|
await persist();
|
|
20591
|
-
log(`[pool] start ${id} (active ${active}/${
|
|
21039
|
+
log(`[pool] start ${id} (active ${active}/${currentCap()})`);
|
|
20592
21040
|
const r = await runWorkstationWithOuterAttempts(
|
|
20593
21041
|
item,
|
|
20594
21042
|
worktreeRoot,
|
|
@@ -20643,29 +21091,43 @@ async function drainWorkstationPool(p) {
|
|
|
20643
21091
|
await p.onItemComplete?.(id);
|
|
20644
21092
|
pump();
|
|
20645
21093
|
};
|
|
20646
|
-
|
|
20647
|
-
|
|
20648
|
-
|
|
20649
|
-
|
|
20650
|
-
|
|
20651
|
-
|
|
21094
|
+
let pressureInterval;
|
|
21095
|
+
if (throttle) {
|
|
21096
|
+
const intervalMs = p.__testOnlyCpuPressureIntervalMs ?? 3e4;
|
|
21097
|
+
pressureInterval = setInterval(() => applyCpuPressure(), intervalMs);
|
|
21098
|
+
}
|
|
21099
|
+
try {
|
|
21100
|
+
while (true) {
|
|
21101
|
+
while (fifo.length > 0 && active < currentCap() && !abortSignal?.aborted) {
|
|
21102
|
+
const id = fifo.shift();
|
|
21103
|
+
const it = byId.get(id);
|
|
21104
|
+
if (!it || it.status !== "pending" || !parentsDone(it, byId)) {
|
|
21105
|
+
continue;
|
|
21106
|
+
}
|
|
21107
|
+
active += 1;
|
|
21108
|
+
void runOne(id);
|
|
20652
21109
|
}
|
|
20653
|
-
active
|
|
20654
|
-
|
|
20655
|
-
}
|
|
20656
|
-
const pendingOrRunning = active > 0 || [...byId.values()].some((v) => v.status === "pending") || fifo.length > 0;
|
|
20657
|
-
if (!pendingOrRunning) {
|
|
20658
|
-
break;
|
|
20659
|
-
}
|
|
20660
|
-
if (abortSignal?.aborted) {
|
|
20661
|
-
if (active === 0) {
|
|
21110
|
+
const pendingOrRunning = active > 0 || [...byId.values()].some((v) => v.status === "pending") || fifo.length > 0;
|
|
21111
|
+
if (!pendingOrRunning) {
|
|
20662
21112
|
break;
|
|
20663
21113
|
}
|
|
20664
|
-
|
|
20665
|
-
|
|
21114
|
+
if (abortSignal?.aborted) {
|
|
21115
|
+
if (active === 0) {
|
|
21116
|
+
break;
|
|
21117
|
+
}
|
|
21118
|
+
await waitTurn();
|
|
21119
|
+
continue;
|
|
21120
|
+
}
|
|
21121
|
+
if (fifo.length === 0 || active >= currentCap()) {
|
|
21122
|
+
await waitTurn();
|
|
21123
|
+
}
|
|
21124
|
+
}
|
|
21125
|
+
} finally {
|
|
21126
|
+
if (pressureInterval) {
|
|
21127
|
+
clearInterval(pressureInterval);
|
|
20666
21128
|
}
|
|
20667
|
-
if (
|
|
20668
|
-
|
|
21129
|
+
if (poolAbortListenerRegistered && abortSignal) {
|
|
21130
|
+
abortSignal.removeEventListener("abort", onPipelineAbort);
|
|
20669
21131
|
}
|
|
20670
21132
|
}
|
|
20671
21133
|
return { cancelled: abortSignal?.aborted === true, skippedWorkItemIds };
|
|
@@ -20703,7 +21165,7 @@ async function runSynthesisPipelineDrainFromPreparedWorktree(storageContext, rep
|
|
|
20703
21165
|
offlineLearnAfterSameSessionTrace: getAceOfflineLearnAfterSameSessionTrace(handle.path)
|
|
20704
21166
|
};
|
|
20705
21167
|
const contextDir2 = path32.join(handle.path, ".gluecharm", "context");
|
|
20706
|
-
|
|
21168
|
+
fs36.mkdirSync(contextDir2, { recursive: true });
|
|
20707
21169
|
const initialItems = buildRootItems();
|
|
20708
21170
|
await startArtefactRun(storageContext, repoRoot, handle.path, initialItems);
|
|
20709
21171
|
await cb.onBootstrapReady?.({ worktreeRoot: handle.path, contextDir: contextDir2 });
|
|
@@ -20804,27 +21266,27 @@ async function runSynthesisPipeline(storageContext, repoRoot, workspaceLabel, ex
|
|
|
20804
21266
|
}
|
|
20805
21267
|
|
|
20806
21268
|
// src/workspaceContextPromote.ts
|
|
20807
|
-
var
|
|
21269
|
+
var fs37 = __toESM(require("fs"));
|
|
20808
21270
|
var path33 = __toESM(require("path"));
|
|
20809
21271
|
function promoteContextDirectoryToWorkspaceFs(sourceContextDir, workspaceRootFs) {
|
|
20810
21272
|
const dest = path33.join(workspaceRootFs, ".gluecharm", "context");
|
|
20811
|
-
|
|
20812
|
-
|
|
21273
|
+
fs37.mkdirSync(path33.join(workspaceRootFs, ".gluecharm"), { recursive: true });
|
|
21274
|
+
fs37.mkdirSync(dest, { recursive: true });
|
|
20813
21275
|
let names;
|
|
20814
21276
|
try {
|
|
20815
|
-
names =
|
|
21277
|
+
names = fs37.readdirSync(sourceContextDir);
|
|
20816
21278
|
} catch {
|
|
20817
21279
|
return { filesCopied: 0 };
|
|
20818
21280
|
}
|
|
20819
21281
|
let filesCopied = 0;
|
|
20820
21282
|
for (const name of names) {
|
|
20821
21283
|
const srcPath = path33.join(sourceContextDir, name);
|
|
20822
|
-
if (!
|
|
21284
|
+
if (!fs37.statSync(srcPath).isFile()) {
|
|
20823
21285
|
continue;
|
|
20824
21286
|
}
|
|
20825
|
-
const buf =
|
|
21287
|
+
const buf = fs37.readFileSync(srcPath);
|
|
20826
21288
|
const target = path33.join(dest, name);
|
|
20827
|
-
|
|
21289
|
+
fs37.writeFileSync(target, buf);
|
|
20828
21290
|
filesCopied += 1;
|
|
20829
21291
|
}
|
|
20830
21292
|
return { filesCopied };
|
|
@@ -21484,7 +21946,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
21484
21946
|
}
|
|
21485
21947
|
|
|
21486
21948
|
// src/factory/generateContextFactoryHeadlessHost.ts
|
|
21487
|
-
var
|
|
21949
|
+
var fs46 = __toESM(require("node:fs"));
|
|
21488
21950
|
var path43 = __toESM(require("node:path"));
|
|
21489
21951
|
|
|
21490
21952
|
// src/stores/pipelineRunStore.ts
|
|
@@ -21585,11 +22047,11 @@ async function noteAgentsMaterialized(context) {
|
|
|
21585
22047
|
}
|
|
21586
22048
|
|
|
21587
22049
|
// src/pipelines/remediation/missingWorkstations.ts
|
|
21588
|
-
var
|
|
22050
|
+
var fs39 = __toESM(require("fs"));
|
|
21589
22051
|
var path35 = __toESM(require("path"));
|
|
21590
22052
|
|
|
21591
22053
|
// src/analysis/analysisDetailMarkdownDiscovery.ts
|
|
21592
|
-
var
|
|
22054
|
+
var fs38 = __toESM(require("fs"));
|
|
21593
22055
|
var path34 = __toESM(require("path"));
|
|
21594
22056
|
var SLUG4 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
21595
22057
|
var FE2 = /^FE-\d+$/;
|
|
@@ -21611,7 +22073,7 @@ var STEM_TO_AGENT = {
|
|
|
21611
22073
|
};
|
|
21612
22074
|
function readJson5(filePath) {
|
|
21613
22075
|
try {
|
|
21614
|
-
let raw =
|
|
22076
|
+
let raw = fs38.readFileSync(filePath, "utf-8");
|
|
21615
22077
|
if (raw.length > 0 && raw.charCodeAt(0) === 65279) {
|
|
21616
22078
|
raw = raw.slice(1);
|
|
21617
22079
|
}
|
|
@@ -21879,7 +22341,7 @@ function fileAndValidationFromKind(kind) {
|
|
|
21879
22341
|
function classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeRoot) {
|
|
21880
22342
|
const abs = path35.join(contextDir2, row2.relativePath);
|
|
21881
22343
|
try {
|
|
21882
|
-
const st =
|
|
22344
|
+
const st = fs39.statSync(abs);
|
|
21883
22345
|
if (!st.isFile()) {
|
|
21884
22346
|
return { kind: "absent", detail: "Path exists but is not a regular file." };
|
|
21885
22347
|
}
|
|
@@ -21917,7 +22379,7 @@ function classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeR
|
|
|
21917
22379
|
};
|
|
21918
22380
|
}
|
|
21919
22381
|
const schemaAbs = path35.join(worktreeRoot, ".opencode", "schemas", "context-lists", schemaBn);
|
|
21920
|
-
if (!
|
|
22382
|
+
if (!fs39.existsSync(schemaAbs)) {
|
|
21921
22383
|
return {
|
|
21922
22384
|
kind: "invalid",
|
|
21923
22385
|
detail: `Schema not found (${schemaBn}). Run **Materialize agents** on this checkout.`
|
|
@@ -22153,7 +22615,7 @@ function listMissingWorkstations(contextDir2, worktreeRoot, snapshot) {
|
|
|
22153
22615
|
}
|
|
22154
22616
|
}
|
|
22155
22617
|
}
|
|
22156
|
-
if (!
|
|
22618
|
+
if (!fs39.existsSync(contextDir2)) {
|
|
22157
22619
|
return [...map.values()].sort((a, b) => a.key.localeCompare(b.key));
|
|
22158
22620
|
}
|
|
22159
22621
|
const dynamic = discoverDynamicAnalysisTestSteps(contextDir2);
|
|
@@ -22333,12 +22795,12 @@ async function runRemediationPipelineMissingPass(p) {
|
|
|
22333
22795
|
}
|
|
22334
22796
|
|
|
22335
22797
|
// src/pipelines/coverage/coveragePipeline.ts
|
|
22336
|
-
var
|
|
22337
|
-
var
|
|
22798
|
+
var import_child_process5 = require("child_process");
|
|
22799
|
+
var fs41 = __toESM(require("fs"));
|
|
22338
22800
|
var path38 = __toESM(require("path"));
|
|
22339
22801
|
|
|
22340
22802
|
// src/analysis/coverageReferenceValidationSchemaValidate.ts
|
|
22341
|
-
var
|
|
22803
|
+
var fs40 = __toESM(require("fs"));
|
|
22342
22804
|
var path37 = __toESM(require("path"));
|
|
22343
22805
|
var import__5 = __toESM(require__());
|
|
22344
22806
|
function stripUtf8Bom4(s) {
|
|
@@ -22368,7 +22830,7 @@ function getValidate() {
|
|
|
22368
22830
|
return compiledValidate;
|
|
22369
22831
|
}
|
|
22370
22832
|
const schemaPath = bundledCoverageReferenceValidationSchemaPath();
|
|
22371
|
-
const schemaRaw = stripUtf8Bom4(
|
|
22833
|
+
const schemaRaw = stripUtf8Bom4(fs40.readFileSync(schemaPath, "utf-8"));
|
|
22372
22834
|
const schema = JSON.parse(schemaRaw);
|
|
22373
22835
|
const ajv2 = new import__5.default({ allErrors: true, strict: false });
|
|
22374
22836
|
compiledValidate = ajv2.compile(schema);
|
|
@@ -22384,7 +22846,7 @@ function validateCoverageReferenceValidationData(data) {
|
|
|
22384
22846
|
function readAndValidateCoverageReferenceValidationFile(jsonAbsolutePath) {
|
|
22385
22847
|
let raw;
|
|
22386
22848
|
try {
|
|
22387
|
-
raw = stripUtf8Bom4(
|
|
22849
|
+
raw = stripUtf8Bom4(fs40.readFileSync(jsonAbsolutePath, "utf-8"));
|
|
22388
22850
|
} catch (e) {
|
|
22389
22851
|
return {
|
|
22390
22852
|
ok: false,
|
|
@@ -22426,7 +22888,7 @@ var DEFAULT_IGNORE_DIR_BASENAMES = [
|
|
|
22426
22888
|
var GIT_LS_FILES_MAX_BUFFER = 64 * 1024 * 1024;
|
|
22427
22889
|
function tryLoadGitNonIgnoredPathSet(repositoryRootAbs) {
|
|
22428
22890
|
const root = path38.resolve(repositoryRootAbs);
|
|
22429
|
-
if (!
|
|
22891
|
+
if (!fs41.existsSync(path38.join(root, ".git"))) {
|
|
22430
22892
|
return null;
|
|
22431
22893
|
}
|
|
22432
22894
|
const env = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
@@ -22437,8 +22899,8 @@ function tryLoadGitNonIgnoredPathSet(repositoryRootAbs) {
|
|
|
22437
22899
|
env
|
|
22438
22900
|
};
|
|
22439
22901
|
try {
|
|
22440
|
-
const tracked = (0,
|
|
22441
|
-
const others = (0,
|
|
22902
|
+
const tracked = (0, import_child_process5.execFileSync)("git", ["-c", "core.quotepath=false", "ls-files", "-z"], opts);
|
|
22903
|
+
const others = (0, import_child_process5.execFileSync)(
|
|
22442
22904
|
"git",
|
|
22443
22905
|
["-c", "core.quotepath=false", "ls-files", "-z", "--others", "--exclude-standard"],
|
|
22444
22906
|
opts
|
|
@@ -22581,7 +23043,7 @@ function extractEvidenceIndexPathCitations(body) {
|
|
|
22581
23043
|
function listContextFilesRecursive(dir, acc) {
|
|
22582
23044
|
let entries;
|
|
22583
23045
|
try {
|
|
22584
|
-
entries =
|
|
23046
|
+
entries = fs41.readdirSync(dir, { withFileTypes: true });
|
|
22585
23047
|
} catch {
|
|
22586
23048
|
return;
|
|
22587
23049
|
}
|
|
@@ -22599,7 +23061,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
22599
23061
|
const walk = (dir) => {
|
|
22600
23062
|
let entries;
|
|
22601
23063
|
try {
|
|
22602
|
-
entries =
|
|
23064
|
+
entries = fs41.readdirSync(dir, { withFileTypes: true });
|
|
22603
23065
|
} catch {
|
|
22604
23066
|
return;
|
|
22605
23067
|
}
|
|
@@ -22629,7 +23091,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
22629
23091
|
}
|
|
22630
23092
|
let st;
|
|
22631
23093
|
try {
|
|
22632
|
-
st =
|
|
23094
|
+
st = fs41.statSync(full);
|
|
22633
23095
|
} catch {
|
|
22634
23096
|
continue;
|
|
22635
23097
|
}
|
|
@@ -22639,7 +23101,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
22639
23101
|
}
|
|
22640
23102
|
let buf;
|
|
22641
23103
|
try {
|
|
22642
|
-
buf =
|
|
23104
|
+
buf = fs41.readFileSync(full);
|
|
22643
23105
|
} catch {
|
|
22644
23106
|
excludedOut.push({ path: rel, reason: "read error" });
|
|
22645
23107
|
continue;
|
|
@@ -22659,7 +23121,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
22659
23121
|
}
|
|
22660
23122
|
function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings) {
|
|
22661
23123
|
const references = [];
|
|
22662
|
-
if (!
|
|
23124
|
+
if (!fs41.existsSync(contextDirAbs)) {
|
|
22663
23125
|
warnings.push(`Context directory missing: ${contextDirAbs}`);
|
|
22664
23126
|
return references;
|
|
22665
23127
|
}
|
|
@@ -22675,7 +23137,7 @@ function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings
|
|
|
22675
23137
|
}
|
|
22676
23138
|
let raw;
|
|
22677
23139
|
try {
|
|
22678
|
-
raw =
|
|
23140
|
+
raw = fs41.readFileSync(abs, "utf-8");
|
|
22679
23141
|
} catch (e) {
|
|
22680
23142
|
warnings.push(`Skip JSON (read error): ${sourceArtefact} \u2014 ${e instanceof Error ? e.message : String(e)}`);
|
|
22681
23143
|
continue;
|
|
@@ -22706,7 +23168,7 @@ function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings
|
|
|
22706
23168
|
if (ext === ".md") {
|
|
22707
23169
|
let text;
|
|
22708
23170
|
try {
|
|
22709
|
-
const buf =
|
|
23171
|
+
const buf = fs41.readFileSync(abs);
|
|
22710
23172
|
text = decodeBufferForLineCount(buf);
|
|
22711
23173
|
} catch (e) {
|
|
22712
23174
|
warnings.push(`Skip markdown (read/decode error): ${sourceArtefact} \u2014 ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -22763,7 +23225,7 @@ function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirA
|
|
|
22763
23225
|
}
|
|
22764
23226
|
const excludedFiles = [];
|
|
22765
23227
|
const gitNonIgnoredPaths = tryLoadGitNonIgnoredPathSet(repoRoot);
|
|
22766
|
-
if (
|
|
23228
|
+
if (fs41.existsSync(path38.join(repoRoot, ".git")) && gitNonIgnoredPaths === null) {
|
|
22767
23229
|
warnings.push(
|
|
22768
23230
|
"Repository has .git but git ls-files failed or git is unavailable; .gitignore / exclude-standard not applied."
|
|
22769
23231
|
);
|
|
@@ -22814,10 +23276,10 @@ function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirA
|
|
|
22814
23276
|
function runCoveragePipeline(opts) {
|
|
22815
23277
|
const repoRoot = path38.resolve(opts.repositoryRootAbs);
|
|
22816
23278
|
const contextDir2 = path38.resolve(opts.contextDirAbs);
|
|
22817
|
-
if (!
|
|
23279
|
+
if (!fs41.existsSync(repoRoot)) {
|
|
22818
23280
|
return { ok: false, error: `Repository root does not exist: ${repoRoot}` };
|
|
22819
23281
|
}
|
|
22820
|
-
if (!
|
|
23282
|
+
if (!fs41.existsSync(contextDir2)) {
|
|
22821
23283
|
return {
|
|
22822
23284
|
ok: false,
|
|
22823
23285
|
error: `Missing .gluecharm/context: ${contextDir2}`
|
|
@@ -22839,7 +23301,7 @@ ${schemaCheck.errors.join("\n")}`,
|
|
|
22839
23301
|
if (opts.write) {
|
|
22840
23302
|
try {
|
|
22841
23303
|
const payload = stableStringifyCoverageDocument(document);
|
|
22842
|
-
|
|
23304
|
+
fs41.writeFileSync(outPath, payload, "utf-8");
|
|
22843
23305
|
} catch (e) {
|
|
22844
23306
|
return {
|
|
22845
23307
|
ok: false,
|
|
@@ -22853,11 +23315,11 @@ ${schemaCheck.errors.join("\n")}`,
|
|
|
22853
23315
|
|
|
22854
23316
|
// src/pipelines/remediation/zeroReferenceWorkstationChain.ts
|
|
22855
23317
|
var crypto = __toESM(require("crypto"));
|
|
22856
|
-
var
|
|
23318
|
+
var fs43 = __toESM(require("fs"));
|
|
22857
23319
|
var path40 = __toESM(require("path"));
|
|
22858
23320
|
|
|
22859
23321
|
// src/analysis/zeroReferenceRemediationSchemaValidate.ts
|
|
22860
|
-
var
|
|
23322
|
+
var fs42 = __toESM(require("fs"));
|
|
22861
23323
|
var path39 = __toESM(require("path"));
|
|
22862
23324
|
var import__6 = __toESM(require__());
|
|
22863
23325
|
function stripUtf8Bom5(s) {
|
|
@@ -22879,7 +23341,7 @@ function formatAjvErrors6(errors) {
|
|
|
22879
23341
|
var ajv = new import__6.default({ allErrors: true, strict: false });
|
|
22880
23342
|
function compileSchema(basename17) {
|
|
22881
23343
|
const schemaPath = path39.join(schemasDir(), basename17);
|
|
22882
|
-
const schemaRaw = stripUtf8Bom5(
|
|
23344
|
+
const schemaRaw = stripUtf8Bom5(fs42.readFileSync(schemaPath, "utf-8"));
|
|
22883
23345
|
const schema = JSON.parse(schemaRaw);
|
|
22884
23346
|
return ajv.compile(schema);
|
|
22885
23347
|
}
|
|
@@ -22923,7 +23385,7 @@ var ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS = 5;
|
|
|
22923
23385
|
var ZERO_REF_STAGING_FILE_PREVIEW_MAX_CHARS = 6e3;
|
|
22924
23386
|
function readStagingOutputPreview(outAbs) {
|
|
22925
23387
|
try {
|
|
22926
|
-
const s =
|
|
23388
|
+
const s = fs43.readFileSync(outAbs, "utf-8");
|
|
22927
23389
|
if (s.length <= ZERO_REF_STAGING_FILE_PREVIEW_MAX_CHARS) {
|
|
22928
23390
|
return s;
|
|
22929
23391
|
}
|
|
@@ -23206,14 +23668,14 @@ function readNonReferencedFilesFromRepositoryRoot(repositoryRootAbs) {
|
|
|
23206
23668
|
return { ok: true, paths, ...generatedAt ? { generatedAt } : {} };
|
|
23207
23669
|
}
|
|
23208
23670
|
function readOrInitRoutingDoc(routingAbs, coverageReferenceGeneratedAt) {
|
|
23209
|
-
if (!
|
|
23671
|
+
if (!fs43.existsSync(routingAbs)) {
|
|
23210
23672
|
return {
|
|
23211
23673
|
schemaVersion: ROUTING_SCHEMA_VERSION,
|
|
23212
23674
|
...coverageReferenceGeneratedAt ? { coverageReferenceGeneratedAt } : {},
|
|
23213
23675
|
records: {}
|
|
23214
23676
|
};
|
|
23215
23677
|
}
|
|
23216
|
-
const raw =
|
|
23678
|
+
const raw = fs43.readFileSync(routingAbs, "utf-8");
|
|
23217
23679
|
const data = JSON.parse(raw);
|
|
23218
23680
|
if (!data.records || typeof data.records !== "object") {
|
|
23219
23681
|
return {
|
|
@@ -23225,10 +23687,10 @@ function readOrInitRoutingDoc(routingAbs, coverageReferenceGeneratedAt) {
|
|
|
23225
23687
|
return data;
|
|
23226
23688
|
}
|
|
23227
23689
|
function readOrInitTriageDoc(triageAbs) {
|
|
23228
|
-
if (!
|
|
23690
|
+
if (!fs43.existsSync(triageAbs)) {
|
|
23229
23691
|
return { schemaVersion: TRIAGE_SCHEMA_VERSION, records: {} };
|
|
23230
23692
|
}
|
|
23231
|
-
const raw =
|
|
23693
|
+
const raw = fs43.readFileSync(triageAbs, "utf-8");
|
|
23232
23694
|
const data = JSON.parse(raw);
|
|
23233
23695
|
if (!data.records || typeof data.records !== "object") {
|
|
23234
23696
|
return { schemaVersion: TRIAGE_SCHEMA_VERSION, records: {} };
|
|
@@ -23279,7 +23741,7 @@ function lineCountRepoFile(worktreeRootAbs, relPosix) {
|
|
|
23279
23741
|
const abs = path40.join(worktreeRootAbs, ...relPosix.split("/"));
|
|
23280
23742
|
let buf;
|
|
23281
23743
|
try {
|
|
23282
|
-
buf =
|
|
23744
|
+
buf = fs43.readFileSync(abs);
|
|
23283
23745
|
} catch {
|
|
23284
23746
|
return 1;
|
|
23285
23747
|
}
|
|
@@ -23333,7 +23795,7 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23333
23795
|
const cfg = LIST_MERGE_CFG[input.listKind];
|
|
23334
23796
|
const listPath = path40.join(input.contextDirAbs, cfg.listBasename);
|
|
23335
23797
|
const schemaPath = path40.join(resolveContextListSchemasDir(), cfg.schemaBasename);
|
|
23336
|
-
if (!
|
|
23798
|
+
if (!fs43.existsSync(listPath)) {
|
|
23337
23799
|
return {
|
|
23338
23800
|
ok: false,
|
|
23339
23801
|
message: `${cfg.listBasename} not found \u2014 run coordination step ${LIST_STEP_HINT[input.listKind]} first.`
|
|
@@ -23344,7 +23806,7 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23344
23806
|
return withCoordinationListFileLock(listPath, {}, async () => {
|
|
23345
23807
|
let raw;
|
|
23346
23808
|
try {
|
|
23347
|
-
raw =
|
|
23809
|
+
raw = fs43.readFileSync(listPath, "utf-8");
|
|
23348
23810
|
} catch (e) {
|
|
23349
23811
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
23350
23812
|
}
|
|
@@ -23412,7 +23874,7 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23412
23874
|
});
|
|
23413
23875
|
const tmp = `${listPath}.tmp.${process.pid}`;
|
|
23414
23876
|
try {
|
|
23415
|
-
|
|
23877
|
+
fs43.writeFileSync(tmp, `${JSON.stringify(doc, null, 2)}
|
|
23416
23878
|
`, "utf-8");
|
|
23417
23879
|
} catch (e) {
|
|
23418
23880
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
@@ -23420,13 +23882,13 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23420
23882
|
const v = validateCoordinationListJson(tmp, schemaPath);
|
|
23421
23883
|
if (!v.ok) {
|
|
23422
23884
|
try {
|
|
23423
|
-
|
|
23885
|
+
fs43.unlinkSync(tmp);
|
|
23424
23886
|
} catch {
|
|
23425
23887
|
}
|
|
23426
23888
|
return { ok: false, message: `${cfg.listBasename} validation failed: ${JSON.stringify(v.failure)}` };
|
|
23427
23889
|
}
|
|
23428
23890
|
try {
|
|
23429
|
-
|
|
23891
|
+
fs43.renameSync(tmp, listPath);
|
|
23430
23892
|
} catch (e) {
|
|
23431
23893
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
23432
23894
|
}
|
|
@@ -23436,9 +23898,9 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
23436
23898
|
}
|
|
23437
23899
|
async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, workspaceLabel) {
|
|
23438
23900
|
const outAbs = stagingPathForTarget(contextDirAbs, "classifier", targetFilePathPosix);
|
|
23439
|
-
|
|
23901
|
+
fs43.mkdirSync(path40.dirname(outAbs), { recursive: true });
|
|
23440
23902
|
const runDir = path40.join(common.worktreeRoot, ".opencode", "_run");
|
|
23441
|
-
|
|
23903
|
+
fs43.mkdirSync(runDir, { recursive: true });
|
|
23442
23904
|
const outputBasename = path40.basename(outAbs);
|
|
23443
23905
|
const listTaskDescription = [
|
|
23444
23906
|
`Target file (repo-relative, POSIX): **${targetFilePathPosix}**`,
|
|
@@ -23476,7 +23938,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
|
|
|
23476
23938
|
...repairAppendix ? { repairAppendix } : {}
|
|
23477
23939
|
});
|
|
23478
23940
|
const promptPath = path40.join(runDir, `zero-ref-classify-a${attempt}-${Date.now()}.prompt.txt`);
|
|
23479
|
-
|
|
23941
|
+
fs43.writeFileSync(promptPath, body, "utf-8");
|
|
23480
23942
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
23481
23943
|
promptFile: promptPath,
|
|
23482
23944
|
agentId: ZERO_REF_CLASSIFY_AGENT_STEM,
|
|
@@ -23503,7 +23965,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
|
|
|
23503
23965
|
const canRetry = attempt < ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS - 1;
|
|
23504
23966
|
let st;
|
|
23505
23967
|
try {
|
|
23506
|
-
st =
|
|
23968
|
+
st = fs43.statSync(outAbs);
|
|
23507
23969
|
} catch {
|
|
23508
23970
|
st = void 0;
|
|
23509
23971
|
}
|
|
@@ -23525,7 +23987,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
|
|
|
23525
23987
|
}
|
|
23526
23988
|
let parsed;
|
|
23527
23989
|
try {
|
|
23528
|
-
parsed = JSON.parse(
|
|
23990
|
+
parsed = JSON.parse(fs43.readFileSync(outAbs, "utf-8"));
|
|
23529
23991
|
} catch (e) {
|
|
23530
23992
|
const msg = e instanceof Error ? e.message : String(e);
|
|
23531
23993
|
lastFailureMessage = `Classifier output not valid JSON: ${msg}`;
|
|
@@ -23610,7 +24072,7 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
|
|
|
23610
24072
|
const mdAbs = path40.join(contextDirAbs, mdBasename);
|
|
23611
24073
|
const agentStem = which === "project" ? ZERO_REF_ADD_REF_PROJECT_AGENT_STEM : ZERO_REF_ADD_REF_ARCH_AGENT_STEM;
|
|
23612
24074
|
const runDir = path40.join(common.worktreeRoot, ".opencode", "_run");
|
|
23613
|
-
|
|
24075
|
+
fs43.mkdirSync(runDir, { recursive: true });
|
|
23614
24076
|
const lines = [
|
|
23615
24077
|
`# SRS-30 \u2014 Add reference to ${mdBasename}`,
|
|
23616
24078
|
``,
|
|
@@ -23626,7 +24088,7 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
|
|
|
23626
24088
|
`- Do not remove unrelated content; append or extend the most appropriate section.`
|
|
23627
24089
|
];
|
|
23628
24090
|
const promptPath = path40.join(runDir, `zero-ref-md-${which}-${Date.now()}.prompt.txt`);
|
|
23629
|
-
|
|
24091
|
+
fs43.writeFileSync(promptPath, lines.join("\n"), "utf-8");
|
|
23630
24092
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
23631
24093
|
promptFile: promptPath,
|
|
23632
24094
|
agentId: agentStem,
|
|
@@ -23653,9 +24115,9 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
|
|
|
23653
24115
|
async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathPosix, routingSummary, workspaceLabel, triageScope) {
|
|
23654
24116
|
const meta = TRIAGE_SCOPE_META[triageScope];
|
|
23655
24117
|
const outAbs = stagingPathForTarget(contextDirAbs, "triage", targetFilePathPosix);
|
|
23656
|
-
|
|
24118
|
+
fs43.mkdirSync(path40.dirname(outAbs), { recursive: true });
|
|
23657
24119
|
const runDir = path40.join(common.worktreeRoot, ".opencode", "_run");
|
|
23658
|
-
|
|
24120
|
+
fs43.mkdirSync(runDir, { recursive: true });
|
|
23659
24121
|
const outputBasename = path40.basename(outAbs);
|
|
23660
24122
|
const listTaskDescription = [
|
|
23661
24123
|
`Target file: **${targetFilePathPosix}** (${workspaceLabel})`,
|
|
@@ -23687,7 +24149,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
23687
24149
|
...repairAppendix ? { repairAppendix } : {}
|
|
23688
24150
|
});
|
|
23689
24151
|
const promptPath = path40.join(runDir, `zero-ref-triage-a${attempt}-${Date.now()}.prompt.txt`);
|
|
23690
|
-
|
|
24152
|
+
fs43.writeFileSync(promptPath, body, "utf-8");
|
|
23691
24153
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
23692
24154
|
promptFile: promptPath,
|
|
23693
24155
|
agentId: ZERO_REF_TRIAGE_COORD_AGENT_STEM,
|
|
@@ -23714,7 +24176,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
23714
24176
|
const canRetry = attempt < ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS - 1;
|
|
23715
24177
|
let st;
|
|
23716
24178
|
try {
|
|
23717
|
-
st =
|
|
24179
|
+
st = fs43.statSync(outAbs);
|
|
23718
24180
|
} catch {
|
|
23719
24181
|
st = void 0;
|
|
23720
24182
|
}
|
|
@@ -23736,7 +24198,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
23736
24198
|
}
|
|
23737
24199
|
let parsed;
|
|
23738
24200
|
try {
|
|
23739
|
-
parsed = JSON.parse(
|
|
24201
|
+
parsed = JSON.parse(fs43.readFileSync(outAbs, "utf-8"));
|
|
23740
24202
|
} catch (e) {
|
|
23741
24203
|
const msg = e instanceof Error ? e.message : String(e);
|
|
23742
24204
|
lastFailureMessage = `Triage output not valid JSON: ${msg}`;
|
|
@@ -23792,7 +24254,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
23792
24254
|
return { ok: false, message: lastFailureMessage, stagingPath: outAbs };
|
|
23793
24255
|
}
|
|
23794
24256
|
try {
|
|
23795
|
-
|
|
24257
|
+
fs43.writeFileSync(outAbs, `${JSON.stringify(parsed, null, 2)}
|
|
23796
24258
|
`, "utf-8");
|
|
23797
24259
|
} catch {
|
|
23798
24260
|
}
|
|
@@ -23810,7 +24272,7 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
23810
24272
|
}
|
|
23811
24273
|
let stagingParsed;
|
|
23812
24274
|
try {
|
|
23813
|
-
stagingParsed = JSON.parse(
|
|
24275
|
+
stagingParsed = JSON.parse(fs43.readFileSync(cr.stagingPath, "utf-8"));
|
|
23814
24276
|
} catch (e) {
|
|
23815
24277
|
return { ok: false, message: String(e) };
|
|
23816
24278
|
}
|
|
@@ -23826,8 +24288,8 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
23826
24288
|
if (!s.ok) {
|
|
23827
24289
|
throw new Error(s.errors.join("; "));
|
|
23828
24290
|
}
|
|
23829
|
-
|
|
23830
|
-
|
|
24291
|
+
fs43.mkdirSync(path40.dirname(routingAbs), { recursive: true });
|
|
24292
|
+
fs43.writeFileSync(routingAbs, s.json, "utf-8");
|
|
23831
24293
|
});
|
|
23832
24294
|
const routing = stagingParsed.routing;
|
|
23833
24295
|
const routingSummary = typeof stagingParsed.projectRelationSummary === "string" ? stagingParsed.projectRelationSummary : "";
|
|
@@ -23858,7 +24320,7 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
23858
24320
|
}
|
|
23859
24321
|
let triageParsed;
|
|
23860
24322
|
try {
|
|
23861
|
-
triageParsed = JSON.parse(
|
|
24323
|
+
triageParsed = JSON.parse(fs43.readFileSync(tr.stagingPath, "utf-8"));
|
|
23862
24324
|
} catch (e) {
|
|
23863
24325
|
return { ok: false, message: String(e) };
|
|
23864
24326
|
}
|
|
@@ -23875,8 +24337,8 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
23875
24337
|
if (!s.ok) {
|
|
23876
24338
|
throw new Error(s.errors.join("; "));
|
|
23877
24339
|
}
|
|
23878
|
-
|
|
23879
|
-
|
|
24340
|
+
fs43.mkdirSync(path40.dirname(triageAbs), { recursive: true });
|
|
24341
|
+
fs43.writeFileSync(triageAbs, s.json, "utf-8");
|
|
23880
24342
|
});
|
|
23881
24343
|
const decision = triageParsed.decision;
|
|
23882
24344
|
if (decision === "new_item" || decision === "enrich_existing") {
|
|
@@ -23964,7 +24426,7 @@ async function runRemediationPipelineZeroRefPass(p) {
|
|
|
23964
24426
|
}
|
|
23965
24427
|
|
|
23966
24428
|
// src/pipelines/coverage/coverageExecutionReport.ts
|
|
23967
|
-
var
|
|
24429
|
+
var fs44 = __toESM(require("fs"));
|
|
23968
24430
|
var path41 = __toESM(require("path"));
|
|
23969
24431
|
var REFERENCE_COVERAGE_EXECUTION_REPORT_BASENAME = "reference-coverage-execution-report.md";
|
|
23970
24432
|
function inlineMdText(s) {
|
|
@@ -24061,7 +24523,7 @@ function collectNoActionRowsFromRoutingDoc(doc) {
|
|
|
24061
24523
|
return rows;
|
|
24062
24524
|
}
|
|
24063
24525
|
function readRoutingDocFromDisk(routingAbs) {
|
|
24064
|
-
if (!
|
|
24526
|
+
if (!fs44.existsSync(routingAbs)) {
|
|
24065
24527
|
return {
|
|
24066
24528
|
ok: true,
|
|
24067
24529
|
doc: { schemaVersion: "1", records: {} }
|
|
@@ -24069,7 +24531,7 @@ function readRoutingDocFromDisk(routingAbs) {
|
|
|
24069
24531
|
}
|
|
24070
24532
|
let raw;
|
|
24071
24533
|
try {
|
|
24072
|
-
raw =
|
|
24534
|
+
raw = fs44.readFileSync(routingAbs, "utf-8");
|
|
24073
24535
|
} catch (e) {
|
|
24074
24536
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
24075
24537
|
}
|
|
@@ -24109,20 +24571,20 @@ async function runCoverageExecutionReport(p) {
|
|
|
24109
24571
|
}
|
|
24110
24572
|
let previous;
|
|
24111
24573
|
try {
|
|
24112
|
-
if (
|
|
24113
|
-
previous =
|
|
24574
|
+
if (fs44.existsSync(outAbs)) {
|
|
24575
|
+
previous = fs44.readFileSync(outAbs, "utf-8");
|
|
24114
24576
|
}
|
|
24115
24577
|
} catch {
|
|
24116
24578
|
previous = void 0;
|
|
24117
24579
|
}
|
|
24118
24580
|
try {
|
|
24119
|
-
|
|
24120
|
-
|
|
24581
|
+
fs44.mkdirSync(path41.dirname(outAbs), { recursive: true });
|
|
24582
|
+
fs44.writeFileSync(outAbs, md, "utf-8");
|
|
24121
24583
|
} catch (e) {
|
|
24122
24584
|
const msg = e instanceof Error ? e.message : String(e);
|
|
24123
24585
|
if (previous !== void 0) {
|
|
24124
24586
|
try {
|
|
24125
|
-
|
|
24587
|
+
fs44.writeFileSync(outAbs, previous, "utf-8");
|
|
24126
24588
|
} catch {
|
|
24127
24589
|
}
|
|
24128
24590
|
}
|
|
@@ -24133,7 +24595,7 @@ async function runCoverageExecutionReport(p) {
|
|
|
24133
24595
|
}
|
|
24134
24596
|
|
|
24135
24597
|
// src/gluecharm/minimalGluecharmLayout.ts
|
|
24136
|
-
var
|
|
24598
|
+
var fs45 = __toESM(require("node:fs"));
|
|
24137
24599
|
var path42 = __toESM(require("node:path"));
|
|
24138
24600
|
var MINIMAL_GLUECHARM_RELATIVE_DIRS = [
|
|
24139
24601
|
[".gluecharm", "docs", "srs"],
|
|
@@ -24146,7 +24608,7 @@ function ensureMinimalGluecharmLayoutNode(repoRootAbs) {
|
|
|
24146
24608
|
for (const segments of MINIMAL_GLUECHARM_RELATIVE_DIRS) {
|
|
24147
24609
|
const dir = path42.join(root, ...segments);
|
|
24148
24610
|
try {
|
|
24149
|
-
|
|
24611
|
+
fs45.mkdirSync(dir, { recursive: true });
|
|
24150
24612
|
} catch (e) {
|
|
24151
24613
|
const err = e;
|
|
24152
24614
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -24528,13 +24990,13 @@ function buildFactoryDepsHeadless(input) {
|
|
|
24528
24990
|
},
|
|
24529
24991
|
runPrepareAnalysisWorktree: async (resume) => {
|
|
24530
24992
|
if (resume) {
|
|
24531
|
-
if (adHocWorktree &&
|
|
24993
|
+
if (adHocWorktree && fs46.existsSync(path43.join(adHocWorktree.path, ".git"))) {
|
|
24532
24994
|
return { ok: true };
|
|
24533
24995
|
}
|
|
24534
24996
|
const snap = readAnalysisWorkspaceSnapshot(storageContext);
|
|
24535
24997
|
const wtPath = snap?.adHocWorktreePath?.trim();
|
|
24536
24998
|
const repo = snap?.adHocRepositoryRoot?.trim() || repoRoot;
|
|
24537
|
-
if (wtPath &&
|
|
24999
|
+
if (wtPath && fs46.existsSync(path43.join(wtPath, ".git"))) {
|
|
24538
25000
|
adHocWorktree = attachWorktreeHandle(wtPath, repo);
|
|
24539
25001
|
macroSourceBranch = snap?.adHocSourceBranchAtCreation;
|
|
24540
25002
|
macroFinalize = () => {
|
|
@@ -24759,7 +25221,7 @@ function stderrLinesForFactoryFailures(failures, exitCode) {
|
|
|
24759
25221
|
var path48 = __toESM(require("node:path"));
|
|
24760
25222
|
|
|
24761
25223
|
// src/factory/updateContext/updateContextBaseline.ts
|
|
24762
|
-
var
|
|
25224
|
+
var fs47 = __toESM(require("node:fs"));
|
|
24763
25225
|
var path44 = __toESM(require("node:path"));
|
|
24764
25226
|
function isValidIso(s) {
|
|
24765
25227
|
const t = Date.parse(s);
|
|
@@ -24770,7 +25232,7 @@ function maxMtimeRegularFilesUnderDir(dirAbs) {
|
|
|
24770
25232
|
const walk = (d) => {
|
|
24771
25233
|
let entries;
|
|
24772
25234
|
try {
|
|
24773
|
-
entries =
|
|
25235
|
+
entries = fs47.readdirSync(d, { withFileTypes: true });
|
|
24774
25236
|
} catch {
|
|
24775
25237
|
return;
|
|
24776
25238
|
}
|
|
@@ -24780,7 +25242,7 @@ function maxMtimeRegularFilesUnderDir(dirAbs) {
|
|
|
24780
25242
|
walk(p);
|
|
24781
25243
|
} else if (e.isFile()) {
|
|
24782
25244
|
try {
|
|
24783
|
-
const st =
|
|
25245
|
+
const st = fs47.statSync(p);
|
|
24784
25246
|
const m = st.mtimeMs;
|
|
24785
25247
|
if (best === null || m > best) {
|
|
24786
25248
|
best = m;
|
|
@@ -24802,7 +25264,7 @@ function resolveUpdateContextBaseline(repoRootAbs, repoConfig) {
|
|
|
24802
25264
|
return { baselineIsoUtc: new Date(last).toISOString(), source: "lastRunAt" };
|
|
24803
25265
|
}
|
|
24804
25266
|
const ctxDir = path44.join(repoRootAbs, ".gluecharm", "context");
|
|
24805
|
-
if (!
|
|
25267
|
+
if (!fs47.existsSync(ctxDir)) {
|
|
24806
25268
|
return null;
|
|
24807
25269
|
}
|
|
24808
25270
|
const maxMs = maxMtimeRegularFilesUnderDir(ctxDir);
|
|
@@ -24824,12 +25286,12 @@ function persistUpdateContextLastRunAt(repoRootAbs, isoUtc) {
|
|
|
24824
25286
|
}
|
|
24825
25287
|
|
|
24826
25288
|
// src/factory/updateContext/updateContextGitWindow.ts
|
|
24827
|
-
var
|
|
24828
|
-
var
|
|
25289
|
+
var import_node_child_process3 = require("node:child_process");
|
|
25290
|
+
var fs48 = __toESM(require("node:fs"));
|
|
24829
25291
|
var path45 = __toESM(require("node:path"));
|
|
24830
25292
|
var GIT_ENV = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
24831
25293
|
function gitLines(repoRootAbs, args) {
|
|
24832
|
-
const r = (0,
|
|
25294
|
+
const r = (0, import_node_child_process3.execFileSync)("git", ["-c", "core.quotepath=false", ...args], {
|
|
24833
25295
|
cwd: repoRootAbs,
|
|
24834
25296
|
encoding: "utf-8",
|
|
24835
25297
|
env: GIT_ENV,
|
|
@@ -24851,7 +25313,7 @@ function parseGitLogIso(line) {
|
|
|
24851
25313
|
}
|
|
24852
25314
|
function discoverCommitWindowAndTouchedPaths(repoRootAbs, baselineIsoUtc) {
|
|
24853
25315
|
const root = path45.resolve(repoRootAbs);
|
|
24854
|
-
if (!
|
|
25316
|
+
if (!fs48.existsSync(path45.join(root, ".git"))) {
|
|
24855
25317
|
return { ok: false, error: "Not a git repository (missing .git)." };
|
|
24856
25318
|
}
|
|
24857
25319
|
const baselineMs = Date.parse(baselineIsoUtc);
|
|
@@ -24916,7 +25378,7 @@ function filterPathsExistingInWorktree(worktreeRootAbs, pathsPosix) {
|
|
|
24916
25378
|
const rel = p.replace(/\\/g, "/");
|
|
24917
25379
|
const abs = path45.join(root, ...rel.split("/"));
|
|
24918
25380
|
try {
|
|
24919
|
-
if (
|
|
25381
|
+
if (fs48.existsSync(abs) && fs48.statSync(abs).isFile()) {
|
|
24920
25382
|
out.push(rel);
|
|
24921
25383
|
}
|
|
24922
25384
|
} catch {
|
|
@@ -24926,7 +25388,7 @@ function filterPathsExistingInWorktree(worktreeRootAbs, pathsPosix) {
|
|
|
24926
25388
|
}
|
|
24927
25389
|
|
|
24928
25390
|
// src/factory/updateContext/updateContextReport.ts
|
|
24929
|
-
var
|
|
25391
|
+
var fs49 = __toESM(require("node:fs"));
|
|
24930
25392
|
var path46 = __toESM(require("node:path"));
|
|
24931
25393
|
var CHANGES_SINCE_DATE_BASENAME = "changes-since-date.md";
|
|
24932
25394
|
function renderChangesSinceDateMarkdown(p) {
|
|
@@ -24968,9 +25430,9 @@ function renderChangesSinceDateMarkdown(p) {
|
|
|
24968
25430
|
}
|
|
24969
25431
|
function writeChangesSinceDateReport(contextDirAbs, body) {
|
|
24970
25432
|
try {
|
|
24971
|
-
|
|
25433
|
+
fs49.mkdirSync(contextDirAbs, { recursive: true });
|
|
24972
25434
|
const target = path46.join(contextDirAbs, CHANGES_SINCE_DATE_BASENAME);
|
|
24973
|
-
|
|
25435
|
+
fs49.writeFileSync(target, body, "utf-8");
|
|
24974
25436
|
return { ok: true };
|
|
24975
25437
|
} catch (e) {
|
|
24976
25438
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
@@ -24978,13 +25440,13 @@ function writeChangesSinceDateReport(contextDirAbs, body) {
|
|
|
24978
25440
|
}
|
|
24979
25441
|
|
|
24980
25442
|
// src/factory/updateContext/updateContextSeedCheck.ts
|
|
24981
|
-
var
|
|
25443
|
+
var fs50 = __toESM(require("node:fs"));
|
|
24982
25444
|
var path47 = __toESM(require("node:path"));
|
|
24983
25445
|
var INDEX_BASENAME = "index-application-context.json";
|
|
24984
25446
|
var CHANGES_REPORT = "changes-since-date.md";
|
|
24985
25447
|
function tryParseJsonFile(abs) {
|
|
24986
25448
|
try {
|
|
24987
|
-
const raw =
|
|
25449
|
+
const raw = fs50.readFileSync(abs, "utf-8");
|
|
24988
25450
|
JSON.parse(raw);
|
|
24989
25451
|
return true;
|
|
24990
25452
|
} catch {
|
|
@@ -24992,16 +25454,16 @@ function tryParseJsonFile(abs) {
|
|
|
24992
25454
|
}
|
|
24993
25455
|
}
|
|
24994
25456
|
function isWorktreeContextSeeded(contextDirAbs) {
|
|
24995
|
-
if (!
|
|
25457
|
+
if (!fs50.existsSync(contextDirAbs)) {
|
|
24996
25458
|
return false;
|
|
24997
25459
|
}
|
|
24998
25460
|
const indexAbs = path47.join(contextDirAbs, INDEX_BASENAME);
|
|
24999
|
-
if (
|
|
25461
|
+
if (fs50.existsSync(indexAbs) && fs50.statSync(indexAbs).isFile() && tryParseJsonFile(indexAbs)) {
|
|
25000
25462
|
return true;
|
|
25001
25463
|
}
|
|
25002
25464
|
let names;
|
|
25003
25465
|
try {
|
|
25004
|
-
names =
|
|
25466
|
+
names = fs50.readdirSync(contextDirAbs);
|
|
25005
25467
|
} catch {
|
|
25006
25468
|
return false;
|
|
25007
25469
|
}
|
|
@@ -25015,7 +25477,7 @@ function isWorktreeContextSeeded(contextDirAbs) {
|
|
|
25015
25477
|
}
|
|
25016
25478
|
const p = path47.join(contextDirAbs, name);
|
|
25017
25479
|
try {
|
|
25018
|
-
if (
|
|
25480
|
+
if (fs50.statSync(p).isFile()) {
|
|
25019
25481
|
distinct.add(name);
|
|
25020
25482
|
}
|
|
25021
25483
|
} catch {
|
|
@@ -25317,11 +25779,11 @@ async function runUpdateContextFactory(deps) {
|
|
|
25317
25779
|
}
|
|
25318
25780
|
|
|
25319
25781
|
// src/factory/contextDrift/runContextDriftFactory.ts
|
|
25320
|
-
var
|
|
25782
|
+
var fs56 = __toESM(require("node:fs"));
|
|
25321
25783
|
var path53 = __toESM(require("node:path"));
|
|
25322
25784
|
|
|
25323
25785
|
// src/factory/contextDrift/contextDriftManifest.ts
|
|
25324
|
-
var
|
|
25786
|
+
var fs51 = __toESM(require("node:fs"));
|
|
25325
25787
|
var path49 = __toESM(require("node:path"));
|
|
25326
25788
|
var MAX_REFERENCE_BYTES = 256 * 1024;
|
|
25327
25789
|
var MAX_EVIDENCE_FILES = 300;
|
|
@@ -25330,7 +25792,7 @@ var MAX_EXCERPT = 4e3;
|
|
|
25330
25792
|
function readFileLimited(abs, maxBytes) {
|
|
25331
25793
|
let buf;
|
|
25332
25794
|
try {
|
|
25333
|
-
buf =
|
|
25795
|
+
buf = fs51.readFileSync(abs);
|
|
25334
25796
|
} catch {
|
|
25335
25797
|
return { text: "", truncated: false };
|
|
25336
25798
|
}
|
|
@@ -25343,14 +25805,14 @@ function collectEvidencePaths(repoRoot) {
|
|
|
25343
25805
|
const roots = ["src", "test", "tests", "packages", ".gluecharm", "scripts"];
|
|
25344
25806
|
for (const rel of roots) {
|
|
25345
25807
|
const abs = path49.join(repoRoot, rel);
|
|
25346
|
-
if (!
|
|
25808
|
+
if (!fs51.existsSync(abs)) {
|
|
25347
25809
|
continue;
|
|
25348
25810
|
}
|
|
25349
25811
|
walkFiles(abs, repoRoot, out, 0);
|
|
25350
25812
|
}
|
|
25351
25813
|
for (const leaf of ["package.json", "tsconfig.json"]) {
|
|
25352
25814
|
const abs = path49.join(repoRoot, leaf);
|
|
25353
|
-
if (
|
|
25815
|
+
if (fs51.existsSync(abs) && fs51.statSync(abs).isFile()) {
|
|
25354
25816
|
const r = path49.relative(repoRoot, abs).split(path49.sep).join("/");
|
|
25355
25817
|
out.push(r);
|
|
25356
25818
|
}
|
|
@@ -25368,7 +25830,7 @@ function walkFiles(dir, repoRoot, out, depth) {
|
|
|
25368
25830
|
}
|
|
25369
25831
|
let entries;
|
|
25370
25832
|
try {
|
|
25371
|
-
entries =
|
|
25833
|
+
entries = fs51.readdirSync(dir, { withFileTypes: true });
|
|
25372
25834
|
} catch {
|
|
25373
25835
|
return;
|
|
25374
25836
|
}
|
|
@@ -25405,7 +25867,7 @@ function buildComparisonManifest(args) {
|
|
|
25405
25867
|
const evidenceFiles = [];
|
|
25406
25868
|
for (const rel of evidencePathsTrimmed) {
|
|
25407
25869
|
const abs = path49.join(args.worktreeRoot, ...rel.split("/"));
|
|
25408
|
-
const st =
|
|
25870
|
+
const st = fs51.existsSync(abs) ? fs51.statSync(abs) : null;
|
|
25409
25871
|
const size = st && st.isFile() ? st.size : 0;
|
|
25410
25872
|
const { text, truncated } = readFileLimited(abs, MAX_EVIDENCE_READ);
|
|
25411
25873
|
const excerpt = truncated ? `${text.slice(0, MAX_EXCERPT)}
|
|
@@ -25427,7 +25889,7 @@ function buildComparisonManifest(args) {
|
|
|
25427
25889
|
}
|
|
25428
25890
|
|
|
25429
25891
|
// src/factory/contextDrift/contextDriftAgent.ts
|
|
25430
|
-
var
|
|
25892
|
+
var fs52 = __toESM(require("node:fs"));
|
|
25431
25893
|
var path50 = __toESM(require("node:path"));
|
|
25432
25894
|
|
|
25433
25895
|
// src/factory/contextDrift/contextDriftPayload.ts
|
|
@@ -25574,16 +26036,16 @@ function buildDriftPrompt(args) {
|
|
|
25574
26036
|
}
|
|
25575
26037
|
async function runDriftComparisonOpenCode(args) {
|
|
25576
26038
|
const runDir = path50.join(args.worktreeRoot, ".opencode", "_run");
|
|
25577
|
-
|
|
26039
|
+
fs52.mkdirSync(runDir, { recursive: true });
|
|
25578
26040
|
const manifestPath = path50.join(runDir, "context-drift-manifest.json");
|
|
25579
26041
|
const outputPath = path50.join(runDir, "context-drift-payload.json");
|
|
25580
|
-
|
|
26042
|
+
fs52.writeFileSync(manifestPath, `${JSON.stringify(args.manifestObject, null, 2)}
|
|
25581
26043
|
`, "utf8");
|
|
25582
|
-
if (
|
|
25583
|
-
|
|
26044
|
+
if (fs52.existsSync(outputPath)) {
|
|
26045
|
+
fs52.unlinkSync(outputPath);
|
|
25584
26046
|
}
|
|
25585
26047
|
const promptPath = path50.join(runDir, `context-drift-${Date.now()}.prompt.txt`);
|
|
25586
|
-
|
|
26048
|
+
fs52.writeFileSync(
|
|
25587
26049
|
promptPath,
|
|
25588
26050
|
buildDriftPrompt({
|
|
25589
26051
|
worktreeRoot: args.worktreeRoot,
|
|
@@ -25625,7 +26087,7 @@ async function runDriftComparisonOpenCode(args) {
|
|
|
25625
26087
|
}
|
|
25626
26088
|
let raw;
|
|
25627
26089
|
try {
|
|
25628
|
-
const txt =
|
|
26090
|
+
const txt = fs52.readFileSync(outputPath, "utf8");
|
|
25629
26091
|
raw = JSON.parse(txt);
|
|
25630
26092
|
} catch (e) {
|
|
25631
26093
|
return {
|
|
@@ -25642,7 +26104,7 @@ async function runDriftComparisonOpenCode(args) {
|
|
|
25642
26104
|
|
|
25643
26105
|
// src/factory/contextDrift/contextDriftPaths.ts
|
|
25644
26106
|
var crypto2 = __toESM(require("node:crypto"));
|
|
25645
|
-
var
|
|
26107
|
+
var fs53 = __toESM(require("node:fs"));
|
|
25646
26108
|
var path51 = __toESM(require("node:path"));
|
|
25647
26109
|
var DRIFT_CONTEXT_SUBDIR = path51.join(".gluecharm", "context", "drift");
|
|
25648
26110
|
function sanitizeSlug(raw) {
|
|
@@ -25681,7 +26143,7 @@ function maybeDedupeSlug(slug, referenceRelPosix) {
|
|
|
25681
26143
|
function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
25682
26144
|
let st;
|
|
25683
26145
|
try {
|
|
25684
|
-
st =
|
|
26146
|
+
st = fs53.statSync(referenceAbsInWorktree);
|
|
25685
26147
|
} catch {
|
|
25686
26148
|
return { ok: false, error: `Reference path not found in analysis worktree: ${referenceAbsInWorktree}` };
|
|
25687
26149
|
}
|
|
@@ -25702,7 +26164,7 @@ function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
|
25702
26164
|
}
|
|
25703
26165
|
let entries;
|
|
25704
26166
|
try {
|
|
25705
|
-
entries =
|
|
26167
|
+
entries = fs53.readdirSync(dir, { withFileTypes: true });
|
|
25706
26168
|
} catch {
|
|
25707
26169
|
return;
|
|
25708
26170
|
}
|
|
@@ -25727,7 +26189,7 @@ function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
|
25727
26189
|
}
|
|
25728
26190
|
function pickReferenceRootDocument(args) {
|
|
25729
26191
|
if (args.indexOverrideAbs) {
|
|
25730
|
-
if (!
|
|
26192
|
+
if (!fs53.existsSync(args.indexOverrideAbs) || !args.indexOverrideAbs.endsWith(".md")) {
|
|
25731
26193
|
return { ok: false, error: "--index must point to an existing .md file under the repo." };
|
|
25732
26194
|
}
|
|
25733
26195
|
return { ok: true, path: args.indexOverrideAbs };
|
|
@@ -25738,7 +26200,7 @@ function pickReferenceRootDocument(args) {
|
|
|
25738
26200
|
const dir = args.referenceAbsInWorktree;
|
|
25739
26201
|
for (const name of ["index.md", "README.md"]) {
|
|
25740
26202
|
const p = path51.join(dir, name);
|
|
25741
|
-
if (
|
|
26203
|
+
if (fs53.existsSync(p) && fs53.statSync(p).isFile()) {
|
|
25742
26204
|
return { ok: true, path: p };
|
|
25743
26205
|
}
|
|
25744
26206
|
}
|
|
@@ -25755,13 +26217,13 @@ function toPosixPath(p) {
|
|
|
25755
26217
|
}
|
|
25756
26218
|
|
|
25757
26219
|
// src/factory/contextDrift/contextDriftIndex.ts
|
|
25758
|
-
var
|
|
26220
|
+
var fs54 = __toESM(require("node:fs"));
|
|
25759
26221
|
var START = "<!-- easyspecs-drift-links:start -->";
|
|
25760
26222
|
var END = "<!-- easyspecs-drift-links:end -->";
|
|
25761
26223
|
function patchReferenceIndexWithDriftLink(args) {
|
|
25762
26224
|
let body;
|
|
25763
26225
|
try {
|
|
25764
|
-
body =
|
|
26226
|
+
body = fs54.readFileSync(args.referenceRootAbsolute, "utf8");
|
|
25765
26227
|
} catch (e) {
|
|
25766
26228
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
25767
26229
|
}
|
|
@@ -25782,7 +26244,7 @@ ${block}
|
|
|
25782
26244
|
`;
|
|
25783
26245
|
}
|
|
25784
26246
|
try {
|
|
25785
|
-
|
|
26247
|
+
fs54.writeFileSync(args.referenceRootAbsolute, next, "utf8");
|
|
25786
26248
|
} catch (e) {
|
|
25787
26249
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
25788
26250
|
}
|
|
@@ -25793,13 +26255,13 @@ function escapeRe(s) {
|
|
|
25793
26255
|
}
|
|
25794
26256
|
|
|
25795
26257
|
// src/factory/contextDrift/contextDriftPromote.ts
|
|
25796
|
-
var
|
|
26258
|
+
var fs55 = __toESM(require("node:fs"));
|
|
25797
26259
|
var path52 = __toESM(require("node:path"));
|
|
25798
26260
|
function copyWorktreeFileToWorkspace(args) {
|
|
25799
26261
|
const src = path52.join(args.worktreeRoot, ...args.relativePosix.split("/"));
|
|
25800
26262
|
const dest = path52.join(args.workspaceRoot, ...args.relativePosix.split("/"));
|
|
25801
|
-
|
|
25802
|
-
|
|
26263
|
+
fs55.mkdirSync(path52.dirname(dest), { recursive: true });
|
|
26264
|
+
fs55.copyFileSync(src, dest);
|
|
25803
26265
|
}
|
|
25804
26266
|
|
|
25805
26267
|
// src/factory/contextDrift/runContextDriftFactory.ts
|
|
@@ -25818,7 +26280,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25818
26280
|
};
|
|
25819
26281
|
}
|
|
25820
26282
|
const refAbsWorkspace = resolved.abs;
|
|
25821
|
-
if (!
|
|
26283
|
+
if (!fs56.existsSync(refAbsWorkspace)) {
|
|
25822
26284
|
return {
|
|
25823
26285
|
exitOk: false,
|
|
25824
26286
|
ok: false,
|
|
@@ -25831,7 +26293,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25831
26293
|
let indexOverrideAbsWorkspace;
|
|
25832
26294
|
if (deps.indexOverrideArg?.trim()) {
|
|
25833
26295
|
const ir = resolveInsideRepo(deps.repoRootAbs, deps.indexOverrideArg.trim());
|
|
25834
|
-
if (!ir.ok || !
|
|
26296
|
+
if (!ir.ok || !fs56.existsSync(ir.abs)) {
|
|
25835
26297
|
return {
|
|
25836
26298
|
exitOk: false,
|
|
25837
26299
|
ok: false,
|
|
@@ -25849,7 +26311,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25849
26311
|
ok: true,
|
|
25850
26312
|
code: "DRY_RUN",
|
|
25851
26313
|
...baseMeta,
|
|
25852
|
-
referenceRootDocument: toPosixPath(path53.relative(deps.repoRootAbs, refAbsWorkspace)) + (
|
|
26314
|
+
referenceRootDocument: toPosixPath(path53.relative(deps.repoRootAbs, refAbsWorkspace)) + (fs56.statSync(refAbsWorkspace).isDirectory() ? "/" : ""),
|
|
25853
26315
|
driftReportPath: null,
|
|
25854
26316
|
analysisWorktreeRoot: "",
|
|
25855
26317
|
promoted: false,
|
|
@@ -25918,7 +26380,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25918
26380
|
}
|
|
25919
26381
|
const indexWt = indexOverrideAbsWorkspace ? path53.join(wt, ...path53.relative(deps.repoRootAbs, indexOverrideAbsWorkspace).split(path53.sep)) : void 0;
|
|
25920
26382
|
const rootPick = pickReferenceRootDocument({
|
|
25921
|
-
referencePathIsFile:
|
|
26383
|
+
referencePathIsFile: fs56.statSync(refAbsWt).isFile(),
|
|
25922
26384
|
referenceAbsInWorktree: refAbsWt,
|
|
25923
26385
|
bundleFiles: bundle.bundleFiles,
|
|
25924
26386
|
indexOverrideAbs: indexWt
|
|
@@ -25945,7 +26407,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25945
26407
|
slug = maybeDedupeSlug(slug, refRel);
|
|
25946
26408
|
const driftBase = driftFilename(slug, runDate);
|
|
25947
26409
|
const driftDirWt = path53.join(wt, DRIFT_CONTEXT_SUBDIR);
|
|
25948
|
-
|
|
26410
|
+
fs56.mkdirSync(driftDirWt, { recursive: true });
|
|
25949
26411
|
const driftAbsWt = path53.join(driftDirWt, driftBase);
|
|
25950
26412
|
let payload;
|
|
25951
26413
|
if (deps.testOnlyFixturePayload) {
|
|
@@ -25982,7 +26444,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25982
26444
|
manifestTruncation: manifest.truncation
|
|
25983
26445
|
});
|
|
25984
26446
|
try {
|
|
25985
|
-
|
|
26447
|
+
fs56.writeFileSync(driftAbsWt, md, "utf8");
|
|
25986
26448
|
} catch (e) {
|
|
25987
26449
|
finalizeWt?.();
|
|
25988
26450
|
return {
|
|
@@ -26061,7 +26523,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26061
26523
|
}
|
|
26062
26524
|
|
|
26063
26525
|
// src/analysis/coordinationDuplicatesDiagnosis.ts
|
|
26064
|
-
var
|
|
26526
|
+
var fs57 = __toESM(require("fs"));
|
|
26065
26527
|
var path54 = __toESM(require("path"));
|
|
26066
26528
|
var import__7 = __toESM(require__());
|
|
26067
26529
|
var COORDINATION_DUPLICATES_REPORT_BASENAME = "coordination-duplicates-report.json";
|
|
@@ -26098,11 +26560,11 @@ function looksLikeCoordinationDetailMarkdownBasename(basename17) {
|
|
|
26098
26560
|
}
|
|
26099
26561
|
function loadRawFeatureRows(contextDirAbs) {
|
|
26100
26562
|
const p = path54.join(contextDirAbs, "features-list.json");
|
|
26101
|
-
if (!
|
|
26563
|
+
if (!fs57.existsSync(p)) {
|
|
26102
26564
|
return [];
|
|
26103
26565
|
}
|
|
26104
26566
|
try {
|
|
26105
|
-
const raw = stripUtf8Bom6(
|
|
26567
|
+
const raw = stripUtf8Bom6(fs57.readFileSync(p, "utf-8"));
|
|
26106
26568
|
const doc = JSON.parse(raw);
|
|
26107
26569
|
return Array.isArray(doc.features) ? doc.features : [];
|
|
26108
26570
|
} catch {
|
|
@@ -26137,7 +26599,7 @@ function findOrphanCoordinationMarkdown(contextDirAbs) {
|
|
|
26137
26599
|
const featureRows = loadRawFeatureRows(contextDirAbs);
|
|
26138
26600
|
let dirents;
|
|
26139
26601
|
try {
|
|
26140
|
-
dirents =
|
|
26602
|
+
dirents = fs57.readdirSync(contextDirAbs, { withFileTypes: true });
|
|
26141
26603
|
} catch {
|
|
26142
26604
|
return [];
|
|
26143
26605
|
}
|
|
@@ -26391,13 +26853,13 @@ function buildCoordinationDuplicatesReport(input) {
|
|
|
26391
26853
|
const duplicateGroups = [];
|
|
26392
26854
|
for (const entry of COORDINATION_LIST_SCAN_ENTRIES) {
|
|
26393
26855
|
const filePath = path54.join(input.contextDirAbsolute, entry.basename);
|
|
26394
|
-
if (!
|
|
26856
|
+
if (!fs57.existsSync(filePath)) {
|
|
26395
26857
|
lists.push({ basename: entry.basename, status: "missing" });
|
|
26396
26858
|
continue;
|
|
26397
26859
|
}
|
|
26398
26860
|
let raw;
|
|
26399
26861
|
try {
|
|
26400
|
-
raw = stripUtf8Bom6(
|
|
26862
|
+
raw = stripUtf8Bom6(fs57.readFileSync(filePath, "utf-8"));
|
|
26401
26863
|
} catch (e) {
|
|
26402
26864
|
lists.push({
|
|
26403
26865
|
basename: entry.basename,
|
|
@@ -26446,7 +26908,7 @@ function validateReportData(data) {
|
|
|
26446
26908
|
if (!validateReportCompiled) {
|
|
26447
26909
|
const ajv2 = new import__7.default({ allErrors: true, strict: false });
|
|
26448
26910
|
const schemaPath = path54.join(resolveContextListSchemasDir(), "coordination-duplicates-report.schema.json");
|
|
26449
|
-
const schemaRaw = stripUtf8Bom6(
|
|
26911
|
+
const schemaRaw = stripUtf8Bom6(fs57.readFileSync(schemaPath, "utf-8"));
|
|
26450
26912
|
validateReportCompiled = ajv2.compile(JSON.parse(schemaRaw));
|
|
26451
26913
|
}
|
|
26452
26914
|
if (validateReportCompiled(data)) {
|
|
@@ -26469,15 +26931,15 @@ function runCoordinationDuplicatesDiagnosis(input) {
|
|
|
26469
26931
|
`;
|
|
26470
26932
|
const tmp = `${outPath}.tmp.${process.pid}`;
|
|
26471
26933
|
try {
|
|
26472
|
-
|
|
26934
|
+
fs57.writeFileSync(tmp, payload, "utf-8");
|
|
26473
26935
|
} catch (e) {
|
|
26474
26936
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
26475
26937
|
}
|
|
26476
26938
|
try {
|
|
26477
|
-
|
|
26939
|
+
fs57.renameSync(tmp, outPath);
|
|
26478
26940
|
} catch (e) {
|
|
26479
26941
|
try {
|
|
26480
|
-
|
|
26942
|
+
fs57.unlinkSync(tmp);
|
|
26481
26943
|
} catch {
|
|
26482
26944
|
}
|
|
26483
26945
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
@@ -26511,7 +26973,7 @@ function runCoordinationDuplicatesDiagnosis(input) {
|
|
|
26511
26973
|
}
|
|
26512
26974
|
|
|
26513
26975
|
// src/pipelines/download/downloadPipeline.ts
|
|
26514
|
-
var
|
|
26976
|
+
var fs58 = __toESM(require("node:fs"));
|
|
26515
26977
|
var path55 = __toESM(require("node:path"));
|
|
26516
26978
|
var SRS_DISCOVERY_BATCH_GET_CHUNK_SIZE = 200;
|
|
26517
26979
|
function isRecord7(v) {
|
|
@@ -26617,19 +27079,19 @@ function chunkIds(ids, size) {
|
|
|
26617
27079
|
return out;
|
|
26618
27080
|
}
|
|
26619
27081
|
function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
26620
|
-
if (!
|
|
27082
|
+
if (!fs58.existsSync(contextDirAbs) || !fs58.statSync(contextDirAbs).isDirectory()) {
|
|
26621
27083
|
return { filesRemoved: 0 };
|
|
26622
27084
|
}
|
|
26623
27085
|
const preserveAbs = path55.resolve(contextDirAbs, UPLOAD_TARGET_FILENAME);
|
|
26624
27086
|
const preserveSet = /* @__PURE__ */ new Set();
|
|
26625
|
-
if (
|
|
27087
|
+
if (fs58.existsSync(preserveAbs) && fs58.statSync(preserveAbs).isFile()) {
|
|
26626
27088
|
preserveSet.add(preserveAbs);
|
|
26627
27089
|
}
|
|
26628
27090
|
let filesRemoved = 0;
|
|
26629
27091
|
const walkRm = (dir) => {
|
|
26630
27092
|
let entries;
|
|
26631
27093
|
try {
|
|
26632
|
-
entries =
|
|
27094
|
+
entries = fs58.readdirSync(dir, { withFileTypes: true });
|
|
26633
27095
|
} catch {
|
|
26634
27096
|
return;
|
|
26635
27097
|
}
|
|
@@ -26638,7 +27100,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
|
26638
27100
|
if (e.isDirectory()) {
|
|
26639
27101
|
walkRm(full);
|
|
26640
27102
|
try {
|
|
26641
|
-
|
|
27103
|
+
fs58.rmdirSync(full);
|
|
26642
27104
|
} catch {
|
|
26643
27105
|
}
|
|
26644
27106
|
} else if (e.isFile()) {
|
|
@@ -26647,7 +27109,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
|
26647
27109
|
continue;
|
|
26648
27110
|
}
|
|
26649
27111
|
try {
|
|
26650
|
-
|
|
27112
|
+
fs58.unlinkSync(abs);
|
|
26651
27113
|
filesRemoved += 1;
|
|
26652
27114
|
} catch {
|
|
26653
27115
|
}
|
|
@@ -26726,15 +27188,15 @@ async function runDownloadPipeline(opts) {
|
|
|
26726
27188
|
failed.push({ id, name, message: "Unsafe or invalid name for local path." });
|
|
26727
27189
|
continue;
|
|
26728
27190
|
}
|
|
26729
|
-
|
|
26730
|
-
const exists =
|
|
27191
|
+
fs58.mkdirSync(path55.dirname(outAbs), { recursive: true });
|
|
27192
|
+
const exists = fs58.existsSync(outAbs);
|
|
26731
27193
|
if (exists && !opts.force && !opts.replaceFromCloud) {
|
|
26732
27194
|
skipped += 1;
|
|
26733
27195
|
log?.(`[pipeline:download] skip existing ${name} (use --force to overwrite).`);
|
|
26734
27196
|
continue;
|
|
26735
27197
|
}
|
|
26736
27198
|
try {
|
|
26737
|
-
|
|
27199
|
+
fs58.writeFileSync(outAbs, bodyText, "utf8");
|
|
26738
27200
|
downloaded += 1;
|
|
26739
27201
|
succeededIds[outAbs] = id;
|
|
26740
27202
|
} catch (e) {
|
|
@@ -26905,11 +27367,11 @@ function createAuthenticatedRequestJson(deps) {
|
|
|
26905
27367
|
}
|
|
26906
27368
|
|
|
26907
27369
|
// src/cli/cliSession.ts
|
|
26908
|
-
var
|
|
26909
|
-
var
|
|
27370
|
+
var fs59 = __toESM(require("node:fs"));
|
|
27371
|
+
var os6 = __toESM(require("node:os"));
|
|
26910
27372
|
var path56 = __toESM(require("node:path"));
|
|
26911
27373
|
function defaultSessionPath() {
|
|
26912
|
-
return path56.join(
|
|
27374
|
+
return path56.join(os6.homedir(), ".easyspecs", "cli-session.json");
|
|
26913
27375
|
}
|
|
26914
27376
|
var configSessionPath;
|
|
26915
27377
|
function setCliSessionPathFromConfig(absPath) {
|
|
@@ -26950,10 +27412,10 @@ function effectiveCliSessionPath() {
|
|
|
26950
27412
|
function readCliSession() {
|
|
26951
27413
|
const p = effectiveCliSessionPath();
|
|
26952
27414
|
try {
|
|
26953
|
-
if (!
|
|
27415
|
+
if (!fs59.existsSync(p)) {
|
|
26954
27416
|
return void 0;
|
|
26955
27417
|
}
|
|
26956
|
-
const j = JSON.parse(
|
|
27418
|
+
const j = JSON.parse(fs59.readFileSync(p, "utf8"));
|
|
26957
27419
|
const apiBaseUrl = typeof j.apiBaseUrl === "string" ? j.apiBaseUrl.trim() : "";
|
|
26958
27420
|
const accessToken = typeof j.accessToken === "string" ? j.accessToken : "";
|
|
26959
27421
|
const refreshToken = typeof j.refreshToken === "string" ? j.refreshToken : "";
|
|
@@ -26967,20 +27429,20 @@ function readCliSession() {
|
|
|
26967
27429
|
}
|
|
26968
27430
|
function writeCliSession(s) {
|
|
26969
27431
|
const p = effectiveCliSessionPath();
|
|
26970
|
-
|
|
26971
|
-
|
|
27432
|
+
fs59.mkdirSync(path56.dirname(p), { recursive: true });
|
|
27433
|
+
fs59.writeFileSync(p, `${JSON.stringify(s, null, 2)}
|
|
26972
27434
|
`, "utf8");
|
|
26973
27435
|
}
|
|
26974
27436
|
function clearCliSession() {
|
|
26975
27437
|
const p = effectiveCliSessionPath();
|
|
26976
27438
|
try {
|
|
26977
|
-
|
|
27439
|
+
fs59.unlinkSync(p);
|
|
26978
27440
|
} catch {
|
|
26979
27441
|
}
|
|
26980
27442
|
}
|
|
26981
27443
|
|
|
26982
27444
|
// src/analysis/acePendingTraces.ts
|
|
26983
|
-
var
|
|
27445
|
+
var fs60 = __toESM(require("fs"));
|
|
26984
27446
|
var path57 = __toESM(require("path"));
|
|
26985
27447
|
function normalizeAceTraceRelativePath(rel) {
|
|
26986
27448
|
return rel.split(/[/\\]/).join("/");
|
|
@@ -26988,12 +27450,12 @@ function normalizeAceTraceRelativePath(rel) {
|
|
|
26988
27450
|
function readCompletedTraceRelativePaths(contextDir2) {
|
|
26989
27451
|
const set = /* @__PURE__ */ new Set();
|
|
26990
27452
|
const jsonlPath = aceConsolidatedSessionsJsonlPath(contextDir2);
|
|
26991
|
-
if (!
|
|
27453
|
+
if (!fs60.existsSync(jsonlPath)) {
|
|
26992
27454
|
return set;
|
|
26993
27455
|
}
|
|
26994
27456
|
let raw;
|
|
26995
27457
|
try {
|
|
26996
|
-
raw =
|
|
27458
|
+
raw = fs60.readFileSync(jsonlPath, "utf8");
|
|
26997
27459
|
} catch {
|
|
26998
27460
|
return set;
|
|
26999
27461
|
}
|
|
@@ -27024,7 +27486,7 @@ function readCompletedTraceRelativePaths(contextDir2) {
|
|
|
27024
27486
|
}
|
|
27025
27487
|
function listPendingAceTraceFiles(contextDir2, worktreeRoot) {
|
|
27026
27488
|
const traceSchema = opencodeAceSchemaPath(worktreeRoot, ACE_SCHEMA_TRACE);
|
|
27027
|
-
if (!
|
|
27489
|
+
if (!fs60.existsSync(traceSchema)) {
|
|
27028
27490
|
return [];
|
|
27029
27491
|
}
|
|
27030
27492
|
const completed = readCompletedTraceRelativePaths(contextDir2);
|
|
@@ -27054,11 +27516,32 @@ function clampConcurrency2(n) {
|
|
|
27054
27516
|
return Math.min(64, Math.max(1, Math.floor(n)));
|
|
27055
27517
|
}
|
|
27056
27518
|
async function runAceAutoLearnPool(p) {
|
|
27057
|
-
const
|
|
27519
|
+
const staticMaxC = clampConcurrency2(p.maxConcurrentOpenCodeAgents);
|
|
27520
|
+
const throttle = p.enableCpuAdaptiveThrottle !== false;
|
|
27521
|
+
let adaptiveMax = staticMaxC;
|
|
27522
|
+
const sample = p.cpuPressureSampler ?? (throttle ? createDefaultCpuPressureSampler() : () => 0);
|
|
27058
27523
|
const contextDir2 = gluecharmContextDir(p.baseOpts.worktreeRoot);
|
|
27059
27524
|
const runner = p.runOfflineLearn ?? runAceOfflineLearnFromTrace;
|
|
27060
27525
|
const fifo = [...p.traceAbsolutePaths];
|
|
27061
27526
|
let active = 0;
|
|
27527
|
+
const applyCpuPressure = () => {
|
|
27528
|
+
if (!throttle || active < 1) {
|
|
27529
|
+
return;
|
|
27530
|
+
}
|
|
27531
|
+
const ratio = sample();
|
|
27532
|
+
const { adaptiveMax: next, changed } = nextAdaptiveMaxAfterCpuSample({
|
|
27533
|
+
ratio,
|
|
27534
|
+
activeRunningCount: active,
|
|
27535
|
+
priorAdaptiveMax: adaptiveMax
|
|
27536
|
+
});
|
|
27537
|
+
if (changed) {
|
|
27538
|
+
adaptiveMax = next;
|
|
27539
|
+
p.log?.(
|
|
27540
|
+
`[ace] cpu pressure ratio=${ratio.toFixed(3)} active=${String(active)} adaptiveMaxConcurrentAi=${String(adaptiveMax)}`
|
|
27541
|
+
);
|
|
27542
|
+
}
|
|
27543
|
+
};
|
|
27544
|
+
const currentCap = () => Math.min(staticMaxC, adaptiveMax);
|
|
27062
27545
|
let wake;
|
|
27063
27546
|
const waitTurn = () => new Promise((resolve20) => {
|
|
27064
27547
|
wake = resolve20;
|
|
@@ -27074,11 +27557,13 @@ async function runAceAutoLearnPool(p) {
|
|
|
27074
27557
|
fifo.length = 0;
|
|
27075
27558
|
pump();
|
|
27076
27559
|
};
|
|
27560
|
+
let poolAbortListenerRegistered = false;
|
|
27077
27561
|
if (abortSignal) {
|
|
27078
27562
|
if (abortSignal.aborted) {
|
|
27079
27563
|
onPipelineAbort();
|
|
27080
27564
|
} else {
|
|
27081
|
-
abortSignal.addEventListener("abort", onPipelineAbort
|
|
27565
|
+
abortSignal.addEventListener("abort", onPipelineAbort);
|
|
27566
|
+
poolAbortListenerRegistered = true;
|
|
27082
27567
|
}
|
|
27083
27568
|
}
|
|
27084
27569
|
const traceRel = (abs) => path58.relative(contextDir2, abs).split(path58.sep).join("/");
|
|
@@ -27088,8 +27573,9 @@ async function runAceAutoLearnPool(p) {
|
|
|
27088
27573
|
pump();
|
|
27089
27574
|
return;
|
|
27090
27575
|
}
|
|
27576
|
+
applyCpuPressure();
|
|
27091
27577
|
const rel = traceRel(traceAbs);
|
|
27092
|
-
p.log?.(`[ace] ace auto-learn: start ${rel} (active ${active}/${
|
|
27578
|
+
p.log?.(`[ace] ace auto-learn: start ${rel} (active ${active}/${currentCap()})`);
|
|
27093
27579
|
await p.onItemStart?.(rel);
|
|
27094
27580
|
const r = await runner(traceAbs, { ...p.baseOpts, abortSignal });
|
|
27095
27581
|
if (r.ok) {
|
|
@@ -27103,25 +27589,39 @@ async function runAceAutoLearnPool(p) {
|
|
|
27103
27589
|
p.log?.(`[ace] ace auto-learn: finished ${rel} ok=${r.ok}`);
|
|
27104
27590
|
pump();
|
|
27105
27591
|
};
|
|
27106
|
-
|
|
27107
|
-
|
|
27108
|
-
|
|
27109
|
-
|
|
27110
|
-
|
|
27111
|
-
|
|
27112
|
-
|
|
27113
|
-
|
|
27114
|
-
|
|
27115
|
-
|
|
27116
|
-
|
|
27117
|
-
|
|
27592
|
+
let pressureInterval;
|
|
27593
|
+
if (throttle) {
|
|
27594
|
+
const intervalMs = p.__testOnlyCpuPressureIntervalMs ?? 3e4;
|
|
27595
|
+
pressureInterval = setInterval(() => applyCpuPressure(), intervalMs);
|
|
27596
|
+
}
|
|
27597
|
+
try {
|
|
27598
|
+
while (true) {
|
|
27599
|
+
while (fifo.length > 0 && active < currentCap() && !abortSignal?.aborted) {
|
|
27600
|
+
const traceAbs = fifo.shift();
|
|
27601
|
+
active += 1;
|
|
27602
|
+
void runOne(traceAbs);
|
|
27603
|
+
}
|
|
27604
|
+
const pendingOrRunning = active > 0 || fifo.length > 0;
|
|
27605
|
+
if (!pendingOrRunning) {
|
|
27118
27606
|
break;
|
|
27119
27607
|
}
|
|
27120
|
-
|
|
27121
|
-
|
|
27608
|
+
if (abortSignal?.aborted) {
|
|
27609
|
+
if (active === 0) {
|
|
27610
|
+
break;
|
|
27611
|
+
}
|
|
27612
|
+
await waitTurn();
|
|
27613
|
+
continue;
|
|
27614
|
+
}
|
|
27615
|
+
if (fifo.length === 0 || active >= currentCap()) {
|
|
27616
|
+
await waitTurn();
|
|
27617
|
+
}
|
|
27618
|
+
}
|
|
27619
|
+
} finally {
|
|
27620
|
+
if (pressureInterval) {
|
|
27621
|
+
clearInterval(pressureInterval);
|
|
27122
27622
|
}
|
|
27123
|
-
if (
|
|
27124
|
-
|
|
27623
|
+
if (poolAbortListenerRegistered && abortSignal) {
|
|
27624
|
+
abortSignal.removeEventListener("abort", onPipelineAbort);
|
|
27125
27625
|
}
|
|
27126
27626
|
}
|
|
27127
27627
|
return { cancelled: abortSignal?.aborted === true, completed, failed };
|
|
@@ -27590,7 +28090,7 @@ function formatCliStderrLine(line, useAnsi) {
|
|
|
27590
28090
|
}
|
|
27591
28091
|
|
|
27592
28092
|
// src/cli/main.ts
|
|
27593
|
-
var PKG_VERSION = "0.0.
|
|
28093
|
+
var PKG_VERSION = "0.0.25";
|
|
27594
28094
|
function isNonEmptyFactoryFailureArray(x) {
|
|
27595
28095
|
if (!Array.isArray(x) || x.length === 0) {
|
|
27596
28096
|
return false;
|
|
@@ -27722,7 +28222,7 @@ function resolveAnalysisRoot(repoRoot, rootKind, worktreePath) {
|
|
|
27722
28222
|
return repoRoot;
|
|
27723
28223
|
}
|
|
27724
28224
|
const wt = worktreePath?.trim();
|
|
27725
|
-
if (wt &&
|
|
28225
|
+
if (wt && fs61.existsSync(path59.join(wt, ".git"))) {
|
|
27726
28226
|
return path59.resolve(wt);
|
|
27727
28227
|
}
|
|
27728
28228
|
throw new Error("worktree mode requires --worktree <path> to an existing analysis checkout.");
|
|
@@ -27731,14 +28231,14 @@ function resolveAdHocCheckoutRoot(_repoRoot, storage, worktreeFlag) {
|
|
|
27731
28231
|
const w = worktreeFlag?.trim();
|
|
27732
28232
|
if (w) {
|
|
27733
28233
|
const abs = path59.resolve(w);
|
|
27734
|
-
if (
|
|
28234
|
+
if (fs61.existsSync(path59.join(abs, ".git"))) {
|
|
27735
28235
|
return abs;
|
|
27736
28236
|
}
|
|
27737
28237
|
throw new Error(`Invalid --worktree (not a git checkout): ${abs}`);
|
|
27738
28238
|
}
|
|
27739
28239
|
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
27740
28240
|
const p = snap?.adHocWorktreePath?.trim();
|
|
27741
|
-
if (p &&
|
|
28241
|
+
if (p && fs61.existsSync(path59.join(p, ".git"))) {
|
|
27742
28242
|
return p;
|
|
27743
28243
|
}
|
|
27744
28244
|
throw new Error("No analysis checkout: run `easyspecs-cli run synthesis` first or pass `--worktree <path>`.");
|
|
@@ -27803,7 +28303,7 @@ async function main() {
|
|
|
27803
28303
|
try {
|
|
27804
28304
|
parsed = parseCliWithCommander(process.argv.slice(2));
|
|
27805
28305
|
} catch (e) {
|
|
27806
|
-
console.error(
|
|
28306
|
+
console.error(formatCliThrownUnknown(e));
|
|
27807
28307
|
logExitCodeSummary(ExitCode.usage);
|
|
27808
28308
|
process.exit(ExitCode.usage);
|
|
27809
28309
|
}
|
|
@@ -27820,6 +28320,58 @@ async function main() {
|
|
|
27820
28320
|
const repoRoot = resolveRepoRoot(flags);
|
|
27821
28321
|
setAceCliHeadlessMode(true);
|
|
27822
28322
|
setAceCliWorkspaceRoot(repoRoot);
|
|
28323
|
+
if (positionals[0] === "workstation" && positionals[1] === "info") {
|
|
28324
|
+
const tail = positionals.slice(2);
|
|
28325
|
+
const wantJson = flags.json || tail.includes("--json");
|
|
28326
|
+
const unknown = tail.filter((t) => t !== "--json");
|
|
28327
|
+
if (unknown.length > 0) {
|
|
28328
|
+
logErr(flags, "Usage: easyspecs-cli [--json] workstation info");
|
|
28329
|
+
logExitCodeSummary(ExitCode.usage, flags);
|
|
28330
|
+
process.exit(ExitCode.usage);
|
|
28331
|
+
}
|
|
28332
|
+
const plat = process.platform;
|
|
28333
|
+
if (plat !== "darwin" && plat !== "linux") {
|
|
28334
|
+
if (!wantJson) {
|
|
28335
|
+
logErr(
|
|
28336
|
+
flags,
|
|
28337
|
+
`[EasySpecs] workstation info is only supported on macOS and Linux (unsupported platform: ${plat}).`
|
|
28338
|
+
);
|
|
28339
|
+
}
|
|
28340
|
+
logExitCodeSummary(ExitCode.misconfiguration, flags);
|
|
28341
|
+
process.exit(ExitCode.misconfiguration);
|
|
28342
|
+
}
|
|
28343
|
+
const profile = collectHostMachineProfile();
|
|
28344
|
+
const nSys = machineConcurrentAiCapFromHost(profile);
|
|
28345
|
+
const hostHardMaxConcurrentAi = hostHardMaxFromHost(profile);
|
|
28346
|
+
const physicalCpus = profile.cpusForCapSource === "physical" ? profile.cpusForCap : null;
|
|
28347
|
+
const totalMemBytes = Math.max(0, Math.floor(profile.totalMemBytes));
|
|
28348
|
+
if (wantJson) {
|
|
28349
|
+
printJsonLine({
|
|
28350
|
+
command: "workstation info",
|
|
28351
|
+
durationMs: Date.now() - t0,
|
|
28352
|
+
ok: true,
|
|
28353
|
+
platform: profile.platform,
|
|
28354
|
+
totalMemBytes,
|
|
28355
|
+
cpusForCap: profile.cpusForCap,
|
|
28356
|
+
cpusForCapSource: profile.cpusForCapSource,
|
|
28357
|
+
physicalCpus,
|
|
28358
|
+
maxSystemConcurrentAiWorkstations: nSys,
|
|
28359
|
+
hostHardMaxConcurrentAi
|
|
28360
|
+
});
|
|
28361
|
+
} else {
|
|
28362
|
+
const gib = totalMemBytes / 2 ** 30;
|
|
28363
|
+
console.log(
|
|
28364
|
+
[
|
|
28365
|
+
`platform=${profile.platform}`,
|
|
28366
|
+
`cpusForCap=${String(profile.cpusForCap)} (${profile.cpusForCapSource})`,
|
|
28367
|
+
`totalMem=${gib.toFixed(2)} GiB (${String(totalMemBytes)} bytes)`,
|
|
28368
|
+
`N_sys (maxSystemConcurrentAiWorkstations)=${String(nSys)}`,
|
|
28369
|
+
`hostHardMaxConcurrentAi (min(N_sys,64))=${String(hostHardMaxConcurrentAi)}`
|
|
28370
|
+
].join("\n")
|
|
28371
|
+
);
|
|
28372
|
+
}
|
|
28373
|
+
process.exit(ExitCode.ok);
|
|
28374
|
+
}
|
|
27823
28375
|
if (positionals[0] === "config" && positionals[1] === "init") {
|
|
27824
28376
|
const tail = positionals.slice(2);
|
|
27825
28377
|
const overwrite = tail.includes("--overwrite");
|
|
@@ -28003,13 +28555,13 @@ async function main() {
|
|
|
28003
28555
|
try {
|
|
28004
28556
|
modes = parseDoctorFlags(pos.slice(1));
|
|
28005
28557
|
} catch (e) {
|
|
28006
|
-
logErr(flags,
|
|
28558
|
+
logErr(flags, formatCliThrownUnknown(e));
|
|
28007
28559
|
logErr(flags, "Usage: easyspecs-cli doctor [--readiness] [--inspect-config]");
|
|
28008
28560
|
logExitCodeSummary(ExitCode.usage, flags);
|
|
28009
28561
|
process.exit(ExitCode.usage);
|
|
28010
28562
|
}
|
|
28011
28563
|
const agentsDir = resolveOpenCodeAgentsDir(repoRoot, repoConfig);
|
|
28012
|
-
const agentsOk =
|
|
28564
|
+
const agentsOk = fs61.existsSync(agentsDir);
|
|
28013
28565
|
const oc = getOpenCodeReadiness({
|
|
28014
28566
|
executable: merged.openCodeExecutable,
|
|
28015
28567
|
skipCredentialsCheck: merged.openCodeSkipCredentialsCheck,
|
|
@@ -28069,7 +28621,7 @@ async function main() {
|
|
|
28069
28621
|
tailForCreds = extracted.rest;
|
|
28070
28622
|
sessionPathRaw = extracted.sessionPath;
|
|
28071
28623
|
} catch (e) {
|
|
28072
|
-
logErr(flags,
|
|
28624
|
+
logErr(flags, formatCliThrownUnknown(e));
|
|
28073
28625
|
logExitCodeSummary(ExitCode.usage, flags);
|
|
28074
28626
|
process.exit(ExitCode.usage);
|
|
28075
28627
|
}
|
|
@@ -28523,7 +29075,7 @@ async function main() {
|
|
|
28523
29075
|
const wt = snap?.adHocWorktreePath?.trim();
|
|
28524
29076
|
if (wt) {
|
|
28525
29077
|
const sourceCtx = path59.join(wt, ".gluecharm", "context");
|
|
28526
|
-
if (
|
|
29078
|
+
if (fs61.existsSync(sourceCtx)) {
|
|
28527
29079
|
const n = promoteContextDirectoryToWorkspaceFs(sourceCtx, repoRoot);
|
|
28528
29080
|
logErr(flags, `[pipeline:analysis] promoted ${String(n.filesCopied)} file(s) \u2192 ${repoRoot}`);
|
|
28529
29081
|
} else {
|
|
@@ -28675,8 +29227,8 @@ async function main() {
|
|
|
28675
29227
|
...flags.verbose && failCount > 0 ? { failures: result.failed } : {}
|
|
28676
29228
|
});
|
|
28677
29229
|
} catch (e) {
|
|
28678
|
-
const msg =
|
|
28679
|
-
finish(ExitCode.internal, { ok: false, error: msg });
|
|
29230
|
+
const msg = formatCliThrownUnknown(e);
|
|
29231
|
+
finish(exitCodeForThrownHttpApiError(e) ?? ExitCode.internal, { ok: false, error: msg });
|
|
28680
29232
|
}
|
|
28681
29233
|
}
|
|
28682
29234
|
if (pos[0] === "upload" && (pos[1] === "context" || pos[1] === "republish")) {
|
|
@@ -28693,12 +29245,12 @@ async function main() {
|
|
|
28693
29245
|
if (pos[1] === "republish") {
|
|
28694
29246
|
const fromCfg = repoConfig.easyspecs?.upload?.contextDirectory?.trim();
|
|
28695
29247
|
const resolvedOverride = fromCfg && fromCfg.length > 0 ? path59.isAbsolute(fromCfg) ? path59.normalize(fromCfg) : path59.resolve(repoRoot, fromCfg) : "";
|
|
28696
|
-
if (resolvedOverride &&
|
|
29248
|
+
if (resolvedOverride && fs61.existsSync(path59.join(resolvedOverride, ".."))) {
|
|
28697
29249
|
ctxDir = resolvedOverride;
|
|
28698
29250
|
} else {
|
|
28699
29251
|
const storage = createFileBackedWorkspaceState(repoRoot);
|
|
28700
29252
|
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
28701
|
-
const wt = snap?.adHocWorktreePath &&
|
|
29253
|
+
const wt = snap?.adHocWorktreePath && fs61.existsSync(path59.join(snap.adHocWorktreePath, ".gluecharm", "context")) ? path59.join(snap.adHocWorktreePath, ".gluecharm", "context") : "";
|
|
28702
29254
|
if (!wt) {
|
|
28703
29255
|
finish(ExitCode.misconfiguration, {
|
|
28704
29256
|
ok: false,
|
|
@@ -28816,16 +29368,16 @@ async function main() {
|
|
|
28816
29368
|
}
|
|
28817
29369
|
if (pos[0] === "ace" && pos[1] === "clear") {
|
|
28818
29370
|
const learnings = path59.join(repoRoot, ".gluecharm", "context", "learnings");
|
|
28819
|
-
if (!
|
|
29371
|
+
if (!fs61.existsSync(learnings)) {
|
|
28820
29372
|
finish(ExitCode.ok, { ok: true, message: "nothing to clear" });
|
|
28821
29373
|
}
|
|
28822
|
-
|
|
29374
|
+
fs61.rmSync(learnings, { recursive: true, force: true });
|
|
28823
29375
|
finish(ExitCode.ok, { ok: true, message: `cleared ${learnings}` });
|
|
28824
29376
|
}
|
|
28825
29377
|
if (pos[0] === "ace" && pos[1] === "learn") {
|
|
28826
29378
|
requireOpenCode(merged, flags);
|
|
28827
29379
|
const { worktree } = parseWorktreeFlag(pos.slice(2));
|
|
28828
|
-
const root = worktree &&
|
|
29380
|
+
const root = worktree && fs61.existsSync(path59.join(worktree, ".opencode", "schemas", "ace")) ? worktree : repoRoot;
|
|
28829
29381
|
const contextDir2 = path59.join(root, ".gluecharm", "context");
|
|
28830
29382
|
const traces = listAceTraceFiles(contextDir2);
|
|
28831
29383
|
if (traces.length === 0) {
|
|
@@ -28850,7 +29402,7 @@ async function main() {
|
|
|
28850
29402
|
if (pos[0] === "ace" && pos[1] === "auto-learn") {
|
|
28851
29403
|
requireOpenCode(merged, flags);
|
|
28852
29404
|
const { worktree } = parseWorktreeFlag(pos.slice(2));
|
|
28853
|
-
const root = worktree &&
|
|
29405
|
+
const root = worktree && fs61.existsSync(path59.join(worktree, ".git")) ? worktree : repoRoot;
|
|
28854
29406
|
const contextDir2 = path59.join(root, ".gluecharm", "context");
|
|
28855
29407
|
const pending = listPendingAceTraceFiles(contextDir2, root);
|
|
28856
29408
|
if (pending.length === 0) {
|
|
@@ -28893,9 +29445,10 @@ async function main() {
|
|
|
28893
29445
|
}
|
|
28894
29446
|
process.exit(ExitCode.misconfiguration);
|
|
28895
29447
|
}
|
|
28896
|
-
const msg =
|
|
29448
|
+
const msg = formatCliThrownUnknown(e);
|
|
29449
|
+
const exitFromApi = exitCodeForThrownHttpApiError(e);
|
|
28897
29450
|
logErr(flags, msg);
|
|
28898
|
-
finish(ExitCode.internal, { ok: false, error: msg });
|
|
29451
|
+
finish(exitFromApi ?? ExitCode.internal, { ok: false, error: msg });
|
|
28899
29452
|
}
|
|
28900
29453
|
}
|
|
28901
29454
|
void main();
|