@gluecharm-lab/easyspecs-cli 0.3.5 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/commands.md +4 -4
- package/dist/main.cjs +1655 -513
- package/dist/main.cjs.map +4 -4
- package/package.json +1 -1
- package/resources/opencode-agents/agent-list-infrastructure-components.md +187 -0
- package/resources/opencode-agents/agent-list-infrastructure.md +222 -0
- package/resources/opencode-agents/agent-list-qa-test-cases.md +187 -0
- package/resources/opencode-agents/agent-list-qa.md +222 -0
- package/resources/opencode-agents/agent-md-infrastructure-component-detail.md +165 -0
- package/resources/opencode-agents/agent-md-infrastructure-detail.md +95 -0
- package/resources/opencode-agents/agent-md-qa-detail.md +95 -0
- package/resources/opencode-agents/agent-md-qa-test-case-detail.md +165 -0
- package/resources/opencode-agents/agent-review-infrastructure-components-list.md +34 -0
- package/resources/opencode-agents/agent-review-infrastructure-list.md +60 -0
- package/resources/opencode-agents/agent-review-qa-list.md +60 -0
- package/resources/opencode-agents/agent-review-qa-test-cases-list.md +34 -0
- package/resources/schemas/context-lists/features-list.schema.json +2 -2
- package/resources/schemas/context-lists/infrastructure-components-list.schema.json +175 -0
- package/resources/schemas/context-lists/infrastructure-list.schema.json +179 -0
- package/resources/schemas/context-lists/qa-list.schema.json +187 -0
- package/resources/schemas/context-lists/qa-test-cases-list.schema.json +180 -0
- package/resources/schemas/context-lists/zero-reference-classifier-record.schema.json +2 -0
- package/resources/schemas/context-lists/zero-reference-routing.schema.json +2 -0
- package/resources/schemas/context-lists/zero-reference-triage-record.schema.json +4 -4
- package/resources/schemas/index-application-context.schema.json +9 -3
package/dist/main.cjs
CHANGED
|
@@ -6,9 +6,16 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __esm = (fn, res) => function __init() {
|
|
10
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
|
+
};
|
|
9
12
|
var __commonJS = (cb, mod) => function __require() {
|
|
10
13
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
14
|
};
|
|
15
|
+
var __export = (target, all) => {
|
|
16
|
+
for (var name in all)
|
|
17
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
18
|
+
};
|
|
12
19
|
var __copyProps = (to, from, except, desc) => {
|
|
13
20
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
21
|
for (let key of __getOwnPropNames(from))
|
|
@@ -959,8 +966,8 @@ var require_command = __commonJS({
|
|
|
959
966
|
"node_modules/commander/lib/command.js"(exports2) {
|
|
960
967
|
var EventEmitter = require("node:events").EventEmitter;
|
|
961
968
|
var childProcess = require("node:child_process");
|
|
962
|
-
var
|
|
963
|
-
var
|
|
969
|
+
var path64 = require("node:path");
|
|
970
|
+
var fs65 = require("node:fs");
|
|
964
971
|
var process2 = require("node:process");
|
|
965
972
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
966
973
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -1892,11 +1899,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1892
1899
|
let launchWithNode = false;
|
|
1893
1900
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1894
1901
|
function findFile(baseDir, baseName) {
|
|
1895
|
-
const localBin =
|
|
1896
|
-
if (
|
|
1897
|
-
if (sourceExt.includes(
|
|
1902
|
+
const localBin = path64.resolve(baseDir, baseName);
|
|
1903
|
+
if (fs65.existsSync(localBin)) return localBin;
|
|
1904
|
+
if (sourceExt.includes(path64.extname(baseName))) return void 0;
|
|
1898
1905
|
const foundExt = sourceExt.find(
|
|
1899
|
-
(ext) =>
|
|
1906
|
+
(ext) => fs65.existsSync(`${localBin}${ext}`)
|
|
1900
1907
|
);
|
|
1901
1908
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1902
1909
|
return void 0;
|
|
@@ -1908,21 +1915,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1908
1915
|
if (this._scriptPath) {
|
|
1909
1916
|
let resolvedScriptPath;
|
|
1910
1917
|
try {
|
|
1911
|
-
resolvedScriptPath =
|
|
1918
|
+
resolvedScriptPath = fs65.realpathSync(this._scriptPath);
|
|
1912
1919
|
} catch (err) {
|
|
1913
1920
|
resolvedScriptPath = this._scriptPath;
|
|
1914
1921
|
}
|
|
1915
|
-
executableDir =
|
|
1916
|
-
|
|
1922
|
+
executableDir = path64.resolve(
|
|
1923
|
+
path64.dirname(resolvedScriptPath),
|
|
1917
1924
|
executableDir
|
|
1918
1925
|
);
|
|
1919
1926
|
}
|
|
1920
1927
|
if (executableDir) {
|
|
1921
1928
|
let localFile = findFile(executableDir, executableFile);
|
|
1922
1929
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
1923
|
-
const legacyName =
|
|
1930
|
+
const legacyName = path64.basename(
|
|
1924
1931
|
this._scriptPath,
|
|
1925
|
-
|
|
1932
|
+
path64.extname(this._scriptPath)
|
|
1926
1933
|
);
|
|
1927
1934
|
if (legacyName !== this._name) {
|
|
1928
1935
|
localFile = findFile(
|
|
@@ -1933,7 +1940,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1933
1940
|
}
|
|
1934
1941
|
executableFile = localFile || executableFile;
|
|
1935
1942
|
}
|
|
1936
|
-
launchWithNode = sourceExt.includes(
|
|
1943
|
+
launchWithNode = sourceExt.includes(path64.extname(executableFile));
|
|
1937
1944
|
let proc;
|
|
1938
1945
|
if (process2.platform !== "win32") {
|
|
1939
1946
|
if (launchWithNode) {
|
|
@@ -2773,7 +2780,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2773
2780
|
* @return {Command}
|
|
2774
2781
|
*/
|
|
2775
2782
|
nameFromFilename(filename) {
|
|
2776
|
-
this._name =
|
|
2783
|
+
this._name = path64.basename(filename, path64.extname(filename));
|
|
2777
2784
|
return this;
|
|
2778
2785
|
}
|
|
2779
2786
|
/**
|
|
@@ -2787,9 +2794,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2787
2794
|
* @param {string} [path]
|
|
2788
2795
|
* @return {(string|null|Command)}
|
|
2789
2796
|
*/
|
|
2790
|
-
executableDir(
|
|
2791
|
-
if (
|
|
2792
|
-
this._executableDir =
|
|
2797
|
+
executableDir(path65) {
|
|
2798
|
+
if (path65 === void 0) return this._executableDir;
|
|
2799
|
+
this._executableDir = path65;
|
|
2793
2800
|
return this;
|
|
2794
2801
|
}
|
|
2795
2802
|
/**
|
|
@@ -5993,7 +6000,7 @@ var require_compile = __commonJS({
|
|
|
5993
6000
|
const schOrFunc = root.refs[ref];
|
|
5994
6001
|
if (schOrFunc)
|
|
5995
6002
|
return schOrFunc;
|
|
5996
|
-
let _sch =
|
|
6003
|
+
let _sch = resolve25.call(this, root, ref);
|
|
5997
6004
|
if (_sch === void 0) {
|
|
5998
6005
|
const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
5999
6006
|
const { schemaId } = this.opts;
|
|
@@ -6020,7 +6027,7 @@ var require_compile = __commonJS({
|
|
|
6020
6027
|
function sameSchemaEnv(s1, s2) {
|
|
6021
6028
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
6022
6029
|
}
|
|
6023
|
-
function
|
|
6030
|
+
function resolve25(root, ref) {
|
|
6024
6031
|
let sch;
|
|
6025
6032
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
6026
6033
|
ref = sch;
|
|
@@ -6235,8 +6242,8 @@ var require_utils = __commonJS({
|
|
|
6235
6242
|
}
|
|
6236
6243
|
return ind;
|
|
6237
6244
|
}
|
|
6238
|
-
function removeDotSegments(
|
|
6239
|
-
let input =
|
|
6245
|
+
function removeDotSegments(path64) {
|
|
6246
|
+
let input = path64;
|
|
6240
6247
|
const output = [];
|
|
6241
6248
|
let nextSlash = -1;
|
|
6242
6249
|
let len = 0;
|
|
@@ -6435,8 +6442,8 @@ var require_schemes = __commonJS({
|
|
|
6435
6442
|
wsComponent.secure = void 0;
|
|
6436
6443
|
}
|
|
6437
6444
|
if (wsComponent.resourceName) {
|
|
6438
|
-
const [
|
|
6439
|
-
wsComponent.path =
|
|
6445
|
+
const [path64, query] = wsComponent.resourceName.split("?");
|
|
6446
|
+
wsComponent.path = path64 && path64 !== "/" ? path64 : void 0;
|
|
6440
6447
|
wsComponent.query = query;
|
|
6441
6448
|
wsComponent.resourceName = void 0;
|
|
6442
6449
|
}
|
|
@@ -6595,7 +6602,7 @@ var require_fast_uri = __commonJS({
|
|
|
6595
6602
|
}
|
|
6596
6603
|
return uri;
|
|
6597
6604
|
}
|
|
6598
|
-
function
|
|
6605
|
+
function resolve25(baseURI, relativeURI, options) {
|
|
6599
6606
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
6600
6607
|
const resolved = resolveComponent(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
6601
6608
|
schemelessOptions.skipEscape = true;
|
|
@@ -6822,7 +6829,7 @@ var require_fast_uri = __commonJS({
|
|
|
6822
6829
|
var fastUri = {
|
|
6823
6830
|
SCHEMES,
|
|
6824
6831
|
normalize: normalize9,
|
|
6825
|
-
resolve:
|
|
6832
|
+
resolve: resolve25,
|
|
6826
6833
|
resolveComponent,
|
|
6827
6834
|
equal,
|
|
6828
6835
|
serialize,
|
|
@@ -10622,12 +10629,12 @@ var require_dist = __commonJS({
|
|
|
10622
10629
|
throw new Error(`Unknown format "${name}"`);
|
|
10623
10630
|
return f;
|
|
10624
10631
|
};
|
|
10625
|
-
function addFormats2(ajv2, list,
|
|
10632
|
+
function addFormats2(ajv2, list, fs65, exportName) {
|
|
10626
10633
|
var _a;
|
|
10627
10634
|
var _b;
|
|
10628
10635
|
(_a = (_b = ajv2.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
10629
10636
|
for (const f of list)
|
|
10630
|
-
ajv2.addFormat(f,
|
|
10637
|
+
ajv2.addFormat(f, fs65[f]);
|
|
10631
10638
|
}
|
|
10632
10639
|
module2.exports = exports2 = formatsPlugin;
|
|
10633
10640
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -10635,9 +10642,160 @@ var require_dist = __commonJS({
|
|
|
10635
10642
|
}
|
|
10636
10643
|
});
|
|
10637
10644
|
|
|
10645
|
+
// src/analysis/migrateSrs52Context.ts
|
|
10646
|
+
var migrateSrs52Context_exports = {};
|
|
10647
|
+
__export(migrateSrs52Context_exports, {
|
|
10648
|
+
migrateSrs52Context: () => migrateSrs52Context
|
|
10649
|
+
});
|
|
10650
|
+
function readJson6(p) {
|
|
10651
|
+
try {
|
|
10652
|
+
return JSON.parse(fs63.readFileSync(p, "utf-8"));
|
|
10653
|
+
} catch {
|
|
10654
|
+
return null;
|
|
10655
|
+
}
|
|
10656
|
+
}
|
|
10657
|
+
function writeJson2(p, data, dryRun) {
|
|
10658
|
+
if (dryRun) {
|
|
10659
|
+
return;
|
|
10660
|
+
}
|
|
10661
|
+
fs63.mkdirSync(path62.dirname(p), { recursive: true });
|
|
10662
|
+
fs63.writeFileSync(p, `${JSON.stringify(data, null, 2)}
|
|
10663
|
+
`, "utf-8");
|
|
10664
|
+
}
|
|
10665
|
+
function nextCode(prefix, existing) {
|
|
10666
|
+
let n = 1;
|
|
10667
|
+
while (existing.has(`${prefix}-${String(n).padStart(2, "0")}`)) {
|
|
10668
|
+
n += 1;
|
|
10669
|
+
}
|
|
10670
|
+
const code = `${prefix}-${String(n).padStart(2, "0")}`;
|
|
10671
|
+
existing.add(code);
|
|
10672
|
+
return code;
|
|
10673
|
+
}
|
|
10674
|
+
function migrateSrs52Context(opts) {
|
|
10675
|
+
const contextDir2 = path62.resolve(opts.contextDir);
|
|
10676
|
+
const featuresPath = path62.join(contextDir2, "features-list.json");
|
|
10677
|
+
const fl = readJson6(featuresPath);
|
|
10678
|
+
if (!fl?.features) {
|
|
10679
|
+
return { ok: false, migratedInfrastructure: 0, migratedQa: 0, errors: ["features-list.json missing or invalid"] };
|
|
10680
|
+
}
|
|
10681
|
+
const infraPath = path62.join(contextDir2, "infrastructure-list.json");
|
|
10682
|
+
const qaPath = path62.join(contextDir2, "qa-list.json");
|
|
10683
|
+
const infraFile = readJson6(infraPath) ?? {
|
|
10684
|
+
infrastructure: [],
|
|
10685
|
+
revisionLog: []
|
|
10686
|
+
};
|
|
10687
|
+
const qaFile = readJson6(qaPath) ?? { qa: [], revisionLog: [] };
|
|
10688
|
+
const inCodes = new Set(
|
|
10689
|
+
(Array.isArray(infraFile.infrastructure) ? infraFile.infrastructure : []).map((r) => r.code).filter((c) => typeof c === "string")
|
|
10690
|
+
);
|
|
10691
|
+
const qaCodes = new Set(
|
|
10692
|
+
(Array.isArray(qaFile.qa) ? qaFile.qa : []).map((r) => r.code).filter((c) => typeof c === "string")
|
|
10693
|
+
);
|
|
10694
|
+
const errors = [];
|
|
10695
|
+
let migratedInfrastructure = 0;
|
|
10696
|
+
let migratedQa = 0;
|
|
10697
|
+
const kept = [];
|
|
10698
|
+
for (const row2 of fl.features) {
|
|
10699
|
+
const kind = typeof row2.featureKind === "string" ? row2.featureKind : "product";
|
|
10700
|
+
const feCode = typeof row2.code === "string" ? row2.code : "";
|
|
10701
|
+
if (!FE3.test(feCode)) {
|
|
10702
|
+
kept.push(row2);
|
|
10703
|
+
continue;
|
|
10704
|
+
}
|
|
10705
|
+
if (kind === "infrastructure") {
|
|
10706
|
+
const inCode = nextCode("IN", inCodes);
|
|
10707
|
+
const slug = typeof row2.slug === "string" ? row2.slug : "migrated";
|
|
10708
|
+
infraFile.infrastructure = Array.isArray(infraFile.infrastructure) ? infraFile.infrastructure : [];
|
|
10709
|
+
infraFile.infrastructure.push({
|
|
10710
|
+
code: inCode,
|
|
10711
|
+
name: row2.name ?? inCode,
|
|
10712
|
+
slug,
|
|
10713
|
+
sourceReferences: row2.sourceReferences ?? [],
|
|
10714
|
+
description: row2.description
|
|
10715
|
+
});
|
|
10716
|
+
const ucPath = path62.join(contextDir2, `${feCode}-use-cases-list.json`);
|
|
10717
|
+
const ucFile = readJson6(ucPath);
|
|
10718
|
+
if (ucFile?.useCases?.length) {
|
|
10719
|
+
const compPath = path62.join(contextDir2, `${inCode}-components-list.json`);
|
|
10720
|
+
const components = ucFile.useCases.filter((u) => typeof u.code === "string" && UC3.test(u.code)).map((u, i) => ({
|
|
10721
|
+
code: `IC-${String(i + 1).padStart(2, "0")}`,
|
|
10722
|
+
name: u.name ?? u.code,
|
|
10723
|
+
slug: u.slug ?? `ic-${i + 1}`,
|
|
10724
|
+
sourceReferences: u.sourceReferences ?? []
|
|
10725
|
+
}));
|
|
10726
|
+
writeJson2(
|
|
10727
|
+
compPath,
|
|
10728
|
+
{
|
|
10729
|
+
infrastructureCode: inCode,
|
|
10730
|
+
components,
|
|
10731
|
+
revisionLog: [{ summary: `Migrated from ${feCode} use cases (SRS-52)` }]
|
|
10732
|
+
},
|
|
10733
|
+
Boolean(opts.dryRun)
|
|
10734
|
+
);
|
|
10735
|
+
}
|
|
10736
|
+
migratedInfrastructure += 1;
|
|
10737
|
+
continue;
|
|
10738
|
+
}
|
|
10739
|
+
if (kind === "testing") {
|
|
10740
|
+
const qaCode = nextCode("QA", qaCodes);
|
|
10741
|
+
const covers = Array.isArray(row2.coversCodes) ? row2.coversCodes.filter((c) => typeof c === "string") : [];
|
|
10742
|
+
if (!covers.length && !opts.force) {
|
|
10743
|
+
errors.push(`${feCode}: cannot derive coversCodes for QA migration (use --force or --mapping-json)`);
|
|
10744
|
+
kept.push(row2);
|
|
10745
|
+
continue;
|
|
10746
|
+
}
|
|
10747
|
+
qaFile.qa = Array.isArray(qaFile.qa) ? qaFile.qa : [];
|
|
10748
|
+
qaFile.qa.push({
|
|
10749
|
+
code: qaCode,
|
|
10750
|
+
name: row2.name ?? qaCode,
|
|
10751
|
+
slug: typeof row2.slug === "string" ? row2.slug : "migrated",
|
|
10752
|
+
coversCodes: covers.length ? covers : ["FE-01"],
|
|
10753
|
+
sourceReferences: row2.sourceReferences ?? []
|
|
10754
|
+
});
|
|
10755
|
+
migratedQa += 1;
|
|
10756
|
+
continue;
|
|
10757
|
+
}
|
|
10758
|
+
kept.push(row2);
|
|
10759
|
+
}
|
|
10760
|
+
if (errors.length && !opts.force) {
|
|
10761
|
+
return { ok: false, migratedInfrastructure, migratedQa, errors };
|
|
10762
|
+
}
|
|
10763
|
+
fl.features = kept;
|
|
10764
|
+
fl.revisionLog = Array.isArray(fl.revisionLog) ? fl.revisionLog : [];
|
|
10765
|
+
fl.revisionLog.push({
|
|
10766
|
+
summary: `SRS-52 migration: moved ${migratedInfrastructure} infrastructure and ${migratedQa} QA rows`
|
|
10767
|
+
});
|
|
10768
|
+
infraFile.revisionLog = Array.isArray(infraFile.revisionLog) ? infraFile.revisionLog : [];
|
|
10769
|
+
if (migratedInfrastructure) {
|
|
10770
|
+
infraFile.revisionLog.push({ summary: `SRS-52 migration: added ${migratedInfrastructure} row(s) from features` });
|
|
10771
|
+
}
|
|
10772
|
+
qaFile.revisionLog = Array.isArray(qaFile.revisionLog) ? qaFile.revisionLog : [];
|
|
10773
|
+
if (migratedQa) {
|
|
10774
|
+
qaFile.revisionLog.push({ summary: `SRS-52 migration: added ${migratedQa} row(s) from features` });
|
|
10775
|
+
}
|
|
10776
|
+
writeJson2(featuresPath, fl, Boolean(opts.dryRun));
|
|
10777
|
+
if (migratedInfrastructure || infraFile.infrastructure?.length) {
|
|
10778
|
+
writeJson2(infraPath, infraFile, Boolean(opts.dryRun));
|
|
10779
|
+
}
|
|
10780
|
+
if (migratedQa || qaFile.qa?.length) {
|
|
10781
|
+
writeJson2(qaPath, qaFile, Boolean(opts.dryRun));
|
|
10782
|
+
}
|
|
10783
|
+
return { ok: true, migratedInfrastructure, migratedQa, errors };
|
|
10784
|
+
}
|
|
10785
|
+
var fs63, path62, FE3, UC3;
|
|
10786
|
+
var init_migrateSrs52Context = __esm({
|
|
10787
|
+
"src/analysis/migrateSrs52Context.ts"() {
|
|
10788
|
+
"use strict";
|
|
10789
|
+
fs63 = __toESM(require("fs"));
|
|
10790
|
+
path62 = __toESM(require("path"));
|
|
10791
|
+
FE3 = /^FE-\d+$/;
|
|
10792
|
+
UC3 = /^UC-\d+$/;
|
|
10793
|
+
}
|
|
10794
|
+
});
|
|
10795
|
+
|
|
10638
10796
|
// src/cli/main.ts
|
|
10639
|
-
var
|
|
10640
|
-
var
|
|
10797
|
+
var fs64 = __toESM(require("node:fs"));
|
|
10798
|
+
var path63 = __toESM(require("node:path"));
|
|
10641
10799
|
|
|
10642
10800
|
// src/cli/exitCodes.ts
|
|
10643
10801
|
var OsExit = {
|
|
@@ -10823,7 +10981,7 @@ function createEasyspecsCliProgram() {
|
|
|
10823
10981
|
program2.command("help").description("Show help");
|
|
10824
10982
|
program2.command("version").description("Print CLI version");
|
|
10825
10983
|
const workstation = program2.command("workstation").description("Host inventory for AI workstation sizing");
|
|
10826
|
-
workstation.command("info").description("Print CPU, RAM, and SRS-
|
|
10984
|
+
workstation.command("info").description("Print CPU, RAM, and SRS-75 N_sys (macOS and Linux only; use global --json)").allowUnknownOption(false);
|
|
10827
10985
|
program2.command("doctor").description("Check readiness and/or inspect configuration").option("--readiness", "Print readiness summary (default)").option("--inspect-config", "Print redacted merged configuration");
|
|
10828
10986
|
const auth = program2.command("auth").description("Authentication");
|
|
10829
10987
|
auth.command("login").description("Log in").option("--email <email>", "Email address").option("--password <password>", "Password").option("--session-path <path>", "Session JSON path override for this run").option("--ci", "Use easyspecs.auth.ciLogin from config when argv credentials are omitted");
|
|
@@ -11366,14 +11524,23 @@ var import_node_child_process2 = require("node:child_process");
|
|
|
11366
11524
|
var ABSOLUTE_MAX_CONCURRENT_AI = 64;
|
|
11367
11525
|
|
|
11368
11526
|
// src/config/machineConcurrentAiFromHost.ts
|
|
11369
|
-
var
|
|
11370
|
-
var
|
|
11527
|
+
var ANCHOR_A_N_SYS = 15;
|
|
11528
|
+
var ANCHOR_B_P = 11;
|
|
11529
|
+
var ANCHOR_B_N_SYS = 100;
|
|
11530
|
+
var CPU_SLOPE_PER_CORE = 8.5;
|
|
11531
|
+
var GIB_PER_CORE_REF = 4;
|
|
11371
11532
|
function clampProductConcurrentLimits(n) {
|
|
11372
11533
|
if (!Number.isFinite(n)) {
|
|
11373
11534
|
return DEFAULT_MAX_CONCURRENT_AI;
|
|
11374
11535
|
}
|
|
11375
11536
|
return Math.min(ABSOLUTE_MAX_CONCURRENT_AI, Math.max(1, Math.floor(n)));
|
|
11376
11537
|
}
|
|
11538
|
+
function nCpuFloatFromPhysicalCpus(p) {
|
|
11539
|
+
if (p <= ANCHOR_B_P) {
|
|
11540
|
+
return ANCHOR_A_N_SYS + CPU_SLOPE_PER_CORE * (p - 1);
|
|
11541
|
+
}
|
|
11542
|
+
return ANCHOR_B_N_SYS + CPU_SLOPE_PER_CORE * (p - ANCHOR_B_P);
|
|
11543
|
+
}
|
|
11377
11544
|
function machineConcurrentAiCapFromHost(profile) {
|
|
11378
11545
|
const memBytes = Number.isFinite(profile.totalMemBytes) && profile.totalMemBytes > 0 ? profile.totalMemBytes : 0;
|
|
11379
11546
|
const rGib = memBytes / 2 ** 30;
|
|
@@ -11384,8 +11551,8 @@ function machineConcurrentAiCapFromHost(profile) {
|
|
|
11384
11551
|
if (!Number.isFinite(rGib) || rGib <= 0) {
|
|
11385
11552
|
return 1;
|
|
11386
11553
|
}
|
|
11387
|
-
const nCpuFloat =
|
|
11388
|
-
const ramRefGib =
|
|
11554
|
+
const nCpuFloat = nCpuFloatFromPhysicalCpus(p);
|
|
11555
|
+
const ramRefGib = GIB_PER_CORE_REF * p;
|
|
11389
11556
|
const ramFactor = Math.min(1, rGib / ramRefGib);
|
|
11390
11557
|
const nFloat = nCpuFloat * ramFactor;
|
|
11391
11558
|
const rounded = Math.round(nFloat);
|
|
@@ -12694,7 +12861,7 @@ function stringifyForSrs13Debug(value) {
|
|
|
12694
12861
|
return truncateForSrs13DebugLog(String(value));
|
|
12695
12862
|
}
|
|
12696
12863
|
}
|
|
12697
|
-
function logSrs13HttpDebug(log,
|
|
12864
|
+
function logSrs13HttpDebug(log, path64, method, requestBody, error) {
|
|
12698
12865
|
if (!log) {
|
|
12699
12866
|
return;
|
|
12700
12867
|
}
|
|
@@ -12704,7 +12871,7 @@ function logSrs13HttpDebug(log, path62, method, requestBody, error) {
|
|
|
12704
12871
|
} catch {
|
|
12705
12872
|
bodyBytes = 0;
|
|
12706
12873
|
}
|
|
12707
|
-
log(`[pipeline:upload] debug ${method} ${
|
|
12874
|
+
log(`[pipeline:upload] debug ${method} ${path64} \u2014 request body ~${bodyBytes} bytes (JSON below):`);
|
|
12708
12875
|
log(stringifyForSrs13Debug(requestBody));
|
|
12709
12876
|
const raw = httpApiResponseBody(error);
|
|
12710
12877
|
const status = error && typeof error === "object" && "status" in error ? Number(error.status) : void 0;
|
|
@@ -12808,18 +12975,18 @@ async function runParallelSinglesIntoAccum(requestJson, applicationId, paths, on
|
|
|
12808
12975
|
const recentWaveMs = [];
|
|
12809
12976
|
let idx = 0;
|
|
12810
12977
|
const runOne = async (absPath) => {
|
|
12811
|
-
const
|
|
12978
|
+
const basename18 = path12.basename(absPath);
|
|
12812
12979
|
let content;
|
|
12813
12980
|
try {
|
|
12814
12981
|
content = fs12.readFileSync(absPath, "utf8");
|
|
12815
12982
|
} catch (e) {
|
|
12816
12983
|
const msg = errorMessage(e);
|
|
12817
|
-
logSrs13Failure(log, `read file file=${
|
|
12984
|
+
logSrs13Failure(log, `read file file=${basename18}`, msg);
|
|
12818
12985
|
accum.failed.push({ path: absPath, message: msg });
|
|
12819
12986
|
return;
|
|
12820
12987
|
}
|
|
12821
12988
|
const existingId = resolveExistingId(absPath);
|
|
12822
|
-
const payload = buildSrsDiscoverySavePayload(applicationId,
|
|
12989
|
+
const payload = buildSrsDiscoverySavePayload(applicationId, basename18, content, existingId);
|
|
12823
12990
|
try {
|
|
12824
12991
|
await postSingleCreate(requestJson, payload, log);
|
|
12825
12992
|
accum.succeeded.push(absPath);
|
|
@@ -12833,7 +13000,7 @@ async function runParallelSinglesIntoAccum(requestJson, applicationId, paths, on
|
|
|
12833
13000
|
throw e;
|
|
12834
13001
|
}
|
|
12835
13002
|
const msg = errorMessage(e);
|
|
12836
|
-
logSrs13Failure(log, `POST /api/content/srs_discovery file=${
|
|
13003
|
+
logSrs13Failure(log, `POST /api/content/srs_discovery file=${basename18}`, msg);
|
|
12837
13004
|
accum.failed.push({ path: absPath, message: msg });
|
|
12838
13005
|
}
|
|
12839
13006
|
};
|
|
@@ -12915,18 +13082,18 @@ async function executeContextSrsDiscoveryUploadPhase(filePaths, phaseOpts, accum
|
|
|
12915
13082
|
const items = [];
|
|
12916
13083
|
const chunkPaths = [];
|
|
12917
13084
|
for (const absPath of chunk) {
|
|
12918
|
-
const
|
|
13085
|
+
const basename18 = path12.basename(absPath);
|
|
12919
13086
|
let content;
|
|
12920
13087
|
try {
|
|
12921
13088
|
content = fs12.readFileSync(absPath, "utf8");
|
|
12922
13089
|
} catch (e) {
|
|
12923
13090
|
const msg = errorMessage(e);
|
|
12924
|
-
logSrs13Failure(log, `read file file=${
|
|
13091
|
+
logSrs13Failure(log, `read file file=${basename18}`, msg);
|
|
12925
13092
|
accum.failed.push({ path: absPath, message: msg });
|
|
12926
13093
|
continue;
|
|
12927
13094
|
}
|
|
12928
13095
|
const existingId = resolveExistingId(absPath);
|
|
12929
|
-
items.push(buildSrsDiscoverySavePayloadForBatch(applicationId,
|
|
13096
|
+
items.push(buildSrsDiscoverySavePayloadForBatch(applicationId, basename18, content, existingId));
|
|
12930
13097
|
chunkPaths.push(absPath);
|
|
12931
13098
|
}
|
|
12932
13099
|
if (items.length === 0) {
|
|
@@ -13317,7 +13484,7 @@ function createFileBackedWorkspaceState(repoRoot) {
|
|
|
13317
13484
|
|
|
13318
13485
|
// src/pipelines/synthesis/synthesisPipeline.ts
|
|
13319
13486
|
var fs37 = __toESM(require("fs"));
|
|
13320
|
-
var
|
|
13487
|
+
var path33 = __toESM(require("path"));
|
|
13321
13488
|
|
|
13322
13489
|
// src/analysis/analysisDynamicTestSteps.ts
|
|
13323
13490
|
var fs14 = __toESM(require("fs"));
|
|
@@ -13342,6 +13509,10 @@ var BH_ROW = /^BH-\d+$/;
|
|
|
13342
13509
|
var SV_ROW = /^SV-\d+$/;
|
|
13343
13510
|
var ME_ROW = /^ME-\d+$/;
|
|
13344
13511
|
var TS_ROW = /^TS-\d+$/;
|
|
13512
|
+
var IN_ROW = /^IN-\d+$/;
|
|
13513
|
+
var IC_ROW = /^IC-\d+$/;
|
|
13514
|
+
var QA_ROW = /^QA-\d+$/;
|
|
13515
|
+
var TC_ROW = /^TC-\d+$/;
|
|
13345
13516
|
function safeCoordStr(v) {
|
|
13346
13517
|
return typeof v === "string" ? v.trim() : "";
|
|
13347
13518
|
}
|
|
@@ -13428,6 +13599,88 @@ function discoverServiceTreeRows(contextDir2) {
|
|
|
13428
13599
|
}
|
|
13429
13600
|
return out;
|
|
13430
13601
|
}
|
|
13602
|
+
function discoverInfrastructureRows(contextDir2) {
|
|
13603
|
+
const p = path14.join(contextDir2, "infrastructure-list.json");
|
|
13604
|
+
const file = readJson(p);
|
|
13605
|
+
const rows = Array.isArray(file?.infrastructure) ? file.infrastructure : [];
|
|
13606
|
+
const out = [];
|
|
13607
|
+
for (const row2 of rows) {
|
|
13608
|
+
const code = safeCoordStr(row2.code);
|
|
13609
|
+
if (!IN_ROW.test(code)) {
|
|
13610
|
+
continue;
|
|
13611
|
+
}
|
|
13612
|
+
const slug = slugOrFallbackCoord(row2);
|
|
13613
|
+
if (!slug) {
|
|
13614
|
+
continue;
|
|
13615
|
+
}
|
|
13616
|
+
out.push({ code, name: safeCoordStr(row2.name) || code, slug });
|
|
13617
|
+
}
|
|
13618
|
+
return out;
|
|
13619
|
+
}
|
|
13620
|
+
function discoverInfrastructureComponentTreeRows(contextDir2) {
|
|
13621
|
+
const parents = discoverInfrastructureRows(contextDir2);
|
|
13622
|
+
const out = [];
|
|
13623
|
+
for (const parent of parents) {
|
|
13624
|
+
const clPath = path14.join(contextDir2, `${parent.code}-components-list.json`);
|
|
13625
|
+
const clFile = readJson(clPath);
|
|
13626
|
+
const comps = Array.isArray(clFile?.components) ? clFile.components : [];
|
|
13627
|
+
const row2 = { ...parent, components: [] };
|
|
13628
|
+
for (const c of comps) {
|
|
13629
|
+
const icCode = safeCoordStr(c.code);
|
|
13630
|
+
if (!IC_ROW.test(icCode)) {
|
|
13631
|
+
continue;
|
|
13632
|
+
}
|
|
13633
|
+
const slug = slugOrFallbackCoord(c);
|
|
13634
|
+
if (!slug) {
|
|
13635
|
+
continue;
|
|
13636
|
+
}
|
|
13637
|
+
row2.components.push({ code: icCode, name: safeCoordStr(c.name) || icCode, slug });
|
|
13638
|
+
}
|
|
13639
|
+
out.push(row2);
|
|
13640
|
+
}
|
|
13641
|
+
return out;
|
|
13642
|
+
}
|
|
13643
|
+
function discoverQaRows(contextDir2) {
|
|
13644
|
+
const p = path14.join(contextDir2, "qa-list.json");
|
|
13645
|
+
const file = readJson(p);
|
|
13646
|
+
const rows = Array.isArray(file?.qa) ? file.qa : [];
|
|
13647
|
+
const out = [];
|
|
13648
|
+
for (const row2 of rows) {
|
|
13649
|
+
const code = safeCoordStr(row2.code);
|
|
13650
|
+
if (!QA_ROW.test(code)) {
|
|
13651
|
+
continue;
|
|
13652
|
+
}
|
|
13653
|
+
const slug = slugOrFallbackCoord(row2);
|
|
13654
|
+
if (!slug) {
|
|
13655
|
+
continue;
|
|
13656
|
+
}
|
|
13657
|
+
out.push({ code, name: safeCoordStr(row2.name) || code, slug });
|
|
13658
|
+
}
|
|
13659
|
+
return out;
|
|
13660
|
+
}
|
|
13661
|
+
function discoverQaTestCaseTreeRows(contextDir2) {
|
|
13662
|
+
const parents = discoverQaRows(contextDir2);
|
|
13663
|
+
const out = [];
|
|
13664
|
+
for (const parent of parents) {
|
|
13665
|
+
const tcPath = path14.join(contextDir2, `${parent.code}-test-cases-list.json`);
|
|
13666
|
+
const tcFile = readJson(tcPath);
|
|
13667
|
+
const tcs = Array.isArray(tcFile?.testCases) ? tcFile.testCases : [];
|
|
13668
|
+
const row2 = { ...parent, testCases: [] };
|
|
13669
|
+
for (const t of tcs) {
|
|
13670
|
+
const tcCode = safeCoordStr(t.code);
|
|
13671
|
+
if (!TC_ROW.test(tcCode)) {
|
|
13672
|
+
continue;
|
|
13673
|
+
}
|
|
13674
|
+
const slug = slugOrFallbackCoord(t);
|
|
13675
|
+
if (!slug) {
|
|
13676
|
+
continue;
|
|
13677
|
+
}
|
|
13678
|
+
row2.testCases.push({ code: tcCode, name: safeCoordStr(t.name) || tcCode, slug });
|
|
13679
|
+
}
|
|
13680
|
+
out.push(row2);
|
|
13681
|
+
}
|
|
13682
|
+
return out;
|
|
13683
|
+
}
|
|
13431
13684
|
function discoverTechStackToolRows(contextDir2) {
|
|
13432
13685
|
const tsPath = path14.join(contextDir2, "tech-stack-list.json");
|
|
13433
13686
|
const tsFile = readJson(tsPath);
|
|
@@ -13466,12 +13719,14 @@ var ANALYSIS_STATIC_CONTEXT_OUTPUTS = [
|
|
|
13466
13719
|
"experiences-list.json",
|
|
13467
13720
|
"services-list.json",
|
|
13468
13721
|
"data-model-list.json",
|
|
13469
|
-
"tech-stack-list.json"
|
|
13722
|
+
"tech-stack-list.json",
|
|
13723
|
+
"infrastructure-list.json",
|
|
13724
|
+
"qa-list.json"
|
|
13470
13725
|
];
|
|
13471
13726
|
function discoverDynamicAnalysisTestSteps(contextDir2) {
|
|
13472
|
-
const staticOutputs = ANALYSIS_STATIC_CONTEXT_OUTPUTS.map((
|
|
13473
|
-
basename:
|
|
13474
|
-
exists: nonEmptyContextFile(path14.join(contextDir2,
|
|
13727
|
+
const staticOutputs = ANALYSIS_STATIC_CONTEXT_OUTPUTS.map((basename18) => ({
|
|
13728
|
+
basename: basename18,
|
|
13729
|
+
exists: nonEmptyContextFile(path14.join(contextDir2, basename18))
|
|
13475
13730
|
}));
|
|
13476
13731
|
const featuresPath = path14.join(contextDir2, "features-list.json");
|
|
13477
13732
|
const featuresData = readJson(featuresPath);
|
|
@@ -13642,8 +13897,8 @@ function aceCurationPath(contextDir2, agentStem, runId) {
|
|
|
13642
13897
|
function aceConsolidatedSessionsJsonlPath(contextDir2) {
|
|
13643
13898
|
return path15.join(aceLearningsRoot(contextDir2), ACE_CONSOLIDATED_SESSIONS_JSONL);
|
|
13644
13899
|
}
|
|
13645
|
-
function opencodeAceSchemaPath(worktreeRoot,
|
|
13646
|
-
return path15.join(worktreeRoot, ".opencode", "schemas", "ace",
|
|
13900
|
+
function opencodeAceSchemaPath(worktreeRoot, basename18) {
|
|
13901
|
+
return path15.join(worktreeRoot, ".opencode", "schemas", "ace", basename18);
|
|
13647
13902
|
}
|
|
13648
13903
|
|
|
13649
13904
|
// src/analysis/aceJsonValidate.ts
|
|
@@ -14060,7 +14315,7 @@ function materializeOpenCodeAgentsWithAce(extensionResourcesAgents, analysisChec
|
|
|
14060
14315
|
|
|
14061
14316
|
// src/workstations/aiWorkstation.ts
|
|
14062
14317
|
var fs30 = __toESM(require("fs"));
|
|
14063
|
-
var
|
|
14318
|
+
var path27 = __toESM(require("path"));
|
|
14064
14319
|
|
|
14065
14320
|
// src/analysis/promptTemplates.ts
|
|
14066
14321
|
function fillMarkdownPrompt(p) {
|
|
@@ -14180,7 +14435,15 @@ var CONTEXT_SYNTHESIS_TEST_STEP_ORDER = [
|
|
|
14180
14435
|
"listUseCases",
|
|
14181
14436
|
"reviewUseCasesList",
|
|
14182
14437
|
"listScenarios",
|
|
14183
|
-
"reviewScenariosList"
|
|
14438
|
+
"reviewScenariosList",
|
|
14439
|
+
"listInfrastructure",
|
|
14440
|
+
"reviewInfrastructureList",
|
|
14441
|
+
"listQa",
|
|
14442
|
+
"reviewQaList",
|
|
14443
|
+
"listInfrastructureComponents",
|
|
14444
|
+
"reviewInfrastructureComponentsList",
|
|
14445
|
+
"listQaTestCases",
|
|
14446
|
+
"reviewQaTestCasesList"
|
|
14184
14447
|
];
|
|
14185
14448
|
function synthesisStepLabel(step, ctx) {
|
|
14186
14449
|
if (step === "listUseCases" || step === "reviewUseCasesList") {
|
|
@@ -14192,6 +14455,12 @@ function synthesisStepLabel(step, ctx) {
|
|
|
14192
14455
|
if (step === "listEntityFields" || step === "reviewEntityFieldsList") {
|
|
14193
14456
|
return ctx?.entityCode ? `${ctx.entityCode}-fields-list.json` : "DM-<nn>-fields-list.json (per entity)";
|
|
14194
14457
|
}
|
|
14458
|
+
if (step === "listInfrastructureComponents" || step === "reviewInfrastructureComponentsList") {
|
|
14459
|
+
return ctx?.infrastructureCode ? `${ctx.infrastructureCode}-components-list.json` : "IN-<nn>-components-list.json (per infrastructure)";
|
|
14460
|
+
}
|
|
14461
|
+
if (step === "listQaTestCases" || step === "reviewQaTestCasesList") {
|
|
14462
|
+
return ctx?.qaCode ? `${ctx.qaCode}-test-cases-list.json` : "QA-<nn>-test-cases-list.json (per QA)";
|
|
14463
|
+
}
|
|
14195
14464
|
const m = {
|
|
14196
14465
|
docsProject: "project.md",
|
|
14197
14466
|
architecture: "architecture.md",
|
|
@@ -14205,7 +14474,11 @@ function synthesisStepLabel(step, ctx) {
|
|
|
14205
14474
|
listDataModel: "data-model-list.json",
|
|
14206
14475
|
reviewDataModelList: "data-model-list.json",
|
|
14207
14476
|
listTechStack: "tech-stack-list.json",
|
|
14208
|
-
reviewTechStackList: "tech-stack-list.json"
|
|
14477
|
+
reviewTechStackList: "tech-stack-list.json",
|
|
14478
|
+
listInfrastructure: "infrastructure-list.json",
|
|
14479
|
+
reviewInfrastructureList: "infrastructure-list.json",
|
|
14480
|
+
listQa: "qa-list.json",
|
|
14481
|
+
reviewQaList: "qa-list.json"
|
|
14209
14482
|
};
|
|
14210
14483
|
return m[step];
|
|
14211
14484
|
}
|
|
@@ -14401,9 +14674,9 @@ function parsePsRssDarwinKilobytes(stdout) {
|
|
|
14401
14674
|
return n;
|
|
14402
14675
|
}
|
|
14403
14676
|
function readLinuxPidRssBytes(pid) {
|
|
14404
|
-
const
|
|
14677
|
+
const path64 = `/proc/${pid}/status`;
|
|
14405
14678
|
try {
|
|
14406
|
-
const content = fs18.readFileSync(
|
|
14679
|
+
const content = fs18.readFileSync(path64, "utf8");
|
|
14407
14680
|
const kb = parseVmRssKilobytesFromProcStatus(content);
|
|
14408
14681
|
if (kb === null) {
|
|
14409
14682
|
return { kind: "unknown", reason: "VmRSS_missing" };
|
|
@@ -14600,9 +14873,9 @@ function runOpenCodeAgent(cwd, args, options) {
|
|
|
14600
14873
|
log?.(`${procTag} command: ${formatCliCommandForLog(cmd, args)}`);
|
|
14601
14874
|
log?.(`${procTag} cwd: ${JSON.stringify(cwd)}`);
|
|
14602
14875
|
log?.(`${procTag} argv: ${JSON.stringify(args)}`);
|
|
14603
|
-
return new Promise((
|
|
14876
|
+
return new Promise((resolve25) => {
|
|
14604
14877
|
if (sig?.aborted) {
|
|
14605
|
-
|
|
14878
|
+
resolve25({ ok: false, message: "Stopped by user.", cancelled: true });
|
|
14606
14879
|
return;
|
|
14607
14880
|
}
|
|
14608
14881
|
const spawnEnv = options?.childEnv && Object.keys(options.childEnv).length > 0 ? { ...process.env, ...options.childEnv } : process.env;
|
|
@@ -14697,7 +14970,7 @@ ${truncateForDiag(outBody, DIAG_STDOUT_MAX)}`);
|
|
|
14697
14970
|
if (diag) {
|
|
14698
14971
|
finishDiag(diag.label, diag.code, diag.dumpStreams);
|
|
14699
14972
|
}
|
|
14700
|
-
|
|
14973
|
+
resolve25(result);
|
|
14701
14974
|
};
|
|
14702
14975
|
let onAbort;
|
|
14703
14976
|
const clearAbortHandler = () => {
|
|
@@ -15671,7 +15944,75 @@ async function runAceTracePhase(params) {
|
|
|
15671
15944
|
|
|
15672
15945
|
// src/analysis/coordinationListJsonValidate.ts
|
|
15673
15946
|
var fs24 = __toESM(require("fs"));
|
|
15947
|
+
var path22 = __toESM(require("path"));
|
|
15674
15948
|
var import__4 = __toESM(require__());
|
|
15949
|
+
|
|
15950
|
+
// src/analysis/qaCoversCodesAnchor.ts
|
|
15951
|
+
var FE_ROOT = /^FE-[0-9]+$/;
|
|
15952
|
+
var FE_UC = /^FE-[0-9]+_UC-[0-9]+$/;
|
|
15953
|
+
var FE_UC_SC = /^FE-[0-9]+_UC-[0-9]+_SC-[0-9]+$/;
|
|
15954
|
+
var SV_ROOT = /^SV-[0-9]+$/;
|
|
15955
|
+
var SV_ME = /^SV-[0-9]+_ME-[0-9]+$/;
|
|
15956
|
+
function isFeatureSubtreeCode(code) {
|
|
15957
|
+
const s = code.trim();
|
|
15958
|
+
return FE_ROOT.test(s) || FE_UC.test(s) || FE_UC_SC.test(s);
|
|
15959
|
+
}
|
|
15960
|
+
function isServiceSubtreeCode(code) {
|
|
15961
|
+
const s = code.trim();
|
|
15962
|
+
return SV_ROOT.test(s) || SV_ME.test(s);
|
|
15963
|
+
}
|
|
15964
|
+
function hasQaCoversCodesAnchor(coversCodes) {
|
|
15965
|
+
return coversCodes.some((c) => isFeatureSubtreeCode(c) || isServiceSubtreeCode(c));
|
|
15966
|
+
}
|
|
15967
|
+
function validateQaCoversCodesAnchors(coversCodes) {
|
|
15968
|
+
if (!Array.isArray(coversCodes)) {
|
|
15969
|
+
return { ok: false, errors: ["coversCodes must be a non-empty array"] };
|
|
15970
|
+
}
|
|
15971
|
+
const codes = coversCodes.filter((c) => typeof c === "string" && c.trim().length > 0);
|
|
15972
|
+
if (codes.length === 0) {
|
|
15973
|
+
return { ok: false, errors: ["coversCodes must contain at least one non-empty string (minItems: 1)"] };
|
|
15974
|
+
}
|
|
15975
|
+
if (!hasQaCoversCodesAnchor(codes)) {
|
|
15976
|
+
return {
|
|
15977
|
+
ok: false,
|
|
15978
|
+
errors: [
|
|
15979
|
+
"coversCodes must include at least one Feature-subtree code (FE-*, FE-*_UC-*, FE-*_UC-*_SC-*) or Service-subtree code (SV-*, SV-*_ME-*)"
|
|
15980
|
+
]
|
|
15981
|
+
};
|
|
15982
|
+
}
|
|
15983
|
+
return { ok: true };
|
|
15984
|
+
}
|
|
15985
|
+
function validateQaListDocumentAnchors(data, basename18) {
|
|
15986
|
+
if (data === null || typeof data !== "object" || Array.isArray(data)) {
|
|
15987
|
+
return { ok: true };
|
|
15988
|
+
}
|
|
15989
|
+
const o = data;
|
|
15990
|
+
const errors = [];
|
|
15991
|
+
if (basename18 === "qa-list.json") {
|
|
15992
|
+
const rows = Array.isArray(o.qa) ? o.qa : [];
|
|
15993
|
+
for (let i = 0; i < rows.length; i++) {
|
|
15994
|
+
const row2 = rows[i];
|
|
15995
|
+
const code = typeof row2?.code === "string" ? row2.code : `qa[${i}]`;
|
|
15996
|
+
const v = validateQaCoversCodesAnchors(row2?.coversCodes);
|
|
15997
|
+
if (!v.ok) {
|
|
15998
|
+
errors.push(`${code}: ${v.errors.join("; ")}`);
|
|
15999
|
+
}
|
|
16000
|
+
}
|
|
16001
|
+
} else if (/^QA-[0-9]+-test-cases-list\.json$/i.test(basename18)) {
|
|
16002
|
+
const rows = Array.isArray(o.testCases) ? o.testCases : [];
|
|
16003
|
+
for (let i = 0; i < rows.length; i++) {
|
|
16004
|
+
const row2 = rows[i];
|
|
16005
|
+
const code = typeof row2?.code === "string" ? row2.code : `testCases[${i}]`;
|
|
16006
|
+
const v = validateQaCoversCodesAnchors(row2?.coversCodes);
|
|
16007
|
+
if (!v.ok) {
|
|
16008
|
+
errors.push(`${code}: ${v.errors.join("; ")}`);
|
|
16009
|
+
}
|
|
16010
|
+
}
|
|
16011
|
+
}
|
|
16012
|
+
return errors.length ? { ok: false, errors } : { ok: true };
|
|
16013
|
+
}
|
|
16014
|
+
|
|
16015
|
+
// src/analysis/coordinationListJsonValidate.ts
|
|
15675
16016
|
function stripUtf8Bom3(s) {
|
|
15676
16017
|
return s.length > 0 && s.charCodeAt(0) === 65279 ? s.slice(1) : s;
|
|
15677
16018
|
}
|
|
@@ -15806,6 +16147,19 @@ function validateCoordinationListJson(jsonAbsolutePath, schemaAbsolutePath) {
|
|
|
15806
16147
|
}
|
|
15807
16148
|
};
|
|
15808
16149
|
}
|
|
16150
|
+
const basename18 = path22.basename(jsonAbsolutePath);
|
|
16151
|
+
const qaAnchor = validateQaListDocumentAnchors(data, basename18);
|
|
16152
|
+
if (!qaAnchor.ok) {
|
|
16153
|
+
const errorsText = qaAnchor.errors.map((e) => `- ${e}`).join("\n");
|
|
16154
|
+
return {
|
|
16155
|
+
ok: false,
|
|
16156
|
+
failure: {
|
|
16157
|
+
kind: "qa_covers",
|
|
16158
|
+
message: "QA coversCodes anchor validation failed (SRS-52 \xA73.1).",
|
|
16159
|
+
errorsText
|
|
16160
|
+
}
|
|
16161
|
+
};
|
|
16162
|
+
}
|
|
15809
16163
|
return { ok: true };
|
|
15810
16164
|
}
|
|
15811
16165
|
var FILE_PREVIEW_MAX = 4e3;
|
|
@@ -15829,11 +16183,19 @@ function coordinationListSchemaBasenameForOutputBasename(outputBasename) {
|
|
|
15829
16183
|
"experiences-list.json": "experiences-list.schema.json",
|
|
15830
16184
|
"services-list.json": "services-list.schema.json",
|
|
15831
16185
|
"data-model-list.json": "data-model-list.schema.json",
|
|
15832
|
-
"tech-stack-list.json": "tech-stack-list.schema.json"
|
|
16186
|
+
"tech-stack-list.json": "tech-stack-list.schema.json",
|
|
16187
|
+
"infrastructure-list.json": "infrastructure-list.schema.json",
|
|
16188
|
+
"qa-list.json": "qa-list.schema.json"
|
|
15833
16189
|
};
|
|
15834
16190
|
if (exact[outputBasename]) {
|
|
15835
16191
|
return exact[outputBasename];
|
|
15836
16192
|
}
|
|
16193
|
+
if (/^IN-\d+-components-list\.json$/i.test(outputBasename)) {
|
|
16194
|
+
return "infrastructure-components-list.schema.json";
|
|
16195
|
+
}
|
|
16196
|
+
if (/^QA-\d+-test-cases-list\.json$/i.test(outputBasename)) {
|
|
16197
|
+
return "qa-test-cases-list.schema.json";
|
|
16198
|
+
}
|
|
15837
16199
|
if (/^FE-\d+-use-cases-list\.json$/.test(outputBasename)) {
|
|
15838
16200
|
return "use-cases-list.schema.json";
|
|
15839
16201
|
}
|
|
@@ -15876,6 +16238,8 @@ function formatCoordinationJsonRepairAppendix(outputBasename, failure, rawFilePr
|
|
|
15876
16238
|
lines.push(failure.errorsText, "");
|
|
15877
16239
|
} else if (failure.kind === "forbidden_ref") {
|
|
15878
16240
|
lines.push("**Forbidden sourceReferences path:**", "", failure.message, "");
|
|
16241
|
+
} else if (failure.kind === "qa_covers") {
|
|
16242
|
+
lines.push(failure.message, "", failure.errorsText, "");
|
|
15879
16243
|
} else {
|
|
15880
16244
|
lines.push(`**Read error:** ${failure.message}`, "");
|
|
15881
16245
|
}
|
|
@@ -15888,12 +16252,12 @@ function formatCoordinationJsonRepairAppendix(outputBasename, failure, rawFilePr
|
|
|
15888
16252
|
|
|
15889
16253
|
// src/analysis/coordinationListStableWrite.ts
|
|
15890
16254
|
var fs26 = __toESM(require("fs"));
|
|
15891
|
-
var
|
|
16255
|
+
var path24 = __toESM(require("path"));
|
|
15892
16256
|
|
|
15893
16257
|
// src/analysis/coordinationListFileLock.ts
|
|
15894
16258
|
var fs25 = __toESM(require("fs"));
|
|
15895
16259
|
var os3 = __toESM(require("os"));
|
|
15896
|
-
var
|
|
16260
|
+
var path23 = __toESM(require("path"));
|
|
15897
16261
|
var DEFAULT_COORDINATION_LIST_LOCK_TIMEOUT_MS = 12e4;
|
|
15898
16262
|
var DEFAULT_COORDINATION_LIST_LOCK_STALE_MS = 30 * 60 * 1e3;
|
|
15899
16263
|
function sleepMs(ms) {
|
|
@@ -15963,7 +16327,7 @@ async function withCoordinationListFileLock(listJsonAbsolutePath, options, fn) {
|
|
|
15963
16327
|
fs25.writeFileSync(lockAbs, `${JSON.stringify(body, null, 0)}
|
|
15964
16328
|
`, { encoding: "utf-8", flag: "wx" });
|
|
15965
16329
|
acquired = true;
|
|
15966
|
-
diagnosticLog?.(`[coord-lock] acquired ${
|
|
16330
|
+
diagnosticLog?.(`[coord-lock] acquired ${path23.basename(lockAbs)}`);
|
|
15967
16331
|
} catch (e) {
|
|
15968
16332
|
const err = e;
|
|
15969
16333
|
if (err.code !== "EEXIST") {
|
|
@@ -15985,7 +16349,7 @@ async function withCoordinationListFileLock(listJsonAbsolutePath, options, fn) {
|
|
|
15985
16349
|
} finally {
|
|
15986
16350
|
try {
|
|
15987
16351
|
fs25.unlinkSync(lockAbs);
|
|
15988
|
-
diagnosticLog?.(`[coord-lock] released ${
|
|
16352
|
+
diagnosticLog?.(`[coord-lock] released ${path23.basename(lockAbs)}`);
|
|
15989
16353
|
} catch {
|
|
15990
16354
|
}
|
|
15991
16355
|
}
|
|
@@ -16082,6 +16446,20 @@ function coordinationListProfileForBasename(outputBasename) {
|
|
|
16082
16446
|
codeRe: /^TS-\d+$/i,
|
|
16083
16447
|
slugField: "slug",
|
|
16084
16448
|
nestedOnPrimary: []
|
|
16449
|
+
},
|
|
16450
|
+
"infrastructure-list.json": {
|
|
16451
|
+
id: "infrastructure",
|
|
16452
|
+
primaryKey: "infrastructure",
|
|
16453
|
+
codeRe: /^IN-\d+$/i,
|
|
16454
|
+
slugField: "slug",
|
|
16455
|
+
nestedOnPrimary: []
|
|
16456
|
+
},
|
|
16457
|
+
"qa-list.json": {
|
|
16458
|
+
id: "qa",
|
|
16459
|
+
primaryKey: "qa",
|
|
16460
|
+
codeRe: /^QA-\d+$/i,
|
|
16461
|
+
slugField: "slug",
|
|
16462
|
+
nestedOnPrimary: []
|
|
16085
16463
|
}
|
|
16086
16464
|
};
|
|
16087
16465
|
if (exact[outputBasename]) {
|
|
@@ -16113,6 +16491,24 @@ function coordinationListProfileForBasename(outputBasename) {
|
|
|
16113
16491
|
nestedOnPrimary: []
|
|
16114
16492
|
};
|
|
16115
16493
|
}
|
|
16494
|
+
if (/^IN-\d+-components-list\.json$/i.test(outputBasename)) {
|
|
16495
|
+
return {
|
|
16496
|
+
id: "infrastructure-components",
|
|
16497
|
+
primaryKey: "components",
|
|
16498
|
+
codeRe: /^IC-\d+$/i,
|
|
16499
|
+
slugField: "slug",
|
|
16500
|
+
nestedOnPrimary: []
|
|
16501
|
+
};
|
|
16502
|
+
}
|
|
16503
|
+
if (/^QA-\d+-test-cases-list\.json$/i.test(outputBasename)) {
|
|
16504
|
+
return {
|
|
16505
|
+
id: "qa-test-cases",
|
|
16506
|
+
primaryKey: "testCases",
|
|
16507
|
+
codeRe: /^TC-\d+$/i,
|
|
16508
|
+
slugField: "slug",
|
|
16509
|
+
nestedOnPrimary: []
|
|
16510
|
+
};
|
|
16511
|
+
}
|
|
16116
16512
|
return void 0;
|
|
16117
16513
|
}
|
|
16118
16514
|
function extractDroppedCodesFromRevisionLog(agent) {
|
|
@@ -16357,7 +16753,7 @@ function mergeRowWithNested(pre, agent, slugField, slugAuth, nestedOnPrimary, dr
|
|
|
16357
16753
|
function buildCascadePathsForDroppedCodes(listBasename, droppedCodes, contextDirAbs) {
|
|
16358
16754
|
const paths = [];
|
|
16359
16755
|
const tryPush = (p) => {
|
|
16360
|
-
const abs =
|
|
16756
|
+
const abs = path24.join(contextDirAbs, p);
|
|
16361
16757
|
if (fs26.existsSync(abs)) {
|
|
16362
16758
|
paths.push(abs);
|
|
16363
16759
|
}
|
|
@@ -16377,19 +16773,19 @@ function buildCascadePathsForDroppedCodes(listBasename, droppedCodes, contextDir
|
|
|
16377
16773
|
const prefix = `${code}-`;
|
|
16378
16774
|
for (const f of listDir()) {
|
|
16379
16775
|
if (f.startsWith(prefix) && f.endsWith(".md")) {
|
|
16380
|
-
paths.push(
|
|
16776
|
+
paths.push(path24.join(contextDirAbs, f));
|
|
16381
16777
|
}
|
|
16382
16778
|
}
|
|
16383
16779
|
tryPush(`${code}-use-cases-list.json`);
|
|
16384
16780
|
for (const f of listDir()) {
|
|
16385
16781
|
if (f.startsWith(`${code}_UC-`) && f.endsWith("-scenarios-list.json")) {
|
|
16386
|
-
paths.push(
|
|
16782
|
+
paths.push(path24.join(contextDirAbs, f));
|
|
16387
16783
|
}
|
|
16388
16784
|
if (f.startsWith(`${code}_UC-`) && f.includes("_SC-") && f.endsWith(".md")) {
|
|
16389
|
-
paths.push(
|
|
16785
|
+
paths.push(path24.join(contextDirAbs, f));
|
|
16390
16786
|
}
|
|
16391
16787
|
if (f.startsWith(`${code}_UC-`) && f.endsWith(".md") && !f.includes("-scenarios-list")) {
|
|
16392
|
-
paths.push(
|
|
16788
|
+
paths.push(path24.join(contextDirAbs, f));
|
|
16393
16789
|
}
|
|
16394
16790
|
}
|
|
16395
16791
|
}
|
|
@@ -16410,7 +16806,7 @@ function buildCascadePathsForDroppedCodes(listBasename, droppedCodes, contextDir
|
|
|
16410
16806
|
tryPush(`${stem}-scenarios-list.json`);
|
|
16411
16807
|
for (const f of listDir()) {
|
|
16412
16808
|
if (f.startsWith(`${stem}_SC-`) && f.endsWith(".md")) {
|
|
16413
|
-
paths.push(
|
|
16809
|
+
paths.push(path24.join(contextDirAbs, f));
|
|
16414
16810
|
}
|
|
16415
16811
|
}
|
|
16416
16812
|
}
|
|
@@ -16442,7 +16838,7 @@ function buildCascadePathsForDroppedCodes(listBasename, droppedCodes, contextDir
|
|
|
16442
16838
|
}
|
|
16443
16839
|
for (const f of listDir()) {
|
|
16444
16840
|
if (f.startsWith(`${dm}_${code}-`) && f.endsWith(".md")) {
|
|
16445
|
-
paths.push(
|
|
16841
|
+
paths.push(path24.join(contextDirAbs, f));
|
|
16446
16842
|
}
|
|
16447
16843
|
}
|
|
16448
16844
|
}
|
|
@@ -16891,10 +17287,10 @@ function formatMarkdownEvidenceRepairAppendix(outputFileAbsolute, kind = "empty"
|
|
|
16891
17287
|
|
|
16892
17288
|
// src/analysis/openQuestionResolution.ts
|
|
16893
17289
|
var fs28 = __toESM(require("fs"));
|
|
16894
|
-
var
|
|
17290
|
+
var path25 = __toESM(require("path"));
|
|
16895
17291
|
var OPEN_QUESTION_RESOLUTION_JSON_BASENAME = "open-question-resolution.json";
|
|
16896
17292
|
function openQuestionResolutionJsonAbsolute(worktreeRoot) {
|
|
16897
|
-
return
|
|
17293
|
+
return path25.join(worktreeRoot, ".opencode", "_run", OPEN_QUESTION_RESOLUTION_JSON_BASENAME);
|
|
16898
17294
|
}
|
|
16899
17295
|
function asTrimmedString(v) {
|
|
16900
17296
|
if (typeof v !== "string") {
|
|
@@ -16951,7 +17347,7 @@ function deleteOpenQuestionResolutionFile(worktreeRoot) {
|
|
|
16951
17347
|
|
|
16952
17348
|
// src/analysis/openQuestionsSectionValidate.ts
|
|
16953
17349
|
var fs29 = __toESM(require("fs"));
|
|
16954
|
-
var
|
|
17350
|
+
var path26 = __toESM(require("path"));
|
|
16955
17351
|
var CANONICAL_NORMALIZED = "open questions";
|
|
16956
17352
|
function normalizeOpenQuestionsHeadingTitle(raw) {
|
|
16957
17353
|
const t = raw.trim().replace(/\s+/gu, " ");
|
|
@@ -17068,9 +17464,9 @@ function parseOpenQuestionsSection(content) {
|
|
|
17068
17464
|
return { kind: "hasResidualQuestions", questions, startLine1Based };
|
|
17069
17465
|
}
|
|
17070
17466
|
function isContextMarkdownPathForOpenQuestions(worktreeRoot, absolutePath) {
|
|
17071
|
-
const ctx =
|
|
17072
|
-
const abs =
|
|
17073
|
-
const ctxNorm = ctx +
|
|
17467
|
+
const ctx = path26.join(path26.resolve(worktreeRoot), ".gluecharm", "context");
|
|
17468
|
+
const abs = path26.resolve(absolutePath);
|
|
17469
|
+
const ctxNorm = ctx + path26.sep;
|
|
17074
17470
|
return abs === ctx || abs.startsWith(ctxNorm);
|
|
17075
17471
|
}
|
|
17076
17472
|
function validateOpenQuestionsSectionFile(absolutePath, scope) {
|
|
@@ -17207,10 +17603,10 @@ var CITATION_EXAMPLE = "`src/example.ts:42` or `src/example.ts:10-25`";
|
|
|
17207
17603
|
var SRS50_COORD_LIST_APPEND_HINT = " **SRS-50 \u2014 stable writes:** Append **new** coded rows at the **end** of each array (never insert new codes between existing ones).";
|
|
17208
17604
|
var SRS50_COORD_LIST_REVIEW_HINT = ' **SRS-50 \u2014 stable writes:** Preserve existing **code** order; append net-new at the end. To **remove** a row, add **revisionLog** with **droppedCodes** (string[]). To change **slug** without changing **code**, add **slugRenames** ([{ "code", "from", "to" }]).';
|
|
17209
17605
|
function contextDir(worktreeRoot) {
|
|
17210
|
-
return
|
|
17606
|
+
return path27.join(worktreeRoot, ".gluecharm", "context");
|
|
17211
17607
|
}
|
|
17212
17608
|
function schemaRef(worktreeRoot, schemaBasename) {
|
|
17213
|
-
return
|
|
17609
|
+
return path27.join(worktreeRoot, ".opencode", "schemas", "context-lists", schemaBasename);
|
|
17214
17610
|
}
|
|
17215
17611
|
function expandArgvTemplate3(template, vars) {
|
|
17216
17612
|
return template.map((part) => {
|
|
@@ -17232,6 +17628,12 @@ function buildCoordStepLabel(step, listTarget) {
|
|
|
17232
17628
|
if (listTarget?.entityCode) {
|
|
17233
17629
|
parts.push(listTarget.entityCode);
|
|
17234
17630
|
}
|
|
17631
|
+
if (listTarget?.infrastructureCode) {
|
|
17632
|
+
parts.push(listTarget.infrastructureCode);
|
|
17633
|
+
}
|
|
17634
|
+
if (listTarget?.qaCode) {
|
|
17635
|
+
parts.push(listTarget.qaCode);
|
|
17636
|
+
}
|
|
17235
17637
|
return parts.join("\xB7");
|
|
17236
17638
|
}
|
|
17237
17639
|
function applyOpenCodeStewardshipToExpandedArgv(expandedArgv, p) {
|
|
@@ -17300,7 +17702,7 @@ function buildPromptBody(step, worktreeRoot, workspaceLabel, outputFileAbsolute,
|
|
|
17300
17702
|
agentId: "ctx-review-features-list",
|
|
17301
17703
|
agentDisplayName: "Features list \u2014 semantic review",
|
|
17302
17704
|
worktreeRoot,
|
|
17303
|
-
listTaskDescription: "Semantically review the **existing** features list at the output path: merge duplicates, remove false features, split overloaded rows, consolidate test-only duplicates of product capabilities (e.g. test login vs login)
|
|
17705
|
+
listTaskDescription: "Semantically review the **existing** features list at the output path: merge duplicates, remove false features, split overloaded rows, consolidate test-only duplicates of product capabilities (e.g. test login vs login); **drop** rows that belong in **infrastructure-list.json** or **qa-list.json** (do not use featureKind infrastructure/testing). Every surviving feature row **must** have **sourceReferences** with **minItems: 1**. Renumber **FE-** only when splitting (new codes at end). Append **revisionLog** entries for substantive edits. Follow the bundled agent instructions." + SRS50_COORD_LIST_REVIEW_HINT,
|
|
17304
17706
|
listSchemaRef: schemaRef(worktreeRoot, "features-list.schema.json"),
|
|
17305
17707
|
outputFileAbsolute,
|
|
17306
17708
|
outputBasename,
|
|
@@ -17454,6 +17856,166 @@ function buildPromptBody(step, worktreeRoot, workspaceLabel, outputFileAbsolute,
|
|
|
17454
17856
|
}),
|
|
17455
17857
|
listSchemaFile: "tech-stack-list.schema.json"
|
|
17456
17858
|
};
|
|
17859
|
+
case "listInfrastructure":
|
|
17860
|
+
return {
|
|
17861
|
+
body: fillListJsonPrompt({
|
|
17862
|
+
agentId: "ctx-list-infrastructure",
|
|
17863
|
+
agentDisplayName: "Infrastructure list",
|
|
17864
|
+
worktreeRoot,
|
|
17865
|
+
listTaskDescription: `Enumerate infrastructure / developer-delivery surfaces (IN-*) with stable codes, names, slugs, and **sourceReferences** (**minItems: 1**). CI/CD, IaC, scripts, hooks, bootstrap \u2014 not product features (FE-*) or runtime catalogue tools (TS-*).${SRS50_COORD_LIST_APPEND_HINT}`,
|
|
17866
|
+
listSchemaRef: schemaRef(worktreeRoot, "infrastructure-list.schema.json"),
|
|
17867
|
+
outputFileAbsolute,
|
|
17868
|
+
outputBasename,
|
|
17869
|
+
allowJsonFence: false,
|
|
17870
|
+
parentContextBlock: "",
|
|
17871
|
+
repairAppendix: listRepairAppendix
|
|
17872
|
+
}),
|
|
17873
|
+
listSchemaFile: "infrastructure-list.schema.json"
|
|
17874
|
+
};
|
|
17875
|
+
case "reviewInfrastructureList":
|
|
17876
|
+
return {
|
|
17877
|
+
body: fillListJsonPrompt({
|
|
17878
|
+
agentId: "ctx-review-infrastructure-list",
|
|
17879
|
+
agentDisplayName: "Infrastructure list \u2014 semantic review",
|
|
17880
|
+
worktreeRoot,
|
|
17881
|
+
listTaskDescription: "Semantically review **infrastructure-list.json**: merge duplicates, remove false rows, stable **IN-*** codes; every row **sourceReferences** minItems 1. Overwrite; follow bundled agent." + SRS50_COORD_LIST_REVIEW_HINT,
|
|
17882
|
+
listSchemaRef: schemaRef(worktreeRoot, "infrastructure-list.schema.json"),
|
|
17883
|
+
outputFileAbsolute,
|
|
17884
|
+
outputBasename,
|
|
17885
|
+
allowJsonFence: false,
|
|
17886
|
+
parentContextBlock: "\n## Parent context\n- File from **listInfrastructure**; **overwrite** with reviewed canonical list.\n",
|
|
17887
|
+
repairAppendix: listRepairAppendix
|
|
17888
|
+
}),
|
|
17889
|
+
listSchemaFile: "infrastructure-list.schema.json"
|
|
17890
|
+
};
|
|
17891
|
+
case "listQa":
|
|
17892
|
+
return {
|
|
17893
|
+
body: fillListJsonPrompt({
|
|
17894
|
+
agentId: "ctx-list-qa",
|
|
17895
|
+
agentDisplayName: "QA list",
|
|
17896
|
+
worktreeRoot,
|
|
17897
|
+
listTaskDescription: `Enumerate QA / verification surfaces (QA-*) with **coversCodes** (minItems 1, \u22651 FE-* or SV-* anchor per SRS-52 \xA73.1), names, slugs, **sourceReferences**. Not product features.${SRS50_COORD_LIST_APPEND_HINT}`,
|
|
17898
|
+
listSchemaRef: schemaRef(worktreeRoot, "qa-list.schema.json"),
|
|
17899
|
+
outputFileAbsolute,
|
|
17900
|
+
outputBasename,
|
|
17901
|
+
allowJsonFence: false,
|
|
17902
|
+
parentContextBlock: "\n## Parent context\n- **features-list.json** is already reviewed; reference real **FE-*** / **SV-*** codes in **coversCodes**.\n",
|
|
17903
|
+
repairAppendix: listRepairAppendix
|
|
17904
|
+
}),
|
|
17905
|
+
listSchemaFile: "qa-list.schema.json"
|
|
17906
|
+
};
|
|
17907
|
+
case "reviewQaList":
|
|
17908
|
+
return {
|
|
17909
|
+
body: fillListJsonPrompt({
|
|
17910
|
+
agentId: "ctx-review-qa-list",
|
|
17911
|
+
agentDisplayName: "QA list \u2014 semantic review",
|
|
17912
|
+
worktreeRoot,
|
|
17913
|
+
listTaskDescription: "Semantically review **qa-list.json**: enforce **coversCodes** anchor rule; merge duplicates; stable **QA-*** codes; **sourceReferences** minItems 1. Overwrite." + SRS50_COORD_LIST_REVIEW_HINT,
|
|
17914
|
+
listSchemaRef: schemaRef(worktreeRoot, "qa-list.schema.json"),
|
|
17915
|
+
outputFileAbsolute,
|
|
17916
|
+
outputBasename,
|
|
17917
|
+
allowJsonFence: false,
|
|
17918
|
+
parentContextBlock: "\n## Parent context\n- File from **listQa**; **overwrite** with reviewed canonical list.\n",
|
|
17919
|
+
repairAppendix: listRepairAppendix
|
|
17920
|
+
}),
|
|
17921
|
+
listSchemaFile: "qa-list.schema.json"
|
|
17922
|
+
};
|
|
17923
|
+
case "listInfrastructureComponents": {
|
|
17924
|
+
const inCode = listTarget?.infrastructureCode;
|
|
17925
|
+
if (!inCode) {
|
|
17926
|
+
throw new Error("listInfrastructureComponents requires listTarget.infrastructureCode");
|
|
17927
|
+
}
|
|
17928
|
+
return {
|
|
17929
|
+
body: fillListJsonPrompt({
|
|
17930
|
+
agentId: "ctx-list-infrastructure-components",
|
|
17931
|
+
agentDisplayName: "Infrastructure components list",
|
|
17932
|
+
worktreeRoot,
|
|
17933
|
+
listTaskDescription: `For infrastructure **${inCode}**, list components (IC-*) with stable codes, names, slugs, **sourceReferences** (minItems 1). Set infrastructureCode **${inCode}**.${SRS50_COORD_LIST_APPEND_HINT}`,
|
|
17934
|
+
listSchemaRef: schemaRef(worktreeRoot, "infrastructure-components-list.schema.json"),
|
|
17935
|
+
outputFileAbsolute,
|
|
17936
|
+
outputBasename,
|
|
17937
|
+
allowJsonFence: false,
|
|
17938
|
+
parentContextBlock: `
|
|
17939
|
+
## Parent context
|
|
17940
|
+
- infrastructureCode: **${inCode}**
|
|
17941
|
+
`,
|
|
17942
|
+
repairAppendix: listRepairAppendix
|
|
17943
|
+
}),
|
|
17944
|
+
listSchemaFile: "infrastructure-components-list.schema.json"
|
|
17945
|
+
};
|
|
17946
|
+
}
|
|
17947
|
+
case "reviewInfrastructureComponentsList": {
|
|
17948
|
+
const inCode = listTarget?.infrastructureCode;
|
|
17949
|
+
if (!inCode) {
|
|
17950
|
+
throw new Error("reviewInfrastructureComponentsList requires listTarget.infrastructureCode");
|
|
17951
|
+
}
|
|
17952
|
+
return {
|
|
17953
|
+
body: fillListJsonPrompt({
|
|
17954
|
+
agentId: "ctx-review-infrastructure-components-list",
|
|
17955
|
+
agentDisplayName: "Infrastructure components \u2014 semantic review",
|
|
17956
|
+
worktreeRoot,
|
|
17957
|
+
listTaskDescription: `Review **${inCode}-components-list.json**: normalize IC rows; **sourceReferences** minItems 1; stable codes. Overwrite.${SRS50_COORD_LIST_REVIEW_HINT}`,
|
|
17958
|
+
listSchemaRef: schemaRef(worktreeRoot, "infrastructure-components-list.schema.json"),
|
|
17959
|
+
outputFileAbsolute,
|
|
17960
|
+
outputBasename,
|
|
17961
|
+
allowJsonFence: false,
|
|
17962
|
+
parentContextBlock: `
|
|
17963
|
+
## Parent context
|
|
17964
|
+
- infrastructureCode: **${inCode}**
|
|
17965
|
+
`,
|
|
17966
|
+
repairAppendix: listRepairAppendix
|
|
17967
|
+
}),
|
|
17968
|
+
listSchemaFile: "infrastructure-components-list.schema.json"
|
|
17969
|
+
};
|
|
17970
|
+
}
|
|
17971
|
+
case "listQaTestCases": {
|
|
17972
|
+
const qaCode = listTarget?.qaCode;
|
|
17973
|
+
if (!qaCode) {
|
|
17974
|
+
throw new Error("listQaTestCases requires listTarget.qaCode");
|
|
17975
|
+
}
|
|
17976
|
+
return {
|
|
17977
|
+
body: fillListJsonPrompt({
|
|
17978
|
+
agentId: "ctx-list-qa-test-cases",
|
|
17979
|
+
agentDisplayName: "QA test cases list",
|
|
17980
|
+
worktreeRoot,
|
|
17981
|
+
listTaskDescription: `For QA **${qaCode}**, list test cases (TC-*) with **coversCodes** (anchor rule), names, slugs, **sourceReferences**. Set qaCode **${qaCode}**.${SRS50_COORD_LIST_APPEND_HINT}`,
|
|
17982
|
+
listSchemaRef: schemaRef(worktreeRoot, "qa-test-cases-list.schema.json"),
|
|
17983
|
+
outputFileAbsolute,
|
|
17984
|
+
outputBasename,
|
|
17985
|
+
allowJsonFence: false,
|
|
17986
|
+
parentContextBlock: `
|
|
17987
|
+
## Parent context
|
|
17988
|
+
- qaCode: **${qaCode}**
|
|
17989
|
+
`,
|
|
17990
|
+
repairAppendix: listRepairAppendix
|
|
17991
|
+
}),
|
|
17992
|
+
listSchemaFile: "qa-test-cases-list.schema.json"
|
|
17993
|
+
};
|
|
17994
|
+
}
|
|
17995
|
+
case "reviewQaTestCasesList": {
|
|
17996
|
+
const qaCode = listTarget?.qaCode;
|
|
17997
|
+
if (!qaCode) {
|
|
17998
|
+
throw new Error("reviewQaTestCasesList requires listTarget.qaCode");
|
|
17999
|
+
}
|
|
18000
|
+
return {
|
|
18001
|
+
body: fillListJsonPrompt({
|
|
18002
|
+
agentId: "ctx-review-qa-test-cases-list",
|
|
18003
|
+
agentDisplayName: "QA test cases \u2014 semantic review",
|
|
18004
|
+
worktreeRoot,
|
|
18005
|
+
listTaskDescription: `Review **${qaCode}-test-cases-list.json**: enforce **coversCodes**; normalize TC rows; **sourceReferences** minItems 1. Overwrite.${SRS50_COORD_LIST_REVIEW_HINT}`,
|
|
18006
|
+
listSchemaRef: schemaRef(worktreeRoot, "qa-test-cases-list.schema.json"),
|
|
18007
|
+
outputFileAbsolute,
|
|
18008
|
+
outputBasename,
|
|
18009
|
+
allowJsonFence: false,
|
|
18010
|
+
parentContextBlock: `
|
|
18011
|
+
## Parent context
|
|
18012
|
+
- qaCode: **${qaCode}**
|
|
18013
|
+
`,
|
|
18014
|
+
repairAppendix: listRepairAppendix
|
|
18015
|
+
}),
|
|
18016
|
+
listSchemaFile: "qa-test-cases-list.schema.json"
|
|
18017
|
+
};
|
|
18018
|
+
}
|
|
17457
18019
|
case "listUseCases": {
|
|
17458
18020
|
const fe = listTarget?.featureCode;
|
|
17459
18021
|
if (!fe) {
|
|
@@ -17626,7 +18188,15 @@ var STEP_OPEN_CODE_AGENT_IDS = {
|
|
|
17626
18188
|
listUseCases: "agent-list-use-cases",
|
|
17627
18189
|
reviewUseCasesList: "agent-review-use-cases-list",
|
|
17628
18190
|
listScenarios: "agent-list-scenarios",
|
|
17629
|
-
reviewScenariosList: "agent-review-scenarios-list"
|
|
18191
|
+
reviewScenariosList: "agent-review-scenarios-list",
|
|
18192
|
+
listInfrastructure: "agent-list-infrastructure",
|
|
18193
|
+
reviewInfrastructureList: "agent-review-infrastructure-list",
|
|
18194
|
+
listInfrastructureComponents: "agent-list-infrastructure-components",
|
|
18195
|
+
reviewInfrastructureComponentsList: "agent-review-infrastructure-components-list",
|
|
18196
|
+
listQa: "agent-list-qa",
|
|
18197
|
+
reviewQaList: "agent-review-qa-list",
|
|
18198
|
+
listQaTestCases: "agent-list-qa-test-cases",
|
|
18199
|
+
reviewQaTestCasesList: "agent-review-qa-test-cases-list"
|
|
17630
18200
|
};
|
|
17631
18201
|
var RESOLVE_OPEN_QUESTION_AGENT_STEM = "agent-resolve-open-question";
|
|
17632
18202
|
function clampMarkdownOpenQuestionIterations(raw) {
|
|
@@ -17654,46 +18224,86 @@ function outputPaths(step, worktreeRoot, listTarget) {
|
|
|
17654
18224
|
const ctx = contextDir(worktreeRoot);
|
|
17655
18225
|
switch (step) {
|
|
17656
18226
|
case "docsProject":
|
|
17657
|
-
return { absolute:
|
|
18227
|
+
return { absolute: path27.join(contextDir(worktreeRoot), "project.md"), basename: "project.md" };
|
|
17658
18228
|
case "architecture":
|
|
17659
|
-
return { absolute:
|
|
18229
|
+
return { absolute: path27.join(ctx, "architecture.md"), basename: "architecture.md" };
|
|
17660
18230
|
case "listFeatures":
|
|
17661
|
-
return { absolute:
|
|
18231
|
+
return { absolute: path27.join(ctx, "features-list.json"), basename: "features-list.json" };
|
|
17662
18232
|
case "reviewFeaturesList":
|
|
17663
|
-
return { absolute:
|
|
18233
|
+
return { absolute: path27.join(ctx, "features-list.json"), basename: "features-list.json" };
|
|
17664
18234
|
case "listRepoSurface":
|
|
17665
|
-
return { absolute:
|
|
18235
|
+
return { absolute: path27.join(ctx, "repo-surface-scan.json"), basename: "repo-surface-scan.json" };
|
|
17666
18236
|
case "listExperiences":
|
|
17667
|
-
return { absolute:
|
|
18237
|
+
return { absolute: path27.join(ctx, "experiences-list.json"), basename: "experiences-list.json" };
|
|
17668
18238
|
case "reviewExperiencesList":
|
|
17669
|
-
return { absolute:
|
|
18239
|
+
return { absolute: path27.join(ctx, "experiences-list.json"), basename: "experiences-list.json" };
|
|
17670
18240
|
case "listServices":
|
|
17671
|
-
return { absolute:
|
|
18241
|
+
return { absolute: path27.join(ctx, "services-list.json"), basename: "services-list.json" };
|
|
17672
18242
|
case "reviewServicesList":
|
|
17673
|
-
return { absolute:
|
|
18243
|
+
return { absolute: path27.join(ctx, "services-list.json"), basename: "services-list.json" };
|
|
17674
18244
|
case "listDataModel":
|
|
17675
|
-
return { absolute:
|
|
18245
|
+
return { absolute: path27.join(ctx, "data-model-list.json"), basename: "data-model-list.json" };
|
|
17676
18246
|
case "reviewDataModelList":
|
|
17677
|
-
return { absolute:
|
|
18247
|
+
return { absolute: path27.join(ctx, "data-model-list.json"), basename: "data-model-list.json" };
|
|
17678
18248
|
case "listTechStack":
|
|
17679
|
-
return { absolute:
|
|
18249
|
+
return { absolute: path27.join(ctx, "tech-stack-list.json"), basename: "tech-stack-list.json" };
|
|
17680
18250
|
case "reviewTechStackList":
|
|
17681
|
-
return { absolute:
|
|
18251
|
+
return { absolute: path27.join(ctx, "tech-stack-list.json"), basename: "tech-stack-list.json" };
|
|
18252
|
+
case "listInfrastructure":
|
|
18253
|
+
return { absolute: path27.join(ctx, "infrastructure-list.json"), basename: "infrastructure-list.json" };
|
|
18254
|
+
case "reviewInfrastructureList":
|
|
18255
|
+
return { absolute: path27.join(ctx, "infrastructure-list.json"), basename: "infrastructure-list.json" };
|
|
18256
|
+
case "listQa":
|
|
18257
|
+
return { absolute: path27.join(ctx, "qa-list.json"), basename: "qa-list.json" };
|
|
18258
|
+
case "reviewQaList":
|
|
18259
|
+
return { absolute: path27.join(ctx, "qa-list.json"), basename: "qa-list.json" };
|
|
18260
|
+
case "listInfrastructureComponents": {
|
|
18261
|
+
const inCode = listTarget?.infrastructureCode;
|
|
18262
|
+
if (!inCode) {
|
|
18263
|
+
throw new Error("listInfrastructureComponents requires listTarget.infrastructureCode");
|
|
18264
|
+
}
|
|
18265
|
+
const basename18 = `${inCode}-components-list.json`;
|
|
18266
|
+
return { absolute: path27.join(ctx, basename18), basename: basename18 };
|
|
18267
|
+
}
|
|
18268
|
+
case "reviewInfrastructureComponentsList": {
|
|
18269
|
+
const inCode = listTarget?.infrastructureCode;
|
|
18270
|
+
if (!inCode) {
|
|
18271
|
+
throw new Error("reviewInfrastructureComponentsList requires listTarget.infrastructureCode");
|
|
18272
|
+
}
|
|
18273
|
+
const basename18 = `${inCode}-components-list.json`;
|
|
18274
|
+
return { absolute: path27.join(ctx, basename18), basename: basename18 };
|
|
18275
|
+
}
|
|
18276
|
+
case "listQaTestCases": {
|
|
18277
|
+
const qaCode = listTarget?.qaCode;
|
|
18278
|
+
if (!qaCode) {
|
|
18279
|
+
throw new Error("listQaTestCases requires listTarget.qaCode");
|
|
18280
|
+
}
|
|
18281
|
+
const basename18 = `${qaCode}-test-cases-list.json`;
|
|
18282
|
+
return { absolute: path27.join(ctx, basename18), basename: basename18 };
|
|
18283
|
+
}
|
|
18284
|
+
case "reviewQaTestCasesList": {
|
|
18285
|
+
const qaCode = listTarget?.qaCode;
|
|
18286
|
+
if (!qaCode) {
|
|
18287
|
+
throw new Error("reviewQaTestCasesList requires listTarget.qaCode");
|
|
18288
|
+
}
|
|
18289
|
+
const basename18 = `${qaCode}-test-cases-list.json`;
|
|
18290
|
+
return { absolute: path27.join(ctx, basename18), basename: basename18 };
|
|
18291
|
+
}
|
|
17682
18292
|
case "listUseCases": {
|
|
17683
18293
|
const fe = listTarget?.featureCode;
|
|
17684
18294
|
if (!fe) {
|
|
17685
18295
|
throw new Error("listUseCases requires listTarget.featureCode");
|
|
17686
18296
|
}
|
|
17687
|
-
const
|
|
17688
|
-
return { absolute:
|
|
18297
|
+
const basename18 = `${fe}-use-cases-list.json`;
|
|
18298
|
+
return { absolute: path27.join(ctx, basename18), basename: basename18 };
|
|
17689
18299
|
}
|
|
17690
18300
|
case "reviewUseCasesList": {
|
|
17691
18301
|
const fe = listTarget?.featureCode;
|
|
17692
18302
|
if (!fe) {
|
|
17693
18303
|
throw new Error("reviewUseCasesList requires listTarget.featureCode");
|
|
17694
18304
|
}
|
|
17695
|
-
const
|
|
17696
|
-
return { absolute:
|
|
18305
|
+
const basename18 = `${fe}-use-cases-list.json`;
|
|
18306
|
+
return { absolute: path27.join(ctx, basename18), basename: basename18 };
|
|
17697
18307
|
}
|
|
17698
18308
|
case "listScenarios": {
|
|
17699
18309
|
const fe = listTarget?.featureCode;
|
|
@@ -17701,8 +18311,8 @@ function outputPaths(step, worktreeRoot, listTarget) {
|
|
|
17701
18311
|
if (!fe || !uc) {
|
|
17702
18312
|
throw new Error("listScenarios requires listTarget.featureCode and useCaseCode");
|
|
17703
18313
|
}
|
|
17704
|
-
const
|
|
17705
|
-
return { absolute:
|
|
18314
|
+
const basename18 = `${fe}_${uc}-scenarios-list.json`;
|
|
18315
|
+
return { absolute: path27.join(ctx, basename18), basename: basename18 };
|
|
17706
18316
|
}
|
|
17707
18317
|
case "reviewScenariosList": {
|
|
17708
18318
|
const fe = listTarget?.featureCode;
|
|
@@ -17710,24 +18320,24 @@ function outputPaths(step, worktreeRoot, listTarget) {
|
|
|
17710
18320
|
if (!fe || !uc) {
|
|
17711
18321
|
throw new Error("reviewScenariosList requires listTarget.featureCode and useCaseCode");
|
|
17712
18322
|
}
|
|
17713
|
-
const
|
|
17714
|
-
return { absolute:
|
|
18323
|
+
const basename18 = `${fe}_${uc}-scenarios-list.json`;
|
|
18324
|
+
return { absolute: path27.join(ctx, basename18), basename: basename18 };
|
|
17715
18325
|
}
|
|
17716
18326
|
case "listEntityFields": {
|
|
17717
18327
|
const dm = listTarget?.entityCode;
|
|
17718
18328
|
if (!dm) {
|
|
17719
18329
|
throw new Error("listEntityFields requires listTarget.entityCode");
|
|
17720
18330
|
}
|
|
17721
|
-
const
|
|
17722
|
-
return { absolute:
|
|
18331
|
+
const basename18 = `${dm}-fields-list.json`;
|
|
18332
|
+
return { absolute: path27.join(ctx, basename18), basename: basename18 };
|
|
17723
18333
|
}
|
|
17724
18334
|
case "reviewEntityFieldsList": {
|
|
17725
18335
|
const dm = listTarget?.entityCode;
|
|
17726
18336
|
if (!dm) {
|
|
17727
18337
|
throw new Error("reviewEntityFieldsList requires listTarget.entityCode");
|
|
17728
18338
|
}
|
|
17729
|
-
const
|
|
17730
|
-
return { absolute:
|
|
18339
|
+
const basename18 = `${dm}-fields-list.json`;
|
|
18340
|
+
return { absolute: path27.join(ctx, basename18), basename: basename18 };
|
|
17731
18341
|
}
|
|
17732
18342
|
default: {
|
|
17733
18343
|
const _u = step;
|
|
@@ -17736,7 +18346,7 @@ function outputPaths(step, worktreeRoot, listTarget) {
|
|
|
17736
18346
|
}
|
|
17737
18347
|
}
|
|
17738
18348
|
async function runOpenQuestionResolutionWorkstation(opts) {
|
|
17739
|
-
const runDir =
|
|
18349
|
+
const runDir = path27.join(opts.worktreeRoot, ".opencode", "_run");
|
|
17740
18350
|
fs30.mkdirSync(runDir, { recursive: true });
|
|
17741
18351
|
const resolutionJsonAbsolute = openQuestionResolutionJsonAbsolute(opts.worktreeRoot);
|
|
17742
18352
|
const body = fillResolveOpenQuestionPrompt({
|
|
@@ -17746,7 +18356,7 @@ async function runOpenQuestionResolutionWorkstation(opts) {
|
|
|
17746
18356
|
questionText: opts.questionText,
|
|
17747
18357
|
resolutionJsonAbsolute
|
|
17748
18358
|
});
|
|
17749
|
-
const promptPath =
|
|
18359
|
+
const promptPath = path27.join(runDir, `resolve-open-question-${Date.now()}.prompt.txt`);
|
|
17750
18360
|
fs30.writeFileSync(promptPath, body, "utf-8");
|
|
17751
18361
|
const vars = {
|
|
17752
18362
|
promptFile: promptPath,
|
|
@@ -18001,7 +18611,7 @@ async function runSynthesisMarkdownRemediationChain(common, step, workspaceLabel
|
|
|
18001
18611
|
if (common.abortSignal?.aborted) {
|
|
18002
18612
|
return { ok: false, cancelled: true, message: "Remediation stopped.", promptPath: "" };
|
|
18003
18613
|
}
|
|
18004
|
-
const runDir =
|
|
18614
|
+
const runDir = path27.join(common.worktreeRoot, ".opencode", "_run");
|
|
18005
18615
|
const r = await runOpenCodeMarkdownEvidenceRepairLoop({
|
|
18006
18616
|
worktreeRoot: common.worktreeRoot,
|
|
18007
18617
|
runDir,
|
|
@@ -18030,7 +18640,7 @@ async function runSynthesisMarkdownRemediationChain(common, step, workspaceLabel
|
|
|
18030
18640
|
void 0,
|
|
18031
18641
|
appendix
|
|
18032
18642
|
).body,
|
|
18033
|
-
promptPathForAttempt: (attemptIndex) =>
|
|
18643
|
+
promptPathForAttempt: (attemptIndex) => path27.join(runDir, `${step}-oqrem-a${String(attemptIndex)}-${Date.now()}.prompt.txt`),
|
|
18034
18644
|
argvVarsForPrompt: (promptPath) => ({
|
|
18035
18645
|
promptFile: promptPath,
|
|
18036
18646
|
agentId: STEP_OPEN_CODE_AGENT_IDS[step],
|
|
@@ -18051,7 +18661,7 @@ async function runDetailMarkdownRemediationChain(common, target, initialMarkdown
|
|
|
18051
18661
|
if (common.abortSignal?.aborted) {
|
|
18052
18662
|
return { ok: false, cancelled: true, message: "Remediation stopped.", promptPath: "" };
|
|
18053
18663
|
}
|
|
18054
|
-
const runDir =
|
|
18664
|
+
const runDir = path27.join(common.worktreeRoot, ".opencode", "_run");
|
|
18055
18665
|
const safeStem = target.outputBasename.replace(/[^A-Za-z0-9_.-]+/g, "_").slice(0, 120);
|
|
18056
18666
|
const r = await runOpenCodeMarkdownEvidenceRepairLoop({
|
|
18057
18667
|
worktreeRoot: common.worktreeRoot,
|
|
@@ -18081,7 +18691,7 @@ async function runDetailMarkdownRemediationChain(common, target, initialMarkdown
|
|
|
18081
18691
|
citationFormatExample: CITATION_EXAMPLE,
|
|
18082
18692
|
repairAppendix: appendix
|
|
18083
18693
|
}),
|
|
18084
|
-
promptPathForAttempt: (attemptIndex) =>
|
|
18694
|
+
promptPathForAttempt: (attemptIndex) => path27.join(
|
|
18085
18695
|
runDir,
|
|
18086
18696
|
`markdownDetail-${target.openCodeAgentStem}-${safeStem}-oqrem-a${String(attemptIndex)}-${Date.now()}.prompt.txt`
|
|
18087
18697
|
),
|
|
@@ -18359,8 +18969,8 @@ Run **Materialize agents** first (copies list schemas into this folder\u2019s \`
|
|
|
18359
18969
|
}
|
|
18360
18970
|
}
|
|
18361
18971
|
}
|
|
18362
|
-
fs30.mkdirSync(
|
|
18363
|
-
const runDir =
|
|
18972
|
+
fs30.mkdirSync(path27.dirname(outputFileAbsolute), { recursive: true });
|
|
18973
|
+
const runDir = path27.join(opts.worktreeRoot, ".opencode", "_run");
|
|
18364
18974
|
fs30.mkdirSync(runDir, { recursive: true });
|
|
18365
18975
|
const scopeSuffix = (opts.step === "listUseCases" || opts.step === "reviewUseCasesList") && opts.listTarget?.featureCode ? `-${opts.listTarget.featureCode}` : (opts.step === "listScenarios" || opts.step === "reviewScenariosList") && opts.listTarget?.featureCode && opts.listTarget?.useCaseCode ? `-${opts.listTarget.featureCode}_${opts.listTarget.useCaseCode}` : (opts.step === "listEntityFields" || opts.step === "reviewEntityFieldsList") && opts.listTarget?.entityCode ? `-${opts.listTarget.entityCode}` : "";
|
|
18366
18976
|
const rawRepair = opts.listJsonSchemaRepairAttempts;
|
|
@@ -18441,7 +19051,7 @@ Run **Materialize agents** first (copies list schemas into this folder\u2019s \`
|
|
|
18441
19051
|
void 0,
|
|
18442
19052
|
appendix
|
|
18443
19053
|
).body,
|
|
18444
|
-
promptPathForAttempt: (attemptIndex) =>
|
|
19054
|
+
promptPathForAttempt: (attemptIndex) => path27.join(runDir, `${opts.step}${scopeSuffix}-a${String(attemptIndex)}-${Date.now()}.prompt.txt`),
|
|
18445
19055
|
argvVarsForPrompt: (promptPath) => ({
|
|
18446
19056
|
promptFile: promptPath,
|
|
18447
19057
|
agentId: STEP_OPEN_CODE_AGENT_IDS[opts.step],
|
|
@@ -18568,7 +19178,7 @@ Run **Materialize agents** first (copies list schemas into this folder\u2019s \`
|
|
|
18568
19178
|
effectiveListSchemaFile ? repairAppendix : void 0,
|
|
18569
19179
|
effectiveListSchemaFile ? void 0 : markdownEvidenceRepairAppendix
|
|
18570
19180
|
);
|
|
18571
|
-
const promptPath =
|
|
19181
|
+
const promptPath = path27.join(runDir, `${opts.step}${scopeSuffix}-a${attempt}-${Date.now()}.prompt.txt`);
|
|
18572
19182
|
lastPromptPath = promptPath;
|
|
18573
19183
|
fs30.writeFileSync(promptPath, body, "utf-8");
|
|
18574
19184
|
const vars = {
|
|
@@ -18754,7 +19364,7 @@ Expected output: ${outputFileAbsolute}`;
|
|
|
18754
19364
|
const orderSet = new Set(CONTEXT_SYNTHESIS_TEST_STEP_ORDER);
|
|
18755
19365
|
if (orderSet.has(opts.step)) {
|
|
18756
19366
|
const ctx = contextDir(opts.worktreeRoot);
|
|
18757
|
-
const rel =
|
|
19367
|
+
const rel = path27.relative(ctx, outputFileAbsolute).split(path27.sep).join("/");
|
|
18758
19368
|
opts.onRemediationPhase?.("aceTracing");
|
|
18759
19369
|
try {
|
|
18760
19370
|
await runAceTracePhase({
|
|
@@ -18801,7 +19411,7 @@ Expected output: ${outputFileAbsolute}`;
|
|
|
18801
19411
|
var DETAIL_MARKDOWN_WORKSTATION_KIND = "markdownDetail";
|
|
18802
19412
|
async function runDetailMarkdownWorkstation(opts) {
|
|
18803
19413
|
const ctx = contextDir(opts.worktreeRoot);
|
|
18804
|
-
const outputFileAbsolute =
|
|
19414
|
+
const outputFileAbsolute = path27.join(ctx, opts.target.outputBasename);
|
|
18805
19415
|
const outputBasename = opts.target.outputBasename;
|
|
18806
19416
|
const rawMdEv = opts.markdownEvidenceRepairAttempts;
|
|
18807
19417
|
let maxMarkdownEvidenceRepairs = rawMdEv === void 0 ? 2 : Math.floor(Number(rawMdEv));
|
|
@@ -18810,8 +19420,8 @@ async function runDetailMarkdownWorkstation(opts) {
|
|
|
18810
19420
|
}
|
|
18811
19421
|
maxMarkdownEvidenceRepairs = Math.min(5, Math.max(0, maxMarkdownEvidenceRepairs));
|
|
18812
19422
|
const totalMarkdownRuns = 1 + maxMarkdownEvidenceRepairs;
|
|
18813
|
-
fs30.mkdirSync(
|
|
18814
|
-
const runDir =
|
|
19423
|
+
fs30.mkdirSync(path27.dirname(outputFileAbsolute), { recursive: true });
|
|
19424
|
+
const runDir = path27.join(opts.worktreeRoot, ".opencode", "_run");
|
|
18815
19425
|
fs30.mkdirSync(runDir, { recursive: true });
|
|
18816
19426
|
const safeStem = opts.target.outputBasename.replace(/[^A-Za-z0-9_.-]+/g, "_").slice(0, 120);
|
|
18817
19427
|
let lastPromptPath = "";
|
|
@@ -18864,7 +19474,7 @@ async function runDetailMarkdownWorkstation(opts) {
|
|
|
18864
19474
|
citationFormatExample: CITATION_EXAMPLE,
|
|
18865
19475
|
repairAppendix: appendix
|
|
18866
19476
|
}),
|
|
18867
|
-
promptPathForAttempt: (attemptIndex) =>
|
|
19477
|
+
promptPathForAttempt: (attemptIndex) => path27.join(
|
|
18868
19478
|
runDir,
|
|
18869
19479
|
`markdownDetail-${opts.target.openCodeAgentStem}-${safeStem}-a${String(attemptIndex)}-${Date.now()}.prompt.txt`
|
|
18870
19480
|
),
|
|
@@ -19009,7 +19619,7 @@ Expected output: ${outputFileAbsolute}`;
|
|
|
19009
19619
|
}
|
|
19010
19620
|
const ok = cliProcessOk && artefactOk && validationOk;
|
|
19011
19621
|
if (ok && opts.aceEnabled && sessionIdForAceTrace) {
|
|
19012
|
-
const rel =
|
|
19622
|
+
const rel = path27.relative(ctx, outputFileAbsolute).split(path27.sep).join("/");
|
|
19013
19623
|
opts.onRemediationPhase?.("aceTracing");
|
|
19014
19624
|
try {
|
|
19015
19625
|
await runAceTracePhase({
|
|
@@ -19057,7 +19667,7 @@ Expected output: ${outputFileAbsolute}`;
|
|
|
19057
19667
|
var import_child_process4 = require("child_process");
|
|
19058
19668
|
var fs31 = __toESM(require("fs"));
|
|
19059
19669
|
var os4 = __toESM(require("os"));
|
|
19060
|
-
var
|
|
19670
|
+
var path28 = __toESM(require("path"));
|
|
19061
19671
|
|
|
19062
19672
|
// src/analysis/gitWorktreeStaleRecovery.ts
|
|
19063
19673
|
var import_child_process3 = require("child_process");
|
|
@@ -19113,7 +19723,7 @@ function allocateEasyspecsWorktreePath(parentDir) {
|
|
|
19113
19723
|
const start = maxEasyspecsWorktreeIndex(parentDir);
|
|
19114
19724
|
for (let i = start + 1; i < start + 1e4; i++) {
|
|
19115
19725
|
const name = formatEasyspecsWorktreeFolderName(i);
|
|
19116
|
-
const wt =
|
|
19726
|
+
const wt = path28.join(parentDir, name);
|
|
19117
19727
|
if (!fs31.existsSync(wt)) {
|
|
19118
19728
|
return wt;
|
|
19119
19729
|
}
|
|
@@ -19133,7 +19743,7 @@ function readHeadBranchShort(repoRoot) {
|
|
|
19133
19743
|
return b.length > 0 ? b : void 0;
|
|
19134
19744
|
}
|
|
19135
19745
|
function createInPlaceWorktreeHandle(repositoryRootAbs) {
|
|
19136
|
-
const root =
|
|
19746
|
+
const root = path28.resolve(repositoryRootAbs);
|
|
19137
19747
|
return {
|
|
19138
19748
|
path: root,
|
|
19139
19749
|
repoRoot: root,
|
|
@@ -19142,16 +19752,16 @@ function createInPlaceWorktreeHandle(repositoryRootAbs) {
|
|
|
19142
19752
|
};
|
|
19143
19753
|
}
|
|
19144
19754
|
function resolveAnalysisCheckoutHandle(worktreePath, repositoryRoot) {
|
|
19145
|
-
const wt =
|
|
19146
|
-
const repo =
|
|
19755
|
+
const wt = path28.resolve(worktreePath);
|
|
19756
|
+
const repo = path28.resolve(repositoryRoot);
|
|
19147
19757
|
if (wt === repo) {
|
|
19148
19758
|
return createInPlaceWorktreeHandle(repo);
|
|
19149
19759
|
}
|
|
19150
19760
|
return attachWorktreeHandle(worktreePath, repositoryRoot);
|
|
19151
19761
|
}
|
|
19152
19762
|
function attachWorktreeHandle(worktreePath, repositoryRoot) {
|
|
19153
|
-
const wt =
|
|
19154
|
-
const repo =
|
|
19763
|
+
const wt = path28.resolve(worktreePath);
|
|
19764
|
+
const repo = path28.resolve(repositoryRoot);
|
|
19155
19765
|
return {
|
|
19156
19766
|
path: wt,
|
|
19157
19767
|
repoRoot: repo,
|
|
@@ -19169,7 +19779,7 @@ function attachWorktreeHandle(worktreePath, repositoryRoot) {
|
|
|
19169
19779
|
};
|
|
19170
19780
|
}
|
|
19171
19781
|
function createAnalysisWorktree(repoRoot, options) {
|
|
19172
|
-
const parent =
|
|
19782
|
+
const parent = path28.join(os4.tmpdir(), "easyspecs-analysis");
|
|
19173
19783
|
const wt = allocateEasyspecsWorktreePath(parent);
|
|
19174
19784
|
if (!wt) {
|
|
19175
19785
|
return {
|
|
@@ -19200,7 +19810,7 @@ function createAnalysisWorktree(repoRoot, options) {
|
|
|
19200
19810
|
if (attempt === 0 && isMissingRegisteredWorktreeError(fullMsg)) {
|
|
19201
19811
|
const pr = gitWorktreePruneSync(repoRoot);
|
|
19202
19812
|
if (pr.ok) {
|
|
19203
|
-
const wtName =
|
|
19813
|
+
const wtName = path28.basename(wt);
|
|
19204
19814
|
options?.log?.(`[worktree] git worktree prune \u2014 cleared stale registration for ${wtName} (${wt})`);
|
|
19205
19815
|
continue;
|
|
19206
19816
|
}
|
|
@@ -19298,7 +19908,7 @@ function noteOpenCodeAgentLaunched() {
|
|
|
19298
19908
|
|
|
19299
19909
|
// src/contextIndexAssembler.ts
|
|
19300
19910
|
var fs32 = __toESM(require("fs"));
|
|
19301
|
-
var
|
|
19911
|
+
var path29 = __toESM(require("path"));
|
|
19302
19912
|
|
|
19303
19913
|
// src/srsModel.ts
|
|
19304
19914
|
var APPLICATION_CONTEXT_KIND = "easyspecs.application-context";
|
|
@@ -19330,7 +19940,7 @@ function tryAttachMarkdown(node, contextDir2, relativePath) {
|
|
|
19330
19940
|
if (!norm || norm.includes("..")) {
|
|
19331
19941
|
return false;
|
|
19332
19942
|
}
|
|
19333
|
-
const full =
|
|
19943
|
+
const full = path29.join(contextDir2, norm);
|
|
19334
19944
|
try {
|
|
19335
19945
|
if (!fs32.existsSync(full) || !fs32.statSync(full).isFile()) {
|
|
19336
19946
|
return false;
|
|
@@ -19388,7 +19998,7 @@ function mergePersistedIndexUploadMetadata(previous, next) {
|
|
|
19388
19998
|
walkScopes3(next, apply);
|
|
19389
19999
|
}
|
|
19390
20000
|
function tryReadExistingIndexForMerge(contextDir2) {
|
|
19391
|
-
const p =
|
|
20001
|
+
const p = path29.join(contextDir2, "index-application-context.json");
|
|
19392
20002
|
try {
|
|
19393
20003
|
if (!fs32.existsSync(p)) {
|
|
19394
20004
|
return null;
|
|
@@ -19447,7 +20057,7 @@ function applyDetailMarkdownToDocument(doc, contextDir2) {
|
|
|
19447
20057
|
}
|
|
19448
20058
|
}
|
|
19449
20059
|
}
|
|
19450
|
-
const exp = readJson2(
|
|
20060
|
+
const exp = readJson2(path29.join(contextDir2, "experiences-list.json"));
|
|
19451
20061
|
if (doc.scopes.Experience?.nodes && exp?.views) {
|
|
19452
20062
|
for (const vNode of doc.scopes.Experience.nodes) {
|
|
19453
20063
|
if (vNode.type !== "View" || !vNode.code) {
|
|
@@ -19473,7 +20083,7 @@ function applyDetailMarkdownToDocument(doc, contextDir2) {
|
|
|
19473
20083
|
}
|
|
19474
20084
|
}
|
|
19475
20085
|
}
|
|
19476
|
-
const svcData = readJson2(
|
|
20086
|
+
const svcData = readJson2(path29.join(contextDir2, "services-list.json"));
|
|
19477
20087
|
if (doc.scopes.Service?.nodes && svcData?.services) {
|
|
19478
20088
|
for (const sNode of doc.scopes.Service.nodes) {
|
|
19479
20089
|
if (sNode.type !== "Service" || !sNode.code) {
|
|
@@ -19499,7 +20109,7 @@ function applyDetailMarkdownToDocument(doc, contextDir2) {
|
|
|
19499
20109
|
}
|
|
19500
20110
|
}
|
|
19501
20111
|
}
|
|
19502
|
-
const dmData = readJson2(
|
|
20112
|
+
const dmData = readJson2(path29.join(contextDir2, "data-model-list.json"));
|
|
19503
20113
|
if (doc.scopes.DataModel?.nodes && dmData?.entities) {
|
|
19504
20114
|
for (const eNode of doc.scopes.DataModel.nodes) {
|
|
19505
20115
|
if (eNode.type !== "Entity" || !eNode.code) {
|
|
@@ -19531,7 +20141,7 @@ function applyDetailMarkdownToDocument(doc, contextDir2) {
|
|
|
19531
20141
|
}
|
|
19532
20142
|
}
|
|
19533
20143
|
}
|
|
19534
|
-
const tsData = readJson2(
|
|
20144
|
+
const tsData = readJson2(path29.join(contextDir2, "tech-stack-list.json"));
|
|
19535
20145
|
if (doc.scopes.TechStack?.nodes && tsData?.tools) {
|
|
19536
20146
|
for (const tNode of doc.scopes.TechStack.nodes) {
|
|
19537
20147
|
if (tNode.type !== "Tool" || !tNode.code) {
|
|
@@ -19544,7 +20154,70 @@ function applyDetailMarkdownToDocument(doc, contextDir2) {
|
|
|
19544
20154
|
}
|
|
19545
20155
|
}
|
|
19546
20156
|
}
|
|
19547
|
-
|
|
20157
|
+
const infraData = readJson2(path29.join(contextDir2, "infrastructure-list.json"));
|
|
20158
|
+
if (doc.scopes.Infrastructure?.nodes && infraData?.infrastructure) {
|
|
20159
|
+
for (const inNode of doc.scopes.Infrastructure.nodes) {
|
|
20160
|
+
if (inNode.type !== "Infrastructure" || !inNode.code) {
|
|
20161
|
+
continue;
|
|
20162
|
+
}
|
|
20163
|
+
const inRow = infraData.infrastructure.find((r) => r.code === inNode.code);
|
|
20164
|
+
const inSlug = inRow ? slugOrFallback(inRow) : slugOrFallback({ code: inNode.code, name: inNode.name });
|
|
20165
|
+
if (inSlug && tryAttachMarkdown(inNode, contextDir2, `${inNode.code}-${inSlug}.md`)) {
|
|
20166
|
+
anyLink = true;
|
|
20167
|
+
}
|
|
20168
|
+
const cl = readJson2(
|
|
20169
|
+
path29.join(contextDir2, `${inNode.code}-components-list.json`)
|
|
20170
|
+
);
|
|
20171
|
+
if (!inNode.children || !cl?.components) {
|
|
20172
|
+
continue;
|
|
20173
|
+
}
|
|
20174
|
+
for (const icNode of inNode.children) {
|
|
20175
|
+
if (icNode.type !== "Component" || !icNode.code) {
|
|
20176
|
+
continue;
|
|
20177
|
+
}
|
|
20178
|
+
const icRow = cl.components.find((c) => c.code === icNode.code);
|
|
20179
|
+
const icSlug = icRow ? slugOrFallback(icRow) : slugOrFallback({ code: icNode.code, name: icNode.name });
|
|
20180
|
+
if (icSlug && tryAttachMarkdown(icNode, contextDir2, `${inNode.code}_${icNode.code}-${icSlug}.md`)) {
|
|
20181
|
+
anyLink = true;
|
|
20182
|
+
}
|
|
20183
|
+
}
|
|
20184
|
+
}
|
|
20185
|
+
}
|
|
20186
|
+
const qaData = readJson2(path29.join(contextDir2, "qa-list.json"));
|
|
20187
|
+
if (doc.scopes.QA?.nodes && qaData?.qa) {
|
|
20188
|
+
for (const qaNode of doc.scopes.QA.nodes) {
|
|
20189
|
+
if (qaNode.type !== "QA" || !qaNode.code) {
|
|
20190
|
+
continue;
|
|
20191
|
+
}
|
|
20192
|
+
const qaRow = qaData.qa.find((r) => r.code === qaNode.code);
|
|
20193
|
+
const qaSlug = qaRow ? slugOrFallback(qaRow) : slugOrFallback({ code: qaNode.code, name: qaNode.name });
|
|
20194
|
+
if (qaSlug && tryAttachMarkdown(qaNode, contextDir2, `${qaNode.code}-${qaSlug}.md`)) {
|
|
20195
|
+
anyLink = true;
|
|
20196
|
+
}
|
|
20197
|
+
const tc = readJson2(path29.join(contextDir2, `${qaNode.code}-test-cases-list.json`));
|
|
20198
|
+
if (!qaNode.children || !tc?.testCases) {
|
|
20199
|
+
continue;
|
|
20200
|
+
}
|
|
20201
|
+
for (const tcNode of qaNode.children) {
|
|
20202
|
+
if (tcNode.type !== "TestCase" || !tcNode.code) {
|
|
20203
|
+
continue;
|
|
20204
|
+
}
|
|
20205
|
+
const tcRow = tc.testCases.find((t) => t.code === tcNode.code);
|
|
20206
|
+
const tcSlug = tcRow ? slugOrFallback(tcRow) : slugOrFallback({ code: tcNode.code, name: tcNode.name });
|
|
20207
|
+
if (tcSlug && tryAttachMarkdown(tcNode, contextDir2, `${qaNode.code}_${tcNode.code}-${tcSlug}.md`)) {
|
|
20208
|
+
anyLink = true;
|
|
20209
|
+
}
|
|
20210
|
+
}
|
|
20211
|
+
}
|
|
20212
|
+
}
|
|
20213
|
+
const hasInfraOrQaScope = Boolean(doc.scopes.Infrastructure?.nodes?.length || doc.scopes.QA?.nodes?.length);
|
|
20214
|
+
if (hasInfraOrQaScope) {
|
|
20215
|
+
doc.version = 3;
|
|
20216
|
+
} else if (anyLink) {
|
|
20217
|
+
doc.version = 2;
|
|
20218
|
+
} else {
|
|
20219
|
+
doc.version = 1;
|
|
20220
|
+
}
|
|
19548
20221
|
}
|
|
19549
20222
|
function readJson2(filePath) {
|
|
19550
20223
|
try {
|
|
@@ -19555,7 +20228,7 @@ function readJson2(filePath) {
|
|
|
19555
20228
|
}
|
|
19556
20229
|
}
|
|
19557
20230
|
function safeReadFeaturesList(contextDir2) {
|
|
19558
|
-
const p =
|
|
20231
|
+
const p = path29.join(contextDir2, "features-list.json");
|
|
19559
20232
|
const data = readJson2(p);
|
|
19560
20233
|
if (!data?.features?.length) {
|
|
19561
20234
|
return null;
|
|
@@ -19563,7 +20236,7 @@ function safeReadFeaturesList(contextDir2) {
|
|
|
19563
20236
|
return data;
|
|
19564
20237
|
}
|
|
19565
20238
|
function safeReadUseCasesList(contextDir2, feCode) {
|
|
19566
|
-
const p =
|
|
20239
|
+
const p = path29.join(contextDir2, `${feCode}-use-cases-list.json`);
|
|
19567
20240
|
const data = readJson2(p);
|
|
19568
20241
|
if (!data?.useCases?.length) {
|
|
19569
20242
|
return null;
|
|
@@ -19571,7 +20244,7 @@ function safeReadUseCasesList(contextDir2, feCode) {
|
|
|
19571
20244
|
return data;
|
|
19572
20245
|
}
|
|
19573
20246
|
function scenariosListPath(contextDir2, feCode, ucCode) {
|
|
19574
|
-
return
|
|
20247
|
+
return path29.join(contextDir2, `${feCode}_${ucCode}-scenarios-list.json`);
|
|
19575
20248
|
}
|
|
19576
20249
|
function buildFeatureScope(contextDir2) {
|
|
19577
20250
|
const fl = safeReadFeaturesList(contextDir2);
|
|
@@ -19608,7 +20281,7 @@ function buildFeatureScope(contextDir2) {
|
|
|
19608
20281
|
return nodes;
|
|
19609
20282
|
}
|
|
19610
20283
|
function buildExperienceScope(contextDir2) {
|
|
19611
|
-
const data = readJson2(
|
|
20284
|
+
const data = readJson2(path29.join(contextDir2, "experiences-list.json"));
|
|
19612
20285
|
if (!data?.views?.length) {
|
|
19613
20286
|
return [];
|
|
19614
20287
|
}
|
|
@@ -19620,7 +20293,7 @@ function buildExperienceScope(contextDir2) {
|
|
|
19620
20293
|
}));
|
|
19621
20294
|
}
|
|
19622
20295
|
function buildServiceScope(contextDir2) {
|
|
19623
|
-
const data = readJson2(
|
|
20296
|
+
const data = readJson2(path29.join(contextDir2, "services-list.json"));
|
|
19624
20297
|
if (!data?.services?.length) {
|
|
19625
20298
|
return [];
|
|
19626
20299
|
}
|
|
@@ -19632,13 +20305,13 @@ function buildServiceScope(contextDir2) {
|
|
|
19632
20305
|
}));
|
|
19633
20306
|
}
|
|
19634
20307
|
function readEntityFieldsList(contextDir2, dmCode) {
|
|
19635
|
-
const p =
|
|
20308
|
+
const p = path29.join(contextDir2, `${dmCode}-fields-list.json`);
|
|
19636
20309
|
const file = readJson2(p);
|
|
19637
20310
|
const rows = Array.isArray(file?.fields) ? file.fields : [];
|
|
19638
20311
|
return rows.filter((f) => Boolean(f?.code && f?.name));
|
|
19639
20312
|
}
|
|
19640
20313
|
function buildDataModelScope(contextDir2) {
|
|
19641
|
-
const data = readJson2(
|
|
20314
|
+
const data = readJson2(path29.join(contextDir2, "data-model-list.json"));
|
|
19642
20315
|
if (!data?.entities?.length) {
|
|
19643
20316
|
return [];
|
|
19644
20317
|
}
|
|
@@ -19656,12 +20329,58 @@ function buildDataModelScope(contextDir2) {
|
|
|
19656
20329
|
});
|
|
19657
20330
|
}
|
|
19658
20331
|
function buildTechStackScope(contextDir2) {
|
|
19659
|
-
const data = readJson2(
|
|
20332
|
+
const data = readJson2(path29.join(contextDir2, "tech-stack-list.json"));
|
|
19660
20333
|
if (!data?.tools?.length) {
|
|
19661
20334
|
return [];
|
|
19662
20335
|
}
|
|
19663
20336
|
return data.tools.map((t) => ({ type: "Tool", code: t.code, name: t.name }));
|
|
19664
20337
|
}
|
|
20338
|
+
function buildInfrastructureScope(contextDir2) {
|
|
20339
|
+
const data = readJson2(path29.join(contextDir2, "infrastructure-list.json"));
|
|
20340
|
+
if (!data?.infrastructure?.length) {
|
|
20341
|
+
return [];
|
|
20342
|
+
}
|
|
20343
|
+
const nodes = [];
|
|
20344
|
+
for (const row2 of data.infrastructure) {
|
|
20345
|
+
const cl = readJson2(
|
|
20346
|
+
path29.join(contextDir2, `${row2.code}-components-list.json`)
|
|
20347
|
+
);
|
|
20348
|
+
const icNodes = cl?.components?.map((c) => ({
|
|
20349
|
+
type: "Component",
|
|
20350
|
+
code: c.code,
|
|
20351
|
+
name: c.name
|
|
20352
|
+
})) ?? [];
|
|
20353
|
+
nodes.push({
|
|
20354
|
+
type: "Infrastructure",
|
|
20355
|
+
code: row2.code,
|
|
20356
|
+
name: row2.name,
|
|
20357
|
+
children: icNodes.length ? icNodes : void 0
|
|
20358
|
+
});
|
|
20359
|
+
}
|
|
20360
|
+
return nodes;
|
|
20361
|
+
}
|
|
20362
|
+
function buildQaScope(contextDir2) {
|
|
20363
|
+
const data = readJson2(path29.join(contextDir2, "qa-list.json"));
|
|
20364
|
+
if (!data?.qa?.length) {
|
|
20365
|
+
return [];
|
|
20366
|
+
}
|
|
20367
|
+
const nodes = [];
|
|
20368
|
+
for (const row2 of data.qa) {
|
|
20369
|
+
const tc = readJson2(path29.join(contextDir2, `${row2.code}-test-cases-list.json`));
|
|
20370
|
+
const tcNodes = tc?.testCases?.map((t) => ({
|
|
20371
|
+
type: "TestCase",
|
|
20372
|
+
code: t.code,
|
|
20373
|
+
name: t.name
|
|
20374
|
+
})) ?? [];
|
|
20375
|
+
nodes.push({
|
|
20376
|
+
type: "QA",
|
|
20377
|
+
code: row2.code,
|
|
20378
|
+
name: row2.name,
|
|
20379
|
+
children: tcNodes.length ? tcNodes : void 0
|
|
20380
|
+
});
|
|
20381
|
+
}
|
|
20382
|
+
return nodes;
|
|
20383
|
+
}
|
|
19665
20384
|
function countDriftNodes(nodes) {
|
|
19666
20385
|
let n = 0;
|
|
19667
20386
|
for (const node of nodes) {
|
|
@@ -19683,6 +20402,8 @@ function assembleApplicationContextIndex(contextDir2, title = "Application conte
|
|
|
19683
20402
|
const serviceNodes = buildServiceScope(contextDir2);
|
|
19684
20403
|
const dataModelNodes = buildDataModelScope(contextDir2);
|
|
19685
20404
|
const techNodes = buildTechStackScope(contextDir2);
|
|
20405
|
+
const infrastructureNodes = buildInfrastructureScope(contextDir2);
|
|
20406
|
+
const qaNodes = buildQaScope(contextDir2);
|
|
19686
20407
|
const scopes = {};
|
|
19687
20408
|
if (featureNodes.length) {
|
|
19688
20409
|
scopes.Feature = { nodes: featureNodes };
|
|
@@ -19699,10 +20420,17 @@ function assembleApplicationContextIndex(contextDir2, title = "Application conte
|
|
|
19699
20420
|
if (techNodes.length) {
|
|
19700
20421
|
scopes.TechStack = { nodes: techNodes };
|
|
19701
20422
|
}
|
|
19702
|
-
|
|
20423
|
+
if (infrastructureNodes.length) {
|
|
20424
|
+
scopes.Infrastructure = { nodes: infrastructureNodes };
|
|
20425
|
+
}
|
|
20426
|
+
if (qaNodes.length) {
|
|
20427
|
+
scopes.QA = { nodes: qaNodes };
|
|
20428
|
+
}
|
|
20429
|
+
const driftCount = countScopeDrift(featureNodes) + countScopeDrift(experienceNodes) + countScopeDrift(serviceNodes) + countScopeDrift(dataModelNodes) + countScopeDrift(techNodes) + countScopeDrift(infrastructureNodes) + countScopeDrift(qaNodes);
|
|
20430
|
+
const hasInfraOrQa = infrastructureNodes.length > 0 || qaNodes.length > 0;
|
|
19703
20431
|
return {
|
|
19704
20432
|
kind: APPLICATION_CONTEXT_KIND,
|
|
19705
|
-
version: 1,
|
|
20433
|
+
version: hasInfraOrQa ? 3 : 1,
|
|
19706
20434
|
title,
|
|
19707
20435
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19708
20436
|
driftCount,
|
|
@@ -19725,7 +20453,7 @@ function writeIndexApplicationContext(contextDir2, title, options) {
|
|
|
19725
20453
|
if (!validation.ok) {
|
|
19726
20454
|
throw new Error(`index-application-context.json schema validation failed: ${validation.errors.join("; ")}`);
|
|
19727
20455
|
}
|
|
19728
|
-
const target =
|
|
20456
|
+
const target = path29.join(contextDir2, "index-application-context.json");
|
|
19729
20457
|
const tmp = `${target}.${process.pid}.tmp`;
|
|
19730
20458
|
try {
|
|
19731
20459
|
fs32.writeFileSync(tmp, JSON.stringify(doc, null, 2), "utf-8");
|
|
@@ -19742,7 +20470,7 @@ function writeIndexApplicationContext(contextDir2, title, options) {
|
|
|
19742
20470
|
|
|
19743
20471
|
// src/pipelines/linkMapping/linkMappingPipeline.ts
|
|
19744
20472
|
var fs33 = __toESM(require("node:fs"));
|
|
19745
|
-
var
|
|
20473
|
+
var path30 = __toESM(require("node:path"));
|
|
19746
20474
|
var SLUG2 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
19747
20475
|
function safeStr2(v) {
|
|
19748
20476
|
return typeof v === "string" ? v.trim() : "";
|
|
@@ -19780,13 +20508,13 @@ var HEADING_CHILD_DOCUMENTS = "## EasySpecs \u2014 Child documents";
|
|
|
19780
20508
|
var HEADING_PARENT_DOCUMENTS = "## EasySpecs \u2014 Parent documents";
|
|
19781
20509
|
var NONE_LINE = "*None.*";
|
|
19782
20510
|
function scenariosListPath2(contextDir2, feCode, ucCode) {
|
|
19783
|
-
return
|
|
20511
|
+
return path30.join(contextDir2, `${feCode}_${ucCode}-scenarios-list.json`);
|
|
19784
20512
|
}
|
|
19785
20513
|
function useCasesListPath(contextDir2, feCode) {
|
|
19786
|
-
return
|
|
20514
|
+
return path30.join(contextDir2, `${feCode}-use-cases-list.json`);
|
|
19787
20515
|
}
|
|
19788
20516
|
function readEntityFieldsList2(contextDir2, dmCode) {
|
|
19789
|
-
const p =
|
|
20517
|
+
const p = path30.join(contextDir2, `${dmCode}-fields-list.json`);
|
|
19790
20518
|
const file = readJson3(p);
|
|
19791
20519
|
const rows = Array.isArray(file?.fields) ? file.fields : [];
|
|
19792
20520
|
return rows.filter((f) => Boolean(f?.code && f?.name));
|
|
@@ -19796,7 +20524,7 @@ function existsContextFile(contextDir2, rel) {
|
|
|
19796
20524
|
if (!norm || norm.includes("..")) {
|
|
19797
20525
|
return false;
|
|
19798
20526
|
}
|
|
19799
|
-
const full =
|
|
20527
|
+
const full = path30.join(contextDir2, norm);
|
|
19800
20528
|
try {
|
|
19801
20529
|
return fs33.existsSync(full) && fs33.statSync(full).isFile();
|
|
19802
20530
|
} catch {
|
|
@@ -19847,11 +20575,39 @@ function toolDetailBasename(t) {
|
|
|
19847
20575
|
const slug = slugOrFallback2(t);
|
|
19848
20576
|
return slug ? `${t.code}-${slug}.md` : null;
|
|
19849
20577
|
}
|
|
20578
|
+
function readInfrastructureComponentsList(contextDir2, inCode) {
|
|
20579
|
+
const p = path30.join(contextDir2, `${inCode}-components-list.json`);
|
|
20580
|
+
const file = readJson3(p);
|
|
20581
|
+
const rows = Array.isArray(file?.components) ? file.components : [];
|
|
20582
|
+
return rows.filter((c) => Boolean(c?.code && c?.name));
|
|
20583
|
+
}
|
|
20584
|
+
function readQaTestCasesList(contextDir2, qaCode) {
|
|
20585
|
+
const p = path30.join(contextDir2, `${qaCode}-test-cases-list.json`);
|
|
20586
|
+
const file = readJson3(p);
|
|
20587
|
+
const rows = Array.isArray(file?.testCases) ? file.testCases : [];
|
|
20588
|
+
return rows.filter((tc) => Boolean(tc?.code && tc?.name));
|
|
20589
|
+
}
|
|
20590
|
+
function infrastructureDetailBasename(item) {
|
|
20591
|
+
const slug = slugOrFallback2(item);
|
|
20592
|
+
return slug ? `${item.code}-${slug}.md` : null;
|
|
20593
|
+
}
|
|
20594
|
+
function componentDetailBasename(inCode, c) {
|
|
20595
|
+
const slug = slugOrFallback2(c);
|
|
20596
|
+
return slug ? `${inCode}_${c.code}-${slug}.md` : null;
|
|
20597
|
+
}
|
|
20598
|
+
function qaDetailBasename(item) {
|
|
20599
|
+
const slug = slugOrFallback2(item);
|
|
20600
|
+
return slug ? `${item.code}-${slug}.md` : null;
|
|
20601
|
+
}
|
|
20602
|
+
function testCaseDetailBasename(qaCode, tc) {
|
|
20603
|
+
const slug = slugOrFallback2(tc);
|
|
20604
|
+
return slug ? `${qaCode}_${tc.code}-${slug}.md` : null;
|
|
20605
|
+
}
|
|
19850
20606
|
function markdownRelativeHref(fromFileAbs, toFileAbs) {
|
|
19851
|
-
const dir =
|
|
19852
|
-
let rel =
|
|
20607
|
+
const dir = path30.dirname(fromFileAbs);
|
|
20608
|
+
let rel = path30.relative(dir, toFileAbs);
|
|
19853
20609
|
rel = rel.replace(/\\/g, "/");
|
|
19854
|
-
if (!rel.startsWith(".") && !
|
|
20610
|
+
if (!rel.startsWith(".") && !path30.isAbsolute(rel)) {
|
|
19855
20611
|
rel = `./${rel}`;
|
|
19856
20612
|
}
|
|
19857
20613
|
return rel;
|
|
@@ -19900,7 +20656,7 @@ function collectMarkdownFilesRecursive(dir, acc) {
|
|
|
19900
20656
|
return;
|
|
19901
20657
|
}
|
|
19902
20658
|
for (const e of entries) {
|
|
19903
|
-
const p =
|
|
20659
|
+
const p = path30.join(dir, e.name);
|
|
19904
20660
|
if (e.isDirectory()) {
|
|
19905
20661
|
collectMarkdownFilesRecursive(p, acc);
|
|
19906
20662
|
} else if (e.isFile() && e.name.endsWith(".md")) {
|
|
@@ -19940,13 +20696,13 @@ function validateEasyspecsNavLinksInContext(contextDirAbs) {
|
|
|
19940
20696
|
if (!href || href.startsWith("http://") || href.startsWith("https://") || href.startsWith("#")) {
|
|
19941
20697
|
continue;
|
|
19942
20698
|
}
|
|
19943
|
-
const target =
|
|
20699
|
+
const target = path30.normalize(path30.join(path30.dirname(abs), href));
|
|
19944
20700
|
try {
|
|
19945
20701
|
if (!fs33.existsSync(target) || !fs33.statSync(target).isFile()) {
|
|
19946
|
-
broken.push(`${
|
|
20702
|
+
broken.push(`${path30.relative(contextDirAbs, abs)} \u2192 ${href}`);
|
|
19947
20703
|
}
|
|
19948
20704
|
} catch {
|
|
19949
|
-
broken.push(`${
|
|
20705
|
+
broken.push(`${path30.relative(contextDirAbs, abs)} \u2192 ${href}`);
|
|
19950
20706
|
}
|
|
19951
20707
|
}
|
|
19952
20708
|
scan = scan.slice(end + NAV_CHILDREN_END.length);
|
|
@@ -19966,13 +20722,13 @@ function validateEasyspecsNavLinksInContext(contextDirAbs) {
|
|
|
19966
20722
|
if (!href || href.startsWith("http://") || href.startsWith("https://") || href.startsWith("#")) {
|
|
19967
20723
|
continue;
|
|
19968
20724
|
}
|
|
19969
|
-
const target =
|
|
20725
|
+
const target = path30.normalize(path30.join(path30.dirname(abs), href));
|
|
19970
20726
|
try {
|
|
19971
20727
|
if (!fs33.existsSync(target) || !fs33.statSync(target).isFile()) {
|
|
19972
|
-
broken.push(`${
|
|
20728
|
+
broken.push(`${path30.relative(contextDirAbs, abs)} \u2192 ${href}`);
|
|
19973
20729
|
}
|
|
19974
20730
|
} catch {
|
|
19975
|
-
broken.push(`${
|
|
20731
|
+
broken.push(`${path30.relative(contextDirAbs, abs)} \u2192 ${href}`);
|
|
19976
20732
|
}
|
|
19977
20733
|
}
|
|
19978
20734
|
scan = scan.slice(end + NAV_PARENTS_END.length);
|
|
@@ -19996,7 +20752,7 @@ function buildNavEdges(contextDir2) {
|
|
|
19996
20752
|
const projectBasename = "project.md";
|
|
19997
20753
|
const archBasename = "architecture.md";
|
|
19998
20754
|
addParent(archBasename, "EasySpecs project", projectBasename);
|
|
19999
|
-
const fl = readJson3(
|
|
20755
|
+
const fl = readJson3(path30.join(contextDir2, "features-list.json"));
|
|
20000
20756
|
if (fl?.features?.length) {
|
|
20001
20757
|
for (const fe of fl.features) {
|
|
20002
20758
|
const feBase = featureDetailBasename(fe);
|
|
@@ -20033,7 +20789,7 @@ function buildNavEdges(contextDir2) {
|
|
|
20033
20789
|
}
|
|
20034
20790
|
}
|
|
20035
20791
|
}
|
|
20036
|
-
const exp = readJson3(
|
|
20792
|
+
const exp = readJson3(path30.join(contextDir2, "experiences-list.json"));
|
|
20037
20793
|
if (exp?.views?.length) {
|
|
20038
20794
|
for (const v of exp.views) {
|
|
20039
20795
|
const vBase = viewDetailBasename(v);
|
|
@@ -20055,7 +20811,7 @@ function buildNavEdges(contextDir2) {
|
|
|
20055
20811
|
}
|
|
20056
20812
|
}
|
|
20057
20813
|
}
|
|
20058
|
-
const svcData = readJson3(
|
|
20814
|
+
const svcData = readJson3(path30.join(contextDir2, "services-list.json"));
|
|
20059
20815
|
if (svcData?.services?.length) {
|
|
20060
20816
|
for (const s of svcData.services) {
|
|
20061
20817
|
const sBase = serviceDetailBasename(s);
|
|
@@ -20077,7 +20833,7 @@ function buildNavEdges(contextDir2) {
|
|
|
20077
20833
|
}
|
|
20078
20834
|
}
|
|
20079
20835
|
}
|
|
20080
|
-
const dmData = readJson3(
|
|
20836
|
+
const dmData = readJson3(path30.join(contextDir2, "data-model-list.json"));
|
|
20081
20837
|
if (dmData?.entities?.length) {
|
|
20082
20838
|
for (const e of dmData.entities) {
|
|
20083
20839
|
const eBase = entityDetailBasename(e);
|
|
@@ -20107,7 +20863,7 @@ function buildNavEdges(contextDir2) {
|
|
|
20107
20863
|
}
|
|
20108
20864
|
}
|
|
20109
20865
|
}
|
|
20110
|
-
const tsData = readJson3(
|
|
20866
|
+
const tsData = readJson3(path30.join(contextDir2, "tech-stack-list.json"));
|
|
20111
20867
|
if (tsData?.tools?.length) {
|
|
20112
20868
|
for (const t of tsData.tools) {
|
|
20113
20869
|
const tBase = toolDetailBasename(t);
|
|
@@ -20117,11 +20873,51 @@ function buildNavEdges(contextDir2) {
|
|
|
20117
20873
|
addParent(tBase, "EasySpecs project", projectBasename);
|
|
20118
20874
|
}
|
|
20119
20875
|
}
|
|
20876
|
+
const inData = readJson3(path30.join(contextDir2, "infrastructure-list.json"));
|
|
20877
|
+
if (inData?.infrastructure?.length) {
|
|
20878
|
+
for (const item of inData.infrastructure) {
|
|
20879
|
+
const inBase = infrastructureDetailBasename(item);
|
|
20880
|
+
if (!inBase || !existsContextFile(contextDir2, inBase)) {
|
|
20881
|
+
continue;
|
|
20882
|
+
}
|
|
20883
|
+
addParent(inBase, "EasySpecs project", projectBasename);
|
|
20884
|
+
const components = readInfrastructureComponentsList(contextDir2, item.code);
|
|
20885
|
+
for (const c of components) {
|
|
20886
|
+
const cBase = componentDetailBasename(item.code, c);
|
|
20887
|
+
if (!cBase || !existsContextFile(contextDir2, cBase)) {
|
|
20888
|
+
continue;
|
|
20889
|
+
}
|
|
20890
|
+
addChild(inBase, c.name || c.code, cBase);
|
|
20891
|
+
addParent(cBase, item.name || item.code, inBase);
|
|
20892
|
+
addParent(cBase, "EasySpecs project", projectBasename);
|
|
20893
|
+
}
|
|
20894
|
+
}
|
|
20895
|
+
}
|
|
20896
|
+
const qaData = readJson3(path30.join(contextDir2, "qa-list.json"));
|
|
20897
|
+
if (qaData?.qa?.length) {
|
|
20898
|
+
for (const item of qaData.qa) {
|
|
20899
|
+
const qaBase = qaDetailBasename(item);
|
|
20900
|
+
if (!qaBase || !existsContextFile(contextDir2, qaBase)) {
|
|
20901
|
+
continue;
|
|
20902
|
+
}
|
|
20903
|
+
addParent(qaBase, "EasySpecs project", projectBasename);
|
|
20904
|
+
const testCases = readQaTestCasesList(contextDir2, item.code);
|
|
20905
|
+
for (const tc of testCases) {
|
|
20906
|
+
const tcBase = testCaseDetailBasename(item.code, tc);
|
|
20907
|
+
if (!tcBase || !existsContextFile(contextDir2, tcBase)) {
|
|
20908
|
+
continue;
|
|
20909
|
+
}
|
|
20910
|
+
addChild(qaBase, tc.name || tc.code, tcBase);
|
|
20911
|
+
addParent(tcBase, item.name || item.code, qaBase);
|
|
20912
|
+
addParent(tcBase, "EasySpecs project", projectBasename);
|
|
20913
|
+
}
|
|
20914
|
+
}
|
|
20915
|
+
}
|
|
20120
20916
|
return { children, parents };
|
|
20121
20917
|
}
|
|
20122
20918
|
function renderProjectMdSections(contextDir2) {
|
|
20123
20919
|
const chunks = [];
|
|
20124
|
-
const fl = readJson3(
|
|
20920
|
+
const fl = readJson3(path30.join(contextDir2, "features-list.json"));
|
|
20125
20921
|
const featureLines = [];
|
|
20126
20922
|
if (fl?.features?.length) {
|
|
20127
20923
|
for (const fe of fl.features) {
|
|
@@ -20132,7 +20928,7 @@ function renderProjectMdSections(contextDir2) {
|
|
|
20132
20928
|
}
|
|
20133
20929
|
}
|
|
20134
20930
|
chunks.push("### Features", "", featureLines.length ? featureLines.join("\n") : NONE_LINE, "");
|
|
20135
|
-
const exp = readJson3(
|
|
20931
|
+
const exp = readJson3(path30.join(contextDir2, "experiences-list.json"));
|
|
20136
20932
|
const xpLines = [];
|
|
20137
20933
|
if (exp?.views?.length) {
|
|
20138
20934
|
for (const v of exp.views) {
|
|
@@ -20143,7 +20939,7 @@ function renderProjectMdSections(contextDir2) {
|
|
|
20143
20939
|
}
|
|
20144
20940
|
}
|
|
20145
20941
|
chunks.push("### Experiences", "", xpLines.length ? xpLines.join("\n") : NONE_LINE, "");
|
|
20146
|
-
const svcData = readJson3(
|
|
20942
|
+
const svcData = readJson3(path30.join(contextDir2, "services-list.json"));
|
|
20147
20943
|
const svLines = [];
|
|
20148
20944
|
if (svcData?.services?.length) {
|
|
20149
20945
|
for (const s of svcData.services) {
|
|
@@ -20154,7 +20950,7 @@ function renderProjectMdSections(contextDir2) {
|
|
|
20154
20950
|
}
|
|
20155
20951
|
}
|
|
20156
20952
|
chunks.push("### Services", "", svLines.length ? svLines.join("\n") : NONE_LINE, "");
|
|
20157
|
-
const tsData = readJson3(
|
|
20953
|
+
const tsData = readJson3(path30.join(contextDir2, "tech-stack-list.json"));
|
|
20158
20954
|
const tsLines = [];
|
|
20159
20955
|
if (tsData?.tools?.length) {
|
|
20160
20956
|
for (const t of tsData.tools) {
|
|
@@ -20165,7 +20961,29 @@ function renderProjectMdSections(contextDir2) {
|
|
|
20165
20961
|
}
|
|
20166
20962
|
}
|
|
20167
20963
|
chunks.push("### Tech stack", "", tsLines.length ? tsLines.join("\n") : NONE_LINE, "");
|
|
20168
|
-
const
|
|
20964
|
+
const inData = readJson3(path30.join(contextDir2, "infrastructure-list.json"));
|
|
20965
|
+
const inLines = [];
|
|
20966
|
+
if (inData?.infrastructure?.length) {
|
|
20967
|
+
for (const item of inData.infrastructure) {
|
|
20968
|
+
const inBase = infrastructureDetailBasename(item);
|
|
20969
|
+
if (inBase && existsContextFile(contextDir2, inBase)) {
|
|
20970
|
+
inLines.push(bulletLink(item.name || item.code, `./${inBase}`));
|
|
20971
|
+
}
|
|
20972
|
+
}
|
|
20973
|
+
}
|
|
20974
|
+
chunks.push("### Infrastructure", "", inLines.length ? inLines.join("\n") : NONE_LINE, "");
|
|
20975
|
+
const qaData = readJson3(path30.join(contextDir2, "qa-list.json"));
|
|
20976
|
+
const qaLines = [];
|
|
20977
|
+
if (qaData?.qa?.length) {
|
|
20978
|
+
for (const item of qaData.qa) {
|
|
20979
|
+
const qaBase = qaDetailBasename(item);
|
|
20980
|
+
if (qaBase && existsContextFile(contextDir2, qaBase)) {
|
|
20981
|
+
qaLines.push(bulletLink(item.name || item.code, `./${qaBase}`));
|
|
20982
|
+
}
|
|
20983
|
+
}
|
|
20984
|
+
}
|
|
20985
|
+
chunks.push("### QA", "", qaLines.length ? qaLines.join("\n") : NONE_LINE, "");
|
|
20986
|
+
const dmData = readJson3(path30.join(contextDir2, "data-model-list.json"));
|
|
20169
20987
|
const dmLines = [];
|
|
20170
20988
|
if (dmData?.entities?.length) {
|
|
20171
20989
|
for (const e of dmData.entities) {
|
|
@@ -20175,15 +20993,15 @@ function renderProjectMdSections(contextDir2) {
|
|
|
20175
20993
|
}
|
|
20176
20994
|
}
|
|
20177
20995
|
}
|
|
20178
|
-
const dmListPath =
|
|
20996
|
+
const dmListPath = path30.join(contextDir2, "data-model-list.json");
|
|
20179
20997
|
if (dmLines.length === 0 && fs33.existsSync(dmListPath)) {
|
|
20180
20998
|
dmLines.push(bulletLink("Data model registry (JSON)", "./data-model-list.json"));
|
|
20181
20999
|
}
|
|
20182
21000
|
chunks.push("### Data model", "", dmLines.length ? dmLines.join("\n") : NONE_LINE, "");
|
|
20183
21001
|
return chunks;
|
|
20184
21002
|
}
|
|
20185
|
-
function patchOneFile(contextDir2,
|
|
20186
|
-
const abs =
|
|
21003
|
+
function patchOneFile(contextDir2, basename18, innerChildren, innerParents, opts) {
|
|
21004
|
+
const abs = path30.join(contextDir2, basename18);
|
|
20187
21005
|
if (!fs33.existsSync(abs)) {
|
|
20188
21006
|
return;
|
|
20189
21007
|
}
|
|
@@ -20191,7 +21009,7 @@ function patchOneFile(contextDir2, basename17, innerChildren, innerParents, opts
|
|
|
20191
21009
|
try {
|
|
20192
21010
|
body = fs33.readFileSync(abs, "utf8");
|
|
20193
21011
|
} catch (e) {
|
|
20194
|
-
opts.log?.(`[pipeline:link-mapping] skip read ${
|
|
21012
|
+
opts.log?.(`[pipeline:link-mapping] skip read ${basename18}: ${e instanceof Error ? e.message : String(e)}`);
|
|
20195
21013
|
return;
|
|
20196
21014
|
}
|
|
20197
21015
|
let next = replaceOrAppendRegion(body, NAV_CHILDREN_START, NAV_CHILDREN_END, innerChildren);
|
|
@@ -20199,13 +21017,13 @@ function patchOneFile(contextDir2, basename17, innerChildren, innerParents, opts
|
|
|
20199
21017
|
fs33.writeFileSync(abs, next, "utf8");
|
|
20200
21018
|
}
|
|
20201
21019
|
function runLinkMappingPipeline(contextDirAbs, opts = {}) {
|
|
20202
|
-
const contextDir2 =
|
|
21020
|
+
const contextDir2 = path30.resolve(contextDirAbs);
|
|
20203
21021
|
if (!fs33.existsSync(contextDir2) || !fs33.statSync(contextDir2).isDirectory()) {
|
|
20204
21022
|
return { ok: false, error: `Context directory does not exist: ${contextDir2}` };
|
|
20205
21023
|
}
|
|
20206
21024
|
const edges = buildNavEdges(contextDir2);
|
|
20207
|
-
const projectAbs =
|
|
20208
|
-
const archAbs =
|
|
21025
|
+
const projectAbs = path30.join(contextDir2, "project.md");
|
|
21026
|
+
const archAbs = path30.join(contextDir2, "architecture.md");
|
|
20209
21027
|
const projectChunks = renderProjectMdSections(contextDir2);
|
|
20210
21028
|
const projectChildrenInner = buildInnerChildren(true, projectChunks);
|
|
20211
21029
|
patchOneFile(contextDir2, "project.md", projectChildrenInner, buildInnerParents([]), opts);
|
|
@@ -20223,28 +21041,28 @@ function runLinkMappingPipeline(contextDirAbs, opts = {}) {
|
|
|
20223
21041
|
};
|
|
20224
21042
|
visitEdgeBasenames(edges.children);
|
|
20225
21043
|
visitEdgeBasenames(edges.parents);
|
|
20226
|
-
for (const
|
|
20227
|
-
if (
|
|
21044
|
+
for (const basename18 of managedBasenames) {
|
|
21045
|
+
if (basename18 === "project.md" || basename18 === "architecture.md") {
|
|
20228
21046
|
continue;
|
|
20229
21047
|
}
|
|
20230
|
-
const abs =
|
|
21048
|
+
const abs = path30.join(contextDir2, basename18);
|
|
20231
21049
|
if (!fs33.existsSync(abs)) {
|
|
20232
21050
|
continue;
|
|
20233
21051
|
}
|
|
20234
|
-
const childRows = edges.children.get(
|
|
20235
|
-
const parentRows = edges.parents.get(
|
|
21052
|
+
const childRows = edges.children.get(basename18) ?? [];
|
|
21053
|
+
const parentRows = edges.parents.get(basename18) ?? [];
|
|
20236
21054
|
const childLines = childRows.length === 0 ? NONE_LINE : childRows.map(
|
|
20237
|
-
(c) => bulletLink(c.title, markdownRelativeHref(abs,
|
|
21055
|
+
(c) => bulletLink(c.title, markdownRelativeHref(abs, path30.join(contextDir2, c.basename)))
|
|
20238
21056
|
).join("\n");
|
|
20239
21057
|
const parentLines = parentRows.length === 0 ? NONE_LINE : parentRows.map(
|
|
20240
|
-
(p) => bulletLink(p.title, markdownRelativeHref(abs,
|
|
21058
|
+
(p) => bulletLink(p.title, markdownRelativeHref(abs, path30.join(contextDir2, p.basename)))
|
|
20241
21059
|
).join("\n");
|
|
20242
21060
|
const innerChildren = `${HEADING_CHILD_DOCUMENTS}
|
|
20243
21061
|
|
|
20244
21062
|
${childLines}
|
|
20245
21063
|
`;
|
|
20246
21064
|
const innerParents = buildInnerParents(parentLines.split("\n").filter(Boolean));
|
|
20247
|
-
patchOneFile(contextDir2,
|
|
21065
|
+
patchOneFile(contextDir2, basename18, innerChildren, innerParents, opts);
|
|
20248
21066
|
}
|
|
20249
21067
|
const validation = validateEasyspecsNavLinksInContext(contextDir2);
|
|
20250
21068
|
if (!validation.ok) {
|
|
@@ -20258,7 +21076,7 @@ ${validation.brokenLinks.join("\n")}`;
|
|
|
20258
21076
|
}
|
|
20259
21077
|
|
|
20260
21078
|
// src/analysis/aceAnalysisConfig.ts
|
|
20261
|
-
var
|
|
21079
|
+
var path31 = __toESM(require("node:path"));
|
|
20262
21080
|
var vscode2 = __toESM(require_vscode_stub());
|
|
20263
21081
|
|
|
20264
21082
|
// src/config/easyspecsAceConfigRead.ts
|
|
@@ -20336,7 +21154,7 @@ function setAceCliHeadlessMode(enabled) {
|
|
|
20336
21154
|
cliHeadlessMode = enabled;
|
|
20337
21155
|
}
|
|
20338
21156
|
function normFs(p) {
|
|
20339
|
-
return
|
|
21157
|
+
return path31.resolve(p.trim());
|
|
20340
21158
|
}
|
|
20341
21159
|
function getAceAnalysisEnabledForCheckout(analysisCheckoutRoot) {
|
|
20342
21160
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -20407,13 +21225,13 @@ function getAceOfflineLearnAfterSameSessionTrace(analysisCheckoutRoot) {
|
|
|
20407
21225
|
|
|
20408
21226
|
// src/analysis/repoSurfaceAssessment.ts
|
|
20409
21227
|
var fs35 = __toESM(require("fs"));
|
|
20410
|
-
var
|
|
21228
|
+
var path32 = __toESM(require("path"));
|
|
20411
21229
|
var REPO_SURFACE_SCAN_BASENAME = "repo-surface-scan.json";
|
|
20412
21230
|
function stripBom(s) {
|
|
20413
21231
|
return s.length > 0 && s.charCodeAt(0) === 65279 ? s.slice(1) : s;
|
|
20414
21232
|
}
|
|
20415
21233
|
function readRepoSurfaceAssessment(contextDir2) {
|
|
20416
|
-
const p =
|
|
21234
|
+
const p = path32.join(contextDir2, REPO_SURFACE_SCAN_BASENAME);
|
|
20417
21235
|
try {
|
|
20418
21236
|
const raw = stripBom(fs35.readFileSync(p, "utf-8"));
|
|
20419
21237
|
const data = JSON.parse(raw);
|
|
@@ -20435,8 +21253,8 @@ function readRepoSurfaceAssessment(contextDir2) {
|
|
|
20435
21253
|
}
|
|
20436
21254
|
}
|
|
20437
21255
|
function writeEmptyExperiencesListJson(contextDir2) {
|
|
20438
|
-
const p =
|
|
20439
|
-
fs35.mkdirSync(
|
|
21256
|
+
const p = path32.join(contextDir2, "experiences-list.json");
|
|
21257
|
+
fs35.mkdirSync(path32.dirname(p), { recursive: true });
|
|
20440
21258
|
fs35.writeFileSync(
|
|
20441
21259
|
p,
|
|
20442
21260
|
`${JSON.stringify(
|
|
@@ -20455,6 +21273,7 @@ function writeEmptyExperiencesListJson(contextDir2) {
|
|
|
20455
21273
|
|
|
20456
21274
|
// src/config/cpuPressureSample.ts
|
|
20457
21275
|
var os5 = __toESM(require("node:os"));
|
|
21276
|
+
var DEFAULT_CPU_PRESSURE_THRESHOLD = 0.85;
|
|
20458
21277
|
function createDefaultCpuPressureSampler() {
|
|
20459
21278
|
const n = Math.max(1, os5.cpus()?.length ?? 1);
|
|
20460
21279
|
return () => {
|
|
@@ -20466,7 +21285,7 @@ function createDefaultCpuPressureSampler() {
|
|
|
20466
21285
|
};
|
|
20467
21286
|
}
|
|
20468
21287
|
function nextAdaptiveMaxAfterCpuSample(p) {
|
|
20469
|
-
const threshold = p.threshold ??
|
|
21288
|
+
const threshold = p.threshold ?? DEFAULT_CPU_PRESSURE_THRESHOLD;
|
|
20470
21289
|
if (p.activeRunningCount < 1 || !Number.isFinite(p.ratio) || p.ratio <= threshold) {
|
|
20471
21290
|
return { adaptiveMax: p.priorAdaptiveMax, changed: false };
|
|
20472
21291
|
}
|
|
@@ -20770,6 +21589,10 @@ function createHostPoolTick(deps) {
|
|
|
20770
21589
|
|
|
20771
21590
|
// src/pipelines/synthesis/synthesisPipeline.ts
|
|
20772
21591
|
var FE = /^FE-\d+$/;
|
|
21592
|
+
var IN = /^IN-\d+$/;
|
|
21593
|
+
var IC = /^IC-\d+$/;
|
|
21594
|
+
var QA = /^QA-\d+$/;
|
|
21595
|
+
var TC = /^TC-\d+$/;
|
|
20773
21596
|
var UC = /^UC-\d+$/;
|
|
20774
21597
|
var SC = /^SC-\d+$/;
|
|
20775
21598
|
var DM = /^DM-\d+$/;
|
|
@@ -20825,7 +21648,11 @@ var ROOT_WORKSTATION_DEFS = [
|
|
|
20825
21648
|
{ id: "root:listDataModel", step: "listDataModel", parentIds: [] },
|
|
20826
21649
|
{ id: "root:reviewDataModelList", step: "reviewDataModelList", parentIds: ["root:listDataModel"] },
|
|
20827
21650
|
{ id: "root:listTechStack", step: "listTechStack", parentIds: [] },
|
|
20828
|
-
{ id: "root:reviewTechStackList", step: "reviewTechStackList", parentIds: ["root:listTechStack"] }
|
|
21651
|
+
{ id: "root:reviewTechStackList", step: "reviewTechStackList", parentIds: ["root:listTechStack"] },
|
|
21652
|
+
{ id: "root:listInfrastructure", step: "listInfrastructure", parentIds: [] },
|
|
21653
|
+
{ id: "root:reviewInfrastructureList", step: "reviewInfrastructureList", parentIds: ["root:listInfrastructure"] },
|
|
21654
|
+
{ id: "root:listQa", step: "listQa", parentIds: ["root:reviewFeaturesList"] },
|
|
21655
|
+
{ id: "root:reviewQaList", step: "reviewQaList", parentIds: ["root:listQa"] }
|
|
20829
21656
|
];
|
|
20830
21657
|
function buildRootItems() {
|
|
20831
21658
|
const out = {};
|
|
@@ -20868,91 +21695,135 @@ function mdItem(id, parentIds, t) {
|
|
|
20868
21695
|
};
|
|
20869
21696
|
}
|
|
20870
21697
|
function featureDetailTarget(contextDir2, code, name, slug) {
|
|
20871
|
-
const
|
|
21698
|
+
const basename18 = `${code}-${slug}.md`;
|
|
20872
21699
|
return {
|
|
20873
21700
|
openCodeAgentStem: "agent-md-feature-detail",
|
|
20874
21701
|
agentId: "ctx-md-feature-detail",
|
|
20875
21702
|
displayName: "Feature detail",
|
|
20876
|
-
outputBasename:
|
|
21703
|
+
outputBasename: basename18,
|
|
20877
21704
|
taskDescription: `Document feature **${code}** (**${name}**, slug **${slug}**) per \`.gluecharm/context/features-list.json\`: scope, behaviour, main dependencies, entry points, and links to code under the worktree. Write exactly one markdown file at the output path; cite substantive claims with file and line (or range).`,
|
|
20878
|
-
exists: fs37.existsSync(
|
|
21705
|
+
exists: fs37.existsSync(path33.join(contextDir2, basename18)) && fs37.statSync(path33.join(contextDir2, basename18)).size > 0
|
|
20879
21706
|
};
|
|
20880
21707
|
}
|
|
20881
21708
|
function viewDetailTarget(row2, contextDir2) {
|
|
20882
|
-
const
|
|
21709
|
+
const basename18 = `${row2.code}-${row2.slug}.md`;
|
|
20883
21710
|
return {
|
|
20884
21711
|
openCodeAgentStem: "agent-md-view-detail",
|
|
20885
21712
|
agentId: "ctx-md-view-detail",
|
|
20886
21713
|
displayName: "View detail",
|
|
20887
|
-
outputBasename:
|
|
21714
|
+
outputBasename: basename18,
|
|
20888
21715
|
taskDescription: `Describe view **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/experiences-list.json\`: purpose, layout, controls, navigation, data shown; ground in components and routes.`,
|
|
20889
|
-
exists: fs37.existsSync(
|
|
21716
|
+
exists: fs37.existsSync(path33.join(contextDir2, basename18)) && fs37.statSync(path33.join(contextDir2, basename18)).size > 0
|
|
20890
21717
|
};
|
|
20891
21718
|
}
|
|
20892
21719
|
function interactionDetailTarget(viewCode, ix, contextDir2) {
|
|
20893
|
-
const
|
|
21720
|
+
const basename18 = `${viewCode}_${ix.code}-${ix.slug}.md`;
|
|
20894
21721
|
return {
|
|
20895
21722
|
openCodeAgentStem: "agent-md-interaction-detail",
|
|
20896
21723
|
agentId: "ctx-md-interaction-detail",
|
|
20897
21724
|
displayName: "Interaction detail",
|
|
20898
|
-
outputBasename:
|
|
21725
|
+
outputBasename: basename18,
|
|
20899
21726
|
taskDescription: `Document interaction **${ix.code}** (**${ix.name}**) on view **${viewCode}** per \`.gluecharm/context/experiences-list.json\`.`,
|
|
20900
|
-
exists: fs37.existsSync(
|
|
21727
|
+
exists: fs37.existsSync(path33.join(contextDir2, basename18)) && fs37.statSync(path33.join(contextDir2, basename18)).size > 0
|
|
20901
21728
|
};
|
|
20902
21729
|
}
|
|
20903
21730
|
function serviceDetailTarget(row2, contextDir2) {
|
|
20904
|
-
const
|
|
21731
|
+
const basename18 = `${row2.code}-${row2.slug}.md`;
|
|
20905
21732
|
return {
|
|
20906
21733
|
openCodeAgentStem: "agent-md-service-detail",
|
|
20907
21734
|
agentId: "ctx-md-service-detail",
|
|
20908
21735
|
displayName: "Service detail",
|
|
20909
|
-
outputBasename:
|
|
21736
|
+
outputBasename: basename18,
|
|
20910
21737
|
taskDescription: `Describe service **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/services-list.json\`: responsibilities, consumers, errors, integration points.`,
|
|
20911
|
-
exists: fs37.existsSync(
|
|
21738
|
+
exists: fs37.existsSync(path33.join(contextDir2, basename18)) && fs37.statSync(path33.join(contextDir2, basename18)).size > 0
|
|
20912
21739
|
};
|
|
20913
21740
|
}
|
|
20914
21741
|
function methodDetailTarget(svc, m, contextDir2) {
|
|
20915
|
-
const
|
|
21742
|
+
const basename18 = `${svc.code}_${m.code}-${m.slug}.md`;
|
|
20916
21743
|
return {
|
|
20917
21744
|
openCodeAgentStem: "agent-md-method-detail",
|
|
20918
21745
|
agentId: "ctx-md-method-detail",
|
|
20919
21746
|
displayName: "Method detail",
|
|
20920
|
-
outputBasename:
|
|
21747
|
+
outputBasename: basename18,
|
|
20921
21748
|
taskDescription: `Document method **${m.code}** (**${m.name}**) on service **${svc.code}** per \`.gluecharm/context/services-list.json\`.`,
|
|
20922
|
-
exists: fs37.existsSync(
|
|
21749
|
+
exists: fs37.existsSync(path33.join(contextDir2, basename18)) && fs37.statSync(path33.join(contextDir2, basename18)).size > 0
|
|
20923
21750
|
};
|
|
20924
21751
|
}
|
|
20925
21752
|
function entityDetailTarget(dmCode, ename, slug, contextDir2) {
|
|
20926
|
-
const
|
|
21753
|
+
const basename18 = `${dmCode}-${slug}.md`;
|
|
20927
21754
|
return {
|
|
20928
21755
|
openCodeAgentStem: "agent-md-entity-detail",
|
|
20929
21756
|
agentId: "ctx-md-entity-detail",
|
|
20930
21757
|
displayName: "Entity detail",
|
|
20931
|
-
outputBasename:
|
|
21758
|
+
outputBasename: basename18,
|
|
20932
21759
|
taskDescription: `Describe entity **${dmCode}** (**${ename}**, slug **${slug}**) per \`.gluecharm/context/data-model-list.json\`: lifecycle, invariants, storage, ORM/schema mapping.`,
|
|
20933
|
-
exists: fs37.existsSync(
|
|
21760
|
+
exists: fs37.existsSync(path33.join(contextDir2, basename18)) && fs37.statSync(path33.join(contextDir2, basename18)).size > 0
|
|
20934
21761
|
};
|
|
20935
21762
|
}
|
|
20936
21763
|
function fieldDetailTarget(dmCode, fdCode, fname, fSlug, contextDir2) {
|
|
20937
|
-
const
|
|
21764
|
+
const basename18 = `${dmCode}_${fdCode}-${fSlug}.md`;
|
|
20938
21765
|
return {
|
|
20939
21766
|
openCodeAgentStem: "agent-md-field-detail",
|
|
20940
21767
|
agentId: "ctx-md-field-detail",
|
|
20941
21768
|
displayName: "Field detail",
|
|
20942
|
-
outputBasename:
|
|
21769
|
+
outputBasename: basename18,
|
|
20943
21770
|
taskDescription: `Document field **${fdCode}** (**${fname}**) on entity **${dmCode}** per \`.gluecharm/context/${dmCode}-fields-list.json\`. Cite types and constraints with file and line.`,
|
|
20944
|
-
exists: fs37.existsSync(
|
|
21771
|
+
exists: fs37.existsSync(path33.join(contextDir2, basename18)) && fs37.statSync(path33.join(contextDir2, basename18)).size > 0
|
|
20945
21772
|
};
|
|
20946
21773
|
}
|
|
20947
21774
|
function toolDetailTarget(row2, contextDir2) {
|
|
20948
|
-
const
|
|
21775
|
+
const basename18 = `${row2.code}-${row2.slug}.md`;
|
|
20949
21776
|
return {
|
|
20950
21777
|
openCodeAgentStem: "agent-md-tool-detail",
|
|
20951
21778
|
agentId: "ctx-md-tool-detail",
|
|
20952
21779
|
displayName: "Tool detail",
|
|
20953
|
-
outputBasename:
|
|
21780
|
+
outputBasename: basename18,
|
|
20954
21781
|
taskDescription: `Describe tool **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/tech-stack-list.json\`: role, version hints, configuration, boundaries.`,
|
|
20955
|
-
exists: fs37.existsSync(
|
|
21782
|
+
exists: fs37.existsSync(path33.join(contextDir2, basename18)) && fs37.statSync(path33.join(contextDir2, basename18)).size > 0
|
|
21783
|
+
};
|
|
21784
|
+
}
|
|
21785
|
+
function infrastructureDetailTarget(contextDir2, code, name, slug) {
|
|
21786
|
+
const basename18 = `${code}-${slug}.md`;
|
|
21787
|
+
return {
|
|
21788
|
+
openCodeAgentStem: "agent-md-infrastructure-detail",
|
|
21789
|
+
agentId: "ctx-md-infrastructure-detail",
|
|
21790
|
+
displayName: "Infrastructure detail",
|
|
21791
|
+
outputBasename: basename18,
|
|
21792
|
+
taskDescription: `Document infrastructure surface **${code}** (**${name}**, slug **${slug}**) per \`.gluecharm/context/infrastructure-list.json\`: delivery/DX role, automation, dependencies, and evidence.`,
|
|
21793
|
+
exists: fs37.existsSync(path33.join(contextDir2, basename18)) && fs37.statSync(path33.join(contextDir2, basename18)).size > 0
|
|
21794
|
+
};
|
|
21795
|
+
}
|
|
21796
|
+
function infrastructureComponentDetailTarget(inCode, ic, contextDir2) {
|
|
21797
|
+
const basename18 = `${inCode}_${ic.code}-${ic.slug}.md`;
|
|
21798
|
+
return {
|
|
21799
|
+
openCodeAgentStem: "agent-md-infrastructure-component-detail",
|
|
21800
|
+
agentId: "ctx-md-infrastructure-component-detail",
|
|
21801
|
+
displayName: "Infrastructure component detail",
|
|
21802
|
+
outputBasename: basename18,
|
|
21803
|
+
taskDescription: `Document component **${ic.code}** (**${ic.name}**) under infrastructure **${inCode}** per \`.gluecharm/context/${inCode}-components-list.json\`.`,
|
|
21804
|
+
exists: fs37.existsSync(path33.join(contextDir2, basename18)) && fs37.statSync(path33.join(contextDir2, basename18)).size > 0
|
|
21805
|
+
};
|
|
21806
|
+
}
|
|
21807
|
+
function qaDetailTarget(contextDir2, code, name, slug) {
|
|
21808
|
+
const basename18 = `${code}-${slug}.md`;
|
|
21809
|
+
return {
|
|
21810
|
+
openCodeAgentStem: "agent-md-qa-detail",
|
|
21811
|
+
agentId: "ctx-md-qa-detail",
|
|
21812
|
+
displayName: "QA detail",
|
|
21813
|
+
outputBasename: basename18,
|
|
21814
|
+
taskDescription: `Document QA surface **${code}** (**${name}**, slug **${slug}**) per \`.gluecharm/context/qa-list.json\`: verification scope, harness, and **coversCodes** anchors.`,
|
|
21815
|
+
exists: fs37.existsSync(path33.join(contextDir2, basename18)) && fs37.statSync(path33.join(contextDir2, basename18)).size > 0
|
|
21816
|
+
};
|
|
21817
|
+
}
|
|
21818
|
+
function qaTestCaseDetailTarget(qaCode, tc, contextDir2) {
|
|
21819
|
+
const basename18 = `${qaCode}_${tc.code}-${tc.slug}.md`;
|
|
21820
|
+
return {
|
|
21821
|
+
openCodeAgentStem: "agent-md-qa-test-case-detail",
|
|
21822
|
+
agentId: "ctx-md-qa-test-case-detail",
|
|
21823
|
+
displayName: "QA test case detail",
|
|
21824
|
+
outputBasename: basename18,
|
|
21825
|
+
taskDescription: `Document test case **${tc.code}** (**${tc.name}**) under QA **${qaCode}** per \`.gluecharm/context/${qaCode}-test-cases-list.json\`; include **coversCodes** anchors.`,
|
|
21826
|
+
exists: fs37.existsSync(path33.join(contextDir2, basename18)) && fs37.statSync(path33.join(contextDir2, basename18)).size > 0
|
|
20956
21827
|
};
|
|
20957
21828
|
}
|
|
20958
21829
|
function useCaseDetailTarget(feCode, ucCode, ucName, ucSlug, contextDir2) {
|
|
@@ -20965,18 +21836,18 @@ function useCaseDetailTarget(feCode, ucCode, ucName, ucSlug, contextDir2) {
|
|
|
20965
21836
|
taskDescription: `Document use case **${ucCode}** (**${ucName}**) under feature **${feCode}** per \`.gluecharm/context/${feCode}-use-cases-list.json\`. Do not change stable codes.
|
|
20966
21837
|
|
|
20967
21838
|
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.`,
|
|
20968
|
-
exists: fs37.existsSync(
|
|
21839
|
+
exists: fs37.existsSync(path33.join(contextDir2, ucBase)) && fs37.statSync(path33.join(contextDir2, ucBase)).size > 0
|
|
20969
21840
|
};
|
|
20970
21841
|
}
|
|
20971
21842
|
function scenarioDetailTarget(feCode, ucCode, scCode, scName, contextDir2) {
|
|
20972
|
-
const
|
|
21843
|
+
const basename18 = `${feCode}_${ucCode}_${scCode}.md`;
|
|
20973
21844
|
return {
|
|
20974
21845
|
openCodeAgentStem: "agent-md-scenario-detail",
|
|
20975
21846
|
agentId: "ctx-md-scenario-detail",
|
|
20976
21847
|
displayName: "Scenario detail",
|
|
20977
|
-
outputBasename:
|
|
21848
|
+
outputBasename: basename18,
|
|
20978
21849
|
taskDescription: `Document scenario **${scCode}** (**${scName}**) for **${feCode}** / **${ucCode}** per \`.gluecharm/context/${feCode}_${ucCode}-scenarios-list.json\`. Cite steps with file and line where possible.`,
|
|
20979
|
-
exists: fs37.existsSync(
|
|
21850
|
+
exists: fs37.existsSync(path33.join(contextDir2, basename18)) && fs37.statSync(path33.join(contextDir2, basename18)).size > 0
|
|
20980
21851
|
};
|
|
20981
21852
|
}
|
|
20982
21853
|
function parentsDone(item, byId) {
|
|
@@ -21029,7 +21900,7 @@ function expandAfterSuccess(completed, contextDir2, byId, fifo) {
|
|
|
21029
21900
|
case "listFeatures":
|
|
21030
21901
|
break;
|
|
21031
21902
|
case "reviewFeaturesList": {
|
|
21032
|
-
const flPath =
|
|
21903
|
+
const flPath = path33.join(contextDir2, "features-list.json");
|
|
21033
21904
|
const fl = readJson4(flPath);
|
|
21034
21905
|
const features = Array.isArray(fl?.features) ? fl.features : [];
|
|
21035
21906
|
for (const row2 of features) {
|
|
@@ -21068,7 +21939,7 @@ function expandAfterSuccess(completed, contextDir2, byId, fifo) {
|
|
|
21068
21939
|
case "listDataModel":
|
|
21069
21940
|
break;
|
|
21070
21941
|
case "reviewDataModelList": {
|
|
21071
|
-
const dmPath =
|
|
21942
|
+
const dmPath = path33.join(contextDir2, "data-model-list.json");
|
|
21072
21943
|
const dmFile = readJson4(dmPath);
|
|
21073
21944
|
const ents = Array.isArray(dmFile?.entities) ? dmFile.entities : [];
|
|
21074
21945
|
for (const erow of ents) {
|
|
@@ -21095,6 +21966,100 @@ function expandAfterSuccess(completed, contextDir2, byId, fifo) {
|
|
|
21095
21966
|
}
|
|
21096
21967
|
break;
|
|
21097
21968
|
}
|
|
21969
|
+
case "listInfrastructure":
|
|
21970
|
+
break;
|
|
21971
|
+
case "reviewInfrastructureList": {
|
|
21972
|
+
for (const row2 of discoverInfrastructureRows(contextDir2)) {
|
|
21973
|
+
const mdId = `md:${row2.code}-${row2.slug}.md`;
|
|
21974
|
+
add(mdItem(mdId, [completed.id], infrastructureDetailTarget(contextDir2, row2.code, row2.name, row2.slug)));
|
|
21975
|
+
add(
|
|
21976
|
+
coordItem(`coord:ic:${row2.code}`, [completed.id], "listInfrastructureComponents", {
|
|
21977
|
+
infrastructureCode: row2.code
|
|
21978
|
+
})
|
|
21979
|
+
);
|
|
21980
|
+
}
|
|
21981
|
+
break;
|
|
21982
|
+
}
|
|
21983
|
+
case "listInfrastructureComponents": {
|
|
21984
|
+
const inCode = listTarget?.infrastructureCode;
|
|
21985
|
+
if (!inCode || !IN.test(inCode)) {
|
|
21986
|
+
break;
|
|
21987
|
+
}
|
|
21988
|
+
add(
|
|
21989
|
+
coordItem(`coord:reviewIc:${inCode}`, [completed.id], "reviewInfrastructureComponentsList", {
|
|
21990
|
+
infrastructureCode: inCode
|
|
21991
|
+
})
|
|
21992
|
+
);
|
|
21993
|
+
break;
|
|
21994
|
+
}
|
|
21995
|
+
case "reviewInfrastructureComponentsList": {
|
|
21996
|
+
const inCode = listTarget?.infrastructureCode;
|
|
21997
|
+
if (!inCode || !IN.test(inCode)) {
|
|
21998
|
+
break;
|
|
21999
|
+
}
|
|
22000
|
+
const clPath = path33.join(contextDir2, `${inCode}-components-list.json`);
|
|
22001
|
+
const clFile = readJson4(clPath);
|
|
22002
|
+
const comps = Array.isArray(clFile?.components) ? clFile.components : [];
|
|
22003
|
+
for (const crow of comps) {
|
|
22004
|
+
const icCode = safeStr3(crow.code);
|
|
22005
|
+
if (!IC.test(icCode)) {
|
|
22006
|
+
continue;
|
|
22007
|
+
}
|
|
22008
|
+
const slug = safeStr3(crow.slug);
|
|
22009
|
+
if (!slug || !SLUG3.test(slug)) {
|
|
22010
|
+
continue;
|
|
22011
|
+
}
|
|
22012
|
+
const cname = safeStr3(crow.name) || icCode;
|
|
22013
|
+
const mdId = `md:${inCode}_${icCode}-${slug}.md`;
|
|
22014
|
+
add(mdItem(mdId, [completed.id], infrastructureComponentDetailTarget(inCode, { code: icCode, name: cname, slug }, contextDir2)));
|
|
22015
|
+
}
|
|
22016
|
+
break;
|
|
22017
|
+
}
|
|
22018
|
+
case "listQa":
|
|
22019
|
+
break;
|
|
22020
|
+
case "reviewQaList": {
|
|
22021
|
+
for (const row2 of discoverQaRows(contextDir2)) {
|
|
22022
|
+
const mdId = `md:${row2.code}-${row2.slug}.md`;
|
|
22023
|
+
add(mdItem(mdId, [completed.id], qaDetailTarget(contextDir2, row2.code, row2.name, row2.slug)));
|
|
22024
|
+
add(coordItem(`coord:tc:${row2.code}`, [completed.id], "listQaTestCases", { qaCode: row2.code }));
|
|
22025
|
+
}
|
|
22026
|
+
break;
|
|
22027
|
+
}
|
|
22028
|
+
case "listQaTestCases": {
|
|
22029
|
+
const qaCode = listTarget?.qaCode;
|
|
22030
|
+
if (!qaCode || !QA.test(qaCode)) {
|
|
22031
|
+
break;
|
|
22032
|
+
}
|
|
22033
|
+
add(
|
|
22034
|
+
coordItem(`coord:reviewTc:${qaCode}`, [completed.id], "reviewQaTestCasesList", {
|
|
22035
|
+
qaCode
|
|
22036
|
+
})
|
|
22037
|
+
);
|
|
22038
|
+
break;
|
|
22039
|
+
}
|
|
22040
|
+
case "reviewQaTestCasesList": {
|
|
22041
|
+
const qaCode = listTarget?.qaCode;
|
|
22042
|
+
if (!qaCode || !QA.test(qaCode)) {
|
|
22043
|
+
break;
|
|
22044
|
+
}
|
|
22045
|
+
const tcPath = path33.join(contextDir2, `${qaCode}-test-cases-list.json`);
|
|
22046
|
+
const tcFile = readJson4(tcPath);
|
|
22047
|
+
const tcs = Array.isArray(tcFile?.testCases) ? tcFile.testCases : [];
|
|
22048
|
+
for (const trow of tcs) {
|
|
22049
|
+
const tcCode = safeStr3(trow.code);
|
|
22050
|
+
if (!TC.test(tcCode)) {
|
|
22051
|
+
continue;
|
|
22052
|
+
}
|
|
22053
|
+
const slug = safeStr3(trow.slug);
|
|
22054
|
+
if (!slug || !SLUG3.test(slug)) {
|
|
22055
|
+
continue;
|
|
22056
|
+
}
|
|
22057
|
+
const tname = safeStr3(trow.name) || tcCode;
|
|
22058
|
+
const mdId = `md:${qaCode}_${tcCode}-${slug}.md`;
|
|
22059
|
+
add(mdItem(mdId, [completed.id], qaTestCaseDetailTarget(qaCode, { code: tcCode, name: tname, slug }, contextDir2)));
|
|
22060
|
+
}
|
|
22061
|
+
break;
|
|
22062
|
+
}
|
|
21098
22063
|
case "listUseCases": {
|
|
21099
22064
|
const fe = listTarget?.featureCode;
|
|
21100
22065
|
if (!fe || !FE.test(fe)) {
|
|
@@ -21108,7 +22073,7 @@ function expandAfterSuccess(completed, contextDir2, byId, fifo) {
|
|
|
21108
22073
|
if (!fe || !FE.test(fe)) {
|
|
21109
22074
|
break;
|
|
21110
22075
|
}
|
|
21111
|
-
const ucListPath =
|
|
22076
|
+
const ucListPath = path33.join(contextDir2, `${fe}-use-cases-list.json`);
|
|
21112
22077
|
const ucFile = readJson4(ucListPath);
|
|
21113
22078
|
const ucs = Array.isArray(ucFile?.useCases) ? ucFile.useCases : [];
|
|
21114
22079
|
for (const ucRow of ucs) {
|
|
@@ -21151,7 +22116,7 @@ function expandAfterSuccess(completed, contextDir2, byId, fifo) {
|
|
|
21151
22116
|
if (!fe || !uc || !FE.test(fe) || !UC.test(uc)) {
|
|
21152
22117
|
break;
|
|
21153
22118
|
}
|
|
21154
|
-
const scPath =
|
|
22119
|
+
const scPath = path33.join(contextDir2, `${fe}_${uc}-scenarios-list.json`);
|
|
21155
22120
|
const scFile = readJson4(scPath);
|
|
21156
22121
|
const scs = Array.isArray(scFile?.scenarios) ? scFile.scenarios : [];
|
|
21157
22122
|
for (const scRow of scs) {
|
|
@@ -21178,7 +22143,7 @@ function expandAfterSuccess(completed, contextDir2, byId, fifo) {
|
|
|
21178
22143
|
if (!dm || !DM.test(dm)) {
|
|
21179
22144
|
break;
|
|
21180
22145
|
}
|
|
21181
|
-
const flPath =
|
|
22146
|
+
const flPath = path33.join(contextDir2, `${dm}-fields-list.json`);
|
|
21182
22147
|
const flFile = readJson4(flPath);
|
|
21183
22148
|
const flds = Array.isArray(flFile?.fields) ? flFile.fields : [];
|
|
21184
22149
|
for (const frow of flds) {
|
|
@@ -21202,15 +22167,15 @@ function expandAfterSuccess(completed, contextDir2, byId, fifo) {
|
|
|
21202
22167
|
return;
|
|
21203
22168
|
}
|
|
21204
22169
|
if (completed.kind === "markdown") {
|
|
21205
|
-
const
|
|
22170
|
+
const basename18 = completed.payload.outputBasename;
|
|
21206
22171
|
const mdId = completed.id;
|
|
21207
|
-
const feFromFeatureMd =
|
|
22172
|
+
const feFromFeatureMd = basename18.match(/^(FE-\d+)-[^/]+\.md$/);
|
|
21208
22173
|
if (feFromFeatureMd) {
|
|
21209
22174
|
const fe = feFromFeatureMd[1];
|
|
21210
22175
|
add(coordItem(`coord:uc:${fe}`, [mdId], "listUseCases", { featureCode: fe }));
|
|
21211
22176
|
return;
|
|
21212
22177
|
}
|
|
21213
|
-
const xpFromView =
|
|
22178
|
+
const xpFromView = basename18.match(/^(XP-\d+)-[^/]+\.md$/);
|
|
21214
22179
|
if (xpFromView) {
|
|
21215
22180
|
const xp = xpFromView[1];
|
|
21216
22181
|
const row2 = discoverExperienceTreeRows(contextDir2).find((r) => r.code === xp);
|
|
@@ -21222,7 +22187,7 @@ function expandAfterSuccess(completed, contextDir2, byId, fifo) {
|
|
|
21222
22187
|
}
|
|
21223
22188
|
return;
|
|
21224
22189
|
}
|
|
21225
|
-
const svFromSvc =
|
|
22190
|
+
const svFromSvc = basename18.match(/^(SV-\d+)-[^/]+\.md$/);
|
|
21226
22191
|
if (svFromSvc) {
|
|
21227
22192
|
const sv = svFromSvc[1];
|
|
21228
22193
|
const srow = discoverServiceTreeRows(contextDir2).find((r) => r.code === sv);
|
|
@@ -21234,7 +22199,7 @@ function expandAfterSuccess(completed, contextDir2, byId, fifo) {
|
|
|
21234
22199
|
}
|
|
21235
22200
|
return;
|
|
21236
22201
|
}
|
|
21237
|
-
const dmFromEnt =
|
|
22202
|
+
const dmFromEnt = basename18.match(/^(DM-\d+)-[^/]+\.md$/);
|
|
21238
22203
|
if (dmFromEnt) {
|
|
21239
22204
|
const dm = dmFromEnt[1];
|
|
21240
22205
|
add(coordItem(`coord:ef:${dm}`, [mdId], "listEntityFields", { entityCode: dm }));
|
|
@@ -21278,7 +22243,7 @@ async function runWorkstationAgent(item, worktreeRoot, workspaceLabel, oc, log,
|
|
|
21278
22243
|
};
|
|
21279
22244
|
if (item.kind === "coord") {
|
|
21280
22245
|
const { step, listTarget } = item.payload;
|
|
21281
|
-
const contextDir2 =
|
|
22246
|
+
const contextDir2 = path33.join(worktreeRoot, ".gluecharm", "context");
|
|
21282
22247
|
if (step === "listExperiences") {
|
|
21283
22248
|
const assessment = readRepoSurfaceAssessment(contextDir2);
|
|
21284
22249
|
if (assessment === null) {
|
|
@@ -21421,8 +22386,8 @@ async function drainWorkstationPool(p) {
|
|
|
21421
22386
|
const artefactRunId = readArtefactRunSnapshot(storageContext)?.runId ?? "unknown-run";
|
|
21422
22387
|
let active = 0;
|
|
21423
22388
|
let wake;
|
|
21424
|
-
const waitTurn = () => new Promise((
|
|
21425
|
-
wake =
|
|
22389
|
+
const waitTurn = () => new Promise((resolve25) => {
|
|
22390
|
+
wake = resolve25;
|
|
21426
22391
|
});
|
|
21427
22392
|
const persist = async () => {
|
|
21428
22393
|
const items = {};
|
|
@@ -21592,7 +22557,7 @@ async function prepareSynthesisWorktree(storageContext, repoRoot, log, options)
|
|
|
21592
22557
|
await clearArtefactRun(storageContext);
|
|
21593
22558
|
}
|
|
21594
22559
|
if (options?.inPlace === true) {
|
|
21595
|
-
const repoResolved =
|
|
22560
|
+
const repoResolved = path33.resolve(repoRoot);
|
|
21596
22561
|
log(`[worktree] in-place analysis \u2014 using repository root ${repoResolved}`);
|
|
21597
22562
|
const handle2 = createInPlaceWorktreeHandle(repoResolved);
|
|
21598
22563
|
const sourceBranchAtCreation = readHeadBranchShort(repoResolved);
|
|
@@ -21639,7 +22604,7 @@ async function runSynthesisPipelineDrainFromPreparedWorktree(storageContext, rep
|
|
|
21639
22604
|
aceEnabled: getAceAnalysisEnabledForCheckout(handle.path),
|
|
21640
22605
|
offlineLearnAfterSameSessionTrace: getAceOfflineLearnAfterSameSessionTrace(handle.path)
|
|
21641
22606
|
};
|
|
21642
|
-
const contextDir2 =
|
|
22607
|
+
const contextDir2 = path33.join(handle.path, ".gluecharm", "context");
|
|
21643
22608
|
fs37.mkdirSync(contextDir2, { recursive: true });
|
|
21644
22609
|
const initialItems = buildRootItems();
|
|
21645
22610
|
await startArtefactRun(storageContext, repoRoot, handle.path, initialItems);
|
|
@@ -21742,10 +22707,10 @@ async function runSynthesisPipeline(storageContext, repoRoot, workspaceLabel, ex
|
|
|
21742
22707
|
|
|
21743
22708
|
// src/workspaceContextPromote.ts
|
|
21744
22709
|
var fs38 = __toESM(require("fs"));
|
|
21745
|
-
var
|
|
22710
|
+
var path34 = __toESM(require("path"));
|
|
21746
22711
|
function promoteContextDirectoryToWorkspaceFs(sourceContextDir, workspaceRootFs) {
|
|
21747
|
-
const dest =
|
|
21748
|
-
fs38.mkdirSync(
|
|
22712
|
+
const dest = path34.join(workspaceRootFs, ".gluecharm", "context");
|
|
22713
|
+
fs38.mkdirSync(path34.join(workspaceRootFs, ".gluecharm"), { recursive: true });
|
|
21749
22714
|
fs38.mkdirSync(dest, { recursive: true });
|
|
21750
22715
|
let names;
|
|
21751
22716
|
try {
|
|
@@ -21755,12 +22720,12 @@ function promoteContextDirectoryToWorkspaceFs(sourceContextDir, workspaceRootFs)
|
|
|
21755
22720
|
}
|
|
21756
22721
|
let filesCopied = 0;
|
|
21757
22722
|
for (const name of names) {
|
|
21758
|
-
const srcPath =
|
|
22723
|
+
const srcPath = path34.join(sourceContextDir, name);
|
|
21759
22724
|
if (!fs38.statSync(srcPath).isFile()) {
|
|
21760
22725
|
continue;
|
|
21761
22726
|
}
|
|
21762
22727
|
const buf = fs38.readFileSync(srcPath);
|
|
21763
|
-
const target =
|
|
22728
|
+
const target = path34.join(dest, name);
|
|
21764
22729
|
fs38.writeFileSync(target, buf);
|
|
21765
22730
|
filesCopied += 1;
|
|
21766
22731
|
}
|
|
@@ -21783,23 +22748,23 @@ var FACTORY_PIPELINE_EXIT_CONDITIONS = {
|
|
|
21783
22748
|
|
|
21784
22749
|
// src/readiness/factoryReadiness.ts
|
|
21785
22750
|
var fs39 = __toESM(require("node:fs"));
|
|
21786
|
-
var
|
|
22751
|
+
var path36 = __toESM(require("node:path"));
|
|
21787
22752
|
|
|
21788
22753
|
// src/readiness/openCodeConfigCandidates.ts
|
|
21789
22754
|
var os6 = __toESM(require("node:os"));
|
|
21790
|
-
var
|
|
22755
|
+
var path35 = __toESM(require("node:path"));
|
|
21791
22756
|
function openCodeUserConfigDir() {
|
|
21792
22757
|
if (process.platform === "win32") {
|
|
21793
|
-
const base = process.env.APPDATA ||
|
|
21794
|
-
return
|
|
22758
|
+
const base = process.env.APPDATA || path35.join(os6.homedir(), "AppData", "Roaming");
|
|
22759
|
+
return path35.join(base, "opencode");
|
|
21795
22760
|
}
|
|
21796
22761
|
const xdg = process.env.XDG_CONFIG_HOME?.trim();
|
|
21797
|
-
const cfgRoot = xdg && xdg.length > 0 ? xdg :
|
|
21798
|
-
return
|
|
22762
|
+
const cfgRoot = xdg && xdg.length > 0 ? xdg : path35.join(os6.homedir(), ".config");
|
|
22763
|
+
return path35.join(cfgRoot, "opencode");
|
|
21799
22764
|
}
|
|
21800
22765
|
function openCodeMacUserApplicationSupportDir() {
|
|
21801
22766
|
if (process.platform === "darwin") {
|
|
21802
|
-
return
|
|
22767
|
+
return path35.join(os6.homedir(), "Library", "Application Support", "opencode");
|
|
21803
22768
|
}
|
|
21804
22769
|
return void 0;
|
|
21805
22770
|
}
|
|
@@ -21807,7 +22772,7 @@ function openCodeWindowsLocalAppDataDir() {
|
|
|
21807
22772
|
if (process.platform === "win32") {
|
|
21808
22773
|
const la = process.env.LOCALAPPDATA?.trim();
|
|
21809
22774
|
if (la && la.length > 0) {
|
|
21810
|
-
return
|
|
22775
|
+
return path35.join(la, "opencode");
|
|
21811
22776
|
}
|
|
21812
22777
|
}
|
|
21813
22778
|
return void 0;
|
|
@@ -21817,25 +22782,25 @@ function managedOpenCodeConfigDir() {
|
|
|
21817
22782
|
return "/Library/Application Support/opencode";
|
|
21818
22783
|
}
|
|
21819
22784
|
if (process.platform === "linux") {
|
|
21820
|
-
return
|
|
22785
|
+
return path35.join("/etc", "opencode");
|
|
21821
22786
|
}
|
|
21822
22787
|
if (process.platform === "win32") {
|
|
21823
22788
|
const pd = process.env.ProgramData?.trim() || "C:\\ProgramData";
|
|
21824
|
-
return
|
|
22789
|
+
return path35.join(pd, "opencode");
|
|
21825
22790
|
}
|
|
21826
22791
|
return void 0;
|
|
21827
22792
|
}
|
|
21828
22793
|
function pushConfigBasenames(out, dir) {
|
|
21829
|
-
const d =
|
|
21830
|
-
out.push(
|
|
21831
|
-
out.push(
|
|
21832
|
-
out.push(
|
|
22794
|
+
const d = path35.normalize(dir);
|
|
22795
|
+
out.push(path35.join(d, "opencode.json"));
|
|
22796
|
+
out.push(path35.join(d, "opencode.jsonc"));
|
|
22797
|
+
out.push(path35.join(d, "config.json"));
|
|
21833
22798
|
}
|
|
21834
22799
|
function dedupeStablePaths(paths) {
|
|
21835
22800
|
const seen = /* @__PURE__ */ new Set();
|
|
21836
22801
|
const out = [];
|
|
21837
22802
|
for (const p of paths) {
|
|
21838
|
-
const n =
|
|
22803
|
+
const n = path35.normalize(p.trim());
|
|
21839
22804
|
if (n.length === 0 || seen.has(n)) {
|
|
21840
22805
|
continue;
|
|
21841
22806
|
}
|
|
@@ -21845,11 +22810,11 @@ function dedupeStablePaths(paths) {
|
|
|
21845
22810
|
return out;
|
|
21846
22811
|
}
|
|
21847
22812
|
function openCodeJsonModelFileCandidates(analysisRootAbs) {
|
|
21848
|
-
const root =
|
|
22813
|
+
const root = path35.resolve(analysisRootAbs);
|
|
21849
22814
|
const acc = [];
|
|
21850
22815
|
const oc = process.env.OPENCODE_CONFIG?.trim();
|
|
21851
22816
|
if (oc) {
|
|
21852
|
-
acc.push(
|
|
22817
|
+
acc.push(path35.resolve(oc));
|
|
21853
22818
|
}
|
|
21854
22819
|
pushConfigBasenames(acc, openCodeUserConfigDir());
|
|
21855
22820
|
const macAs = openCodeMacUserApplicationSupportDir();
|
|
@@ -21860,13 +22825,13 @@ function openCodeJsonModelFileCandidates(analysisRootAbs) {
|
|
|
21860
22825
|
if (winLoc) {
|
|
21861
22826
|
pushConfigBasenames(acc, winLoc);
|
|
21862
22827
|
}
|
|
21863
|
-
pushConfigBasenames(acc,
|
|
22828
|
+
pushConfigBasenames(acc, path35.join(os6.homedir(), ".opencode"));
|
|
21864
22829
|
const ocd = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
21865
22830
|
if (ocd) {
|
|
21866
|
-
pushConfigBasenames(acc,
|
|
22831
|
+
pushConfigBasenames(acc, path35.resolve(ocd));
|
|
21867
22832
|
}
|
|
21868
22833
|
pushConfigBasenames(acc, root);
|
|
21869
|
-
pushConfigBasenames(acc,
|
|
22834
|
+
pushConfigBasenames(acc, path35.join(root, ".opencode"));
|
|
21870
22835
|
const managed = managedOpenCodeConfigDir();
|
|
21871
22836
|
if (managed) {
|
|
21872
22837
|
pushConfigBasenames(acc, managed);
|
|
@@ -22031,7 +22996,7 @@ function buildReadinessProbeFacts(ctx) {
|
|
|
22031
22996
|
});
|
|
22032
22997
|
const openCodeConfigFiles = buildOpenCodeConfigInventory(ctx.analysisRootAbs);
|
|
22033
22998
|
const mandatoryOk = MANDATORY_OPEN_CODE_CONFIG_REL_PATHS.every((rel) => {
|
|
22034
|
-
const abs =
|
|
22999
|
+
const abs = path36.join(path36.resolve(ctx.analysisRootAbs), rel);
|
|
22035
23000
|
return fs39.existsSync(abs);
|
|
22036
23001
|
});
|
|
22037
23002
|
const model = resolveModelFromContext(ctx);
|
|
@@ -22347,7 +23312,7 @@ function sleepUntilAborted(ms, signal) {
|
|
|
22347
23312
|
if (signal.aborted) {
|
|
22348
23313
|
return Promise.reject(new DOMException("The operation was aborted.", "AbortError"));
|
|
22349
23314
|
}
|
|
22350
|
-
return new Promise((
|
|
23315
|
+
return new Promise((resolve25, reject) => {
|
|
22351
23316
|
const onAbort = () => {
|
|
22352
23317
|
clearTimeout(t);
|
|
22353
23318
|
signal.removeEventListener("abort", onAbort);
|
|
@@ -22355,7 +23320,7 @@ function sleepUntilAborted(ms, signal) {
|
|
|
22355
23320
|
};
|
|
22356
23321
|
const t = setTimeout(() => {
|
|
22357
23322
|
signal.removeEventListener("abort", onAbort);
|
|
22358
|
-
|
|
23323
|
+
resolve25();
|
|
22359
23324
|
}, ms);
|
|
22360
23325
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
22361
23326
|
});
|
|
@@ -22902,7 +23867,7 @@ async function runGenerateContextFactory(deps) {
|
|
|
22902
23867
|
|
|
22903
23868
|
// src/factory/generateContextFactoryHeadlessHost.ts
|
|
22904
23869
|
var fs48 = __toESM(require("node:fs"));
|
|
22905
|
-
var
|
|
23870
|
+
var path46 = __toESM(require("node:path"));
|
|
22906
23871
|
|
|
22907
23872
|
// src/stores/pipelineRunStore.ts
|
|
22908
23873
|
var STORAGE_KEY2 = SRS53_PIPELINE_RUN_KEY_V2;
|
|
@@ -23003,11 +23968,11 @@ async function noteAgentsMaterialized(context) {
|
|
|
23003
23968
|
|
|
23004
23969
|
// src/pipelines/remediation/missingWorkstations.ts
|
|
23005
23970
|
var fs41 = __toESM(require("fs"));
|
|
23006
|
-
var
|
|
23971
|
+
var path38 = __toESM(require("path"));
|
|
23007
23972
|
|
|
23008
23973
|
// src/analysis/analysisDetailMarkdownDiscovery.ts
|
|
23009
23974
|
var fs40 = __toESM(require("fs"));
|
|
23010
|
-
var
|
|
23975
|
+
var path37 = __toESM(require("path"));
|
|
23011
23976
|
var SLUG4 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
23012
23977
|
var FE2 = /^FE-\d+$/;
|
|
23013
23978
|
var UC2 = /^UC-\d+$/;
|
|
@@ -23024,7 +23989,17 @@ var STEM_TO_AGENT = {
|
|
|
23024
23989
|
"agent-md-method-detail": { agentId: "ctx-md-method-detail", displayName: "Method detail" },
|
|
23025
23990
|
"agent-md-entity-detail": { agentId: "ctx-md-entity-detail", displayName: "Entity detail" },
|
|
23026
23991
|
"agent-md-field-detail": { agentId: "ctx-md-field-detail", displayName: "Field detail" },
|
|
23027
|
-
"agent-md-tool-detail": { agentId: "ctx-md-tool-detail", displayName: "Tool detail" }
|
|
23992
|
+
"agent-md-tool-detail": { agentId: "ctx-md-tool-detail", displayName: "Tool detail" },
|
|
23993
|
+
"agent-md-infrastructure-detail": {
|
|
23994
|
+
agentId: "ctx-md-infrastructure-detail",
|
|
23995
|
+
displayName: "Infrastructure detail"
|
|
23996
|
+
},
|
|
23997
|
+
"agent-md-infrastructure-component-detail": {
|
|
23998
|
+
agentId: "ctx-md-infrastructure-component-detail",
|
|
23999
|
+
displayName: "Infrastructure component detail"
|
|
24000
|
+
},
|
|
24001
|
+
"agent-md-qa-detail": { agentId: "ctx-md-qa-detail", displayName: "QA detail" },
|
|
24002
|
+
"agent-md-qa-test-case-detail": { agentId: "ctx-md-qa-test-case-detail", displayName: "QA test case detail" }
|
|
23028
24003
|
};
|
|
23029
24004
|
function readJson5(filePath) {
|
|
23030
24005
|
try {
|
|
@@ -23068,8 +24043,8 @@ function expectedFeatureDetailBasenameFromRow(row2) {
|
|
|
23068
24043
|
}
|
|
23069
24044
|
return `${code}-${slug}.md`;
|
|
23070
24045
|
}
|
|
23071
|
-
function ctxPath(contextDir2,
|
|
23072
|
-
return
|
|
24046
|
+
function ctxPath(contextDir2, basename18) {
|
|
24047
|
+
return path37.join(contextDir2, basename18);
|
|
23073
24048
|
}
|
|
23074
24049
|
function pushTarget(targets, stem, outputBasename, taskDescription, contextDir2) {
|
|
23075
24050
|
const meta = STEM_TO_AGENT[stem];
|
|
@@ -23085,7 +24060,7 @@ function pushTarget(targets, stem, outputBasename, taskDescription, contextDir2)
|
|
|
23085
24060
|
function discoverDetailMarkdownGroups(contextDir2) {
|
|
23086
24061
|
const groups = [];
|
|
23087
24062
|
const featureTargets = [];
|
|
23088
|
-
const flPath =
|
|
24063
|
+
const flPath = path37.join(contextDir2, "features-list.json");
|
|
23089
24064
|
const fl = readJson5(flPath);
|
|
23090
24065
|
const features = Array.isArray(fl?.features) ? fl.features : [];
|
|
23091
24066
|
for (const row2 of features) {
|
|
@@ -23098,11 +24073,11 @@ function discoverDetailMarkdownGroups(contextDir2) {
|
|
|
23098
24073
|
continue;
|
|
23099
24074
|
}
|
|
23100
24075
|
const name = safeStr4(row2.name) || code;
|
|
23101
|
-
const
|
|
24076
|
+
const basename18 = `${code}-${slug}.md`;
|
|
23102
24077
|
pushTarget(
|
|
23103
24078
|
featureTargets,
|
|
23104
24079
|
"agent-md-feature-detail",
|
|
23105
|
-
|
|
24080
|
+
basename18,
|
|
23106
24081
|
`Document feature **${code}** (**${name}**, slug **${slug}**) per \`.gluecharm/context/features-list.json\`: scope, behaviour, main dependencies, entry points, and links to code under the worktree. Write exactly one markdown file at the output path; cite substantive claims with file and line (or range).`,
|
|
23107
24082
|
contextDir2
|
|
23108
24083
|
);
|
|
@@ -23115,7 +24090,7 @@ function discoverDetailMarkdownGroups(contextDir2) {
|
|
|
23115
24090
|
if (!FE2.test(feCode)) {
|
|
23116
24091
|
continue;
|
|
23117
24092
|
}
|
|
23118
|
-
const ucListPath =
|
|
24093
|
+
const ucListPath = path37.join(contextDir2, `${feCode}-use-cases-list.json`);
|
|
23119
24094
|
const ucFile = readJson5(ucListPath);
|
|
23120
24095
|
const ucs = Array.isArray(ucFile?.useCases) ? ucFile.useCases : [];
|
|
23121
24096
|
for (const ucRow of ucs) {
|
|
@@ -23135,7 +24110,7 @@ function discoverDetailMarkdownGroups(contextDir2) {
|
|
|
23135
24110
|
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.`,
|
|
23136
24111
|
contextDir2
|
|
23137
24112
|
);
|
|
23138
|
-
const scPath =
|
|
24113
|
+
const scPath = path37.join(contextDir2, `${feCode}_${ucCode}-scenarios-list.json`);
|
|
23139
24114
|
const scFile = readJson5(scPath);
|
|
23140
24115
|
const scs = Array.isArray(scFile?.scenarios) ? scFile.scenarios : [];
|
|
23141
24116
|
for (const scRow of scs) {
|
|
@@ -23206,7 +24181,7 @@ Follow bundled agent **agent-md-use-case-detail**: include **## Data inputs and
|
|
|
23206
24181
|
groups.push({ id: "detail-services", label: "Detail markdown \u2014 Services", targets: svcTargets });
|
|
23207
24182
|
groups.push({ id: "detail-methods", label: "Detail markdown \u2014 Methods", targets: meTargets });
|
|
23208
24183
|
const entTargets = [];
|
|
23209
|
-
const dmPath =
|
|
24184
|
+
const dmPath = path37.join(contextDir2, "data-model-list.json");
|
|
23210
24185
|
const dmFile = readJson5(dmPath);
|
|
23211
24186
|
const ents = Array.isArray(dmFile?.entities) ? dmFile.entities : [];
|
|
23212
24187
|
for (const erow of ents) {
|
|
@@ -23235,7 +24210,7 @@ Follow bundled agent **agent-md-use-case-detail**: include **## Data inputs and
|
|
|
23235
24210
|
if (!DM2.test(dmCode)) {
|
|
23236
24211
|
continue;
|
|
23237
24212
|
}
|
|
23238
|
-
const flPath2 =
|
|
24213
|
+
const flPath2 = path37.join(contextDir2, `${dmCode}-fields-list.json`);
|
|
23239
24214
|
const flFile = readJson5(flPath2);
|
|
23240
24215
|
const flds = Array.isArray(flFile?.fields) ? flFile.fields : [];
|
|
23241
24216
|
for (const frow of flds) {
|
|
@@ -23271,6 +24246,58 @@ Follow bundled agent **agent-md-use-case-detail**: include **## Data inputs and
|
|
|
23271
24246
|
);
|
|
23272
24247
|
}
|
|
23273
24248
|
groups.push({ id: "detail-tools", label: "Detail markdown \u2014 Tech stack", targets: toolTargets });
|
|
24249
|
+
const infraTargets = [];
|
|
24250
|
+
const icTargets = [];
|
|
24251
|
+
for (const row2 of discoverInfrastructureComponentTreeRows(contextDir2)) {
|
|
24252
|
+
const inBase = `${row2.code}-${row2.slug}.md`;
|
|
24253
|
+
pushTarget(
|
|
24254
|
+
infraTargets,
|
|
24255
|
+
"agent-md-infrastructure-detail",
|
|
24256
|
+
inBase,
|
|
24257
|
+
`Document infrastructure **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/infrastructure-list.json\`.`,
|
|
24258
|
+
contextDir2
|
|
24259
|
+
);
|
|
24260
|
+
for (const comp of row2.components) {
|
|
24261
|
+
const icBase = `${row2.code}_${comp.code}-${comp.slug}.md`;
|
|
24262
|
+
pushTarget(
|
|
24263
|
+
icTargets,
|
|
24264
|
+
"agent-md-infrastructure-component-detail",
|
|
24265
|
+
icBase,
|
|
24266
|
+
`Document component **${comp.code}** (**${comp.name}**) under infrastructure **${row2.code}** per \`.gluecharm/context/${row2.code}-components-list.json\`.`,
|
|
24267
|
+
contextDir2
|
|
24268
|
+
);
|
|
24269
|
+
}
|
|
24270
|
+
}
|
|
24271
|
+
groups.push({ id: "detail-infrastructure", label: "Detail markdown \u2014 Infrastructure", targets: infraTargets });
|
|
24272
|
+
groups.push({
|
|
24273
|
+
id: "detail-infrastructure-components",
|
|
24274
|
+
label: "Detail markdown \u2014 Infrastructure components",
|
|
24275
|
+
targets: icTargets
|
|
24276
|
+
});
|
|
24277
|
+
const qaTargets = [];
|
|
24278
|
+
const tcTargets = [];
|
|
24279
|
+
for (const row2 of discoverQaTestCaseTreeRows(contextDir2)) {
|
|
24280
|
+
const qaBase = `${row2.code}-${row2.slug}.md`;
|
|
24281
|
+
pushTarget(
|
|
24282
|
+
qaTargets,
|
|
24283
|
+
"agent-md-qa-detail",
|
|
24284
|
+
qaBase,
|
|
24285
|
+
`Document QA area **${row2.code}** (**${row2.name}**, slug **${row2.slug}**) per \`.gluecharm/context/qa-list.json\`.`,
|
|
24286
|
+
contextDir2
|
|
24287
|
+
);
|
|
24288
|
+
for (const tc of row2.testCases) {
|
|
24289
|
+
const tcBase = `${row2.code}_${tc.code}-${tc.slug}.md`;
|
|
24290
|
+
pushTarget(
|
|
24291
|
+
tcTargets,
|
|
24292
|
+
"agent-md-qa-test-case-detail",
|
|
24293
|
+
tcBase,
|
|
24294
|
+
`Document test case **${tc.code}** (**${tc.name}**) under QA **${row2.code}**; include **coversCodes** anchors per \`.gluecharm/context/${row2.code}-test-cases-list.json\`.`,
|
|
24295
|
+
contextDir2
|
|
24296
|
+
);
|
|
24297
|
+
}
|
|
24298
|
+
}
|
|
24299
|
+
groups.push({ id: "detail-qa", label: "Detail markdown \u2014 QA", targets: qaTargets });
|
|
24300
|
+
groups.push({ id: "detail-qa-test-cases", label: "Detail markdown \u2014 QA test cases", targets: tcTargets });
|
|
23274
24301
|
return groups;
|
|
23275
24302
|
}
|
|
23276
24303
|
function collectExpectedDetailMarkdownBasenames(contextDir2) {
|
|
@@ -23294,7 +24321,7 @@ function fileAndValidationFromKind(kind) {
|
|
|
23294
24321
|
return { filePresentYesNo: "no", validationYesNo: "na" };
|
|
23295
24322
|
}
|
|
23296
24323
|
function classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeRoot) {
|
|
23297
|
-
const abs =
|
|
24324
|
+
const abs = path38.join(contextDir2, row2.relativePath);
|
|
23298
24325
|
try {
|
|
23299
24326
|
const st = fs41.statSync(abs);
|
|
23300
24327
|
if (!st.isFile()) {
|
|
@@ -23333,7 +24360,7 @@ function classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeR
|
|
|
23333
24360
|
detail: "Unknown coordination list basename \u2014 no JSON Schema mapping."
|
|
23334
24361
|
};
|
|
23335
24362
|
}
|
|
23336
|
-
const schemaAbs =
|
|
24363
|
+
const schemaAbs = path38.join(worktreeRoot, ".opencode", "schemas", "context-lists", schemaBn);
|
|
23337
24364
|
if (!fs41.existsSync(schemaAbs)) {
|
|
23338
24365
|
return {
|
|
23339
24366
|
kind: "invalid",
|
|
@@ -23363,7 +24390,7 @@ function classifyWorkstationOutputOnDisk(item, contextDir2, worktreeRoot) {
|
|
|
23363
24390
|
return classifyMissingWorkstationOutputFileStatus(row2, contextDir2, worktreeRoot).kind;
|
|
23364
24391
|
}
|
|
23365
24392
|
function isWorkstationRunSnapshotForWorktree(snapshot, worktreeRoot) {
|
|
23366
|
-
return !!(snapshot && snapshot.overallStatus !== "running" && snapshot.overallStatus !== "idle" &&
|
|
24393
|
+
return !!(snapshot && snapshot.overallStatus !== "running" && snapshot.overallStatus !== "idle" && path38.resolve(snapshot.analysisRoot) === path38.resolve(worktreeRoot));
|
|
23367
24394
|
}
|
|
23368
24395
|
function expectedBasenameForCoordPayload(p) {
|
|
23369
24396
|
const { step, listTarget } = p;
|
|
@@ -23420,6 +24447,22 @@ function expectedBasenameForCoordPayload(p) {
|
|
|
23420
24447
|
const dm = listTarget?.entityCode?.trim();
|
|
23421
24448
|
return dm ? `${dm}-fields-list.json` : null;
|
|
23422
24449
|
}
|
|
24450
|
+
case "listInfrastructure":
|
|
24451
|
+
case "reviewInfrastructureList":
|
|
24452
|
+
return "infrastructure-list.json";
|
|
24453
|
+
case "listQa":
|
|
24454
|
+
case "reviewQaList":
|
|
24455
|
+
return "qa-list.json";
|
|
24456
|
+
case "listInfrastructureComponents":
|
|
24457
|
+
case "reviewInfrastructureComponentsList": {
|
|
24458
|
+
const inCode = listTarget?.infrastructureCode?.trim();
|
|
24459
|
+
return inCode ? `${inCode}-components-list.json` : null;
|
|
24460
|
+
}
|
|
24461
|
+
case "listQaTestCases":
|
|
24462
|
+
case "reviewQaTestCasesList": {
|
|
24463
|
+
const qaCode = listTarget?.qaCode?.trim();
|
|
24464
|
+
return qaCode ? `${qaCode}-test-cases-list.json` : null;
|
|
24465
|
+
}
|
|
23423
24466
|
default:
|
|
23424
24467
|
return null;
|
|
23425
24468
|
}
|
|
@@ -23432,15 +24475,17 @@ function labelContextForCoordPayload(p) {
|
|
|
23432
24475
|
return {
|
|
23433
24476
|
...lt.featureCode ? { featureCode: lt.featureCode } : {},
|
|
23434
24477
|
...lt.useCaseCode ? { useCaseCode: lt.useCaseCode } : {},
|
|
23435
|
-
...lt.entityCode ? { entityCode: lt.entityCode } : {}
|
|
24478
|
+
...lt.entityCode ? { entityCode: lt.entityCode } : {},
|
|
24479
|
+
...lt.infrastructureCode ? { infrastructureCode: lt.infrastructureCode } : {},
|
|
24480
|
+
...lt.qaCode ? { qaCode: lt.qaCode } : {}
|
|
23436
24481
|
};
|
|
23437
24482
|
}
|
|
23438
24483
|
function contextPathForWorkItem(item, contextDir2) {
|
|
23439
24484
|
if (item.kind === "markdown") {
|
|
23440
|
-
return
|
|
24485
|
+
return path38.join(contextDir2, item.payload.outputBasename);
|
|
23441
24486
|
}
|
|
23442
24487
|
const bn = expectedBasenameForCoordPayload(item.payload);
|
|
23443
|
-
return bn ?
|
|
24488
|
+
return bn ? path38.join(contextDir2, bn) : null;
|
|
23444
24489
|
}
|
|
23445
24490
|
function syntheticRunnerId(key) {
|
|
23446
24491
|
return `remediation:${key}`;
|
|
@@ -23450,7 +24495,7 @@ function rowFromSkippedItem(item, contextDir2) {
|
|
|
23450
24495
|
return null;
|
|
23451
24496
|
}
|
|
23452
24497
|
const abs = contextPathForWorkItem(item, contextDir2);
|
|
23453
|
-
const rel = abs ?
|
|
24498
|
+
const rel = abs ? path38.basename(abs) : item.kind === "markdown" ? item.payload.outputBasename : item.id;
|
|
23454
24499
|
if (abs && nonEmptyContextFile(abs)) {
|
|
23455
24500
|
return null;
|
|
23456
24501
|
}
|
|
@@ -23521,7 +24566,9 @@ function rowsFromDynamicPayload(contextDir2, p) {
|
|
|
23521
24566
|
"experiences-list.json": "listExperiences",
|
|
23522
24567
|
"services-list.json": "listServices",
|
|
23523
24568
|
"data-model-list.json": "listDataModel",
|
|
23524
|
-
"tech-stack-list.json": "listTechStack"
|
|
24569
|
+
"tech-stack-list.json": "listTechStack",
|
|
24570
|
+
"infrastructure-list.json": "listInfrastructure",
|
|
24571
|
+
"qa-list.json": "listQa"
|
|
23525
24572
|
};
|
|
23526
24573
|
const step = stepMap[bn];
|
|
23527
24574
|
if (step) {
|
|
@@ -23557,6 +24604,24 @@ function rowsFromDynamicPayload(contextDir2, p) {
|
|
|
23557
24604
|
);
|
|
23558
24605
|
}
|
|
23559
24606
|
}
|
|
24607
|
+
for (const row2 of discoverInfrastructureComponentTreeRows(contextDir2)) {
|
|
24608
|
+
const rel = `${row2.code}-components-list.json`;
|
|
24609
|
+
const exists = nonEmptyContextFile(path38.join(contextDir2, rel));
|
|
24610
|
+
if (!exists) {
|
|
24611
|
+
pushCoord("listInfrastructureComponents", rel, rel, synthesisStepLabel("listInfrastructureComponents", { infrastructureCode: row2.code }), {
|
|
24612
|
+
infrastructureCode: row2.code
|
|
24613
|
+
});
|
|
24614
|
+
}
|
|
24615
|
+
}
|
|
24616
|
+
for (const row2 of discoverQaTestCaseTreeRows(contextDir2)) {
|
|
24617
|
+
const rel = `${row2.code}-test-cases-list.json`;
|
|
24618
|
+
const exists = nonEmptyContextFile(path38.join(contextDir2, rel));
|
|
24619
|
+
if (!exists) {
|
|
24620
|
+
pushCoord("listQaTestCases", rel, rel, synthesisStepLabel("listQaTestCases", { qaCode: row2.code }), {
|
|
24621
|
+
qaCode: row2.code
|
|
24622
|
+
});
|
|
24623
|
+
}
|
|
24624
|
+
}
|
|
23560
24625
|
return out;
|
|
23561
24626
|
}
|
|
23562
24627
|
function listMissingWorkstations(contextDir2, worktreeRoot, snapshot) {
|
|
@@ -23625,7 +24690,7 @@ function toMissingWorkstationUiRows(rows, contextDir2, worktreeRoot) {
|
|
|
23625
24690
|
}
|
|
23626
24691
|
|
|
23627
24692
|
// src/pipelines/remediation/missingWorkstationsPool.ts
|
|
23628
|
-
var
|
|
24693
|
+
var path39 = __toESM(require("path"));
|
|
23629
24694
|
function reconcileSkippedWorkItemsWithDisk(byId, contextDir2, worktreeRoot) {
|
|
23630
24695
|
for (const item of byId.values()) {
|
|
23631
24696
|
if (item.status !== "skipped") {
|
|
@@ -23685,7 +24750,7 @@ async function runRemediationPipelineMissingPass(p) {
|
|
|
23685
24750
|
onItemComplete,
|
|
23686
24751
|
sourceBranchAtWorktreeCreation
|
|
23687
24752
|
} = p;
|
|
23688
|
-
const contextDir2 =
|
|
24753
|
+
const contextDir2 = path39.join(worktreeRoot, ".gluecharm", "context");
|
|
23689
24754
|
const snap = readArtefactRunSnapshot(storageContext);
|
|
23690
24755
|
const snapOk = isWorkstationRunSnapshotForWorktree(snap, worktreeRoot);
|
|
23691
24756
|
let byId;
|
|
@@ -23752,17 +24817,17 @@ async function runRemediationPipelineMissingPass(p) {
|
|
|
23752
24817
|
// src/pipelines/coverage/coveragePipeline.ts
|
|
23753
24818
|
var import_child_process5 = require("child_process");
|
|
23754
24819
|
var fs43 = __toESM(require("fs"));
|
|
23755
|
-
var
|
|
24820
|
+
var path41 = __toESM(require("path"));
|
|
23756
24821
|
|
|
23757
24822
|
// src/analysis/coverageReferenceValidationSchemaValidate.ts
|
|
23758
24823
|
var fs42 = __toESM(require("fs"));
|
|
23759
|
-
var
|
|
24824
|
+
var path40 = __toESM(require("path"));
|
|
23760
24825
|
var import__5 = __toESM(require__());
|
|
23761
24826
|
function stripUtf8Bom4(s) {
|
|
23762
24827
|
return s.length > 0 && s.charCodeAt(0) === 65279 ? s.slice(1) : s;
|
|
23763
24828
|
}
|
|
23764
24829
|
function bundledCoverageReferenceValidationSchemaPath() {
|
|
23765
|
-
return
|
|
24830
|
+
return path40.join(
|
|
23766
24831
|
resolveRepoResourcesRoot(),
|
|
23767
24832
|
"schemas",
|
|
23768
24833
|
"context-lists",
|
|
@@ -23842,8 +24907,8 @@ var DEFAULT_IGNORE_DIR_BASENAMES = [
|
|
|
23842
24907
|
];
|
|
23843
24908
|
var GIT_LS_FILES_MAX_BUFFER = 64 * 1024 * 1024;
|
|
23844
24909
|
function tryLoadGitNonIgnoredPathSet(repositoryRootAbs) {
|
|
23845
|
-
const root =
|
|
23846
|
-
if (!fs43.existsSync(
|
|
24910
|
+
const root = path41.resolve(repositoryRootAbs);
|
|
24911
|
+
if (!fs43.existsSync(path41.join(root, ".git"))) {
|
|
23847
24912
|
return null;
|
|
23848
24913
|
}
|
|
23849
24914
|
const env = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
@@ -23911,12 +24976,12 @@ var REFERENCE_COVERAGE_IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
23911
24976
|
".emf"
|
|
23912
24977
|
]);
|
|
23913
24978
|
function isReferenceCoverageExcludedImagePath(relPosix) {
|
|
23914
|
-
const ext =
|
|
24979
|
+
const ext = path41.extname(relPosix).toLowerCase();
|
|
23915
24980
|
return ext.length > 0 && REFERENCE_COVERAGE_IMAGE_EXTENSIONS.has(ext);
|
|
23916
24981
|
}
|
|
23917
24982
|
var REFERENCE_COVERAGE_EXCLUDED_FILE_BASENAMES = /* @__PURE__ */ new Set([".gitignore"]);
|
|
23918
24983
|
function isReferenceCoverageExcludedDefaultBasename(relPosix) {
|
|
23919
|
-
const base =
|
|
24984
|
+
const base = path41.basename(relPosix.replace(/\\/g, "/")).toLowerCase();
|
|
23920
24985
|
return REFERENCE_COVERAGE_EXCLUDED_FILE_BASENAMES.has(base);
|
|
23921
24986
|
}
|
|
23922
24987
|
function decodeBufferForLineCount(buf) {
|
|
@@ -23953,12 +25018,12 @@ function normalizeRepoRelativePath(repoRoot, raw) {
|
|
|
23953
25018
|
if (!trimmed || trimmed.includes("\0")) {
|
|
23954
25019
|
return null;
|
|
23955
25020
|
}
|
|
23956
|
-
const abs =
|
|
23957
|
-
const rel =
|
|
23958
|
-
if (rel.startsWith("..") ||
|
|
25021
|
+
const abs = path41.resolve(repoRoot, trimmed);
|
|
25022
|
+
const rel = path41.relative(repoRoot, abs);
|
|
25023
|
+
if (rel.startsWith("..") || path41.isAbsolute(rel)) {
|
|
23959
25024
|
return null;
|
|
23960
25025
|
}
|
|
23961
|
-
return rel.split(
|
|
25026
|
+
return rel.split(path41.sep).join("/");
|
|
23962
25027
|
}
|
|
23963
25028
|
function collectJsonSourceReferences(node, out) {
|
|
23964
25029
|
if (node === null || typeof node !== "object") {
|
|
@@ -24003,7 +25068,7 @@ function listContextFilesRecursive(dir, acc) {
|
|
|
24003
25068
|
return;
|
|
24004
25069
|
}
|
|
24005
25070
|
for (const e of entries) {
|
|
24006
|
-
const full =
|
|
25071
|
+
const full = path41.join(dir, e.name);
|
|
24007
25072
|
if (e.isDirectory()) {
|
|
24008
25073
|
listContextFilesRecursive(full, acc);
|
|
24009
25074
|
} else if (e.isFile()) {
|
|
@@ -24024,8 +25089,8 @@ function walkRepositoryFiles(repoRoot, ignoreBasenames, maxBytes, excludedOut, g
|
|
|
24024
25089
|
if (ignoreBasenames.has(e.name)) {
|
|
24025
25090
|
continue;
|
|
24026
25091
|
}
|
|
24027
|
-
const full =
|
|
24028
|
-
const rel =
|
|
25092
|
+
const full = path41.join(dir, e.name);
|
|
25093
|
+
const rel = path41.relative(repoRoot, full).split(path41.sep).join("/");
|
|
24029
25094
|
if (rel.startsWith("..")) {
|
|
24030
25095
|
continue;
|
|
24031
25096
|
}
|
|
@@ -24083,9 +25148,9 @@ function collectReferencesFromContext(contextDirAbs, repositoryRootAbs, warnings
|
|
|
24083
25148
|
const allFiles = [];
|
|
24084
25149
|
listContextFilesRecursive(contextDirAbs, allFiles);
|
|
24085
25150
|
for (const abs of allFiles) {
|
|
24086
|
-
const ext =
|
|
24087
|
-
const base =
|
|
24088
|
-
const sourceArtefact =
|
|
25151
|
+
const ext = path41.extname(abs).toLowerCase();
|
|
25152
|
+
const base = path41.basename(abs);
|
|
25153
|
+
const sourceArtefact = path41.relative(contextDirAbs, abs).split(path41.sep).join("/");
|
|
24089
25154
|
if (ext === ".json") {
|
|
24090
25155
|
if (SKIP_CONTEXT_JSON.has(base)) {
|
|
24091
25156
|
continue;
|
|
@@ -24167,12 +25232,12 @@ function sortReferenceRows(a, b) {
|
|
|
24167
25232
|
return (a.startLine ?? 0) - (b.startLine ?? 0);
|
|
24168
25233
|
}
|
|
24169
25234
|
function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirAbs, options) {
|
|
24170
|
-
const repoRoot =
|
|
25235
|
+
const repoRoot = path41.resolve(repositoryRootAbs);
|
|
24171
25236
|
const warnings = [];
|
|
24172
25237
|
const ignoreDirs = [...DEFAULT_IGNORE_DIR_BASENAMES];
|
|
24173
25238
|
const ignoreSet = new Set(ignoreDirs);
|
|
24174
25239
|
const maxBytes = options?.maxFileBytes ?? MAX_FILE_BYTES;
|
|
24175
|
-
const references = collectReferencesFromContext(
|
|
25240
|
+
const references = collectReferencesFromContext(path41.resolve(contextDirAbs), repoRoot, warnings);
|
|
24176
25241
|
references.sort(sortReferenceRows);
|
|
24177
25242
|
const referencedSet = /* @__PURE__ */ new Set();
|
|
24178
25243
|
for (const r of references) {
|
|
@@ -24180,7 +25245,7 @@ function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirA
|
|
|
24180
25245
|
}
|
|
24181
25246
|
const excludedFiles = [];
|
|
24182
25247
|
const gitNonIgnoredPaths = tryLoadGitNonIgnoredPathSet(repoRoot);
|
|
24183
|
-
if (fs43.existsSync(
|
|
25248
|
+
if (fs43.existsSync(path41.join(repoRoot, ".git")) && gitNonIgnoredPaths === null) {
|
|
24184
25249
|
warnings.push(
|
|
24185
25250
|
"Repository has .git but git ls-files failed or git is unavailable; .gitignore / exclude-standard not applied."
|
|
24186
25251
|
);
|
|
@@ -24229,8 +25294,8 @@ function buildCoverageReferenceValidationDocument(repositoryRootAbs, contextDirA
|
|
|
24229
25294
|
return { document: doc, warnings };
|
|
24230
25295
|
}
|
|
24231
25296
|
function runCoveragePipeline(opts) {
|
|
24232
|
-
const repoRoot =
|
|
24233
|
-
const contextDir2 =
|
|
25297
|
+
const repoRoot = path41.resolve(opts.repositoryRootAbs);
|
|
25298
|
+
const contextDir2 = path41.resolve(opts.contextDirAbs);
|
|
24234
25299
|
if (!fs43.existsSync(repoRoot)) {
|
|
24235
25300
|
return { ok: false, error: `Repository root does not exist: ${repoRoot}` };
|
|
24236
25301
|
}
|
|
@@ -24252,7 +25317,7 @@ ${schemaCheck.errors.join("\n")}`,
|
|
|
24252
25317
|
warnings
|
|
24253
25318
|
};
|
|
24254
25319
|
}
|
|
24255
|
-
const outPath =
|
|
25320
|
+
const outPath = path41.join(contextDir2, COVERAGE_REFERENCE_VALIDATION_BASENAME);
|
|
24256
25321
|
if (opts.write) {
|
|
24257
25322
|
try {
|
|
24258
25323
|
const payload = stableStringifyCoverageDocument(document);
|
|
@@ -24271,11 +25336,11 @@ ${schemaCheck.errors.join("\n")}`,
|
|
|
24271
25336
|
// src/pipelines/remediation/zeroReferenceWorkstationChain.ts
|
|
24272
25337
|
var crypto = __toESM(require("crypto"));
|
|
24273
25338
|
var fs45 = __toESM(require("fs"));
|
|
24274
|
-
var
|
|
25339
|
+
var path43 = __toESM(require("path"));
|
|
24275
25340
|
|
|
24276
25341
|
// src/analysis/zeroReferenceRemediationSchemaValidate.ts
|
|
24277
25342
|
var fs44 = __toESM(require("fs"));
|
|
24278
|
-
var
|
|
25343
|
+
var path42 = __toESM(require("path"));
|
|
24279
25344
|
var import__6 = __toESM(require__());
|
|
24280
25345
|
function stripUtf8Bom5(s) {
|
|
24281
25346
|
return s.length > 0 && s.charCodeAt(0) === 65279 ? s.slice(1) : s;
|
|
@@ -24294,8 +25359,8 @@ function formatAjvErrors6(errors) {
|
|
|
24294
25359
|
});
|
|
24295
25360
|
}
|
|
24296
25361
|
var ajv = new import__6.default({ allErrors: true, strict: false });
|
|
24297
|
-
function compileSchema(
|
|
24298
|
-
const schemaPath =
|
|
25362
|
+
function compileSchema(basename18) {
|
|
25363
|
+
const schemaPath = path42.join(schemasDir(), basename18);
|
|
24299
25364
|
const schemaRaw = stripUtf8Bom5(fs44.readFileSync(schemaPath, "utf-8"));
|
|
24300
25365
|
const schema = JSON.parse(schemaRaw);
|
|
24301
25366
|
return ajv.compile(schema);
|
|
@@ -24506,7 +25571,9 @@ var COORD_SCOPE_TO_TOP_ROUTING = {
|
|
|
24506
25571
|
use_case: "feature",
|
|
24507
25572
|
scenario: "feature",
|
|
24508
25573
|
behavior: "experiences",
|
|
24509
|
-
field_domain: "data_models"
|
|
25574
|
+
field_domain: "data_models",
|
|
25575
|
+
infrastructure: "infrastructure",
|
|
25576
|
+
qa: "qa"
|
|
24510
25577
|
};
|
|
24511
25578
|
function normalizeClassifierRouting(record) {
|
|
24512
25579
|
const raw = record.routing;
|
|
@@ -24542,6 +25609,16 @@ function normalizeClassifierRouting(record) {
|
|
|
24542
25609
|
delete record.coordinationScope;
|
|
24543
25610
|
return;
|
|
24544
25611
|
}
|
|
25612
|
+
if (r === "infrastructure") {
|
|
25613
|
+
record.routing = "infrastructure";
|
|
25614
|
+
delete record.coordinationScope;
|
|
25615
|
+
return;
|
|
25616
|
+
}
|
|
25617
|
+
if (r === "qa") {
|
|
25618
|
+
record.routing = "qa";
|
|
25619
|
+
delete record.coordinationScope;
|
|
25620
|
+
return;
|
|
25621
|
+
}
|
|
24545
25622
|
record.routing = r;
|
|
24546
25623
|
}
|
|
24547
25624
|
function normalizeClassifierStagingRecord(record) {
|
|
@@ -24563,6 +25640,12 @@ function resolveListTriageKindFromStaging(staging) {
|
|
|
24563
25640
|
if (routing === "data_models") {
|
|
24564
25641
|
return "data_model";
|
|
24565
25642
|
}
|
|
25643
|
+
if (routing === "infrastructure") {
|
|
25644
|
+
return "infrastructure";
|
|
25645
|
+
}
|
|
25646
|
+
if (routing === "qa") {
|
|
25647
|
+
return "qa";
|
|
25648
|
+
}
|
|
24566
25649
|
if (routing === "coordination_follow_up") {
|
|
24567
25650
|
const top = COORD_SCOPE_TO_TOP_ROUTING[scope] || "feature";
|
|
24568
25651
|
if (top === "experiences") {
|
|
@@ -24574,6 +25657,12 @@ function resolveListTriageKindFromStaging(staging) {
|
|
|
24574
25657
|
if (top === "data_models") {
|
|
24575
25658
|
return "data_model";
|
|
24576
25659
|
}
|
|
25660
|
+
if (top === "infrastructure") {
|
|
25661
|
+
return "infrastructure";
|
|
25662
|
+
}
|
|
25663
|
+
if (top === "qa") {
|
|
25664
|
+
return "qa";
|
|
25665
|
+
}
|
|
24577
25666
|
return "feature";
|
|
24578
25667
|
}
|
|
24579
25668
|
return null;
|
|
@@ -24590,17 +25679,17 @@ function expandArgvTemplate4(template, vars) {
|
|
|
24590
25679
|
});
|
|
24591
25680
|
}
|
|
24592
25681
|
function schemaRef2(worktreeRoot, schemaBasename) {
|
|
24593
|
-
return
|
|
25682
|
+
return path43.join(worktreeRoot, ".opencode", "schemas", "context-lists", schemaBasename);
|
|
24594
25683
|
}
|
|
24595
25684
|
function stagingDir(contextDirAbs) {
|
|
24596
|
-
return
|
|
25685
|
+
return path43.join(contextDirAbs, "_zero-ref-staging");
|
|
24597
25686
|
}
|
|
24598
25687
|
function stagingPathForTarget(contextDirAbs, kind, targetFilePathPosix) {
|
|
24599
25688
|
const h = crypto.createHash("sha256").update(targetFilePathPosix, "utf8").digest("hex").slice(0, 16);
|
|
24600
|
-
return
|
|
25689
|
+
return path43.join(stagingDir(contextDirAbs), `${kind}-${h}.json`);
|
|
24601
25690
|
}
|
|
24602
25691
|
function readNonReferencedFilesFromRepositoryRoot(repositoryRootAbs) {
|
|
24603
|
-
const p =
|
|
25692
|
+
const p = path43.join(repositoryRootAbs, ".gluecharm", "context", "coverage-reference-validation.json");
|
|
24604
25693
|
const r = readAndValidateCoverageReferenceValidationFile(p);
|
|
24605
25694
|
if (!r.ok) {
|
|
24606
25695
|
return { ok: false, error: r.errors.join("; ") };
|
|
@@ -24693,7 +25782,7 @@ function slugifyFeatureLabel(s) {
|
|
|
24693
25782
|
return t.length > 0 ? t : "feature";
|
|
24694
25783
|
}
|
|
24695
25784
|
function lineCountRepoFile(worktreeRootAbs, relPosix) {
|
|
24696
|
-
const abs =
|
|
25785
|
+
const abs = path43.join(worktreeRootAbs, ...relPosix.split("/"));
|
|
24697
25786
|
let buf;
|
|
24698
25787
|
try {
|
|
24699
25788
|
buf = fs45.readFileSync(abs);
|
|
@@ -24732,24 +25821,42 @@ var LIST_MERGE_CFG = {
|
|
|
24732
25821
|
arrayKey: "entities",
|
|
24733
25822
|
codeRe: /^DM-(\d+)$/,
|
|
24734
25823
|
prefix: "DM"
|
|
25824
|
+
},
|
|
25825
|
+
infrastructure: {
|
|
25826
|
+
listBasename: "infrastructure-list.json",
|
|
25827
|
+
schemaBasename: "infrastructure-list.schema.json",
|
|
25828
|
+
arrayKey: "infrastructure",
|
|
25829
|
+
codeRe: /^IN-(\d+)$/,
|
|
25830
|
+
prefix: "IN"
|
|
25831
|
+
},
|
|
25832
|
+
qa: {
|
|
25833
|
+
listBasename: "qa-list.json",
|
|
25834
|
+
schemaBasename: "qa-list.schema.json",
|
|
25835
|
+
arrayKey: "qa",
|
|
25836
|
+
codeRe: /^QA-(\d+)$/,
|
|
25837
|
+
prefix: "QA"
|
|
24735
25838
|
}
|
|
24736
25839
|
};
|
|
24737
25840
|
var DETAIL_MD_BASENAME_FOR_LIST_KIND = {
|
|
24738
25841
|
feature: /^FE-\d+-.+\.md$/i,
|
|
24739
25842
|
experience: /^XP-\d+-.+\.md$/i,
|
|
24740
25843
|
service: /^SV-\d+-.+\.md$/i,
|
|
24741
|
-
data_model: /^DM-\d+-.+\.md$/i
|
|
25844
|
+
data_model: /^DM-\d+-.+\.md$/i,
|
|
25845
|
+
infrastructure: /^IN-\d+-.+\.md$/i,
|
|
25846
|
+
qa: /^QA-\d+-.+\.md$/i
|
|
24742
25847
|
};
|
|
24743
25848
|
var LIST_STEP_HINT = {
|
|
24744
25849
|
feature: "listFeatures",
|
|
24745
25850
|
experience: "listExperiences",
|
|
24746
25851
|
service: "listServices",
|
|
24747
|
-
data_model: "listDataModel"
|
|
25852
|
+
data_model: "listDataModel",
|
|
25853
|
+
infrastructure: "listInfrastructure",
|
|
25854
|
+
qa: "listQa"
|
|
24748
25855
|
};
|
|
24749
25856
|
async function applyCoordinationListTriageMerge(input) {
|
|
24750
25857
|
const cfg = LIST_MERGE_CFG[input.listKind];
|
|
24751
|
-
const listPath =
|
|
24752
|
-
const schemaPath =
|
|
25858
|
+
const listPath = path43.join(input.contextDirAbs, cfg.listBasename);
|
|
25859
|
+
const schemaPath = path43.join(resolveContextListSchemasDir(), cfg.schemaBasename);
|
|
24753
25860
|
if (!fs45.existsSync(listPath)) {
|
|
24754
25861
|
return {
|
|
24755
25862
|
ok: false,
|
|
@@ -24853,10 +25960,10 @@ async function applyCoordinationListTriageMerge(input) {
|
|
|
24853
25960
|
}
|
|
24854
25961
|
async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, workspaceLabel) {
|
|
24855
25962
|
const outAbs = stagingPathForTarget(contextDirAbs, "classifier", targetFilePathPosix);
|
|
24856
|
-
fs45.mkdirSync(
|
|
24857
|
-
const runDir =
|
|
25963
|
+
fs45.mkdirSync(path43.dirname(outAbs), { recursive: true });
|
|
25964
|
+
const runDir = path43.join(common.worktreeRoot, ".opencode", "_run");
|
|
24858
25965
|
fs45.mkdirSync(runDir, { recursive: true });
|
|
24859
|
-
const outputBasename =
|
|
25966
|
+
const outputBasename = path43.basename(outAbs);
|
|
24860
25967
|
const listTaskDescription = [
|
|
24861
25968
|
`Target file (repo-relative, POSIX): **${targetFilePathPosix}**`,
|
|
24862
25969
|
`Workspace label hint: **${workspaceLabel}**.`,
|
|
@@ -24892,7 +25999,7 @@ async function runClassifierAgent(common, contextDirAbs, targetFilePathPosix, wo
|
|
|
24892
25999
|
parentContextBlock: "",
|
|
24893
26000
|
...repairAppendix ? { repairAppendix } : {}
|
|
24894
26001
|
});
|
|
24895
|
-
const promptPath =
|
|
26002
|
+
const promptPath = path43.join(runDir, `zero-ref-classify-a${attempt}-${Date.now()}.prompt.txt`);
|
|
24896
26003
|
fs45.writeFileSync(promptPath, body, "utf-8");
|
|
24897
26004
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
24898
26005
|
promptFile: promptPath,
|
|
@@ -25020,13 +26127,25 @@ var TRIAGE_SCOPE_META = {
|
|
|
25020
26127
|
codeExample: "DM-01",
|
|
25021
26128
|
codeKind: "DM-* (**entities**)",
|
|
25022
26129
|
agentLabel: "data_model"
|
|
26130
|
+
},
|
|
26131
|
+
infrastructure: {
|
|
26132
|
+
listFile: "infrastructure-list.json",
|
|
26133
|
+
codeExample: "IN-01",
|
|
26134
|
+
codeKind: "IN-*",
|
|
26135
|
+
agentLabel: "infrastructure"
|
|
26136
|
+
},
|
|
26137
|
+
qa: {
|
|
26138
|
+
listFile: "qa-list.json",
|
|
26139
|
+
codeExample: "QA-01",
|
|
26140
|
+
codeKind: "QA-*",
|
|
26141
|
+
agentLabel: "qa"
|
|
25023
26142
|
}
|
|
25024
26143
|
};
|
|
25025
26144
|
async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPosix, routingSummary, which) {
|
|
25026
26145
|
const mdBasename = which === "project" ? "project.md" : "architecture.md";
|
|
25027
|
-
const mdAbs =
|
|
26146
|
+
const mdAbs = path43.join(contextDirAbs, mdBasename);
|
|
25028
26147
|
const agentStem = which === "project" ? ZERO_REF_ADD_REF_PROJECT_AGENT_STEM : ZERO_REF_ADD_REF_ARCH_AGENT_STEM;
|
|
25029
|
-
const runDir =
|
|
26148
|
+
const runDir = path43.join(common.worktreeRoot, ".opencode", "_run");
|
|
25030
26149
|
fs45.mkdirSync(runDir, { recursive: true });
|
|
25031
26150
|
const lines = [
|
|
25032
26151
|
`# SRS-30 \u2014 Add reference to ${mdBasename}`,
|
|
@@ -25042,7 +26161,7 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
|
|
|
25042
26161
|
`- If the file is short, \`${targetFilePathPosix}:1-<lastLine>\` is acceptable.`,
|
|
25043
26162
|
`- Do not remove unrelated content; append or extend the most appropriate section.`
|
|
25044
26163
|
];
|
|
25045
|
-
const promptPath =
|
|
26164
|
+
const promptPath = path43.join(runDir, `zero-ref-md-${which}-${Date.now()}.prompt.txt`);
|
|
25046
26165
|
fs45.writeFileSync(promptPath, lines.join("\n"), "utf-8");
|
|
25047
26166
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
25048
26167
|
promptFile: promptPath,
|
|
@@ -25070,10 +26189,10 @@ async function runMarkdownReferenceAgent(common, contextDirAbs, targetFilePathPo
|
|
|
25070
26189
|
async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathPosix, routingSummary, workspaceLabel, triageScope) {
|
|
25071
26190
|
const meta = TRIAGE_SCOPE_META[triageScope];
|
|
25072
26191
|
const outAbs = stagingPathForTarget(contextDirAbs, "triage", targetFilePathPosix);
|
|
25073
|
-
fs45.mkdirSync(
|
|
25074
|
-
const runDir =
|
|
26192
|
+
fs45.mkdirSync(path43.dirname(outAbs), { recursive: true });
|
|
26193
|
+
const runDir = path43.join(common.worktreeRoot, ".opencode", "_run");
|
|
25075
26194
|
fs45.mkdirSync(runDir, { recursive: true });
|
|
25076
|
-
const outputBasename =
|
|
26195
|
+
const outputBasename = path43.basename(outAbs);
|
|
25077
26196
|
const listTaskDescription = [
|
|
25078
26197
|
`Target file: **${targetFilePathPosix}** (${workspaceLabel})`,
|
|
25079
26198
|
"**Classifier summary:**",
|
|
@@ -25103,7 +26222,7 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
25103
26222
|
parentContextBlock: "",
|
|
25104
26223
|
...repairAppendix ? { repairAppendix } : {}
|
|
25105
26224
|
});
|
|
25106
|
-
const promptPath =
|
|
26225
|
+
const promptPath = path43.join(runDir, `zero-ref-triage-a${attempt}-${Date.now()}.prompt.txt`);
|
|
25107
26226
|
fs45.writeFileSync(promptPath, body, "utf-8");
|
|
25108
26227
|
const argv = expandArgvTemplate4(common.argvTemplate, {
|
|
25109
26228
|
promptFile: promptPath,
|
|
@@ -25218,8 +26337,8 @@ async function runCoordinationTriageAgent(common, contextDirAbs, targetFilePathP
|
|
|
25218
26337
|
return { ok: false, message: lastFailureMessage, stagingPath: outAbs };
|
|
25219
26338
|
}
|
|
25220
26339
|
async function runOneUnreferencedFilePipeline(p) {
|
|
25221
|
-
const routingAbs =
|
|
25222
|
-
const triageAbs =
|
|
26340
|
+
const routingAbs = path43.join(p.contextDirAbs, ZERO_REF_ROUTING_BASENAME);
|
|
26341
|
+
const triageAbs = path43.join(p.contextDirAbs, ZERO_REF_TRIAGE_BASENAME);
|
|
25223
26342
|
const key = p.targetFilePathPosix;
|
|
25224
26343
|
const cr = await runClassifierAgent(p, p.contextDirAbs, key, p.workspaceLabel);
|
|
25225
26344
|
if (!cr.ok) {
|
|
@@ -25243,7 +26362,7 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
25243
26362
|
if (!s.ok) {
|
|
25244
26363
|
throw new Error(s.errors.join("; "));
|
|
25245
26364
|
}
|
|
25246
|
-
fs45.mkdirSync(
|
|
26365
|
+
fs45.mkdirSync(path43.dirname(routingAbs), { recursive: true });
|
|
25247
26366
|
fs45.writeFileSync(routingAbs, s.json, "utf-8");
|
|
25248
26367
|
});
|
|
25249
26368
|
const routing = stagingParsed.routing;
|
|
@@ -25292,7 +26411,7 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
25292
26411
|
if (!s.ok) {
|
|
25293
26412
|
throw new Error(s.errors.join("; "));
|
|
25294
26413
|
}
|
|
25295
|
-
fs45.mkdirSync(
|
|
26414
|
+
fs45.mkdirSync(path43.dirname(triageAbs), { recursive: true });
|
|
25296
26415
|
fs45.writeFileSync(triageAbs, s.json, "utf-8");
|
|
25297
26416
|
});
|
|
25298
26417
|
const decision = triageParsed.decision;
|
|
@@ -25320,11 +26439,11 @@ async function runOneUnreferencedFilePipeline(p) {
|
|
|
25320
26439
|
return { ok: true, message: `Triage ${decision}.` };
|
|
25321
26440
|
}
|
|
25322
26441
|
async function runRemediationPipelineZeroRefPass(p) {
|
|
25323
|
-
const contextDirAbs =
|
|
26442
|
+
const contextDirAbs = path43.join(p.worktreeRoot, ".gluecharm", "context");
|
|
25324
26443
|
const covRoot = p.coverageRepositoryRootAbs ?? p.workspaceRootAbs;
|
|
25325
26444
|
const cov = readNonReferencedFilesFromRepositoryRoot(covRoot);
|
|
25326
26445
|
const coverageAt = cov.ok ? cov.generatedAt : void 0;
|
|
25327
|
-
const workspaceLabel =
|
|
26446
|
+
const workspaceLabel = path43.basename(p.worktreeRoot);
|
|
25328
26447
|
const routingMutex = new AsyncMutex();
|
|
25329
26448
|
const triageMutex = new AsyncMutex();
|
|
25330
26449
|
const paths = [...p.paths];
|
|
@@ -25386,7 +26505,7 @@ async function runRemediationPipelineZeroRefPass(p) {
|
|
|
25386
26505
|
|
|
25387
26506
|
// src/pipelines/coverage/coverageExecutionReport.ts
|
|
25388
26507
|
var fs46 = __toESM(require("fs"));
|
|
25389
|
-
var
|
|
26508
|
+
var path44 = __toESM(require("path"));
|
|
25390
26509
|
var REFERENCE_COVERAGE_EXECUTION_REPORT_BASENAME = "reference-coverage-execution-report.md";
|
|
25391
26510
|
function inlineMdText(s) {
|
|
25392
26511
|
const t = s.replace(/\r\n/g, "\n").replace(/\n/g, " ").trim();
|
|
@@ -25527,10 +26646,10 @@ async function runCoverageExecutionReport(p) {
|
|
|
25527
26646
|
if (p.abortSignal?.aborted) {
|
|
25528
26647
|
return { ok: false, error: "Stopped.", cancelled: true };
|
|
25529
26648
|
}
|
|
25530
|
-
const contextDirAbs =
|
|
25531
|
-
const coverageAbs =
|
|
25532
|
-
const routingAbs =
|
|
25533
|
-
const outAbs =
|
|
26649
|
+
const contextDirAbs = path44.join(p.repositoryRootAbs, ".gluecharm", "context");
|
|
26650
|
+
const coverageAbs = path44.join(contextDirAbs, "coverage-reference-validation.json");
|
|
26651
|
+
const routingAbs = path44.join(contextDirAbs, "zero-reference-routing.json");
|
|
26652
|
+
const outAbs = path44.join(contextDirAbs, REFERENCE_COVERAGE_EXECUTION_REPORT_BASENAME);
|
|
25534
26653
|
const cov = readAndValidateCoverageReferenceValidationFile(coverageAbs);
|
|
25535
26654
|
if (!cov.ok) {
|
|
25536
26655
|
return { ok: false, error: `Coverage JSON: ${cov.errors.join("; ")}` };
|
|
@@ -25557,7 +26676,7 @@ async function runCoverageExecutionReport(p) {
|
|
|
25557
26676
|
previous = void 0;
|
|
25558
26677
|
}
|
|
25559
26678
|
try {
|
|
25560
|
-
fs46.mkdirSync(
|
|
26679
|
+
fs46.mkdirSync(path44.dirname(outAbs), { recursive: true });
|
|
25561
26680
|
fs46.writeFileSync(outAbs, md, "utf-8");
|
|
25562
26681
|
} catch (e) {
|
|
25563
26682
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -25575,7 +26694,7 @@ async function runCoverageExecutionReport(p) {
|
|
|
25575
26694
|
|
|
25576
26695
|
// src/gluecharm/minimalGluecharmLayout.ts
|
|
25577
26696
|
var fs47 = __toESM(require("node:fs"));
|
|
25578
|
-
var
|
|
26697
|
+
var path45 = __toESM(require("node:path"));
|
|
25579
26698
|
var MINIMAL_GLUECHARM_RELATIVE_DIRS = [
|
|
25580
26699
|
[".gluecharm", "docs", "srs"],
|
|
25581
26700
|
[".gluecharm", "content"],
|
|
@@ -25583,9 +26702,9 @@ var MINIMAL_GLUECHARM_RELATIVE_DIRS = [
|
|
|
25583
26702
|
[".gluecharm", "context"]
|
|
25584
26703
|
];
|
|
25585
26704
|
function ensureMinimalGluecharmLayoutNode(repoRootAbs) {
|
|
25586
|
-
const root =
|
|
26705
|
+
const root = path45.resolve(repoRootAbs);
|
|
25587
26706
|
for (const segments of MINIMAL_GLUECHARM_RELATIVE_DIRS) {
|
|
25588
|
-
const dir =
|
|
26707
|
+
const dir = path45.join(root, ...segments);
|
|
25589
26708
|
try {
|
|
25590
26709
|
fs47.mkdirSync(dir, { recursive: true });
|
|
25591
26710
|
} catch (e) {
|
|
@@ -25720,7 +26839,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25720
26839
|
if (!layout.ok) {
|
|
25721
26840
|
return { ok: false, error: layout.error };
|
|
25722
26841
|
}
|
|
25723
|
-
const ctxDir =
|
|
26842
|
+
const ctxDir = path46.join(ar, ".gluecharm", "context");
|
|
25724
26843
|
const snap = readArtefactRunSnapshot(storageContext);
|
|
25725
26844
|
const rows = listMissingWorkstations(ctxDir, ar, snap);
|
|
25726
26845
|
if (rows.length === 0) {
|
|
@@ -25734,7 +26853,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25734
26853
|
storageContext,
|
|
25735
26854
|
repositoryRoot: repoRoot,
|
|
25736
26855
|
worktreeRoot: ar,
|
|
25737
|
-
workspaceLabel:
|
|
26856
|
+
workspaceLabel: path46.basename(ar),
|
|
25738
26857
|
oc: {
|
|
25739
26858
|
...oc,
|
|
25740
26859
|
aceEnabled: getAceAnalysisEnabledForCheckout(ar),
|
|
@@ -25762,7 +26881,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25762
26881
|
}
|
|
25763
26882
|
try {
|
|
25764
26883
|
await startPipelineRun(storageContext, repoRoot);
|
|
25765
|
-
const folderName =
|
|
26884
|
+
const folderName = path46.basename(repoRoot);
|
|
25766
26885
|
const oc = buildOpenCodeOptions(handle.path);
|
|
25767
26886
|
const result = await runSynthesisPipelineDrainFromPreparedWorktree(
|
|
25768
26887
|
storageContext,
|
|
@@ -25819,7 +26938,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25819
26938
|
if (!ar) {
|
|
25820
26939
|
return 0;
|
|
25821
26940
|
}
|
|
25822
|
-
const ctxDir =
|
|
26941
|
+
const ctxDir = path46.join(ar, ".gluecharm", "context");
|
|
25823
26942
|
const snap = readArtefactRunSnapshot(storageContext);
|
|
25824
26943
|
return listMissingWorkstations(ctxDir, ar, snap).length;
|
|
25825
26944
|
};
|
|
@@ -25832,7 +26951,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25832
26951
|
if (!layout.ok) {
|
|
25833
26952
|
return { ok: false, message: layout.error };
|
|
25834
26953
|
}
|
|
25835
|
-
const contextDir2 =
|
|
26954
|
+
const contextDir2 = path46.join(ar, ".gluecharm", "context");
|
|
25836
26955
|
log(`[factory] reference coverage (worktree) \u2014 ${ar}`);
|
|
25837
26956
|
const res = runCoveragePipeline({
|
|
25838
26957
|
repositoryRootAbs: ar,
|
|
@@ -25895,7 +27014,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25895
27014
|
...remaining ? { remainingRemediationFailures: remaining } : {}
|
|
25896
27015
|
});
|
|
25897
27016
|
if (res.ok) {
|
|
25898
|
-
return { ok: true, message: `Report: ${
|
|
27017
|
+
return { ok: true, message: `Report: ${path46.basename(res.outputAbsolutePath)}` };
|
|
25899
27018
|
}
|
|
25900
27019
|
if (res.cancelled) {
|
|
25901
27020
|
return { ok: false, cancelled: true, message: "Report generation stopped." };
|
|
@@ -25911,7 +27030,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25911
27030
|
if (!lmLayout.ok) {
|
|
25912
27031
|
return { ok: false, message: lmLayout.error };
|
|
25913
27032
|
}
|
|
25914
|
-
const contextDir2 =
|
|
27033
|
+
const contextDir2 = path46.join(snap.adHocWorktreePath, ".gluecharm", "context");
|
|
25915
27034
|
const linkGraph = runLinkMappingPipeline(contextDir2, { log });
|
|
25916
27035
|
if (!linkGraph.ok) {
|
|
25917
27036
|
return { ok: false, message: linkGraph.error };
|
|
@@ -25927,7 +27046,7 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25927
27046
|
if (!idxLayout.ok) {
|
|
25928
27047
|
return { ok: false, message: idxLayout.error };
|
|
25929
27048
|
}
|
|
25930
|
-
const contextDir2 =
|
|
27049
|
+
const contextDir2 = path46.join(snap.adHocWorktreePath, ".gluecharm", "context");
|
|
25931
27050
|
try {
|
|
25932
27051
|
writeIndexApplicationContext(contextDir2, void 0, {
|
|
25933
27052
|
sourceBranchAtWorktreeCreation: snap.adHocSourceBranchAtCreation
|
|
@@ -25983,13 +27102,13 @@ function buildFactoryDepsHeadless(input) {
|
|
|
25983
27102
|
},
|
|
25984
27103
|
runPrepareAnalysisWorktree: async (resume) => {
|
|
25985
27104
|
if (resume) {
|
|
25986
|
-
if (adHocWorktree && fs48.existsSync(
|
|
27105
|
+
if (adHocWorktree && fs48.existsSync(path46.join(adHocWorktree.path, ".git"))) {
|
|
25987
27106
|
return { ok: true };
|
|
25988
27107
|
}
|
|
25989
27108
|
const snap = readAnalysisWorkspaceSnapshot(storageContext);
|
|
25990
27109
|
const wtPath = snap?.adHocWorktreePath?.trim();
|
|
25991
27110
|
const repo = snap?.adHocRepositoryRoot?.trim() || repoRoot;
|
|
25992
|
-
if (wtPath && fs48.existsSync(
|
|
27111
|
+
if (wtPath && fs48.existsSync(path46.join(wtPath, ".git"))) {
|
|
25993
27112
|
adHocWorktree = resolveAnalysisCheckoutHandle(wtPath, repo);
|
|
25994
27113
|
macroSourceBranch = snap?.adHocSourceBranchAtCreation;
|
|
25995
27114
|
macroFinalize = () => {
|
|
@@ -26207,11 +27326,11 @@ function stderrLinesForFactoryFailures(failures, exitCode) {
|
|
|
26207
27326
|
}
|
|
26208
27327
|
|
|
26209
27328
|
// src/factory/updateContext/runUpdateContextFactory.ts
|
|
26210
|
-
var
|
|
27329
|
+
var path51 = __toESM(require("node:path"));
|
|
26211
27330
|
|
|
26212
27331
|
// src/factory/updateContext/updateContextBaseline.ts
|
|
26213
27332
|
var fs49 = __toESM(require("node:fs"));
|
|
26214
|
-
var
|
|
27333
|
+
var path47 = __toESM(require("node:path"));
|
|
26215
27334
|
function isValidIso(s) {
|
|
26216
27335
|
const t = Date.parse(s);
|
|
26217
27336
|
return Number.isFinite(t);
|
|
@@ -26226,7 +27345,7 @@ function maxMtimeRegularFilesUnderDir(dirAbs) {
|
|
|
26226
27345
|
return;
|
|
26227
27346
|
}
|
|
26228
27347
|
for (const e of entries) {
|
|
26229
|
-
const p =
|
|
27348
|
+
const p = path47.join(d, e.name);
|
|
26230
27349
|
if (e.isDirectory()) {
|
|
26231
27350
|
walk(p);
|
|
26232
27351
|
} else if (e.isFile()) {
|
|
@@ -26252,7 +27371,7 @@ function resolveUpdateContextBaseline(repoRootAbs, repoConfig) {
|
|
|
26252
27371
|
if (last.length > 0 && isValidIso(last)) {
|
|
26253
27372
|
return { baselineIsoUtc: new Date(last).toISOString(), source: "lastRunAt" };
|
|
26254
27373
|
}
|
|
26255
|
-
const ctxDir =
|
|
27374
|
+
const ctxDir = path47.join(repoRootAbs, ".gluecharm", "context");
|
|
26256
27375
|
if (!fs49.existsSync(ctxDir)) {
|
|
26257
27376
|
return null;
|
|
26258
27377
|
}
|
|
@@ -26277,7 +27396,7 @@ function persistUpdateContextLastRunAt(repoRootAbs, isoUtc) {
|
|
|
26277
27396
|
// src/factory/updateContext/updateContextGitWindow.ts
|
|
26278
27397
|
var import_node_child_process3 = require("node:child_process");
|
|
26279
27398
|
var fs50 = __toESM(require("node:fs"));
|
|
26280
|
-
var
|
|
27399
|
+
var path48 = __toESM(require("node:path"));
|
|
26281
27400
|
var GIT_ENV = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
26282
27401
|
function gitLines(repoRootAbs, args) {
|
|
26283
27402
|
const r = (0, import_node_child_process3.execFileSync)("git", ["-c", "core.quotepath=false", ...args], {
|
|
@@ -26301,8 +27420,8 @@ function parseGitLogIso(line) {
|
|
|
26301
27420
|
return { hash, iso };
|
|
26302
27421
|
}
|
|
26303
27422
|
function discoverCommitWindowAndTouchedPaths(repoRootAbs, baselineIsoUtc) {
|
|
26304
|
-
const root =
|
|
26305
|
-
if (!fs50.existsSync(
|
|
27423
|
+
const root = path48.resolve(repoRootAbs);
|
|
27424
|
+
if (!fs50.existsSync(path48.join(root, ".git"))) {
|
|
26306
27425
|
return { ok: false, error: "Not a git repository (missing .git)." };
|
|
26307
27426
|
}
|
|
26308
27427
|
const baselineMs = Date.parse(baselineIsoUtc);
|
|
@@ -26361,11 +27480,11 @@ function discoverCommitWindowAndTouchedPaths(repoRootAbs, baselineIsoUtc) {
|
|
|
26361
27480
|
};
|
|
26362
27481
|
}
|
|
26363
27482
|
function filterPathsExistingInWorktree(worktreeRootAbs, pathsPosix) {
|
|
26364
|
-
const root =
|
|
27483
|
+
const root = path48.resolve(worktreeRootAbs);
|
|
26365
27484
|
const out = [];
|
|
26366
27485
|
for (const p of pathsPosix) {
|
|
26367
27486
|
const rel = p.replace(/\\/g, "/");
|
|
26368
|
-
const abs =
|
|
27487
|
+
const abs = path48.join(root, ...rel.split("/"));
|
|
26369
27488
|
try {
|
|
26370
27489
|
if (fs50.existsSync(abs) && fs50.statSync(abs).isFile()) {
|
|
26371
27490
|
out.push(rel);
|
|
@@ -26378,7 +27497,7 @@ function filterPathsExistingInWorktree(worktreeRootAbs, pathsPosix) {
|
|
|
26378
27497
|
|
|
26379
27498
|
// src/factory/updateContext/updateContextReport.ts
|
|
26380
27499
|
var fs51 = __toESM(require("node:fs"));
|
|
26381
|
-
var
|
|
27500
|
+
var path49 = __toESM(require("node:path"));
|
|
26382
27501
|
var CHANGES_SINCE_DATE_BASENAME = "changes-since-date.md";
|
|
26383
27502
|
function renderChangesSinceDateMarkdown(p) {
|
|
26384
27503
|
const lines = [
|
|
@@ -26420,7 +27539,7 @@ function renderChangesSinceDateMarkdown(p) {
|
|
|
26420
27539
|
function writeChangesSinceDateReport(contextDirAbs, body) {
|
|
26421
27540
|
try {
|
|
26422
27541
|
fs51.mkdirSync(contextDirAbs, { recursive: true });
|
|
26423
|
-
const target =
|
|
27542
|
+
const target = path49.join(contextDirAbs, CHANGES_SINCE_DATE_BASENAME);
|
|
26424
27543
|
fs51.writeFileSync(target, body, "utf-8");
|
|
26425
27544
|
return { ok: true };
|
|
26426
27545
|
} catch (e) {
|
|
@@ -26430,7 +27549,7 @@ function writeChangesSinceDateReport(contextDirAbs, body) {
|
|
|
26430
27549
|
|
|
26431
27550
|
// src/factory/updateContext/updateContextSeedCheck.ts
|
|
26432
27551
|
var fs52 = __toESM(require("node:fs"));
|
|
26433
|
-
var
|
|
27552
|
+
var path50 = __toESM(require("node:path"));
|
|
26434
27553
|
var INDEX_BASENAME = "index-application-context.json";
|
|
26435
27554
|
var CHANGES_REPORT = "changes-since-date.md";
|
|
26436
27555
|
function tryParseJsonFile(abs) {
|
|
@@ -26446,7 +27565,7 @@ function isWorktreeContextSeeded(contextDirAbs) {
|
|
|
26446
27565
|
if (!fs52.existsSync(contextDirAbs)) {
|
|
26447
27566
|
return false;
|
|
26448
27567
|
}
|
|
26449
|
-
const indexAbs =
|
|
27568
|
+
const indexAbs = path50.join(contextDirAbs, INDEX_BASENAME);
|
|
26450
27569
|
if (fs52.existsSync(indexAbs) && fs52.statSync(indexAbs).isFile() && tryParseJsonFile(indexAbs)) {
|
|
26451
27570
|
return true;
|
|
26452
27571
|
}
|
|
@@ -26464,7 +27583,7 @@ function isWorktreeContextSeeded(contextDirAbs) {
|
|
|
26464
27583
|
if (!name.endsWith(".md") && !name.endsWith(".json")) {
|
|
26465
27584
|
continue;
|
|
26466
27585
|
}
|
|
26467
|
-
const p =
|
|
27586
|
+
const p = path50.join(contextDirAbs, name);
|
|
26468
27587
|
try {
|
|
26469
27588
|
if (fs52.statSync(p).isFile()) {
|
|
26470
27589
|
distinct.add(name);
|
|
@@ -26478,7 +27597,7 @@ function isWorktreeContextSeeded(contextDirAbs) {
|
|
|
26478
27597
|
// src/factory/updateContext/runUpdateContextFactory.ts
|
|
26479
27598
|
var REMEDIATION_CHUNK_MAX = 40;
|
|
26480
27599
|
function contextDirUnderRoot(wtRoot) {
|
|
26481
|
-
return
|
|
27600
|
+
return path51.join(wtRoot, ".gluecharm", "context");
|
|
26482
27601
|
}
|
|
26483
27602
|
async function runUpdateContextFactory(deps) {
|
|
26484
27603
|
const inPlace = deps.inPlace === true;
|
|
@@ -26809,11 +27928,11 @@ async function runUpdateContextFactory(deps) {
|
|
|
26809
27928
|
|
|
26810
27929
|
// src/factory/contextDrift/runContextDriftFactory.ts
|
|
26811
27930
|
var fs58 = __toESM(require("node:fs"));
|
|
26812
|
-
var
|
|
27931
|
+
var path56 = __toESM(require("node:path"));
|
|
26813
27932
|
|
|
26814
27933
|
// src/factory/contextDrift/contextDriftManifest.ts
|
|
26815
27934
|
var fs53 = __toESM(require("node:fs"));
|
|
26816
|
-
var
|
|
27935
|
+
var path52 = __toESM(require("node:path"));
|
|
26817
27936
|
var MAX_REFERENCE_BYTES = 256 * 1024;
|
|
26818
27937
|
var MAX_EVIDENCE_FILES = 300;
|
|
26819
27938
|
var MAX_EVIDENCE_READ = 512 * 1024;
|
|
@@ -26833,16 +27952,16 @@ function collectEvidencePaths(repoRoot) {
|
|
|
26833
27952
|
const out = [];
|
|
26834
27953
|
const roots = ["src", "test", "tests", "packages", ".gluecharm", "scripts"];
|
|
26835
27954
|
for (const rel of roots) {
|
|
26836
|
-
const abs =
|
|
27955
|
+
const abs = path52.join(repoRoot, rel);
|
|
26837
27956
|
if (!fs53.existsSync(abs)) {
|
|
26838
27957
|
continue;
|
|
26839
27958
|
}
|
|
26840
27959
|
walkFiles(abs, repoRoot, out, 0);
|
|
26841
27960
|
}
|
|
26842
27961
|
for (const leaf of ["package.json", "tsconfig.json"]) {
|
|
26843
|
-
const abs =
|
|
27962
|
+
const abs = path52.join(repoRoot, leaf);
|
|
26844
27963
|
if (fs53.existsSync(abs) && fs53.statSync(abs).isFile()) {
|
|
26845
|
-
const r =
|
|
27964
|
+
const r = path52.relative(repoRoot, abs).split(path52.sep).join("/");
|
|
26846
27965
|
out.push(r);
|
|
26847
27966
|
}
|
|
26848
27967
|
}
|
|
@@ -26867,13 +27986,13 @@ function walkFiles(dir, repoRoot, out, depth) {
|
|
|
26867
27986
|
if (e.name === "node_modules" || e.name === ".git" || e.name === "dist" || e.name === "out") {
|
|
26868
27987
|
continue;
|
|
26869
27988
|
}
|
|
26870
|
-
const full =
|
|
27989
|
+
const full = path52.join(dir, e.name);
|
|
26871
27990
|
if (e.isDirectory()) {
|
|
26872
27991
|
walkFiles(full, repoRoot, out, depth + 1);
|
|
26873
27992
|
} else if (e.isFile()) {
|
|
26874
|
-
const ext =
|
|
27993
|
+
const ext = path52.extname(e.name).toLowerCase();
|
|
26875
27994
|
if ([".ts", ".tsx", ".js", ".mjs", ".cjs", ".json", ".md", ".yaml", ".yml"].includes(ext) || e.name === "Dockerfile") {
|
|
26876
|
-
const rel =
|
|
27995
|
+
const rel = path52.relative(repoRoot, full).split(path52.sep).join("/");
|
|
26877
27996
|
out.push(rel);
|
|
26878
27997
|
}
|
|
26879
27998
|
}
|
|
@@ -26883,7 +28002,7 @@ function buildComparisonManifest(args) {
|
|
|
26883
28002
|
const references = [];
|
|
26884
28003
|
let referenceTruncated = false;
|
|
26885
28004
|
for (const abs of args.bundleAbsFiles) {
|
|
26886
|
-
const rel =
|
|
28005
|
+
const rel = path52.relative(args.worktreeRoot, abs).split(path52.sep).join("/");
|
|
26887
28006
|
const { text, truncated } = readFileLimited(abs, MAX_REFERENCE_BYTES);
|
|
26888
28007
|
references.push({ path: rel, content: text, truncated });
|
|
26889
28008
|
if (truncated) {
|
|
@@ -26895,7 +28014,7 @@ function buildComparisonManifest(args) {
|
|
|
26895
28014
|
const omitted = Math.max(0, allEvidence.length - evidencePathsTrimmed.length);
|
|
26896
28015
|
const evidenceFiles = [];
|
|
26897
28016
|
for (const rel of evidencePathsTrimmed) {
|
|
26898
|
-
const abs =
|
|
28017
|
+
const abs = path52.join(args.worktreeRoot, ...rel.split("/"));
|
|
26899
28018
|
const st = fs53.existsSync(abs) ? fs53.statSync(abs) : null;
|
|
26900
28019
|
const size = st && st.isFile() ? st.size : 0;
|
|
26901
28020
|
const { text, truncated } = readFileLimited(abs, MAX_EVIDENCE_READ);
|
|
@@ -26906,7 +28025,7 @@ function buildComparisonManifest(args) {
|
|
|
26906
28025
|
}
|
|
26907
28026
|
return {
|
|
26908
28027
|
runDate: args.runDate,
|
|
26909
|
-
referenceRelPaths: args.bundleAbsFiles.map((a) =>
|
|
28028
|
+
referenceRelPaths: args.bundleAbsFiles.map((a) => path52.relative(args.worktreeRoot, a).split(path52.sep).join("/")),
|
|
26910
28029
|
references,
|
|
26911
28030
|
evidenceFiles,
|
|
26912
28031
|
evidencePathsOnly: [],
|
|
@@ -26919,7 +28038,7 @@ function buildComparisonManifest(args) {
|
|
|
26919
28038
|
|
|
26920
28039
|
// src/factory/contextDrift/contextDriftAgent.ts
|
|
26921
28040
|
var fs54 = __toESM(require("node:fs"));
|
|
26922
|
-
var
|
|
28041
|
+
var path53 = __toESM(require("node:path"));
|
|
26923
28042
|
|
|
26924
28043
|
// src/factory/contextDrift/contextDriftPayload.ts
|
|
26925
28044
|
function isNonEmptyString2(v) {
|
|
@@ -27064,16 +28183,16 @@ function buildDriftPrompt(args) {
|
|
|
27064
28183
|
].join("\n");
|
|
27065
28184
|
}
|
|
27066
28185
|
async function runDriftComparisonOpenCode(args) {
|
|
27067
|
-
const runDir =
|
|
28186
|
+
const runDir = path53.join(args.worktreeRoot, ".opencode", "_run");
|
|
27068
28187
|
fs54.mkdirSync(runDir, { recursive: true });
|
|
27069
|
-
const manifestPath =
|
|
27070
|
-
const outputPath =
|
|
28188
|
+
const manifestPath = path53.join(runDir, "context-drift-manifest.json");
|
|
28189
|
+
const outputPath = path53.join(runDir, "context-drift-payload.json");
|
|
27071
28190
|
fs54.writeFileSync(manifestPath, `${JSON.stringify(args.manifestObject, null, 2)}
|
|
27072
28191
|
`, "utf8");
|
|
27073
28192
|
if (fs54.existsSync(outputPath)) {
|
|
27074
28193
|
fs54.unlinkSync(outputPath);
|
|
27075
28194
|
}
|
|
27076
|
-
const promptPath =
|
|
28195
|
+
const promptPath = path53.join(runDir, `context-drift-${Date.now()}.prompt.txt`);
|
|
27077
28196
|
fs54.writeFileSync(
|
|
27078
28197
|
promptPath,
|
|
27079
28198
|
buildDriftPrompt({
|
|
@@ -27091,7 +28210,7 @@ async function runDriftComparisonOpenCode(args) {
|
|
|
27091
28210
|
});
|
|
27092
28211
|
const title = buildOpenCodeSessionTitle({
|
|
27093
28212
|
runId: "context-drift",
|
|
27094
|
-
workItemId:
|
|
28213
|
+
workItemId: path53.basename(args.worktreeRoot).slice(0, 24) || "wt",
|
|
27095
28214
|
stepLabel: "context-drift"
|
|
27096
28215
|
});
|
|
27097
28216
|
const argv = injectPrimaryOpenCodeSessionArgv(expanded, title);
|
|
@@ -27134,8 +28253,8 @@ async function runDriftComparisonOpenCode(args) {
|
|
|
27134
28253
|
// src/factory/contextDrift/contextDriftPaths.ts
|
|
27135
28254
|
var crypto2 = __toESM(require("node:crypto"));
|
|
27136
28255
|
var fs55 = __toESM(require("node:fs"));
|
|
27137
|
-
var
|
|
27138
|
-
var DRIFT_CONTEXT_SUBDIR =
|
|
28256
|
+
var path54 = __toESM(require("node:path"));
|
|
28257
|
+
var DRIFT_CONTEXT_SUBDIR = path54.join(".gluecharm", "context", "drift");
|
|
27139
28258
|
function sanitizeSlug(raw) {
|
|
27140
28259
|
const s = raw.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
27141
28260
|
return s.length > 0 ? s : "drift";
|
|
@@ -27144,9 +28263,9 @@ function utcDateString(d) {
|
|
|
27144
28263
|
return d.toISOString().slice(0, 10);
|
|
27145
28264
|
}
|
|
27146
28265
|
function resolveInsideRepo(repoRootAbs, userPath) {
|
|
27147
|
-
const abs =
|
|
27148
|
-
const rel =
|
|
27149
|
-
if (rel.startsWith("..") ||
|
|
28266
|
+
const abs = path54.isAbsolute(userPath) ? path54.normalize(userPath) : path54.resolve(repoRootAbs, userPath);
|
|
28267
|
+
const rel = path54.relative(repoRootAbs, abs);
|
|
28268
|
+
if (rel.startsWith("..") || path54.isAbsolute(rel)) {
|
|
27150
28269
|
return { ok: false };
|
|
27151
28270
|
}
|
|
27152
28271
|
return { ok: true, abs };
|
|
@@ -27156,7 +28275,7 @@ function computeSlug(args) {
|
|
|
27156
28275
|
return sanitizeSlug(args.label.trim());
|
|
27157
28276
|
}
|
|
27158
28277
|
const r = resolveInsideRepo(args.repoRootAbs, args.referencePath);
|
|
27159
|
-
const base = r.ok ?
|
|
28278
|
+
const base = r.ok ? path54.basename(r.abs) : path54.basename(args.referencePath);
|
|
27160
28279
|
return sanitizeSlug(base);
|
|
27161
28280
|
}
|
|
27162
28281
|
function driftFilename(slug, runDate) {
|
|
@@ -27198,7 +28317,7 @@ function discoverReferenceBundle(worktreeRoot, referenceAbsInWorktree) {
|
|
|
27198
28317
|
return;
|
|
27199
28318
|
}
|
|
27200
28319
|
for (const e of entries) {
|
|
27201
|
-
const full =
|
|
28320
|
+
const full = path54.join(dir, e.name);
|
|
27202
28321
|
if (e.isDirectory()) {
|
|
27203
28322
|
if (e.name === "node_modules" || e.name === ".git") {
|
|
27204
28323
|
continue;
|
|
@@ -27228,7 +28347,7 @@ function pickReferenceRootDocument(args) {
|
|
|
27228
28347
|
}
|
|
27229
28348
|
const dir = args.referenceAbsInWorktree;
|
|
27230
28349
|
for (const name of ["index.md", "README.md"]) {
|
|
27231
|
-
const p =
|
|
28350
|
+
const p = path54.join(dir, name);
|
|
27232
28351
|
if (fs55.existsSync(p) && fs55.statSync(p).isFile()) {
|
|
27233
28352
|
return { ok: true, path: p };
|
|
27234
28353
|
}
|
|
@@ -27239,10 +28358,10 @@ function pickReferenceRootDocument(args) {
|
|
|
27239
28358
|
};
|
|
27240
28359
|
}
|
|
27241
28360
|
function toWorktreeRelative(worktreeRoot, absolute) {
|
|
27242
|
-
return
|
|
28361
|
+
return path54.relative(worktreeRoot, absolute).split(path54.sep).join("/");
|
|
27243
28362
|
}
|
|
27244
28363
|
function toPosixPath(p) {
|
|
27245
|
-
return p.split(
|
|
28364
|
+
return p.split(path54.sep).join("/");
|
|
27246
28365
|
}
|
|
27247
28366
|
|
|
27248
28367
|
// src/factory/contextDrift/contextDriftIndex.ts
|
|
@@ -27285,19 +28404,19 @@ function escapeRe(s) {
|
|
|
27285
28404
|
|
|
27286
28405
|
// src/factory/contextDrift/contextDriftPromote.ts
|
|
27287
28406
|
var fs57 = __toESM(require("node:fs"));
|
|
27288
|
-
var
|
|
28407
|
+
var path55 = __toESM(require("node:path"));
|
|
27289
28408
|
function copyWorktreeFileToWorkspace(args) {
|
|
27290
|
-
const wt =
|
|
27291
|
-
const ws =
|
|
28409
|
+
const wt = path55.resolve(args.worktreeRoot);
|
|
28410
|
+
const ws = path55.resolve(args.workspaceRoot);
|
|
27292
28411
|
if (wt === ws) {
|
|
27293
28412
|
return;
|
|
27294
28413
|
}
|
|
27295
|
-
const src =
|
|
27296
|
-
const dest =
|
|
27297
|
-
if (
|
|
28414
|
+
const src = path55.join(args.worktreeRoot, ...args.relativePosix.split("/"));
|
|
28415
|
+
const dest = path55.join(args.workspaceRoot, ...args.relativePosix.split("/"));
|
|
28416
|
+
if (path55.resolve(src) === path55.resolve(dest)) {
|
|
27298
28417
|
return;
|
|
27299
28418
|
}
|
|
27300
|
-
fs57.mkdirSync(
|
|
28419
|
+
fs57.mkdirSync(path55.dirname(dest), { recursive: true });
|
|
27301
28420
|
fs57.copyFileSync(src, dest);
|
|
27302
28421
|
}
|
|
27303
28422
|
|
|
@@ -27353,7 +28472,7 @@ async function runContextDriftFactory(deps) {
|
|
|
27353
28472
|
ok: true,
|
|
27354
28473
|
code: "DRY_RUN",
|
|
27355
28474
|
...baseMeta,
|
|
27356
|
-
referenceRootDocument: toPosixPath(
|
|
28475
|
+
referenceRootDocument: toPosixPath(path56.relative(deps.repoRootAbs, refAbsWorkspace)) + (fs58.statSync(refAbsWorkspace).isDirectory() ? "/" : ""),
|
|
27357
28476
|
driftReportPath: null,
|
|
27358
28477
|
analysisWorktreeRoot: "",
|
|
27359
28478
|
promoted: false,
|
|
@@ -27410,8 +28529,8 @@ async function runContextDriftFactory(deps) {
|
|
|
27410
28529
|
const handle = prep.handle;
|
|
27411
28530
|
const finalizeWt = prep.finalize;
|
|
27412
28531
|
const wt = handle.path;
|
|
27413
|
-
const refRel =
|
|
27414
|
-
const refAbsWt =
|
|
28532
|
+
const refRel = path56.relative(deps.repoRootAbs, refAbsWorkspace).split(path56.sep).join("/");
|
|
28533
|
+
const refAbsWt = path56.join(wt, ...refRel.split("/"));
|
|
27415
28534
|
try {
|
|
27416
28535
|
materializeOpenCodeAgentsWithAce(deps.agentsDirFs, wt, {
|
|
27417
28536
|
enabled: getAceAnalysisEnabledForCheckout(wt),
|
|
@@ -27450,7 +28569,7 @@ async function runContextDriftFactory(deps) {
|
|
|
27450
28569
|
...baseMeta
|
|
27451
28570
|
};
|
|
27452
28571
|
}
|
|
27453
|
-
const indexWt = indexOverrideAbsWorkspace ?
|
|
28572
|
+
const indexWt = indexOverrideAbsWorkspace ? path56.join(wt, ...path56.relative(deps.repoRootAbs, indexOverrideAbsWorkspace).split(path56.sep)) : void 0;
|
|
27454
28573
|
const rootPick = pickReferenceRootDocument({
|
|
27455
28574
|
referencePathIsFile: fs58.statSync(refAbsWt).isFile(),
|
|
27456
28575
|
referenceAbsInWorktree: refAbsWt,
|
|
@@ -27478,9 +28597,9 @@ async function runContextDriftFactory(deps) {
|
|
|
27478
28597
|
let slug = computeSlug({ label: deps.label, referencePath: deps.referencePathArg, repoRootAbs: deps.repoRootAbs });
|
|
27479
28598
|
slug = maybeDedupeSlug(slug, refRel);
|
|
27480
28599
|
const driftBase = driftFilename(slug, runDate);
|
|
27481
|
-
const driftDirWt =
|
|
28600
|
+
const driftDirWt = path56.join(wt, DRIFT_CONTEXT_SUBDIR);
|
|
27482
28601
|
fs58.mkdirSync(driftDirWt, { recursive: true });
|
|
27483
|
-
const driftAbsWt =
|
|
28602
|
+
const driftAbsWt = path56.join(driftDirWt, driftBase);
|
|
27484
28603
|
let payload;
|
|
27485
28604
|
if (deps.testOnlyFixturePayload) {
|
|
27486
28605
|
payload = deps.testOnlyFixturePayload;
|
|
@@ -27529,7 +28648,7 @@ async function runContextDriftFactory(deps) {
|
|
|
27529
28648
|
...baseMeta
|
|
27530
28649
|
};
|
|
27531
28650
|
}
|
|
27532
|
-
const driftRelFromRootDir =
|
|
28651
|
+
const driftRelFromRootDir = path56.relative(path56.dirname(refRootAbsWt), driftAbsWt).split(path56.sep).join("/");
|
|
27533
28652
|
const linkRes = patchReferenceIndexWithDriftLink({
|
|
27534
28653
|
referenceRootAbsolute: refRootAbsWt,
|
|
27535
28654
|
relativeLinkFromRootToDrift: driftRelFromRootDir,
|
|
@@ -27548,8 +28667,8 @@ async function runContextDriftFactory(deps) {
|
|
|
27548
28667
|
...baseMeta
|
|
27549
28668
|
};
|
|
27550
28669
|
}
|
|
27551
|
-
const driftRelPosix = toPosixPath(
|
|
27552
|
-
const rootRelPosix = toPosixPath(
|
|
28670
|
+
const driftRelPosix = toPosixPath(path56.relative(wt, driftAbsWt));
|
|
28671
|
+
const rootRelPosix = toPosixPath(path56.relative(wt, refRootAbsWt));
|
|
27553
28672
|
const promoteEffective = deps.merged.promoteContextToWorkspace !== false;
|
|
27554
28673
|
if (promoteEffective && !inPlace) {
|
|
27555
28674
|
try {
|
|
@@ -27579,7 +28698,7 @@ async function runContextDriftFactory(deps) {
|
|
|
27579
28698
|
} else if (promoteEffective && inPlace) {
|
|
27580
28699
|
deps.log("[context-drift] in-place analysis \u2014 promote skipped (artefacts already under repository root)");
|
|
27581
28700
|
}
|
|
27582
|
-
const driftReportPathFs = promoteEffective ?
|
|
28701
|
+
const driftReportPathFs = promoteEffective ? path56.join(deps.repoRootAbs, ...driftRelPosix.split("/")) : driftAbsWt;
|
|
27583
28702
|
return {
|
|
27584
28703
|
exitOk: true,
|
|
27585
28704
|
ok: true,
|
|
@@ -27598,14 +28717,16 @@ async function runContextDriftFactory(deps) {
|
|
|
27598
28717
|
|
|
27599
28718
|
// src/analysis/coordinationDuplicatesDiagnosis.ts
|
|
27600
28719
|
var fs59 = __toESM(require("fs"));
|
|
27601
|
-
var
|
|
28720
|
+
var path57 = __toESM(require("path"));
|
|
27602
28721
|
var import__7 = __toESM(require__());
|
|
27603
28722
|
var COORDINATION_DUPLICATES_REPORT_BASENAME = "coordination-duplicates-report.json";
|
|
27604
28723
|
var COORDINATION_LIST_SCAN_ENTRIES = [
|
|
27605
28724
|
{ basename: "features-list.json", arrayKey: "features" },
|
|
27606
28725
|
{ basename: "experiences-list.json", arrayKey: "views" },
|
|
27607
28726
|
{ basename: "services-list.json", arrayKey: "services" },
|
|
27608
|
-
{ basename: "data-model-list.json", arrayKey: "entities" }
|
|
28727
|
+
{ basename: "data-model-list.json", arrayKey: "entities" },
|
|
28728
|
+
{ basename: "infrastructure-list.json", arrayKey: "infrastructure" },
|
|
28729
|
+
{ basename: "qa-list.json", arrayKey: "qa" }
|
|
27609
28730
|
];
|
|
27610
28731
|
var STAPLE_CONTEXT_MARKDOWN_BASENAMES = /* @__PURE__ */ new Set([
|
|
27611
28732
|
"project.md",
|
|
@@ -27623,17 +28744,21 @@ var RE_MD_SV = /^SV-\d+-.+\.md$/i;
|
|
|
27623
28744
|
var RE_MD_DM_FD = /^DM-\d+_FD-\d+-.+\.md$/i;
|
|
27624
28745
|
var RE_MD_DM = /^DM-\d+-.+\.md$/i;
|
|
27625
28746
|
var RE_MD_TS = /^TS-\d+-.+\.md$/i;
|
|
27626
|
-
|
|
27627
|
-
|
|
28747
|
+
var RE_MD_IN_IC = /^IN-\d+_IC-\d+-.+\.md$/i;
|
|
28748
|
+
var RE_MD_IN = /^IN-\d+-.+\.md$/i;
|
|
28749
|
+
var RE_MD_QA_TC = /^QA-\d+_TC-\d+-.+\.md$/i;
|
|
28750
|
+
var RE_MD_QA = /^QA-\d+-.+\.md$/i;
|
|
28751
|
+
function looksLikeCoordinationDetailMarkdownBasename(basename18) {
|
|
28752
|
+
if (!basename18 || basename18 !== path57.basename(basename18) || !/\.md$/i.test(basename18)) {
|
|
27628
28753
|
return false;
|
|
27629
28754
|
}
|
|
27630
|
-
if (STAPLE_CONTEXT_MARKDOWN_BASENAMES.has(
|
|
28755
|
+
if (STAPLE_CONTEXT_MARKDOWN_BASENAMES.has(basename18)) {
|
|
27631
28756
|
return false;
|
|
27632
28757
|
}
|
|
27633
|
-
return RE_MD_FE_UC_SC.test(
|
|
28758
|
+
return RE_MD_FE_UC_SC.test(basename18) || RE_MD_FE_UC_SLUG.test(basename18) || RE_MD_FE_UC_PLAIN.test(basename18) || RE_MD_FE_FEATURE.test(basename18) || RE_MD_XP_BH.test(basename18) || RE_MD_XP_VIEW.test(basename18) || RE_MD_SV_ME.test(basename18) || RE_MD_SV.test(basename18) || RE_MD_DM_FD.test(basename18) || RE_MD_DM.test(basename18) || RE_MD_TS.test(basename18) || RE_MD_IN_IC.test(basename18) || RE_MD_IN.test(basename18) || RE_MD_QA_TC.test(basename18) || RE_MD_QA.test(basename18);
|
|
27634
28759
|
}
|
|
27635
28760
|
function loadRawFeatureRows(contextDirAbs) {
|
|
27636
|
-
const p =
|
|
28761
|
+
const p = path57.join(contextDirAbs, "features-list.json");
|
|
27637
28762
|
if (!fs59.existsSync(p)) {
|
|
27638
28763
|
return [];
|
|
27639
28764
|
}
|
|
@@ -27645,8 +28770,8 @@ function loadRawFeatureRows(contextDirAbs) {
|
|
|
27645
28770
|
return [];
|
|
27646
28771
|
}
|
|
27647
28772
|
}
|
|
27648
|
-
function hintForOrphanFeatureMarkdown(
|
|
27649
|
-
const m = /^FE-(\d+)-(.+)\.md$/i.exec(
|
|
28773
|
+
function hintForOrphanFeatureMarkdown(basename18, featureRows) {
|
|
28774
|
+
const m = /^FE-(\d+)-(.+)\.md$/i.exec(basename18);
|
|
27650
28775
|
if (!m) {
|
|
27651
28776
|
return void 0;
|
|
27652
28777
|
}
|
|
@@ -27658,8 +28783,8 @@ function hintForOrphanFeatureMarkdown(basename17, featureRows) {
|
|
|
27658
28783
|
continue;
|
|
27659
28784
|
}
|
|
27660
28785
|
const expected = expectedFeatureDetailBasenameFromRow(row2);
|
|
27661
|
-
if (expected && expected !==
|
|
27662
|
-
return `features-list row ${code} currently implies detail file ${expected} (slug/name changed \u2014 ${
|
|
28786
|
+
if (expected && expected !== basename18) {
|
|
28787
|
+
return `features-list row ${code} currently implies detail file ${expected} (slug/name changed \u2014 ${basename18} may be stale).`;
|
|
27663
28788
|
}
|
|
27664
28789
|
if (!expected) {
|
|
27665
28790
|
return `features-list row ${code} has no resolvable slug for a detail markdown basename.`;
|
|
@@ -27926,7 +29051,7 @@ function buildCoordinationDuplicatesReport(input) {
|
|
|
27926
29051
|
const lists = [];
|
|
27927
29052
|
const duplicateGroups = [];
|
|
27928
29053
|
for (const entry of COORDINATION_LIST_SCAN_ENTRIES) {
|
|
27929
|
-
const filePath =
|
|
29054
|
+
const filePath = path57.join(input.contextDirAbsolute, entry.basename);
|
|
27930
29055
|
if (!fs59.existsSync(filePath)) {
|
|
27931
29056
|
lists.push({ basename: entry.basename, status: "missing" });
|
|
27932
29057
|
continue;
|
|
@@ -27981,7 +29106,7 @@ var validateReportCompiled;
|
|
|
27981
29106
|
function validateReportData(data) {
|
|
27982
29107
|
if (!validateReportCompiled) {
|
|
27983
29108
|
const ajv2 = new import__7.default({ allErrors: true, strict: false });
|
|
27984
|
-
const schemaPath =
|
|
29109
|
+
const schemaPath = path57.join(resolveContextListSchemasDir(), "coordination-duplicates-report.schema.json");
|
|
27985
29110
|
const schemaRaw = stripUtf8Bom6(fs59.readFileSync(schemaPath, "utf-8"));
|
|
27986
29111
|
validateReportCompiled = ajv2.compile(JSON.parse(schemaRaw));
|
|
27987
29112
|
}
|
|
@@ -28000,7 +29125,7 @@ function runCoordinationDuplicatesDiagnosis(input) {
|
|
|
28000
29125
|
if (!v.ok) {
|
|
28001
29126
|
return { ok: false, message: `Report validation failed: ${v.errors.join("; ")}` };
|
|
28002
29127
|
}
|
|
28003
|
-
const outPath =
|
|
29128
|
+
const outPath = path57.join(input.contextDirAbsolute, COORDINATION_DUPLICATES_REPORT_BASENAME);
|
|
28004
29129
|
const payload = `${JSON.stringify(report, null, 2)}
|
|
28005
29130
|
`;
|
|
28006
29131
|
const tmp = `${outPath}.tmp.${process.pid}`;
|
|
@@ -28048,7 +29173,7 @@ function runCoordinationDuplicatesDiagnosis(input) {
|
|
|
28048
29173
|
|
|
28049
29174
|
// src/pipelines/download/downloadPipeline.ts
|
|
28050
29175
|
var fs60 = __toESM(require("node:fs"));
|
|
28051
|
-
var
|
|
29176
|
+
var path58 = __toESM(require("node:path"));
|
|
28052
29177
|
var SRS_DISCOVERY_BATCH_GET_CHUNK_SIZE = 200;
|
|
28053
29178
|
function isRecord7(v) {
|
|
28054
29179
|
return Boolean(v) && typeof v === "object" && !Array.isArray(v);
|
|
@@ -28138,9 +29263,9 @@ function resolveSafeContextOutputPath(contextDirAbs, nameRaw) {
|
|
|
28138
29263
|
return null;
|
|
28139
29264
|
}
|
|
28140
29265
|
}
|
|
28141
|
-
const resolved =
|
|
28142
|
-
const rel =
|
|
28143
|
-
if (rel.startsWith("..") ||
|
|
29266
|
+
const resolved = path58.resolve(contextDirAbs, ...segments);
|
|
29267
|
+
const rel = path58.relative(contextDirAbs, resolved);
|
|
29268
|
+
if (rel.startsWith("..") || path58.isAbsolute(rel)) {
|
|
28144
29269
|
return null;
|
|
28145
29270
|
}
|
|
28146
29271
|
return resolved;
|
|
@@ -28156,7 +29281,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
|
28156
29281
|
if (!fs60.existsSync(contextDirAbs) || !fs60.statSync(contextDirAbs).isDirectory()) {
|
|
28157
29282
|
return { filesRemoved: 0 };
|
|
28158
29283
|
}
|
|
28159
|
-
const preserveAbs =
|
|
29284
|
+
const preserveAbs = path58.resolve(contextDirAbs, UPLOAD_TARGET_FILENAME);
|
|
28160
29285
|
const preserveSet = /* @__PURE__ */ new Set();
|
|
28161
29286
|
if (fs60.existsSync(preserveAbs) && fs60.statSync(preserveAbs).isFile()) {
|
|
28162
29287
|
preserveSet.add(preserveAbs);
|
|
@@ -28170,7 +29295,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
|
28170
29295
|
return;
|
|
28171
29296
|
}
|
|
28172
29297
|
for (const e of entries) {
|
|
28173
|
-
const full =
|
|
29298
|
+
const full = path58.join(dir, e.name);
|
|
28174
29299
|
if (e.isDirectory()) {
|
|
28175
29300
|
walkRm(full);
|
|
28176
29301
|
try {
|
|
@@ -28178,7 +29303,7 @@ function clearContextDirectoryForCloudReplace(contextDirAbs) {
|
|
|
28178
29303
|
} catch {
|
|
28179
29304
|
}
|
|
28180
29305
|
} else if (e.isFile()) {
|
|
28181
|
-
const abs =
|
|
29306
|
+
const abs = path58.resolve(full);
|
|
28182
29307
|
if (preserveSet.has(abs)) {
|
|
28183
29308
|
continue;
|
|
28184
29309
|
}
|
|
@@ -28251,7 +29376,7 @@ async function runDownloadPipeline(opts) {
|
|
|
28251
29376
|
failed.push({ id, message: "Missing name on srs_discovery node." });
|
|
28252
29377
|
continue;
|
|
28253
29378
|
}
|
|
28254
|
-
if (name === UPLOAD_TARGET_FILENAME ||
|
|
29379
|
+
if (name === UPLOAD_TARGET_FILENAME || path58.basename(name) === UPLOAD_TARGET_FILENAME) {
|
|
28255
29380
|
skipped += 1;
|
|
28256
29381
|
log?.(`[pipeline:download] skip ${name} (upload target row).`);
|
|
28257
29382
|
continue;
|
|
@@ -28262,7 +29387,7 @@ async function runDownloadPipeline(opts) {
|
|
|
28262
29387
|
failed.push({ id, name, message: "Unsafe or invalid name for local path." });
|
|
28263
29388
|
continue;
|
|
28264
29389
|
}
|
|
28265
|
-
fs60.mkdirSync(
|
|
29390
|
+
fs60.mkdirSync(path58.dirname(outAbs), { recursive: true });
|
|
28266
29391
|
const exists = fs60.existsSync(outAbs);
|
|
28267
29392
|
if (exists && !opts.force && !opts.replaceFromCloud) {
|
|
28268
29393
|
skipped += 1;
|
|
@@ -28345,12 +29470,12 @@ function toFetchErrorMessage(e) {
|
|
|
28345
29470
|
|
|
28346
29471
|
// src/auth/gluecharmContentNegotiation.ts
|
|
28347
29472
|
var GLUECHARM_WS_LEGACY_JSON = "application/vnd.gluecharm.v1.ws-legacy+json";
|
|
28348
|
-
function pathWithoutQuery(
|
|
28349
|
-
const q =
|
|
28350
|
-
return q === -1 ?
|
|
29473
|
+
function pathWithoutQuery(path64) {
|
|
29474
|
+
const q = path64.indexOf("?");
|
|
29475
|
+
return q === -1 ? path64 : path64.slice(0, q);
|
|
28351
29476
|
}
|
|
28352
|
-
function isGluecharmContentApiPath(
|
|
28353
|
-
const p = pathWithoutQuery(
|
|
29477
|
+
function isGluecharmContentApiPath(path64) {
|
|
29478
|
+
const p = pathWithoutQuery(path64);
|
|
28354
29479
|
return p.startsWith("/api/content/") || p.startsWith("/api/batch/content/");
|
|
28355
29480
|
}
|
|
28356
29481
|
function gluecharmContentHeaders(method) {
|
|
@@ -28388,7 +29513,7 @@ async function fetchWithTimeout2(url, init, fetchImpl, timeoutMs, externalSignal
|
|
|
28388
29513
|
}
|
|
28389
29514
|
function createAuthenticatedRequestJson(deps) {
|
|
28390
29515
|
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
28391
|
-
async function requestJson(
|
|
29516
|
+
async function requestJson(path64, options = {}) {
|
|
28392
29517
|
const base = deps.getApiBaseUrl();
|
|
28393
29518
|
if (!base) {
|
|
28394
29519
|
const err = { status: 0, message: "easyspecs.apiBaseUrl is not configured." };
|
|
@@ -28396,7 +29521,7 @@ function createAuthenticatedRequestJson(deps) {
|
|
|
28396
29521
|
}
|
|
28397
29522
|
const method = options.method ?? "GET";
|
|
28398
29523
|
const headers = { ...options.headers };
|
|
28399
|
-
if (isGluecharmContentApiPath(
|
|
29524
|
+
if (isGluecharmContentApiPath(path64)) {
|
|
28400
29525
|
Object.assign(headers, gluecharmContentHeaders(method));
|
|
28401
29526
|
} else {
|
|
28402
29527
|
if (!headers.Accept) {
|
|
@@ -28410,7 +29535,7 @@ function createAuthenticatedRequestJson(deps) {
|
|
|
28410
29535
|
if (options.withAuth !== false && access) {
|
|
28411
29536
|
headers.Authorization = `Bearer ${access}`;
|
|
28412
29537
|
}
|
|
28413
|
-
const url = `${base}${
|
|
29538
|
+
const url = `${base}${path64}`;
|
|
28414
29539
|
const timeoutMs = options.timeoutMs ?? API_TIMEOUT_MS;
|
|
28415
29540
|
const response = await fetchWithTimeout2(
|
|
28416
29541
|
url,
|
|
@@ -28431,7 +29556,7 @@ function createAuthenticatedRequestJson(deps) {
|
|
|
28431
29556
|
if (shouldRetryUnauthorized) {
|
|
28432
29557
|
const refreshed = await deps.refreshSession();
|
|
28433
29558
|
if (refreshed) {
|
|
28434
|
-
return requestJson(
|
|
29559
|
+
return requestJson(path64, { ...options, retryOnUnauthorized: false });
|
|
28435
29560
|
}
|
|
28436
29561
|
}
|
|
28437
29562
|
const fallback = payload == null ? `${response.statusText || "HTTP error"} (response body empty or not JSON)` : "Request failed.";
|
|
@@ -28443,13 +29568,13 @@ function createAuthenticatedRequestJson(deps) {
|
|
|
28443
29568
|
// src/cli/cliSession.ts
|
|
28444
29569
|
var fs61 = __toESM(require("node:fs"));
|
|
28445
29570
|
var os7 = __toESM(require("node:os"));
|
|
28446
|
-
var
|
|
29571
|
+
var path59 = __toESM(require("node:path"));
|
|
28447
29572
|
function defaultSessionPath() {
|
|
28448
|
-
return
|
|
29573
|
+
return path59.join(os7.homedir(), ".easyspecs", "cli-session.json");
|
|
28449
29574
|
}
|
|
28450
29575
|
var configSessionPath;
|
|
28451
29576
|
function setCliSessionPathFromConfig(absPath) {
|
|
28452
|
-
configSessionPath = absPath?.trim() ?
|
|
29577
|
+
configSessionPath = absPath?.trim() ? path59.resolve(absPath) : void 0;
|
|
28453
29578
|
}
|
|
28454
29579
|
function applyCliSessionPathFromRepoConfig(repoRoot, cfg) {
|
|
28455
29580
|
const raw = cfg.easyspecs?.cliSessionPath?.trim();
|
|
@@ -28457,7 +29582,7 @@ function applyCliSessionPathFromRepoConfig(repoRoot, cfg) {
|
|
|
28457
29582
|
setCliSessionPathFromConfig(void 0);
|
|
28458
29583
|
return;
|
|
28459
29584
|
}
|
|
28460
|
-
const abs =
|
|
29585
|
+
const abs = path59.isAbsolute(raw) ? raw : path59.join(repoRoot, raw);
|
|
28461
29586
|
setCliSessionPathFromConfig(abs);
|
|
28462
29587
|
}
|
|
28463
29588
|
function normalizeCliSessionPathForConfig(repoRoot, raw) {
|
|
@@ -28465,15 +29590,15 @@ function normalizeCliSessionPathForConfig(repoRoot, raw) {
|
|
|
28465
29590
|
if (!t) {
|
|
28466
29591
|
return "";
|
|
28467
29592
|
}
|
|
28468
|
-
const resolvedRepo =
|
|
28469
|
-
const abs =
|
|
28470
|
-
const rel =
|
|
29593
|
+
const resolvedRepo = path59.resolve(repoRoot);
|
|
29594
|
+
const abs = path59.isAbsolute(t) ? path59.normalize(t) : path59.resolve(resolvedRepo, t);
|
|
29595
|
+
const rel = path59.relative(resolvedRepo, abs);
|
|
28471
29596
|
if (rel === "") {
|
|
28472
29597
|
return abs;
|
|
28473
29598
|
}
|
|
28474
|
-
const underRepo = !rel.startsWith("..") && !
|
|
29599
|
+
const underRepo = !rel.startsWith("..") && !path59.isAbsolute(rel);
|
|
28475
29600
|
if (underRepo) {
|
|
28476
|
-
return rel.split(
|
|
29601
|
+
return rel.split(path59.sep).join("/");
|
|
28477
29602
|
}
|
|
28478
29603
|
return abs;
|
|
28479
29604
|
}
|
|
@@ -28503,7 +29628,7 @@ function readCliSession() {
|
|
|
28503
29628
|
}
|
|
28504
29629
|
function writeCliSession(s) {
|
|
28505
29630
|
const p = effectiveCliSessionPath();
|
|
28506
|
-
fs61.mkdirSync(
|
|
29631
|
+
fs61.mkdirSync(path59.dirname(p), { recursive: true });
|
|
28507
29632
|
fs61.writeFileSync(p, `${JSON.stringify(s, null, 2)}
|
|
28508
29633
|
`, "utf8");
|
|
28509
29634
|
}
|
|
@@ -28517,7 +29642,7 @@ function clearCliSession() {
|
|
|
28517
29642
|
|
|
28518
29643
|
// src/analysis/acePendingTraces.ts
|
|
28519
29644
|
var fs62 = __toESM(require("fs"));
|
|
28520
|
-
var
|
|
29645
|
+
var path60 = __toESM(require("path"));
|
|
28521
29646
|
function normalizeAceTraceRelativePath(rel) {
|
|
28522
29647
|
return rel.split(/[/\\]/).join("/");
|
|
28523
29648
|
}
|
|
@@ -28567,7 +29692,7 @@ function listPendingAceTraceFiles(contextDir2, worktreeRoot) {
|
|
|
28567
29692
|
const allAbs = listAceTraceFiles(contextDir2);
|
|
28568
29693
|
const pending = [];
|
|
28569
29694
|
for (const abs of allAbs) {
|
|
28570
|
-
const rel = normalizeAceTraceRelativePath(
|
|
29695
|
+
const rel = normalizeAceTraceRelativePath(path60.relative(contextDir2, abs));
|
|
28571
29696
|
const v = validateAceJsonFile(abs, traceSchema);
|
|
28572
29697
|
if (!v.ok) {
|
|
28573
29698
|
continue;
|
|
@@ -28582,7 +29707,7 @@ function listPendingAceTraceFiles(contextDir2, worktreeRoot) {
|
|
|
28582
29707
|
}
|
|
28583
29708
|
|
|
28584
29709
|
// src/analysis/aceAutoLearnPool.ts
|
|
28585
|
-
var
|
|
29710
|
+
var path61 = __toESM(require("path"));
|
|
28586
29711
|
function clampConcurrency2(n) {
|
|
28587
29712
|
if (!Number.isFinite(n)) {
|
|
28588
29713
|
return DEFAULT_MAX_CONCURRENT_AI;
|
|
@@ -28617,8 +29742,8 @@ async function runAceAutoLearnPool(p) {
|
|
|
28617
29742
|
};
|
|
28618
29743
|
const currentCap = () => Math.min(staticMaxC, adaptiveMax);
|
|
28619
29744
|
let wake;
|
|
28620
|
-
const waitTurn = () => new Promise((
|
|
28621
|
-
wake =
|
|
29745
|
+
const waitTurn = () => new Promise((resolve25) => {
|
|
29746
|
+
wake = resolve25;
|
|
28622
29747
|
});
|
|
28623
29748
|
const pump = () => {
|
|
28624
29749
|
wake?.();
|
|
@@ -28640,7 +29765,7 @@ async function runAceAutoLearnPool(p) {
|
|
|
28640
29765
|
poolAbortListenerRegistered = true;
|
|
28641
29766
|
}
|
|
28642
29767
|
}
|
|
28643
|
-
const traceRel = (abs) =>
|
|
29768
|
+
const traceRel = (abs) => path61.relative(contextDir2, abs).split(path61.sep).join("/");
|
|
28644
29769
|
const runOne = async (traceAbs) => {
|
|
28645
29770
|
if (abortSignal?.aborted) {
|
|
28646
29771
|
active -= 1;
|
|
@@ -29173,15 +30298,15 @@ function formatCliStderrLine(line, useAnsi) {
|
|
|
29173
30298
|
// src/cli/main.ts
|
|
29174
30299
|
function resolveCliPackageVersion() {
|
|
29175
30300
|
if (true) {
|
|
29176
|
-
return "0.3.
|
|
30301
|
+
return "0.3.6";
|
|
29177
30302
|
}
|
|
29178
30303
|
const candidates = [
|
|
29179
|
-
|
|
29180
|
-
|
|
30304
|
+
path63.join(__dirname, "..", "package.json"),
|
|
30305
|
+
path63.join(__dirname, "..", "..", "packages", "cli", "package.json")
|
|
29181
30306
|
];
|
|
29182
30307
|
for (const pkgPath of candidates) {
|
|
29183
30308
|
try {
|
|
29184
|
-
const raw =
|
|
30309
|
+
const raw = fs64.readFileSync(pkgPath, "utf8");
|
|
29185
30310
|
const j = JSON.parse(raw);
|
|
29186
30311
|
if (typeof j.version === "string") {
|
|
29187
30312
|
return j.version;
|
|
@@ -29333,23 +30458,23 @@ function resolveAnalysisRoot(repoRoot, rootKind, worktreePath) {
|
|
|
29333
30458
|
return repoRoot;
|
|
29334
30459
|
}
|
|
29335
30460
|
const wt = worktreePath?.trim();
|
|
29336
|
-
if (wt &&
|
|
29337
|
-
return
|
|
30461
|
+
if (wt && fs64.existsSync(path63.join(wt, ".git"))) {
|
|
30462
|
+
return path63.resolve(wt);
|
|
29338
30463
|
}
|
|
29339
30464
|
throw new Error("worktree mode requires --worktree <path> to an existing analysis checkout.");
|
|
29340
30465
|
}
|
|
29341
30466
|
function resolveAdHocCheckoutRoot(_repoRoot, storage, worktreeFlag) {
|
|
29342
30467
|
const w = worktreeFlag?.trim();
|
|
29343
30468
|
if (w) {
|
|
29344
|
-
const abs =
|
|
29345
|
-
if (
|
|
30469
|
+
const abs = path63.resolve(w);
|
|
30470
|
+
if (fs64.existsSync(path63.join(abs, ".git"))) {
|
|
29346
30471
|
return abs;
|
|
29347
30472
|
}
|
|
29348
30473
|
throw new Error(`Invalid --worktree (not a git checkout): ${abs}`);
|
|
29349
30474
|
}
|
|
29350
30475
|
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
29351
30476
|
const p = snap?.adHocWorktreePath?.trim();
|
|
29352
|
-
if (p &&
|
|
30477
|
+
if (p && fs64.existsSync(path63.join(p, ".git"))) {
|
|
29353
30478
|
return p;
|
|
29354
30479
|
}
|
|
29355
30480
|
throw new Error("No analysis checkout: run `easyspecs-cli run synthesis` first or pass `--worktree <path>`.");
|
|
@@ -29376,7 +30501,7 @@ async function runResumeRemediationPool(storage, repoRoot, analysisRoot, merged,
|
|
|
29376
30501
|
requireOpenCode(merged, flags);
|
|
29377
30502
|
const agentsDir = resolveOpenCodeAgentsDir(repoRoot, repoConfig);
|
|
29378
30503
|
assertAgentsDirExists(agentsDir);
|
|
29379
|
-
const ctxDir =
|
|
30504
|
+
const ctxDir = path63.join(analysisRoot, ".gluecharm", "context");
|
|
29380
30505
|
const snap = readArtefactRunSnapshot(storage);
|
|
29381
30506
|
const rows = listMissingWorkstations(ctxDir, analysisRoot, snap);
|
|
29382
30507
|
if (rows.length === 0) {
|
|
@@ -29394,7 +30519,7 @@ async function runResumeRemediationPool(storage, repoRoot, analysisRoot, merged,
|
|
|
29394
30519
|
storageContext: storage,
|
|
29395
30520
|
repositoryRoot: repoRoot,
|
|
29396
30521
|
worktreeRoot: analysisRoot,
|
|
29397
|
-
workspaceLabel:
|
|
30522
|
+
workspaceLabel: path63.basename(analysisRoot),
|
|
29398
30523
|
oc,
|
|
29399
30524
|
log: (line) => logErr(flags, line),
|
|
29400
30525
|
abortSignal: void 0,
|
|
@@ -29571,17 +30696,17 @@ async function main() {
|
|
|
29571
30696
|
{ easyspecs: { defaultGitRemoteUrl: url } },
|
|
29572
30697
|
{ warnMigration: (m) => logErr(flags, `[EasySpecs] ${m}`) }
|
|
29573
30698
|
);
|
|
29574
|
-
const
|
|
30699
|
+
const path64 = easyspecsConfigPath(repoRoot);
|
|
29575
30700
|
if (flags.json) {
|
|
29576
30701
|
printJsonLine({
|
|
29577
30702
|
command: "config set-git-remote",
|
|
29578
30703
|
durationMs: Date.now() - t0,
|
|
29579
30704
|
ok: true,
|
|
29580
|
-
path:
|
|
30705
|
+
path: path64,
|
|
29581
30706
|
defaultGitRemoteUrl: cfg.easyspecs?.defaultGitRemoteUrl ?? ""
|
|
29582
30707
|
});
|
|
29583
30708
|
} else {
|
|
29584
|
-
console.log(`Updated ${
|
|
30709
|
+
console.log(`Updated ${path64} \u2014 easyspecs.defaultGitRemoteUrl`);
|
|
29585
30710
|
}
|
|
29586
30711
|
process.exit(ExitCode.ok);
|
|
29587
30712
|
} catch (e) {
|
|
@@ -29614,7 +30739,7 @@ async function main() {
|
|
|
29614
30739
|
applyCliSessionPathFromRepoConfig(repoRoot, repoConfig);
|
|
29615
30740
|
if (flags.sessionPath?.trim()) {
|
|
29616
30741
|
const sp = flags.sessionPath.trim();
|
|
29617
|
-
const abs =
|
|
30742
|
+
const abs = path63.isAbsolute(sp) ? path63.normalize(sp) : path63.resolve(repoRoot, sp);
|
|
29618
30743
|
setCliSessionPathFromConfig(abs);
|
|
29619
30744
|
}
|
|
29620
30745
|
const apiResolved = initApiBaseUrlForCli(repoRoot, flags, repoConfig);
|
|
@@ -29855,7 +30980,7 @@ async function main() {
|
|
|
29855
30980
|
const result = await runSynthesisPipeline(
|
|
29856
30981
|
storage,
|
|
29857
30982
|
repoRoot,
|
|
29858
|
-
|
|
30983
|
+
path63.basename(repoRoot),
|
|
29859
30984
|
agentsDir,
|
|
29860
30985
|
{
|
|
29861
30986
|
...merged.pipelineOpenCode
|
|
@@ -29910,7 +31035,7 @@ async function main() {
|
|
|
29910
31035
|
if (sub === "reference-coverage") {
|
|
29911
31036
|
const rootAbs = resolveAnalysisRoot(repoRoot, rootKind, worktree);
|
|
29912
31037
|
requireMinimalGluecharmLayoutAt(rootAbs);
|
|
29913
|
-
const contextDir2 =
|
|
31038
|
+
const contextDir2 = path63.join(rootAbs, ".gluecharm", "context");
|
|
29914
31039
|
const res = runCoveragePipeline({
|
|
29915
31040
|
repositoryRootAbs: rootAbs,
|
|
29916
31041
|
contextDirAbs: contextDir2,
|
|
@@ -29933,7 +31058,7 @@ async function main() {
|
|
|
29933
31058
|
if (sub === "coordination-duplicates") {
|
|
29934
31059
|
const rootAbs = resolveAnalysisRoot(repoRoot, rootKind, worktree);
|
|
29935
31060
|
requireMinimalGluecharmLayoutAt(rootAbs);
|
|
29936
|
-
const contextDir2 =
|
|
31061
|
+
const contextDir2 = path63.join(rootAbs, ".gluecharm", "context");
|
|
29937
31062
|
const res = runCoordinationDuplicatesDiagnosis({
|
|
29938
31063
|
contextDirAbsolute: contextDir2,
|
|
29939
31064
|
sourceRoot: rootKind === "worktree" ? "worktree" : "workspace"
|
|
@@ -29969,7 +31094,7 @@ async function main() {
|
|
|
29969
31094
|
if (sub === "missing-artefacts") {
|
|
29970
31095
|
const rootAbs = resolveAnalysisRoot(repoRoot, rootKind, worktree);
|
|
29971
31096
|
requireMinimalGluecharmLayoutAt(rootAbs);
|
|
29972
|
-
const ctxDir =
|
|
31097
|
+
const ctxDir = path63.join(rootAbs, ".gluecharm", "context");
|
|
29973
31098
|
const storage = createFileBackedWorkspaceState(repoRoot);
|
|
29974
31099
|
const snap = readArtefactRunSnapshot(storage);
|
|
29975
31100
|
const rows = listMissingWorkstations(ctxDir, rootAbs, snap);
|
|
@@ -30019,7 +31144,7 @@ async function main() {
|
|
|
30019
31144
|
});
|
|
30020
31145
|
const bad = poolRes.cancelled || poolRes.failures > 0;
|
|
30021
31146
|
if (!bad) {
|
|
30022
|
-
const ctxDir =
|
|
31147
|
+
const ctxDir = path63.join(analysisRoot, ".gluecharm", "context");
|
|
30023
31148
|
const lg = runLinkMappingPipeline(ctxDir, { log: (line) => logErr(flags, line) });
|
|
30024
31149
|
if (!lg.ok) {
|
|
30025
31150
|
finish(OsExit.diagnoseZeroReferenceLinkMapping, {
|
|
@@ -30042,6 +31167,23 @@ async function main() {
|
|
|
30042
31167
|
}
|
|
30043
31168
|
finish(ExitCode.usage, { ok: false, error: `Unknown diagnose subcommand: ${sub ?? ""}` });
|
|
30044
31169
|
}
|
|
31170
|
+
if (pos[0] === "context" && pos[1] === "migrate-srs52") {
|
|
31171
|
+
const tail = pos.slice(2);
|
|
31172
|
+
const { rootKind, worktree: wtFromRoot } = parseTailFlags(tail);
|
|
31173
|
+
const { worktree: wtExplicit } = parseWorktreeFlag(tail);
|
|
31174
|
+
const worktree = wtExplicit ?? wtFromRoot;
|
|
31175
|
+
const rootAbs = resolveAnalysisRoot(repoRoot, rootKind, worktree);
|
|
31176
|
+
requireMinimalGluecharmLayoutAt(rootAbs);
|
|
31177
|
+
const contextDir2 = path63.join(rootAbs, ".gluecharm", "context");
|
|
31178
|
+
const dryRun = tail.includes("--dry-run");
|
|
31179
|
+
const force = tail.includes("--force");
|
|
31180
|
+
const { migrateSrs52Context: migrateSrs52Context2 } = await Promise.resolve().then(() => (init_migrateSrs52Context(), migrateSrs52Context_exports));
|
|
31181
|
+
const res = migrateSrs52Context2({ contextDir: contextDir2, dryRun, force });
|
|
31182
|
+
if (!res.ok) {
|
|
31183
|
+
finish(ExitCode.usage, { contextDir: contextDir2, dryRun, ...res });
|
|
31184
|
+
}
|
|
31185
|
+
finish(ExitCode.ok, { contextDir: contextDir2, dryRun, ...res });
|
|
31186
|
+
}
|
|
30045
31187
|
if (pos[0] === "context" && pos[1] === "link-graph") {
|
|
30046
31188
|
const tail = pos.slice(2);
|
|
30047
31189
|
const { rootKind, worktree: wtFromRoot } = parseTailFlags(tail);
|
|
@@ -30049,7 +31191,7 @@ async function main() {
|
|
|
30049
31191
|
const worktree = wtExplicit ?? wtFromRoot;
|
|
30050
31192
|
const rootAbs = resolveAnalysisRoot(repoRoot, rootKind, worktree);
|
|
30051
31193
|
requireMinimalGluecharmLayoutAt(rootAbs);
|
|
30052
|
-
const contextDir2 =
|
|
31194
|
+
const contextDir2 = path63.join(rootAbs, ".gluecharm", "context");
|
|
30053
31195
|
const res = runLinkMappingPipeline(contextDir2, {
|
|
30054
31196
|
log: (line) => logErr(flags, line)
|
|
30055
31197
|
});
|
|
@@ -30246,13 +31388,13 @@ async function main() {
|
|
|
30246
31388
|
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
30247
31389
|
const wt = snap?.adHocWorktreePath?.trim();
|
|
30248
31390
|
if (wt) {
|
|
30249
|
-
const sourceCtx =
|
|
30250
|
-
if (
|
|
31391
|
+
const sourceCtx = path63.join(wt, ".gluecharm", "context");
|
|
31392
|
+
if (path63.resolve(wt) === path63.resolve(repoRoot)) {
|
|
30251
31393
|
logErr(
|
|
30252
31394
|
flags,
|
|
30253
31395
|
"[pipeline:analysis] promote skipped (in-place: analysis checkout is the repository root)"
|
|
30254
31396
|
);
|
|
30255
|
-
} else if (
|
|
31397
|
+
} else if (fs64.existsSync(sourceCtx)) {
|
|
30256
31398
|
const n = promoteContextDirectoryToWorkspaceFs(sourceCtx, repoRoot);
|
|
30257
31399
|
logErr(flags, `[pipeline:analysis] promoted ${String(n.filesCopied)} file(s) \u2192 ${repoRoot}`);
|
|
30258
31400
|
} else {
|
|
@@ -30350,10 +31492,10 @@ async function main() {
|
|
|
30350
31492
|
finish(ExitCode.usage, { ok: false, error: `unknown download context flag: ${a}` });
|
|
30351
31493
|
}
|
|
30352
31494
|
requireMinimalGluecharmLayoutAt(repoRoot);
|
|
30353
|
-
const ctxDir =
|
|
30354
|
-
const gluecharmParent =
|
|
30355
|
-
if (
|
|
30356
|
-
requireMinimalGluecharmLayoutAt(
|
|
31495
|
+
const ctxDir = path63.resolve(path63.join(repoRoot, ".gluecharm", "context"));
|
|
31496
|
+
const gluecharmParent = path63.dirname(ctxDir);
|
|
31497
|
+
if (path63.basename(gluecharmParent) === ".gluecharm" && path63.basename(ctxDir) === "context") {
|
|
31498
|
+
requireMinimalGluecharmLayoutAt(path63.dirname(gluecharmParent));
|
|
30357
31499
|
}
|
|
30358
31500
|
const appIdRaw = getEasyspecsProjectIdFromRepoConfig(repoConfig)?.trim();
|
|
30359
31501
|
if (!appIdRaw) {
|
|
@@ -30436,16 +31578,16 @@ async function main() {
|
|
|
30436
31578
|
}
|
|
30437
31579
|
const sess = sessRaw;
|
|
30438
31580
|
requireMinimalGluecharmLayoutAt(repoRoot);
|
|
30439
|
-
let ctxDir =
|
|
31581
|
+
let ctxDir = path63.join(repoRoot, ".gluecharm", "context");
|
|
30440
31582
|
if (pos[1] === "republish") {
|
|
30441
31583
|
const fromCfg = repoConfig.easyspecs?.upload?.contextDirectory?.trim();
|
|
30442
|
-
const resolvedOverride = fromCfg && fromCfg.length > 0 ?
|
|
30443
|
-
if (resolvedOverride &&
|
|
31584
|
+
const resolvedOverride = fromCfg && fromCfg.length > 0 ? path63.isAbsolute(fromCfg) ? path63.normalize(fromCfg) : path63.resolve(repoRoot, fromCfg) : "";
|
|
31585
|
+
if (resolvedOverride && fs64.existsSync(path63.join(resolvedOverride, ".."))) {
|
|
30444
31586
|
ctxDir = resolvedOverride;
|
|
30445
31587
|
} else {
|
|
30446
31588
|
const storage = createFileBackedWorkspaceState(repoRoot);
|
|
30447
31589
|
const snap = readAnalysisWorkspaceSnapshot(storage);
|
|
30448
|
-
const wt = snap?.adHocWorktreePath &&
|
|
31590
|
+
const wt = snap?.adHocWorktreePath && fs64.existsSync(path63.join(snap.adHocWorktreePath, ".gluecharm", "context")) ? path63.join(snap.adHocWorktreePath, ".gluecharm", "context") : "";
|
|
30449
31591
|
if (!wt) {
|
|
30450
31592
|
finish(ExitCode.misconfiguration, {
|
|
30451
31593
|
ok: false,
|
|
@@ -30455,10 +31597,10 @@ async function main() {
|
|
|
30455
31597
|
ctxDir = wt;
|
|
30456
31598
|
}
|
|
30457
31599
|
}
|
|
30458
|
-
const ctxResolved =
|
|
30459
|
-
const gluecharmParent =
|
|
30460
|
-
if (
|
|
30461
|
-
requireMinimalGluecharmLayoutAt(
|
|
31600
|
+
const ctxResolved = path63.resolve(ctxDir);
|
|
31601
|
+
const gluecharmParent = path63.dirname(ctxResolved);
|
|
31602
|
+
if (path63.basename(gluecharmParent) === ".gluecharm" && path63.basename(ctxResolved) === "context") {
|
|
31603
|
+
requireMinimalGluecharmLayoutAt(path63.dirname(gluecharmParent));
|
|
30462
31604
|
}
|
|
30463
31605
|
const appIdRaw = getEasyspecsProjectIdFromRepoConfig(repoConfig)?.trim();
|
|
30464
31606
|
if (!appIdRaw) {
|
|
@@ -30562,18 +31704,18 @@ async function main() {
|
|
|
30562
31704
|
finish(failed ? ExitCode.upload : ExitCode.ok, primary);
|
|
30563
31705
|
}
|
|
30564
31706
|
if (pos[0] === "ace" && pos[1] === "clear") {
|
|
30565
|
-
const learnings =
|
|
30566
|
-
if (!
|
|
31707
|
+
const learnings = path63.join(repoRoot, ".gluecharm", "context", "learnings");
|
|
31708
|
+
if (!fs64.existsSync(learnings)) {
|
|
30567
31709
|
finish(ExitCode.ok, { ok: true, message: "nothing to clear" });
|
|
30568
31710
|
}
|
|
30569
|
-
|
|
31711
|
+
fs64.rmSync(learnings, { recursive: true, force: true });
|
|
30570
31712
|
finish(ExitCode.ok, { ok: true, message: `cleared ${learnings}` });
|
|
30571
31713
|
}
|
|
30572
31714
|
if (pos[0] === "ace" && pos[1] === "learn") {
|
|
30573
31715
|
requireOpenCode(merged, flags);
|
|
30574
31716
|
const { worktree } = parseWorktreeFlag(pos.slice(2));
|
|
30575
|
-
const root = worktree &&
|
|
30576
|
-
const contextDir2 =
|
|
31717
|
+
const root = worktree && fs64.existsSync(path63.join(worktree, ".opencode", "schemas", "ace")) ? worktree : repoRoot;
|
|
31718
|
+
const contextDir2 = path63.join(root, ".gluecharm", "context");
|
|
30577
31719
|
const traces = listAceTraceFiles(contextDir2);
|
|
30578
31720
|
if (traces.length === 0) {
|
|
30579
31721
|
finish(ExitCode.ok, { ok: true, message: "no traces", traceCount: 0 });
|
|
@@ -30597,8 +31739,8 @@ async function main() {
|
|
|
30597
31739
|
if (pos[0] === "ace" && pos[1] === "auto-learn") {
|
|
30598
31740
|
requireOpenCode(merged, flags);
|
|
30599
31741
|
const { worktree } = parseWorktreeFlag(pos.slice(2));
|
|
30600
|
-
const root = worktree &&
|
|
30601
|
-
const contextDir2 =
|
|
31742
|
+
const root = worktree && fs64.existsSync(path63.join(worktree, ".git")) ? worktree : repoRoot;
|
|
31743
|
+
const contextDir2 = path63.join(root, ".gluecharm", "context");
|
|
30602
31744
|
const pending = listPendingAceTraceFiles(contextDir2, root);
|
|
30603
31745
|
if (pending.length === 0) {
|
|
30604
31746
|
finish(ExitCode.ok, { ok: true, pending: 0 });
|