@gluecharm-lab/easyspecs-cli 0.2.1 → 0.3.1

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
@@ -959,7 +959,7 @@ var require_command = __commonJS({
959
959
  "node_modules/commander/lib/command.js"(exports2) {
960
960
  var EventEmitter = require("node:events").EventEmitter;
961
961
  var childProcess = require("node:child_process");
962
- var path61 = require("node:path");
962
+ var path62 = require("node:path");
963
963
  var fs64 = require("node:fs");
964
964
  var process2 = require("node:process");
965
965
  var { Argument: Argument2, humanReadableArgName } = require_argument();
@@ -1892,9 +1892,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
1892
1892
  let launchWithNode = false;
1893
1893
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1894
1894
  function findFile(baseDir, baseName) {
1895
- const localBin = path61.resolve(baseDir, baseName);
1895
+ const localBin = path62.resolve(baseDir, baseName);
1896
1896
  if (fs64.existsSync(localBin)) return localBin;
1897
- if (sourceExt.includes(path61.extname(baseName))) return void 0;
1897
+ if (sourceExt.includes(path62.extname(baseName))) return void 0;
1898
1898
  const foundExt = sourceExt.find(
1899
1899
  (ext) => fs64.existsSync(`${localBin}${ext}`)
1900
1900
  );
@@ -1912,17 +1912,17 @@ Expecting one of '${allowedValues.join("', '")}'`);
1912
1912
  } catch (err) {
1913
1913
  resolvedScriptPath = this._scriptPath;
1914
1914
  }
1915
- executableDir = path61.resolve(
1916
- path61.dirname(resolvedScriptPath),
1915
+ executableDir = path62.resolve(
1916
+ path62.dirname(resolvedScriptPath),
1917
1917
  executableDir
1918
1918
  );
1919
1919
  }
1920
1920
  if (executableDir) {
1921
1921
  let localFile = findFile(executableDir, executableFile);
1922
1922
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
1923
- const legacyName = path61.basename(
1923
+ const legacyName = path62.basename(
1924
1924
  this._scriptPath,
1925
- path61.extname(this._scriptPath)
1925
+ path62.extname(this._scriptPath)
1926
1926
  );
1927
1927
  if (legacyName !== this._name) {
1928
1928
  localFile = findFile(
@@ -1933,7 +1933,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1933
1933
  }
1934
1934
  executableFile = localFile || executableFile;
1935
1935
  }
1936
- launchWithNode = sourceExt.includes(path61.extname(executableFile));
1936
+ launchWithNode = sourceExt.includes(path62.extname(executableFile));
1937
1937
  let proc;
1938
1938
  if (process2.platform !== "win32") {
1939
1939
  if (launchWithNode) {
@@ -2773,7 +2773,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2773
2773
  * @return {Command}
2774
2774
  */
2775
2775
  nameFromFilename(filename) {
2776
- this._name = path61.basename(filename, path61.extname(filename));
2776
+ this._name = path62.basename(filename, path62.extname(filename));
2777
2777
  return this;
2778
2778
  }
2779
2779
  /**
@@ -2787,9 +2787,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2787
2787
  * @param {string} [path]
2788
2788
  * @return {(string|null|Command)}
2789
2789
  */
2790
- executableDir(path62) {
2791
- if (path62 === void 0) return this._executableDir;
2792
- this._executableDir = path62;
2790
+ executableDir(path63) {
2791
+ if (path63 === void 0) return this._executableDir;
2792
+ this._executableDir = path63;
2793
2793
  return this;
2794
2794
  }
2795
2795
  /**
@@ -5244,8 +5244,8 @@ var require_resolve = __commonJS({
5244
5244
  }
5245
5245
  return count;
5246
5246
  }
5247
- function getFullPath(resolver, id = "", normalize8) {
5248
- if (normalize8 !== false)
5247
+ function getFullPath(resolver, id = "", normalize9) {
5248
+ if (normalize9 !== false)
5249
5249
  id = normalizeId(id);
5250
5250
  const p = resolver.parse(id);
5251
5251
  return _getFullPath(resolver, p);
@@ -5993,7 +5993,7 @@ var require_compile = __commonJS({
5993
5993
  const schOrFunc = root.refs[ref];
5994
5994
  if (schOrFunc)
5995
5995
  return schOrFunc;
5996
- let _sch = resolve23.call(this, root, ref);
5996
+ let _sch = resolve24.call(this, root, ref);
5997
5997
  if (_sch === void 0) {
5998
5998
  const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
5999
5999
  const { schemaId } = this.opts;
@@ -6020,7 +6020,7 @@ var require_compile = __commonJS({
6020
6020
  function sameSchemaEnv(s1, s2) {
6021
6021
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
6022
6022
  }
6023
- function resolve23(root, ref) {
6023
+ function resolve24(root, ref) {
6024
6024
  let sch;
6025
6025
  while (typeof (sch = this.refs[ref]) == "string")
6026
6026
  ref = sch;
@@ -6235,8 +6235,8 @@ var require_utils = __commonJS({
6235
6235
  }
6236
6236
  return ind;
6237
6237
  }
6238
- function removeDotSegments(path61) {
6239
- let input = path61;
6238
+ function removeDotSegments(path62) {
6239
+ let input = path62;
6240
6240
  const output = [];
6241
6241
  let nextSlash = -1;
6242
6242
  let len = 0;
@@ -6435,8 +6435,8 @@ var require_schemes = __commonJS({
6435
6435
  wsComponent.secure = void 0;
6436
6436
  }
6437
6437
  if (wsComponent.resourceName) {
6438
- const [path61, query] = wsComponent.resourceName.split("?");
6439
- wsComponent.path = path61 && path61 !== "/" ? path61 : void 0;
6438
+ const [path62, query] = wsComponent.resourceName.split("?");
6439
+ wsComponent.path = path62 && path62 !== "/" ? path62 : void 0;
6440
6440
  wsComponent.query = query;
6441
6441
  wsComponent.resourceName = void 0;
6442
6442
  }
@@ -6585,7 +6585,7 @@ var require_fast_uri = __commonJS({
6585
6585
  "use strict";
6586
6586
  var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4, nonSimpleDomain } = require_utils();
6587
6587
  var { SCHEMES, getSchemeHandler } = require_schemes();
6588
- function normalize8(uri, options) {
6588
+ function normalize9(uri, options) {
6589
6589
  if (typeof uri === "string") {
6590
6590
  uri = /** @type {T} */
6591
6591
  serialize(parse(uri, options), options);
@@ -6595,7 +6595,7 @@ var require_fast_uri = __commonJS({
6595
6595
  }
6596
6596
  return uri;
6597
6597
  }
6598
- function resolve23(baseURI, relativeURI, options) {
6598
+ function resolve24(baseURI, relativeURI, options) {
6599
6599
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
6600
6600
  const resolved = resolveComponent(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true);
6601
6601
  schemelessOptions.skipEscape = true;
@@ -6821,8 +6821,8 @@ var require_fast_uri = __commonJS({
6821
6821
  }
6822
6822
  var fastUri = {
6823
6823
  SCHEMES,
6824
- normalize: normalize8,
6825
- resolve: resolve23,
6824
+ normalize: normalize9,
6825
+ resolve: resolve24,
6826
6826
  resolveComponent,
6827
6827
  equal,
6828
6828
  serialize,
@@ -10637,7 +10637,7 @@ var require_dist = __commonJS({
10637
10637
 
10638
10638
  // src/cli/main.ts
10639
10639
  var fs63 = __toESM(require("node:fs"));
10640
- var path60 = __toESM(require("node:path"));
10640
+ var path61 = __toESM(require("node:path"));
10641
10641
 
10642
10642
  // src/cli/exitCodes.ts
10643
10643
  var OsExit = {
@@ -10677,7 +10677,7 @@ var OsExit = {
10677
10677
  readinessOpenCodeNotInstalled: 84,
10678
10678
  /** SRS-72 readiness gate (b): credentials not ready. */
10679
10679
  readinessOpenCodeCredentials: 85,
10680
- /** SRS-72 readiness gate (c): default model not configured. */
10680
+ /** SRS-72: reserved — readiness no longer exits for missing default model when install + credentials pass. */
10681
10681
  readinessOpenCodeModel: 86,
10682
10682
  /** SRS-72 readiness gate (d): mandatory OpenCode config file missing. */
10683
10683
  readinessOpenCodeMandatoryConfig: 87
@@ -10778,9 +10778,9 @@ function describeExitCode(code) {
10778
10778
  case OsExit.readinessOpenCodeCredentials:
10779
10779
  return "OpenCode credentials not ready for factory run.";
10780
10780
  case OsExit.readinessOpenCodeModel:
10781
- return "OpenCode default model is not configured \u2014 add a model in repo `opencode.json` or `easyspecs.openCodeRuntime.providers`.";
10781
+ return "Reserved exit code 86 \u2014 factory readiness no longer fails solely for a missing OpenCode default model when the CLI is installed and credentials are ready; configure a model in OpenCode or EasySpecs settings if agent runs fail later.";
10782
10782
  case OsExit.readinessOpenCodeMandatoryConfig:
10783
- return "Mandatory OpenCode project config is missing \u2014 create `opencode.json` at the repository / analysis root.";
10783
+ return "Reserved exit code 87 \u2014 factory readiness does not fail for a missing repo-root `opencode.json` in the current product rules.";
10784
10784
  default:
10785
10785
  return `Non-zero exit (${String(code)}) \u2014 see stderr and any JSON \`error\` field for detail.`;
10786
10786
  }
@@ -12687,7 +12687,7 @@ function stringifyForSrs13Debug(value) {
12687
12687
  return truncateForSrs13DebugLog(String(value));
12688
12688
  }
12689
12689
  }
12690
- function logSrs13HttpDebug(log, path61, method, requestBody, error) {
12690
+ function logSrs13HttpDebug(log, path62, method, requestBody, error) {
12691
12691
  if (!log) {
12692
12692
  return;
12693
12693
  }
@@ -12697,7 +12697,7 @@ function logSrs13HttpDebug(log, path61, method, requestBody, error) {
12697
12697
  } catch {
12698
12698
  bodyBytes = 0;
12699
12699
  }
12700
- log(`[pipeline:upload] debug ${method} ${path61} \u2014 request body ~${bodyBytes} bytes (JSON below):`);
12700
+ log(`[pipeline:upload] debug ${method} ${path62} \u2014 request body ~${bodyBytes} bytes (JSON below):`);
12701
12701
  log(stringifyForSrs13Debug(requestBody));
12702
12702
  const raw = httpApiResponseBody(error);
12703
12703
  const status = error && typeof error === "object" && "status" in error ? Number(error.status) : void 0;
@@ -14394,9 +14394,9 @@ function parsePsRssDarwinKilobytes(stdout) {
14394
14394
  return n;
14395
14395
  }
14396
14396
  function readLinuxPidRssBytes(pid) {
14397
- const path61 = `/proc/${pid}/status`;
14397
+ const path62 = `/proc/${pid}/status`;
14398
14398
  try {
14399
- const content = fs18.readFileSync(path61, "utf8");
14399
+ const content = fs18.readFileSync(path62, "utf8");
14400
14400
  const kb = parseVmRssKilobytesFromProcStatus(content);
14401
14401
  if (kb === null) {
14402
14402
  return { kind: "unknown", reason: "VmRSS_missing" };
@@ -14497,7 +14497,16 @@ var PROVIDER_ENV_KEYS = [
14497
14497
  "OPENAI_API_KEY",
14498
14498
  "OPENROUTER_API_KEY",
14499
14499
  "GOOGLE_API_KEY",
14500
- "OPENCODE_API_KEY"
14500
+ "GEMINI_API_KEY",
14501
+ "GOOGLE_GENERATIVE_AI_API_KEY",
14502
+ "OPENCODE_API_KEY",
14503
+ "MISTRAL_API_KEY",
14504
+ "GROQ_API_KEY",
14505
+ "COHERE_API_KEY",
14506
+ "XAI_API_KEY",
14507
+ "DEEPSEEK_API_KEY",
14508
+ "AZURE_OPENAI_API_KEY",
14509
+ "AWS_BEARER_TOKEN_BEDROCK"
14501
14510
  ];
14502
14511
  function hasProviderEnvConfigured() {
14503
14512
  for (const k of PROVIDER_ENV_KEYS) {
@@ -14584,9 +14593,9 @@ function runOpenCodeAgent(cwd, args, options) {
14584
14593
  log?.(`${procTag} command: ${formatCliCommandForLog(cmd, args)}`);
14585
14594
  log?.(`${procTag} cwd: ${JSON.stringify(cwd)}`);
14586
14595
  log?.(`${procTag} argv: ${JSON.stringify(args)}`);
14587
- return new Promise((resolve23) => {
14596
+ return new Promise((resolve24) => {
14588
14597
  if (sig?.aborted) {
14589
- resolve23({ ok: false, message: "Stopped by user.", cancelled: true });
14598
+ resolve24({ ok: false, message: "Stopped by user.", cancelled: true });
14590
14599
  return;
14591
14600
  }
14592
14601
  const spawnEnv = options?.childEnv && Object.keys(options.childEnv).length > 0 ? { ...process.env, ...options.childEnv } : process.env;
@@ -14681,7 +14690,7 @@ ${truncateForDiag(outBody, DIAG_STDOUT_MAX)}`);
14681
14690
  if (diag) {
14682
14691
  finishDiag(diag.label, diag.code, diag.dumpStreams);
14683
14692
  }
14684
- resolve23(result);
14693
+ resolve24(result);
14685
14694
  };
14686
14695
  let onAbort;
14687
14696
  const clearAbortHandler = () => {
@@ -21405,8 +21414,8 @@ async function drainWorkstationPool(p) {
21405
21414
  const artefactRunId = readArtefactRunSnapshot(storageContext)?.runId ?? "unknown-run";
21406
21415
  let active = 0;
21407
21416
  let wake;
21408
- const waitTurn = () => new Promise((resolve23) => {
21409
- wake = resolve23;
21417
+ const waitTurn = () => new Promise((resolve24) => {
21418
+ wake = resolve24;
21410
21419
  });
21411
21420
  const persist = async () => {
21412
21421
  const items = {};
@@ -21753,7 +21762,7 @@ function promoteContextDirectoryToWorkspaceFs(sourceContextDir, workspaceRootFs)
21753
21762
 
21754
21763
  // src/shared/factoryPipelineExitConditions.ts
21755
21764
  var FACTORY_PIPELINE_EXIT_CONDITIONS = {
21756
- diagnose_readiness: "OpenCode CLI, credentials, default model, and mandatory project `opencode.json` are ready before worktree / agent work (SRS-72).",
21765
+ diagnose_readiness: "OpenCode CLI and credentials are required before worktree / agent work; default model is reported (informational) but does not block readiness when install and credentials pass (SRS-72).",
21757
21766
  create_analysis_worktree: "Git analysis checkout exists under the configured temp parent (SRS-8); ready for agent materialization.",
21758
21767
  materialize_opencode_agents: "Bundled OpenCode agent definitions are copied into the analysis worktree (`.opencode/` tree).",
21759
21768
  synthesis_convergence: "Missing artefact count is 0. May run again after remediation (R5) if a refreshed check finds new expected outputs.",
@@ -21767,30 +21776,103 @@ var FACTORY_PIPELINE_EXIT_CONDITIONS = {
21767
21776
 
21768
21777
  // src/readiness/factoryReadiness.ts
21769
21778
  var fs39 = __toESM(require("node:fs"));
21779
+ var path35 = __toESM(require("node:path"));
21780
+
21781
+ // src/readiness/openCodeConfigCandidates.ts
21770
21782
  var os6 = __toESM(require("node:os"));
21771
21783
  var path34 = __toESM(require("node:path"));
21772
- var MANDATORY_OPEN_CODE_CONFIG_REL_PATHS = ["opencode.json"];
21773
- var READINESS_OPENCODE_NOT_INSTALLED = "READINESS_OPENCODE_NOT_INSTALLED";
21774
- var READINESS_OPENCODE_CREDENTIALS = "READINESS_OPENCODE_CREDENTIALS";
21775
- var READINESS_OPENCODE_MODEL = "READINESS_OPENCODE_MODEL";
21776
- var READINESS_OPENCODE_MANDATORY_CONFIG = "READINESS_OPENCODE_MANDATORY_CONFIG";
21777
- function userOpenCodeConfigPath() {
21784
+ function openCodeUserConfigDir() {
21778
21785
  if (process.platform === "win32") {
21779
21786
  const base = process.env.APPDATA || path34.join(os6.homedir(), "AppData", "Roaming");
21780
- return path34.join(base, "opencode", "config.json");
21787
+ return path34.join(base, "opencode");
21781
21788
  }
21782
21789
  const xdg = process.env.XDG_CONFIG_HOME?.trim();
21783
21790
  const cfgRoot = xdg && xdg.length > 0 ? xdg : path34.join(os6.homedir(), ".config");
21784
- return path34.join(cfgRoot, "opencode", "config.json");
21791
+ return path34.join(cfgRoot, "opencode");
21785
21792
  }
21786
- function buildOpenCodeConfigInventory(analysisRootAbs) {
21793
+ function openCodeMacUserApplicationSupportDir() {
21794
+ if (process.platform === "darwin") {
21795
+ return path34.join(os6.homedir(), "Library", "Application Support", "opencode");
21796
+ }
21797
+ return void 0;
21798
+ }
21799
+ function openCodeWindowsLocalAppDataDir() {
21800
+ if (process.platform === "win32") {
21801
+ const la = process.env.LOCALAPPDATA?.trim();
21802
+ if (la && la.length > 0) {
21803
+ return path34.join(la, "opencode");
21804
+ }
21805
+ }
21806
+ return void 0;
21807
+ }
21808
+ function managedOpenCodeConfigDir() {
21809
+ if (process.platform === "darwin") {
21810
+ return "/Library/Application Support/opencode";
21811
+ }
21812
+ if (process.platform === "linux") {
21813
+ return path34.join("/etc", "opencode");
21814
+ }
21815
+ if (process.platform === "win32") {
21816
+ const pd = process.env.ProgramData?.trim() || "C:\\ProgramData";
21817
+ return path34.join(pd, "opencode");
21818
+ }
21819
+ return void 0;
21820
+ }
21821
+ function pushConfigBasenames(out, dir) {
21822
+ const d = path34.normalize(dir);
21823
+ out.push(path34.join(d, "opencode.json"));
21824
+ out.push(path34.join(d, "opencode.jsonc"));
21825
+ out.push(path34.join(d, "config.json"));
21826
+ }
21827
+ function dedupeStablePaths(paths) {
21828
+ const seen = /* @__PURE__ */ new Set();
21829
+ const out = [];
21830
+ for (const p of paths) {
21831
+ const n = path34.normalize(p.trim());
21832
+ if (n.length === 0 || seen.has(n)) {
21833
+ continue;
21834
+ }
21835
+ seen.add(n);
21836
+ out.push(n);
21837
+ }
21838
+ return out;
21839
+ }
21840
+ function openCodeJsonModelFileCandidates(analysisRootAbs) {
21787
21841
  const root = path34.resolve(analysisRootAbs);
21788
- const list = [
21789
- { path: path34.join(root, "opencode.json"), exists: false },
21790
- { path: path34.join(root, ".opencode", "config.json"), exists: false },
21791
- { path: userOpenCodeConfigPath(), exists: false }
21792
- ];
21793
- return list.map((e) => ({ ...e, exists: fs39.existsSync(e.path) }));
21842
+ const acc = [];
21843
+ const oc = process.env.OPENCODE_CONFIG?.trim();
21844
+ if (oc) {
21845
+ acc.push(path34.resolve(oc));
21846
+ }
21847
+ pushConfigBasenames(acc, openCodeUserConfigDir());
21848
+ const macAs = openCodeMacUserApplicationSupportDir();
21849
+ if (macAs) {
21850
+ pushConfigBasenames(acc, macAs);
21851
+ }
21852
+ const winLoc = openCodeWindowsLocalAppDataDir();
21853
+ if (winLoc) {
21854
+ pushConfigBasenames(acc, winLoc);
21855
+ }
21856
+ pushConfigBasenames(acc, path34.join(os6.homedir(), ".opencode"));
21857
+ const ocd = process.env.OPENCODE_CONFIG_DIR?.trim();
21858
+ if (ocd) {
21859
+ pushConfigBasenames(acc, path34.resolve(ocd));
21860
+ }
21861
+ pushConfigBasenames(acc, root);
21862
+ pushConfigBasenames(acc, path34.join(root, ".opencode"));
21863
+ const managed = managedOpenCodeConfigDir();
21864
+ if (managed) {
21865
+ pushConfigBasenames(acc, managed);
21866
+ }
21867
+ return dedupeStablePaths(acc);
21868
+ }
21869
+
21870
+ // src/readiness/factoryReadiness.ts
21871
+ var MANDATORY_OPEN_CODE_CONFIG_REL_PATHS = ["opencode.json"];
21872
+ var READINESS_OPENCODE_NOT_INSTALLED = "READINESS_OPENCODE_NOT_INSTALLED";
21873
+ var READINESS_OPENCODE_CREDENTIALS = "READINESS_OPENCODE_CREDENTIALS";
21874
+ function buildOpenCodeConfigInventory(analysisRootAbs) {
21875
+ return openCodeJsonModelFileCandidates(analysisRootAbs).map((p) => ({ path: p, exists: fs39.existsSync(p) }));
21794
21876
  }
21795
21877
  function defaultModelFromEasyspecsConfig(cfg) {
21796
21878
  const providers = cfg.easyspecs?.openCodeRuntime?.providers;
@@ -21808,19 +21890,37 @@ function defaultModelFromEasyspecsConfig(cfg) {
21808
21890
  function pickString(v) {
21809
21891
  return typeof v === "string" && v.trim().length > 0 ? v.trim() : void 0;
21810
21892
  }
21893
+ function pickModelLike(v) {
21894
+ const s = pickString(v);
21895
+ if (s) {
21896
+ return s;
21897
+ }
21898
+ if (v && typeof v === "object") {
21899
+ const r = v;
21900
+ return pickString(r.id) ?? pickString(r.name) ?? pickString(r.model);
21901
+ }
21902
+ return void 0;
21903
+ }
21904
+ function modelFromEasyspecsProjectConfigOverlay(cfg) {
21905
+ const overlay = cfg.easyspecs?.openCodeRuntime?.projectConfigOverlay;
21906
+ if (!overlay || typeof overlay !== "object") {
21907
+ return void 0;
21908
+ }
21909
+ return extractModelFromOpenCodeJson(overlay);
21910
+ }
21811
21911
  function extractModelFromOpenCodeJson(data) {
21812
21912
  if (!data || typeof data !== "object") {
21813
21913
  return void 0;
21814
21914
  }
21815
21915
  const o = data;
21816
- const direct = pickString(o.model) ?? pickString(o.defaultModel);
21817
- if (direct) {
21818
- return direct;
21916
+ const top = pickModelLike(o.model) ?? pickString(o.defaultModel) ?? pickModelLike(o.small_model) ?? pickString(o.smallModel);
21917
+ if (top) {
21918
+ return top;
21819
21919
  }
21820
21920
  const models = o.models;
21821
21921
  if (models && typeof models === "object") {
21822
21922
  const m = models;
21823
- const def = pickString(m.default) ?? pickString(m.defaultModel);
21923
+ const def = pickModelLike(m.default) ?? pickString(m.defaultModel);
21824
21924
  if (def) {
21825
21925
  return def;
21826
21926
  }
@@ -21828,13 +21928,59 @@ function extractModelFromOpenCodeJson(data) {
21828
21928
  const agent = o.agent;
21829
21929
  if (agent && typeof agent === "object") {
21830
21930
  const a = agent;
21831
- const am = pickString(a.model) ?? pickString(a.defaultModel);
21931
+ const am = pickModelLike(a.model) ?? pickString(a.defaultModel);
21832
21932
  if (am) {
21833
21933
  return am;
21834
21934
  }
21835
21935
  }
21936
+ const prov = o.provider;
21937
+ if (prov && typeof prov === "object") {
21938
+ for (const v of Object.values(prov)) {
21939
+ if (v && typeof v === "object") {
21940
+ const rec = v;
21941
+ const pm = pickModelLike(rec.model);
21942
+ if (pm) {
21943
+ return pm;
21944
+ }
21945
+ }
21946
+ }
21947
+ }
21836
21948
  return void 0;
21837
21949
  }
21950
+ function parseOpenCodeConfigText(raw) {
21951
+ const t = raw.trim();
21952
+ if (!t) {
21953
+ return void 0;
21954
+ }
21955
+ try {
21956
+ return JSON.parse(t);
21957
+ } catch {
21958
+ const noBlock = t.replace(/\/\*[\s\S]*?\*\//g, "");
21959
+ const noLine = noBlock.replace(/^\s*\/\/[^\n\r]*/gm, "");
21960
+ try {
21961
+ return JSON.parse(noLine);
21962
+ } catch {
21963
+ return void 0;
21964
+ }
21965
+ }
21966
+ }
21967
+ function modelFromOpencodeConfigContentEnv() {
21968
+ const v = process.env.OPENCODE_CONFIG_CONTENT?.trim();
21969
+ if (!v) {
21970
+ return void 0;
21971
+ }
21972
+ const data = parseOpenCodeConfigText(v);
21973
+ return data !== void 0 ? extractModelFromOpenCodeJson(data) : void 0;
21974
+ }
21975
+ function tryModelFromConfigFile(absPath) {
21976
+ try {
21977
+ const txt = fs39.readFileSync(absPath, "utf-8");
21978
+ const data = parseOpenCodeConfigText(txt);
21979
+ return data !== void 0 ? extractModelFromOpenCodeJson(data) : void 0;
21980
+ } catch {
21981
+ return void 0;
21982
+ }
21983
+ }
21838
21984
  function sanitizeModelSummary(raw) {
21839
21985
  const t = raw.trim();
21840
21986
  if (!t) {
@@ -21854,15 +22000,19 @@ function resolveModelFromContext(ctx) {
21854
22000
  if (fromCfg) {
21855
22001
  return { configured: true, summary: sanitizeModelSummary(fromCfg) };
21856
22002
  }
21857
- const p = path34.join(path34.resolve(ctx.analysisRootAbs), "opencode.json");
21858
- try {
21859
- const txt = fs39.readFileSync(p, "utf-8");
21860
- const data = JSON.parse(txt);
21861
- const m = extractModelFromOpenCodeJson(data);
22003
+ const fromOverlay = modelFromEasyspecsProjectConfigOverlay(ctx.repoConfig);
22004
+ if (fromOverlay) {
22005
+ return { configured: true, summary: sanitizeModelSummary(fromOverlay) };
22006
+ }
22007
+ const fromInline = modelFromOpencodeConfigContentEnv();
22008
+ if (fromInline) {
22009
+ return { configured: true, summary: sanitizeModelSummary(fromInline) };
22010
+ }
22011
+ for (const p of openCodeJsonModelFileCandidates(ctx.analysisRootAbs)) {
22012
+ const m = tryModelFromConfigFile(p);
21862
22013
  if (m) {
21863
22014
  return { configured: true, summary: sanitizeModelSummary(m) };
21864
22015
  }
21865
- } catch {
21866
22016
  }
21867
22017
  return { configured: false, summary: "(not configured)" };
21868
22018
  }
@@ -21874,7 +22024,7 @@ function buildReadinessProbeFacts(ctx) {
21874
22024
  });
21875
22025
  const openCodeConfigFiles = buildOpenCodeConfigInventory(ctx.analysisRootAbs);
21876
22026
  const mandatoryOk = MANDATORY_OPEN_CODE_CONFIG_REL_PATHS.every((rel) => {
21877
- const abs = path34.join(path34.resolve(ctx.analysisRootAbs), rel);
22027
+ const abs = path35.join(path35.resolve(ctx.analysisRootAbs), rel);
21878
22028
  return fs39.existsSync(abs);
21879
22029
  });
21880
22030
  const model = resolveModelFromContext(ctx);
@@ -21898,7 +22048,8 @@ function buildReadinessLineBlock(facts, ctx) {
21898
22048
  `repoRoot=${ctx.repoRootAbs}`,
21899
22049
  `apiBaseUrl=${apiDisp}`,
21900
22050
  `opencode installed=${String(facts.installed)} credentialsReady=${String(facts.credentialsReady)}`,
21901
- `opencode modelConfigured=${String(facts.modelConfigured)} modelSummary=${facts.modelSummary}`
22051
+ `opencode modelConfigured=${String(facts.modelConfigured)} modelSummary=${facts.modelSummary}`,
22052
+ `mandatoryRepoOpenCodeJsonPathsOk=${String(facts.mandatoryConfigPathsOk)} (informational)`
21902
22053
  ];
21903
22054
  for (const e of facts.openCodeConfigFiles) {
21904
22055
  lines.push(`opencodeConfigFile ${e.path} exists=${String(e.exists)}`);
@@ -21923,22 +22074,6 @@ function evaluateReadinessGates(facts) {
21923
22074
  readinessReasonCode: READINESS_OPENCODE_CREDENTIALS
21924
22075
  };
21925
22076
  }
21926
- if (!facts.modelConfigured) {
21927
- return {
21928
- ok: false,
21929
- gate: "c",
21930
- exitCode: OsExit.readinessOpenCodeModel,
21931
- readinessReasonCode: READINESS_OPENCODE_MODEL
21932
- };
21933
- }
21934
- if (!facts.mandatoryConfigPathsOk) {
21935
- return {
21936
- ok: false,
21937
- gate: "d",
21938
- exitCode: OsExit.readinessOpenCodeMandatoryConfig,
21939
- readinessReasonCode: READINESS_OPENCODE_MANDATORY_CONFIG
21940
- };
21941
- }
21942
22077
  return { ok: true };
21943
22078
  }
21944
22079
  function buildReadinessJsonFields(facts) {
@@ -22013,7 +22148,8 @@ var ERROR_JOIN_MAX = 900;
22013
22148
  var ADDITIONAL_APPEND_MAX = 200;
22014
22149
  var PHASE_TO_OS_EXIT = {
22015
22150
  unknown_factory_phase: OsExit.factoryUnknown,
22016
- diagnose_readiness: OsExit.readinessOpenCodeModel,
22151
+ /** Fallback when a failed row lacks an explicit exitCode; real readiness failures embed 84/85 from gates. */
22152
+ diagnose_readiness: OsExit.readinessOpenCodeNotInstalled,
22017
22153
  create_analysis_worktree: OsExit.createAnalysisWorktree,
22018
22154
  materialize_opencode_agents: OsExit.materializeOpenCodeAgents,
22019
22155
  synthesis_convergence: OsExit.synthesisConvergence,
@@ -22026,7 +22162,7 @@ var PHASE_TO_OS_EXIT = {
22026
22162
  };
22027
22163
  var TITLE_BY_PHASE = {
22028
22164
  unknown_factory_phase: "EasySpecs stopped: the failing pipeline phase could not be identified. Retry with --verbose; report this outcome if it persists.",
22029
- diagnose_readiness: "Factory readiness preflight failed: OpenCode install, credentials, default model, or mandatory `opencode.json` is not satisfied. See stderr lines above and `readinessReasonCode` in JSON.",
22165
+ diagnose_readiness: "Factory readiness preflight failed \u2014 see stderr lines above and `readinessReasonCode` / `readinessGate` in JSON.",
22030
22166
  create_analysis_worktree: "Could not prepare the analysis Git worktree (temporary checkout). Check disk space, repo permissions, and that the project is a valid Git checkout.",
22031
22167
  materialize_opencode_agents: "Could not install OpenCode agent files into the analysis worktree. Check bundled extension assets and disk permissions under the worktree path.",
22032
22168
  synthesis_convergence: "Context synthesis did not finish: required context files are still missing or invalid after retries. Inspect OpenCode errors and workstation logs for this phase.",
@@ -22204,7 +22340,7 @@ function sleepUntilAborted(ms, signal) {
22204
22340
  if (signal.aborted) {
22205
22341
  return Promise.reject(new DOMException("The operation was aborted.", "AbortError"));
22206
22342
  }
22207
- return new Promise((resolve23, reject) => {
22343
+ return new Promise((resolve24, reject) => {
22208
22344
  const onAbort = () => {
22209
22345
  clearTimeout(t);
22210
22346
  signal.removeEventListener("abort", onAbort);
@@ -22212,7 +22348,7 @@ function sleepUntilAborted(ms, signal) {
22212
22348
  };
22213
22349
  const t = setTimeout(() => {
22214
22350
  signal.removeEventListener("abort", onAbort);
22215
- resolve23();
22351
+ resolve24();
22216
22352
  }, ms);
22217
22353
  signal.addEventListener("abort", onAbort, { once: true });
22218
22354
  });
@@ -22711,7 +22847,7 @@ async function runGenerateContextFactory(deps) {
22711
22847
 
22712
22848
  // src/factory/generateContextFactoryHeadlessHost.ts
22713
22849
  var fs48 = __toESM(require("node:fs"));
22714
- var path44 = __toESM(require("node:path"));
22850
+ var path45 = __toESM(require("node:path"));
22715
22851
 
22716
22852
  // src/stores/pipelineRunStore.ts
22717
22853
  var STORAGE_KEY2 = SRS53_PIPELINE_RUN_KEY_V2;
@@ -22812,11 +22948,11 @@ async function noteAgentsMaterialized(context) {
22812
22948
 
22813
22949
  // src/pipelines/remediation/missingWorkstations.ts
22814
22950
  var fs41 = __toESM(require("fs"));
22815
- var path36 = __toESM(require("path"));
22951
+ var path37 = __toESM(require("path"));
22816
22952
 
22817
22953
  // src/analysis/analysisDetailMarkdownDiscovery.ts
22818
22954
  var fs40 = __toESM(require("fs"));
22819
- var path35 = __toESM(require("path"));
22955
+ var path36 = __toESM(require("path"));
22820
22956
  var SLUG4 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
22821
22957
  var FE2 = /^FE-\d+$/;
22822
22958
  var UC2 = /^UC-\d+$/;
@@ -22878,7 +23014,7 @@ function expectedFeatureDetailBasenameFromRow(row2) {
22878
23014
  return `${code}-${slug}.md`;
22879
23015
  }
22880
23016
  function ctxPath(contextDir2, basename17) {
22881
- return path35.join(contextDir2, basename17);
23017
+ return path36.join(contextDir2, basename17);
22882
23018
  }
22883
23019
  function pushTarget(targets, stem, outputBasename, taskDescription, contextDir2) {
22884
23020
  const meta = STEM_TO_AGENT[stem];
@@ -22894,7 +23030,7 @@ function pushTarget(targets, stem, outputBasename, taskDescription, contextDir2)
22894
23030
  function discoverDetailMarkdownGroups(contextDir2) {
22895
23031
  const groups = [];
22896
23032
  const featureTargets = [];
22897
- const flPath = path35.join(contextDir2, "features-list.json");
23033
+ const flPath = path36.join(contextDir2, "features-list.json");
22898
23034
  const fl = readJson5(flPath);
22899
23035
  const features = Array.isArray(fl?.features) ? fl.features : [];
22900
23036
  for (const row2 of features) {
@@ -22924,7 +23060,7 @@ function discoverDetailMarkdownGroups(contextDir2) {
22924
23060
  if (!FE2.test(feCode)) {
22925
23061
  continue;
22926
23062
  }
22927
- const ucListPath = path35.join(contextDir2, `${feCode}-use-cases-list.json`);
23063
+ const ucListPath = path36.join(contextDir2, `${feCode}-use-cases-list.json`);
22928
23064
  const ucFile = readJson5(ucListPath);
22929
23065
  const ucs = Array.isArray(ucFile?.useCases) ? ucFile.useCases : [];
22930
23066
  for (const ucRow of ucs) {
@@ -22944,7 +23080,7 @@ function discoverDetailMarkdownGroups(contextDir2) {
22944
23080
  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.`,
22945
23081
  contextDir2
22946
23082
  );
22947
- const scPath = path35.join(contextDir2, `${feCode}_${ucCode}-scenarios-list.json`);
23083
+ const scPath = path36.join(contextDir2, `${feCode}_${ucCode}-scenarios-list.json`);
22948
23084
  const scFile = readJson5(scPath);
22949
23085
  const scs = Array.isArray(scFile?.scenarios) ? scFile.scenarios : [];
22950
23086
  for (const scRow of scs) {
@@ -23015,7 +23151,7 @@ Follow bundled agent **agent-md-use-case-detail**: include **## Data inputs and
23015
23151
  groups.push({ id: "detail-services", label: "Detail markdown \u2014 Services", targets: svcTargets });
23016
23152
  groups.push({ id: "detail-methods", label: "Detail markdown \u2014 Methods", targets: meTargets });
23017
23153
  const entTargets = [];
23018
- const dmPath = path35.join(contextDir2, "data-model-list.json");
23154
+ const dmPath = path36.join(contextDir2, "data-model-list.json");
23019
23155
  const dmFile = readJson5(dmPath);
23020
23156
  const ents = Array.isArray(dmFile?.entities) ? dmFile.entities : [];
23021
23157
  for (const erow of ents) {
@@ -23044,7 +23180,7 @@ Follow bundled agent **agent-md-use-case-detail**: include **## Data inputs and
23044
23180
  if (!DM2.test(dmCode)) {
23045
23181
  continue;
23046
23182
  }
23047
- const flPath2 = path35.join(contextDir2, `${dmCode}-fields-list.json`);
23183
+ const flPath2 = path36.join(contextDir2, `${dmCode}-fields-list.json`);
23048
23184
  const flFile = readJson5(flPath2);
23049
23185
  const flds = Array.isArray(flFile?.fields) ? flFile.fields : [];
23050
23186
  for (const frow of flds) {
@@ -23103,7 +23239,7 @@ function fileAndValidationFromKind(kind) {
23103
23239
  return { filePresentYesNo: "no", validationYesNo: "na" };
23104
23240
  }
23105
23241
  function classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeRoot) {
23106
- const abs = path36.join(contextDir2, row2.relativePath);
23242
+ const abs = path37.join(contextDir2, row2.relativePath);
23107
23243
  try {
23108
23244
  const st = fs41.statSync(abs);
23109
23245
  if (!st.isFile()) {
@@ -23142,7 +23278,7 @@ function classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeR
23142
23278
  detail: "Unknown coordination list basename \u2014 no JSON Schema mapping."
23143
23279
  };
23144
23280
  }
23145
- const schemaAbs = path36.join(worktreeRoot, ".opencode", "schemas", "context-lists", schemaBn);
23281
+ const schemaAbs = path37.join(worktreeRoot, ".opencode", "schemas", "context-lists", schemaBn);
23146
23282
  if (!fs41.existsSync(schemaAbs)) {
23147
23283
  return {
23148
23284
  kind: "invalid",
@@ -23172,7 +23308,7 @@ function classifyWorkstationOutputOnDisk(item, contextDir2, worktreeRoot) {
23172
23308
  return classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeRoot).kind;
23173
23309
  }
23174
23310
  function isWorkstationRunSnapshotForWorktree(snapshot, worktreeRoot) {
23175
- return !!(snapshot && snapshot.overallStatus !== "running" && snapshot.overallStatus !== "idle" && path36.resolve(snapshot.analysisRoot) === path36.resolve(worktreeRoot));
23311
+ return !!(snapshot && snapshot.overallStatus !== "running" && snapshot.overallStatus !== "idle" && path37.resolve(snapshot.analysisRoot) === path37.resolve(worktreeRoot));
23176
23312
  }
23177
23313
  function expectedBasenameForCoordPayload(p) {
23178
23314
  const { step, listTarget } = p;
@@ -23246,10 +23382,10 @@ function labelContextForCoordPayload(p) {
23246
23382
  }
23247
23383
  function contextPathForWorkItem(item, contextDir2) {
23248
23384
  if (item.kind === "markdown") {
23249
- return path36.join(contextDir2, item.payload.outputBasename);
23385
+ return path37.join(contextDir2, item.payload.outputBasename);
23250
23386
  }
23251
23387
  const bn = expectedBasenameForCoordPayload(item.payload);
23252
- return bn ? path36.join(contextDir2, bn) : null;
23388
+ return bn ? path37.join(contextDir2, bn) : null;
23253
23389
  }
23254
23390
  function syntheticRunnerId(key) {
23255
23391
  return `remediation:${key}`;
@@ -23259,7 +23395,7 @@ function rowFromSkippedItem(item, contextDir2) {
23259
23395
  return null;
23260
23396
  }
23261
23397
  const abs = contextPathForWorkItem(item, contextDir2);
23262
- const rel = abs ? path36.basename(abs) : item.kind === "markdown" ? item.payload.outputBasename : item.id;
23398
+ const rel = abs ? path37.basename(abs) : item.kind === "markdown" ? item.payload.outputBasename : item.id;
23263
23399
  if (abs && nonEmptyContextFile(abs)) {
23264
23400
  return null;
23265
23401
  }
@@ -23434,7 +23570,7 @@ function toMissingWorkstationUiRows(rows, contextDir2, worktreeRoot) {
23434
23570
  }
23435
23571
 
23436
23572
  // src/pipelines/remediation/missingWorkstationsPool.ts
23437
- var path37 = __toESM(require("path"));
23573
+ var path38 = __toESM(require("path"));
23438
23574
  function reconcileSkippedWorkItemsWithDisk(byId, contextDir2, worktreeRoot) {
23439
23575
  for (const item of byId.values()) {
23440
23576
  if (item.status !== "skipped") {
@@ -23494,7 +23630,7 @@ async function runRemediationPipelineMissingPass(p) {
23494
23630
  onItemComplete,
23495
23631
  sourceBranchAtWorktreeCreation
23496
23632
  } = p;
23497
- const contextDir2 = path37.join(worktreeRoot, ".gluecharm", "context");
23633
+ const contextDir2 = path38.join(worktreeRoot, ".gluecharm", "context");
23498
23634
  const snap = readArtefactRunSnapshot(storageContext);
23499
23635
  const snapOk = isWorkstationRunSnapshotForWorktree(snap, worktreeRoot);
23500
23636
  let byId;
@@ -23561,17 +23697,17 @@ async function runRemediationPipelineMissingPass(p) {
23561
23697
  // src/pipelines/coverage/coveragePipeline.ts
23562
23698
  var import_child_process5 = require("child_process");
23563
23699
  var fs43 = __toESM(require("fs"));
23564
- var path39 = __toESM(require("path"));
23700
+ var path40 = __toESM(require("path"));
23565
23701
 
23566
23702
  // src/analysis/coverageReferenceValidationSchemaValidate.ts
23567
23703
  var fs42 = __toESM(require("fs"));
23568
- var path38 = __toESM(require("path"));
23704
+ var path39 = __toESM(require("path"));
23569
23705
  var import__5 = __toESM(require__());
23570
23706
  function stripUtf8Bom4(s) {
23571
23707
  return s.length > 0 && s.charCodeAt(0) === 65279 ? s.slice(1) : s;
23572
23708
  }
23573
23709
  function bundledCoverageReferenceValidationSchemaPath() {
23574
- return path38.join(
23710
+ return path39.join(
23575
23711
  resolveRepoResourcesRoot(),
23576
23712
  "schemas",
23577
23713
  "context-lists",
@@ -23651,8 +23787,8 @@ var DEFAULT_IGNORE_DIR_BASENAMES = [
23651
23787
  ];
23652
23788
  var GIT_LS_FILES_MAX_BUFFER = 64 * 1024 * 1024;
23653
23789
  function tryLoadGitNonIgnoredPathSet(repositoryRootAbs) {
23654
- const root = path39.resolve(repositoryRootAbs);
23655
- if (!fs43.existsSync(path39.join(root, ".git"))) {
23790
+ const root = path40.resolve(repositoryRootAbs);
23791
+ if (!fs43.existsSync(path40.join(root, ".git"))) {
23656
23792
  return null;
23657
23793
  }
23658
23794
  const env = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
@@ -23720,12 +23856,12 @@ var REFERENCE_COVERAGE_IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
23720
23856
  ".emf"
23721
23857
  ]);
23722
23858
  function isReferenceCoverageExcludedImagePath(relPosix) {
23723
- const ext = path39.extname(relPosix).toLowerCase();
23859
+ const ext = path40.extname(relPosix).toLowerCase();
23724
23860
  return ext.length > 0 && REFERENCE_COVERAGE_IMAGE_EXTENSIONS.has(ext);
23725
23861
  }
23726
23862
  var REFERENCE_COVERAGE_EXCLUDED_FILE_BASENAMES = /* @__PURE__ */ new Set([".gitignore"]);
23727
23863
  function isReferenceCoverageExcludedDefaultBasename(relPosix) {
23728
- const base = path39.basename(relPosix.replace(/\\/g, "/")).toLowerCase();
23864
+ const base = path40.basename(relPosix.replace(/\\/g, "/")).toLowerCase();
23729
23865
  return REFERENCE_COVERAGE_EXCLUDED_FILE_BASENAMES.has(base);
23730
23866
  }
23731
23867
  function decodeBufferForLineCount(buf) {
@@ -23762,12 +23898,12 @@ function normalizeRepoRelativePath(repoRoot, raw) {
23762
23898
  if (!trimmed || trimmed.includes("\0")) {
23763
23899
  return null;
23764
23900
  }
23765
- const abs = path39.resolve(repoRoot, trimmed);
23766
- const rel = path39.relative(repoRoot, abs);
23767
- if (rel.startsWith("..") || path39.isAbsolute(rel)) {
23901
+ const abs = path40.resolve(repoRoot, trimmed);
23902
+ const rel = path40.relative(repoRoot, abs);
23903
+ if (rel.startsWith("..") || path40.isAbsolute(rel)) {
23768
23904
  return null;
23769
23905
  }
23770
- return rel.split(path39.sep).join("/");
23906
+ return rel.split(path40.sep).join("/");
23771
23907
  }
23772
23908
  function collectJsonSourceReferences(node, out) {
23773
23909
  if (node === null || typeof node !== "object") {
@@ -23812,7 +23948,7 @@ function listContextFilesRecursive(dir, acc) {
23812
23948
  return;
23813
23949
  }
23814
23950
  for (const e of entries) {
23815
- const full = path39.join(dir, e.name);
23951
+ const full = path40.join(dir, e.name);
23816
23952
  if (e.isDirectory()) {
23817
23953
  listContextFilesRecursive(full, acc);
23818
23954
  } else if (e.isFile()) {
@@ -23833,8 +23969,8 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
23833
23969
  if (ignoreBasenames.has(e.name)) {
23834
23970
  continue;
23835
23971
  }
23836
- const full = path39.join(dir, e.name);
23837
- const rel = path39.relative(repoRoot, full).split(path39.sep).join("/");
23972
+ const full = path40.join(dir, e.name);
23973
+ const rel = path40.relative(repoRoot, full).split(path40.sep).join("/");
23838
23974
  if (rel.startsWith("..")) {
23839
23975
  continue;
23840
23976
  }
@@ -23892,9 +24028,9 @@ function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings
23892
24028
  const allFiles = [];
23893
24029
  listContextFilesRecursive(contextDirAbs, allFiles);
23894
24030
  for (const abs of allFiles) {
23895
- const ext = path39.extname(abs).toLowerCase();
23896
- const base = path39.basename(abs);
23897
- const sourceArtefact = path39.relative(contextDirAbs, abs).split(path39.sep).join("/");
24031
+ const ext = path40.extname(abs).toLowerCase();
24032
+ const base = path40.basename(abs);
24033
+ const sourceArtefact = path40.relative(contextDirAbs, abs).split(path40.sep).join("/");
23898
24034
  if (ext === ".json") {
23899
24035
  if (SKIP_CONTEXT_JSON.has(base)) {
23900
24036
  continue;
@@ -23976,12 +24112,12 @@ function sortReferenceRows(a, b) {
23976
24112
  return (a.startLine ?? 0) - (b.startLine ?? 0);
23977
24113
  }
23978
24114
  function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirAbs, options) {
23979
- const repoRoot = path39.resolve(repositoryRootAbs);
24115
+ const repoRoot = path40.resolve(repositoryRootAbs);
23980
24116
  const warnings = [];
23981
24117
  const ignoreDirs = [...DEFAULT_IGNORE_DIR_BASENAMES];
23982
24118
  const ignoreSet = new Set(ignoreDirs);
23983
24119
  const maxBytes = options?.maxFileBytes ?? MAX_FILE_BYTES;
23984
- const references = collectReferencesFromContext(path39.resolve(contextDirAbs), repoRoot, warnings);
24120
+ const references = collectReferencesFromContext(path40.resolve(contextDirAbs), repoRoot, warnings);
23985
24121
  references.sort(sortReferenceRows);
23986
24122
  const referencedSet = /* @__PURE__ */ new Set();
23987
24123
  for (const r of references) {
@@ -23989,7 +24125,7 @@ function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirA
23989
24125
  }
23990
24126
  const excludedFiles = [];
23991
24127
  const gitNonIgnoredPaths = tryLoadGitNonIgnoredPathSet(repoRoot);
23992
- if (fs43.existsSync(path39.join(repoRoot, ".git")) && gitNonIgnoredPaths === null) {
24128
+ if (fs43.existsSync(path40.join(repoRoot, ".git")) && gitNonIgnoredPaths === null) {
23993
24129
  warnings.push(
23994
24130
  "Repository has .git but git ls-files failed or git is unavailable; .gitignore / exclude-standard not applied."
23995
24131
  );
@@ -24038,8 +24174,8 @@ function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirA
24038
24174
  return { document: doc, warnings };
24039
24175
  }
24040
24176
  function runCoveragePipeline(opts) {
24041
- const repoRoot = path39.resolve(opts.repositoryRootAbs);
24042
- const contextDir2 = path39.resolve(opts.contextDirAbs);
24177
+ const repoRoot = path40.resolve(opts.repositoryRootAbs);
24178
+ const contextDir2 = path40.resolve(opts.contextDirAbs);
24043
24179
  if (!fs43.existsSync(repoRoot)) {
24044
24180
  return { ok: false, error: `Repository root does not exist: ${repoRoot}` };
24045
24181
  }
@@ -24061,7 +24197,7 @@ ${schemaCheck.errors.join("\n")}`,
24061
24197
  warnings
24062
24198
  };
24063
24199
  }
24064
- const outPath = path39.join(contextDir2, COVERAGE_REFERENCE_VALIDATION_BASENAME);
24200
+ const outPath = path40.join(contextDir2, COVERAGE_REFERENCE_VALIDATION_BASENAME);
24065
24201
  if (opts.write) {
24066
24202
  try {
24067
24203
  const payload = stableStringifyCoverageDocument(document);
@@ -24080,11 +24216,11 @@ ${schemaCheck.errors.join("\n")}`,
24080
24216
  // src/pipelines/remediation/zeroReferenceWorkstationChain.ts
24081
24217
  var crypto = __toESM(require("crypto"));
24082
24218
  var fs45 = __toESM(require("fs"));
24083
- var path41 = __toESM(require("path"));
24219
+ var path42 = __toESM(require("path"));
24084
24220
 
24085
24221
  // src/analysis/zeroReferenceRemediationSchemaValidate.ts
24086
24222
  var fs44 = __toESM(require("fs"));
24087
- var path40 = __toESM(require("path"));
24223
+ var path41 = __toESM(require("path"));
24088
24224
  var import__6 = __toESM(require__());
24089
24225
  function stripUtf8Bom5(s) {
24090
24226
  return s.length > 0 && s.charCodeAt(0) === 65279 ? s.slice(1) : s;
@@ -24104,7 +24240,7 @@ function formatAjvErrors6(errors) {
24104
24240
  }
24105
24241
  var ajv = new import__6.default({ allErrors: true, strict: false });
24106
24242
  function compileSchema(basename17) {
24107
- const schemaPath = path40.join(schemasDir(), basename17);
24243
+ const schemaPath = path41.join(schemasDir(), basename17);
24108
24244
  const schemaRaw = stripUtf8Bom5(fs44.readFileSync(schemaPath, "utf-8"));
24109
24245
  const schema = JSON.parse(schemaRaw);
24110
24246
  return ajv.compile(schema);
@@ -24399,17 +24535,17 @@ function expandArgvTemplate4(template, vars) {
24399
24535
  });
24400
24536
  }
24401
24537
  function schemaRef2(worktreeRoot, schemaBasename) {
24402
- return path41.join(worktreeRoot, ".opencode", "schemas", "context-lists", schemaBasename);
24538
+ return path42.join(worktreeRoot, ".opencode", "schemas", "context-lists", schemaBasename);
24403
24539
  }
24404
24540
  function stagingDir(contextDirAbs) {
24405
- return path41.join(contextDirAbs, "_zero-ref-staging");
24541
+ return path42.join(contextDirAbs, "_zero-ref-staging");
24406
24542
  }
24407
24543
  function stagingPathForTarget(contextDirAbs, kind, targetFilePathPosix) {
24408
24544
  const h = crypto.createHash("sha256").update(targetFilePathPosix, "utf8").digest("hex").slice(0, 16);
24409
- return path41.join(stagingDir(contextDirAbs), `${kind}-${h}.json`);
24545
+ return path42.join(stagingDir(contextDirAbs), `${kind}-${h}.json`);
24410
24546
  }
24411
24547
  function readNonReferencedFilesFromRepositoryRoot(repositoryRootAbs) {
24412
- const p = path41.join(repositoryRootAbs, ".gluecharm", "context", "coverage-reference-validation.json");
24548
+ const p = path42.join(repositoryRootAbs, ".gluecharm", "context", "coverage-reference-validation.json");
24413
24549
  const r = readAndValidateCoverageReferenceValidationFile(p);
24414
24550
  if (!r.ok) {
24415
24551
  return { ok: false, error: r.errors.join("; ") };
@@ -24502,7 +24638,7 @@ function slugifyFeatureLabel(s) {
24502
24638
  return t.length > 0 ? t : "feature";
24503
24639
  }
24504
24640
  function lineCountRepoFile(worktreeRootAbs, relPosix) {
24505
- const abs = path41.join(worktreeRootAbs, ...relPosix.split("/"));
24641
+ const abs = path42.join(worktreeRootAbs, ...relPosix.split("/"));
24506
24642
  let buf;
24507
24643
  try {
24508
24644
  buf = fs45.readFileSync(abs);
@@ -24557,8 +24693,8 @@ var LIST_STEP_HINT = {
24557
24693
  };
24558
24694
  async function applyCoordinationListTriageMerge(input) {
24559
24695
  const cfg = LIST_MERGE_CFG[input.listKind];
24560
- const listPath = path41.join(input.contextDirAbs, cfg.listBasename);
24561
- const schemaPath = path41.join(resolveContextListSchemasDir(), cfg.schemaBasename);
24696
+ const listPath = path42.join(input.contextDirAbs, cfg.listBasename);
24697
+ const schemaPath = path42.join(resolveContextListSchemasDir(), cfg.schemaBasename);
24562
24698
  if (!fs45.existsSync(listPath)) {
24563
24699
  return {
24564
24700
  ok: false,
@@ -24662,10 +24798,10 @@ async function applyCoordinationListTriageMerge(input) {
24662
24798
  }
24663
24799
  async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, workspaceLabel) {
24664
24800
  const outAbs = stagingPathForTarget(contextDirAbs, "classifier", targetFilePathPosix);
24665
- fs45.mkdirSync(path41.dirname(outAbs), { recursive: true });
24666
- const runDir = path41.join(common.worktreeRoot, ".opencode", "_run");
24801
+ fs45.mkdirSync(path42.dirname(outAbs), { recursive: true });
24802
+ const runDir = path42.join(common.worktreeRoot, ".opencode", "_run");
24667
24803
  fs45.mkdirSync(runDir, { recursive: true });
24668
- const outputBasename = path41.basename(outAbs);
24804
+ const outputBasename = path42.basename(outAbs);
24669
24805
  const listTaskDescription = [
24670
24806
  `Target file (repo-relative, POSIX): **${targetFilePathPosix}**`,
24671
24807
  `Workspace label hint: **${workspaceLabel}**.`,
@@ -24701,7 +24837,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
24701
24837
  parentContextBlock: "",
24702
24838
  ...repairAppendix ? { repairAppendix } : {}
24703
24839
  });
24704
- const promptPath = path41.join(runDir, `zero-ref-classify-a${attempt}-${Date.now()}.prompt.txt`);
24840
+ const promptPath = path42.join(runDir, `zero-ref-classify-a${attempt}-${Date.now()}.prompt.txt`);
24705
24841
  fs45.writeFileSync(promptPath, body, "utf-8");
24706
24842
  const argv = expandArgvTemplate4(common.argvTemplate, {
24707
24843
  promptFile: promptPath,
@@ -24833,9 +24969,9 @@ var TRIAGE_SCOPE_META = {
24833
24969
  };
24834
24970
  async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPosix, routingSummary, which) {
24835
24971
  const mdBasename = which === "project" ? "project.md" : "architecture.md";
24836
- const mdAbs = path41.join(contextDirAbs, mdBasename);
24972
+ const mdAbs = path42.join(contextDirAbs, mdBasename);
24837
24973
  const agentStem = which === "project" ? ZERO_REF_ADD_REF_PROJECT_AGENT_STEM : ZERO_REF_ADD_REF_ARCH_AGENT_STEM;
24838
- const runDir = path41.join(common.worktreeRoot, ".opencode", "_run");
24974
+ const runDir = path42.join(common.worktreeRoot, ".opencode", "_run");
24839
24975
  fs45.mkdirSync(runDir, { recursive: true });
24840
24976
  const lines = [
24841
24977
  `# SRS-30 \u2014 Add reference to ${mdBasename}`,
@@ -24851,7 +24987,7 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
24851
24987
  `- If the file is short, \`${targetFilePathPosix}:1-<lastLine>\` is acceptable.`,
24852
24988
  `- Do not remove unrelated content; append or extend the most appropriate section.`
24853
24989
  ];
24854
- const promptPath = path41.join(runDir, `zero-ref-md-${which}-${Date.now()}.prompt.txt`);
24990
+ const promptPath = path42.join(runDir, `zero-ref-md-${which}-${Date.now()}.prompt.txt`);
24855
24991
  fs45.writeFileSync(promptPath, lines.join("\n"), "utf-8");
24856
24992
  const argv = expandArgvTemplate4(common.argvTemplate, {
24857
24993
  promptFile: promptPath,
@@ -24879,10 +25015,10 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
24879
25015
  async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathPosix, routingSummary, workspaceLabel, triageScope) {
24880
25016
  const meta = TRIAGE_SCOPE_META[triageScope];
24881
25017
  const outAbs = stagingPathForTarget(contextDirAbs, "triage", targetFilePathPosix);
24882
- fs45.mkdirSync(path41.dirname(outAbs), { recursive: true });
24883
- const runDir = path41.join(common.worktreeRoot, ".opencode", "_run");
25018
+ fs45.mkdirSync(path42.dirname(outAbs), { recursive: true });
25019
+ const runDir = path42.join(common.worktreeRoot, ".opencode", "_run");
24884
25020
  fs45.mkdirSync(runDir, { recursive: true });
24885
- const outputBasename = path41.basename(outAbs);
25021
+ const outputBasename = path42.basename(outAbs);
24886
25022
  const listTaskDescription = [
24887
25023
  `Target file: **${targetFilePathPosix}** (${workspaceLabel})`,
24888
25024
  "**Classifier summary:**",
@@ -24912,7 +25048,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
24912
25048
  parentContextBlock: "",
24913
25049
  ...repairAppendix ? { repairAppendix } : {}
24914
25050
  });
24915
- const promptPath = path41.join(runDir, `zero-ref-triage-a${attempt}-${Date.now()}.prompt.txt`);
25051
+ const promptPath = path42.join(runDir, `zero-ref-triage-a${attempt}-${Date.now()}.prompt.txt`);
24916
25052
  fs45.writeFileSync(promptPath, body, "utf-8");
24917
25053
  const argv = expandArgvTemplate4(common.argvTemplate, {
24918
25054
  promptFile: promptPath,
@@ -25027,8 +25163,8 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
25027
25163
  return { ok: false, message: lastFailureMessage, stagingPath: outAbs };
25028
25164
  }
25029
25165
  async function runOneUnreferencedFilePipeline(p) {
25030
- const routingAbs = path41.join(p.contextDirAbs, ZERO_REF_ROUTING_BASENAME);
25031
- const triageAbs = path41.join(p.contextDirAbs, ZERO_REF_TRIAGE_BASENAME);
25166
+ const routingAbs = path42.join(p.contextDirAbs, ZERO_REF_ROUTING_BASENAME);
25167
+ const triageAbs = path42.join(p.contextDirAbs, ZERO_REF_TRIAGE_BASENAME);
25032
25168
  const key = p.targetFilePathPosix;
25033
25169
  const cr = await runClassifierAgent(p, p.contextDirAbs, key, p.workspaceLabel);
25034
25170
  if (!cr.ok) {
@@ -25052,7 +25188,7 @@ async function runOneUnreferencedFilePipeline(p) {
25052
25188
  if (!s.ok) {
25053
25189
  throw new Error(s.errors.join("; "));
25054
25190
  }
25055
- fs45.mkdirSync(path41.dirname(routingAbs), { recursive: true });
25191
+ fs45.mkdirSync(path42.dirname(routingAbs), { recursive: true });
25056
25192
  fs45.writeFileSync(routingAbs, s.json, "utf-8");
25057
25193
  });
25058
25194
  const routing = stagingParsed.routing;
@@ -25101,7 +25237,7 @@ async function runOneUnreferencedFilePipeline(p) {
25101
25237
  if (!s.ok) {
25102
25238
  throw new Error(s.errors.join("; "));
25103
25239
  }
25104
- fs45.mkdirSync(path41.dirname(triageAbs), { recursive: true });
25240
+ fs45.mkdirSync(path42.dirname(triageAbs), { recursive: true });
25105
25241
  fs45.writeFileSync(triageAbs, s.json, "utf-8");
25106
25242
  });
25107
25243
  const decision = triageParsed.decision;
@@ -25129,11 +25265,11 @@ async function runOneUnreferencedFilePipeline(p) {
25129
25265
  return { ok: true, message: `Triage ${decision}.` };
25130
25266
  }
25131
25267
  async function runRemediationPipelineZeroRefPass(p) {
25132
- const contextDirAbs = path41.join(p.worktreeRoot, ".gluecharm", "context");
25268
+ const contextDirAbs = path42.join(p.worktreeRoot, ".gluecharm", "context");
25133
25269
  const covRoot = p.coverageRepositoryRootAbs ?? p.workspaceRootAbs;
25134
25270
  const cov = readNonReferencedFilesFromRepositoryRoot(covRoot);
25135
25271
  const coverageAt = cov.ok ? cov.generatedAt : void 0;
25136
- const workspaceLabel = path41.basename(p.worktreeRoot);
25272
+ const workspaceLabel = path42.basename(p.worktreeRoot);
25137
25273
  const routingMutex = new AsyncMutex();
25138
25274
  const triageMutex = new AsyncMutex();
25139
25275
  const paths = [...p.paths];
@@ -25191,7 +25327,7 @@ async function runRemediationPipelineZeroRefPass(p) {
25191
25327
 
25192
25328
  // src/pipelines/coverage/coverageExecutionReport.ts
25193
25329
  var fs46 = __toESM(require("fs"));
25194
- var path42 = __toESM(require("path"));
25330
+ var path43 = __toESM(require("path"));
25195
25331
  var REFERENCE_COVERAGE_EXECUTION_REPORT_BASENAME = "reference-coverage-execution-report.md";
25196
25332
  function inlineMdText(s) {
25197
25333
  const t = s.replace(/\r\n/g, "\n").replace(/\n/g, " ").trim();
@@ -25315,10 +25451,10 @@ async function runCoverageExecutionReport(p) {
25315
25451
  if (p.abortSignal?.aborted) {
25316
25452
  return { ok: false, error: "Stopped.", cancelled: true };
25317
25453
  }
25318
- const contextDirAbs = path42.join(p.repositoryRootAbs, ".gluecharm", "context");
25319
- const coverageAbs = path42.join(contextDirAbs, "coverage-reference-validation.json");
25320
- const routingAbs = path42.join(contextDirAbs, "zero-reference-routing.json");
25321
- const outAbs = path42.join(contextDirAbs, REFERENCE_COVERAGE_EXECUTION_REPORT_BASENAME);
25454
+ const contextDirAbs = path43.join(p.repositoryRootAbs, ".gluecharm", "context");
25455
+ const coverageAbs = path43.join(contextDirAbs, "coverage-reference-validation.json");
25456
+ const routingAbs = path43.join(contextDirAbs, "zero-reference-routing.json");
25457
+ const outAbs = path43.join(contextDirAbs, REFERENCE_COVERAGE_EXECUTION_REPORT_BASENAME);
25322
25458
  const cov = readAndValidateCoverageReferenceValidationFile(coverageAbs);
25323
25459
  if (!cov.ok) {
25324
25460
  return { ok: false, error: `Coverage JSON: ${cov.errors.join("; ")}` };
@@ -25342,7 +25478,7 @@ async function runCoverageExecutionReport(p) {
25342
25478
  previous = void 0;
25343
25479
  }
25344
25480
  try {
25345
- fs46.mkdirSync(path42.dirname(outAbs), { recursive: true });
25481
+ fs46.mkdirSync(path43.dirname(outAbs), { recursive: true });
25346
25482
  fs46.writeFileSync(outAbs, md, "utf-8");
25347
25483
  } catch (e) {
25348
25484
  const msg = e instanceof Error ? e.message : String(e);
@@ -25360,7 +25496,7 @@ async function runCoverageExecutionReport(p) {
25360
25496
 
25361
25497
  // src/gluecharm/minimalGluecharmLayout.ts
25362
25498
  var fs47 = __toESM(require("node:fs"));
25363
- var path43 = __toESM(require("node:path"));
25499
+ var path44 = __toESM(require("node:path"));
25364
25500
  var MINIMAL_GLUECHARM_RELATIVE_DIRS = [
25365
25501
  [".gluecharm", "docs", "srs"],
25366
25502
  [".gluecharm", "content"],
@@ -25368,9 +25504,9 @@ var MINIMAL_GLUECHARM_RELATIVE_DIRS = [
25368
25504
  [".gluecharm", "context"]
25369
25505
  ];
25370
25506
  function ensureMinimalGluecharmLayoutNode(repoRootAbs) {
25371
- const root = path43.resolve(repoRootAbs);
25507
+ const root = path44.resolve(repoRootAbs);
25372
25508
  for (const segments of MINIMAL_GLUECHARM_RELATIVE_DIRS) {
25373
- const dir = path43.join(root, ...segments);
25509
+ const dir = path44.join(root, ...segments);
25374
25510
  try {
25375
25511
  fs47.mkdirSync(dir, { recursive: true });
25376
25512
  } catch (e) {
@@ -25502,7 +25638,7 @@ function buildFactoryDepsHeadless(input) {
25502
25638
  if (!layout.ok) {
25503
25639
  return { ok: false, error: layout.error };
25504
25640
  }
25505
- const ctxDir = path44.join(ar, ".gluecharm", "context");
25641
+ const ctxDir = path45.join(ar, ".gluecharm", "context");
25506
25642
  const snap = readArtefactRunSnapshot(storageContext);
25507
25643
  const rows = listMissingWorkstations(ctxDir, ar, snap);
25508
25644
  if (rows.length === 0) {
@@ -25516,7 +25652,7 @@ function buildFactoryDepsHeadless(input) {
25516
25652
  storageContext,
25517
25653
  repositoryRoot: repoRoot,
25518
25654
  worktreeRoot: ar,
25519
- workspaceLabel: path44.basename(ar),
25655
+ workspaceLabel: path45.basename(ar),
25520
25656
  oc: {
25521
25657
  ...oc,
25522
25658
  aceEnabled: getAceAnalysisEnabledForCheckout(ar),
@@ -25544,7 +25680,7 @@ function buildFactoryDepsHeadless(input) {
25544
25680
  }
25545
25681
  try {
25546
25682
  await startPipelineRun(storageContext, repoRoot);
25547
- const folderName = path44.basename(repoRoot);
25683
+ const folderName = path45.basename(repoRoot);
25548
25684
  const oc = buildOpenCodeOptions(handle.path);
25549
25685
  const result = await runSynthesisPipelineDrainFromPreparedWorktree(
25550
25686
  storageContext,
@@ -25601,7 +25737,7 @@ function buildFactoryDepsHeadless(input) {
25601
25737
  if (!ar) {
25602
25738
  return 0;
25603
25739
  }
25604
- const ctxDir = path44.join(ar, ".gluecharm", "context");
25740
+ const ctxDir = path45.join(ar, ".gluecharm", "context");
25605
25741
  const snap = readArtefactRunSnapshot(storageContext);
25606
25742
  return listMissingWorkstations(ctxDir, ar, snap).length;
25607
25743
  };
@@ -25614,7 +25750,7 @@ function buildFactoryDepsHeadless(input) {
25614
25750
  if (!layout.ok) {
25615
25751
  return { ok: false, message: layout.error };
25616
25752
  }
25617
- const contextDir2 = path44.join(ar, ".gluecharm", "context");
25753
+ const contextDir2 = path45.join(ar, ".gluecharm", "context");
25618
25754
  log(`[factory] reference coverage (worktree) \u2014 ${ar}`);
25619
25755
  const res = runCoveragePipeline({
25620
25756
  repositoryRootAbs: ar,
@@ -25674,7 +25810,7 @@ function buildFactoryDepsHeadless(input) {
25674
25810
  diagnosticLog: log
25675
25811
  });
25676
25812
  if (res.ok) {
25677
- return { ok: true, message: `Report: ${path44.basename(res.outputAbsolutePath)}` };
25813
+ return { ok: true, message: `Report: ${path45.basename(res.outputAbsolutePath)}` };
25678
25814
  }
25679
25815
  if (res.cancelled) {
25680
25816
  return { ok: false, cancelled: true, message: "Report generation stopped." };
@@ -25690,7 +25826,7 @@ function buildFactoryDepsHeadless(input) {
25690
25826
  if (!lmLayout.ok) {
25691
25827
  return { ok: false, message: lmLayout.error };
25692
25828
  }
25693
- const contextDir2 = path44.join(snap.adHocWorktreePath, ".gluecharm", "context");
25829
+ const contextDir2 = path45.join(snap.adHocWorktreePath, ".gluecharm", "context");
25694
25830
  const linkGraph = runLinkMappingPipeline(contextDir2, { log });
25695
25831
  if (!linkGraph.ok) {
25696
25832
  return { ok: false, message: linkGraph.error };
@@ -25706,7 +25842,7 @@ function buildFactoryDepsHeadless(input) {
25706
25842
  if (!idxLayout.ok) {
25707
25843
  return { ok: false, message: idxLayout.error };
25708
25844
  }
25709
- const contextDir2 = path44.join(snap.adHocWorktreePath, ".gluecharm", "context");
25845
+ const contextDir2 = path45.join(snap.adHocWorktreePath, ".gluecharm", "context");
25710
25846
  try {
25711
25847
  writeIndexApplicationContext(contextDir2, void 0, {
25712
25848
  sourceBranchAtWorktreeCreation: snap.adHocSourceBranchAtCreation
@@ -25761,13 +25897,13 @@ function buildFactoryDepsHeadless(input) {
25761
25897
  },
25762
25898
  runPrepareAnalysisWorktree: async (resume) => {
25763
25899
  if (resume) {
25764
- if (adHocWorktree && fs48.existsSync(path44.join(adHocWorktree.path, ".git"))) {
25900
+ if (adHocWorktree && fs48.existsSync(path45.join(adHocWorktree.path, ".git"))) {
25765
25901
  return { ok: true };
25766
25902
  }
25767
25903
  const snap = readAnalysisWorkspaceSnapshot(storageContext);
25768
25904
  const wtPath = snap?.adHocWorktreePath?.trim();
25769
25905
  const repo = snap?.adHocRepositoryRoot?.trim() || repoRoot;
25770
- if (wtPath && fs48.existsSync(path44.join(wtPath, ".git"))) {
25906
+ if (wtPath && fs48.existsSync(path45.join(wtPath, ".git"))) {
25771
25907
  adHocWorktree = resolveAnalysisCheckoutHandle(wtPath, repo);
25772
25908
  macroSourceBranch = snap?.adHocSourceBranchAtCreation;
25773
25909
  macroFinalize = () => {
@@ -25985,11 +26121,11 @@ function stderrLinesForFactoryFailures(failures, exitCode) {
25985
26121
  }
25986
26122
 
25987
26123
  // src/factory/updateContext/runUpdateContextFactory.ts
25988
- var path49 = __toESM(require("node:path"));
26124
+ var path50 = __toESM(require("node:path"));
25989
26125
 
25990
26126
  // src/factory/updateContext/updateContextBaseline.ts
25991
26127
  var fs49 = __toESM(require("node:fs"));
25992
- var path45 = __toESM(require("node:path"));
26128
+ var path46 = __toESM(require("node:path"));
25993
26129
  function isValidIso(s) {
25994
26130
  const t = Date.parse(s);
25995
26131
  return Number.isFinite(t);
@@ -26004,7 +26140,7 @@ function maxMtimeRegularFilesUnderDir(dirAbs) {
26004
26140
  return;
26005
26141
  }
26006
26142
  for (const e of entries) {
26007
- const p = path45.join(d, e.name);
26143
+ const p = path46.join(d, e.name);
26008
26144
  if (e.isDirectory()) {
26009
26145
  walk(p);
26010
26146
  } else if (e.isFile()) {
@@ -26030,7 +26166,7 @@ function resolveUpdateContextBaseline(repoRootAbs, repoConfig) {
26030
26166
  if (last.length > 0 && isValidIso(last)) {
26031
26167
  return { baselineIsoUtc: new Date(last).toISOString(), source: "lastRunAt" };
26032
26168
  }
26033
- const ctxDir = path45.join(repoRootAbs, ".gluecharm", "context");
26169
+ const ctxDir = path46.join(repoRootAbs, ".gluecharm", "context");
26034
26170
  if (!fs49.existsSync(ctxDir)) {
26035
26171
  return null;
26036
26172
  }
@@ -26055,7 +26191,7 @@ function persistUpdateContextLastRunAt(repoRootAbs, isoUtc) {
26055
26191
  // src/factory/updateContext/updateContextGitWindow.ts
26056
26192
  var import_node_child_process3 = require("node:child_process");
26057
26193
  var fs50 = __toESM(require("node:fs"));
26058
- var path46 = __toESM(require("node:path"));
26194
+ var path47 = __toESM(require("node:path"));
26059
26195
  var GIT_ENV = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
26060
26196
  function gitLines(repoRootAbs, args) {
26061
26197
  const r = (0, import_node_child_process3.execFileSync)("git", ["-c", "core.quotepath=false", ...args], {
@@ -26079,8 +26215,8 @@ function parseGitLogIso(line) {
26079
26215
  return { hash, iso };
26080
26216
  }
26081
26217
  function discoverCommitWindowAndTouchedPaths(repoRootAbs, baselineIsoUtc) {
26082
- const root = path46.resolve(repoRootAbs);
26083
- if (!fs50.existsSync(path46.join(root, ".git"))) {
26218
+ const root = path47.resolve(repoRootAbs);
26219
+ if (!fs50.existsSync(path47.join(root, ".git"))) {
26084
26220
  return { ok: false, error: "Not a git repository (missing .git)." };
26085
26221
  }
26086
26222
  const baselineMs = Date.parse(baselineIsoUtc);
@@ -26139,11 +26275,11 @@ function discoverCommitWindowAndTouchedPaths(repoRootAbs, baselineIsoUtc) {
26139
26275
  };
26140
26276
  }
26141
26277
  function filterPathsExistingInWorktree(worktreeRootAbs, pathsPosix) {
26142
- const root = path46.resolve(worktreeRootAbs);
26278
+ const root = path47.resolve(worktreeRootAbs);
26143
26279
  const out = [];
26144
26280
  for (const p of pathsPosix) {
26145
26281
  const rel = p.replace(/\\/g, "/");
26146
- const abs = path46.join(root, ...rel.split("/"));
26282
+ const abs = path47.join(root, ...rel.split("/"));
26147
26283
  try {
26148
26284
  if (fs50.existsSync(abs) && fs50.statSync(abs).isFile()) {
26149
26285
  out.push(rel);
@@ -26156,7 +26292,7 @@ function filterPathsExistingInWorktree(worktreeRootAbs, pathsPosix) {
26156
26292
 
26157
26293
  // src/factory/updateContext/updateContextReport.ts
26158
26294
  var fs51 = __toESM(require("node:fs"));
26159
- var path47 = __toESM(require("node:path"));
26295
+ var path48 = __toESM(require("node:path"));
26160
26296
  var CHANGES_SINCE_DATE_BASENAME = "changes-since-date.md";
26161
26297
  function renderChangesSinceDateMarkdown(p) {
26162
26298
  const lines = [
@@ -26198,7 +26334,7 @@ function renderChangesSinceDateMarkdown(p) {
26198
26334
  function writeChangesSinceDateReport(contextDirAbs, body) {
26199
26335
  try {
26200
26336
  fs51.mkdirSync(contextDirAbs, { recursive: true });
26201
- const target = path47.join(contextDirAbs, CHANGES_SINCE_DATE_BASENAME);
26337
+ const target = path48.join(contextDirAbs, CHANGES_SINCE_DATE_BASENAME);
26202
26338
  fs51.writeFileSync(target, body, "utf-8");
26203
26339
  return { ok: true };
26204
26340
  } catch (e) {
@@ -26208,7 +26344,7 @@ function writeChangesSinceDateReport(contextDirAbs, body) {
26208
26344
 
26209
26345
  // src/factory/updateContext/updateContextSeedCheck.ts
26210
26346
  var fs52 = __toESM(require("node:fs"));
26211
- var path48 = __toESM(require("node:path"));
26347
+ var path49 = __toESM(require("node:path"));
26212
26348
  var INDEX_BASENAME = "index-application-context.json";
26213
26349
  var CHANGES_REPORT = "changes-since-date.md";
26214
26350
  function tryParseJsonFile(abs) {
@@ -26224,7 +26360,7 @@ function isWorktreeContextSeeded(contextDirAbs) {
26224
26360
  if (!fs52.existsSync(contextDirAbs)) {
26225
26361
  return false;
26226
26362
  }
26227
- const indexAbs = path48.join(contextDirAbs, INDEX_BASENAME);
26363
+ const indexAbs = path49.join(contextDirAbs, INDEX_BASENAME);
26228
26364
  if (fs52.existsSync(indexAbs) && fs52.statSync(indexAbs).isFile() && tryParseJsonFile(indexAbs)) {
26229
26365
  return true;
26230
26366
  }
@@ -26242,7 +26378,7 @@ function isWorktreeContextSeeded(contextDirAbs) {
26242
26378
  if (!name.endsWith(".md") && !name.endsWith(".json")) {
26243
26379
  continue;
26244
26380
  }
26245
- const p = path48.join(contextDirAbs, name);
26381
+ const p = path49.join(contextDirAbs, name);
26246
26382
  try {
26247
26383
  if (fs52.statSync(p).isFile()) {
26248
26384
  distinct.add(name);
@@ -26256,7 +26392,7 @@ function isWorktreeContextSeeded(contextDirAbs) {
26256
26392
  // src/factory/updateContext/runUpdateContextFactory.ts
26257
26393
  var REMEDIATION_CHUNK_MAX = 40;
26258
26394
  function contextDirUnderRoot(wtRoot) {
26259
- return path49.join(wtRoot, ".gluecharm", "context");
26395
+ return path50.join(wtRoot, ".gluecharm", "context");
26260
26396
  }
26261
26397
  async function runUpdateContextFactory(deps) {
26262
26398
  const inPlace = deps.inPlace === true;
@@ -26587,11 +26723,11 @@ async function runUpdateContextFactory(deps) {
26587
26723
 
26588
26724
  // src/factory/contextDrift/runContextDriftFactory.ts
26589
26725
  var fs58 = __toESM(require("node:fs"));
26590
- var path54 = __toESM(require("node:path"));
26726
+ var path55 = __toESM(require("node:path"));
26591
26727
 
26592
26728
  // src/factory/contextDrift/contextDriftManifest.ts
26593
26729
  var fs53 = __toESM(require("node:fs"));
26594
- var path50 = __toESM(require("node:path"));
26730
+ var path51 = __toESM(require("node:path"));
26595
26731
  var MAX_REFERENCE_BYTES = 256 * 1024;
26596
26732
  var MAX_EVIDENCE_FILES = 300;
26597
26733
  var MAX_EVIDENCE_READ = 512 * 1024;
@@ -26611,16 +26747,16 @@ function collectEvidencePaths(repoRoot) {
26611
26747
  const out = [];
26612
26748
  const roots = ["src", "test", "tests", "packages", ".gluecharm", "scripts"];
26613
26749
  for (const rel of roots) {
26614
- const abs = path50.join(repoRoot, rel);
26750
+ const abs = path51.join(repoRoot, rel);
26615
26751
  if (!fs53.existsSync(abs)) {
26616
26752
  continue;
26617
26753
  }
26618
26754
  walkFiles(abs, repoRoot, out, 0);
26619
26755
  }
26620
26756
  for (const leaf of ["package.json", "tsconfig.json"]) {
26621
- const abs = path50.join(repoRoot, leaf);
26757
+ const abs = path51.join(repoRoot, leaf);
26622
26758
  if (fs53.existsSync(abs) && fs53.statSync(abs).isFile()) {
26623
- const r = path50.relative(repoRoot, abs).split(path50.sep).join("/");
26759
+ const r = path51.relative(repoRoot, abs).split(path51.sep).join("/");
26624
26760
  out.push(r);
26625
26761
  }
26626
26762
  }
@@ -26645,13 +26781,13 @@ function walkFiles(dir, repoRoot, out, depth) {
26645
26781
  if (e.name === "node_modules" || e.name === ".git" || e.name === "dist" || e.name === "out") {
26646
26782
  continue;
26647
26783
  }
26648
- const full = path50.join(dir, e.name);
26784
+ const full = path51.join(dir, e.name);
26649
26785
  if (e.isDirectory()) {
26650
26786
  walkFiles(full, repoRoot, out, depth + 1);
26651
26787
  } else if (e.isFile()) {
26652
- const ext = path50.extname(e.name).toLowerCase();
26788
+ const ext = path51.extname(e.name).toLowerCase();
26653
26789
  if ([".ts", ".tsx", ".js", ".mjs", ".cjs", ".json", ".md", ".yaml", ".yml"].includes(ext) || e.name === "Dockerfile") {
26654
- const rel = path50.relative(repoRoot, full).split(path50.sep).join("/");
26790
+ const rel = path51.relative(repoRoot, full).split(path51.sep).join("/");
26655
26791
  out.push(rel);
26656
26792
  }
26657
26793
  }
@@ -26661,7 +26797,7 @@ function buildComparisonManifest(args) {
26661
26797
  const references = [];
26662
26798
  let referenceTruncated = false;
26663
26799
  for (const abs of args.bundleAbsFiles) {
26664
- const rel = path50.relative(args.worktreeRoot, abs).split(path50.sep).join("/");
26800
+ const rel = path51.relative(args.worktreeRoot, abs).split(path51.sep).join("/");
26665
26801
  const { text, truncated } = readFileLimited(abs, MAX_REFERENCE_BYTES);
26666
26802
  references.push({ path: rel, content: text, truncated });
26667
26803
  if (truncated) {
@@ -26673,7 +26809,7 @@ function buildComparisonManifest(args) {
26673
26809
  const omitted = Math.max(0, allEvidence.length - evidencePathsTrimmed.length);
26674
26810
  const evidenceFiles = [];
26675
26811
  for (const rel of evidencePathsTrimmed) {
26676
- const abs = path50.join(args.worktreeRoot, ...rel.split("/"));
26812
+ const abs = path51.join(args.worktreeRoot, ...rel.split("/"));
26677
26813
  const st = fs53.existsSync(abs) ? fs53.statSync(abs) : null;
26678
26814
  const size = st && st.isFile() ? st.size : 0;
26679
26815
  const { text, truncated } = readFileLimited(abs, MAX_EVIDENCE_READ);
@@ -26684,7 +26820,7 @@ function buildComparisonManifest(args) {
26684
26820
  }
26685
26821
  return {
26686
26822
  runDate: args.runDate,
26687
- referenceRelPaths: args.bundleAbsFiles.map((a) => path50.relative(args.worktreeRoot, a).split(path50.sep).join("/")),
26823
+ referenceRelPaths: args.bundleAbsFiles.map((a) => path51.relative(args.worktreeRoot, a).split(path51.sep).join("/")),
26688
26824
  references,
26689
26825
  evidenceFiles,
26690
26826
  evidencePathsOnly: [],
@@ -26697,7 +26833,7 @@ function buildComparisonManifest(args) {
26697
26833
 
26698
26834
  // src/factory/contextDrift/contextDriftAgent.ts
26699
26835
  var fs54 = __toESM(require("node:fs"));
26700
- var path51 = __toESM(require("node:path"));
26836
+ var path52 = __toESM(require("node:path"));
26701
26837
 
26702
26838
  // src/factory/contextDrift/contextDriftPayload.ts
26703
26839
  function isNonEmptyString2(v) {
@@ -26842,16 +26978,16 @@ function buildDriftPrompt(args) {
26842
26978
  ].join("\n");
26843
26979
  }
26844
26980
  async function runDriftComparisonOpenCode(args) {
26845
- const runDir = path51.join(args.worktreeRoot, ".opencode", "_run");
26981
+ const runDir = path52.join(args.worktreeRoot, ".opencode", "_run");
26846
26982
  fs54.mkdirSync(runDir, { recursive: true });
26847
- const manifestPath = path51.join(runDir, "context-drift-manifest.json");
26848
- const outputPath = path51.join(runDir, "context-drift-payload.json");
26983
+ const manifestPath = path52.join(runDir, "context-drift-manifest.json");
26984
+ const outputPath = path52.join(runDir, "context-drift-payload.json");
26849
26985
  fs54.writeFileSync(manifestPath, `${JSON.stringify(args.manifestObject, null, 2)}
26850
26986
  `, "utf8");
26851
26987
  if (fs54.existsSync(outputPath)) {
26852
26988
  fs54.unlinkSync(outputPath);
26853
26989
  }
26854
- const promptPath = path51.join(runDir, `context-drift-${Date.now()}.prompt.txt`);
26990
+ const promptPath = path52.join(runDir, `context-drift-${Date.now()}.prompt.txt`);
26855
26991
  fs54.writeFileSync(
26856
26992
  promptPath,
26857
26993
  buildDriftPrompt({
@@ -26869,7 +27005,7 @@ async function runDriftComparisonOpenCode(args) {
26869
27005
  });
26870
27006
  const title = buildOpenCodeSessionTitle({
26871
27007
  runId: "context-drift",
26872
- workItemId: path51.basename(args.worktreeRoot).slice(0, 24) || "wt",
27008
+ workItemId: path52.basename(args.worktreeRoot).slice(0, 24) || "wt",
26873
27009
  stepLabel: "context-drift"
26874
27010
  });
26875
27011
  const argv = injectPrimaryOpenCodeSessionArgv(expanded, title);
@@ -26912,8 +27048,8 @@ async function runDriftComparisonOpenCode(args) {
26912
27048
  // src/factory/contextDrift/contextDriftPaths.ts
26913
27049
  var crypto2 = __toESM(require("node:crypto"));
26914
27050
  var fs55 = __toESM(require("node:fs"));
26915
- var path52 = __toESM(require("node:path"));
26916
- var DRIFT_CONTEXT_SUBDIR = path52.join(".gluecharm", "context", "drift");
27051
+ var path53 = __toESM(require("node:path"));
27052
+ var DRIFT_CONTEXT_SUBDIR = path53.join(".gluecharm", "context", "drift");
26917
27053
  function sanitizeSlug(raw) {
26918
27054
  const s = raw.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
26919
27055
  return s.length > 0 ? s : "drift";
@@ -26922,9 +27058,9 @@ function utcDateString(d) {
26922
27058
  return d.toISOString().slice(0, 10);
26923
27059
  }
26924
27060
  function resolveInsideRepo(repoRootAbs, userPath) {
26925
- const abs = path52.isAbsolute(userPath) ? path52.normalize(userPath) : path52.resolve(repoRootAbs, userPath);
26926
- const rel = path52.relative(repoRootAbs, abs);
26927
- if (rel.startsWith("..") || path52.isAbsolute(rel)) {
27061
+ const abs = path53.isAbsolute(userPath) ? path53.normalize(userPath) : path53.resolve(repoRootAbs, userPath);
27062
+ const rel = path53.relative(repoRootAbs, abs);
27063
+ if (rel.startsWith("..") || path53.isAbsolute(rel)) {
26928
27064
  return { ok: false };
26929
27065
  }
26930
27066
  return { ok: true, abs };
@@ -26934,7 +27070,7 @@ function computeSlug(args) {
26934
27070
  return sanitizeSlug(args.label.trim());
26935
27071
  }
26936
27072
  const r = resolveInsideRepo(args.repoRootAbs, args.referencePath);
26937
- const base = r.ok ? path52.basename(r.abs) : path52.basename(args.referencePath);
27073
+ const base = r.ok ? path53.basename(r.abs) : path53.basename(args.referencePath);
26938
27074
  return sanitizeSlug(base);
26939
27075
  }
26940
27076
  function driftFilename(slug, runDate) {
@@ -26976,7 +27112,7 @@ function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
26976
27112
  return;
26977
27113
  }
26978
27114
  for (const e of entries) {
26979
- const full = path52.join(dir, e.name);
27115
+ const full = path53.join(dir, e.name);
26980
27116
  if (e.isDirectory()) {
26981
27117
  if (e.name === "node_modules" || e.name === ".git") {
26982
27118
  continue;
@@ -27006,7 +27142,7 @@ function pickReferenceRootDocument(args) {
27006
27142
  }
27007
27143
  const dir = args.referenceAbsInWorktree;
27008
27144
  for (const name of ["index.md", "README.md"]) {
27009
- const p = path52.join(dir, name);
27145
+ const p = path53.join(dir, name);
27010
27146
  if (fs55.existsSync(p) && fs55.statSync(p).isFile()) {
27011
27147
  return { ok: true, path: p };
27012
27148
  }
@@ -27017,10 +27153,10 @@ function pickReferenceRootDocument(args) {
27017
27153
  };
27018
27154
  }
27019
27155
  function toWorktreeRelative(worktreeRoot, absolute) {
27020
- return path52.relative(worktreeRoot, absolute).split(path52.sep).join("/");
27156
+ return path53.relative(worktreeRoot, absolute).split(path53.sep).join("/");
27021
27157
  }
27022
27158
  function toPosixPath(p) {
27023
- return p.split(path52.sep).join("/");
27159
+ return p.split(path53.sep).join("/");
27024
27160
  }
27025
27161
 
27026
27162
  // src/factory/contextDrift/contextDriftIndex.ts
@@ -27063,19 +27199,19 @@ function escapeRe(s) {
27063
27199
 
27064
27200
  // src/factory/contextDrift/contextDriftPromote.ts
27065
27201
  var fs57 = __toESM(require("node:fs"));
27066
- var path53 = __toESM(require("node:path"));
27202
+ var path54 = __toESM(require("node:path"));
27067
27203
  function copyWorktreeFileToWorkspace(args) {
27068
- const wt = path53.resolve(args.worktreeRoot);
27069
- const ws = path53.resolve(args.workspaceRoot);
27204
+ const wt = path54.resolve(args.worktreeRoot);
27205
+ const ws = path54.resolve(args.workspaceRoot);
27070
27206
  if (wt === ws) {
27071
27207
  return;
27072
27208
  }
27073
- const src = path53.join(args.worktreeRoot, ...args.relativePosix.split("/"));
27074
- const dest = path53.join(args.workspaceRoot, ...args.relativePosix.split("/"));
27075
- if (path53.resolve(src) === path53.resolve(dest)) {
27209
+ const src = path54.join(args.worktreeRoot, ...args.relativePosix.split("/"));
27210
+ const dest = path54.join(args.workspaceRoot, ...args.relativePosix.split("/"));
27211
+ if (path54.resolve(src) === path54.resolve(dest)) {
27076
27212
  return;
27077
27213
  }
27078
- fs57.mkdirSync(path53.dirname(dest), { recursive: true });
27214
+ fs57.mkdirSync(path54.dirname(dest), { recursive: true });
27079
27215
  fs57.copyFileSync(src, dest);
27080
27216
  }
27081
27217
 
@@ -27131,7 +27267,7 @@ async function runContextDriftFactory(deps) {
27131
27267
  ok: true,
27132
27268
  code: "DRY_RUN",
27133
27269
  ...baseMeta,
27134
- referenceRootDocument: toPosixPath(path54.relative(deps.repoRootAbs, refAbsWorkspace)) + (fs58.statSync(refAbsWorkspace).isDirectory() ? "/" : ""),
27270
+ referenceRootDocument: toPosixPath(path55.relative(deps.repoRootAbs, refAbsWorkspace)) + (fs58.statSync(refAbsWorkspace).isDirectory() ? "/" : ""),
27135
27271
  driftReportPath: null,
27136
27272
  analysisWorktreeRoot: "",
27137
27273
  promoted: false,
@@ -27188,8 +27324,8 @@ async function runContextDriftFactory(deps) {
27188
27324
  const handle = prep.handle;
27189
27325
  const finalizeWt = prep.finalize;
27190
27326
  const wt = handle.path;
27191
- const refRel = path54.relative(deps.repoRootAbs, refAbsWorkspace).split(path54.sep).join("/");
27192
- const refAbsWt = path54.join(wt, ...refRel.split("/"));
27327
+ const refRel = path55.relative(deps.repoRootAbs, refAbsWorkspace).split(path55.sep).join("/");
27328
+ const refAbsWt = path55.join(wt, ...refRel.split("/"));
27193
27329
  try {
27194
27330
  materializeOpenCodeAgentsWithAce(deps.agentsDirFs, wt, {
27195
27331
  enabled: getAceAnalysisEnabledForCheckout(wt),
@@ -27228,7 +27364,7 @@ async function runContextDriftFactory(deps) {
27228
27364
  ...baseMeta
27229
27365
  };
27230
27366
  }
27231
- const indexWt = indexOverrideAbsWorkspace ? path54.join(wt, ...path54.relative(deps.repoRootAbs, indexOverrideAbsWorkspace).split(path54.sep)) : void 0;
27367
+ const indexWt = indexOverrideAbsWorkspace ? path55.join(wt, ...path55.relative(deps.repoRootAbs, indexOverrideAbsWorkspace).split(path55.sep)) : void 0;
27232
27368
  const rootPick = pickReferenceRootDocument({
27233
27369
  referencePathIsFile: fs58.statSync(refAbsWt).isFile(),
27234
27370
  referenceAbsInWorktree: refAbsWt,
@@ -27256,9 +27392,9 @@ async function runContextDriftFactory(deps) {
27256
27392
  let slug = computeSlug({ label: deps.label, referencePath: deps.referencePathArg, repoRootAbs: deps.repoRootAbs });
27257
27393
  slug = maybeDedupeSlug(slug, refRel);
27258
27394
  const driftBase = driftFilename(slug, runDate);
27259
- const driftDirWt = path54.join(wt, DRIFT_CONTEXT_SUBDIR);
27395
+ const driftDirWt = path55.join(wt, DRIFT_CONTEXT_SUBDIR);
27260
27396
  fs58.mkdirSync(driftDirWt, { recursive: true });
27261
- const driftAbsWt = path54.join(driftDirWt, driftBase);
27397
+ const driftAbsWt = path55.join(driftDirWt, driftBase);
27262
27398
  let payload;
27263
27399
  if (deps.testOnlyFixturePayload) {
27264
27400
  payload = deps.testOnlyFixturePayload;
@@ -27307,7 +27443,7 @@ async function runContextDriftFactory(deps) {
27307
27443
  ...baseMeta
27308
27444
  };
27309
27445
  }
27310
- const driftRelFromRootDir = path54.relative(path54.dirname(refRootAbsWt), driftAbsWt).split(path54.sep).join("/");
27446
+ const driftRelFromRootDir = path55.relative(path55.dirname(refRootAbsWt), driftAbsWt).split(path55.sep).join("/");
27311
27447
  const linkRes = patchReferenceIndexWithDriftLink({
27312
27448
  referenceRootAbsolute: refRootAbsWt,
27313
27449
  relativeLinkFromRootToDrift: driftRelFromRootDir,
@@ -27326,8 +27462,8 @@ async function runContextDriftFactory(deps) {
27326
27462
  ...baseMeta
27327
27463
  };
27328
27464
  }
27329
- const driftRelPosix = toPosixPath(path54.relative(wt, driftAbsWt));
27330
- const rootRelPosix = toPosixPath(path54.relative(wt, refRootAbsWt));
27465
+ const driftRelPosix = toPosixPath(path55.relative(wt, driftAbsWt));
27466
+ const rootRelPosix = toPosixPath(path55.relative(wt, refRootAbsWt));
27331
27467
  const promoteEffective = deps.merged.promoteContextToWorkspace !== false;
27332
27468
  if (promoteEffective && !inPlace) {
27333
27469
  try {
@@ -27357,7 +27493,7 @@ async function runContextDriftFactory(deps) {
27357
27493
  } else if (promoteEffective && inPlace) {
27358
27494
  deps.log("[context-drift] in-place analysis \u2014 promote skipped (artefacts already under repository root)");
27359
27495
  }
27360
- const driftReportPathFs = promoteEffective ? path54.join(deps.repoRootAbs, ...driftRelPosix.split("/")) : driftAbsWt;
27496
+ const driftReportPathFs = promoteEffective ? path55.join(deps.repoRootAbs, ...driftRelPosix.split("/")) : driftAbsWt;
27361
27497
  return {
27362
27498
  exitOk: true,
27363
27499
  ok: true,
@@ -27376,7 +27512,7 @@ async function runContextDriftFactory(deps) {
27376
27512
 
27377
27513
  // src/analysis/coordinationDuplicatesDiagnosis.ts
27378
27514
  var fs59 = __toESM(require("fs"));
27379
- var path55 = __toESM(require("path"));
27515
+ var path56 = __toESM(require("path"));
27380
27516
  var import__7 = __toESM(require__());
27381
27517
  var COORDINATION_DUPLICATES_REPORT_BASENAME = "coordination-duplicates-report.json";
27382
27518
  var COORDINATION_LIST_SCAN_ENTRIES = [
@@ -27402,7 +27538,7 @@ var RE_MD_DM_FD = /^DM-\d+_FD-\d+-.+\.md$/i;
27402
27538
  var RE_MD_DM = /^DM-\d+-.+\.md$/i;
27403
27539
  var RE_MD_TS = /^TS-\d+-.+\.md$/i;
27404
27540
  function looksLikeCoordinationDetailMarkdownBasename(basename17) {
27405
- if (!basename17 || basename17 !== path55.basename(basename17) || !/\.md$/i.test(basename17)) {
27541
+ if (!basename17 || basename17 !== path56.basename(basename17) || !/\.md$/i.test(basename17)) {
27406
27542
  return false;
27407
27543
  }
27408
27544
  if (STAPLE_CONTEXT_MARKDOWN_BASENAMES.has(basename17)) {
@@ -27411,7 +27547,7 @@ function looksLikeCoordinationDetailMarkdownBasename(basename17) {
27411
27547
  return RE_MD_FE_UC_SC.test(basename17) || RE_MD_FE_UC_SLUG.test(basename17) || RE_MD_FE_UC_PLAIN.test(basename17) || RE_MD_FE_FEATURE.test(basename17) || RE_MD_XP_BH.test(basename17) || RE_MD_XP_VIEW.test(basename17) || RE_MD_SV_ME.test(basename17) || RE_MD_SV.test(basename17) || RE_MD_DM_FD.test(basename17) || RE_MD_DM.test(basename17) || RE_MD_TS.test(basename17);
27412
27548
  }
27413
27549
  function loadRawFeatureRows(contextDirAbs) {
27414
- const p = path55.join(contextDirAbs, "features-list.json");
27550
+ const p = path56.join(contextDirAbs, "features-list.json");
27415
27551
  if (!fs59.existsSync(p)) {
27416
27552
  return [];
27417
27553
  }
@@ -27704,7 +27840,7 @@ function buildCoordinationDuplicatesReport(input) {
27704
27840
  const lists = [];
27705
27841
  const duplicateGroups = [];
27706
27842
  for (const entry of COORDINATION_LIST_SCAN_ENTRIES) {
27707
- const filePath = path55.join(input.contextDirAbsolute, entry.basename);
27843
+ const filePath = path56.join(input.contextDirAbsolute, entry.basename);
27708
27844
  if (!fs59.existsSync(filePath)) {
27709
27845
  lists.push({ basename: entry.basename, status: "missing" });
27710
27846
  continue;
@@ -27759,7 +27895,7 @@ var validateReportCompiled;
27759
27895
  function validateReportData(data) {
27760
27896
  if (!validateReportCompiled) {
27761
27897
  const ajv2 = new import__7.default({ allErrors: true, strict: false });
27762
- const schemaPath = path55.join(resolveContextListSchemasDir(), "coordination-duplicates-report.schema.json");
27898
+ const schemaPath = path56.join(resolveContextListSchemasDir(), "coordination-duplicates-report.schema.json");
27763
27899
  const schemaRaw = stripUtf8Bom6(fs59.readFileSync(schemaPath, "utf-8"));
27764
27900
  validateReportCompiled = ajv2.compile(JSON.parse(schemaRaw));
27765
27901
  }
@@ -27778,7 +27914,7 @@ function runCoordinationDuplicatesDiagnosis(input) {
27778
27914
  if (!v.ok) {
27779
27915
  return { ok: false, message: `Report validation failed: ${v.errors.join("; ")}` };
27780
27916
  }
27781
- const outPath = path55.join(input.contextDirAbsolute, COORDINATION_DUPLICATES_REPORT_BASENAME);
27917
+ const outPath = path56.join(input.contextDirAbsolute, COORDINATION_DUPLICATES_REPORT_BASENAME);
27782
27918
  const payload = `${JSON.stringify(report, null, 2)}
27783
27919
  `;
27784
27920
  const tmp = `${outPath}.tmp.${process.pid}`;
@@ -27826,7 +27962,7 @@ function runCoordinationDuplicatesDiagnosis(input) {
27826
27962
 
27827
27963
  // src/pipelines/download/downloadPipeline.ts
27828
27964
  var fs60 = __toESM(require("node:fs"));
27829
- var path56 = __toESM(require("node:path"));
27965
+ var path57 = __toESM(require("node:path"));
27830
27966
  var SRS_DISCOVERY_BATCH_GET_CHUNK_SIZE = 200;
27831
27967
  function isRecord7(v) {
27832
27968
  return Boolean(v) && typeof v === "object" && !Array.isArray(v);
@@ -27916,9 +28052,9 @@ function resolveSafeContextOutputPath(contextDirAbs, nameRaw) {
27916
28052
  return null;
27917
28053
  }
27918
28054
  }
27919
- const resolved = path56.resolve(contextDirAbs, ...segments);
27920
- const rel = path56.relative(contextDirAbs, resolved);
27921
- if (rel.startsWith("..") || path56.isAbsolute(rel)) {
28055
+ const resolved = path57.resolve(contextDirAbs, ...segments);
28056
+ const rel = path57.relative(contextDirAbs, resolved);
28057
+ if (rel.startsWith("..") || path57.isAbsolute(rel)) {
27922
28058
  return null;
27923
28059
  }
27924
28060
  return resolved;
@@ -27934,7 +28070,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
27934
28070
  if (!fs60.existsSync(contextDirAbs) || !fs60.statSync(contextDirAbs).isDirectory()) {
27935
28071
  return { filesRemoved: 0 };
27936
28072
  }
27937
- const preserveAbs = path56.resolve(contextDirAbs, UPLOAD_TARGET_FILENAME);
28073
+ const preserveAbs = path57.resolve(contextDirAbs, UPLOAD_TARGET_FILENAME);
27938
28074
  const preserveSet = /* @__PURE__ */ new Set();
27939
28075
  if (fs60.existsSync(preserveAbs) && fs60.statSync(preserveAbs).isFile()) {
27940
28076
  preserveSet.add(preserveAbs);
@@ -27948,7 +28084,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
27948
28084
  return;
27949
28085
  }
27950
28086
  for (const e of entries) {
27951
- const full = path56.join(dir, e.name);
28087
+ const full = path57.join(dir, e.name);
27952
28088
  if (e.isDirectory()) {
27953
28089
  walkRm(full);
27954
28090
  try {
@@ -27956,7 +28092,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
27956
28092
  } catch {
27957
28093
  }
27958
28094
  } else if (e.isFile()) {
27959
- const abs = path56.resolve(full);
28095
+ const abs = path57.resolve(full);
27960
28096
  if (preserveSet.has(abs)) {
27961
28097
  continue;
27962
28098
  }
@@ -28029,7 +28165,7 @@ async function runDownloadPipeline(opts) {
28029
28165
  failed.push({ id, message: "Missing name on srs_discovery node." });
28030
28166
  continue;
28031
28167
  }
28032
- if (name === UPLOAD_TARGET_FILENAME || path56.basename(name) === UPLOAD_TARGET_FILENAME) {
28168
+ if (name === UPLOAD_TARGET_FILENAME || path57.basename(name) === UPLOAD_TARGET_FILENAME) {
28033
28169
  skipped += 1;
28034
28170
  log?.(`[pipeline:download] skip ${name} (upload target row).`);
28035
28171
  continue;
@@ -28040,7 +28176,7 @@ async function runDownloadPipeline(opts) {
28040
28176
  failed.push({ id, name, message: "Unsafe or invalid name for local path." });
28041
28177
  continue;
28042
28178
  }
28043
- fs60.mkdirSync(path56.dirname(outAbs), { recursive: true });
28179
+ fs60.mkdirSync(path57.dirname(outAbs), { recursive: true });
28044
28180
  const exists = fs60.existsSync(outAbs);
28045
28181
  if (exists && !opts.force && !opts.replaceFromCloud) {
28046
28182
  skipped += 1;
@@ -28123,12 +28259,12 @@ function toFetchErrorMessage(e) {
28123
28259
 
28124
28260
  // src/auth/gluecharmContentNegotiation.ts
28125
28261
  var GLUECHARM_WS_LEGACY_JSON = "application/vnd.gluecharm.v1.ws-legacy+json";
28126
- function pathWithoutQuery(path61) {
28127
- const q = path61.indexOf("?");
28128
- return q === -1 ? path61 : path61.slice(0, q);
28262
+ function pathWithoutQuery(path62) {
28263
+ const q = path62.indexOf("?");
28264
+ return q === -1 ? path62 : path62.slice(0, q);
28129
28265
  }
28130
- function isGluecharmContentApiPath(path61) {
28131
- const p = pathWithoutQuery(path61);
28266
+ function isGluecharmContentApiPath(path62) {
28267
+ const p = pathWithoutQuery(path62);
28132
28268
  return p.startsWith("/api/content/") || p.startsWith("/api/batch/content/");
28133
28269
  }
28134
28270
  function gluecharmContentHeaders(method) {
@@ -28166,7 +28302,7 @@ async function fetchWithTimeout2(url, init, fetchImpl, timeoutMs, externalSignal
28166
28302
  }
28167
28303
  function createAuthenticatedRequestJson(deps) {
28168
28304
  const fetchImpl = deps.fetchImpl ?? fetch;
28169
- async function requestJson(path61, options = {}) {
28305
+ async function requestJson(path62, options = {}) {
28170
28306
  const base = deps.getApiBaseUrl();
28171
28307
  if (!base) {
28172
28308
  const err = { status: 0, message: "easyspecs.apiBaseUrl is not configured." };
@@ -28174,7 +28310,7 @@ function createAuthenticatedRequestJson(deps) {
28174
28310
  }
28175
28311
  const method = options.method ?? "GET";
28176
28312
  const headers = { ...options.headers };
28177
- if (isGluecharmContentApiPath(path61)) {
28313
+ if (isGluecharmContentApiPath(path62)) {
28178
28314
  Object.assign(headers, gluecharmContentHeaders(method));
28179
28315
  } else {
28180
28316
  if (!headers.Accept) {
@@ -28188,7 +28324,7 @@ function createAuthenticatedRequestJson(deps) {
28188
28324
  if (options.withAuth !== false && access) {
28189
28325
  headers.Authorization = `Bearer ${access}`;
28190
28326
  }
28191
- const url = `${base}${path61}`;
28327
+ const url = `${base}${path62}`;
28192
28328
  const timeoutMs = options.timeoutMs ?? API_TIMEOUT_MS;
28193
28329
  const response = await fetchWithTimeout2(
28194
28330
  url,
@@ -28209,7 +28345,7 @@ function createAuthenticatedRequestJson(deps) {
28209
28345
  if (shouldRetryUnauthorized) {
28210
28346
  const refreshed = await deps.refreshSession();
28211
28347
  if (refreshed) {
28212
- return requestJson(path61, { ...options, retryOnUnauthorized: false });
28348
+ return requestJson(path62, { ...options, retryOnUnauthorized: false });
28213
28349
  }
28214
28350
  }
28215
28351
  const fallback = payload == null ? `${response.statusText || "HTTP error"} (response body empty or not JSON)` : "Request failed.";
@@ -28221,13 +28357,13 @@ function createAuthenticatedRequestJson(deps) {
28221
28357
  // src/cli/cliSession.ts
28222
28358
  var fs61 = __toESM(require("node:fs"));
28223
28359
  var os7 = __toESM(require("node:os"));
28224
- var path57 = __toESM(require("node:path"));
28360
+ var path58 = __toESM(require("node:path"));
28225
28361
  function defaultSessionPath() {
28226
- return path57.join(os7.homedir(), ".easyspecs", "cli-session.json");
28362
+ return path58.join(os7.homedir(), ".easyspecs", "cli-session.json");
28227
28363
  }
28228
28364
  var configSessionPath;
28229
28365
  function setCliSessionPathFromConfig(absPath) {
28230
- configSessionPath = absPath?.trim() ? path57.resolve(absPath) : void 0;
28366
+ configSessionPath = absPath?.trim() ? path58.resolve(absPath) : void 0;
28231
28367
  }
28232
28368
  function applyCliSessionPathFromRepoConfig(repoRoot, cfg) {
28233
28369
  const raw = cfg.easyspecs?.cliSessionPath?.trim();
@@ -28235,7 +28371,7 @@ function applyCliSessionPathFromRepoConfig(repoRoot, cfg) {
28235
28371
  setCliSessionPathFromConfig(void 0);
28236
28372
  return;
28237
28373
  }
28238
- const abs = path57.isAbsolute(raw) ? raw : path57.join(repoRoot, raw);
28374
+ const abs = path58.isAbsolute(raw) ? raw : path58.join(repoRoot, raw);
28239
28375
  setCliSessionPathFromConfig(abs);
28240
28376
  }
28241
28377
  function normalizeCliSessionPathForConfig(repoRoot, raw) {
@@ -28243,15 +28379,15 @@ function normalizeCliSessionPathForConfig(repoRoot, raw) {
28243
28379
  if (!t) {
28244
28380
  return "";
28245
28381
  }
28246
- const resolvedRepo = path57.resolve(repoRoot);
28247
- const abs = path57.isAbsolute(t) ? path57.normalize(t) : path57.resolve(resolvedRepo, t);
28248
- const rel = path57.relative(resolvedRepo, abs);
28382
+ const resolvedRepo = path58.resolve(repoRoot);
28383
+ const abs = path58.isAbsolute(t) ? path58.normalize(t) : path58.resolve(resolvedRepo, t);
28384
+ const rel = path58.relative(resolvedRepo, abs);
28249
28385
  if (rel === "") {
28250
28386
  return abs;
28251
28387
  }
28252
- const underRepo = !rel.startsWith("..") && !path57.isAbsolute(rel);
28388
+ const underRepo = !rel.startsWith("..") && !path58.isAbsolute(rel);
28253
28389
  if (underRepo) {
28254
- return rel.split(path57.sep).join("/");
28390
+ return rel.split(path58.sep).join("/");
28255
28391
  }
28256
28392
  return abs;
28257
28393
  }
@@ -28281,7 +28417,7 @@ function readCliSession() {
28281
28417
  }
28282
28418
  function writeCliSession(s) {
28283
28419
  const p = effectiveCliSessionPath();
28284
- fs61.mkdirSync(path57.dirname(p), { recursive: true });
28420
+ fs61.mkdirSync(path58.dirname(p), { recursive: true });
28285
28421
  fs61.writeFileSync(p, `${JSON.stringify(s, null, 2)}
28286
28422
  `, "utf8");
28287
28423
  }
@@ -28295,7 +28431,7 @@ function clearCliSession() {
28295
28431
 
28296
28432
  // src/analysis/acePendingTraces.ts
28297
28433
  var fs62 = __toESM(require("fs"));
28298
- var path58 = __toESM(require("path"));
28434
+ var path59 = __toESM(require("path"));
28299
28435
  function normalizeAceTraceRelativePath(rel) {
28300
28436
  return rel.split(/[/\\]/).join("/");
28301
28437
  }
@@ -28345,7 +28481,7 @@ function listPendingAceTraceFiles(contextDir2, worktreeRoot) {
28345
28481
  const allAbs = listAceTraceFiles(contextDir2);
28346
28482
  const pending = [];
28347
28483
  for (const abs of allAbs) {
28348
- const rel = normalizeAceTraceRelativePath(path58.relative(contextDir2, abs));
28484
+ const rel = normalizeAceTraceRelativePath(path59.relative(contextDir2, abs));
28349
28485
  const v = validateAceJsonFile(abs, traceSchema);
28350
28486
  if (!v.ok) {
28351
28487
  continue;
@@ -28360,7 +28496,7 @@ function listPendingAceTraceFiles(contextDir2, worktreeRoot) {
28360
28496
  }
28361
28497
 
28362
28498
  // src/analysis/aceAutoLearnPool.ts
28363
- var path59 = __toESM(require("path"));
28499
+ var path60 = __toESM(require("path"));
28364
28500
  function clampConcurrency2(n) {
28365
28501
  if (!Number.isFinite(n)) {
28366
28502
  return DEFAULT_MAX_CONCURRENT_AI;
@@ -28395,8 +28531,8 @@ async function runAceAutoLearnPool(p) {
28395
28531
  };
28396
28532
  const currentCap = () => Math.min(staticMaxC, adaptiveMax);
28397
28533
  let wake;
28398
- const waitTurn = () => new Promise((resolve23) => {
28399
- wake = resolve23;
28534
+ const waitTurn = () => new Promise((resolve24) => {
28535
+ wake = resolve24;
28400
28536
  });
28401
28537
  const pump = () => {
28402
28538
  wake?.();
@@ -28418,7 +28554,7 @@ async function runAceAutoLearnPool(p) {
28418
28554
  poolAbortListenerRegistered = true;
28419
28555
  }
28420
28556
  }
28421
- const traceRel = (abs) => path59.relative(contextDir2, abs).split(path59.sep).join("/");
28557
+ const traceRel = (abs) => path60.relative(contextDir2, abs).split(path60.sep).join("/");
28422
28558
  const runOne = async (traceAbs) => {
28423
28559
  if (abortSignal?.aborted) {
28424
28560
  active -= 1;
@@ -28949,7 +29085,7 @@ function formatCliStderrLine(line, useAnsi) {
28949
29085
  }
28950
29086
 
28951
29087
  // src/cli/main.ts
28952
- var PKG_VERSION = "0.2.1";
29088
+ var PKG_VERSION = "0.3.1";
28953
29089
  function isNonEmptyFactoryFailureArray(x) {
28954
29090
  if (!Array.isArray(x) || x.length === 0) {
28955
29091
  return false;
@@ -29091,23 +29227,23 @@ function resolveAnalysisRoot(repoRoot, rootKind, worktreePath) {
29091
29227
  return repoRoot;
29092
29228
  }
29093
29229
  const wt = worktreePath?.trim();
29094
- if (wt && fs63.existsSync(path60.join(wt, ".git"))) {
29095
- return path60.resolve(wt);
29230
+ if (wt && fs63.existsSync(path61.join(wt, ".git"))) {
29231
+ return path61.resolve(wt);
29096
29232
  }
29097
29233
  throw new Error("worktree mode requires --worktree <path> to an existing analysis checkout.");
29098
29234
  }
29099
29235
  function resolveAdHocCheckoutRoot(_repoRoot, storage, worktreeFlag) {
29100
29236
  const w = worktreeFlag?.trim();
29101
29237
  if (w) {
29102
- const abs = path60.resolve(w);
29103
- if (fs63.existsSync(path60.join(abs, ".git"))) {
29238
+ const abs = path61.resolve(w);
29239
+ if (fs63.existsSync(path61.join(abs, ".git"))) {
29104
29240
  return abs;
29105
29241
  }
29106
29242
  throw new Error(`Invalid --worktree (not a git checkout): ${abs}`);
29107
29243
  }
29108
29244
  const snap = readAnalysisWorkspaceSnapshot(storage);
29109
29245
  const p = snap?.adHocWorktreePath?.trim();
29110
- if (p && fs63.existsSync(path60.join(p, ".git"))) {
29246
+ if (p && fs63.existsSync(path61.join(p, ".git"))) {
29111
29247
  return p;
29112
29248
  }
29113
29249
  throw new Error("No analysis checkout: run `easyspecs-cli run synthesis` first or pass `--worktree <path>`.");
@@ -29134,7 +29270,7 @@ async function runResumeRemediationPool(storage, repoRoot, analysisRoot, merged,
29134
29270
  requireOpenCode(merged, flags);
29135
29271
  const agentsDir = resolveOpenCodeAgentsDir(repoRoot, repoConfig);
29136
29272
  assertAgentsDirExists(agentsDir);
29137
- const ctxDir = path60.join(analysisRoot, ".gluecharm", "context");
29273
+ const ctxDir = path61.join(analysisRoot, ".gluecharm", "context");
29138
29274
  const snap = readArtefactRunSnapshot(storage);
29139
29275
  const rows = listMissingWorkstations(ctxDir, analysisRoot, snap);
29140
29276
  if (rows.length === 0) {
@@ -29152,7 +29288,7 @@ async function runResumeRemediationPool(storage, repoRoot, analysisRoot, merged,
29152
29288
  storageContext: storage,
29153
29289
  repositoryRoot: repoRoot,
29154
29290
  worktreeRoot: analysisRoot,
29155
- workspaceLabel: path60.basename(analysisRoot),
29291
+ workspaceLabel: path61.basename(analysisRoot),
29156
29292
  oc,
29157
29293
  log: (line) => logErr(flags, line),
29158
29294
  abortSignal: void 0,
@@ -29329,17 +29465,17 @@ async function main() {
29329
29465
  { easyspecs: { defaultGitRemoteUrl: url } },
29330
29466
  { warnMigration: (m) => logErr(flags, `[EasySpecs] ${m}`) }
29331
29467
  );
29332
- const path61 = easyspecsConfigPath(repoRoot);
29468
+ const path62 = easyspecsConfigPath(repoRoot);
29333
29469
  if (flags.json) {
29334
29470
  printJsonLine({
29335
29471
  command: "config set-git-remote",
29336
29472
  durationMs: Date.now() - t0,
29337
29473
  ok: true,
29338
- path: path61,
29474
+ path: path62,
29339
29475
  defaultGitRemoteUrl: cfg.easyspecs?.defaultGitRemoteUrl ?? ""
29340
29476
  });
29341
29477
  } else {
29342
- console.log(`Updated ${path61} \u2014 easyspecs.defaultGitRemoteUrl`);
29478
+ console.log(`Updated ${path62} \u2014 easyspecs.defaultGitRemoteUrl`);
29343
29479
  }
29344
29480
  process.exit(ExitCode.ok);
29345
29481
  } catch (e) {
@@ -29372,7 +29508,7 @@ async function main() {
29372
29508
  applyCliSessionPathFromRepoConfig(repoRoot, repoConfig);
29373
29509
  if (flags.sessionPath?.trim()) {
29374
29510
  const sp = flags.sessionPath.trim();
29375
- const abs = path60.isAbsolute(sp) ? path60.normalize(sp) : path60.resolve(repoRoot, sp);
29511
+ const abs = path61.isAbsolute(sp) ? path61.normalize(sp) : path61.resolve(repoRoot, sp);
29376
29512
  setCliSessionPathFromConfig(abs);
29377
29513
  }
29378
29514
  const apiResolved = initApiBaseUrlForCli(repoRoot, flags, repoConfig);
@@ -29613,7 +29749,7 @@ async function main() {
29613
29749
  const result = await runSynthesisPipeline(
29614
29750
  storage,
29615
29751
  repoRoot,
29616
- path60.basename(repoRoot),
29752
+ path61.basename(repoRoot),
29617
29753
  agentsDir,
29618
29754
  {
29619
29755
  ...merged.pipelineOpenCode
@@ -29668,7 +29804,7 @@ async function main() {
29668
29804
  if (sub === "reference-coverage") {
29669
29805
  const rootAbs = resolveAnalysisRoot(repoRoot, rootKind, worktree);
29670
29806
  requireMinimalGluecharmLayoutAt(rootAbs);
29671
- const contextDir2 = path60.join(rootAbs, ".gluecharm", "context");
29807
+ const contextDir2 = path61.join(rootAbs, ".gluecharm", "context");
29672
29808
  const res = runCoveragePipeline({
29673
29809
  repositoryRootAbs: rootAbs,
29674
29810
  contextDirAbs: contextDir2,
@@ -29691,7 +29827,7 @@ async function main() {
29691
29827
  if (sub === "coordination-duplicates") {
29692
29828
  const rootAbs = resolveAnalysisRoot(repoRoot, rootKind, worktree);
29693
29829
  requireMinimalGluecharmLayoutAt(rootAbs);
29694
- const contextDir2 = path60.join(rootAbs, ".gluecharm", "context");
29830
+ const contextDir2 = path61.join(rootAbs, ".gluecharm", "context");
29695
29831
  const res = runCoordinationDuplicatesDiagnosis({
29696
29832
  contextDirAbsolute: contextDir2,
29697
29833
  sourceRoot: rootKind === "worktree" ? "worktree" : "workspace"
@@ -29727,7 +29863,7 @@ async function main() {
29727
29863
  if (sub === "missing-artefacts") {
29728
29864
  const rootAbs = resolveAnalysisRoot(repoRoot, rootKind, worktree);
29729
29865
  requireMinimalGluecharmLayoutAt(rootAbs);
29730
- const ctxDir = path60.join(rootAbs, ".gluecharm", "context");
29866
+ const ctxDir = path61.join(rootAbs, ".gluecharm", "context");
29731
29867
  const storage = createFileBackedWorkspaceState(repoRoot);
29732
29868
  const snap = readArtefactRunSnapshot(storage);
29733
29869
  const rows = listMissingWorkstations(ctxDir, rootAbs, snap);
@@ -29777,7 +29913,7 @@ async function main() {
29777
29913
  });
29778
29914
  const bad = poolRes.cancelled || poolRes.failures > 0;
29779
29915
  if (!bad) {
29780
- const ctxDir = path60.join(analysisRoot, ".gluecharm", "context");
29916
+ const ctxDir = path61.join(analysisRoot, ".gluecharm", "context");
29781
29917
  const lg = runLinkMappingPipeline(ctxDir, { log: (line) => logErr(flags, line) });
29782
29918
  if (!lg.ok) {
29783
29919
  finish(OsExit.diagnoseZeroReferenceLinkMapping, {
@@ -29807,7 +29943,7 @@ async function main() {
29807
29943
  const worktree = wtExplicit ?? wtFromRoot;
29808
29944
  const rootAbs = resolveAnalysisRoot(repoRoot, rootKind, worktree);
29809
29945
  requireMinimalGluecharmLayoutAt(rootAbs);
29810
- const contextDir2 = path60.join(rootAbs, ".gluecharm", "context");
29946
+ const contextDir2 = path61.join(rootAbs, ".gluecharm", "context");
29811
29947
  const res = runLinkMappingPipeline(contextDir2, {
29812
29948
  log: (line) => logErr(flags, line)
29813
29949
  });
@@ -29985,8 +30121,8 @@ async function main() {
29985
30121
  const snap = readAnalysisWorkspaceSnapshot(storage);
29986
30122
  const wt = snap?.adHocWorktreePath?.trim();
29987
30123
  if (wt) {
29988
- const sourceCtx = path60.join(wt, ".gluecharm", "context");
29989
- if (path60.resolve(wt) === path60.resolve(repoRoot)) {
30124
+ const sourceCtx = path61.join(wt, ".gluecharm", "context");
30125
+ if (path61.resolve(wt) === path61.resolve(repoRoot)) {
29990
30126
  logErr(
29991
30127
  flags,
29992
30128
  "[pipeline:analysis] promote skipped (in-place: analysis checkout is the repository root)"
@@ -30088,10 +30224,10 @@ async function main() {
30088
30224
  finish(ExitCode.usage, { ok: false, error: `unknown download context flag: ${a}` });
30089
30225
  }
30090
30226
  requireMinimalGluecharmLayoutAt(repoRoot);
30091
- const ctxDir = path60.resolve(path60.join(repoRoot, ".gluecharm", "context"));
30092
- const gluecharmParent = path60.dirname(ctxDir);
30093
- if (path60.basename(gluecharmParent) === ".gluecharm" && path60.basename(ctxDir) === "context") {
30094
- requireMinimalGluecharmLayoutAt(path60.dirname(gluecharmParent));
30227
+ const ctxDir = path61.resolve(path61.join(repoRoot, ".gluecharm", "context"));
30228
+ const gluecharmParent = path61.dirname(ctxDir);
30229
+ if (path61.basename(gluecharmParent) === ".gluecharm" && path61.basename(ctxDir) === "context") {
30230
+ requireMinimalGluecharmLayoutAt(path61.dirname(gluecharmParent));
30095
30231
  }
30096
30232
  const appIdRaw = getEasyspecsProjectIdFromRepoConfig(repoConfig)?.trim();
30097
30233
  if (!appIdRaw) {
@@ -30174,16 +30310,16 @@ async function main() {
30174
30310
  }
30175
30311
  const sess = sessRaw;
30176
30312
  requireMinimalGluecharmLayoutAt(repoRoot);
30177
- let ctxDir = path60.join(repoRoot, ".gluecharm", "context");
30313
+ let ctxDir = path61.join(repoRoot, ".gluecharm", "context");
30178
30314
  if (pos[1] === "republish") {
30179
30315
  const fromCfg = repoConfig.easyspecs?.upload?.contextDirectory?.trim();
30180
- const resolvedOverride = fromCfg && fromCfg.length > 0 ? path60.isAbsolute(fromCfg) ? path60.normalize(fromCfg) : path60.resolve(repoRoot, fromCfg) : "";
30181
- if (resolvedOverride && fs63.existsSync(path60.join(resolvedOverride, ".."))) {
30316
+ const resolvedOverride = fromCfg && fromCfg.length > 0 ? path61.isAbsolute(fromCfg) ? path61.normalize(fromCfg) : path61.resolve(repoRoot, fromCfg) : "";
30317
+ if (resolvedOverride && fs63.existsSync(path61.join(resolvedOverride, ".."))) {
30182
30318
  ctxDir = resolvedOverride;
30183
30319
  } else {
30184
30320
  const storage = createFileBackedWorkspaceState(repoRoot);
30185
30321
  const snap = readAnalysisWorkspaceSnapshot(storage);
30186
- const wt = snap?.adHocWorktreePath && fs63.existsSync(path60.join(snap.adHocWorktreePath, ".gluecharm", "context")) ? path60.join(snap.adHocWorktreePath, ".gluecharm", "context") : "";
30322
+ const wt = snap?.adHocWorktreePath && fs63.existsSync(path61.join(snap.adHocWorktreePath, ".gluecharm", "context")) ? path61.join(snap.adHocWorktreePath, ".gluecharm", "context") : "";
30187
30323
  if (!wt) {
30188
30324
  finish(ExitCode.misconfiguration, {
30189
30325
  ok: false,
@@ -30193,10 +30329,10 @@ async function main() {
30193
30329
  ctxDir = wt;
30194
30330
  }
30195
30331
  }
30196
- const ctxResolved = path60.resolve(ctxDir);
30197
- const gluecharmParent = path60.dirname(ctxResolved);
30198
- if (path60.basename(gluecharmParent) === ".gluecharm" && path60.basename(ctxResolved) === "context") {
30199
- requireMinimalGluecharmLayoutAt(path60.dirname(gluecharmParent));
30332
+ const ctxResolved = path61.resolve(ctxDir);
30333
+ const gluecharmParent = path61.dirname(ctxResolved);
30334
+ if (path61.basename(gluecharmParent) === ".gluecharm" && path61.basename(ctxResolved) === "context") {
30335
+ requireMinimalGluecharmLayoutAt(path61.dirname(gluecharmParent));
30200
30336
  }
30201
30337
  const appIdRaw = getEasyspecsProjectIdFromRepoConfig(repoConfig)?.trim();
30202
30338
  if (!appIdRaw) {
@@ -30300,7 +30436,7 @@ async function main() {
30300
30436
  finish(failed ? ExitCode.upload : ExitCode.ok, primary);
30301
30437
  }
30302
30438
  if (pos[0] === "ace" && pos[1] === "clear") {
30303
- const learnings = path60.join(repoRoot, ".gluecharm", "context", "learnings");
30439
+ const learnings = path61.join(repoRoot, ".gluecharm", "context", "learnings");
30304
30440
  if (!fs63.existsSync(learnings)) {
30305
30441
  finish(ExitCode.ok, { ok: true, message: "nothing to clear" });
30306
30442
  }
@@ -30310,8 +30446,8 @@ async function main() {
30310
30446
  if (pos[0] === "ace" && pos[1] === "learn") {
30311
30447
  requireOpenCode(merged, flags);
30312
30448
  const { worktree } = parseWorktreeFlag(pos.slice(2));
30313
- const root = worktree && fs63.existsSync(path60.join(worktree, ".opencode", "schemas", "ace")) ? worktree : repoRoot;
30314
- const contextDir2 = path60.join(root, ".gluecharm", "context");
30449
+ const root = worktree && fs63.existsSync(path61.join(worktree, ".opencode", "schemas", "ace")) ? worktree : repoRoot;
30450
+ const contextDir2 = path61.join(root, ".gluecharm", "context");
30315
30451
  const traces = listAceTraceFiles(contextDir2);
30316
30452
  if (traces.length === 0) {
30317
30453
  finish(ExitCode.ok, { ok: true, message: "no traces", traceCount: 0 });
@@ -30335,8 +30471,8 @@ async function main() {
30335
30471
  if (pos[0] === "ace" && pos[1] === "auto-learn") {
30336
30472
  requireOpenCode(merged, flags);
30337
30473
  const { worktree } = parseWorktreeFlag(pos.slice(2));
30338
- const root = worktree && fs63.existsSync(path60.join(worktree, ".git")) ? worktree : repoRoot;
30339
- const contextDir2 = path60.join(root, ".gluecharm", "context");
30474
+ const root = worktree && fs63.existsSync(path61.join(worktree, ".git")) ? worktree : repoRoot;
30475
+ const contextDir2 = path61.join(root, ".gluecharm", "context");
30340
30476
  const pending = listPendingAceTraceFiles(contextDir2, root);
30341
30477
  if (pending.length === 0) {
30342
30478
  finish(ExitCode.ok, { ok: true, pending: 0 });