@gluecharm-lab/easyspecs-cli 0.0.17 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/commands.md +119 -101
- package/dist/main.cjs +257 -393
- package/dist/main.cjs.map +4 -4
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -960,7 +960,7 @@ var require_command = __commonJS({
|
|
|
960
960
|
var EventEmitter = require("node:events").EventEmitter;
|
|
961
961
|
var childProcess = require("node:child_process");
|
|
962
962
|
var path60 = require("node:path");
|
|
963
|
-
var
|
|
963
|
+
var fs60 = require("node:fs");
|
|
964
964
|
var process2 = require("node:process");
|
|
965
965
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
966
966
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -1893,10 +1893,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1893
1893
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1894
1894
|
function findFile(baseDir, baseName) {
|
|
1895
1895
|
const localBin = path60.resolve(baseDir, baseName);
|
|
1896
|
-
if (
|
|
1896
|
+
if (fs60.existsSync(localBin)) return localBin;
|
|
1897
1897
|
if (sourceExt.includes(path60.extname(baseName))) return void 0;
|
|
1898
1898
|
const foundExt = sourceExt.find(
|
|
1899
|
-
(ext) =>
|
|
1899
|
+
(ext) => fs60.existsSync(`${localBin}${ext}`)
|
|
1900
1900
|
);
|
|
1901
1901
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1902
1902
|
return void 0;
|
|
@@ -1908,7 +1908,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1908
1908
|
if (this._scriptPath) {
|
|
1909
1909
|
let resolvedScriptPath;
|
|
1910
1910
|
try {
|
|
1911
|
-
resolvedScriptPath =
|
|
1911
|
+
resolvedScriptPath = fs60.realpathSync(this._scriptPath);
|
|
1912
1912
|
} catch (err) {
|
|
1913
1913
|
resolvedScriptPath = this._scriptPath;
|
|
1914
1914
|
}
|
|
@@ -10622,12 +10622,12 @@ var require_dist = __commonJS({
|
|
|
10622
10622
|
throw new Error(`Unknown format "${name}"`);
|
|
10623
10623
|
return f;
|
|
10624
10624
|
};
|
|
10625
|
-
function addFormats2(ajv2, list,
|
|
10625
|
+
function addFormats2(ajv2, list, fs60, exportName) {
|
|
10626
10626
|
var _a;
|
|
10627
10627
|
var _b;
|
|
10628
10628
|
(_a = (_b = ajv2.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
10629
10629
|
for (const f of list)
|
|
10630
|
-
ajv2.addFormat(f,
|
|
10630
|
+
ajv2.addFormat(f, fs60[f]);
|
|
10631
10631
|
}
|
|
10632
10632
|
module2.exports = exports2 = formatsPlugin;
|
|
10633
10633
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -10636,7 +10636,7 @@ var require_dist = __commonJS({
|
|
|
10636
10636
|
});
|
|
10637
10637
|
|
|
10638
10638
|
// src/cli/main.ts
|
|
10639
|
-
var
|
|
10639
|
+
var fs59 = __toESM(require("node:fs"));
|
|
10640
10640
|
var path59 = __toESM(require("node:path"));
|
|
10641
10641
|
|
|
10642
10642
|
// src/cli/exitCodes.ts
|
|
@@ -10715,7 +10715,7 @@ function createEasyspecsCliProgram() {
|
|
|
10715
10715
|
const runSynthesis = run.command("synthesis").description("Run synthesis pipeline");
|
|
10716
10716
|
runSynthesis.command("resume-missing").description("Resume remediation pool for missing artefacts").option("--worktree <path>", "Path to an analysis checkout");
|
|
10717
10717
|
runSynthesis.command("resume-synthesis").description("Resume synthesis pipeline").option("--worktree <path>", "Path to an analysis checkout");
|
|
10718
|
-
program2.command("analysis").description("Run full Factory (Generate Context)").option("--
|
|
10718
|
+
program2.command("analysis").description("Run full Factory (Generate Context)").option("--force-new-context-analysis", "Force a new analysis even when cloud cache says analyzed").addOption(new Option("--synthesis-only", "(deprecated; no effect)").hideHelp()).allowUnknownOption(true);
|
|
10719
10719
|
const diagnose = program2.command("diagnose").description("Deterministic diagnostics");
|
|
10720
10720
|
const addRootAndWorktree = (c) => c.option("--root <root>", "workspace|worktree").option("--worktree <path>", "Path to an analysis checkout");
|
|
10721
10721
|
addRootAndWorktree(diagnose.command("reference-coverage").description("Compute reference coverage"));
|
|
@@ -10729,7 +10729,7 @@ function createEasyspecsCliProgram() {
|
|
|
10729
10729
|
context.command("drift").description("Compare repo to reference docs; write drift report and update index (worktree + promote)").argument("<referencePath>", "File or directory (spec, SRS, PRD, \u2026)").option("--label <slug>", "Slug for drift-<slug>-<date>.md").option("--index <path>", "Override reference root markdown (relative to repo root)").option("--dry-run", "Validate reference only; skip worktree, agent, and writes")
|
|
10730
10730
|
);
|
|
10731
10731
|
const update = program2.command("update").description("Incremental context refresh");
|
|
10732
|
-
update.command("context").description("Update context since last baseline (git delta, optional remediation, promote
|
|
10732
|
+
update.command("context").description("Update context since last baseline (git delta, optional remediation, promote)").allowUnknownOption(true);
|
|
10733
10733
|
const download = program2.command("download").description("Download resources");
|
|
10734
10734
|
download.command("context").description("Download context from EasySpecs cloud").option("--force", "Overwrite existing local files").option("--replace-from-cloud", "Remove local files before writing cloud versions");
|
|
10735
10735
|
const upload = program2.command("upload").description("Upload resources");
|
|
@@ -12507,18 +12507,18 @@ async function runParallelSinglesIntoAccum(requestJson, applicationId, paths, on
|
|
|
12507
12507
|
const recentWaveMs = [];
|
|
12508
12508
|
let idx = 0;
|
|
12509
12509
|
const runOne = async (absPath) => {
|
|
12510
|
-
const
|
|
12510
|
+
const basename17 = path12.basename(absPath);
|
|
12511
12511
|
let content;
|
|
12512
12512
|
try {
|
|
12513
12513
|
content = fs11.readFileSync(absPath, "utf8");
|
|
12514
12514
|
} catch (e) {
|
|
12515
12515
|
const msg = errorMessage(e);
|
|
12516
|
-
logSrs13Failure(log, `read file file=${
|
|
12516
|
+
logSrs13Failure(log, `read file file=${basename17}`, msg);
|
|
12517
12517
|
accum.failed.push({ path: absPath, message: msg });
|
|
12518
12518
|
return;
|
|
12519
12519
|
}
|
|
12520
12520
|
const existingId = resolveExistingId(absPath);
|
|
12521
|
-
const payload = buildSrsDiscoverySavePayload(applicationId,
|
|
12521
|
+
const payload = buildSrsDiscoverySavePayload(applicationId, basename17, content, existingId);
|
|
12522
12522
|
try {
|
|
12523
12523
|
await postSingleCreate(requestJson, payload, log);
|
|
12524
12524
|
accum.succeeded.push(absPath);
|
|
@@ -12532,7 +12532,7 @@ async function runParallelSinglesIntoAccum(requestJson, applicationId, paths, on
|
|
|
12532
12532
|
throw e;
|
|
12533
12533
|
}
|
|
12534
12534
|
const msg = errorMessage(e);
|
|
12535
|
-
logSrs13Failure(log, `POST /api/content/srs_discovery file=${
|
|
12535
|
+
logSrs13Failure(log, `POST /api/content/srs_discovery file=${basename17}`, msg);
|
|
12536
12536
|
accum.failed.push({ path: absPath, message: msg });
|
|
12537
12537
|
}
|
|
12538
12538
|
};
|
|
@@ -12614,18 +12614,18 @@ async function executeContextSrsDiscoveryUploadPhase(filePaths, phaseOpts, accum
|
|
|
12614
12614
|
const items = [];
|
|
12615
12615
|
const chunkPaths = [];
|
|
12616
12616
|
for (const absPath of chunk) {
|
|
12617
|
-
const
|
|
12617
|
+
const basename17 = path12.basename(absPath);
|
|
12618
12618
|
let content;
|
|
12619
12619
|
try {
|
|
12620
12620
|
content = fs11.readFileSync(absPath, "utf8");
|
|
12621
12621
|
} catch (e) {
|
|
12622
12622
|
const msg = errorMessage(e);
|
|
12623
|
-
logSrs13Failure(log, `read file file=${
|
|
12623
|
+
logSrs13Failure(log, `read file file=${basename17}`, msg);
|
|
12624
12624
|
accum.failed.push({ path: absPath, message: msg });
|
|
12625
12625
|
continue;
|
|
12626
12626
|
}
|
|
12627
12627
|
const existingId = resolveExistingId(absPath);
|
|
12628
|
-
items.push(buildSrsDiscoverySavePayloadForBatch(applicationId,
|
|
12628
|
+
items.push(buildSrsDiscoverySavePayloadForBatch(applicationId, basename17, content, existingId));
|
|
12629
12629
|
chunkPaths.push(absPath);
|
|
12630
12630
|
}
|
|
12631
12631
|
if (items.length === 0) {
|
|
@@ -12811,7 +12811,7 @@ async function fetchUploadCloudContextStatusWithR8Policy(args) {
|
|
|
12811
12811
|
}
|
|
12812
12812
|
}
|
|
12813
12813
|
function shouldSkipAnalysisForCachedCloudContext(args) {
|
|
12814
|
-
if (args.
|
|
12814
|
+
if (args.forceNewContextAnalysis) {
|
|
12815
12815
|
return false;
|
|
12816
12816
|
}
|
|
12817
12817
|
return args.cloudContextAnalyzed === true;
|
|
@@ -13101,9 +13101,9 @@ var ANALYSIS_STATIC_CONTEXT_OUTPUTS = [
|
|
|
13101
13101
|
"tech-stack-list.json"
|
|
13102
13102
|
];
|
|
13103
13103
|
function discoverDynamicAnalysisTestSteps(contextDir2) {
|
|
13104
|
-
const staticOutputs = ANALYSIS_STATIC_CONTEXT_OUTPUTS.map((
|
|
13105
|
-
basename:
|
|
13106
|
-
exists: nonEmptyContextFile(path14.join(contextDir2,
|
|
13104
|
+
const staticOutputs = ANALYSIS_STATIC_CONTEXT_OUTPUTS.map((basename17) => ({
|
|
13105
|
+
basename: basename17,
|
|
13106
|
+
exists: nonEmptyContextFile(path14.join(contextDir2, basename17))
|
|
13107
13107
|
}));
|
|
13108
13108
|
const featuresPath = path14.join(contextDir2, "features-list.json");
|
|
13109
13109
|
const featuresData = readJson(featuresPath);
|
|
@@ -13274,8 +13274,8 @@ function aceCurationPath(contextDir2, agentStem, runId) {
|
|
|
13274
13274
|
function aceConsolidatedSessionsJsonlPath(contextDir2) {
|
|
13275
13275
|
return path15.join(aceLearningsRoot(contextDir2), ACE_CONSOLIDATED_SESSIONS_JSONL);
|
|
13276
13276
|
}
|
|
13277
|
-
function opencodeAceSchemaPath(worktreeRoot,
|
|
13278
|
-
return path15.join(worktreeRoot, ".opencode", "schemas", "ace",
|
|
13277
|
+
function opencodeAceSchemaPath(worktreeRoot, basename17) {
|
|
13278
|
+
return path15.join(worktreeRoot, ".opencode", "schemas", "ace", basename17);
|
|
13279
13279
|
}
|
|
13280
13280
|
|
|
13281
13281
|
// src/analysis/aceJsonValidate.ts
|
|
@@ -17149,16 +17149,16 @@ function outputPaths(step, worktreeRoot, listTarget) {
|
|
|
17149
17149
|
if (!fe) {
|
|
17150
17150
|
throw new Error("listUseCases requires listTarget.featureCode");
|
|
17151
17151
|
}
|
|
17152
|
-
const
|
|
17153
|
-
return { absolute: path26.join(ctx,
|
|
17152
|
+
const basename17 = `${fe}-use-cases-list.json`;
|
|
17153
|
+
return { absolute: path26.join(ctx, basename17), basename: basename17 };
|
|
17154
17154
|
}
|
|
17155
17155
|
case "reviewUseCasesList": {
|
|
17156
17156
|
const fe = listTarget?.featureCode;
|
|
17157
17157
|
if (!fe) {
|
|
17158
17158
|
throw new Error("reviewUseCasesList requires listTarget.featureCode");
|
|
17159
17159
|
}
|
|
17160
|
-
const
|
|
17161
|
-
return { absolute: path26.join(ctx,
|
|
17160
|
+
const basename17 = `${fe}-use-cases-list.json`;
|
|
17161
|
+
return { absolute: path26.join(ctx, basename17), basename: basename17 };
|
|
17162
17162
|
}
|
|
17163
17163
|
case "listScenarios": {
|
|
17164
17164
|
const fe = listTarget?.featureCode;
|
|
@@ -17166,8 +17166,8 @@ function outputPaths(step, worktreeRoot, listTarget) {
|
|
|
17166
17166
|
if (!fe || !uc) {
|
|
17167
17167
|
throw new Error("listScenarios requires listTarget.featureCode and useCaseCode");
|
|
17168
17168
|
}
|
|
17169
|
-
const
|
|
17170
|
-
return { absolute: path26.join(ctx,
|
|
17169
|
+
const basename17 = `${fe}_${uc}-scenarios-list.json`;
|
|
17170
|
+
return { absolute: path26.join(ctx, basename17), basename: basename17 };
|
|
17171
17171
|
}
|
|
17172
17172
|
case "reviewScenariosList": {
|
|
17173
17173
|
const fe = listTarget?.featureCode;
|
|
@@ -17175,24 +17175,24 @@ function outputPaths(step, worktreeRoot, listTarget) {
|
|
|
17175
17175
|
if (!fe || !uc) {
|
|
17176
17176
|
throw new Error("reviewScenariosList requires listTarget.featureCode and useCaseCode");
|
|
17177
17177
|
}
|
|
17178
|
-
const
|
|
17179
|
-
return { absolute: path26.join(ctx,
|
|
17178
|
+
const basename17 = `${fe}_${uc}-scenarios-list.json`;
|
|
17179
|
+
return { absolute: path26.join(ctx, basename17), basename: basename17 };
|
|
17180
17180
|
}
|
|
17181
17181
|
case "listEntityFields": {
|
|
17182
17182
|
const dm = listTarget?.entityCode;
|
|
17183
17183
|
if (!dm) {
|
|
17184
17184
|
throw new Error("listEntityFields requires listTarget.entityCode");
|
|
17185
17185
|
}
|
|
17186
|
-
const
|
|
17187
|
-
return { absolute: path26.join(ctx,
|
|
17186
|
+
const basename17 = `${dm}-fields-list.json`;
|
|
17187
|
+
return { absolute: path26.join(ctx, basename17), basename: basename17 };
|
|
17188
17188
|
}
|
|
17189
17189
|
case "reviewEntityFieldsList": {
|
|
17190
17190
|
const dm = listTarget?.entityCode;
|
|
17191
17191
|
if (!dm) {
|
|
17192
17192
|
throw new Error("reviewEntityFieldsList requires listTarget.entityCode");
|
|
17193
17193
|
}
|
|
17194
|
-
const
|
|
17195
|
-
return { absolute: path26.join(ctx,
|
|
17194
|
+
const basename17 = `${dm}-fields-list.json`;
|
|
17195
|
+
return { absolute: path26.join(ctx, basename17), basename: basename17 };
|
|
17196
17196
|
}
|
|
17197
17197
|
default: {
|
|
17198
17198
|
const _u = step;
|
|
@@ -18519,10 +18519,33 @@ Expected output: ${outputFileAbsolute}`;
|
|
|
18519
18519
|
}
|
|
18520
18520
|
|
|
18521
18521
|
// src/analysis/worktreeManager.ts
|
|
18522
|
-
var
|
|
18522
|
+
var import_child_process3 = require("child_process");
|
|
18523
18523
|
var fs29 = __toESM(require("fs"));
|
|
18524
18524
|
var os2 = __toESM(require("os"));
|
|
18525
18525
|
var path27 = __toESM(require("path"));
|
|
18526
|
+
|
|
18527
|
+
// src/analysis/gitWorktreeStaleRecovery.ts
|
|
18528
|
+
var import_child_process2 = require("child_process");
|
|
18529
|
+
function isMissingRegisteredWorktreeError(combinedStderrStdout) {
|
|
18530
|
+
return /missing but already registered worktree/i.test(combinedStderrStdout);
|
|
18531
|
+
}
|
|
18532
|
+
function gitWorktreePruneSync(repoRoot) {
|
|
18533
|
+
const r = (0, import_child_process2.spawnSync)("git", ["worktree", "prune"], {
|
|
18534
|
+
cwd: repoRoot,
|
|
18535
|
+
encoding: "utf-8",
|
|
18536
|
+
timeout: 6e4
|
|
18537
|
+
});
|
|
18538
|
+
if (r.status !== 0) {
|
|
18539
|
+
const msg = [r.stderr, r.stdout].filter(Boolean).join("\n").trim();
|
|
18540
|
+
return {
|
|
18541
|
+
ok: false,
|
|
18542
|
+
message: msg || `git worktree prune failed (exit ${String(r.status ?? "unknown")}).`
|
|
18543
|
+
};
|
|
18544
|
+
}
|
|
18545
|
+
return { ok: true };
|
|
18546
|
+
}
|
|
18547
|
+
|
|
18548
|
+
// src/analysis/worktreeManager.ts
|
|
18526
18549
|
var EASYSPECS_WT_DIR_RE = /^easyspecs-(\d+)$/;
|
|
18527
18550
|
function maxEasyspecsWorktreeIndex(parentDir) {
|
|
18528
18551
|
let max = 0;
|
|
@@ -18563,7 +18586,7 @@ function allocateEasyspecsWorktreePath(parentDir) {
|
|
|
18563
18586
|
return null;
|
|
18564
18587
|
}
|
|
18565
18588
|
function readHeadBranchShort(repoRoot) {
|
|
18566
|
-
const r = (0,
|
|
18589
|
+
const r = (0, import_child_process3.spawnSync)("git", ["symbolic-ref", "--short", "-q", "HEAD"], {
|
|
18567
18590
|
cwd: repoRoot,
|
|
18568
18591
|
encoding: "utf-8",
|
|
18569
18592
|
timeout: 3e4
|
|
@@ -18581,7 +18604,7 @@ function attachWorktreeHandle(worktreePath, repositoryRoot) {
|
|
|
18581
18604
|
path: wt,
|
|
18582
18605
|
repoRoot: repo,
|
|
18583
18606
|
remove() {
|
|
18584
|
-
(0,
|
|
18607
|
+
(0, import_child_process3.spawnSync)("git", ["worktree", "remove", "--force", wt], {
|
|
18585
18608
|
cwd: repo,
|
|
18586
18609
|
encoding: "utf-8",
|
|
18587
18610
|
timeout: 6e4
|
|
@@ -18593,7 +18616,7 @@ function attachWorktreeHandle(worktreePath, repositoryRoot) {
|
|
|
18593
18616
|
}
|
|
18594
18617
|
};
|
|
18595
18618
|
}
|
|
18596
|
-
function createAnalysisWorktree(repoRoot) {
|
|
18619
|
+
function createAnalysisWorktree(repoRoot, options) {
|
|
18597
18620
|
const parent = path27.join(os2.tmpdir(), "easyspecs-analysis");
|
|
18598
18621
|
const wt = allocateEasyspecsWorktreePath(parent);
|
|
18599
18622
|
if (!wt) {
|
|
@@ -18603,27 +18626,41 @@ function createAnalysisWorktree(repoRoot) {
|
|
|
18603
18626
|
};
|
|
18604
18627
|
}
|
|
18605
18628
|
const sourceBranchAtCreation = readHeadBranchShort(repoRoot);
|
|
18606
|
-
|
|
18607
|
-
|
|
18608
|
-
|
|
18609
|
-
|
|
18610
|
-
|
|
18611
|
-
|
|
18629
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
18630
|
+
const r = (0, import_child_process3.spawnSync)("git", ["worktree", "add", "--detach", wt, "HEAD"], {
|
|
18631
|
+
cwd: repoRoot,
|
|
18632
|
+
encoding: "utf-8",
|
|
18633
|
+
timeout: 12e4
|
|
18634
|
+
});
|
|
18635
|
+
if (r.status === 0) {
|
|
18636
|
+
try {
|
|
18637
|
+
writeAnalysisWorktreeMarker(wt, repoRoot);
|
|
18638
|
+
} catch {
|
|
18639
|
+
}
|
|
18640
|
+
return {
|
|
18641
|
+
ok: true,
|
|
18642
|
+
handle: attachWorktreeHandle(wt, repoRoot),
|
|
18643
|
+
...sourceBranchAtCreation ? { sourceBranchAtCreation } : {}
|
|
18644
|
+
};
|
|
18645
|
+
}
|
|
18612
18646
|
const msg = [r.stderr, r.stdout].filter(Boolean).join("\n").trim();
|
|
18613
|
-
|
|
18614
|
-
|
|
18615
|
-
|
|
18616
|
-
|
|
18617
|
-
|
|
18618
|
-
|
|
18619
|
-
|
|
18620
|
-
|
|
18647
|
+
const fullMsg = msg || `git worktree add failed (exit ${r.status ?? "unknown"}). Is this folder a Git repository?`;
|
|
18648
|
+
if (attempt === 0 && isMissingRegisteredWorktreeError(fullMsg)) {
|
|
18649
|
+
const pr = gitWorktreePruneSync(repoRoot);
|
|
18650
|
+
if (pr.ok) {
|
|
18651
|
+
const wtName = path27.basename(wt);
|
|
18652
|
+
options?.log?.(`[worktree] git worktree prune \u2014 cleared stale registration for ${wtName} (${wt})`);
|
|
18653
|
+
continue;
|
|
18654
|
+
}
|
|
18655
|
+
return {
|
|
18656
|
+
ok: false,
|
|
18657
|
+
error: `${fullMsg}
|
|
18658
|
+
(git worktree prune failed: ${pr.message ?? "unknown"})`
|
|
18659
|
+
};
|
|
18660
|
+
}
|
|
18661
|
+
return { ok: false, error: fullMsg };
|
|
18621
18662
|
}
|
|
18622
|
-
|
|
18623
|
-
ok: true,
|
|
18624
|
-
handle: attachWorktreeHandle(wt, repoRoot),
|
|
18625
|
-
...sourceBranchAtCreation ? { sourceBranchAtCreation } : {}
|
|
18626
|
-
};
|
|
18663
|
+
throw new Error("createAnalysisWorktree: retry loop exited without result.");
|
|
18627
18664
|
}
|
|
18628
18665
|
|
|
18629
18666
|
// src/stores/workstationRunStore.ts
|
|
@@ -19593,8 +19630,8 @@ function renderProjectMdSections(contextDir2) {
|
|
|
19593
19630
|
chunks.push("### Data model", "", dmLines.length ? dmLines.join("\n") : NONE_LINE, "");
|
|
19594
19631
|
return chunks;
|
|
19595
19632
|
}
|
|
19596
|
-
function patchOneFile(contextDir2,
|
|
19597
|
-
const abs = path29.join(contextDir2,
|
|
19633
|
+
function patchOneFile(contextDir2, basename17, innerChildren, innerParents, opts) {
|
|
19634
|
+
const abs = path29.join(contextDir2, basename17);
|
|
19598
19635
|
if (!fs31.existsSync(abs)) {
|
|
19599
19636
|
return;
|
|
19600
19637
|
}
|
|
@@ -19602,7 +19639,7 @@ function patchOneFile(contextDir2, basename16, innerChildren, innerParents, opts
|
|
|
19602
19639
|
try {
|
|
19603
19640
|
body = fs31.readFileSync(abs, "utf8");
|
|
19604
19641
|
} catch (e) {
|
|
19605
|
-
opts.log?.(`[pipeline:link-mapping] skip read ${
|
|
19642
|
+
opts.log?.(`[pipeline:link-mapping] skip read ${basename17}: ${e instanceof Error ? e.message : String(e)}`);
|
|
19606
19643
|
return;
|
|
19607
19644
|
}
|
|
19608
19645
|
let next = replaceOrAppendRegion(body, NAV_CHILDREN_START, NAV_CHILDREN_END, innerChildren);
|
|
@@ -19634,16 +19671,16 @@ function runLinkMappingPipeline(contextDirAbs, opts = {}) {
|
|
|
19634
19671
|
};
|
|
19635
19672
|
visitEdgeBasenames(edges.children);
|
|
19636
19673
|
visitEdgeBasenames(edges.parents);
|
|
19637
|
-
for (const
|
|
19638
|
-
if (
|
|
19674
|
+
for (const basename17 of managedBasenames) {
|
|
19675
|
+
if (basename17 === "project.md" || basename17 === "architecture.md") {
|
|
19639
19676
|
continue;
|
|
19640
19677
|
}
|
|
19641
|
-
const abs = path29.join(contextDir2,
|
|
19678
|
+
const abs = path29.join(contextDir2, basename17);
|
|
19642
19679
|
if (!fs31.existsSync(abs)) {
|
|
19643
19680
|
continue;
|
|
19644
19681
|
}
|
|
19645
|
-
const childRows = edges.children.get(
|
|
19646
|
-
const parentRows = edges.parents.get(
|
|
19682
|
+
const childRows = edges.children.get(basename17) ?? [];
|
|
19683
|
+
const parentRows = edges.parents.get(basename17) ?? [];
|
|
19647
19684
|
const childLines = childRows.length === 0 ? NONE_LINE : childRows.map(
|
|
19648
19685
|
(c) => bulletLink(c.title, markdownRelativeHref(abs, path29.join(contextDir2, c.basename)))
|
|
19649
19686
|
).join("\n");
|
|
@@ -19655,7 +19692,7 @@ function runLinkMappingPipeline(contextDirAbs, opts = {}) {
|
|
|
19655
19692
|
${childLines}
|
|
19656
19693
|
`;
|
|
19657
19694
|
const innerParents = buildInnerParents(parentLines.split("\n").filter(Boolean));
|
|
19658
|
-
patchOneFile(contextDir2,
|
|
19695
|
+
patchOneFile(contextDir2, basename17, innerChildren, innerParents, opts);
|
|
19659
19696
|
}
|
|
19660
19697
|
const validation = validateEasyspecsNavLinksInContext(contextDir2);
|
|
19661
19698
|
if (!validation.ok) {
|
|
@@ -19964,91 +20001,91 @@ function mdItem(id, parentIds, t) {
|
|
|
19964
20001
|
};
|
|
19965
20002
|
}
|
|
19966
20003
|
function featureDetailTarget(contextDir2, code, name, slug) {
|
|
19967
|
-
const
|
|
20004
|
+
const basename17 = `${code}-${slug}.md`;
|
|
19968
20005
|
return {
|
|
19969
20006
|
openCodeAgentStem: "agent-md-feature-detail",
|
|
19970
20007
|
agentId: "ctx-md-feature-detail",
|
|
19971
20008
|
displayName: "Feature detail",
|
|
19972
|
-
outputBasename:
|
|
20009
|
+
outputBasename: basename17,
|
|
19973
20010
|
taskDescription: `Document feature **${code}** (**${name}**, slug **${slug}**) per \`.gluecharm/context/features-list.json\`: scope, behaviour, main dependencies, entry points, and links to code under the worktree. Write exactly one markdown file at the output path; cite substantive claims with file and line (or range).`,
|
|
19974
|
-
exists: fs34.existsSync(path32.join(contextDir2,
|
|
20011
|
+
exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
19975
20012
|
};
|
|
19976
20013
|
}
|
|
19977
20014
|
function viewDetailTarget(row2, contextDir2) {
|
|
19978
|
-
const
|
|
20015
|
+
const basename17 = `${row2.code}-${row2.slug}.md`;
|
|
19979
20016
|
return {
|
|
19980
20017
|
openCodeAgentStem: "agent-md-view-detail",
|
|
19981
20018
|
agentId: "ctx-md-view-detail",
|
|
19982
20019
|
displayName: "View detail",
|
|
19983
|
-
outputBasename:
|
|
20020
|
+
outputBasename: basename17,
|
|
19984
20021
|
taskDescription: `Describe view **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/experiences-list.json\`: purpose, layout, controls, navigation, data shown; ground in components and routes.`,
|
|
19985
|
-
exists: fs34.existsSync(path32.join(contextDir2,
|
|
20022
|
+
exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
19986
20023
|
};
|
|
19987
20024
|
}
|
|
19988
20025
|
function interactionDetailTarget(viewCode, ix, contextDir2) {
|
|
19989
|
-
const
|
|
20026
|
+
const basename17 = `${viewCode}_${ix.code}-${ix.slug}.md`;
|
|
19990
20027
|
return {
|
|
19991
20028
|
openCodeAgentStem: "agent-md-interaction-detail",
|
|
19992
20029
|
agentId: "ctx-md-interaction-detail",
|
|
19993
20030
|
displayName: "Interaction detail",
|
|
19994
|
-
outputBasename:
|
|
20031
|
+
outputBasename: basename17,
|
|
19995
20032
|
taskDescription: `Document interaction **${ix.code}** (**${ix.name}**) on view **${viewCode}** per \`.gluecharm/context/experiences-list.json\`.`,
|
|
19996
|
-
exists: fs34.existsSync(path32.join(contextDir2,
|
|
20033
|
+
exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
19997
20034
|
};
|
|
19998
20035
|
}
|
|
19999
20036
|
function serviceDetailTarget(row2, contextDir2) {
|
|
20000
|
-
const
|
|
20037
|
+
const basename17 = `${row2.code}-${row2.slug}.md`;
|
|
20001
20038
|
return {
|
|
20002
20039
|
openCodeAgentStem: "agent-md-service-detail",
|
|
20003
20040
|
agentId: "ctx-md-service-detail",
|
|
20004
20041
|
displayName: "Service detail",
|
|
20005
|
-
outputBasename:
|
|
20042
|
+
outputBasename: basename17,
|
|
20006
20043
|
taskDescription: `Describe service **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/services-list.json\`: responsibilities, consumers, errors, integration points.`,
|
|
20007
|
-
exists: fs34.existsSync(path32.join(contextDir2,
|
|
20044
|
+
exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20008
20045
|
};
|
|
20009
20046
|
}
|
|
20010
20047
|
function methodDetailTarget(svc, m, contextDir2) {
|
|
20011
|
-
const
|
|
20048
|
+
const basename17 = `${svc.code}_${m.code}-${m.slug}.md`;
|
|
20012
20049
|
return {
|
|
20013
20050
|
openCodeAgentStem: "agent-md-method-detail",
|
|
20014
20051
|
agentId: "ctx-md-method-detail",
|
|
20015
20052
|
displayName: "Method detail",
|
|
20016
|
-
outputBasename:
|
|
20053
|
+
outputBasename: basename17,
|
|
20017
20054
|
taskDescription: `Document method **${m.code}** (**${m.name}**) on service **${svc.code}** per \`.gluecharm/context/services-list.json\`.`,
|
|
20018
|
-
exists: fs34.existsSync(path32.join(contextDir2,
|
|
20055
|
+
exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20019
20056
|
};
|
|
20020
20057
|
}
|
|
20021
20058
|
function entityDetailTarget(dmCode, ename, slug, contextDir2) {
|
|
20022
|
-
const
|
|
20059
|
+
const basename17 = `${dmCode}-${slug}.md`;
|
|
20023
20060
|
return {
|
|
20024
20061
|
openCodeAgentStem: "agent-md-entity-detail",
|
|
20025
20062
|
agentId: "ctx-md-entity-detail",
|
|
20026
20063
|
displayName: "Entity detail",
|
|
20027
|
-
outputBasename:
|
|
20064
|
+
outputBasename: basename17,
|
|
20028
20065
|
taskDescription: `Describe entity **${dmCode}** (**${ename}**, slug **${slug}**) per \`.gluecharm/context/data-model-list.json\`: lifecycle, invariants, storage, ORM/schema mapping.`,
|
|
20029
|
-
exists: fs34.existsSync(path32.join(contextDir2,
|
|
20066
|
+
exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20030
20067
|
};
|
|
20031
20068
|
}
|
|
20032
20069
|
function fieldDetailTarget(dmCode, fdCode, fname, fSlug, contextDir2) {
|
|
20033
|
-
const
|
|
20070
|
+
const basename17 = `${dmCode}_${fdCode}-${fSlug}.md`;
|
|
20034
20071
|
return {
|
|
20035
20072
|
openCodeAgentStem: "agent-md-field-detail",
|
|
20036
20073
|
agentId: "ctx-md-field-detail",
|
|
20037
20074
|
displayName: "Field detail",
|
|
20038
|
-
outputBasename:
|
|
20075
|
+
outputBasename: basename17,
|
|
20039
20076
|
taskDescription: `Document field **${fdCode}** (**${fname}**) on entity **${dmCode}** per \`.gluecharm/context/${dmCode}-fields-list.json\`. Cite types and constraints with file and line.`,
|
|
20040
|
-
exists: fs34.existsSync(path32.join(contextDir2,
|
|
20077
|
+
exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20041
20078
|
};
|
|
20042
20079
|
}
|
|
20043
20080
|
function toolDetailTarget(row2, contextDir2) {
|
|
20044
|
-
const
|
|
20081
|
+
const basename17 = `${row2.code}-${row2.slug}.md`;
|
|
20045
20082
|
return {
|
|
20046
20083
|
openCodeAgentStem: "agent-md-tool-detail",
|
|
20047
20084
|
agentId: "ctx-md-tool-detail",
|
|
20048
20085
|
displayName: "Tool detail",
|
|
20049
|
-
outputBasename:
|
|
20086
|
+
outputBasename: basename17,
|
|
20050
20087
|
taskDescription: `Describe tool **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/tech-stack-list.json\`: role, version hints, configuration, boundaries.`,
|
|
20051
|
-
exists: fs34.existsSync(path32.join(contextDir2,
|
|
20088
|
+
exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20052
20089
|
};
|
|
20053
20090
|
}
|
|
20054
20091
|
function useCaseDetailTarget(feCode, ucCode, ucName, ucSlug, contextDir2) {
|
|
@@ -20065,14 +20102,14 @@ Follow bundled agent **agent-md-use-case-detail**: include **## Data inputs and
|
|
|
20065
20102
|
};
|
|
20066
20103
|
}
|
|
20067
20104
|
function scenarioDetailTarget(feCode, ucCode, scCode, scName, contextDir2) {
|
|
20068
|
-
const
|
|
20105
|
+
const basename17 = `${feCode}_${ucCode}_${scCode}.md`;
|
|
20069
20106
|
return {
|
|
20070
20107
|
openCodeAgentStem: "agent-md-scenario-detail",
|
|
20071
20108
|
agentId: "ctx-md-scenario-detail",
|
|
20072
20109
|
displayName: "Scenario detail",
|
|
20073
|
-
outputBasename:
|
|
20110
|
+
outputBasename: basename17,
|
|
20074
20111
|
taskDescription: `Document scenario **${scCode}** (**${scName}**) for **${feCode}** / **${ucCode}** per \`.gluecharm/context/${feCode}_${ucCode}-scenarios-list.json\`. Cite steps with file and line where possible.`,
|
|
20075
|
-
exists: fs34.existsSync(path32.join(contextDir2,
|
|
20112
|
+
exists: fs34.existsSync(path32.join(contextDir2, basename17)) && fs34.statSync(path32.join(contextDir2, basename17)).size > 0
|
|
20076
20113
|
};
|
|
20077
20114
|
}
|
|
20078
20115
|
function parentsDone(item, byId) {
|
|
@@ -20298,15 +20335,15 @@ function expandAfterSuccess(completed, contextDir2, byId, fifo) {
|
|
|
20298
20335
|
return;
|
|
20299
20336
|
}
|
|
20300
20337
|
if (completed.kind === "markdown") {
|
|
20301
|
-
const
|
|
20338
|
+
const basename17 = completed.payload.outputBasename;
|
|
20302
20339
|
const mdId = completed.id;
|
|
20303
|
-
const feFromFeatureMd =
|
|
20340
|
+
const feFromFeatureMd = basename17.match(/^(FE-\d+)-[^/]+\.md$/);
|
|
20304
20341
|
if (feFromFeatureMd) {
|
|
20305
20342
|
const fe = feFromFeatureMd[1];
|
|
20306
20343
|
add(coordItem(`coord:uc:${fe}`, [mdId], "listUseCases", { featureCode: fe }));
|
|
20307
20344
|
return;
|
|
20308
20345
|
}
|
|
20309
|
-
const xpFromView =
|
|
20346
|
+
const xpFromView = basename17.match(/^(XP-\d+)-[^/]+\.md$/);
|
|
20310
20347
|
if (xpFromView) {
|
|
20311
20348
|
const xp = xpFromView[1];
|
|
20312
20349
|
const row2 = discoverExperienceTreeRows(contextDir2).find((r) => r.code === xp);
|
|
@@ -20318,7 +20355,7 @@ function expandAfterSuccess(completed, contextDir2, byId, fifo) {
|
|
|
20318
20355
|
}
|
|
20319
20356
|
return;
|
|
20320
20357
|
}
|
|
20321
|
-
const svFromSvc =
|
|
20358
|
+
const svFromSvc = basename17.match(/^(SV-\d+)-[^/]+\.md$/);
|
|
20322
20359
|
if (svFromSvc) {
|
|
20323
20360
|
const sv = svFromSvc[1];
|
|
20324
20361
|
const srow = discoverServiceTreeRows(contextDir2).find((r) => r.code === sv);
|
|
@@ -20330,7 +20367,7 @@ function expandAfterSuccess(completed, contextDir2, byId, fifo) {
|
|
|
20330
20367
|
}
|
|
20331
20368
|
return;
|
|
20332
20369
|
}
|
|
20333
|
-
const dmFromEnt =
|
|
20370
|
+
const dmFromEnt = basename17.match(/^(DM-\d+)-[^/]+\.md$/);
|
|
20334
20371
|
if (dmFromEnt) {
|
|
20335
20372
|
const dm = dmFromEnt[1];
|
|
20336
20373
|
add(coordItem(`coord:ef:${dm}`, [mdId], "listEntityFields", { entityCode: dm }));
|
|
@@ -20634,7 +20671,7 @@ async function prepareSynthesisWorktree(storageContext, repoRoot, log, options)
|
|
|
20634
20671
|
if (options?.clearPriorArtefactRun !== false) {
|
|
20635
20672
|
await clearArtefactRun(storageContext);
|
|
20636
20673
|
}
|
|
20637
|
-
const wt = createAnalysisWorktree(repoRoot);
|
|
20674
|
+
const wt = createAnalysisWorktree(repoRoot, { log });
|
|
20638
20675
|
if (!wt.ok) {
|
|
20639
20676
|
return { ok: false, error: wt.error };
|
|
20640
20677
|
}
|
|
@@ -21596,8 +21633,8 @@ function expectedFeatureDetailBasenameFromRow(row2) {
|
|
|
21596
21633
|
}
|
|
21597
21634
|
return `${code}-${slug}.md`;
|
|
21598
21635
|
}
|
|
21599
|
-
function ctxPath(contextDir2,
|
|
21600
|
-
return path34.join(contextDir2,
|
|
21636
|
+
function ctxPath(contextDir2, basename17) {
|
|
21637
|
+
return path34.join(contextDir2, basename17);
|
|
21601
21638
|
}
|
|
21602
21639
|
function pushTarget(targets, stem, outputBasename, taskDescription, contextDir2) {
|
|
21603
21640
|
const meta = STEM_TO_AGENT[stem];
|
|
@@ -21626,11 +21663,11 @@ function discoverDetailMarkdownGroups(contextDir2) {
|
|
|
21626
21663
|
continue;
|
|
21627
21664
|
}
|
|
21628
21665
|
const name = safeStr4(row2.name) || code;
|
|
21629
|
-
const
|
|
21666
|
+
const basename17 = `${code}-${slug}.md`;
|
|
21630
21667
|
pushTarget(
|
|
21631
21668
|
featureTargets,
|
|
21632
21669
|
"agent-md-feature-detail",
|
|
21633
|
-
|
|
21670
|
+
basename17,
|
|
21634
21671
|
`Document feature **${code}** (**${name}**, slug **${slug}**) per \`.gluecharm/context/features-list.json\`: scope, behaviour, main dependencies, entry points, and links to code under the worktree. Write exactly one markdown file at the output path; cite substantive claims with file and line (or range).`,
|
|
21635
21672
|
contextDir2
|
|
21636
21673
|
);
|
|
@@ -22278,7 +22315,7 @@ async function runRemediationPipelineMissingPass(p) {
|
|
|
22278
22315
|
}
|
|
22279
22316
|
|
|
22280
22317
|
// src/pipelines/coverage/coveragePipeline.ts
|
|
22281
|
-
var
|
|
22318
|
+
var import_child_process4 = require("child_process");
|
|
22282
22319
|
var fs39 = __toESM(require("fs"));
|
|
22283
22320
|
var path38 = __toESM(require("path"));
|
|
22284
22321
|
|
|
@@ -22382,8 +22419,8 @@ function tryLoadGitNonIgnoredPathSet(repositoryRootAbs) {
|
|
|
22382
22419
|
env
|
|
22383
22420
|
};
|
|
22384
22421
|
try {
|
|
22385
|
-
const tracked = (0,
|
|
22386
|
-
const others = (0,
|
|
22422
|
+
const tracked = (0, import_child_process4.execFileSync)("git", ["-c", "core.quotepath=false", "ls-files", "-z"], opts);
|
|
22423
|
+
const others = (0, import_child_process4.execFileSync)(
|
|
22387
22424
|
"git",
|
|
22388
22425
|
["-c", "core.quotepath=false", "ls-files", "-z", "--others", "--exclude-standard"],
|
|
22389
22426
|
opts
|
|
@@ -22822,8 +22859,8 @@ function formatAjvErrors6(errors) {
|
|
|
22822
22859
|
});
|
|
22823
22860
|
}
|
|
22824
22861
|
var ajv = new import__6.default({ allErrors: true, strict: false });
|
|
22825
|
-
function compileSchema(
|
|
22826
|
-
const schemaPath = path39.join(schemasDir(),
|
|
22862
|
+
function compileSchema(basename17) {
|
|
22863
|
+
const schemaPath = path39.join(schemasDir(), basename17);
|
|
22827
22864
|
const schemaRaw = stripUtf8Bom5(fs40.readFileSync(schemaPath, "utf-8"));
|
|
22828
22865
|
const schema = JSON.parse(schemaRaw);
|
|
22829
22866
|
return ajv.compile(schema);
|
|
@@ -24700,7 +24737,6 @@ function stderrLinesForFactoryFailures(failures, exitCode) {
|
|
|
24700
24737
|
}
|
|
24701
24738
|
|
|
24702
24739
|
// src/factory/updateContext/runUpdateContextFactory.ts
|
|
24703
|
-
var fs49 = __toESM(require("node:fs"));
|
|
24704
24740
|
var path48 = __toESM(require("node:path"));
|
|
24705
24741
|
|
|
24706
24742
|
// src/factory/updateContext/updateContextBaseline.ts
|
|
@@ -24886,7 +24922,7 @@ function renderChangesSinceDateMarkdown(p) {
|
|
|
24886
24922
|
`- **Paths touched (union):** ${String(p.touchedPathsPosix.length)}`,
|
|
24887
24923
|
`- **Remediation:** ${p.remediationSkipped ? `skipped (${p.remediationSkipReason ?? "n/a"})` : "ran"}`,
|
|
24888
24924
|
`- **Promote:** ${p.promoteEffective ? "yes" : "no"}`,
|
|
24889
|
-
`- **Upload
|
|
24925
|
+
`- **Upload:** run \`easyspecs-cli upload context\` (or \`upload republish\`) after this command if you need cloud sync`,
|
|
24890
24926
|
`- **Analysis worktree:** \`${p.worktreeRootAbs}\``,
|
|
24891
24927
|
"",
|
|
24892
24928
|
"## Commits (oldest \u2192 newest)",
|
|
@@ -24974,41 +25010,10 @@ var REMEDIATION_CHUNK_MAX = 40;
|
|
|
24974
25010
|
function contextDirUnderRoot(wtRoot) {
|
|
24975
25011
|
return path48.join(wtRoot, ".gluecharm", "context");
|
|
24976
25012
|
}
|
|
24977
|
-
function listContextPathsWithMtimeSince(contextDirAbs, sinceMs) {
|
|
24978
|
-
const out = [];
|
|
24979
|
-
const walk = (dir) => {
|
|
24980
|
-
let entries;
|
|
24981
|
-
try {
|
|
24982
|
-
entries = fs49.readdirSync(dir, { withFileTypes: true });
|
|
24983
|
-
} catch {
|
|
24984
|
-
return;
|
|
24985
|
-
}
|
|
24986
|
-
for (const e of entries) {
|
|
24987
|
-
const full = path48.join(dir, e.name);
|
|
24988
|
-
if (e.isDirectory()) {
|
|
24989
|
-
if (e.name === ".git") {
|
|
24990
|
-
continue;
|
|
24991
|
-
}
|
|
24992
|
-
walk(full);
|
|
24993
|
-
} else if (e.isFile()) {
|
|
24994
|
-
try {
|
|
24995
|
-
if (fs49.statSync(full).mtimeMs >= sinceMs) {
|
|
24996
|
-
out.push(full);
|
|
24997
|
-
}
|
|
24998
|
-
} catch {
|
|
24999
|
-
}
|
|
25000
|
-
}
|
|
25001
|
-
}
|
|
25002
|
-
};
|
|
25003
|
-
walk(contextDirAbs);
|
|
25004
|
-
out.sort((a, b) => a.localeCompare(b));
|
|
25005
|
-
return out;
|
|
25006
|
-
}
|
|
25007
25013
|
async function runUpdateContextFactory(deps) {
|
|
25008
|
-
const runStartMs = Date.now();
|
|
25009
25014
|
const baseMeta = {
|
|
25010
25015
|
command: "update_context",
|
|
25011
|
-
uploadRequested:
|
|
25016
|
+
uploadRequested: false
|
|
25012
25017
|
};
|
|
25013
25018
|
const baseline = resolveUpdateContextBaseline(deps.repoRootAbs, deps.repoConfig);
|
|
25014
25019
|
if (!baseline) {
|
|
@@ -25123,7 +25128,6 @@ async function runUpdateContextFactory(deps) {
|
|
|
25123
25128
|
commitsInOrder: gitWin.commitsInOrder,
|
|
25124
25129
|
touchedPathsPosix: gitWin.touchedPathsPosix,
|
|
25125
25130
|
promoteEffective,
|
|
25126
|
-
uploadRequested: deps.wantsUpload,
|
|
25127
25131
|
remediationSkipped,
|
|
25128
25132
|
remediationSkipReason,
|
|
25129
25133
|
worktreeRootAbs: handle.path
|
|
@@ -25261,52 +25265,8 @@ async function runUpdateContextFactory(deps) {
|
|
|
25261
25265
|
};
|
|
25262
25266
|
}
|
|
25263
25267
|
}
|
|
25264
|
-
|
|
25265
|
-
|
|
25266
|
-
if (deps.wantsUpload) {
|
|
25267
|
-
if (!deps.runUploadFn) {
|
|
25268
|
-
finalizeWt?.();
|
|
25269
|
-
return {
|
|
25270
|
-
exitOk: false,
|
|
25271
|
-
ok: false,
|
|
25272
|
-
code: "UPLOAD_FAILED",
|
|
25273
|
-
error: "Upload requested but no upload implementation was wired.",
|
|
25274
|
-
...baseMeta
|
|
25275
|
-
};
|
|
25276
|
-
}
|
|
25277
|
-
const cand = listContextPathsWithMtimeSince(ctxDirAbs, runStartMs);
|
|
25278
|
-
if (cand.length === 0) {
|
|
25279
|
-
deps.log("[update-context] upload \u2014 no context files modified at or after run start (skip).");
|
|
25280
|
-
uploadSkipped = true;
|
|
25281
|
-
} else {
|
|
25282
|
-
uploadSkipped = false;
|
|
25283
|
-
const ur = await deps.runUploadFn({ wtContextDir: ctxDirAbs, filePaths: cand });
|
|
25284
|
-
if (!ur.ok) {
|
|
25285
|
-
finalizeWt?.();
|
|
25286
|
-
return {
|
|
25287
|
-
exitOk: false,
|
|
25288
|
-
ok: false,
|
|
25289
|
-
code: "UPLOAD_FAILED",
|
|
25290
|
-
error: ur.message ?? "Upload failed.",
|
|
25291
|
-
baselineDate: baseline.baselineIsoUtc,
|
|
25292
|
-
baselineSource: baseline.source,
|
|
25293
|
-
headCommit: gitWin.headCommit,
|
|
25294
|
-
rangeStartCommit: gitWin.rangeStartCommit,
|
|
25295
|
-
commitsReviewed: gitWin.commitsInOrder.length,
|
|
25296
|
-
filesDetected: inventory.length,
|
|
25297
|
-
filesRemediated,
|
|
25298
|
-
analysisWorktreeRoot: handle.path,
|
|
25299
|
-
promoted,
|
|
25300
|
-
remediationSkipped,
|
|
25301
|
-
...remediationSkipReason ? { skipReason: remediationSkipReason } : {},
|
|
25302
|
-
changesReportRelativePath: ".gluecharm/context/changes-since-date.md",
|
|
25303
|
-
uploadSkipped: false,
|
|
25304
|
-
...baseMeta
|
|
25305
|
-
};
|
|
25306
|
-
}
|
|
25307
|
-
filesUploaded = ur.uploadedCount ?? cand.length;
|
|
25308
|
-
}
|
|
25309
|
-
}
|
|
25268
|
+
const uploadSkipped = true;
|
|
25269
|
+
const filesUploaded = 0;
|
|
25310
25270
|
let persisted = false;
|
|
25311
25271
|
try {
|
|
25312
25272
|
persistUpdateContextLastRunAt(deps.repoRootAbs, (/* @__PURE__ */ new Date()).toISOString());
|
|
@@ -25338,11 +25298,11 @@ async function runUpdateContextFactory(deps) {
|
|
|
25338
25298
|
}
|
|
25339
25299
|
|
|
25340
25300
|
// src/factory/contextDrift/runContextDriftFactory.ts
|
|
25341
|
-
var
|
|
25301
|
+
var fs54 = __toESM(require("node:fs"));
|
|
25342
25302
|
var path53 = __toESM(require("node:path"));
|
|
25343
25303
|
|
|
25344
25304
|
// src/factory/contextDrift/contextDriftManifest.ts
|
|
25345
|
-
var
|
|
25305
|
+
var fs49 = __toESM(require("node:fs"));
|
|
25346
25306
|
var path49 = __toESM(require("node:path"));
|
|
25347
25307
|
var MAX_REFERENCE_BYTES = 256 * 1024;
|
|
25348
25308
|
var MAX_EVIDENCE_FILES = 300;
|
|
@@ -25351,7 +25311,7 @@ var MAX_EXCERPT = 4e3;
|
|
|
25351
25311
|
function readFileLimited(abs, maxBytes) {
|
|
25352
25312
|
let buf;
|
|
25353
25313
|
try {
|
|
25354
|
-
buf =
|
|
25314
|
+
buf = fs49.readFileSync(abs);
|
|
25355
25315
|
} catch {
|
|
25356
25316
|
return { text: "", truncated: false };
|
|
25357
25317
|
}
|
|
@@ -25364,14 +25324,14 @@ function collectEvidencePaths(repoRoot) {
|
|
|
25364
25324
|
const roots = ["src", "test", "tests", "packages", ".gluecharm", "scripts"];
|
|
25365
25325
|
for (const rel of roots) {
|
|
25366
25326
|
const abs = path49.join(repoRoot, rel);
|
|
25367
|
-
if (!
|
|
25327
|
+
if (!fs49.existsSync(abs)) {
|
|
25368
25328
|
continue;
|
|
25369
25329
|
}
|
|
25370
25330
|
walkFiles(abs, repoRoot, out, 0);
|
|
25371
25331
|
}
|
|
25372
25332
|
for (const leaf of ["package.json", "tsconfig.json"]) {
|
|
25373
25333
|
const abs = path49.join(repoRoot, leaf);
|
|
25374
|
-
if (
|
|
25334
|
+
if (fs49.existsSync(abs) && fs49.statSync(abs).isFile()) {
|
|
25375
25335
|
const r = path49.relative(repoRoot, abs).split(path49.sep).join("/");
|
|
25376
25336
|
out.push(r);
|
|
25377
25337
|
}
|
|
@@ -25389,7 +25349,7 @@ function walkFiles(dir, repoRoot, out, depth) {
|
|
|
25389
25349
|
}
|
|
25390
25350
|
let entries;
|
|
25391
25351
|
try {
|
|
25392
|
-
entries =
|
|
25352
|
+
entries = fs49.readdirSync(dir, { withFileTypes: true });
|
|
25393
25353
|
} catch {
|
|
25394
25354
|
return;
|
|
25395
25355
|
}
|
|
@@ -25426,7 +25386,7 @@ function buildComparisonManifest(args) {
|
|
|
25426
25386
|
const evidenceFiles = [];
|
|
25427
25387
|
for (const rel of evidencePathsTrimmed) {
|
|
25428
25388
|
const abs = path49.join(args.worktreeRoot, ...rel.split("/"));
|
|
25429
|
-
const st =
|
|
25389
|
+
const st = fs49.existsSync(abs) ? fs49.statSync(abs) : null;
|
|
25430
25390
|
const size = st && st.isFile() ? st.size : 0;
|
|
25431
25391
|
const { text, truncated } = readFileLimited(abs, MAX_EVIDENCE_READ);
|
|
25432
25392
|
const excerpt = truncated ? `${text.slice(0, MAX_EXCERPT)}
|
|
@@ -25448,7 +25408,7 @@ function buildComparisonManifest(args) {
|
|
|
25448
25408
|
}
|
|
25449
25409
|
|
|
25450
25410
|
// src/factory/contextDrift/contextDriftAgent.ts
|
|
25451
|
-
var
|
|
25411
|
+
var fs50 = __toESM(require("node:fs"));
|
|
25452
25412
|
var path50 = __toESM(require("node:path"));
|
|
25453
25413
|
|
|
25454
25414
|
// src/factory/contextDrift/contextDriftPayload.ts
|
|
@@ -25595,16 +25555,16 @@ function buildDriftPrompt(args) {
|
|
|
25595
25555
|
}
|
|
25596
25556
|
async function runDriftComparisonOpenCode(args) {
|
|
25597
25557
|
const runDir = path50.join(args.worktreeRoot, ".opencode", "_run");
|
|
25598
|
-
|
|
25558
|
+
fs50.mkdirSync(runDir, { recursive: true });
|
|
25599
25559
|
const manifestPath = path50.join(runDir, "context-drift-manifest.json");
|
|
25600
25560
|
const outputPath = path50.join(runDir, "context-drift-payload.json");
|
|
25601
|
-
|
|
25561
|
+
fs50.writeFileSync(manifestPath, `${JSON.stringify(args.manifestObject, null, 2)}
|
|
25602
25562
|
`, "utf8");
|
|
25603
|
-
if (
|
|
25604
|
-
|
|
25563
|
+
if (fs50.existsSync(outputPath)) {
|
|
25564
|
+
fs50.unlinkSync(outputPath);
|
|
25605
25565
|
}
|
|
25606
25566
|
const promptPath = path50.join(runDir, `context-drift-${Date.now()}.prompt.txt`);
|
|
25607
|
-
|
|
25567
|
+
fs50.writeFileSync(
|
|
25608
25568
|
promptPath,
|
|
25609
25569
|
buildDriftPrompt({
|
|
25610
25570
|
worktreeRoot: args.worktreeRoot,
|
|
@@ -25646,7 +25606,7 @@ async function runDriftComparisonOpenCode(args) {
|
|
|
25646
25606
|
}
|
|
25647
25607
|
let raw;
|
|
25648
25608
|
try {
|
|
25649
|
-
const txt =
|
|
25609
|
+
const txt = fs50.readFileSync(outputPath, "utf8");
|
|
25650
25610
|
raw = JSON.parse(txt);
|
|
25651
25611
|
} catch (e) {
|
|
25652
25612
|
return {
|
|
@@ -25663,7 +25623,7 @@ async function runDriftComparisonOpenCode(args) {
|
|
|
25663
25623
|
|
|
25664
25624
|
// src/factory/contextDrift/contextDriftPaths.ts
|
|
25665
25625
|
var crypto2 = __toESM(require("node:crypto"));
|
|
25666
|
-
var
|
|
25626
|
+
var fs51 = __toESM(require("node:fs"));
|
|
25667
25627
|
var path51 = __toESM(require("node:path"));
|
|
25668
25628
|
var DRIFT_CONTEXT_SUBDIR = path51.join(".gluecharm", "context", "drift");
|
|
25669
25629
|
function sanitizeSlug(raw) {
|
|
@@ -25702,7 +25662,7 @@ function maybeDedupeSlug(slug, referenceRelPosix) {
|
|
|
25702
25662
|
function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
25703
25663
|
let st;
|
|
25704
25664
|
try {
|
|
25705
|
-
st =
|
|
25665
|
+
st = fs51.statSync(referenceAbsInWorktree);
|
|
25706
25666
|
} catch {
|
|
25707
25667
|
return { ok: false, error: `Reference path not found in analysis worktree: ${referenceAbsInWorktree}` };
|
|
25708
25668
|
}
|
|
@@ -25723,7 +25683,7 @@ function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
|
25723
25683
|
}
|
|
25724
25684
|
let entries;
|
|
25725
25685
|
try {
|
|
25726
|
-
entries =
|
|
25686
|
+
entries = fs51.readdirSync(dir, { withFileTypes: true });
|
|
25727
25687
|
} catch {
|
|
25728
25688
|
return;
|
|
25729
25689
|
}
|
|
@@ -25748,7 +25708,7 @@ function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
|
25748
25708
|
}
|
|
25749
25709
|
function pickReferenceRootDocument(args) {
|
|
25750
25710
|
if (args.indexOverrideAbs) {
|
|
25751
|
-
if (!
|
|
25711
|
+
if (!fs51.existsSync(args.indexOverrideAbs) || !args.indexOverrideAbs.endsWith(".md")) {
|
|
25752
25712
|
return { ok: false, error: "--index must point to an existing .md file under the repo." };
|
|
25753
25713
|
}
|
|
25754
25714
|
return { ok: true, path: args.indexOverrideAbs };
|
|
@@ -25759,7 +25719,7 @@ function pickReferenceRootDocument(args) {
|
|
|
25759
25719
|
const dir = args.referenceAbsInWorktree;
|
|
25760
25720
|
for (const name of ["index.md", "README.md"]) {
|
|
25761
25721
|
const p = path51.join(dir, name);
|
|
25762
|
-
if (
|
|
25722
|
+
if (fs51.existsSync(p) && fs51.statSync(p).isFile()) {
|
|
25763
25723
|
return { ok: true, path: p };
|
|
25764
25724
|
}
|
|
25765
25725
|
}
|
|
@@ -25776,13 +25736,13 @@ function toPosixPath(p) {
|
|
|
25776
25736
|
}
|
|
25777
25737
|
|
|
25778
25738
|
// src/factory/contextDrift/contextDriftIndex.ts
|
|
25779
|
-
var
|
|
25739
|
+
var fs52 = __toESM(require("node:fs"));
|
|
25780
25740
|
var START = "<!-- easyspecs-drift-links:start -->";
|
|
25781
25741
|
var END = "<!-- easyspecs-drift-links:end -->";
|
|
25782
25742
|
function patchReferenceIndexWithDriftLink(args) {
|
|
25783
25743
|
let body;
|
|
25784
25744
|
try {
|
|
25785
|
-
body =
|
|
25745
|
+
body = fs52.readFileSync(args.referenceRootAbsolute, "utf8");
|
|
25786
25746
|
} catch (e) {
|
|
25787
25747
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
25788
25748
|
}
|
|
@@ -25803,7 +25763,7 @@ ${block}
|
|
|
25803
25763
|
`;
|
|
25804
25764
|
}
|
|
25805
25765
|
try {
|
|
25806
|
-
|
|
25766
|
+
fs52.writeFileSync(args.referenceRootAbsolute, next, "utf8");
|
|
25807
25767
|
} catch (e) {
|
|
25808
25768
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
25809
25769
|
}
|
|
@@ -25814,13 +25774,13 @@ function escapeRe(s) {
|
|
|
25814
25774
|
}
|
|
25815
25775
|
|
|
25816
25776
|
// src/factory/contextDrift/contextDriftPromote.ts
|
|
25817
|
-
var
|
|
25777
|
+
var fs53 = __toESM(require("node:fs"));
|
|
25818
25778
|
var path52 = __toESM(require("node:path"));
|
|
25819
25779
|
function copyWorktreeFileToWorkspace(args) {
|
|
25820
25780
|
const src = path52.join(args.worktreeRoot, ...args.relativePosix.split("/"));
|
|
25821
25781
|
const dest = path52.join(args.workspaceRoot, ...args.relativePosix.split("/"));
|
|
25822
|
-
|
|
25823
|
-
|
|
25782
|
+
fs53.mkdirSync(path52.dirname(dest), { recursive: true });
|
|
25783
|
+
fs53.copyFileSync(src, dest);
|
|
25824
25784
|
}
|
|
25825
25785
|
|
|
25826
25786
|
// src/factory/contextDrift/runContextDriftFactory.ts
|
|
@@ -25839,7 +25799,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25839
25799
|
};
|
|
25840
25800
|
}
|
|
25841
25801
|
const refAbsWorkspace = resolved.abs;
|
|
25842
|
-
if (!
|
|
25802
|
+
if (!fs54.existsSync(refAbsWorkspace)) {
|
|
25843
25803
|
return {
|
|
25844
25804
|
exitOk: false,
|
|
25845
25805
|
ok: false,
|
|
@@ -25852,7 +25812,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25852
25812
|
let indexOverrideAbsWorkspace;
|
|
25853
25813
|
if (deps.indexOverrideArg?.trim()) {
|
|
25854
25814
|
const ir = resolveInsideRepo(deps.repoRootAbs, deps.indexOverrideArg.trim());
|
|
25855
|
-
if (!ir.ok || !
|
|
25815
|
+
if (!ir.ok || !fs54.existsSync(ir.abs)) {
|
|
25856
25816
|
return {
|
|
25857
25817
|
exitOk: false,
|
|
25858
25818
|
ok: false,
|
|
@@ -25870,7 +25830,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25870
25830
|
ok: true,
|
|
25871
25831
|
code: "DRY_RUN",
|
|
25872
25832
|
...baseMeta,
|
|
25873
|
-
referenceRootDocument: toPosixPath(path53.relative(deps.repoRootAbs, refAbsWorkspace)) + (
|
|
25833
|
+
referenceRootDocument: toPosixPath(path53.relative(deps.repoRootAbs, refAbsWorkspace)) + (fs54.statSync(refAbsWorkspace).isDirectory() ? "/" : ""),
|
|
25874
25834
|
driftReportPath: null,
|
|
25875
25835
|
analysisWorktreeRoot: "",
|
|
25876
25836
|
promoted: false,
|
|
@@ -25939,7 +25899,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25939
25899
|
}
|
|
25940
25900
|
const indexWt = indexOverrideAbsWorkspace ? path53.join(wt, ...path53.relative(deps.repoRootAbs, indexOverrideAbsWorkspace).split(path53.sep)) : void 0;
|
|
25941
25901
|
const rootPick = pickReferenceRootDocument({
|
|
25942
|
-
referencePathIsFile:
|
|
25902
|
+
referencePathIsFile: fs54.statSync(refAbsWt).isFile(),
|
|
25943
25903
|
referenceAbsInWorktree: refAbsWt,
|
|
25944
25904
|
bundleFiles: bundle.bundleFiles,
|
|
25945
25905
|
indexOverrideAbs: indexWt
|
|
@@ -25966,7 +25926,7 @@ async function runContextDriftFactory(deps) {
|
|
|
25966
25926
|
slug = maybeDedupeSlug(slug, refRel);
|
|
25967
25927
|
const driftBase = driftFilename(slug, runDate);
|
|
25968
25928
|
const driftDirWt = path53.join(wt, DRIFT_CONTEXT_SUBDIR);
|
|
25969
|
-
|
|
25929
|
+
fs54.mkdirSync(driftDirWt, { recursive: true });
|
|
25970
25930
|
const driftAbsWt = path53.join(driftDirWt, driftBase);
|
|
25971
25931
|
let payload;
|
|
25972
25932
|
if (deps.testOnlyFixturePayload) {
|
|
@@ -26003,7 +25963,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26003
25963
|
manifestTruncation: manifest.truncation
|
|
26004
25964
|
});
|
|
26005
25965
|
try {
|
|
26006
|
-
|
|
25966
|
+
fs54.writeFileSync(driftAbsWt, md, "utf8");
|
|
26007
25967
|
} catch (e) {
|
|
26008
25968
|
finalizeWt?.();
|
|
26009
25969
|
return {
|
|
@@ -26082,7 +26042,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26082
26042
|
}
|
|
26083
26043
|
|
|
26084
26044
|
// src/analysis/coordinationDuplicatesDiagnosis.ts
|
|
26085
|
-
var
|
|
26045
|
+
var fs55 = __toESM(require("fs"));
|
|
26086
26046
|
var path54 = __toESM(require("path"));
|
|
26087
26047
|
var import__7 = __toESM(require__());
|
|
26088
26048
|
var COORDINATION_DUPLICATES_REPORT_BASENAME = "coordination-duplicates-report.json";
|
|
@@ -26108,30 +26068,30 @@ var RE_MD_SV = /^SV-\d+-.+\.md$/i;
|
|
|
26108
26068
|
var RE_MD_DM_FD = /^DM-\d+_FD-\d+-.+\.md$/i;
|
|
26109
26069
|
var RE_MD_DM = /^DM-\d+-.+\.md$/i;
|
|
26110
26070
|
var RE_MD_TS = /^TS-\d+-.+\.md$/i;
|
|
26111
|
-
function looksLikeCoordinationDetailMarkdownBasename(
|
|
26112
|
-
if (!
|
|
26071
|
+
function looksLikeCoordinationDetailMarkdownBasename(basename17) {
|
|
26072
|
+
if (!basename17 || basename17 !== path54.basename(basename17) || !/\.md$/i.test(basename17)) {
|
|
26113
26073
|
return false;
|
|
26114
26074
|
}
|
|
26115
|
-
if (STAPLE_CONTEXT_MARKDOWN_BASENAMES.has(
|
|
26075
|
+
if (STAPLE_CONTEXT_MARKDOWN_BASENAMES.has(basename17)) {
|
|
26116
26076
|
return false;
|
|
26117
26077
|
}
|
|
26118
|
-
return RE_MD_FE_UC_SC.test(
|
|
26078
|
+
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);
|
|
26119
26079
|
}
|
|
26120
26080
|
function loadRawFeatureRows(contextDirAbs) {
|
|
26121
26081
|
const p = path54.join(contextDirAbs, "features-list.json");
|
|
26122
|
-
if (!
|
|
26082
|
+
if (!fs55.existsSync(p)) {
|
|
26123
26083
|
return [];
|
|
26124
26084
|
}
|
|
26125
26085
|
try {
|
|
26126
|
-
const raw = stripUtf8Bom6(
|
|
26086
|
+
const raw = stripUtf8Bom6(fs55.readFileSync(p, "utf-8"));
|
|
26127
26087
|
const doc = JSON.parse(raw);
|
|
26128
26088
|
return Array.isArray(doc.features) ? doc.features : [];
|
|
26129
26089
|
} catch {
|
|
26130
26090
|
return [];
|
|
26131
26091
|
}
|
|
26132
26092
|
}
|
|
26133
|
-
function hintForOrphanFeatureMarkdown(
|
|
26134
|
-
const m = /^FE-(\d+)-(.+)\.md$/i.exec(
|
|
26093
|
+
function hintForOrphanFeatureMarkdown(basename17, featureRows) {
|
|
26094
|
+
const m = /^FE-(\d+)-(.+)\.md$/i.exec(basename17);
|
|
26135
26095
|
if (!m) {
|
|
26136
26096
|
return void 0;
|
|
26137
26097
|
}
|
|
@@ -26143,8 +26103,8 @@ function hintForOrphanFeatureMarkdown(basename16, featureRows) {
|
|
|
26143
26103
|
continue;
|
|
26144
26104
|
}
|
|
26145
26105
|
const expected = expectedFeatureDetailBasenameFromRow(row2);
|
|
26146
|
-
if (expected && expected !==
|
|
26147
|
-
return `features-list row ${code} currently implies detail file ${expected} (slug/name changed \u2014 ${
|
|
26106
|
+
if (expected && expected !== basename17) {
|
|
26107
|
+
return `features-list row ${code} currently implies detail file ${expected} (slug/name changed \u2014 ${basename17} may be stale).`;
|
|
26148
26108
|
}
|
|
26149
26109
|
if (!expected) {
|
|
26150
26110
|
return `features-list row ${code} has no resolvable slug for a detail markdown basename.`;
|
|
@@ -26158,7 +26118,7 @@ function findOrphanCoordinationMarkdown(contextDirAbs) {
|
|
|
26158
26118
|
const featureRows = loadRawFeatureRows(contextDirAbs);
|
|
26159
26119
|
let dirents;
|
|
26160
26120
|
try {
|
|
26161
|
-
dirents =
|
|
26121
|
+
dirents = fs55.readdirSync(contextDirAbs, { withFileTypes: true });
|
|
26162
26122
|
} catch {
|
|
26163
26123
|
return [];
|
|
26164
26124
|
}
|
|
@@ -26412,13 +26372,13 @@ function buildCoordinationDuplicatesReport(input) {
|
|
|
26412
26372
|
const duplicateGroups = [];
|
|
26413
26373
|
for (const entry of COORDINATION_LIST_SCAN_ENTRIES) {
|
|
26414
26374
|
const filePath = path54.join(input.contextDirAbsolute, entry.basename);
|
|
26415
|
-
if (!
|
|
26375
|
+
if (!fs55.existsSync(filePath)) {
|
|
26416
26376
|
lists.push({ basename: entry.basename, status: "missing" });
|
|
26417
26377
|
continue;
|
|
26418
26378
|
}
|
|
26419
26379
|
let raw;
|
|
26420
26380
|
try {
|
|
26421
|
-
raw = stripUtf8Bom6(
|
|
26381
|
+
raw = stripUtf8Bom6(fs55.readFileSync(filePath, "utf-8"));
|
|
26422
26382
|
} catch (e) {
|
|
26423
26383
|
lists.push({
|
|
26424
26384
|
basename: entry.basename,
|
|
@@ -26467,7 +26427,7 @@ function validateReportData(data) {
|
|
|
26467
26427
|
if (!validateReportCompiled) {
|
|
26468
26428
|
const ajv2 = new import__7.default({ allErrors: true, strict: false });
|
|
26469
26429
|
const schemaPath = path54.join(resolveContextListSchemasDir(), "coordination-duplicates-report.schema.json");
|
|
26470
|
-
const schemaRaw = stripUtf8Bom6(
|
|
26430
|
+
const schemaRaw = stripUtf8Bom6(fs55.readFileSync(schemaPath, "utf-8"));
|
|
26471
26431
|
validateReportCompiled = ajv2.compile(JSON.parse(schemaRaw));
|
|
26472
26432
|
}
|
|
26473
26433
|
if (validateReportCompiled(data)) {
|
|
@@ -26490,15 +26450,15 @@ function runCoordinationDuplicatesDiagnosis(input) {
|
|
|
26490
26450
|
`;
|
|
26491
26451
|
const tmp = `${outPath}.tmp.${process.pid}`;
|
|
26492
26452
|
try {
|
|
26493
|
-
|
|
26453
|
+
fs55.writeFileSync(tmp, payload, "utf-8");
|
|
26494
26454
|
} catch (e) {
|
|
26495
26455
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
26496
26456
|
}
|
|
26497
26457
|
try {
|
|
26498
|
-
|
|
26458
|
+
fs55.renameSync(tmp, outPath);
|
|
26499
26459
|
} catch (e) {
|
|
26500
26460
|
try {
|
|
26501
|
-
|
|
26461
|
+
fs55.unlinkSync(tmp);
|
|
26502
26462
|
} catch {
|
|
26503
26463
|
}
|
|
26504
26464
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
@@ -26532,7 +26492,7 @@ function runCoordinationDuplicatesDiagnosis(input) {
|
|
|
26532
26492
|
}
|
|
26533
26493
|
|
|
26534
26494
|
// src/pipelines/download/downloadPipeline.ts
|
|
26535
|
-
var
|
|
26495
|
+
var fs56 = __toESM(require("node:fs"));
|
|
26536
26496
|
var path55 = __toESM(require("node:path"));
|
|
26537
26497
|
var SRS_DISCOVERY_BATCH_GET_CHUNK_SIZE = 200;
|
|
26538
26498
|
function isRecord7(v) {
|
|
@@ -26638,19 +26598,19 @@ function chunkIds(ids, size) {
|
|
|
26638
26598
|
return out;
|
|
26639
26599
|
}
|
|
26640
26600
|
function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
26641
|
-
if (!
|
|
26601
|
+
if (!fs56.existsSync(contextDirAbs) || !fs56.statSync(contextDirAbs).isDirectory()) {
|
|
26642
26602
|
return { filesRemoved: 0 };
|
|
26643
26603
|
}
|
|
26644
26604
|
const preserveAbs = path55.resolve(contextDirAbs, UPLOAD_TARGET_FILENAME);
|
|
26645
26605
|
const preserveSet = /* @__PURE__ */ new Set();
|
|
26646
|
-
if (
|
|
26606
|
+
if (fs56.existsSync(preserveAbs) && fs56.statSync(preserveAbs).isFile()) {
|
|
26647
26607
|
preserveSet.add(preserveAbs);
|
|
26648
26608
|
}
|
|
26649
26609
|
let filesRemoved = 0;
|
|
26650
26610
|
const walkRm = (dir) => {
|
|
26651
26611
|
let entries;
|
|
26652
26612
|
try {
|
|
26653
|
-
entries =
|
|
26613
|
+
entries = fs56.readdirSync(dir, { withFileTypes: true });
|
|
26654
26614
|
} catch {
|
|
26655
26615
|
return;
|
|
26656
26616
|
}
|
|
@@ -26659,7 +26619,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
|
26659
26619
|
if (e.isDirectory()) {
|
|
26660
26620
|
walkRm(full);
|
|
26661
26621
|
try {
|
|
26662
|
-
|
|
26622
|
+
fs56.rmdirSync(full);
|
|
26663
26623
|
} catch {
|
|
26664
26624
|
}
|
|
26665
26625
|
} else if (e.isFile()) {
|
|
@@ -26668,7 +26628,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
|
26668
26628
|
continue;
|
|
26669
26629
|
}
|
|
26670
26630
|
try {
|
|
26671
|
-
|
|
26631
|
+
fs56.unlinkSync(abs);
|
|
26672
26632
|
filesRemoved += 1;
|
|
26673
26633
|
} catch {
|
|
26674
26634
|
}
|
|
@@ -26747,15 +26707,15 @@ async function runDownloadPipeline(opts) {
|
|
|
26747
26707
|
failed.push({ id, name, message: "Unsafe or invalid name for local path." });
|
|
26748
26708
|
continue;
|
|
26749
26709
|
}
|
|
26750
|
-
|
|
26751
|
-
const exists =
|
|
26710
|
+
fs56.mkdirSync(path55.dirname(outAbs), { recursive: true });
|
|
26711
|
+
const exists = fs56.existsSync(outAbs);
|
|
26752
26712
|
if (exists && !opts.force && !opts.replaceFromCloud) {
|
|
26753
26713
|
skipped += 1;
|
|
26754
26714
|
log?.(`[pipeline:download] skip existing ${name} (use --force to overwrite).`);
|
|
26755
26715
|
continue;
|
|
26756
26716
|
}
|
|
26757
26717
|
try {
|
|
26758
|
-
|
|
26718
|
+
fs56.writeFileSync(outAbs, bodyText, "utf8");
|
|
26759
26719
|
downloaded += 1;
|
|
26760
26720
|
succeededIds[outAbs] = id;
|
|
26761
26721
|
} catch (e) {
|
|
@@ -26926,7 +26886,7 @@ function createAuthenticatedRequestJson(deps) {
|
|
|
26926
26886
|
}
|
|
26927
26887
|
|
|
26928
26888
|
// src/cli/cliSession.ts
|
|
26929
|
-
var
|
|
26889
|
+
var fs57 = __toESM(require("node:fs"));
|
|
26930
26890
|
var os3 = __toESM(require("node:os"));
|
|
26931
26891
|
var path56 = __toESM(require("node:path"));
|
|
26932
26892
|
function defaultSessionPath() {
|
|
@@ -26971,10 +26931,10 @@ function effectiveCliSessionPath() {
|
|
|
26971
26931
|
function readCliSession() {
|
|
26972
26932
|
const p = effectiveCliSessionPath();
|
|
26973
26933
|
try {
|
|
26974
|
-
if (!
|
|
26934
|
+
if (!fs57.existsSync(p)) {
|
|
26975
26935
|
return void 0;
|
|
26976
26936
|
}
|
|
26977
|
-
const j = JSON.parse(
|
|
26937
|
+
const j = JSON.parse(fs57.readFileSync(p, "utf8"));
|
|
26978
26938
|
const apiBaseUrl = typeof j.apiBaseUrl === "string" ? j.apiBaseUrl.trim() : "";
|
|
26979
26939
|
const accessToken = typeof j.accessToken === "string" ? j.accessToken : "";
|
|
26980
26940
|
const refreshToken = typeof j.refreshToken === "string" ? j.refreshToken : "";
|
|
@@ -26988,20 +26948,20 @@ function readCliSession() {
|
|
|
26988
26948
|
}
|
|
26989
26949
|
function writeCliSession(s) {
|
|
26990
26950
|
const p = effectiveCliSessionPath();
|
|
26991
|
-
|
|
26992
|
-
|
|
26951
|
+
fs57.mkdirSync(path56.dirname(p), { recursive: true });
|
|
26952
|
+
fs57.writeFileSync(p, `${JSON.stringify(s, null, 2)}
|
|
26993
26953
|
`, "utf8");
|
|
26994
26954
|
}
|
|
26995
26955
|
function clearCliSession() {
|
|
26996
26956
|
const p = effectiveCliSessionPath();
|
|
26997
26957
|
try {
|
|
26998
|
-
|
|
26958
|
+
fs57.unlinkSync(p);
|
|
26999
26959
|
} catch {
|
|
27000
26960
|
}
|
|
27001
26961
|
}
|
|
27002
26962
|
|
|
27003
26963
|
// src/analysis/acePendingTraces.ts
|
|
27004
|
-
var
|
|
26964
|
+
var fs58 = __toESM(require("fs"));
|
|
27005
26965
|
var path57 = __toESM(require("path"));
|
|
27006
26966
|
function normalizeAceTraceRelativePath(rel) {
|
|
27007
26967
|
return rel.split(/[/\\]/).join("/");
|
|
@@ -27009,12 +26969,12 @@ function normalizeAceTraceRelativePath(rel) {
|
|
|
27009
26969
|
function readCompletedTraceRelativePaths(contextDir2) {
|
|
27010
26970
|
const set = /* @__PURE__ */ new Set();
|
|
27011
26971
|
const jsonlPath = aceConsolidatedSessionsJsonlPath(contextDir2);
|
|
27012
|
-
if (!
|
|
26972
|
+
if (!fs58.existsSync(jsonlPath)) {
|
|
27013
26973
|
return set;
|
|
27014
26974
|
}
|
|
27015
26975
|
let raw;
|
|
27016
26976
|
try {
|
|
27017
|
-
raw =
|
|
26977
|
+
raw = fs58.readFileSync(jsonlPath, "utf8");
|
|
27018
26978
|
} catch {
|
|
27019
26979
|
return set;
|
|
27020
26980
|
}
|
|
@@ -27045,7 +27005,7 @@ function readCompletedTraceRelativePaths(contextDir2) {
|
|
|
27045
27005
|
}
|
|
27046
27006
|
function listPendingAceTraceFiles(contextDir2, worktreeRoot) {
|
|
27047
27007
|
const traceSchema = opencodeAceSchemaPath(worktreeRoot, ACE_SCHEMA_TRACE);
|
|
27048
|
-
if (!
|
|
27008
|
+
if (!fs58.existsSync(traceSchema)) {
|
|
27049
27009
|
return [];
|
|
27050
27010
|
}
|
|
27051
27011
|
const completed = readCompletedTraceRelativePaths(contextDir2);
|
|
@@ -27611,7 +27571,7 @@ function formatCliStderrLine(line, useAnsi) {
|
|
|
27611
27571
|
}
|
|
27612
27572
|
|
|
27613
27573
|
// src/cli/main.ts
|
|
27614
|
-
var PKG_VERSION = "0.0.
|
|
27574
|
+
var PKG_VERSION = "0.0.19";
|
|
27615
27575
|
function isNonEmptyFactoryFailureArray(x) {
|
|
27616
27576
|
if (!Array.isArray(x) || x.length === 0) {
|
|
27617
27577
|
return false;
|
|
@@ -27743,7 +27703,7 @@ function resolveAnalysisRoot(repoRoot, rootKind, worktreePath) {
|
|
|
27743
27703
|
return repoRoot;
|
|
27744
27704
|
}
|
|
27745
27705
|
const wt = worktreePath?.trim();
|
|
27746
|
-
if (wt &&
|
|
27706
|
+
if (wt && fs59.existsSync(path59.join(wt, ".git"))) {
|
|
27747
27707
|
return path59.resolve(wt);
|
|
27748
27708
|
}
|
|
27749
27709
|
throw new Error("worktree mode requires --worktree <path> to an existing analysis checkout.");
|
|
@@ -27752,14 +27712,14 @@ function resolveAdHocCheckoutRoot(_repoRoot, storage, worktreeFlag) {
|
|
|
27752
27712
|
const w = worktreeFlag?.trim();
|
|
27753
27713
|
if (w) {
|
|
27754
27714
|
const abs = path59.resolve(w);
|
|
27755
|
-
if (
|
|
27715
|
+
if (fs59.existsSync(path59.join(abs, ".git"))) {
|
|
27756
27716
|
return abs;
|
|
27757
27717
|
}
|
|
27758
27718
|
throw new Error(`Invalid --worktree (not a git checkout): ${abs}`);
|
|
27759
27719
|
}
|
|
27760
27720
|
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
27761
27721
|
const p = snap?.adHocWorktreePath?.trim();
|
|
27762
|
-
if (p &&
|
|
27722
|
+
if (p && fs59.existsSync(path59.join(p, ".git"))) {
|
|
27763
27723
|
return p;
|
|
27764
27724
|
}
|
|
27765
27725
|
throw new Error("No analysis checkout: run `easyspecs-cli run synthesis` first or pass `--worktree <path>`.");
|
|
@@ -28030,7 +27990,7 @@ async function main() {
|
|
|
28030
27990
|
process.exit(ExitCode.usage);
|
|
28031
27991
|
}
|
|
28032
27992
|
const agentsDir = resolveOpenCodeAgentsDir(repoRoot, repoConfig);
|
|
28033
|
-
const agentsOk =
|
|
27993
|
+
const agentsOk = fs59.existsSync(agentsDir);
|
|
28034
27994
|
const oc = getOpenCodeReadiness({
|
|
28035
27995
|
executable: merged.openCodeExecutable,
|
|
28036
27996
|
skipCredentialsCheck: merged.openCodeSkipCredentialsCheck,
|
|
@@ -28477,7 +28437,27 @@ async function main() {
|
|
|
28477
28437
|
finish(ExitCode.internal, { ok: false, error: "Unexpected context drift result shape." });
|
|
28478
28438
|
}
|
|
28479
28439
|
if (pos[0] === "analysis") {
|
|
28480
|
-
const
|
|
28440
|
+
for (const a of pos.slice(1)) {
|
|
28441
|
+
if (a === "--force-new-context-analysis") {
|
|
28442
|
+
continue;
|
|
28443
|
+
}
|
|
28444
|
+
if (a === "--upload") {
|
|
28445
|
+
finish(ExitCode.usage, {
|
|
28446
|
+
ok: false,
|
|
28447
|
+
error: "Removed flag: analysis --upload. Run `easyspecs-cli upload context` or `easyspecs-cli upload republish` after analysis (after `auth login` and easyspecs.easyspecsProjectId)."
|
|
28448
|
+
});
|
|
28449
|
+
}
|
|
28450
|
+
if (a === "--synthesis-only") {
|
|
28451
|
+
console.error(
|
|
28452
|
+
"[deprecated] Ignoring deprecated flag --synthesis-only (it has no effect). Use `easyspecs-cli run synthesis` for a single synthesis pass, or the VS Code Factory \u201CSynthesis only\u201D control for factory-style convergence."
|
|
28453
|
+
);
|
|
28454
|
+
continue;
|
|
28455
|
+
}
|
|
28456
|
+
finish(ExitCode.usage, {
|
|
28457
|
+
ok: false,
|
|
28458
|
+
error: `unknown analysis flag: ${a} (allowed: --force-new-context-analysis)`
|
|
28459
|
+
});
|
|
28460
|
+
}
|
|
28481
28461
|
const forceNewContextAnalysis = positionals.includes("--force-new-context-analysis");
|
|
28482
28462
|
const cloudCached = readEasyspecsMergedSetting(
|
|
28483
28463
|
repoConfig.easyspecs,
|
|
@@ -28486,12 +28466,11 @@ async function main() {
|
|
|
28486
28466
|
const cloudCachedAt = readEasyspecsMergedSetting(repoConfig.easyspecs, "easyspecs.factory.cloudContextAnalyzedAt") ?? null;
|
|
28487
28467
|
if (shouldSkipAnalysisForCachedCloudContext({
|
|
28488
28468
|
cloudContextAnalyzed: cloudCached,
|
|
28489
|
-
synthesisOnly,
|
|
28490
28469
|
forceNewContextAnalysis
|
|
28491
28470
|
})) {
|
|
28492
28471
|
if (!flags.json) {
|
|
28493
28472
|
console.error(
|
|
28494
|
-
`Skipping analysis: easyspecs.factory.cloudContextAnalyzed is true (cached at ${cloudCachedAt ?? "null"}). Re-run with --force-new-context-analysis to run the factory, or use upload context / upload republish without
|
|
28473
|
+
`Skipping analysis: easyspecs.factory.cloudContextAnalyzed is true (cached at ${cloudCachedAt ?? "null"}). Re-run with --force-new-context-analysis to run the factory, or use upload context / upload republish without running analysis.`
|
|
28495
28474
|
);
|
|
28496
28475
|
}
|
|
28497
28476
|
finish(ExitCode.ok, {
|
|
@@ -28503,65 +28482,9 @@ async function main() {
|
|
|
28503
28482
|
}
|
|
28504
28483
|
requireMinimalGluecharmLayoutAt(repoRoot);
|
|
28505
28484
|
requireOpenCode(merged, flags);
|
|
28506
|
-
const wantsUpload = positionals.includes("--upload");
|
|
28507
|
-
const uploadSession = wantsUpload ? readCliSession() : void 0;
|
|
28508
|
-
if (wantsUpload && !uploadSession) {
|
|
28509
|
-
finish(ExitCode.auth, {
|
|
28510
|
-
ok: false,
|
|
28511
|
-
error: "analysis --upload requires `easyspecs-cli auth login --email \u2026 --password \u2026` or `--ci` with easyspecs.auth.ciLogin in .easyspecs/config.json."
|
|
28512
|
-
});
|
|
28513
|
-
}
|
|
28514
|
-
const skipBackendSync = !wantsUpload;
|
|
28515
28485
|
const agentsDir = resolveOpenCodeAgentsDir(repoRoot, repoConfig);
|
|
28516
28486
|
assertAgentsDirExists(agentsDir);
|
|
28517
28487
|
const storage = createFileBackedWorkspaceState(repoRoot);
|
|
28518
|
-
const runBackendSyncImpl = wantsUpload && uploadSession ? async () => {
|
|
28519
|
-
const s = uploadSession;
|
|
28520
|
-
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
28521
|
-
const wsContextDir = path59.join(repoRoot, ".gluecharm", "context");
|
|
28522
|
-
const wtContextDir = snap?.adHocWorktreePath && fs60.existsSync(path59.join(snap.adHocWorktreePath, ".gluecharm", "context")) ? path59.join(snap.adHocWorktreePath, ".gluecharm", "context") : "";
|
|
28523
|
-
if (!wtContextDir) {
|
|
28524
|
-
return { ok: false, message: "No worktree context to upload." };
|
|
28525
|
-
}
|
|
28526
|
-
const appId = getEasyspecsProjectIdFromRepoConfig(repoConfig)?.trim();
|
|
28527
|
-
if (!appId) {
|
|
28528
|
-
return {
|
|
28529
|
-
ok: false,
|
|
28530
|
-
message: "Missing easyspecs.easyspecsProjectId in .easyspecs/config.json."
|
|
28531
|
-
};
|
|
28532
|
-
}
|
|
28533
|
-
let access = s.accessToken;
|
|
28534
|
-
const refresh = s.refreshToken;
|
|
28535
|
-
const requestJson = createAuthenticatedRequestJson({
|
|
28536
|
-
getApiBaseUrl: () => s.apiBaseUrl,
|
|
28537
|
-
getAccessToken: () => access,
|
|
28538
|
-
getRefreshToken: () => refresh,
|
|
28539
|
-
refreshSession: async () => {
|
|
28540
|
-
try {
|
|
28541
|
-
const r = await refreshTokenWithApi(s.apiBaseUrl, fetch, refresh);
|
|
28542
|
-
access = r.accessToken;
|
|
28543
|
-
writeCliSession({ ...s, accessToken: r.accessToken, refreshToken: r.refreshToken });
|
|
28544
|
-
return true;
|
|
28545
|
-
} catch {
|
|
28546
|
-
return false;
|
|
28547
|
-
}
|
|
28548
|
-
}
|
|
28549
|
-
});
|
|
28550
|
-
await validateApplicationExists(requestJson, appId);
|
|
28551
|
-
const paths = listContextFilesForUpload(wtContextDir);
|
|
28552
|
-
const up = await runUploadPipeline({
|
|
28553
|
-
requestJson,
|
|
28554
|
-
applicationId: appId,
|
|
28555
|
-
useBatch: true,
|
|
28556
|
-
contextDir: wtContextDir,
|
|
28557
|
-
filePaths: paths,
|
|
28558
|
-
log: (line) => logErr(flags, line)
|
|
28559
|
-
});
|
|
28560
|
-
if (up.failed.length > 0) {
|
|
28561
|
-
return { ok: false, message: `${String(up.failed.length)} file(s) failed to upload.` };
|
|
28562
|
-
}
|
|
28563
|
-
return { ok: true, message: `Uploaded ${String(up.succeeded.length)} file(s).` };
|
|
28564
|
-
} : void 0;
|
|
28565
28488
|
const ctrl = new AbortController();
|
|
28566
28489
|
const deps = buildFactoryDepsHeadless({
|
|
28567
28490
|
storageContext: storage,
|
|
@@ -28573,9 +28496,7 @@ async function main() {
|
|
|
28573
28496
|
}),
|
|
28574
28497
|
log: (line) => logErr(flags, line),
|
|
28575
28498
|
signal: ctrl.signal,
|
|
28576
|
-
|
|
28577
|
-
skipBackendSync,
|
|
28578
|
-
runBackendSyncImpl
|
|
28499
|
+
skipBackendSync: true
|
|
28579
28500
|
});
|
|
28580
28501
|
const res = await runGenerateContextFactory(deps);
|
|
28581
28502
|
const analysisEnvelope = {
|
|
@@ -28594,87 +28515,30 @@ async function main() {
|
|
|
28594
28515
|
if (pos[0] === "update" && pos[1] === "context") {
|
|
28595
28516
|
for (const a of pos.slice(2)) {
|
|
28596
28517
|
if (a === "--upload") {
|
|
28597
|
-
|
|
28518
|
+
finish(ExitCode.usage, {
|
|
28519
|
+
ok: false,
|
|
28520
|
+
error: "Removed flag: update context --upload. Run `easyspecs-cli upload context` or `upload republish` after update context completes."
|
|
28521
|
+
});
|
|
28598
28522
|
}
|
|
28599
28523
|
finish(ExitCode.usage, { ok: false, error: `unknown update context flag: ${a}` });
|
|
28600
28524
|
}
|
|
28601
28525
|
requireMinimalGluecharmLayoutAt(repoRoot);
|
|
28602
28526
|
requireOpenCode(merged, flags);
|
|
28603
|
-
const wantsUpload = positionals.includes("--upload");
|
|
28604
|
-
const uploadSession = wantsUpload ? readCliSession() : void 0;
|
|
28605
|
-
if (wantsUpload && !uploadSession) {
|
|
28606
|
-
finish(ExitCode.auth, {
|
|
28607
|
-
ok: false,
|
|
28608
|
-
error: "update context --upload requires `easyspecs-cli auth login --email \u2026 --password \u2026` or `--ci` with easyspecs.auth.ciLogin in .easyspecs/config.json."
|
|
28609
|
-
});
|
|
28610
|
-
}
|
|
28611
28527
|
const agentsDir = resolveOpenCodeAgentsDir(repoRoot, repoConfig);
|
|
28612
28528
|
assertAgentsDirExists(agentsDir);
|
|
28613
28529
|
const storage = createFileBackedWorkspaceState(repoRoot);
|
|
28614
28530
|
const ctrl = new AbortController();
|
|
28615
|
-
const uploadBatch = readEasyspecsMergedSetting(repoConfig.easyspecs, "easyspecs.pipelines.upload.useBatch") !== false;
|
|
28616
|
-
const runUploadFn = wantsUpload && uploadSession ? async (args) => {
|
|
28617
|
-
const s = uploadSession;
|
|
28618
|
-
const appId = getEasyspecsProjectIdFromRepoConfig(repoConfig)?.trim();
|
|
28619
|
-
if (!appId) {
|
|
28620
|
-
return { ok: false, message: "Missing easyspecs.easyspecsProjectId in .easyspecs/config.json." };
|
|
28621
|
-
}
|
|
28622
|
-
let access = s.accessToken;
|
|
28623
|
-
const refresh = s.refreshToken;
|
|
28624
|
-
const requestJson = createAuthenticatedRequestJson({
|
|
28625
|
-
getApiBaseUrl: () => s.apiBaseUrl,
|
|
28626
|
-
getAccessToken: () => access,
|
|
28627
|
-
getRefreshToken: () => refresh,
|
|
28628
|
-
refreshSession: async () => {
|
|
28629
|
-
try {
|
|
28630
|
-
const r = await refreshTokenWithApi(s.apiBaseUrl, fetch, refresh);
|
|
28631
|
-
access = r.accessToken;
|
|
28632
|
-
writeCliSession({ ...s, accessToken: r.accessToken, refreshToken: r.refreshToken });
|
|
28633
|
-
return true;
|
|
28634
|
-
} catch {
|
|
28635
|
-
return false;
|
|
28636
|
-
}
|
|
28637
|
-
}
|
|
28638
|
-
});
|
|
28639
|
-
try {
|
|
28640
|
-
await validateApplicationExists(requestJson, appId);
|
|
28641
|
-
} catch (e) {
|
|
28642
|
-
return { ok: false, message: toFetchErrorMessage(e).message };
|
|
28643
|
-
}
|
|
28644
|
-
const up = await runUploadPipeline({
|
|
28645
|
-
requestJson,
|
|
28646
|
-
applicationId: appId,
|
|
28647
|
-
useBatch: uploadBatch,
|
|
28648
|
-
contextDir: args.wtContextDir,
|
|
28649
|
-
filePaths: args.filePaths,
|
|
28650
|
-
log: (line) => logErr(flags, line)
|
|
28651
|
-
});
|
|
28652
|
-
if (up.failed.length > 0) {
|
|
28653
|
-
return {
|
|
28654
|
-
ok: false,
|
|
28655
|
-
message: `${String(up.failed.length)} file(s) failed to upload.`,
|
|
28656
|
-
uploadedCount: up.succeeded.length
|
|
28657
|
-
};
|
|
28658
|
-
}
|
|
28659
|
-
return {
|
|
28660
|
-
ok: true,
|
|
28661
|
-
uploadedCount: up.succeeded.length,
|
|
28662
|
-
message: `Uploaded ${String(up.succeeded.length)} file(s).`
|
|
28663
|
-
};
|
|
28664
|
-
} : void 0;
|
|
28665
28531
|
const ures = await runUpdateContextFactory({
|
|
28666
28532
|
repoRootAbs: repoRoot,
|
|
28667
28533
|
repoConfig,
|
|
28668
28534
|
merged,
|
|
28669
28535
|
agentsDirFs: agentsDir,
|
|
28670
28536
|
storage,
|
|
28671
|
-
wantsUpload,
|
|
28672
28537
|
signal: ctrl.signal,
|
|
28673
|
-
log: (line) => logErr(flags, line)
|
|
28674
|
-
runUploadFn
|
|
28538
|
+
log: (line) => logErr(flags, line)
|
|
28675
28539
|
});
|
|
28676
28540
|
const { exitOk, ...payload } = ures;
|
|
28677
|
-
const code = exitOk ? ExitCode.ok : ures.code === "MISSING_BASELINE" ? ExitCode.usage :
|
|
28541
|
+
const code = exitOk ? ExitCode.ok : ures.code === "MISSING_BASELINE" ? ExitCode.usage : ExitCode.validation;
|
|
28678
28542
|
finish(code, payload);
|
|
28679
28543
|
}
|
|
28680
28544
|
if (pos[0] === "download" && pos[1] === "context") {
|
|
@@ -28789,12 +28653,12 @@ async function main() {
|
|
|
28789
28653
|
if (pos[1] === "republish") {
|
|
28790
28654
|
const fromCfg = repoConfig.easyspecs?.upload?.contextDirectory?.trim();
|
|
28791
28655
|
const resolvedOverride = fromCfg && fromCfg.length > 0 ? path59.isAbsolute(fromCfg) ? path59.normalize(fromCfg) : path59.resolve(repoRoot, fromCfg) : "";
|
|
28792
|
-
if (resolvedOverride &&
|
|
28656
|
+
if (resolvedOverride && fs59.existsSync(path59.join(resolvedOverride, ".."))) {
|
|
28793
28657
|
ctxDir = resolvedOverride;
|
|
28794
28658
|
} else {
|
|
28795
28659
|
const storage = createFileBackedWorkspaceState(repoRoot);
|
|
28796
28660
|
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
28797
|
-
const wt = snap?.adHocWorktreePath &&
|
|
28661
|
+
const wt = snap?.adHocWorktreePath && fs59.existsSync(path59.join(snap.adHocWorktreePath, ".gluecharm", "context")) ? path59.join(snap.adHocWorktreePath, ".gluecharm", "context") : "";
|
|
28798
28662
|
if (!wt) {
|
|
28799
28663
|
finish(ExitCode.misconfiguration, {
|
|
28800
28664
|
ok: false,
|
|
@@ -28912,16 +28776,16 @@ async function main() {
|
|
|
28912
28776
|
}
|
|
28913
28777
|
if (pos[0] === "ace" && pos[1] === "clear") {
|
|
28914
28778
|
const learnings = path59.join(repoRoot, ".gluecharm", "context", "learnings");
|
|
28915
|
-
if (!
|
|
28779
|
+
if (!fs59.existsSync(learnings)) {
|
|
28916
28780
|
finish(ExitCode.ok, { ok: true, message: "nothing to clear" });
|
|
28917
28781
|
}
|
|
28918
|
-
|
|
28782
|
+
fs59.rmSync(learnings, { recursive: true, force: true });
|
|
28919
28783
|
finish(ExitCode.ok, { ok: true, message: `cleared ${learnings}` });
|
|
28920
28784
|
}
|
|
28921
28785
|
if (pos[0] === "ace" && pos[1] === "learn") {
|
|
28922
28786
|
requireOpenCode(merged, flags);
|
|
28923
28787
|
const { worktree } = parseWorktreeFlag(pos.slice(2));
|
|
28924
|
-
const root = worktree &&
|
|
28788
|
+
const root = worktree && fs59.existsSync(path59.join(worktree, ".opencode", "schemas", "ace")) ? worktree : repoRoot;
|
|
28925
28789
|
const contextDir2 = path59.join(root, ".gluecharm", "context");
|
|
28926
28790
|
const traces = listAceTraceFiles(contextDir2);
|
|
28927
28791
|
if (traces.length === 0) {
|
|
@@ -28946,7 +28810,7 @@ async function main() {
|
|
|
28946
28810
|
if (pos[0] === "ace" && pos[1] === "auto-learn") {
|
|
28947
28811
|
requireOpenCode(merged, flags);
|
|
28948
28812
|
const { worktree } = parseWorktreeFlag(pos.slice(2));
|
|
28949
|
-
const root = worktree &&
|
|
28813
|
+
const root = worktree && fs59.existsSync(path59.join(worktree, ".git")) ? worktree : repoRoot;
|
|
28950
28814
|
const contextDir2 = path59.join(root, ".gluecharm", "context");
|
|
28951
28815
|
const pending = listPendingAceTraceFiles(contextDir2, root);
|
|
28952
28816
|
if (pending.length === 0) {
|