@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/commands.md +1 -1
- package/dist/main.cjs +445 -309
- package/dist/main.cjs.map +4 -4
- package/error-code.md +2 -2
- package/package.json +1 -1
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
|
|
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 =
|
|
1895
|
+
const localBin = path62.resolve(baseDir, baseName);
|
|
1896
1896
|
if (fs64.existsSync(localBin)) return localBin;
|
|
1897
|
-
if (sourceExt.includes(
|
|
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 =
|
|
1916
|
-
|
|
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 =
|
|
1923
|
+
const legacyName = path62.basename(
|
|
1924
1924
|
this._scriptPath,
|
|
1925
|
-
|
|
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(
|
|
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 =
|
|
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(
|
|
2791
|
-
if (
|
|
2792
|
-
this._executableDir =
|
|
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 = "",
|
|
5248
|
-
if (
|
|
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 =
|
|
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
|
|
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(
|
|
6239
|
-
let input =
|
|
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 [
|
|
6439
|
-
wsComponent.path =
|
|
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
|
|
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
|
|
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:
|
|
6825
|
-
resolve:
|
|
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
|
|
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
|
|
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
|
|
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 "
|
|
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,
|
|
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} ${
|
|
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
|
|
14397
|
+
const path62 = `/proc/${pid}/status`;
|
|
14398
14398
|
try {
|
|
14399
|
-
const content = fs18.readFileSync(
|
|
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
|
-
"
|
|
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((
|
|
14596
|
+
return new Promise((resolve24) => {
|
|
14588
14597
|
if (sig?.aborted) {
|
|
14589
|
-
|
|
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
|
-
|
|
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((
|
|
21409
|
-
wake =
|
|
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
|
|
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
|
-
|
|
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"
|
|
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"
|
|
21791
|
+
return path34.join(cfgRoot, "opencode");
|
|
21785
21792
|
}
|
|
21786
|
-
function
|
|
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
|
|
21789
|
-
|
|
21790
|
-
|
|
21791
|
-
|
|
21792
|
-
|
|
21793
|
-
|
|
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
|
|
21817
|
-
if (
|
|
21818
|
-
return
|
|
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 =
|
|
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 =
|
|
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
|
|
21858
|
-
|
|
21859
|
-
|
|
21860
|
-
|
|
21861
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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((
|
|
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
|
-
|
|
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
|
|
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
|
|
22951
|
+
var path37 = __toESM(require("path"));
|
|
22816
22952
|
|
|
22817
22953
|
// src/analysis/analysisDetailMarkdownDiscovery.ts
|
|
22818
22954
|
var fs40 = __toESM(require("fs"));
|
|
22819
|
-
var
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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" &&
|
|
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
|
|
23385
|
+
return path37.join(contextDir2, item.payload.outputBasename);
|
|
23250
23386
|
}
|
|
23251
23387
|
const bn = expectedBasenameForCoordPayload(item.payload);
|
|
23252
|
-
return bn ?
|
|
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 ?
|
|
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
|
|
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 =
|
|
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
|
|
23700
|
+
var path40 = __toESM(require("path"));
|
|
23565
23701
|
|
|
23566
23702
|
// src/analysis/coverageReferenceValidationSchemaValidate.ts
|
|
23567
23703
|
var fs42 = __toESM(require("fs"));
|
|
23568
|
-
var
|
|
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
|
|
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 =
|
|
23655
|
-
if (!fs43.existsSync(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
23766
|
-
const rel =
|
|
23767
|
-
if (rel.startsWith("..") ||
|
|
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(
|
|
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 =
|
|
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 =
|
|
23837
|
-
const rel =
|
|
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 =
|
|
23896
|
-
const base =
|
|
23897
|
-
const sourceArtefact =
|
|
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 =
|
|
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(
|
|
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(
|
|
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 =
|
|
24042
|
-
const contextDir2 =
|
|
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 =
|
|
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
|
|
24219
|
+
var path42 = __toESM(require("path"));
|
|
24084
24220
|
|
|
24085
24221
|
// src/analysis/zeroReferenceRemediationSchemaValidate.ts
|
|
24086
24222
|
var fs44 = __toESM(require("fs"));
|
|
24087
|
-
var
|
|
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 =
|
|
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
|
|
24538
|
+
return path42.join(worktreeRoot, ".opencode", "schemas", "context-lists", schemaBasename);
|
|
24403
24539
|
}
|
|
24404
24540
|
function stagingDir(contextDirAbs) {
|
|
24405
|
-
return
|
|
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
|
|
24545
|
+
return path42.join(stagingDir(contextDirAbs), `${kind}-${h}.json`);
|
|
24410
24546
|
}
|
|
24411
24547
|
function readNonReferencedFilesFromRepositoryRoot(repositoryRootAbs) {
|
|
24412
|
-
const p =
|
|
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 =
|
|
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 =
|
|
24561
|
-
const schemaPath =
|
|
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(
|
|
24666
|
-
const runDir =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
24883
|
-
const runDir =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
25031
|
-
const triageAbs =
|
|
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(
|
|
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(
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
25319
|
-
const coverageAbs =
|
|
25320
|
-
const routingAbs =
|
|
25321
|
-
const outAbs =
|
|
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(
|
|
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
|
|
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 =
|
|
25507
|
+
const root = path44.resolve(repoRootAbs);
|
|
25372
25508
|
for (const segments of MINIMAL_GLUECHARM_RELATIVE_DIRS) {
|
|
25373
|
-
const dir =
|
|
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 =
|
|
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:
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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: ${
|
|
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 =
|
|
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 =
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
26083
|
-
if (!fs50.existsSync(
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
26757
|
+
const abs = path51.join(repoRoot, leaf);
|
|
26622
26758
|
if (fs53.existsSync(abs) && fs53.statSync(abs).isFile()) {
|
|
26623
|
-
const r =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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) =>
|
|
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
|
|
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 =
|
|
26981
|
+
const runDir = path52.join(args.worktreeRoot, ".opencode", "_run");
|
|
26846
26982
|
fs54.mkdirSync(runDir, { recursive: true });
|
|
26847
|
-
const manifestPath =
|
|
26848
|
-
const outputPath =
|
|
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 =
|
|
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:
|
|
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
|
|
26916
|
-
var DRIFT_CONTEXT_SUBDIR =
|
|
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 =
|
|
26926
|
-
const rel =
|
|
26927
|
-
if (rel.startsWith("..") ||
|
|
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 ?
|
|
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 =
|
|
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 =
|
|
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
|
|
27156
|
+
return path53.relative(worktreeRoot, absolute).split(path53.sep).join("/");
|
|
27021
27157
|
}
|
|
27022
27158
|
function toPosixPath(p) {
|
|
27023
|
-
return p.split(
|
|
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
|
|
27202
|
+
var path54 = __toESM(require("node:path"));
|
|
27067
27203
|
function copyWorktreeFileToWorkspace(args) {
|
|
27068
|
-
const wt =
|
|
27069
|
-
const ws =
|
|
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 =
|
|
27074
|
-
const dest =
|
|
27075
|
-
if (
|
|
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(
|
|
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(
|
|
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 =
|
|
27192
|
-
const refAbsWt =
|
|
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 ?
|
|
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 =
|
|
27395
|
+
const driftDirWt = path55.join(wt, DRIFT_CONTEXT_SUBDIR);
|
|
27260
27396
|
fs58.mkdirSync(driftDirWt, { recursive: true });
|
|
27261
|
-
const driftAbsWt =
|
|
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 =
|
|
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(
|
|
27330
|
-
const rootRelPosix = toPosixPath(
|
|
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 ?
|
|
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
|
|
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 !==
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
27920
|
-
const rel =
|
|
27921
|
-
if (rel.startsWith("..") ||
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 ||
|
|
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(
|
|
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(
|
|
28127
|
-
const q =
|
|
28128
|
-
return q === -1 ?
|
|
28262
|
+
function pathWithoutQuery(path62) {
|
|
28263
|
+
const q = path62.indexOf("?");
|
|
28264
|
+
return q === -1 ? path62 : path62.slice(0, q);
|
|
28129
28265
|
}
|
|
28130
|
-
function isGluecharmContentApiPath(
|
|
28131
|
-
const p = pathWithoutQuery(
|
|
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(
|
|
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(
|
|
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}${
|
|
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(
|
|
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
|
|
28360
|
+
var path58 = __toESM(require("node:path"));
|
|
28225
28361
|
function defaultSessionPath() {
|
|
28226
|
-
return
|
|
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() ?
|
|
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 =
|
|
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 =
|
|
28247
|
-
const abs =
|
|
28248
|
-
const rel =
|
|
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("..") && !
|
|
28388
|
+
const underRepo = !rel.startsWith("..") && !path58.isAbsolute(rel);
|
|
28253
28389
|
if (underRepo) {
|
|
28254
|
-
return rel.split(
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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((
|
|
28399
|
-
wake =
|
|
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) =>
|
|
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.
|
|
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(
|
|
29095
|
-
return
|
|
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 =
|
|
29103
|
-
if (fs63.existsSync(
|
|
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(
|
|
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 =
|
|
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:
|
|
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
|
|
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:
|
|
29474
|
+
path: path62,
|
|
29339
29475
|
defaultGitRemoteUrl: cfg.easyspecs?.defaultGitRemoteUrl ?? ""
|
|
29340
29476
|
});
|
|
29341
29477
|
} else {
|
|
29342
|
-
console.log(`Updated ${
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
29989
|
-
if (
|
|
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 =
|
|
30092
|
-
const gluecharmParent =
|
|
30093
|
-
if (
|
|
30094
|
-
requireMinimalGluecharmLayoutAt(
|
|
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 =
|
|
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 ?
|
|
30181
|
-
if (resolvedOverride && fs63.existsSync(
|
|
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(
|
|
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 =
|
|
30197
|
-
const gluecharmParent =
|
|
30198
|
-
if (
|
|
30199
|
-
requireMinimalGluecharmLayoutAt(
|
|
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 =
|
|
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(
|
|
30314
|
-
const contextDir2 =
|
|
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(
|
|
30339
|
-
const contextDir2 =
|
|
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 });
|