@gluecharm-lab/easyspecs-cli 0.0.28 → 0.2.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/README.md +7 -7
- package/commands.md +13 -13
- package/dist/main.cjs +1181 -555
- package/dist/main.cjs.map +4 -4
- package/error-code.md +79 -81
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -959,8 +959,8 @@ 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
|
|
963
|
-
var
|
|
962
|
+
var path61 = require("node:path");
|
|
963
|
+
var fs64 = 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();
|
|
@@ -1892,11 +1892,11 @@ 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 =
|
|
1896
|
-
if (
|
|
1897
|
-
if (sourceExt.includes(
|
|
1895
|
+
const localBin = path61.resolve(baseDir, baseName);
|
|
1896
|
+
if (fs64.existsSync(localBin)) return localBin;
|
|
1897
|
+
if (sourceExt.includes(path61.extname(baseName))) return void 0;
|
|
1898
1898
|
const foundExt = sourceExt.find(
|
|
1899
|
-
(ext) =>
|
|
1899
|
+
(ext) => fs64.existsSync(`${localBin}${ext}`)
|
|
1900
1900
|
);
|
|
1901
1901
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1902
1902
|
return void 0;
|
|
@@ -1908,21 +1908,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1908
1908
|
if (this._scriptPath) {
|
|
1909
1909
|
let resolvedScriptPath;
|
|
1910
1910
|
try {
|
|
1911
|
-
resolvedScriptPath =
|
|
1911
|
+
resolvedScriptPath = fs64.realpathSync(this._scriptPath);
|
|
1912
1912
|
} catch (err) {
|
|
1913
1913
|
resolvedScriptPath = this._scriptPath;
|
|
1914
1914
|
}
|
|
1915
|
-
executableDir =
|
|
1916
|
-
|
|
1915
|
+
executableDir = path61.resolve(
|
|
1916
|
+
path61.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 = path61.basename(
|
|
1924
1924
|
this._scriptPath,
|
|
1925
|
-
|
|
1925
|
+
path61.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(path61.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 = path61.basename(filename, path61.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(path62) {
|
|
2791
|
+
if (path62 === void 0) return this._executableDir;
|
|
2792
|
+
this._executableDir = path62;
|
|
2793
2793
|
return this;
|
|
2794
2794
|
}
|
|
2795
2795
|
/**
|
|
@@ -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 = resolve23.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 resolve23(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(path61) {
|
|
6239
|
+
let input = path61;
|
|
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 [path61, query] = wsComponent.resourceName.split("?");
|
|
6439
|
+
wsComponent.path = path61 && path61 !== "/" ? path61 : void 0;
|
|
6440
6440
|
wsComponent.query = query;
|
|
6441
6441
|
wsComponent.resourceName = void 0;
|
|
6442
6442
|
}
|
|
@@ -6595,7 +6595,7 @@ var require_fast_uri = __commonJS({
|
|
|
6595
6595
|
}
|
|
6596
6596
|
return uri;
|
|
6597
6597
|
}
|
|
6598
|
-
function
|
|
6598
|
+
function resolve23(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;
|
|
@@ -6822,7 +6822,7 @@ var require_fast_uri = __commonJS({
|
|
|
6822
6822
|
var fastUri = {
|
|
6823
6823
|
SCHEMES,
|
|
6824
6824
|
normalize: normalize8,
|
|
6825
|
-
resolve:
|
|
6825
|
+
resolve: resolve23,
|
|
6826
6826
|
resolveComponent,
|
|
6827
6827
|
equal,
|
|
6828
6828
|
serialize,
|
|
@@ -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, fs64, 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, fs64[f]);
|
|
10631
10631
|
}
|
|
10632
10632
|
module2.exports = exports2 = formatsPlugin;
|
|
10633
10633
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -10636,21 +10636,65 @@ var require_dist = __commonJS({
|
|
|
10636
10636
|
});
|
|
10637
10637
|
|
|
10638
10638
|
// src/cli/main.ts
|
|
10639
|
-
var
|
|
10640
|
-
var
|
|
10639
|
+
var fs63 = __toESM(require("node:fs"));
|
|
10640
|
+
var path60 = __toESM(require("node:path"));
|
|
10641
10641
|
|
|
10642
10642
|
// src/cli/exitCodes.ts
|
|
10643
|
+
var OsExit = {
|
|
10644
|
+
/** Unknown / unclassified factory failure */
|
|
10645
|
+
factoryUnknown: 49,
|
|
10646
|
+
/** Rollup: multiple failed generate_context phases with distinct OS codes in one run */
|
|
10647
|
+
factoryMultiPhaseRollup: 59,
|
|
10648
|
+
createAnalysisWorktree: 50,
|
|
10649
|
+
materializeOpenCodeAgents: 51,
|
|
10650
|
+
synthesisConvergence: 52,
|
|
10651
|
+
referenceCoverage: 53,
|
|
10652
|
+
zeroReferenceRemediation: 54,
|
|
10653
|
+
referenceCoverageExecutionReport: 55,
|
|
10654
|
+
linkMappingPipeline: 56,
|
|
10655
|
+
assembleApplicationContextIndex: 57,
|
|
10656
|
+
backendContextSync: 58,
|
|
10657
|
+
driftEmptyBundle: 60,
|
|
10658
|
+
driftUnresolvedReferenceRoot: 61,
|
|
10659
|
+
driftManifestFailed: 62,
|
|
10660
|
+
driftReportWriteFailed: 63,
|
|
10661
|
+
driftIndexPatchFailed: 64,
|
|
10662
|
+
diagnoseReferenceCoveragePipeline: 70,
|
|
10663
|
+
diagnoseReferenceCoverageThreshold: 71,
|
|
10664
|
+
diagnoseCoordinationDuplicatesPolicy: 72,
|
|
10665
|
+
diagnoseCoordinationDuplicatesEngine: 73,
|
|
10666
|
+
diagnoseCoverageReport: 74,
|
|
10667
|
+
diagnoseZeroReferenceReadCoverage: 75,
|
|
10668
|
+
diagnoseZeroReferenceLinkMapping: 76,
|
|
10669
|
+
diagnoseZeroReferencePool: 77,
|
|
10670
|
+
contextLinkGraph: 78,
|
|
10671
|
+
resumeSynthesisIndex: 79,
|
|
10672
|
+
runSynthesisPipeline: 80,
|
|
10673
|
+
aceLearnTrace: 81,
|
|
10674
|
+
aceAutoLearnPool: 82,
|
|
10675
|
+
updateContextFactory: 83,
|
|
10676
|
+
/** SRS-72 readiness gate (a): OpenCode not installed / not callable. */
|
|
10677
|
+
readinessOpenCodeNotInstalled: 84,
|
|
10678
|
+
/** SRS-72 readiness gate (b): credentials not ready. */
|
|
10679
|
+
readinessOpenCodeCredentials: 85,
|
|
10680
|
+
/** SRS-72 readiness gate (c): default model not configured. */
|
|
10681
|
+
readinessOpenCodeModel: 86,
|
|
10682
|
+
/** SRS-72 readiness gate (d): mandatory OpenCode config file missing. */
|
|
10683
|
+
readinessOpenCodeMandatoryConfig: 87
|
|
10684
|
+
};
|
|
10643
10685
|
var ExitCode = {
|
|
10644
10686
|
ok: 0,
|
|
10645
10687
|
usage: 2,
|
|
10646
10688
|
misconfiguration: 3,
|
|
10647
10689
|
opencode: 4,
|
|
10648
|
-
validation: 5,
|
|
10649
10690
|
auth: 6,
|
|
10650
10691
|
upload: 7,
|
|
10651
10692
|
cancelled: 8,
|
|
10652
10693
|
internal: 99
|
|
10653
10694
|
};
|
|
10695
|
+
function failureExitIdFromParts(exitCode, minor) {
|
|
10696
|
+
return `${String(exitCode)}.${String(minor)}`;
|
|
10697
|
+
}
|
|
10654
10698
|
function describeExitCode(code) {
|
|
10655
10699
|
switch (code) {
|
|
10656
10700
|
case ExitCode.ok:
|
|
@@ -10661,8 +10705,6 @@ function describeExitCode(code) {
|
|
|
10661
10705
|
return "Configuration or repo layout problem \u2014 fix `.easyspecs/config.json`, paths, or prerequisites, then retry.";
|
|
10662
10706
|
case ExitCode.opencode:
|
|
10663
10707
|
return "OpenCode (agent runner) failed \u2014 check `opencode` install, credentials, and stderr from the tool run.";
|
|
10664
|
-
case ExitCode.validation:
|
|
10665
|
-
return "Validation or factory pipeline did not succeed \u2014 see `error` above and logs for the failing phase (synthesis, coverage, remediation, index, etc.).";
|
|
10666
10708
|
case ExitCode.auth:
|
|
10667
10709
|
return "Authentication failed or session missing \u2014 run `easyspecs-cli auth login` or fix CI credentials in config.";
|
|
10668
10710
|
case ExitCode.upload:
|
|
@@ -10671,6 +10713,74 @@ function describeExitCode(code) {
|
|
|
10671
10713
|
return "Operation was cancelled (abort/stop).";
|
|
10672
10714
|
case ExitCode.internal:
|
|
10673
10715
|
return "Unexpected internal CLI error \u2014 retry; if it persists, report with full stderr and `--verbose` output.";
|
|
10716
|
+
case OsExit.factoryUnknown:
|
|
10717
|
+
return "Factory pipeline failed (phase could not be classified). See `error` and logs; retry with --verbose.";
|
|
10718
|
+
case OsExit.factoryMultiPhaseRollup:
|
|
10719
|
+
return "Multiple factory pipeline phases failed in one run. Inspect `factoryFailures` for each phase.";
|
|
10720
|
+
case OsExit.createAnalysisWorktree:
|
|
10721
|
+
return "Analysis Git worktree could not be prepared. Check disk space, permissions, and a valid Git checkout.";
|
|
10722
|
+
case OsExit.materializeOpenCodeAgents:
|
|
10723
|
+
return "OpenCode agent files could not be installed into the analysis worktree.";
|
|
10724
|
+
case OsExit.synthesisConvergence:
|
|
10725
|
+
return "Context synthesis did not finish successfully. Inspect OpenCode logs and workstation output.";
|
|
10726
|
+
case OsExit.referenceCoverage:
|
|
10727
|
+
return "Reference coverage could not be computed or written. Check coverage JSON and schema.";
|
|
10728
|
+
case OsExit.zeroReferenceRemediation:
|
|
10729
|
+
return "Zero-reference remediation did not complete. Inspect remediation logs and outputs.";
|
|
10730
|
+
case OsExit.referenceCoverageExecutionReport:
|
|
10731
|
+
return "Coverage execution report could not be generated. Ensure coverage inputs exist.";
|
|
10732
|
+
case OsExit.linkMappingPipeline:
|
|
10733
|
+
return "Context link graph could not be updated. Check coordination JSON and markdown.";
|
|
10734
|
+
case OsExit.assembleApplicationContextIndex:
|
|
10735
|
+
return "Application context index could not be assembled or failed schema validation.";
|
|
10736
|
+
case OsExit.backendContextSync:
|
|
10737
|
+
return "Upload or cloud sync after analysis did not succeed.";
|
|
10738
|
+
case OsExit.driftEmptyBundle:
|
|
10739
|
+
return "Context drift: reference bundle was empty or could not be read.";
|
|
10740
|
+
case OsExit.driftUnresolvedReferenceRoot:
|
|
10741
|
+
return "Context drift: reference root document could not be resolved.";
|
|
10742
|
+
case OsExit.driftManifestFailed:
|
|
10743
|
+
return "Context drift: comparison manifest could not be built.";
|
|
10744
|
+
case OsExit.driftReportWriteFailed:
|
|
10745
|
+
return "Context drift: report markdown could not be written.";
|
|
10746
|
+
case OsExit.driftIndexPatchFailed:
|
|
10747
|
+
return "Context drift: reference index could not be updated with the drift link.";
|
|
10748
|
+
case OsExit.diagnoseReferenceCoveragePipeline:
|
|
10749
|
+
return "diagnose reference-coverage: pipeline or write failed.";
|
|
10750
|
+
case OsExit.diagnoseReferenceCoverageThreshold:
|
|
10751
|
+
return "diagnose reference-coverage: percentNonReferenced exceeded the configured threshold.";
|
|
10752
|
+
case OsExit.diagnoseCoordinationDuplicatesPolicy:
|
|
10753
|
+
return "diagnose coordination-duplicates: strict mode reported duplicates or orphan markdown.";
|
|
10754
|
+
case OsExit.diagnoseCoordinationDuplicatesEngine:
|
|
10755
|
+
return "diagnose coordination-duplicates: scan or I/O failed.";
|
|
10756
|
+
case OsExit.diagnoseCoverageReport:
|
|
10757
|
+
return "diagnose coverage-report: report generation failed.";
|
|
10758
|
+
case OsExit.diagnoseZeroReferenceReadCoverage:
|
|
10759
|
+
return "diagnose zero-reference: could not read coverage / zero-reference inputs.";
|
|
10760
|
+
case OsExit.diagnoseZeroReferenceLinkMapping:
|
|
10761
|
+
return "diagnose zero-reference: link mapping after remediation failed.";
|
|
10762
|
+
case OsExit.diagnoseZeroReferencePool:
|
|
10763
|
+
return "diagnose zero-reference: remediation pool reported failures or cancellation.";
|
|
10764
|
+
case OsExit.contextLinkGraph:
|
|
10765
|
+
return "context link-graph: link mapping pipeline failed.";
|
|
10766
|
+
case OsExit.resumeSynthesisIndex:
|
|
10767
|
+
return "run synthesis resume-*: index assembly after remediation failed.";
|
|
10768
|
+
case OsExit.runSynthesisPipeline:
|
|
10769
|
+
return "run synthesis: pipeline did not complete successfully.";
|
|
10770
|
+
case OsExit.aceLearnTrace:
|
|
10771
|
+
return "ace learn: processing a trace failed.";
|
|
10772
|
+
case OsExit.aceAutoLearnPool:
|
|
10773
|
+
return "ace auto-learn: one or more learn runs failed.";
|
|
10774
|
+
case OsExit.updateContextFactory:
|
|
10775
|
+
return "update context: factory run did not succeed.";
|
|
10776
|
+
case OsExit.readinessOpenCodeNotInstalled:
|
|
10777
|
+
return "OpenCode CLI is not installed or not callable on PATH \u2014 install `opencode` or set `easyspecs.openCode.executable`.";
|
|
10778
|
+
case OsExit.readinessOpenCodeCredentials:
|
|
10779
|
+
return "OpenCode credentials not ready for factory run.";
|
|
10780
|
+
case OsExit.readinessOpenCodeModel:
|
|
10781
|
+
return "OpenCode default model is not configured \u2014 add a model in repo `opencode.json` or `easyspecs.openCodeRuntime.providers`.";
|
|
10782
|
+
case OsExit.readinessOpenCodeMandatoryConfig:
|
|
10783
|
+
return "Mandatory OpenCode project config is missing \u2014 create `opencode.json` at the repository / analysis root.";
|
|
10674
10784
|
default:
|
|
10675
10785
|
return `Non-zero exit (${String(code)}) \u2014 see stderr and any JSON \`error\` field for detail.`;
|
|
10676
10786
|
}
|
|
@@ -10700,6 +10810,12 @@ var {
|
|
|
10700
10810
|
} = import_index.default;
|
|
10701
10811
|
|
|
10702
10812
|
// src/cli/cliProgram.ts
|
|
10813
|
+
function addNoWorktreeCliOption(cmd) {
|
|
10814
|
+
return cmd.option(
|
|
10815
|
+
"--in-place",
|
|
10816
|
+
"Use repository root as the analysis checkout (no detached git worktree). Synonym: --no-worktree (see main argv rewrite)."
|
|
10817
|
+
).option("--noworktree", "Alias for --in-place (SRS-71)");
|
|
10818
|
+
}
|
|
10703
10819
|
function createEasyspecsCliProgram() {
|
|
10704
10820
|
const program2 = new Command();
|
|
10705
10821
|
program2.name("easyspecs-cli").allowExcessArguments(false).enablePositionalOptions();
|
|
@@ -10717,7 +10833,9 @@ function createEasyspecsCliProgram() {
|
|
|
10717
10833
|
const runSynthesis = run.command("synthesis").description("Run synthesis pipeline");
|
|
10718
10834
|
runSynthesis.command("resume-missing").description("Resume remediation pool for missing artefacts").option("--worktree <path>", "Path to an analysis checkout");
|
|
10719
10835
|
runSynthesis.command("resume-synthesis").description("Resume synthesis pipeline").option("--worktree <path>", "Path to an analysis checkout");
|
|
10720
|
-
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())
|
|
10836
|
+
const analysisCmd = 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());
|
|
10837
|
+
addNoWorktreeCliOption(analysisCmd);
|
|
10838
|
+
analysisCmd.allowUnknownOption(true);
|
|
10721
10839
|
const diagnose = program2.command("diagnose").description("Deterministic diagnostics");
|
|
10722
10840
|
const addRootAndWorktree = (c) => c.option("--root <root>", "workspace|worktree").option("--worktree <path>", "Path to an analysis checkout");
|
|
10723
10841
|
addRootAndWorktree(diagnose.command("reference-coverage").description("Compute reference coverage"));
|
|
@@ -10727,11 +10845,12 @@ function createEasyspecsCliProgram() {
|
|
|
10727
10845
|
diagnose.command("zero-reference").description("Run zero-reference remediation").option("--worktree <path>", "Path to an analysis checkout");
|
|
10728
10846
|
const context = program2.command("context").description("Context operations");
|
|
10729
10847
|
addRootAndWorktree(context.command("link-graph").description("Validate EasySpecs navigation links in context markdown"));
|
|
10730
|
-
|
|
10731
|
-
|
|
10732
|
-
);
|
|
10848
|
+
const driftCmd = 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");
|
|
10849
|
+
addNoWorktreeCliOption(driftCmd);
|
|
10850
|
+
addRootAndWorktree(driftCmd);
|
|
10733
10851
|
const update = program2.command("update").description("Incremental context refresh");
|
|
10734
|
-
update.command("context").description("Update context since last baseline (git delta, optional remediation, promote)").allowUnknownOption(true);
|
|
10852
|
+
const updateContextCmd = update.command("context").description("Update context since last baseline (git delta, optional remediation, promote)").allowUnknownOption(true);
|
|
10853
|
+
addNoWorktreeCliOption(updateContextCmd);
|
|
10735
10854
|
const download = program2.command("download").description("Download resources");
|
|
10736
10855
|
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");
|
|
10737
10856
|
const upload = program2.command("upload").description("Upload resources");
|
|
@@ -12568,7 +12687,7 @@ function stringifyForSrs13Debug(value) {
|
|
|
12568
12687
|
return truncateForSrs13DebugLog(String(value));
|
|
12569
12688
|
}
|
|
12570
12689
|
}
|
|
12571
|
-
function logSrs13HttpDebug(log,
|
|
12690
|
+
function logSrs13HttpDebug(log, path61, method, requestBody, error) {
|
|
12572
12691
|
if (!log) {
|
|
12573
12692
|
return;
|
|
12574
12693
|
}
|
|
@@ -12578,7 +12697,7 @@ function logSrs13HttpDebug(log, path60, method, requestBody, error) {
|
|
|
12578
12697
|
} catch {
|
|
12579
12698
|
bodyBytes = 0;
|
|
12580
12699
|
}
|
|
12581
|
-
log(`[pipeline:upload] debug ${method} ${
|
|
12700
|
+
log(`[pipeline:upload] debug ${method} ${path61} \u2014 request body ~${bodyBytes} bytes (JSON below):`);
|
|
12582
12701
|
log(stringifyForSrs13Debug(requestBody));
|
|
12583
12702
|
const raw = httpApiResponseBody(error);
|
|
12584
12703
|
const status = error && typeof error === "object" && "status" in error ? Number(error.status) : void 0;
|
|
@@ -14275,9 +14394,9 @@ function parsePsRssDarwinKilobytes(stdout) {
|
|
|
14275
14394
|
return n;
|
|
14276
14395
|
}
|
|
14277
14396
|
function readLinuxPidRssBytes(pid) {
|
|
14278
|
-
const
|
|
14397
|
+
const path61 = `/proc/${pid}/status`;
|
|
14279
14398
|
try {
|
|
14280
|
-
const content = fs18.readFileSync(
|
|
14399
|
+
const content = fs18.readFileSync(path61, "utf8");
|
|
14281
14400
|
const kb = parseVmRssKilobytesFromProcStatus(content);
|
|
14282
14401
|
if (kb === null) {
|
|
14283
14402
|
return { kind: "unknown", reason: "VmRSS_missing" };
|
|
@@ -14465,9 +14584,9 @@ function runOpenCodeAgent(cwd, args, options) {
|
|
|
14465
14584
|
log?.(`${procTag} command: ${formatCliCommandForLog(cmd, args)}`);
|
|
14466
14585
|
log?.(`${procTag} cwd: ${JSON.stringify(cwd)}`);
|
|
14467
14586
|
log?.(`${procTag} argv: ${JSON.stringify(args)}`);
|
|
14468
|
-
return new Promise((
|
|
14587
|
+
return new Promise((resolve23) => {
|
|
14469
14588
|
if (sig?.aborted) {
|
|
14470
|
-
|
|
14589
|
+
resolve23({ ok: false, message: "Stopped by user.", cancelled: true });
|
|
14471
14590
|
return;
|
|
14472
14591
|
}
|
|
14473
14592
|
const spawnEnv = options?.childEnv && Object.keys(options.childEnv).length > 0 ? { ...process.env, ...options.childEnv } : process.env;
|
|
@@ -14562,7 +14681,7 @@ ${truncateForDiag(outBody, DIAG_STDOUT_MAX)}`);
|
|
|
14562
14681
|
if (diag) {
|
|
14563
14682
|
finishDiag(diag.label, diag.code, diag.dumpStreams);
|
|
14564
14683
|
}
|
|
14565
|
-
|
|
14684
|
+
resolve23(result);
|
|
14566
14685
|
};
|
|
14567
14686
|
let onAbort;
|
|
14568
14687
|
const clearAbortHandler = () => {
|
|
@@ -18997,6 +19116,23 @@ function readHeadBranchShort(repoRoot) {
|
|
|
18997
19116
|
const b = (r.stdout ?? "").trim();
|
|
18998
19117
|
return b.length > 0 ? b : void 0;
|
|
18999
19118
|
}
|
|
19119
|
+
function createInPlaceWorktreeHandle(repositoryRootAbs) {
|
|
19120
|
+
const root = path27.resolve(repositoryRootAbs);
|
|
19121
|
+
return {
|
|
19122
|
+
path: root,
|
|
19123
|
+
repoRoot: root,
|
|
19124
|
+
remove() {
|
|
19125
|
+
}
|
|
19126
|
+
};
|
|
19127
|
+
}
|
|
19128
|
+
function resolveAnalysisCheckoutHandle(worktreePath, repositoryRoot) {
|
|
19129
|
+
const wt = path27.resolve(worktreePath);
|
|
19130
|
+
const repo = path27.resolve(repositoryRoot);
|
|
19131
|
+
if (wt === repo) {
|
|
19132
|
+
return createInPlaceWorktreeHandle(repo);
|
|
19133
|
+
}
|
|
19134
|
+
return attachWorktreeHandle(worktreePath, repositoryRoot);
|
|
19135
|
+
}
|
|
19000
19136
|
function attachWorktreeHandle(worktreePath, repositoryRoot) {
|
|
19001
19137
|
const wt = path27.resolve(worktreePath);
|
|
19002
19138
|
const repo = path27.resolve(repositoryRoot);
|
|
@@ -21269,8 +21405,8 @@ async function drainWorkstationPool(p) {
|
|
|
21269
21405
|
const artefactRunId = readArtefactRunSnapshot(storageContext)?.runId ?? "unknown-run";
|
|
21270
21406
|
let active = 0;
|
|
21271
21407
|
let wake;
|
|
21272
|
-
const waitTurn = () => new Promise((
|
|
21273
|
-
wake =
|
|
21408
|
+
const waitTurn = () => new Promise((resolve23) => {
|
|
21409
|
+
wake = resolve23;
|
|
21274
21410
|
});
|
|
21275
21411
|
const persist = async () => {
|
|
21276
21412
|
const items = {};
|
|
@@ -21439,6 +21575,26 @@ async function prepareSynthesisWorktree(storageContext, repoRoot, log, options)
|
|
|
21439
21575
|
if (options?.clearPriorArtefactRun !== false) {
|
|
21440
21576
|
await clearArtefactRun(storageContext);
|
|
21441
21577
|
}
|
|
21578
|
+
if (options?.inPlace === true) {
|
|
21579
|
+
const repoResolved = path32.resolve(repoRoot);
|
|
21580
|
+
log(`[worktree] in-place analysis \u2014 using repository root ${repoResolved}`);
|
|
21581
|
+
const handle2 = createInPlaceWorktreeHandle(repoResolved);
|
|
21582
|
+
const sourceBranchAtCreation = readHeadBranchShort(repoResolved);
|
|
21583
|
+
let finalized2 = false;
|
|
21584
|
+
const finalize2 = () => {
|
|
21585
|
+
if (finalized2) {
|
|
21586
|
+
return;
|
|
21587
|
+
}
|
|
21588
|
+
finalized2 = true;
|
|
21589
|
+
log(`[worktree] in-place mode \u2014 no teardown`);
|
|
21590
|
+
};
|
|
21591
|
+
return {
|
|
21592
|
+
ok: true,
|
|
21593
|
+
handle: handle2,
|
|
21594
|
+
finalize: finalize2,
|
|
21595
|
+
...sourceBranchAtCreation ? { sourceBranchAtCreation } : {}
|
|
21596
|
+
};
|
|
21597
|
+
}
|
|
21442
21598
|
const wt = createAnalysisWorktree(repoRoot, { log });
|
|
21443
21599
|
if (!wt.ok) {
|
|
21444
21600
|
return { ok: false, error: wt.error };
|
|
@@ -21597,6 +21753,7 @@ function promoteContextDirectoryToWorkspaceFs(sourceContextDir, workspaceRootFs)
|
|
|
21597
21753
|
|
|
21598
21754
|
// src/shared/factoryPipelineExitConditions.ts
|
|
21599
21755
|
var FACTORY_PIPELINE_EXIT_CONDITIONS = {
|
|
21756
|
+
diagnose_readiness: "OpenCode CLI, credentials, default model, and mandatory project `opencode.json` are ready before worktree / agent work (SRS-72).",
|
|
21600
21757
|
create_analysis_worktree: "Git analysis checkout exists under the configured temp parent (SRS-8); ready for agent materialization.",
|
|
21601
21758
|
materialize_opencode_agents: "Bundled OpenCode agent definitions are copied into the analysis worktree (`.opencode/` tree).",
|
|
21602
21759
|
synthesis_convergence: "Missing artefact count is 0. May run again after remediation (R5) if a refreshed check finds new expected outputs.",
|
|
@@ -21608,13 +21765,225 @@ var FACTORY_PIPELINE_EXIT_CONDITIONS = {
|
|
|
21608
21765
|
backend_context_sync: "Context upload finished with no failures (quiet SRS-13 path; or cancel)."
|
|
21609
21766
|
};
|
|
21610
21767
|
|
|
21768
|
+
// src/readiness/factoryReadiness.ts
|
|
21769
|
+
var fs39 = __toESM(require("node:fs"));
|
|
21770
|
+
var os6 = __toESM(require("node:os"));
|
|
21771
|
+
var path34 = __toESM(require("node:path"));
|
|
21772
|
+
var MANDATORY_OPEN_CODE_CONFIG_REL_PATHS = ["opencode.json"];
|
|
21773
|
+
var READINESS_OPENCODE_NOT_INSTALLED = "READINESS_OPENCODE_NOT_INSTALLED";
|
|
21774
|
+
var READINESS_OPENCODE_CREDENTIALS = "READINESS_OPENCODE_CREDENTIALS";
|
|
21775
|
+
var READINESS_OPENCODE_MODEL = "READINESS_OPENCODE_MODEL";
|
|
21776
|
+
var READINESS_OPENCODE_MANDATORY_CONFIG = "READINESS_OPENCODE_MANDATORY_CONFIG";
|
|
21777
|
+
function userOpenCodeConfigPath() {
|
|
21778
|
+
if (process.platform === "win32") {
|
|
21779
|
+
const base = process.env.APPDATA || path34.join(os6.homedir(), "AppData", "Roaming");
|
|
21780
|
+
return path34.join(base, "opencode", "config.json");
|
|
21781
|
+
}
|
|
21782
|
+
const xdg = process.env.XDG_CONFIG_HOME?.trim();
|
|
21783
|
+
const cfgRoot = xdg && xdg.length > 0 ? xdg : path34.join(os6.homedir(), ".config");
|
|
21784
|
+
return path34.join(cfgRoot, "opencode", "config.json");
|
|
21785
|
+
}
|
|
21786
|
+
function buildOpenCodeConfigInventory(analysisRootAbs) {
|
|
21787
|
+
const root = path34.resolve(analysisRootAbs);
|
|
21788
|
+
const list = [
|
|
21789
|
+
{ path: path34.join(root, "opencode.json"), exists: false },
|
|
21790
|
+
{ path: path34.join(root, ".opencode", "config.json"), exists: false },
|
|
21791
|
+
{ path: userOpenCodeConfigPath(), exists: false }
|
|
21792
|
+
];
|
|
21793
|
+
return list.map((e) => ({ ...e, exists: fs39.existsSync(e.path) }));
|
|
21794
|
+
}
|
|
21795
|
+
function defaultModelFromEasyspecsConfig(cfg) {
|
|
21796
|
+
const providers = cfg.easyspecs?.openCodeRuntime?.providers;
|
|
21797
|
+
if (!providers || typeof providers !== "object") {
|
|
21798
|
+
return void 0;
|
|
21799
|
+
}
|
|
21800
|
+
for (const rec of Object.values(providers)) {
|
|
21801
|
+
const dm = rec?.defaultModel?.trim();
|
|
21802
|
+
if (dm) {
|
|
21803
|
+
return dm;
|
|
21804
|
+
}
|
|
21805
|
+
}
|
|
21806
|
+
return void 0;
|
|
21807
|
+
}
|
|
21808
|
+
function pickString(v) {
|
|
21809
|
+
return typeof v === "string" && v.trim().length > 0 ? v.trim() : void 0;
|
|
21810
|
+
}
|
|
21811
|
+
function extractModelFromOpenCodeJson(data) {
|
|
21812
|
+
if (!data || typeof data !== "object") {
|
|
21813
|
+
return void 0;
|
|
21814
|
+
}
|
|
21815
|
+
const o = data;
|
|
21816
|
+
const direct = pickString(o.model) ?? pickString(o.defaultModel);
|
|
21817
|
+
if (direct) {
|
|
21818
|
+
return direct;
|
|
21819
|
+
}
|
|
21820
|
+
const models = o.models;
|
|
21821
|
+
if (models && typeof models === "object") {
|
|
21822
|
+
const m = models;
|
|
21823
|
+
const def = pickString(m.default) ?? pickString(m.defaultModel);
|
|
21824
|
+
if (def) {
|
|
21825
|
+
return def;
|
|
21826
|
+
}
|
|
21827
|
+
}
|
|
21828
|
+
const agent = o.agent;
|
|
21829
|
+
if (agent && typeof agent === "object") {
|
|
21830
|
+
const a = agent;
|
|
21831
|
+
const am = pickString(a.model) ?? pickString(a.defaultModel);
|
|
21832
|
+
if (am) {
|
|
21833
|
+
return am;
|
|
21834
|
+
}
|
|
21835
|
+
}
|
|
21836
|
+
return void 0;
|
|
21837
|
+
}
|
|
21838
|
+
function sanitizeModelSummary(raw) {
|
|
21839
|
+
const t = raw.trim();
|
|
21840
|
+
if (!t) {
|
|
21841
|
+
return "(not configured)";
|
|
21842
|
+
}
|
|
21843
|
+
if (t.length > 160) {
|
|
21844
|
+
return `${t.slice(0, 157)}\u2026`;
|
|
21845
|
+
}
|
|
21846
|
+
const lower = t.toLowerCase();
|
|
21847
|
+
if (lower.includes("bearer ") || lower.includes("authorization:") || lower.startsWith("sk-")) {
|
|
21848
|
+
return "(redacted)";
|
|
21849
|
+
}
|
|
21850
|
+
return t;
|
|
21851
|
+
}
|
|
21852
|
+
function resolveModelFromContext(ctx) {
|
|
21853
|
+
const fromCfg = defaultModelFromEasyspecsConfig(ctx.repoConfig);
|
|
21854
|
+
if (fromCfg) {
|
|
21855
|
+
return { configured: true, summary: sanitizeModelSummary(fromCfg) };
|
|
21856
|
+
}
|
|
21857
|
+
const p = path34.join(path34.resolve(ctx.analysisRootAbs), "opencode.json");
|
|
21858
|
+
try {
|
|
21859
|
+
const txt = fs39.readFileSync(p, "utf-8");
|
|
21860
|
+
const data = JSON.parse(txt);
|
|
21861
|
+
const m = extractModelFromOpenCodeJson(data);
|
|
21862
|
+
if (m) {
|
|
21863
|
+
return { configured: true, summary: sanitizeModelSummary(m) };
|
|
21864
|
+
}
|
|
21865
|
+
} catch {
|
|
21866
|
+
}
|
|
21867
|
+
return { configured: false, summary: "(not configured)" };
|
|
21868
|
+
}
|
|
21869
|
+
function buildReadinessProbeFacts(ctx) {
|
|
21870
|
+
const oc = ctx.__testOnlyOpenCodeReadiness?.() ?? getOpenCodeReadiness({
|
|
21871
|
+
executable: ctx.openCodeExecutable,
|
|
21872
|
+
skipCredentialsCheck: ctx.openCodeSkipCredentialsCheck,
|
|
21873
|
+
providerEnvFromConfig: ctx.providerEnvFromConfig
|
|
21874
|
+
});
|
|
21875
|
+
const openCodeConfigFiles = buildOpenCodeConfigInventory(ctx.analysisRootAbs);
|
|
21876
|
+
const mandatoryOk = MANDATORY_OPEN_CODE_CONFIG_REL_PATHS.every((rel) => {
|
|
21877
|
+
const abs = path34.join(path34.resolve(ctx.analysisRootAbs), rel);
|
|
21878
|
+
return fs39.existsSync(abs);
|
|
21879
|
+
});
|
|
21880
|
+
const model = resolveModelFromContext(ctx);
|
|
21881
|
+
const agentsDir = resolveOpenCodeAgentsDir(ctx.repoRootAbs, ctx.repoConfig);
|
|
21882
|
+
return {
|
|
21883
|
+
installed: oc.installed,
|
|
21884
|
+
credentialsReady: oc.credentialsReady,
|
|
21885
|
+
skipCredentialsCheck: ctx.openCodeSkipCredentialsCheck === true,
|
|
21886
|
+
modelConfigured: model.configured,
|
|
21887
|
+
modelSummary: model.summary,
|
|
21888
|
+
mandatoryConfigPathsOk: mandatoryOk,
|
|
21889
|
+
openCodeConfigFiles,
|
|
21890
|
+
agentsDir,
|
|
21891
|
+
agentsDirExists: fs39.existsSync(agentsDir)
|
|
21892
|
+
};
|
|
21893
|
+
}
|
|
21894
|
+
function buildReadinessLineBlock(facts, ctx) {
|
|
21895
|
+
const apiDisp = ctx.apiBaseUrl.trim().length > 0 ? ctx.apiBaseUrl : "(empty \u2014 stub auth only)";
|
|
21896
|
+
const lines = [
|
|
21897
|
+
`cliVersion=${ctx.cliVersion}`,
|
|
21898
|
+
`repoRoot=${ctx.repoRootAbs}`,
|
|
21899
|
+
`apiBaseUrl=${apiDisp}`,
|
|
21900
|
+
`opencode installed=${String(facts.installed)} credentialsReady=${String(facts.credentialsReady)}`,
|
|
21901
|
+
`opencode modelConfigured=${String(facts.modelConfigured)} modelSummary=${facts.modelSummary}`
|
|
21902
|
+
];
|
|
21903
|
+
for (const e of facts.openCodeConfigFiles) {
|
|
21904
|
+
lines.push(`opencodeConfigFile ${e.path} exists=${String(e.exists)}`);
|
|
21905
|
+
}
|
|
21906
|
+
lines.push(`agentsDir=${facts.agentsDir} exists=${String(facts.agentsDirExists)}`);
|
|
21907
|
+
return lines;
|
|
21908
|
+
}
|
|
21909
|
+
function evaluateReadinessGates(facts) {
|
|
21910
|
+
if (!facts.installed) {
|
|
21911
|
+
return {
|
|
21912
|
+
ok: false,
|
|
21913
|
+
gate: "a",
|
|
21914
|
+
exitCode: OsExit.readinessOpenCodeNotInstalled,
|
|
21915
|
+
readinessReasonCode: READINESS_OPENCODE_NOT_INSTALLED
|
|
21916
|
+
};
|
|
21917
|
+
}
|
|
21918
|
+
if (!facts.credentialsReady && !facts.skipCredentialsCheck) {
|
|
21919
|
+
return {
|
|
21920
|
+
ok: false,
|
|
21921
|
+
gate: "b",
|
|
21922
|
+
exitCode: OsExit.readinessOpenCodeCredentials,
|
|
21923
|
+
readinessReasonCode: READINESS_OPENCODE_CREDENTIALS
|
|
21924
|
+
};
|
|
21925
|
+
}
|
|
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
|
+
return { ok: true };
|
|
21943
|
+
}
|
|
21944
|
+
function buildReadinessJsonFields(facts) {
|
|
21945
|
+
return {
|
|
21946
|
+
modelConfigured: facts.modelConfigured,
|
|
21947
|
+
credentialsReady: facts.credentialsReady,
|
|
21948
|
+
openCodeConfigFiles: facts.openCodeConfigFiles,
|
|
21949
|
+
agentsDir: facts.agentsDir,
|
|
21950
|
+
agentsDirExists: facts.agentsDirExists
|
|
21951
|
+
};
|
|
21952
|
+
}
|
|
21953
|
+
function emitCliFactoryReadinessPreflight(log, bannerPrefix, ctx) {
|
|
21954
|
+
const facts = buildReadinessProbeFacts(ctx);
|
|
21955
|
+
const lines = buildReadinessLineBlock(facts, ctx);
|
|
21956
|
+
log(`${bannerPrefix} \u2014 ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
21957
|
+
for (const ln of lines) {
|
|
21958
|
+
log(ln);
|
|
21959
|
+
}
|
|
21960
|
+
const gateRes = evaluateReadinessGates(facts);
|
|
21961
|
+
if (!gateRes.ok) {
|
|
21962
|
+
log(`${bannerPrefix} \u2014 failed (readinessReasonCode=${gateRes.readinessReasonCode})`);
|
|
21963
|
+
log(`Exit ${String(gateRes.exitCode)} \u2014 ${describeExitCode(gateRes.exitCode)}`);
|
|
21964
|
+
return { ok: false, facts, failure: gateRes };
|
|
21965
|
+
}
|
|
21966
|
+
log(`${bannerPrefix} \u2014 succeeded (detail: all checks ok)`);
|
|
21967
|
+
return { ok: true, facts };
|
|
21968
|
+
}
|
|
21969
|
+
|
|
21611
21970
|
// src/factory/factoryValidationFailures.ts
|
|
21612
21971
|
function factoryFailureDisplayId(row2) {
|
|
21613
21972
|
return row2.failureExitId;
|
|
21614
21973
|
}
|
|
21974
|
+
function parseMajorFromFailureExitId(id) {
|
|
21975
|
+
const m = /^(\d+)\.\d+$/.exec(id.trim());
|
|
21976
|
+
if (!m) {
|
|
21977
|
+
return void 0;
|
|
21978
|
+
}
|
|
21979
|
+
const n = Number(m[1]);
|
|
21980
|
+
return Number.isFinite(n) ? n : void 0;
|
|
21981
|
+
}
|
|
21615
21982
|
function normalizeFactoryFailureRow(r) {
|
|
21616
|
-
const failureExitId = r.failureExitId ?? r.validationExitId ??
|
|
21617
|
-
const
|
|
21983
|
+
const failureExitId = r.failureExitId ?? r.validationExitId ?? failureExitIdFromParts(OsExit.factoryUnknown, 0);
|
|
21984
|
+
const exitCodeFromField = typeof r.exitCode === "number" ? r.exitCode : void 0;
|
|
21985
|
+
const exitCodeFromId = parseMajorFromFailureExitId(failureExitId);
|
|
21986
|
+
const exitCode = exitCodeFromField ?? exitCodeFromId ?? OsExit.factoryUnknown;
|
|
21618
21987
|
const factory = r.factory ?? "generate_context";
|
|
21619
21988
|
const base = {
|
|
21620
21989
|
factory,
|
|
@@ -21625,12 +21994,10 @@ function normalizeFactoryFailureRow(r) {
|
|
|
21625
21994
|
...typeof r.detail === "string" ? { detail: r.detail } : {},
|
|
21626
21995
|
...typeof r.validationSubcode === "string" ? { validationSubcode: r.validationSubcode } : {}
|
|
21627
21996
|
};
|
|
21628
|
-
|
|
21629
|
-
return { ...base, validationExitId: r.validationExitId ?? failureExitId };
|
|
21630
|
-
}
|
|
21631
|
-
return base;
|
|
21997
|
+
return { ...base, validationExitId: r.validationExitId ?? failureExitId };
|
|
21632
21998
|
}
|
|
21633
21999
|
var FACTORY_VALIDATION_PHASE_ORDER = [
|
|
22000
|
+
"diagnose_readiness",
|
|
21634
22001
|
"create_analysis_worktree",
|
|
21635
22002
|
"materialize_opencode_agents",
|
|
21636
22003
|
"synthesis_convergence",
|
|
@@ -21644,31 +22011,34 @@ var FACTORY_VALIDATION_PHASE_ORDER = [
|
|
|
21644
22011
|
var DETAIL_MAX = 600;
|
|
21645
22012
|
var ERROR_JOIN_MAX = 900;
|
|
21646
22013
|
var ADDITIONAL_APPEND_MAX = 200;
|
|
21647
|
-
var
|
|
21648
|
-
unknown_factory_phase:
|
|
21649
|
-
|
|
21650
|
-
|
|
21651
|
-
|
|
21652
|
-
|
|
21653
|
-
|
|
21654
|
-
|
|
21655
|
-
|
|
21656
|
-
|
|
21657
|
-
|
|
22014
|
+
var PHASE_TO_OS_EXIT = {
|
|
22015
|
+
unknown_factory_phase: OsExit.factoryUnknown,
|
|
22016
|
+
diagnose_readiness: OsExit.readinessOpenCodeModel,
|
|
22017
|
+
create_analysis_worktree: OsExit.createAnalysisWorktree,
|
|
22018
|
+
materialize_opencode_agents: OsExit.materializeOpenCodeAgents,
|
|
22019
|
+
synthesis_convergence: OsExit.synthesisConvergence,
|
|
22020
|
+
reference_coverage: OsExit.referenceCoverage,
|
|
22021
|
+
zero_reference_remediation_convergence: OsExit.zeroReferenceRemediation,
|
|
22022
|
+
reference_coverage_execution_report: OsExit.referenceCoverageExecutionReport,
|
|
22023
|
+
link_mapping_pipeline: OsExit.linkMappingPipeline,
|
|
22024
|
+
assemble_application_context_index: OsExit.assembleApplicationContextIndex,
|
|
22025
|
+
backend_context_sync: OsExit.backendContextSync
|
|
21658
22026
|
};
|
|
21659
|
-
var
|
|
21660
|
-
|
|
21661
|
-
|
|
21662
|
-
|
|
21663
|
-
|
|
21664
|
-
|
|
21665
|
-
|
|
21666
|
-
|
|
21667
|
-
|
|
21668
|
-
|
|
21669
|
-
|
|
22027
|
+
var TITLE_BY_PHASE = {
|
|
22028
|
+
unknown_factory_phase: "EasySpecs stopped: the failing pipeline phase could not be identified. Retry with --verbose; report this outcome if it persists.",
|
|
22029
|
+
diagnose_readiness: "Factory readiness preflight failed: OpenCode install, credentials, default model, or mandatory `opencode.json` is not satisfied. See stderr lines above and `readinessReasonCode` in JSON.",
|
|
22030
|
+
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
|
+
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
|
+
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.",
|
|
22033
|
+
reference_coverage: "Reference coverage could not be computed or written. Check coverage-reference-validation.json prerequisites and disk/schema errors.",
|
|
22034
|
+
zero_reference_remediation_convergence: "Zero-reference remediation did not complete successfully. Inspect remediation logs and zero-reference outputs for this checkout.",
|
|
22035
|
+
reference_coverage_execution_report: "Reference coverage execution report could not be generated. Ensure coverage inputs exist from the coverage phase; see coverage-reference-validation.json.",
|
|
22036
|
+
link_mapping_pipeline: "Context link graph (navigation links) could not be updated. Check coordination JSON and markdown under .gluecharm/context.",
|
|
22037
|
+
assemble_application_context_index: "Application context index could not be assembled or failed schema validation. Inspect index-application-context.json and preceding context files.",
|
|
22038
|
+
backend_context_sync: "Upload / cloud sync after analysis did not succeed. Check auth, project id, network, and upload error details."
|
|
21670
22039
|
};
|
|
21671
22040
|
var READABLE_PHASE_LABEL = {
|
|
22041
|
+
diagnose_readiness: "Diagnose readiness",
|
|
21672
22042
|
create_analysis_worktree: "Analysis worktree",
|
|
21673
22043
|
materialize_opencode_agents: "OpenCode agents",
|
|
21674
22044
|
synthesis_convergence: "Synthesis",
|
|
@@ -21700,11 +22070,11 @@ function inferValidationSubcode(phase, detail) {
|
|
|
21700
22070
|
}
|
|
21701
22071
|
return void 0;
|
|
21702
22072
|
}
|
|
21703
|
-
function
|
|
21704
|
-
return
|
|
22073
|
+
function phaseToSemanticOsExitForGenerateContext(phase) {
|
|
22074
|
+
return PHASE_TO_OS_EXIT[phase] ?? OsExit.factoryUnknown;
|
|
21705
22075
|
}
|
|
21706
|
-
function
|
|
21707
|
-
return
|
|
22076
|
+
function titleForGenerateContextPhase(phase) {
|
|
22077
|
+
return TITLE_BY_PHASE[phase] ?? TITLE_BY_PHASE.unknown_factory_phase;
|
|
21708
22078
|
}
|
|
21709
22079
|
function readableLabelForFactoryPhase(phase) {
|
|
21710
22080
|
return READABLE_PHASE_LABEL[phase] ?? phase;
|
|
@@ -21713,33 +22083,53 @@ function phaseIndex(key) {
|
|
|
21713
22083
|
const i = FACTORY_VALIDATION_PHASE_ORDER.indexOf(key);
|
|
21714
22084
|
return i >= 0 ? i : 999;
|
|
21715
22085
|
}
|
|
22086
|
+
function finalizeFactoryFailuresForProcessExit(rows) {
|
|
22087
|
+
if (rows.length === 0) {
|
|
22088
|
+
return [];
|
|
22089
|
+
}
|
|
22090
|
+
const candidates = [...new Set(rows.map((r) => r.exitCode))];
|
|
22091
|
+
const processExit = candidates.length > 1 ? OsExit.factoryMultiPhaseRollup : candidates[0] ?? OsExit.factoryUnknown;
|
|
22092
|
+
return rows.map((r, i) => {
|
|
22093
|
+
const minor = processExit === OsExit.factoryMultiPhaseRollup ? i : 0;
|
|
22094
|
+
const fid = failureExitIdFromParts(processExit, minor);
|
|
22095
|
+
return {
|
|
22096
|
+
...r,
|
|
22097
|
+
exitCode: processExit,
|
|
22098
|
+
failureExitId: fid,
|
|
22099
|
+
validationExitId: fid
|
|
22100
|
+
};
|
|
22101
|
+
});
|
|
22102
|
+
}
|
|
21716
22103
|
function buildFactoryFailuresFromRows(phases) {
|
|
21717
22104
|
const failed = phases.filter((p) => p.status === "failed");
|
|
21718
22105
|
failed.sort((a, b) => phaseIndex(a.key) - phaseIndex(b.key));
|
|
21719
|
-
|
|
21720
|
-
const
|
|
22106
|
+
const semantic = failed.map((p) => {
|
|
22107
|
+
const os8 = phaseToSemanticOsExitForGenerateContext(p.key);
|
|
21721
22108
|
const sub = inferValidationSubcode(p.key, p.detail);
|
|
22109
|
+
const fid = failureExitIdFromParts(os8, 0);
|
|
21722
22110
|
return {
|
|
21723
22111
|
factory: "generate_context",
|
|
21724
22112
|
phase: p.key,
|
|
21725
|
-
exitCode:
|
|
21726
|
-
failureExitId:
|
|
21727
|
-
validationExitId:
|
|
21728
|
-
title:
|
|
22113
|
+
exitCode: os8,
|
|
22114
|
+
failureExitId: fid,
|
|
22115
|
+
validationExitId: fid,
|
|
22116
|
+
title: titleForGenerateContextPhase(p.key),
|
|
21729
22117
|
detail: trimDetail(p.detail),
|
|
21730
22118
|
...sub !== void 0 ? { validationSubcode: sub } : {}
|
|
21731
22119
|
};
|
|
21732
22120
|
});
|
|
22121
|
+
return finalizeFactoryFailuresForProcessExit(semantic);
|
|
21733
22122
|
}
|
|
21734
22123
|
function syntheticUnknownFactoryFailure(message) {
|
|
22124
|
+
const fid = failureExitIdFromParts(OsExit.factoryUnknown, 0);
|
|
21735
22125
|
return [
|
|
21736
22126
|
{
|
|
21737
22127
|
factory: "generate_context",
|
|
21738
22128
|
phase: "unknown_factory_phase",
|
|
21739
|
-
exitCode:
|
|
21740
|
-
failureExitId:
|
|
21741
|
-
validationExitId:
|
|
21742
|
-
title:
|
|
22129
|
+
exitCode: OsExit.factoryUnknown,
|
|
22130
|
+
failureExitId: fid,
|
|
22131
|
+
validationExitId: fid,
|
|
22132
|
+
title: titleForGenerateContextPhase("unknown_factory_phase"),
|
|
21743
22133
|
detail: trimDetail(message)
|
|
21744
22134
|
}
|
|
21745
22135
|
];
|
|
@@ -21747,7 +22137,8 @@ function syntheticUnknownFactoryFailure(message) {
|
|
|
21747
22137
|
function primaryFailureAliases(failures) {
|
|
21748
22138
|
const last = failures[failures.length - 1];
|
|
21749
22139
|
if (!last) {
|
|
21750
|
-
|
|
22140
|
+
const fid = failureExitIdFromParts(OsExit.factoryUnknown, 0);
|
|
22141
|
+
return { failurePhase: "unknown_factory_phase", validationExitId: fid };
|
|
21751
22142
|
}
|
|
21752
22143
|
return {
|
|
21753
22144
|
failurePhase: last.phase,
|
|
@@ -21767,7 +22158,7 @@ function exitMeaningFromFactoryFailures(failures) {
|
|
|
21767
22158
|
function composeFactoryValidationError(orchestratorMessage, failures) {
|
|
21768
22159
|
const m = orchestratorMessage?.trim() ?? "";
|
|
21769
22160
|
if (failures.length <= 1) {
|
|
21770
|
-
return m.length > 0 ? m : failures[0]?.title ?? "
|
|
22161
|
+
return m.length > 0 ? m : failures[0]?.title ?? "Factory pipeline failed.";
|
|
21771
22162
|
}
|
|
21772
22163
|
const extraIds = failures.slice(1).map((f) => factoryFailureDisplayId(f)).join(", ");
|
|
21773
22164
|
let appendix = `(+${String(failures.length - 1)} additional phase failure(s): ${extraIds})`;
|
|
@@ -21784,6 +22175,7 @@ function composeFactoryValidationError(orchestratorMessage, failures) {
|
|
|
21784
22175
|
|
|
21785
22176
|
// src/factory/generateContextFactory.ts
|
|
21786
22177
|
var FACTORY_PIPELINE_KEYS = [
|
|
22178
|
+
"diagnose_readiness",
|
|
21787
22179
|
"create_analysis_worktree",
|
|
21788
22180
|
"materialize_opencode_agents",
|
|
21789
22181
|
"synthesis_convergence",
|
|
@@ -21812,7 +22204,7 @@ function sleepUntilAborted(ms, signal) {
|
|
|
21812
22204
|
if (signal.aborted) {
|
|
21813
22205
|
return Promise.reject(new DOMException("The operation was aborted.", "AbortError"));
|
|
21814
22206
|
}
|
|
21815
|
-
return new Promise((
|
|
22207
|
+
return new Promise((resolve23, reject) => {
|
|
21816
22208
|
const onAbort = () => {
|
|
21817
22209
|
clearTimeout(t);
|
|
21818
22210
|
signal.removeEventListener("abort", onAbort);
|
|
@@ -21820,7 +22212,7 @@ function sleepUntilAborted(ms, signal) {
|
|
|
21820
22212
|
};
|
|
21821
22213
|
const t = setTimeout(() => {
|
|
21822
22214
|
signal.removeEventListener("abort", onAbort);
|
|
21823
|
-
|
|
22215
|
+
resolve23();
|
|
21824
22216
|
}, ms);
|
|
21825
22217
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
21826
22218
|
});
|
|
@@ -21919,6 +22311,59 @@ async function runGenerateContextFactory(deps) {
|
|
|
21919
22311
|
};
|
|
21920
22312
|
let pingPong = 0;
|
|
21921
22313
|
try {
|
|
22314
|
+
if (!deps.readiness) {
|
|
22315
|
+
setRowTimed("diagnose_readiness", "succeeded", "Readiness context omitted (narrow unit test).");
|
|
22316
|
+
await post();
|
|
22317
|
+
} else {
|
|
22318
|
+
setRowTimed("diagnose_readiness", "running", "Running diagnose readiness preflight\u2026");
|
|
22319
|
+
await post();
|
|
22320
|
+
const facts = buildReadinessProbeFacts(deps.readiness);
|
|
22321
|
+
const lines = buildReadinessLineBlock(facts, deps.readiness);
|
|
22322
|
+
const gateRes = evaluateReadinessGates(facts);
|
|
22323
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
22324
|
+
const rlog = deps.readinessLog ?? deps.factoryLog;
|
|
22325
|
+
rlog?.(`[factory] diagnose readiness \u2014 ${stamp}`);
|
|
22326
|
+
for (const ln of lines) {
|
|
22327
|
+
rlog?.(ln);
|
|
22328
|
+
}
|
|
22329
|
+
if (!gateRes.ok) {
|
|
22330
|
+
rlog?.(
|
|
22331
|
+
`[factory] diagnose readiness \u2014 failed (readinessReasonCode=${gateRes.readinessReasonCode})`
|
|
22332
|
+
);
|
|
22333
|
+
rlog?.(`Exit ${String(gateRes.exitCode)} \u2014 ${describeExitCode(gateRes.exitCode)}`);
|
|
22334
|
+
const detail = `${gateRes.readinessReasonCode} (gate ${gateRes.gate})`;
|
|
22335
|
+
setRowTimed("diagnose_readiness", "failed", detail);
|
|
22336
|
+
await post();
|
|
22337
|
+
const fr = {
|
|
22338
|
+
factory: "generate_context",
|
|
22339
|
+
phase: "diagnose_readiness",
|
|
22340
|
+
exitCode: gateRes.exitCode,
|
|
22341
|
+
failureExitId: failureExitIdFromParts(gateRes.exitCode, 0),
|
|
22342
|
+
validationExitId: failureExitIdFromParts(gateRes.exitCode, 0),
|
|
22343
|
+
title: titleForGenerateContextPhase("diagnose_readiness"),
|
|
22344
|
+
detail: detail.length > 600 ? `${detail.slice(0, 597)}\u2026` : detail
|
|
22345
|
+
};
|
|
22346
|
+
const ff = finalizeFactoryFailuresForProcessExit([fr]);
|
|
22347
|
+
const msg = `Readiness failed: ${gateRes.readinessReasonCode}`;
|
|
22348
|
+
const r = {
|
|
22349
|
+
ok: false,
|
|
22350
|
+
message: msg,
|
|
22351
|
+
totalElapsedMs: macroEnd(),
|
|
22352
|
+
factoryFailures: ff,
|
|
22353
|
+
readinessFailure: {
|
|
22354
|
+
exitCode: gateRes.exitCode,
|
|
22355
|
+
readinessReasonCode: gateRes.readinessReasonCode,
|
|
22356
|
+
readinessGate: gateRes.gate
|
|
22357
|
+
}
|
|
22358
|
+
};
|
|
22359
|
+
logFactoryEnd(r);
|
|
22360
|
+
return r;
|
|
22361
|
+
}
|
|
22362
|
+
const joined = lines.join(" | ");
|
|
22363
|
+
const okDetail = joined.length > 600 ? `${lines[0] ?? "ok"} | \u2026 (${String(lines.length)} lines)` : joined;
|
|
22364
|
+
setRowTimed("diagnose_readiness", "succeeded", okDetail);
|
|
22365
|
+
await post();
|
|
22366
|
+
}
|
|
21922
22367
|
outer: while (true) {
|
|
21923
22368
|
if (isAborted(signal)) {
|
|
21924
22369
|
setRowTimed("synthesis_convergence", "cancelled", "Stopped.");
|
|
@@ -21935,7 +22380,15 @@ async function runGenerateContextFactory(deps) {
|
|
|
21935
22380
|
return fin({ ok: false, cancelled: true, message: "Factory stopped.", totalElapsedMs: macroEnd() });
|
|
21936
22381
|
}
|
|
21937
22382
|
if (!resumeSynthesis) {
|
|
21938
|
-
|
|
22383
|
+
if (deps.analysisInPlace === true) {
|
|
22384
|
+
setRowTimed(
|
|
22385
|
+
"create_analysis_worktree",
|
|
22386
|
+
"running",
|
|
22387
|
+
"In-place analysis \u2014 preparing repository root (no temp worktree)\u2026"
|
|
22388
|
+
);
|
|
22389
|
+
} else {
|
|
22390
|
+
setRowTimed("create_analysis_worktree", "running", "Creating git analysis worktree\u2026");
|
|
22391
|
+
}
|
|
21939
22392
|
await post();
|
|
21940
22393
|
const wtRes = await deps.runPrepareAnalysisWorktree(false);
|
|
21941
22394
|
if (!wtRes.ok) {
|
|
@@ -21943,7 +22396,15 @@ async function runGenerateContextFactory(deps) {
|
|
|
21943
22396
|
await post();
|
|
21944
22397
|
return fail(wtRes.error ?? "Worktree creation failed.");
|
|
21945
22398
|
}
|
|
21946
|
-
|
|
22399
|
+
if (deps.analysisInPlace === true) {
|
|
22400
|
+
setRowTimed(
|
|
22401
|
+
"create_analysis_worktree",
|
|
22402
|
+
"skipped",
|
|
22403
|
+
"In-place analysis \u2014 using repository root (no detached checkout)."
|
|
22404
|
+
);
|
|
22405
|
+
} else {
|
|
22406
|
+
setRowTimed("create_analysis_worktree", "succeeded", "Analysis checkout ready.");
|
|
22407
|
+
}
|
|
21947
22408
|
await post();
|
|
21948
22409
|
if (isAborted(signal)) {
|
|
21949
22410
|
setRowTimed("materialize_opencode_agents", "cancelled");
|
|
@@ -22249,8 +22710,8 @@ async function runGenerateContextFactory(deps) {
|
|
|
22249
22710
|
}
|
|
22250
22711
|
|
|
22251
22712
|
// src/factory/generateContextFactoryHeadlessHost.ts
|
|
22252
|
-
var
|
|
22253
|
-
var
|
|
22713
|
+
var fs48 = __toESM(require("node:fs"));
|
|
22714
|
+
var path44 = __toESM(require("node:path"));
|
|
22254
22715
|
|
|
22255
22716
|
// src/stores/pipelineRunStore.ts
|
|
22256
22717
|
var STORAGE_KEY2 = SRS53_PIPELINE_RUN_KEY_V2;
|
|
@@ -22350,12 +22811,12 @@ async function noteAgentsMaterialized(context) {
|
|
|
22350
22811
|
}
|
|
22351
22812
|
|
|
22352
22813
|
// src/pipelines/remediation/missingWorkstations.ts
|
|
22353
|
-
var
|
|
22354
|
-
var
|
|
22814
|
+
var fs41 = __toESM(require("fs"));
|
|
22815
|
+
var path36 = __toESM(require("path"));
|
|
22355
22816
|
|
|
22356
22817
|
// src/analysis/analysisDetailMarkdownDiscovery.ts
|
|
22357
|
-
var
|
|
22358
|
-
var
|
|
22818
|
+
var fs40 = __toESM(require("fs"));
|
|
22819
|
+
var path35 = __toESM(require("path"));
|
|
22359
22820
|
var SLUG4 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
22360
22821
|
var FE2 = /^FE-\d+$/;
|
|
22361
22822
|
var UC2 = /^UC-\d+$/;
|
|
@@ -22376,7 +22837,7 @@ var STEM_TO_AGENT = {
|
|
|
22376
22837
|
};
|
|
22377
22838
|
function readJson5(filePath) {
|
|
22378
22839
|
try {
|
|
22379
|
-
let raw =
|
|
22840
|
+
let raw = fs40.readFileSync(filePath, "utf-8");
|
|
22380
22841
|
if (raw.length > 0 && raw.charCodeAt(0) === 65279) {
|
|
22381
22842
|
raw = raw.slice(1);
|
|
22382
22843
|
}
|
|
@@ -22417,7 +22878,7 @@ function expectedFeatureDetailBasenameFromRow(row2) {
|
|
|
22417
22878
|
return `${code}-${slug}.md`;
|
|
22418
22879
|
}
|
|
22419
22880
|
function ctxPath(contextDir2, basename17) {
|
|
22420
|
-
return
|
|
22881
|
+
return path35.join(contextDir2, basename17);
|
|
22421
22882
|
}
|
|
22422
22883
|
function pushTarget(targets, stem, outputBasename, taskDescription, contextDir2) {
|
|
22423
22884
|
const meta = STEM_TO_AGENT[stem];
|
|
@@ -22433,7 +22894,7 @@ function pushTarget(targets, stem, outputBasename, taskDescription, contextDir2)
|
|
|
22433
22894
|
function discoverDetailMarkdownGroups(contextDir2) {
|
|
22434
22895
|
const groups = [];
|
|
22435
22896
|
const featureTargets = [];
|
|
22436
|
-
const flPath =
|
|
22897
|
+
const flPath = path35.join(contextDir2, "features-list.json");
|
|
22437
22898
|
const fl = readJson5(flPath);
|
|
22438
22899
|
const features = Array.isArray(fl?.features) ? fl.features : [];
|
|
22439
22900
|
for (const row2 of features) {
|
|
@@ -22463,7 +22924,7 @@ function discoverDetailMarkdownGroups(contextDir2) {
|
|
|
22463
22924
|
if (!FE2.test(feCode)) {
|
|
22464
22925
|
continue;
|
|
22465
22926
|
}
|
|
22466
|
-
const ucListPath =
|
|
22927
|
+
const ucListPath = path35.join(contextDir2, `${feCode}-use-cases-list.json`);
|
|
22467
22928
|
const ucFile = readJson5(ucListPath);
|
|
22468
22929
|
const ucs = Array.isArray(ucFile?.useCases) ? ucFile.useCases : [];
|
|
22469
22930
|
for (const ucRow of ucs) {
|
|
@@ -22483,7 +22944,7 @@ function discoverDetailMarkdownGroups(contextDir2) {
|
|
|
22483
22944
|
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.`,
|
|
22484
22945
|
contextDir2
|
|
22485
22946
|
);
|
|
22486
|
-
const scPath =
|
|
22947
|
+
const scPath = path35.join(contextDir2, `${feCode}_${ucCode}-scenarios-list.json`);
|
|
22487
22948
|
const scFile = readJson5(scPath);
|
|
22488
22949
|
const scs = Array.isArray(scFile?.scenarios) ? scFile.scenarios : [];
|
|
22489
22950
|
for (const scRow of scs) {
|
|
@@ -22554,7 +23015,7 @@ Follow bundled agent **agent-md-use-case-detail**: include **## Data inputs and
|
|
|
22554
23015
|
groups.push({ id: "detail-services", label: "Detail markdown \u2014 Services", targets: svcTargets });
|
|
22555
23016
|
groups.push({ id: "detail-methods", label: "Detail markdown \u2014 Methods", targets: meTargets });
|
|
22556
23017
|
const entTargets = [];
|
|
22557
|
-
const dmPath =
|
|
23018
|
+
const dmPath = path35.join(contextDir2, "data-model-list.json");
|
|
22558
23019
|
const dmFile = readJson5(dmPath);
|
|
22559
23020
|
const ents = Array.isArray(dmFile?.entities) ? dmFile.entities : [];
|
|
22560
23021
|
for (const erow of ents) {
|
|
@@ -22583,7 +23044,7 @@ Follow bundled agent **agent-md-use-case-detail**: include **## Data inputs and
|
|
|
22583
23044
|
if (!DM2.test(dmCode)) {
|
|
22584
23045
|
continue;
|
|
22585
23046
|
}
|
|
22586
|
-
const flPath2 =
|
|
23047
|
+
const flPath2 = path35.join(contextDir2, `${dmCode}-fields-list.json`);
|
|
22587
23048
|
const flFile = readJson5(flPath2);
|
|
22588
23049
|
const flds = Array.isArray(flFile?.fields) ? flFile.fields : [];
|
|
22589
23050
|
for (const frow of flds) {
|
|
@@ -22642,9 +23103,9 @@ function fileAndValidationFromKind(kind) {
|
|
|
22642
23103
|
return { filePresentYesNo: "no", validationYesNo: "na" };
|
|
22643
23104
|
}
|
|
22644
23105
|
function classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeRoot) {
|
|
22645
|
-
const abs =
|
|
23106
|
+
const abs = path36.join(contextDir2, row2.relativePath);
|
|
22646
23107
|
try {
|
|
22647
|
-
const st =
|
|
23108
|
+
const st = fs41.statSync(abs);
|
|
22648
23109
|
if (!st.isFile()) {
|
|
22649
23110
|
return { kind: "absent", detail: "Path exists but is not a regular file." };
|
|
22650
23111
|
}
|
|
@@ -22681,8 +23142,8 @@ function classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeR
|
|
|
22681
23142
|
detail: "Unknown coordination list basename \u2014 no JSON Schema mapping."
|
|
22682
23143
|
};
|
|
22683
23144
|
}
|
|
22684
|
-
const schemaAbs =
|
|
22685
|
-
if (!
|
|
23145
|
+
const schemaAbs = path36.join(worktreeRoot, ".opencode", "schemas", "context-lists", schemaBn);
|
|
23146
|
+
if (!fs41.existsSync(schemaAbs)) {
|
|
22686
23147
|
return {
|
|
22687
23148
|
kind: "invalid",
|
|
22688
23149
|
detail: `Schema not found (${schemaBn}). Run **Materialize agents** on this checkout.`
|
|
@@ -22711,7 +23172,7 @@ function classifyWorkstationOutputOnDisk(item, contextDir2, worktreeRoot) {
|
|
|
22711
23172
|
return classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeRoot).kind;
|
|
22712
23173
|
}
|
|
22713
23174
|
function isWorkstationRunSnapshotForWorktree(snapshot, worktreeRoot) {
|
|
22714
|
-
return !!(snapshot && snapshot.overallStatus !== "running" && snapshot.overallStatus !== "idle" &&
|
|
23175
|
+
return !!(snapshot && snapshot.overallStatus !== "running" && snapshot.overallStatus !== "idle" && path36.resolve(snapshot.analysisRoot) === path36.resolve(worktreeRoot));
|
|
22715
23176
|
}
|
|
22716
23177
|
function expectedBasenameForCoordPayload(p) {
|
|
22717
23178
|
const { step, listTarget } = p;
|
|
@@ -22785,10 +23246,10 @@ function labelContextForCoordPayload(p) {
|
|
|
22785
23246
|
}
|
|
22786
23247
|
function contextPathForWorkItem(item, contextDir2) {
|
|
22787
23248
|
if (item.kind === "markdown") {
|
|
22788
|
-
return
|
|
23249
|
+
return path36.join(contextDir2, item.payload.outputBasename);
|
|
22789
23250
|
}
|
|
22790
23251
|
const bn = expectedBasenameForCoordPayload(item.payload);
|
|
22791
|
-
return bn ?
|
|
23252
|
+
return bn ? path36.join(contextDir2, bn) : null;
|
|
22792
23253
|
}
|
|
22793
23254
|
function syntheticRunnerId(key) {
|
|
22794
23255
|
return `remediation:${key}`;
|
|
@@ -22798,7 +23259,7 @@ function rowFromSkippedItem(item, contextDir2) {
|
|
|
22798
23259
|
return null;
|
|
22799
23260
|
}
|
|
22800
23261
|
const abs = contextPathForWorkItem(item, contextDir2);
|
|
22801
|
-
const rel = abs ?
|
|
23262
|
+
const rel = abs ? path36.basename(abs) : item.kind === "markdown" ? item.payload.outputBasename : item.id;
|
|
22802
23263
|
if (abs && nonEmptyContextFile(abs)) {
|
|
22803
23264
|
return null;
|
|
22804
23265
|
}
|
|
@@ -22918,7 +23379,7 @@ function listMissingWorkstations(contextDir2, worktreeRoot, snapshot) {
|
|
|
22918
23379
|
}
|
|
22919
23380
|
}
|
|
22920
23381
|
}
|
|
22921
|
-
if (!
|
|
23382
|
+
if (!fs41.existsSync(contextDir2)) {
|
|
22922
23383
|
return [...map.values()].sort((a, b) => a.key.localeCompare(b.key));
|
|
22923
23384
|
}
|
|
22924
23385
|
const dynamic = discoverDynamicAnalysisTestSteps(contextDir2);
|
|
@@ -22973,7 +23434,7 @@ function toMissingWorkstationUiRows(rows, contextDir2, worktreeRoot) {
|
|
|
22973
23434
|
}
|
|
22974
23435
|
|
|
22975
23436
|
// src/pipelines/remediation/missingWorkstationsPool.ts
|
|
22976
|
-
var
|
|
23437
|
+
var path37 = __toESM(require("path"));
|
|
22977
23438
|
function reconcileSkippedWorkItemsWithDisk(byId, contextDir2, worktreeRoot) {
|
|
22978
23439
|
for (const item of byId.values()) {
|
|
22979
23440
|
if (item.status !== "skipped") {
|
|
@@ -23033,7 +23494,7 @@ async function runRemediationPipelineMissingPass(p) {
|
|
|
23033
23494
|
onItemComplete,
|
|
23034
23495
|
sourceBranchAtWorktreeCreation
|
|
23035
23496
|
} = p;
|
|
23036
|
-
const contextDir2 =
|
|
23497
|
+
const contextDir2 = path37.join(worktreeRoot, ".gluecharm", "context");
|
|
23037
23498
|
const snap = readArtefactRunSnapshot(storageContext);
|
|
23038
23499
|
const snapOk = isWorkstationRunSnapshotForWorktree(snap, worktreeRoot);
|
|
23039
23500
|
let byId;
|
|
@@ -23099,18 +23560,18 @@ async function runRemediationPipelineMissingPass(p) {
|
|
|
23099
23560
|
|
|
23100
23561
|
// src/pipelines/coverage/coveragePipeline.ts
|
|
23101
23562
|
var import_child_process5 = require("child_process");
|
|
23102
|
-
var
|
|
23103
|
-
var
|
|
23563
|
+
var fs43 = __toESM(require("fs"));
|
|
23564
|
+
var path39 = __toESM(require("path"));
|
|
23104
23565
|
|
|
23105
23566
|
// src/analysis/coverageReferenceValidationSchemaValidate.ts
|
|
23106
|
-
var
|
|
23107
|
-
var
|
|
23567
|
+
var fs42 = __toESM(require("fs"));
|
|
23568
|
+
var path38 = __toESM(require("path"));
|
|
23108
23569
|
var import__5 = __toESM(require__());
|
|
23109
23570
|
function stripUtf8Bom4(s) {
|
|
23110
23571
|
return s.length > 0 && s.charCodeAt(0) === 65279 ? s.slice(1) : s;
|
|
23111
23572
|
}
|
|
23112
23573
|
function bundledCoverageReferenceValidationSchemaPath() {
|
|
23113
|
-
return
|
|
23574
|
+
return path38.join(
|
|
23114
23575
|
resolveRepoResourcesRoot(),
|
|
23115
23576
|
"schemas",
|
|
23116
23577
|
"context-lists",
|
|
@@ -23133,7 +23594,7 @@ function getValidate() {
|
|
|
23133
23594
|
return compiledValidate;
|
|
23134
23595
|
}
|
|
23135
23596
|
const schemaPath = bundledCoverageReferenceValidationSchemaPath();
|
|
23136
|
-
const schemaRaw = stripUtf8Bom4(
|
|
23597
|
+
const schemaRaw = stripUtf8Bom4(fs42.readFileSync(schemaPath, "utf-8"));
|
|
23137
23598
|
const schema = JSON.parse(schemaRaw);
|
|
23138
23599
|
const ajv2 = new import__5.default({ allErrors: true, strict: false });
|
|
23139
23600
|
compiledValidate = ajv2.compile(schema);
|
|
@@ -23149,7 +23610,7 @@ function validateCoverageReferenceValidationData(data) {
|
|
|
23149
23610
|
function readAndValidateCoverageReferenceValidationFile(jsonAbsolutePath) {
|
|
23150
23611
|
let raw;
|
|
23151
23612
|
try {
|
|
23152
|
-
raw = stripUtf8Bom4(
|
|
23613
|
+
raw = stripUtf8Bom4(fs42.readFileSync(jsonAbsolutePath, "utf-8"));
|
|
23153
23614
|
} catch (e) {
|
|
23154
23615
|
return {
|
|
23155
23616
|
ok: false,
|
|
@@ -23190,8 +23651,8 @@ var DEFAULT_IGNORE_DIR_BASENAMES = [
|
|
|
23190
23651
|
];
|
|
23191
23652
|
var GIT_LS_FILES_MAX_BUFFER = 64 * 1024 * 1024;
|
|
23192
23653
|
function tryLoadGitNonIgnoredPathSet(repositoryRootAbs) {
|
|
23193
|
-
const root =
|
|
23194
|
-
if (!
|
|
23654
|
+
const root = path39.resolve(repositoryRootAbs);
|
|
23655
|
+
if (!fs43.existsSync(path39.join(root, ".git"))) {
|
|
23195
23656
|
return null;
|
|
23196
23657
|
}
|
|
23197
23658
|
const env = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
@@ -23259,12 +23720,12 @@ var REFERENCE_COVERAGE_IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
23259
23720
|
".emf"
|
|
23260
23721
|
]);
|
|
23261
23722
|
function isReferenceCoverageExcludedImagePath(relPosix) {
|
|
23262
|
-
const ext =
|
|
23723
|
+
const ext = path39.extname(relPosix).toLowerCase();
|
|
23263
23724
|
return ext.length > 0 && REFERENCE_COVERAGE_IMAGE_EXTENSIONS.has(ext);
|
|
23264
23725
|
}
|
|
23265
23726
|
var REFERENCE_COVERAGE_EXCLUDED_FILE_BASENAMES = /* @__PURE__ */ new Set([".gitignore"]);
|
|
23266
23727
|
function isReferenceCoverageExcludedDefaultBasename(relPosix) {
|
|
23267
|
-
const base =
|
|
23728
|
+
const base = path39.basename(relPosix.replace(/\\/g, "/")).toLowerCase();
|
|
23268
23729
|
return REFERENCE_COVERAGE_EXCLUDED_FILE_BASENAMES.has(base);
|
|
23269
23730
|
}
|
|
23270
23731
|
function decodeBufferForLineCount(buf) {
|
|
@@ -23301,12 +23762,12 @@ function normalizeRepoRelativePath(repoRoot, raw) {
|
|
|
23301
23762
|
if (!trimmed || trimmed.includes("\0")) {
|
|
23302
23763
|
return null;
|
|
23303
23764
|
}
|
|
23304
|
-
const abs =
|
|
23305
|
-
const rel =
|
|
23306
|
-
if (rel.startsWith("..") ||
|
|
23765
|
+
const abs = path39.resolve(repoRoot, trimmed);
|
|
23766
|
+
const rel = path39.relative(repoRoot, abs);
|
|
23767
|
+
if (rel.startsWith("..") || path39.isAbsolute(rel)) {
|
|
23307
23768
|
return null;
|
|
23308
23769
|
}
|
|
23309
|
-
return rel.split(
|
|
23770
|
+
return rel.split(path39.sep).join("/");
|
|
23310
23771
|
}
|
|
23311
23772
|
function collectJsonSourceReferences(node, out) {
|
|
23312
23773
|
if (node === null || typeof node !== "object") {
|
|
@@ -23346,12 +23807,12 @@ function extractEvidenceIndexPathCitations(body) {
|
|
|
23346
23807
|
function listContextFilesRecursive(dir, acc) {
|
|
23347
23808
|
let entries;
|
|
23348
23809
|
try {
|
|
23349
|
-
entries =
|
|
23810
|
+
entries = fs43.readdirSync(dir, { withFileTypes: true });
|
|
23350
23811
|
} catch {
|
|
23351
23812
|
return;
|
|
23352
23813
|
}
|
|
23353
23814
|
for (const e of entries) {
|
|
23354
|
-
const full =
|
|
23815
|
+
const full = path39.join(dir, e.name);
|
|
23355
23816
|
if (e.isDirectory()) {
|
|
23356
23817
|
listContextFilesRecursive(full, acc);
|
|
23357
23818
|
} else if (e.isFile()) {
|
|
@@ -23364,7 +23825,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
23364
23825
|
const walk = (dir) => {
|
|
23365
23826
|
let entries;
|
|
23366
23827
|
try {
|
|
23367
|
-
entries =
|
|
23828
|
+
entries = fs43.readdirSync(dir, { withFileTypes: true });
|
|
23368
23829
|
} catch {
|
|
23369
23830
|
return;
|
|
23370
23831
|
}
|
|
@@ -23372,8 +23833,8 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
23372
23833
|
if (ignoreBasenames.has(e.name)) {
|
|
23373
23834
|
continue;
|
|
23374
23835
|
}
|
|
23375
|
-
const full =
|
|
23376
|
-
const rel =
|
|
23836
|
+
const full = path39.join(dir, e.name);
|
|
23837
|
+
const rel = path39.relative(repoRoot, full).split(path39.sep).join("/");
|
|
23377
23838
|
if (rel.startsWith("..")) {
|
|
23378
23839
|
continue;
|
|
23379
23840
|
}
|
|
@@ -23394,7 +23855,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
23394
23855
|
}
|
|
23395
23856
|
let st;
|
|
23396
23857
|
try {
|
|
23397
|
-
st =
|
|
23858
|
+
st = fs43.statSync(full);
|
|
23398
23859
|
} catch {
|
|
23399
23860
|
continue;
|
|
23400
23861
|
}
|
|
@@ -23404,7 +23865,7 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
23404
23865
|
}
|
|
23405
23866
|
let buf;
|
|
23406
23867
|
try {
|
|
23407
|
-
buf =
|
|
23868
|
+
buf = fs43.readFileSync(full);
|
|
23408
23869
|
} catch {
|
|
23409
23870
|
excludedOut.push({ path: rel, reason: "read error" });
|
|
23410
23871
|
continue;
|
|
@@ -23424,23 +23885,23 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
23424
23885
|
}
|
|
23425
23886
|
function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings) {
|
|
23426
23887
|
const references = [];
|
|
23427
|
-
if (!
|
|
23888
|
+
if (!fs43.existsSync(contextDirAbs)) {
|
|
23428
23889
|
warnings.push(`Context directory missing: ${contextDirAbs}`);
|
|
23429
23890
|
return references;
|
|
23430
23891
|
}
|
|
23431
23892
|
const allFiles = [];
|
|
23432
23893
|
listContextFilesRecursive(contextDirAbs, allFiles);
|
|
23433
23894
|
for (const abs of allFiles) {
|
|
23434
|
-
const ext =
|
|
23435
|
-
const base =
|
|
23436
|
-
const sourceArtefact =
|
|
23895
|
+
const ext = path39.extname(abs).toLowerCase();
|
|
23896
|
+
const base = path39.basename(abs);
|
|
23897
|
+
const sourceArtefact = path39.relative(contextDirAbs, abs).split(path39.sep).join("/");
|
|
23437
23898
|
if (ext === ".json") {
|
|
23438
23899
|
if (SKIP_CONTEXT_JSON.has(base)) {
|
|
23439
23900
|
continue;
|
|
23440
23901
|
}
|
|
23441
23902
|
let raw;
|
|
23442
23903
|
try {
|
|
23443
|
-
raw =
|
|
23904
|
+
raw = fs43.readFileSync(abs, "utf-8");
|
|
23444
23905
|
} catch (e) {
|
|
23445
23906
|
warnings.push(`Skip JSON (read error): ${sourceArtefact} \u2014 ${e instanceof Error ? e.message : String(e)}`);
|
|
23446
23907
|
continue;
|
|
@@ -23471,7 +23932,7 @@ function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings
|
|
|
23471
23932
|
if (ext === ".md") {
|
|
23472
23933
|
let text;
|
|
23473
23934
|
try {
|
|
23474
|
-
const buf =
|
|
23935
|
+
const buf = fs43.readFileSync(abs);
|
|
23475
23936
|
text = decodeBufferForLineCount(buf);
|
|
23476
23937
|
} catch (e) {
|
|
23477
23938
|
warnings.push(`Skip markdown (read/decode error): ${sourceArtefact} \u2014 ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -23515,12 +23976,12 @@ function sortReferenceRows(a, b) {
|
|
|
23515
23976
|
return (a.startLine ?? 0) - (b.startLine ?? 0);
|
|
23516
23977
|
}
|
|
23517
23978
|
function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirAbs, options) {
|
|
23518
|
-
const repoRoot =
|
|
23979
|
+
const repoRoot = path39.resolve(repositoryRootAbs);
|
|
23519
23980
|
const warnings = [];
|
|
23520
23981
|
const ignoreDirs = [...DEFAULT_IGNORE_DIR_BASENAMES];
|
|
23521
23982
|
const ignoreSet = new Set(ignoreDirs);
|
|
23522
23983
|
const maxBytes = options?.maxFileBytes ?? MAX_FILE_BYTES;
|
|
23523
|
-
const references = collectReferencesFromContext(
|
|
23984
|
+
const references = collectReferencesFromContext(path39.resolve(contextDirAbs), repoRoot, warnings);
|
|
23524
23985
|
references.sort(sortReferenceRows);
|
|
23525
23986
|
const referencedSet = /* @__PURE__ */ new Set();
|
|
23526
23987
|
for (const r of references) {
|
|
@@ -23528,7 +23989,7 @@ function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirA
|
|
|
23528
23989
|
}
|
|
23529
23990
|
const excludedFiles = [];
|
|
23530
23991
|
const gitNonIgnoredPaths = tryLoadGitNonIgnoredPathSet(repoRoot);
|
|
23531
|
-
if (
|
|
23992
|
+
if (fs43.existsSync(path39.join(repoRoot, ".git")) && gitNonIgnoredPaths === null) {
|
|
23532
23993
|
warnings.push(
|
|
23533
23994
|
"Repository has .git but git ls-files failed or git is unavailable; .gitignore / exclude-standard not applied."
|
|
23534
23995
|
);
|
|
@@ -23577,12 +24038,12 @@ function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirA
|
|
|
23577
24038
|
return { document: doc, warnings };
|
|
23578
24039
|
}
|
|
23579
24040
|
function runCoveragePipeline(opts) {
|
|
23580
|
-
const repoRoot =
|
|
23581
|
-
const contextDir2 =
|
|
23582
|
-
if (!
|
|
24041
|
+
const repoRoot = path39.resolve(opts.repositoryRootAbs);
|
|
24042
|
+
const contextDir2 = path39.resolve(opts.contextDirAbs);
|
|
24043
|
+
if (!fs43.existsSync(repoRoot)) {
|
|
23583
24044
|
return { ok: false, error: `Repository root does not exist: ${repoRoot}` };
|
|
23584
24045
|
}
|
|
23585
|
-
if (!
|
|
24046
|
+
if (!fs43.existsSync(contextDir2)) {
|
|
23586
24047
|
return {
|
|
23587
24048
|
ok: false,
|
|
23588
24049
|
error: `Missing .gluecharm/context: ${contextDir2}`
|
|
@@ -23600,11 +24061,11 @@ ${schemaCheck.errors.join("\n")}`,
|
|
|
23600
24061
|
warnings
|
|
23601
24062
|
};
|
|
23602
24063
|
}
|
|
23603
|
-
const outPath =
|
|
24064
|
+
const outPath = path39.join(contextDir2, COVERAGE_REFERENCE_VALIDATION_BASENAME);
|
|
23604
24065
|
if (opts.write) {
|
|
23605
24066
|
try {
|
|
23606
24067
|
const payload = stableStringifyCoverageDocument(document);
|
|
23607
|
-
|
|
24068
|
+
fs43.writeFileSync(outPath, payload, "utf-8");
|
|
23608
24069
|
} catch (e) {
|
|
23609
24070
|
return {
|
|
23610
24071
|
ok: false,
|
|
@@ -23618,12 +24079,12 @@ ${schemaCheck.errors.join("\n")}`,
|
|
|
23618
24079
|
|
|
23619
24080
|
// src/pipelines/remediation/zeroReferenceWorkstationChain.ts
|
|
23620
24081
|
var crypto = __toESM(require("crypto"));
|
|
23621
|
-
var
|
|
23622
|
-
var
|
|
24082
|
+
var fs45 = __toESM(require("fs"));
|
|
24083
|
+
var path41 = __toESM(require("path"));
|
|
23623
24084
|
|
|
23624
24085
|
// src/analysis/zeroReferenceRemediationSchemaValidate.ts
|
|
23625
|
-
var
|
|
23626
|
-
var
|
|
24086
|
+
var fs44 = __toESM(require("fs"));
|
|
24087
|
+
var path40 = __toESM(require("path"));
|
|
23627
24088
|
var import__6 = __toESM(require__());
|
|
23628
24089
|
function stripUtf8Bom5(s) {
|
|
23629
24090
|
return s.length > 0 && s.charCodeAt(0) === 65279 ? s.slice(1) : s;
|
|
@@ -23643,8 +24104,8 @@ function formatAjvErrors6(errors) {
|
|
|
23643
24104
|
}
|
|
23644
24105
|
var ajv = new import__6.default({ allErrors: true, strict: false });
|
|
23645
24106
|
function compileSchema(basename17) {
|
|
23646
|
-
const schemaPath =
|
|
23647
|
-
const schemaRaw = stripUtf8Bom5(
|
|
24107
|
+
const schemaPath = path40.join(schemasDir(), basename17);
|
|
24108
|
+
const schemaRaw = stripUtf8Bom5(fs44.readFileSync(schemaPath, "utf-8"));
|
|
23648
24109
|
const schema = JSON.parse(schemaRaw);
|
|
23649
24110
|
return ajv.compile(schema);
|
|
23650
24111
|
}
|
|
@@ -23688,7 +24149,7 @@ var ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS = 5;
|
|
|
23688
24149
|
var ZERO_REF_STAGING_FILE_PREVIEW_MAX_CHARS = 6e3;
|
|
23689
24150
|
function readStagingOutputPreview(outAbs) {
|
|
23690
24151
|
try {
|
|
23691
|
-
const s =
|
|
24152
|
+
const s = fs45.readFileSync(outAbs, "utf-8");
|
|
23692
24153
|
if (s.length <= ZERO_REF_STAGING_FILE_PREVIEW_MAX_CHARS) {
|
|
23693
24154
|
return s;
|
|
23694
24155
|
}
|
|
@@ -23938,17 +24399,17 @@ function expandArgvTemplate4(template, vars) {
|
|
|
23938
24399
|
});
|
|
23939
24400
|
}
|
|
23940
24401
|
function schemaRef2(worktreeRoot, schemaBasename) {
|
|
23941
|
-
return
|
|
24402
|
+
return path41.join(worktreeRoot, ".opencode", "schemas", "context-lists", schemaBasename);
|
|
23942
24403
|
}
|
|
23943
24404
|
function stagingDir(contextDirAbs) {
|
|
23944
|
-
return
|
|
24405
|
+
return path41.join(contextDirAbs, "_zero-ref-staging");
|
|
23945
24406
|
}
|
|
23946
24407
|
function stagingPathForTarget(contextDirAbs, kind, targetFilePathPosix) {
|
|
23947
24408
|
const h = crypto.createHash("sha256").update(targetFilePathPosix, "utf8").digest("hex").slice(0, 16);
|
|
23948
|
-
return
|
|
24409
|
+
return path41.join(stagingDir(contextDirAbs), `${kind}-${h}.json`);
|
|
23949
24410
|
}
|
|
23950
24411
|
function readNonReferencedFilesFromRepositoryRoot(repositoryRootAbs) {
|
|
23951
|
-
const p =
|
|
24412
|
+
const p = path41.join(repositoryRootAbs, ".gluecharm", "context", "coverage-reference-validation.json");
|
|
23952
24413
|
const r = readAndValidateCoverageReferenceValidationFile(p);
|
|
23953
24414
|
if (!r.ok) {
|
|
23954
24415
|
return { ok: false, error: r.errors.join("; ") };
|
|
@@ -23971,14 +24432,14 @@ function readNonReferencedFilesFromRepositoryRoot(repositoryRootAbs) {
|
|
|
23971
24432
|
return { ok: true, paths, ...generatedAt ? { generatedAt } : {} };
|
|
23972
24433
|
}
|
|
23973
24434
|
function readOrInitRoutingDoc(routingAbs, coverageReferenceGeneratedAt) {
|
|
23974
|
-
if (!
|
|
24435
|
+
if (!fs45.existsSync(routingAbs)) {
|
|
23975
24436
|
return {
|
|
23976
24437
|
schemaVersion: ROUTING_SCHEMA_VERSION,
|
|
23977
24438
|
...coverageReferenceGeneratedAt ? { coverageReferenceGeneratedAt } : {},
|
|
23978
24439
|
records: {}
|
|
23979
24440
|
};
|
|
23980
24441
|
}
|
|
23981
|
-
const raw =
|
|
24442
|
+
const raw = fs45.readFileSync(routingAbs, "utf-8");
|
|
23982
24443
|
const data = JSON.parse(raw);
|
|
23983
24444
|
if (!data.records || typeof data.records !== "object") {
|
|
23984
24445
|
return {
|
|
@@ -23990,10 +24451,10 @@ function readOrInitRoutingDoc(routingAbs, coverageReferenceGeneratedAt) {
|
|
|
23990
24451
|
return data;
|
|
23991
24452
|
}
|
|
23992
24453
|
function readOrInitTriageDoc(triageAbs) {
|
|
23993
|
-
if (!
|
|
24454
|
+
if (!fs45.existsSync(triageAbs)) {
|
|
23994
24455
|
return { schemaVersion: TRIAGE_SCHEMA_VERSION, records: {} };
|
|
23995
24456
|
}
|
|
23996
|
-
const raw =
|
|
24457
|
+
const raw = fs45.readFileSync(triageAbs, "utf-8");
|
|
23997
24458
|
const data = JSON.parse(raw);
|
|
23998
24459
|
if (!data.records || typeof data.records !== "object") {
|
|
23999
24460
|
return { schemaVersion: TRIAGE_SCHEMA_VERSION, records: {} };
|
|
@@ -24041,10 +24502,10 @@ function slugifyFeatureLabel(s) {
|
|
|
24041
24502
|
return t.length > 0 ? t : "feature";
|
|
24042
24503
|
}
|
|
24043
24504
|
function lineCountRepoFile(worktreeRootAbs, relPosix) {
|
|
24044
|
-
const abs =
|
|
24505
|
+
const abs = path41.join(worktreeRootAbs, ...relPosix.split("/"));
|
|
24045
24506
|
let buf;
|
|
24046
24507
|
try {
|
|
24047
|
-
buf =
|
|
24508
|
+
buf = fs45.readFileSync(abs);
|
|
24048
24509
|
} catch {
|
|
24049
24510
|
return 1;
|
|
24050
24511
|
}
|
|
@@ -24096,9 +24557,9 @@ var LIST_STEP_HINT = {
|
|
|
24096
24557
|
};
|
|
24097
24558
|
async function applyCoordinationListTriageMerge(input) {
|
|
24098
24559
|
const cfg = LIST_MERGE_CFG[input.listKind];
|
|
24099
|
-
const listPath =
|
|
24100
|
-
const schemaPath =
|
|
24101
|
-
if (!
|
|
24560
|
+
const listPath = path41.join(input.contextDirAbs, cfg.listBasename);
|
|
24561
|
+
const schemaPath = path41.join(resolveContextListSchemasDir(), cfg.schemaBasename);
|
|
24562
|
+
if (!fs45.existsSync(listPath)) {
|
|
24102
24563
|
return {
|
|
24103
24564
|
ok: false,
|
|
24104
24565
|
message: `${cfg.listBasename} not found \u2014 run coordination step ${LIST_STEP_HINT[input.listKind]} first.`
|
|
@@ -24109,7 +24570,7 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
24109
24570
|
return withCoordinationListFileLock(listPath, {}, async () => {
|
|
24110
24571
|
let raw;
|
|
24111
24572
|
try {
|
|
24112
|
-
raw =
|
|
24573
|
+
raw = fs45.readFileSync(listPath, "utf-8");
|
|
24113
24574
|
} catch (e) {
|
|
24114
24575
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
24115
24576
|
}
|
|
@@ -24177,7 +24638,7 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
24177
24638
|
});
|
|
24178
24639
|
const tmp = `${listPath}.tmp.${process.pid}`;
|
|
24179
24640
|
try {
|
|
24180
|
-
|
|
24641
|
+
fs45.writeFileSync(tmp, `${JSON.stringify(doc, null, 2)}
|
|
24181
24642
|
`, "utf-8");
|
|
24182
24643
|
} catch (e) {
|
|
24183
24644
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
@@ -24185,13 +24646,13 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
24185
24646
|
const v = validateCoordinationListJson(tmp, schemaPath);
|
|
24186
24647
|
if (!v.ok) {
|
|
24187
24648
|
try {
|
|
24188
|
-
|
|
24649
|
+
fs45.unlinkSync(tmp);
|
|
24189
24650
|
} catch {
|
|
24190
24651
|
}
|
|
24191
24652
|
return { ok: false, message: `${cfg.listBasename} validation failed: ${JSON.stringify(v.failure)}` };
|
|
24192
24653
|
}
|
|
24193
24654
|
try {
|
|
24194
|
-
|
|
24655
|
+
fs45.renameSync(tmp, listPath);
|
|
24195
24656
|
} catch (e) {
|
|
24196
24657
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
24197
24658
|
}
|
|
@@ -24201,10 +24662,10 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
24201
24662
|
}
|
|
24202
24663
|
async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, workspaceLabel) {
|
|
24203
24664
|
const outAbs = stagingPathForTarget(contextDirAbs, "classifier", targetFilePathPosix);
|
|
24204
|
-
|
|
24205
|
-
const runDir =
|
|
24206
|
-
|
|
24207
|
-
const outputBasename =
|
|
24665
|
+
fs45.mkdirSync(path41.dirname(outAbs), { recursive: true });
|
|
24666
|
+
const runDir = path41.join(common.worktreeRoot, ".opencode", "_run");
|
|
24667
|
+
fs45.mkdirSync(runDir, { recursive: true });
|
|
24668
|
+
const outputBasename = path41.basename(outAbs);
|
|
24208
24669
|
const listTaskDescription = [
|
|
24209
24670
|
`Target file (repo-relative, POSIX): **${targetFilePathPosix}**`,
|
|
24210
24671
|
`Workspace label hint: **${workspaceLabel}**.`,
|
|
@@ -24240,8 +24701,8 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
|
|
|
24240
24701
|
parentContextBlock: "",
|
|
24241
24702
|
...repairAppendix ? { repairAppendix } : {}
|
|
24242
24703
|
});
|
|
24243
|
-
const promptPath =
|
|
24244
|
-
|
|
24704
|
+
const promptPath = path41.join(runDir, `zero-ref-classify-a${attempt}-${Date.now()}.prompt.txt`);
|
|
24705
|
+
fs45.writeFileSync(promptPath, body, "utf-8");
|
|
24245
24706
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
24246
24707
|
promptFile: promptPath,
|
|
24247
24708
|
agentId: ZERO_REF_CLASSIFY_AGENT_STEM,
|
|
@@ -24268,7 +24729,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
|
|
|
24268
24729
|
const canRetry = attempt < ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS - 1;
|
|
24269
24730
|
let st;
|
|
24270
24731
|
try {
|
|
24271
|
-
st =
|
|
24732
|
+
st = fs45.statSync(outAbs);
|
|
24272
24733
|
} catch {
|
|
24273
24734
|
st = void 0;
|
|
24274
24735
|
}
|
|
@@ -24290,7 +24751,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
|
|
|
24290
24751
|
}
|
|
24291
24752
|
let parsed;
|
|
24292
24753
|
try {
|
|
24293
|
-
parsed = JSON.parse(
|
|
24754
|
+
parsed = JSON.parse(fs45.readFileSync(outAbs, "utf-8"));
|
|
24294
24755
|
} catch (e) {
|
|
24295
24756
|
const msg = e instanceof Error ? e.message : String(e);
|
|
24296
24757
|
lastFailureMessage = `Classifier output not valid JSON: ${msg}`;
|
|
@@ -24372,10 +24833,10 @@ var TRIAGE_SCOPE_META = {
|
|
|
24372
24833
|
};
|
|
24373
24834
|
async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPosix, routingSummary, which) {
|
|
24374
24835
|
const mdBasename = which === "project" ? "project.md" : "architecture.md";
|
|
24375
|
-
const mdAbs =
|
|
24836
|
+
const mdAbs = path41.join(contextDirAbs, mdBasename);
|
|
24376
24837
|
const agentStem = which === "project" ? ZERO_REF_ADD_REF_PROJECT_AGENT_STEM : ZERO_REF_ADD_REF_ARCH_AGENT_STEM;
|
|
24377
|
-
const runDir =
|
|
24378
|
-
|
|
24838
|
+
const runDir = path41.join(common.worktreeRoot, ".opencode", "_run");
|
|
24839
|
+
fs45.mkdirSync(runDir, { recursive: true });
|
|
24379
24840
|
const lines = [
|
|
24380
24841
|
`# SRS-30 \u2014 Add reference to ${mdBasename}`,
|
|
24381
24842
|
``,
|
|
@@ -24390,8 +24851,8 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
|
|
|
24390
24851
|
`- If the file is short, \`${targetFilePathPosix}:1-<lastLine>\` is acceptable.`,
|
|
24391
24852
|
`- Do not remove unrelated content; append or extend the most appropriate section.`
|
|
24392
24853
|
];
|
|
24393
|
-
const promptPath =
|
|
24394
|
-
|
|
24854
|
+
const promptPath = path41.join(runDir, `zero-ref-md-${which}-${Date.now()}.prompt.txt`);
|
|
24855
|
+
fs45.writeFileSync(promptPath, lines.join("\n"), "utf-8");
|
|
24395
24856
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
24396
24857
|
promptFile: promptPath,
|
|
24397
24858
|
agentId: agentStem,
|
|
@@ -24418,10 +24879,10 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
|
|
|
24418
24879
|
async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathPosix, routingSummary, workspaceLabel, triageScope) {
|
|
24419
24880
|
const meta = TRIAGE_SCOPE_META[triageScope];
|
|
24420
24881
|
const outAbs = stagingPathForTarget(contextDirAbs, "triage", targetFilePathPosix);
|
|
24421
|
-
|
|
24422
|
-
const runDir =
|
|
24423
|
-
|
|
24424
|
-
const outputBasename =
|
|
24882
|
+
fs45.mkdirSync(path41.dirname(outAbs), { recursive: true });
|
|
24883
|
+
const runDir = path41.join(common.worktreeRoot, ".opencode", "_run");
|
|
24884
|
+
fs45.mkdirSync(runDir, { recursive: true });
|
|
24885
|
+
const outputBasename = path41.basename(outAbs);
|
|
24425
24886
|
const listTaskDescription = [
|
|
24426
24887
|
`Target file: **${targetFilePathPosix}** (${workspaceLabel})`,
|
|
24427
24888
|
"**Classifier summary:**",
|
|
@@ -24451,8 +24912,8 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
24451
24912
|
parentContextBlock: "",
|
|
24452
24913
|
...repairAppendix ? { repairAppendix } : {}
|
|
24453
24914
|
});
|
|
24454
|
-
const promptPath =
|
|
24455
|
-
|
|
24915
|
+
const promptPath = path41.join(runDir, `zero-ref-triage-a${attempt}-${Date.now()}.prompt.txt`);
|
|
24916
|
+
fs45.writeFileSync(promptPath, body, "utf-8");
|
|
24456
24917
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
24457
24918
|
promptFile: promptPath,
|
|
24458
24919
|
agentId: ZERO_REF_TRIAGE_COORD_AGENT_STEM,
|
|
@@ -24479,7 +24940,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
24479
24940
|
const canRetry = attempt < ZERO_REF_STAGING_JSON_TOTAL_ATTEMPTS - 1;
|
|
24480
24941
|
let st;
|
|
24481
24942
|
try {
|
|
24482
|
-
st =
|
|
24943
|
+
st = fs45.statSync(outAbs);
|
|
24483
24944
|
} catch {
|
|
24484
24945
|
st = void 0;
|
|
24485
24946
|
}
|
|
@@ -24501,7 +24962,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
24501
24962
|
}
|
|
24502
24963
|
let parsed;
|
|
24503
24964
|
try {
|
|
24504
|
-
parsed = JSON.parse(
|
|
24965
|
+
parsed = JSON.parse(fs45.readFileSync(outAbs, "utf-8"));
|
|
24505
24966
|
} catch (e) {
|
|
24506
24967
|
const msg = e instanceof Error ? e.message : String(e);
|
|
24507
24968
|
lastFailureMessage = `Triage output not valid JSON: ${msg}`;
|
|
@@ -24557,7 +25018,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
24557
25018
|
return { ok: false, message: lastFailureMessage, stagingPath: outAbs };
|
|
24558
25019
|
}
|
|
24559
25020
|
try {
|
|
24560
|
-
|
|
25021
|
+
fs45.writeFileSync(outAbs, `${JSON.stringify(parsed, null, 2)}
|
|
24561
25022
|
`, "utf-8");
|
|
24562
25023
|
} catch {
|
|
24563
25024
|
}
|
|
@@ -24566,8 +25027,8 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
24566
25027
|
return { ok: false, message: lastFailureMessage, stagingPath: outAbs };
|
|
24567
25028
|
}
|
|
24568
25029
|
async function runOneUnreferencedFilePipeline(p) {
|
|
24569
|
-
const routingAbs =
|
|
24570
|
-
const triageAbs =
|
|
25030
|
+
const routingAbs = path41.join(p.contextDirAbs, ZERO_REF_ROUTING_BASENAME);
|
|
25031
|
+
const triageAbs = path41.join(p.contextDirAbs, ZERO_REF_TRIAGE_BASENAME);
|
|
24571
25032
|
const key = p.targetFilePathPosix;
|
|
24572
25033
|
const cr = await runClassifierAgent(p, p.contextDirAbs, key, p.workspaceLabel);
|
|
24573
25034
|
if (!cr.ok) {
|
|
@@ -24575,7 +25036,7 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
24575
25036
|
}
|
|
24576
25037
|
let stagingParsed;
|
|
24577
25038
|
try {
|
|
24578
|
-
stagingParsed = JSON.parse(
|
|
25039
|
+
stagingParsed = JSON.parse(fs45.readFileSync(cr.stagingPath, "utf-8"));
|
|
24579
25040
|
} catch (e) {
|
|
24580
25041
|
return { ok: false, message: String(e) };
|
|
24581
25042
|
}
|
|
@@ -24591,8 +25052,8 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
24591
25052
|
if (!s.ok) {
|
|
24592
25053
|
throw new Error(s.errors.join("; "));
|
|
24593
25054
|
}
|
|
24594
|
-
|
|
24595
|
-
|
|
25055
|
+
fs45.mkdirSync(path41.dirname(routingAbs), { recursive: true });
|
|
25056
|
+
fs45.writeFileSync(routingAbs, s.json, "utf-8");
|
|
24596
25057
|
});
|
|
24597
25058
|
const routing = stagingParsed.routing;
|
|
24598
25059
|
const routingSummary = typeof stagingParsed.projectRelationSummary === "string" ? stagingParsed.projectRelationSummary : "";
|
|
@@ -24623,7 +25084,7 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
24623
25084
|
}
|
|
24624
25085
|
let triageParsed;
|
|
24625
25086
|
try {
|
|
24626
|
-
triageParsed = JSON.parse(
|
|
25087
|
+
triageParsed = JSON.parse(fs45.readFileSync(tr.stagingPath, "utf-8"));
|
|
24627
25088
|
} catch (e) {
|
|
24628
25089
|
return { ok: false, message: String(e) };
|
|
24629
25090
|
}
|
|
@@ -24640,8 +25101,8 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
24640
25101
|
if (!s.ok) {
|
|
24641
25102
|
throw new Error(s.errors.join("; "));
|
|
24642
25103
|
}
|
|
24643
|
-
|
|
24644
|
-
|
|
25104
|
+
fs45.mkdirSync(path41.dirname(triageAbs), { recursive: true });
|
|
25105
|
+
fs45.writeFileSync(triageAbs, s.json, "utf-8");
|
|
24645
25106
|
});
|
|
24646
25107
|
const decision = triageParsed.decision;
|
|
24647
25108
|
if (decision === "new_item" || decision === "enrich_existing") {
|
|
@@ -24668,11 +25129,11 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
24668
25129
|
return { ok: true, message: `Triage ${decision}.` };
|
|
24669
25130
|
}
|
|
24670
25131
|
async function runRemediationPipelineZeroRefPass(p) {
|
|
24671
|
-
const contextDirAbs =
|
|
25132
|
+
const contextDirAbs = path41.join(p.worktreeRoot, ".gluecharm", "context");
|
|
24672
25133
|
const covRoot = p.coverageRepositoryRootAbs ?? p.workspaceRootAbs;
|
|
24673
25134
|
const cov = readNonReferencedFilesFromRepositoryRoot(covRoot);
|
|
24674
25135
|
const coverageAt = cov.ok ? cov.generatedAt : void 0;
|
|
24675
|
-
const workspaceLabel =
|
|
25136
|
+
const workspaceLabel = path41.basename(p.worktreeRoot);
|
|
24676
25137
|
const routingMutex = new AsyncMutex();
|
|
24677
25138
|
const triageMutex = new AsyncMutex();
|
|
24678
25139
|
const paths = [...p.paths];
|
|
@@ -24729,8 +25190,8 @@ async function runRemediationPipelineZeroRefPass(p) {
|
|
|
24729
25190
|
}
|
|
24730
25191
|
|
|
24731
25192
|
// src/pipelines/coverage/coverageExecutionReport.ts
|
|
24732
|
-
var
|
|
24733
|
-
var
|
|
25193
|
+
var fs46 = __toESM(require("fs"));
|
|
25194
|
+
var path42 = __toESM(require("path"));
|
|
24734
25195
|
var REFERENCE_COVERAGE_EXECUTION_REPORT_BASENAME = "reference-coverage-execution-report.md";
|
|
24735
25196
|
function inlineMdText(s) {
|
|
24736
25197
|
const t = s.replace(/\r\n/g, "\n").replace(/\n/g, " ").trim();
|
|
@@ -24826,7 +25287,7 @@ function collectNoActionRowsFromRoutingDoc(doc) {
|
|
|
24826
25287
|
return rows;
|
|
24827
25288
|
}
|
|
24828
25289
|
function readRoutingDocFromDisk(routingAbs) {
|
|
24829
|
-
if (!
|
|
25290
|
+
if (!fs46.existsSync(routingAbs)) {
|
|
24830
25291
|
return {
|
|
24831
25292
|
ok: true,
|
|
24832
25293
|
doc: { schemaVersion: "1", records: {} }
|
|
@@ -24834,7 +25295,7 @@ function readRoutingDocFromDisk(routingAbs) {
|
|
|
24834
25295
|
}
|
|
24835
25296
|
let raw;
|
|
24836
25297
|
try {
|
|
24837
|
-
raw =
|
|
25298
|
+
raw = fs46.readFileSync(routingAbs, "utf-8");
|
|
24838
25299
|
} catch (e) {
|
|
24839
25300
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
24840
25301
|
}
|
|
@@ -24854,10 +25315,10 @@ async function runCoverageExecutionReport(p) {
|
|
|
24854
25315
|
if (p.abortSignal?.aborted) {
|
|
24855
25316
|
return { ok: false, error: "Stopped.", cancelled: true };
|
|
24856
25317
|
}
|
|
24857
|
-
const contextDirAbs =
|
|
24858
|
-
const coverageAbs =
|
|
24859
|
-
const routingAbs =
|
|
24860
|
-
const outAbs =
|
|
25318
|
+
const contextDirAbs = path42.join(p.repositoryRootAbs, ".gluecharm", "context");
|
|
25319
|
+
const coverageAbs = path42.join(contextDirAbs, "coverage-reference-validation.json");
|
|
25320
|
+
const routingAbs = path42.join(contextDirAbs, "zero-reference-routing.json");
|
|
25321
|
+
const outAbs = path42.join(contextDirAbs, REFERENCE_COVERAGE_EXECUTION_REPORT_BASENAME);
|
|
24861
25322
|
const cov = readAndValidateCoverageReferenceValidationFile(coverageAbs);
|
|
24862
25323
|
if (!cov.ok) {
|
|
24863
25324
|
return { ok: false, error: `Coverage JSON: ${cov.errors.join("; ")}` };
|
|
@@ -24874,20 +25335,20 @@ async function runCoverageExecutionReport(p) {
|
|
|
24874
25335
|
}
|
|
24875
25336
|
let previous;
|
|
24876
25337
|
try {
|
|
24877
|
-
if (
|
|
24878
|
-
previous =
|
|
25338
|
+
if (fs46.existsSync(outAbs)) {
|
|
25339
|
+
previous = fs46.readFileSync(outAbs, "utf-8");
|
|
24879
25340
|
}
|
|
24880
25341
|
} catch {
|
|
24881
25342
|
previous = void 0;
|
|
24882
25343
|
}
|
|
24883
25344
|
try {
|
|
24884
|
-
|
|
24885
|
-
|
|
25345
|
+
fs46.mkdirSync(path42.dirname(outAbs), { recursive: true });
|
|
25346
|
+
fs46.writeFileSync(outAbs, md, "utf-8");
|
|
24886
25347
|
} catch (e) {
|
|
24887
25348
|
const msg = e instanceof Error ? e.message : String(e);
|
|
24888
25349
|
if (previous !== void 0) {
|
|
24889
25350
|
try {
|
|
24890
|
-
|
|
25351
|
+
fs46.writeFileSync(outAbs, previous, "utf-8");
|
|
24891
25352
|
} catch {
|
|
24892
25353
|
}
|
|
24893
25354
|
}
|
|
@@ -24898,8 +25359,8 @@ async function runCoverageExecutionReport(p) {
|
|
|
24898
25359
|
}
|
|
24899
25360
|
|
|
24900
25361
|
// src/gluecharm/minimalGluecharmLayout.ts
|
|
24901
|
-
var
|
|
24902
|
-
var
|
|
25362
|
+
var fs47 = __toESM(require("node:fs"));
|
|
25363
|
+
var path43 = __toESM(require("node:path"));
|
|
24903
25364
|
var MINIMAL_GLUECHARM_RELATIVE_DIRS = [
|
|
24904
25365
|
[".gluecharm", "docs", "srs"],
|
|
24905
25366
|
[".gluecharm", "content"],
|
|
@@ -24907,11 +25368,11 @@ var MINIMAL_GLUECHARM_RELATIVE_DIRS = [
|
|
|
24907
25368
|
[".gluecharm", "context"]
|
|
24908
25369
|
];
|
|
24909
25370
|
function ensureMinimalGluecharmLayoutNode(repoRootAbs) {
|
|
24910
|
-
const root =
|
|
25371
|
+
const root = path43.resolve(repoRootAbs);
|
|
24911
25372
|
for (const segments of MINIMAL_GLUECHARM_RELATIVE_DIRS) {
|
|
24912
|
-
const dir =
|
|
25373
|
+
const dir = path43.join(root, ...segments);
|
|
24913
25374
|
try {
|
|
24914
|
-
|
|
25375
|
+
fs47.mkdirSync(dir, { recursive: true });
|
|
24915
25376
|
} catch (e) {
|
|
24916
25377
|
const err = e;
|
|
24917
25378
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -25026,6 +25487,7 @@ function buildFactoryPipelineRegistry(cb) {
|
|
|
25026
25487
|
// src/factory/generateContextFactoryHeadlessHost.ts
|
|
25027
25488
|
function buildFactoryDepsHeadless(input) {
|
|
25028
25489
|
const { storageContext, repoRoot, agentsDirFs, buildOpenCodeOptions, log, signal, macroConfig } = input;
|
|
25490
|
+
const inPlace = input.inPlace === true;
|
|
25029
25491
|
let adHocWorktree;
|
|
25030
25492
|
let macroFinalize;
|
|
25031
25493
|
let macroSourceBranch;
|
|
@@ -25040,7 +25502,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25040
25502
|
if (!layout.ok) {
|
|
25041
25503
|
return { ok: false, error: layout.error };
|
|
25042
25504
|
}
|
|
25043
|
-
const ctxDir =
|
|
25505
|
+
const ctxDir = path44.join(ar, ".gluecharm", "context");
|
|
25044
25506
|
const snap = readArtefactRunSnapshot(storageContext);
|
|
25045
25507
|
const rows = listMissingWorkstations(ctxDir, ar, snap);
|
|
25046
25508
|
if (rows.length === 0) {
|
|
@@ -25054,7 +25516,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25054
25516
|
storageContext,
|
|
25055
25517
|
repositoryRoot: repoRoot,
|
|
25056
25518
|
worktreeRoot: ar,
|
|
25057
|
-
workspaceLabel:
|
|
25519
|
+
workspaceLabel: path44.basename(ar),
|
|
25058
25520
|
oc: {
|
|
25059
25521
|
...oc,
|
|
25060
25522
|
aceEnabled: getAceAnalysisEnabledForCheckout(ar),
|
|
@@ -25082,7 +25544,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25082
25544
|
}
|
|
25083
25545
|
try {
|
|
25084
25546
|
await startPipelineRun(storageContext, repoRoot);
|
|
25085
|
-
const folderName =
|
|
25547
|
+
const folderName = path44.basename(repoRoot);
|
|
25086
25548
|
const oc = buildOpenCodeOptions(handle.path);
|
|
25087
25549
|
const result = await runSynthesisPipelineDrainFromPreparedWorktree(
|
|
25088
25550
|
storageContext,
|
|
@@ -25139,7 +25601,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25139
25601
|
if (!ar) {
|
|
25140
25602
|
return 0;
|
|
25141
25603
|
}
|
|
25142
|
-
const ctxDir =
|
|
25604
|
+
const ctxDir = path44.join(ar, ".gluecharm", "context");
|
|
25143
25605
|
const snap = readArtefactRunSnapshot(storageContext);
|
|
25144
25606
|
return listMissingWorkstations(ctxDir, ar, snap).length;
|
|
25145
25607
|
};
|
|
@@ -25152,7 +25614,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25152
25614
|
if (!layout.ok) {
|
|
25153
25615
|
return { ok: false, message: layout.error };
|
|
25154
25616
|
}
|
|
25155
|
-
const contextDir2 =
|
|
25617
|
+
const contextDir2 = path44.join(ar, ".gluecharm", "context");
|
|
25156
25618
|
log(`[factory] reference coverage (worktree) \u2014 ${ar}`);
|
|
25157
25619
|
const res = runCoveragePipeline({
|
|
25158
25620
|
repositoryRootAbs: ar,
|
|
@@ -25212,7 +25674,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25212
25674
|
diagnosticLog: log
|
|
25213
25675
|
});
|
|
25214
25676
|
if (res.ok) {
|
|
25215
|
-
return { ok: true, message: `Report: ${
|
|
25677
|
+
return { ok: true, message: `Report: ${path44.basename(res.outputAbsolutePath)}` };
|
|
25216
25678
|
}
|
|
25217
25679
|
if (res.cancelled) {
|
|
25218
25680
|
return { ok: false, cancelled: true, message: "Report generation stopped." };
|
|
@@ -25228,7 +25690,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25228
25690
|
if (!lmLayout.ok) {
|
|
25229
25691
|
return { ok: false, message: lmLayout.error };
|
|
25230
25692
|
}
|
|
25231
|
-
const contextDir2 =
|
|
25693
|
+
const contextDir2 = path44.join(snap.adHocWorktreePath, ".gluecharm", "context");
|
|
25232
25694
|
const linkGraph = runLinkMappingPipeline(contextDir2, { log });
|
|
25233
25695
|
if (!linkGraph.ok) {
|
|
25234
25696
|
return { ok: false, message: linkGraph.error };
|
|
@@ -25244,7 +25706,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25244
25706
|
if (!idxLayout.ok) {
|
|
25245
25707
|
return { ok: false, message: idxLayout.error };
|
|
25246
25708
|
}
|
|
25247
|
-
const contextDir2 =
|
|
25709
|
+
const contextDir2 = path44.join(snap.adHocWorktreePath, ".gluecharm", "context");
|
|
25248
25710
|
try {
|
|
25249
25711
|
writeIndexApplicationContext(contextDir2, void 0, {
|
|
25250
25712
|
sourceBranchAtWorktreeCreation: snap.adHocSourceBranchAtCreation
|
|
@@ -25284,6 +25746,12 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25284
25746
|
return {
|
|
25285
25747
|
signal,
|
|
25286
25748
|
factoryLog: log,
|
|
25749
|
+
readinessLog: (line) => {
|
|
25750
|
+
process.stderr.write(`${line}
|
|
25751
|
+
`);
|
|
25752
|
+
},
|
|
25753
|
+
...inPlace ? { analysisInPlace: true } : {},
|
|
25754
|
+
readiness: input.readiness,
|
|
25287
25755
|
config: { ...macroConfig, ...input.synthesisOnly ? { synthesisOnly: true } : {} },
|
|
25288
25756
|
sleep: (ms) => sleepUntilAborted(ms, signal),
|
|
25289
25757
|
post: (payload) => {
|
|
@@ -25293,14 +25761,14 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25293
25761
|
},
|
|
25294
25762
|
runPrepareAnalysisWorktree: async (resume) => {
|
|
25295
25763
|
if (resume) {
|
|
25296
|
-
if (adHocWorktree &&
|
|
25764
|
+
if (adHocWorktree && fs48.existsSync(path44.join(adHocWorktree.path, ".git"))) {
|
|
25297
25765
|
return { ok: true };
|
|
25298
25766
|
}
|
|
25299
25767
|
const snap = readAnalysisWorkspaceSnapshot(storageContext);
|
|
25300
25768
|
const wtPath = snap?.adHocWorktreePath?.trim();
|
|
25301
25769
|
const repo = snap?.adHocRepositoryRoot?.trim() || repoRoot;
|
|
25302
|
-
if (wtPath &&
|
|
25303
|
-
adHocWorktree =
|
|
25770
|
+
if (wtPath && fs48.existsSync(path44.join(wtPath, ".git"))) {
|
|
25771
|
+
adHocWorktree = resolveAnalysisCheckoutHandle(wtPath, repo);
|
|
25304
25772
|
macroSourceBranch = snap?.adHocSourceBranchAtCreation;
|
|
25305
25773
|
macroFinalize = () => {
|
|
25306
25774
|
try {
|
|
@@ -25322,8 +25790,10 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25322
25790
|
}
|
|
25323
25791
|
macroFinalize = void 0;
|
|
25324
25792
|
macroSourceBranch = void 0;
|
|
25325
|
-
log(
|
|
25326
|
-
|
|
25793
|
+
log(
|
|
25794
|
+
inPlace ? `[factory] in-place analysis checkout \u2014 ${(/* @__PURE__ */ new Date()).toISOString()}` : `[factory] create analysis worktree \u2014 ${(/* @__PURE__ */ new Date()).toISOString()}`
|
|
25795
|
+
);
|
|
25796
|
+
const prep = await prepareSynthesisWorktree(storageContext, repoRoot, log, { inPlace });
|
|
25327
25797
|
if (!prep.ok) {
|
|
25328
25798
|
prep.finalize?.();
|
|
25329
25799
|
return { ok: false, error: prep.error };
|
|
@@ -25373,9 +25843,6 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25373
25843
|
|
|
25374
25844
|
// src/cli/failureExitRegistry.ts
|
|
25375
25845
|
var DRIFT_FACTORY = "context_drift";
|
|
25376
|
-
function failureExitIdFromParts(exitCode, minor) {
|
|
25377
|
-
return `${String(exitCode)}.${String(minor)}`;
|
|
25378
|
-
}
|
|
25379
25846
|
var DRIFT_META = {
|
|
25380
25847
|
INVALID_REFERENCE_PATH: {
|
|
25381
25848
|
phase: "resolve_reference_bundle",
|
|
@@ -25391,20 +25858,20 @@ var DRIFT_META = {
|
|
|
25391
25858
|
},
|
|
25392
25859
|
EMPTY_BUNDLE: {
|
|
25393
25860
|
phase: "resolve_reference_bundle",
|
|
25394
|
-
exitCode:
|
|
25395
|
-
minor:
|
|
25861
|
+
exitCode: OsExit.driftEmptyBundle,
|
|
25862
|
+
minor: 0,
|
|
25396
25863
|
title: "Reference bundle was empty or could not be read for drift analysis."
|
|
25397
25864
|
},
|
|
25398
25865
|
UNRESOLVED_REFERENCE_ROOT: {
|
|
25399
25866
|
phase: "resolve_reference_root",
|
|
25400
|
-
exitCode:
|
|
25401
|
-
minor:
|
|
25867
|
+
exitCode: OsExit.driftUnresolvedReferenceRoot,
|
|
25868
|
+
minor: 0,
|
|
25402
25869
|
title: "Reference root document could not be resolved. Use --index or ensure an index markdown exists."
|
|
25403
25870
|
},
|
|
25404
25871
|
MANIFEST_FAILED: {
|
|
25405
25872
|
phase: "build_comparison_manifest",
|
|
25406
|
-
exitCode:
|
|
25407
|
-
minor:
|
|
25873
|
+
exitCode: OsExit.driftManifestFailed,
|
|
25874
|
+
minor: 0,
|
|
25408
25875
|
title: "Comparison manifest could not be built for drift analysis."
|
|
25409
25876
|
},
|
|
25410
25877
|
AGENT_FAILED: {
|
|
@@ -25421,14 +25888,14 @@ var DRIFT_META = {
|
|
|
25421
25888
|
},
|
|
25422
25889
|
REPORT_WRITE_FAILED: {
|
|
25423
25890
|
phase: "validate_and_render_report",
|
|
25424
|
-
exitCode:
|
|
25425
|
-
minor:
|
|
25891
|
+
exitCode: OsExit.driftReportWriteFailed,
|
|
25892
|
+
minor: 0,
|
|
25426
25893
|
title: "Drift report markdown could not be written under the analysis worktree."
|
|
25427
25894
|
},
|
|
25428
25895
|
INDEX_PATCH_FAILED: {
|
|
25429
25896
|
phase: "update_reference_index",
|
|
25430
|
-
exitCode:
|
|
25431
|
-
minor:
|
|
25897
|
+
exitCode: OsExit.driftIndexPatchFailed,
|
|
25898
|
+
minor: 0,
|
|
25432
25899
|
title: "Reference root markdown could not be updated with the drift report link."
|
|
25433
25900
|
},
|
|
25434
25901
|
PROMOTE_FAILED: {
|
|
@@ -25484,10 +25951,7 @@ function contextDriftFactoryFailureRow(code, error) {
|
|
|
25484
25951
|
title: meta.title,
|
|
25485
25952
|
detail
|
|
25486
25953
|
};
|
|
25487
|
-
|
|
25488
|
-
return { ...base, validationExitId: failureExitId };
|
|
25489
|
-
}
|
|
25490
|
-
return base;
|
|
25954
|
+
return { ...base, validationExitId: failureExitId };
|
|
25491
25955
|
}
|
|
25492
25956
|
|
|
25493
25957
|
// src/cli/factoryValidationStderr.ts
|
|
@@ -25521,11 +25985,11 @@ function stderrLinesForFactoryFailures(failures, exitCode) {
|
|
|
25521
25985
|
}
|
|
25522
25986
|
|
|
25523
25987
|
// src/factory/updateContext/runUpdateContextFactory.ts
|
|
25524
|
-
var
|
|
25988
|
+
var path49 = __toESM(require("node:path"));
|
|
25525
25989
|
|
|
25526
25990
|
// src/factory/updateContext/updateContextBaseline.ts
|
|
25527
|
-
var
|
|
25528
|
-
var
|
|
25991
|
+
var fs49 = __toESM(require("node:fs"));
|
|
25992
|
+
var path45 = __toESM(require("node:path"));
|
|
25529
25993
|
function isValidIso(s) {
|
|
25530
25994
|
const t = Date.parse(s);
|
|
25531
25995
|
return Number.isFinite(t);
|
|
@@ -25535,17 +25999,17 @@ function maxMtimeRegularFilesUnderDir(dirAbs) {
|
|
|
25535
25999
|
const walk = (d) => {
|
|
25536
26000
|
let entries;
|
|
25537
26001
|
try {
|
|
25538
|
-
entries =
|
|
26002
|
+
entries = fs49.readdirSync(d, { withFileTypes: true });
|
|
25539
26003
|
} catch {
|
|
25540
26004
|
return;
|
|
25541
26005
|
}
|
|
25542
26006
|
for (const e of entries) {
|
|
25543
|
-
const p =
|
|
26007
|
+
const p = path45.join(d, e.name);
|
|
25544
26008
|
if (e.isDirectory()) {
|
|
25545
26009
|
walk(p);
|
|
25546
26010
|
} else if (e.isFile()) {
|
|
25547
26011
|
try {
|
|
25548
|
-
const st =
|
|
26012
|
+
const st = fs49.statSync(p);
|
|
25549
26013
|
const m = st.mtimeMs;
|
|
25550
26014
|
if (best === null || m > best) {
|
|
25551
26015
|
best = m;
|
|
@@ -25566,8 +26030,8 @@ function resolveUpdateContextBaseline(repoRootAbs, repoConfig) {
|
|
|
25566
26030
|
if (last.length > 0 && isValidIso(last)) {
|
|
25567
26031
|
return { baselineIsoUtc: new Date(last).toISOString(), source: "lastRunAt" };
|
|
25568
26032
|
}
|
|
25569
|
-
const ctxDir =
|
|
25570
|
-
if (!
|
|
26033
|
+
const ctxDir = path45.join(repoRootAbs, ".gluecharm", "context");
|
|
26034
|
+
if (!fs49.existsSync(ctxDir)) {
|
|
25571
26035
|
return null;
|
|
25572
26036
|
}
|
|
25573
26037
|
const maxMs = maxMtimeRegularFilesUnderDir(ctxDir);
|
|
@@ -25590,8 +26054,8 @@ function persistUpdateContextLastRunAt(repoRootAbs, isoUtc) {
|
|
|
25590
26054
|
|
|
25591
26055
|
// src/factory/updateContext/updateContextGitWindow.ts
|
|
25592
26056
|
var import_node_child_process3 = require("node:child_process");
|
|
25593
|
-
var
|
|
25594
|
-
var
|
|
26057
|
+
var fs50 = __toESM(require("node:fs"));
|
|
26058
|
+
var path46 = __toESM(require("node:path"));
|
|
25595
26059
|
var GIT_ENV = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
25596
26060
|
function gitLines(repoRootAbs, args) {
|
|
25597
26061
|
const r = (0, import_node_child_process3.execFileSync)("git", ["-c", "core.quotepath=false", ...args], {
|
|
@@ -25615,8 +26079,8 @@ function parseGitLogIso(line) {
|
|
|
25615
26079
|
return { hash, iso };
|
|
25616
26080
|
}
|
|
25617
26081
|
function discoverCommitWindowAndTouchedPaths(repoRootAbs, baselineIsoUtc) {
|
|
25618
|
-
const root =
|
|
25619
|
-
if (!
|
|
26082
|
+
const root = path46.resolve(repoRootAbs);
|
|
26083
|
+
if (!fs50.existsSync(path46.join(root, ".git"))) {
|
|
25620
26084
|
return { ok: false, error: "Not a git repository (missing .git)." };
|
|
25621
26085
|
}
|
|
25622
26086
|
const baselineMs = Date.parse(baselineIsoUtc);
|
|
@@ -25675,13 +26139,13 @@ function discoverCommitWindowAndTouchedPaths(repoRootAbs, baselineIsoUtc) {
|
|
|
25675
26139
|
};
|
|
25676
26140
|
}
|
|
25677
26141
|
function filterPathsExistingInWorktree(worktreeRootAbs, pathsPosix) {
|
|
25678
|
-
const root =
|
|
26142
|
+
const root = path46.resolve(worktreeRootAbs);
|
|
25679
26143
|
const out = [];
|
|
25680
26144
|
for (const p of pathsPosix) {
|
|
25681
26145
|
const rel = p.replace(/\\/g, "/");
|
|
25682
|
-
const abs =
|
|
26146
|
+
const abs = path46.join(root, ...rel.split("/"));
|
|
25683
26147
|
try {
|
|
25684
|
-
if (
|
|
26148
|
+
if (fs50.existsSync(abs) && fs50.statSync(abs).isFile()) {
|
|
25685
26149
|
out.push(rel);
|
|
25686
26150
|
}
|
|
25687
26151
|
} catch {
|
|
@@ -25691,8 +26155,8 @@ function filterPathsExistingInWorktree(worktreeRootAbs, pathsPosix) {
|
|
|
25691
26155
|
}
|
|
25692
26156
|
|
|
25693
26157
|
// src/factory/updateContext/updateContextReport.ts
|
|
25694
|
-
var
|
|
25695
|
-
var
|
|
26158
|
+
var fs51 = __toESM(require("node:fs"));
|
|
26159
|
+
var path47 = __toESM(require("node:path"));
|
|
25696
26160
|
var CHANGES_SINCE_DATE_BASENAME = "changes-since-date.md";
|
|
25697
26161
|
function renderChangesSinceDateMarkdown(p) {
|
|
25698
26162
|
const lines = [
|
|
@@ -25733,9 +26197,9 @@ function renderChangesSinceDateMarkdown(p) {
|
|
|
25733
26197
|
}
|
|
25734
26198
|
function writeChangesSinceDateReport(contextDirAbs, body) {
|
|
25735
26199
|
try {
|
|
25736
|
-
|
|
25737
|
-
const target =
|
|
25738
|
-
|
|
26200
|
+
fs51.mkdirSync(contextDirAbs, { recursive: true });
|
|
26201
|
+
const target = path47.join(contextDirAbs, CHANGES_SINCE_DATE_BASENAME);
|
|
26202
|
+
fs51.writeFileSync(target, body, "utf-8");
|
|
25739
26203
|
return { ok: true };
|
|
25740
26204
|
} catch (e) {
|
|
25741
26205
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
@@ -25743,13 +26207,13 @@ function writeChangesSinceDateReport(contextDirAbs, body) {
|
|
|
25743
26207
|
}
|
|
25744
26208
|
|
|
25745
26209
|
// src/factory/updateContext/updateContextSeedCheck.ts
|
|
25746
|
-
var
|
|
25747
|
-
var
|
|
26210
|
+
var fs52 = __toESM(require("node:fs"));
|
|
26211
|
+
var path48 = __toESM(require("node:path"));
|
|
25748
26212
|
var INDEX_BASENAME = "index-application-context.json";
|
|
25749
26213
|
var CHANGES_REPORT = "changes-since-date.md";
|
|
25750
26214
|
function tryParseJsonFile(abs) {
|
|
25751
26215
|
try {
|
|
25752
|
-
const raw =
|
|
26216
|
+
const raw = fs52.readFileSync(abs, "utf-8");
|
|
25753
26217
|
JSON.parse(raw);
|
|
25754
26218
|
return true;
|
|
25755
26219
|
} catch {
|
|
@@ -25757,16 +26221,16 @@ function tryParseJsonFile(abs) {
|
|
|
25757
26221
|
}
|
|
25758
26222
|
}
|
|
25759
26223
|
function isWorktreeContextSeeded(contextDirAbs) {
|
|
25760
|
-
if (!
|
|
26224
|
+
if (!fs52.existsSync(contextDirAbs)) {
|
|
25761
26225
|
return false;
|
|
25762
26226
|
}
|
|
25763
|
-
const indexAbs =
|
|
25764
|
-
if (
|
|
26227
|
+
const indexAbs = path48.join(contextDirAbs, INDEX_BASENAME);
|
|
26228
|
+
if (fs52.existsSync(indexAbs) && fs52.statSync(indexAbs).isFile() && tryParseJsonFile(indexAbs)) {
|
|
25765
26229
|
return true;
|
|
25766
26230
|
}
|
|
25767
26231
|
let names;
|
|
25768
26232
|
try {
|
|
25769
|
-
names =
|
|
26233
|
+
names = fs52.readdirSync(contextDirAbs);
|
|
25770
26234
|
} catch {
|
|
25771
26235
|
return false;
|
|
25772
26236
|
}
|
|
@@ -25778,9 +26242,9 @@ function isWorktreeContextSeeded(contextDirAbs) {
|
|
|
25778
26242
|
if (!name.endsWith(".md") && !name.endsWith(".json")) {
|
|
25779
26243
|
continue;
|
|
25780
26244
|
}
|
|
25781
|
-
const p =
|
|
26245
|
+
const p = path48.join(contextDirAbs, name);
|
|
25782
26246
|
try {
|
|
25783
|
-
if (
|
|
26247
|
+
if (fs52.statSync(p).isFile()) {
|
|
25784
26248
|
distinct.add(name);
|
|
25785
26249
|
}
|
|
25786
26250
|
} catch {
|
|
@@ -25792,12 +26256,14 @@ function isWorktreeContextSeeded(contextDirAbs) {
|
|
|
25792
26256
|
// src/factory/updateContext/runUpdateContextFactory.ts
|
|
25793
26257
|
var REMEDIATION_CHUNK_MAX = 40;
|
|
25794
26258
|
function contextDirUnderRoot(wtRoot) {
|
|
25795
|
-
return
|
|
26259
|
+
return path49.join(wtRoot, ".gluecharm", "context");
|
|
25796
26260
|
}
|
|
25797
26261
|
async function runUpdateContextFactory(deps) {
|
|
26262
|
+
const inPlace = deps.inPlace === true;
|
|
25798
26263
|
const baseMeta = {
|
|
25799
26264
|
command: "update_context",
|
|
25800
|
-
uploadRequested: false
|
|
26265
|
+
uploadRequested: false,
|
|
26266
|
+
...inPlace ? { analysisInPlace: true } : {}
|
|
25801
26267
|
};
|
|
25802
26268
|
const baseline = resolveUpdateContextBaseline(deps.repoRootAbs, deps.repoConfig);
|
|
25803
26269
|
if (!baseline) {
|
|
@@ -25822,8 +26288,42 @@ async function runUpdateContextFactory(deps) {
|
|
|
25822
26288
|
};
|
|
25823
26289
|
}
|
|
25824
26290
|
const shortNoCommits = gitWin.commitsInOrder.length === 0;
|
|
26291
|
+
const cliVersion = deps.cliVersion?.trim() || "0.0.0";
|
|
26292
|
+
const readinessCtx = {
|
|
26293
|
+
cliVersion,
|
|
26294
|
+
repoRootAbs: deps.repoRootAbs,
|
|
26295
|
+
analysisRootAbs: deps.repoRootAbs,
|
|
26296
|
+
apiBaseUrl: deps.merged.apiBaseUrl,
|
|
26297
|
+
openCodeExecutable: deps.merged.openCodeExecutable,
|
|
26298
|
+
openCodeSkipCredentialsCheck: deps.merged.openCodeSkipCredentialsCheck,
|
|
26299
|
+
providerEnvFromConfig: deps.merged.openCodeChildEnv,
|
|
26300
|
+
repoConfig: deps.repoConfig
|
|
26301
|
+
};
|
|
26302
|
+
const rlog = deps.readinessLog ?? deps.log;
|
|
26303
|
+
const pre = emitCliFactoryReadinessPreflight(rlog, "[factory] update context readiness", readinessCtx);
|
|
26304
|
+
if (!pre.ok) {
|
|
26305
|
+
const g = pre.failure;
|
|
26306
|
+
return {
|
|
26307
|
+
exitOk: false,
|
|
26308
|
+
ok: false,
|
|
26309
|
+
code: "READINESS_FAILED",
|
|
26310
|
+
error: `Factory readiness failed (${g.readinessReasonCode}).`,
|
|
26311
|
+
readinessExitCode: g.exitCode,
|
|
26312
|
+
readinessReasonCode: g.readinessReasonCode,
|
|
26313
|
+
readinessGate: g.gate,
|
|
26314
|
+
openCodeConfigFiles: pre.facts.openCodeConfigFiles,
|
|
26315
|
+
modelConfigured: pre.facts.modelConfigured,
|
|
26316
|
+
baselineDate: baseline.baselineIsoUtc,
|
|
26317
|
+
baselineSource: baseline.source,
|
|
26318
|
+
headCommit: gitWin.headCommit,
|
|
26319
|
+
rangeStartCommit: gitWin.rangeStartCommit,
|
|
26320
|
+
commitsReviewed: gitWin.commitsInOrder.length,
|
|
26321
|
+
...baseMeta
|
|
26322
|
+
};
|
|
26323
|
+
}
|
|
25825
26324
|
const prep = await prepareSynthesisWorktree(deps.storage, deps.repoRootAbs, deps.log, {
|
|
25826
|
-
clearPriorArtefactRun: true
|
|
26325
|
+
clearPriorArtefactRun: true,
|
|
26326
|
+
inPlace
|
|
25827
26327
|
});
|
|
25828
26328
|
if (!prep.ok) {
|
|
25829
26329
|
prep.finalize?.();
|
|
@@ -25844,7 +26344,7 @@ async function runUpdateContextFactory(deps) {
|
|
|
25844
26344
|
const finalizeWt = prep.finalize;
|
|
25845
26345
|
const wsCtxDir = contextDirUnderRoot(deps.repoRootAbs);
|
|
25846
26346
|
let ctxDirAbs = contextDirUnderRoot(handle.path);
|
|
25847
|
-
if (!isWorktreeContextSeeded(ctxDirAbs) && isWorktreeContextSeeded(wsCtxDir)) {
|
|
26347
|
+
if (!inPlace && !isWorktreeContextSeeded(ctxDirAbs) && isWorktreeContextSeeded(wsCtxDir)) {
|
|
25848
26348
|
deps.log("[update-context] seeding worktree context from workspace .gluecharm/context/");
|
|
25849
26349
|
promoteContextDirectoryToWorkspaceFs(wsCtxDir, handle.path);
|
|
25850
26350
|
ctxDirAbs = contextDirUnderRoot(handle.path);
|
|
@@ -26023,30 +26523,34 @@ async function runUpdateContextFactory(deps) {
|
|
|
26023
26523
|
}
|
|
26024
26524
|
let promoted = false;
|
|
26025
26525
|
if (deps.merged.promoteContextToWorkspace && ctxDirAbs) {
|
|
26026
|
-
|
|
26027
|
-
|
|
26028
|
-
|
|
26029
|
-
|
|
26030
|
-
|
|
26031
|
-
|
|
26032
|
-
|
|
26033
|
-
|
|
26034
|
-
|
|
26035
|
-
|
|
26036
|
-
|
|
26037
|
-
|
|
26038
|
-
|
|
26039
|
-
|
|
26040
|
-
|
|
26041
|
-
|
|
26042
|
-
|
|
26043
|
-
|
|
26044
|
-
|
|
26045
|
-
|
|
26046
|
-
|
|
26047
|
-
|
|
26048
|
-
|
|
26049
|
-
|
|
26526
|
+
if (inPlace) {
|
|
26527
|
+
deps.log("[update-context] in-place analysis \u2014 promote skipped (context already at repository root)");
|
|
26528
|
+
} else {
|
|
26529
|
+
try {
|
|
26530
|
+
const { filesCopied } = promoteContextDirectoryToWorkspaceFs(ctxDirAbs, deps.repoRootAbs);
|
|
26531
|
+
deps.log(`[update-context] promoted ${String(filesCopied)} file(s) \u2192 ${deps.repoRootAbs}`);
|
|
26532
|
+
promoted = filesCopied > 0;
|
|
26533
|
+
} catch (e) {
|
|
26534
|
+
finalizeWt?.();
|
|
26535
|
+
return {
|
|
26536
|
+
exitOk: false,
|
|
26537
|
+
ok: false,
|
|
26538
|
+
code: "PROMOTE_FAILED",
|
|
26539
|
+
error: e instanceof Error ? e.message : String(e),
|
|
26540
|
+
baselineDate: baseline.baselineIsoUtc,
|
|
26541
|
+
baselineSource: baseline.source,
|
|
26542
|
+
headCommit: gitWin.headCommit,
|
|
26543
|
+
rangeStartCommit: gitWin.rangeStartCommit,
|
|
26544
|
+
commitsReviewed: gitWin.commitsInOrder.length,
|
|
26545
|
+
filesDetected: inventory.length,
|
|
26546
|
+
filesRemediated,
|
|
26547
|
+
analysisWorktreeRoot: handle.path,
|
|
26548
|
+
changesReportRelativePath: ".gluecharm/context/changes-since-date.md",
|
|
26549
|
+
remediationSkipped,
|
|
26550
|
+
...remediationSkipReason ? { skipReason: remediationSkipReason } : {},
|
|
26551
|
+
...baseMeta
|
|
26552
|
+
};
|
|
26553
|
+
}
|
|
26050
26554
|
}
|
|
26051
26555
|
}
|
|
26052
26556
|
const uploadSkipped = true;
|
|
@@ -26082,12 +26586,12 @@ async function runUpdateContextFactory(deps) {
|
|
|
26082
26586
|
}
|
|
26083
26587
|
|
|
26084
26588
|
// src/factory/contextDrift/runContextDriftFactory.ts
|
|
26085
|
-
var
|
|
26086
|
-
var
|
|
26589
|
+
var fs58 = __toESM(require("node:fs"));
|
|
26590
|
+
var path54 = __toESM(require("node:path"));
|
|
26087
26591
|
|
|
26088
26592
|
// src/factory/contextDrift/contextDriftManifest.ts
|
|
26089
|
-
var
|
|
26090
|
-
var
|
|
26593
|
+
var fs53 = __toESM(require("node:fs"));
|
|
26594
|
+
var path50 = __toESM(require("node:path"));
|
|
26091
26595
|
var MAX_REFERENCE_BYTES = 256 * 1024;
|
|
26092
26596
|
var MAX_EVIDENCE_FILES = 300;
|
|
26093
26597
|
var MAX_EVIDENCE_READ = 512 * 1024;
|
|
@@ -26095,7 +26599,7 @@ var MAX_EXCERPT = 4e3;
|
|
|
26095
26599
|
function readFileLimited(abs, maxBytes) {
|
|
26096
26600
|
let buf;
|
|
26097
26601
|
try {
|
|
26098
|
-
buf =
|
|
26602
|
+
buf = fs53.readFileSync(abs);
|
|
26099
26603
|
} catch {
|
|
26100
26604
|
return { text: "", truncated: false };
|
|
26101
26605
|
}
|
|
@@ -26107,16 +26611,16 @@ function collectEvidencePaths(repoRoot) {
|
|
|
26107
26611
|
const out = [];
|
|
26108
26612
|
const roots = ["src", "test", "tests", "packages", ".gluecharm", "scripts"];
|
|
26109
26613
|
for (const rel of roots) {
|
|
26110
|
-
const abs =
|
|
26111
|
-
if (!
|
|
26614
|
+
const abs = path50.join(repoRoot, rel);
|
|
26615
|
+
if (!fs53.existsSync(abs)) {
|
|
26112
26616
|
continue;
|
|
26113
26617
|
}
|
|
26114
26618
|
walkFiles(abs, repoRoot, out, 0);
|
|
26115
26619
|
}
|
|
26116
26620
|
for (const leaf of ["package.json", "tsconfig.json"]) {
|
|
26117
|
-
const abs =
|
|
26118
|
-
if (
|
|
26119
|
-
const r =
|
|
26621
|
+
const abs = path50.join(repoRoot, leaf);
|
|
26622
|
+
if (fs53.existsSync(abs) && fs53.statSync(abs).isFile()) {
|
|
26623
|
+
const r = path50.relative(repoRoot, abs).split(path50.sep).join("/");
|
|
26120
26624
|
out.push(r);
|
|
26121
26625
|
}
|
|
26122
26626
|
}
|
|
@@ -26133,7 +26637,7 @@ function walkFiles(dir, repoRoot, out, depth) {
|
|
|
26133
26637
|
}
|
|
26134
26638
|
let entries;
|
|
26135
26639
|
try {
|
|
26136
|
-
entries =
|
|
26640
|
+
entries = fs53.readdirSync(dir, { withFileTypes: true });
|
|
26137
26641
|
} catch {
|
|
26138
26642
|
return;
|
|
26139
26643
|
}
|
|
@@ -26141,13 +26645,13 @@ function walkFiles(dir, repoRoot, out, depth) {
|
|
|
26141
26645
|
if (e.name === "node_modules" || e.name === ".git" || e.name === "dist" || e.name === "out") {
|
|
26142
26646
|
continue;
|
|
26143
26647
|
}
|
|
26144
|
-
const full =
|
|
26648
|
+
const full = path50.join(dir, e.name);
|
|
26145
26649
|
if (e.isDirectory()) {
|
|
26146
26650
|
walkFiles(full, repoRoot, out, depth + 1);
|
|
26147
26651
|
} else if (e.isFile()) {
|
|
26148
|
-
const ext =
|
|
26652
|
+
const ext = path50.extname(e.name).toLowerCase();
|
|
26149
26653
|
if ([".ts", ".tsx", ".js", ".mjs", ".cjs", ".json", ".md", ".yaml", ".yml"].includes(ext) || e.name === "Dockerfile") {
|
|
26150
|
-
const rel =
|
|
26654
|
+
const rel = path50.relative(repoRoot, full).split(path50.sep).join("/");
|
|
26151
26655
|
out.push(rel);
|
|
26152
26656
|
}
|
|
26153
26657
|
}
|
|
@@ -26157,7 +26661,7 @@ function buildComparisonManifest(args) {
|
|
|
26157
26661
|
const references = [];
|
|
26158
26662
|
let referenceTruncated = false;
|
|
26159
26663
|
for (const abs of args.bundleAbsFiles) {
|
|
26160
|
-
const rel =
|
|
26664
|
+
const rel = path50.relative(args.worktreeRoot, abs).split(path50.sep).join("/");
|
|
26161
26665
|
const { text, truncated } = readFileLimited(abs, MAX_REFERENCE_BYTES);
|
|
26162
26666
|
references.push({ path: rel, content: text, truncated });
|
|
26163
26667
|
if (truncated) {
|
|
@@ -26169,8 +26673,8 @@ function buildComparisonManifest(args) {
|
|
|
26169
26673
|
const omitted = Math.max(0, allEvidence.length - evidencePathsTrimmed.length);
|
|
26170
26674
|
const evidenceFiles = [];
|
|
26171
26675
|
for (const rel of evidencePathsTrimmed) {
|
|
26172
|
-
const abs =
|
|
26173
|
-
const st =
|
|
26676
|
+
const abs = path50.join(args.worktreeRoot, ...rel.split("/"));
|
|
26677
|
+
const st = fs53.existsSync(abs) ? fs53.statSync(abs) : null;
|
|
26174
26678
|
const size = st && st.isFile() ? st.size : 0;
|
|
26175
26679
|
const { text, truncated } = readFileLimited(abs, MAX_EVIDENCE_READ);
|
|
26176
26680
|
const excerpt = truncated ? `${text.slice(0, MAX_EXCERPT)}
|
|
@@ -26180,7 +26684,7 @@ function buildComparisonManifest(args) {
|
|
|
26180
26684
|
}
|
|
26181
26685
|
return {
|
|
26182
26686
|
runDate: args.runDate,
|
|
26183
|
-
referenceRelPaths: args.bundleAbsFiles.map((a) =>
|
|
26687
|
+
referenceRelPaths: args.bundleAbsFiles.map((a) => path50.relative(args.worktreeRoot, a).split(path50.sep).join("/")),
|
|
26184
26688
|
references,
|
|
26185
26689
|
evidenceFiles,
|
|
26186
26690
|
evidencePathsOnly: [],
|
|
@@ -26192,8 +26696,8 @@ function buildComparisonManifest(args) {
|
|
|
26192
26696
|
}
|
|
26193
26697
|
|
|
26194
26698
|
// src/factory/contextDrift/contextDriftAgent.ts
|
|
26195
|
-
var
|
|
26196
|
-
var
|
|
26699
|
+
var fs54 = __toESM(require("node:fs"));
|
|
26700
|
+
var path51 = __toESM(require("node:path"));
|
|
26197
26701
|
|
|
26198
26702
|
// src/factory/contextDrift/contextDriftPayload.ts
|
|
26199
26703
|
function isNonEmptyString2(v) {
|
|
@@ -26338,17 +26842,17 @@ function buildDriftPrompt(args) {
|
|
|
26338
26842
|
].join("\n");
|
|
26339
26843
|
}
|
|
26340
26844
|
async function runDriftComparisonOpenCode(args) {
|
|
26341
|
-
const runDir =
|
|
26342
|
-
|
|
26343
|
-
const manifestPath =
|
|
26344
|
-
const outputPath =
|
|
26345
|
-
|
|
26845
|
+
const runDir = path51.join(args.worktreeRoot, ".opencode", "_run");
|
|
26846
|
+
fs54.mkdirSync(runDir, { recursive: true });
|
|
26847
|
+
const manifestPath = path51.join(runDir, "context-drift-manifest.json");
|
|
26848
|
+
const outputPath = path51.join(runDir, "context-drift-payload.json");
|
|
26849
|
+
fs54.writeFileSync(manifestPath, `${JSON.stringify(args.manifestObject, null, 2)}
|
|
26346
26850
|
`, "utf8");
|
|
26347
|
-
if (
|
|
26348
|
-
|
|
26851
|
+
if (fs54.existsSync(outputPath)) {
|
|
26852
|
+
fs54.unlinkSync(outputPath);
|
|
26349
26853
|
}
|
|
26350
|
-
const promptPath =
|
|
26351
|
-
|
|
26854
|
+
const promptPath = path51.join(runDir, `context-drift-${Date.now()}.prompt.txt`);
|
|
26855
|
+
fs54.writeFileSync(
|
|
26352
26856
|
promptPath,
|
|
26353
26857
|
buildDriftPrompt({
|
|
26354
26858
|
worktreeRoot: args.worktreeRoot,
|
|
@@ -26365,7 +26869,7 @@ async function runDriftComparisonOpenCode(args) {
|
|
|
26365
26869
|
});
|
|
26366
26870
|
const title = buildOpenCodeSessionTitle({
|
|
26367
26871
|
runId: "context-drift",
|
|
26368
|
-
workItemId:
|
|
26872
|
+
workItemId: path51.basename(args.worktreeRoot).slice(0, 24) || "wt",
|
|
26369
26873
|
stepLabel: "context-drift"
|
|
26370
26874
|
});
|
|
26371
26875
|
const argv = injectPrimaryOpenCodeSessionArgv(expanded, title);
|
|
@@ -26390,7 +26894,7 @@ async function runDriftComparisonOpenCode(args) {
|
|
|
26390
26894
|
}
|
|
26391
26895
|
let raw;
|
|
26392
26896
|
try {
|
|
26393
|
-
const txt =
|
|
26897
|
+
const txt = fs54.readFileSync(outputPath, "utf8");
|
|
26394
26898
|
raw = JSON.parse(txt);
|
|
26395
26899
|
} catch (e) {
|
|
26396
26900
|
return {
|
|
@@ -26407,9 +26911,9 @@ async function runDriftComparisonOpenCode(args) {
|
|
|
26407
26911
|
|
|
26408
26912
|
// src/factory/contextDrift/contextDriftPaths.ts
|
|
26409
26913
|
var crypto2 = __toESM(require("node:crypto"));
|
|
26410
|
-
var
|
|
26411
|
-
var
|
|
26412
|
-
var DRIFT_CONTEXT_SUBDIR =
|
|
26914
|
+
var fs55 = __toESM(require("node:fs"));
|
|
26915
|
+
var path52 = __toESM(require("node:path"));
|
|
26916
|
+
var DRIFT_CONTEXT_SUBDIR = path52.join(".gluecharm", "context", "drift");
|
|
26413
26917
|
function sanitizeSlug(raw) {
|
|
26414
26918
|
const s = raw.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
26415
26919
|
return s.length > 0 ? s : "drift";
|
|
@@ -26418,9 +26922,9 @@ function utcDateString(d) {
|
|
|
26418
26922
|
return d.toISOString().slice(0, 10);
|
|
26419
26923
|
}
|
|
26420
26924
|
function resolveInsideRepo(repoRootAbs, userPath) {
|
|
26421
|
-
const abs =
|
|
26422
|
-
const rel =
|
|
26423
|
-
if (rel.startsWith("..") ||
|
|
26925
|
+
const abs = path52.isAbsolute(userPath) ? path52.normalize(userPath) : path52.resolve(repoRootAbs, userPath);
|
|
26926
|
+
const rel = path52.relative(repoRootAbs, abs);
|
|
26927
|
+
if (rel.startsWith("..") || path52.isAbsolute(rel)) {
|
|
26424
26928
|
return { ok: false };
|
|
26425
26929
|
}
|
|
26426
26930
|
return { ok: true, abs };
|
|
@@ -26430,7 +26934,7 @@ function computeSlug(args) {
|
|
|
26430
26934
|
return sanitizeSlug(args.label.trim());
|
|
26431
26935
|
}
|
|
26432
26936
|
const r = resolveInsideRepo(args.repoRootAbs, args.referencePath);
|
|
26433
|
-
const base = r.ok ?
|
|
26937
|
+
const base = r.ok ? path52.basename(r.abs) : path52.basename(args.referencePath);
|
|
26434
26938
|
return sanitizeSlug(base);
|
|
26435
26939
|
}
|
|
26436
26940
|
function driftFilename(slug, runDate) {
|
|
@@ -26446,7 +26950,7 @@ function maybeDedupeSlug(slug, referenceRelPosix) {
|
|
|
26446
26950
|
function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
26447
26951
|
let st;
|
|
26448
26952
|
try {
|
|
26449
|
-
st =
|
|
26953
|
+
st = fs55.statSync(referenceAbsInWorktree);
|
|
26450
26954
|
} catch {
|
|
26451
26955
|
return { ok: false, error: `Reference path not found in analysis worktree: ${referenceAbsInWorktree}` };
|
|
26452
26956
|
}
|
|
@@ -26467,12 +26971,12 @@ function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
|
26467
26971
|
}
|
|
26468
26972
|
let entries;
|
|
26469
26973
|
try {
|
|
26470
|
-
entries =
|
|
26974
|
+
entries = fs55.readdirSync(dir, { withFileTypes: true });
|
|
26471
26975
|
} catch {
|
|
26472
26976
|
return;
|
|
26473
26977
|
}
|
|
26474
26978
|
for (const e of entries) {
|
|
26475
|
-
const full =
|
|
26979
|
+
const full = path52.join(dir, e.name);
|
|
26476
26980
|
if (e.isDirectory()) {
|
|
26477
26981
|
if (e.name === "node_modules" || e.name === ".git") {
|
|
26478
26982
|
continue;
|
|
@@ -26492,7 +26996,7 @@ function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
|
26492
26996
|
}
|
|
26493
26997
|
function pickReferenceRootDocument(args) {
|
|
26494
26998
|
if (args.indexOverrideAbs) {
|
|
26495
|
-
if (!
|
|
26999
|
+
if (!fs55.existsSync(args.indexOverrideAbs) || !args.indexOverrideAbs.endsWith(".md")) {
|
|
26496
27000
|
return { ok: false, error: "--index must point to an existing .md file under the repo." };
|
|
26497
27001
|
}
|
|
26498
27002
|
return { ok: true, path: args.indexOverrideAbs };
|
|
@@ -26502,8 +27006,8 @@ function pickReferenceRootDocument(args) {
|
|
|
26502
27006
|
}
|
|
26503
27007
|
const dir = args.referenceAbsInWorktree;
|
|
26504
27008
|
for (const name of ["index.md", "README.md"]) {
|
|
26505
|
-
const p =
|
|
26506
|
-
if (
|
|
27009
|
+
const p = path52.join(dir, name);
|
|
27010
|
+
if (fs55.existsSync(p) && fs55.statSync(p).isFile()) {
|
|
26507
27011
|
return { ok: true, path: p };
|
|
26508
27012
|
}
|
|
26509
27013
|
}
|
|
@@ -26513,20 +27017,20 @@ function pickReferenceRootDocument(args) {
|
|
|
26513
27017
|
};
|
|
26514
27018
|
}
|
|
26515
27019
|
function toWorktreeRelative(worktreeRoot, absolute) {
|
|
26516
|
-
return
|
|
27020
|
+
return path52.relative(worktreeRoot, absolute).split(path52.sep).join("/");
|
|
26517
27021
|
}
|
|
26518
27022
|
function toPosixPath(p) {
|
|
26519
|
-
return p.split(
|
|
27023
|
+
return p.split(path52.sep).join("/");
|
|
26520
27024
|
}
|
|
26521
27025
|
|
|
26522
27026
|
// src/factory/contextDrift/contextDriftIndex.ts
|
|
26523
|
-
var
|
|
27027
|
+
var fs56 = __toESM(require("node:fs"));
|
|
26524
27028
|
var START = "<!-- easyspecs-drift-links:start -->";
|
|
26525
27029
|
var END = "<!-- easyspecs-drift-links:end -->";
|
|
26526
27030
|
function patchReferenceIndexWithDriftLink(args) {
|
|
26527
27031
|
let body;
|
|
26528
27032
|
try {
|
|
26529
|
-
body =
|
|
27033
|
+
body = fs56.readFileSync(args.referenceRootAbsolute, "utf8");
|
|
26530
27034
|
} catch (e) {
|
|
26531
27035
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
26532
27036
|
}
|
|
@@ -26547,7 +27051,7 @@ ${block}
|
|
|
26547
27051
|
`;
|
|
26548
27052
|
}
|
|
26549
27053
|
try {
|
|
26550
|
-
|
|
27054
|
+
fs56.writeFileSync(args.referenceRootAbsolute, next, "utf8");
|
|
26551
27055
|
} catch (e) {
|
|
26552
27056
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
26553
27057
|
}
|
|
@@ -26558,19 +27062,32 @@ function escapeRe(s) {
|
|
|
26558
27062
|
}
|
|
26559
27063
|
|
|
26560
27064
|
// src/factory/contextDrift/contextDriftPromote.ts
|
|
26561
|
-
var
|
|
26562
|
-
var
|
|
27065
|
+
var fs57 = __toESM(require("node:fs"));
|
|
27066
|
+
var path53 = __toESM(require("node:path"));
|
|
26563
27067
|
function copyWorktreeFileToWorkspace(args) {
|
|
26564
|
-
const
|
|
26565
|
-
const
|
|
26566
|
-
|
|
26567
|
-
|
|
27068
|
+
const wt = path53.resolve(args.worktreeRoot);
|
|
27069
|
+
const ws = path53.resolve(args.workspaceRoot);
|
|
27070
|
+
if (wt === ws) {
|
|
27071
|
+
return;
|
|
27072
|
+
}
|
|
27073
|
+
const src = path53.join(args.worktreeRoot, ...args.relativePosix.split("/"));
|
|
27074
|
+
const dest = path53.join(args.workspaceRoot, ...args.relativePosix.split("/"));
|
|
27075
|
+
if (path53.resolve(src) === path53.resolve(dest)) {
|
|
27076
|
+
return;
|
|
27077
|
+
}
|
|
27078
|
+
fs57.mkdirSync(path53.dirname(dest), { recursive: true });
|
|
27079
|
+
fs57.copyFileSync(src, dest);
|
|
26568
27080
|
}
|
|
26569
27081
|
|
|
26570
27082
|
// src/factory/contextDrift/runContextDriftFactory.ts
|
|
26571
27083
|
async function runContextDriftFactory(deps) {
|
|
26572
27084
|
const runDate = utcDateString(/* @__PURE__ */ new Date());
|
|
26573
|
-
const
|
|
27085
|
+
const inPlace = deps.inPlace === true;
|
|
27086
|
+
const baseMeta = {
|
|
27087
|
+
command: "context_drift",
|
|
27088
|
+
referencePath: deps.referencePathArg,
|
|
27089
|
+
...inPlace ? { analysisInPlace: true } : {}
|
|
27090
|
+
};
|
|
26574
27091
|
const resolved = resolveInsideRepo(deps.repoRootAbs, deps.referencePathArg);
|
|
26575
27092
|
if (!resolved.ok) {
|
|
26576
27093
|
return {
|
|
@@ -26583,7 +27100,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26583
27100
|
};
|
|
26584
27101
|
}
|
|
26585
27102
|
const refAbsWorkspace = resolved.abs;
|
|
26586
|
-
if (!
|
|
27103
|
+
if (!fs58.existsSync(refAbsWorkspace)) {
|
|
26587
27104
|
return {
|
|
26588
27105
|
exitOk: false,
|
|
26589
27106
|
ok: false,
|
|
@@ -26596,7 +27113,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26596
27113
|
let indexOverrideAbsWorkspace;
|
|
26597
27114
|
if (deps.indexOverrideArg?.trim()) {
|
|
26598
27115
|
const ir = resolveInsideRepo(deps.repoRootAbs, deps.indexOverrideArg.trim());
|
|
26599
|
-
if (!ir.ok || !
|
|
27116
|
+
if (!ir.ok || !fs58.existsSync(ir.abs)) {
|
|
26600
27117
|
return {
|
|
26601
27118
|
exitOk: false,
|
|
26602
27119
|
ok: false,
|
|
@@ -26614,7 +27131,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26614
27131
|
ok: true,
|
|
26615
27132
|
code: "DRY_RUN",
|
|
26616
27133
|
...baseMeta,
|
|
26617
|
-
referenceRootDocument: toPosixPath(
|
|
27134
|
+
referenceRootDocument: toPosixPath(path54.relative(deps.repoRootAbs, refAbsWorkspace)) + (fs58.statSync(refAbsWorkspace).isDirectory() ? "/" : ""),
|
|
26618
27135
|
driftReportPath: null,
|
|
26619
27136
|
analysisWorktreeRoot: "",
|
|
26620
27137
|
promoted: false,
|
|
@@ -26624,8 +27141,38 @@ async function runContextDriftFactory(deps) {
|
|
|
26624
27141
|
dryRun: true
|
|
26625
27142
|
};
|
|
26626
27143
|
}
|
|
27144
|
+
const cliVersion = deps.cliVersion?.trim() || "0.0.0";
|
|
27145
|
+
const readinessCtx = {
|
|
27146
|
+
cliVersion,
|
|
27147
|
+
repoRootAbs: deps.repoRootAbs,
|
|
27148
|
+
analysisRootAbs: deps.repoRootAbs,
|
|
27149
|
+
apiBaseUrl: deps.merged.apiBaseUrl,
|
|
27150
|
+
openCodeExecutable: deps.merged.openCodeExecutable,
|
|
27151
|
+
openCodeSkipCredentialsCheck: deps.merged.openCodeSkipCredentialsCheck,
|
|
27152
|
+
providerEnvFromConfig: deps.merged.openCodeChildEnv,
|
|
27153
|
+
repoConfig: deps.repoConfig
|
|
27154
|
+
};
|
|
27155
|
+
const rlog = deps.readinessLog ?? deps.log;
|
|
27156
|
+
const pre = emitCliFactoryReadinessPreflight(rlog, "[factory] context drift readiness", readinessCtx);
|
|
27157
|
+
if (!pre.ok) {
|
|
27158
|
+
const g = pre.failure;
|
|
27159
|
+
return {
|
|
27160
|
+
exitOk: false,
|
|
27161
|
+
ok: false,
|
|
27162
|
+
code: "READINESS_FAILED",
|
|
27163
|
+
error: `Factory readiness failed (${g.readinessReasonCode}).`,
|
|
27164
|
+
readinessExitCode: g.exitCode,
|
|
27165
|
+
readinessReasonCode: g.readinessReasonCode,
|
|
27166
|
+
readinessGate: g.gate,
|
|
27167
|
+
openCodeConfigFiles: pre.facts.openCodeConfigFiles,
|
|
27168
|
+
modelConfigured: pre.facts.modelConfigured,
|
|
27169
|
+
driftReportPath: null,
|
|
27170
|
+
...baseMeta
|
|
27171
|
+
};
|
|
27172
|
+
}
|
|
26627
27173
|
const prep = await prepareSynthesisWorktree(deps.storage, deps.repoRootAbs, deps.log, {
|
|
26628
|
-
clearPriorArtefactRun: false
|
|
27174
|
+
clearPriorArtefactRun: false,
|
|
27175
|
+
inPlace
|
|
26629
27176
|
});
|
|
26630
27177
|
if (!prep.ok) {
|
|
26631
27178
|
prep.finalize?.();
|
|
@@ -26641,8 +27188,8 @@ async function runContextDriftFactory(deps) {
|
|
|
26641
27188
|
const handle = prep.handle;
|
|
26642
27189
|
const finalizeWt = prep.finalize;
|
|
26643
27190
|
const wt = handle.path;
|
|
26644
|
-
const refRel =
|
|
26645
|
-
const refAbsWt =
|
|
27191
|
+
const refRel = path54.relative(deps.repoRootAbs, refAbsWorkspace).split(path54.sep).join("/");
|
|
27192
|
+
const refAbsWt = path54.join(wt, ...refRel.split("/"));
|
|
26646
27193
|
try {
|
|
26647
27194
|
materializeOpenCodeAgentsWithAce(deps.agentsDirFs, wt, {
|
|
26648
27195
|
enabled: getAceAnalysisEnabledForCheckout(wt),
|
|
@@ -26681,9 +27228,9 @@ async function runContextDriftFactory(deps) {
|
|
|
26681
27228
|
...baseMeta
|
|
26682
27229
|
};
|
|
26683
27230
|
}
|
|
26684
|
-
const indexWt = indexOverrideAbsWorkspace ?
|
|
27231
|
+
const indexWt = indexOverrideAbsWorkspace ? path54.join(wt, ...path54.relative(deps.repoRootAbs, indexOverrideAbsWorkspace).split(path54.sep)) : void 0;
|
|
26685
27232
|
const rootPick = pickReferenceRootDocument({
|
|
26686
|
-
referencePathIsFile:
|
|
27233
|
+
referencePathIsFile: fs58.statSync(refAbsWt).isFile(),
|
|
26687
27234
|
referenceAbsInWorktree: refAbsWt,
|
|
26688
27235
|
bundleFiles: bundle.bundleFiles,
|
|
26689
27236
|
indexOverrideAbs: indexWt
|
|
@@ -26709,9 +27256,9 @@ async function runContextDriftFactory(deps) {
|
|
|
26709
27256
|
let slug = computeSlug({ label: deps.label, referencePath: deps.referencePathArg, repoRootAbs: deps.repoRootAbs });
|
|
26710
27257
|
slug = maybeDedupeSlug(slug, refRel);
|
|
26711
27258
|
const driftBase = driftFilename(slug, runDate);
|
|
26712
|
-
const driftDirWt =
|
|
26713
|
-
|
|
26714
|
-
const driftAbsWt =
|
|
27259
|
+
const driftDirWt = path54.join(wt, DRIFT_CONTEXT_SUBDIR);
|
|
27260
|
+
fs58.mkdirSync(driftDirWt, { recursive: true });
|
|
27261
|
+
const driftAbsWt = path54.join(driftDirWt, driftBase);
|
|
26715
27262
|
let payload;
|
|
26716
27263
|
if (deps.testOnlyFixturePayload) {
|
|
26717
27264
|
payload = deps.testOnlyFixturePayload;
|
|
@@ -26747,7 +27294,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26747
27294
|
manifestTruncation: manifest.truncation
|
|
26748
27295
|
});
|
|
26749
27296
|
try {
|
|
26750
|
-
|
|
27297
|
+
fs58.writeFileSync(driftAbsWt, md, "utf8");
|
|
26751
27298
|
} catch (e) {
|
|
26752
27299
|
finalizeWt?.();
|
|
26753
27300
|
return {
|
|
@@ -26760,7 +27307,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26760
27307
|
...baseMeta
|
|
26761
27308
|
};
|
|
26762
27309
|
}
|
|
26763
|
-
const driftRelFromRootDir =
|
|
27310
|
+
const driftRelFromRootDir = path54.relative(path54.dirname(refRootAbsWt), driftAbsWt).split(path54.sep).join("/");
|
|
26764
27311
|
const linkRes = patchReferenceIndexWithDriftLink({
|
|
26765
27312
|
referenceRootAbsolute: refRootAbsWt,
|
|
26766
27313
|
relativeLinkFromRootToDrift: driftRelFromRootDir,
|
|
@@ -26779,10 +27326,10 @@ async function runContextDriftFactory(deps) {
|
|
|
26779
27326
|
...baseMeta
|
|
26780
27327
|
};
|
|
26781
27328
|
}
|
|
26782
|
-
const driftRelPosix = toPosixPath(
|
|
26783
|
-
const rootRelPosix = toPosixPath(
|
|
27329
|
+
const driftRelPosix = toPosixPath(path54.relative(wt, driftAbsWt));
|
|
27330
|
+
const rootRelPosix = toPosixPath(path54.relative(wt, refRootAbsWt));
|
|
26784
27331
|
const promoteEffective = deps.merged.promoteContextToWorkspace !== false;
|
|
26785
|
-
if (promoteEffective) {
|
|
27332
|
+
if (promoteEffective && !inPlace) {
|
|
26786
27333
|
try {
|
|
26787
27334
|
copyWorktreeFileToWorkspace({
|
|
26788
27335
|
worktreeRoot: wt,
|
|
@@ -26807,8 +27354,10 @@ async function runContextDriftFactory(deps) {
|
|
|
26807
27354
|
...baseMeta
|
|
26808
27355
|
};
|
|
26809
27356
|
}
|
|
27357
|
+
} else if (promoteEffective && inPlace) {
|
|
27358
|
+
deps.log("[context-drift] in-place analysis \u2014 promote skipped (artefacts already under repository root)");
|
|
26810
27359
|
}
|
|
26811
|
-
const driftReportPathFs = promoteEffective ?
|
|
27360
|
+
const driftReportPathFs = promoteEffective ? path54.join(deps.repoRootAbs, ...driftRelPosix.split("/")) : driftAbsWt;
|
|
26812
27361
|
return {
|
|
26813
27362
|
exitOk: true,
|
|
26814
27363
|
ok: true,
|
|
@@ -26817,7 +27366,7 @@ async function runContextDriftFactory(deps) {
|
|
|
26817
27366
|
referenceRootDocument: rootRelPosix,
|
|
26818
27367
|
driftReportPath: driftReportPathFs,
|
|
26819
27368
|
analysisWorktreeRoot: wt,
|
|
26820
|
-
promoted: promoteEffective,
|
|
27369
|
+
promoted: promoteEffective && !inPlace,
|
|
26821
27370
|
nameOfChangeSlug: slug,
|
|
26822
27371
|
runDate,
|
|
26823
27372
|
agentInvoked: !deps.testOnlyFixturePayload,
|
|
@@ -26826,8 +27375,8 @@ async function runContextDriftFactory(deps) {
|
|
|
26826
27375
|
}
|
|
26827
27376
|
|
|
26828
27377
|
// src/analysis/coordinationDuplicatesDiagnosis.ts
|
|
26829
|
-
var
|
|
26830
|
-
var
|
|
27378
|
+
var fs59 = __toESM(require("fs"));
|
|
27379
|
+
var path55 = __toESM(require("path"));
|
|
26831
27380
|
var import__7 = __toESM(require__());
|
|
26832
27381
|
var COORDINATION_DUPLICATES_REPORT_BASENAME = "coordination-duplicates-report.json";
|
|
26833
27382
|
var COORDINATION_LIST_SCAN_ENTRIES = [
|
|
@@ -26853,7 +27402,7 @@ var RE_MD_DM_FD = /^DM-\d+_FD-\d+-.+\.md$/i;
|
|
|
26853
27402
|
var RE_MD_DM = /^DM-\d+-.+\.md$/i;
|
|
26854
27403
|
var RE_MD_TS = /^TS-\d+-.+\.md$/i;
|
|
26855
27404
|
function looksLikeCoordinationDetailMarkdownBasename(basename17) {
|
|
26856
|
-
if (!basename17 || basename17 !==
|
|
27405
|
+
if (!basename17 || basename17 !== path55.basename(basename17) || !/\.md$/i.test(basename17)) {
|
|
26857
27406
|
return false;
|
|
26858
27407
|
}
|
|
26859
27408
|
if (STAPLE_CONTEXT_MARKDOWN_BASENAMES.has(basename17)) {
|
|
@@ -26862,12 +27411,12 @@ function looksLikeCoordinationDetailMarkdownBasename(basename17) {
|
|
|
26862
27411
|
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);
|
|
26863
27412
|
}
|
|
26864
27413
|
function loadRawFeatureRows(contextDirAbs) {
|
|
26865
|
-
const p =
|
|
26866
|
-
if (!
|
|
27414
|
+
const p = path55.join(contextDirAbs, "features-list.json");
|
|
27415
|
+
if (!fs59.existsSync(p)) {
|
|
26867
27416
|
return [];
|
|
26868
27417
|
}
|
|
26869
27418
|
try {
|
|
26870
|
-
const raw = stripUtf8Bom6(
|
|
27419
|
+
const raw = stripUtf8Bom6(fs59.readFileSync(p, "utf-8"));
|
|
26871
27420
|
const doc = JSON.parse(raw);
|
|
26872
27421
|
return Array.isArray(doc.features) ? doc.features : [];
|
|
26873
27422
|
} catch {
|
|
@@ -26902,7 +27451,7 @@ function findOrphanCoordinationMarkdown(contextDirAbs) {
|
|
|
26902
27451
|
const featureRows = loadRawFeatureRows(contextDirAbs);
|
|
26903
27452
|
let dirents;
|
|
26904
27453
|
try {
|
|
26905
|
-
dirents =
|
|
27454
|
+
dirents = fs59.readdirSync(contextDirAbs, { withFileTypes: true });
|
|
26906
27455
|
} catch {
|
|
26907
27456
|
return [];
|
|
26908
27457
|
}
|
|
@@ -27155,14 +27704,14 @@ function buildCoordinationDuplicatesReport(input) {
|
|
|
27155
27704
|
const lists = [];
|
|
27156
27705
|
const duplicateGroups = [];
|
|
27157
27706
|
for (const entry of COORDINATION_LIST_SCAN_ENTRIES) {
|
|
27158
|
-
const filePath =
|
|
27159
|
-
if (!
|
|
27707
|
+
const filePath = path55.join(input.contextDirAbsolute, entry.basename);
|
|
27708
|
+
if (!fs59.existsSync(filePath)) {
|
|
27160
27709
|
lists.push({ basename: entry.basename, status: "missing" });
|
|
27161
27710
|
continue;
|
|
27162
27711
|
}
|
|
27163
27712
|
let raw;
|
|
27164
27713
|
try {
|
|
27165
|
-
raw = stripUtf8Bom6(
|
|
27714
|
+
raw = stripUtf8Bom6(fs59.readFileSync(filePath, "utf-8"));
|
|
27166
27715
|
} catch (e) {
|
|
27167
27716
|
lists.push({
|
|
27168
27717
|
basename: entry.basename,
|
|
@@ -27210,8 +27759,8 @@ var validateReportCompiled;
|
|
|
27210
27759
|
function validateReportData(data) {
|
|
27211
27760
|
if (!validateReportCompiled) {
|
|
27212
27761
|
const ajv2 = new import__7.default({ allErrors: true, strict: false });
|
|
27213
|
-
const schemaPath =
|
|
27214
|
-
const schemaRaw = stripUtf8Bom6(
|
|
27762
|
+
const schemaPath = path55.join(resolveContextListSchemasDir(), "coordination-duplicates-report.schema.json");
|
|
27763
|
+
const schemaRaw = stripUtf8Bom6(fs59.readFileSync(schemaPath, "utf-8"));
|
|
27215
27764
|
validateReportCompiled = ajv2.compile(JSON.parse(schemaRaw));
|
|
27216
27765
|
}
|
|
27217
27766
|
if (validateReportCompiled(data)) {
|
|
@@ -27229,20 +27778,20 @@ function runCoordinationDuplicatesDiagnosis(input) {
|
|
|
27229
27778
|
if (!v.ok) {
|
|
27230
27779
|
return { ok: false, message: `Report validation failed: ${v.errors.join("; ")}` };
|
|
27231
27780
|
}
|
|
27232
|
-
const outPath =
|
|
27781
|
+
const outPath = path55.join(input.contextDirAbsolute, COORDINATION_DUPLICATES_REPORT_BASENAME);
|
|
27233
27782
|
const payload = `${JSON.stringify(report, null, 2)}
|
|
27234
27783
|
`;
|
|
27235
27784
|
const tmp = `${outPath}.tmp.${process.pid}`;
|
|
27236
27785
|
try {
|
|
27237
|
-
|
|
27786
|
+
fs59.writeFileSync(tmp, payload, "utf-8");
|
|
27238
27787
|
} catch (e) {
|
|
27239
27788
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
27240
27789
|
}
|
|
27241
27790
|
try {
|
|
27242
|
-
|
|
27791
|
+
fs59.renameSync(tmp, outPath);
|
|
27243
27792
|
} catch (e) {
|
|
27244
27793
|
try {
|
|
27245
|
-
|
|
27794
|
+
fs59.unlinkSync(tmp);
|
|
27246
27795
|
} catch {
|
|
27247
27796
|
}
|
|
27248
27797
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
@@ -27276,8 +27825,8 @@ function runCoordinationDuplicatesDiagnosis(input) {
|
|
|
27276
27825
|
}
|
|
27277
27826
|
|
|
27278
27827
|
// src/pipelines/download/downloadPipeline.ts
|
|
27279
|
-
var
|
|
27280
|
-
var
|
|
27828
|
+
var fs60 = __toESM(require("node:fs"));
|
|
27829
|
+
var path56 = __toESM(require("node:path"));
|
|
27281
27830
|
var SRS_DISCOVERY_BATCH_GET_CHUNK_SIZE = 200;
|
|
27282
27831
|
function isRecord7(v) {
|
|
27283
27832
|
return Boolean(v) && typeof v === "object" && !Array.isArray(v);
|
|
@@ -27367,9 +27916,9 @@ function resolveSafeContextOutputPath(contextDirAbs, nameRaw) {
|
|
|
27367
27916
|
return null;
|
|
27368
27917
|
}
|
|
27369
27918
|
}
|
|
27370
|
-
const resolved =
|
|
27371
|
-
const rel =
|
|
27372
|
-
if (rel.startsWith("..") ||
|
|
27919
|
+
const resolved = path56.resolve(contextDirAbs, ...segments);
|
|
27920
|
+
const rel = path56.relative(contextDirAbs, resolved);
|
|
27921
|
+
if (rel.startsWith("..") || path56.isAbsolute(rel)) {
|
|
27373
27922
|
return null;
|
|
27374
27923
|
}
|
|
27375
27924
|
return resolved;
|
|
@@ -27382,37 +27931,37 @@ function chunkIds(ids, size) {
|
|
|
27382
27931
|
return out;
|
|
27383
27932
|
}
|
|
27384
27933
|
function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
27385
|
-
if (!
|
|
27934
|
+
if (!fs60.existsSync(contextDirAbs) || !fs60.statSync(contextDirAbs).isDirectory()) {
|
|
27386
27935
|
return { filesRemoved: 0 };
|
|
27387
27936
|
}
|
|
27388
|
-
const preserveAbs =
|
|
27937
|
+
const preserveAbs = path56.resolve(contextDirAbs, UPLOAD_TARGET_FILENAME);
|
|
27389
27938
|
const preserveSet = /* @__PURE__ */ new Set();
|
|
27390
|
-
if (
|
|
27939
|
+
if (fs60.existsSync(preserveAbs) && fs60.statSync(preserveAbs).isFile()) {
|
|
27391
27940
|
preserveSet.add(preserveAbs);
|
|
27392
27941
|
}
|
|
27393
27942
|
let filesRemoved = 0;
|
|
27394
27943
|
const walkRm = (dir) => {
|
|
27395
27944
|
let entries;
|
|
27396
27945
|
try {
|
|
27397
|
-
entries =
|
|
27946
|
+
entries = fs60.readdirSync(dir, { withFileTypes: true });
|
|
27398
27947
|
} catch {
|
|
27399
27948
|
return;
|
|
27400
27949
|
}
|
|
27401
27950
|
for (const e of entries) {
|
|
27402
|
-
const full =
|
|
27951
|
+
const full = path56.join(dir, e.name);
|
|
27403
27952
|
if (e.isDirectory()) {
|
|
27404
27953
|
walkRm(full);
|
|
27405
27954
|
try {
|
|
27406
|
-
|
|
27955
|
+
fs60.rmdirSync(full);
|
|
27407
27956
|
} catch {
|
|
27408
27957
|
}
|
|
27409
27958
|
} else if (e.isFile()) {
|
|
27410
|
-
const abs =
|
|
27959
|
+
const abs = path56.resolve(full);
|
|
27411
27960
|
if (preserveSet.has(abs)) {
|
|
27412
27961
|
continue;
|
|
27413
27962
|
}
|
|
27414
27963
|
try {
|
|
27415
|
-
|
|
27964
|
+
fs60.unlinkSync(abs);
|
|
27416
27965
|
filesRemoved += 1;
|
|
27417
27966
|
} catch {
|
|
27418
27967
|
}
|
|
@@ -27480,7 +28029,7 @@ async function runDownloadPipeline(opts) {
|
|
|
27480
28029
|
failed.push({ id, message: "Missing name on srs_discovery node." });
|
|
27481
28030
|
continue;
|
|
27482
28031
|
}
|
|
27483
|
-
if (name === UPLOAD_TARGET_FILENAME ||
|
|
28032
|
+
if (name === UPLOAD_TARGET_FILENAME || path56.basename(name) === UPLOAD_TARGET_FILENAME) {
|
|
27484
28033
|
skipped += 1;
|
|
27485
28034
|
log?.(`[pipeline:download] skip ${name} (upload target row).`);
|
|
27486
28035
|
continue;
|
|
@@ -27491,15 +28040,15 @@ async function runDownloadPipeline(opts) {
|
|
|
27491
28040
|
failed.push({ id, name, message: "Unsafe or invalid name for local path." });
|
|
27492
28041
|
continue;
|
|
27493
28042
|
}
|
|
27494
|
-
|
|
27495
|
-
const exists =
|
|
28043
|
+
fs60.mkdirSync(path56.dirname(outAbs), { recursive: true });
|
|
28044
|
+
const exists = fs60.existsSync(outAbs);
|
|
27496
28045
|
if (exists && !opts.force && !opts.replaceFromCloud) {
|
|
27497
28046
|
skipped += 1;
|
|
27498
28047
|
log?.(`[pipeline:download] skip existing ${name} (use --force to overwrite).`);
|
|
27499
28048
|
continue;
|
|
27500
28049
|
}
|
|
27501
28050
|
try {
|
|
27502
|
-
|
|
28051
|
+
fs60.writeFileSync(outAbs, bodyText, "utf8");
|
|
27503
28052
|
downloaded += 1;
|
|
27504
28053
|
succeededIds[outAbs] = id;
|
|
27505
28054
|
} catch (e) {
|
|
@@ -27574,12 +28123,12 @@ function toFetchErrorMessage(e) {
|
|
|
27574
28123
|
|
|
27575
28124
|
// src/auth/gluecharmContentNegotiation.ts
|
|
27576
28125
|
var GLUECHARM_WS_LEGACY_JSON = "application/vnd.gluecharm.v1.ws-legacy+json";
|
|
27577
|
-
function pathWithoutQuery(
|
|
27578
|
-
const q =
|
|
27579
|
-
return q === -1 ?
|
|
28126
|
+
function pathWithoutQuery(path61) {
|
|
28127
|
+
const q = path61.indexOf("?");
|
|
28128
|
+
return q === -1 ? path61 : path61.slice(0, q);
|
|
27580
28129
|
}
|
|
27581
|
-
function isGluecharmContentApiPath(
|
|
27582
|
-
const p = pathWithoutQuery(
|
|
28130
|
+
function isGluecharmContentApiPath(path61) {
|
|
28131
|
+
const p = pathWithoutQuery(path61);
|
|
27583
28132
|
return p.startsWith("/api/content/") || p.startsWith("/api/batch/content/");
|
|
27584
28133
|
}
|
|
27585
28134
|
function gluecharmContentHeaders(method) {
|
|
@@ -27617,7 +28166,7 @@ async function fetchWithTimeout2(url, init, fetchImpl, timeoutMs, externalSignal
|
|
|
27617
28166
|
}
|
|
27618
28167
|
function createAuthenticatedRequestJson(deps) {
|
|
27619
28168
|
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
27620
|
-
async function requestJson(
|
|
28169
|
+
async function requestJson(path61, options = {}) {
|
|
27621
28170
|
const base = deps.getApiBaseUrl();
|
|
27622
28171
|
if (!base) {
|
|
27623
28172
|
const err = { status: 0, message: "easyspecs.apiBaseUrl is not configured." };
|
|
@@ -27625,7 +28174,7 @@ function createAuthenticatedRequestJson(deps) {
|
|
|
27625
28174
|
}
|
|
27626
28175
|
const method = options.method ?? "GET";
|
|
27627
28176
|
const headers = { ...options.headers };
|
|
27628
|
-
if (isGluecharmContentApiPath(
|
|
28177
|
+
if (isGluecharmContentApiPath(path61)) {
|
|
27629
28178
|
Object.assign(headers, gluecharmContentHeaders(method));
|
|
27630
28179
|
} else {
|
|
27631
28180
|
if (!headers.Accept) {
|
|
@@ -27639,7 +28188,7 @@ function createAuthenticatedRequestJson(deps) {
|
|
|
27639
28188
|
if (options.withAuth !== false && access) {
|
|
27640
28189
|
headers.Authorization = `Bearer ${access}`;
|
|
27641
28190
|
}
|
|
27642
|
-
const url = `${base}${
|
|
28191
|
+
const url = `${base}${path61}`;
|
|
27643
28192
|
const timeoutMs = options.timeoutMs ?? API_TIMEOUT_MS;
|
|
27644
28193
|
const response = await fetchWithTimeout2(
|
|
27645
28194
|
url,
|
|
@@ -27660,7 +28209,7 @@ function createAuthenticatedRequestJson(deps) {
|
|
|
27660
28209
|
if (shouldRetryUnauthorized) {
|
|
27661
28210
|
const refreshed = await deps.refreshSession();
|
|
27662
28211
|
if (refreshed) {
|
|
27663
|
-
return requestJson(
|
|
28212
|
+
return requestJson(path61, { ...options, retryOnUnauthorized: false });
|
|
27664
28213
|
}
|
|
27665
28214
|
}
|
|
27666
28215
|
const fallback = payload == null ? `${response.statusText || "HTTP error"} (response body empty or not JSON)` : "Request failed.";
|
|
@@ -27670,15 +28219,15 @@ function createAuthenticatedRequestJson(deps) {
|
|
|
27670
28219
|
}
|
|
27671
28220
|
|
|
27672
28221
|
// src/cli/cliSession.ts
|
|
27673
|
-
var
|
|
27674
|
-
var
|
|
27675
|
-
var
|
|
28222
|
+
var fs61 = __toESM(require("node:fs"));
|
|
28223
|
+
var os7 = __toESM(require("node:os"));
|
|
28224
|
+
var path57 = __toESM(require("node:path"));
|
|
27676
28225
|
function defaultSessionPath() {
|
|
27677
|
-
return
|
|
28226
|
+
return path57.join(os7.homedir(), ".easyspecs", "cli-session.json");
|
|
27678
28227
|
}
|
|
27679
28228
|
var configSessionPath;
|
|
27680
28229
|
function setCliSessionPathFromConfig(absPath) {
|
|
27681
|
-
configSessionPath = absPath?.trim() ?
|
|
28230
|
+
configSessionPath = absPath?.trim() ? path57.resolve(absPath) : void 0;
|
|
27682
28231
|
}
|
|
27683
28232
|
function applyCliSessionPathFromRepoConfig(repoRoot, cfg) {
|
|
27684
28233
|
const raw = cfg.easyspecs?.cliSessionPath?.trim();
|
|
@@ -27686,7 +28235,7 @@ function applyCliSessionPathFromRepoConfig(repoRoot, cfg) {
|
|
|
27686
28235
|
setCliSessionPathFromConfig(void 0);
|
|
27687
28236
|
return;
|
|
27688
28237
|
}
|
|
27689
|
-
const abs =
|
|
28238
|
+
const abs = path57.isAbsolute(raw) ? raw : path57.join(repoRoot, raw);
|
|
27690
28239
|
setCliSessionPathFromConfig(abs);
|
|
27691
28240
|
}
|
|
27692
28241
|
function normalizeCliSessionPathForConfig(repoRoot, raw) {
|
|
@@ -27694,15 +28243,15 @@ function normalizeCliSessionPathForConfig(repoRoot, raw) {
|
|
|
27694
28243
|
if (!t) {
|
|
27695
28244
|
return "";
|
|
27696
28245
|
}
|
|
27697
|
-
const resolvedRepo =
|
|
27698
|
-
const abs =
|
|
27699
|
-
const rel =
|
|
28246
|
+
const resolvedRepo = path57.resolve(repoRoot);
|
|
28247
|
+
const abs = path57.isAbsolute(t) ? path57.normalize(t) : path57.resolve(resolvedRepo, t);
|
|
28248
|
+
const rel = path57.relative(resolvedRepo, abs);
|
|
27700
28249
|
if (rel === "") {
|
|
27701
28250
|
return abs;
|
|
27702
28251
|
}
|
|
27703
|
-
const underRepo = !rel.startsWith("..") && !
|
|
28252
|
+
const underRepo = !rel.startsWith("..") && !path57.isAbsolute(rel);
|
|
27704
28253
|
if (underRepo) {
|
|
27705
|
-
return rel.split(
|
|
28254
|
+
return rel.split(path57.sep).join("/");
|
|
27706
28255
|
}
|
|
27707
28256
|
return abs;
|
|
27708
28257
|
}
|
|
@@ -27715,10 +28264,10 @@ function effectiveCliSessionPath() {
|
|
|
27715
28264
|
function readCliSession() {
|
|
27716
28265
|
const p = effectiveCliSessionPath();
|
|
27717
28266
|
try {
|
|
27718
|
-
if (!
|
|
28267
|
+
if (!fs61.existsSync(p)) {
|
|
27719
28268
|
return void 0;
|
|
27720
28269
|
}
|
|
27721
|
-
const j = JSON.parse(
|
|
28270
|
+
const j = JSON.parse(fs61.readFileSync(p, "utf8"));
|
|
27722
28271
|
const apiBaseUrl = typeof j.apiBaseUrl === "string" ? j.apiBaseUrl.trim() : "";
|
|
27723
28272
|
const accessToken = typeof j.accessToken === "string" ? j.accessToken : "";
|
|
27724
28273
|
const refreshToken = typeof j.refreshToken === "string" ? j.refreshToken : "";
|
|
@@ -27732,33 +28281,33 @@ function readCliSession() {
|
|
|
27732
28281
|
}
|
|
27733
28282
|
function writeCliSession(s) {
|
|
27734
28283
|
const p = effectiveCliSessionPath();
|
|
27735
|
-
|
|
27736
|
-
|
|
28284
|
+
fs61.mkdirSync(path57.dirname(p), { recursive: true });
|
|
28285
|
+
fs61.writeFileSync(p, `${JSON.stringify(s, null, 2)}
|
|
27737
28286
|
`, "utf8");
|
|
27738
28287
|
}
|
|
27739
28288
|
function clearCliSession() {
|
|
27740
28289
|
const p = effectiveCliSessionPath();
|
|
27741
28290
|
try {
|
|
27742
|
-
|
|
28291
|
+
fs61.unlinkSync(p);
|
|
27743
28292
|
} catch {
|
|
27744
28293
|
}
|
|
27745
28294
|
}
|
|
27746
28295
|
|
|
27747
28296
|
// src/analysis/acePendingTraces.ts
|
|
27748
|
-
var
|
|
27749
|
-
var
|
|
28297
|
+
var fs62 = __toESM(require("fs"));
|
|
28298
|
+
var path58 = __toESM(require("path"));
|
|
27750
28299
|
function normalizeAceTraceRelativePath(rel) {
|
|
27751
28300
|
return rel.split(/[/\\]/).join("/");
|
|
27752
28301
|
}
|
|
27753
28302
|
function readCompletedTraceRelativePaths(contextDir2) {
|
|
27754
28303
|
const set = /* @__PURE__ */ new Set();
|
|
27755
28304
|
const jsonlPath = aceConsolidatedSessionsJsonlPath(contextDir2);
|
|
27756
|
-
if (!
|
|
28305
|
+
if (!fs62.existsSync(jsonlPath)) {
|
|
27757
28306
|
return set;
|
|
27758
28307
|
}
|
|
27759
28308
|
let raw;
|
|
27760
28309
|
try {
|
|
27761
|
-
raw =
|
|
28310
|
+
raw = fs62.readFileSync(jsonlPath, "utf8");
|
|
27762
28311
|
} catch {
|
|
27763
28312
|
return set;
|
|
27764
28313
|
}
|
|
@@ -27789,14 +28338,14 @@ function readCompletedTraceRelativePaths(contextDir2) {
|
|
|
27789
28338
|
}
|
|
27790
28339
|
function listPendingAceTraceFiles(contextDir2, worktreeRoot) {
|
|
27791
28340
|
const traceSchema = opencodeAceSchemaPath(worktreeRoot, ACE_SCHEMA_TRACE);
|
|
27792
|
-
if (!
|
|
28341
|
+
if (!fs62.existsSync(traceSchema)) {
|
|
27793
28342
|
return [];
|
|
27794
28343
|
}
|
|
27795
28344
|
const completed = readCompletedTraceRelativePaths(contextDir2);
|
|
27796
28345
|
const allAbs = listAceTraceFiles(contextDir2);
|
|
27797
28346
|
const pending = [];
|
|
27798
28347
|
for (const abs of allAbs) {
|
|
27799
|
-
const rel = normalizeAceTraceRelativePath(
|
|
28348
|
+
const rel = normalizeAceTraceRelativePath(path58.relative(contextDir2, abs));
|
|
27800
28349
|
const v = validateAceJsonFile(abs, traceSchema);
|
|
27801
28350
|
if (!v.ok) {
|
|
27802
28351
|
continue;
|
|
@@ -27811,7 +28360,7 @@ function listPendingAceTraceFiles(contextDir2, worktreeRoot) {
|
|
|
27811
28360
|
}
|
|
27812
28361
|
|
|
27813
28362
|
// src/analysis/aceAutoLearnPool.ts
|
|
27814
|
-
var
|
|
28363
|
+
var path59 = __toESM(require("path"));
|
|
27815
28364
|
function clampConcurrency2(n) {
|
|
27816
28365
|
if (!Number.isFinite(n)) {
|
|
27817
28366
|
return DEFAULT_MAX_CONCURRENT_AI;
|
|
@@ -27846,8 +28395,8 @@ async function runAceAutoLearnPool(p) {
|
|
|
27846
28395
|
};
|
|
27847
28396
|
const currentCap = () => Math.min(staticMaxC, adaptiveMax);
|
|
27848
28397
|
let wake;
|
|
27849
|
-
const waitTurn = () => new Promise((
|
|
27850
|
-
wake =
|
|
28398
|
+
const waitTurn = () => new Promise((resolve23) => {
|
|
28399
|
+
wake = resolve23;
|
|
27851
28400
|
});
|
|
27852
28401
|
const pump = () => {
|
|
27853
28402
|
wake?.();
|
|
@@ -27869,7 +28418,7 @@ async function runAceAutoLearnPool(p) {
|
|
|
27869
28418
|
poolAbortListenerRegistered = true;
|
|
27870
28419
|
}
|
|
27871
28420
|
}
|
|
27872
|
-
const traceRel = (abs) =>
|
|
28421
|
+
const traceRel = (abs) => path59.relative(contextDir2, abs).split(path59.sep).join("/");
|
|
27873
28422
|
const runOne = async (traceAbs) => {
|
|
27874
28423
|
if (abortSignal?.aborted) {
|
|
27875
28424
|
active -= 1;
|
|
@@ -27961,8 +28510,13 @@ function parseContextDriftTail(tail) {
|
|
|
27961
28510
|
let label;
|
|
27962
28511
|
let index;
|
|
27963
28512
|
let dryRun = false;
|
|
28513
|
+
let inPlace = false;
|
|
27964
28514
|
for (let i = 0; i < tail.length; i += 1) {
|
|
27965
28515
|
const a = tail[i] ?? "";
|
|
28516
|
+
if (a === "--no-worktree" || a === "--noworktree" || a === "--in-place") {
|
|
28517
|
+
inPlace = true;
|
|
28518
|
+
continue;
|
|
28519
|
+
}
|
|
27966
28520
|
if (a === "--label" && tail[i + 1]) {
|
|
27967
28521
|
label = tail[i + 1];
|
|
27968
28522
|
i += 1;
|
|
@@ -27979,7 +28533,7 @@ function parseContextDriftTail(tail) {
|
|
|
27979
28533
|
}
|
|
27980
28534
|
rest.push(a);
|
|
27981
28535
|
}
|
|
27982
|
-
return { label, index, dryRun, rest };
|
|
28536
|
+
return { label, index, dryRun, inPlace, rest };
|
|
27983
28537
|
}
|
|
27984
28538
|
function stripRootWorktreeTokens(tokens) {
|
|
27985
28539
|
const out = [...tokens];
|
|
@@ -28395,7 +28949,7 @@ function formatCliStderrLine(line, useAnsi) {
|
|
|
28395
28949
|
}
|
|
28396
28950
|
|
|
28397
28951
|
// src/cli/main.ts
|
|
28398
|
-
var PKG_VERSION = "0.
|
|
28952
|
+
var PKG_VERSION = "0.2.1";
|
|
28399
28953
|
function isNonEmptyFactoryFailureArray(x) {
|
|
28400
28954
|
if (!Array.isArray(x) || x.length === 0) {
|
|
28401
28955
|
return false;
|
|
@@ -28412,6 +28966,12 @@ function isNonEmptyFactoryFailureArray(x) {
|
|
|
28412
28966
|
}
|
|
28413
28967
|
return true;
|
|
28414
28968
|
}
|
|
28969
|
+
function processExitFromNormalizedFactoryFailures(rows) {
|
|
28970
|
+
return rows?.length ? rows[0].exitCode : OsExit.factoryUnknown;
|
|
28971
|
+
}
|
|
28972
|
+
function isContextDriftSrs70ValidationExit(code) {
|
|
28973
|
+
return code >= OsExit.driftEmptyBundle && code <= OsExit.driftIndexPatchFailed;
|
|
28974
|
+
}
|
|
28415
28975
|
function isEasyspecsConfigReadError(e) {
|
|
28416
28976
|
return e instanceof EasyspecsConfigInvalidJsonError || e instanceof EasyspecsConfigSchemaError;
|
|
28417
28977
|
}
|
|
@@ -28478,12 +29038,16 @@ function extractLegacyPositionals(argv) {
|
|
|
28478
29038
|
}
|
|
28479
29039
|
return [];
|
|
28480
29040
|
}
|
|
29041
|
+
function rewriteArgvForCommanderParse(argv) {
|
|
29042
|
+
return argv.map((t) => t === "--no-worktree" ? "--in-place" : t);
|
|
29043
|
+
}
|
|
28481
29044
|
function parseCliWithCommander(argv) {
|
|
28482
29045
|
const program2 = createEasyspecsCliProgram();
|
|
28483
29046
|
program2.version(PKG_VERSION, "--version", "output the version number");
|
|
28484
29047
|
program2.exitOverride();
|
|
29048
|
+
const rawArgv = [...argv];
|
|
28485
29049
|
try {
|
|
28486
|
-
program2.parse(
|
|
29050
|
+
program2.parse(rewriteArgvForCommanderParse(rawArgv), { from: "user" });
|
|
28487
29051
|
} catch (e) {
|
|
28488
29052
|
const code = e?.code;
|
|
28489
29053
|
if (code === "commander.helpDisplayed" || code === "commander.version") {
|
|
@@ -28506,7 +29070,7 @@ function parseCliWithCommander(argv) {
|
|
|
28506
29070
|
help: false,
|
|
28507
29071
|
version: false
|
|
28508
29072
|
};
|
|
28509
|
-
const positionals = extractLegacyPositionals(
|
|
29073
|
+
const positionals = extractLegacyPositionals(rawArgv);
|
|
28510
29074
|
return { flags, positionals };
|
|
28511
29075
|
}
|
|
28512
29076
|
function printHelp() {
|
|
@@ -28527,23 +29091,23 @@ function resolveAnalysisRoot(repoRoot, rootKind, worktreePath) {
|
|
|
28527
29091
|
return repoRoot;
|
|
28528
29092
|
}
|
|
28529
29093
|
const wt = worktreePath?.trim();
|
|
28530
|
-
if (wt &&
|
|
28531
|
-
return
|
|
29094
|
+
if (wt && fs63.existsSync(path60.join(wt, ".git"))) {
|
|
29095
|
+
return path60.resolve(wt);
|
|
28532
29096
|
}
|
|
28533
29097
|
throw new Error("worktree mode requires --worktree <path> to an existing analysis checkout.");
|
|
28534
29098
|
}
|
|
28535
29099
|
function resolveAdHocCheckoutRoot(_repoRoot, storage, worktreeFlag) {
|
|
28536
29100
|
const w = worktreeFlag?.trim();
|
|
28537
29101
|
if (w) {
|
|
28538
|
-
const abs =
|
|
28539
|
-
if (
|
|
29102
|
+
const abs = path60.resolve(w);
|
|
29103
|
+
if (fs63.existsSync(path60.join(abs, ".git"))) {
|
|
28540
29104
|
return abs;
|
|
28541
29105
|
}
|
|
28542
29106
|
throw new Error(`Invalid --worktree (not a git checkout): ${abs}`);
|
|
28543
29107
|
}
|
|
28544
29108
|
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
28545
29109
|
const p = snap?.adHocWorktreePath?.trim();
|
|
28546
|
-
if (p &&
|
|
29110
|
+
if (p && fs63.existsSync(path60.join(p, ".git"))) {
|
|
28547
29111
|
return p;
|
|
28548
29112
|
}
|
|
28549
29113
|
throw new Error("No analysis checkout: run `easyspecs-cli run synthesis` first or pass `--worktree <path>`.");
|
|
@@ -28570,7 +29134,7 @@ async function runResumeRemediationPool(storage, repoRoot, analysisRoot, merged,
|
|
|
28570
29134
|
requireOpenCode(merged, flags);
|
|
28571
29135
|
const agentsDir = resolveOpenCodeAgentsDir(repoRoot, repoConfig);
|
|
28572
29136
|
assertAgentsDirExists(agentsDir);
|
|
28573
|
-
const ctxDir =
|
|
29137
|
+
const ctxDir = path60.join(analysisRoot, ".gluecharm", "context");
|
|
28574
29138
|
const snap = readArtefactRunSnapshot(storage);
|
|
28575
29139
|
const rows = listMissingWorkstations(ctxDir, analysisRoot, snap);
|
|
28576
29140
|
if (rows.length === 0) {
|
|
@@ -28588,7 +29152,7 @@ async function runResumeRemediationPool(storage, repoRoot, analysisRoot, merged,
|
|
|
28588
29152
|
storageContext: storage,
|
|
28589
29153
|
repositoryRoot: repoRoot,
|
|
28590
29154
|
worktreeRoot: analysisRoot,
|
|
28591
|
-
workspaceLabel:
|
|
29155
|
+
workspaceLabel: path60.basename(analysisRoot),
|
|
28592
29156
|
oc,
|
|
28593
29157
|
log: (line) => logErr(flags, line),
|
|
28594
29158
|
abortSignal: void 0,
|
|
@@ -28765,17 +29329,17 @@ async function main() {
|
|
|
28765
29329
|
{ easyspecs: { defaultGitRemoteUrl: url } },
|
|
28766
29330
|
{ warnMigration: (m) => logErr(flags, `[EasySpecs] ${m}`) }
|
|
28767
29331
|
);
|
|
28768
|
-
const
|
|
29332
|
+
const path61 = easyspecsConfigPath(repoRoot);
|
|
28769
29333
|
if (flags.json) {
|
|
28770
29334
|
printJsonLine({
|
|
28771
29335
|
command: "config set-git-remote",
|
|
28772
29336
|
durationMs: Date.now() - t0,
|
|
28773
29337
|
ok: true,
|
|
28774
|
-
path:
|
|
29338
|
+
path: path61,
|
|
28775
29339
|
defaultGitRemoteUrl: cfg.easyspecs?.defaultGitRemoteUrl ?? ""
|
|
28776
29340
|
});
|
|
28777
29341
|
} else {
|
|
28778
|
-
console.log(`Updated ${
|
|
29342
|
+
console.log(`Updated ${path61} \u2014 easyspecs.defaultGitRemoteUrl`);
|
|
28779
29343
|
}
|
|
28780
29344
|
process.exit(ExitCode.ok);
|
|
28781
29345
|
} catch (e) {
|
|
@@ -28808,7 +29372,7 @@ async function main() {
|
|
|
28808
29372
|
applyCliSessionPathFromRepoConfig(repoRoot, repoConfig);
|
|
28809
29373
|
if (flags.sessionPath?.trim()) {
|
|
28810
29374
|
const sp = flags.sessionPath.trim();
|
|
28811
|
-
const abs =
|
|
29375
|
+
const abs = path60.isAbsolute(sp) ? path60.normalize(sp) : path60.resolve(repoRoot, sp);
|
|
28812
29376
|
setCliSessionPathFromConfig(abs);
|
|
28813
29377
|
}
|
|
28814
29378
|
const apiResolved = initApiBaseUrlForCli(repoRoot, flags, repoConfig);
|
|
@@ -28865,20 +29429,18 @@ async function main() {
|
|
|
28865
29429
|
logExitCodeSummary(ExitCode.usage, flags);
|
|
28866
29430
|
process.exit(ExitCode.usage);
|
|
28867
29431
|
}
|
|
28868
|
-
const
|
|
28869
|
-
|
|
28870
|
-
|
|
28871
|
-
|
|
28872
|
-
|
|
28873
|
-
|
|
28874
|
-
|
|
28875
|
-
|
|
28876
|
-
|
|
28877
|
-
|
|
28878
|
-
|
|
28879
|
-
|
|
28880
|
-
`agentsDir=${agentsDir} exists=${String(agentsOk)}`
|
|
28881
|
-
];
|
|
29432
|
+
const readinessCtx = {
|
|
29433
|
+
cliVersion: PKG_VERSION,
|
|
29434
|
+
repoRootAbs: repoRoot,
|
|
29435
|
+
analysisRootAbs: repoRoot,
|
|
29436
|
+
apiBaseUrl: merged.apiBaseUrl,
|
|
29437
|
+
openCodeExecutable: merged.openCodeExecutable,
|
|
29438
|
+
openCodeSkipCredentialsCheck: merged.openCodeSkipCredentialsCheck,
|
|
29439
|
+
providerEnvFromConfig: merged.openCodeChildEnv,
|
|
29440
|
+
repoConfig
|
|
29441
|
+
};
|
|
29442
|
+
const facts = buildReadinessProbeFacts(readinessCtx);
|
|
29443
|
+
const lines = buildReadinessLineBlock(facts, readinessCtx);
|
|
28882
29444
|
const inspectPayload = buildDoctorInspectPayload(merged, repoConfig);
|
|
28883
29445
|
if (!flags.json) {
|
|
28884
29446
|
const parts = [];
|
|
@@ -28894,6 +29456,12 @@ async function main() {
|
|
|
28894
29456
|
if (modes.readiness) {
|
|
28895
29457
|
envelope.lines = lines;
|
|
28896
29458
|
envelope.cliVersion = PKG_VERSION;
|
|
29459
|
+
const jf = buildReadinessJsonFields(facts);
|
|
29460
|
+
envelope.modelConfigured = jf.modelConfigured;
|
|
29461
|
+
envelope.credentialsReady = jf.credentialsReady;
|
|
29462
|
+
envelope.openCodeConfigFiles = jf.openCodeConfigFiles;
|
|
29463
|
+
envelope.agentsDir = jf.agentsDir;
|
|
29464
|
+
envelope.agentsDirExists = jf.agentsDirExists;
|
|
28897
29465
|
}
|
|
28898
29466
|
if (modes.inspectConfig) {
|
|
28899
29467
|
envelope.config = inspectPayload;
|
|
@@ -29012,7 +29580,7 @@ async function main() {
|
|
|
29012
29580
|
finish(ExitCode.cancelled, { ok: false, error: "Remediation cancelled.", analysisWorktreePath: analysisRoot });
|
|
29013
29581
|
}
|
|
29014
29582
|
if (!poolRes.indexOk) {
|
|
29015
|
-
finish(
|
|
29583
|
+
finish(OsExit.resumeSynthesisIndex, {
|
|
29016
29584
|
ok: false,
|
|
29017
29585
|
error: poolRes.indexError ?? "Index failed after remediation.",
|
|
29018
29586
|
analysisWorktreePath: analysisRoot
|
|
@@ -29029,7 +29597,7 @@ async function main() {
|
|
|
29029
29597
|
finish(ExitCode.cancelled, { ok: false, error: "Remediation cancelled.", analysisWorktreePath: analysisRoot });
|
|
29030
29598
|
}
|
|
29031
29599
|
if (!poolRes.indexOk) {
|
|
29032
|
-
finish(
|
|
29600
|
+
finish(OsExit.resumeSynthesisIndex, {
|
|
29033
29601
|
ok: false,
|
|
29034
29602
|
error: poolRes.indexError ?? "Index failed after remediation.",
|
|
29035
29603
|
analysisWorktreePath: analysisRoot
|
|
@@ -29045,7 +29613,7 @@ async function main() {
|
|
|
29045
29613
|
const result = await runSynthesisPipeline(
|
|
29046
29614
|
storage,
|
|
29047
29615
|
repoRoot,
|
|
29048
|
-
|
|
29616
|
+
path60.basename(repoRoot),
|
|
29049
29617
|
agentsDir,
|
|
29050
29618
|
{
|
|
29051
29619
|
...merged.pipelineOpenCode
|
|
@@ -29082,7 +29650,7 @@ async function main() {
|
|
|
29082
29650
|
adHocCreatedAtIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
29083
29651
|
});
|
|
29084
29652
|
}
|
|
29085
|
-
finish(result.cancelled ? ExitCode.cancelled :
|
|
29653
|
+
finish(result.cancelled ? ExitCode.cancelled : OsExit.runSynthesisPipeline, {
|
|
29086
29654
|
ok: false,
|
|
29087
29655
|
error: result.error ?? "run synthesis failed",
|
|
29088
29656
|
cancelled: result.cancelled === true,
|
|
@@ -29100,7 +29668,7 @@ async function main() {
|
|
|
29100
29668
|
if (sub === "reference-coverage") {
|
|
29101
29669
|
const rootAbs = resolveAnalysisRoot(repoRoot, rootKind, worktree);
|
|
29102
29670
|
requireMinimalGluecharmLayoutAt(rootAbs);
|
|
29103
|
-
const contextDir2 =
|
|
29671
|
+
const contextDir2 = path60.join(rootAbs, ".gluecharm", "context");
|
|
29104
29672
|
const res = runCoveragePipeline({
|
|
29105
29673
|
repositoryRootAbs: rootAbs,
|
|
29106
29674
|
contextDirAbs: contextDir2,
|
|
@@ -29110,20 +29678,20 @@ async function main() {
|
|
|
29110
29678
|
const d = res.document;
|
|
29111
29679
|
const maxPct = repoConfig.easyspecs?.diagnose?.zeroReference?.maxPercentNonReferenced;
|
|
29112
29680
|
if (maxPct !== null && maxPct !== void 0 && Number.isFinite(maxPct) && d.metrics.percentNonReferenced > maxPct) {
|
|
29113
|
-
finish(
|
|
29681
|
+
finish(OsExit.diagnoseReferenceCoverageThreshold, {
|
|
29114
29682
|
ok: false,
|
|
29115
29683
|
error: `percentNonReferenced ${String(d.metrics.percentNonReferenced)} > ${String(maxPct)}`
|
|
29116
29684
|
});
|
|
29117
29685
|
}
|
|
29118
29686
|
finish(ExitCode.ok, { ok: true, percentNonReferenced: d.metrics.percentNonReferenced });
|
|
29119
29687
|
} else {
|
|
29120
|
-
finish(
|
|
29688
|
+
finish(OsExit.diagnoseReferenceCoveragePipeline, { ok: false, error: res.error ?? "coverage failed" });
|
|
29121
29689
|
}
|
|
29122
29690
|
}
|
|
29123
29691
|
if (sub === "coordination-duplicates") {
|
|
29124
29692
|
const rootAbs = resolveAnalysisRoot(repoRoot, rootKind, worktree);
|
|
29125
29693
|
requireMinimalGluecharmLayoutAt(rootAbs);
|
|
29126
|
-
const contextDir2 =
|
|
29694
|
+
const contextDir2 = path60.join(rootAbs, ".gluecharm", "context");
|
|
29127
29695
|
const res = runCoordinationDuplicatesDiagnosis({
|
|
29128
29696
|
contextDirAbsolute: contextDir2,
|
|
29129
29697
|
sourceRoot: rootKind === "worktree" ? "worktree" : "workspace"
|
|
@@ -29131,7 +29699,7 @@ async function main() {
|
|
|
29131
29699
|
if (res.ok) {
|
|
29132
29700
|
const strict = repoConfig.easyspecs?.diagnose?.coordinationDuplicates?.strict !== false;
|
|
29133
29701
|
const bad = strict && ((res.groupCount ?? 0) > 0 || (res.orphanMarkdownCount ?? 0) > 0);
|
|
29134
|
-
finish(bad ?
|
|
29702
|
+
finish(bad ? OsExit.diagnoseCoordinationDuplicatesPolicy : ExitCode.ok, {
|
|
29135
29703
|
ok: !bad,
|
|
29136
29704
|
groupCount: res.groupCount,
|
|
29137
29705
|
orphanMarkdownCount: res.orphanMarkdownCount,
|
|
@@ -29141,7 +29709,7 @@ async function main() {
|
|
|
29141
29709
|
groupsByList: res.groupsByList
|
|
29142
29710
|
});
|
|
29143
29711
|
}
|
|
29144
|
-
finish(
|
|
29712
|
+
finish(OsExit.diagnoseCoordinationDuplicatesEngine, { ok: false, error: res.message ?? "duplicates failed" });
|
|
29145
29713
|
}
|
|
29146
29714
|
if (sub === "coverage-report") {
|
|
29147
29715
|
const rootAbs = resolveAnalysisRoot(repoRoot, rootKind, worktree);
|
|
@@ -29153,13 +29721,13 @@ async function main() {
|
|
|
29153
29721
|
if (rep.ok) {
|
|
29154
29722
|
finish(ExitCode.ok, { ok: true, reportPath: rep.outputAbsolutePath });
|
|
29155
29723
|
} else {
|
|
29156
|
-
finish(
|
|
29724
|
+
finish(OsExit.diagnoseCoverageReport, { ok: false, error: rep.error ?? "report failed" });
|
|
29157
29725
|
}
|
|
29158
29726
|
}
|
|
29159
29727
|
if (sub === "missing-artefacts") {
|
|
29160
29728
|
const rootAbs = resolveAnalysisRoot(repoRoot, rootKind, worktree);
|
|
29161
29729
|
requireMinimalGluecharmLayoutAt(rootAbs);
|
|
29162
|
-
const ctxDir =
|
|
29730
|
+
const ctxDir = path60.join(rootAbs, ".gluecharm", "context");
|
|
29163
29731
|
const storage = createFileBackedWorkspaceState(repoRoot);
|
|
29164
29732
|
const snap = readArtefactRunSnapshot(storage);
|
|
29165
29733
|
const rows = listMissingWorkstations(ctxDir, rootAbs, snap);
|
|
@@ -29183,7 +29751,7 @@ async function main() {
|
|
|
29183
29751
|
requireMinimalGluecharmLayoutAt(analysisRoot);
|
|
29184
29752
|
const cov = readNonReferencedFilesFromRepositoryRoot(analysisRoot);
|
|
29185
29753
|
if (!cov.ok) {
|
|
29186
|
-
finish(
|
|
29754
|
+
finish(OsExit.diagnoseZeroReferenceReadCoverage, { ok: false, error: cov.error });
|
|
29187
29755
|
} else {
|
|
29188
29756
|
const zrPaths = cov.paths;
|
|
29189
29757
|
if (zrPaths.length === 0) {
|
|
@@ -29209,10 +29777,10 @@ async function main() {
|
|
|
29209
29777
|
});
|
|
29210
29778
|
const bad = poolRes.cancelled || poolRes.failures > 0;
|
|
29211
29779
|
if (!bad) {
|
|
29212
|
-
const ctxDir =
|
|
29780
|
+
const ctxDir = path60.join(analysisRoot, ".gluecharm", "context");
|
|
29213
29781
|
const lg = runLinkMappingPipeline(ctxDir, { log: (line) => logErr(flags, line) });
|
|
29214
29782
|
if (!lg.ok) {
|
|
29215
|
-
finish(
|
|
29783
|
+
finish(OsExit.diagnoseZeroReferenceLinkMapping, {
|
|
29216
29784
|
ok: false,
|
|
29217
29785
|
completed: poolRes.completed,
|
|
29218
29786
|
failures: poolRes.failures,
|
|
@@ -29222,7 +29790,7 @@ async function main() {
|
|
|
29222
29790
|
});
|
|
29223
29791
|
}
|
|
29224
29792
|
}
|
|
29225
|
-
finish(bad ?
|
|
29793
|
+
finish(bad ? OsExit.diagnoseZeroReferencePool : ExitCode.ok, {
|
|
29226
29794
|
ok: !bad,
|
|
29227
29795
|
completed: poolRes.completed,
|
|
29228
29796
|
failures: poolRes.failures,
|
|
@@ -29239,12 +29807,12 @@ async function main() {
|
|
|
29239
29807
|
const worktree = wtExplicit ?? wtFromRoot;
|
|
29240
29808
|
const rootAbs = resolveAnalysisRoot(repoRoot, rootKind, worktree);
|
|
29241
29809
|
requireMinimalGluecharmLayoutAt(rootAbs);
|
|
29242
|
-
const contextDir2 =
|
|
29810
|
+
const contextDir2 = path60.join(rootAbs, ".gluecharm", "context");
|
|
29243
29811
|
const res = runLinkMappingPipeline(contextDir2, {
|
|
29244
29812
|
log: (line) => logErr(flags, line)
|
|
29245
29813
|
});
|
|
29246
29814
|
if (!res.ok) {
|
|
29247
|
-
finish(
|
|
29815
|
+
finish(OsExit.contextLinkGraph, {
|
|
29248
29816
|
ok: false,
|
|
29249
29817
|
contextDir: contextDir2,
|
|
29250
29818
|
error: res.error,
|
|
@@ -29258,10 +29826,19 @@ async function main() {
|
|
|
29258
29826
|
if (!refPath) {
|
|
29259
29827
|
finish(ExitCode.usage, {
|
|
29260
29828
|
ok: false,
|
|
29261
|
-
error: "Usage: easyspecs-cli context drift <referencePath> [--label <slug>] [--index <path>] [--dry-run]"
|
|
29829
|
+
error: "Usage: easyspecs-cli context drift <referencePath> [--label <slug>] [--index <path>] [--dry-run] [--in-place|--no-worktree|--noworktree]"
|
|
29262
29830
|
});
|
|
29263
29831
|
}
|
|
29264
29832
|
const parsedTail = parseContextDriftTail(pos.slice(3));
|
|
29833
|
+
const { rootKind, worktree: wtFromRoot } = parseTailFlags(parsedTail.rest);
|
|
29834
|
+
const { worktree: wtExplicit } = parseWorktreeFlag(parsedTail.rest);
|
|
29835
|
+
const extWorktree = wtExplicit ?? wtFromRoot;
|
|
29836
|
+
if (parsedTail.inPlace && (rootKind === "worktree" || typeof extWorktree === "string" && extWorktree.trim().length > 0)) {
|
|
29837
|
+
finish(ExitCode.usage, {
|
|
29838
|
+
ok: false,
|
|
29839
|
+
error: "`--no-worktree` cannot be combined with `--root worktree` or `--worktree <path>`."
|
|
29840
|
+
});
|
|
29841
|
+
}
|
|
29265
29842
|
const leftover = stripRootWorktreeTokens(parsedTail.rest);
|
|
29266
29843
|
if (leftover.length > 0) {
|
|
29267
29844
|
finish(ExitCode.usage, {
|
|
@@ -29270,11 +29847,11 @@ async function main() {
|
|
|
29270
29847
|
});
|
|
29271
29848
|
}
|
|
29272
29849
|
requireMinimalGluecharmLayoutAt(repoRoot);
|
|
29273
|
-
|
|
29274
|
-
|
|
29275
|
-
|
|
29850
|
+
const readinessLog = (line) => {
|
|
29851
|
+
process.stderr.write(`${line}
|
|
29852
|
+
`);
|
|
29853
|
+
};
|
|
29276
29854
|
const agentsDir = resolveOpenCodeAgentsDir(repoRoot, repoConfig);
|
|
29277
|
-
assertAgentsDirExists(agentsDir);
|
|
29278
29855
|
const storage = createFileBackedWorkspaceState(repoRoot);
|
|
29279
29856
|
const ctrl = new AbortController();
|
|
29280
29857
|
const dres = await runContextDriftFactory({
|
|
@@ -29287,8 +29864,11 @@ async function main() {
|
|
|
29287
29864
|
label: parsedTail.label,
|
|
29288
29865
|
indexOverrideArg: parsedTail.index,
|
|
29289
29866
|
dryRun: parsedTail.dryRun,
|
|
29867
|
+
inPlace: parsedTail.inPlace,
|
|
29290
29868
|
signal: ctrl.signal,
|
|
29291
|
-
log: (line) => logErr(flags, line)
|
|
29869
|
+
log: (line) => logErr(flags, line),
|
|
29870
|
+
cliVersion: PKG_VERSION,
|
|
29871
|
+
readinessLog
|
|
29292
29872
|
});
|
|
29293
29873
|
if (dres.exitOk && dres.ok) {
|
|
29294
29874
|
if (dres.driftReportPath && !flags.json && !dres.dryRun) {
|
|
@@ -29298,19 +29878,29 @@ async function main() {
|
|
|
29298
29878
|
finish(ExitCode.ok, driftPayload);
|
|
29299
29879
|
}
|
|
29300
29880
|
if (dres.ok === false) {
|
|
29301
|
-
|
|
29302
|
-
|
|
29303
|
-
|
|
29304
|
-
|
|
29305
|
-
|
|
29306
|
-
|
|
29307
|
-
|
|
29308
|
-
|
|
29309
|
-
}
|
|
29310
|
-
|
|
29311
|
-
|
|
29881
|
+
if (dres.code === "READINESS_FAILED") {
|
|
29882
|
+
const ec = dres.readinessExitCode ?? OsExit.readinessOpenCodeCredentials;
|
|
29883
|
+
const { exitOk: _ex, ...driftRest } = dres;
|
|
29884
|
+
finish(ec, {
|
|
29885
|
+
...driftRest,
|
|
29886
|
+
ok: false,
|
|
29887
|
+
exitCode: ec
|
|
29888
|
+
});
|
|
29889
|
+
} else {
|
|
29890
|
+
const row2 = contextDriftFactoryFailureRow(dres.code, dres.error);
|
|
29891
|
+
const driftExit = contextDriftExitCodeFor(dres.code, dres.error);
|
|
29892
|
+
const { exitOk: _driftOkB, ...driftRest } = dres;
|
|
29893
|
+
const envelope = {
|
|
29894
|
+
...driftRest,
|
|
29895
|
+
ok: false,
|
|
29896
|
+
factoryFailures: [row2],
|
|
29897
|
+
error: composeFactoryValidationError(dres.error, [row2])
|
|
29898
|
+
};
|
|
29899
|
+
if (isContextDriftSrs70ValidationExit(driftExit)) {
|
|
29900
|
+
Object.assign(envelope, primaryFailureAliases([row2]));
|
|
29901
|
+
}
|
|
29902
|
+
finish(driftExit, envelope);
|
|
29312
29903
|
}
|
|
29313
|
-
finish(driftExit, envelope);
|
|
29314
29904
|
}
|
|
29315
29905
|
finish(ExitCode.internal, { ok: false, error: "Unexpected context drift result shape." });
|
|
29316
29906
|
}
|
|
@@ -29319,6 +29909,9 @@ async function main() {
|
|
|
29319
29909
|
if (a === "--force-new-context-analysis") {
|
|
29320
29910
|
continue;
|
|
29321
29911
|
}
|
|
29912
|
+
if (a === "--no-worktree" || a === "--noworktree" || a === "--in-place") {
|
|
29913
|
+
continue;
|
|
29914
|
+
}
|
|
29322
29915
|
if (a === "--upload") {
|
|
29323
29916
|
finish(ExitCode.usage, {
|
|
29324
29917
|
ok: false,
|
|
@@ -29333,10 +29926,11 @@ async function main() {
|
|
|
29333
29926
|
}
|
|
29334
29927
|
finish(ExitCode.usage, {
|
|
29335
29928
|
ok: false,
|
|
29336
|
-
error: `unknown analysis flag: ${a} (allowed: --force-new-context-analysis)`
|
|
29929
|
+
error: `unknown analysis flag: ${a} (allowed: --force-new-context-analysis, --in-place, --no-worktree, --noworktree)`
|
|
29337
29930
|
});
|
|
29338
29931
|
}
|
|
29339
29932
|
const forceNewContextAnalysis = positionals.includes("--force-new-context-analysis");
|
|
29933
|
+
const analysisInPlace = positionals.includes("--no-worktree") || positionals.includes("--noworktree") || positionals.includes("--in-place");
|
|
29340
29934
|
const cloudCached = readEasyspecsMergedSetting(
|
|
29341
29935
|
repoConfig.easyspecs,
|
|
29342
29936
|
"easyspecs.factory.cloudContextAnalyzed"
|
|
@@ -29359,11 +29953,19 @@ async function main() {
|
|
|
29359
29953
|
});
|
|
29360
29954
|
}
|
|
29361
29955
|
requireMinimalGluecharmLayoutAt(repoRoot);
|
|
29362
|
-
requireOpenCode(merged, flags);
|
|
29363
29956
|
const agentsDir = resolveOpenCodeAgentsDir(repoRoot, repoConfig);
|
|
29364
|
-
assertAgentsDirExists(agentsDir);
|
|
29365
29957
|
const storage = createFileBackedWorkspaceState(repoRoot);
|
|
29366
29958
|
const ctrl = new AbortController();
|
|
29959
|
+
const analysisReadinessCtx = {
|
|
29960
|
+
cliVersion: PKG_VERSION,
|
|
29961
|
+
repoRootAbs: repoRoot,
|
|
29962
|
+
analysisRootAbs: repoRoot,
|
|
29963
|
+
apiBaseUrl: merged.apiBaseUrl,
|
|
29964
|
+
openCodeExecutable: merged.openCodeExecutable,
|
|
29965
|
+
openCodeSkipCredentialsCheck: merged.openCodeSkipCredentialsCheck,
|
|
29966
|
+
providerEnvFromConfig: merged.openCodeChildEnv,
|
|
29967
|
+
repoConfig
|
|
29968
|
+
};
|
|
29367
29969
|
const deps = buildFactoryDepsHeadless({
|
|
29368
29970
|
storageContext: storage,
|
|
29369
29971
|
repoRoot,
|
|
@@ -29374,15 +29976,22 @@ async function main() {
|
|
|
29374
29976
|
}),
|
|
29375
29977
|
log: (line) => logErr(flags, line),
|
|
29376
29978
|
signal: ctrl.signal,
|
|
29377
|
-
skipBackendSync: true
|
|
29979
|
+
skipBackendSync: true,
|
|
29980
|
+
inPlace: analysisInPlace,
|
|
29981
|
+
readiness: analysisReadinessCtx
|
|
29378
29982
|
});
|
|
29379
29983
|
const res = await runGenerateContextFactory(deps);
|
|
29380
29984
|
if (res.ok && res.cancelled !== true && flags.promote !== false) {
|
|
29381
29985
|
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
29382
29986
|
const wt = snap?.adHocWorktreePath?.trim();
|
|
29383
29987
|
if (wt) {
|
|
29384
|
-
const sourceCtx =
|
|
29385
|
-
if (
|
|
29988
|
+
const sourceCtx = path60.join(wt, ".gluecharm", "context");
|
|
29989
|
+
if (path60.resolve(wt) === path60.resolve(repoRoot)) {
|
|
29990
|
+
logErr(
|
|
29991
|
+
flags,
|
|
29992
|
+
"[pipeline:analysis] promote skipped (in-place: analysis checkout is the repository root)"
|
|
29993
|
+
);
|
|
29994
|
+
} else if (fs63.existsSync(sourceCtx)) {
|
|
29386
29995
|
const n = promoteContextDirectoryToWorkspaceFs(sourceCtx, repoRoot);
|
|
29387
29996
|
logErr(flags, `[pipeline:analysis] promoted ${String(n.filesCopied)} file(s) \u2192 ${repoRoot}`);
|
|
29388
29997
|
} else {
|
|
@@ -29402,16 +30011,24 @@ async function main() {
|
|
|
29402
30011
|
ok: res.ok,
|
|
29403
30012
|
cancelled: res.cancelled,
|
|
29404
30013
|
totalElapsedMs: res.totalElapsedMs,
|
|
29405
|
-
error: res.message
|
|
30014
|
+
error: res.message,
|
|
30015
|
+
...analysisInPlace ? { analysisInPlace: true } : {}
|
|
29406
30016
|
};
|
|
29407
30017
|
if (!res.ok && !res.cancelled && res.factoryFailures && res.factoryFailures.length > 0) {
|
|
29408
30018
|
analysisEnvelope.factoryFailures = res.factoryFailures;
|
|
29409
30019
|
Object.assign(analysisEnvelope, primaryFailureAliases(res.factoryFailures));
|
|
29410
30020
|
analysisEnvelope.error = composeFactoryValidationError(res.message, res.factoryFailures);
|
|
29411
30021
|
}
|
|
29412
|
-
|
|
30022
|
+
if (res.readinessFailure) {
|
|
30023
|
+
Object.assign(analysisEnvelope, res.readinessFailure);
|
|
30024
|
+
}
|
|
30025
|
+
finish(
|
|
30026
|
+
res.ok ? ExitCode.ok : res.cancelled ? ExitCode.cancelled : processExitFromNormalizedFactoryFailures(res.factoryFailures),
|
|
30027
|
+
analysisEnvelope
|
|
30028
|
+
);
|
|
29413
30029
|
}
|
|
29414
30030
|
if (pos[0] === "update" && pos[1] === "context") {
|
|
30031
|
+
let updateContextInPlace = false;
|
|
29415
30032
|
for (const a of pos.slice(2)) {
|
|
29416
30033
|
if (a === "--upload") {
|
|
29417
30034
|
finish(ExitCode.usage, {
|
|
@@ -29419,14 +30036,20 @@ async function main() {
|
|
|
29419
30036
|
error: "Removed flag: update context --upload. Run `easyspecs-cli upload context` or `upload republish` after update context completes."
|
|
29420
30037
|
});
|
|
29421
30038
|
}
|
|
30039
|
+
if (a === "--no-worktree" || a === "--noworktree" || a === "--in-place") {
|
|
30040
|
+
updateContextInPlace = true;
|
|
30041
|
+
continue;
|
|
30042
|
+
}
|
|
29422
30043
|
finish(ExitCode.usage, { ok: false, error: `unknown update context flag: ${a}` });
|
|
29423
30044
|
}
|
|
29424
30045
|
requireMinimalGluecharmLayoutAt(repoRoot);
|
|
29425
|
-
requireOpenCode(merged, flags);
|
|
29426
30046
|
const agentsDir = resolveOpenCodeAgentsDir(repoRoot, repoConfig);
|
|
29427
|
-
assertAgentsDirExists(agentsDir);
|
|
29428
30047
|
const storage = createFileBackedWorkspaceState(repoRoot);
|
|
29429
30048
|
const ctrl = new AbortController();
|
|
30049
|
+
const readinessLog = (line) => {
|
|
30050
|
+
process.stderr.write(`${line}
|
|
30051
|
+
`);
|
|
30052
|
+
};
|
|
29430
30053
|
const ures = await runUpdateContextFactory({
|
|
29431
30054
|
repoRootAbs: repoRoot,
|
|
29432
30055
|
repoConfig,
|
|
@@ -29434,10 +30057,13 @@ async function main() {
|
|
|
29434
30057
|
agentsDirFs: agentsDir,
|
|
29435
30058
|
storage,
|
|
29436
30059
|
signal: ctrl.signal,
|
|
29437
|
-
log: (line) => logErr(flags, line)
|
|
30060
|
+
log: (line) => logErr(flags, line),
|
|
30061
|
+
inPlace: updateContextInPlace,
|
|
30062
|
+
cliVersion: PKG_VERSION,
|
|
30063
|
+
readinessLog
|
|
29438
30064
|
});
|
|
29439
30065
|
const { exitOk, ...payload } = ures;
|
|
29440
|
-
const code = exitOk ? ExitCode.ok : ures.code === "MISSING_BASELINE" ? ExitCode.usage :
|
|
30066
|
+
const code = exitOk ? ExitCode.ok : ures.code === "MISSING_BASELINE" ? ExitCode.usage : ures.code === "READINESS_FAILED" && typeof ures.readinessExitCode === "number" ? ures.readinessExitCode : OsExit.updateContextFactory;
|
|
29441
30067
|
finish(code, payload);
|
|
29442
30068
|
}
|
|
29443
30069
|
if (pos[0] === "download" && pos[1] === "context") {
|
|
@@ -29462,10 +30088,10 @@ async function main() {
|
|
|
29462
30088
|
finish(ExitCode.usage, { ok: false, error: `unknown download context flag: ${a}` });
|
|
29463
30089
|
}
|
|
29464
30090
|
requireMinimalGluecharmLayoutAt(repoRoot);
|
|
29465
|
-
const ctxDir =
|
|
29466
|
-
const gluecharmParent =
|
|
29467
|
-
if (
|
|
29468
|
-
requireMinimalGluecharmLayoutAt(
|
|
30091
|
+
const ctxDir = path60.resolve(path60.join(repoRoot, ".gluecharm", "context"));
|
|
30092
|
+
const gluecharmParent = path60.dirname(ctxDir);
|
|
30093
|
+
if (path60.basename(gluecharmParent) === ".gluecharm" && path60.basename(ctxDir) === "context") {
|
|
30094
|
+
requireMinimalGluecharmLayoutAt(path60.dirname(gluecharmParent));
|
|
29469
30095
|
}
|
|
29470
30096
|
const appIdRaw = getEasyspecsProjectIdFromRepoConfig(repoConfig)?.trim();
|
|
29471
30097
|
if (!appIdRaw) {
|
|
@@ -29548,16 +30174,16 @@ async function main() {
|
|
|
29548
30174
|
}
|
|
29549
30175
|
const sess = sessRaw;
|
|
29550
30176
|
requireMinimalGluecharmLayoutAt(repoRoot);
|
|
29551
|
-
let ctxDir =
|
|
30177
|
+
let ctxDir = path60.join(repoRoot, ".gluecharm", "context");
|
|
29552
30178
|
if (pos[1] === "republish") {
|
|
29553
30179
|
const fromCfg = repoConfig.easyspecs?.upload?.contextDirectory?.trim();
|
|
29554
|
-
const resolvedOverride = fromCfg && fromCfg.length > 0 ?
|
|
29555
|
-
if (resolvedOverride &&
|
|
30180
|
+
const resolvedOverride = fromCfg && fromCfg.length > 0 ? path60.isAbsolute(fromCfg) ? path60.normalize(fromCfg) : path60.resolve(repoRoot, fromCfg) : "";
|
|
30181
|
+
if (resolvedOverride && fs63.existsSync(path60.join(resolvedOverride, ".."))) {
|
|
29556
30182
|
ctxDir = resolvedOverride;
|
|
29557
30183
|
} else {
|
|
29558
30184
|
const storage = createFileBackedWorkspaceState(repoRoot);
|
|
29559
30185
|
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
29560
|
-
const wt = snap?.adHocWorktreePath &&
|
|
30186
|
+
const wt = snap?.adHocWorktreePath && fs63.existsSync(path60.join(snap.adHocWorktreePath, ".gluecharm", "context")) ? path60.join(snap.adHocWorktreePath, ".gluecharm", "context") : "";
|
|
29561
30187
|
if (!wt) {
|
|
29562
30188
|
finish(ExitCode.misconfiguration, {
|
|
29563
30189
|
ok: false,
|
|
@@ -29567,10 +30193,10 @@ async function main() {
|
|
|
29567
30193
|
ctxDir = wt;
|
|
29568
30194
|
}
|
|
29569
30195
|
}
|
|
29570
|
-
const ctxResolved =
|
|
29571
|
-
const gluecharmParent =
|
|
29572
|
-
if (
|
|
29573
|
-
requireMinimalGluecharmLayoutAt(
|
|
30196
|
+
const ctxResolved = path60.resolve(ctxDir);
|
|
30197
|
+
const gluecharmParent = path60.dirname(ctxResolved);
|
|
30198
|
+
if (path60.basename(gluecharmParent) === ".gluecharm" && path60.basename(ctxResolved) === "context") {
|
|
30199
|
+
requireMinimalGluecharmLayoutAt(path60.dirname(gluecharmParent));
|
|
29574
30200
|
}
|
|
29575
30201
|
const appIdRaw = getEasyspecsProjectIdFromRepoConfig(repoConfig)?.trim();
|
|
29576
30202
|
if (!appIdRaw) {
|
|
@@ -29674,18 +30300,18 @@ async function main() {
|
|
|
29674
30300
|
finish(failed ? ExitCode.upload : ExitCode.ok, primary);
|
|
29675
30301
|
}
|
|
29676
30302
|
if (pos[0] === "ace" && pos[1] === "clear") {
|
|
29677
|
-
const learnings =
|
|
29678
|
-
if (!
|
|
30303
|
+
const learnings = path60.join(repoRoot, ".gluecharm", "context", "learnings");
|
|
30304
|
+
if (!fs63.existsSync(learnings)) {
|
|
29679
30305
|
finish(ExitCode.ok, { ok: true, message: "nothing to clear" });
|
|
29680
30306
|
}
|
|
29681
|
-
|
|
30307
|
+
fs63.rmSync(learnings, { recursive: true, force: true });
|
|
29682
30308
|
finish(ExitCode.ok, { ok: true, message: `cleared ${learnings}` });
|
|
29683
30309
|
}
|
|
29684
30310
|
if (pos[0] === "ace" && pos[1] === "learn") {
|
|
29685
30311
|
requireOpenCode(merged, flags);
|
|
29686
30312
|
const { worktree } = parseWorktreeFlag(pos.slice(2));
|
|
29687
|
-
const root = worktree &&
|
|
29688
|
-
const contextDir2 =
|
|
30313
|
+
const root = worktree && fs63.existsSync(path60.join(worktree, ".opencode", "schemas", "ace")) ? worktree : repoRoot;
|
|
30314
|
+
const contextDir2 = path60.join(root, ".gluecharm", "context");
|
|
29689
30315
|
const traces = listAceTraceFiles(contextDir2);
|
|
29690
30316
|
if (traces.length === 0) {
|
|
29691
30317
|
finish(ExitCode.ok, { ok: true, message: "no traces", traceCount: 0 });
|
|
@@ -29700,7 +30326,7 @@ async function main() {
|
|
|
29700
30326
|
diagnosticLog: (line) => logErr(flags, line)
|
|
29701
30327
|
});
|
|
29702
30328
|
if (!res.ok) {
|
|
29703
|
-
finish(
|
|
30329
|
+
finish(OsExit.aceLearnTrace, { ok: false, error: res.message });
|
|
29704
30330
|
}
|
|
29705
30331
|
okCount += 1;
|
|
29706
30332
|
}
|
|
@@ -29709,8 +30335,8 @@ async function main() {
|
|
|
29709
30335
|
if (pos[0] === "ace" && pos[1] === "auto-learn") {
|
|
29710
30336
|
requireOpenCode(merged, flags);
|
|
29711
30337
|
const { worktree } = parseWorktreeFlag(pos.slice(2));
|
|
29712
|
-
const root = worktree &&
|
|
29713
|
-
const contextDir2 =
|
|
30338
|
+
const root = worktree && fs63.existsSync(path60.join(worktree, ".git")) ? worktree : repoRoot;
|
|
30339
|
+
const contextDir2 = path60.join(root, ".gluecharm", "context");
|
|
29714
30340
|
const pending = listPendingAceTraceFiles(contextDir2, root);
|
|
29715
30341
|
if (pending.length === 0) {
|
|
29716
30342
|
finish(ExitCode.ok, { ok: true, pending: 0 });
|
|
@@ -29726,7 +30352,7 @@ async function main() {
|
|
|
29726
30352
|
diagnosticLog: (line) => logErr(flags, line)
|
|
29727
30353
|
}
|
|
29728
30354
|
});
|
|
29729
|
-
finish(pool.failed ?
|
|
30355
|
+
finish(pool.failed ? OsExit.aceAutoLearnPool : ExitCode.ok, {
|
|
29730
30356
|
ok: pool.failed === 0,
|
|
29731
30357
|
completed: pool.completed,
|
|
29732
30358
|
failed: pool.failed,
|