@gluecharm-lab/easyspecs-cli 0.0.24 → 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/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 fs60 = require("node:fs");
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 (fs60.existsSync(localBin)) return localBin;
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) => fs60.existsSync(`${localBin}${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 = fs60.realpathSync(this._scriptPath);
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, fs60, exportName) {
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, fs60[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 fs59 = __toESM(require("node:fs"));
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 maxConcurrentOpenCodeAgents = overrides.maxConcurrentOpenCodeAgents ?? readEasyspecsMergedSetting(cfg.easyspecs, "easyspecs.workstations.maxConcurrentAi") ?? rt?.pool?.maxConcurrentAgents ?? DEFAULT_MAX_CONCURRENT_AI;
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 fs6 = __toESM(require("node:fs"));
11641
+ var fs7 = __toESM(require("node:fs"));
11468
11642
  var path7 = __toESM(require("node:path"));
11469
11643
 
11470
11644
  // src/easySpecsWorkspaceSettingsCore.ts
11471
- var fs4 = __toESM(require("node:fs"));
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 fs3 = __toESM(require("fs"));
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
- fs3.mkdirSync(dir, { recursive: true });
11656
+ fs4.mkdirSync(dir, { recursive: true });
11483
11657
  const payload = {
11484
11658
  kind: MARKER_KIND,
11485
11659
  repositoryRoot: path4.resolve(repositoryRoot)
11486
11660
  };
11487
- fs3.writeFileSync(path4.join(dir, "analysis-worktree.json"), `${JSON.stringify(payload)}
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 = fs4.readFileSync(filePath, "utf8");
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 = fs4.readFileSync(filePath, "utf8");
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 fs5 = __toESM(require("node:fs"));
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 (fs5.existsSync(p)) {
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 (fs5.existsSync(p)) {
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 = fs5.readFileSync(schemaPath, "utf8");
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 = fs6.readFileSync(p, "utf8");
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
- fs6.mkdirSync(dir, { recursive: true });
11867
+ fs7.mkdirSync(dir, { recursive: true });
11694
11868
  const tmp = path7.join(dir, `.${path7.basename(targetPath)}.${process.pid}.${Date.now()}.tmp`);
11695
- fs6.writeFileSync(tmp, contents, "utf8");
11696
- fs6.renameSync(tmp, targetPath);
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 (fs6.existsSync(legacyPath)) {
11875
+ if (fs7.existsSync(legacyPath)) {
11702
11876
  try {
11703
- const rawLegacy = fs6.readFileSync(legacyPath, "utf8");
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 (fs6.existsSync(settingsLegacyPath)) {
11886
+ if (fs7.existsSync(settingsLegacyPath)) {
11713
11887
  try {
11714
- const rawS = fs6.readFileSync(settingsLegacyPath, "utf8");
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 = fs6.existsSync(configPath);
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 (fs6.existsSync(configPath)) {
11760
- if (fs6.existsSync(legacyPath)) {
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 (fs6.existsSync(settingsLegacy)) {
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 (!fs6.existsSync(configPath)) {
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 = fs6.existsSync(configPath) ? readEasyspecsConfig(repoRoot) : buildFreshEasyspecsConfigFromLegacy(repoRoot, opts?.warnMigration);
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 fs11 = __toESM(require("node:fs"));
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 fs10 = __toESM(require("node:fs"));
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 fs9 = __toESM(require("node:fs"));
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 fs8 = __toESM(require("fs"));
12082
+ var fs9 = __toESM(require("fs"));
11909
12083
  var path9 = __toESM(require("path"));
11910
12084
 
11911
12085
  // src/shared/repoResourcesRoot.ts
11912
- var fs7 = __toESM(require("node:fs"));
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 fs7.existsSync(path8.join(resourcesRoot, CONTEXT_LIST_MARKER));
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 = fs8.readFileSync(abs, "utf-8");
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
- fs9.writeFileSync(tmp, `${JSON.stringify(doc, null, 2)}
12205
+ fs10.writeFileSync(tmp, `${JSON.stringify(doc, null, 2)}
12032
12206
  `, "utf-8");
12033
- fs9.renameSync(tmp, targetPath);
12207
+ fs10.renameSync(tmp, targetPath);
12034
12208
  } catch (e) {
12035
12209
  try {
12036
- fs9.unlinkSync(tmp);
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 (!fs9.existsSync(target)) {
12219
+ if (!fs10.existsSync(target)) {
12046
12220
  return { ok: true };
12047
12221
  }
12048
12222
  let raw;
12049
12223
  try {
12050
- raw = fs9.readFileSync(target, "utf-8");
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 || !fs10.existsSync(contextDir2) || !fs10.statSync(contextDir2).isDirectory()) {
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 (!fs10.existsSync(indexPath)) {
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 = fs10.readFileSync(indexPath, "utf8");
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 (!fs11.existsSync(contextDir2) || !fs11.statSync(contextDir2).isDirectory()) {
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 = fs11.readdirSync(dir, { withFileTypes: true });
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 = fs11.readFileSync(absPath, "utf8");
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 = fs11.readFileSync(absPath, "utf8");
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 = fs11.readFileSync(onlyPath, "utf8");
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 = e instanceof Error ? e.message : String(e);
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 fs12 = __toESM(require("node:fs"));
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
- fs12.mkdirSync(dir, { recursive: true });
13156
+ fs13.mkdirSync(dir, { recursive: true });
12916
13157
  const load = () => {
12917
13158
  try {
12918
- if (!fs12.existsSync(file)) {
13159
+ if (!fs13.existsSync(file)) {
12919
13160
  return {};
12920
13161
  }
12921
- const j = JSON.parse(fs12.readFileSync(file, "utf8"));
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
- fs12.writeFileSync(file, `${JSON.stringify(m, null, 2)}
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 fs34 = __toESM(require("fs"));
13195
+ var fs36 = __toESM(require("fs"));
12955
13196
  var path32 = __toESM(require("path"));
12956
13197
 
12957
13198
  // src/analysis/analysisDynamicTestSteps.ts
12958
- var fs13 = __toESM(require("fs"));
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(fs13.readFileSync(filePath, "utf-8"));
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 = fs13.statSync(absolutePath);
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 = !fs13.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." : "";
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 = !fs13.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)." : "";
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 = !fs13.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)." : "";
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 = !fs13.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)." : "";
13206
- const useCaseEmptyHint = !fs13.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." : "";
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 fs16 = __toESM(require("fs"));
13467
+ var fs17 = __toESM(require("fs"));
13227
13468
  var path17 = __toESM(require("path"));
13228
13469
 
13229
13470
  // src/analysis/applyAceMaterializedAgents.ts
13230
- var fs15 = __toESM(require("fs"));
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 fs14 = __toESM(require("fs"));
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(fs14.readFileSync(jsonAbsolutePath, "utf-8"));
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(fs14.readFileSync(schemaAbsolutePath, "utf-8"));
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 (!fs15.existsSync(agentsDir) || !fs15.statSync(agentsDir).isDirectory()) {
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
- fs15.mkdirSync(learningsRoot, { recursive: true });
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 = fs15.readdirSync(agentsDir, { withFileTypes: true });
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 = fs15.readFileSync(agentPath, "utf-8");
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 (fs15.existsSync(pbPath)) {
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 (fs15.existsSync(ovPath)) {
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
- fs15.writeFileSync(agentPath, out, "utf-8");
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 (fs16.existsSync(configPath)) {
13866
+ if (fs17.existsSync(configPath)) {
13626
13867
  try {
13627
- const raw = fs16.readFileSync(configPath, "utf-8");
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
- fs16.writeFileSync(configPath, `${JSON.stringify(cfg, null, 2)}
13891
+ fs17.writeFileSync(configPath, `${JSON.stringify(cfg, null, 2)}
13651
13892
  `, "utf-8");
13652
13893
  }
13653
13894
  function copyRecursive(src, dest) {
13654
- fs16.mkdirSync(dest, { recursive: true });
13655
- const entries = fs16.readdirSync(src, { withFileTypes: true });
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
- fs16.copyFileSync(s, d);
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 (!fs16.existsSync(extensionResourcesAgents)) {
13669
- fs16.mkdirSync(dest, { recursive: true });
13670
- fs16.writeFileSync(
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 (fs16.existsSync(schemasSrc)) {
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 (fs16.existsSync(aceSchemasSrc)) {
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 fs28 = __toESM(require("fs"));
13938
+ var fs30 = __toESM(require("fs"));
13698
13939
  var path26 = __toESM(require("path"));
13699
13940
 
13700
13941
  // src/analysis/promptTemplates.ts
@@ -13846,12 +14087,11 @@ function synthesisStepLabel(step, ctx) {
13846
14087
  }
13847
14088
 
13848
14089
  // src/analysis/aceTracePhase.ts
13849
- var fs21 = __toESM(require("fs"));
14090
+ var fs23 = __toESM(require("fs"));
13850
14091
  var path21 = __toESM(require("path"));
13851
14092
 
13852
14093
  // src/opencodeCli.ts
13853
- var import_child_process = require("child_process");
13854
- var import_node_events = require("node:events");
14094
+ var import_child_process2 = require("child_process");
13855
14095
 
13856
14096
  // src/analysis/openCodeSessionStewardship.ts
13857
14097
  var TITLE_MAX_LEN = 80;
@@ -13975,8 +14215,140 @@ function logOpenCodeSessionFollowUpStart(diagnosticLog, p) {
13975
14215
  );
13976
14216
  }
13977
14217
 
14218
+ // src/opencodeSpawnDiagnostics.ts
14219
+ var import_child_process = require("child_process");
14220
+ var fs18 = __toESM(require("fs"));
14221
+ var os2 = __toESM(require("os"));
14222
+ function defaultCpusLogical() {
14223
+ const ap = os2.availableParallelism?.();
14224
+ if (typeof ap === "number" && Number.isFinite(ap) && ap >= 1) {
14225
+ return ap;
14226
+ }
14227
+ const n = os2.cpus()?.length ?? 1;
14228
+ return Math.max(1, n);
14229
+ }
14230
+ function collectHostSnapshot(deps) {
14231
+ const totalmem3 = deps?.totalmem ?? (() => os2.totalmem());
14232
+ const freemem2 = deps?.freemem ?? (() => os2.freemem());
14233
+ const loadavg3 = deps?.loadavg ?? (() => os2.loadavg());
14234
+ const cpusLogicalFn = deps?.cpusLogical ?? defaultCpusLogical;
14235
+ const total = Math.max(0, Math.floor(totalmem3()));
14236
+ const free = Math.max(0, Math.floor(freemem2()));
14237
+ const used = Math.max(0, total - free);
14238
+ const cpusLogical = Math.max(1, Math.floor(cpusLogicalFn()));
14239
+ const la = loadavg3();
14240
+ const raw = Array.isArray(la) && la.length > 0 ? la[0] : NaN;
14241
+ const load1 = Number.isFinite(raw) && raw >= 0 ? raw : null;
14242
+ const load1PerCpu = load1 === null ? null : load1 / cpusLogical;
14243
+ return {
14244
+ hostRamTotalB: total,
14245
+ hostRamFreeB: free,
14246
+ hostRamUsedB: used,
14247
+ load1,
14248
+ cpusLogical,
14249
+ load1PerCpu
14250
+ };
14251
+ }
14252
+ function formatHostSnapshotLine(procTag, childPid, s) {
14253
+ const load1Str = s.load1 === null ? "unknown" : String(s.load1);
14254
+ const perCpuStr = s.load1PerCpu === null ? "unknown" : String(s.load1PerCpu);
14255
+ return `${procTag} scope=host childPid=${childPid} hostRamTotalB=${s.hostRamTotalB} hostRamFreeB=${s.hostRamFreeB} hostRamUsedB=${s.hostRamUsedB} load1=${load1Str} cpusLogical=${s.cpusLogical} load1PerCpu=${perCpuStr}`;
14256
+ }
14257
+ function parseVmRssKilobytesFromProcStatus(content) {
14258
+ for (const line of content.split(/\r?\n/)) {
14259
+ const m = /^\s*VmRSS:\s*(\d+)\s*kB/i.exec(line);
14260
+ if (m) {
14261
+ const kb = Number(m[1]);
14262
+ return Number.isFinite(kb) && kb >= 0 ? kb : null;
14263
+ }
14264
+ }
14265
+ return null;
14266
+ }
14267
+ function parsePsRssDarwinKilobytes(stdout) {
14268
+ const t = stdout.trim();
14269
+ if (!t) {
14270
+ return null;
14271
+ }
14272
+ const first = t.split(/\s+/)[0] ?? "";
14273
+ const n = Number(first);
14274
+ if (!Number.isFinite(n) || n < 0) {
14275
+ return null;
14276
+ }
14277
+ return n;
14278
+ }
14279
+ function readLinuxPidRssBytes(pid) {
14280
+ const path60 = `/proc/${pid}/status`;
14281
+ try {
14282
+ const content = fs18.readFileSync(path60, "utf8");
14283
+ const kb = parseVmRssKilobytesFromProcStatus(content);
14284
+ if (kb === null) {
14285
+ return { kind: "unknown", reason: "VmRSS_missing" };
14286
+ }
14287
+ return { kind: "ok", bytes: Math.floor(kb * 1024) };
14288
+ } catch (e) {
14289
+ const msg = e instanceof Error ? e.message : String(e);
14290
+ return { kind: "unknown", reason: truncateReason(msg) };
14291
+ }
14292
+ }
14293
+ function readDarwinPidRssBytes(pid) {
14294
+ try {
14295
+ const out = (0, import_child_process.execFileSync)("ps", ["-o", "rss=", "-p", String(pid)], {
14296
+ encoding: "utf8",
14297
+ stdio: ["ignore", "pipe", "pipe"],
14298
+ maxBuffer: 64 * 1024
14299
+ });
14300
+ const kb = parsePsRssDarwinKilobytes(out);
14301
+ if (kb === null) {
14302
+ return { kind: "unknown", reason: "ps_parse" };
14303
+ }
14304
+ return { kind: "ok", bytes: Math.floor(kb * 1024) };
14305
+ } catch (e) {
14306
+ const msg = e instanceof Error ? e.message : String(e);
14307
+ return { kind: "unknown", reason: truncateReason(msg) };
14308
+ }
14309
+ }
14310
+ var MAX_RSS_REASON = 48;
14311
+ function truncateReason(s) {
14312
+ const one = s.replace(/\s+/g, " ").trim();
14313
+ if (one.length <= MAX_RSS_REASON) {
14314
+ return one;
14315
+ }
14316
+ return `${one.slice(0, MAX_RSS_REASON - 3)}...`;
14317
+ }
14318
+ function readProcessRssBytes(pid) {
14319
+ if (!Number.isFinite(pid) || pid <= 0) {
14320
+ return { kind: "unknown", reason: "bad_pid" };
14321
+ }
14322
+ const plat = process.platform;
14323
+ if (plat === "linux") {
14324
+ return readLinuxPidRssBytes(pid);
14325
+ }
14326
+ if (plat === "darwin") {
14327
+ return readDarwinPidRssBytes(pid);
14328
+ }
14329
+ return { kind: "unknown", reason: "platform" };
14330
+ }
14331
+ function formatChildResourceLine(procTag, childPid, childCpuMs, rss) {
14332
+ const cpu = Math.max(0, Math.round(childCpuMs));
14333
+ if (rss.kind === "ok") {
14334
+ return `${procTag} scope=child childPid=${childPid} childCpuMs=${cpu} childRssBytes=${rss.bytes}`;
14335
+ }
14336
+ const esc = rss.reason.replace(/\\/g, "\\\\").replace(/\s+/g, " ");
14337
+ return `${procTag} scope=child childPid=${childPid} childCpuMs=${cpu} childRssBytes=unknown rssErr=${esc}`;
14338
+ }
14339
+ function childCpuTimeMsFromUsageDelta(delta) {
14340
+ const us = Math.max(0, delta.user) + Math.max(0, delta.system);
14341
+ return Math.round(us / 1e3);
14342
+ }
14343
+ function subprocessCpuUsage(proc, previous) {
14344
+ const p = proc;
14345
+ if (typeof p.cpuUsage !== "function") {
14346
+ return { user: 0, system: 0 };
14347
+ }
14348
+ return previous === void 0 ? p.cpuUsage() : p.cpuUsage(previous);
14349
+ }
14350
+
13978
14351
  // src/opencodeCli.ts
13979
- var SHARED_OPEN_CODE_ABORT_LISTENER_BUDGET = 512;
13980
14352
  var USE_SHELL = process.platform === "win32";
13981
14353
  function resolveExecutable(executable) {
13982
14354
  const t = executable?.trim();
@@ -13984,7 +14356,7 @@ function resolveExecutable(executable) {
13984
14356
  }
13985
14357
  function spawnCliSync(executable, args, cwd, timeoutMs, env) {
13986
14358
  const mergedEnv = env ? { ...process.env, ...env } : process.env;
13987
- return (0, import_child_process.spawnSync)(executable, args, {
14359
+ return (0, import_child_process2.spawnSync)(executable, args, {
13988
14360
  encoding: "utf-8",
13989
14361
  cwd,
13990
14362
  shell: USE_SHELL,
@@ -14101,12 +14473,36 @@ function runOpenCodeAgent(cwd, args, options) {
14101
14473
  return;
14102
14474
  }
14103
14475
  const spawnEnv = options?.childEnv && Object.keys(options.childEnv).length > 0 ? { ...process.env, ...options.childEnv } : process.env;
14104
- const child = (0, import_child_process.spawn)(cmd, args, {
14476
+ const child = (0, import_child_process2.spawn)(cmd, args, {
14105
14477
  cwd,
14106
14478
  shell: USE_SHELL,
14107
14479
  env: spawnEnv,
14108
14480
  stdio: ["ignore", "pipe", "pipe"]
14109
14481
  });
14482
+ let childResourceLogged = false;
14483
+ let cpuBaseline;
14484
+ const tryEmitChildResourceDiag = () => {
14485
+ if (childResourceLogged || !log) {
14486
+ return;
14487
+ }
14488
+ if (typeof child.pid !== "number" || child.pid <= 0 || !cpuBaseline) {
14489
+ return;
14490
+ }
14491
+ childResourceLogged = true;
14492
+ let delta;
14493
+ try {
14494
+ delta = subprocessCpuUsage(child, cpuBaseline);
14495
+ } catch {
14496
+ delta = { user: 0, system: 0 };
14497
+ }
14498
+ const cpuMs = childCpuTimeMsFromUsageDelta(delta);
14499
+ const rss = readProcessRssBytes(child.pid);
14500
+ log(formatChildResourceLine(procTag, child.pid, cpuMs, rss));
14501
+ };
14502
+ if (log && typeof child.pid === "number" && child.pid > 0) {
14503
+ log(formatHostSnapshotLine(procTag, child.pid, collectHostSnapshot()));
14504
+ cpuBaseline = subprocessCpuUsage(child);
14505
+ }
14110
14506
  options?.onAgentLaunched?.();
14111
14507
  let stdout = "";
14112
14508
  let stderr = "";
@@ -14164,6 +14560,7 @@ ${truncateForDiag(outBody, DIAG_STDOUT_MAX)}`);
14164
14560
  return;
14165
14561
  }
14166
14562
  settled = true;
14563
+ tryEmitChildResourceDiag();
14167
14564
  if (diag) {
14168
14565
  finishDiag(diag.label, diag.code, diag.dumpStreams);
14169
14566
  }
@@ -14177,9 +14574,6 @@ ${truncateForDiag(outBody, DIAG_STDOUT_MAX)}`);
14177
14574
  }
14178
14575
  };
14179
14576
  if (sig) {
14180
- if ((0, import_node_events.getMaxListeners)(sig) < SHARED_OPEN_CODE_ABORT_LISTENER_BUDGET) {
14181
- (0, import_node_events.setMaxListeners)(SHARED_OPEN_CODE_ABORT_LISTENER_BUDGET, sig);
14182
- }
14183
14577
  onAbort = () => {
14184
14578
  child.kill("SIGTERM");
14185
14579
  settle(
@@ -14245,7 +14639,7 @@ ${truncateForDiag(outBody, DIAG_STDOUT_MAX)}`);
14245
14639
  }
14246
14640
 
14247
14641
  // src/analysis/aceTraceNormalize.ts
14248
- var fs17 = __toESM(require("fs"));
14642
+ var fs19 = __toESM(require("fs"));
14249
14643
  var ACE_VERSION = "1.0.0-draft";
14250
14644
  var REASONING_PHASES = /* @__PURE__ */ new Set([
14251
14645
  "explore",
@@ -14390,7 +14784,7 @@ function sanitizePlaybookHooks(input) {
14390
14784
  function rewriteAceTraceFileWithCanonicalEnvelope(traceAbsolutePath, canonical, diagnosticLog) {
14391
14785
  let raw;
14392
14786
  try {
14393
- raw = fs17.readFileSync(traceAbsolutePath, "utf-8");
14787
+ raw = fs19.readFileSync(traceAbsolutePath, "utf-8");
14394
14788
  } catch (e) {
14395
14789
  diagnosticLog?.(`[ace] trace normalize read failed: ${e instanceof Error ? e.message : String(e)}`);
14396
14790
  return false;
@@ -14435,7 +14829,7 @@ function rewriteAceTraceFileWithCanonicalEnvelope(traceAbsolutePath, canonical,
14435
14829
  doc.playbookHooks = hooks;
14436
14830
  }
14437
14831
  try {
14438
- fs17.writeFileSync(traceAbsolutePath, `${JSON.stringify(doc, null, 2)}
14832
+ fs19.writeFileSync(traceAbsolutePath, `${JSON.stringify(doc, null, 2)}
14439
14833
  `, "utf-8");
14440
14834
  } catch (e) {
14441
14835
  diagnosticLog?.(`[ace] trace normalize write failed: ${e instanceof Error ? e.message : String(e)}`);
@@ -14446,15 +14840,15 @@ function rewriteAceTraceFileWithCanonicalEnvelope(traceAbsolutePath, canonical,
14446
14840
  }
14447
14841
 
14448
14842
  // src/analysis/aceOfflineLearn.ts
14449
- var fs20 = __toESM(require("fs"));
14843
+ var fs22 = __toESM(require("fs"));
14450
14844
  var path20 = __toESM(require("path"));
14451
14845
 
14452
14846
  // src/analysis/aceCuratorApplier.ts
14453
- var fs18 = __toESM(require("fs"));
14847
+ var fs20 = __toESM(require("fs"));
14454
14848
  var path18 = __toESM(require("path"));
14455
14849
  function writeJson(pathAbs, obj) {
14456
- fs18.mkdirSync(path18.dirname(pathAbs), { recursive: true });
14457
- fs18.writeFileSync(pathAbs, `${JSON.stringify(obj, null, 2)}
14850
+ fs20.mkdirSync(path18.dirname(pathAbs), { recursive: true });
14851
+ fs20.writeFileSync(pathAbs, `${JSON.stringify(obj, null, 2)}
14458
14852
  `, "utf-8");
14459
14853
  }
14460
14854
  function emptyPlaybook(agentStem) {
@@ -14480,7 +14874,7 @@ function applyAceCuratorDeltaFile(worktreeRoot, deltaAbsolutePath, log) {
14480
14874
  const pbPath = acePlaybookPath(contextDir2, agentStem);
14481
14875
  const ovPath = aceOverlayPath(contextDir2, agentStem);
14482
14876
  let playbook;
14483
- if (fs18.existsSync(pbPath)) {
14877
+ if (fs20.existsSync(pbPath)) {
14484
14878
  const pv = validateAceJsonFile(pbPath, playbookSchema);
14485
14879
  if (!pv.ok) {
14486
14880
  return { ok: false, message: `Existing playbook invalid: ${pv.message}` };
@@ -14490,7 +14884,7 @@ function applyAceCuratorDeltaFile(worktreeRoot, deltaAbsolutePath, log) {
14490
14884
  playbook = emptyPlaybook(agentStem);
14491
14885
  }
14492
14886
  let overlay;
14493
- if (fs18.existsSync(ovPath)) {
14887
+ if (fs20.existsSync(ovPath)) {
14494
14888
  const ov = validateAceJsonFile(ovPath, overlaySchema);
14495
14889
  if (!ov.ok) {
14496
14890
  return { ok: false, message: `Existing overlay invalid: ${ov.message}` };
@@ -14568,7 +14962,7 @@ function applyAceCuratorDeltaFile(worktreeRoot, deltaAbsolutePath, log) {
14568
14962
  }
14569
14963
 
14570
14964
  // src/analysis/aceOfflineLearnFallbacks.ts
14571
- var fs19 = __toESM(require("fs"));
14965
+ var fs21 = __toESM(require("fs"));
14572
14966
  var path19 = __toESM(require("path"));
14573
14967
  var ACE_VERSION2 = "1.0.0-draft";
14574
14968
  function buildEmptyReflectorLessons(traceRelativePath, sessionRunId) {
@@ -14593,8 +14987,8 @@ function buildEmptyCuratorDelta(agentStem, lessonsRelativePath) {
14593
14987
  function appendAceConsolidatedSessionRecord(contextDir2, record, diagnosticLog) {
14594
14988
  const abs = aceConsolidatedSessionsJsonlPath(contextDir2);
14595
14989
  const rel = path19.relative(contextDir2, abs).split(path19.sep).join("/");
14596
- fs19.mkdirSync(aceLearningsRoot(contextDir2), { recursive: true });
14597
- fs19.appendFileSync(abs, `${JSON.stringify(record)}
14990
+ fs21.mkdirSync(aceLearningsRoot(contextDir2), { recursive: true });
14991
+ fs21.appendFileSync(abs, `${JSON.stringify(record)}
14598
14992
  `, "utf-8");
14599
14993
  diagnosticLog?.(`[ace] consolidated session record appended \u2014 ${rel}`);
14600
14994
  }
@@ -14616,7 +15010,7 @@ function safeRunIdSegment(runId) {
14616
15010
  }
14617
15011
  function readHead(p, max) {
14618
15012
  try {
14619
- const raw = fs20.readFileSync(p, "utf-8");
15013
+ const raw = fs22.readFileSync(p, "utf-8");
14620
15014
  return raw.length <= max ? raw : `${raw.slice(0, max)}
14621
15015
  \u2026 (truncated)`;
14622
15016
  } catch {
@@ -14625,12 +15019,12 @@ function readHead(p, max) {
14625
15019
  }
14626
15020
  function listAceTraceFiles(contextDir2) {
14627
15021
  const root = path20.join(aceLearningsRoot(contextDir2), "traces");
14628
- if (!fs20.existsSync(root)) {
15022
+ if (!fs22.existsSync(root)) {
14629
15023
  return [];
14630
15024
  }
14631
15025
  const out = [];
14632
15026
  const walk = (dir) => {
14633
- for (const e of fs20.readdirSync(dir, { withFileTypes: true })) {
15027
+ for (const e of fs22.readdirSync(dir, { withFileTypes: true })) {
14634
15028
  const full = path20.join(dir, e.name);
14635
15029
  if (e.isDirectory()) {
14636
15030
  walk(full);
@@ -14658,14 +15052,14 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
14658
15052
  const traceRel = path20.relative(contextDir2, traceAbsolutePath).split(path20.sep).join("/");
14659
15053
  const lessonsAbs = aceReflectionPath(contextDir2, agentStem, safeId);
14660
15054
  const deltaAbs = aceCurationPath(contextDir2, agentStem, safeId);
14661
- fs20.mkdirSync(path20.dirname(lessonsAbs), { recursive: true });
14662
- fs20.mkdirSync(path20.dirname(deltaAbs), { recursive: true });
15055
+ fs22.mkdirSync(path20.dirname(lessonsAbs), { recursive: true });
15056
+ fs22.mkdirSync(path20.dirname(deltaAbs), { recursive: true });
14663
15057
  const pbPath = path20.join(aceLearningsRoot(contextDir2), `${agentStem}.json`);
14664
15058
  const ovPath = path20.join(aceLearningsRoot(contextDir2), "overlays", `${agentStem}.json`);
14665
- const pbExcerpt = fs20.existsSync(pbPath) ? readHead(pbPath, 6e3) : "(no playbook yet)";
14666
- const ovExcerpt = fs20.existsSync(ovPath) ? readHead(ovPath, 4e3) : "(no overlay yet)";
15059
+ const pbExcerpt = fs22.existsSync(pbPath) ? readHead(pbPath, 6e3) : "(no playbook yet)";
15060
+ const ovExcerpt = fs22.existsSync(ovPath) ? readHead(ovPath, 4e3) : "(no overlay yet)";
14667
15061
  const runDir = path20.join(opts.worktreeRoot, ".opencode", "_run");
14668
- fs20.mkdirSync(runDir, { recursive: true });
15062
+ fs22.mkdirSync(runDir, { recursive: true });
14669
15063
  let reflectorUsedEmptyFallback = false;
14670
15064
  let curatorUsedEmptyFallback = false;
14671
15065
  const reflectPrompt = [
@@ -14684,7 +15078,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
14684
15078
  "Schema: `aceSchemaVersion` **1.0.0-draft**, `sourceTrace`, `lessons` (see ace-reflector-lessons schema)."
14685
15079
  ].join("\n");
14686
15080
  const reflectPromptPath = path20.join(runDir, `ace-reflect-${safeId}-${Date.now()}.prompt.txt`);
14687
- fs20.writeFileSync(reflectPromptPath, reflectPrompt, "utf-8");
15081
+ fs22.writeFileSync(reflectPromptPath, reflectPrompt, "utf-8");
14688
15082
  const reflectVars = {
14689
15083
  promptFile: reflectPromptPath,
14690
15084
  agentId: ACE_REFLECTOR_AGENT_STEM,
@@ -14716,11 +15110,11 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
14716
15110
  if (!rCli.ok) {
14717
15111
  return { ok: false, message: `[ace] reflector OpenCode failed: ${rCli.message}` };
14718
15112
  }
14719
- if (!fs20.existsSync(lessonsAbs)) {
15113
+ if (!fs22.existsSync(lessonsAbs)) {
14720
15114
  const recovered = extractJsonObjectWithTopLevelKeys(rCli.message, ["aceSchemaVersion", "sourceTrace", "lessons"]);
14721
15115
  if (recovered) {
14722
15116
  try {
14723
- fs20.writeFileSync(lessonsAbs, `${recovered}
15117
+ fs22.writeFileSync(lessonsAbs, `${recovered}
14724
15118
  `, "utf-8");
14725
15119
  opts.diagnosticLog?.(`[ace] reflector recovered from OpenCode stdout/stderr \u2192 ${lessonsAbs}`);
14726
15120
  } catch (e) {
@@ -14730,7 +15124,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
14730
15124
  }
14731
15125
  }
14732
15126
  }
14733
- if (!fs20.existsSync(lessonsAbs)) {
15127
+ if (!fs22.existsSync(lessonsAbs)) {
14734
15128
  return { ok: false, message: `[ace] reflector output missing: ${lessonsAbs}` };
14735
15129
  }
14736
15130
  let lv = validateAceJsonFile(lessonsAbs, reflectorSchema);
@@ -14742,7 +15136,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
14742
15136
  ]);
14743
15137
  if (recoveredAgain) {
14744
15138
  try {
14745
- fs20.writeFileSync(lessonsAbs, `${recoveredAgain}
15139
+ fs22.writeFileSync(lessonsAbs, `${recoveredAgain}
14746
15140
  `, "utf-8");
14747
15141
  opts.diagnosticLog?.(`[ace] reflector re-recovered from CLI output after schema failure \u2192 ${lessonsAbs}`);
14748
15142
  lv = validateAceJsonFile(lessonsAbs, reflectorSchema);
@@ -14756,7 +15150,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
14756
15150
  if (!lv.ok) {
14757
15151
  const hint = lv.message.length > 220 ? `${lv.message.slice(0, 220)}\u2026` : lv.message;
14758
15152
  opts.diagnosticLog?.(`[ace] reflector lessons failed schema \u2014 writing valid empty lessons \u2014 ${hint}`);
14759
- fs20.writeFileSync(
15153
+ fs22.writeFileSync(
14760
15154
  lessonsAbs,
14761
15155
  `${JSON.stringify(buildEmptyReflectorLessons(traceRel, runId), null, 2)}
14762
15156
  `,
@@ -14803,7 +15197,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
14803
15197
  "Schema: `aceSchemaVersion` **1.0.0-draft**, `agentStem`, `sourceLessons`, `operations` (see ace-curator-delta schema)."
14804
15198
  ].join("\n");
14805
15199
  const curPromptPath = path20.join(runDir, `ace-curate-${safeId}-${Date.now()}.prompt.txt`);
14806
- fs20.writeFileSync(curPromptPath, curPrompt, "utf-8");
15200
+ fs22.writeFileSync(curPromptPath, curPrompt, "utf-8");
14807
15201
  const curVars = {
14808
15202
  promptFile: curPromptPath,
14809
15203
  agentId: ACE_CURATOR_AGENT_STEM,
@@ -14834,7 +15228,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
14834
15228
  if (!cCli.ok) {
14835
15229
  return { ok: false, message: `[ace] curator OpenCode failed: ${cCli.message}` };
14836
15230
  }
14837
- if (!fs20.existsSync(deltaAbs)) {
15231
+ if (!fs22.existsSync(deltaAbs)) {
14838
15232
  const recovered = extractJsonObjectWithTopLevelKeys(cCli.message, [
14839
15233
  "aceSchemaVersion",
14840
15234
  "agentStem",
@@ -14843,7 +15237,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
14843
15237
  ]);
14844
15238
  if (recovered) {
14845
15239
  try {
14846
- fs20.writeFileSync(deltaAbs, `${recovered}
15240
+ fs22.writeFileSync(deltaAbs, `${recovered}
14847
15241
  `, "utf-8");
14848
15242
  opts.diagnosticLog?.(`[ace] curator recovered from OpenCode stdout/stderr \u2192 ${deltaAbs}`);
14849
15243
  } catch (e) {
@@ -14853,7 +15247,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
14853
15247
  }
14854
15248
  }
14855
15249
  }
14856
- if (!fs20.existsSync(deltaAbs)) {
15250
+ if (!fs22.existsSync(deltaAbs)) {
14857
15251
  return { ok: false, message: `[ace] curator output missing: ${deltaAbs}` };
14858
15252
  }
14859
15253
  let dv = validateAceJsonFile(deltaAbs, curatorSchema);
@@ -14866,7 +15260,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
14866
15260
  ]);
14867
15261
  if (recoveredCur) {
14868
15262
  try {
14869
- fs20.writeFileSync(deltaAbs, `${recoveredCur}
15263
+ fs22.writeFileSync(deltaAbs, `${recoveredCur}
14870
15264
  `, "utf-8");
14871
15265
  opts.diagnosticLog?.(`[ace] curator re-recovered from CLI output after schema failure \u2192 ${deltaAbs}`);
14872
15266
  dv = validateAceJsonFile(deltaAbs, curatorSchema);
@@ -14880,7 +15274,7 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
14880
15274
  if (!dv.ok) {
14881
15275
  const hint = dv.message.length > 220 ? `${dv.message.slice(0, 220)}\u2026` : dv.message;
14882
15276
  opts.diagnosticLog?.(`[ace] curator delta failed schema \u2014 writing valid empty operations \u2014 ${hint}`);
14883
- fs20.writeFileSync(
15277
+ fs22.writeFileSync(
14884
15278
  deltaAbs,
14885
15279
  `${JSON.stringify(buildEmptyCuratorDelta(agentStem, lessonsRel), null, 2)}
14886
15280
  `,
@@ -14899,9 +15293,9 @@ async function runAceOfflineLearnFromTrace(traceAbsolutePath, opts) {
14899
15293
  let lessonCount = 0;
14900
15294
  let curatorOperationCount = 0;
14901
15295
  try {
14902
- const lessonsDoc = JSON.parse(fs20.readFileSync(lessonsAbs, "utf-8"));
15296
+ const lessonsDoc = JSON.parse(fs22.readFileSync(lessonsAbs, "utf-8"));
14903
15297
  lessonCount = Array.isArray(lessonsDoc.lessons) ? lessonsDoc.lessons.length : 0;
14904
- const deltaDoc = JSON.parse(fs20.readFileSync(deltaAbs, "utf-8"));
15298
+ const deltaDoc = JSON.parse(fs22.readFileSync(deltaAbs, "utf-8"));
14905
15299
  curatorOperationCount = Array.isArray(deltaDoc.operations) ? deltaDoc.operations.length : 0;
14906
15300
  } catch {
14907
15301
  }
@@ -14960,9 +15354,9 @@ async function runAceTracePhase(params) {
14960
15354
  const contextDir2 = gluecharmContextDir(params.worktreeRoot);
14961
15355
  const traceStem = aceTraceFileRunStem(params.artefactRunId, params.followUpSessionId);
14962
15356
  const traceAbs = aceTracePath(contextDir2, params.producerAgentStem, traceStem);
14963
- fs21.mkdirSync(path21.dirname(traceAbs), { recursive: true });
15357
+ fs23.mkdirSync(path21.dirname(traceAbs), { recursive: true });
14964
15358
  const schemaAbs = opencodeAceSchemaPath(params.worktreeRoot, ACE_SCHEMA_TRACE);
14965
- if (!fs21.existsSync(schemaAbs)) {
15359
+ if (!fs23.existsSync(schemaAbs)) {
14966
15360
  const msg = `[ace] trace skipped \u2014 schema missing: ${schemaAbs}`;
14967
15361
  params.diagnosticLog?.(msg);
14968
15362
  return { ok: false, message: msg };
@@ -15011,9 +15405,9 @@ async function runAceTracePhase(params) {
15011
15405
  `Use only evidence from this session's transcript and tool history.`
15012
15406
  ].join("\n");
15013
15407
  const runDir = path21.join(params.worktreeRoot, ".opencode", "_run");
15014
- fs21.mkdirSync(runDir, { recursive: true });
15408
+ fs23.mkdirSync(runDir, { recursive: true });
15015
15409
  const promptPath = path21.join(runDir, `ace-trace-${traceStem}-${Date.now()}.prompt.txt`);
15016
- fs21.writeFileSync(promptPath, promptBody, "utf-8");
15410
+ fs23.writeFileSync(promptPath, promptBody, "utf-8");
15017
15411
  const vars = {
15018
15412
  promptFile: promptPath,
15019
15413
  agentId: ACE_TRACE_RECORDER_AGENT_STEM,
@@ -15037,7 +15431,7 @@ async function runAceTracePhase(params) {
15037
15431
  if (!cli.ok) {
15038
15432
  return { ok: false, message: `[ace] trace OpenCode failed: ${cli.message}` };
15039
15433
  }
15040
- if (!fs21.existsSync(traceAbs)) {
15434
+ if (!fs23.existsSync(traceAbs)) {
15041
15435
  const recovered = extractJsonObjectWithTopLevelKeys(cli.message, [
15042
15436
  "aceSchemaVersion",
15043
15437
  "sessionMeta",
@@ -15045,7 +15439,7 @@ async function runAceTracePhase(params) {
15045
15439
  ]);
15046
15440
  if (recovered) {
15047
15441
  try {
15048
- fs21.writeFileSync(traceAbs, `${recovered}
15442
+ fs23.writeFileSync(traceAbs, `${recovered}
15049
15443
  `, "utf-8");
15050
15444
  params.diagnosticLog?.(`[ace] trace recovered from OpenCode stdout/stderr \u2192 ${traceAbs}`);
15051
15445
  } catch (e) {
@@ -15055,7 +15449,7 @@ async function runAceTracePhase(params) {
15055
15449
  }
15056
15450
  }
15057
15451
  }
15058
- if (!fs21.existsSync(traceAbs)) {
15452
+ if (!fs23.existsSync(traceAbs)) {
15059
15453
  const msg = `[ace] trace file missing after run: ${traceAbs}`;
15060
15454
  params.diagnosticLog?.(msg);
15061
15455
  return { ok: false, message: msg };
@@ -15087,7 +15481,7 @@ async function runAceTracePhase(params) {
15087
15481
  return { ok: false, message: msg };
15088
15482
  }
15089
15483
  try {
15090
- const rawAlign = fs21.readFileSync(traceAbs, "utf-8");
15484
+ const rawAlign = fs23.readFileSync(traceAbs, "utf-8");
15091
15485
  const docAlign = JSON.parse(rawAlign);
15092
15486
  const smRun = docAlign.sessionMeta?.runId;
15093
15487
  if (typeof smRun !== "string" || smRun !== traceStem) {
@@ -15143,7 +15537,7 @@ async function runAceTracePhase(params) {
15143
15537
  }
15144
15538
 
15145
15539
  // src/analysis/coordinationListJsonValidate.ts
15146
- var fs22 = __toESM(require("fs"));
15540
+ var fs24 = __toESM(require("fs"));
15147
15541
  var import__4 = __toESM(require__());
15148
15542
  function stripUtf8Bom3(s) {
15149
15543
  return s.length > 0 && s.charCodeAt(0) === 65279 ? s.slice(1) : s;
@@ -15207,7 +15601,7 @@ function formatAjvErrors4(errors) {
15207
15601
  function validateCoordinationListJson(jsonAbsolutePath, schemaAbsolutePath) {
15208
15602
  let raw;
15209
15603
  try {
15210
- raw = stripUtf8Bom3(fs22.readFileSync(jsonAbsolutePath, "utf-8"));
15604
+ raw = stripUtf8Bom3(fs24.readFileSync(jsonAbsolutePath, "utf-8"));
15211
15605
  } catch (e) {
15212
15606
  return {
15213
15607
  ok: false,
@@ -15223,7 +15617,7 @@ function validateCoordinationListJson(jsonAbsolutePath, schemaAbsolutePath) {
15223
15617
  }
15224
15618
  let schemaRaw;
15225
15619
  try {
15226
- schemaRaw = stripUtf8Bom3(fs22.readFileSync(schemaAbsolutePath, "utf-8"));
15620
+ schemaRaw = stripUtf8Bom3(fs24.readFileSync(schemaAbsolutePath, "utf-8"));
15227
15621
  } catch (e) {
15228
15622
  return {
15229
15623
  ok: false,
@@ -15284,7 +15678,7 @@ function validateCoordinationListJson(jsonAbsolutePath, schemaAbsolutePath) {
15284
15678
  var FILE_PREVIEW_MAX = 4e3;
15285
15679
  function readCoordinationJsonPreview(jsonAbsolutePath) {
15286
15680
  try {
15287
- const raw = stripUtf8Bom3(fs22.readFileSync(jsonAbsolutePath, "utf-8"));
15681
+ const raw = stripUtf8Bom3(fs24.readFileSync(jsonAbsolutePath, "utf-8"));
15288
15682
  return raw.length <= FILE_PREVIEW_MAX ? raw : `${raw.slice(0, FILE_PREVIEW_MAX)}
15289
15683
 
15290
15684
  \u2026 (truncated)`;
@@ -15360,12 +15754,12 @@ function formatCoordinationJsonRepairAppendix(outputBasename, failure, rawFilePr
15360
15754
  }
15361
15755
 
15362
15756
  // src/analysis/coordinationListStableWrite.ts
15363
- var fs24 = __toESM(require("fs"));
15757
+ var fs26 = __toESM(require("fs"));
15364
15758
  var path23 = __toESM(require("path"));
15365
15759
 
15366
15760
  // src/analysis/coordinationListFileLock.ts
15367
- var fs23 = __toESM(require("fs"));
15368
- var os = __toESM(require("os"));
15761
+ var fs25 = __toESM(require("fs"));
15762
+ var os3 = __toESM(require("os"));
15369
15763
  var path22 = __toESM(require("path"));
15370
15764
  var DEFAULT_COORDINATION_LIST_LOCK_TIMEOUT_MS = 12e4;
15371
15765
  var DEFAULT_COORDINATION_LIST_LOCK_STALE_MS = 30 * 60 * 1e3;
@@ -15385,7 +15779,7 @@ function lockPathForList(listJsonAbsolutePath) {
15385
15779
  }
15386
15780
  function tryReadLockBody(lockAbs) {
15387
15781
  try {
15388
- const raw = fs23.readFileSync(lockAbs, "utf-8");
15782
+ const raw = fs25.readFileSync(lockAbs, "utf-8");
15389
15783
  const j = JSON.parse(raw);
15390
15784
  if (typeof j.pid === "number" && typeof j.createdAt === "string") {
15391
15785
  return j;
@@ -15397,7 +15791,7 @@ function tryReadLockBody(lockAbs) {
15397
15791
  function tryRemoveStaleLock(lockAbs, staleMs, diagnosticLog) {
15398
15792
  let st;
15399
15793
  try {
15400
- st = fs23.statSync(lockAbs);
15794
+ st = fs25.statSync(lockAbs);
15401
15795
  } catch {
15402
15796
  return false;
15403
15797
  }
@@ -15412,7 +15806,7 @@ function tryRemoveStaleLock(lockAbs, staleMs, diagnosticLog) {
15412
15806
  return false;
15413
15807
  }
15414
15808
  try {
15415
- fs23.unlinkSync(lockAbs);
15809
+ fs25.unlinkSync(lockAbs);
15416
15810
  diagnosticLog?.(`[coord-lock] removed stale lock ${lockAbs} (age ${Math.round(age)} ms)`);
15417
15811
  return true;
15418
15812
  } catch {
@@ -15429,11 +15823,11 @@ async function withCoordinationListFileLock(listJsonAbsolutePath, options, fn) {
15429
15823
  while (!acquired && Date.now() < deadline) {
15430
15824
  const body = {
15431
15825
  pid: process.pid,
15432
- host: os.hostname(),
15826
+ host: os3.hostname(),
15433
15827
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
15434
15828
  };
15435
15829
  try {
15436
- fs23.writeFileSync(lockAbs, `${JSON.stringify(body, null, 0)}
15830
+ fs25.writeFileSync(lockAbs, `${JSON.stringify(body, null, 0)}
15437
15831
  `, { encoding: "utf-8", flag: "wx" });
15438
15832
  acquired = true;
15439
15833
  diagnosticLog?.(`[coord-lock] acquired ${path22.basename(lockAbs)}`);
@@ -15457,7 +15851,7 @@ async function withCoordinationListFileLock(listJsonAbsolutePath, options, fn) {
15457
15851
  return await fn();
15458
15852
  } finally {
15459
15853
  try {
15460
- fs23.unlinkSync(lockAbs);
15854
+ fs25.unlinkSync(lockAbs);
15461
15855
  diagnosticLog?.(`[coord-lock] released ${path22.basename(lockAbs)}`);
15462
15856
  } catch {
15463
15857
  }
@@ -15831,13 +16225,13 @@ function buildCascadePathsForDroppedCodes(listBasename, droppedCodes, contextDir
15831
16225
  const paths = [];
15832
16226
  const tryPush = (p) => {
15833
16227
  const abs = path23.join(contextDirAbs, p);
15834
- if (fs24.existsSync(abs)) {
16228
+ if (fs26.existsSync(abs)) {
15835
16229
  paths.push(abs);
15836
16230
  }
15837
16231
  };
15838
16232
  const listDir = () => {
15839
16233
  try {
15840
- return fs24.readdirSync(contextDirAbs);
16234
+ return fs26.readdirSync(contextDirAbs);
15841
16235
  } catch {
15842
16236
  return [];
15843
16237
  }
@@ -16038,7 +16432,7 @@ async function finalizeCoordinationListWrite(p) {
16038
16432
  async () => {
16039
16433
  let agentRaw;
16040
16434
  try {
16041
- agentRaw = fs24.readFileSync(p.listJsonAbsolutePath, "utf-8");
16435
+ agentRaw = fs26.readFileSync(p.listJsonAbsolutePath, "utf-8");
16042
16436
  } catch (e) {
16043
16437
  return { ok: false, message: `SRS-50 re-read failed: ${e instanceof Error ? e.message : String(e)}` };
16044
16438
  }
@@ -16066,7 +16460,7 @@ async function finalizeCoordinationListWrite(p) {
16066
16460
  p.diagnosticLog?.(formatStableWriteDiagnosticLine(p.listBasename, m.diff));
16067
16461
  const tmp = `${p.listJsonAbsolutePath}.tmp.${process.pid}`;
16068
16462
  try {
16069
- fs24.writeFileSync(tmp, `${JSON.stringify(m.merged, null, 2)}
16463
+ fs26.writeFileSync(tmp, `${JSON.stringify(m.merged, null, 2)}
16070
16464
  `, "utf-8");
16071
16465
  } catch (e) {
16072
16466
  return { ok: false, message: `SRS-50 temp write failed: ${e instanceof Error ? e.message : String(e)}` };
@@ -16074,14 +16468,14 @@ async function finalizeCoordinationListWrite(p) {
16074
16468
  const v = validateCoordinationListJson(tmp, p.schemaAbsolutePath);
16075
16469
  if (!v.ok) {
16076
16470
  try {
16077
- fs24.unlinkSync(tmp);
16471
+ fs26.unlinkSync(tmp);
16078
16472
  } catch {
16079
16473
  }
16080
16474
  const detail = v.failure.kind === "schema" ? v.failure.errorsText : v.failure.kind === "parse" ? v.failure.message : v.failure.message;
16081
16475
  return { ok: false, message: `SRS-50 merged output failed schema: ${detail}` };
16082
16476
  }
16083
16477
  try {
16084
- fs24.renameSync(tmp, p.listJsonAbsolutePath);
16478
+ fs26.renameSync(tmp, p.listJsonAbsolutePath);
16085
16479
  } catch (e) {
16086
16480
  return { ok: false, message: `SRS-50 rename failed: ${e instanceof Error ? e.message : String(e)}` };
16087
16481
  }
@@ -16151,7 +16545,7 @@ function allocateNextListRowCode(input) {
16151
16545
  }
16152
16546
  let names = [];
16153
16547
  try {
16154
- names = fs24.readdirSync(contextDirAbs);
16548
+ names = fs26.readdirSync(contextDirAbs);
16155
16549
  } catch {
16156
16550
  names = [];
16157
16551
  }
@@ -16194,7 +16588,7 @@ function allocateNextListRowCode(input) {
16194
16588
  }
16195
16589
 
16196
16590
  // src/analysis/markdownEvidenceIndexValidate.ts
16197
- var fs25 = __toESM(require("fs"));
16591
+ var fs27 = __toESM(require("fs"));
16198
16592
  var EVIDENCE_HEADING = "## Evidence index";
16199
16593
  function evidenceIndexMentionsReadmeMd(body) {
16200
16594
  const re = /README\.md/gi;
@@ -16322,7 +16716,7 @@ function markdownEvidenceValidationPasses(content) {
16322
16716
  function validateMarkdownEvidenceIndexFile(absolutePath) {
16323
16717
  let text;
16324
16718
  try {
16325
- const buf = fs25.readFileSync(absolutePath);
16719
+ const buf = fs27.readFileSync(absolutePath);
16326
16720
  const decoder = new TextDecoder("utf-8", { fatal: true });
16327
16721
  text = decoder.decode(buf);
16328
16722
  } catch (e) {
@@ -16363,7 +16757,7 @@ function formatMarkdownEvidenceRepairAppendix(outputFileAbsolute, kind = "empty"
16363
16757
  }
16364
16758
 
16365
16759
  // src/analysis/openQuestionResolution.ts
16366
- var fs26 = __toESM(require("fs"));
16760
+ var fs28 = __toESM(require("fs"));
16367
16761
  var path24 = __toESM(require("path"));
16368
16762
  var OPEN_QUESTION_RESOLUTION_JSON_BASENAME = "open-question-resolution.json";
16369
16763
  function openQuestionResolutionJsonAbsolute(worktreeRoot) {
@@ -16402,10 +16796,10 @@ function parseOpenQuestionResolutionJsonText(raw) {
16402
16796
  function readOpenQuestionResolutionFile(worktreeRoot) {
16403
16797
  const p = openQuestionResolutionJsonAbsolute(worktreeRoot);
16404
16798
  try {
16405
- if (!fs26.existsSync(p)) {
16799
+ if (!fs28.existsSync(p)) {
16406
16800
  return { ok: false, error: `Missing resolution file: ${p}` };
16407
16801
  }
16408
- const raw = fs26.readFileSync(p, "utf-8");
16802
+ const raw = fs28.readFileSync(p, "utf-8");
16409
16803
  return parseOpenQuestionResolutionJsonText(raw);
16410
16804
  } catch (e) {
16411
16805
  const m = e instanceof Error ? e.message : String(e);
@@ -16415,15 +16809,15 @@ function readOpenQuestionResolutionFile(worktreeRoot) {
16415
16809
  function deleteOpenQuestionResolutionFile(worktreeRoot) {
16416
16810
  try {
16417
16811
  const p = openQuestionResolutionJsonAbsolute(worktreeRoot);
16418
- if (fs26.existsSync(p)) {
16419
- fs26.unlinkSync(p);
16812
+ if (fs28.existsSync(p)) {
16813
+ fs28.unlinkSync(p);
16420
16814
  }
16421
16815
  } catch {
16422
16816
  }
16423
16817
  }
16424
16818
 
16425
16819
  // src/analysis/openQuestionsSectionValidate.ts
16426
- var fs27 = __toESM(require("fs"));
16820
+ var fs29 = __toESM(require("fs"));
16427
16821
  var path25 = __toESM(require("path"));
16428
16822
  var CANONICAL_NORMALIZED = "open questions";
16429
16823
  function normalizeOpenQuestionsHeadingTitle(raw) {
@@ -16556,7 +16950,7 @@ function validateOpenQuestionsSectionFile(absolutePath, scope) {
16556
16950
  }
16557
16951
  let text;
16558
16952
  try {
16559
- const buf = fs27.readFileSync(absolutePath);
16953
+ const buf = fs29.readFileSync(absolutePath);
16560
16954
  const decoder = new TextDecoder("utf-8", { fatal: true });
16561
16955
  text = decoder.decode(buf);
16562
16956
  } catch (e) {
@@ -17111,7 +17505,7 @@ function clampMarkdownOpenQuestionIterations(raw) {
17111
17505
  }
17112
17506
  function getExpectedOutputArtefactStatus(absolutePath) {
17113
17507
  try {
17114
- const st = fs28.statSync(absolutePath);
17508
+ const st = fs30.statSync(absolutePath);
17115
17509
  if (!st.isFile()) {
17116
17510
  return { generated: false, reason: "not_a_file" };
17117
17511
  }
@@ -17210,7 +17604,7 @@ function outputPaths(step, worktreeRoot, listTarget) {
17210
17604
  }
17211
17605
  async function runOpenQuestionResolutionWorkstation(opts) {
17212
17606
  const runDir = path26.join(opts.worktreeRoot, ".opencode", "_run");
17213
- fs28.mkdirSync(runDir, { recursive: true });
17607
+ fs30.mkdirSync(runDir, { recursive: true });
17214
17608
  const resolutionJsonAbsolute = openQuestionResolutionJsonAbsolute(opts.worktreeRoot);
17215
17609
  const body = fillResolveOpenQuestionPrompt({
17216
17610
  worktreeRoot: opts.worktreeRoot,
@@ -17220,7 +17614,7 @@ async function runOpenQuestionResolutionWorkstation(opts) {
17220
17614
  resolutionJsonAbsolute
17221
17615
  });
17222
17616
  const promptPath = path26.join(runDir, `resolve-open-question-${Date.now()}.prompt.txt`);
17223
- fs28.writeFileSync(promptPath, body, "utf-8");
17617
+ fs30.writeFileSync(promptPath, body, "utf-8");
17224
17618
  const vars = {
17225
17619
  promptFile: promptPath,
17226
17620
  agentId: RESOLVE_OPEN_QUESTION_AGENT_STEM,
@@ -17284,7 +17678,7 @@ ${cli.message}`,
17284
17678
  }
17285
17679
  async function runOpenCodeMarkdownEvidenceRepairLoop(input) {
17286
17680
  const totalMarkdownRuns = 1 + input.maxMarkdownEvidenceRepairs;
17287
- fs28.mkdirSync(input.runDir, { recursive: true });
17681
+ fs30.mkdirSync(input.runDir, { recursive: true });
17288
17682
  let attemptIndex = 0;
17289
17683
  let capturedProducerSessionId;
17290
17684
  const repair = await runWorkstationRepairLoop({
@@ -17307,7 +17701,7 @@ async function runOpenCodeMarkdownEvidenceRepairLoop(input) {
17307
17701
  const idx = attemptIndex;
17308
17702
  const promptPath = input.promptPathForAttempt(idx);
17309
17703
  attemptIndex += 1;
17310
- fs28.writeFileSync(promptPath, body, "utf-8");
17704
+ fs30.writeFileSync(promptPath, body, "utf-8");
17311
17705
  const vars = input.argvVarsForPrompt(promptPath);
17312
17706
  const expanded = expandArgvTemplate3(input.argvTemplate, vars);
17313
17707
  const followUpSessionId = input.resolveFollowUpSessionId({
@@ -17799,7 +18193,7 @@ async function runCoordinationListWorkstation(opts) {
17799
18193
  let schemaAbsoluteForList;
17800
18194
  if (effectiveListSchemaFile) {
17801
18195
  schemaAbsoluteForList = schemaRef(opts.worktreeRoot, effectiveListSchemaFile);
17802
- if (!fs28.existsSync(schemaAbsoluteForList)) {
18196
+ if (!fs30.existsSync(schemaAbsoluteForList)) {
17803
18197
  return {
17804
18198
  ok: false,
17805
18199
  message: `JSON Schema not found: ${schemaAbsoluteForList}
@@ -17812,11 +18206,11 @@ Run **Materialize agents** first (copies list schemas into this folder\u2019s \`
17812
18206
  }
17813
18207
  if (opts.step === "reviewExperiencesList" && effectiveListSchemaFile) {
17814
18208
  const schemaAbs = schemaRef(opts.worktreeRoot, effectiveListSchemaFile);
17815
- if (fs28.existsSync(outputFileAbsolute)) {
18209
+ if (fs30.existsSync(outputFileAbsolute)) {
17816
18210
  const v = validateCoordinationListJson(outputFileAbsolute, schemaAbs);
17817
18211
  if (v.ok) {
17818
18212
  try {
17819
- const raw = fs28.readFileSync(outputFileAbsolute, "utf-8");
18213
+ const raw = fs30.readFileSync(outputFileAbsolute, "utf-8");
17820
18214
  const data = JSON.parse(raw);
17821
18215
  if (Array.isArray(data.views) && data.views.length === 0) {
17822
18216
  return {
@@ -17832,9 +18226,9 @@ Run **Materialize agents** first (copies list schemas into this folder\u2019s \`
17832
18226
  }
17833
18227
  }
17834
18228
  }
17835
- fs28.mkdirSync(path26.dirname(outputFileAbsolute), { recursive: true });
18229
+ fs30.mkdirSync(path26.dirname(outputFileAbsolute), { recursive: true });
17836
18230
  const runDir = path26.join(opts.worktreeRoot, ".opencode", "_run");
17837
- fs28.mkdirSync(runDir, { recursive: true });
18231
+ fs30.mkdirSync(runDir, { recursive: true });
17838
18232
  const scopeSuffix = (opts.step === "listUseCases" || opts.step === "reviewUseCasesList") && opts.listTarget?.featureCode ? `-${opts.listTarget.featureCode}` : (opts.step === "listScenarios" || opts.step === "reviewScenariosList") && opts.listTarget?.featureCode && opts.listTarget?.useCaseCode ? `-${opts.listTarget.featureCode}_${opts.listTarget.useCaseCode}` : (opts.step === "listEntityFields" || opts.step === "reviewEntityFieldsList") && opts.listTarget?.entityCode ? `-${opts.listTarget.entityCode}` : "";
17839
18233
  const rawRepair = opts.listJsonSchemaRepairAttempts;
17840
18234
  let maxRepairAttempts = rawRepair === void 0 ? 1 : Math.floor(Number(rawRepair));
@@ -17853,8 +18247,8 @@ Run **Materialize agents** first (copies list schemas into this folder\u2019s \`
17853
18247
  let preImageDocForStableWrite = {};
17854
18248
  if (effectiveListSchemaFile && schemaAbsoluteForList && shouldApplyStableMergeForCoordinationBasename(outputBasename)) {
17855
18249
  try {
17856
- if (fs28.existsSync(outputFileAbsolute)) {
17857
- preImageDocForStableWrite = JSON.parse(fs28.readFileSync(outputFileAbsolute, "utf-8"));
18250
+ if (fs30.existsSync(outputFileAbsolute)) {
18251
+ preImageDocForStableWrite = JSON.parse(fs30.readFileSync(outputFileAbsolute, "utf-8"));
17858
18252
  }
17859
18253
  } catch {
17860
18254
  preImageDocForStableWrite = {};
@@ -18043,7 +18437,7 @@ Run **Materialize agents** first (copies list schemas into this folder\u2019s \`
18043
18437
  );
18044
18438
  const promptPath = path26.join(runDir, `${opts.step}${scopeSuffix}-a${attempt}-${Date.now()}.prompt.txt`);
18045
18439
  lastPromptPath = promptPath;
18046
- fs28.writeFileSync(promptPath, body, "utf-8");
18440
+ fs30.writeFileSync(promptPath, body, "utf-8");
18047
18441
  const vars = {
18048
18442
  promptFile: promptPath,
18049
18443
  agentId: STEP_OPEN_CODE_AGENT_IDS[opts.step],
@@ -18283,9 +18677,9 @@ async function runDetailMarkdownWorkstation(opts) {
18283
18677
  }
18284
18678
  maxMarkdownEvidenceRepairs = Math.min(5, Math.max(0, maxMarkdownEvidenceRepairs));
18285
18679
  const totalMarkdownRuns = 1 + maxMarkdownEvidenceRepairs;
18286
- fs28.mkdirSync(path26.dirname(outputFileAbsolute), { recursive: true });
18680
+ fs30.mkdirSync(path26.dirname(outputFileAbsolute), { recursive: true });
18287
18681
  const runDir = path26.join(opts.worktreeRoot, ".opencode", "_run");
18288
- fs28.mkdirSync(runDir, { recursive: true });
18682
+ fs30.mkdirSync(runDir, { recursive: true });
18289
18683
  const safeStem = opts.target.outputBasename.replace(/[^A-Za-z0-9_.-]+/g, "_").slice(0, 120);
18290
18684
  let lastPromptPath = "";
18291
18685
  let lastCliMessage = "";
@@ -18527,18 +18921,18 @@ Expected output: ${outputFileAbsolute}`;
18527
18921
  }
18528
18922
 
18529
18923
  // src/analysis/worktreeManager.ts
18530
- var import_child_process3 = require("child_process");
18531
- var fs29 = __toESM(require("fs"));
18532
- var os2 = __toESM(require("os"));
18924
+ var import_child_process4 = require("child_process");
18925
+ var fs31 = __toESM(require("fs"));
18926
+ var os4 = __toESM(require("os"));
18533
18927
  var path27 = __toESM(require("path"));
18534
18928
 
18535
18929
  // src/analysis/gitWorktreeStaleRecovery.ts
18536
- var import_child_process2 = require("child_process");
18930
+ var import_child_process3 = require("child_process");
18537
18931
  function isMissingRegisteredWorktreeError(combinedStderrStdout) {
18538
18932
  return /missing but already registered worktree/i.test(combinedStderrStdout);
18539
18933
  }
18540
18934
  function gitWorktreePruneSync(repoRoot) {
18541
- const r = (0, import_child_process2.spawnSync)("git", ["worktree", "prune"], {
18935
+ const r = (0, import_child_process3.spawnSync)("git", ["worktree", "prune"], {
18542
18936
  cwd: repoRoot,
18543
18937
  encoding: "utf-8",
18544
18938
  timeout: 6e4
@@ -18559,7 +18953,7 @@ function maxEasyspecsWorktreeIndex(parentDir) {
18559
18953
  let max = 0;
18560
18954
  let entries;
18561
18955
  try {
18562
- entries = fs29.readdirSync(parentDir, { withFileTypes: true });
18956
+ entries = fs31.readdirSync(parentDir, { withFileTypes: true });
18563
18957
  } catch {
18564
18958
  return 0;
18565
18959
  }
@@ -18582,19 +18976,19 @@ function formatEasyspecsWorktreeFolderName(index) {
18582
18976
  return `easyspecs-${String(index).padStart(3, "0")}`;
18583
18977
  }
18584
18978
  function allocateEasyspecsWorktreePath(parentDir) {
18585
- fs29.mkdirSync(parentDir, { recursive: true });
18979
+ fs31.mkdirSync(parentDir, { recursive: true });
18586
18980
  const start = maxEasyspecsWorktreeIndex(parentDir);
18587
18981
  for (let i = start + 1; i < start + 1e4; i++) {
18588
18982
  const name = formatEasyspecsWorktreeFolderName(i);
18589
18983
  const wt = path27.join(parentDir, name);
18590
- if (!fs29.existsSync(wt)) {
18984
+ if (!fs31.existsSync(wt)) {
18591
18985
  return wt;
18592
18986
  }
18593
18987
  }
18594
18988
  return null;
18595
18989
  }
18596
18990
  function readHeadBranchShort(repoRoot) {
18597
- const r = (0, import_child_process3.spawnSync)("git", ["symbolic-ref", "--short", "-q", "HEAD"], {
18991
+ const r = (0, import_child_process4.spawnSync)("git", ["symbolic-ref", "--short", "-q", "HEAD"], {
18598
18992
  cwd: repoRoot,
18599
18993
  encoding: "utf-8",
18600
18994
  timeout: 3e4
@@ -18612,20 +19006,20 @@ function attachWorktreeHandle(worktreePath, repositoryRoot) {
18612
19006
  path: wt,
18613
19007
  repoRoot: repo,
18614
19008
  remove() {
18615
- (0, import_child_process3.spawnSync)("git", ["worktree", "remove", "--force", wt], {
19009
+ (0, import_child_process4.spawnSync)("git", ["worktree", "remove", "--force", wt], {
18616
19010
  cwd: repo,
18617
19011
  encoding: "utf-8",
18618
19012
  timeout: 6e4
18619
19013
  });
18620
19014
  try {
18621
- fs29.rmSync(wt, { recursive: true, force: true });
19015
+ fs31.rmSync(wt, { recursive: true, force: true });
18622
19016
  } catch {
18623
19017
  }
18624
19018
  }
18625
19019
  };
18626
19020
  }
18627
19021
  function createAnalysisWorktree(repoRoot, options) {
18628
- const parent = path27.join(os2.tmpdir(), "easyspecs-analysis");
19022
+ const parent = path27.join(os4.tmpdir(), "easyspecs-analysis");
18629
19023
  const wt = allocateEasyspecsWorktreePath(parent);
18630
19024
  if (!wt) {
18631
19025
  return {
@@ -18635,7 +19029,7 @@ function createAnalysisWorktree(repoRoot, options) {
18635
19029
  }
18636
19030
  const sourceBranchAtCreation = readHeadBranchShort(repoRoot);
18637
19031
  for (let attempt = 0; attempt < 2; attempt++) {
18638
- const r = (0, import_child_process3.spawnSync)("git", ["worktree", "add", "--detach", wt, "HEAD"], {
19032
+ const r = (0, import_child_process4.spawnSync)("git", ["worktree", "add", "--detach", wt, "HEAD"], {
18639
19033
  cwd: repoRoot,
18640
19034
  encoding: "utf-8",
18641
19035
  timeout: 12e4
@@ -18753,7 +19147,7 @@ function noteOpenCodeAgentLaunched() {
18753
19147
  }
18754
19148
 
18755
19149
  // src/contextIndexAssembler.ts
18756
- var fs30 = __toESM(require("fs"));
19150
+ var fs32 = __toESM(require("fs"));
18757
19151
  var path28 = __toESM(require("path"));
18758
19152
 
18759
19153
  // src/srsModel.ts
@@ -18788,7 +19182,7 @@ function tryAttachMarkdown(node, contextDir2, relativePath) {
18788
19182
  }
18789
19183
  const full = path28.join(contextDir2, norm);
18790
19184
  try {
18791
- if (!fs30.existsSync(full) || !fs30.statSync(full).isFile()) {
19185
+ if (!fs32.existsSync(full) || !fs32.statSync(full).isFile()) {
18792
19186
  return false;
18793
19187
  }
18794
19188
  } catch {
@@ -18846,10 +19240,10 @@ function mergePersistedIndexUploadMetadata(previous, next) {
18846
19240
  function tryReadExistingIndexForMerge(contextDir2) {
18847
19241
  const p = path28.join(contextDir2, "index-application-context.json");
18848
19242
  try {
18849
- if (!fs30.existsSync(p)) {
19243
+ if (!fs32.existsSync(p)) {
18850
19244
  return null;
18851
19245
  }
18852
- const j = JSON.parse(fs30.readFileSync(p, "utf8"));
19246
+ const j = JSON.parse(fs32.readFileSync(p, "utf8"));
18853
19247
  if (j && typeof j === "object" && j.kind === APPLICATION_CONTEXT_KIND) {
18854
19248
  return j;
18855
19249
  }
@@ -19004,7 +19398,7 @@ function applyDetailMarkdownToDocument(doc, contextDir2) {
19004
19398
  }
19005
19399
  function readJson2(filePath) {
19006
19400
  try {
19007
- const raw = fs30.readFileSync(filePath, "utf-8");
19401
+ const raw = fs32.readFileSync(filePath, "utf-8");
19008
19402
  return JSON.parse(raw);
19009
19403
  } catch {
19010
19404
  return null;
@@ -19184,11 +19578,11 @@ function writeIndexApplicationContext(contextDir2, title, options) {
19184
19578
  const target = path28.join(contextDir2, "index-application-context.json");
19185
19579
  const tmp = `${target}.${process.pid}.tmp`;
19186
19580
  try {
19187
- fs30.writeFileSync(tmp, JSON.stringify(doc, null, 2), "utf-8");
19188
- fs30.renameSync(tmp, target);
19581
+ fs32.writeFileSync(tmp, JSON.stringify(doc, null, 2), "utf-8");
19582
+ fs32.renameSync(tmp, target);
19189
19583
  } catch (e) {
19190
19584
  try {
19191
- fs30.unlinkSync(tmp);
19585
+ fs32.unlinkSync(tmp);
19192
19586
  } catch {
19193
19587
  }
19194
19588
  throw e;
@@ -19197,7 +19591,7 @@ function writeIndexApplicationContext(contextDir2, title, options) {
19197
19591
  }
19198
19592
 
19199
19593
  // src/pipelines/linkMapping/linkMappingPipeline.ts
19200
- var fs31 = __toESM(require("node:fs"));
19594
+ var fs33 = __toESM(require("node:fs"));
19201
19595
  var path29 = __toESM(require("node:path"));
19202
19596
  var SLUG2 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
19203
19597
  function safeStr2(v) {
@@ -19222,7 +19616,7 @@ function slugOrFallback2(row2) {
19222
19616
  }
19223
19617
  function readJson3(filePath) {
19224
19618
  try {
19225
- const raw = fs31.readFileSync(filePath, "utf-8");
19619
+ const raw = fs33.readFileSync(filePath, "utf-8");
19226
19620
  return JSON.parse(raw);
19227
19621
  } catch {
19228
19622
  return null;
@@ -19254,7 +19648,7 @@ function existsContextFile(contextDir2, rel) {
19254
19648
  }
19255
19649
  const full = path29.join(contextDir2, norm);
19256
19650
  try {
19257
- return fs31.existsSync(full) && fs31.statSync(full).isFile();
19651
+ return fs33.existsSync(full) && fs33.statSync(full).isFile();
19258
19652
  } catch {
19259
19653
  return false;
19260
19654
  }
@@ -19351,7 +19745,7 @@ ${lines.join("\n")}
19351
19745
  function collectMarkdownFilesRecursive(dir, acc) {
19352
19746
  let entries;
19353
19747
  try {
19354
- entries = fs31.readdirSync(dir, { withFileTypes: true });
19748
+ entries = fs33.readdirSync(dir, { withFileTypes: true });
19355
19749
  } catch {
19356
19750
  return;
19357
19751
  }
@@ -19372,7 +19766,7 @@ function validateEasyspecsNavLinksInContext(contextDirAbs) {
19372
19766
  for (const abs of mdFiles) {
19373
19767
  let raw;
19374
19768
  try {
19375
- raw = fs31.readFileSync(abs, "utf8");
19769
+ raw = fs33.readFileSync(abs, "utf8");
19376
19770
  } catch {
19377
19771
  continue;
19378
19772
  }
@@ -19398,7 +19792,7 @@ function validateEasyspecsNavLinksInContext(contextDirAbs) {
19398
19792
  }
19399
19793
  const target = path29.normalize(path29.join(path29.dirname(abs), href));
19400
19794
  try {
19401
- if (!fs31.existsSync(target) || !fs31.statSync(target).isFile()) {
19795
+ if (!fs33.existsSync(target) || !fs33.statSync(target).isFile()) {
19402
19796
  broken.push(`${path29.relative(contextDirAbs, abs)} \u2192 ${href}`);
19403
19797
  }
19404
19798
  } catch {
@@ -19424,7 +19818,7 @@ function validateEasyspecsNavLinksInContext(contextDirAbs) {
19424
19818
  }
19425
19819
  const target = path29.normalize(path29.join(path29.dirname(abs), href));
19426
19820
  try {
19427
- if (!fs31.existsSync(target) || !fs31.statSync(target).isFile()) {
19821
+ if (!fs33.existsSync(target) || !fs33.statSync(target).isFile()) {
19428
19822
  broken.push(`${path29.relative(contextDirAbs, abs)} \u2192 ${href}`);
19429
19823
  }
19430
19824
  } catch {
@@ -19632,7 +20026,7 @@ function renderProjectMdSections(contextDir2) {
19632
20026
  }
19633
20027
  }
19634
20028
  const dmListPath = path29.join(contextDir2, "data-model-list.json");
19635
- if (dmLines.length === 0 && fs31.existsSync(dmListPath)) {
20029
+ if (dmLines.length === 0 && fs33.existsSync(dmListPath)) {
19636
20030
  dmLines.push(bulletLink("Data model registry (JSON)", "./data-model-list.json"));
19637
20031
  }
19638
20032
  chunks.push("### Data model", "", dmLines.length ? dmLines.join("\n") : NONE_LINE, "");
@@ -19640,23 +20034,23 @@ function renderProjectMdSections(contextDir2) {
19640
20034
  }
19641
20035
  function patchOneFile(contextDir2, basename17, innerChildren, innerParents, opts) {
19642
20036
  const abs = path29.join(contextDir2, basename17);
19643
- if (!fs31.existsSync(abs)) {
20037
+ if (!fs33.existsSync(abs)) {
19644
20038
  return;
19645
20039
  }
19646
20040
  let body;
19647
20041
  try {
19648
- body = fs31.readFileSync(abs, "utf8");
20042
+ body = fs33.readFileSync(abs, "utf8");
19649
20043
  } catch (e) {
19650
20044
  opts.log?.(`[pipeline:link-mapping] skip read ${basename17}: ${e instanceof Error ? e.message : String(e)}`);
19651
20045
  return;
19652
20046
  }
19653
20047
  let next = replaceOrAppendRegion(body, NAV_CHILDREN_START, NAV_CHILDREN_END, innerChildren);
19654
20048
  next = replaceOrAppendRegion(next, NAV_PARENTS_START, NAV_PARENTS_END, innerParents);
19655
- fs31.writeFileSync(abs, next, "utf8");
20049
+ fs33.writeFileSync(abs, next, "utf8");
19656
20050
  }
19657
20051
  function runLinkMappingPipeline(contextDirAbs, opts = {}) {
19658
20052
  const contextDir2 = path29.resolve(contextDirAbs);
19659
- if (!fs31.existsSync(contextDir2) || !fs31.statSync(contextDir2).isDirectory()) {
20053
+ if (!fs33.existsSync(contextDir2) || !fs33.statSync(contextDir2).isDirectory()) {
19660
20054
  return { ok: false, error: `Context directory does not exist: ${contextDir2}` };
19661
20055
  }
19662
20056
  const edges = buildNavEdges(contextDir2);
@@ -19684,7 +20078,7 @@ function runLinkMappingPipeline(contextDirAbs, opts = {}) {
19684
20078
  continue;
19685
20079
  }
19686
20080
  const abs = path29.join(contextDir2, basename17);
19687
- if (!fs31.existsSync(abs)) {
20081
+ if (!fs33.existsSync(abs)) {
19688
20082
  continue;
19689
20083
  }
19690
20084
  const childRows = edges.children.get(basename17) ?? [];
@@ -19718,15 +20112,15 @@ var path30 = __toESM(require("node:path"));
19718
20112
  var vscode2 = __toESM(require_vscode_stub());
19719
20113
 
19720
20114
  // src/config/easyspecsAceConfigRead.ts
19721
- var fs32 = __toESM(require("node:fs"));
20115
+ var fs34 = __toESM(require("node:fs"));
19722
20116
  function readRawConfigJson(repoRoot) {
19723
20117
  const p = easyspecsConfigPath(repoRoot);
19724
- if (!fs32.existsSync(p)) {
20118
+ if (!fs34.existsSync(p)) {
19725
20119
  return void 0;
19726
20120
  }
19727
20121
  let raw;
19728
20122
  try {
19729
- raw = fs32.readFileSync(p, "utf8");
20123
+ raw = fs34.readFileSync(p, "utf8");
19730
20124
  } catch {
19731
20125
  return void 0;
19732
20126
  }
@@ -19862,7 +20256,7 @@ function getAceOfflineLearnAfterSameSessionTrace(analysisCheckoutRoot) {
19862
20256
  }
19863
20257
 
19864
20258
  // src/analysis/repoSurfaceAssessment.ts
19865
- var fs33 = __toESM(require("fs"));
20259
+ var fs35 = __toESM(require("fs"));
19866
20260
  var path31 = __toESM(require("path"));
19867
20261
  var REPO_SURFACE_SCAN_BASENAME = "repo-surface-scan.json";
19868
20262
  function stripBom(s) {
@@ -19871,7 +20265,7 @@ function stripBom(s) {
19871
20265
  function readRepoSurfaceAssessment(contextDir2) {
19872
20266
  const p = path31.join(contextDir2, REPO_SURFACE_SCAN_BASENAME);
19873
20267
  try {
19874
- const raw = stripBom(fs33.readFileSync(p, "utf-8"));
20268
+ const raw = stripBom(fs35.readFileSync(p, "utf-8"));
19875
20269
  const data = JSON.parse(raw);
19876
20270
  if (!data || typeof data !== "object") {
19877
20271
  return null;
@@ -19892,8 +20286,8 @@ function readRepoSurfaceAssessment(contextDir2) {
19892
20286
  }
19893
20287
  function writeEmptyExperiencesListJson(contextDir2) {
19894
20288
  const p = path31.join(contextDir2, "experiences-list.json");
19895
- fs33.mkdirSync(path31.dirname(p), { recursive: true });
19896
- fs33.writeFileSync(
20289
+ fs35.mkdirSync(path31.dirname(p), { recursive: true });
20290
+ fs35.writeFileSync(
19897
20291
  p,
19898
20292
  `${JSON.stringify(
19899
20293
  {
@@ -19909,6 +20303,31 @@ function writeEmptyExperiencesListJson(contextDir2) {
19909
20303
  );
19910
20304
  }
19911
20305
 
20306
+ // src/config/cpuPressureSample.ts
20307
+ var os5 = __toESM(require("node:os"));
20308
+ function createDefaultCpuPressureSampler() {
20309
+ const n = Math.max(1, os5.cpus()?.length ?? 1);
20310
+ return () => {
20311
+ const [l1] = os5.loadavg();
20312
+ if (!Number.isFinite(l1) || l1 <= 0) {
20313
+ return 0;
20314
+ }
20315
+ return Math.min(1, l1 / n);
20316
+ };
20317
+ }
20318
+ function nextAdaptiveMaxAfterCpuSample(p) {
20319
+ const threshold = p.threshold ?? 0.96;
20320
+ if (p.activeRunningCount < 1 || !Number.isFinite(p.ratio) || p.ratio <= threshold) {
20321
+ return { adaptiveMax: p.priorAdaptiveMax, changed: false };
20322
+ }
20323
+ const 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
+
19912
20331
  // src/pipelines/synthesis/synthesisPipeline.ts
19913
20332
  var FE = /^FE-\d+$/;
19914
20333
  var UC = /^UC-\d+$/;
@@ -19921,7 +20340,7 @@ function stripBom2(s) {
19921
20340
  }
19922
20341
  function readJson4(filePath) {
19923
20342
  try {
19924
- const raw = stripBom2(fs34.readFileSync(filePath, "utf-8"));
20343
+ const raw = stripBom2(fs36.readFileSync(filePath, "utf-8"));
19925
20344
  return JSON.parse(raw);
19926
20345
  } catch {
19927
20346
  return null;
@@ -20016,7 +20435,7 @@ function featureDetailTarget(contextDir2, code, name, slug) {
20016
20435
  displayName: "Feature detail",
20017
20436
  outputBasename: basename17,
20018
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).`,
20019
- exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
20438
+ exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
20020
20439
  };
20021
20440
  }
20022
20441
  function viewDetailTarget(row2, contextDir2) {
@@ -20027,7 +20446,7 @@ function viewDetailTarget(row2, contextDir2) {
20027
20446
  displayName: "View detail",
20028
20447
  outputBasename: basename17,
20029
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.`,
20030
- exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
20449
+ exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
20031
20450
  };
20032
20451
  }
20033
20452
  function interactionDetailTarget(viewCode, ix, contextDir2) {
@@ -20038,7 +20457,7 @@ function interactionDetailTarget(viewCode, ix, contextDir2) {
20038
20457
  displayName: "Interaction detail",
20039
20458
  outputBasename: basename17,
20040
20459
  taskDescription: `Document interaction **${ix.code}** (**${ix.name}**) on view **${viewCode}** per \`.gluecharm/context/experiences-list.json\`.`,
20041
- exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
20460
+ exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
20042
20461
  };
20043
20462
  }
20044
20463
  function serviceDetailTarget(row2, contextDir2) {
@@ -20049,7 +20468,7 @@ function serviceDetailTarget(row2, contextDir2) {
20049
20468
  displayName: "Service detail",
20050
20469
  outputBasename: basename17,
20051
20470
  taskDescription: `Describe service **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/services-list.json\`: responsibilities, consumers, errors, integration points.`,
20052
- exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
20471
+ exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
20053
20472
  };
20054
20473
  }
20055
20474
  function methodDetailTarget(svc, m, contextDir2) {
@@ -20060,7 +20479,7 @@ function methodDetailTarget(svc, m, contextDir2) {
20060
20479
  displayName: "Method detail",
20061
20480
  outputBasename: basename17,
20062
20481
  taskDescription: `Document method **${m.code}** (**${m.name}**) on service **${svc.code}** per \`.gluecharm/context/services-list.json\`.`,
20063
- exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
20482
+ exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
20064
20483
  };
20065
20484
  }
20066
20485
  function entityDetailTarget(dmCode, ename, slug, contextDir2) {
@@ -20071,7 +20490,7 @@ function entityDetailTarget(dmCode, ename, slug, contextDir2) {
20071
20490
  displayName: "Entity detail",
20072
20491
  outputBasename: basename17,
20073
20492
  taskDescription: `Describe entity **${dmCode}** (**${ename}**, slug **${slug}**) per \`.gluecharm/context/data-model-list.json\`: lifecycle, invariants, storage, ORM/schema mapping.`,
20074
- exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
20493
+ exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
20075
20494
  };
20076
20495
  }
20077
20496
  function fieldDetailTarget(dmCode, fdCode, fname, fSlug, contextDir2) {
@@ -20082,7 +20501,7 @@ function fieldDetailTarget(dmCode, fdCode, fname, fSlug, contextDir2) {
20082
20501
  displayName: "Field detail",
20083
20502
  outputBasename: basename17,
20084
20503
  taskDescription: `Document field **${fdCode}** (**${fname}**) on entity **${dmCode}** per \`.gluecharm/context/${dmCode}-fields-list.json\`. Cite types and constraints with file and line.`,
20085
- exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
20504
+ exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
20086
20505
  };
20087
20506
  }
20088
20507
  function toolDetailTarget(row2, contextDir2) {
@@ -20093,7 +20512,7 @@ function toolDetailTarget(row2, contextDir2) {
20093
20512
  displayName: "Tool detail",
20094
20513
  outputBasename: basename17,
20095
20514
  taskDescription: `Describe tool **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/tech-stack-list.json\`: role, version hints, configuration, boundaries.`,
20096
- exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
20515
+ exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
20097
20516
  };
20098
20517
  }
20099
20518
  function useCaseDetailTarget(feCode, ucCode, ucName, ucSlug, contextDir2) {
@@ -20106,7 +20525,7 @@ function useCaseDetailTarget(feCode, ucCode, ucName, ucSlug, contextDir2) {
20106
20525
  taskDescription: `Document use case **${ucCode}** (**${ucName}**) under feature **${feCode}** per \`.gluecharm/context/${feCode}-use-cases-list.json\`. Do not change stable codes.
20107
20526
 
20108
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.`,
20109
- exists: fs34.existsSync(path32.join(contextDir2, ucBase)) && fs34.statSync(path32.join(contextDir2, ucBase)).size > 0
20528
+ exists: fs36.existsSync(path32.join(contextDir2, ucBase)) && fs36.statSync(path32.join(contextDir2, ucBase)).size > 0
20110
20529
  };
20111
20530
  }
20112
20531
  function scenarioDetailTarget(feCode, ucCode, scCode, scName, contextDir2) {
@@ -20117,7 +20536,7 @@ function scenarioDetailTarget(feCode, ucCode, scCode, scName, contextDir2) {
20117
20536
  displayName: "Scenario detail",
20118
20537
  outputBasename: basename17,
20119
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.`,
20120
- exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
20539
+ exists: fs36.existsSync(path32.join(contextDir2, basename17)) && fs36.statSync(path32.join(contextDir2, basename17)).size > 0
20121
20540
  };
20122
20541
  }
20123
20542
  function parentsDone(item, byId) {
@@ -20536,8 +20955,29 @@ async function runWorkstationWithOuterAttempts(item, worktreeRoot, workspaceLabe
20536
20955
  };
20537
20956
  }
20538
20957
  async function drainWorkstationPool(p) {
20539
- const maxC = clampConcurrency(p.oc.maxConcurrentOpenCodeAgents);
20540
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);
20541
20981
  const artefactRunId = readArtefactRunSnapshot(storageContext)?.runId ?? "unknown-run";
20542
20982
  let active = 0;
20543
20983
  let wake;
@@ -20593,9 +21033,10 @@ async function drainWorkstationPool(p) {
20593
21033
  pump();
20594
21034
  return;
20595
21035
  }
21036
+ applyCpuPressure();
20596
21037
  item.status = "running";
20597
21038
  await persist();
20598
- log(`[pool] start ${id} (active ${active}/${maxC})`);
21039
+ log(`[pool] start ${id} (active ${active}/${currentCap()})`);
20599
21040
  const r = await runWorkstationWithOuterAttempts(
20600
21041
  item,
20601
21042
  worktreeRoot,
@@ -20650,9 +21091,14 @@ async function drainWorkstationPool(p) {
20650
21091
  await p.onItemComplete?.(id);
20651
21092
  pump();
20652
21093
  };
21094
+ let pressureInterval;
21095
+ if (throttle) {
21096
+ const intervalMs = p.__testOnlyCpuPressureIntervalMs ?? 3e4;
21097
+ pressureInterval = setInterval(() => applyCpuPressure(), intervalMs);
21098
+ }
20653
21099
  try {
20654
21100
  while (true) {
20655
- while (fifo.length > 0 && active < maxC && !abortSignal?.aborted) {
21101
+ while (fifo.length > 0 && active < currentCap() && !abortSignal?.aborted) {
20656
21102
  const id = fifo.shift();
20657
21103
  const it = byId.get(id);
20658
21104
  if (!it || it.status !== "pending" || !parentsDone(it, byId)) {
@@ -20672,11 +21118,14 @@ async function drainWorkstationPool(p) {
20672
21118
  await waitTurn();
20673
21119
  continue;
20674
21120
  }
20675
- if (fifo.length === 0 || active >= maxC) {
21121
+ if (fifo.length === 0 || active >= currentCap()) {
20676
21122
  await waitTurn();
20677
21123
  }
20678
21124
  }
20679
21125
  } finally {
21126
+ if (pressureInterval) {
21127
+ clearInterval(pressureInterval);
21128
+ }
20680
21129
  if (poolAbortListenerRegistered && abortSignal) {
20681
21130
  abortSignal.removeEventListener("abort", onPipelineAbort);
20682
21131
  }
@@ -20716,7 +21165,7 @@ async function runSynthesisPipelineDrainFromPreparedWorktree(storageContext, rep
20716
21165
  offlineLearnAfterSameSessionTrace: getAceOfflineLearnAfterSameSessionTrace(handle.path)
20717
21166
  };
20718
21167
  const contextDir2 = path32.join(handle.path, ".gluecharm", "context");
20719
- fs34.mkdirSync(contextDir2, { recursive: true });
21168
+ fs36.mkdirSync(contextDir2, { recursive: true });
20720
21169
  const initialItems = buildRootItems();
20721
21170
  await startArtefactRun(storageContext, repoRoot, handle.path, initialItems);
20722
21171
  await cb.onBootstrapReady?.({ worktreeRoot: handle.path, contextDir: contextDir2 });
@@ -20817,27 +21266,27 @@ async function runSynthesisPipeline(storageContext, repoRoot, workspaceLabel, ex
20817
21266
  }
20818
21267
 
20819
21268
  // src/workspaceContextPromote.ts
20820
- var fs35 = __toESM(require("fs"));
21269
+ var fs37 = __toESM(require("fs"));
20821
21270
  var path33 = __toESM(require("path"));
20822
21271
  function promoteContextDirectoryToWorkspaceFs(sourceContextDir, workspaceRootFs) {
20823
21272
  const dest = path33.join(workspaceRootFs, ".gluecharm", "context");
20824
- fs35.mkdirSync(path33.join(workspaceRootFs, ".gluecharm"), { recursive: true });
20825
- fs35.mkdirSync(dest, { recursive: true });
21273
+ fs37.mkdirSync(path33.join(workspaceRootFs, ".gluecharm"), { recursive: true });
21274
+ fs37.mkdirSync(dest, { recursive: true });
20826
21275
  let names;
20827
21276
  try {
20828
- names = fs35.readdirSync(sourceContextDir);
21277
+ names = fs37.readdirSync(sourceContextDir);
20829
21278
  } catch {
20830
21279
  return { filesCopied: 0 };
20831
21280
  }
20832
21281
  let filesCopied = 0;
20833
21282
  for (const name of names) {
20834
21283
  const srcPath = path33.join(sourceContextDir, name);
20835
- if (!fs35.statSync(srcPath).isFile()) {
21284
+ if (!fs37.statSync(srcPath).isFile()) {
20836
21285
  continue;
20837
21286
  }
20838
- const buf = fs35.readFileSync(srcPath);
21287
+ const buf = fs37.readFileSync(srcPath);
20839
21288
  const target = path33.join(dest, name);
20840
- fs35.writeFileSync(target, buf);
21289
+ fs37.writeFileSync(target, buf);
20841
21290
  filesCopied += 1;
20842
21291
  }
20843
21292
  return { filesCopied };
@@ -21497,7 +21946,7 @@ async function runGenerateContextFactory(deps) {
21497
21946
  }
21498
21947
 
21499
21948
  // src/factory/generateContextFactoryHeadlessHost.ts
21500
- var fs44 = __toESM(require("node:fs"));
21949
+ var fs46 = __toESM(require("node:fs"));
21501
21950
  var path43 = __toESM(require("node:path"));
21502
21951
 
21503
21952
  // src/stores/pipelineRunStore.ts
@@ -21598,11 +22047,11 @@ async function noteAgentsMaterialized(context) {
21598
22047
  }
21599
22048
 
21600
22049
  // src/pipelines/remediation/missingWorkstations.ts
21601
- var fs37 = __toESM(require("fs"));
22050
+ var fs39 = __toESM(require("fs"));
21602
22051
  var path35 = __toESM(require("path"));
21603
22052
 
21604
22053
  // src/analysis/analysisDetailMarkdownDiscovery.ts
21605
- var fs36 = __toESM(require("fs"));
22054
+ var fs38 = __toESM(require("fs"));
21606
22055
  var path34 = __toESM(require("path"));
21607
22056
  var SLUG4 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
21608
22057
  var FE2 = /^FE-\d+$/;
@@ -21624,7 +22073,7 @@ var STEM_TO_AGENT = {
21624
22073
  };
21625
22074
  function readJson5(filePath) {
21626
22075
  try {
21627
- let raw = fs36.readFileSync(filePath, "utf-8");
22076
+ let raw = fs38.readFileSync(filePath, "utf-8");
21628
22077
  if (raw.length > 0 && raw.charCodeAt(0) === 65279) {
21629
22078
  raw = raw.slice(1);
21630
22079
  }
@@ -21892,7 +22341,7 @@ function fileAndValidationFromKind(kind) {
21892
22341
  function classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeRoot) {
21893
22342
  const abs = path35.join(contextDir2, row2.relativePath);
21894
22343
  try {
21895
- const st = fs37.statSync(abs);
22344
+ const st = fs39.statSync(abs);
21896
22345
  if (!st.isFile()) {
21897
22346
  return { kind: "absent", detail: "Path exists but is not a regular file." };
21898
22347
  }
@@ -21930,7 +22379,7 @@ function classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeR
21930
22379
  };
21931
22380
  }
21932
22381
  const schemaAbs = path35.join(worktreeRoot, ".opencode", "schemas", "context-lists", schemaBn);
21933
- if (!fs37.existsSync(schemaAbs)) {
22382
+ if (!fs39.existsSync(schemaAbs)) {
21934
22383
  return {
21935
22384
  kind: "invalid",
21936
22385
  detail: `Schema not found (${schemaBn}). Run **Materialize agents** on this checkout.`
@@ -22166,7 +22615,7 @@ function listMissingWorkstations(contextDir2, worktreeRoot, snapshot) {
22166
22615
  }
22167
22616
  }
22168
22617
  }
22169
- if (!fs37.existsSync(contextDir2)) {
22618
+ if (!fs39.existsSync(contextDir2)) {
22170
22619
  return [...map.values()].sort((a, b) => a.key.localeCompare(b.key));
22171
22620
  }
22172
22621
  const dynamic = discoverDynamicAnalysisTestSteps(contextDir2);
@@ -22346,12 +22795,12 @@ async function runRemediationPipelineMissingPass(p) {
22346
22795
  }
22347
22796
 
22348
22797
  // src/pipelines/coverage/coveragePipeline.ts
22349
- var import_child_process4 = require("child_process");
22350
- var fs39 = __toESM(require("fs"));
22798
+ var import_child_process5 = require("child_process");
22799
+ var fs41 = __toESM(require("fs"));
22351
22800
  var path38 = __toESM(require("path"));
22352
22801
 
22353
22802
  // src/analysis/coverageReferenceValidationSchemaValidate.ts
22354
- var fs38 = __toESM(require("fs"));
22803
+ var fs40 = __toESM(require("fs"));
22355
22804
  var path37 = __toESM(require("path"));
22356
22805
  var import__5 = __toESM(require__());
22357
22806
  function stripUtf8Bom4(s) {
@@ -22381,7 +22830,7 @@ function getValidate() {
22381
22830
  return compiledValidate;
22382
22831
  }
22383
22832
  const schemaPath = bundledCoverageReferenceValidationSchemaPath();
22384
- const schemaRaw = stripUtf8Bom4(fs38.readFileSync(schemaPath, "utf-8"));
22833
+ const schemaRaw = stripUtf8Bom4(fs40.readFileSync(schemaPath, "utf-8"));
22385
22834
  const schema = JSON.parse(schemaRaw);
22386
22835
  const ajv2 = new import__5.default({ allErrors: true, strict: false });
22387
22836
  compiledValidate = ajv2.compile(schema);
@@ -22397,7 +22846,7 @@ function validateCoverageReferenceValidationData(data) {
22397
22846
  function readAndValidateCoverageReferenceValidationFile(jsonAbsolutePath) {
22398
22847
  let raw;
22399
22848
  try {
22400
- raw = stripUtf8Bom4(fs38.readFileSync(jsonAbsolutePath, "utf-8"));
22849
+ raw = stripUtf8Bom4(fs40.readFileSync(jsonAbsolutePath, "utf-8"));
22401
22850
  } catch (e) {
22402
22851
  return {
22403
22852
  ok: false,
@@ -22439,7 +22888,7 @@ var DEFAULT_IGNORE_DIR_BASENAMES = [
22439
22888
  var GIT_LS_FILES_MAX_BUFFER = 64 * 1024 * 1024;
22440
22889
  function tryLoadGitNonIgnoredPathSet(repositoryRootAbs) {
22441
22890
  const root = path38.resolve(repositoryRootAbs);
22442
- if (!fs39.existsSync(path38.join(root, ".git"))) {
22891
+ if (!fs41.existsSync(path38.join(root, ".git"))) {
22443
22892
  return null;
22444
22893
  }
22445
22894
  const env = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
@@ -22450,8 +22899,8 @@ function tryLoadGitNonIgnoredPathSet(repositoryRootAbs) {
22450
22899
  env
22451
22900
  };
22452
22901
  try {
22453
- const tracked = (0, import_child_process4.execFileSync)("git", ["-c", "core.quotepath=false", "ls-files", "-z"], opts);
22454
- const others = (0, import_child_process4.execFileSync)(
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)(
22455
22904
  "git",
22456
22905
  ["-c", "core.quotepath=false", "ls-files", "-z", "--others", "--exclude-standard"],
22457
22906
  opts
@@ -22594,7 +23043,7 @@ function extractEvidenceIndexPathCitations(body) {
22594
23043
  function listContextFilesRecursive(dir, acc) {
22595
23044
  let entries;
22596
23045
  try {
22597
- entries = fs39.readdirSync(dir, { withFileTypes: true });
23046
+ entries = fs41.readdirSync(dir, { withFileTypes: true });
22598
23047
  } catch {
22599
23048
  return;
22600
23049
  }
@@ -22612,7 +23061,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
22612
23061
  const walk = (dir) => {
22613
23062
  let entries;
22614
23063
  try {
22615
- entries = fs39.readdirSync(dir, { withFileTypes: true });
23064
+ entries = fs41.readdirSync(dir, { withFileTypes: true });
22616
23065
  } catch {
22617
23066
  return;
22618
23067
  }
@@ -22642,7 +23091,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
22642
23091
  }
22643
23092
  let st;
22644
23093
  try {
22645
- st = fs39.statSync(full);
23094
+ st = fs41.statSync(full);
22646
23095
  } catch {
22647
23096
  continue;
22648
23097
  }
@@ -22652,7 +23101,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
22652
23101
  }
22653
23102
  let buf;
22654
23103
  try {
22655
- buf = fs39.readFileSync(full);
23104
+ buf = fs41.readFileSync(full);
22656
23105
  } catch {
22657
23106
  excludedOut.push({ path: rel, reason: "read error" });
22658
23107
  continue;
@@ -22672,7 +23121,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
22672
23121
  }
22673
23122
  function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings) {
22674
23123
  const references = [];
22675
- if (!fs39.existsSync(contextDirAbs)) {
23124
+ if (!fs41.existsSync(contextDirAbs)) {
22676
23125
  warnings.push(`Context directory missing: ${contextDirAbs}`);
22677
23126
  return references;
22678
23127
  }
@@ -22688,7 +23137,7 @@ function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings
22688
23137
  }
22689
23138
  let raw;
22690
23139
  try {
22691
- raw = fs39.readFileSync(abs, "utf-8");
23140
+ raw = fs41.readFileSync(abs, "utf-8");
22692
23141
  } catch (e) {
22693
23142
  warnings.push(`Skip JSON (read error): ${sourceArtefact} \u2014 ${e instanceof Error ? e.message : String(e)}`);
22694
23143
  continue;
@@ -22719,7 +23168,7 @@ function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings
22719
23168
  if (ext === ".md") {
22720
23169
  let text;
22721
23170
  try {
22722
- const buf = fs39.readFileSync(abs);
23171
+ const buf = fs41.readFileSync(abs);
22723
23172
  text = decodeBufferForLineCount(buf);
22724
23173
  } catch (e) {
22725
23174
  warnings.push(`Skip markdown (read/decode error): ${sourceArtefact} \u2014 ${e instanceof Error ? e.message : String(e)}`);
@@ -22776,7 +23225,7 @@ function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirA
22776
23225
  }
22777
23226
  const excludedFiles = [];
22778
23227
  const gitNonIgnoredPaths = tryLoadGitNonIgnoredPathSet(repoRoot);
22779
- if (fs39.existsSync(path38.join(repoRoot, ".git")) && gitNonIgnoredPaths === null) {
23228
+ if (fs41.existsSync(path38.join(repoRoot, ".git")) && gitNonIgnoredPaths === null) {
22780
23229
  warnings.push(
22781
23230
  "Repository has .git but git ls-files failed or git is unavailable; .gitignore / exclude-standard not applied."
22782
23231
  );
@@ -22827,10 +23276,10 @@ function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirA
22827
23276
  function runCoveragePipeline(opts) {
22828
23277
  const repoRoot = path38.resolve(opts.repositoryRootAbs);
22829
23278
  const contextDir2 = path38.resolve(opts.contextDirAbs);
22830
- if (!fs39.existsSync(repoRoot)) {
23279
+ if (!fs41.existsSync(repoRoot)) {
22831
23280
  return { ok: false, error: `Repository root does not exist: ${repoRoot}` };
22832
23281
  }
22833
- if (!fs39.existsSync(contextDir2)) {
23282
+ if (!fs41.existsSync(contextDir2)) {
22834
23283
  return {
22835
23284
  ok: false,
22836
23285
  error: `Missing .gluecharm/context: ${contextDir2}`
@@ -22852,7 +23301,7 @@ ${schemaCheck.errors.join("\n")}`,
22852
23301
  if (opts.write) {
22853
23302
  try {
22854
23303
  const payload = stableStringifyCoverageDocument(document);
22855
- fs39.writeFileSync(outPath, payload, "utf-8");
23304
+ fs41.writeFileSync(outPath, payload, "utf-8");
22856
23305
  } catch (e) {
22857
23306
  return {
22858
23307
  ok: false,
@@ -22866,11 +23315,11 @@ ${schemaCheck.errors.join("\n")}`,
22866
23315
 
22867
23316
  // src/pipelines/remediation/zeroReferenceWorkstationChain.ts
22868
23317
  var crypto = __toESM(require("crypto"));
22869
- var fs41 = __toESM(require("fs"));
23318
+ var fs43 = __toESM(require("fs"));
22870
23319
  var path40 = __toESM(require("path"));
22871
23320
 
22872
23321
  // src/analysis/zeroReferenceRemediationSchemaValidate.ts
22873
- var fs40 = __toESM(require("fs"));
23322
+ var fs42 = __toESM(require("fs"));
22874
23323
  var path39 = __toESM(require("path"));
22875
23324
  var import__6 = __toESM(require__());
22876
23325
  function stripUtf8Bom5(s) {
@@ -22892,7 +23341,7 @@ function formatAjvErrors6(errors) {
22892
23341
  var ajv = new import__6.default({ allErrors: true, strict: false });
22893
23342
  function compileSchema(basename17) {
22894
23343
  const schemaPath = path39.join(schemasDir(), basename17);
22895
- const schemaRaw = stripUtf8Bom5(fs40.readFileSync(schemaPath, "utf-8"));
23344
+ const schemaRaw = stripUtf8Bom5(fs42.readFileSync(schemaPath, "utf-8"));
22896
23345
  const schema = JSON.parse(schemaRaw);
22897
23346
  return ajv.compile(schema);
22898
23347
  }
@@ -22936,7 +23385,7 @@ var ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS = 5;
22936
23385
  var ZERO_REF_STAGING_FILE_PREVIEW_MAX_CHARS = 6e3;
22937
23386
  function readStagingOutputPreview(outAbs) {
22938
23387
  try {
22939
- const s = fs41.readFileSync(outAbs, "utf-8");
23388
+ const s = fs43.readFileSync(outAbs, "utf-8");
22940
23389
  if (s.length <= ZERO_REF_STAGING_FILE_PREVIEW_MAX_CHARS) {
22941
23390
  return s;
22942
23391
  }
@@ -23219,14 +23668,14 @@ function readNonReferencedFilesFromRepositoryRoot(repositoryRootAbs) {
23219
23668
  return { ok: true, paths, ...generatedAt ? { generatedAt } : {} };
23220
23669
  }
23221
23670
  function readOrInitRoutingDoc(routingAbs, coverageReferenceGeneratedAt) {
23222
- if (!fs41.existsSync(routingAbs)) {
23671
+ if (!fs43.existsSync(routingAbs)) {
23223
23672
  return {
23224
23673
  schemaVersion: ROUTING_SCHEMA_VERSION,
23225
23674
  ...coverageReferenceGeneratedAt ? { coverageReferenceGeneratedAt } : {},
23226
23675
  records: {}
23227
23676
  };
23228
23677
  }
23229
- const raw = fs41.readFileSync(routingAbs, "utf-8");
23678
+ const raw = fs43.readFileSync(routingAbs, "utf-8");
23230
23679
  const data = JSON.parse(raw);
23231
23680
  if (!data.records || typeof data.records !== "object") {
23232
23681
  return {
@@ -23238,10 +23687,10 @@ function readOrInitRoutingDoc(routingAbs, coverageReferenceGeneratedAt) {
23238
23687
  return data;
23239
23688
  }
23240
23689
  function readOrInitTriageDoc(triageAbs) {
23241
- if (!fs41.existsSync(triageAbs)) {
23690
+ if (!fs43.existsSync(triageAbs)) {
23242
23691
  return { schemaVersion: TRIAGE_SCHEMA_VERSION, records: {} };
23243
23692
  }
23244
- const raw = fs41.readFileSync(triageAbs, "utf-8");
23693
+ const raw = fs43.readFileSync(triageAbs, "utf-8");
23245
23694
  const data = JSON.parse(raw);
23246
23695
  if (!data.records || typeof data.records !== "object") {
23247
23696
  return { schemaVersion: TRIAGE_SCHEMA_VERSION, records: {} };
@@ -23292,7 +23741,7 @@ function lineCountRepoFile(worktreeRootAbs, relPosix) {
23292
23741
  const abs = path40.join(worktreeRootAbs, ...relPosix.split("/"));
23293
23742
  let buf;
23294
23743
  try {
23295
- buf = fs41.readFileSync(abs);
23744
+ buf = fs43.readFileSync(abs);
23296
23745
  } catch {
23297
23746
  return 1;
23298
23747
  }
@@ -23346,7 +23795,7 @@ async function applyCoordinationListTriageMerge(input) {
23346
23795
  const cfg = LIST_MERGE_CFG[input.listKind];
23347
23796
  const listPath = path40.join(input.contextDirAbs, cfg.listBasename);
23348
23797
  const schemaPath = path40.join(resolveContextListSchemasDir(), cfg.schemaBasename);
23349
- if (!fs41.existsSync(listPath)) {
23798
+ if (!fs43.existsSync(listPath)) {
23350
23799
  return {
23351
23800
  ok: false,
23352
23801
  message: `${cfg.listBasename} not found \u2014 run coordination step ${LIST_STEP_HINT[input.listKind]} first.`
@@ -23357,7 +23806,7 @@ async function applyCoordinationListTriageMerge(input) {
23357
23806
  return withCoordinationListFileLock(listPath, {}, async () => {
23358
23807
  let raw;
23359
23808
  try {
23360
- raw = fs41.readFileSync(listPath, "utf-8");
23809
+ raw = fs43.readFileSync(listPath, "utf-8");
23361
23810
  } catch (e) {
23362
23811
  return { ok: false, message: e instanceof Error ? e.message : String(e) };
23363
23812
  }
@@ -23425,7 +23874,7 @@ async function applyCoordinationListTriageMerge(input) {
23425
23874
  });
23426
23875
  const tmp = `${listPath}.tmp.${process.pid}`;
23427
23876
  try {
23428
- fs41.writeFileSync(tmp, `${JSON.stringify(doc, null, 2)}
23877
+ fs43.writeFileSync(tmp, `${JSON.stringify(doc, null, 2)}
23429
23878
  `, "utf-8");
23430
23879
  } catch (e) {
23431
23880
  return { ok: false, message: e instanceof Error ? e.message : String(e) };
@@ -23433,13 +23882,13 @@ async function applyCoordinationListTriageMerge(input) {
23433
23882
  const v = validateCoordinationListJson(tmp, schemaPath);
23434
23883
  if (!v.ok) {
23435
23884
  try {
23436
- fs41.unlinkSync(tmp);
23885
+ fs43.unlinkSync(tmp);
23437
23886
  } catch {
23438
23887
  }
23439
23888
  return { ok: false, message: `${cfg.listBasename} validation failed: ${JSON.stringify(v.failure)}` };
23440
23889
  }
23441
23890
  try {
23442
- fs41.renameSync(tmp, listPath);
23891
+ fs43.renameSync(tmp, listPath);
23443
23892
  } catch (e) {
23444
23893
  return { ok: false, message: e instanceof Error ? e.message : String(e) };
23445
23894
  }
@@ -23449,9 +23898,9 @@ async function applyCoordinationListTriageMerge(input) {
23449
23898
  }
23450
23899
  async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, workspaceLabel) {
23451
23900
  const outAbs = stagingPathForTarget(contextDirAbs, "classifier", targetFilePathPosix);
23452
- fs41.mkdirSync(path40.dirname(outAbs), { recursive: true });
23901
+ fs43.mkdirSync(path40.dirname(outAbs), { recursive: true });
23453
23902
  const runDir = path40.join(common.worktreeRoot, ".opencode", "_run");
23454
- fs41.mkdirSync(runDir, { recursive: true });
23903
+ fs43.mkdirSync(runDir, { recursive: true });
23455
23904
  const outputBasename = path40.basename(outAbs);
23456
23905
  const listTaskDescription = [
23457
23906
  `Target file (repo-relative, POSIX): **${targetFilePathPosix}**`,
@@ -23489,7 +23938,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
23489
23938
  ...repairAppendix ? { repairAppendix } : {}
23490
23939
  });
23491
23940
  const promptPath = path40.join(runDir, `zero-ref-classify-a${attempt}-${Date.now()}.prompt.txt`);
23492
- fs41.writeFileSync(promptPath, body, "utf-8");
23941
+ fs43.writeFileSync(promptPath, body, "utf-8");
23493
23942
  const argv = expandArgvTemplate4(common.argvTemplate, {
23494
23943
  promptFile: promptPath,
23495
23944
  agentId: ZERO_REF_CLASSIFY_AGENT_STEM,
@@ -23516,7 +23965,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
23516
23965
  const canRetry = attempt < ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS - 1;
23517
23966
  let st;
23518
23967
  try {
23519
- st = fs41.statSync(outAbs);
23968
+ st = fs43.statSync(outAbs);
23520
23969
  } catch {
23521
23970
  st = void 0;
23522
23971
  }
@@ -23538,7 +23987,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
23538
23987
  }
23539
23988
  let parsed;
23540
23989
  try {
23541
- parsed = JSON.parse(fs41.readFileSync(outAbs, "utf-8"));
23990
+ parsed = JSON.parse(fs43.readFileSync(outAbs, "utf-8"));
23542
23991
  } catch (e) {
23543
23992
  const msg = e instanceof Error ? e.message : String(e);
23544
23993
  lastFailureMessage = `Classifier output not valid JSON: ${msg}`;
@@ -23623,7 +24072,7 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
23623
24072
  const mdAbs = path40.join(contextDirAbs, mdBasename);
23624
24073
  const agentStem = which === "project" ? ZERO_REF_ADD_REF_PROJECT_AGENT_STEM : ZERO_REF_ADD_REF_ARCH_AGENT_STEM;
23625
24074
  const runDir = path40.join(common.worktreeRoot, ".opencode", "_run");
23626
- fs41.mkdirSync(runDir, { recursive: true });
24075
+ fs43.mkdirSync(runDir, { recursive: true });
23627
24076
  const lines = [
23628
24077
  `# SRS-30 \u2014 Add reference to ${mdBasename}`,
23629
24078
  ``,
@@ -23639,7 +24088,7 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
23639
24088
  `- Do not remove unrelated content; append or extend the most appropriate section.`
23640
24089
  ];
23641
24090
  const promptPath = path40.join(runDir, `zero-ref-md-${which}-${Date.now()}.prompt.txt`);
23642
- fs41.writeFileSync(promptPath, lines.join("\n"), "utf-8");
24091
+ fs43.writeFileSync(promptPath, lines.join("\n"), "utf-8");
23643
24092
  const argv = expandArgvTemplate4(common.argvTemplate, {
23644
24093
  promptFile: promptPath,
23645
24094
  agentId: agentStem,
@@ -23666,9 +24115,9 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
23666
24115
  async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathPosix, routingSummary, workspaceLabel, triageScope) {
23667
24116
  const meta = TRIAGE_SCOPE_META[triageScope];
23668
24117
  const outAbs = stagingPathForTarget(contextDirAbs, "triage", targetFilePathPosix);
23669
- fs41.mkdirSync(path40.dirname(outAbs), { recursive: true });
24118
+ fs43.mkdirSync(path40.dirname(outAbs), { recursive: true });
23670
24119
  const runDir = path40.join(common.worktreeRoot, ".opencode", "_run");
23671
- fs41.mkdirSync(runDir, { recursive: true });
24120
+ fs43.mkdirSync(runDir, { recursive: true });
23672
24121
  const outputBasename = path40.basename(outAbs);
23673
24122
  const listTaskDescription = [
23674
24123
  `Target file: **${targetFilePathPosix}** (${workspaceLabel})`,
@@ -23700,7 +24149,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
23700
24149
  ...repairAppendix ? { repairAppendix } : {}
23701
24150
  });
23702
24151
  const promptPath = path40.join(runDir, `zero-ref-triage-a${attempt}-${Date.now()}.prompt.txt`);
23703
- fs41.writeFileSync(promptPath, body, "utf-8");
24152
+ fs43.writeFileSync(promptPath, body, "utf-8");
23704
24153
  const argv = expandArgvTemplate4(common.argvTemplate, {
23705
24154
  promptFile: promptPath,
23706
24155
  agentId: ZERO_REF_TRIAGE_COORD_AGENT_STEM,
@@ -23727,7 +24176,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
23727
24176
  const canRetry = attempt < ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS - 1;
23728
24177
  let st;
23729
24178
  try {
23730
- st = fs41.statSync(outAbs);
24179
+ st = fs43.statSync(outAbs);
23731
24180
  } catch {
23732
24181
  st = void 0;
23733
24182
  }
@@ -23749,7 +24198,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
23749
24198
  }
23750
24199
  let parsed;
23751
24200
  try {
23752
- parsed = JSON.parse(fs41.readFileSync(outAbs, "utf-8"));
24201
+ parsed = JSON.parse(fs43.readFileSync(outAbs, "utf-8"));
23753
24202
  } catch (e) {
23754
24203
  const msg = e instanceof Error ? e.message : String(e);
23755
24204
  lastFailureMessage = `Triage output not valid JSON: ${msg}`;
@@ -23805,7 +24254,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
23805
24254
  return { ok: false, message: lastFailureMessage, stagingPath: outAbs };
23806
24255
  }
23807
24256
  try {
23808
- fs41.writeFileSync(outAbs, `${JSON.stringify(parsed, null, 2)}
24257
+ fs43.writeFileSync(outAbs, `${JSON.stringify(parsed, null, 2)}
23809
24258
  `, "utf-8");
23810
24259
  } catch {
23811
24260
  }
@@ -23823,7 +24272,7 @@ async function runOneUnreferencedFilePipeline(p) {
23823
24272
  }
23824
24273
  let stagingParsed;
23825
24274
  try {
23826
- stagingParsed = JSON.parse(fs41.readFileSync(cr.stagingPath, "utf-8"));
24275
+ stagingParsed = JSON.parse(fs43.readFileSync(cr.stagingPath, "utf-8"));
23827
24276
  } catch (e) {
23828
24277
  return { ok: false, message: String(e) };
23829
24278
  }
@@ -23839,8 +24288,8 @@ async function runOneUnreferencedFilePipeline(p) {
23839
24288
  if (!s.ok) {
23840
24289
  throw new Error(s.errors.join("; "));
23841
24290
  }
23842
- fs41.mkdirSync(path40.dirname(routingAbs), { recursive: true });
23843
- fs41.writeFileSync(routingAbs, s.json, "utf-8");
24291
+ fs43.mkdirSync(path40.dirname(routingAbs), { recursive: true });
24292
+ fs43.writeFileSync(routingAbs, s.json, "utf-8");
23844
24293
  });
23845
24294
  const routing = stagingParsed.routing;
23846
24295
  const routingSummary = typeof stagingParsed.projectRelationSummary === "string" ? stagingParsed.projectRelationSummary : "";
@@ -23871,7 +24320,7 @@ async function runOneUnreferencedFilePipeline(p) {
23871
24320
  }
23872
24321
  let triageParsed;
23873
24322
  try {
23874
- triageParsed = JSON.parse(fs41.readFileSync(tr.stagingPath, "utf-8"));
24323
+ triageParsed = JSON.parse(fs43.readFileSync(tr.stagingPath, "utf-8"));
23875
24324
  } catch (e) {
23876
24325
  return { ok: false, message: String(e) };
23877
24326
  }
@@ -23888,8 +24337,8 @@ async function runOneUnreferencedFilePipeline(p) {
23888
24337
  if (!s.ok) {
23889
24338
  throw new Error(s.errors.join("; "));
23890
24339
  }
23891
- fs41.mkdirSync(path40.dirname(triageAbs), { recursive: true });
23892
- fs41.writeFileSync(triageAbs, s.json, "utf-8");
24340
+ fs43.mkdirSync(path40.dirname(triageAbs), { recursive: true });
24341
+ fs43.writeFileSync(triageAbs, s.json, "utf-8");
23893
24342
  });
23894
24343
  const decision = triageParsed.decision;
23895
24344
  if (decision === "new_item" || decision === "enrich_existing") {
@@ -23977,7 +24426,7 @@ async function runRemediationPipelineZeroRefPass(p) {
23977
24426
  }
23978
24427
 
23979
24428
  // src/pipelines/coverage/coverageExecutionReport.ts
23980
- var fs42 = __toESM(require("fs"));
24429
+ var fs44 = __toESM(require("fs"));
23981
24430
  var path41 = __toESM(require("path"));
23982
24431
  var REFERENCE_COVERAGE_EXECUTION_REPORT_BASENAME = "reference-coverage-execution-report.md";
23983
24432
  function inlineMdText(s) {
@@ -24074,7 +24523,7 @@ function collectNoActionRowsFromRoutingDoc(doc) {
24074
24523
  return rows;
24075
24524
  }
24076
24525
  function readRoutingDocFromDisk(routingAbs) {
24077
- if (!fs42.existsSync(routingAbs)) {
24526
+ if (!fs44.existsSync(routingAbs)) {
24078
24527
  return {
24079
24528
  ok: true,
24080
24529
  doc: { schemaVersion: "1", records: {} }
@@ -24082,7 +24531,7 @@ function readRoutingDocFromDisk(routingAbs) {
24082
24531
  }
24083
24532
  let raw;
24084
24533
  try {
24085
- raw = fs42.readFileSync(routingAbs, "utf-8");
24534
+ raw = fs44.readFileSync(routingAbs, "utf-8");
24086
24535
  } catch (e) {
24087
24536
  return { ok: false, error: e instanceof Error ? e.message : String(e) };
24088
24537
  }
@@ -24122,20 +24571,20 @@ async function runCoverageExecutionReport(p) {
24122
24571
  }
24123
24572
  let previous;
24124
24573
  try {
24125
- if (fs42.existsSync(outAbs)) {
24126
- previous = fs42.readFileSync(outAbs, "utf-8");
24574
+ if (fs44.existsSync(outAbs)) {
24575
+ previous = fs44.readFileSync(outAbs, "utf-8");
24127
24576
  }
24128
24577
  } catch {
24129
24578
  previous = void 0;
24130
24579
  }
24131
24580
  try {
24132
- fs42.mkdirSync(path41.dirname(outAbs), { recursive: true });
24133
- fs42.writeFileSync(outAbs, md, "utf-8");
24581
+ fs44.mkdirSync(path41.dirname(outAbs), { recursive: true });
24582
+ fs44.writeFileSync(outAbs, md, "utf-8");
24134
24583
  } catch (e) {
24135
24584
  const msg = e instanceof Error ? e.message : String(e);
24136
24585
  if (previous !== void 0) {
24137
24586
  try {
24138
- fs42.writeFileSync(outAbs, previous, "utf-8");
24587
+ fs44.writeFileSync(outAbs, previous, "utf-8");
24139
24588
  } catch {
24140
24589
  }
24141
24590
  }
@@ -24146,7 +24595,7 @@ async function runCoverageExecutionReport(p) {
24146
24595
  }
24147
24596
 
24148
24597
  // src/gluecharm/minimalGluecharmLayout.ts
24149
- var fs43 = __toESM(require("node:fs"));
24598
+ var fs45 = __toESM(require("node:fs"));
24150
24599
  var path42 = __toESM(require("node:path"));
24151
24600
  var MINIMAL_GLUECHARM_RELATIVE_DIRS = [
24152
24601
  [".gluecharm", "docs", "srs"],
@@ -24159,7 +24608,7 @@ function ensureMinimalGluecharmLayoutNode(repoRootAbs) {
24159
24608
  for (const segments of MINIMAL_GLUECHARM_RELATIVE_DIRS) {
24160
24609
  const dir = path42.join(root, ...segments);
24161
24610
  try {
24162
- fs43.mkdirSync(dir, { recursive: true });
24611
+ fs45.mkdirSync(dir, { recursive: true });
24163
24612
  } catch (e) {
24164
24613
  const err = e;
24165
24614
  const msg = e instanceof Error ? e.message : String(e);
@@ -24541,13 +24990,13 @@ function buildFactoryDepsHeadless(input) {
24541
24990
  },
24542
24991
  runPrepareAnalysisWorktree: async (resume) => {
24543
24992
  if (resume) {
24544
- if (adHocWorktree && fs44.existsSync(path43.join(adHocWorktree.path, ".git"))) {
24993
+ if (adHocWorktree && fs46.existsSync(path43.join(adHocWorktree.path, ".git"))) {
24545
24994
  return { ok: true };
24546
24995
  }
24547
24996
  const snap = readAnalysisWorkspaceSnapshot(storageContext);
24548
24997
  const wtPath = snap?.adHocWorktreePath?.trim();
24549
24998
  const repo = snap?.adHocRepositoryRoot?.trim() || repoRoot;
24550
- if (wtPath && fs44.existsSync(path43.join(wtPath, ".git"))) {
24999
+ if (wtPath && fs46.existsSync(path43.join(wtPath, ".git"))) {
24551
25000
  adHocWorktree = attachWorktreeHandle(wtPath, repo);
24552
25001
  macroSourceBranch = snap?.adHocSourceBranchAtCreation;
24553
25002
  macroFinalize = () => {
@@ -24772,7 +25221,7 @@ function stderrLinesForFactoryFailures(failures, exitCode) {
24772
25221
  var path48 = __toESM(require("node:path"));
24773
25222
 
24774
25223
  // src/factory/updateContext/updateContextBaseline.ts
24775
- var fs45 = __toESM(require("node:fs"));
25224
+ var fs47 = __toESM(require("node:fs"));
24776
25225
  var path44 = __toESM(require("node:path"));
24777
25226
  function isValidIso(s) {
24778
25227
  const t = Date.parse(s);
@@ -24783,7 +25232,7 @@ function maxMtimeRegularFilesUnderDir(dirAbs) {
24783
25232
  const walk = (d) => {
24784
25233
  let entries;
24785
25234
  try {
24786
- entries = fs45.readdirSync(d, { withFileTypes: true });
25235
+ entries = fs47.readdirSync(d, { withFileTypes: true });
24787
25236
  } catch {
24788
25237
  return;
24789
25238
  }
@@ -24793,7 +25242,7 @@ function maxMtimeRegularFilesUnderDir(dirAbs) {
24793
25242
  walk(p);
24794
25243
  } else if (e.isFile()) {
24795
25244
  try {
24796
- const st = fs45.statSync(p);
25245
+ const st = fs47.statSync(p);
24797
25246
  const m = st.mtimeMs;
24798
25247
  if (best === null || m > best) {
24799
25248
  best = m;
@@ -24815,7 +25264,7 @@ function resolveUpdateContextBaseline(repoRootAbs, repoConfig) {
24815
25264
  return { baselineIsoUtc: new Date(last).toISOString(), source: "lastRunAt" };
24816
25265
  }
24817
25266
  const ctxDir = path44.join(repoRootAbs, ".gluecharm", "context");
24818
- if (!fs45.existsSync(ctxDir)) {
25267
+ if (!fs47.existsSync(ctxDir)) {
24819
25268
  return null;
24820
25269
  }
24821
25270
  const maxMs = maxMtimeRegularFilesUnderDir(ctxDir);
@@ -24837,12 +25286,12 @@ function persistUpdateContextLastRunAt(repoRootAbs, isoUtc) {
24837
25286
  }
24838
25287
 
24839
25288
  // src/factory/updateContext/updateContextGitWindow.ts
24840
- var import_node_child_process2 = require("node:child_process");
24841
- var fs46 = __toESM(require("node:fs"));
25289
+ var import_node_child_process3 = require("node:child_process");
25290
+ var fs48 = __toESM(require("node:fs"));
24842
25291
  var path45 = __toESM(require("node:path"));
24843
25292
  var GIT_ENV = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
24844
25293
  function gitLines(repoRootAbs, args) {
24845
- const r = (0, import_node_child_process2.execFileSync)("git", ["-c", "core.quotepath=false", ...args], {
25294
+ const r = (0, import_node_child_process3.execFileSync)("git", ["-c", "core.quotepath=false", ...args], {
24846
25295
  cwd: repoRootAbs,
24847
25296
  encoding: "utf-8",
24848
25297
  env: GIT_ENV,
@@ -24864,7 +25313,7 @@ function parseGitLogIso(line) {
24864
25313
  }
24865
25314
  function discoverCommitWindowAndTouchedPaths(repoRootAbs, baselineIsoUtc) {
24866
25315
  const root = path45.resolve(repoRootAbs);
24867
- if (!fs46.existsSync(path45.join(root, ".git"))) {
25316
+ if (!fs48.existsSync(path45.join(root, ".git"))) {
24868
25317
  return { ok: false, error: "Not a git repository (missing .git)." };
24869
25318
  }
24870
25319
  const baselineMs = Date.parse(baselineIsoUtc);
@@ -24929,7 +25378,7 @@ function filterPathsExistingInWorktree(worktreeRootAbs, pathsPosix) {
24929
25378
  const rel = p.replace(/\\/g, "/");
24930
25379
  const abs = path45.join(root, ...rel.split("/"));
24931
25380
  try {
24932
- if (fs46.existsSync(abs) && fs46.statSync(abs).isFile()) {
25381
+ if (fs48.existsSync(abs) && fs48.statSync(abs).isFile()) {
24933
25382
  out.push(rel);
24934
25383
  }
24935
25384
  } catch {
@@ -24939,7 +25388,7 @@ function filterPathsExistingInWorktree(worktreeRootAbs, pathsPosix) {
24939
25388
  }
24940
25389
 
24941
25390
  // src/factory/updateContext/updateContextReport.ts
24942
- var fs47 = __toESM(require("node:fs"));
25391
+ var fs49 = __toESM(require("node:fs"));
24943
25392
  var path46 = __toESM(require("node:path"));
24944
25393
  var CHANGES_SINCE_DATE_BASENAME = "changes-since-date.md";
24945
25394
  function renderChangesSinceDateMarkdown(p) {
@@ -24981,9 +25430,9 @@ function renderChangesSinceDateMarkdown(p) {
24981
25430
  }
24982
25431
  function writeChangesSinceDateReport(contextDirAbs, body) {
24983
25432
  try {
24984
- fs47.mkdirSync(contextDirAbs, { recursive: true });
25433
+ fs49.mkdirSync(contextDirAbs, { recursive: true });
24985
25434
  const target = path46.join(contextDirAbs, CHANGES_SINCE_DATE_BASENAME);
24986
- fs47.writeFileSync(target, body, "utf-8");
25435
+ fs49.writeFileSync(target, body, "utf-8");
24987
25436
  return { ok: true };
24988
25437
  } catch (e) {
24989
25438
  return { ok: false, error: e instanceof Error ? e.message : String(e) };
@@ -24991,13 +25440,13 @@ function writeChangesSinceDateReport(contextDirAbs, body) {
24991
25440
  }
24992
25441
 
24993
25442
  // src/factory/updateContext/updateContextSeedCheck.ts
24994
- var fs48 = __toESM(require("node:fs"));
25443
+ var fs50 = __toESM(require("node:fs"));
24995
25444
  var path47 = __toESM(require("node:path"));
24996
25445
  var INDEX_BASENAME = "index-application-context.json";
24997
25446
  var CHANGES_REPORT = "changes-since-date.md";
24998
25447
  function tryParseJsonFile(abs) {
24999
25448
  try {
25000
- const raw = fs48.readFileSync(abs, "utf-8");
25449
+ const raw = fs50.readFileSync(abs, "utf-8");
25001
25450
  JSON.parse(raw);
25002
25451
  return true;
25003
25452
  } catch {
@@ -25005,16 +25454,16 @@ function tryParseJsonFile(abs) {
25005
25454
  }
25006
25455
  }
25007
25456
  function isWorktreeContextSeeded(contextDirAbs) {
25008
- if (!fs48.existsSync(contextDirAbs)) {
25457
+ if (!fs50.existsSync(contextDirAbs)) {
25009
25458
  return false;
25010
25459
  }
25011
25460
  const indexAbs = path47.join(contextDirAbs, INDEX_BASENAME);
25012
- if (fs48.existsSync(indexAbs) && fs48.statSync(indexAbs).isFile() && tryParseJsonFile(indexAbs)) {
25461
+ if (fs50.existsSync(indexAbs) && fs50.statSync(indexAbs).isFile() && tryParseJsonFile(indexAbs)) {
25013
25462
  return true;
25014
25463
  }
25015
25464
  let names;
25016
25465
  try {
25017
- names = fs48.readdirSync(contextDirAbs);
25466
+ names = fs50.readdirSync(contextDirAbs);
25018
25467
  } catch {
25019
25468
  return false;
25020
25469
  }
@@ -25028,7 +25477,7 @@ function isWorktreeContextSeeded(contextDirAbs) {
25028
25477
  }
25029
25478
  const p = path47.join(contextDirAbs, name);
25030
25479
  try {
25031
- if (fs48.statSync(p).isFile()) {
25480
+ if (fs50.statSync(p).isFile()) {
25032
25481
  distinct.add(name);
25033
25482
  }
25034
25483
  } catch {
@@ -25330,11 +25779,11 @@ async function runUpdateContextFactory(deps) {
25330
25779
  }
25331
25780
 
25332
25781
  // src/factory/contextDrift/runContextDriftFactory.ts
25333
- var fs54 = __toESM(require("node:fs"));
25782
+ var fs56 = __toESM(require("node:fs"));
25334
25783
  var path53 = __toESM(require("node:path"));
25335
25784
 
25336
25785
  // src/factory/contextDrift/contextDriftManifest.ts
25337
- var fs49 = __toESM(require("node:fs"));
25786
+ var fs51 = __toESM(require("node:fs"));
25338
25787
  var path49 = __toESM(require("node:path"));
25339
25788
  var MAX_REFERENCE_BYTES = 256 * 1024;
25340
25789
  var MAX_EVIDENCE_FILES = 300;
@@ -25343,7 +25792,7 @@ var MAX_EXCERPT = 4e3;
25343
25792
  function readFileLimited(abs, maxBytes) {
25344
25793
  let buf;
25345
25794
  try {
25346
- buf = fs49.readFileSync(abs);
25795
+ buf = fs51.readFileSync(abs);
25347
25796
  } catch {
25348
25797
  return { text: "", truncated: false };
25349
25798
  }
@@ -25356,14 +25805,14 @@ function collectEvidencePaths(repoRoot) {
25356
25805
  const roots = ["src", "test", "tests", "packages", ".gluecharm", "scripts"];
25357
25806
  for (const rel of roots) {
25358
25807
  const abs = path49.join(repoRoot, rel);
25359
- if (!fs49.existsSync(abs)) {
25808
+ if (!fs51.existsSync(abs)) {
25360
25809
  continue;
25361
25810
  }
25362
25811
  walkFiles(abs, repoRoot, out, 0);
25363
25812
  }
25364
25813
  for (const leaf of ["package.json", "tsconfig.json"]) {
25365
25814
  const abs = path49.join(repoRoot, leaf);
25366
- if (fs49.existsSync(abs) && fs49.statSync(abs).isFile()) {
25815
+ if (fs51.existsSync(abs) && fs51.statSync(abs).isFile()) {
25367
25816
  const r = path49.relative(repoRoot, abs).split(path49.sep).join("/");
25368
25817
  out.push(r);
25369
25818
  }
@@ -25381,7 +25830,7 @@ function walkFiles(dir, repoRoot, out, depth) {
25381
25830
  }
25382
25831
  let entries;
25383
25832
  try {
25384
- entries = fs49.readdirSync(dir, { withFileTypes: true });
25833
+ entries = fs51.readdirSync(dir, { withFileTypes: true });
25385
25834
  } catch {
25386
25835
  return;
25387
25836
  }
@@ -25418,7 +25867,7 @@ function buildComparisonManifest(args) {
25418
25867
  const evidenceFiles = [];
25419
25868
  for (const rel of evidencePathsTrimmed) {
25420
25869
  const abs = path49.join(args.worktreeRoot, ...rel.split("/"));
25421
- const st = fs49.existsSync(abs) ? fs49.statSync(abs) : null;
25870
+ const st = fs51.existsSync(abs) ? fs51.statSync(abs) : null;
25422
25871
  const size = st && st.isFile() ? st.size : 0;
25423
25872
  const { text, truncated } = readFileLimited(abs, MAX_EVIDENCE_READ);
25424
25873
  const excerpt = truncated ? `${text.slice(0, MAX_EXCERPT)}
@@ -25440,7 +25889,7 @@ function buildComparisonManifest(args) {
25440
25889
  }
25441
25890
 
25442
25891
  // src/factory/contextDrift/contextDriftAgent.ts
25443
- var fs50 = __toESM(require("node:fs"));
25892
+ var fs52 = __toESM(require("node:fs"));
25444
25893
  var path50 = __toESM(require("node:path"));
25445
25894
 
25446
25895
  // src/factory/contextDrift/contextDriftPayload.ts
@@ -25587,16 +26036,16 @@ function buildDriftPrompt(args) {
25587
26036
  }
25588
26037
  async function runDriftComparisonOpenCode(args) {
25589
26038
  const runDir = path50.join(args.worktreeRoot, ".opencode", "_run");
25590
- fs50.mkdirSync(runDir, { recursive: true });
26039
+ fs52.mkdirSync(runDir, { recursive: true });
25591
26040
  const manifestPath = path50.join(runDir, "context-drift-manifest.json");
25592
26041
  const outputPath = path50.join(runDir, "context-drift-payload.json");
25593
- fs50.writeFileSync(manifestPath, `${JSON.stringify(args.manifestObject, null, 2)}
26042
+ fs52.writeFileSync(manifestPath, `${JSON.stringify(args.manifestObject, null, 2)}
25594
26043
  `, "utf8");
25595
- if (fs50.existsSync(outputPath)) {
25596
- fs50.unlinkSync(outputPath);
26044
+ if (fs52.existsSync(outputPath)) {
26045
+ fs52.unlinkSync(outputPath);
25597
26046
  }
25598
26047
  const promptPath = path50.join(runDir, `context-drift-${Date.now()}.prompt.txt`);
25599
- fs50.writeFileSync(
26048
+ fs52.writeFileSync(
25600
26049
  promptPath,
25601
26050
  buildDriftPrompt({
25602
26051
  worktreeRoot: args.worktreeRoot,
@@ -25638,7 +26087,7 @@ async function runDriftComparisonOpenCode(args) {
25638
26087
  }
25639
26088
  let raw;
25640
26089
  try {
25641
- const txt = fs50.readFileSync(outputPath, "utf8");
26090
+ const txt = fs52.readFileSync(outputPath, "utf8");
25642
26091
  raw = JSON.parse(txt);
25643
26092
  } catch (e) {
25644
26093
  return {
@@ -25655,7 +26104,7 @@ async function runDriftComparisonOpenCode(args) {
25655
26104
 
25656
26105
  // src/factory/contextDrift/contextDriftPaths.ts
25657
26106
  var crypto2 = __toESM(require("node:crypto"));
25658
- var fs51 = __toESM(require("node:fs"));
26107
+ var fs53 = __toESM(require("node:fs"));
25659
26108
  var path51 = __toESM(require("node:path"));
25660
26109
  var DRIFT_CONTEXT_SUBDIR = path51.join(".gluecharm", "context", "drift");
25661
26110
  function sanitizeSlug(raw) {
@@ -25694,7 +26143,7 @@ function maybeDedupeSlug(slug, referenceRelPosix) {
25694
26143
  function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
25695
26144
  let st;
25696
26145
  try {
25697
- st = fs51.statSync(referenceAbsInWorktree);
26146
+ st = fs53.statSync(referenceAbsInWorktree);
25698
26147
  } catch {
25699
26148
  return { ok: false, error: `Reference path not found in analysis worktree: ${referenceAbsInWorktree}` };
25700
26149
  }
@@ -25715,7 +26164,7 @@ function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
25715
26164
  }
25716
26165
  let entries;
25717
26166
  try {
25718
- entries = fs51.readdirSync(dir, { withFileTypes: true });
26167
+ entries = fs53.readdirSync(dir, { withFileTypes: true });
25719
26168
  } catch {
25720
26169
  return;
25721
26170
  }
@@ -25740,7 +26189,7 @@ function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
25740
26189
  }
25741
26190
  function pickReferenceRootDocument(args) {
25742
26191
  if (args.indexOverrideAbs) {
25743
- if (!fs51.existsSync(args.indexOverrideAbs) || !args.indexOverrideAbs.endsWith(".md")) {
26192
+ if (!fs53.existsSync(args.indexOverrideAbs) || !args.indexOverrideAbs.endsWith(".md")) {
25744
26193
  return { ok: false, error: "--index must point to an existing .md file under the repo." };
25745
26194
  }
25746
26195
  return { ok: true, path: args.indexOverrideAbs };
@@ -25751,7 +26200,7 @@ function pickReferenceRootDocument(args) {
25751
26200
  const dir = args.referenceAbsInWorktree;
25752
26201
  for (const name of ["index.md", "README.md"]) {
25753
26202
  const p = path51.join(dir, name);
25754
- if (fs51.existsSync(p) && fs51.statSync(p).isFile()) {
26203
+ if (fs53.existsSync(p) && fs53.statSync(p).isFile()) {
25755
26204
  return { ok: true, path: p };
25756
26205
  }
25757
26206
  }
@@ -25768,13 +26217,13 @@ function toPosixPath(p) {
25768
26217
  }
25769
26218
 
25770
26219
  // src/factory/contextDrift/contextDriftIndex.ts
25771
- var fs52 = __toESM(require("node:fs"));
26220
+ var fs54 = __toESM(require("node:fs"));
25772
26221
  var START = "<!-- easyspecs-drift-links:start -->";
25773
26222
  var END = "<!-- easyspecs-drift-links:end -->";
25774
26223
  function patchReferenceIndexWithDriftLink(args) {
25775
26224
  let body;
25776
26225
  try {
25777
- body = fs52.readFileSync(args.referenceRootAbsolute, "utf8");
26226
+ body = fs54.readFileSync(args.referenceRootAbsolute, "utf8");
25778
26227
  } catch (e) {
25779
26228
  return { ok: false, error: e instanceof Error ? e.message : String(e) };
25780
26229
  }
@@ -25795,7 +26244,7 @@ ${block}
25795
26244
  `;
25796
26245
  }
25797
26246
  try {
25798
- fs52.writeFileSync(args.referenceRootAbsolute, next, "utf8");
26247
+ fs54.writeFileSync(args.referenceRootAbsolute, next, "utf8");
25799
26248
  } catch (e) {
25800
26249
  return { ok: false, error: e instanceof Error ? e.message : String(e) };
25801
26250
  }
@@ -25806,13 +26255,13 @@ function escapeRe(s) {
25806
26255
  }
25807
26256
 
25808
26257
  // src/factory/contextDrift/contextDriftPromote.ts
25809
- var fs53 = __toESM(require("node:fs"));
26258
+ var fs55 = __toESM(require("node:fs"));
25810
26259
  var path52 = __toESM(require("node:path"));
25811
26260
  function copyWorktreeFileToWorkspace(args) {
25812
26261
  const src = path52.join(args.worktreeRoot, ...args.relativePosix.split("/"));
25813
26262
  const dest = path52.join(args.workspaceRoot, ...args.relativePosix.split("/"));
25814
- fs53.mkdirSync(path52.dirname(dest), { recursive: true });
25815
- fs53.copyFileSync(src, dest);
26263
+ fs55.mkdirSync(path52.dirname(dest), { recursive: true });
26264
+ fs55.copyFileSync(src, dest);
25816
26265
  }
25817
26266
 
25818
26267
  // src/factory/contextDrift/runContextDriftFactory.ts
@@ -25831,7 +26280,7 @@ async function runContextDriftFactory(deps) {
25831
26280
  };
25832
26281
  }
25833
26282
  const refAbsWorkspace = resolved.abs;
25834
- if (!fs54.existsSync(refAbsWorkspace)) {
26283
+ if (!fs56.existsSync(refAbsWorkspace)) {
25835
26284
  return {
25836
26285
  exitOk: false,
25837
26286
  ok: false,
@@ -25844,7 +26293,7 @@ async function runContextDriftFactory(deps) {
25844
26293
  let indexOverrideAbsWorkspace;
25845
26294
  if (deps.indexOverrideArg?.trim()) {
25846
26295
  const ir = resolveInsideRepo(deps.repoRootAbs, deps.indexOverrideArg.trim());
25847
- if (!ir.ok || !fs54.existsSync(ir.abs)) {
26296
+ if (!ir.ok || !fs56.existsSync(ir.abs)) {
25848
26297
  return {
25849
26298
  exitOk: false,
25850
26299
  ok: false,
@@ -25862,7 +26311,7 @@ async function runContextDriftFactory(deps) {
25862
26311
  ok: true,
25863
26312
  code: "DRY_RUN",
25864
26313
  ...baseMeta,
25865
- referenceRootDocument: toPosixPath(path53.relative(deps.repoRootAbs, refAbsWorkspace)) + (fs54.statSync(refAbsWorkspace).isDirectory() ? "/" : ""),
26314
+ referenceRootDocument: toPosixPath(path53.relative(deps.repoRootAbs, refAbsWorkspace)) + (fs56.statSync(refAbsWorkspace).isDirectory() ? "/" : ""),
25866
26315
  driftReportPath: null,
25867
26316
  analysisWorktreeRoot: "",
25868
26317
  promoted: false,
@@ -25931,7 +26380,7 @@ async function runContextDriftFactory(deps) {
25931
26380
  }
25932
26381
  const indexWt = indexOverrideAbsWorkspace ? path53.join(wt, ...path53.relative(deps.repoRootAbs, indexOverrideAbsWorkspace).split(path53.sep)) : void 0;
25933
26382
  const rootPick = pickReferenceRootDocument({
25934
- referencePathIsFile: fs54.statSync(refAbsWt).isFile(),
26383
+ referencePathIsFile: fs56.statSync(refAbsWt).isFile(),
25935
26384
  referenceAbsInWorktree: refAbsWt,
25936
26385
  bundleFiles: bundle.bundleFiles,
25937
26386
  indexOverrideAbs: indexWt
@@ -25958,7 +26407,7 @@ async function runContextDriftFactory(deps) {
25958
26407
  slug = maybeDedupeSlug(slug, refRel);
25959
26408
  const driftBase = driftFilename(slug, runDate);
25960
26409
  const driftDirWt = path53.join(wt, DRIFT_CONTEXT_SUBDIR);
25961
- fs54.mkdirSync(driftDirWt, { recursive: true });
26410
+ fs56.mkdirSync(driftDirWt, { recursive: true });
25962
26411
  const driftAbsWt = path53.join(driftDirWt, driftBase);
25963
26412
  let payload;
25964
26413
  if (deps.testOnlyFixturePayload) {
@@ -25995,7 +26444,7 @@ async function runContextDriftFactory(deps) {
25995
26444
  manifestTruncation: manifest.truncation
25996
26445
  });
25997
26446
  try {
25998
- fs54.writeFileSync(driftAbsWt, md, "utf8");
26447
+ fs56.writeFileSync(driftAbsWt, md, "utf8");
25999
26448
  } catch (e) {
26000
26449
  finalizeWt?.();
26001
26450
  return {
@@ -26074,7 +26523,7 @@ async function runContextDriftFactory(deps) {
26074
26523
  }
26075
26524
 
26076
26525
  // src/analysis/coordinationDuplicatesDiagnosis.ts
26077
- var fs55 = __toESM(require("fs"));
26526
+ var fs57 = __toESM(require("fs"));
26078
26527
  var path54 = __toESM(require("path"));
26079
26528
  var import__7 = __toESM(require__());
26080
26529
  var COORDINATION_DUPLICATES_REPORT_BASENAME = "coordination-duplicates-report.json";
@@ -26111,11 +26560,11 @@ function looksLikeCoordinationDetailMarkdownBasename(basename17) {
26111
26560
  }
26112
26561
  function loadRawFeatureRows(contextDirAbs) {
26113
26562
  const p = path54.join(contextDirAbs, "features-list.json");
26114
- if (!fs55.existsSync(p)) {
26563
+ if (!fs57.existsSync(p)) {
26115
26564
  return [];
26116
26565
  }
26117
26566
  try {
26118
- const raw = stripUtf8Bom6(fs55.readFileSync(p, "utf-8"));
26567
+ const raw = stripUtf8Bom6(fs57.readFileSync(p, "utf-8"));
26119
26568
  const doc = JSON.parse(raw);
26120
26569
  return Array.isArray(doc.features) ? doc.features : [];
26121
26570
  } catch {
@@ -26150,7 +26599,7 @@ function findOrphanCoordinationMarkdown(contextDirAbs) {
26150
26599
  const featureRows = loadRawFeatureRows(contextDirAbs);
26151
26600
  let dirents;
26152
26601
  try {
26153
- dirents = fs55.readdirSync(contextDirAbs, { withFileTypes: true });
26602
+ dirents = fs57.readdirSync(contextDirAbs, { withFileTypes: true });
26154
26603
  } catch {
26155
26604
  return [];
26156
26605
  }
@@ -26404,13 +26853,13 @@ function buildCoordinationDuplicatesReport(input) {
26404
26853
  const duplicateGroups = [];
26405
26854
  for (const entry of COORDINATION_LIST_SCAN_ENTRIES) {
26406
26855
  const filePath = path54.join(input.contextDirAbsolute, entry.basename);
26407
- if (!fs55.existsSync(filePath)) {
26856
+ if (!fs57.existsSync(filePath)) {
26408
26857
  lists.push({ basename: entry.basename, status: "missing" });
26409
26858
  continue;
26410
26859
  }
26411
26860
  let raw;
26412
26861
  try {
26413
- raw = stripUtf8Bom6(fs55.readFileSync(filePath, "utf-8"));
26862
+ raw = stripUtf8Bom6(fs57.readFileSync(filePath, "utf-8"));
26414
26863
  } catch (e) {
26415
26864
  lists.push({
26416
26865
  basename: entry.basename,
@@ -26459,7 +26908,7 @@ function validateReportData(data) {
26459
26908
  if (!validateReportCompiled) {
26460
26909
  const ajv2 = new import__7.default({ allErrors: true, strict: false });
26461
26910
  const schemaPath = path54.join(resolveContextListSchemasDir(), "coordination-duplicates-report.schema.json");
26462
- const schemaRaw = stripUtf8Bom6(fs55.readFileSync(schemaPath, "utf-8"));
26911
+ const schemaRaw = stripUtf8Bom6(fs57.readFileSync(schemaPath, "utf-8"));
26463
26912
  validateReportCompiled = ajv2.compile(JSON.parse(schemaRaw));
26464
26913
  }
26465
26914
  if (validateReportCompiled(data)) {
@@ -26482,15 +26931,15 @@ function runCoordinationDuplicatesDiagnosis(input) {
26482
26931
  `;
26483
26932
  const tmp = `${outPath}.tmp.${process.pid}`;
26484
26933
  try {
26485
- fs55.writeFileSync(tmp, payload, "utf-8");
26934
+ fs57.writeFileSync(tmp, payload, "utf-8");
26486
26935
  } catch (e) {
26487
26936
  return { ok: false, message: e instanceof Error ? e.message : String(e) };
26488
26937
  }
26489
26938
  try {
26490
- fs55.renameSync(tmp, outPath);
26939
+ fs57.renameSync(tmp, outPath);
26491
26940
  } catch (e) {
26492
26941
  try {
26493
- fs55.unlinkSync(tmp);
26942
+ fs57.unlinkSync(tmp);
26494
26943
  } catch {
26495
26944
  }
26496
26945
  return { ok: false, message: e instanceof Error ? e.message : String(e) };
@@ -26524,7 +26973,7 @@ function runCoordinationDuplicatesDiagnosis(input) {
26524
26973
  }
26525
26974
 
26526
26975
  // src/pipelines/download/downloadPipeline.ts
26527
- var fs56 = __toESM(require("node:fs"));
26976
+ var fs58 = __toESM(require("node:fs"));
26528
26977
  var path55 = __toESM(require("node:path"));
26529
26978
  var SRS_DISCOVERY_BATCH_GET_CHUNK_SIZE = 200;
26530
26979
  function isRecord7(v) {
@@ -26630,19 +27079,19 @@ function chunkIds(ids, size) {
26630
27079
  return out;
26631
27080
  }
26632
27081
  function clearContextDirectoryForCloudReplace(contextDirAbs) {
26633
- if (!fs56.existsSync(contextDirAbs) || !fs56.statSync(contextDirAbs).isDirectory()) {
27082
+ if (!fs58.existsSync(contextDirAbs) || !fs58.statSync(contextDirAbs).isDirectory()) {
26634
27083
  return { filesRemoved: 0 };
26635
27084
  }
26636
27085
  const preserveAbs = path55.resolve(contextDirAbs, UPLOAD_TARGET_FILENAME);
26637
27086
  const preserveSet = /* @__PURE__ */ new Set();
26638
- if (fs56.existsSync(preserveAbs) && fs56.statSync(preserveAbs).isFile()) {
27087
+ if (fs58.existsSync(preserveAbs) && fs58.statSync(preserveAbs).isFile()) {
26639
27088
  preserveSet.add(preserveAbs);
26640
27089
  }
26641
27090
  let filesRemoved = 0;
26642
27091
  const walkRm = (dir) => {
26643
27092
  let entries;
26644
27093
  try {
26645
- entries = fs56.readdirSync(dir, { withFileTypes: true });
27094
+ entries = fs58.readdirSync(dir, { withFileTypes: true });
26646
27095
  } catch {
26647
27096
  return;
26648
27097
  }
@@ -26651,7 +27100,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
26651
27100
  if (e.isDirectory()) {
26652
27101
  walkRm(full);
26653
27102
  try {
26654
- fs56.rmdirSync(full);
27103
+ fs58.rmdirSync(full);
26655
27104
  } catch {
26656
27105
  }
26657
27106
  } else if (e.isFile()) {
@@ -26660,7 +27109,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
26660
27109
  continue;
26661
27110
  }
26662
27111
  try {
26663
- fs56.unlinkSync(abs);
27112
+ fs58.unlinkSync(abs);
26664
27113
  filesRemoved += 1;
26665
27114
  } catch {
26666
27115
  }
@@ -26739,15 +27188,15 @@ async function runDownloadPipeline(opts) {
26739
27188
  failed.push({ id, name, message: "Unsafe or invalid name for local path." });
26740
27189
  continue;
26741
27190
  }
26742
- fs56.mkdirSync(path55.dirname(outAbs), { recursive: true });
26743
- const exists = fs56.existsSync(outAbs);
27191
+ fs58.mkdirSync(path55.dirname(outAbs), { recursive: true });
27192
+ const exists = fs58.existsSync(outAbs);
26744
27193
  if (exists && !opts.force && !opts.replaceFromCloud) {
26745
27194
  skipped += 1;
26746
27195
  log?.(`[pipeline:download] skip existing ${name} (use --force to overwrite).`);
26747
27196
  continue;
26748
27197
  }
26749
27198
  try {
26750
- fs56.writeFileSync(outAbs, bodyText, "utf8");
27199
+ fs58.writeFileSync(outAbs, bodyText, "utf8");
26751
27200
  downloaded += 1;
26752
27201
  succeededIds[outAbs] = id;
26753
27202
  } catch (e) {
@@ -26918,11 +27367,11 @@ function createAuthenticatedRequestJson(deps) {
26918
27367
  }
26919
27368
 
26920
27369
  // src/cli/cliSession.ts
26921
- var fs57 = __toESM(require("node:fs"));
26922
- var os3 = __toESM(require("node:os"));
27370
+ var fs59 = __toESM(require("node:fs"));
27371
+ var os6 = __toESM(require("node:os"));
26923
27372
  var path56 = __toESM(require("node:path"));
26924
27373
  function defaultSessionPath() {
26925
- return path56.join(os3.homedir(), ".easyspecs", "cli-session.json");
27374
+ return path56.join(os6.homedir(), ".easyspecs", "cli-session.json");
26926
27375
  }
26927
27376
  var configSessionPath;
26928
27377
  function setCliSessionPathFromConfig(absPath) {
@@ -26963,10 +27412,10 @@ function effectiveCliSessionPath() {
26963
27412
  function readCliSession() {
26964
27413
  const p = effectiveCliSessionPath();
26965
27414
  try {
26966
- if (!fs57.existsSync(p)) {
27415
+ if (!fs59.existsSync(p)) {
26967
27416
  return void 0;
26968
27417
  }
26969
- const j = JSON.parse(fs57.readFileSync(p, "utf8"));
27418
+ const j = JSON.parse(fs59.readFileSync(p, "utf8"));
26970
27419
  const apiBaseUrl = typeof j.apiBaseUrl === "string" ? j.apiBaseUrl.trim() : "";
26971
27420
  const accessToken = typeof j.accessToken === "string" ? j.accessToken : "";
26972
27421
  const refreshToken = typeof j.refreshToken === "string" ? j.refreshToken : "";
@@ -26980,20 +27429,20 @@ function readCliSession() {
26980
27429
  }
26981
27430
  function writeCliSession(s) {
26982
27431
  const p = effectiveCliSessionPath();
26983
- fs57.mkdirSync(path56.dirname(p), { recursive: true });
26984
- fs57.writeFileSync(p, `${JSON.stringify(s, null, 2)}
27432
+ fs59.mkdirSync(path56.dirname(p), { recursive: true });
27433
+ fs59.writeFileSync(p, `${JSON.stringify(s, null, 2)}
26985
27434
  `, "utf8");
26986
27435
  }
26987
27436
  function clearCliSession() {
26988
27437
  const p = effectiveCliSessionPath();
26989
27438
  try {
26990
- fs57.unlinkSync(p);
27439
+ fs59.unlinkSync(p);
26991
27440
  } catch {
26992
27441
  }
26993
27442
  }
26994
27443
 
26995
27444
  // src/analysis/acePendingTraces.ts
26996
- var fs58 = __toESM(require("fs"));
27445
+ var fs60 = __toESM(require("fs"));
26997
27446
  var path57 = __toESM(require("path"));
26998
27447
  function normalizeAceTraceRelativePath(rel) {
26999
27448
  return rel.split(/[/\\]/).join("/");
@@ -27001,12 +27450,12 @@ function normalizeAceTraceRelativePath(rel) {
27001
27450
  function readCompletedTraceRelativePaths(contextDir2) {
27002
27451
  const set = /* @__PURE__ */ new Set();
27003
27452
  const jsonlPath = aceConsolidatedSessionsJsonlPath(contextDir2);
27004
- if (!fs58.existsSync(jsonlPath)) {
27453
+ if (!fs60.existsSync(jsonlPath)) {
27005
27454
  return set;
27006
27455
  }
27007
27456
  let raw;
27008
27457
  try {
27009
- raw = fs58.readFileSync(jsonlPath, "utf8");
27458
+ raw = fs60.readFileSync(jsonlPath, "utf8");
27010
27459
  } catch {
27011
27460
  return set;
27012
27461
  }
@@ -27037,7 +27486,7 @@ function readCompletedTraceRelativePaths(contextDir2) {
27037
27486
  }
27038
27487
  function listPendingAceTraceFiles(contextDir2, worktreeRoot) {
27039
27488
  const traceSchema = opencodeAceSchemaPath(worktreeRoot, ACE_SCHEMA_TRACE);
27040
- if (!fs58.existsSync(traceSchema)) {
27489
+ if (!fs60.existsSync(traceSchema)) {
27041
27490
  return [];
27042
27491
  }
27043
27492
  const completed = readCompletedTraceRelativePaths(contextDir2);
@@ -27067,11 +27516,32 @@ function clampConcurrency2(n) {
27067
27516
  return Math.min(64, Math.max(1, Math.floor(n)));
27068
27517
  }
27069
27518
  async function runAceAutoLearnPool(p) {
27070
- const maxC = clampConcurrency2(p.maxConcurrentOpenCodeAgents);
27519
+ const staticMaxC = clampConcurrency2(p.maxConcurrentOpenCodeAgents);
27520
+ const throttle = p.enableCpuAdaptiveThrottle !== false;
27521
+ let adaptiveMax = staticMaxC;
27522
+ const sample = p.cpuPressureSampler ?? (throttle ? createDefaultCpuPressureSampler() : () => 0);
27071
27523
  const contextDir2 = gluecharmContextDir(p.baseOpts.worktreeRoot);
27072
27524
  const runner = p.runOfflineLearn ?? runAceOfflineLearnFromTrace;
27073
27525
  const fifo = [...p.traceAbsolutePaths];
27074
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);
27075
27545
  let wake;
27076
27546
  const waitTurn = () => new Promise((resolve20) => {
27077
27547
  wake = resolve20;
@@ -27103,8 +27573,9 @@ async function runAceAutoLearnPool(p) {
27103
27573
  pump();
27104
27574
  return;
27105
27575
  }
27576
+ applyCpuPressure();
27106
27577
  const rel = traceRel(traceAbs);
27107
- p.log?.(`[ace] ace auto-learn: start ${rel} (active ${active}/${maxC})`);
27578
+ p.log?.(`[ace] ace auto-learn: start ${rel} (active ${active}/${currentCap()})`);
27108
27579
  await p.onItemStart?.(rel);
27109
27580
  const r = await runner(traceAbs, { ...p.baseOpts, abortSignal });
27110
27581
  if (r.ok) {
@@ -27118,9 +27589,14 @@ async function runAceAutoLearnPool(p) {
27118
27589
  p.log?.(`[ace] ace auto-learn: finished ${rel} ok=${r.ok}`);
27119
27590
  pump();
27120
27591
  };
27592
+ let pressureInterval;
27593
+ if (throttle) {
27594
+ const intervalMs = p.__testOnlyCpuPressureIntervalMs ?? 3e4;
27595
+ pressureInterval = setInterval(() => applyCpuPressure(), intervalMs);
27596
+ }
27121
27597
  try {
27122
27598
  while (true) {
27123
- while (fifo.length > 0 && active < maxC && !abortSignal?.aborted) {
27599
+ while (fifo.length > 0 && active < currentCap() && !abortSignal?.aborted) {
27124
27600
  const traceAbs = fifo.shift();
27125
27601
  active += 1;
27126
27602
  void runOne(traceAbs);
@@ -27136,11 +27612,14 @@ async function runAceAutoLearnPool(p) {
27136
27612
  await waitTurn();
27137
27613
  continue;
27138
27614
  }
27139
- if (fifo.length === 0 || active >= maxC) {
27615
+ if (fifo.length === 0 || active >= currentCap()) {
27140
27616
  await waitTurn();
27141
27617
  }
27142
27618
  }
27143
27619
  } finally {
27620
+ if (pressureInterval) {
27621
+ clearInterval(pressureInterval);
27622
+ }
27144
27623
  if (poolAbortListenerRegistered && abortSignal) {
27145
27624
  abortSignal.removeEventListener("abort", onPipelineAbort);
27146
27625
  }
@@ -27611,7 +28090,7 @@ function formatCliStderrLine(line, useAnsi) {
27611
28090
  }
27612
28091
 
27613
28092
  // src/cli/main.ts
27614
- var PKG_VERSION = "0.0.24";
28093
+ var PKG_VERSION = "0.0.25";
27615
28094
  function isNonEmptyFactoryFailureArray(x) {
27616
28095
  if (!Array.isArray(x) || x.length === 0) {
27617
28096
  return false;
@@ -27743,7 +28222,7 @@ function resolveAnalysisRoot(repoRoot, rootKind, worktreePath) {
27743
28222
  return repoRoot;
27744
28223
  }
27745
28224
  const wt = worktreePath?.trim();
27746
- if (wt && fs59.existsSync(path59.join(wt, ".git"))) {
28225
+ if (wt && fs61.existsSync(path59.join(wt, ".git"))) {
27747
28226
  return path59.resolve(wt);
27748
28227
  }
27749
28228
  throw new Error("worktree mode requires --worktree <path> to an existing analysis checkout.");
@@ -27752,14 +28231,14 @@ function resolveAdHocCheckoutRoot(_repoRoot, storage, worktreeFlag) {
27752
28231
  const w = worktreeFlag?.trim();
27753
28232
  if (w) {
27754
28233
  const abs = path59.resolve(w);
27755
- if (fs59.existsSync(path59.join(abs, ".git"))) {
28234
+ if (fs61.existsSync(path59.join(abs, ".git"))) {
27756
28235
  return abs;
27757
28236
  }
27758
28237
  throw new Error(`Invalid --worktree (not a git checkout): ${abs}`);
27759
28238
  }
27760
28239
  const snap = readAnalysisWorkspaceSnapshot(storage);
27761
28240
  const p = snap?.adHocWorktreePath?.trim();
27762
- if (p && fs59.existsSync(path59.join(p, ".git"))) {
28241
+ if (p && fs61.existsSync(path59.join(p, ".git"))) {
27763
28242
  return p;
27764
28243
  }
27765
28244
  throw new Error("No analysis checkout: run `easyspecs-cli run synthesis` first or pass `--worktree <path>`.");
@@ -27824,7 +28303,7 @@ async function main() {
27824
28303
  try {
27825
28304
  parsed = parseCliWithCommander(process.argv.slice(2));
27826
28305
  } catch (e) {
27827
- console.error(e instanceof Error ? e.message : String(e));
28306
+ console.error(formatCliThrownUnknown(e));
27828
28307
  logExitCodeSummary(ExitCode.usage);
27829
28308
  process.exit(ExitCode.usage);
27830
28309
  }
@@ -27841,6 +28320,58 @@ async function main() {
27841
28320
  const repoRoot = resolveRepoRoot(flags);
27842
28321
  setAceCliHeadlessMode(true);
27843
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
+ }
27844
28375
  if (positionals[0] === "config" && positionals[1] === "init") {
27845
28376
  const tail = positionals.slice(2);
27846
28377
  const overwrite = tail.includes("--overwrite");
@@ -28024,13 +28555,13 @@ async function main() {
28024
28555
  try {
28025
28556
  modes = parseDoctorFlags(pos.slice(1));
28026
28557
  } catch (e) {
28027
- logErr(flags, e instanceof Error ? e.message : String(e));
28558
+ logErr(flags, formatCliThrownUnknown(e));
28028
28559
  logErr(flags, "Usage: easyspecs-cli doctor [--readiness] [--inspect-config]");
28029
28560
  logExitCodeSummary(ExitCode.usage, flags);
28030
28561
  process.exit(ExitCode.usage);
28031
28562
  }
28032
28563
  const agentsDir = resolveOpenCodeAgentsDir(repoRoot, repoConfig);
28033
- const agentsOk = fs59.existsSync(agentsDir);
28564
+ const agentsOk = fs61.existsSync(agentsDir);
28034
28565
  const oc = getOpenCodeReadiness({
28035
28566
  executable: merged.openCodeExecutable,
28036
28567
  skipCredentialsCheck: merged.openCodeSkipCredentialsCheck,
@@ -28090,7 +28621,7 @@ async function main() {
28090
28621
  tailForCreds = extracted.rest;
28091
28622
  sessionPathRaw = extracted.sessionPath;
28092
28623
  } catch (e) {
28093
- logErr(flags, e instanceof Error ? e.message : String(e));
28624
+ logErr(flags, formatCliThrownUnknown(e));
28094
28625
  logExitCodeSummary(ExitCode.usage, flags);
28095
28626
  process.exit(ExitCode.usage);
28096
28627
  }
@@ -28544,7 +29075,7 @@ async function main() {
28544
29075
  const wt = snap?.adHocWorktreePath?.trim();
28545
29076
  if (wt) {
28546
29077
  const sourceCtx = path59.join(wt, ".gluecharm", "context");
28547
- if (fs59.existsSync(sourceCtx)) {
29078
+ if (fs61.existsSync(sourceCtx)) {
28548
29079
  const n = promoteContextDirectoryToWorkspaceFs(sourceCtx, repoRoot);
28549
29080
  logErr(flags, `[pipeline:analysis] promoted ${String(n.filesCopied)} file(s) \u2192 ${repoRoot}`);
28550
29081
  } else {
@@ -28696,8 +29227,8 @@ async function main() {
28696
29227
  ...flags.verbose && failCount > 0 ? { failures: result.failed } : {}
28697
29228
  });
28698
29229
  } catch (e) {
28699
- const msg = e instanceof Error ? e.message : String(e);
28700
- finish(ExitCode.internal, { ok: false, error: msg });
29230
+ const msg = formatCliThrownUnknown(e);
29231
+ finish(exitCodeForThrownHttpApiError(e) ?? ExitCode.internal, { ok: false, error: msg });
28701
29232
  }
28702
29233
  }
28703
29234
  if (pos[0] === "upload" && (pos[1] === "context" || pos[1] === "republish")) {
@@ -28714,12 +29245,12 @@ async function main() {
28714
29245
  if (pos[1] === "republish") {
28715
29246
  const fromCfg = repoConfig.easyspecs?.upload?.contextDirectory?.trim();
28716
29247
  const resolvedOverride = fromCfg && fromCfg.length > 0 ? path59.isAbsolute(fromCfg) ? path59.normalize(fromCfg) : path59.resolve(repoRoot, fromCfg) : "";
28717
- if (resolvedOverride && fs59.existsSync(path59.join(resolvedOverride, ".."))) {
29248
+ if (resolvedOverride && fs61.existsSync(path59.join(resolvedOverride, ".."))) {
28718
29249
  ctxDir = resolvedOverride;
28719
29250
  } else {
28720
29251
  const storage = createFileBackedWorkspaceState(repoRoot);
28721
29252
  const snap = readAnalysisWorkspaceSnapshot(storage);
28722
- const wt = snap?.adHocWorktreePath && fs59.existsSync(path59.join(snap.adHocWorktreePath, ".gluecharm", "context")) ? path59.join(snap.adHocWorktreePath, ".gluecharm", "context") : "";
29253
+ const wt = snap?.adHocWorktreePath && fs61.existsSync(path59.join(snap.adHocWorktreePath, ".gluecharm", "context")) ? path59.join(snap.adHocWorktreePath, ".gluecharm", "context") : "";
28723
29254
  if (!wt) {
28724
29255
  finish(ExitCode.misconfiguration, {
28725
29256
  ok: false,
@@ -28837,16 +29368,16 @@ async function main() {
28837
29368
  }
28838
29369
  if (pos[0] === "ace" && pos[1] === "clear") {
28839
29370
  const learnings = path59.join(repoRoot, ".gluecharm", "context", "learnings");
28840
- if (!fs59.existsSync(learnings)) {
29371
+ if (!fs61.existsSync(learnings)) {
28841
29372
  finish(ExitCode.ok, { ok: true, message: "nothing to clear" });
28842
29373
  }
28843
- fs59.rmSync(learnings, { recursive: true, force: true });
29374
+ fs61.rmSync(learnings, { recursive: true, force: true });
28844
29375
  finish(ExitCode.ok, { ok: true, message: `cleared ${learnings}` });
28845
29376
  }
28846
29377
  if (pos[0] === "ace" && pos[1] === "learn") {
28847
29378
  requireOpenCode(merged, flags);
28848
29379
  const { worktree } = parseWorktreeFlag(pos.slice(2));
28849
- const root = worktree && fs59.existsSync(path59.join(worktree, ".opencode", "schemas", "ace")) ? worktree : repoRoot;
29380
+ const root = worktree && fs61.existsSync(path59.join(worktree, ".opencode", "schemas", "ace")) ? worktree : repoRoot;
28850
29381
  const contextDir2 = path59.join(root, ".gluecharm", "context");
28851
29382
  const traces = listAceTraceFiles(contextDir2);
28852
29383
  if (traces.length === 0) {
@@ -28871,7 +29402,7 @@ async function main() {
28871
29402
  if (pos[0] === "ace" && pos[1] === "auto-learn") {
28872
29403
  requireOpenCode(merged, flags);
28873
29404
  const { worktree } = parseWorktreeFlag(pos.slice(2));
28874
- const root = worktree && fs59.existsSync(path59.join(worktree, ".git")) ? worktree : repoRoot;
29405
+ const root = worktree && fs61.existsSync(path59.join(worktree, ".git")) ? worktree : repoRoot;
28875
29406
  const contextDir2 = path59.join(root, ".gluecharm", "context");
28876
29407
  const pending = listPendingAceTraceFiles(contextDir2, root);
28877
29408
  if (pending.length === 0) {
@@ -28914,9 +29445,10 @@ async function main() {
28914
29445
  }
28915
29446
  process.exit(ExitCode.misconfiguration);
28916
29447
  }
28917
- const msg = e instanceof Error ? e.message : String(e);
29448
+ const msg = formatCliThrownUnknown(e);
29449
+ const exitFromApi = exitCodeForThrownHttpApiError(e);
28918
29450
  logErr(flags, msg);
28919
- finish(ExitCode.internal, { ok: false, error: msg });
29451
+ finish(exitFromApi ?? ExitCode.internal, { ok: false, error: msg });
28920
29452
  }
28921
29453
  }
28922
29454
  void main();