@mrciphersmith/keryx 0.3.31 → 0.3.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/cli.js +1911 -1658
- package/dist/core.js +850 -702
- package/package.json +1 -1
package/dist/core.js
CHANGED
|
@@ -3390,16 +3390,16 @@ var init_exfil = __esm(() => {
|
|
|
3390
3390
|
// src/lib/contained-path.ts
|
|
3391
3391
|
import { lstat as lstat2, realpath } from "fs/promises";
|
|
3392
3392
|
import { existsSync, lstatSync, realpathSync } from "fs";
|
|
3393
|
-
import
|
|
3393
|
+
import path17 from "path";
|
|
3394
3394
|
function resolveProjectRoot(startDir) {
|
|
3395
|
-
let current =
|
|
3395
|
+
let current = path17.resolve(startDir);
|
|
3396
3396
|
for (;; ) {
|
|
3397
|
-
if (existsSync(
|
|
3397
|
+
if (existsSync(path17.join(current, ".metaproject")) || existsSync(path17.join(current, ".git"))) {
|
|
3398
3398
|
return current;
|
|
3399
3399
|
}
|
|
3400
|
-
const parent =
|
|
3400
|
+
const parent = path17.dirname(current);
|
|
3401
3401
|
if (parent === current) {
|
|
3402
|
-
return
|
|
3402
|
+
return path17.resolve(startDir);
|
|
3403
3403
|
}
|
|
3404
3404
|
current = parent;
|
|
3405
3405
|
}
|
|
@@ -3408,11 +3408,11 @@ function isInside(root, candidate) {
|
|
|
3408
3408
|
if (candidate === root) {
|
|
3409
3409
|
return true;
|
|
3410
3410
|
}
|
|
3411
|
-
const relative =
|
|
3412
|
-
if (relative.length === 0 ||
|
|
3411
|
+
const relative = path17.relative(root, candidate);
|
|
3412
|
+
if (relative.length === 0 || path17.isAbsolute(relative)) {
|
|
3413
3413
|
return false;
|
|
3414
3414
|
}
|
|
3415
|
-
return relative !== ".." && !relative.startsWith(`..${
|
|
3415
|
+
return relative !== ".." && !relative.startsWith(`..${path17.sep}`);
|
|
3416
3416
|
}
|
|
3417
3417
|
async function resolveContainedPath(projectRoot, candidate) {
|
|
3418
3418
|
try {
|
|
@@ -3423,8 +3423,8 @@ async function resolveContainedPath(projectRoot, candidate) {
|
|
|
3423
3423
|
} catch {
|
|
3424
3424
|
return { ok: false, reason: "not-found", message: `no such file or directory: ${candidate}` };
|
|
3425
3425
|
}
|
|
3426
|
-
const rootReal = await realpath(projectRoot).catch(() =>
|
|
3427
|
-
const absolute =
|
|
3426
|
+
const rootReal = await realpath(projectRoot).catch(() => path17.resolve(projectRoot));
|
|
3427
|
+
const absolute = path17.resolve(rootReal, candidate);
|
|
3428
3428
|
const real = await realpath(absolute).catch(() => null);
|
|
3429
3429
|
const effective = real ?? absolute;
|
|
3430
3430
|
if (!isInside(rootReal, effective)) {
|
|
@@ -3764,16 +3764,16 @@ var init_schemas = __esm(() => {
|
|
|
3764
3764
|
});
|
|
3765
3765
|
|
|
3766
3766
|
// src/security/config.ts
|
|
3767
|
-
import
|
|
3767
|
+
import path18 from "path";
|
|
3768
3768
|
import { createHash as createHash3 } from "crypto";
|
|
3769
3769
|
function securityProjectRoot(cwd) {
|
|
3770
3770
|
return resolveProjectRoot(cwd);
|
|
3771
3771
|
}
|
|
3772
3772
|
function securityDataRoot(cwd) {
|
|
3773
|
-
return
|
|
3773
|
+
return path18.join(securityProjectRoot(cwd), ".metaproject", "data", "security");
|
|
3774
3774
|
}
|
|
3775
3775
|
function configPath(cwd) {
|
|
3776
|
-
return
|
|
3776
|
+
return path18.join(securityProjectRoot(cwd), ".metaproject", "security.config.json");
|
|
3777
3777
|
}
|
|
3778
3778
|
function mergePolicy(base, override) {
|
|
3779
3779
|
const merged = {
|
|
@@ -4381,7 +4381,7 @@ var init_entropy_gate = __esm(() => {
|
|
|
4381
4381
|
});
|
|
4382
4382
|
|
|
4383
4383
|
// src/security/redact.ts
|
|
4384
|
-
import
|
|
4384
|
+
import path19 from "path";
|
|
4385
4385
|
import { createHmac, randomBytes as randomBytes2 } from "crypto";
|
|
4386
4386
|
import { mkdir as mkdir4, readFile as readFile11, writeFile as writeFile3, chmod as chmod2 } from "fs/promises";
|
|
4387
4387
|
function maskFor(match) {
|
|
@@ -4461,11 +4461,11 @@ function redactSensitiveText(text) {
|
|
|
4461
4461
|
return applyRedaction(text, matches);
|
|
4462
4462
|
}
|
|
4463
4463
|
function keyDir(cwd) {
|
|
4464
|
-
return
|
|
4464
|
+
return path19.join(securityDataRoot(cwd), "raw");
|
|
4465
4465
|
}
|
|
4466
4466
|
async function getHmacKey(cwd) {
|
|
4467
4467
|
const dir = keyDir(cwd);
|
|
4468
|
-
const file =
|
|
4468
|
+
const file = path19.join(dir, KEY_FILE);
|
|
4469
4469
|
if (await pathExists(file)) {
|
|
4470
4470
|
const existing = (await readFile11(file, "utf8")).trim();
|
|
4471
4471
|
if (existing.length > 0) {
|
|
@@ -5033,9 +5033,9 @@ var init_output_validation = __esm(() => {
|
|
|
5033
5033
|
});
|
|
5034
5034
|
|
|
5035
5035
|
// src/assets/lock.ts
|
|
5036
|
-
import
|
|
5036
|
+
import path20 from "path";
|
|
5037
5037
|
function lockPath(cwd) {
|
|
5038
|
-
return
|
|
5038
|
+
return path20.join(cwd, ".metaproject", "assets.lock.json");
|
|
5039
5039
|
}
|
|
5040
5040
|
function normalizeLock(parsed) {
|
|
5041
5041
|
const assets = {};
|
|
@@ -5090,16 +5090,16 @@ var init_lock = __esm(() => {
|
|
|
5090
5090
|
import { createHash as createHash4 } from "crypto";
|
|
5091
5091
|
import { readFile as readFile12 } from "fs/promises";
|
|
5092
5092
|
import os2 from "os";
|
|
5093
|
-
import
|
|
5093
|
+
import path21 from "path";
|
|
5094
5094
|
function assetCacheDir() {
|
|
5095
5095
|
const override = process.env.KERYX_ASSET_CACHE;
|
|
5096
5096
|
if (override && override.length > 0) {
|
|
5097
5097
|
return override;
|
|
5098
5098
|
}
|
|
5099
|
-
return
|
|
5099
|
+
return path21.join(os2.homedir(), ".cache", "keryx", "assets");
|
|
5100
5100
|
}
|
|
5101
5101
|
function cacheAssetPath(id) {
|
|
5102
|
-
return
|
|
5102
|
+
return path21.join(assetCacheDir(), id);
|
|
5103
5103
|
}
|
|
5104
5104
|
async function sha256File(file) {
|
|
5105
5105
|
const buffer = await readFile12(file);
|
|
@@ -5151,9 +5151,9 @@ var init_warn_once = __esm(() => {
|
|
|
5151
5151
|
});
|
|
5152
5152
|
|
|
5153
5153
|
// src/capability/seam.ts
|
|
5154
|
-
import
|
|
5154
|
+
import path22 from "path";
|
|
5155
5155
|
async function isCapabilityEnabled(cwd, id) {
|
|
5156
|
-
const manifestPath =
|
|
5156
|
+
const manifestPath = path22.join(cwd, ".metaproject", "metaproject.json");
|
|
5157
5157
|
if (!await pathExists(manifestPath)) {
|
|
5158
5158
|
return false;
|
|
5159
5159
|
}
|
|
@@ -5792,7 +5792,7 @@ var init_resolve = __esm(() => {
|
|
|
5792
5792
|
});
|
|
5793
5793
|
|
|
5794
5794
|
// src/security/report.ts
|
|
5795
|
-
import
|
|
5795
|
+
import path23 from "path";
|
|
5796
5796
|
import { mkdir as mkdir5, writeFile as writeFile4 } from "fs/promises";
|
|
5797
5797
|
function tally(values) {
|
|
5798
5798
|
const counts = {};
|
|
@@ -5912,26 +5912,26 @@ function renderFindings(findings) {
|
|
|
5912
5912
|
`);
|
|
5913
5913
|
}
|
|
5914
5914
|
function artifactsDir(cwd) {
|
|
5915
|
-
return
|
|
5915
|
+
return path23.join(securityDataRoot(cwd), "artifacts");
|
|
5916
5916
|
}
|
|
5917
5917
|
async function writeSecurityArtifacts(cwd, report, config) {
|
|
5918
5918
|
const dir = artifactsDir(cwd);
|
|
5919
5919
|
await mkdir5(dir, { recursive: true });
|
|
5920
5920
|
const committable = toCommittableReport(report);
|
|
5921
|
-
const markdown =
|
|
5922
|
-
const json =
|
|
5921
|
+
const markdown = path23.join(dir, "latest.md");
|
|
5922
|
+
const json = path23.join(dir, "latest.json");
|
|
5923
5923
|
await writeFile4(markdown, renderReportMarkdown(committable), "utf8");
|
|
5924
5924
|
await writeFile4(json, `${JSON.stringify(committable, null, 2)}
|
|
5925
5925
|
`, "utf8");
|
|
5926
5926
|
if (config.storeHashes) {
|
|
5927
|
-
const rawDir =
|
|
5927
|
+
const rawDir = path23.join(securityDataRoot(cwd), "raw");
|
|
5928
5928
|
await mkdir5(rawDir, { recursive: true });
|
|
5929
|
-
await writeFile4(
|
|
5929
|
+
await writeFile4(path23.join(rawDir, "report.local.json"), `${JSON.stringify(report, null, 2)}
|
|
5930
5930
|
`, "utf8");
|
|
5931
5931
|
}
|
|
5932
5932
|
return {
|
|
5933
|
-
markdownPath:
|
|
5934
|
-
jsonPath:
|
|
5933
|
+
markdownPath: path23.relative(cwd, markdown),
|
|
5934
|
+
jsonPath: path23.relative(cwd, json)
|
|
5935
5935
|
};
|
|
5936
5936
|
}
|
|
5937
5937
|
var SCHEMA_VERSION = 1;
|
|
@@ -5940,13 +5940,13 @@ var init_report2 = __esm(() => {
|
|
|
5940
5940
|
});
|
|
5941
5941
|
|
|
5942
5942
|
// src/security/incidents.ts
|
|
5943
|
-
import
|
|
5943
|
+
import path24 from "path";
|
|
5944
5944
|
import { appendFile as appendFile2, mkdir as mkdir6, readFile as readFile13 } from "fs/promises";
|
|
5945
5945
|
function incidentsDir(cwd) {
|
|
5946
|
-
return
|
|
5946
|
+
return path24.join(securityDataRoot(cwd), "incidents");
|
|
5947
5947
|
}
|
|
5948
5948
|
function incidentsFile(cwd) {
|
|
5949
|
-
return
|
|
5949
|
+
return path24.join(incidentsDir(cwd), "incidents.jsonl");
|
|
5950
5950
|
}
|
|
5951
5951
|
async function appendIncident(cwd, entry) {
|
|
5952
5952
|
const dir = incidentsDir(cwd);
|
|
@@ -5965,7 +5965,7 @@ var init_incidents = __esm(() => {
|
|
|
5965
5965
|
});
|
|
5966
5966
|
|
|
5967
5967
|
// src/security/self-protect.ts
|
|
5968
|
-
import
|
|
5968
|
+
import path25 from "path";
|
|
5969
5969
|
import { mkdir as mkdir7, readFile as readFile14, writeFile as writeFile5 } from "fs/promises";
|
|
5970
5970
|
function currentState(config) {
|
|
5971
5971
|
const policies = {};
|
|
@@ -6024,7 +6024,7 @@ function evaluateSelfProtection(config, previous, now = new Date().toISOString()
|
|
|
6024
6024
|
return { warnings, incidents, findings, checksumMatch: checksum.match };
|
|
6025
6025
|
}
|
|
6026
6026
|
function stateFile(cwd) {
|
|
6027
|
-
return
|
|
6027
|
+
return path25.join(securityDataRoot(cwd), "raw", "state.json");
|
|
6028
6028
|
}
|
|
6029
6029
|
async function readState(cwd) {
|
|
6030
6030
|
const file = stateFile(cwd);
|
|
@@ -6039,7 +6039,7 @@ async function readState(cwd) {
|
|
|
6039
6039
|
}
|
|
6040
6040
|
async function writeState(cwd, state) {
|
|
6041
6041
|
const file = stateFile(cwd);
|
|
6042
|
-
await mkdir7(
|
|
6042
|
+
await mkdir7(path25.dirname(file), { recursive: true });
|
|
6043
6043
|
await writeFile5(file, `${JSON.stringify(state, null, 2)}
|
|
6044
6044
|
`, "utf8");
|
|
6045
6045
|
}
|
|
@@ -6057,12 +6057,12 @@ var init_self_protect = __esm(() => {
|
|
|
6057
6057
|
|
|
6058
6058
|
// src/lib/descriptor-read.ts
|
|
6059
6059
|
import { constants, fstatSync, lstatSync as lstatSync2, statSync } from "fs";
|
|
6060
|
-
import
|
|
6060
|
+
import path26 from "path";
|
|
6061
6061
|
import { dlopen, FFIType, ptr } from "bun:ffi";
|
|
6062
6062
|
function readDescriptorChain(workspaceRoot, absolutePath, options = {}) {
|
|
6063
|
-
const relativePath =
|
|
6064
|
-
const components = relativePath.split(
|
|
6065
|
-
if (!relativePath ||
|
|
6063
|
+
const relativePath = path26.relative(workspaceRoot, absolutePath);
|
|
6064
|
+
const components = relativePath.split(path26.sep);
|
|
6065
|
+
if (!relativePath || path26.isAbsolute(relativePath) || components.some((component) => !component || component === "." || component === "..")) {
|
|
6066
6066
|
throw new DescriptorReadError("invalid-path", "safe source path is not workspace-relative");
|
|
6067
6067
|
}
|
|
6068
6068
|
if (options.maxBytes !== undefined && (!Number.isSafeInteger(options.maxBytes) || options.maxBytes < 0)) {
|
|
@@ -6185,7 +6185,7 @@ var init_descriptor_read = __esm(() => {
|
|
|
6185
6185
|
|
|
6186
6186
|
// src/lib/contained-read.ts
|
|
6187
6187
|
import { lstat as lstat3, realpath as realpath2, stat as stat3 } from "fs/promises";
|
|
6188
|
-
import
|
|
6188
|
+
import path27 from "path";
|
|
6189
6189
|
async function readContainedFile(ownerRoot, candidatePath, options = {}) {
|
|
6190
6190
|
if (options.backend === "unsupported") {
|
|
6191
6191
|
throw new ContainedReadError("CONTAINED_READ_UNAVAILABLE", "safe descriptor source reads are unavailable on this platform");
|
|
@@ -6234,8 +6234,8 @@ async function readContainedFile(ownerRoot, candidatePath, options = {}) {
|
|
|
6234
6234
|
}
|
|
6235
6235
|
}
|
|
6236
6236
|
function isInside2(root, candidate) {
|
|
6237
|
-
const relative =
|
|
6238
|
-
return relative === "" || !
|
|
6237
|
+
const relative = path27.relative(root, candidate);
|
|
6238
|
+
return relative === "" || !path27.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path27.sep}`);
|
|
6239
6239
|
}
|
|
6240
6240
|
function mapDescriptorError(error) {
|
|
6241
6241
|
if (!(error instanceof DescriptorReadError))
|
|
@@ -6260,16 +6260,16 @@ var init_contained_read = __esm(() => {
|
|
|
6260
6260
|
|
|
6261
6261
|
// src/security/path-scan.ts
|
|
6262
6262
|
import { readdir as readdir6, realpath as realpath3, stat as stat4 } from "fs/promises";
|
|
6263
|
-
import
|
|
6263
|
+
import path28 from "path";
|
|
6264
6264
|
function isInside3(root, candidate) {
|
|
6265
|
-
const relative =
|
|
6266
|
-
return relative === "" || !
|
|
6265
|
+
const relative = path28.relative(root, candidate);
|
|
6266
|
+
return relative === "" || !path28.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path28.sep}`);
|
|
6267
6267
|
}
|
|
6268
6268
|
function identityFor(value) {
|
|
6269
6269
|
return `${String(value.dev)}:${String(value.ino)}`;
|
|
6270
6270
|
}
|
|
6271
6271
|
function relativePath(root, candidate) {
|
|
6272
|
-
const relative =
|
|
6272
|
+
const relative = path28.relative(root, candidate);
|
|
6273
6273
|
return relative === "" ? "." : relative;
|
|
6274
6274
|
}
|
|
6275
6275
|
function safeReason(error) {
|
|
@@ -6298,7 +6298,7 @@ async function secretBearingFilesIn(dirAbsolute, remainingDepth) {
|
|
|
6298
6298
|
}
|
|
6299
6299
|
const matches = [];
|
|
6300
6300
|
for (const entry of entries) {
|
|
6301
|
-
const entryPath =
|
|
6301
|
+
const entryPath = path28.join(dirAbsolute, entry);
|
|
6302
6302
|
let entryStat;
|
|
6303
6303
|
try {
|
|
6304
6304
|
entryStat = await stat4(entryPath);
|
|
@@ -6362,14 +6362,14 @@ async function scanContainedPath(input) {
|
|
|
6362
6362
|
throw new Error("security scan target is outside the project root");
|
|
6363
6363
|
}
|
|
6364
6364
|
const exclusions = (input.exclusions ?? []).map((entry) => {
|
|
6365
|
-
const absolute =
|
|
6365
|
+
const absolute = path28.resolve(ownerRoot, entry);
|
|
6366
6366
|
return isInside3(ownerRoot, absolute) ? absolute : null;
|
|
6367
6367
|
}).filter((entry) => entry !== null);
|
|
6368
6368
|
const scope = {
|
|
6369
6369
|
path: relativePath(ownerRoot, targetReal),
|
|
6370
6370
|
recursive: input.recursive ?? true,
|
|
6371
6371
|
exclusions: (input.exclusions ?? []).map((entry) => {
|
|
6372
|
-
const absolute =
|
|
6372
|
+
const absolute = path28.resolve(ownerRoot, entry);
|
|
6373
6373
|
return isInside3(ownerRoot, absolute) ? relativePath(ownerRoot, absolute) : "[external exclusion omitted]";
|
|
6374
6374
|
}),
|
|
6375
6375
|
limits
|
|
@@ -6390,15 +6390,15 @@ async function scanContainedPath(input) {
|
|
|
6390
6390
|
if (!coverage.reasons.includes(reason))
|
|
6391
6391
|
coverage.reasons.push(reason);
|
|
6392
6392
|
};
|
|
6393
|
-
const excluded = (candidate) => exclusions.some((entry) => candidate === entry || candidate.startsWith(`${entry}${
|
|
6393
|
+
const excluded = (candidate) => exclusions.some((entry) => candidate === entry || candidate.startsWith(`${entry}${path28.sep}`));
|
|
6394
6394
|
const visit = async (candidate, depth) => {
|
|
6395
6395
|
if (stoppedByLimit)
|
|
6396
6396
|
return;
|
|
6397
6397
|
const displayPath = relativePath(ownerRoot, candidate);
|
|
6398
6398
|
if (respectIgnoreRules) {
|
|
6399
|
-
const normalized = displayPath.split(
|
|
6399
|
+
const normalized = displayPath.split(path28.sep).join("/");
|
|
6400
6400
|
if (isIgnoredPath(ignoredPaths, normalized)) {
|
|
6401
|
-
const basename =
|
|
6401
|
+
const basename = path28.basename(displayPath);
|
|
6402
6402
|
const inHardcodedIgnore = ALWAYS_IGNORED_RELATIVE_DIRS.some((dir) => normalized === dir || normalized.startsWith(`${dir}/`));
|
|
6403
6403
|
if (!inHardcodedIgnore && looksSecretBearingByName(basename)) {} else {
|
|
6404
6404
|
if (!inHardcodedIgnore) {
|
|
@@ -6480,7 +6480,7 @@ async function scanContainedPath(input) {
|
|
|
6480
6480
|
return;
|
|
6481
6481
|
}
|
|
6482
6482
|
for (const entry of entries) {
|
|
6483
|
-
await visit(
|
|
6483
|
+
await visit(path28.join(canonical, entry), depth + 1);
|
|
6484
6484
|
if (stoppedByLimit)
|
|
6485
6485
|
break;
|
|
6486
6486
|
}
|
|
@@ -6555,7 +6555,7 @@ var init_path_scan = __esm(() => {
|
|
|
6555
6555
|
|
|
6556
6556
|
// src/security/read-source.ts
|
|
6557
6557
|
import { realpath as realpath4, stat as stat5 } from "fs/promises";
|
|
6558
|
-
import
|
|
6558
|
+
import path29 from "path";
|
|
6559
6559
|
async function sourceForFileRead(cwd, absolutePath) {
|
|
6560
6560
|
const projectRoot = resolveProjectRoot(cwd);
|
|
6561
6561
|
const contained = await resolveContainedPath(projectRoot, absolutePath);
|
|
@@ -6563,8 +6563,8 @@ async function sourceForFileRead(cwd, absolutePath) {
|
|
|
6563
6563
|
return "untrusted-external";
|
|
6564
6564
|
}
|
|
6565
6565
|
const projectRootReal = await realpath4(projectRoot).catch(() => projectRoot);
|
|
6566
|
-
const relativePath =
|
|
6567
|
-
if (relativePath.length === 0 ||
|
|
6566
|
+
const relativePath = path29.relative(projectRootReal, contained.path);
|
|
6567
|
+
if (relativePath.length === 0 || path29.isAbsolute(relativePath)) {
|
|
6568
6568
|
return "untrusted-external";
|
|
6569
6569
|
}
|
|
6570
6570
|
const fileStat = await stat5(contained.path).catch(() => null);
|
|
@@ -6931,9 +6931,9 @@ var SUBSYSTEM_INSTRUCTIONS = "instructions", SUBSYSTEM_ACP_PERMISSION = "acp-per
|
|
|
6931
6931
|
|
|
6932
6932
|
// src/lib/symlink-safety.ts
|
|
6933
6933
|
import { lstat as lstat4, realpath as realpath5 } from "fs/promises";
|
|
6934
|
-
import
|
|
6934
|
+
import path30 from "path";
|
|
6935
6935
|
async function refuseEscapingSymlink(root, relativePath) {
|
|
6936
|
-
const rootResolved =
|
|
6936
|
+
const rootResolved = path30.resolve(root);
|
|
6937
6937
|
let rootReal;
|
|
6938
6938
|
try {
|
|
6939
6939
|
rootReal = await realpath5(rootResolved);
|
|
@@ -6943,7 +6943,7 @@ async function refuseEscapingSymlink(root, relativePath) {
|
|
|
6943
6943
|
const segments = relativePath.split("/").filter((s) => s.length > 0);
|
|
6944
6944
|
let current = rootResolved;
|
|
6945
6945
|
for (const segment of segments) {
|
|
6946
|
-
current =
|
|
6946
|
+
current = path30.join(current, segment);
|
|
6947
6947
|
let stats;
|
|
6948
6948
|
try {
|
|
6949
6949
|
stats = await lstat4(current);
|
|
@@ -6956,21 +6956,21 @@ async function refuseEscapingSymlink(root, relativePath) {
|
|
|
6956
6956
|
try {
|
|
6957
6957
|
real = await realpath5(current);
|
|
6958
6958
|
} catch {
|
|
6959
|
-
return `${relativePath}: refuses to write through a broken symlink at ${
|
|
6959
|
+
return `${relativePath}: refuses to write through a broken symlink at ${path30.relative(rootResolved, current) || "."}`;
|
|
6960
6960
|
}
|
|
6961
|
-
const rel =
|
|
6962
|
-
const escapes = rel === ".." || rel.startsWith(`..${
|
|
6961
|
+
const rel = path30.relative(rootReal, real);
|
|
6962
|
+
const escapes = rel === ".." || rel.startsWith(`..${path30.sep}`) || path30.isAbsolute(rel);
|
|
6963
6963
|
if (escapes) {
|
|
6964
|
-
return `${relativePath}: refuses to write through a symlink at ${
|
|
6964
|
+
return `${relativePath}: refuses to write through a symlink at ${path30.relative(rootResolved, current) || "."} that resolves outside the project root`;
|
|
6965
6965
|
}
|
|
6966
6966
|
if (hasGitSegment(rel)) {
|
|
6967
|
-
return `${relativePath}: refuses to write through a symlink at ${
|
|
6967
|
+
return `${relativePath}: refuses to write through a symlink at ${path30.relative(rootResolved, current) || "."} that resolves through a .git directory`;
|
|
6968
6968
|
}
|
|
6969
6969
|
}
|
|
6970
6970
|
return;
|
|
6971
6971
|
}
|
|
6972
6972
|
function hasGitSegment(rel) {
|
|
6973
|
-
return rel.split(
|
|
6973
|
+
return rel.split(path30.sep).some((segment) => segment.toLowerCase() === ".git");
|
|
6974
6974
|
}
|
|
6975
6975
|
var SymlinkRefusedError;
|
|
6976
6976
|
var init_symlink_safety = __esm(() => {
|
|
@@ -6982,12 +6982,12 @@ var init_symlink_safety = __esm(() => {
|
|
|
6982
6982
|
import { chmod as chmod3, lstat as lstat5, mkdir as mkdir8, open, readdir as readdir7, realpath as realpath6, rename as rename4, rm as rm3, rmdir, stat as stat6 } from "fs/promises";
|
|
6983
6983
|
import { constants as fsConstants } from "fs";
|
|
6984
6984
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
6985
|
-
import
|
|
6985
|
+
import path31 from "path";
|
|
6986
6986
|
function splitRel(rel) {
|
|
6987
6987
|
return rel.split("/").filter((s) => s.length > 0);
|
|
6988
6988
|
}
|
|
6989
6989
|
function assertSafeRel(rel) {
|
|
6990
|
-
if (
|
|
6990
|
+
if (path31.isAbsolute(rel)) {
|
|
6991
6991
|
throw new ContainedWriteError("absolute-path", `${rel}: refuses an absolute path`);
|
|
6992
6992
|
}
|
|
6993
6993
|
const segments = splitRel(rel);
|
|
@@ -7006,10 +7006,10 @@ function assertSafeRel(rel) {
|
|
|
7006
7006
|
return nonDotSegments;
|
|
7007
7007
|
}
|
|
7008
7008
|
async function assertNoCycleOrDangling(root, rel, segments) {
|
|
7009
|
-
const rootResolved =
|
|
7009
|
+
const rootResolved = path31.resolve(root);
|
|
7010
7010
|
let current = rootResolved;
|
|
7011
7011
|
for (const segment of segments) {
|
|
7012
|
-
current =
|
|
7012
|
+
current = path31.join(current, segment);
|
|
7013
7013
|
let stats;
|
|
7014
7014
|
try {
|
|
7015
7015
|
stats = await lstat5(current);
|
|
@@ -7022,7 +7022,7 @@ async function assertNoCycleOrDangling(root, rel, segments) {
|
|
|
7022
7022
|
await realpath6(current);
|
|
7023
7023
|
} catch (error) {
|
|
7024
7024
|
const code = error.code;
|
|
7025
|
-
const at =
|
|
7025
|
+
const at = path31.relative(rootResolved, current) || ".";
|
|
7026
7026
|
if (code === "ELOOP") {
|
|
7027
7027
|
throw new ContainedWriteError("symlink-cycle", `${rel}: refuses a symlink cycle at ${at}`);
|
|
7028
7028
|
}
|
|
@@ -7037,13 +7037,13 @@ async function assertContained(root, rel, opts = {}) {
|
|
|
7037
7037
|
if (refusal) {
|
|
7038
7038
|
throw new ContainedWriteError("escaping-symlink", refusal);
|
|
7039
7039
|
}
|
|
7040
|
-
const rootResolved =
|
|
7041
|
-
const targetPath =
|
|
7040
|
+
const rootResolved = path31.resolve(root);
|
|
7041
|
+
const targetPath = path31.join(rootResolved, ...segments);
|
|
7042
7042
|
const rootReal = await realpath6(rootResolved).catch(() => rootResolved);
|
|
7043
7043
|
const targetReal = await realpath6(targetPath).catch(() => null);
|
|
7044
7044
|
if (targetReal !== null) {
|
|
7045
|
-
const relToRoot =
|
|
7046
|
-
const escapes = relToRoot === ".." || relToRoot.startsWith(`..${
|
|
7045
|
+
const relToRoot = path31.relative(rootReal, targetReal);
|
|
7046
|
+
const escapes = relToRoot === ".." || relToRoot.startsWith(`..${path31.sep}`) || path31.isAbsolute(relToRoot);
|
|
7047
7047
|
if (escapes) {
|
|
7048
7048
|
throw new ContainedWriteError("not-contained", `${rel}: resolves outside ${rootReal}`);
|
|
7049
7049
|
}
|
|
@@ -7065,7 +7065,7 @@ async function assertContained(root, rel, opts = {}) {
|
|
|
7065
7065
|
}
|
|
7066
7066
|
}
|
|
7067
7067
|
const resolvedPath = targetReal ?? targetPath;
|
|
7068
|
-
return { targetPath, dir:
|
|
7068
|
+
return { targetPath, dir: path31.dirname(targetPath), resolvedPath, resolvedDir: path31.dirname(resolvedPath) };
|
|
7069
7069
|
}
|
|
7070
7070
|
async function pathExistsLstat(p) {
|
|
7071
7071
|
try {
|
|
@@ -7102,7 +7102,7 @@ async function writeContained(root, rel, data, opts = {}) {
|
|
|
7102
7102
|
} catch {
|
|
7103
7103
|
existingMode = undefined;
|
|
7104
7104
|
}
|
|
7105
|
-
const tmp =
|
|
7105
|
+
const tmp = path31.join(resolvedDir, `.${path31.basename(resolvedPath)}.tmp-${randomBytes3(6).toString("hex")}`);
|
|
7106
7106
|
try {
|
|
7107
7107
|
const handle = await open(tmp, "wx", opts.mode);
|
|
7108
7108
|
try {
|
|
@@ -7371,7 +7371,7 @@ var init_codecs = __esm(() => {
|
|
|
7371
7371
|
});
|
|
7372
7372
|
|
|
7373
7373
|
// src/integrations/surfaces.ts
|
|
7374
|
-
import
|
|
7374
|
+
import path32 from "path";
|
|
7375
7375
|
function ctxHookCommand(id) {
|
|
7376
7376
|
return `keryx ctx hook ${id}`;
|
|
7377
7377
|
}
|
|
@@ -7416,7 +7416,7 @@ function nestedCtxSurface(opts) {
|
|
|
7416
7416
|
confidence,
|
|
7417
7417
|
sourceDocs,
|
|
7418
7418
|
...riskNotes !== undefined ? { riskNotes } : {},
|
|
7419
|
-
settingsFile: (root) =>
|
|
7419
|
+
settingsFile: (root) => path32.join(root, ...relativePath.split("/")),
|
|
7420
7420
|
relativePath,
|
|
7421
7421
|
slots: [
|
|
7422
7422
|
{ key: container ?? "hooks", type: "object", access: "owns" },
|
|
@@ -7530,7 +7530,7 @@ function flatSecuritySurface(harnessId, on, relativePath) {
|
|
|
7530
7530
|
"`securityHooks` matches no documented hook contract for this harness; it is keryx's own invention (tracked as OQ-3)."
|
|
7531
7531
|
],
|
|
7532
7532
|
sourceDocs: ["src/security/agent-hooks/runtimes.ts"],
|
|
7533
|
-
settingsFile: (root) =>
|
|
7533
|
+
settingsFile: (root) => path32.join(root, ...relativePath.split("/")),
|
|
7534
7534
|
relativePath,
|
|
7535
7535
|
slots: [
|
|
7536
7536
|
{ key: SECURITY_HOOKS_KEY, type: "array", access: "owns" },
|
|
@@ -7609,7 +7609,7 @@ var init_surfaces = __esm(() => {
|
|
|
7609
7609
|
sentinel: CTX_HOOK_SENTINEL,
|
|
7610
7610
|
confidence: "verified",
|
|
7611
7611
|
sourceDocs: ["src/ctx/runtimes.ts"],
|
|
7612
|
-
settingsFile: (root) =>
|
|
7612
|
+
settingsFile: (root) => path32.join(root, ".cursor", "hooks.json"),
|
|
7613
7613
|
relativePath: ".cursor/hooks.json",
|
|
7614
7614
|
slots: [
|
|
7615
7615
|
{ key: "hooks", type: "object", access: "owns" },
|
|
@@ -7636,7 +7636,7 @@ var init_surfaces = __esm(() => {
|
|
|
7636
7636
|
sentinel: CTX_HOOK_SENTINEL,
|
|
7637
7637
|
confidence: "verified",
|
|
7638
7638
|
sourceDocs: ["src/ctx/runtimes.ts"],
|
|
7639
|
-
settingsFile: (root) =>
|
|
7639
|
+
settingsFile: (root) => path32.join(root, ".windsurf", "hooks.json"),
|
|
7640
7640
|
relativePath: ".windsurf/hooks.json",
|
|
7641
7641
|
slots: [
|
|
7642
7642
|
{ key: "hooks", type: "object", access: "owns" },
|
|
@@ -7660,7 +7660,7 @@ var init_surfaces = __esm(() => {
|
|
|
7660
7660
|
confidence: "experimental",
|
|
7661
7661
|
riskNotes: ["No first-party docs confirm this hook contract; verify on a live install."],
|
|
7662
7662
|
sourceDocs: ["src/ctx/runtimes.ts"],
|
|
7663
|
-
settingsFile: (root) =>
|
|
7663
|
+
settingsFile: (root) => path32.join(root, ".agents", "hooks.json"),
|
|
7664
7664
|
relativePath: ".agents/hooks.json",
|
|
7665
7665
|
slots: [
|
|
7666
7666
|
{ key: ANTIGRAVITY_CONTAINER, type: "object", access: "owns" },
|
|
@@ -7713,7 +7713,7 @@ var init_surfaces = __esm(() => {
|
|
|
7713
7713
|
confidence: "experimental",
|
|
7714
7714
|
riskNotes: ["Bridged via a generated plugin file rather than a documented hook config."],
|
|
7715
7715
|
sourceDocs: ["src/ctx/runtimes.ts"],
|
|
7716
|
-
settingsFile: (root) =>
|
|
7716
|
+
settingsFile: (root) => path32.join(root, ...OPENCODE_PLUGIN_RELATIVE_PATH.split("/")),
|
|
7717
7717
|
relativePath: OPENCODE_PLUGIN_RELATIVE_PATH,
|
|
7718
7718
|
slots: [],
|
|
7719
7719
|
label: OPENCODE_PLUGIN_RELATIVE_PATH,
|
|
@@ -7750,7 +7750,7 @@ var init_surfaces = __esm(() => {
|
|
|
7750
7750
|
sentinel: ORIENT_SENTINEL,
|
|
7751
7751
|
confidence: "verified",
|
|
7752
7752
|
sourceDocs: ["src/ctx/orient-runtimes.ts"],
|
|
7753
|
-
settingsFile: (root) =>
|
|
7753
|
+
settingsFile: (root) => path32.join(root, ".claude", "settings.json"),
|
|
7754
7754
|
relativePath: ".claude/settings.json",
|
|
7755
7755
|
slots: [
|
|
7756
7756
|
{ key: "hooks", type: "object", access: "owns" },
|
|
@@ -7771,7 +7771,7 @@ var init_surfaces = __esm(() => {
|
|
|
7771
7771
|
sentinel: ORIENT_SENTINEL,
|
|
7772
7772
|
confidence: "verified",
|
|
7773
7773
|
sourceDocs: ["src/ctx/orient-runtimes.ts"],
|
|
7774
|
-
settingsFile: (root) =>
|
|
7774
|
+
settingsFile: (root) => path32.join(root, ".codex", "hooks.json"),
|
|
7775
7775
|
relativePath: ".codex/hooks.json",
|
|
7776
7776
|
slots: [
|
|
7777
7777
|
{ key: "hooks", type: "object", access: "owns" },
|
|
@@ -7792,7 +7792,7 @@ var init_surfaces = __esm(() => {
|
|
|
7792
7792
|
sentinel: ORIENT_SENTINEL,
|
|
7793
7793
|
confidence: "verified",
|
|
7794
7794
|
sourceDocs: ["src/ctx/orient-runtimes.ts"],
|
|
7795
|
-
settingsFile: (root) =>
|
|
7795
|
+
settingsFile: (root) => path32.join(root, ".cursor", "hooks.json"),
|
|
7796
7796
|
relativePath: ".cursor/hooks.json",
|
|
7797
7797
|
slots: [
|
|
7798
7798
|
{ key: "hooks", type: "object", access: "owns" },
|
|
@@ -7823,7 +7823,7 @@ var init_surfaces = __esm(() => {
|
|
|
7823
7823
|
sentinel: AGENT_HOOKS_SENTINEL,
|
|
7824
7824
|
confidence: "verified",
|
|
7825
7825
|
sourceDocs: ["src/security/agent-hooks/runtimes.ts"],
|
|
7826
|
-
settingsFile: (root) =>
|
|
7826
|
+
settingsFile: (root) => path32.join(root, ".claude", "settings.json"),
|
|
7827
7827
|
relativePath: ".claude/settings.json",
|
|
7828
7828
|
slots: [
|
|
7829
7829
|
{ key: "hooks", type: "object", access: "owns" },
|
|
@@ -7843,7 +7843,7 @@ var init_surfaces = __esm(() => {
|
|
|
7843
7843
|
sentinel: AGENT_HOOKS_SENTINEL,
|
|
7844
7844
|
confidence: "verified",
|
|
7845
7845
|
sourceDocs: ["src/security/agent-hooks/runtimes.ts"],
|
|
7846
|
-
settingsFile: (root) =>
|
|
7846
|
+
settingsFile: (root) => path32.join(root, ".claude", "settings.json"),
|
|
7847
7847
|
relativePath: ".claude/settings.json",
|
|
7848
7848
|
slots: [
|
|
7849
7849
|
{ key: "hooks", type: "object", access: "owns" },
|
|
@@ -7870,7 +7870,7 @@ var init_surfaces = __esm(() => {
|
|
|
7870
7870
|
|
|
7871
7871
|
// src/integrations/markdown-block.ts
|
|
7872
7872
|
import { readFile as readFile15 } from "fs/promises";
|
|
7873
|
-
import
|
|
7873
|
+
import path33 from "path";
|
|
7874
7874
|
function dominantEol(content) {
|
|
7875
7875
|
const crlf = (content.match(/\r\n/g) ?? []).length;
|
|
7876
7876
|
const totalLf = (content.match(/\n/g) ?? []).length;
|
|
@@ -8012,7 +8012,7 @@ function appendBlock(content, block, eol) {
|
|
|
8012
8012
|
return endsWithEol(content) ? `${content}${eol}${block}` : `${content}${eol}${eol}${block}`;
|
|
8013
8013
|
}
|
|
8014
8014
|
function fileFor(root, relativePath) {
|
|
8015
|
-
return
|
|
8015
|
+
return path33.join(root, ...relativePath.split("/"));
|
|
8016
8016
|
}
|
|
8017
8017
|
async function installMarkdownBlock(root, relativePath, frontMatter, spec = INSTRUCTIONS_BLOCK_SPEC) {
|
|
8018
8018
|
const symlinkRefusal = await refuseEscapingSymlink(root, relativePath);
|
|
@@ -8124,7 +8124,7 @@ var init_markdown_block = __esm(() => {
|
|
|
8124
8124
|
});
|
|
8125
8125
|
|
|
8126
8126
|
// src/integrations/surfaces-w5b.ts
|
|
8127
|
-
import
|
|
8127
|
+
import path34 from "path";
|
|
8128
8128
|
function kiroHookEntry() {
|
|
8129
8129
|
return {
|
|
8130
8130
|
name: KIRO_HOOK_ID,
|
|
@@ -8151,7 +8151,7 @@ function copilotHookEntry() {
|
|
|
8151
8151
|
};
|
|
8152
8152
|
}
|
|
8153
8153
|
async function agentsMdHasKeryxBlock(root) {
|
|
8154
|
-
const file =
|
|
8154
|
+
const file = path34.join(root, "AGENTS.md");
|
|
8155
8155
|
if (!await pathExists(file))
|
|
8156
8156
|
return false;
|
|
8157
8157
|
const { readFile } = await import("fs/promises");
|
|
@@ -8209,7 +8209,7 @@ var init_surfaces_w5b = __esm(() => {
|
|
|
8209
8209
|
confidence: "experimental",
|
|
8210
8210
|
riskNotes: ["Whether Gemini CLI actually reads GEMINI.md end-to-end (beyond the documented context.fileName option) is not independently confirmed here."],
|
|
8211
8211
|
sourceDocs: ["https://github.com/google-gemini/gemini-cli/blob/main/docs/cli/gemini-md.md"],
|
|
8212
|
-
settingsFile: (root) =>
|
|
8212
|
+
settingsFile: (root) => path34.join(root, "GEMINI.md"),
|
|
8213
8213
|
relativePath: "GEMINI.md",
|
|
8214
8214
|
slots: [],
|
|
8215
8215
|
customInstall: (root) => installMarkdownBlock(root, "GEMINI.md"),
|
|
@@ -8233,7 +8233,7 @@ var init_surfaces_w5b = __esm(() => {
|
|
|
8233
8233
|
"Kiro's hook stdin field names and its shell tool's name are third-party-reported only, not confirmed by first-party docs \u2014 the matcher above is a best guess and may gate nothing on a real install; verify before relying on it."
|
|
8234
8234
|
],
|
|
8235
8235
|
sourceDocs: KIRO_SOURCE_DOCS,
|
|
8236
|
-
settingsFile: (root) =>
|
|
8236
|
+
settingsFile: (root) => path34.join(root, ".kiro", "hooks", "keryx-ctx-guard.json"),
|
|
8237
8237
|
relativePath: ".kiro/hooks/keryx-ctx-guard.json",
|
|
8238
8238
|
slots: [
|
|
8239
8239
|
{ key: "version", type: "string", access: "owns" },
|
|
@@ -8278,7 +8278,7 @@ var init_surfaces_w5b = __esm(() => {
|
|
|
8278
8278
|
"Open Kiro issues report that steering file `inclusion` modes are not always honoured, even with `inclusion: always` set \u2014 verify on a live install."
|
|
8279
8279
|
],
|
|
8280
8280
|
sourceDocs: ["https://kiro.dev/docs/steering/"],
|
|
8281
|
-
settingsFile: (root) =>
|
|
8281
|
+
settingsFile: (root) => path34.join(root, ".kiro", "steering", "keryx.md"),
|
|
8282
8282
|
relativePath: ".kiro/steering/keryx.md",
|
|
8283
8283
|
slots: [],
|
|
8284
8284
|
customInstall: (root) => installMarkdownBlock(root, ".kiro/steering/keryx.md", KIRO_STEERING_FRONT_MATTER),
|
|
@@ -8301,7 +8301,7 @@ var init_surfaces_w5b = __esm(() => {
|
|
|
8301
8301
|
"The shell tool's name Copilot's hook payload carries is not documented; this guard parses any tool call whose payload carries `toolArgs.command`, whatever `toolName` is."
|
|
8302
8302
|
],
|
|
8303
8303
|
sourceDocs: COPILOT_SOURCE_DOCS,
|
|
8304
|
-
settingsFile: (root) =>
|
|
8304
|
+
settingsFile: (root) => path34.join(root, ".github", "hooks", "keryx-ctx-guard.json"),
|
|
8305
8305
|
relativePath: ".github/hooks/keryx-ctx-guard.json",
|
|
8306
8306
|
slots: [
|
|
8307
8307
|
{ key: "version", type: "number", access: "owns" },
|
|
@@ -8345,7 +8345,7 @@ var init_surfaces_w5b = __esm(() => {
|
|
|
8345
8345
|
"https://docs.github.com/en/copilot/how-tos/configure-custom-instructions-in-your-ide/add-repository-instructions-in-your-ide",
|
|
8346
8346
|
"https://github.blog/changelog/2025-08-28-copilot-coding-agent-now-supports-agents-md-custom-instructions/"
|
|
8347
8347
|
],
|
|
8348
|
-
settingsFile: (root) =>
|
|
8348
|
+
settingsFile: (root) => path34.join(root, ".github", "copilot-instructions.md"),
|
|
8349
8349
|
relativePath: ".github/copilot-instructions.md",
|
|
8350
8350
|
slots: [],
|
|
8351
8351
|
customInstall: (root) => installMarkdownBlock(root, ".github/copilot-instructions.md"),
|
|
@@ -8384,7 +8384,7 @@ var init_surfaces_w5b = __esm(() => {
|
|
|
8384
8384
|
`Zed uses the first matching rules file among ${ZED_SHADOWING_RULES_FILES.join(", ")}, AGENT.md, AGENTS.md, CLAUDE.md, GEMINI.md, ... \u2014 an earlier file in that list shadows AGENTS.md even when AGENTS.md itself carries Keryx's block.`
|
|
8385
8385
|
],
|
|
8386
8386
|
sourceDocs: ["https://github.com/zed-industries/zed/blob/main/docs/src/ai/rules.md"],
|
|
8387
|
-
settingsFile: (root) =>
|
|
8387
|
+
settingsFile: (root) => path34.join(root, "AGENTS.md"),
|
|
8388
8388
|
relativePath: "AGENTS.md",
|
|
8389
8389
|
slots: [],
|
|
8390
8390
|
probe: async (root) => await agentsMdHasKeryxBlock(root) ? [] : ["zed: AGENTS.md is missing or missing Keryx's block \u2014 run `keryx update`"]
|
|
@@ -8614,7 +8614,7 @@ function parseSkillFrontmatter(content) {
|
|
|
8614
8614
|
|
|
8615
8615
|
// src/gdskills/catalog.ts
|
|
8616
8616
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
8617
|
-
import
|
|
8617
|
+
import path35 from "path";
|
|
8618
8618
|
import { fileURLToPath } from "url";
|
|
8619
8619
|
function skill(name, category, profiles, purpose, workflow) {
|
|
8620
8620
|
let routing;
|
|
@@ -8637,10 +8637,10 @@ function renderedSkill(name, category, profiles, purpose, workflow, triggers, de
|
|
|
8637
8637
|
return { name, category, description, purpose, workflow, triggers, profiles };
|
|
8638
8638
|
}
|
|
8639
8639
|
function bundledSkillMarkdownPath(category, name) {
|
|
8640
|
-
const here =
|
|
8640
|
+
const here = path35.dirname(fileURLToPath(import.meta.url));
|
|
8641
8641
|
return [
|
|
8642
|
-
|
|
8643
|
-
|
|
8642
|
+
path35.join(here, "bundled", "skills", category, name, "SKILL.md"),
|
|
8643
|
+
path35.join(here, "..", "src", "gdskills", "bundled", "skills", category, name, "SKILL.md")
|
|
8644
8644
|
].find((candidate) => existsSync2(candidate));
|
|
8645
8645
|
}
|
|
8646
8646
|
function readBundledSkillRouting(category, name) {
|
|
@@ -9150,7 +9150,7 @@ var init_catalog = __esm(() => {
|
|
|
9150
9150
|
"Sync only selected skills and report changed files."
|
|
9151
9151
|
], ["sync skills", "install runtime skills", "global skill sync"], "Use when already-exported runtime skills need pushing to configured local runtimes, and only when sync is explicitly enabled. NOT for: producing the runtime export itself (see skill-runtime-exporter).")
|
|
9152
9152
|
];
|
|
9153
|
-
BUNDLED_TREE_MARKER =
|
|
9153
|
+
BUNDLED_TREE_MARKER = path35.join("src", "gdskills", "bundled");
|
|
9154
9154
|
});
|
|
9155
9155
|
|
|
9156
9156
|
// src/gdskills/resolve.ts
|
|
@@ -9284,12 +9284,12 @@ var init_skill_length_ceilings = __esm(() => {
|
|
|
9284
9284
|
|
|
9285
9285
|
// src/gdskills/bundled-eval.ts
|
|
9286
9286
|
import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync } from "fs";
|
|
9287
|
-
import
|
|
9287
|
+
import path36 from "path";
|
|
9288
9288
|
function defaultBundledRoot() {
|
|
9289
|
-
const directPath =
|
|
9289
|
+
const directPath = path36.join(import.meta.dir, "bundled");
|
|
9290
9290
|
if (existsSync3(directPath))
|
|
9291
9291
|
return directPath;
|
|
9292
|
-
const packagedPath =
|
|
9292
|
+
const packagedPath = path36.join(import.meta.dir, "..", "src", "gdskills", "bundled");
|
|
9293
9293
|
if (existsSync3(packagedPath))
|
|
9294
9294
|
return packagedPath;
|
|
9295
9295
|
return directPath;
|
|
@@ -9806,12 +9806,12 @@ var init_schema = __esm(() => {
|
|
|
9806
9806
|
|
|
9807
9807
|
// src/agents/catalog.ts
|
|
9808
9808
|
import { existsSync as existsSync4, readdirSync as readdirSync2, readFileSync as readFileSync4 } from "fs";
|
|
9809
|
-
import
|
|
9809
|
+
import path37 from "path";
|
|
9810
9810
|
function agentDefinitionFiles(dir) {
|
|
9811
9811
|
if (!existsSync4(dir)) {
|
|
9812
9812
|
return [];
|
|
9813
9813
|
}
|
|
9814
|
-
return readdirSync2(dir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".md")).map((entry) =>
|
|
9814
|
+
return readdirSync2(dir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".md")).map((entry) => path37.join(dir, entry.name)).sort();
|
|
9815
9815
|
}
|
|
9816
9816
|
function loadOne(filePath, kind) {
|
|
9817
9817
|
let raw;
|
|
@@ -9843,7 +9843,7 @@ function loadOne(filePath, kind) {
|
|
|
9843
9843
|
};
|
|
9844
9844
|
}
|
|
9845
9845
|
const definition = buildAgentDefinition(parsed.result.data, parsed.result.body);
|
|
9846
|
-
const stem =
|
|
9846
|
+
const stem = path37.basename(filePath, ".md");
|
|
9847
9847
|
if (stem !== definition.name) {
|
|
9848
9848
|
return {
|
|
9849
9849
|
error: {
|
|
@@ -9877,8 +9877,8 @@ function loadSource(dir, kind, byName, errors) {
|
|
|
9877
9877
|
}
|
|
9878
9878
|
}
|
|
9879
9879
|
function loadAgentCatalog(projectRoot, options = {}) {
|
|
9880
|
-
const bundledRoot = options.bundledRoot ??
|
|
9881
|
-
const projectDir =
|
|
9880
|
+
const bundledRoot = options.bundledRoot ?? path37.join(defaultBundledRoot(), "agents");
|
|
9881
|
+
const projectDir = path37.join(projectRoot, ".metaproject", "agents");
|
|
9882
9882
|
const byName = new Map;
|
|
9883
9883
|
const errors = [];
|
|
9884
9884
|
loadSource(bundledRoot, "bundled", byName, errors);
|
|
@@ -10671,7 +10671,7 @@ var init_compile = __esm(() => {
|
|
|
10671
10671
|
|
|
10672
10672
|
// src/agents/export.ts
|
|
10673
10673
|
import { readFile as readFile16, readdir as readdir8, lstat as lstat6, realpath as realpath7 } from "fs/promises";
|
|
10674
|
-
import
|
|
10674
|
+
import path38 from "path";
|
|
10675
10675
|
function matrixStateToExportLevel(state) {
|
|
10676
10676
|
return state === "native" || state === "adapter" ? state : "instruction-only";
|
|
10677
10677
|
}
|
|
@@ -10683,7 +10683,7 @@ function proseExportRelativePath(runtime, name) {
|
|
|
10683
10683
|
return `${PROSE_EXPORT_ROOT}/${runtime}/${name}.md`;
|
|
10684
10684
|
}
|
|
10685
10685
|
async function readExistingFileContent(projectRoot, relativePath) {
|
|
10686
|
-
const absolute =
|
|
10686
|
+
const absolute = path38.join(projectRoot, ...relativePath.split("/"));
|
|
10687
10687
|
try {
|
|
10688
10688
|
return await readFile16(absolute, "utf8");
|
|
10689
10689
|
} catch (error) {
|
|
@@ -10696,7 +10696,7 @@ async function checkExportPathSafety(projectRoot, relativePath) {
|
|
|
10696
10696
|
const segments = relativePath.split("/");
|
|
10697
10697
|
let current = projectRoot;
|
|
10698
10698
|
for (const segment of segments) {
|
|
10699
|
-
current =
|
|
10699
|
+
current = path38.join(current, segment);
|
|
10700
10700
|
let stats;
|
|
10701
10701
|
try {
|
|
10702
10702
|
stats = await lstat6(current);
|
|
@@ -10706,12 +10706,12 @@ async function checkExportPathSafety(projectRoot, relativePath) {
|
|
|
10706
10706
|
throw error;
|
|
10707
10707
|
}
|
|
10708
10708
|
if (stats.isSymbolicLink()) {
|
|
10709
|
-
return `refusing to write ${relativePath} \u2014 ${
|
|
10709
|
+
return `refusing to write ${relativePath} \u2014 ${path38.relative(projectRoot, current) || "."} is a symlink; this exporter never writes through a symlink`;
|
|
10710
10710
|
}
|
|
10711
10711
|
}
|
|
10712
|
-
let ancestor =
|
|
10712
|
+
let ancestor = path38.dirname(path38.join(projectRoot, ...segments));
|
|
10713
10713
|
for (let guard = 0;guard < segments.length + 1 && !await pathExists(ancestor); guard += 1) {
|
|
10714
|
-
const parent =
|
|
10714
|
+
const parent = path38.dirname(ancestor);
|
|
10715
10715
|
if (parent === ancestor)
|
|
10716
10716
|
break;
|
|
10717
10717
|
ancestor = parent;
|
|
@@ -10744,7 +10744,7 @@ function decideAction(existing, generated, format, expectedName) {
|
|
|
10744
10744
|
return { action: "update" };
|
|
10745
10745
|
}
|
|
10746
10746
|
async function readClaudeSubagentAliasesConfig(projectRoot) {
|
|
10747
|
-
const file =
|
|
10747
|
+
const file = path38.join(projectRoot, CLAUDE_SUBAGENT_ALIASES_CONFIG_PATH);
|
|
10748
10748
|
if (!await pathExists(file)) {
|
|
10749
10749
|
return { enabled: true };
|
|
10750
10750
|
}
|
|
@@ -10886,7 +10886,7 @@ async function writeAgentExport(projectRoot, plan, opts = {}) {
|
|
|
10886
10886
|
}
|
|
10887
10887
|
async function scanManagedAgentExports(projectRoot, runtime) {
|
|
10888
10888
|
const dirRelative = HOST_AGENTS_DIR[runtime];
|
|
10889
|
-
const dirAbsolute =
|
|
10889
|
+
const dirAbsolute = path38.join(projectRoot, ...dirRelative.split("/"));
|
|
10890
10890
|
let dirStats;
|
|
10891
10891
|
try {
|
|
10892
10892
|
dirStats = await lstat6(dirAbsolute);
|
|
@@ -10907,7 +10907,7 @@ async function scanManagedAgentExports(projectRoot, runtime) {
|
|
|
10907
10907
|
if (!entry.isFile())
|
|
10908
10908
|
continue;
|
|
10909
10909
|
const relativePath = `${dirRelative}/${entry.name}`;
|
|
10910
|
-
const absolute =
|
|
10910
|
+
const absolute = path38.join(projectRoot, ...relativePath.split("/"));
|
|
10911
10911
|
let entryStats;
|
|
10912
10912
|
try {
|
|
10913
10913
|
entryStats = await lstat6(absolute);
|
|
@@ -10922,7 +10922,7 @@ async function scanManagedAgentExports(projectRoot, runtime) {
|
|
|
10922
10922
|
} catch {
|
|
10923
10923
|
continue;
|
|
10924
10924
|
}
|
|
10925
|
-
const stem = entry.name.slice(0, entry.name.length -
|
|
10925
|
+
const stem = entry.name.slice(0, entry.name.length - path38.extname(entry.name).length);
|
|
10926
10926
|
const format = agentSentinelFormatOf(relativePath);
|
|
10927
10927
|
if (!isStructurallyManaged(content, format, stem))
|
|
10928
10928
|
continue;
|
|
@@ -11092,7 +11092,7 @@ var init_surfaces_agents = __esm(() => {
|
|
|
11092
11092
|
|
|
11093
11093
|
// src/rules/export-render.ts
|
|
11094
11094
|
import { readFile as readFile17, readdir as readdir9 } from "fs/promises";
|
|
11095
|
-
import
|
|
11095
|
+
import path39 from "path";
|
|
11096
11096
|
function isUnsafeRulePath(relativePath) {
|
|
11097
11097
|
return UNSAFE_RULE_PATH_PATTERN.test(relativePath) || relativePath.includes("<!--") || relativePath.includes("-->");
|
|
11098
11098
|
}
|
|
@@ -11135,7 +11135,7 @@ function firstHeading(body) {
|
|
|
11135
11135
|
return match ? match[1].trim() : undefined;
|
|
11136
11136
|
}
|
|
11137
11137
|
function titleFromFileName(relativePath) {
|
|
11138
|
-
const base =
|
|
11138
|
+
const base = path39.basename(relativePath).replace(/\.(mdc|md)$/i, "");
|
|
11139
11139
|
return base.split(/[-_]+/).filter((part) => part.length > 0).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
11140
11140
|
}
|
|
11141
11141
|
function parseRuleFile(fileName, content) {
|
|
@@ -11148,7 +11148,7 @@ function parseRuleFile(fileName, content) {
|
|
|
11148
11148
|
return { title: neutralise(collapseSingleLine(title, 120)), description };
|
|
11149
11149
|
}
|
|
11150
11150
|
async function collectCanonicalRules(root) {
|
|
11151
|
-
const rulesDir =
|
|
11151
|
+
const rulesDir = path39.join(root, ".metaproject", "rules");
|
|
11152
11152
|
if (!await pathExists(rulesDir))
|
|
11153
11153
|
return { rules: [], skipped: [] };
|
|
11154
11154
|
const rules = [];
|
|
@@ -11162,14 +11162,14 @@ async function collectCanonicalRules(root) {
|
|
|
11162
11162
|
}
|
|
11163
11163
|
for (const dirent of dirents) {
|
|
11164
11164
|
const childRelative = dirRelative ? `${dirRelative}/${dirent.name}` : dirent.name;
|
|
11165
|
-
const childAbsolute =
|
|
11165
|
+
const childAbsolute = path39.join(dirAbsolute, dirent.name);
|
|
11166
11166
|
if (dirent.isDirectory()) {
|
|
11167
11167
|
await walk(childAbsolute, childRelative);
|
|
11168
11168
|
continue;
|
|
11169
11169
|
}
|
|
11170
11170
|
if (!dirent.isFile())
|
|
11171
11171
|
continue;
|
|
11172
|
-
const ext =
|
|
11172
|
+
const ext = path39.extname(dirent.name).toLowerCase();
|
|
11173
11173
|
if (!RULE_EXTENSIONS.has(ext))
|
|
11174
11174
|
continue;
|
|
11175
11175
|
if (dirent.name.toLowerCase() === README_BASENAME)
|
|
@@ -11220,7 +11220,7 @@ var init_export_render = __esm(() => {
|
|
|
11220
11220
|
});
|
|
11221
11221
|
|
|
11222
11222
|
// src/integrations/surfaces-rules.ts
|
|
11223
|
-
import
|
|
11223
|
+
import path40 from "path";
|
|
11224
11224
|
async function rulesSpec(root) {
|
|
11225
11225
|
const { rules, skipped } = await collectCanonicalRules(root);
|
|
11226
11226
|
const body = renderRulesBlockBody(rules);
|
|
@@ -11265,7 +11265,7 @@ function rulesExportSurface(params) {
|
|
|
11265
11265
|
...riskNotes !== undefined ? { riskNotes } : {},
|
|
11266
11266
|
sourceDocs,
|
|
11267
11267
|
optIn: true,
|
|
11268
|
-
settingsFile: (root) =>
|
|
11268
|
+
settingsFile: (root) => path40.join(root, ...relativePath.split("/")),
|
|
11269
11269
|
relativePath,
|
|
11270
11270
|
label: relativePath,
|
|
11271
11271
|
slots: [],
|
|
@@ -11348,7 +11348,7 @@ var init_surfaces_rules = __esm(() => {
|
|
|
11348
11348
|
});
|
|
11349
11349
|
|
|
11350
11350
|
// src/integrations/surfaces-learning.ts
|
|
11351
|
-
import
|
|
11351
|
+
import path41 from "path";
|
|
11352
11352
|
function learningObserverCommand() {
|
|
11353
11353
|
return "keryx learn observe --hook claude";
|
|
11354
11354
|
}
|
|
@@ -11403,7 +11403,7 @@ var init_surfaces_learning = __esm(() => {
|
|
|
11403
11403
|
"docs/requirements/keryx-agent-platform-expansion/workstreams/W3-self-learning.md",
|
|
11404
11404
|
"src/learning/observe.ts"
|
|
11405
11405
|
],
|
|
11406
|
-
settingsFile: (root) =>
|
|
11406
|
+
settingsFile: (root) => path41.join(root, ".claude", "settings.json"),
|
|
11407
11407
|
relativePath: ".claude/settings.json",
|
|
11408
11408
|
slots: [
|
|
11409
11409
|
{ key: "hooks", type: "object", access: "owns" },
|
|
@@ -11752,13 +11752,13 @@ var init_registry = __esm(() => {
|
|
|
11752
11752
|
var init_package = () => {};
|
|
11753
11753
|
|
|
11754
11754
|
// src/lib/install-plan.ts
|
|
11755
|
-
import
|
|
11755
|
+
import path42 from "path";
|
|
11756
11756
|
var INSTALL_JOURNAL_RELATIVE_PATH;
|
|
11757
11757
|
var init_install_plan = __esm(() => {
|
|
11758
11758
|
init_package();
|
|
11759
11759
|
init_fs();
|
|
11760
11760
|
init_contained_write();
|
|
11761
|
-
INSTALL_JOURNAL_RELATIVE_PATH =
|
|
11761
|
+
INSTALL_JOURNAL_RELATIVE_PATH = path42.join("runtime", "install", "journal.json");
|
|
11762
11762
|
});
|
|
11763
11763
|
|
|
11764
11764
|
// src/integrations/install-state.ts
|
|
@@ -11813,11 +11813,11 @@ var init_integrations = __esm(() => {
|
|
|
11813
11813
|
});
|
|
11814
11814
|
|
|
11815
11815
|
// src/security/audit-harness/surfaces.ts
|
|
11816
|
-
import
|
|
11816
|
+
import path43 from "path";
|
|
11817
11817
|
import { lstat as lstat7, readdir as readdir10, realpath as realpath8, stat as stat7 } from "fs/promises";
|
|
11818
11818
|
async function resolvesInsideRoot(root, absolute) {
|
|
11819
11819
|
try {
|
|
11820
|
-
const rootReal = await realpath8(root).catch(() =>
|
|
11820
|
+
const rootReal = await realpath8(root).catch(() => path43.resolve(root));
|
|
11821
11821
|
const real = await realpath8(absolute);
|
|
11822
11822
|
return isPathInside(rootReal, real);
|
|
11823
11823
|
} catch {
|
|
@@ -11827,7 +11827,7 @@ async function resolvesInsideRoot(root, absolute) {
|
|
|
11827
11827
|
async function existingFiles(root, relativePaths) {
|
|
11828
11828
|
const found = [];
|
|
11829
11829
|
for (const relativePath of relativePaths) {
|
|
11830
|
-
const absolute =
|
|
11830
|
+
const absolute = path43.join(root, relativePath);
|
|
11831
11831
|
if (await pathExists(absolute)) {
|
|
11832
11832
|
found.push(toPosix(relativePath));
|
|
11833
11833
|
}
|
|
@@ -11850,7 +11850,7 @@ async function discoverHookSurfaceFiles(root) {
|
|
|
11850
11850
|
return existingFiles(root, [...NON_JSON_HOOK_SURFACE_PATHS, ".metaproject/hooks.json"]);
|
|
11851
11851
|
}
|
|
11852
11852
|
async function listFilesByExtensions(root, dirRelative, extensions) {
|
|
11853
|
-
const dirAbsolute =
|
|
11853
|
+
const dirAbsolute = path43.join(root, dirRelative);
|
|
11854
11854
|
if (!await pathExists(dirAbsolute)) {
|
|
11855
11855
|
return { found: [], unreadable: [] };
|
|
11856
11856
|
}
|
|
@@ -11863,15 +11863,15 @@ async function listFilesByExtensions(root, dirRelative, extensions) {
|
|
|
11863
11863
|
const found = [];
|
|
11864
11864
|
const unreadable = [];
|
|
11865
11865
|
for (const entry of entries) {
|
|
11866
|
-
if (!extensions.has(
|
|
11866
|
+
if (!extensions.has(path43.extname(entry.name)))
|
|
11867
11867
|
continue;
|
|
11868
|
-
const childRelative =
|
|
11868
|
+
const childRelative = path43.join(dirRelative, entry.name);
|
|
11869
11869
|
if (entry.isFile()) {
|
|
11870
11870
|
found.push(toPosix(childRelative));
|
|
11871
11871
|
continue;
|
|
11872
11872
|
}
|
|
11873
11873
|
if (entry.isSymbolicLink()) {
|
|
11874
|
-
const absolute =
|
|
11874
|
+
const absolute = path43.join(root, childRelative);
|
|
11875
11875
|
if (await resolvesInsideRoot(root, absolute)) {
|
|
11876
11876
|
found.push(toPosix(childRelative));
|
|
11877
11877
|
} else {
|
|
@@ -11907,7 +11907,7 @@ async function walkScripts(root, dirRelative, depth, visited, acc) {
|
|
|
11907
11907
|
acc.reasons.add(`skills: walk truncated at depth ${depth} (${toPosix(dirRelative)})`);
|
|
11908
11908
|
return;
|
|
11909
11909
|
}
|
|
11910
|
-
const dirAbsolute =
|
|
11910
|
+
const dirAbsolute = path43.join(root, dirRelative);
|
|
11911
11911
|
if (!await pathExists(dirAbsolute)) {
|
|
11912
11912
|
return;
|
|
11913
11913
|
}
|
|
@@ -11934,17 +11934,17 @@ async function walkScripts(root, dirRelative, depth, visited, acc) {
|
|
|
11934
11934
|
return;
|
|
11935
11935
|
}
|
|
11936
11936
|
for (const entry of entries) {
|
|
11937
|
-
const childRelative =
|
|
11937
|
+
const childRelative = path43.join(dirRelative, entry.name);
|
|
11938
11938
|
if (entry.isDirectory()) {
|
|
11939
11939
|
await walkScripts(root, childRelative, depth + 1, visited, acc);
|
|
11940
11940
|
continue;
|
|
11941
11941
|
}
|
|
11942
|
-
if (entry.isFile() && SCRIPT_EXTENSIONS.has(
|
|
11942
|
+
if (entry.isFile() && SCRIPT_EXTENSIONS.has(path43.extname(entry.name))) {
|
|
11943
11943
|
acc.found.push(toPosix(childRelative));
|
|
11944
11944
|
continue;
|
|
11945
11945
|
}
|
|
11946
11946
|
if (entry.isSymbolicLink()) {
|
|
11947
|
-
const absolute =
|
|
11947
|
+
const absolute = path43.join(root, childRelative);
|
|
11948
11948
|
if (!await resolvesInsideRoot(root, absolute)) {
|
|
11949
11949
|
acc.unreadable.push(toPosix(childRelative));
|
|
11950
11950
|
continue;
|
|
@@ -11954,7 +11954,7 @@ async function walkScripts(root, dirRelative, depth, visited, acc) {
|
|
|
11954
11954
|
});
|
|
11955
11955
|
if (stats?.isDirectory()) {
|
|
11956
11956
|
await walkScripts(root, childRelative, depth + 1, visited, acc);
|
|
11957
|
-
} else if (stats?.isFile() && SCRIPT_EXTENSIONS.has(
|
|
11957
|
+
} else if (stats?.isFile() && SCRIPT_EXTENSIONS.has(path43.extname(entry.name))) {
|
|
11958
11958
|
acc.found.push(toPosix(childRelative));
|
|
11959
11959
|
} else if (stats === undefined) {
|
|
11960
11960
|
acc.unreadable.push(toPosix(childRelative));
|
|
@@ -13480,10 +13480,10 @@ var init_checks = __esm(() => {
|
|
|
13480
13480
|
});
|
|
13481
13481
|
|
|
13482
13482
|
// src/security/audit-harness/baseline.ts
|
|
13483
|
-
import
|
|
13483
|
+
import path44 from "path";
|
|
13484
13484
|
import { readFile as readFile18 } from "fs/promises";
|
|
13485
13485
|
function defaultBaselinePath(root) {
|
|
13486
|
-
return
|
|
13486
|
+
return path44.join(root, ".metaproject", "security-audit-baseline.json");
|
|
13487
13487
|
}
|
|
13488
13488
|
async function readBaseline(baselinePath) {
|
|
13489
13489
|
if (!await pathExists(baselinePath)) {
|
|
@@ -13582,7 +13582,7 @@ async function addBaselineEntry(root, entry, options = {}) {
|
|
|
13582
13582
|
const now = options.now ? options.now() : new Date;
|
|
13583
13583
|
backupPath = `${filePath}.bak-${now.toISOString().replace(/[:.]/g, "-")}`;
|
|
13584
13584
|
const preResealBytes = await readFile18(filePath);
|
|
13585
|
-
await writeContained(root,
|
|
13585
|
+
await writeContained(root, path44.relative(root, backupPath), preResealBytes);
|
|
13586
13586
|
entries = loaded.state.entries;
|
|
13587
13587
|
const rawIds = await readRawBaselineFindingIds(filePath);
|
|
13588
13588
|
const keptIds = new Set(entries.map((e) => e.findingId));
|
|
@@ -13596,7 +13596,7 @@ async function addBaselineEntry(root, entry, options = {}) {
|
|
|
13596
13596
|
const next = [...entries.filter((existing) => existing.findingId !== entry.findingId), entry];
|
|
13597
13597
|
const checksum = computeObjectChecksum(next);
|
|
13598
13598
|
const payload = { schemaVersion: 1, entries: next, checksum };
|
|
13599
|
-
await writeContained(root,
|
|
13599
|
+
await writeContained(root, path44.relative(root, filePath), `${JSON.stringify(payload, null, 2)}
|
|
13600
13600
|
`);
|
|
13601
13601
|
return { resealed, carriedOver, discarded, ...backupPath ? { backupPath } : {} };
|
|
13602
13602
|
}
|
|
@@ -13687,7 +13687,7 @@ var init_types2 = __esm(() => {
|
|
|
13687
13687
|
});
|
|
13688
13688
|
|
|
13689
13689
|
// src/security/audit-harness/proposals.ts
|
|
13690
|
-
import
|
|
13690
|
+
import path45 from "path";
|
|
13691
13691
|
import { readFile as readFile19, realpath as realpath9 } from "fs/promises";
|
|
13692
13692
|
async function assertContained2(rootReal, absolute, label) {
|
|
13693
13693
|
if (!isPathInside(rootReal, absolute)) {
|
|
@@ -13702,7 +13702,7 @@ async function assertContained2(rootReal, absolute, label) {
|
|
|
13702
13702
|
}
|
|
13703
13703
|
return;
|
|
13704
13704
|
}
|
|
13705
|
-
let dir =
|
|
13705
|
+
let dir = path45.dirname(absolute);
|
|
13706
13706
|
for (;; ) {
|
|
13707
13707
|
const dirReal = await realpath9(dir).catch(() => {
|
|
13708
13708
|
return;
|
|
@@ -13713,23 +13713,23 @@ async function assertContained2(rootReal, absolute, label) {
|
|
|
13713
13713
|
}
|
|
13714
13714
|
return;
|
|
13715
13715
|
}
|
|
13716
|
-
const parent =
|
|
13716
|
+
const parent = path45.dirname(dir);
|
|
13717
13717
|
if (parent === dir)
|
|
13718
13718
|
return;
|
|
13719
13719
|
dir = parent;
|
|
13720
13720
|
}
|
|
13721
13721
|
}
|
|
13722
13722
|
function dataRoot(root) {
|
|
13723
|
-
return
|
|
13723
|
+
return path45.join(root, ".metaproject", "data", "security", "audit-harness");
|
|
13724
13724
|
}
|
|
13725
13725
|
function lockPath2(root) {
|
|
13726
|
-
return
|
|
13726
|
+
return path45.join(dataRoot(root), "apply.lock");
|
|
13727
13727
|
}
|
|
13728
13728
|
function changelogPath(root) {
|
|
13729
|
-
return
|
|
13729
|
+
return path45.join(dataRoot(root), "changelog.jsonl");
|
|
13730
13730
|
}
|
|
13731
13731
|
function appliedMarkerPath(root, proposalId) {
|
|
13732
|
-
return
|
|
13732
|
+
return path45.join(dataRoot(root), `${proposalId}.applied.json`);
|
|
13733
13733
|
}
|
|
13734
13734
|
function setPointer(target, pointer, mutate) {
|
|
13735
13735
|
const segments = pointer.split("/").filter((s) => s.length > 0).map((s) => s.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
@@ -13751,7 +13751,7 @@ function setPointer(target, pointer, mutate) {
|
|
|
13751
13751
|
return target;
|
|
13752
13752
|
}
|
|
13753
13753
|
async function applyJsonEdit(rootReal, edit) {
|
|
13754
|
-
const absolute =
|
|
13754
|
+
const absolute = path45.resolve(rootReal, edit.path);
|
|
13755
13755
|
await assertContained2(rootReal, absolute, `target file "${edit.path}"`);
|
|
13756
13756
|
const read = await readJsonObjectFile(absolute);
|
|
13757
13757
|
if (read.state !== "object") {
|
|
@@ -13784,7 +13784,7 @@ async function applyJsonEdit(rootReal, edit) {
|
|
|
13784
13784
|
} catch {
|
|
13785
13785
|
throw new Error(`Cannot apply proposal: result is not valid JSON for ${edit.path}; refusing to write.`);
|
|
13786
13786
|
}
|
|
13787
|
-
await writeContained(rootReal,
|
|
13787
|
+
await writeContained(rootReal, path45.relative(rootReal, absolute), serialized);
|
|
13788
13788
|
}
|
|
13789
13789
|
function countOccurrences(haystack, needle) {
|
|
13790
13790
|
if (needle.length === 0)
|
|
@@ -13800,7 +13800,7 @@ function countOccurrences(haystack, needle) {
|
|
|
13800
13800
|
}
|
|
13801
13801
|
}
|
|
13802
13802
|
async function applyTextEdit(rootReal, edit) {
|
|
13803
|
-
const absolute =
|
|
13803
|
+
const absolute = path45.resolve(rootReal, edit.path);
|
|
13804
13804
|
await assertContained2(rootReal, absolute, `target file "${edit.path}"`);
|
|
13805
13805
|
const content = await readFile19(absolute, "utf8");
|
|
13806
13806
|
const occurrences = countOccurrences(content, edit.from);
|
|
@@ -13821,7 +13821,7 @@ async function applyTextEdit(rootReal, edit) {
|
|
|
13821
13821
|
throw new Error(`Cannot apply proposal: result is not valid JSON for ${edit.path}; refusing to write.`);
|
|
13822
13822
|
}
|
|
13823
13823
|
}
|
|
13824
|
-
await writeContained(rootReal,
|
|
13824
|
+
await writeContained(rootReal, path45.relative(rootReal, absolute), next);
|
|
13825
13825
|
}
|
|
13826
13826
|
async function applyAuditProposal(root, proposalId, options = {}) {
|
|
13827
13827
|
if (!PROPOSAL_ID_RE.test(proposalId)) {
|
|
@@ -13829,7 +13829,7 @@ async function applyAuditProposal(root, proposalId, options = {}) {
|
|
|
13829
13829
|
}
|
|
13830
13830
|
const rootReal = await realpath9(root).catch(() => {
|
|
13831
13831
|
return;
|
|
13832
|
-
}) ??
|
|
13832
|
+
}) ?? path45.resolve(root);
|
|
13833
13833
|
return withFileLock(lockPath2(rootReal), async () => {
|
|
13834
13834
|
const marker = appliedMarkerPath(rootReal, proposalId);
|
|
13835
13835
|
await assertContained2(rootReal, marker, "applied-marker file");
|
|
@@ -13864,9 +13864,9 @@ async function applyAuditProposal(root, proposalId, options = {}) {
|
|
|
13864
13864
|
};
|
|
13865
13865
|
const changelog = changelogPath(rootReal);
|
|
13866
13866
|
await assertContained2(rootReal, changelog, "changelog file");
|
|
13867
|
-
await appendContained(rootReal,
|
|
13867
|
+
await appendContained(rootReal, path45.relative(rootReal, changelog), `${JSON.stringify(result)}
|
|
13868
13868
|
`);
|
|
13869
|
-
await writeContained(rootReal,
|
|
13869
|
+
await writeContained(rootReal, path45.relative(rootReal, marker), `${JSON.stringify(result, null, 2)}
|
|
13870
13870
|
`);
|
|
13871
13871
|
return result;
|
|
13872
13872
|
});
|
|
@@ -13882,7 +13882,7 @@ var init_proposals = __esm(() => {
|
|
|
13882
13882
|
|
|
13883
13883
|
// src/security/audit-harness/index.ts
|
|
13884
13884
|
import { createHash as createHash7 } from "crypto";
|
|
13885
|
-
import
|
|
13885
|
+
import path46 from "path";
|
|
13886
13886
|
import { readFile as readFile20 } from "fs/promises";
|
|
13887
13887
|
function findingId(f) {
|
|
13888
13888
|
const pointerOrLine = f.location?.pointer ?? (f.location?.line !== undefined ? `line:${f.location.line}` : "");
|
|
@@ -14057,7 +14057,7 @@ function asBundleFindings(findings, bundleCheck) {
|
|
|
14057
14057
|
function isSafeBundleEntryPath(relativePath) {
|
|
14058
14058
|
if (relativePath.length === 0)
|
|
14059
14059
|
return false;
|
|
14060
|
-
if (
|
|
14060
|
+
if (path46.isAbsolute(relativePath))
|
|
14061
14061
|
return false;
|
|
14062
14062
|
if (relativePath.includes("\\"))
|
|
14063
14063
|
return false;
|
|
@@ -14074,7 +14074,7 @@ async function scanImportedBundle(root, entries) {
|
|
|
14074
14074
|
unreadable.push(entry.path);
|
|
14075
14075
|
continue;
|
|
14076
14076
|
}
|
|
14077
|
-
const absolute =
|
|
14077
|
+
const absolute = path46.join(root, entry.path);
|
|
14078
14078
|
if (!isPathInside(root, absolute)) {
|
|
14079
14079
|
unreadable.push(entry.path);
|
|
14080
14080
|
continue;
|
|
@@ -14183,7 +14183,7 @@ async function scanImportedBundle(root, entries) {
|
|
|
14183
14183
|
return { raw, surface: surfaceResult("imported-bundles", scanned, unreadable), notes };
|
|
14184
14184
|
}
|
|
14185
14185
|
async function mcpBaselineTools(root) {
|
|
14186
|
-
const file =
|
|
14186
|
+
const file = path46.join(securityDataRoot(root), "mcp-baseline.json");
|
|
14187
14187
|
if (!await pathExists(file)) {
|
|
14188
14188
|
return { tools: {}, state: "absent" };
|
|
14189
14189
|
}
|
|
@@ -14202,7 +14202,7 @@ async function computeAuditInternal(root, options = {}) {
|
|
|
14202
14202
|
const files = await discoverInstructions(root);
|
|
14203
14203
|
const unreadable = [];
|
|
14204
14204
|
for (const relativePath of files) {
|
|
14205
|
-
const content = await safeReadText(
|
|
14205
|
+
const content = await safeReadText(path46.join(root, relativePath));
|
|
14206
14206
|
if (content === undefined) {
|
|
14207
14207
|
unreadable.push(relativePath);
|
|
14208
14208
|
continue;
|
|
@@ -14222,7 +14222,7 @@ async function computeAuditInternal(root, options = {}) {
|
|
|
14222
14222
|
if (relativePath.endsWith(".toml")) {
|
|
14223
14223
|
continue;
|
|
14224
14224
|
}
|
|
14225
|
-
const read = await readJsonObjectFile(
|
|
14225
|
+
const read = await readJsonObjectFile(path46.join(root, relativePath));
|
|
14226
14226
|
if (read.state !== "object") {
|
|
14227
14227
|
unreadable.push(relativePath);
|
|
14228
14228
|
continue;
|
|
@@ -14250,7 +14250,7 @@ async function computeAuditInternal(root, options = {}) {
|
|
|
14250
14250
|
const { tools: baselineTools, state: baselineState } = await mcpBaselineTools(root);
|
|
14251
14251
|
for (const relativePath of uniqueFiles) {
|
|
14252
14252
|
if (relativePath.endsWith(".toml")) {
|
|
14253
|
-
const content = await safeReadText(
|
|
14253
|
+
const content = await safeReadText(path46.join(root, relativePath));
|
|
14254
14254
|
if (content === undefined) {
|
|
14255
14255
|
unreadable.push(relativePath);
|
|
14256
14256
|
continue;
|
|
@@ -14272,7 +14272,7 @@ async function computeAuditInternal(root, options = {}) {
|
|
|
14272
14272
|
}
|
|
14273
14273
|
let record = settingsJsonByPath.get(relativePath);
|
|
14274
14274
|
if (record === undefined) {
|
|
14275
|
-
const read = await readJsonObjectFile(
|
|
14275
|
+
const read = await readJsonObjectFile(path46.join(root, relativePath));
|
|
14276
14276
|
record = read.state === "object" ? read.value : undefined;
|
|
14277
14277
|
}
|
|
14278
14278
|
if (!record) {
|
|
@@ -14334,7 +14334,7 @@ async function computeAuditInternal(root, options = {}) {
|
|
|
14334
14334
|
}
|
|
14335
14335
|
}
|
|
14336
14336
|
for (const relativePath of nonJsonFiles) {
|
|
14337
|
-
const content = await safeReadText(
|
|
14337
|
+
const content = await safeReadText(path46.join(root, relativePath));
|
|
14338
14338
|
if (content === undefined) {
|
|
14339
14339
|
unreadable.push(relativePath);
|
|
14340
14340
|
continue;
|
|
@@ -14348,7 +14348,7 @@ async function computeAuditInternal(root, options = {}) {
|
|
|
14348
14348
|
const { found: files, unreadable: discoveryUnreadable } = await discoverAgentDefinitions(root);
|
|
14349
14349
|
const unreadable = [...discoveryUnreadable];
|
|
14350
14350
|
for (const relativePath of files) {
|
|
14351
|
-
const buffer = await safeReadBuffer(
|
|
14351
|
+
const buffer = await safeReadBuffer(path46.join(root, relativePath));
|
|
14352
14352
|
if (buffer === undefined) {
|
|
14353
14353
|
unreadable.push(relativePath);
|
|
14354
14354
|
continue;
|
|
@@ -14365,7 +14365,7 @@ async function computeAuditInternal(root, options = {}) {
|
|
|
14365
14365
|
const { found: files, unreadable: discoveryUnreadable, reasons: skillReasons } = await discoverSkillScripts(root);
|
|
14366
14366
|
const unreadable = [...discoveryUnreadable];
|
|
14367
14367
|
for (const relativePath of files) {
|
|
14368
|
-
const content = await safeReadText(
|
|
14368
|
+
const content = await safeReadText(path46.join(root, relativePath));
|
|
14369
14369
|
if (content === undefined) {
|
|
14370
14370
|
unreadable.push(relativePath);
|
|
14371
14371
|
continue;
|
|
@@ -14512,7 +14512,7 @@ __export(exports_service, {
|
|
|
14512
14512
|
validateSerializedOutput: () => validateSerializedOutput,
|
|
14513
14513
|
verifyConfigChecksum: () => verifyConfigChecksum
|
|
14514
14514
|
});
|
|
14515
|
-
import
|
|
14515
|
+
import path47 from "path";
|
|
14516
14516
|
import { readFile as readFile21 } from "fs/promises";
|
|
14517
14517
|
import { randomBytes as randomBytes4 } from "crypto";
|
|
14518
14518
|
function validateSerializedOutput(content, exemptExfil) {
|
|
@@ -14640,7 +14640,7 @@ function hasRecognizedGate(value) {
|
|
|
14640
14640
|
return typeof gate === "string" && RECOGNIZED_GATES.has(gate);
|
|
14641
14641
|
}
|
|
14642
14642
|
async function readLatestReport(cwd) {
|
|
14643
|
-
const file =
|
|
14643
|
+
const file = path47.join(artifactsDir(cwd), "latest.json");
|
|
14644
14644
|
if (!await pathExists(file)) {
|
|
14645
14645
|
return { kind: "absent" };
|
|
14646
14646
|
}
|
|
@@ -14766,9 +14766,9 @@ var init_service2 = __esm(() => {
|
|
|
14766
14766
|
});
|
|
14767
14767
|
|
|
14768
14768
|
// src/gdgraph/config.ts
|
|
14769
|
-
import
|
|
14769
|
+
import path52 from "path";
|
|
14770
14770
|
function gdgraphConfigPath(cwd) {
|
|
14771
|
-
return
|
|
14771
|
+
return path52.join(cwd, ".metaproject", "gdgraph.config.json");
|
|
14772
14772
|
}
|
|
14773
14773
|
function mergeGdgraphConfig(parsed) {
|
|
14774
14774
|
const base = DEFAULT_GDGRAPH_CONFIG;
|
|
@@ -15373,7 +15373,7 @@ var init_extract = __esm(() => {
|
|
|
15373
15373
|
});
|
|
15374
15374
|
|
|
15375
15375
|
// src/gdgraph/treesitter/grammars.ts
|
|
15376
|
-
import
|
|
15376
|
+
import path53 from "path";
|
|
15377
15377
|
function grammarAssetId(language) {
|
|
15378
15378
|
return `tree-sitter-${language}`;
|
|
15379
15379
|
}
|
|
@@ -15389,7 +15389,7 @@ function symbolLanguage(language) {
|
|
|
15389
15389
|
async function resolveGrammar(cwd, language, grammarsPath) {
|
|
15390
15390
|
const id = grammarAssetId(language);
|
|
15391
15391
|
const lock = await loadAssetsLock(cwd);
|
|
15392
|
-
const overrides = grammarsPath ? { [id]: { path:
|
|
15392
|
+
const overrides = grammarsPath ? { [id]: { path: path53.join(grammarsPath, `${id}.wasm`) } } : undefined;
|
|
15393
15393
|
const registry = registryFromLock(lock, overrides);
|
|
15394
15394
|
const resolved = await resolveAsset(registry, id);
|
|
15395
15395
|
if (!resolved) {
|
|
@@ -15419,7 +15419,7 @@ function toGrammarLanguages(languages) {
|
|
|
15419
15419
|
return out;
|
|
15420
15420
|
}
|
|
15421
15421
|
function grammarForFile(file, available) {
|
|
15422
|
-
const ext =
|
|
15422
|
+
const ext = path53.extname(file);
|
|
15423
15423
|
const preference = ext === ".tsx" ? ["tsx", "typescript"] : ext === ".ts" ? ["typescript"] : ext === ".jsx" || ext === ".js" || ext === ".mjs" || ext === ".cjs" ? ["javascript"] : ext === ".java" ? ["java"] : ext === ".py" ? ["python"] : [];
|
|
15424
15424
|
for (const language of preference) {
|
|
15425
15425
|
if (available.includes(language)) {
|
|
@@ -15681,7 +15681,7 @@ var init_adapter = __esm(() => {
|
|
|
15681
15681
|
|
|
15682
15682
|
// src/gdgraph/enrich.ts
|
|
15683
15683
|
import { mkdir as mkdir12, writeFile as writeFile6 } from "fs/promises";
|
|
15684
|
-
import
|
|
15684
|
+
import path54 from "path";
|
|
15685
15685
|
async function enrichBuildWithSymbols(cwd, files, resolve) {
|
|
15686
15686
|
const config = await loadGdgraphConfig(cwd);
|
|
15687
15687
|
const treesitterConfig = {
|
|
@@ -15697,12 +15697,12 @@ async function enrichBuildWithSymbols(cwd, files, resolve) {
|
|
|
15697
15697
|
return { enriched: true, symbols: layer.symbols.length, calls: layer.calls.length };
|
|
15698
15698
|
}
|
|
15699
15699
|
async function writeSymbolLayer(cwd, layer) {
|
|
15700
|
-
const storageDir =
|
|
15700
|
+
const storageDir = path54.join(cwd, ".metaproject", "data", "gdgraph", "storage");
|
|
15701
15701
|
await mkdir12(storageDir, { recursive: true });
|
|
15702
|
-
await writeFile6(
|
|
15702
|
+
await writeFile6(path54.join(storageDir, "symbols.jsonl"), layer.symbols.map((symbol) => JSON.stringify(symbol)).join(`
|
|
15703
15703
|
`) + `
|
|
15704
15704
|
`, "utf8");
|
|
15705
|
-
await writeFile6(
|
|
15705
|
+
await writeFile6(path54.join(storageDir, "calls.jsonl"), layer.calls.map((call) => JSON.stringify(call)).join(`
|
|
15706
15706
|
`) + `
|
|
15707
15707
|
`, "utf8");
|
|
15708
15708
|
}
|
|
@@ -15895,10 +15895,10 @@ var init_describes = () => {};
|
|
|
15895
15895
|
|
|
15896
15896
|
// src/sync/provenance.ts
|
|
15897
15897
|
import { mkdir as mkdir13, readFile as readFile25, writeFile as writeFile7 } from "fs/promises";
|
|
15898
|
-
import
|
|
15898
|
+
import path55 from "path";
|
|
15899
15899
|
import { spawn } from "child_process";
|
|
15900
15900
|
function provenancePath(cwd, module) {
|
|
15901
|
-
return
|
|
15901
|
+
return path55.join(cwd, ".metaproject", "data", module, ".provenance.json");
|
|
15902
15902
|
}
|
|
15903
15903
|
function gitCmdResult(cwd, args) {
|
|
15904
15904
|
return new Promise((resolve) => {
|
|
@@ -15943,7 +15943,7 @@ async function recordProvenance(cwd, module, at) {
|
|
|
15943
15943
|
if (!head)
|
|
15944
15944
|
return;
|
|
15945
15945
|
const file = provenancePath(cwd, module);
|
|
15946
|
-
await mkdir13(
|
|
15946
|
+
await mkdir13(path55.dirname(file), { recursive: true });
|
|
15947
15947
|
const provenance = { commit: head.commit, branch: head.branch, builtAt: at };
|
|
15948
15948
|
await writeFile7(file, `${JSON.stringify(provenance, null, 2)}
|
|
15949
15949
|
`, "utf8");
|
|
@@ -15968,7 +15968,7 @@ var init_provenance = __esm(() => {
|
|
|
15968
15968
|
// src/gdgraph/staleness.ts
|
|
15969
15969
|
import { spawn as spawn2 } from "child_process";
|
|
15970
15970
|
import { stat as stat8 } from "fs/promises";
|
|
15971
|
-
import
|
|
15971
|
+
import path56 from "path";
|
|
15972
15972
|
function gitStatusPorcelain(cwd) {
|
|
15973
15973
|
return new Promise((resolve) => {
|
|
15974
15974
|
try {
|
|
@@ -15991,10 +15991,10 @@ function gitStatusPorcelain(cwd) {
|
|
|
15991
15991
|
});
|
|
15992
15992
|
}
|
|
15993
15993
|
function nodesJsonlPath(cwd) {
|
|
15994
|
-
return
|
|
15994
|
+
return path56.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
|
|
15995
15995
|
}
|
|
15996
15996
|
function gdgraphConfigPath2(cwd) {
|
|
15997
|
-
return
|
|
15997
|
+
return path56.join(cwd, ".metaproject", "gdgraph.config.json");
|
|
15998
15998
|
}
|
|
15999
15999
|
function categorizeStatusEntries(entries, rootPrefix) {
|
|
16000
16000
|
const metaprojectPrefix = `${rootPrefix}.metaproject/`;
|
|
@@ -16075,7 +16075,7 @@ async function checkGraphStaleness(cwd) {
|
|
|
16075
16075
|
}
|
|
16076
16076
|
} else {
|
|
16077
16077
|
provenanceMissing = true;
|
|
16078
|
-
const logsHeadStat = await stat8(
|
|
16078
|
+
const logsHeadStat = await stat8(path56.join(cwd, ".git", "logs", "HEAD")).catch(() => null);
|
|
16079
16079
|
if (logsHeadStat && logsHeadStat.mtimeMs > nodesStat.mtimeMs) {
|
|
16080
16080
|
reasons.push("repo HEAD moved since the graph was built (no build provenance recorded; inferred from .git/logs/HEAD)");
|
|
16081
16081
|
}
|
|
@@ -16104,7 +16104,7 @@ async function checkGraphStaleness(cwd) {
|
|
|
16104
16104
|
if (projectRelative === null) {
|
|
16105
16105
|
continue;
|
|
16106
16106
|
}
|
|
16107
|
-
const fileStat = await stat8(
|
|
16107
|
+
const fileStat = await stat8(path56.join(cwd, projectRelative)).catch(() => null);
|
|
16108
16108
|
if (fileStat && fileStat.mtimeMs > nodesStat.mtimeMs) {
|
|
16109
16109
|
postBuildEdits.push(displayPath);
|
|
16110
16110
|
}
|
|
@@ -16240,15 +16240,15 @@ var init_types3 = __esm(() => {
|
|
|
16240
16240
|
|
|
16241
16241
|
// src/wiki/collect.ts
|
|
16242
16242
|
import { readFile as readFile26, readdir as readdir11 } from "fs/promises";
|
|
16243
|
-
import
|
|
16243
|
+
import path57 from "path";
|
|
16244
16244
|
function wikiRootPath(cwd) {
|
|
16245
|
-
return
|
|
16245
|
+
return path57.join(cwd, ".metaproject", "wiki");
|
|
16246
16246
|
}
|
|
16247
16247
|
async function collectPages(cwd) {
|
|
16248
16248
|
const root = wikiRootPath(cwd);
|
|
16249
16249
|
const pages = [];
|
|
16250
16250
|
for (const { type, folder } of WIKI_PAGE_TYPES) {
|
|
16251
|
-
const dir =
|
|
16251
|
+
const dir = path57.join(root, folder);
|
|
16252
16252
|
let names;
|
|
16253
16253
|
try {
|
|
16254
16254
|
names = await readdir11(dir);
|
|
@@ -16263,7 +16263,7 @@ async function collectPages(cwd) {
|
|
|
16263
16263
|
if (!entry.endsWith(".md")) {
|
|
16264
16264
|
continue;
|
|
16265
16265
|
}
|
|
16266
|
-
const absolutePath =
|
|
16266
|
+
const absolutePath = path57.join(dir, entry);
|
|
16267
16267
|
let content;
|
|
16268
16268
|
try {
|
|
16269
16269
|
content = await readFile26(absolutePath, "utf8");
|
|
@@ -17073,7 +17073,7 @@ var init_section_index = __esm(() => {
|
|
|
17073
17073
|
});
|
|
17074
17074
|
|
|
17075
17075
|
// src/security/guard.ts
|
|
17076
|
-
import
|
|
17076
|
+
import path58 from "path";
|
|
17077
17077
|
function prepareOutputForPersistence(guard, original) {
|
|
17078
17078
|
if (!guard.allowed) {
|
|
17079
17079
|
return { allowed: false, reason: guard.reason ?? "security gate blocked" };
|
|
@@ -17091,7 +17091,7 @@ function prepareOutputForPersistence(guard, original) {
|
|
|
17091
17091
|
};
|
|
17092
17092
|
}
|
|
17093
17093
|
async function resolveManifestSecurityState(cwd) {
|
|
17094
|
-
const manifestPath =
|
|
17094
|
+
const manifestPath = path58.join(securityProjectRoot(cwd), ".metaproject", "metaproject.json");
|
|
17095
17095
|
if (!await pathExists(manifestPath)) {
|
|
17096
17096
|
return { enabled: false, manifestUnreadable: false };
|
|
17097
17097
|
}
|
|
@@ -17298,9 +17298,9 @@ var MEMORY_EMBEDDING_ID = "memory.embedding", DEFAULT_EMBED_DIMS = 96;
|
|
|
17298
17298
|
// src/memory/embedding/index.ts
|
|
17299
17299
|
import { createHash as createHash10 } from "crypto";
|
|
17300
17300
|
import { mkdir as mkdir14, readFile as readFile27, writeFile as writeFile8 } from "fs/promises";
|
|
17301
|
-
import
|
|
17301
|
+
import path59 from "path";
|
|
17302
17302
|
function embeddingsDir(cwd) {
|
|
17303
|
-
return
|
|
17303
|
+
return path59.join(cwd, ".metaproject", "data", "memory", "embeddings");
|
|
17304
17304
|
}
|
|
17305
17305
|
function entryText(entry) {
|
|
17306
17306
|
return `${entry.title}
|
|
@@ -17329,17 +17329,17 @@ async function buildEmbeddingIndex(cwd, entries, embedder, model, now) {
|
|
|
17329
17329
|
};
|
|
17330
17330
|
const dir = embeddingsDir(cwd);
|
|
17331
17331
|
await mkdir14(dir, { recursive: true });
|
|
17332
|
-
await writeFile8(
|
|
17332
|
+
await writeFile8(path59.join(dir, "index.meta.json"), `${JSON.stringify(meta, null, 2)}
|
|
17333
17333
|
`, "utf8");
|
|
17334
|
-
await writeFile8(
|
|
17334
|
+
await writeFile8(path59.join(dir, "vectors.jsonl"), records.map((record) => JSON.stringify(record)).join(`
|
|
17335
17335
|
`) + (records.length > 0 ? `
|
|
17336
17336
|
` : ""), "utf8");
|
|
17337
17337
|
return toIndex(meta, records);
|
|
17338
17338
|
}
|
|
17339
17339
|
async function loadEmbeddingIndex(cwd) {
|
|
17340
17340
|
const dir = embeddingsDir(cwd);
|
|
17341
|
-
const metaPath =
|
|
17342
|
-
const vectorsPath =
|
|
17341
|
+
const metaPath = path59.join(dir, "index.meta.json");
|
|
17342
|
+
const vectorsPath = path59.join(dir, "vectors.jsonl");
|
|
17343
17343
|
if (!await pathExists(metaPath) || !await pathExists(vectorsPath)) {
|
|
17344
17344
|
return null;
|
|
17345
17345
|
}
|
|
@@ -17420,10 +17420,10 @@ var init_embedding = __esm(() => {
|
|
|
17420
17420
|
});
|
|
17421
17421
|
|
|
17422
17422
|
// src/wiki/section-tombstone.ts
|
|
17423
|
-
import
|
|
17423
|
+
import path60 from "path";
|
|
17424
17424
|
import { stat as stat9 } from "fs/promises";
|
|
17425
17425
|
function sectionRegistryPath(cwd) {
|
|
17426
|
-
return
|
|
17426
|
+
return path60.join(cwd, ".metaproject", "wiki", ".sections.json");
|
|
17427
17427
|
}
|
|
17428
17428
|
function emptySectionRegistry() {
|
|
17429
17429
|
return { version: SECTION_REGISTRY_VERSION, entries: [], tombstones: [], lifted: [] };
|
|
@@ -17725,10 +17725,10 @@ var init_section_tombstone = __esm(() => {
|
|
|
17725
17725
|
|
|
17726
17726
|
// src/memory/cross-layer.ts
|
|
17727
17727
|
import { readFile as readFile28 } from "fs/promises";
|
|
17728
|
-
import
|
|
17728
|
+
import path61 from "path";
|
|
17729
17729
|
function extractWikiReferences(entryRelativePath, entryAbsolutePath, content, wikiRoot) {
|
|
17730
17730
|
const references = [];
|
|
17731
|
-
const entryDir =
|
|
17731
|
+
const entryDir = path61.dirname(entryAbsolutePath);
|
|
17732
17732
|
const lines = content.split(`
|
|
17733
17733
|
`);
|
|
17734
17734
|
for (let index = 0;index < lines.length; index += 1) {
|
|
@@ -17743,16 +17743,16 @@ function extractWikiReferences(entryRelativePath, entryAbsolutePath, content, wi
|
|
|
17743
17743
|
if (withoutAnchor.length === 0) {
|
|
17744
17744
|
continue;
|
|
17745
17745
|
}
|
|
17746
|
-
const absolute =
|
|
17747
|
-
const relativeToWiki =
|
|
17748
|
-
if (relativeToWiki.startsWith("..") ||
|
|
17746
|
+
const absolute = path61.resolve(entryDir, withoutAnchor);
|
|
17747
|
+
const relativeToWiki = path61.relative(wikiRoot, absolute);
|
|
17748
|
+
if (relativeToWiki.startsWith("..") || path61.isAbsolute(relativeToWiki)) {
|
|
17749
17749
|
continue;
|
|
17750
17750
|
}
|
|
17751
17751
|
references.push({
|
|
17752
17752
|
entry: entryRelativePath,
|
|
17753
17753
|
kind: "page-path",
|
|
17754
17754
|
raw: href,
|
|
17755
|
-
target: relativeToWiki.split(
|
|
17755
|
+
target: relativeToWiki.split(path61.sep).join("/"),
|
|
17756
17756
|
line
|
|
17757
17757
|
});
|
|
17758
17758
|
}
|
|
@@ -17772,7 +17772,7 @@ function isDangling(finding) {
|
|
|
17772
17772
|
return finding.state !== "intact";
|
|
17773
17773
|
}
|
|
17774
17774
|
async function loadWikiKnowledgeView(cwd) {
|
|
17775
|
-
const wikiRoot =
|
|
17775
|
+
const wikiRoot = path61.join(cwd, ".metaproject", "wiki");
|
|
17776
17776
|
const pages = await collectPages(cwd);
|
|
17777
17777
|
const index = buildSectionIndex(await Promise.all(pages.map(async (page) => ({
|
|
17778
17778
|
page,
|
|
@@ -17990,7 +17990,7 @@ function round2(value) {
|
|
|
17990
17990
|
var init_dedup = () => {};
|
|
17991
17991
|
|
|
17992
17992
|
// src/memory/check.ts
|
|
17993
|
-
import
|
|
17993
|
+
import path62 from "path";
|
|
17994
17994
|
async function checkMemory(cwd, config) {
|
|
17995
17995
|
const entries = await collectEntries(cwd);
|
|
17996
17996
|
const issues = [];
|
|
@@ -18006,7 +18006,7 @@ async function checkMemory(cwd, config) {
|
|
|
18006
18006
|
}
|
|
18007
18007
|
for (const file of entry.scopes.files) {
|
|
18008
18008
|
const clean = file.replace(/^`|`$/g, "");
|
|
18009
|
-
if (!await pathExists(
|
|
18009
|
+
if (!await pathExists(path62.resolve(cwd, clean))) {
|
|
18010
18010
|
issues.push({ path: entry.relativePath, kind: "link", message: `related file not found: ${clean}` });
|
|
18011
18011
|
}
|
|
18012
18012
|
}
|
|
@@ -18061,12 +18061,12 @@ var init_check = __esm(() => {
|
|
|
18061
18061
|
|
|
18062
18062
|
// src/memory/write.ts
|
|
18063
18063
|
import { mkdir as mkdir15, open as open2, readFile as readFile29, rename as rename5, rm as rm4, writeFile as writeFile9 } from "fs/promises";
|
|
18064
|
-
import
|
|
18064
|
+
import path63 from "path";
|
|
18065
18065
|
async function resolveCanonicalEntryPath(cwd, relativePath) {
|
|
18066
|
-
const root =
|
|
18067
|
-
const absolutePath =
|
|
18068
|
-
const normalized = toPosix2(
|
|
18069
|
-
if (!normalized || normalized.startsWith("../") ||
|
|
18066
|
+
const root = path63.resolve(memoryRoot(cwd));
|
|
18067
|
+
const absolutePath = path63.resolve(root, relativePath);
|
|
18068
|
+
const normalized = toPosix2(path63.relative(root, absolutePath));
|
|
18069
|
+
if (!normalized || normalized.startsWith("../") || path63.isAbsolute(normalized) || !normalized.endsWith(".md")) {
|
|
18070
18070
|
return null;
|
|
18071
18071
|
}
|
|
18072
18072
|
return { absolutePath, relativePath: normalized };
|
|
@@ -18162,9 +18162,9 @@ function validateNextEntry(relativePath, content) {
|
|
|
18162
18162
|
return null;
|
|
18163
18163
|
}
|
|
18164
18164
|
async function replaceAtomically(target, content) {
|
|
18165
|
-
const dir =
|
|
18165
|
+
const dir = path63.dirname(target);
|
|
18166
18166
|
await mkdir15(dir, { recursive: true });
|
|
18167
|
-
const tmp =
|
|
18167
|
+
const tmp = path63.join(dir, `.${path63.basename(target)}.keryx-tmp-${process.pid}-${Math.random().toString(16).slice(2)}`);
|
|
18168
18168
|
try {
|
|
18169
18169
|
await writeFile9(tmp, content, "utf8");
|
|
18170
18170
|
const file = await open2(tmp, "r");
|
|
@@ -18200,7 +18200,7 @@ function header(content, name) {
|
|
|
18200
18200
|
return content.match(new RegExp(`^${name}:\\s*(.+)$`, "mi"))?.[1]?.trim() ?? null;
|
|
18201
18201
|
}
|
|
18202
18202
|
function toPosix2(value) {
|
|
18203
|
-
return value.split(
|
|
18203
|
+
return value.split(path63.sep).join("/");
|
|
18204
18204
|
}
|
|
18205
18205
|
function message(cause) {
|
|
18206
18206
|
return cause instanceof Error ? cause.message : String(cause);
|
|
@@ -18214,9 +18214,9 @@ var init_write = __esm(() => {
|
|
|
18214
18214
|
// src/memory/ingest.ts
|
|
18215
18215
|
import { existsSync as existsSync5 } from "fs";
|
|
18216
18216
|
import { readFile as readFile30 } from "fs/promises";
|
|
18217
|
-
import
|
|
18217
|
+
import path64 from "path";
|
|
18218
18218
|
async function ingestMemory(cwd, source, filePath, config, now) {
|
|
18219
|
-
const absolute =
|
|
18219
|
+
const absolute = path64.resolve(cwd, filePath);
|
|
18220
18220
|
if (!await pathExists(absolute)) {
|
|
18221
18221
|
throw new Error(`Ingest source not found: ${filePath}`);
|
|
18222
18222
|
}
|
|
@@ -18233,8 +18233,8 @@ async function ingestMemory(cwd, source, filePath, config, now) {
|
|
|
18233
18233
|
const securityWarnings = [];
|
|
18234
18234
|
const securitySkipped = [];
|
|
18235
18235
|
let skippedDuplicates = 0;
|
|
18236
|
-
const dir =
|
|
18237
|
-
const link =
|
|
18236
|
+
const dir = path64.join(memoryRoot(cwd), folder);
|
|
18237
|
+
const link = path64.relative(cwd, absolute);
|
|
18238
18238
|
const date = dateString(now);
|
|
18239
18239
|
for (const text of candidates) {
|
|
18240
18240
|
const title = toTitle(text);
|
|
@@ -18415,7 +18415,7 @@ function uniqueSlug(dir, title) {
|
|
|
18415
18415
|
const base = slugify2(title) || "entry";
|
|
18416
18416
|
let slug = base;
|
|
18417
18417
|
let counter = 2;
|
|
18418
|
-
while (existsSync5(
|
|
18418
|
+
while (existsSync5(path64.join(dir, `${slug}.md`))) {
|
|
18419
18419
|
slug = `${base}-${counter}`;
|
|
18420
18420
|
counter += 1;
|
|
18421
18421
|
}
|
|
@@ -18450,7 +18450,7 @@ var init_ingest = __esm(() => {
|
|
|
18450
18450
|
|
|
18451
18451
|
// src/memory/supersede.ts
|
|
18452
18452
|
import { readFile as readFile31 } from "fs/promises";
|
|
18453
|
-
import
|
|
18453
|
+
import path65 from "path";
|
|
18454
18454
|
async function supersedeEntry(input, now) {
|
|
18455
18455
|
const date = input.date ?? now.toISOString().slice(0, 10);
|
|
18456
18456
|
const today = now.toISOString().slice(0, 10);
|
|
@@ -18510,12 +18510,12 @@ async function supersedeEntry(input, now) {
|
|
|
18510
18510
|
async function resolveEntryPath(cwd, raw) {
|
|
18511
18511
|
const root = memoryRoot(cwd);
|
|
18512
18512
|
const candidates = [
|
|
18513
|
-
|
|
18514
|
-
|
|
18515
|
-
|
|
18513
|
+
path65.resolve(cwd, raw),
|
|
18514
|
+
path65.resolve(root, raw),
|
|
18515
|
+
path65.isAbsolute(raw) ? raw : path65.join(cwd, raw)
|
|
18516
18516
|
];
|
|
18517
18517
|
for (const absolute of candidates) {
|
|
18518
|
-
const confined = await resolveCanonicalEntryPath(cwd,
|
|
18518
|
+
const confined = await resolveCanonicalEntryPath(cwd, path65.relative(root, absolute));
|
|
18519
18519
|
if (confined && await pathExists(confined.absolutePath)) {
|
|
18520
18520
|
return { absolute: confined.absolutePath, relative: confined.relativePath };
|
|
18521
18521
|
}
|
|
@@ -18711,9 +18711,9 @@ __export(exports_service3, {
|
|
|
18711
18711
|
});
|
|
18712
18712
|
import { createHash as createHash11 } from "crypto";
|
|
18713
18713
|
import { mkdir as mkdir16, readFile as readFile32, writeFile as writeFile10 } from "fs/promises";
|
|
18714
|
-
import
|
|
18714
|
+
import path66 from "path";
|
|
18715
18715
|
function dataRoot2(cwd) {
|
|
18716
|
-
return
|
|
18716
|
+
return path66.join(cwd, ".metaproject", "data", "memory");
|
|
18717
18717
|
}
|
|
18718
18718
|
function createMemoryService() {
|
|
18719
18719
|
const reportStore = createMemoryReportStore();
|
|
@@ -18728,9 +18728,9 @@ function createMemoryService() {
|
|
|
18728
18728
|
if (!/^[a-z0-9][a-z0-9-]*$/.test(slug)) {
|
|
18729
18729
|
throw new Error(`Invalid slug: ${slug}. Use lowercase letters, digits, and hyphens.`);
|
|
18730
18730
|
}
|
|
18731
|
-
const dir =
|
|
18732
|
-
const filePath =
|
|
18733
|
-
const relativePath =
|
|
18731
|
+
const dir = path66.join(memoryRoot(input.cwd), typeConfig.folder);
|
|
18732
|
+
const filePath = path66.join(dir, `${slug}.md`);
|
|
18733
|
+
const relativePath = path66.relative(input.cwd, filePath);
|
|
18734
18734
|
if (await pathExists(filePath) && !input.force) {
|
|
18735
18735
|
throw new Error(`Entry already exists: ${relativePath}. Use --force to overwrite.`);
|
|
18736
18736
|
}
|
|
@@ -18761,9 +18761,9 @@ function createMemoryService() {
|
|
|
18761
18761
|
async index(input) {
|
|
18762
18762
|
const entries = await collectEntries(input.cwd);
|
|
18763
18763
|
const generatedAt = new Date().toISOString();
|
|
18764
|
-
const indexDir =
|
|
18764
|
+
const indexDir = path66.join(dataRoot2(input.cwd), "index");
|
|
18765
18765
|
await mkdir16(indexDir, { recursive: true });
|
|
18766
|
-
const indexPath =
|
|
18766
|
+
const indexPath = path66.join(indexDir, "index.json");
|
|
18767
18767
|
await writeFile10(indexPath, `${JSON.stringify({
|
|
18768
18768
|
catalogVersion: 1,
|
|
18769
18769
|
sourceFingerprint: createHash11("sha256").update(JSON.stringify(entries.map((e) => ({
|
|
@@ -18784,7 +18784,7 @@ function createMemoryService() {
|
|
|
18784
18784
|
}, null, 2)}
|
|
18785
18785
|
`, "utf8");
|
|
18786
18786
|
const result = {
|
|
18787
|
-
path:
|
|
18787
|
+
path: path66.relative(input.cwd, indexPath),
|
|
18788
18788
|
entryCount: entries.length,
|
|
18789
18789
|
generatedAt
|
|
18790
18790
|
};
|
|
@@ -18797,7 +18797,7 @@ function createMemoryService() {
|
|
|
18797
18797
|
const built = await buildEmbeddingIndex(input.cwd, entries, embedder.embed, embedder.model, new Date);
|
|
18798
18798
|
result.embeddings = {
|
|
18799
18799
|
built: true,
|
|
18800
|
-
path:
|
|
18800
|
+
path: path66.relative(input.cwd, embeddingsDir(input.cwd)),
|
|
18801
18801
|
vectorCount: built.meta.entryCount,
|
|
18802
18802
|
model: built.meta.model
|
|
18803
18803
|
};
|
|
@@ -19399,7 +19399,7 @@ var init_ask = __esm(() => {
|
|
|
19399
19399
|
});
|
|
19400
19400
|
|
|
19401
19401
|
// src/wiki/backlinks.ts
|
|
19402
|
-
import
|
|
19402
|
+
import path67 from "path";
|
|
19403
19403
|
function extractCodePaths(content) {
|
|
19404
19404
|
const out = [];
|
|
19405
19405
|
let match;
|
|
@@ -19429,8 +19429,8 @@ function resolveLink(fromRepoPath, raw) {
|
|
|
19429
19429
|
const clean = (raw.split("#")[0] ?? "").trim();
|
|
19430
19430
|
if (!clean)
|
|
19431
19431
|
return "";
|
|
19432
|
-
const fromDir =
|
|
19433
|
-
return
|
|
19432
|
+
const fromDir = path67.posix.dirname(fromRepoPath.split(path67.sep).join("/"));
|
|
19433
|
+
return path67.posix.normalize(path67.posix.join(fromDir, clean));
|
|
19434
19434
|
}
|
|
19435
19435
|
function buildBacklinkIndex(pages) {
|
|
19436
19436
|
const index = new Map;
|
|
@@ -19444,18 +19444,18 @@ function buildBacklinkIndex(pages) {
|
|
|
19444
19444
|
}
|
|
19445
19445
|
};
|
|
19446
19446
|
for (const page of pages) {
|
|
19447
|
-
const from = page.repoPath.split(
|
|
19447
|
+
const from = page.repoPath.split(path67.sep).join("/");
|
|
19448
19448
|
for (const raw of extractLinks(page.content))
|
|
19449
19449
|
add(resolveLink(from, raw), from);
|
|
19450
19450
|
for (const raw of extractCodePaths(page.content))
|
|
19451
|
-
add(
|
|
19451
|
+
add(path67.posix.normalize(raw), from);
|
|
19452
19452
|
}
|
|
19453
19453
|
for (const list of index.values())
|
|
19454
19454
|
list.sort();
|
|
19455
19455
|
return index;
|
|
19456
19456
|
}
|
|
19457
19457
|
function backlinksFor(index, targetRepoPath) {
|
|
19458
|
-
const key =
|
|
19458
|
+
const key = path67.posix.normalize(targetRepoPath.split(path67.sep).join("/"));
|
|
19459
19459
|
return index.get(key) ?? [];
|
|
19460
19460
|
}
|
|
19461
19461
|
var LINK, CODE_SPAN, FILE_LIKE;
|
|
@@ -19468,7 +19468,7 @@ var init_backlinks = __esm(() => {
|
|
|
19468
19468
|
// src/ctx/assembly.ts
|
|
19469
19469
|
import { createHash as createHash12 } from "crypto";
|
|
19470
19470
|
import { mkdir as mkdir17, rename as rename6, writeFile as writeFile11 } from "fs/promises";
|
|
19471
|
-
import
|
|
19471
|
+
import path68 from "path";
|
|
19472
19472
|
function assembleContext(input) {
|
|
19473
19473
|
let items = 0;
|
|
19474
19474
|
let tokens = 0;
|
|
@@ -19512,9 +19512,9 @@ async function recordNoContentContext(input) {
|
|
|
19512
19512
|
return assembly;
|
|
19513
19513
|
}
|
|
19514
19514
|
async function recordContextAssembly(input) {
|
|
19515
|
-
const directory =
|
|
19515
|
+
const directory = path68.join(input.workspaceRoot, ".metaproject", "context-operations", "traces");
|
|
19516
19516
|
await mkdir17(directory, { recursive: true });
|
|
19517
|
-
const target =
|
|
19517
|
+
const target = path68.join(directory, path68.basename(input.assembly.traceRef));
|
|
19518
19518
|
const temporary = `${target}.${process.pid}.tmp`;
|
|
19519
19519
|
await writeFile11(temporary, `${JSON.stringify({ schemaVersion: "1.0", correlationId: input.correlationId, outcome: input.outcome, configurationRevision: input.assembly.configurationRevision, policy: { ref: input.assembly.policyRef, revision: input.assembly.policyRevision }, selected: input.assembly.selected, omittedOptional: input.assembly.omittedOptional, partial: input.assembly.partial })}
|
|
19520
19520
|
`, { mode: 384 });
|
|
@@ -20365,15 +20365,15 @@ __export(exports_service4, {
|
|
|
20365
20365
|
import { spawn as spawn3 } from "child_process";
|
|
20366
20366
|
import { createHash as createHash14 } from "crypto";
|
|
20367
20367
|
import { mkdir as mkdir18, readFile as readFile34, readdir as readdir12, rm as rm5, writeFile as writeFile12 } from "fs/promises";
|
|
20368
|
-
import
|
|
20368
|
+
import path69 from "path";
|
|
20369
20369
|
function wikiRootPath2(cwd) {
|
|
20370
|
-
return
|
|
20370
|
+
return path69.join(cwd, ".metaproject", "wiki");
|
|
20371
20371
|
}
|
|
20372
20372
|
function dataRootPath(cwd) {
|
|
20373
|
-
return
|
|
20373
|
+
return path69.join(cwd, ".metaproject", "data", "gdwiki");
|
|
20374
20374
|
}
|
|
20375
20375
|
function linkCheckReportPath(cwd) {
|
|
20376
|
-
return
|
|
20376
|
+
return path69.join(dataRootPath(cwd), "link-check", "latest.md");
|
|
20377
20377
|
}
|
|
20378
20378
|
async function wikiStatus(cwd) {
|
|
20379
20379
|
const root = wikiRootPath2(cwd);
|
|
@@ -20381,7 +20381,7 @@ async function wikiStatus(cwd) {
|
|
|
20381
20381
|
const pages = enabled ? await collectPages(cwd) : [];
|
|
20382
20382
|
return {
|
|
20383
20383
|
enabled,
|
|
20384
|
-
wikiRoot:
|
|
20384
|
+
wikiRoot: path69.relative(cwd, root),
|
|
20385
20385
|
totalPages: pages.length,
|
|
20386
20386
|
countsByType: WIKI_PAGE_TYPES.map(({ type }) => ({
|
|
20387
20387
|
type,
|
|
@@ -20412,9 +20412,9 @@ async function wikiCreatePage(input) {
|
|
|
20412
20412
|
if (!/^[a-z0-9][a-z0-9-]*$/.test(input.slug)) {
|
|
20413
20413
|
throw new Error(`Invalid slug: ${input.slug}. Use lowercase letters, digits, and hyphens.`);
|
|
20414
20414
|
}
|
|
20415
|
-
const dir =
|
|
20416
|
-
const filePath =
|
|
20417
|
-
const relativePath =
|
|
20415
|
+
const dir = path69.join(wikiRootPath2(input.cwd), typeConfig.folder);
|
|
20416
|
+
const filePath = path69.join(dir, `${input.slug}.md`);
|
|
20417
|
+
const relativePath = path69.relative(input.cwd, filePath);
|
|
20418
20418
|
if (await pathExists(filePath) && !input.force) {
|
|
20419
20419
|
throw new Error(`Page already exists: ${relativePath}. Use --force to overwrite.`);
|
|
20420
20420
|
}
|
|
@@ -20425,7 +20425,7 @@ async function wikiCreatePage(input) {
|
|
|
20425
20425
|
}
|
|
20426
20426
|
async function wikiGenerateIndex(cwd) {
|
|
20427
20427
|
const root = wikiRootPath2(cwd);
|
|
20428
|
-
const indexPath =
|
|
20428
|
+
const indexPath = path69.join(root, "index.md");
|
|
20429
20429
|
const pages = await collectPages(cwd);
|
|
20430
20430
|
const generatedAt = new Date().toISOString();
|
|
20431
20431
|
const managedBlock = `${WIKI_INDEX_BEGIN}
|
|
@@ -20443,7 +20443,7 @@ ${managedBlock}
|
|
|
20443
20443
|
await mkdir18(root, { recursive: true });
|
|
20444
20444
|
await writeFile12(indexPath, next, "utf8");
|
|
20445
20445
|
return {
|
|
20446
|
-
path:
|
|
20446
|
+
path: path69.relative(cwd, indexPath),
|
|
20447
20447
|
pageCount: pages.length,
|
|
20448
20448
|
generatedAt
|
|
20449
20449
|
};
|
|
@@ -20451,13 +20451,13 @@ ${managedBlock}
|
|
|
20451
20451
|
async function wikiCheckLinks(cwd) {
|
|
20452
20452
|
const root = wikiRootPath2(cwd);
|
|
20453
20453
|
const allFiles = await pathExists(root) ? await walkMarkdown(root) : [];
|
|
20454
|
-
const files = allFiles.filter((absolutePath) => !
|
|
20454
|
+
const files = allFiles.filter((absolutePath) => !path69.relative(root, absolutePath).startsWith(`templates${path69.sep}`));
|
|
20455
20455
|
const broken = [];
|
|
20456
20456
|
let checkedLinks = 0;
|
|
20457
20457
|
let skippedExternal = 0;
|
|
20458
20458
|
for (const absolutePath of files) {
|
|
20459
20459
|
const content = await readFile34(absolutePath, "utf8");
|
|
20460
|
-
const pageRelative =
|
|
20460
|
+
const pageRelative = path69.relative(cwd, absolutePath);
|
|
20461
20461
|
for (const target of extractLinkTargets(content)) {
|
|
20462
20462
|
if (EXTERNAL_LINK.test(target)) {
|
|
20463
20463
|
skippedExternal += 1;
|
|
@@ -20468,7 +20468,7 @@ async function wikiCheckLinks(cwd) {
|
|
|
20468
20468
|
continue;
|
|
20469
20469
|
}
|
|
20470
20470
|
checkedLinks += 1;
|
|
20471
|
-
const resolved =
|
|
20471
|
+
const resolved = path69.resolve(path69.dirname(absolutePath), filePart);
|
|
20472
20472
|
if (!await pathExists(resolved)) {
|
|
20473
20473
|
broken.push({
|
|
20474
20474
|
page: pageRelative,
|
|
@@ -20480,7 +20480,7 @@ async function wikiCheckLinks(cwd) {
|
|
|
20480
20480
|
}
|
|
20481
20481
|
const generatedAt = new Date().toISOString();
|
|
20482
20482
|
const reportPath = linkCheckReportPath(cwd);
|
|
20483
|
-
await mkdir18(
|
|
20483
|
+
await mkdir18(path69.dirname(reportPath), { recursive: true });
|
|
20484
20484
|
await writeFile12(reportPath, renderLinkCheckReport({
|
|
20485
20485
|
generatedAt,
|
|
20486
20486
|
checkedPages: files.length,
|
|
@@ -20489,7 +20489,7 @@ async function wikiCheckLinks(cwd) {
|
|
|
20489
20489
|
broken
|
|
20490
20490
|
}), "utf8");
|
|
20491
20491
|
return {
|
|
20492
|
-
reportPath:
|
|
20492
|
+
reportPath: path69.relative(cwd, reportPath),
|
|
20493
20493
|
checkedPages: files.length,
|
|
20494
20494
|
checkedLinks,
|
|
20495
20495
|
skippedExternal,
|
|
@@ -20539,7 +20539,7 @@ async function wikiValidate(cwd) {
|
|
|
20539
20539
|
}
|
|
20540
20540
|
if (await isIndexStale(cwd, pages)) {
|
|
20541
20541
|
issues.push({
|
|
20542
|
-
page:
|
|
20542
|
+
page: path69.join(path69.relative(cwd, wikiRootPath2(cwd)), "index.md"),
|
|
20543
20543
|
kind: "index",
|
|
20544
20544
|
message: "index out of date, run `keryx wiki index`"
|
|
20545
20545
|
});
|
|
@@ -20576,7 +20576,7 @@ async function wikiCollect(input) {
|
|
|
20576
20576
|
};
|
|
20577
20577
|
}
|
|
20578
20578
|
async function wikiPruneOrphans(cwd) {
|
|
20579
|
-
const componentsDir =
|
|
20579
|
+
const componentsDir = path69.join(wikiRootPath2(cwd), "components");
|
|
20580
20580
|
if (!await pathExists(componentsDir)) {
|
|
20581
20581
|
return { pruned: [], orphanedAccepted: [] };
|
|
20582
20582
|
}
|
|
@@ -20593,20 +20593,20 @@ async function wikiPruneOrphans(cwd) {
|
|
|
20593
20593
|
if (validSlugs.has(slug)) {
|
|
20594
20594
|
continue;
|
|
20595
20595
|
}
|
|
20596
|
-
const filePath =
|
|
20596
|
+
const filePath = path69.join(componentsDir, entry);
|
|
20597
20597
|
const current = await readFile34(filePath, "utf8");
|
|
20598
20598
|
const isUnmodifiedDraft = /\nStatus:\s*draft\s*\n/.test(current) && current.includes("Generated by `keryx wiki collect`");
|
|
20599
20599
|
if (isUnmodifiedDraft) {
|
|
20600
20600
|
await rm5(filePath);
|
|
20601
|
-
pruned.push(
|
|
20601
|
+
pruned.push(path69.relative(cwd, filePath));
|
|
20602
20602
|
} else {
|
|
20603
|
-
orphanedAccepted.push(
|
|
20603
|
+
orphanedAccepted.push(path69.relative(cwd, filePath));
|
|
20604
20604
|
}
|
|
20605
20605
|
}
|
|
20606
20606
|
return { pruned, orphanedAccepted };
|
|
20607
20607
|
}
|
|
20608
20608
|
async function validModuleNames(cwd) {
|
|
20609
|
-
const nodesPath =
|
|
20609
|
+
const nodesPath = path69.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
|
|
20610
20610
|
if (!await pathExists(nodesPath)) {
|
|
20611
20611
|
return;
|
|
20612
20612
|
}
|
|
@@ -20676,9 +20676,9 @@ async function wikiEvidence(input) {
|
|
|
20676
20676
|
});
|
|
20677
20677
|
}
|
|
20678
20678
|
function resolveEvidenceScope(cwd, override) {
|
|
20679
|
-
const absolute =
|
|
20679
|
+
const absolute = path69.resolve(cwd);
|
|
20680
20680
|
return {
|
|
20681
|
-
projectId: override?.projectId ?? (
|
|
20681
|
+
projectId: override?.projectId ?? (path69.basename(absolute) || "project"),
|
|
20682
20682
|
checkoutId: override?.checkoutId ?? `checkout:${createHash14("sha256").update(absolute).digest("hex").slice(0, 16)}`,
|
|
20683
20683
|
...override?.workspaceId ? { workspaceId: override.workspaceId } : {},
|
|
20684
20684
|
...override?.taskId ? { taskId: override.taskId } : {}
|
|
@@ -20693,7 +20693,7 @@ function isMachineAuthoredPage(pageType, relativePath, content) {
|
|
|
20693
20693
|
if (source === null) {
|
|
20694
20694
|
return false;
|
|
20695
20695
|
}
|
|
20696
|
-
const normalised = relativePath.split(
|
|
20696
|
+
const normalised = relativePath.split(path69.sep).join("/").replace(/^wiki\//, "");
|
|
20697
20697
|
return WIKI_PAGE_PRODUCERS.some((producer) => producer.source === source && producer.pageType === pageType && producer.path.test(normalised) && /^-[ \t]+Link:.*\bsha256\b/m.test(content));
|
|
20698
20698
|
}
|
|
20699
20699
|
function createGdWikiService() {
|
|
@@ -20709,8 +20709,8 @@ function createGdWikiService() {
|
|
|
20709
20709
|
};
|
|
20710
20710
|
}
|
|
20711
20711
|
async function collectGraphWikiCandidates(cwd, generatedAt, limit, onlyModules) {
|
|
20712
|
-
const nodesPath =
|
|
20713
|
-
const edgesPath =
|
|
20712
|
+
const nodesPath = path69.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
|
|
20713
|
+
const edgesPath = path69.join(cwd, ".metaproject", "data", "gdgraph", "storage", "edges.jsonl");
|
|
20714
20714
|
if (!await pathExists(nodesPath) || !await pathExists(edgesPath)) {
|
|
20715
20715
|
return [];
|
|
20716
20716
|
}
|
|
@@ -20894,7 +20894,7 @@ function topCounts(bucket, limit) {
|
|
|
20894
20894
|
return [...bucket.entries()].sort((a, b) => b[1] - a[1]).slice(0, limit);
|
|
20895
20895
|
}
|
|
20896
20896
|
async function readModuleReadme(cwd, moduleName) {
|
|
20897
|
-
const readmePath =
|
|
20897
|
+
const readmePath = path69.join(cwd, ...moduleName.split("/"), "README.md");
|
|
20898
20898
|
if (!await pathExists(readmePath)) {
|
|
20899
20899
|
return null;
|
|
20900
20900
|
}
|
|
@@ -20915,7 +20915,7 @@ async function extractModuleExports(cwd, files) {
|
|
|
20915
20915
|
const declRe = /export\s+(?:async\s+)?(?:default\s+)?(?:const|let|var|function|class|type|interface|enum)\s+([A-Za-z_$][\w$]*)/g;
|
|
20916
20916
|
const braceRe = /export\s*\{([^}]+)\}/g;
|
|
20917
20917
|
for (const file of files.slice(0, 4)) {
|
|
20918
|
-
const filePath =
|
|
20918
|
+
const filePath = path69.join(cwd, ...file.split("/"));
|
|
20919
20919
|
if (!await pathExists(filePath)) {
|
|
20920
20920
|
continue;
|
|
20921
20921
|
}
|
|
@@ -20946,7 +20946,7 @@ async function extractModuleExports(cwd, files) {
|
|
|
20946
20946
|
}
|
|
20947
20947
|
async function extractModuleApi(cwd, files) {
|
|
20948
20948
|
const names = await extractModuleExports(cwd, files);
|
|
20949
|
-
const symbolsPath =
|
|
20949
|
+
const symbolsPath = path69.join(cwd, ".metaproject", "data", "gdgraph", "storage", "symbols.jsonl");
|
|
20950
20950
|
if (names.length === 0 || !await pathExists(symbolsPath)) {
|
|
20951
20951
|
return names.map((name) => "`" + name + "`");
|
|
20952
20952
|
}
|
|
@@ -20972,7 +20972,7 @@ async function extractModuleApi(cwd, files) {
|
|
|
20972
20972
|
});
|
|
20973
20973
|
}
|
|
20974
20974
|
async function collectHealthWikiCandidates(cwd, generatedAt) {
|
|
20975
|
-
const healthPath =
|
|
20975
|
+
const healthPath = path69.join(cwd, ".metaproject", "data", "health", "artifacts", "latest.json");
|
|
20976
20976
|
if (!await pathExists(healthPath)) {
|
|
20977
20977
|
return [];
|
|
20978
20978
|
}
|
|
@@ -21014,7 +21014,7 @@ async function collectHealthWikiCandidates(cwd, generatedAt) {
|
|
|
21014
21014
|
}];
|
|
21015
21015
|
}
|
|
21016
21016
|
async function collectTestingWikiCandidates(cwd, generatedAt) {
|
|
21017
|
-
const contextPath =
|
|
21017
|
+
const contextPath = path69.join(cwd, ".metaproject", "data", "testing", "context.md");
|
|
21018
21018
|
if (!await pathExists(contextPath)) {
|
|
21019
21019
|
return [];
|
|
21020
21020
|
}
|
|
@@ -21045,8 +21045,8 @@ async function writeCollectedPage(cwd, candidate, force) {
|
|
|
21045
21045
|
if (!folder) {
|
|
21046
21046
|
throw new Error(`Unsupported collected wiki type: ${candidate.type}`);
|
|
21047
21047
|
}
|
|
21048
|
-
const filePath =
|
|
21049
|
-
const relativePath =
|
|
21048
|
+
const filePath = path69.join(wikiRootPath2(cwd), folder, `${candidate.slug}.md`);
|
|
21049
|
+
const relativePath = path69.relative(cwd, filePath);
|
|
21050
21050
|
const exists = await pathExists(filePath);
|
|
21051
21051
|
if (exists && !force) {
|
|
21052
21052
|
return { path: relativePath, type: candidate.type, source: candidate.source, action: "skipped" };
|
|
@@ -21074,7 +21074,7 @@ async function writeCollectedPage(cwd, candidate, force) {
|
|
|
21074
21074
|
securityReason: output.reason
|
|
21075
21075
|
};
|
|
21076
21076
|
}
|
|
21077
|
-
await mkdir18(
|
|
21077
|
+
await mkdir18(path69.dirname(filePath), { recursive: true });
|
|
21078
21078
|
await writeFile12(filePath, output.content, "utf8");
|
|
21079
21079
|
return {
|
|
21080
21080
|
path: relativePath,
|
|
@@ -21086,7 +21086,7 @@ async function writeCollectedPage(cwd, candidate, force) {
|
|
|
21086
21086
|
async function wikiPagesForFile(cwd, targetRepoPath) {
|
|
21087
21087
|
const pages = await collectPages(cwd);
|
|
21088
21088
|
const refs = await Promise.all(pages.map(async (page) => ({
|
|
21089
|
-
repoPath:
|
|
21089
|
+
repoPath: path69.relative(cwd, page.absolutePath).split(path69.sep).join("/"),
|
|
21090
21090
|
content: await readFile34(page.absolutePath, "utf8")
|
|
21091
21091
|
})));
|
|
21092
21092
|
return backlinksFor(buildBacklinkIndex(refs), targetRepoPath);
|
|
@@ -21125,7 +21125,7 @@ function renderIndexBody(pages, generatedAt) {
|
|
|
21125
21125
|
`).trimEnd();
|
|
21126
21126
|
}
|
|
21127
21127
|
async function isIndexStale(cwd, pages) {
|
|
21128
|
-
const indexPath =
|
|
21128
|
+
const indexPath = path69.join(wikiRootPath2(cwd), "index.md");
|
|
21129
21129
|
if (!await pathExists(indexPath)) {
|
|
21130
21130
|
return true;
|
|
21131
21131
|
}
|
|
@@ -21143,7 +21143,7 @@ async function walkMarkdown(root) {
|
|
|
21143
21143
|
const results = [];
|
|
21144
21144
|
const entries = await readdir12(root, { withFileTypes: true });
|
|
21145
21145
|
for (const entry of entries) {
|
|
21146
|
-
const absolutePath =
|
|
21146
|
+
const absolutePath = path69.join(root, entry.name);
|
|
21147
21147
|
if (entry.isDirectory()) {
|
|
21148
21148
|
results.push(...await walkMarkdown(absolutePath));
|
|
21149
21149
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -21200,7 +21200,7 @@ ${JSON.stringify(state, null, 2)}
|
|
|
21200
21200
|
`;
|
|
21201
21201
|
}
|
|
21202
21202
|
async function readIndexGeneratedAt(cwd) {
|
|
21203
|
-
const indexPath =
|
|
21203
|
+
const indexPath = path69.join(wikiRootPath2(cwd), "index.md");
|
|
21204
21204
|
if (!await pathExists(indexPath)) {
|
|
21205
21205
|
return null;
|
|
21206
21206
|
}
|
|
@@ -21437,7 +21437,7 @@ async function validateStructure(cwd, pages, issues) {
|
|
|
21437
21437
|
if (pattern.includes("*")) {
|
|
21438
21438
|
continue;
|
|
21439
21439
|
}
|
|
21440
|
-
if (!await pathExists(
|
|
21440
|
+
if (!await pathExists(path69.join(cwd, pattern))) {
|
|
21441
21441
|
issues.push({
|
|
21442
21442
|
page: page.relativePath,
|
|
21443
21443
|
kind: "describes",
|
|
@@ -21508,9 +21508,9 @@ var init_service4 = __esm(() => {
|
|
|
21508
21508
|
// src/gdgraph/wiki-layer.ts
|
|
21509
21509
|
import { createHash as createHash15 } from "crypto";
|
|
21510
21510
|
import { mkdir as mkdir19, stat as stat10, writeFile as writeFile13 } from "fs/promises";
|
|
21511
|
-
import
|
|
21511
|
+
import path70 from "path";
|
|
21512
21512
|
function storageDir(projectRoot) {
|
|
21513
|
-
return
|
|
21513
|
+
return path70.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
|
|
21514
21514
|
}
|
|
21515
21515
|
function wikiPageId(relativePath) {
|
|
21516
21516
|
return `wiki:${relativePath}`;
|
|
@@ -21576,11 +21576,11 @@ async function enrichBuildWithWikiLayer(input) {
|
|
|
21576
21576
|
const mtimes = new Map;
|
|
21577
21577
|
for (const record of input.fileRecords) {
|
|
21578
21578
|
try {
|
|
21579
|
-
const info = await stat10(
|
|
21579
|
+
const info = await stat10(path70.join(input.projectRoot, record.path));
|
|
21580
21580
|
mtimes.set(record.path, info.mtimeMs);
|
|
21581
21581
|
} catch {}
|
|
21582
21582
|
}
|
|
21583
|
-
await writeFile13(
|
|
21583
|
+
await writeFile13(path70.join(dir, BUILD_MANIFEST_FILE), `${JSON.stringify({ version: 1, files: computeFingerprints(input.fileRecords, mtimes) }, null, 2)}
|
|
21584
21584
|
`, "utf8");
|
|
21585
21585
|
const validModules = input.validModules !== undefined ? input.validModules : await (input.loadValidModules ?? defaultLoadValidModules)(input.projectRoot);
|
|
21586
21586
|
const wikiPages = await collectPages(input.projectRoot);
|
|
@@ -21605,8 +21605,8 @@ async function enrichBuildWithWikiLayer(input) {
|
|
|
21605
21605
|
version: page.version
|
|
21606
21606
|
}))
|
|
21607
21607
|
});
|
|
21608
|
-
await writeJsonl(
|
|
21609
|
-
await writeJsonl(
|
|
21608
|
+
await writeJsonl(path70.join(dir, WIKI_PAGES_FILE), layer.pages);
|
|
21609
|
+
await writeJsonl(path70.join(dir, DESCRIBES_FILE), layer.describes);
|
|
21610
21610
|
return layer;
|
|
21611
21611
|
}
|
|
21612
21612
|
async function defaultLoadValidModules(projectRoot) {
|
|
@@ -21629,6 +21629,9 @@ __export(exports_service2, {
|
|
|
21629
21629
|
AC_CHECK_TOKEN_BUDGET: () => AC_CHECK_TOKEN_BUDGET,
|
|
21630
21630
|
AC_KINDS: () => AC_KINDS,
|
|
21631
21631
|
CONFIRMATION_CAVEAT: () => CONFIRMATION_CAVEAT,
|
|
21632
|
+
DEFAULT_OUTCOME_AUTHOR: () => DEFAULT_OUTCOME_AUTHOR,
|
|
21633
|
+
OUTCOME_AUTHORS: () => OUTCOME_AUTHORS,
|
|
21634
|
+
OUTCOME_AUTHOR_READINGS: () => OUTCOME_AUTHOR_READINGS,
|
|
21632
21635
|
OUTCOME_HINT: () => OUTCOME_HINT,
|
|
21633
21636
|
REVIEW_GATE_CONFIG_PATH: () => REVIEW_GATE_CONFIG_PATH,
|
|
21634
21637
|
acCheckCacheKey: () => acCheckCacheKey,
|
|
@@ -21655,11 +21658,13 @@ __export(exports_service2, {
|
|
|
21655
21658
|
isFrozen: () => isFrozen,
|
|
21656
21659
|
notCheckableVerdict: () => notCheckableVerdict,
|
|
21657
21660
|
parseAcceptanceCriteria: () => parseAcceptanceCriteria,
|
|
21661
|
+
parseOutcomeAuthor: () => parseOutcomeAuthor,
|
|
21658
21662
|
proseOutsideFences: () => proseOutsideFences,
|
|
21659
21663
|
readAcCheckCache: () => readAcCheckCache,
|
|
21660
21664
|
readAcCheckEnabled: () => readAcCheckEnabled,
|
|
21661
21665
|
readAcKindRecords: () => readAcKindRecords,
|
|
21662
21666
|
readFlow: () => readFlow,
|
|
21667
|
+
readOutcomeAuthor: () => readOutcomeAuthor,
|
|
21663
21668
|
renderAcCheckAdvisoryNotice: () => renderAcCheckAdvisoryNotice,
|
|
21664
21669
|
renderAcCheckReport: () => renderAcCheckReport,
|
|
21665
21670
|
renderAcKindDistribution: () => renderAcKindDistribution,
|
|
@@ -21671,11 +21676,13 @@ __export(exports_service2, {
|
|
|
21671
21676
|
statusLabel: () => statusLabel,
|
|
21672
21677
|
stripVerifyMarker: () => stripVerifyMarker,
|
|
21673
21678
|
summarizeVerdicts: () => summarizeVerdicts,
|
|
21679
|
+
uncommittedFlowStateNote: () => uncommittedFlowStateNote,
|
|
21680
|
+
uncommittedFlowStateNotes: () => uncommittedFlowStateNotes,
|
|
21674
21681
|
validateCriterionName: () => validateCriterionName,
|
|
21675
21682
|
writeAcCheckCache: () => writeAcCheckCache
|
|
21676
21683
|
});
|
|
21677
21684
|
import { mkdir as mkdir11, readFile as readFile24 } from "fs/promises";
|
|
21678
|
-
import
|
|
21685
|
+
import path51 from "path";
|
|
21679
21686
|
|
|
21680
21687
|
// src/flow/machine.ts
|
|
21681
21688
|
var TRANSITIONS = {
|
|
@@ -23120,6 +23127,19 @@ async function reviewGate(input) {
|
|
|
23120
23127
|
return { name: "review", status: verdict.status, detail: verdict.detail };
|
|
23121
23128
|
}
|
|
23122
23129
|
|
|
23130
|
+
// src/flow/outcome-author.ts
|
|
23131
|
+
var OUTCOME_AUTHORS = ["agent", "human"];
|
|
23132
|
+
var OUTCOME_AUTHOR_READINGS = [...OUTCOME_AUTHORS, "unknown"];
|
|
23133
|
+
var DEFAULT_OUTCOME_AUTHOR = "agent";
|
|
23134
|
+
function readOutcomeAuthor(value) {
|
|
23135
|
+
return value === "agent" || value === "human" ? value : "unknown";
|
|
23136
|
+
}
|
|
23137
|
+
function parseOutcomeAuthor(raw, flag = "--outcome-author") {
|
|
23138
|
+
if (raw === "agent" || raw === "human")
|
|
23139
|
+
return raw;
|
|
23140
|
+
const shown = typeof raw === "string" ? `"${raw}"` : "nothing";
|
|
23141
|
+
throw new Error(`${flag} must be one of: ${OUTCOME_AUTHORS.join(", ")} (got ${shown}).`);
|
|
23142
|
+
}
|
|
23123
23143
|
// src/flow/identity.ts
|
|
23124
23144
|
function resolveSignerIdentity(input) {
|
|
23125
23145
|
const stated = input.stated?.trim();
|
|
@@ -23406,6 +23426,11 @@ function flowStateSchema() {
|
|
|
23406
23426
|
$ref: "#/definitions/identity",
|
|
23407
23427
|
description: "The human accountable for this flow, or absent if one was never set. Never inferred: only ever written by an explicit `--owner` on `flow init` or `flow owner set`, so `basis` is always `stated`."
|
|
23408
23428
|
},
|
|
23429
|
+
outcomeAuthor: {
|
|
23430
|
+
type: "string",
|
|
23431
|
+
enum: ["agent", "human"],
|
|
23432
|
+
description: "Who wrote the outcome criterion. Written by `flow init --outcome-author` (default `agent`; `human` only when the flag says so, never inferred) and changed only by `flow outcome author`, which journals the change. Absent on flows created before the field existed, and read as `unknown` (neither agent nor human). Gates nothing."
|
|
23433
|
+
},
|
|
23409
23434
|
signatures: {
|
|
23410
23435
|
type: "array",
|
|
23411
23436
|
description: "Append-only signing record for `flow ac confirm` and a passing `flow complete`. Absent means never signed under this field's existence.",
|
|
@@ -23994,6 +24019,108 @@ async function readRequireConfirmationDefault(cwd) {
|
|
|
23994
24019
|
return false;
|
|
23995
24020
|
}
|
|
23996
24021
|
}
|
|
24022
|
+
// src/flow/uncommitted-state.ts
|
|
24023
|
+
import path15 from "path";
|
|
24024
|
+
var UNCOMMITTED_LIST_CAP = 5;
|
|
24025
|
+
var READ_ONLY_GIT_FLAGS = ["--no-optional-locks"];
|
|
24026
|
+
var GIT_TIMEOUT_MS = 5000;
|
|
24027
|
+
var spawnGit = async (cwd, args) => {
|
|
24028
|
+
const proc = Bun.spawn(["git", ...args], {
|
|
24029
|
+
cwd,
|
|
24030
|
+
stdout: "pipe",
|
|
24031
|
+
stderr: "pipe",
|
|
24032
|
+
timeout: GIT_TIMEOUT_MS
|
|
24033
|
+
});
|
|
24034
|
+
const [out, code] = await Promise.all([new Response(proc.stdout).text(), proc.exited]);
|
|
24035
|
+
return { code: proc.signalCode === null ? code : -1, out };
|
|
24036
|
+
};
|
|
24037
|
+
var FLOW_PATH = /(?:^|\/)\.metaproject\/flows\/([^/]+)\/(.+)$/;
|
|
24038
|
+
function groupByFlowDir(listing, porcelain) {
|
|
24039
|
+
const groups = new Map;
|
|
24040
|
+
for (const line of listing.split(`
|
|
24041
|
+
`)) {
|
|
24042
|
+
let file = porcelain ? line.length < 4 ? "" : line.slice(3) : line;
|
|
24043
|
+
const renamed = porcelain ? file.indexOf(" -> ") : -1;
|
|
24044
|
+
if (renamed !== -1)
|
|
24045
|
+
file = file.slice(renamed + 4);
|
|
24046
|
+
file = file.replace(/^"|"$/g, "");
|
|
24047
|
+
const match = FLOW_PATH.exec(file);
|
|
24048
|
+
if (match === null)
|
|
24049
|
+
continue;
|
|
24050
|
+
const [, dir, inside] = match;
|
|
24051
|
+
if (dir === undefined || inside === undefined)
|
|
24052
|
+
continue;
|
|
24053
|
+
const list = groups.get(dir);
|
|
24054
|
+
if (list === undefined)
|
|
24055
|
+
groups.set(dir, [inside]);
|
|
24056
|
+
else
|
|
24057
|
+
list.push(inside);
|
|
24058
|
+
}
|
|
24059
|
+
return groups;
|
|
24060
|
+
}
|
|
24061
|
+
function noteFor(flowId, dir, listings) {
|
|
24062
|
+
if ((listings.tracked.get(dir) ?? []).length === 0)
|
|
24063
|
+
return null;
|
|
24064
|
+
const seen = new Set;
|
|
24065
|
+
for (const inside of listings.status.get(dir) ?? []) {
|
|
24066
|
+
const slash = inside.indexOf("/");
|
|
24067
|
+
seen.add(slash === -1 ? inside : `${inside.slice(0, slash)}/`);
|
|
24068
|
+
}
|
|
24069
|
+
const entries = [...seen];
|
|
24070
|
+
if (entries.length === 0)
|
|
24071
|
+
return null;
|
|
24072
|
+
const shown = entries.slice(0, UNCOMMITTED_LIST_CAP);
|
|
24073
|
+
const more = entries.length - shown.length;
|
|
24074
|
+
const list = `${shown.join(", ")}${more > 0 ? `, +${more} more` : ""}`;
|
|
24075
|
+
return `flow ${flowId} has uncommitted changes in .metaproject/flows/${dir}: ${list} \u2014 ` + "a common cause is the closing state `flow complete` writes after the merge; commit it (nothing gates on this)";
|
|
24076
|
+
}
|
|
24077
|
+
async function readGit(cwd, scope, git) {
|
|
24078
|
+
const tracked = await git(cwd, [...READ_ONLY_GIT_FLAGS, "ls-files", "--", scope]);
|
|
24079
|
+
if (tracked.code !== 0)
|
|
24080
|
+
return null;
|
|
24081
|
+
const empty = { tracked: new Map, status: new Map };
|
|
24082
|
+
if (tracked.out.trim().length === 0)
|
|
24083
|
+
return empty;
|
|
24084
|
+
const status = await git(cwd, [
|
|
24085
|
+
...READ_ONLY_GIT_FLAGS,
|
|
24086
|
+
"-c",
|
|
24087
|
+
"core.quotepath=off",
|
|
24088
|
+
"status",
|
|
24089
|
+
"--porcelain",
|
|
24090
|
+
"--untracked-files=all",
|
|
24091
|
+
"--",
|
|
24092
|
+
scope
|
|
24093
|
+
]);
|
|
24094
|
+
if (status.code !== 0)
|
|
24095
|
+
return null;
|
|
24096
|
+
return { tracked: groupByFlowDir(tracked.out, false), status: groupByFlowDir(status.out, true) };
|
|
24097
|
+
}
|
|
24098
|
+
async function uncommittedFlowStateNote(cwd, flowId, dir, git = spawnGit) {
|
|
24099
|
+
try {
|
|
24100
|
+
const read = await readGit(cwd, path15.join(flowsRoot(cwd), dir), git);
|
|
24101
|
+
return read === null ? null : noteFor(flowId, dir, read);
|
|
24102
|
+
} catch {
|
|
24103
|
+
return null;
|
|
24104
|
+
}
|
|
24105
|
+
}
|
|
24106
|
+
async function uncommittedFlowStateNotes(cwd, flows, git = spawnGit) {
|
|
24107
|
+
const notes = new Map;
|
|
24108
|
+
if (flows.length === 0)
|
|
24109
|
+
return notes;
|
|
24110
|
+
try {
|
|
24111
|
+
const read = await readGit(cwd, flowsRoot(cwd), git);
|
|
24112
|
+
if (read === null)
|
|
24113
|
+
return notes;
|
|
24114
|
+
for (const flow of flows) {
|
|
24115
|
+
const text = noteFor(flow.id, flow.dir, read);
|
|
24116
|
+
if (text !== null)
|
|
24117
|
+
notes.set(flow.dir, text);
|
|
24118
|
+
}
|
|
24119
|
+
} catch {
|
|
24120
|
+
return new Map;
|
|
24121
|
+
}
|
|
24122
|
+
return notes;
|
|
24123
|
+
}
|
|
23997
24124
|
// src/flow/ac-kinds.ts
|
|
23998
24125
|
var AC_KINDS = ["exec", "invariant", "judged", "none", "unclassified"];
|
|
23999
24126
|
var AC_LINE = /^\s*[-*]\s*(AC\d+)\s*:\s?(.*)$/i;
|
|
@@ -24151,7 +24278,7 @@ function readAcKindRecords(value) {
|
|
|
24151
24278
|
}
|
|
24152
24279
|
// src/flow/description-intent.ts
|
|
24153
24280
|
import { readFile as readFile10 } from "fs/promises";
|
|
24154
|
-
import
|
|
24281
|
+
import path16 from "path";
|
|
24155
24282
|
var OUTCOME_HINT = 'State an outcome criterion: what you would look at afterwards to see this helped, as a bullet. Or write "- not measured \u2014 <reason>".';
|
|
24156
24283
|
var PLACEHOLDERS = ["Describe the problem precisely", "What must be true when this flow is done"];
|
|
24157
24284
|
var FLOW_STATEMENT_HEADINGS = [/^problem$/i, /^expected outcome$/i];
|
|
@@ -24238,7 +24365,7 @@ function initIntentNote(description) {
|
|
|
24238
24365
|
}
|
|
24239
24366
|
async function intentNoteForNewFlow(cwd, dir) {
|
|
24240
24367
|
try {
|
|
24241
|
-
return initIntentNote(await readFile10(
|
|
24368
|
+
return initIntentNote(await readFile10(path16.join(cwd, dir, "description.md"), "utf8"));
|
|
24242
24369
|
} catch {
|
|
24243
24370
|
return null;
|
|
24244
24371
|
}
|
|
@@ -24246,7 +24373,7 @@ async function intentNoteForNewFlow(cwd, dir) {
|
|
|
24246
24373
|
// src/flow/check-ac.ts
|
|
24247
24374
|
import { createHash as createHash8 } from "crypto";
|
|
24248
24375
|
import { chmod as chmod4, mkdir as mkdir9, readFile as readFile22 } from "fs/promises";
|
|
24249
|
-
import
|
|
24376
|
+
import path48 from "path";
|
|
24250
24377
|
|
|
24251
24378
|
// src/review/cost.ts
|
|
24252
24379
|
function estimateTokens(text) {
|
|
@@ -24434,7 +24561,7 @@ function factsOnlyVerdict(item) {
|
|
|
24434
24561
|
}
|
|
24435
24562
|
async function readAcCheckEnabled(cwd) {
|
|
24436
24563
|
try {
|
|
24437
|
-
const parsed = JSON.parse(await readFile22(
|
|
24564
|
+
const parsed = JSON.parse(await readFile22(path48.join(cwd, REVIEW_GATE_CONFIG_PATH), "utf8"));
|
|
24438
24565
|
if (typeof parsed !== "object" || parsed === null)
|
|
24439
24566
|
return false;
|
|
24440
24567
|
const review = parsed["review"];
|
|
@@ -24455,7 +24582,7 @@ function acCheckCacheKey(criteriaChecksum, diffText) {
|
|
|
24455
24582
|
return `${criteriaChecksum}:${hashDiff(diffText)}`;
|
|
24456
24583
|
}
|
|
24457
24584
|
function acCheckCachePath(cwd, flowDir) {
|
|
24458
|
-
return
|
|
24585
|
+
return path48.join(cwd, ".metaproject", "data", "ac-check", `${flowDir}.json`);
|
|
24459
24586
|
}
|
|
24460
24587
|
async function readAcCheckCache(cachePath) {
|
|
24461
24588
|
if (!await pathExists(cachePath))
|
|
@@ -24467,7 +24594,7 @@ async function readAcCheckCache(cachePath) {
|
|
|
24467
24594
|
}
|
|
24468
24595
|
}
|
|
24469
24596
|
async function writeAcCheckCache(cachePath, record) {
|
|
24470
|
-
await mkdir9(
|
|
24597
|
+
await mkdir9(path48.dirname(cachePath), { recursive: true });
|
|
24471
24598
|
await writeFileAtomic(cachePath, `${JSON.stringify(record, null, 2)}
|
|
24472
24599
|
`, { mode: 384 });
|
|
24473
24600
|
if (process.platform !== "win32") {
|
|
@@ -24525,10 +24652,10 @@ function renderAcCheckAdvisoryNotice(verdicts) {
|
|
|
24525
24652
|
}
|
|
24526
24653
|
// src/flow/allocation.ts
|
|
24527
24654
|
import { appendFile as appendFile3, mkdir as mkdir10, readFile as readFile23 } from "fs/promises";
|
|
24528
|
-
import
|
|
24655
|
+
import path50 from "path";
|
|
24529
24656
|
|
|
24530
24657
|
// src/lib/clone-scope.ts
|
|
24531
|
-
import
|
|
24658
|
+
import path49 from "path";
|
|
24532
24659
|
async function gitCommonDir(cwd) {
|
|
24533
24660
|
try {
|
|
24534
24661
|
const proc = Bun.spawn(["git", "rev-parse", "--git-common-dir"], {
|
|
@@ -24540,7 +24667,7 @@ async function gitCommonDir(cwd) {
|
|
|
24540
24667
|
if (await proc.exited !== 0 || output.length === 0) {
|
|
24541
24668
|
return null;
|
|
24542
24669
|
}
|
|
24543
|
-
return
|
|
24670
|
+
return path49.isAbsolute(output) ? output : path49.resolve(cwd, output);
|
|
24544
24671
|
} catch {
|
|
24545
24672
|
return null;
|
|
24546
24673
|
}
|
|
@@ -24565,23 +24692,23 @@ function projectKey(toplevel, cwd) {
|
|
|
24565
24692
|
if (!toplevel) {
|
|
24566
24693
|
return "root";
|
|
24567
24694
|
}
|
|
24568
|
-
const relative =
|
|
24695
|
+
const relative = path50.relative(toplevel, cwd);
|
|
24569
24696
|
return relative === "" ? "root" : slugify(relative);
|
|
24570
24697
|
}
|
|
24571
24698
|
async function resolveAllocationScope(cwd) {
|
|
24572
24699
|
const commonDir = await gitCommonDir(cwd);
|
|
24573
24700
|
if (!commonDir) {
|
|
24574
24701
|
return {
|
|
24575
|
-
lockPath:
|
|
24702
|
+
lockPath: path50.join(flowsRoot(cwd), ".flow-init.lock"),
|
|
24576
24703
|
ledgerPath: null,
|
|
24577
24704
|
project: "root"
|
|
24578
24705
|
};
|
|
24579
24706
|
}
|
|
24580
24707
|
const key = projectKey(await gitToplevel(cwd), cwd);
|
|
24581
|
-
const dir =
|
|
24708
|
+
const dir = path50.join(commonDir, "keryx", "flow-ids");
|
|
24582
24709
|
return {
|
|
24583
|
-
lockPath:
|
|
24584
|
-
ledgerPath:
|
|
24710
|
+
lockPath: path50.join(dir, `${key}.lock`),
|
|
24711
|
+
ledgerPath: path50.join(dir, `${key}.jsonl`),
|
|
24585
24712
|
project: key
|
|
24586
24713
|
};
|
|
24587
24714
|
}
|
|
@@ -24614,7 +24741,7 @@ async function recordAllocation(scope, record) {
|
|
|
24614
24741
|
if (!scope.ledgerPath) {
|
|
24615
24742
|
return;
|
|
24616
24743
|
}
|
|
24617
|
-
await mkdir10(
|
|
24744
|
+
await mkdir10(path50.dirname(scope.ledgerPath), { recursive: true });
|
|
24618
24745
|
await appendFile3(scope.ledgerPath, `${JSON.stringify(record)}
|
|
24619
24746
|
`, "utf8");
|
|
24620
24747
|
}
|
|
@@ -24786,6 +24913,7 @@ function createFlowService(deps) {
|
|
|
24786
24913
|
if (input.owner !== undefined && !input.owner.trim()) {
|
|
24787
24914
|
throw new Error(BLANK_OWNER_MESSAGE);
|
|
24788
24915
|
}
|
|
24916
|
+
const outcomeAuthor = input.outcomeAuthor === undefined ? DEFAULT_OUTCOME_AUTHOR : parseOutcomeAuthor(input.outcomeAuthor);
|
|
24789
24917
|
const trackerReady = deps.tracker ? await deps.tracker.detect() : false;
|
|
24790
24918
|
const tracker = trackerReady ? deps.tracker : null;
|
|
24791
24919
|
const issueRef = input.issue && deps.tracker ? deps.tracker.parseRef(input.issue) : null;
|
|
@@ -24808,7 +24936,7 @@ function createFlowService(deps) {
|
|
|
24808
24936
|
const date = now().slice(0, 10);
|
|
24809
24937
|
const slug = slugify(input.slug ?? title);
|
|
24810
24938
|
const dir = `${id}-${date}-${slug}`;
|
|
24811
|
-
const absolute =
|
|
24939
|
+
const absolute = path51.join(flowsRoot(input.cwd), dir);
|
|
24812
24940
|
if (await pathExists(absolute)) {
|
|
24813
24941
|
throw new Error(`Flow directory already exists: ${dir}`);
|
|
24814
24942
|
}
|
|
@@ -24837,19 +24965,20 @@ function createFlowService(deps) {
|
|
|
24837
24965
|
pr: { url: null },
|
|
24838
24966
|
...input.baseBranch === undefined ? {} : { baseBranch: input.baseBranch },
|
|
24839
24967
|
...input.owner?.trim() ? { owner: ownerIdentity(input.owner.trim(), "`--owner` flag on `flow init`") } : {},
|
|
24968
|
+
outcomeAuthor,
|
|
24840
24969
|
tasks: DEFAULT_TASKS.map((task) => ({ ...task, status: "todo" })),
|
|
24841
24970
|
history: [{ at: createdAt, event: "created" }]
|
|
24842
24971
|
};
|
|
24843
24972
|
const sourceLabel = input.issue ?? "user description";
|
|
24844
|
-
await writeFileAtomic(
|
|
24845
|
-
await writeFileAtomic(
|
|
24846
|
-
await writeFileAtomic(
|
|
24847
|
-
await writeFileAtomic(
|
|
24848
|
-
await writeFileAtomic(
|
|
24849
|
-
await writeFileAtomic(
|
|
24973
|
+
await writeFileAtomic(path51.join(absolute, "description.md"), renderDescription(title, sourceLabel));
|
|
24974
|
+
await writeFileAtomic(path51.join(absolute, "context.md"), context.markdown);
|
|
24975
|
+
await writeFileAtomic(path51.join(absolute, "plan.md"), renderPlan());
|
|
24976
|
+
await writeFileAtomic(path51.join(absolute, "tasks.md"), renderTasksDoc());
|
|
24977
|
+
await writeFileAtomic(path51.join(absolute, "acceptance-criteria.md"), renderAcceptanceCriteria());
|
|
24978
|
+
await writeFileAtomic(path51.join(absolute, "journal.md"), renderJournal(createdAt));
|
|
24850
24979
|
await writeFlow(input.cwd, dir, flow);
|
|
24851
24980
|
await recordAllocation(scope, { id, dir, at: createdAt, project: scope.project });
|
|
24852
|
-
return { flow, dir:
|
|
24981
|
+
return { flow, dir: path51.relative(input.cwd, absolute), contextNotes: context.notes };
|
|
24853
24982
|
});
|
|
24854
24983
|
},
|
|
24855
24984
|
async list({ cwd }) {
|
|
@@ -24894,6 +25023,25 @@ function createFlowService(deps) {
|
|
|
24894
25023
|
return save(cwd, dir, flow, previous === null ? "owner-set" : "owner-changed", detail);
|
|
24895
25024
|
});
|
|
24896
25025
|
},
|
|
25026
|
+
async outcomeAuthorSet({ cwd, id, author, reason }) {
|
|
25027
|
+
const next = parseOutcomeAuthor(author, "outcome author");
|
|
25028
|
+
if (!reason?.trim()) {
|
|
25029
|
+
throw new Error('flow outcome author requires --reason "<why>"');
|
|
25030
|
+
}
|
|
25031
|
+
validateSingleLineReason(reason);
|
|
25032
|
+
let previous = "unknown";
|
|
25033
|
+
let changed = false;
|
|
25034
|
+
const flow = await mutate(cwd, id, async ({ dir, flow: current }) => {
|
|
25035
|
+
previous = readOutcomeAuthor(current.outcomeAuthor);
|
|
25036
|
+
if (previous === next) {
|
|
25037
|
+
return current;
|
|
25038
|
+
}
|
|
25039
|
+
changed = true;
|
|
25040
|
+
current.outcomeAuthor = next;
|
|
25041
|
+
return save(cwd, dir, current, "outcome-author-set", `${previous} -> ${next} (${reason.trim()})`);
|
|
25042
|
+
});
|
|
25043
|
+
return { flow, previous, changed };
|
|
25044
|
+
},
|
|
24897
25045
|
async freeze({ cwd, id }) {
|
|
24898
25046
|
return mutate(cwd, id, async ({ dir, flow }) => {
|
|
24899
25047
|
assertTransition(flow.status, "ready");
|
|
@@ -25433,7 +25581,7 @@ function createFlowService(deps) {
|
|
|
25433
25581
|
issues.push({ flow: dir, kind: "schema", message: `unknown schemaVersion ${flow.schemaVersion}` });
|
|
25434
25582
|
}
|
|
25435
25583
|
try {
|
|
25436
|
-
const raw = JSON.parse(await Bun.file(
|
|
25584
|
+
const raw = JSON.parse(await Bun.file(path51.join(flowsRoot(cwd), dir, "flow.json")).text());
|
|
25437
25585
|
const validation = validateAgainstSchemaObject(flowStateSchema(), raw);
|
|
25438
25586
|
if (!validation.valid) {
|
|
25439
25587
|
issues.push({
|
|
@@ -25444,7 +25592,7 @@ function createFlowService(deps) {
|
|
|
25444
25592
|
}
|
|
25445
25593
|
} catch {}
|
|
25446
25594
|
for (const file of ["description.md", "context.md", "plan.md", "tasks.md", "acceptance-criteria.md", "journal.md"]) {
|
|
25447
|
-
if (!await pathExists(
|
|
25595
|
+
if (!await pathExists(path51.join(flowsRoot(cwd), dir, file))) {
|
|
25448
25596
|
issues.push({ flow: dir, kind: "structure", message: `missing ${file}` });
|
|
25449
25597
|
}
|
|
25450
25598
|
}
|
|
@@ -25483,7 +25631,7 @@ function createFlowService(deps) {
|
|
|
25483
25631
|
};
|
|
25484
25632
|
}
|
|
25485
25633
|
async function appendIdMap(cwd, entry) {
|
|
25486
|
-
const file =
|
|
25634
|
+
const file = path51.join(flowsRoot(cwd), "id-map.json");
|
|
25487
25635
|
let entries = [];
|
|
25488
25636
|
if (await pathExists(file)) {
|
|
25489
25637
|
const raw = await readFile24(file, "utf8");
|
|
@@ -25494,7 +25642,7 @@ async function appendIdMap(cwd, entry) {
|
|
|
25494
25642
|
}
|
|
25495
25643
|
entries = parsed;
|
|
25496
25644
|
} catch (error) {
|
|
25497
|
-
throw new Error(`Cannot read ${
|
|
25645
|
+
throw new Error(`Cannot read ${path51.relative(cwd, file)}: ${error instanceof Error ? error.message : String(error)}`);
|
|
25498
25646
|
}
|
|
25499
25647
|
}
|
|
25500
25648
|
entries.push(entry);
|
|
@@ -25747,7 +25895,7 @@ __export(exports_service5, {
|
|
|
25747
25895
|
// src/gdgraph/build.ts
|
|
25748
25896
|
import { mkdir as mkdir20, readdir as readdir13, readFile as readFile35, writeFile as writeFile14 } from "fs/promises";
|
|
25749
25897
|
import { existsSync as existsSync6 } from "fs";
|
|
25750
|
-
import
|
|
25898
|
+
import path71 from "path";
|
|
25751
25899
|
|
|
25752
25900
|
// src/gdgraph/types.ts
|
|
25753
25901
|
var UNKNOWN_IMPORT_KIND = "unknown-static";
|
|
@@ -25812,7 +25960,7 @@ async function buildGraph(projectRoot) {
|
|
|
25812
25960
|
const assetNodes = new Map;
|
|
25813
25961
|
const fileRecords = [];
|
|
25814
25962
|
for (const file of files) {
|
|
25815
|
-
const absolutePath =
|
|
25963
|
+
const absolutePath = path71.join(projectRoot, file);
|
|
25816
25964
|
const content = await readFile35(absolutePath, "utf8");
|
|
25817
25965
|
fileRecords.push({ path: file, content });
|
|
25818
25966
|
const language = getLanguage(file);
|
|
@@ -25865,24 +26013,24 @@ async function collectSourceFiles(projectRoot) {
|
|
|
25865
26013
|
const result = [];
|
|
25866
26014
|
const skippedDirectories = [];
|
|
25867
26015
|
async function walk(relativeDir) {
|
|
25868
|
-
const absoluteDir =
|
|
26016
|
+
const absoluteDir = path71.join(projectRoot, relativeDir);
|
|
25869
26017
|
const entries = await readdir13(absoluteDir, { withFileTypes: true });
|
|
25870
26018
|
for (const entry of entries) {
|
|
25871
26019
|
if (entry.isDirectory()) {
|
|
25872
26020
|
if (IGNORE_DIRS.has(entry.name)) {
|
|
25873
|
-
skippedDirectories.push(normalizePath2(
|
|
26021
|
+
skippedDirectories.push(normalizePath2(path71.posix.join(relativeDir, entry.name)).replace(/^\.\//, ""));
|
|
25874
26022
|
continue;
|
|
25875
26023
|
}
|
|
25876
|
-
await walk(normalizePath2(
|
|
26024
|
+
await walk(normalizePath2(path71.posix.join(relativeDir, entry.name)));
|
|
25877
26025
|
continue;
|
|
25878
26026
|
}
|
|
25879
26027
|
if (!entry.isFile()) {
|
|
25880
26028
|
continue;
|
|
25881
26029
|
}
|
|
25882
|
-
if (!SOURCE_EXTENSIONS.includes(
|
|
26030
|
+
if (!SOURCE_EXTENSIONS.includes(path71.extname(entry.name))) {
|
|
25883
26031
|
continue;
|
|
25884
26032
|
}
|
|
25885
|
-
result.push(normalizePath2(
|
|
26033
|
+
result.push(normalizePath2(path71.posix.join(relativeDir, entry.name)).replace(/^\.\//, ""));
|
|
25886
26034
|
}
|
|
25887
26035
|
}
|
|
25888
26036
|
await walk(".");
|
|
@@ -25964,8 +26112,8 @@ function resolveImport(projectRoot, fromFile, specifier, fileSet, resolver) {
|
|
|
25964
26112
|
}
|
|
25965
26113
|
function resolveAssetImport(projectRoot, fromFile, specifier, resolver) {
|
|
25966
26114
|
for (const candidate of importCandidateBases(projectRoot, fromFile, specifier, resolver)) {
|
|
25967
|
-
const extension =
|
|
25968
|
-
if (ASSET_EXTENSIONS.includes(extension) && existsSync6(
|
|
26115
|
+
const extension = path71.posix.extname(candidate);
|
|
26116
|
+
if (ASSET_EXTENSIONS.includes(extension) && existsSync6(path71.join(projectRoot, candidate))) {
|
|
25969
26117
|
return candidate;
|
|
25970
26118
|
}
|
|
25971
26119
|
}
|
|
@@ -25974,17 +26122,17 @@ function resolveAssetImport(projectRoot, fromFile, specifier, resolver) {
|
|
|
25974
26122
|
function importCandidateBases(projectRoot, fromFile, specifier, resolver) {
|
|
25975
26123
|
const normalizedSpecifier = stripImportSuffix(specifier);
|
|
25976
26124
|
if (normalizedSpecifier.startsWith(".") && getLanguage(fromFile) !== "python") {
|
|
25977
|
-
const fromDir =
|
|
25978
|
-
return [normalizePath2(
|
|
26125
|
+
const fromDir = path71.posix.dirname(fromFile);
|
|
26126
|
+
return [normalizePath2(path71.posix.normalize(path71.posix.join(fromDir, normalizedSpecifier)))];
|
|
25979
26127
|
}
|
|
25980
|
-
return resolver.candidateBases(normalizedSpecifier, fromFile).map((candidate) => normalizePath2(
|
|
26128
|
+
return resolver.candidateBases(normalizedSpecifier, fromFile).map((candidate) => normalizePath2(path71.relative(projectRoot, path71.join(projectRoot, candidate))));
|
|
25981
26129
|
}
|
|
25982
26130
|
function resolveSourceCandidate(base, fileSet) {
|
|
25983
26131
|
const candidates = [
|
|
25984
26132
|
base,
|
|
25985
26133
|
...SOURCE_RESOLUTION_EXTENSIONS.map((extension) => `${base}${extension}`),
|
|
25986
|
-
...SOURCE_RESOLUTION_EXTENSIONS.map((extension) =>
|
|
25987
|
-
|
|
26134
|
+
...SOURCE_RESOLUTION_EXTENSIONS.map((extension) => path71.posix.join(base, `index${extension}`)),
|
|
26135
|
+
path71.posix.join(base, "__init__.py")
|
|
25988
26136
|
];
|
|
25989
26137
|
return candidates.find((candidate) => fileSet.has(candidate)) ?? null;
|
|
25990
26138
|
}
|
|
@@ -26014,7 +26162,7 @@ async function loadJavaResolver(projectRoot) {
|
|
|
26014
26162
|
return createJavaResolver(roots);
|
|
26015
26163
|
}
|
|
26016
26164
|
async function discoverJavaSourceRoots(projectRoot) {
|
|
26017
|
-
const pomPath =
|
|
26165
|
+
const pomPath = path71.join(projectRoot, "pom.xml");
|
|
26018
26166
|
if (existsSync6(pomPath)) {
|
|
26019
26167
|
try {
|
|
26020
26168
|
const roots = parseMavenSourceRoots(await readFile35(pomPath, "utf8"));
|
|
@@ -26024,7 +26172,7 @@ async function discoverJavaSourceRoots(projectRoot) {
|
|
|
26024
26172
|
} catch {}
|
|
26025
26173
|
}
|
|
26026
26174
|
for (const gradleName of ["build.gradle", "build.gradle.kts"]) {
|
|
26027
|
-
const gradlePath =
|
|
26175
|
+
const gradlePath = path71.join(projectRoot, gradleName);
|
|
26028
26176
|
if (existsSync6(gradlePath)) {
|
|
26029
26177
|
try {
|
|
26030
26178
|
const roots = parseGradleSourceRoots(await readFile35(gradlePath, "utf8"));
|
|
@@ -26046,12 +26194,12 @@ function createJavaResolver(sourceRoots) {
|
|
|
26046
26194
|
return [];
|
|
26047
26195
|
}
|
|
26048
26196
|
const relative = specifier.split(".").join("/");
|
|
26049
|
-
return sourceRoots.map((root) => normalizePath2(
|
|
26197
|
+
return sourceRoots.map((root) => normalizePath2(path71.posix.join(root, relative)));
|
|
26050
26198
|
}
|
|
26051
26199
|
};
|
|
26052
26200
|
}
|
|
26053
26201
|
function loadPythonResolver(projectRoot) {
|
|
26054
|
-
const hasSrc = existsSync6(
|
|
26202
|
+
const hasSrc = existsSync6(path71.join(projectRoot, "src"));
|
|
26055
26203
|
return createPythonResolver(hasSrc);
|
|
26056
26204
|
}
|
|
26057
26205
|
function createPythonResolver(hasSrc) {
|
|
@@ -26064,16 +26212,16 @@ function createPythonResolver(hasSrc) {
|
|
|
26064
26212
|
if (specifier.startsWith(".")) {
|
|
26065
26213
|
const dots = /^\.+/.exec(specifier)?.[0].length ?? 0;
|
|
26066
26214
|
const rest = specifier.slice(dots);
|
|
26067
|
-
let baseDir =
|
|
26215
|
+
let baseDir = path71.posix.dirname(fromFile);
|
|
26068
26216
|
for (let level = 1;level < dots; level += 1) {
|
|
26069
|
-
baseDir =
|
|
26217
|
+
baseDir = path71.posix.dirname(baseDir);
|
|
26070
26218
|
}
|
|
26071
26219
|
const suffix = rest ? rest.split(".").join("/") : "";
|
|
26072
|
-
const base = suffix ?
|
|
26220
|
+
const base = suffix ? path71.posix.join(baseDir, suffix) : baseDir;
|
|
26073
26221
|
return [normalizePath2(base)];
|
|
26074
26222
|
}
|
|
26075
26223
|
const relative = specifier.split(".").join("/");
|
|
26076
|
-
return roots.map((root) => normalizePath2(root ?
|
|
26224
|
+
return roots.map((root) => normalizePath2(root ? path71.posix.join(root, relative) : relative));
|
|
26077
26225
|
}
|
|
26078
26226
|
};
|
|
26079
26227
|
}
|
|
@@ -26082,8 +26230,8 @@ function parseMavenSourceRoots(pomXml) {
|
|
|
26082
26230
|
for (const match of pomXml.matchAll(/<module>\s*([^<]+?)\s*<\/module>/g)) {
|
|
26083
26231
|
const moduleDir = match[1]?.trim();
|
|
26084
26232
|
if (moduleDir && !moduleDir.includes("${")) {
|
|
26085
|
-
roots.add(normalizePath2(
|
|
26086
|
-
roots.add(normalizePath2(
|
|
26233
|
+
roots.add(normalizePath2(path71.posix.join(moduleDir, "src/main/java")));
|
|
26234
|
+
roots.add(normalizePath2(path71.posix.join(moduleDir, "src/test/java")));
|
|
26087
26235
|
}
|
|
26088
26236
|
}
|
|
26089
26237
|
for (const tag of ["sourceDirectory", "testSourceDirectory"]) {
|
|
@@ -26116,7 +26264,7 @@ function parseGradleSourceRoots(buildGradle) {
|
|
|
26116
26264
|
var TSCONFIG_EXTENDS_MAX_DEPTH = 10;
|
|
26117
26265
|
async function loadTsconfigResolver(projectRoot) {
|
|
26118
26266
|
const empty = createTsconfigResolver(null, []);
|
|
26119
|
-
const tsconfigPath =
|
|
26267
|
+
const tsconfigPath = path71.join(projectRoot, "tsconfig.json");
|
|
26120
26268
|
if (!existsSync6(tsconfigPath)) {
|
|
26121
26269
|
return empty;
|
|
26122
26270
|
}
|
|
@@ -26129,7 +26277,7 @@ async function loadTsconfigResolver(projectRoot) {
|
|
|
26129
26277
|
return createTsconfigResolver(resolved.baseUrl, paths);
|
|
26130
26278
|
}
|
|
26131
26279
|
function toProjectRelativeDir(projectRoot, absoluteDir) {
|
|
26132
|
-
const relative = normalizePath2(
|
|
26280
|
+
const relative = normalizePath2(path71.relative(projectRoot, absoluteDir)).replace(/^\.\//, "");
|
|
26133
26281
|
return relative === "." ? "" : relative;
|
|
26134
26282
|
}
|
|
26135
26283
|
async function readTsconfigJson(configPath) {
|
|
@@ -26144,11 +26292,11 @@ function resolveTsconfigExtendsPath(configDir, extendsSpecifier) {
|
|
|
26144
26292
|
if (!extendsSpecifier.startsWith(".") && !extendsSpecifier.startsWith("/")) {
|
|
26145
26293
|
return null;
|
|
26146
26294
|
}
|
|
26147
|
-
const resolved =
|
|
26295
|
+
const resolved = path71.resolve(configDir, extendsSpecifier);
|
|
26148
26296
|
return resolved.endsWith(".json") ? resolved : `${resolved}.json`;
|
|
26149
26297
|
}
|
|
26150
26298
|
async function resolveTsconfigOptions(configPath, visited, depth, projectRoot) {
|
|
26151
|
-
const resolvedPath =
|
|
26299
|
+
const resolvedPath = path71.resolve(configPath);
|
|
26152
26300
|
if (depth > TSCONFIG_EXTENDS_MAX_DEPTH || visited.has(resolvedPath)) {
|
|
26153
26301
|
return null;
|
|
26154
26302
|
}
|
|
@@ -26159,15 +26307,15 @@ async function resolveTsconfigOptions(configPath, visited, depth, projectRoot) {
|
|
|
26159
26307
|
}
|
|
26160
26308
|
let inherited = null;
|
|
26161
26309
|
if (typeof parsed.extends === "string") {
|
|
26162
|
-
const basePath = resolveTsconfigExtendsPath(
|
|
26310
|
+
const basePath = resolveTsconfigExtendsPath(path71.dirname(resolvedPath), parsed.extends);
|
|
26163
26311
|
if (basePath) {
|
|
26164
26312
|
inherited = await resolveTsconfigOptions(basePath, visited, depth + 1, projectRoot);
|
|
26165
26313
|
}
|
|
26166
26314
|
}
|
|
26167
|
-
const configDir =
|
|
26315
|
+
const configDir = path71.dirname(resolvedPath);
|
|
26168
26316
|
const declaringDir = toProjectRelativeDir(projectRoot, configDir);
|
|
26169
26317
|
const options = parsed.compilerOptions ?? {};
|
|
26170
|
-
const ownBaseUrl = typeof options.baseUrl === "string" ? toProjectRelativeDir(projectRoot,
|
|
26318
|
+
const ownBaseUrl = typeof options.baseUrl === "string" ? toProjectRelativeDir(projectRoot, path71.resolve(configDir, options.baseUrl)) : null;
|
|
26171
26319
|
const baseUrl = ownBaseUrl ?? inherited?.baseUrl ?? null;
|
|
26172
26320
|
const ownPaths = isRecord2(options.paths) ? Object.entries(options.paths).filter((entry) => Array.isArray(entry[1])).map(([pattern, targets]) => ({
|
|
26173
26321
|
pattern,
|
|
@@ -26196,7 +26344,7 @@ function createTsconfigResolver(baseUrl, mappings) {
|
|
|
26196
26344
|
}
|
|
26197
26345
|
}
|
|
26198
26346
|
if (baseUrl !== null) {
|
|
26199
|
-
candidates.push(normalizePath2(
|
|
26347
|
+
candidates.push(normalizePath2(path71.posix.join(baseUrl, normalizedSpecifier)));
|
|
26200
26348
|
}
|
|
26201
26349
|
return [...new Set(candidates.map((candidate) => candidate.replace(/^\.\//, "")))];
|
|
26202
26350
|
}
|
|
@@ -26216,7 +26364,7 @@ function matchPathPattern(pattern, specifier) {
|
|
|
26216
26364
|
}
|
|
26217
26365
|
function applyPathTarget(base, target, wildcard) {
|
|
26218
26366
|
const replaced = target.includes("*") ? target.replace("*", wildcard) : target;
|
|
26219
|
-
return normalizePath2(
|
|
26367
|
+
return normalizePath2(path71.posix.normalize(path71.posix.join(base, replaced)));
|
|
26220
26368
|
}
|
|
26221
26369
|
function stripJsonComments(source) {
|
|
26222
26370
|
let out = "";
|
|
@@ -26269,21 +26417,21 @@ function isRecord2(value) {
|
|
|
26269
26417
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26270
26418
|
}
|
|
26271
26419
|
async function writeGraph(projectRoot, graph) {
|
|
26272
|
-
const storageDir =
|
|
26273
|
-
const artifactsDir =
|
|
26420
|
+
const storageDir = path71.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
|
|
26421
|
+
const artifactsDir = path71.join(projectRoot, ".metaproject", "data", "gdgraph", "artifacts");
|
|
26274
26422
|
await mkdir20(storageDir, { recursive: true });
|
|
26275
26423
|
await mkdir20(artifactsDir, { recursive: true });
|
|
26276
|
-
await writeFile14(
|
|
26424
|
+
await writeFile14(path71.join(storageDir, "nodes.jsonl"), graph.nodes.map((node) => JSON.stringify(node)).join(`
|
|
26277
26425
|
`) + `
|
|
26278
26426
|
`, "utf8");
|
|
26279
|
-
await writeFile14(
|
|
26427
|
+
await writeFile14(path71.join(storageDir, "edges.jsonl"), graph.edges.map((edge) => JSON.stringify(edge)).join(`
|
|
26280
26428
|
`) + `
|
|
26281
26429
|
`, "utf8");
|
|
26282
|
-
await writeFile14(
|
|
26430
|
+
await writeFile14(path71.join(artifactsDir, "module-map.json"), JSON.stringify(buildModuleMap(graph), null, 2) + `
|
|
26283
26431
|
`, "utf8");
|
|
26284
26432
|
}
|
|
26285
26433
|
async function writeSummary(projectRoot, graph, collection) {
|
|
26286
|
-
const artifactsDir =
|
|
26434
|
+
const artifactsDir = path71.join(projectRoot, ".metaproject", "data", "gdgraph", "artifacts");
|
|
26287
26435
|
await mkdir20(artifactsDir, { recursive: true });
|
|
26288
26436
|
const unresolved = graph.edges.filter((edge) => edge.kind === "unresolved");
|
|
26289
26437
|
const imports = graph.edges.filter((edge) => edge.kind === "imports");
|
|
@@ -26298,7 +26446,7 @@ async function writeSummary(projectRoot, graph, collection) {
|
|
|
26298
26446
|
`);
|
|
26299
26447
|
const skippedList = collection.skippedDirectories.length > 0 ? collection.skippedDirectories.slice(0, 30).map((dir) => `- \`${dir}\``).join(`
|
|
26300
26448
|
`) : "- none";
|
|
26301
|
-
const summaryPath =
|
|
26449
|
+
const summaryPath = path71.join(artifactsDir, "summary.md");
|
|
26302
26450
|
const content = `# gdgraph Summary
|
|
26303
26451
|
|
|
26304
26452
|
## Stats
|
|
@@ -26379,7 +26527,7 @@ function groupBy(items, getKey) {
|
|
|
26379
26527
|
}
|
|
26380
26528
|
function unresolvedType(specifier) {
|
|
26381
26529
|
const stripped = stripImportSuffix(specifier);
|
|
26382
|
-
const extension =
|
|
26530
|
+
const extension = path71.posix.extname(stripped);
|
|
26383
26531
|
if (extension) {
|
|
26384
26532
|
return extension;
|
|
26385
26533
|
}
|
|
@@ -26389,13 +26537,13 @@ function unresolvedType(specifier) {
|
|
|
26389
26537
|
return "package";
|
|
26390
26538
|
}
|
|
26391
26539
|
function normalizePath2(value) {
|
|
26392
|
-
return value.split(
|
|
26540
|
+
return value.split(path71.sep).join("/");
|
|
26393
26541
|
}
|
|
26394
26542
|
|
|
26395
26543
|
// src/gdgraph/target.ts
|
|
26396
|
-
import
|
|
26544
|
+
import path72 from "path";
|
|
26397
26545
|
function normalizeTarget(target) {
|
|
26398
|
-
return target.replace(/^\.\//, "").split(
|
|
26546
|
+
return target.replace(/^\.\//, "").split(path72.sep).join("/");
|
|
26399
26547
|
}
|
|
26400
26548
|
function resolveGraphTarget(graph, target) {
|
|
26401
26549
|
const normalized = normalizeTarget(target);
|
|
@@ -26488,15 +26636,15 @@ init_config3();
|
|
|
26488
26636
|
|
|
26489
26637
|
// src/gdgraph/query.ts
|
|
26490
26638
|
import { readFile as readFile36 } from "fs/promises";
|
|
26491
|
-
import
|
|
26639
|
+
import path73 from "path";
|
|
26492
26640
|
async function loadGraph(projectRoot) {
|
|
26493
|
-
const storageDir =
|
|
26494
|
-
const nodes = await readJsonl(
|
|
26495
|
-
const edges = await readJsonl(
|
|
26496
|
-
const symbols = await readJsonl(
|
|
26497
|
-
const calls = await readJsonl(
|
|
26498
|
-
const wikiPages = await readJsonl(
|
|
26499
|
-
const describes = await readJsonl(
|
|
26641
|
+
const storageDir = path73.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
|
|
26642
|
+
const nodes = await readJsonl(path73.join(storageDir, "nodes.jsonl"));
|
|
26643
|
+
const edges = await readJsonl(path73.join(storageDir, "edges.jsonl"));
|
|
26644
|
+
const symbols = await readJsonl(path73.join(storageDir, "symbols.jsonl"));
|
|
26645
|
+
const calls = await readJsonl(path73.join(storageDir, "calls.jsonl"));
|
|
26646
|
+
const wikiPages = await readJsonl(path73.join(storageDir, "wiki-pages.jsonl"));
|
|
26647
|
+
const describes = await readJsonl(path73.join(storageDir, "describes.jsonl"));
|
|
26500
26648
|
const graph = { nodes, edges };
|
|
26501
26649
|
if (symbols.length > 0) {
|
|
26502
26650
|
graph.symbols = symbols;
|
|
@@ -26556,7 +26704,7 @@ async function bunfigPreloadRoots(projectRoot) {
|
|
|
26556
26704
|
const roots = new Set;
|
|
26557
26705
|
let text;
|
|
26558
26706
|
try {
|
|
26559
|
-
text = await readFile36(
|
|
26707
|
+
text = await readFile36(path73.join(projectRoot, "bunfig.toml"), "utf8");
|
|
26560
26708
|
} catch {
|
|
26561
26709
|
return roots;
|
|
26562
26710
|
}
|
|
@@ -26570,8 +26718,8 @@ async function bunfigPreloadRoots(projectRoot) {
|
|
|
26570
26718
|
if (raw.length === 0) {
|
|
26571
26719
|
continue;
|
|
26572
26720
|
}
|
|
26573
|
-
const absolute =
|
|
26574
|
-
const relative =
|
|
26721
|
+
const absolute = path73.resolve(projectRoot, raw);
|
|
26722
|
+
const relative = path73.relative(projectRoot, absolute).split(path73.sep).join("/");
|
|
26575
26723
|
roots.add(relative);
|
|
26576
26724
|
}
|
|
26577
26725
|
}
|
|
@@ -26644,7 +26792,7 @@ function canonicalCycle(cycle) {
|
|
|
26644
26792
|
|
|
26645
26793
|
// src/gdgraph/repomap.ts
|
|
26646
26794
|
import { mkdir as mkdir21, writeFile as writeFile15 } from "fs/promises";
|
|
26647
|
-
import
|
|
26795
|
+
import path74 from "path";
|
|
26648
26796
|
|
|
26649
26797
|
// src/gdgraph/pagerank.ts
|
|
26650
26798
|
function personalizedPageRank(nodes, edges, options) {
|
|
@@ -26755,7 +26903,7 @@ function overflowContent(required, missing, budget) {
|
|
|
26755
26903
|
`);
|
|
26756
26904
|
}
|
|
26757
26905
|
function repomapArtifactPath(cwd) {
|
|
26758
|
-
return
|
|
26906
|
+
return path74.join(cwd, ".metaproject", "data", "gdgraph", "artifacts", "repomap.md");
|
|
26759
26907
|
}
|
|
26760
26908
|
function buildRankEdges(graph, config) {
|
|
26761
26909
|
const edges = [];
|
|
@@ -26900,7 +27048,7 @@ function computeRepomap(graph, config, options = {}) {
|
|
|
26900
27048
|
async function writeRepomap(cwd, graph, config, options = {}) {
|
|
26901
27049
|
const result = computeRepomap(graph, config, options);
|
|
26902
27050
|
const artifactPath = repomapArtifactPath(cwd);
|
|
26903
|
-
await mkdir21(
|
|
27051
|
+
await mkdir21(path74.dirname(artifactPath), { recursive: true });
|
|
26904
27052
|
await writeFile15(artifactPath, result.content, "utf8");
|
|
26905
27053
|
return { ...result, path: artifactPath };
|
|
26906
27054
|
}
|
|
@@ -26983,12 +27131,12 @@ init_section_tombstone();
|
|
|
26983
27131
|
// src/forgetting/journal.ts
|
|
26984
27132
|
init_fs();
|
|
26985
27133
|
import { appendFile as appendFile4, mkdir as mkdir22, readFile as readFile37, stat as stat11 } from "fs/promises";
|
|
26986
|
-
import
|
|
27134
|
+
import path75 from "path";
|
|
26987
27135
|
function forgettingDataDir(cwd) {
|
|
26988
|
-
return
|
|
27136
|
+
return path75.join(cwd, ".metaproject", "data", "forgetting");
|
|
26989
27137
|
}
|
|
26990
27138
|
function deletionJournalPath(cwd) {
|
|
26991
|
-
return
|
|
27139
|
+
return path75.join(forgettingDataDir(cwd), "journal.jsonl");
|
|
26992
27140
|
}
|
|
26993
27141
|
async function readDeletionJournal(cwd) {
|
|
26994
27142
|
const file = deletionJournalPath(cwd);
|
|
@@ -27407,12 +27555,12 @@ __export(exports_service7, {
|
|
|
27407
27555
|
gateExitCode: () => gateExitCode,
|
|
27408
27556
|
readWikiFreshnessMetric: () => readWikiFreshnessMetric
|
|
27409
27557
|
});
|
|
27410
|
-
import
|
|
27558
|
+
import path95 from "path";
|
|
27411
27559
|
|
|
27412
27560
|
// src/health/config.ts
|
|
27413
27561
|
init_fs();
|
|
27414
27562
|
init_json();
|
|
27415
|
-
import
|
|
27563
|
+
import path76 from "path";
|
|
27416
27564
|
var DEFAULT_HEALTH_CONFIG = {
|
|
27417
27565
|
schemaVersion: 2,
|
|
27418
27566
|
ignore: {
|
|
@@ -27468,7 +27616,7 @@ var DEFAULT_HEALTH_CONFIG = {
|
|
|
27468
27616
|
}
|
|
27469
27617
|
};
|
|
27470
27618
|
function configPath2(cwd) {
|
|
27471
|
-
return
|
|
27619
|
+
return path76.join(cwd, ".metaproject", "health.config.json");
|
|
27472
27620
|
}
|
|
27473
27621
|
var STRICTEST_GATE = {
|
|
27474
27622
|
failOnPriorities: ["P0", "P1", "P2", "P3"],
|
|
@@ -27519,7 +27667,7 @@ async function loadHealthConfig(cwd) {
|
|
|
27519
27667
|
// src/health/run.ts
|
|
27520
27668
|
init_fs();
|
|
27521
27669
|
import { mkdir as mkdir26, writeFile as writeFile19 } from "fs/promises";
|
|
27522
|
-
import
|
|
27670
|
+
import path94 from "path";
|
|
27523
27671
|
|
|
27524
27672
|
// src/metrics/provenance.ts
|
|
27525
27673
|
async function collectGitProvenance(cwd) {
|
|
@@ -27619,12 +27767,12 @@ function computeGate2(input) {
|
|
|
27619
27767
|
}
|
|
27620
27768
|
|
|
27621
27769
|
// src/health/scopes.ts
|
|
27622
|
-
import
|
|
27770
|
+
import path79 from "path";
|
|
27623
27771
|
|
|
27624
27772
|
// src/health/util.ts
|
|
27625
27773
|
init_fs();
|
|
27626
27774
|
import { mkdir as mkdir23, readFile as readFile38, readdir as readdir14, writeFile as writeFile16 } from "fs/promises";
|
|
27627
|
-
import
|
|
27775
|
+
import path77 from "path";
|
|
27628
27776
|
var IGNORED_DIRS = new Set([
|
|
27629
27777
|
"node_modules",
|
|
27630
27778
|
".git",
|
|
@@ -27668,14 +27816,14 @@ async function toolVersion(command, cwd) {
|
|
|
27668
27816
|
}
|
|
27669
27817
|
}
|
|
27670
27818
|
function dataRoot3(cwd) {
|
|
27671
|
-
return
|
|
27819
|
+
return path77.join(cwd, ".metaproject", "data", "health");
|
|
27672
27820
|
}
|
|
27673
27821
|
async function writeRaw(cwd, source, content, stamp) {
|
|
27674
|
-
const dir =
|
|
27822
|
+
const dir = path77.join(dataRoot3(cwd), "raw", source);
|
|
27675
27823
|
await mkdir23(dir, { recursive: true });
|
|
27676
|
-
const file =
|
|
27824
|
+
const file = path77.join(dir, `${stamp}.log`);
|
|
27677
27825
|
await writeFile16(file, content, "utf8");
|
|
27678
|
-
return
|
|
27826
|
+
return path77.relative(cwd, file);
|
|
27679
27827
|
}
|
|
27680
27828
|
async function listSourceFiles(cwd, ignorePaths = []) {
|
|
27681
27829
|
const { files } = await listSourceFilesWithReasons(cwd, ignorePaths);
|
|
@@ -27695,7 +27843,7 @@ async function walk2(root, dir, out, incompleteReasons) {
|
|
|
27695
27843
|
try {
|
|
27696
27844
|
entries = await readdir14(dir, { withFileTypes: true });
|
|
27697
27845
|
} catch (error) {
|
|
27698
|
-
incompleteReasons.push(`${
|
|
27846
|
+
incompleteReasons.push(`${path77.relative(root, dir) || "."}: ${error instanceof Error ? error.message : String(error)}`);
|
|
27699
27847
|
return;
|
|
27700
27848
|
}
|
|
27701
27849
|
for (const entry of entries) {
|
|
@@ -27703,14 +27851,14 @@ async function walk2(root, dir, out, incompleteReasons) {
|
|
|
27703
27851
|
if (entry.isDirectory() && !IGNORED_DIRS.has(entry.name)) {}
|
|
27704
27852
|
continue;
|
|
27705
27853
|
}
|
|
27706
|
-
const abs =
|
|
27854
|
+
const abs = path77.join(dir, entry.name);
|
|
27707
27855
|
if (entry.isDirectory()) {
|
|
27708
27856
|
if (IGNORED_DIRS.has(entry.name)) {
|
|
27709
27857
|
continue;
|
|
27710
27858
|
}
|
|
27711
27859
|
await walk2(root, abs, out, incompleteReasons);
|
|
27712
|
-
} else if (entry.isFile() && SOURCE_EXT.has(
|
|
27713
|
-
out.push(
|
|
27860
|
+
} else if (entry.isFile() && SOURCE_EXT.has(path77.extname(entry.name))) {
|
|
27861
|
+
out.push(path77.relative(root, abs));
|
|
27714
27862
|
}
|
|
27715
27863
|
}
|
|
27716
27864
|
}
|
|
@@ -27725,7 +27873,7 @@ function moduleOfFile(file) {
|
|
|
27725
27873
|
return null;
|
|
27726
27874
|
}
|
|
27727
27875
|
function isSourceFile(file) {
|
|
27728
|
-
return SOURCE_EXT.has(
|
|
27876
|
+
return SOURCE_EXT.has(path77.extname(file));
|
|
27729
27877
|
}
|
|
27730
27878
|
function matchesAnyPattern(file, patterns) {
|
|
27731
27879
|
const normalized = file.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
@@ -27825,7 +27973,7 @@ function rankHotspots(files, churn, sourceAnalysis) {
|
|
|
27825
27973
|
// src/health/source-analysis.ts
|
|
27826
27974
|
init_fs();
|
|
27827
27975
|
import { readFile as readFile39 } from "fs/promises";
|
|
27828
|
-
import
|
|
27976
|
+
import path78 from "path";
|
|
27829
27977
|
|
|
27830
27978
|
// src/health/metrics/complexity.ts
|
|
27831
27979
|
var CONTROL_KEYWORDS = new Set([
|
|
@@ -28059,7 +28207,7 @@ async function analyzeSourceFiles(cwd, sourceFiles) {
|
|
|
28059
28207
|
return new Map(entries.filter((entry) => entry !== null));
|
|
28060
28208
|
}
|
|
28061
28209
|
async function analyzeSourceFile(cwd, file) {
|
|
28062
|
-
const abs =
|
|
28210
|
+
const abs = path78.join(cwd, file);
|
|
28063
28211
|
if (!await pathExists(abs)) {
|
|
28064
28212
|
return null;
|
|
28065
28213
|
}
|
|
@@ -28132,14 +28280,14 @@ async function computeMetrics(input) {
|
|
|
28132
28280
|
}
|
|
28133
28281
|
const components = new Map;
|
|
28134
28282
|
for (const file of sourceFiles) {
|
|
28135
|
-
const dir =
|
|
28283
|
+
const dir = path79.posix.dirname(file);
|
|
28136
28284
|
if (dir === "." || dir === moduleOfFile(file)) {
|
|
28137
28285
|
continue;
|
|
28138
28286
|
}
|
|
28139
28287
|
components.set(dir, [...components.get(dir) ?? [], file]);
|
|
28140
28288
|
}
|
|
28141
28289
|
for (const [name, files] of [...components.entries()].sort()) {
|
|
28142
|
-
const compFindings = findings.filter((f) => f.file &&
|
|
28290
|
+
const compFindings = findings.filter((f) => f.file && path79.posix.dirname(f.file) === name);
|
|
28143
28291
|
scopes.push(build("component", `component:${name}`, name, files, compFindings, averageCoverage(files, coverage)));
|
|
28144
28292
|
}
|
|
28145
28293
|
const findingFiles = findings.map((f) => f.file).filter((f) => Boolean(f));
|
|
@@ -28184,9 +28332,9 @@ function tally2(values) {
|
|
|
28184
28332
|
// src/health/baseline.ts
|
|
28185
28333
|
init_fs();
|
|
28186
28334
|
import { mkdir as mkdir24, readFile as readFile40, writeFile as writeFile17 } from "fs/promises";
|
|
28187
|
-
import
|
|
28335
|
+
import path80 from "path";
|
|
28188
28336
|
function baselinePath(cwd) {
|
|
28189
|
-
return
|
|
28337
|
+
return path80.join(cwd, ".metaproject", "health", "baselines", "scores.json");
|
|
28190
28338
|
}
|
|
28191
28339
|
async function loadBaseline(cwd) {
|
|
28192
28340
|
const file = baselinePath(cwd);
|
|
@@ -28218,7 +28366,7 @@ async function writeBaseline(cwd, metrics, generatedAt, selector) {
|
|
|
28218
28366
|
scopes[key] = value;
|
|
28219
28367
|
}
|
|
28220
28368
|
const file = baselinePath(cwd);
|
|
28221
|
-
await mkdir24(
|
|
28369
|
+
await mkdir24(path80.dirname(file), { recursive: true });
|
|
28222
28370
|
await writeFile17(file, `${JSON.stringify({ generatedAt, scopes }, null, 2)}
|
|
28223
28371
|
`, "utf8");
|
|
28224
28372
|
return updated;
|
|
@@ -28272,10 +28420,10 @@ async function getChurn(cwd, windowDays) {
|
|
|
28272
28420
|
|
|
28273
28421
|
// src/health/metrics/wiki-freshness.ts
|
|
28274
28422
|
import { readFile as readFile41, stat as stat12 } from "fs/promises";
|
|
28275
|
-
import
|
|
28423
|
+
import path81 from "path";
|
|
28276
28424
|
var DEFAULT_STALE_EVIDENCE_DAYS = 7;
|
|
28277
28425
|
function freshnessReportPath(cwd) {
|
|
28278
|
-
return
|
|
28426
|
+
return path81.join(cwd, ".metaproject", "data", "wiki", "freshness", "latest.json");
|
|
28279
28427
|
}
|
|
28280
28428
|
async function readWikiFreshnessMetric(cwd, options = {}) {
|
|
28281
28429
|
const file = freshnessReportPath(cwd);
|
|
@@ -28296,7 +28444,7 @@ async function readWikiFreshnessMetric(cwd, options = {}) {
|
|
|
28296
28444
|
} catch {
|
|
28297
28445
|
return {
|
|
28298
28446
|
status: "unreadable-report",
|
|
28299
|
-
reason: `${
|
|
28447
|
+
reason: `${path81.relative(cwd, file)} is not valid JSON; re-run \`keryx wiki freshness\`.`
|
|
28300
28448
|
};
|
|
28301
28449
|
}
|
|
28302
28450
|
const report = parsed;
|
|
@@ -28306,7 +28454,7 @@ async function readWikiFreshnessMetric(cwd, options = {}) {
|
|
|
28306
28454
|
if (pagesTotal === null || pagesFresh === null) {
|
|
28307
28455
|
return {
|
|
28308
28456
|
status: "unreadable-report",
|
|
28309
|
-
reason: `${
|
|
28457
|
+
reason: `${path81.relative(cwd, file)} is missing its totals; re-run \`keryx wiki freshness\`.`
|
|
28310
28458
|
};
|
|
28311
28459
|
}
|
|
28312
28460
|
const pagesUndecidable = numberOr2(totals.pagesUndecidable) ?? 0;
|
|
@@ -28360,12 +28508,12 @@ function renderWikiFreshnessLine(metric) {
|
|
|
28360
28508
|
}
|
|
28361
28509
|
|
|
28362
28510
|
// src/health/sources/helpers.ts
|
|
28363
|
-
import
|
|
28511
|
+
import path82 from "path";
|
|
28364
28512
|
import { existsSync as existsSync7 } from "fs";
|
|
28365
28513
|
class NoImportError extends Error {
|
|
28366
28514
|
}
|
|
28367
28515
|
function resolveBin(cwd, name) {
|
|
28368
|
-
const local =
|
|
28516
|
+
const local = path82.join(cwd, "node_modules", ".bin", name);
|
|
28369
28517
|
if (existsSync7(local)) {
|
|
28370
28518
|
return local;
|
|
28371
28519
|
}
|
|
@@ -28446,13 +28594,13 @@ async function getComplexityFindings(cwd, sourceFiles, config, sourceAnalysis) {
|
|
|
28446
28594
|
|
|
28447
28595
|
// src/health/metrics/coverage.ts
|
|
28448
28596
|
import { existsSync as existsSync8 } from "fs";
|
|
28449
|
-
import
|
|
28597
|
+
import path83 from "path";
|
|
28450
28598
|
var SUMMARY_PATHS = [
|
|
28451
28599
|
"coverage/coverage-summary.json",
|
|
28452
28600
|
"coverage/coverage-final.json"
|
|
28453
28601
|
];
|
|
28454
28602
|
async function getCoverage(cwd) {
|
|
28455
|
-
const summary = SUMMARY_PATHS.map((rel) =>
|
|
28603
|
+
const summary = SUMMARY_PATHS.map((rel) => path83.join(cwd, rel)).find((abs) => existsSync8(abs));
|
|
28456
28604
|
if (!summary) {
|
|
28457
28605
|
return { status: "missing", total: null, byFile: new Map };
|
|
28458
28606
|
}
|
|
@@ -28473,7 +28621,7 @@ async function getCoverage(cwd) {
|
|
|
28473
28621
|
total = pct;
|
|
28474
28622
|
continue;
|
|
28475
28623
|
}
|
|
28476
|
-
const relative =
|
|
28624
|
+
const relative = path83.isAbsolute(key) ? path83.relative(cwd, key) : key;
|
|
28477
28625
|
byFile.set(relative.replace(/\\/g, "/"), pct);
|
|
28478
28626
|
}
|
|
28479
28627
|
return { status: "available", total, byFile };
|
|
@@ -28606,10 +28754,10 @@ function renderWikiFreshness(metric) {
|
|
|
28606
28754
|
// src/health/skills.ts
|
|
28607
28755
|
init_fs();
|
|
28608
28756
|
import { readFile as readFile42 } from "fs/promises";
|
|
28609
|
-
import
|
|
28757
|
+
import path84 from "path";
|
|
28610
28758
|
var EMPTY = { skills: [], skillForFile: () => null };
|
|
28611
28759
|
async function loadSkillOwnership(cwd) {
|
|
28612
|
-
const manifestPath =
|
|
28760
|
+
const manifestPath = path84.join(cwd, ".metaproject", "metaproject.json");
|
|
28613
28761
|
if (!await pathExists(manifestPath)) {
|
|
28614
28762
|
return EMPTY;
|
|
28615
28763
|
}
|
|
@@ -28647,7 +28795,7 @@ function normalize(value) {
|
|
|
28647
28795
|
|
|
28648
28796
|
// src/health/sources/eslint.ts
|
|
28649
28797
|
import { existsSync as existsSync9 } from "fs";
|
|
28650
|
-
import
|
|
28798
|
+
import path85 from "path";
|
|
28651
28799
|
var CONFIG_FILES = [
|
|
28652
28800
|
".eslintrc",
|
|
28653
28801
|
".eslintrc.js",
|
|
@@ -28661,7 +28809,7 @@ var CONFIG_FILES = [
|
|
|
28661
28809
|
"eslint.config.ts"
|
|
28662
28810
|
];
|
|
28663
28811
|
function hasConfig(cwd) {
|
|
28664
|
-
return CONFIG_FILES.some((file) => existsSync9(
|
|
28812
|
+
return CONFIG_FILES.some((file) => existsSync9(path85.join(cwd, file)));
|
|
28665
28813
|
}
|
|
28666
28814
|
var eslintAdapter = {
|
|
28667
28815
|
id: "eslint",
|
|
@@ -28686,7 +28834,7 @@ var eslintAdapter = {
|
|
|
28686
28834
|
};
|
|
28687
28835
|
},
|
|
28688
28836
|
async import(ctx) {
|
|
28689
|
-
const report =
|
|
28837
|
+
const report = path85.join(ctx.cwd, "eslint-report.json");
|
|
28690
28838
|
if (!existsSync9(report)) {
|
|
28691
28839
|
throw new NoImportError("no eslint-report.json");
|
|
28692
28840
|
}
|
|
@@ -28713,7 +28861,7 @@ var eslintAdapter = {
|
|
|
28713
28861
|
}
|
|
28714
28862
|
const findings = [];
|
|
28715
28863
|
for (const file of data) {
|
|
28716
|
-
const relative =
|
|
28864
|
+
const relative = path85.isAbsolute(file.filePath) ? path85.relative(ctx.cwd, file.filePath) : file.filePath;
|
|
28717
28865
|
for (const message of file.messages ?? []) {
|
|
28718
28866
|
const isError = message.severity === 2;
|
|
28719
28867
|
findings.push(makeFinding({
|
|
@@ -28745,9 +28893,9 @@ var eslintAdapter = {
|
|
|
28745
28893
|
|
|
28746
28894
|
// src/health/sources/typescript.ts
|
|
28747
28895
|
import { existsSync as existsSync10 } from "fs";
|
|
28748
|
-
import
|
|
28896
|
+
import path86 from "path";
|
|
28749
28897
|
function hasTsconfig(cwd) {
|
|
28750
|
-
return existsSync10(
|
|
28898
|
+
return existsSync10(path86.join(cwd, "tsconfig.json"));
|
|
28751
28899
|
}
|
|
28752
28900
|
var typescriptAdapter = {
|
|
28753
28901
|
id: "typescript",
|
|
@@ -28823,7 +28971,7 @@ __export(exports_service6, {
|
|
|
28823
28971
|
});
|
|
28824
28972
|
import { existsSync as existsSync11 } from "fs";
|
|
28825
28973
|
import { readFile as readFile45, readdir as readdir15 } from "fs/promises";
|
|
28826
|
-
import
|
|
28974
|
+
import path91 from "path";
|
|
28827
28975
|
|
|
28828
28976
|
// src/lib/git-env.ts
|
|
28829
28977
|
var GIT_DISCOVERY_OVERRIDE_VARS = [
|
|
@@ -28848,7 +28996,7 @@ function withoutGitDiscoveryOverrides(env) {
|
|
|
28848
28996
|
init_fs();
|
|
28849
28997
|
init_guard();
|
|
28850
28998
|
import { readFile as readFile43 } from "fs/promises";
|
|
28851
|
-
import
|
|
28999
|
+
import path87 from "path";
|
|
28852
29000
|
|
|
28853
29001
|
// src/metrics/record.ts
|
|
28854
29002
|
var RELIABILITIES = new Set(["exact", "estimated", "unknown"]);
|
|
@@ -28863,7 +29011,7 @@ var RETRY_TYPES = new Set([
|
|
|
28863
29011
|
|
|
28864
29012
|
// src/metrics/lifecycle.ts
|
|
28865
29013
|
async function readArtifactPointer(root, expected) {
|
|
28866
|
-
const pointerFile =
|
|
29014
|
+
const pointerFile = path87.join(root, "latest.json");
|
|
28867
29015
|
if (!await pathExists(pointerFile))
|
|
28868
29016
|
return { status: "missing", pointer: null };
|
|
28869
29017
|
let pointer;
|
|
@@ -28872,7 +29020,7 @@ async function readArtifactPointer(root, expected) {
|
|
|
28872
29020
|
} catch {
|
|
28873
29021
|
return { status: "stale", pointer: null, reason: "latest pointer is invalid JSON" };
|
|
28874
29022
|
}
|
|
28875
|
-
const recordFile = pointer.record ?
|
|
29023
|
+
const recordFile = pointer.record ? path87.join(root, pointer.record) : null;
|
|
28876
29024
|
if (!recordFile || !isPathInside(root, recordFile) || !await pathExists(recordFile)) {
|
|
28877
29025
|
return { status: "stale", pointer, reason: "pointer record is missing" };
|
|
28878
29026
|
}
|
|
@@ -28888,9 +29036,9 @@ init_guard();
|
|
|
28888
29036
|
// src/testing/capability.ts
|
|
28889
29037
|
init_fs();
|
|
28890
29038
|
init_json();
|
|
28891
|
-
import
|
|
29039
|
+
import path88 from "path";
|
|
28892
29040
|
async function isTestingCapabilityEnabled(cwd, capability) {
|
|
28893
|
-
const manifestPath =
|
|
29041
|
+
const manifestPath = path88.join(cwd, ".metaproject", "metaproject.json");
|
|
28894
29042
|
if (!await pathExists(manifestPath)) {
|
|
28895
29043
|
return false;
|
|
28896
29044
|
}
|
|
@@ -28916,10 +29064,10 @@ async function isTestingCapabilityEnabled(cwd, capability) {
|
|
|
28916
29064
|
init_fs();
|
|
28917
29065
|
init_guard();
|
|
28918
29066
|
import { readFile as readFile44, mkdir as mkdir25, writeFile as writeFile18 } from "fs/promises";
|
|
28919
|
-
import
|
|
29067
|
+
import path89 from "path";
|
|
28920
29068
|
var COVERAGE_MAP_SCHEMA_VERSION = 1;
|
|
28921
29069
|
function coverageMapPath(cwd, cfg) {
|
|
28922
|
-
return
|
|
29070
|
+
return path89.isAbsolute(cfg.coverageMap.artifact) ? cfg.coverageMap.artifact : path89.join(cwd, cfg.coverageMap.artifact);
|
|
28923
29071
|
}
|
|
28924
29072
|
async function loadCoverageMap(cwd, cfg) {
|
|
28925
29073
|
const file = coverageMapPath(cwd, cfg);
|
|
@@ -28993,20 +29141,20 @@ function normalizePath4(file) {
|
|
|
28993
29141
|
}
|
|
28994
29142
|
|
|
28995
29143
|
// src/testing/selection.ts
|
|
28996
|
-
import
|
|
29144
|
+
import path90 from "path";
|
|
28997
29145
|
var TEST_FILE_RE = /(^|\/)(__tests__\/.*|.*\.(test|spec)\.[cm]?[tj]sx?$|e2e\/.*\.[cm]?[tj]sx?$|tests\/.*\.[cm]?[tj]sx?$)/;
|
|
28998
29146
|
function normalizePath5(file) {
|
|
28999
29147
|
return file.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
29000
29148
|
}
|
|
29001
29149
|
function relatedByNamingAndDirectory(target, testFiles) {
|
|
29002
29150
|
const normalized = normalizePath5(target);
|
|
29003
|
-
const ext =
|
|
29151
|
+
const ext = path90.extname(normalized);
|
|
29004
29152
|
const withoutExt = ext ? normalized.slice(0, -ext.length) : normalized;
|
|
29005
|
-
const base =
|
|
29006
|
-
const dir =
|
|
29153
|
+
const base = path90.basename(withoutExt);
|
|
29154
|
+
const dir = path90.dirname(normalized);
|
|
29007
29155
|
return testFiles.filter((file) => {
|
|
29008
|
-
const fileDir =
|
|
29009
|
-
const fileBase =
|
|
29156
|
+
const fileDir = path90.dirname(file);
|
|
29157
|
+
const fileBase = path90.basename(file);
|
|
29010
29158
|
return file.startsWith(`${withoutExt}.`) || file.includes(`${withoutExt}.`) || fileDir === dir && fileBase.startsWith(`${base}.`) || fileDir.startsWith(dir) && fileBase.includes(base);
|
|
29011
29159
|
}).sort();
|
|
29012
29160
|
}
|
|
@@ -29136,7 +29284,7 @@ var DEFAULT_TESTING_CONFIG = {
|
|
|
29136
29284
|
}
|
|
29137
29285
|
};
|
|
29138
29286
|
function testingDataRoot(cwd) {
|
|
29139
|
-
return
|
|
29287
|
+
return path91.join(cwd, ".metaproject", "data", "testing");
|
|
29140
29288
|
}
|
|
29141
29289
|
async function computeTestingContext(cwd) {
|
|
29142
29290
|
const { files, incompleteReasons } = await listProjectFiles(cwd);
|
|
@@ -29311,7 +29459,7 @@ async function runTesting(input) {
|
|
|
29311
29459
|
return runResult;
|
|
29312
29460
|
}
|
|
29313
29461
|
async function loadTestingContext(cwd) {
|
|
29314
|
-
const file =
|
|
29462
|
+
const file = path91.join(testingDataRoot(cwd), "context.json");
|
|
29315
29463
|
if (!await pathExists(file)) {
|
|
29316
29464
|
return null;
|
|
29317
29465
|
}
|
|
@@ -29322,18 +29470,18 @@ async function loadTestingContext(cwd) {
|
|
|
29322
29470
|
}
|
|
29323
29471
|
}
|
|
29324
29472
|
async function loadTestingReport(cwd) {
|
|
29325
|
-
const file =
|
|
29473
|
+
const file = path91.join(testingDataRoot(cwd), "artifacts", "latest.json");
|
|
29326
29474
|
if (!await pathExists(file)) {
|
|
29327
29475
|
return null;
|
|
29328
29476
|
}
|
|
29329
29477
|
try {
|
|
29330
29478
|
const latest = JSON.parse(await readFile45(file, "utf8"));
|
|
29331
29479
|
if (typeof latest.record === "string") {
|
|
29332
|
-
const pointer = await readArtifactPointer(
|
|
29480
|
+
const pointer = await readArtifactPointer(path91.join(testingDataRoot(cwd), "artifacts"), await collectGitProvenance(cwd));
|
|
29333
29481
|
if (pointer.status !== "fresh")
|
|
29334
29482
|
return null;
|
|
29335
|
-
const recordFile =
|
|
29336
|
-
if (!isPathInside(
|
|
29483
|
+
const recordFile = path91.join(testingDataRoot(cwd), "artifacts", latest.record);
|
|
29484
|
+
if (!isPathInside(path91.join(testingDataRoot(cwd), "artifacts"), recordFile))
|
|
29337
29485
|
return null;
|
|
29338
29486
|
if (!await pathExists(recordFile))
|
|
29339
29487
|
return null;
|
|
@@ -29380,28 +29528,28 @@ async function ensureContext(cwd) {
|
|
|
29380
29528
|
}
|
|
29381
29529
|
async function writeContext(cwd, context) {
|
|
29382
29530
|
const root = testingDataRoot(cwd);
|
|
29383
|
-
const rel = (p) =>
|
|
29531
|
+
const rel = (p) => path91.relative(cwd, p);
|
|
29384
29532
|
await mkdirContained(cwd, rel(root));
|
|
29385
|
-
await writeContained(cwd, rel(
|
|
29533
|
+
await writeContained(cwd, rel(path91.join(root, "context.json")), `${JSON.stringify(context, null, 2)}
|
|
29386
29534
|
`);
|
|
29387
|
-
await writeContained(cwd, rel(
|
|
29388
|
-
await writeContained(cwd, rel(
|
|
29535
|
+
await writeContained(cwd, rel(path91.join(root, "context.md")), renderContextMarkdown(context));
|
|
29536
|
+
await writeContained(cwd, rel(path91.join(root, "recommendations.md")), renderRecommendationsMarkdown(context));
|
|
29389
29537
|
}
|
|
29390
29538
|
async function writeReport(cwd, report) {
|
|
29391
29539
|
const root = testingDataRoot(cwd);
|
|
29392
|
-
const artifacts =
|
|
29393
|
-
const history =
|
|
29394
|
-
const rel = (p) =>
|
|
29540
|
+
const artifacts = path91.join(root, "artifacts");
|
|
29541
|
+
const history = path91.join(root, "history");
|
|
29542
|
+
const rel = (p) => path91.relative(cwd, p);
|
|
29395
29543
|
await mkdirContained(cwd, rel(artifacts));
|
|
29396
29544
|
await mkdirContained(cwd, rel(history));
|
|
29397
29545
|
const stamp = report.generatedAt.replace(/[:.]/g, "-");
|
|
29398
|
-
const json =
|
|
29399
|
-
const markdown =
|
|
29546
|
+
const json = path91.join(artifacts, "latest.json");
|
|
29547
|
+
const markdown = path91.join(artifacts, "latest.md");
|
|
29400
29548
|
const serialized = `${JSON.stringify(report, null, 2)}
|
|
29401
29549
|
`;
|
|
29402
29550
|
if (report.runId) {
|
|
29403
|
-
const runJson =
|
|
29404
|
-
const runMarkdown =
|
|
29551
|
+
const runJson = path91.join(artifacts, "runs", `${report.runId}.json`);
|
|
29552
|
+
const runMarkdown = path91.join(artifacts, "runs", `${report.runId}.md`);
|
|
29405
29553
|
if (await pathExists(runJson))
|
|
29406
29554
|
throw new Error(`immutable testing run already exists: ${report.runId}`);
|
|
29407
29555
|
await writeContained(cwd, rel(runJson), serialized);
|
|
@@ -29412,26 +29560,26 @@ async function writeReport(cwd, report) {
|
|
|
29412
29560
|
branch: report.provenance?.branch ?? null,
|
|
29413
29561
|
worktree: report.provenance?.worktree ?? null,
|
|
29414
29562
|
generated_at: report.generatedAt,
|
|
29415
|
-
record:
|
|
29563
|
+
record: path91.posix.join("runs", `${report.runId}.json`)
|
|
29416
29564
|
}, null, 2)}
|
|
29417
29565
|
`);
|
|
29418
29566
|
} else {
|
|
29419
29567
|
await writeContained(cwd, rel(json), serialized);
|
|
29420
29568
|
}
|
|
29421
29569
|
await writeContained(cwd, rel(markdown), renderReportMarkdown3(report));
|
|
29422
|
-
await writeContained(cwd, rel(
|
|
29570
|
+
await writeContained(cwd, rel(path91.join(history, `${stamp}.json`)), serialized);
|
|
29423
29571
|
return {
|
|
29424
|
-
markdownPath:
|
|
29425
|
-
jsonPath:
|
|
29572
|
+
markdownPath: path91.relative(cwd, markdown),
|
|
29573
|
+
jsonPath: path91.relative(cwd, json)
|
|
29426
29574
|
};
|
|
29427
29575
|
}
|
|
29428
29576
|
async function writeRawLog(cwd, raw) {
|
|
29429
|
-
const logs =
|
|
29430
|
-
const rel = (p) =>
|
|
29577
|
+
const logs = path91.join(testingDataRoot(cwd), "logs");
|
|
29578
|
+
const rel = (p) => path91.relative(cwd, p);
|
|
29431
29579
|
await mkdirContained(cwd, rel(logs));
|
|
29432
|
-
const latest =
|
|
29580
|
+
const latest = path91.join(logs, "latest.raw.log");
|
|
29433
29581
|
await writeContained(cwd, rel(latest), raw);
|
|
29434
|
-
return
|
|
29582
|
+
return path91.relative(cwd, latest);
|
|
29435
29583
|
}
|
|
29436
29584
|
async function listProjectFiles(cwd) {
|
|
29437
29585
|
const out = [];
|
|
@@ -29444,11 +29592,11 @@ async function walk3(root, dir, out, incompleteReasons) {
|
|
|
29444
29592
|
try {
|
|
29445
29593
|
entries = await readdir15(dir, { withFileTypes: true });
|
|
29446
29594
|
} catch (error) {
|
|
29447
|
-
incompleteReasons.push(`${normalizePath6(
|
|
29595
|
+
incompleteReasons.push(`${normalizePath6(path91.relative(root, dir)) || "."}: ${error instanceof Error ? error.message : String(error)}`);
|
|
29448
29596
|
return;
|
|
29449
29597
|
}
|
|
29450
29598
|
for (const entry of entries) {
|
|
29451
|
-
const abs =
|
|
29599
|
+
const abs = path91.join(dir, entry.name);
|
|
29452
29600
|
if (entry.isDirectory()) {
|
|
29453
29601
|
if (IGNORED_DIRS2.has(entry.name) || entry.name.startsWith(".tmp-")) {
|
|
29454
29602
|
continue;
|
|
@@ -29457,12 +29605,12 @@ async function walk3(root, dir, out, incompleteReasons) {
|
|
|
29457
29605
|
continue;
|
|
29458
29606
|
}
|
|
29459
29607
|
if (entry.isFile()) {
|
|
29460
|
-
out.push(normalizePath6(
|
|
29608
|
+
out.push(normalizePath6(path91.relative(root, abs)));
|
|
29461
29609
|
}
|
|
29462
29610
|
}
|
|
29463
29611
|
}
|
|
29464
29612
|
async function readPackageJson(cwd) {
|
|
29465
|
-
const file =
|
|
29613
|
+
const file = path91.join(cwd, "package.json");
|
|
29466
29614
|
if (!await pathExists(file)) {
|
|
29467
29615
|
return null;
|
|
29468
29616
|
}
|
|
@@ -29473,7 +29621,7 @@ async function readPackageJson(cwd) {
|
|
|
29473
29621
|
}
|
|
29474
29622
|
}
|
|
29475
29623
|
async function loadTestingConfig(cwd) {
|
|
29476
|
-
const file =
|
|
29624
|
+
const file = path91.join(cwd, ".metaproject", "testing.config.json");
|
|
29477
29625
|
if (!await pathExists(file)) {
|
|
29478
29626
|
return DEFAULT_TESTING_CONFIG;
|
|
29479
29627
|
}
|
|
@@ -29538,7 +29686,7 @@ function detectFrameworks(input) {
|
|
|
29538
29686
|
async function extractConventions(cwd, files) {
|
|
29539
29687
|
const conventions = new Set;
|
|
29540
29688
|
for (const file of files.slice(0, 40)) {
|
|
29541
|
-
const abs =
|
|
29689
|
+
const abs = path91.join(cwd, file);
|
|
29542
29690
|
if (!await pathExists(abs)) {
|
|
29543
29691
|
continue;
|
|
29544
29692
|
}
|
|
@@ -29668,7 +29816,7 @@ async function findTestsByImportedTargets(cwd, targets, testFiles) {
|
|
|
29668
29816
|
const targetKeys = new Set(targets.map((target) => modulePathKey(normalizePath6(target))));
|
|
29669
29817
|
const selected = new Set;
|
|
29670
29818
|
for (const testFile of testFiles) {
|
|
29671
|
-
const absoluteTest =
|
|
29819
|
+
const absoluteTest = path91.join(cwd, testFile);
|
|
29672
29820
|
if (!await pathExists(absoluteTest)) {
|
|
29673
29821
|
continue;
|
|
29674
29822
|
}
|
|
@@ -29702,10 +29850,10 @@ function resolveImportPath(cwd, testFile, importPath) {
|
|
|
29702
29850
|
if (!importPath.startsWith(".")) {
|
|
29703
29851
|
return null;
|
|
29704
29852
|
}
|
|
29705
|
-
const importerDir =
|
|
29706
|
-
const absoluteResolved =
|
|
29707
|
-
const relative =
|
|
29708
|
-
if (relative.startsWith(`..${
|
|
29853
|
+
const importerDir = path91.dirname(testFile);
|
|
29854
|
+
const absoluteResolved = path91.resolve(path91.join(cwd, importerDir), importPath);
|
|
29855
|
+
const relative = path91.relative(cwd, absoluteResolved);
|
|
29856
|
+
if (relative.startsWith(`..${path91.sep}`) || relative === "..") {
|
|
29709
29857
|
return null;
|
|
29710
29858
|
}
|
|
29711
29859
|
const relativeNormalized = normalizePath6(relative);
|
|
@@ -29757,13 +29905,13 @@ function resolveTestCommand(cwd, context, input) {
|
|
|
29757
29905
|
}
|
|
29758
29906
|
var BUN_LOCKFILES = ["bun.lock", "bun.lockb"];
|
|
29759
29907
|
function detectPackageManager(cwd) {
|
|
29760
|
-
if (resolveBunBin() && BUN_LOCKFILES.some((name) => pathExistsSync(
|
|
29908
|
+
if (resolveBunBin() && BUN_LOCKFILES.some((name) => pathExistsSync(path91.join(cwd, name)))) {
|
|
29761
29909
|
return "bun";
|
|
29762
29910
|
}
|
|
29763
|
-
if (Bun.which("pnpm") && pathExistsSync(
|
|
29911
|
+
if (Bun.which("pnpm") && pathExistsSync(path91.join(cwd, "pnpm-lock.yaml"))) {
|
|
29764
29912
|
return "pnpm";
|
|
29765
29913
|
}
|
|
29766
|
-
if (Bun.which("yarn") && pathExistsSync(
|
|
29914
|
+
if (Bun.which("yarn") && pathExistsSync(path91.join(cwd, "yarn.lock"))) {
|
|
29767
29915
|
return "yarn";
|
|
29768
29916
|
}
|
|
29769
29917
|
return "npm";
|
|
@@ -30103,7 +30251,7 @@ async function compatibleReportForHealth(ctx) {
|
|
|
30103
30251
|
|
|
30104
30252
|
// src/health/sources/dependency-audit.ts
|
|
30105
30253
|
import { existsSync as existsSync12 } from "fs";
|
|
30106
|
-
import
|
|
30254
|
+
import path92 from "path";
|
|
30107
30255
|
function auditSeverityToPriority(severity) {
|
|
30108
30256
|
if (severity === "critical" || severity === "high")
|
|
30109
30257
|
return "P0";
|
|
@@ -30222,7 +30370,7 @@ var LOCKFILE_COMMANDS = [
|
|
|
30222
30370
|
];
|
|
30223
30371
|
function auditCommand(cwd) {
|
|
30224
30372
|
for (const entry of LOCKFILE_COMMANDS) {
|
|
30225
|
-
if (!entry.lockfiles.some((name) => existsSync12(
|
|
30373
|
+
if (!entry.lockfiles.some((name) => existsSync12(path92.join(cwd, name))))
|
|
30226
30374
|
continue;
|
|
30227
30375
|
const bin = resolveBin(cwd, entry.bin);
|
|
30228
30376
|
if (bin)
|
|
@@ -30281,13 +30429,13 @@ var dependencyAuditAdapter = {
|
|
|
30281
30429
|
|
|
30282
30430
|
// src/health/sources/sonarqube.ts
|
|
30283
30431
|
import { existsSync as existsSync13 } from "fs";
|
|
30284
|
-
import
|
|
30432
|
+
import path93 from "path";
|
|
30285
30433
|
var REPORT_FILES = ["sonar-issues.json", ".metaproject/data/health/sonar-issues.json"];
|
|
30286
30434
|
function reportPath(cwd) {
|
|
30287
30435
|
const fromEnv = process.env.SONAR_ISSUES_FILE;
|
|
30288
30436
|
const candidates = fromEnv ? [fromEnv, ...REPORT_FILES] : REPORT_FILES;
|
|
30289
30437
|
for (const rel of candidates) {
|
|
30290
|
-
const abs =
|
|
30438
|
+
const abs = path93.isAbsolute(rel) ? rel : path93.join(cwd, rel);
|
|
30291
30439
|
if (existsSync13(abs)) {
|
|
30292
30440
|
return abs;
|
|
30293
30441
|
}
|
|
@@ -30371,7 +30519,7 @@ var sonarqubeAdapter = {
|
|
|
30371
30519
|
function relativizeComponent(component, cwd) {
|
|
30372
30520
|
const colon = component.indexOf(":");
|
|
30373
30521
|
const value = colon >= 0 ? component.slice(colon + 1) : component;
|
|
30374
|
-
return
|
|
30522
|
+
return path93.isAbsolute(value) ? path93.relative(cwd, value) : value;
|
|
30375
30523
|
}
|
|
30376
30524
|
|
|
30377
30525
|
// src/health/sources/index.ts
|
|
@@ -30708,19 +30856,19 @@ function filteredInfo(source, cfg) {
|
|
|
30708
30856
|
};
|
|
30709
30857
|
}
|
|
30710
30858
|
async function writeOutputs(cwd, report, config, stamp) {
|
|
30711
|
-
const artifacts =
|
|
30712
|
-
const history =
|
|
30859
|
+
const artifacts = path94.join(dataRoot3(cwd), "artifacts");
|
|
30860
|
+
const history = path94.join(dataRoot3(cwd), "history");
|
|
30713
30861
|
await mkdir26(artifacts, { recursive: true });
|
|
30714
30862
|
await mkdir26(history, { recursive: true });
|
|
30715
|
-
const markdown =
|
|
30716
|
-
const json =
|
|
30717
|
-
const historyJson =
|
|
30863
|
+
const markdown = path94.join(artifacts, "latest.md");
|
|
30864
|
+
const json = path94.join(artifacts, "latest.json");
|
|
30865
|
+
const historyJson = path94.join(history, `${stamp}.json`);
|
|
30718
30866
|
const serialized = `${JSON.stringify(report, null, 2)}
|
|
30719
30867
|
`;
|
|
30720
30868
|
await writeFile19(markdown, renderReportMarkdown2(report, config), "utf8");
|
|
30721
30869
|
if (report.runId) {
|
|
30722
|
-
const runJson =
|
|
30723
|
-
const runMarkdown =
|
|
30870
|
+
const runJson = path94.join(artifacts, "runs", `${report.runId}.json`);
|
|
30871
|
+
const runMarkdown = path94.join(artifacts, "runs", `${report.runId}.md`);
|
|
30724
30872
|
if (await pathExists(runJson))
|
|
30725
30873
|
throw new Error(`immutable health run already exists: ${report.runId}`);
|
|
30726
30874
|
await writeFileAtomic(runJson, serialized);
|
|
@@ -30731,7 +30879,7 @@ async function writeOutputs(cwd, report, config, stamp) {
|
|
|
30731
30879
|
branch: report.provenance?.branch ?? null,
|
|
30732
30880
|
worktree: report.provenance?.worktree ?? null,
|
|
30733
30881
|
generated_at: report.generatedAt,
|
|
30734
|
-
record:
|
|
30882
|
+
record: path94.posix.join("runs", `${report.runId}.json`)
|
|
30735
30883
|
}, null, 2)}
|
|
30736
30884
|
`);
|
|
30737
30885
|
} else {
|
|
@@ -30739,8 +30887,8 @@ async function writeOutputs(cwd, report, config, stamp) {
|
|
|
30739
30887
|
}
|
|
30740
30888
|
await writeFile19(historyJson, serialized, "utf8");
|
|
30741
30889
|
return {
|
|
30742
|
-
markdownPath:
|
|
30743
|
-
jsonPath:
|
|
30890
|
+
markdownPath: path94.relative(cwd, markdown),
|
|
30891
|
+
jsonPath: path94.relative(cwd, json)
|
|
30744
30892
|
};
|
|
30745
30893
|
}
|
|
30746
30894
|
async function resolveChanged(cwd, selector) {
|
|
@@ -30793,7 +30941,7 @@ function hasGateShape(value) {
|
|
|
30793
30941
|
return Array.isArray(report.metrics) && Array.isArray(report.sources) && Array.isArray(report.findings);
|
|
30794
30942
|
}
|
|
30795
30943
|
async function readLatest(cwd) {
|
|
30796
|
-
const file =
|
|
30944
|
+
const file = path95.join(dataRoot3(cwd), "artifacts", "latest.json");
|
|
30797
30945
|
if (!await pathExists(file)) {
|
|
30798
30946
|
return null;
|
|
30799
30947
|
}
|
|
@@ -30804,11 +30952,11 @@ async function readLatest(cwd) {
|
|
|
30804
30952
|
const latest = read.value;
|
|
30805
30953
|
const record = latest.record;
|
|
30806
30954
|
if (typeof record === "string") {
|
|
30807
|
-
const pointer = await readArtifactPointer(
|
|
30955
|
+
const pointer = await readArtifactPointer(path95.join(dataRoot3(cwd), "artifacts"), await collectGitProvenance(cwd));
|
|
30808
30956
|
if (pointer.status !== "fresh")
|
|
30809
30957
|
return null;
|
|
30810
|
-
const recordFile =
|
|
30811
|
-
if (!isPathInside(
|
|
30958
|
+
const recordFile = path95.join(dataRoot3(cwd), "artifacts", record);
|
|
30959
|
+
if (!isPathInside(path95.join(dataRoot3(cwd), "artifacts"), recordFile))
|
|
30812
30960
|
return null;
|
|
30813
30961
|
if (!await pathExists(recordFile))
|
|
30814
30962
|
return null;
|
|
@@ -30881,7 +31029,7 @@ function createCodeHealthService() {
|
|
|
30881
31029
|
return {
|
|
30882
31030
|
run: (input) => runHealth(input),
|
|
30883
31031
|
async status(input) {
|
|
30884
|
-
const enabled = await pathExists(
|
|
31032
|
+
const enabled = await pathExists(path95.join(input.cwd, ".metaproject", "health.config.json"));
|
|
30885
31033
|
const latest = await readLatest(input.cwd);
|
|
30886
31034
|
const project = latest?.metrics.find((m) => m.key === "project") ?? null;
|
|
30887
31035
|
const decliningScopes = latest ? latest.metrics.filter((m) => m.regression_score > 0).length : 0;
|
|
@@ -31039,10 +31187,10 @@ function renderEvidenceBlock(evidences, siblings) {
|
|
|
31039
31187
|
init_fs();
|
|
31040
31188
|
init_contained_write();
|
|
31041
31189
|
init_json();
|
|
31042
|
-
import
|
|
31190
|
+
import path96 from "path";
|
|
31043
31191
|
import { createHash as createHash16 } from "crypto";
|
|
31044
31192
|
function impactEvidenceDataRoot(root) {
|
|
31045
|
-
return
|
|
31193
|
+
return path96.join(root, ".metaproject", "data", "security", "impact-evidence");
|
|
31046
31194
|
}
|
|
31047
31195
|
function sanitizeSessionId(sessionId) {
|
|
31048
31196
|
const cleaned = sessionId.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
@@ -31054,7 +31202,7 @@ function sessionStateFilename(sessionId) {
|
|
|
31054
31202
|
return `${sanitized}-${suffix}.json`;
|
|
31055
31203
|
}
|
|
31056
31204
|
function sessionStatePath(root, sessionId) {
|
|
31057
|
-
return
|
|
31205
|
+
return path96.join(impactEvidenceDataRoot(root), "sessions", sessionStateFilename(sessionId));
|
|
31058
31206
|
}
|
|
31059
31207
|
async function loadSessionState(root, sessionId) {
|
|
31060
31208
|
const file = sessionStatePath(root, sessionId);
|
|
@@ -31073,11 +31221,11 @@ async function loadSessionState(root, sessionId) {
|
|
|
31073
31221
|
}
|
|
31074
31222
|
async function saveSessionState(root, sessionId, state) {
|
|
31075
31223
|
const file = sessionStatePath(root, sessionId);
|
|
31076
|
-
await writeContained(root,
|
|
31224
|
+
await writeContained(root, path96.relative(root, file), `${JSON.stringify(state, null, 2)}
|
|
31077
31225
|
`);
|
|
31078
31226
|
}
|
|
31079
31227
|
function logPath(root) {
|
|
31080
|
-
return
|
|
31228
|
+
return path96.join(impactEvidenceDataRoot(root), "log.jsonl");
|
|
31081
31229
|
}
|
|
31082
31230
|
async function appendLogRecord(root, record) {
|
|
31083
31231
|
const full = {
|
|
@@ -31088,7 +31236,7 @@ async function appendLogRecord(root, record) {
|
|
|
31088
31236
|
...record.detail !== undefined ? { detail: record.detail } : {}
|
|
31089
31237
|
};
|
|
31090
31238
|
const file = logPath(root);
|
|
31091
|
-
await appendContained(root,
|
|
31239
|
+
await appendContained(root, path96.relative(root, file), `${JSON.stringify(full)}
|
|
31092
31240
|
`);
|
|
31093
31241
|
return full;
|
|
31094
31242
|
}
|
|
@@ -31115,7 +31263,7 @@ init_command_risk();
|
|
|
31115
31263
|
init_shell_syntax();
|
|
31116
31264
|
init_fs();
|
|
31117
31265
|
init_service2();
|
|
31118
|
-
import
|
|
31266
|
+
import path97 from "path";
|
|
31119
31267
|
import { createHash as createHash17 } from "crypto";
|
|
31120
31268
|
import { realpathSync as realpathSync2 } from "fs";
|
|
31121
31269
|
function impactEvidenceHookClass(strict) {
|
|
@@ -31131,29 +31279,29 @@ function realpathNearestExisting(p) {
|
|
|
31131
31279
|
for (;; ) {
|
|
31132
31280
|
try {
|
|
31133
31281
|
const real = realpathSync2(current);
|
|
31134
|
-
return tail.length > 0 ?
|
|
31282
|
+
return tail.length > 0 ? path97.join(real, ...tail) : real;
|
|
31135
31283
|
} catch {
|
|
31136
|
-
const parent =
|
|
31284
|
+
const parent = path97.dirname(current);
|
|
31137
31285
|
if (parent === current) {
|
|
31138
|
-
return tail.length > 0 ?
|
|
31286
|
+
return tail.length > 0 ? path97.join(current, ...tail) : current;
|
|
31139
31287
|
}
|
|
31140
|
-
tail.unshift(
|
|
31288
|
+
tail.unshift(path97.basename(current));
|
|
31141
31289
|
current = parent;
|
|
31142
31290
|
}
|
|
31143
31291
|
}
|
|
31144
31292
|
}
|
|
31145
31293
|
function normalizeRequestFiles(root, files) {
|
|
31146
|
-
const rootReal = realpathNearestExisting(
|
|
31294
|
+
const rootReal = realpathNearestExisting(path97.resolve(root));
|
|
31147
31295
|
const normalized = [];
|
|
31148
31296
|
const rejected = [];
|
|
31149
31297
|
for (const file of files) {
|
|
31150
|
-
const lexicalAbsolute =
|
|
31298
|
+
const lexicalAbsolute = path97.isAbsolute(file) ? path97.resolve(file) : path97.resolve(rootReal, toPosix(file).replace(/^\.\//, ""));
|
|
31151
31299
|
const effective = realpathNearestExisting(lexicalAbsolute);
|
|
31152
31300
|
if (!isPathInside(rootReal, effective)) {
|
|
31153
31301
|
rejected.push(file);
|
|
31154
31302
|
continue;
|
|
31155
31303
|
}
|
|
31156
|
-
normalized.push(toPosix(
|
|
31304
|
+
normalized.push(toPosix(path97.relative(rootReal, effective)));
|
|
31157
31305
|
}
|
|
31158
31306
|
return { files: [...new Set(normalized)], rejected };
|
|
31159
31307
|
}
|
|
@@ -31439,7 +31587,7 @@ __export(exports_service8, {
|
|
|
31439
31587
|
createJobService: () => createJobService
|
|
31440
31588
|
});
|
|
31441
31589
|
import { copyFile, mkdir as mkdir28 } from "fs/promises";
|
|
31442
|
-
import
|
|
31590
|
+
import path100 from "path";
|
|
31443
31591
|
|
|
31444
31592
|
// src/job/types.ts
|
|
31445
31593
|
var JOB_INTENTS = ["implement", "analyze", "review", "custom"];
|
|
@@ -31578,12 +31726,12 @@ function defaultPlan(intent) {
|
|
|
31578
31726
|
// src/job/store.ts
|
|
31579
31727
|
init_validator();
|
|
31580
31728
|
import { appendFile as appendFile5, mkdir as mkdir27, readFile as readFile47, readdir as readdir16 } from "fs/promises";
|
|
31581
|
-
import
|
|
31729
|
+
import path99 from "path";
|
|
31582
31730
|
|
|
31583
31731
|
// src/gdskills/contracts.ts
|
|
31584
31732
|
import { readFile as readFile46 } from "fs/promises";
|
|
31585
31733
|
import { existsSync as existsSync14 } from "fs";
|
|
31586
|
-
import
|
|
31734
|
+
import path98 from "path";
|
|
31587
31735
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
31588
31736
|
var CONTRACTS = [
|
|
31589
31737
|
{
|
|
@@ -31706,10 +31854,10 @@ async function loadSchema(name) {
|
|
|
31706
31854
|
return JSON.parse(raw);
|
|
31707
31855
|
}
|
|
31708
31856
|
function contractPath(contract) {
|
|
31709
|
-
const here =
|
|
31857
|
+
const here = path98.dirname(fileURLToPath2(import.meta.url));
|
|
31710
31858
|
if (contract.sourcePath) {
|
|
31711
|
-
for (const root of [
|
|
31712
|
-
const candidate =
|
|
31859
|
+
for (const root of [path98.join(here, "..", ".."), path98.join(here, ".."), here]) {
|
|
31860
|
+
const candidate = path98.resolve(root, contract.sourcePath);
|
|
31713
31861
|
if (existsSync14(candidate)) {
|
|
31714
31862
|
return candidate;
|
|
31715
31863
|
}
|
|
@@ -31719,7 +31867,7 @@ function contractPath(contract) {
|
|
|
31719
31867
|
if (existsSync14(directPath)) {
|
|
31720
31868
|
return directPath;
|
|
31721
31869
|
}
|
|
31722
|
-
const packagedSourcePath =
|
|
31870
|
+
const packagedSourcePath = path98.join(here, "..", "src", "gdskills", "contracts", contract.fileName);
|
|
31723
31871
|
if (existsSync14(packagedSourcePath)) {
|
|
31724
31872
|
return packagedSourcePath;
|
|
31725
31873
|
}
|
|
@@ -31733,13 +31881,13 @@ var SCHEMA_ROOTS = [
|
|
|
31733
31881
|
// src/job/store.ts
|
|
31734
31882
|
init_fs();
|
|
31735
31883
|
function jobsRoot(cwd) {
|
|
31736
|
-
return
|
|
31884
|
+
return path99.join(cwd, ".metaproject", "jobs");
|
|
31737
31885
|
}
|
|
31738
31886
|
function jobDir(cwd, name) {
|
|
31739
|
-
return
|
|
31887
|
+
return path99.join(jobsRoot(cwd), name);
|
|
31740
31888
|
}
|
|
31741
31889
|
function jobStatePath(cwd, name) {
|
|
31742
|
-
return
|
|
31890
|
+
return path99.join(jobDir(cwd, name), "state.json");
|
|
31743
31891
|
}
|
|
31744
31892
|
var JOB_NAME_PATTERN = /^[a-z0-9-]+$/;
|
|
31745
31893
|
function assertJobName(name) {
|
|
@@ -31776,12 +31924,12 @@ async function writeJob(cwd, name, state) {
|
|
|
31776
31924
|
`));
|
|
31777
31925
|
}
|
|
31778
31926
|
const file = jobStatePath(cwd, name);
|
|
31779
|
-
await mkdir27(
|
|
31927
|
+
await mkdir27(path99.dirname(file), { recursive: true });
|
|
31780
31928
|
await writeFileAtomic(file, `${JSON.stringify(state, null, 2)}
|
|
31781
31929
|
`);
|
|
31782
31930
|
}
|
|
31783
31931
|
async function appendJournal2(cwd, name, at, line) {
|
|
31784
|
-
await appendFile5(
|
|
31932
|
+
await appendFile5(path99.join(jobDir(cwd, name), "journal.md"), `- ${at} - ${line}
|
|
31785
31933
|
`, "utf8");
|
|
31786
31934
|
}
|
|
31787
31935
|
function renderJournal2(name, at) {
|
|
@@ -31802,7 +31950,7 @@ function assertDocumentType(raw) {
|
|
|
31802
31950
|
return raw;
|
|
31803
31951
|
}
|
|
31804
31952
|
function documentFileName(type, sourcePath) {
|
|
31805
|
-
const extension =
|
|
31953
|
+
const extension = path99.extname(sourcePath) || ".md";
|
|
31806
31954
|
return `${type}${extension}`;
|
|
31807
31955
|
}
|
|
31808
31956
|
|
|
@@ -31810,7 +31958,7 @@ function documentFileName(type, sourcePath) {
|
|
|
31810
31958
|
function createJobService(deps) {
|
|
31811
31959
|
const now = () => deps.now().toISOString();
|
|
31812
31960
|
function lockPath(cwd, name) {
|
|
31813
|
-
return
|
|
31961
|
+
return path100.join(jobsRoot(cwd), `.job-lock-${name}`);
|
|
31814
31962
|
}
|
|
31815
31963
|
async function mutate(cwd, name, run) {
|
|
31816
31964
|
assertJobName(name);
|
|
@@ -31859,20 +32007,20 @@ function createJobService(deps) {
|
|
|
31859
32007
|
},
|
|
31860
32008
|
plan: { steps: defaultPlan(intent) },
|
|
31861
32009
|
documentation: {
|
|
31862
|
-
job_path:
|
|
32010
|
+
job_path: path100.join(".metaproject", "jobs", name),
|
|
31863
32011
|
documents_created: []
|
|
31864
32012
|
},
|
|
31865
32013
|
metrics: { steps: [] },
|
|
31866
|
-
jobs_root:
|
|
32014
|
+
jobs_root: path100.join(".metaproject", "jobs"),
|
|
31867
32015
|
updated_at: createdAt
|
|
31868
32016
|
};
|
|
31869
32017
|
const first = firstOpenStep(state.plan.steps);
|
|
31870
32018
|
if (first) {
|
|
31871
32019
|
state.plan.current_step = first.id;
|
|
31872
32020
|
}
|
|
31873
|
-
await writeFileAtomic(
|
|
32021
|
+
await writeFileAtomic(path100.join(absolute, "journal.md"), renderJournal2(name, createdAt));
|
|
31874
32022
|
await writeJob(input.cwd, name, state);
|
|
31875
|
-
return { state, dir:
|
|
32023
|
+
return { state, dir: path100.relative(input.cwd, absolute) };
|
|
31876
32024
|
},
|
|
31877
32025
|
async status({ cwd, name }) {
|
|
31878
32026
|
assertJobName(name);
|
|
@@ -31884,7 +32032,7 @@ function createJobService(deps) {
|
|
|
31884
32032
|
}
|
|
31885
32033
|
return {
|
|
31886
32034
|
state,
|
|
31887
|
-
dir:
|
|
32035
|
+
dir: path100.join(".metaproject", "jobs", name),
|
|
31888
32036
|
stepsDone: state.plan.steps.filter((step) => isTerminalStep(step.status)).length,
|
|
31889
32037
|
stepsTotal: state.plan.steps.length,
|
|
31890
32038
|
nextStep: firstOpenStep(state.plan.steps),
|
|
@@ -31941,23 +32089,23 @@ function createJobService(deps) {
|
|
|
31941
32089
|
if (!input.file) {
|
|
31942
32090
|
throw new Error("Missing --file. Usage: keryx job document <name> --type <type> --file <path>");
|
|
31943
32091
|
}
|
|
31944
|
-
const source =
|
|
32092
|
+
const source = path100.isAbsolute(input.file) ? input.file : path100.join(input.cwd, input.file);
|
|
31945
32093
|
if (!await pathExists(source)) {
|
|
31946
32094
|
throw new Error(`--file not found: ${input.file}. Write the document first, then record it.`);
|
|
31947
32095
|
}
|
|
31948
32096
|
let recorded;
|
|
31949
32097
|
await mutate(input.cwd, input.name, async (state) => {
|
|
31950
32098
|
const fileName = documentFileName(type, source);
|
|
31951
|
-
const target =
|
|
32099
|
+
const target = path100.join(jobDir(input.cwd, state.job_name), fileName);
|
|
31952
32100
|
await copyFile(source, target);
|
|
31953
32101
|
state.documentation ??= {};
|
|
31954
|
-
state.documentation.job_path ??=
|
|
32102
|
+
state.documentation.job_path ??= path100.join(".metaproject", "jobs", state.job_name);
|
|
31955
32103
|
const created = state.documentation.documents_created ?? [];
|
|
31956
32104
|
state.documentation.documents_created = created.includes(fileName) ? created : [...created, fileName];
|
|
31957
32105
|
recorded = {
|
|
31958
32106
|
state,
|
|
31959
32107
|
document: fileName,
|
|
31960
|
-
path:
|
|
32108
|
+
path: path100.join(".metaproject", "jobs", state.job_name, fileName)
|
|
31961
32109
|
};
|
|
31962
32110
|
return { state, event: "document", detail: `${type} -> ${fileName}` };
|
|
31963
32111
|
});
|
|
@@ -31992,7 +32140,7 @@ function createJobService(deps) {
|
|
|
31992
32140
|
name: state.job_name,
|
|
31993
32141
|
phase: state.phase,
|
|
31994
32142
|
intent: state.intent,
|
|
31995
|
-
dir:
|
|
32143
|
+
dir: path100.join(".metaproject", "jobs", name),
|
|
31996
32144
|
stepsDone: state.plan.steps.filter((step) => isTerminalStep(step.status)).length,
|
|
31997
32145
|
stepsTotal: state.plan.steps.length,
|
|
31998
32146
|
nextStep: firstOpenStep(state.plan.steps)?.id ?? null
|
|
@@ -32097,12 +32245,12 @@ function normalizeWorkspaceReference(raw) {
|
|
|
32097
32245
|
// src/sac/fwk-service.ts
|
|
32098
32246
|
init_assembly();
|
|
32099
32247
|
import { appendFile as appendFile6, mkdir as mkdir30, open as open3, readFile as readFile50, rename as rename7, rm as rm6, stat as stat13, writeFile as writeFile20 } from "fs/promises";
|
|
32100
|
-
import
|
|
32248
|
+
import path104 from "path";
|
|
32101
32249
|
|
|
32102
32250
|
// src/sac/index.ts
|
|
32103
32251
|
import { access as access3, readFile as readFile48, realpath as realpath10 } from "fs/promises";
|
|
32104
32252
|
import { createHash as createHash18 } from "crypto";
|
|
32105
|
-
import
|
|
32253
|
+
import path101 from "path";
|
|
32106
32254
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
32107
32255
|
var idPattern = /^[a-z][a-z0-9-]{2,63}$/;
|
|
32108
32256
|
var subjectPattern = /^(?:user|team|service|agent):[a-z0-9][a-z0-9._-]{0,127}$/;
|
|
@@ -32120,21 +32268,21 @@ var normativeSchemaFiles = {
|
|
|
32120
32268
|
"review-decision": "review-decision.schema.json"
|
|
32121
32269
|
};
|
|
32122
32270
|
var normativeSchemas = new Map;
|
|
32123
|
-
var NORMATIVE_SCHEMA_DIR =
|
|
32271
|
+
var NORMATIVE_SCHEMA_DIR = path101.join("docs", "requirements", "shared-agent-context", "schemas");
|
|
32124
32272
|
async function resolveSacNormativeSchemaPath(fileName, searchFrom = [fileURLToPath3(new URL(".", import.meta.url)), process.cwd()]) {
|
|
32125
32273
|
const seen = new Set;
|
|
32126
32274
|
for (const start of searchFrom) {
|
|
32127
|
-
let dir =
|
|
32275
|
+
let dir = path101.resolve(start);
|
|
32128
32276
|
for (let i = 0;i < 10; i++) {
|
|
32129
32277
|
if (seen.has(dir))
|
|
32130
32278
|
break;
|
|
32131
32279
|
seen.add(dir);
|
|
32132
|
-
const candidate =
|
|
32280
|
+
const candidate = path101.join(dir, NORMATIVE_SCHEMA_DIR, fileName);
|
|
32133
32281
|
try {
|
|
32134
32282
|
await access3(candidate);
|
|
32135
32283
|
return candidate;
|
|
32136
32284
|
} catch {}
|
|
32137
|
-
const parent =
|
|
32285
|
+
const parent = path101.dirname(dir);
|
|
32138
32286
|
if (parent === dir)
|
|
32139
32287
|
break;
|
|
32140
32288
|
dir = parent;
|
|
@@ -32803,12 +32951,12 @@ class SacReferenceError extends Error {
|
|
|
32803
32951
|
code = "unsafe_workspace_reference";
|
|
32804
32952
|
}
|
|
32805
32953
|
async function resolveWorkspaceReference(input) {
|
|
32806
|
-
if (!workspacePathPattern.test(input.uri) ||
|
|
32954
|
+
if (!workspacePathPattern.test(input.uri) || path101.isAbsolute(input.uri) || /^[a-z][a-z0-9+.-]*:/i.test(input.uri) || input.uri.includes("\\"))
|
|
32807
32955
|
throw new SacReferenceError("unsafe workspace reference");
|
|
32808
|
-
const lexicalRoot =
|
|
32956
|
+
const lexicalRoot = path101.resolve(input.workspaceRoot);
|
|
32809
32957
|
const root = await realpath10(lexicalRoot);
|
|
32810
|
-
const candidate =
|
|
32811
|
-
if (candidate !== lexicalRoot && !candidate.startsWith(`${lexicalRoot}${
|
|
32958
|
+
const candidate = path101.resolve(lexicalRoot, input.uri.slice(2));
|
|
32959
|
+
if (candidate !== lexicalRoot && !candidate.startsWith(`${lexicalRoot}${path101.sep}`))
|
|
32812
32960
|
throw new SacReferenceError("workspace reference escapes root");
|
|
32813
32961
|
let resolved;
|
|
32814
32962
|
try {
|
|
@@ -32816,7 +32964,7 @@ async function resolveWorkspaceReference(input) {
|
|
|
32816
32964
|
} catch {
|
|
32817
32965
|
throw new SacReferenceError("workspace reference is not resolvable");
|
|
32818
32966
|
}
|
|
32819
|
-
if (resolved !== root && !resolved.startsWith(`${root}${
|
|
32967
|
+
if (resolved !== root && !resolved.startsWith(`${root}${path101.sep}`))
|
|
32820
32968
|
throw new SacReferenceError("workspace reference escapes root after realpath");
|
|
32821
32969
|
return candidate;
|
|
32822
32970
|
}
|
|
@@ -32872,16 +33020,16 @@ async function evaluateStrictSacGuard(input) {
|
|
|
32872
33020
|
init_fs();
|
|
32873
33021
|
import { mkdir as mkdir29, readdir as readdir17, readFile as readFile49 } from "fs/promises";
|
|
32874
33022
|
import { createHash as createHash19, randomUUID as randomUUID3 } from "crypto";
|
|
32875
|
-
import
|
|
33023
|
+
import path103 from "path";
|
|
32876
33024
|
|
|
32877
33025
|
// src/sac/secure-resource-read.ts
|
|
32878
33026
|
init_contained_read();
|
|
32879
33027
|
init_descriptor_read();
|
|
32880
|
-
import
|
|
33028
|
+
import path102 from "path";
|
|
32881
33029
|
function readWorkspaceFileNoFollow(workspaceRoot, absolutePath) {
|
|
32882
|
-
const relativePath =
|
|
32883
|
-
const components = relativePath.split(
|
|
32884
|
-
if (!relativePath ||
|
|
33030
|
+
const relativePath = path102.relative(workspaceRoot, absolutePath);
|
|
33031
|
+
const components = relativePath.split(path102.sep);
|
|
33032
|
+
if (!relativePath || path102.isAbsolute(relativePath) || components.some((component) => !component || component === "." || component === "..")) {
|
|
32885
33033
|
throw new Error("safe source path is not workspace-relative");
|
|
32886
33034
|
}
|
|
32887
33035
|
return readDescriptorChain(workspaceRoot, absolutePath, {
|
|
@@ -32908,8 +33056,8 @@ class WorkspaceService {
|
|
|
32908
33056
|
now;
|
|
32909
33057
|
constructor(options) {
|
|
32910
33058
|
this.options = options;
|
|
32911
|
-
this.root =
|
|
32912
|
-
this.storageRoot =
|
|
33059
|
+
this.root = path103.resolve(options.workspaceRoot);
|
|
33060
|
+
this.storageRoot = path103.resolve(options.storageRoot ?? path103.join(this.root, ".metaproject", "workspaces"));
|
|
32913
33061
|
this.now = options.now ?? (() => new Date);
|
|
32914
33062
|
}
|
|
32915
33063
|
async create(input) {
|
|
@@ -33234,13 +33382,13 @@ class WorkspaceService {
|
|
|
33234
33382
|
return parsed;
|
|
33235
33383
|
}
|
|
33236
33384
|
workspaceDir(id) {
|
|
33237
|
-
return
|
|
33385
|
+
return path103.join(this.storageRoot, id);
|
|
33238
33386
|
}
|
|
33239
33387
|
manifestPath(id) {
|
|
33240
|
-
return
|
|
33388
|
+
return path103.join(this.workspaceDir(id), "workspace.json");
|
|
33241
33389
|
}
|
|
33242
33390
|
lockPath(id) {
|
|
33243
|
-
return
|
|
33391
|
+
return path103.join(this.storageRoot, `.${id}.lock`);
|
|
33244
33392
|
}
|
|
33245
33393
|
timestamp() {
|
|
33246
33394
|
return this.now().toISOString();
|
|
@@ -34029,7 +34177,7 @@ function hasReportIntegrity(report) {
|
|
|
34029
34177
|
return reportHashPattern.test(reportDigest) && sha2564(body) === reportDigest;
|
|
34030
34178
|
}
|
|
34031
34179
|
async function resolvePolicySelection(workspaceRoot, canonicalFallback) {
|
|
34032
|
-
const configPath =
|
|
34180
|
+
const configPath = path104.join(workspaceRoot, ...policyExperimentConfigPath);
|
|
34033
34181
|
let configJson;
|
|
34034
34182
|
try {
|
|
34035
34183
|
const raw = await readFile50(configPath, "utf8").catch((error) => {
|
|
@@ -34227,9 +34375,9 @@ class FwkReadService {
|
|
|
34227
34375
|
const recordedAt = nowIso(now);
|
|
34228
34376
|
const id = `receipt-${randomUUID4().replace(/-/g, "").slice(0, 16)}`;
|
|
34229
34377
|
const base = { schemaVersion: "1.0", id, workspaceId, actor, action, decision, recordedAt, cost: { tokens: 0, toolCalls: 1, elapsedMs: 0 }, contextAssembly: { traceRef: assembly.traceRef, configurationRevision: assembly.configurationRevision, selected: assembly.selected.map((id) => `./ids/${id}`), omittedOptional: assembly.omittedOptional.map((id) => `./ids/${id}`) }, policy: { ref: assembly.policyRef, revision: assembly.policyRevision }, ...action === "resource" ? { resourceRef: `./ids/${resourceId ?? "unknown"}` } : {} };
|
|
34230
|
-
const ledger =
|
|
34231
|
-
const checkpointPath =
|
|
34232
|
-
await mkdir30(
|
|
34378
|
+
const ledger = path104.join(this.options.canonical.workspaceRoot, ".metaproject", "context-operations", "access-receipts.jsonl");
|
|
34379
|
+
const checkpointPath = path104.join(path104.dirname(ledger), "access-receipts.checkpoint.json");
|
|
34380
|
+
await mkdir30(path104.dirname(ledger), { recursive: true, mode: 448 });
|
|
34233
34381
|
return withFileLock(`${ledger}.lock`, async () => {
|
|
34234
34382
|
const state = await resolveLedgerState(ledger, checkpointPath, this.options.verifyReceiptLedger ?? verifyAccessReceiptLedger);
|
|
34235
34383
|
const receipt = sealAccessReceipt(base, state.headHash);
|
|
@@ -34333,7 +34481,7 @@ function normalizeFwkResult(result) {
|
|
|
34333
34481
|
init_fs();
|
|
34334
34482
|
import { createHash as createHash29, randomUUID as randomUUID7 } from "crypto";
|
|
34335
34483
|
import { appendFile as appendFile7, mkdir as mkdir34, readdir as readdir19, readFile as readFile59 } from "fs/promises";
|
|
34336
|
-
import
|
|
34484
|
+
import path114 from "path";
|
|
34337
34485
|
|
|
34338
34486
|
// src/sac/trusted-wrap-up.ts
|
|
34339
34487
|
import { createHash as createHash23, randomUUID as randomUUID5 } from "crypto";
|
|
@@ -34405,7 +34553,7 @@ function bindingHash(owner, intent) {
|
|
|
34405
34553
|
// src/sac/session-wrap-up.ts
|
|
34406
34554
|
import { createHash as createHash25 } from "crypto";
|
|
34407
34555
|
import { mkdir as mkdir32, writeFile as writeFile21 } from "fs/promises";
|
|
34408
|
-
import
|
|
34556
|
+
import path108 from "path";
|
|
34409
34557
|
|
|
34410
34558
|
// src/session/store.ts
|
|
34411
34559
|
import {
|
|
@@ -34416,7 +34564,7 @@ import {
|
|
|
34416
34564
|
renameSync as renameSync2,
|
|
34417
34565
|
writeFileSync as writeFileSync2
|
|
34418
34566
|
} from "fs";
|
|
34419
|
-
import
|
|
34567
|
+
import path107 from "path";
|
|
34420
34568
|
|
|
34421
34569
|
// src/lib/config-dir.ts
|
|
34422
34570
|
import {
|
|
@@ -34461,7 +34609,7 @@ function readTranscriptFile(file) {
|
|
|
34461
34609
|
// src/session/paths.ts
|
|
34462
34610
|
import { existsSync as existsSync15 } from "fs";
|
|
34463
34611
|
import { homedir } from "os";
|
|
34464
|
-
import
|
|
34612
|
+
import path105 from "path";
|
|
34465
34613
|
function keryxDataDir(override) {
|
|
34466
34614
|
if (override !== undefined && override.length > 0) {
|
|
34467
34615
|
return override;
|
|
@@ -34473,22 +34621,22 @@ function keryxDataDir(override) {
|
|
|
34473
34621
|
const home = homedir();
|
|
34474
34622
|
if (process.platform === "win32") {
|
|
34475
34623
|
const appData = process.env.APPDATA;
|
|
34476
|
-
const base = appData !== undefined && appData.length > 0 ? appData :
|
|
34477
|
-
return
|
|
34624
|
+
const base = appData !== undefined && appData.length > 0 ? appData : path105.join(home, "AppData", "Roaming");
|
|
34625
|
+
return path105.join(base, "keryx");
|
|
34478
34626
|
}
|
|
34479
34627
|
const xdg = process.env.XDG_DATA_HOME;
|
|
34480
|
-
const base = xdg !== undefined && xdg.length > 0 ? xdg :
|
|
34481
|
-
return
|
|
34628
|
+
const base = xdg !== undefined && xdg.length > 0 ? xdg : path105.join(home, ".local", "share");
|
|
34629
|
+
return path105.join(base, "keryx");
|
|
34482
34630
|
}
|
|
34483
34631
|
function resolveProjectRoot2(cwd) {
|
|
34484
|
-
const abs =
|
|
34632
|
+
const abs = path105.resolve(cwd);
|
|
34485
34633
|
let dir = abs;
|
|
34486
34634
|
for (;; ) {
|
|
34487
|
-
const gitPath =
|
|
34635
|
+
const gitPath = path105.join(dir, ".git");
|
|
34488
34636
|
if (existsSync15(gitPath)) {
|
|
34489
34637
|
return dir;
|
|
34490
34638
|
}
|
|
34491
|
-
const parent =
|
|
34639
|
+
const parent = path105.dirname(dir);
|
|
34492
34640
|
if (parent === dir) {
|
|
34493
34641
|
break;
|
|
34494
34642
|
}
|
|
@@ -34497,12 +34645,12 @@ function resolveProjectRoot2(cwd) {
|
|
|
34497
34645
|
return abs;
|
|
34498
34646
|
}
|
|
34499
34647
|
function projectKeyFromPath(projectPath) {
|
|
34500
|
-
const abs =
|
|
34648
|
+
const abs = path105.resolve(projectPath);
|
|
34501
34649
|
const encoded = encodeURIComponent(abs);
|
|
34502
34650
|
if (encoded.length <= 200) {
|
|
34503
34651
|
return encoded;
|
|
34504
34652
|
}
|
|
34505
|
-
const base =
|
|
34653
|
+
const base = path105.basename(abs).replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 40);
|
|
34506
34654
|
let h = 0;
|
|
34507
34655
|
for (let i = 0;i < abs.length; i++) {
|
|
34508
34656
|
h = Math.imul(31, h) + abs.charCodeAt(i) | 0;
|
|
@@ -34512,17 +34660,17 @@ function projectKeyFromPath(projectPath) {
|
|
|
34512
34660
|
}
|
|
34513
34661
|
function projectSessionsDir(projectPath, dataDir) {
|
|
34514
34662
|
const key = projectKeyFromPath(resolveProjectRoot2(projectPath));
|
|
34515
|
-
return
|
|
34663
|
+
return path105.join(keryxDataDir(dataDir), "sessions", key);
|
|
34516
34664
|
}
|
|
34517
34665
|
function sessionDir(projectPath, sessionId, dataDir) {
|
|
34518
|
-
return
|
|
34666
|
+
return path105.join(projectSessionsDir(projectPath, dataDir), sessionId);
|
|
34519
34667
|
}
|
|
34520
34668
|
|
|
34521
34669
|
// src/session/slate.ts
|
|
34522
34670
|
init_fs();
|
|
34523
34671
|
init_assembly();
|
|
34524
34672
|
import { mkdir as mkdir31, readFile as readFile51, rm as rm7 } from "fs/promises";
|
|
34525
|
-
import
|
|
34673
|
+
import path106 from "path";
|
|
34526
34674
|
init_redact();
|
|
34527
34675
|
var SLATE_SEED_KINDS = [
|
|
34528
34676
|
"decision",
|
|
@@ -34537,7 +34685,7 @@ function isSlateSeedKind(value) {
|
|
|
34537
34685
|
}
|
|
34538
34686
|
var SEED_TEXT_MAX_LENGTH = 4000;
|
|
34539
34687
|
function slatePath(dir) {
|
|
34540
|
-
return
|
|
34688
|
+
return path106.join(dir, "slate.json");
|
|
34541
34689
|
}
|
|
34542
34690
|
function slateLockPath(dir) {
|
|
34543
34691
|
return `${slatePath(dir)}.lock`;
|
|
@@ -34740,11 +34888,11 @@ function listSessions(cwd, dataDir) {
|
|
|
34740
34888
|
if (name.startsWith(".")) {
|
|
34741
34889
|
continue;
|
|
34742
34890
|
}
|
|
34743
|
-
const summary = readSummaryFile(
|
|
34891
|
+
const summary = readSummaryFile(path107.join(root, name, "summary.json"));
|
|
34744
34892
|
if (summary === undefined) {
|
|
34745
34893
|
continue;
|
|
34746
34894
|
}
|
|
34747
|
-
if (
|
|
34895
|
+
if (path107.resolve(summary.projectPath) !== path107.resolve(projectPath)) {
|
|
34748
34896
|
continue;
|
|
34749
34897
|
}
|
|
34750
34898
|
out.push(summary);
|
|
@@ -34777,15 +34925,15 @@ async function readSessionSlate(cwd, sessionId, dataDir) {
|
|
|
34777
34925
|
}
|
|
34778
34926
|
function loadContext(cwd, sessionId, dataDir) {
|
|
34779
34927
|
const dir = sessionDir(resolveProjectRoot2(cwd), sessionId, dataDir);
|
|
34780
|
-
const contextPath =
|
|
34928
|
+
const contextPath = path107.join(dir, "context.jsonl");
|
|
34781
34929
|
if (existsSync16(contextPath)) {
|
|
34782
34930
|
return readJsonl2(contextPath);
|
|
34783
34931
|
}
|
|
34784
|
-
return readJsonl2(
|
|
34932
|
+
return readJsonl2(path107.join(dir, "transcript.jsonl"));
|
|
34785
34933
|
}
|
|
34786
34934
|
function loadArchive(cwd, sessionId, dataDir, onDegraded) {
|
|
34787
34935
|
const dir = sessionDir(resolveProjectRoot2(cwd), sessionId, dataDir);
|
|
34788
|
-
const archivePath =
|
|
34936
|
+
const archivePath = path107.join(dir, "archive.jsonl");
|
|
34789
34937
|
if (existsSync16(archivePath)) {
|
|
34790
34938
|
try {
|
|
34791
34939
|
const archive = readJsonl2(archivePath);
|
|
@@ -34969,7 +35117,7 @@ function sessionEvidenceRef(workspaceId, sessionId) {
|
|
|
34969
35117
|
}
|
|
34970
35118
|
async function resolveSessionWrapUp(input) {
|
|
34971
35119
|
const now = input.now ?? (() => new Date);
|
|
34972
|
-
const sessionId =
|
|
35120
|
+
const sessionId = path108.posix.basename(input.sourceRef, ".md");
|
|
34973
35121
|
const summary = findSession(input.cwd, sessionId);
|
|
34974
35122
|
if (summary === undefined || input.sourceRef !== sessionEvidenceRef(input.workspaceId, summary.id)) {
|
|
34975
35123
|
throw new SessionWrapUpError("session_not_found", `no session matching "${input.sourceRef}" in this project \u2014 use \`keryx sessions list\``);
|
|
@@ -34986,7 +35134,7 @@ async function resolveSessionWrapUp(input) {
|
|
|
34986
35134
|
throw new SessionWrapUpError("session_unreadable", `session "${summary.id}" could not be read: ${cause.message}`);
|
|
34987
35135
|
}
|
|
34988
35136
|
const relPath = sessionEvidenceRef(input.workspaceId, summary.id).slice(2);
|
|
34989
|
-
const evidenceDir =
|
|
35137
|
+
const evidenceDir = path108.dirname(relPath);
|
|
34990
35138
|
const slate = await readSessionSlate(input.cwd, summary.id);
|
|
34991
35139
|
const diff = await gitDiff(input.cwd);
|
|
34992
35140
|
const diffBody = diff.kind === "measured" ? diff.text : unmeasurableDiffBody(diff.detail);
|
|
@@ -35008,23 +35156,23 @@ async function resolveSessionWrapUp(input) {
|
|
|
35008
35156
|
""
|
|
35009
35157
|
].join(`
|
|
35010
35158
|
`);
|
|
35011
|
-
const wrapUpRelPath =
|
|
35012
|
-
const diffRelPath =
|
|
35013
|
-
const noticeRelPath =
|
|
35159
|
+
const wrapUpRelPath = path108.join(evidenceDir, `${summary.id}.wrap-up.md`);
|
|
35160
|
+
const diffRelPath = path108.join(evidenceDir, `${summary.id}.diff.txt`);
|
|
35161
|
+
const noticeRelPath = path108.join(evidenceDir, `${summary.id}.redaction.md`);
|
|
35014
35162
|
const floor = await applyEvidenceRedactionFloor(input.cwd, [
|
|
35015
|
-
{ name:
|
|
35016
|
-
{ name:
|
|
35017
|
-
{ name:
|
|
35163
|
+
{ name: path108.basename(relPath), content: markdown, path: relPath, source: "generated" },
|
|
35164
|
+
{ name: path108.basename(wrapUpRelPath), content: wrapUpMarkdown, path: wrapUpRelPath, source: "generated" },
|
|
35165
|
+
{ name: path108.basename(diffRelPath), content: diffBody, path: diffRelPath, source: "tool-output" }
|
|
35018
35166
|
]);
|
|
35019
35167
|
if (!floor.ok)
|
|
35020
35168
|
throw new SessionWrapUpError("security_denied", floor.reason);
|
|
35021
35169
|
const [safeSession, safeWrapUp, safeDiff] = floor.bodies;
|
|
35022
|
-
await mkdir32(
|
|
35023
|
-
await writeFile21(
|
|
35024
|
-
await writeFile21(
|
|
35025
|
-
await writeFile21(
|
|
35170
|
+
await mkdir32(path108.join(input.cwd, evidenceDir), { recursive: true });
|
|
35171
|
+
await writeFile21(path108.join(input.cwd, relPath), safeSession.content, "utf8");
|
|
35172
|
+
await writeFile21(path108.join(input.cwd, wrapUpRelPath), safeWrapUp.content, "utf8");
|
|
35173
|
+
await writeFile21(path108.join(input.cwd, diffRelPath), safeDiff.content, "utf8");
|
|
35026
35174
|
if (floor.notice !== undefined)
|
|
35027
|
-
await writeFile21(
|
|
35175
|
+
await writeFile21(path108.join(input.cwd, noticeRelPath), floor.notice, "utf8");
|
|
35028
35176
|
const observedAt = now().toISOString();
|
|
35029
35177
|
const evidence = [
|
|
35030
35178
|
{ kind: "wrap-up", uri: `./${wrapUpRelPath}`, revision: createHash25("sha256").update(safeWrapUp.content).digest("hex"), observedAt },
|
|
@@ -35047,13 +35195,13 @@ async function resolveSessionWrapUp(input) {
|
|
|
35047
35195
|
init_fs();
|
|
35048
35196
|
import { createHash as createHash26, randomBytes as randomBytes5 } from "crypto";
|
|
35049
35197
|
import { readFile as readFile52 } from "fs/promises";
|
|
35050
|
-
import
|
|
35198
|
+
import path109 from "path";
|
|
35051
35199
|
var CONFIRM_TOKEN_TTL_MS = 2 * 60000;
|
|
35052
35200
|
function confirmTokenPath2(cwd, workspaceId, proposalId) {
|
|
35053
|
-
return
|
|
35201
|
+
return path109.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.confirm-token.json`);
|
|
35054
35202
|
}
|
|
35055
35203
|
function confirmReceiptPath(cwd, workspaceId, proposalId, idempotencyKey) {
|
|
35056
|
-
return
|
|
35204
|
+
return path109.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${sha2565(idempotencyKey)}.confirm-receipt.json`);
|
|
35057
35205
|
}
|
|
35058
35206
|
function sha2565(text) {
|
|
35059
35207
|
return createHash26("sha256").update(text).digest("hex");
|
|
@@ -35094,21 +35242,21 @@ init_store();
|
|
|
35094
35242
|
init_config();
|
|
35095
35243
|
import { readFile as readFile54, readdir as readdir18 } from "fs/promises";
|
|
35096
35244
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
35097
|
-
import
|
|
35245
|
+
import path111 from "path";
|
|
35098
35246
|
|
|
35099
35247
|
// src/sac/proposal-evidence.ts
|
|
35100
35248
|
init_fs();
|
|
35101
35249
|
import { createHash as createHash27 } from "crypto";
|
|
35102
35250
|
import { readFile as readFile53, rm as rm8 } from "fs/promises";
|
|
35103
|
-
import
|
|
35251
|
+
import path110 from "path";
|
|
35104
35252
|
function proposalPath(cwd, workspaceId, proposalId) {
|
|
35105
|
-
return
|
|
35253
|
+
return path110.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
|
|
35106
35254
|
}
|
|
35107
35255
|
function ownerReceiptPath(cwd, owner, workspaceId, idempotencyKey) {
|
|
35108
|
-
return
|
|
35256
|
+
return path110.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-receipts`, `${idempotencyKey}.json`);
|
|
35109
35257
|
}
|
|
35110
35258
|
function proposalNotePath(cwd, workspaceId, proposalId) {
|
|
35111
|
-
return
|
|
35259
|
+
return path110.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.note.txt`);
|
|
35112
35260
|
}
|
|
35113
35261
|
async function readVerifiedProposalEvidence(cwd, workspaceId, proposalId) {
|
|
35114
35262
|
let proposal;
|
|
@@ -35122,7 +35270,7 @@ async function readVerifiedProposalEvidence(cwd, workspaceId, proposalId) {
|
|
|
35122
35270
|
return { ok: false, code: "no_evidence_to_write" };
|
|
35123
35271
|
let content;
|
|
35124
35272
|
try {
|
|
35125
|
-
content = await readFile53(
|
|
35273
|
+
content = await readFile53(path110.join(cwd, evidence.uri), "utf8");
|
|
35126
35274
|
} catch {
|
|
35127
35275
|
return { ok: false, code: "evidence_file_unreadable" };
|
|
35128
35276
|
}
|
|
@@ -35152,22 +35300,22 @@ function targetRelPath(targetRef) {
|
|
|
35152
35300
|
return targetRef.replace(/^\.\//, "");
|
|
35153
35301
|
}
|
|
35154
35302
|
function targetAbsolutePath(cwd, targetRef) {
|
|
35155
|
-
return
|
|
35303
|
+
return path110.join(cwd, ".metaproject", targetRelPath(targetRef));
|
|
35156
35304
|
}
|
|
35157
35305
|
function targetKey(targetRef) {
|
|
35158
35306
|
return digestOf2(targetRelPath(targetRef)).slice(0, 32);
|
|
35159
35307
|
}
|
|
35160
35308
|
function ownerTargetVersionPath(cwd, owner, workspaceId, targetRef) {
|
|
35161
|
-
return
|
|
35309
|
+
return path110.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-target-versions`, `${targetKey(targetRef)}.json`);
|
|
35162
35310
|
}
|
|
35163
35311
|
function ownerTargetLockPath(cwd, owner, targetRef) {
|
|
35164
|
-
return
|
|
35312
|
+
return path110.join(cwd, ".metaproject", "data", "sac", "target-locks", owner, `${targetKey(targetRef)}.lock`);
|
|
35165
35313
|
}
|
|
35166
35314
|
function ownerStagingDir(cwd, owner, workspaceId, idempotencyKey) {
|
|
35167
|
-
return
|
|
35315
|
+
return path110.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-staging`, digestOf2(idempotencyKey).slice(0, 32));
|
|
35168
35316
|
}
|
|
35169
35317
|
function ownerConflictDir(cwd, owner, workspaceId, idempotencyKey) {
|
|
35170
|
-
return
|
|
35318
|
+
return path110.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-conflicts`, digestOf2(idempotencyKey).slice(0, 32));
|
|
35171
35319
|
}
|
|
35172
35320
|
async function readJson2(file) {
|
|
35173
35321
|
try {
|
|
@@ -35238,7 +35386,7 @@ async function applyGuardedTargetWrite(input) {
|
|
|
35238
35386
|
staged: input.staged,
|
|
35239
35387
|
stagedAt: receipt.completedAt
|
|
35240
35388
|
};
|
|
35241
|
-
await writeFileAtomic(
|
|
35389
|
+
await writeFileAtomic(path110.join(ownerStagingDir(cwd, owner, intent.workspaceId, intent.idempotencyKey), "plan.json"), `${JSON.stringify(staged, null, 2)}
|
|
35242
35390
|
`);
|
|
35243
35391
|
const applied = await input.apply(input.staged);
|
|
35244
35392
|
if (!applied.ok) {
|
|
@@ -35264,15 +35412,15 @@ async function recoverStagedOwnerWrite(input) {
|
|
|
35264
35412
|
});
|
|
35265
35413
|
}
|
|
35266
35414
|
async function readStagedOwnerWrite(cwd, owner, workspaceId, idempotencyKey) {
|
|
35267
|
-
return readJson2(
|
|
35415
|
+
return readJson2(path110.join(ownerStagingDir(cwd, owner, workspaceId, idempotencyKey), "plan.json"));
|
|
35268
35416
|
}
|
|
35269
35417
|
async function recordConflict(input) {
|
|
35270
35418
|
const base = { targetRef: input.targetRef, expectedVersion: input.expectedVersion, currentVersion: input.currentVersion };
|
|
35271
35419
|
if (input.proposedContent === undefined)
|
|
35272
35420
|
return base;
|
|
35273
35421
|
const dir = ownerConflictDir(input.cwd, input.owner, input.intent.workspaceId, input.intent.idempotencyKey);
|
|
35274
|
-
await writeFileAtomic(
|
|
35275
|
-
const diffRef = `./workspaces/${input.intent.workspaceId}/${input.owner}-write-conflicts/${
|
|
35422
|
+
await writeFileAtomic(path110.join(dir, "proposed"), input.proposedContent);
|
|
35423
|
+
const diffRef = `./workspaces/${input.intent.workspaceId}/${input.owner}-write-conflicts/${path110.basename(dir)}/proposed`;
|
|
35276
35424
|
return { ...base, diffRef };
|
|
35277
35425
|
}
|
|
35278
35426
|
|
|
@@ -35322,7 +35470,7 @@ async function resolveWorkspaceModule(cwd, workspaceId) {
|
|
|
35322
35470
|
}
|
|
35323
35471
|
}
|
|
35324
35472
|
async function collectWikiDecisionEntries(cwd) {
|
|
35325
|
-
const dir =
|
|
35473
|
+
const dir = path111.join(cwd, ".metaproject", "wiki", "decisions");
|
|
35326
35474
|
let files;
|
|
35327
35475
|
try {
|
|
35328
35476
|
files = (await readdir18(dir)).filter((name) => name.endsWith(".md"));
|
|
@@ -35331,12 +35479,12 @@ async function collectWikiDecisionEntries(cwd) {
|
|
|
35331
35479
|
}
|
|
35332
35480
|
const entries = [];
|
|
35333
35481
|
for (const file of files) {
|
|
35334
|
-
const absolutePath =
|
|
35482
|
+
const absolutePath = path111.join(dir, file);
|
|
35335
35483
|
try {
|
|
35336
35484
|
const content = await readFile54(absolutePath, "utf8");
|
|
35337
35485
|
entries.push({
|
|
35338
35486
|
absolutePath,
|
|
35339
|
-
relativePath:
|
|
35487
|
+
relativePath: path111.posix.join("decisions", file),
|
|
35340
35488
|
type: extractHeaderField(content, "Type") ?? "decision",
|
|
35341
35489
|
title: extractTitle(content),
|
|
35342
35490
|
version: extractHeaderField(content, "Version") ?? null,
|
|
@@ -35558,7 +35706,7 @@ function createRealMemoryOwnerWriter(cwd, opts) {
|
|
|
35558
35706
|
init_fs();
|
|
35559
35707
|
init_guard();
|
|
35560
35708
|
import { readFile as readFile56 } from "fs/promises";
|
|
35561
|
-
import
|
|
35709
|
+
import path112 from "path";
|
|
35562
35710
|
function renderWrapUpDecisionPage(input) {
|
|
35563
35711
|
const note = input.note?.trim();
|
|
35564
35712
|
return `# ${input.title}
|
|
@@ -35599,14 +35747,14 @@ export is the source of truth for what actually happened.
|
|
|
35599
35747
|
`;
|
|
35600
35748
|
}
|
|
35601
35749
|
function wikiPageRelativePath(proposalId) {
|
|
35602
|
-
return
|
|
35750
|
+
return path112.posix.join("decisions", `sac-${proposalId}.md`);
|
|
35603
35751
|
}
|
|
35604
35752
|
function createRealWikiOwnerWriter(cwd, opts) {
|
|
35605
35753
|
const now = opts?.now ?? (() => new Date);
|
|
35606
35754
|
const applyStaged = async (staged) => {
|
|
35607
35755
|
const relativePath = staged.relativePath;
|
|
35608
35756
|
const content = staged.content;
|
|
35609
|
-
await writeFileAtomic(
|
|
35757
|
+
await writeFileAtomic(path112.join(cwd, ".metaproject", "wiki", relativePath), content);
|
|
35610
35758
|
return { ok: true };
|
|
35611
35759
|
};
|
|
35612
35760
|
return {
|
|
@@ -35675,10 +35823,10 @@ init_guard();
|
|
|
35675
35823
|
import { createHash as createHash28 } from "crypto";
|
|
35676
35824
|
import { homedir as homedir2 } from "os";
|
|
35677
35825
|
import { mkdir as mkdir33, readFile as readFile57, stat as stat14 } from "fs/promises";
|
|
35678
|
-
import
|
|
35826
|
+
import path113 from "path";
|
|
35679
35827
|
var VERSION = "0.1.0";
|
|
35680
35828
|
async function createProjectSkill(projectRoot, options) {
|
|
35681
|
-
const metaprojectRoot =
|
|
35829
|
+
const metaprojectRoot = path113.join(projectRoot, ".metaproject");
|
|
35682
35830
|
if (!await pathExists(metaprojectRoot)) {
|
|
35683
35831
|
throw new Error("Metaproject is not initialized. Run: keryx init");
|
|
35684
35832
|
}
|
|
@@ -35688,8 +35836,8 @@ async function createProjectSkill(projectRoot, options) {
|
|
|
35688
35836
|
const moduleName = slugify5(options.module ?? inferModule(options.target));
|
|
35689
35837
|
const skillName = slugify5(options.name ?? inferSkillName(options.target));
|
|
35690
35838
|
const format = options.format ?? "auto";
|
|
35691
|
-
const packageRoot =
|
|
35692
|
-
const relativeSkillPath = toPosix(
|
|
35839
|
+
const packageRoot = path113.join(metaprojectRoot, "project-skills", moduleName, skillName);
|
|
35840
|
+
const relativeSkillPath = toPosix(path113.relative(projectRoot, packageRoot));
|
|
35693
35841
|
const origin = options.origin ? options.originContent !== undefined ? {
|
|
35694
35842
|
ref: options.origin.trim(),
|
|
35695
35843
|
hash: hashOriginContent(options.originContent),
|
|
@@ -35699,7 +35847,7 @@ async function createProjectSkill(projectRoot, options) {
|
|
|
35699
35847
|
const warnings = collectWarnings(evidence, format);
|
|
35700
35848
|
const files = filesForPackage(packageRoot, format);
|
|
35701
35849
|
if (!options.dryRun) {
|
|
35702
|
-
await withFileLock(
|
|
35850
|
+
await withFileLock(path113.join(metaprojectRoot, "data", "gdskills", "project-skills.lock"), async () => {
|
|
35703
35851
|
await writeProjectSkillPackage({
|
|
35704
35852
|
projectRoot,
|
|
35705
35853
|
packageRoot,
|
|
@@ -35728,7 +35876,7 @@ async function createProjectSkill(projectRoot, options) {
|
|
|
35728
35876
|
name: skillName,
|
|
35729
35877
|
target: options.target,
|
|
35730
35878
|
skillPath: relativeSkillPath,
|
|
35731
|
-
files: files.map((filePath) => toPosix(
|
|
35879
|
+
files: files.map((filePath) => toPosix(path113.relative(projectRoot, filePath))),
|
|
35732
35880
|
warnings,
|
|
35733
35881
|
dryRun: options.dryRun === true
|
|
35734
35882
|
};
|
|
@@ -35737,9 +35885,9 @@ var MAX_SKILL_TARGET_LENGTH = 80;
|
|
|
35737
35885
|
function resolveOriginPath(ref, projectRoot) {
|
|
35738
35886
|
const trimmed = ref.trim();
|
|
35739
35887
|
if (trimmed === "~" || trimmed.startsWith("~/")) {
|
|
35740
|
-
return
|
|
35888
|
+
return path113.join(homedir2(), trimmed.slice(1));
|
|
35741
35889
|
}
|
|
35742
|
-
return
|
|
35890
|
+
return path113.resolve(projectRoot, trimmed);
|
|
35743
35891
|
}
|
|
35744
35892
|
function hashOriginContent(content) {
|
|
35745
35893
|
return `sha256:${createHash28("sha256").update(content).digest("hex")}`;
|
|
@@ -35777,32 +35925,32 @@ async function writeProjectSkillPackage({
|
|
|
35777
35925
|
}) {
|
|
35778
35926
|
const packageFormat = format === "single" ? "single" : "package";
|
|
35779
35927
|
const skillContent = renderProjectSkill({ moduleName, skillName, target, note, origin, evidence, packageFormat });
|
|
35780
|
-
const relativeSkillMdPath = toPosix(
|
|
35928
|
+
const relativeSkillMdPath = toPosix(path113.join(path113.relative(projectRoot, packageRoot), "SKILL.md"));
|
|
35781
35929
|
const guard = await guardOutput({ cwd: projectRoot, content: skillContent, target: "skill", source: "generated", path: relativeSkillMdPath });
|
|
35782
35930
|
const output = prepareOutputForPersistence(guard, skillContent);
|
|
35783
35931
|
if (!output.allowed) {
|
|
35784
35932
|
throw new Error(`Project skill blocked by the security gate: ${output.reason}`);
|
|
35785
35933
|
}
|
|
35786
35934
|
await mkdir33(packageRoot, { recursive: true });
|
|
35787
|
-
const skillPath =
|
|
35935
|
+
const skillPath = path113.join(packageRoot, "SKILL.md");
|
|
35788
35936
|
await writeFileAtomic(skillPath, output.content);
|
|
35789
|
-
const changelogPath =
|
|
35937
|
+
const changelogPath = path113.join(packageRoot, "skill-changelog.md");
|
|
35790
35938
|
if (!await pathExists(changelogPath)) {
|
|
35791
35939
|
await writeFileAtomic(changelogPath, renderSkillChangelog({ moduleName, skillName, target }));
|
|
35792
35940
|
}
|
|
35793
35941
|
if (packageFormat === "package") {
|
|
35794
|
-
await mkdir33(
|
|
35795
|
-
await mkdir33(
|
|
35796
|
-
await writeFileAtomic(
|
|
35797
|
-
await writeFileAtomic(
|
|
35798
|
-
await writeFileAtomic(
|
|
35942
|
+
await mkdir33(path113.join(packageRoot, "references"), { recursive: true });
|
|
35943
|
+
await mkdir33(path113.join(packageRoot, "templates"), { recursive: true });
|
|
35944
|
+
await writeFileAtomic(path113.join(packageRoot, "references", "context.md"), renderReferenceContext({ moduleName, skillName, target, evidence }));
|
|
35945
|
+
await writeFileAtomic(path113.join(packageRoot, "templates", "README.md"), renderTemplatesReadme({ moduleName, skillName }));
|
|
35946
|
+
await writeFileAtomic(path113.join(packageRoot, "verification.md"), renderVerification({ moduleName, skillName, evidence }));
|
|
35799
35947
|
}
|
|
35800
35948
|
}
|
|
35801
35949
|
async function collectEvidence(projectRoot, target) {
|
|
35802
|
-
const absoluteTarget =
|
|
35950
|
+
const absoluteTarget = path113.resolve(projectRoot, target);
|
|
35803
35951
|
const targetExists = await pathExists(absoluteTarget);
|
|
35804
35952
|
const targetKind = await classifyTarget(absoluteTarget, targetExists);
|
|
35805
|
-
const maybeRelativeTarget = targetExists ? toPosix(
|
|
35953
|
+
const maybeRelativeTarget = targetExists ? toPosix(path113.relative(projectRoot, absoluteTarget)) : undefined;
|
|
35806
35954
|
const graphArtifacts = await existingRelativePaths(projectRoot, [
|
|
35807
35955
|
".metaproject/data/gdgraph/artifacts/summary.md",
|
|
35808
35956
|
".metaproject/data/gdgraph/artifacts/module-map.json"
|
|
@@ -35832,7 +35980,7 @@ async function classifyTarget(absoluteTarget, targetExists) {
|
|
|
35832
35980
|
async function existingRelativePaths(projectRoot, candidates) {
|
|
35833
35981
|
const existing = [];
|
|
35834
35982
|
for (const candidate of candidates) {
|
|
35835
|
-
if (await pathExists(
|
|
35983
|
+
if (await pathExists(path113.join(projectRoot, candidate))) {
|
|
35836
35984
|
existing.push(candidate);
|
|
35837
35985
|
}
|
|
35838
35986
|
}
|
|
@@ -35859,17 +36007,17 @@ function collectWarnings(evidence, format) {
|
|
|
35859
36007
|
}
|
|
35860
36008
|
function filesForPackage(packageRoot, format) {
|
|
35861
36009
|
const base = [
|
|
35862
|
-
|
|
35863
|
-
|
|
36010
|
+
path113.join(packageRoot, "SKILL.md"),
|
|
36011
|
+
path113.join(packageRoot, "skill-changelog.md")
|
|
35864
36012
|
];
|
|
35865
36013
|
if (format === "single") {
|
|
35866
36014
|
return base;
|
|
35867
36015
|
}
|
|
35868
36016
|
return [
|
|
35869
36017
|
...base,
|
|
35870
|
-
|
|
35871
|
-
|
|
35872
|
-
|
|
36018
|
+
path113.join(packageRoot, "verification.md"),
|
|
36019
|
+
path113.join(packageRoot, "references", "context.md"),
|
|
36020
|
+
path113.join(packageRoot, "templates", "README.md")
|
|
35873
36021
|
];
|
|
35874
36022
|
}
|
|
35875
36023
|
function renderProjectSkill({
|
|
@@ -36097,7 +36245,7 @@ keryx skills verify ${moduleName}/${skillName}
|
|
|
36097
36245
|
`;
|
|
36098
36246
|
}
|
|
36099
36247
|
async function updateManifest(projectRoot, entry) {
|
|
36100
|
-
const manifestPath =
|
|
36248
|
+
const manifestPath = path113.join(projectRoot, ".metaproject", "metaproject.json");
|
|
36101
36249
|
const manifest = await readJsonFileOr(manifestPath, {});
|
|
36102
36250
|
manifest.modules ??= {};
|
|
36103
36251
|
manifest.modules.gdskills ??= {};
|
|
@@ -36111,8 +36259,8 @@ async function updateManifest(projectRoot, entry) {
|
|
|
36111
36259
|
`);
|
|
36112
36260
|
}
|
|
36113
36261
|
async function updateSkillsCatalog(projectRoot) {
|
|
36114
|
-
const manifestPath =
|
|
36115
|
-
const catalogPath =
|
|
36262
|
+
const manifestPath = path113.join(projectRoot, ".metaproject", "metaproject.json");
|
|
36263
|
+
const catalogPath = path113.join(projectRoot, ".metaproject", "skills", "catalog.md");
|
|
36116
36264
|
const manifest = await readJsonFileOr(manifestPath, {});
|
|
36117
36265
|
const registry = manifest.modules?.gdskills?.projectSkillRegistry ?? [];
|
|
36118
36266
|
const rows = registry.length > 0 ? registry.map((entry) => `| ${entry.module} | ${entry.name} | \`${entry.target}\` | ${entry.path}/SKILL.md |`).join(`
|
|
@@ -36152,7 +36300,7 @@ function inferModule(target) {
|
|
|
36152
36300
|
}
|
|
36153
36301
|
function inferSkillName(target) {
|
|
36154
36302
|
const normalized = target.trim().replace(/[#:]+/g, "/");
|
|
36155
|
-
const base =
|
|
36303
|
+
const base = path113.basename(normalized).replace(/\.[^.]+$/, "");
|
|
36156
36304
|
return base || "entity";
|
|
36157
36305
|
}
|
|
36158
36306
|
function slugify5(value) {
|
|
@@ -36255,7 +36403,7 @@ class ProposalLifecycleService {
|
|
|
36255
36403
|
now;
|
|
36256
36404
|
constructor(options) {
|
|
36257
36405
|
this.options = options;
|
|
36258
|
-
this.root =
|
|
36406
|
+
this.root = path114.resolve(options.workspaceRoot);
|
|
36259
36407
|
this.now = options.now ?? (() => new Date);
|
|
36260
36408
|
}
|
|
36261
36409
|
async create(input) {
|
|
@@ -36274,7 +36422,7 @@ class ProposalLifecycleService {
|
|
|
36274
36422
|
if (manifest.status === "archived")
|
|
36275
36423
|
throw new ProposalLifecycleError("guard_denied", "workspace is archived");
|
|
36276
36424
|
const file = this.proposalPath(workspaceId, proposal.id);
|
|
36277
|
-
await mkdir34(
|
|
36425
|
+
await mkdir34(path114.dirname(file), { recursive: true, mode: 448 });
|
|
36278
36426
|
return withFileLock(`${file}.lock`, async () => {
|
|
36279
36427
|
const consume = this.options.wrapUpAuthority.consume(input.wrapUp, { actor, workspaceId });
|
|
36280
36428
|
if (consume !== "ok")
|
|
@@ -36302,7 +36450,7 @@ class ProposalLifecycleService {
|
|
|
36302
36450
|
return this.options.workspaces.withAuthorizedActor({ actorContext: actor, workspaceId: input.workspaceId, action: "review", execute: async (manifest) => {
|
|
36303
36451
|
const proposal = await this.loadProposal(input.workspaceId, input.proposalId);
|
|
36304
36452
|
const ledger = this.ledgerPath(input.workspaceId);
|
|
36305
|
-
await mkdir34(
|
|
36453
|
+
await mkdir34(path114.dirname(ledger), { recursive: true, mode: 448 });
|
|
36306
36454
|
return withFileLock(`${ledger}.lock`, async () => {
|
|
36307
36455
|
const records = (await this.records(ledger)).filter((record) => record.proposalId === proposal.id);
|
|
36308
36456
|
const events = records.filter((record) => record.recordType === "proposal-transition");
|
|
@@ -36344,7 +36492,7 @@ class ProposalLifecycleService {
|
|
|
36344
36492
|
} });
|
|
36345
36493
|
}
|
|
36346
36494
|
async listProposedProposals(workspaceId) {
|
|
36347
|
-
const proposalsDir =
|
|
36495
|
+
const proposalsDir = path114.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals");
|
|
36348
36496
|
let entries;
|
|
36349
36497
|
try {
|
|
36350
36498
|
entries = (await readdir19(proposalsDir)).filter((name) => name.endsWith(".json"));
|
|
@@ -36356,7 +36504,7 @@ class ProposalLifecycleService {
|
|
|
36356
36504
|
const proposals = [];
|
|
36357
36505
|
for (const entry of entries) {
|
|
36358
36506
|
try {
|
|
36359
|
-
const parsed = JSON.parse(await readFile59(
|
|
36507
|
+
const parsed = JSON.parse(await readFile59(path114.join(proposalsDir, entry), "utf8"));
|
|
36360
36508
|
if (parsed.recordType === "proposal-created")
|
|
36361
36509
|
proposals.push(parsed);
|
|
36362
36510
|
} catch {}
|
|
@@ -36622,31 +36770,31 @@ class ProposalLifecycleService {
|
|
|
36622
36770
|
}
|
|
36623
36771
|
}
|
|
36624
36772
|
proposalPath(workspaceId, proposalId) {
|
|
36625
|
-
return
|
|
36773
|
+
return path114.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
|
|
36626
36774
|
}
|
|
36627
36775
|
decisionRef(proposalId, key) {
|
|
36628
36776
|
return `./proposals/${proposalId}.${hash(key)}.decision.json`;
|
|
36629
36777
|
}
|
|
36630
36778
|
decisionPath(workspaceId, proposalId, key) {
|
|
36631
|
-
return
|
|
36779
|
+
return path114.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.decision.json`);
|
|
36632
36780
|
}
|
|
36633
36781
|
approvalRef(proposalId, key) {
|
|
36634
36782
|
return `./proposals/${proposalId}.${hash(key)}.approval.json`;
|
|
36635
36783
|
}
|
|
36636
36784
|
approvalPath(workspaceId, proposalId, key) {
|
|
36637
|
-
return
|
|
36785
|
+
return path114.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.approval.json`);
|
|
36638
36786
|
}
|
|
36639
36787
|
writeResultPath(workspaceId, proposalId, key) {
|
|
36640
|
-
return
|
|
36788
|
+
return path114.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.write-result.json`);
|
|
36641
36789
|
}
|
|
36642
36790
|
intentRef(proposalId, key) {
|
|
36643
36791
|
return `./proposals/${proposalId}.${hash(key)}.write-intent.json`;
|
|
36644
36792
|
}
|
|
36645
36793
|
intentPath(workspaceId, proposalId, key) {
|
|
36646
|
-
return
|
|
36794
|
+
return path114.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.write-intent.json`);
|
|
36647
36795
|
}
|
|
36648
36796
|
attemptPath(workspaceId, proposalId, key) {
|
|
36649
|
-
return
|
|
36797
|
+
return path114.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.owner-write-attempt.json`);
|
|
36650
36798
|
}
|
|
36651
36799
|
async loadWriteResult(workspaceId, proposalId, key) {
|
|
36652
36800
|
try {
|
|
@@ -36673,7 +36821,7 @@ class ProposalLifecycleService {
|
|
|
36673
36821
|
}
|
|
36674
36822
|
}
|
|
36675
36823
|
ledgerPath(workspaceId) {
|
|
36676
|
-
return
|
|
36824
|
+
return path114.join(this.root, ".metaproject", "workspaces", workspaceId, "activity.jsonl");
|
|
36677
36825
|
}
|
|
36678
36826
|
timestamp() {
|
|
36679
36827
|
return this.now().toISOString();
|
|
@@ -36756,7 +36904,7 @@ function normalizeProposalLifecycleResult(value) {
|
|
|
36756
36904
|
// src/sac/collaboration-service.ts
|
|
36757
36905
|
import { appendFile as appendFile8, mkdir as mkdir35, readFile as readFile60 } from "fs/promises";
|
|
36758
36906
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
36759
|
-
import
|
|
36907
|
+
import path115 from "path";
|
|
36760
36908
|
class CollaborationServiceError extends Error {
|
|
36761
36909
|
code;
|
|
36762
36910
|
constructor(code, message) {
|
|
@@ -36771,7 +36919,7 @@ class CollaborationService {
|
|
|
36771
36919
|
this.input = input;
|
|
36772
36920
|
}
|
|
36773
36921
|
file(id) {
|
|
36774
|
-
return
|
|
36922
|
+
return path115.join(this.input.workspaceRoot, ".metaproject", "workspaces", id, "activity.jsonl");
|
|
36775
36923
|
}
|
|
36776
36924
|
async overview(input) {
|
|
36777
36925
|
const manifest = await this.input.workspaces.show(input);
|
|
@@ -36808,7 +36956,7 @@ class CollaborationService {
|
|
|
36808
36956
|
occurredAt: (this.input.now ?? (() => new Date))().toISOString(),
|
|
36809
36957
|
...suppliedHandoff ? { handoff: { ...suppliedHandoff, from: actor.subject } } : {}
|
|
36810
36958
|
});
|
|
36811
|
-
await mkdir35(
|
|
36959
|
+
await mkdir35(path115.dirname(this.file(manifest.id)), { recursive: true, mode: 448 });
|
|
36812
36960
|
await appendFile8(this.file(manifest.id), `${JSON.stringify(activity)}
|
|
36813
36961
|
`, { mode: 384 });
|
|
36814
36962
|
return normalizeCollaborationResult(activity);
|
|
@@ -36858,13 +37006,13 @@ function normalizeCollaborationResult(value) {
|
|
|
36858
37006
|
// src/session/external-slate.ts
|
|
36859
37007
|
init_fs();
|
|
36860
37008
|
import { mkdir as mkdir37, readdir as readdir20, readFile as readFile61 } from "fs/promises";
|
|
36861
|
-
import
|
|
37009
|
+
import path117 from "path";
|
|
36862
37010
|
|
|
36863
37011
|
// src/sac/machine-wrap-up.ts
|
|
36864
37012
|
init_fs();
|
|
36865
37013
|
import { createHash as createHash30, randomUUID as randomUUID10 } from "crypto";
|
|
36866
37014
|
import { mkdir as mkdir36 } from "fs/promises";
|
|
36867
|
-
import
|
|
37015
|
+
import path116 from "path";
|
|
36868
37016
|
|
|
36869
37017
|
// src/sac/workspace-resolve.ts
|
|
36870
37018
|
init_redact();
|
|
@@ -37005,11 +37153,11 @@ async function resolveMachineWrapUp(input) {
|
|
|
37005
37153
|
`;
|
|
37006
37154
|
const seedsJson = `${JSON.stringify(seedsForKind.map((seed) => ({ text: seed.text, source: describeSource(seed.source) })), null, 2)}
|
|
37007
37155
|
`;
|
|
37008
|
-
const evidenceRelBase =
|
|
37156
|
+
const evidenceRelBase = path116.posix.join(".metaproject", "workspaces", input.workspaceId, "machine-evidence");
|
|
37009
37157
|
const floor = await applyEvidenceRedactionFloor(input.cwd, [
|
|
37010
|
-
{ name: `${input.kind}.diff.txt`, content: diffBody, path:
|
|
37011
|
-
{ name: `${input.kind}.flow.json`, content: flowSnapshotJson, path:
|
|
37012
|
-
{ name: `${input.kind}.seeds.json`, content: seedsJson, path:
|
|
37158
|
+
{ name: `${input.kind}.diff.txt`, content: diffBody, path: path116.posix.join(evidenceRelBase, `${input.kind}.diff.txt`), source: "tool-output" },
|
|
37159
|
+
{ name: `${input.kind}.flow.json`, content: flowSnapshotJson, path: path116.posix.join(evidenceRelBase, `${input.kind}.flow.json`), source: "generated" },
|
|
37160
|
+
{ name: `${input.kind}.seeds.json`, content: seedsJson, path: path116.posix.join(evidenceRelBase, `${input.kind}.seeds.json`), source: "generated" }
|
|
37013
37161
|
]);
|
|
37014
37162
|
if (!floor.ok)
|
|
37015
37163
|
return { ok: false, code: "security_denied", detail: floor.reason };
|
|
@@ -37063,14 +37211,14 @@ ${safeSeeds.content}`;
|
|
|
37063
37211
|
}
|
|
37064
37212
|
summary = result.text.trim().length > 0 ? result.text.trim() : mechanicalSummary(summaryDiff, course);
|
|
37065
37213
|
}
|
|
37066
|
-
const evidenceDir =
|
|
37214
|
+
const evidenceDir = path116.join(input.cwd, ".metaproject", "workspaces", input.workspaceId, "machine-evidence");
|
|
37067
37215
|
await mkdir36(evidenceDir, { recursive: true });
|
|
37068
37216
|
const diffFile = `${input.kind}.${shortHash}.diff.txt`;
|
|
37069
37217
|
const flowFile = `${input.kind}.${shortHash}.flow.json`;
|
|
37070
37218
|
const seedsFile = `${input.kind}.${shortHash}.seeds.json`;
|
|
37071
|
-
await writeFileAtomic(
|
|
37072
|
-
await writeFileAtomic(
|
|
37073
|
-
await writeFileAtomic(
|
|
37219
|
+
await writeFileAtomic(path116.join(evidenceDir, diffFile), safeDiff.content);
|
|
37220
|
+
await writeFileAtomic(path116.join(evidenceDir, flowFile), safeFlow.content);
|
|
37221
|
+
await writeFileAtomic(path116.join(evidenceDir, seedsFile), safeSeeds.content);
|
|
37074
37222
|
const observedAt = now().toISOString();
|
|
37075
37223
|
const relBase = `./.metaproject/workspaces/${input.workspaceId}/machine-evidence`;
|
|
37076
37224
|
const evidence = [
|
|
@@ -37080,7 +37228,7 @@ ${safeSeeds.content}`;
|
|
|
37080
37228
|
];
|
|
37081
37229
|
if (floor.notice !== undefined) {
|
|
37082
37230
|
const noticeFile = `${input.kind}.${shortHash}.redaction.md`;
|
|
37083
|
-
await writeFileAtomic(
|
|
37231
|
+
await writeFileAtomic(path116.join(evidenceDir, noticeFile), floor.notice);
|
|
37084
37232
|
evidence.push({ kind: REDACTION_NOTICE_KIND, uri: `${relBase}/${noticeFile}`, revision: sha2566(floor.notice), observedAt });
|
|
37085
37233
|
}
|
|
37086
37234
|
return {
|
|
@@ -37099,18 +37247,18 @@ async function writeFlooredArchiveArtifact(params) {
|
|
|
37099
37247
|
{
|
|
37100
37248
|
name: params.filename,
|
|
37101
37249
|
content: params.content,
|
|
37102
|
-
path:
|
|
37250
|
+
path: path116.posix.join("slate-archive", params.filename),
|
|
37103
37251
|
source: "generated"
|
|
37104
37252
|
}
|
|
37105
37253
|
]);
|
|
37106
37254
|
if (!floor.ok)
|
|
37107
37255
|
return { ok: false, code: "security_denied", detail: floor.reason };
|
|
37108
37256
|
const body = floor.bodies[0];
|
|
37109
|
-
const archiveDir =
|
|
37257
|
+
const archiveDir = path116.join(params.dir, "slate-archive");
|
|
37110
37258
|
await mkdir36(archiveDir, { recursive: true });
|
|
37111
|
-
await writeFileAtomic(
|
|
37259
|
+
await writeFileAtomic(path116.join(archiveDir, params.filename), body.content);
|
|
37112
37260
|
if (floor.notice !== undefined) {
|
|
37113
|
-
await writeFileAtomic(
|
|
37261
|
+
await writeFileAtomic(path116.join(archiveDir, `${params.filename}${ARCHIVE_REDACTION_NOTICE_SUFFIX}`), floor.notice);
|
|
37114
37262
|
}
|
|
37115
37263
|
return { ok: true, altered: body.altered };
|
|
37116
37264
|
}
|
|
@@ -37146,9 +37294,9 @@ async function writeWrapUpOutcomeArtifact(cwd, dir, trigger, now, groups) {
|
|
|
37146
37294
|
return;
|
|
37147
37295
|
const refusalIso = now().toISOString();
|
|
37148
37296
|
const refusalFilename = `${refusalIso.replace(/[:.]/g, "-")}-wrap-up-outcome.json`;
|
|
37149
|
-
const archiveDir =
|
|
37297
|
+
const archiveDir = path116.join(dir, "slate-archive");
|
|
37150
37298
|
await mkdir36(archiveDir, { recursive: true });
|
|
37151
|
-
await writeFileAtomic(
|
|
37299
|
+
await writeFileAtomic(path116.join(archiveDir, refusalFilename), `${JSON.stringify({
|
|
37152
37300
|
recordType: "wrap-up-outcome",
|
|
37153
37301
|
trigger,
|
|
37154
37302
|
generatedAt: refusalIso,
|
|
@@ -37284,7 +37432,7 @@ async function runWrapUp(input) {
|
|
|
37284
37432
|
|
|
37285
37433
|
// src/session/external-slate.ts
|
|
37286
37434
|
function externalSlatesDir(cwd) {
|
|
37287
|
-
return
|
|
37435
|
+
return path117.join(cwd, ".keryx", "external-slates");
|
|
37288
37436
|
}
|
|
37289
37437
|
var EXTERNAL_SESSION_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
|
|
37290
37438
|
function assertValidExternalSessionId(externalSessionId) {
|
|
@@ -37294,14 +37442,14 @@ function assertValidExternalSessionId(externalSessionId) {
|
|
|
37294
37442
|
}
|
|
37295
37443
|
function externalSlatePath(cwd, externalSessionId) {
|
|
37296
37444
|
assertValidExternalSessionId(externalSessionId);
|
|
37297
|
-
return
|
|
37445
|
+
return path117.join(externalSlatesDir(cwd), `${externalSessionId}.json`);
|
|
37298
37446
|
}
|
|
37299
37447
|
function externalSlateLockPath(cwd, externalSessionId) {
|
|
37300
37448
|
return `${externalSlatePath(cwd, externalSessionId)}.lock`;
|
|
37301
37449
|
}
|
|
37302
37450
|
function externalSlateEvidenceDir(cwd, externalSessionId) {
|
|
37303
37451
|
assertValidExternalSessionId(externalSessionId);
|
|
37304
|
-
return
|
|
37452
|
+
return path117.join(externalSlatesDir(cwd), externalSessionId);
|
|
37305
37453
|
}
|
|
37306
37454
|
async function readExternalSlate(cwd, externalSessionId) {
|
|
37307
37455
|
try {
|
|
@@ -37407,12 +37555,12 @@ __export(exports_service10, {
|
|
|
37407
37555
|
runDoctor: () => runDoctor,
|
|
37408
37556
|
runValidate: () => runValidate
|
|
37409
37557
|
});
|
|
37410
|
-
import
|
|
37558
|
+
import path120 from "path";
|
|
37411
37559
|
import { readFile as readFile64 } from "fs/promises";
|
|
37412
37560
|
|
|
37413
37561
|
// src/standard/validate.ts
|
|
37414
37562
|
init_fs();
|
|
37415
|
-
import
|
|
37563
|
+
import path119 from "path";
|
|
37416
37564
|
import { readFile as readFile63 } from "fs/promises";
|
|
37417
37565
|
|
|
37418
37566
|
// src/standard/schemas.ts
|
|
@@ -37541,7 +37689,7 @@ var SCHEMA_REGISTRY2 = {
|
|
|
37541
37689
|
|
|
37542
37690
|
// src/standard/profiles.ts
|
|
37543
37691
|
init_fs();
|
|
37544
|
-
import
|
|
37692
|
+
import path118 from "path";
|
|
37545
37693
|
import { readFile as readFile62 } from "fs/promises";
|
|
37546
37694
|
var AGENT_MODULES = ["gdgraph", "gdctx", "gdskills", "gdwiki", "memory"];
|
|
37547
37695
|
var CI_MODULES = ["health", "testing"];
|
|
@@ -37553,7 +37701,7 @@ function enabledModuleKeys(manifest) {
|
|
|
37553
37701
|
}
|
|
37554
37702
|
async function rootEntrypointLinksIndex(cwd) {
|
|
37555
37703
|
for (const name of ROOT_ENTRYPOINTS) {
|
|
37556
|
-
const filePath =
|
|
37704
|
+
const filePath = path118.join(cwd, name);
|
|
37557
37705
|
if (!await pathExists(filePath)) {
|
|
37558
37706
|
continue;
|
|
37559
37707
|
}
|
|
@@ -37565,16 +37713,16 @@ async function rootEntrypointLinksIndex(cwd) {
|
|
|
37565
37713
|
return false;
|
|
37566
37714
|
}
|
|
37567
37715
|
async function minimalSatisfied(cwd) {
|
|
37568
|
-
const metaprojectRoot =
|
|
37716
|
+
const metaprojectRoot = path118.join(cwd, ".metaproject");
|
|
37569
37717
|
const requiredFiles = ["index.md", "README.md", "metaproject.json"];
|
|
37570
37718
|
const requiredDirs = ["modules", "rules", "skills", "data"];
|
|
37571
37719
|
for (const file of requiredFiles) {
|
|
37572
|
-
if (!await pathExists(
|
|
37720
|
+
if (!await pathExists(path118.join(metaprojectRoot, file))) {
|
|
37573
37721
|
return false;
|
|
37574
37722
|
}
|
|
37575
37723
|
}
|
|
37576
37724
|
for (const dir of requiredDirs) {
|
|
37577
|
-
if (!await pathExists(
|
|
37725
|
+
if (!await pathExists(path118.join(metaprojectRoot, dir))) {
|
|
37578
37726
|
return false;
|
|
37579
37727
|
}
|
|
37580
37728
|
}
|
|
@@ -37587,7 +37735,7 @@ async function ciSatisfied(cwd, manifest) {
|
|
|
37587
37735
|
return false;
|
|
37588
37736
|
}
|
|
37589
37737
|
for (const key of ciModules) {
|
|
37590
|
-
if (await pathExists(
|
|
37738
|
+
if (await pathExists(path118.join(cwd, ".metaproject", "data", key, "artifacts"))) {
|
|
37591
37739
|
return true;
|
|
37592
37740
|
}
|
|
37593
37741
|
}
|
|
@@ -37600,7 +37748,7 @@ async function evaluateProfiles(cwd, manifest) {
|
|
|
37600
37748
|
satisfied.push("minimal");
|
|
37601
37749
|
}
|
|
37602
37750
|
const hasAgentModule = AGENT_MODULES.some((key) => new Set(enabledModuleKeys(manifest)).has(key));
|
|
37603
|
-
const agent = minimal && hasAgentModule && await rootEntrypointLinksIndex(cwd) && await pathExists(
|
|
37751
|
+
const agent = minimal && hasAgentModule && await rootEntrypointLinksIndex(cwd) && await pathExists(path118.join(cwd, ".metaproject", "rules"));
|
|
37604
37752
|
if (agent) {
|
|
37605
37753
|
satisfied.push("agent");
|
|
37606
37754
|
}
|
|
@@ -37770,20 +37918,20 @@ var MANIFEST_TOP_LEVEL_SCHEMA = {
|
|
|
37770
37918
|
async function validateWorkspace2(cwd) {
|
|
37771
37919
|
const errors = [];
|
|
37772
37920
|
const warnings = [];
|
|
37773
|
-
const metaprojectRoot =
|
|
37921
|
+
const metaprojectRoot = path119.join(cwd, ".metaproject");
|
|
37774
37922
|
const requiredFiles = ["index.md", "README.md", "metaproject.json"];
|
|
37775
37923
|
for (const file of requiredFiles) {
|
|
37776
|
-
if (!await pathExists(
|
|
37924
|
+
if (!await pathExists(path119.join(metaprojectRoot, file))) {
|
|
37777
37925
|
errors.push(issue("missing-required-file", `Required file .metaproject/${file} is missing`, `Run \`keryx init\` to scaffold .metaproject/${file}.`));
|
|
37778
37926
|
}
|
|
37779
37927
|
}
|
|
37780
37928
|
const requiredDirs = ["modules", "rules", "skills", "data"];
|
|
37781
37929
|
for (const dir of requiredDirs) {
|
|
37782
|
-
if (!await pathExists(
|
|
37930
|
+
if (!await pathExists(path119.join(metaprojectRoot, dir))) {
|
|
37783
37931
|
errors.push(issue("missing-required-dir", `Required directory .metaproject/${dir}/ is missing`, `Run \`keryx init\` to create .metaproject/${dir}/.`));
|
|
37784
37932
|
}
|
|
37785
37933
|
}
|
|
37786
|
-
const manifestPath =
|
|
37934
|
+
const manifestPath = path119.join(metaprojectRoot, "metaproject.json");
|
|
37787
37935
|
if (!await pathExists(manifestPath)) {
|
|
37788
37936
|
return { ok: errors.length === 0, errors, warnings };
|
|
37789
37937
|
}
|
|
@@ -37815,7 +37963,7 @@ async function validateWorkspace2(cwd) {
|
|
|
37815
37963
|
if (typeof value !== "string") {
|
|
37816
37964
|
continue;
|
|
37817
37965
|
}
|
|
37818
|
-
if (!await pathExists(
|
|
37966
|
+
if (!await pathExists(path119.join(cwd, value))) {
|
|
37819
37967
|
errors.push(issue("missing-declared-path", `Declared path paths.${key} -> ${value} does not exist`, `Create ${value} or remove paths.${key} from metaproject.json.`));
|
|
37820
37968
|
}
|
|
37821
37969
|
}
|
|
@@ -37825,7 +37973,7 @@ async function validateWorkspace2(cwd) {
|
|
|
37825
37973
|
continue;
|
|
37826
37974
|
}
|
|
37827
37975
|
if (typeof entry.manifest === "string") {
|
|
37828
|
-
if (!await pathExists(
|
|
37976
|
+
if (!await pathExists(path119.join(cwd, entry.manifest))) {
|
|
37829
37977
|
errors.push(issue("missing-module-manifest", `Enabled module "${key}" manifest ${entry.manifest} is missing`, `Create ${entry.manifest} or run \`keryx update\` to regenerate module manifests.`));
|
|
37830
37978
|
}
|
|
37831
37979
|
}
|
|
@@ -37834,14 +37982,14 @@ async function validateWorkspace2(cwd) {
|
|
|
37834
37982
|
if (typeof value !== "string") {
|
|
37835
37983
|
continue;
|
|
37836
37984
|
}
|
|
37837
|
-
if (!await pathExists(
|
|
37985
|
+
if (!await pathExists(path119.join(cwd, value))) {
|
|
37838
37986
|
const sink = field === "data" ? warnings : errors;
|
|
37839
37987
|
sink.push(issue("missing-module-path", `Module "${key}" declares ${String(field)} ${value}, which does not exist`, field === "data" ? `Run the module (e.g. \`keryx ${key} ...\`) to generate ${value}, or update modules.${key}.data in metaproject.json.` : `Create ${value} or update modules.${key}.${String(field)} in metaproject.json.`));
|
|
37840
37988
|
}
|
|
37841
37989
|
}
|
|
37842
37990
|
}
|
|
37843
37991
|
for (const name of ROOT_ENTRYPOINTS2) {
|
|
37844
|
-
const filePath =
|
|
37992
|
+
const filePath = path119.join(cwd, name);
|
|
37845
37993
|
if (!await pathExists(filePath)) {
|
|
37846
37994
|
continue;
|
|
37847
37995
|
}
|
|
@@ -38685,7 +38833,7 @@ async function runDoctor(cwd) {
|
|
|
38685
38833
|
return validateWorkspace2(cwd);
|
|
38686
38834
|
}
|
|
38687
38835
|
async function readManifest(cwd) {
|
|
38688
|
-
const manifestPath =
|
|
38836
|
+
const manifestPath = path120.join(cwd, ".metaproject", "metaproject.json");
|
|
38689
38837
|
if (!await pathExists(manifestPath)) {
|
|
38690
38838
|
throw new Error("Metaproject is not initialized (missing .metaproject/metaproject.json). Run `keryx init` first.");
|
|
38691
38839
|
}
|