@mrciphersmith/keryx 0.3.80 → 0.3.82
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/dist/cli.js +2248 -2114
- package/dist/core.js +550 -435
- package/package.json +1 -1
package/dist/core.js
CHANGED
|
@@ -22803,7 +22803,7 @@ var MARKER_VERSION = 1, BEGIN, END, REFERENCE_HEADING;
|
|
|
22803
22803
|
var init_managed_block = __esm(() => {
|
|
22804
22804
|
BEGIN = /^<!--\s*keryx:reference:begin\s+v=(\d+)(?:\s+hash=([0-9a-f]{64}))?\s*-->$/;
|
|
22805
22805
|
END = /^<!--\s*keryx:reference:end\s*-->$/;
|
|
22806
|
-
REFERENCE_HEADING = /^##\s+Reference
|
|
22806
|
+
REFERENCE_HEADING = /^##\s+Reference(?:\s*\([^)]*\))?\s*$/i;
|
|
22807
22807
|
});
|
|
22808
22808
|
|
|
22809
22809
|
// src/wiki/page-invariants.ts
|
|
@@ -23010,6 +23010,49 @@ ${entry}
|
|
|
23010
23010
|
return all.join(`
|
|
23011
23011
|
`);
|
|
23012
23012
|
}
|
|
23013
|
+
function repairVersionAndOrder(markdown) {
|
|
23014
|
+
let next = markdown;
|
|
23015
|
+
const all = next.split(`
|
|
23016
|
+
`);
|
|
23017
|
+
const range = changelogRange(all);
|
|
23018
|
+
if (range !== null) {
|
|
23019
|
+
const mask = fencedLines2(all);
|
|
23020
|
+
const starts = [];
|
|
23021
|
+
for (let index = range.heading + 1;index < range.end; index += 1) {
|
|
23022
|
+
if (!mask[index] && ENTRY_START.test(all[index]))
|
|
23023
|
+
starts.push(index);
|
|
23024
|
+
}
|
|
23025
|
+
const chunks = starts.map((start, position) => {
|
|
23026
|
+
const end = position + 1 < starts.length ? starts[position + 1] : range.end;
|
|
23027
|
+
const body = all.slice(start, end);
|
|
23028
|
+
while (body.length > 1 && body[body.length - 1].trim() === "")
|
|
23029
|
+
body.pop();
|
|
23030
|
+
return { body, version: ENTRY_VERSION.exec(body[0])?.[1] ?? null };
|
|
23031
|
+
});
|
|
23032
|
+
const ordered = chunks.every((chunk) => chunk.version !== null) ? [...chunks].sort((left, right) => compareVersions(right.version, left.version)) : chunks;
|
|
23033
|
+
if (ordered.some((chunk, index) => chunk !== chunks[index])) {
|
|
23034
|
+
const spaced = starts.length > 1 && all[starts[1] - 1].trim() === "";
|
|
23035
|
+
const rebuilt = [];
|
|
23036
|
+
ordered.forEach((chunk, index) => {
|
|
23037
|
+
if (index > 0 && spaced)
|
|
23038
|
+
rebuilt.push("");
|
|
23039
|
+
rebuilt.push(...chunk.body);
|
|
23040
|
+
});
|
|
23041
|
+
let tail = range.end;
|
|
23042
|
+
while (tail > starts[0] && all[tail - 1].trim() === "")
|
|
23043
|
+
tail -= 1;
|
|
23044
|
+
all.splice(starts[0], tail - starts[0], ...rebuilt);
|
|
23045
|
+
next = all.join(`
|
|
23046
|
+
`);
|
|
23047
|
+
}
|
|
23048
|
+
}
|
|
23049
|
+
const version = pageVersion(next);
|
|
23050
|
+
const newest = newestChangelogVersion(parseChangelog(next));
|
|
23051
|
+
if (version !== null && newest !== null && compareVersions(version, newest) < 0) {
|
|
23052
|
+
next = setPageVersion(next, newest);
|
|
23053
|
+
}
|
|
23054
|
+
return next;
|
|
23055
|
+
}
|
|
23013
23056
|
function sectionsOf(markdown) {
|
|
23014
23057
|
const all = lines2(markdown);
|
|
23015
23058
|
const mask = fencedLines2(all);
|
|
@@ -23095,6 +23138,8 @@ function withAddedLines(fresh, existingBody) {
|
|
|
23095
23138
|
return false;
|
|
23096
23139
|
if (/^[-*]\s+\[Module [^\]]+\]\([^)]+\.md\)$/.test(text))
|
|
23097
23140
|
return false;
|
|
23141
|
+
if (/^[-*]\s+`[^`]+`\s+\(no wiki page\)$/.test(text))
|
|
23142
|
+
return false;
|
|
23098
23143
|
if (/^graph-derived\b/i.test(text))
|
|
23099
23144
|
return false;
|
|
23100
23145
|
return !freshText.includes(text);
|
|
@@ -23155,10 +23200,11 @@ ${replacement.lines.join(`
|
|
|
23155
23200
|
`);
|
|
23156
23201
|
}
|
|
23157
23202
|
}
|
|
23203
|
+
const repaired = repairVersionAndOrder(next);
|
|
23158
23204
|
if (next === source)
|
|
23159
|
-
return existing;
|
|
23160
|
-
const version = nextPageVersion(
|
|
23161
|
-
return inEolOf(existing, prependChangelogEntry(setPageVersion(
|
|
23205
|
+
return repaired === source ? existing : inEolOf(existing, repaired);
|
|
23206
|
+
const version = nextPageVersion(repaired);
|
|
23207
|
+
return inEolOf(existing, prependChangelogEntry(setPageVersion(repaired, version), `- ${version} - ${entryNote}`));
|
|
23162
23208
|
}
|
|
23163
23209
|
var CHANGELOG_HEADING, SECTION_HEADING, H2, ENTRY_START, ENTRY_VERSION, LEGACY_META_KEYS;
|
|
23164
23210
|
var init_page_invariants = __esm(() => {
|
|
@@ -23182,6 +23228,55 @@ var init_page_invariants = __esm(() => {
|
|
|
23182
23228
|
]);
|
|
23183
23229
|
});
|
|
23184
23230
|
|
|
23231
|
+
// src/wiki/readme-links.ts
|
|
23232
|
+
import path76 from "path";
|
|
23233
|
+
function rewriteReadmeLinks(text, readmeDir, pageLink) {
|
|
23234
|
+
return text.replace(MARKDOWN_LINK, (whole, bang, label, target) => {
|
|
23235
|
+
if (target === "" || HAS_SCHEME.test(target)) {
|
|
23236
|
+
return whole;
|
|
23237
|
+
}
|
|
23238
|
+
const filePart = target.split(/[#?]/)[0] ?? "";
|
|
23239
|
+
if (filePart === "") {
|
|
23240
|
+
return label;
|
|
23241
|
+
}
|
|
23242
|
+
const resolved = path76.posix.normalize(filePart.startsWith("/") ? filePart.replace(/^\/+/, "") : path76.posix.join(readmeDir, filePart));
|
|
23243
|
+
const codePath = resolved.replace(/\/+$/, "");
|
|
23244
|
+
if (codePath === "" || codePath === "." || codePath === ".." || codePath.startsWith("../")) {
|
|
23245
|
+
return label;
|
|
23246
|
+
}
|
|
23247
|
+
const named = label.length > 0 ? `${label} (\`${codePath}\`)` : `\`${codePath}\``;
|
|
23248
|
+
if (bang === "!") {
|
|
23249
|
+
return named;
|
|
23250
|
+
}
|
|
23251
|
+
const moduleName = moduleOfTarget(filePart, codePath);
|
|
23252
|
+
const page = moduleName === null ? null : pageLink(moduleName);
|
|
23253
|
+
return page === null ? named : `[${label.length > 0 ? label : moduleName}](${page})`;
|
|
23254
|
+
});
|
|
23255
|
+
}
|
|
23256
|
+
function moduleOfTarget(filePart, codePath) {
|
|
23257
|
+
const base = path76.posix.basename(codePath);
|
|
23258
|
+
if (filePart.endsWith("/") || !/\.[A-Za-z0-9]+$/.test(base)) {
|
|
23259
|
+
return codePath;
|
|
23260
|
+
}
|
|
23261
|
+
if (DOC_ENTRY.test(base)) {
|
|
23262
|
+
const dir = path76.posix.dirname(codePath);
|
|
23263
|
+
return dir === "." ? null : dir;
|
|
23264
|
+
}
|
|
23265
|
+
return null;
|
|
23266
|
+
}
|
|
23267
|
+
function truncateMarkdown(text, max) {
|
|
23268
|
+
if (text.length <= max) {
|
|
23269
|
+
return text;
|
|
23270
|
+
}
|
|
23271
|
+
return text.slice(0, max).replace(/\s*!?\[[^\]]*$|\s*!?\[[^\]]*\]\([^)]*$/, "").trimEnd();
|
|
23272
|
+
}
|
|
23273
|
+
var MARKDOWN_LINK, HAS_SCHEME, DOC_ENTRY;
|
|
23274
|
+
var init_readme_links = __esm(() => {
|
|
23275
|
+
MARKDOWN_LINK = /(!?)\[([^[\]]*)\]\(\s*<?([^)\s>]*)>?(?:\s+(?:"[^"]*"|'[^']*'))?\s*\)/g;
|
|
23276
|
+
HAS_SCHEME = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
|
|
23277
|
+
DOC_ENTRY = /^(?:readme|index)\.(?:md|mdx)$/i;
|
|
23278
|
+
});
|
|
23279
|
+
|
|
23185
23280
|
// src/wiki/think-tags.ts
|
|
23186
23281
|
function maskCodeRegions(text) {
|
|
23187
23282
|
const maskMatch = (m) => "\x00".repeat(m.length);
|
|
@@ -23570,15 +23665,15 @@ __export(exports_service4, {
|
|
|
23570
23665
|
import { spawn as spawn3 } from "child_process";
|
|
23571
23666
|
import { createHash as createHash15 } from "crypto";
|
|
23572
23667
|
import { mkdir as mkdir20, readFile as readFile39, readdir as readdir13, writeFile as writeFile14 } from "fs/promises";
|
|
23573
|
-
import
|
|
23668
|
+
import path77 from "path";
|
|
23574
23669
|
function wikiRootPath3(cwd) {
|
|
23575
|
-
return
|
|
23670
|
+
return path77.join(cwd, ".metaproject", "wiki");
|
|
23576
23671
|
}
|
|
23577
23672
|
function dataRootPath(cwd) {
|
|
23578
|
-
return
|
|
23673
|
+
return path77.join(cwd, ".metaproject", "data", "gdwiki");
|
|
23579
23674
|
}
|
|
23580
23675
|
function linkCheckReportPath(cwd) {
|
|
23581
|
-
return
|
|
23676
|
+
return path77.join(dataRootPath(cwd), "link-check", "latest.md");
|
|
23582
23677
|
}
|
|
23583
23678
|
async function wikiStatus(cwd) {
|
|
23584
23679
|
const root = wikiRootPath3(cwd);
|
|
@@ -23586,7 +23681,7 @@ async function wikiStatus(cwd) {
|
|
|
23586
23681
|
const pages = enabled ? await collectPages(cwd) : [];
|
|
23587
23682
|
return {
|
|
23588
23683
|
enabled,
|
|
23589
|
-
wikiRoot:
|
|
23684
|
+
wikiRoot: path77.relative(cwd, root),
|
|
23590
23685
|
totalPages: pages.length,
|
|
23591
23686
|
countsByType: WIKI_PAGE_TYPES.map(({ type }) => ({
|
|
23592
23687
|
type,
|
|
@@ -23617,9 +23712,9 @@ async function wikiCreatePage(input) {
|
|
|
23617
23712
|
if (!/^[a-z0-9][a-z0-9-]*$/.test(input.slug)) {
|
|
23618
23713
|
throw new Error(`Invalid slug: ${input.slug}. Use lowercase letters, digits, and hyphens.`);
|
|
23619
23714
|
}
|
|
23620
|
-
const dir =
|
|
23621
|
-
const filePath =
|
|
23622
|
-
const relativePath =
|
|
23715
|
+
const dir = path77.join(wikiRootPath3(input.cwd), typeConfig.folder);
|
|
23716
|
+
const filePath = path77.join(dir, `${input.slug}.md`);
|
|
23717
|
+
const relativePath = path77.relative(input.cwd, filePath);
|
|
23623
23718
|
if (await pathExists(filePath) && !input.force) {
|
|
23624
23719
|
throw new Error(`Page already exists: ${relativePath}. Use --force to overwrite.`);
|
|
23625
23720
|
}
|
|
@@ -23631,7 +23726,7 @@ async function wikiCreatePage(input) {
|
|
|
23631
23726
|
}
|
|
23632
23727
|
async function wikiGenerateIndex(cwd, history) {
|
|
23633
23728
|
const root = wikiRootPath3(cwd);
|
|
23634
|
-
const indexPath =
|
|
23729
|
+
const indexPath = path77.join(root, "index.md");
|
|
23635
23730
|
const pages = await collectPages(cwd);
|
|
23636
23731
|
const generatedAt = new Date().toISOString();
|
|
23637
23732
|
const managedBlock = `${WIKI_INDEX_BEGIN}
|
|
@@ -23648,7 +23743,7 @@ ${managedBlock}
|
|
|
23648
23743
|
`;
|
|
23649
23744
|
await writeWikiPage(history ?? await openWikiWriteContext(cwd, "wiki index"), indexPath, next);
|
|
23650
23745
|
return {
|
|
23651
|
-
path:
|
|
23746
|
+
path: path77.relative(cwd, indexPath),
|
|
23652
23747
|
pageCount: pages.length,
|
|
23653
23748
|
generatedAt
|
|
23654
23749
|
};
|
|
@@ -23656,13 +23751,13 @@ ${managedBlock}
|
|
|
23656
23751
|
async function wikiCheckLinks(cwd) {
|
|
23657
23752
|
const root = wikiRootPath3(cwd);
|
|
23658
23753
|
const allFiles = await pathExists(root) ? await walkMarkdown(root) : [];
|
|
23659
|
-
const files = allFiles.filter((absolutePath) => !
|
|
23754
|
+
const files = allFiles.filter((absolutePath) => !path77.relative(root, absolutePath).startsWith(`templates${path77.sep}`));
|
|
23660
23755
|
const broken = [];
|
|
23661
23756
|
let checkedLinks = 0;
|
|
23662
23757
|
let skippedExternal = 0;
|
|
23663
23758
|
for (const absolutePath of files) {
|
|
23664
23759
|
const content = await readFile39(absolutePath, "utf8");
|
|
23665
|
-
const pageRelative =
|
|
23760
|
+
const pageRelative = path77.relative(cwd, absolutePath);
|
|
23666
23761
|
for (const target of extractLinkTargets(content)) {
|
|
23667
23762
|
if (EXTERNAL_LINK.test(target)) {
|
|
23668
23763
|
skippedExternal += 1;
|
|
@@ -23673,7 +23768,7 @@ async function wikiCheckLinks(cwd) {
|
|
|
23673
23768
|
continue;
|
|
23674
23769
|
}
|
|
23675
23770
|
checkedLinks += 1;
|
|
23676
|
-
const resolved =
|
|
23771
|
+
const resolved = path77.resolve(path77.dirname(absolutePath), filePart);
|
|
23677
23772
|
if (!await pathExists(resolved)) {
|
|
23678
23773
|
broken.push({
|
|
23679
23774
|
page: pageRelative,
|
|
@@ -23685,7 +23780,7 @@ async function wikiCheckLinks(cwd) {
|
|
|
23685
23780
|
}
|
|
23686
23781
|
const generatedAt = new Date().toISOString();
|
|
23687
23782
|
const reportPath = linkCheckReportPath(cwd);
|
|
23688
|
-
await mkdir20(
|
|
23783
|
+
await mkdir20(path77.dirname(reportPath), { recursive: true });
|
|
23689
23784
|
await writeFile14(reportPath, renderLinkCheckReport({
|
|
23690
23785
|
generatedAt,
|
|
23691
23786
|
checkedPages: files.length,
|
|
@@ -23694,7 +23789,7 @@ async function wikiCheckLinks(cwd) {
|
|
|
23694
23789
|
broken
|
|
23695
23790
|
}), "utf8");
|
|
23696
23791
|
return {
|
|
23697
|
-
reportPath:
|
|
23792
|
+
reportPath: path77.relative(cwd, reportPath),
|
|
23698
23793
|
checkedPages: files.length,
|
|
23699
23794
|
checkedLinks,
|
|
23700
23795
|
skippedExternal,
|
|
@@ -23745,7 +23840,7 @@ async function wikiValidate(cwd) {
|
|
|
23745
23840
|
}
|
|
23746
23841
|
if (await isIndexStale(cwd, pages)) {
|
|
23747
23842
|
issues.push({
|
|
23748
|
-
page:
|
|
23843
|
+
page: path77.join(path77.relative(cwd, wikiRootPath3(cwd)), "index.md"),
|
|
23749
23844
|
kind: "index",
|
|
23750
23845
|
message: "index out of date, run `keryx wiki index`"
|
|
23751
23846
|
});
|
|
@@ -23791,13 +23886,15 @@ function collectCommandLabel(input) {
|
|
|
23791
23886
|
return ["wiki collect", ...flags].join(" ");
|
|
23792
23887
|
}
|
|
23793
23888
|
async function wikiPruneOrphans(cwd, history) {
|
|
23794
|
-
const componentsDir =
|
|
23889
|
+
const componentsDir = path77.join(wikiRootPath3(cwd), "components");
|
|
23795
23890
|
if (!await pathExists(componentsDir)) {
|
|
23796
23891
|
return { pruned: [], orphanedAccepted: [] };
|
|
23797
23892
|
}
|
|
23798
|
-
const
|
|
23799
|
-
|
|
23800
|
-
|
|
23893
|
+
const counts = await moduleFileCounts(cwd);
|
|
23894
|
+
if (counts === undefined || counts.size === 0) {
|
|
23895
|
+
return { pruned: [], orphanedAccepted: [] };
|
|
23896
|
+
}
|
|
23897
|
+
const validSlugs = new Set([...counts].filter(([, files]) => files >= MIN_MODULE_FILES).map(([name]) => slugifyPath(name)));
|
|
23801
23898
|
const pruned = [];
|
|
23802
23899
|
const orphanedAccepted = [];
|
|
23803
23900
|
let run;
|
|
@@ -23809,32 +23906,37 @@ async function wikiPruneOrphans(cwd, history) {
|
|
|
23809
23906
|
if (validSlugs.has(slug)) {
|
|
23810
23907
|
continue;
|
|
23811
23908
|
}
|
|
23812
|
-
const filePath =
|
|
23909
|
+
const filePath = path77.join(componentsDir, entry);
|
|
23813
23910
|
const current = await readFile39(filePath, "utf8");
|
|
23814
23911
|
const isUnmodifiedDraft = /\nStatus:\s*draft\s*\n/.test(current) && current.includes("Generated by `keryx wiki collect`");
|
|
23815
23912
|
if (isUnmodifiedDraft) {
|
|
23816
23913
|
run ??= history ?? await openWikiWriteContext(cwd, "wiki prune");
|
|
23817
23914
|
await deleteWikiPage(run, filePath);
|
|
23818
|
-
pruned.push(
|
|
23915
|
+
pruned.push(path77.relative(cwd, filePath));
|
|
23819
23916
|
} else {
|
|
23820
|
-
orphanedAccepted.push(
|
|
23917
|
+
orphanedAccepted.push(path77.relative(cwd, filePath));
|
|
23821
23918
|
}
|
|
23822
23919
|
}
|
|
23823
23920
|
return { pruned, orphanedAccepted };
|
|
23824
23921
|
}
|
|
23825
23922
|
async function validModuleNames(cwd) {
|
|
23826
|
-
const
|
|
23923
|
+
const counts = await moduleFileCounts(cwd);
|
|
23924
|
+
return counts === undefined ? undefined : new Set(counts.keys());
|
|
23925
|
+
}
|
|
23926
|
+
async function moduleFileCounts(cwd) {
|
|
23927
|
+
const nodesPath = path77.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
|
|
23827
23928
|
if (!await pathExists(nodesPath)) {
|
|
23828
23929
|
return;
|
|
23829
23930
|
}
|
|
23830
|
-
const
|
|
23931
|
+
const counts = new Map;
|
|
23831
23932
|
for (const node of parseJsonl(await readFile39(nodesPath, "utf8"))) {
|
|
23832
23933
|
if (node.kind === "asset")
|
|
23833
23934
|
continue;
|
|
23834
23935
|
const nodePath = String(node.path ?? node.id ?? "unknown");
|
|
23835
|
-
|
|
23936
|
+
const moduleName = moduleNameFromProjectPath(nodePath);
|
|
23937
|
+
counts.set(moduleName, (counts.get(moduleName) ?? 0) + 1);
|
|
23836
23938
|
}
|
|
23837
|
-
return
|
|
23939
|
+
return counts;
|
|
23838
23940
|
}
|
|
23839
23941
|
async function wikiEvidence(input) {
|
|
23840
23942
|
const ask = await wikiAsk({
|
|
@@ -23893,9 +23995,9 @@ async function wikiEvidence(input) {
|
|
|
23893
23995
|
});
|
|
23894
23996
|
}
|
|
23895
23997
|
function resolveEvidenceScope(cwd, override) {
|
|
23896
|
-
const absolute =
|
|
23998
|
+
const absolute = path77.resolve(cwd);
|
|
23897
23999
|
return {
|
|
23898
|
-
projectId: override?.projectId ?? (
|
|
24000
|
+
projectId: override?.projectId ?? (path77.basename(absolute) || "project"),
|
|
23899
24001
|
checkoutId: override?.checkoutId ?? `checkout:${createHash15("sha256").update(absolute).digest("hex").slice(0, 16)}`,
|
|
23900
24002
|
...override?.workspaceId ? { workspaceId: override.workspaceId } : {},
|
|
23901
24003
|
...override?.taskId ? { taskId: override.taskId } : {}
|
|
@@ -23910,7 +24012,7 @@ function isMachineAuthoredPage(pageType, relativePath, content) {
|
|
|
23910
24012
|
if (source === null) {
|
|
23911
24013
|
return false;
|
|
23912
24014
|
}
|
|
23913
|
-
const normalised = relativePath.split(
|
|
24015
|
+
const normalised = relativePath.split(path77.sep).join("/").replace(/^wiki\//, "");
|
|
23914
24016
|
return WIKI_PAGE_PRODUCERS.some((producer) => producer.source === source && producer.pageType === pageType && producer.path.test(normalised) && /^-[ \t]+Link:.*\bsha256\b/m.test(content));
|
|
23915
24017
|
}
|
|
23916
24018
|
function createGdWikiService() {
|
|
@@ -23926,8 +24028,8 @@ function createGdWikiService() {
|
|
|
23926
24028
|
};
|
|
23927
24029
|
}
|
|
23928
24030
|
async function collectGraphWikiCandidates(cwd, generatedAt, limit, onlyModules) {
|
|
23929
|
-
const nodesPath =
|
|
23930
|
-
const edgesPath =
|
|
24031
|
+
const nodesPath = path77.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
|
|
24032
|
+
const edgesPath = path77.join(cwd, ".metaproject", "data", "gdgraph", "storage", "edges.jsonl");
|
|
23931
24033
|
if (!await pathExists(nodesPath) || !await pathExists(edgesPath)) {
|
|
23932
24034
|
return [];
|
|
23933
24035
|
}
|
|
@@ -24014,6 +24116,12 @@ async function collectGraphWikiCandidates(cwd, generatedAt, limit, onlyModules)
|
|
|
24014
24116
|
};
|
|
24015
24117
|
const moduleCandidates = [];
|
|
24016
24118
|
const pageModules = new Set(topModules.map((entry) => entry.name));
|
|
24119
|
+
const componentsDir = path77.join(wikiRootPath3(cwd), "components");
|
|
24120
|
+
const existingSlugs = new Set((await pathExists(componentsDir) ? await readdir13(componentsDir) : []).filter((entry) => entry.endsWith(".md")).map((entry) => entry.slice(0, -3)));
|
|
24121
|
+
const pageLink = (name) => {
|
|
24122
|
+
const slug = slugifyPath(name);
|
|
24123
|
+
return pageModules.has(name) || existingSlugs.has(slug) ? `${slug}.md` : null;
|
|
24124
|
+
};
|
|
24017
24125
|
for (const item of topModules) {
|
|
24018
24126
|
const moduleName = item.name;
|
|
24019
24127
|
const moduleFileList = moduleFiles.get(moduleName) ?? [];
|
|
@@ -24025,7 +24133,7 @@ async function collectGraphWikiCandidates(cwd, generatedAt, limit, onlyModules)
|
|
|
24025
24133
|
const entryFiles = moduleFileList.filter((file) => /(^|\/)index\.[jt]sx?$/.test(file)).slice(0, 4);
|
|
24026
24134
|
const deps = topCounts(moduleDeps.get(moduleName), 6);
|
|
24027
24135
|
const dependents = topCounts(moduleDependents.get(moduleName), 6);
|
|
24028
|
-
const readme = await readModuleReadme(cwd, moduleName);
|
|
24136
|
+
const readme = await readModuleReadme(cwd, moduleName, pageLink);
|
|
24029
24137
|
const exportsFrom = entryFiles.length > 0 ? entryFiles : keyFiles.slice(0, 2).map((entry) => entry.file);
|
|
24030
24138
|
const exportApi = await extractModuleApi(cwd, exportsFrom);
|
|
24031
24139
|
const reference = [];
|
|
@@ -24057,15 +24165,20 @@ async function collectGraphWikiCandidates(cwd, generatedAt, limit, onlyModules)
|
|
|
24057
24165
|
if (exportApi.length > 0) {
|
|
24058
24166
|
summaryParts.push("Exposes " + exportApi.length + " public symbol(s).");
|
|
24059
24167
|
}
|
|
24060
|
-
const
|
|
24168
|
+
const linkedNames = [];
|
|
24169
|
+
const unlinkedNames = [];
|
|
24061
24170
|
const seenRelated = new Set([moduleName]);
|
|
24062
24171
|
for (const [name] of [...deps, ...dependents]) {
|
|
24063
|
-
if (
|
|
24064
|
-
|
|
24065
|
-
relatedNames.push(name);
|
|
24172
|
+
if (seenRelated.has(name)) {
|
|
24173
|
+
continue;
|
|
24066
24174
|
}
|
|
24175
|
+
seenRelated.add(name);
|
|
24176
|
+
(pageLink(name) === null ? unlinkedNames : linkedNames).push(name);
|
|
24067
24177
|
}
|
|
24068
|
-
const related =
|
|
24178
|
+
const related = [
|
|
24179
|
+
...linkedNames.slice(0, 8).map((name) => ({ name, page: pageLink(name) })),
|
|
24180
|
+
...unlinkedNames.slice(0, 8).map((name) => ({ name, page: null }))
|
|
24181
|
+
];
|
|
24069
24182
|
moduleCandidates.push({
|
|
24070
24183
|
type: "component",
|
|
24071
24184
|
slug: slugifyPath(moduleName),
|
|
@@ -24110,8 +24223,8 @@ function topCounts(bucket, limit) {
|
|
|
24110
24223
|
}
|
|
24111
24224
|
return [...bucket.entries()].sort((a, b) => b[1] - a[1]).slice(0, limit);
|
|
24112
24225
|
}
|
|
24113
|
-
async function readModuleReadme(cwd, moduleName) {
|
|
24114
|
-
const readmePath =
|
|
24226
|
+
async function readModuleReadme(cwd, moduleName, pageLink) {
|
|
24227
|
+
const readmePath = path77.join(cwd, ...moduleName.split("/"), "README.md");
|
|
24115
24228
|
if (!await pathExists(readmePath)) {
|
|
24116
24229
|
return null;
|
|
24117
24230
|
}
|
|
@@ -24121,7 +24234,7 @@ async function readModuleReadme(cwd, moduleName) {
|
|
|
24121
24234
|
if (!paragraph) {
|
|
24122
24235
|
return null;
|
|
24123
24236
|
}
|
|
24124
|
-
const normalized = paragraph.replace(/\s+/g, " ")
|
|
24237
|
+
const normalized = truncateMarkdown(rewriteReadmeLinks(paragraph.replace(/\s+/g, " "), moduleName, pageLink), 400);
|
|
24125
24238
|
return "- " + normalized + " (from module README)";
|
|
24126
24239
|
} catch {
|
|
24127
24240
|
return null;
|
|
@@ -24132,7 +24245,7 @@ async function extractModuleExports(cwd, files) {
|
|
|
24132
24245
|
const declRe = /export\s+(?:async\s+)?(?:default\s+)?(?:const|let|var|function|class|type|interface|enum)\s+([A-Za-z_$][\w$]*)/g;
|
|
24133
24246
|
const braceRe = /export\s*\{([^}]+)\}/g;
|
|
24134
24247
|
for (const file of files.slice(0, 4)) {
|
|
24135
|
-
const filePath =
|
|
24248
|
+
const filePath = path77.join(cwd, ...file.split("/"));
|
|
24136
24249
|
if (!await pathExists(filePath)) {
|
|
24137
24250
|
continue;
|
|
24138
24251
|
}
|
|
@@ -24163,7 +24276,7 @@ async function extractModuleExports(cwd, files) {
|
|
|
24163
24276
|
}
|
|
24164
24277
|
async function extractModuleApi(cwd, files) {
|
|
24165
24278
|
const names = await extractModuleExports(cwd, files);
|
|
24166
|
-
const symbolsPath =
|
|
24279
|
+
const symbolsPath = path77.join(cwd, ".metaproject", "data", "gdgraph", "storage", "symbols.jsonl");
|
|
24167
24280
|
if (names.length === 0 || !await pathExists(symbolsPath)) {
|
|
24168
24281
|
return names.map((name) => "`" + name + "`");
|
|
24169
24282
|
}
|
|
@@ -24189,7 +24302,7 @@ async function extractModuleApi(cwd, files) {
|
|
|
24189
24302
|
});
|
|
24190
24303
|
}
|
|
24191
24304
|
async function collectHealthWikiCandidates(cwd, generatedAt) {
|
|
24192
|
-
const healthPath =
|
|
24305
|
+
const healthPath = path77.join(cwd, ".metaproject", "data", "health", "artifacts", "latest.json");
|
|
24193
24306
|
if (!await pathExists(healthPath)) {
|
|
24194
24307
|
return [];
|
|
24195
24308
|
}
|
|
@@ -24231,7 +24344,7 @@ async function collectHealthWikiCandidates(cwd, generatedAt) {
|
|
|
24231
24344
|
}];
|
|
24232
24345
|
}
|
|
24233
24346
|
async function collectTestingWikiCandidates(cwd, generatedAt) {
|
|
24234
|
-
const contextPath =
|
|
24347
|
+
const contextPath = path77.join(cwd, ".metaproject", "data", "testing", "context.md");
|
|
24235
24348
|
if (!await pathExists(contextPath)) {
|
|
24236
24349
|
return [];
|
|
24237
24350
|
}
|
|
@@ -24262,8 +24375,8 @@ async function writeCollectedPage(cwd, candidate, force, history) {
|
|
|
24262
24375
|
if (!folder) {
|
|
24263
24376
|
throw new Error(`Unsupported collected wiki type: ${candidate.type}`);
|
|
24264
24377
|
}
|
|
24265
|
-
const filePath =
|
|
24266
|
-
const relativePath =
|
|
24378
|
+
const filePath = path77.join(wikiRootPath3(cwd), folder, `${candidate.slug}.md`);
|
|
24379
|
+
const relativePath = path77.relative(cwd, filePath);
|
|
24267
24380
|
const exists = await pathExists(filePath);
|
|
24268
24381
|
if (exists && !force) {
|
|
24269
24382
|
return { path: relativePath, type: candidate.type, source: candidate.source, action: "skipped" };
|
|
@@ -24314,7 +24427,7 @@ async function writeCollectedPage(cwd, candidate, force, history) {
|
|
|
24314
24427
|
async function wikiPagesForFile(cwd, targetRepoPath) {
|
|
24315
24428
|
const pages = await collectPages(cwd);
|
|
24316
24429
|
const refs = await Promise.all(pages.map(async (page) => ({
|
|
24317
|
-
repoPath:
|
|
24430
|
+
repoPath: path77.relative(cwd, page.absolutePath).split(path77.sep).join("/"),
|
|
24318
24431
|
content: await readFile39(page.absolutePath, "utf8")
|
|
24319
24432
|
})));
|
|
24320
24433
|
return backlinksFor(buildBacklinkIndex(refs), targetRepoPath);
|
|
@@ -24353,7 +24466,7 @@ function renderIndexBody(pages, generatedAt) {
|
|
|
24353
24466
|
`).trimEnd();
|
|
24354
24467
|
}
|
|
24355
24468
|
async function isIndexStale(cwd, pages) {
|
|
24356
|
-
const indexPath =
|
|
24469
|
+
const indexPath = path77.join(wikiRootPath3(cwd), "index.md");
|
|
24357
24470
|
if (!await pathExists(indexPath)) {
|
|
24358
24471
|
return true;
|
|
24359
24472
|
}
|
|
@@ -24371,7 +24484,7 @@ async function walkMarkdown(root) {
|
|
|
24371
24484
|
const results = [];
|
|
24372
24485
|
const entries = await readdir13(root, { withFileTypes: true });
|
|
24373
24486
|
for (const entry of entries) {
|
|
24374
|
-
const absolutePath =
|
|
24487
|
+
const absolutePath = path77.join(root, entry.name);
|
|
24375
24488
|
if (entry.isDirectory()) {
|
|
24376
24489
|
results.push(...await walkMarkdown(absolutePath));
|
|
24377
24490
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -24428,7 +24541,7 @@ ${JSON.stringify(state, null, 2)}
|
|
|
24428
24541
|
`;
|
|
24429
24542
|
}
|
|
24430
24543
|
async function readIndexGeneratedAt(cwd) {
|
|
24431
|
-
const indexPath =
|
|
24544
|
+
const indexPath = path77.join(wikiRootPath3(cwd), "index.md");
|
|
24432
24545
|
if (!await pathExists(indexPath)) {
|
|
24433
24546
|
return null;
|
|
24434
24547
|
}
|
|
@@ -24511,10 +24624,11 @@ ${reference.join(`
|
|
|
24511
24624
|
## Related Wiki
|
|
24512
24625
|
|
|
24513
24626
|
Graph-derived - regenerated by \`keryx wiki collect --force\`. Only pages that
|
|
24514
|
-
exist are linked
|
|
24627
|
+
exist are linked, other modules are named as code paths; when enriching, add
|
|
24628
|
+
new links only to pages you have verified.
|
|
24515
24629
|
|
|
24516
24630
|
- [Wiki Index](../index.md)
|
|
24517
|
-
${related.map((entry) => "- [Module " + entry.name + "](" + entry.
|
|
24631
|
+
${related.map((entry) => entry.page === null ? "- `" + entry.name + "` (no wiki page)" : "- [Module " + entry.name + "](" + entry.page + ")").join(`
|
|
24518
24632
|
`)}
|
|
24519
24633
|
|
|
24520
24634
|
## Changelog
|
|
@@ -24665,7 +24779,7 @@ async function validateStructure(cwd, pages, issues) {
|
|
|
24665
24779
|
if (pattern.includes("*")) {
|
|
24666
24780
|
continue;
|
|
24667
24781
|
}
|
|
24668
|
-
if (!await pathExists(
|
|
24782
|
+
if (!await pathExists(path77.join(cwd, pattern))) {
|
|
24669
24783
|
issues.push({
|
|
24670
24784
|
page: page.relativePath,
|
|
24671
24785
|
kind: "describes",
|
|
@@ -24735,7 +24849,7 @@ async function validatePageInvariants(cwd, pages, issues) {
|
|
|
24735
24849
|
}
|
|
24736
24850
|
}
|
|
24737
24851
|
function toPosixPath(value) {
|
|
24738
|
-
return value.split(
|
|
24852
|
+
return value.split(path77.sep).join("/");
|
|
24739
24853
|
}
|
|
24740
24854
|
function compareSemver(a, b) {
|
|
24741
24855
|
const pa = a.split(".").map(Number);
|
|
@@ -24757,6 +24871,7 @@ var init_service4 = __esm(() => {
|
|
|
24757
24871
|
init_evidence();
|
|
24758
24872
|
init_history();
|
|
24759
24873
|
init_page_invariants();
|
|
24874
|
+
init_readme_links();
|
|
24760
24875
|
init_section_index();
|
|
24761
24876
|
init_section_tombstone();
|
|
24762
24877
|
init_staleness2();
|
|
@@ -24778,9 +24893,9 @@ var init_service4 = __esm(() => {
|
|
|
24778
24893
|
// src/gdgraph/wiki-layer.ts
|
|
24779
24894
|
import { createHash as createHash16 } from "crypto";
|
|
24780
24895
|
import { mkdir as mkdir21, stat as stat12, writeFile as writeFile15 } from "fs/promises";
|
|
24781
|
-
import
|
|
24896
|
+
import path78 from "path";
|
|
24782
24897
|
function storageDir(projectRoot) {
|
|
24783
|
-
return
|
|
24898
|
+
return path78.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
|
|
24784
24899
|
}
|
|
24785
24900
|
function wikiPageId(relativePath) {
|
|
24786
24901
|
return `wiki:${relativePath}`;
|
|
@@ -24846,11 +24961,11 @@ async function enrichBuildWithWikiLayer(input) {
|
|
|
24846
24961
|
const mtimes = new Map;
|
|
24847
24962
|
for (const record of input.fileRecords) {
|
|
24848
24963
|
try {
|
|
24849
|
-
const info = await stat12(
|
|
24964
|
+
const info = await stat12(path78.join(input.projectRoot, record.path));
|
|
24850
24965
|
mtimes.set(record.path, info.mtimeMs);
|
|
24851
24966
|
} catch {}
|
|
24852
24967
|
}
|
|
24853
|
-
await writeFile15(
|
|
24968
|
+
await writeFile15(path78.join(dir, BUILD_MANIFEST_FILE), `${JSON.stringify({ version: 1, files: computeFingerprints(input.fileRecords, mtimes) }, null, 2)}
|
|
24854
24969
|
`, "utf8");
|
|
24855
24970
|
const validModules = input.validModules !== undefined ? input.validModules : await (input.loadValidModules ?? defaultLoadValidModules)(input.projectRoot);
|
|
24856
24971
|
const wikiPages = await collectPages(input.projectRoot);
|
|
@@ -24875,8 +24990,8 @@ async function enrichBuildWithWikiLayer(input) {
|
|
|
24875
24990
|
version: page.version
|
|
24876
24991
|
}))
|
|
24877
24992
|
});
|
|
24878
|
-
await writeJsonl(
|
|
24879
|
-
await writeJsonl(
|
|
24993
|
+
await writeJsonl(path78.join(dir, WIKI_PAGES_FILE), layer.pages);
|
|
24994
|
+
await writeJsonl(path78.join(dir, DESCRIBES_FILE), layer.describes);
|
|
24880
24995
|
return layer;
|
|
24881
24996
|
}
|
|
24882
24997
|
async function defaultLoadValidModules(projectRoot) {
|
|
@@ -24894,7 +25009,7 @@ var init_wiki_layer = __esm(() => {
|
|
|
24894
25009
|
// src/gdskills/contracts.ts
|
|
24895
25010
|
import { readFile as readFile51 } from "fs/promises";
|
|
24896
25011
|
import { existsSync as existsSync15 } from "fs";
|
|
24897
|
-
import
|
|
25012
|
+
import path106 from "path";
|
|
24898
25013
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
24899
25014
|
async function loadSchema(name) {
|
|
24900
25015
|
const contract = CONTRACTS.find((entry) => entry.name === name);
|
|
@@ -24905,10 +25020,10 @@ async function loadSchema(name) {
|
|
|
24905
25020
|
return JSON.parse(raw);
|
|
24906
25021
|
}
|
|
24907
25022
|
function contractPath(contract) {
|
|
24908
|
-
const here =
|
|
25023
|
+
const here = path106.dirname(fileURLToPath2(import.meta.url));
|
|
24909
25024
|
if (contract.sourcePath) {
|
|
24910
|
-
for (const root of [
|
|
24911
|
-
const candidate =
|
|
25025
|
+
for (const root of [path106.join(here, "..", ".."), path106.join(here, ".."), here]) {
|
|
25026
|
+
const candidate = path106.resolve(root, contract.sourcePath);
|
|
24912
25027
|
if (existsSync15(candidate)) {
|
|
24913
25028
|
return candidate;
|
|
24914
25029
|
}
|
|
@@ -24918,7 +25033,7 @@ function contractPath(contract) {
|
|
|
24918
25033
|
if (existsSync15(directPath)) {
|
|
24919
25034
|
return directPath;
|
|
24920
25035
|
}
|
|
24921
|
-
const packagedSourcePath =
|
|
25036
|
+
const packagedSourcePath = path106.join(here, "..", "src", "gdskills", "contracts", contract.fileName);
|
|
24922
25037
|
if (existsSync15(packagedSourcePath)) {
|
|
24923
25038
|
return packagedSourcePath;
|
|
24924
25039
|
}
|
|
@@ -29952,7 +30067,7 @@ __export(exports_service5, {
|
|
|
29952
30067
|
// src/gdgraph/build.ts
|
|
29953
30068
|
import { mkdir as mkdir22, readdir as readdir14, readFile as readFile40, writeFile as writeFile16 } from "fs/promises";
|
|
29954
30069
|
import { existsSync as existsSync7 } from "fs";
|
|
29955
|
-
import
|
|
30070
|
+
import path79 from "path";
|
|
29956
30071
|
|
|
29957
30072
|
// src/gdgraph/types.ts
|
|
29958
30073
|
var UNKNOWN_IMPORT_KIND = "unknown-static";
|
|
@@ -30017,7 +30132,7 @@ async function buildGraph(projectRoot) {
|
|
|
30017
30132
|
const assetNodes = new Map;
|
|
30018
30133
|
const fileRecords = [];
|
|
30019
30134
|
for (const file of files) {
|
|
30020
|
-
const absolutePath =
|
|
30135
|
+
const absolutePath = path79.join(projectRoot, file);
|
|
30021
30136
|
const content = await readFile40(absolutePath, "utf8");
|
|
30022
30137
|
fileRecords.push({ path: file, content });
|
|
30023
30138
|
const language = getLanguage(file);
|
|
@@ -30070,24 +30185,24 @@ async function collectSourceFiles(projectRoot) {
|
|
|
30070
30185
|
const result = [];
|
|
30071
30186
|
const skippedDirectories = [];
|
|
30072
30187
|
async function walk(relativeDir) {
|
|
30073
|
-
const absoluteDir =
|
|
30188
|
+
const absoluteDir = path79.join(projectRoot, relativeDir);
|
|
30074
30189
|
const entries = await readdir14(absoluteDir, { withFileTypes: true });
|
|
30075
30190
|
for (const entry of entries) {
|
|
30076
30191
|
if (entry.isDirectory()) {
|
|
30077
30192
|
if (IGNORE_DIRS.has(entry.name)) {
|
|
30078
|
-
skippedDirectories.push(normalizePath2(
|
|
30193
|
+
skippedDirectories.push(normalizePath2(path79.posix.join(relativeDir, entry.name)).replace(/^\.\//, ""));
|
|
30079
30194
|
continue;
|
|
30080
30195
|
}
|
|
30081
|
-
await walk(normalizePath2(
|
|
30196
|
+
await walk(normalizePath2(path79.posix.join(relativeDir, entry.name)));
|
|
30082
30197
|
continue;
|
|
30083
30198
|
}
|
|
30084
30199
|
if (!entry.isFile()) {
|
|
30085
30200
|
continue;
|
|
30086
30201
|
}
|
|
30087
|
-
if (!SOURCE_EXTENSIONS.includes(
|
|
30202
|
+
if (!SOURCE_EXTENSIONS.includes(path79.extname(entry.name))) {
|
|
30088
30203
|
continue;
|
|
30089
30204
|
}
|
|
30090
|
-
result.push(normalizePath2(
|
|
30205
|
+
result.push(normalizePath2(path79.posix.join(relativeDir, entry.name)).replace(/^\.\//, ""));
|
|
30091
30206
|
}
|
|
30092
30207
|
}
|
|
30093
30208
|
await walk(".");
|
|
@@ -30169,8 +30284,8 @@ function resolveImport(projectRoot, fromFile, specifier, fileSet, resolver) {
|
|
|
30169
30284
|
}
|
|
30170
30285
|
function resolveAssetImport(projectRoot, fromFile, specifier, resolver) {
|
|
30171
30286
|
for (const candidate of importCandidateBases(projectRoot, fromFile, specifier, resolver)) {
|
|
30172
|
-
const extension =
|
|
30173
|
-
if (ASSET_EXTENSIONS.includes(extension) && existsSync7(
|
|
30287
|
+
const extension = path79.posix.extname(candidate);
|
|
30288
|
+
if (ASSET_EXTENSIONS.includes(extension) && existsSync7(path79.join(projectRoot, candidate))) {
|
|
30174
30289
|
return candidate;
|
|
30175
30290
|
}
|
|
30176
30291
|
}
|
|
@@ -30179,17 +30294,17 @@ function resolveAssetImport(projectRoot, fromFile, specifier, resolver) {
|
|
|
30179
30294
|
function importCandidateBases(projectRoot, fromFile, specifier, resolver) {
|
|
30180
30295
|
const normalizedSpecifier = stripImportSuffix(specifier);
|
|
30181
30296
|
if (normalizedSpecifier.startsWith(".") && getLanguage(fromFile) !== "python") {
|
|
30182
|
-
const fromDir =
|
|
30183
|
-
return [normalizePath2(
|
|
30297
|
+
const fromDir = path79.posix.dirname(fromFile);
|
|
30298
|
+
return [normalizePath2(path79.posix.normalize(path79.posix.join(fromDir, normalizedSpecifier)))];
|
|
30184
30299
|
}
|
|
30185
|
-
return resolver.candidateBases(normalizedSpecifier, fromFile).map((candidate) => normalizePath2(
|
|
30300
|
+
return resolver.candidateBases(normalizedSpecifier, fromFile).map((candidate) => normalizePath2(path79.relative(projectRoot, path79.join(projectRoot, candidate))));
|
|
30186
30301
|
}
|
|
30187
30302
|
function resolveSourceCandidate(base, fileSet) {
|
|
30188
30303
|
const candidates = [
|
|
30189
30304
|
base,
|
|
30190
30305
|
...SOURCE_RESOLUTION_EXTENSIONS.map((extension) => `${base}${extension}`),
|
|
30191
|
-
...SOURCE_RESOLUTION_EXTENSIONS.map((extension) =>
|
|
30192
|
-
|
|
30306
|
+
...SOURCE_RESOLUTION_EXTENSIONS.map((extension) => path79.posix.join(base, `index${extension}`)),
|
|
30307
|
+
path79.posix.join(base, "__init__.py")
|
|
30193
30308
|
];
|
|
30194
30309
|
return candidates.find((candidate) => fileSet.has(candidate)) ?? null;
|
|
30195
30310
|
}
|
|
@@ -30219,7 +30334,7 @@ async function loadJavaResolver(projectRoot) {
|
|
|
30219
30334
|
return createJavaResolver(roots);
|
|
30220
30335
|
}
|
|
30221
30336
|
async function discoverJavaSourceRoots(projectRoot) {
|
|
30222
|
-
const pomPath =
|
|
30337
|
+
const pomPath = path79.join(projectRoot, "pom.xml");
|
|
30223
30338
|
if (existsSync7(pomPath)) {
|
|
30224
30339
|
try {
|
|
30225
30340
|
const roots = parseMavenSourceRoots(await readFile40(pomPath, "utf8"));
|
|
@@ -30229,7 +30344,7 @@ async function discoverJavaSourceRoots(projectRoot) {
|
|
|
30229
30344
|
} catch {}
|
|
30230
30345
|
}
|
|
30231
30346
|
for (const gradleName of ["build.gradle", "build.gradle.kts"]) {
|
|
30232
|
-
const gradlePath =
|
|
30347
|
+
const gradlePath = path79.join(projectRoot, gradleName);
|
|
30233
30348
|
if (existsSync7(gradlePath)) {
|
|
30234
30349
|
try {
|
|
30235
30350
|
const roots = parseGradleSourceRoots(await readFile40(gradlePath, "utf8"));
|
|
@@ -30251,12 +30366,12 @@ function createJavaResolver(sourceRoots) {
|
|
|
30251
30366
|
return [];
|
|
30252
30367
|
}
|
|
30253
30368
|
const relative = specifier.split(".").join("/");
|
|
30254
|
-
return sourceRoots.map((root) => normalizePath2(
|
|
30369
|
+
return sourceRoots.map((root) => normalizePath2(path79.posix.join(root, relative)));
|
|
30255
30370
|
}
|
|
30256
30371
|
};
|
|
30257
30372
|
}
|
|
30258
30373
|
function loadPythonResolver(projectRoot) {
|
|
30259
|
-
const hasSrc = existsSync7(
|
|
30374
|
+
const hasSrc = existsSync7(path79.join(projectRoot, "src"));
|
|
30260
30375
|
return createPythonResolver(hasSrc);
|
|
30261
30376
|
}
|
|
30262
30377
|
function createPythonResolver(hasSrc) {
|
|
@@ -30269,16 +30384,16 @@ function createPythonResolver(hasSrc) {
|
|
|
30269
30384
|
if (specifier.startsWith(".")) {
|
|
30270
30385
|
const dots = /^\.+/.exec(specifier)?.[0].length ?? 0;
|
|
30271
30386
|
const rest = specifier.slice(dots);
|
|
30272
|
-
let baseDir =
|
|
30387
|
+
let baseDir = path79.posix.dirname(fromFile);
|
|
30273
30388
|
for (let level = 1;level < dots; level += 1) {
|
|
30274
|
-
baseDir =
|
|
30389
|
+
baseDir = path79.posix.dirname(baseDir);
|
|
30275
30390
|
}
|
|
30276
30391
|
const suffix = rest ? rest.split(".").join("/") : "";
|
|
30277
|
-
const base = suffix ?
|
|
30392
|
+
const base = suffix ? path79.posix.join(baseDir, suffix) : baseDir;
|
|
30278
30393
|
return [normalizePath2(base)];
|
|
30279
30394
|
}
|
|
30280
30395
|
const relative = specifier.split(".").join("/");
|
|
30281
|
-
return roots.map((root) => normalizePath2(root ?
|
|
30396
|
+
return roots.map((root) => normalizePath2(root ? path79.posix.join(root, relative) : relative));
|
|
30282
30397
|
}
|
|
30283
30398
|
};
|
|
30284
30399
|
}
|
|
@@ -30287,8 +30402,8 @@ function parseMavenSourceRoots(pomXml) {
|
|
|
30287
30402
|
for (const match of pomXml.matchAll(/<module>\s*([^<]+?)\s*<\/module>/g)) {
|
|
30288
30403
|
const moduleDir = match[1]?.trim();
|
|
30289
30404
|
if (moduleDir && !moduleDir.includes("${")) {
|
|
30290
|
-
roots.add(normalizePath2(
|
|
30291
|
-
roots.add(normalizePath2(
|
|
30405
|
+
roots.add(normalizePath2(path79.posix.join(moduleDir, "src/main/java")));
|
|
30406
|
+
roots.add(normalizePath2(path79.posix.join(moduleDir, "src/test/java")));
|
|
30292
30407
|
}
|
|
30293
30408
|
}
|
|
30294
30409
|
for (const tag of ["sourceDirectory", "testSourceDirectory"]) {
|
|
@@ -30321,7 +30436,7 @@ function parseGradleSourceRoots(buildGradle) {
|
|
|
30321
30436
|
var TSCONFIG_EXTENDS_MAX_DEPTH = 10;
|
|
30322
30437
|
async function loadTsconfigResolver(projectRoot) {
|
|
30323
30438
|
const empty = createTsconfigResolver(null, []);
|
|
30324
|
-
const tsconfigPath =
|
|
30439
|
+
const tsconfigPath = path79.join(projectRoot, "tsconfig.json");
|
|
30325
30440
|
if (!existsSync7(tsconfigPath)) {
|
|
30326
30441
|
return empty;
|
|
30327
30442
|
}
|
|
@@ -30334,7 +30449,7 @@ async function loadTsconfigResolver(projectRoot) {
|
|
|
30334
30449
|
return createTsconfigResolver(resolved.baseUrl, paths);
|
|
30335
30450
|
}
|
|
30336
30451
|
function toProjectRelativeDir(projectRoot, absoluteDir) {
|
|
30337
|
-
const relative = normalizePath2(
|
|
30452
|
+
const relative = normalizePath2(path79.relative(projectRoot, absoluteDir)).replace(/^\.\//, "");
|
|
30338
30453
|
return relative === "." ? "" : relative;
|
|
30339
30454
|
}
|
|
30340
30455
|
async function readTsconfigJson(configPath) {
|
|
@@ -30349,11 +30464,11 @@ function resolveTsconfigExtendsPath(configDir, extendsSpecifier) {
|
|
|
30349
30464
|
if (!extendsSpecifier.startsWith(".") && !extendsSpecifier.startsWith("/")) {
|
|
30350
30465
|
return null;
|
|
30351
30466
|
}
|
|
30352
|
-
const resolved =
|
|
30467
|
+
const resolved = path79.resolve(configDir, extendsSpecifier);
|
|
30353
30468
|
return resolved.endsWith(".json") ? resolved : `${resolved}.json`;
|
|
30354
30469
|
}
|
|
30355
30470
|
async function resolveTsconfigOptions(configPath, visited, depth, projectRoot) {
|
|
30356
|
-
const resolvedPath =
|
|
30471
|
+
const resolvedPath = path79.resolve(configPath);
|
|
30357
30472
|
if (depth > TSCONFIG_EXTENDS_MAX_DEPTH || visited.has(resolvedPath)) {
|
|
30358
30473
|
return null;
|
|
30359
30474
|
}
|
|
@@ -30364,15 +30479,15 @@ async function resolveTsconfigOptions(configPath, visited, depth, projectRoot) {
|
|
|
30364
30479
|
}
|
|
30365
30480
|
let inherited = null;
|
|
30366
30481
|
if (typeof parsed.extends === "string") {
|
|
30367
|
-
const basePath = resolveTsconfigExtendsPath(
|
|
30482
|
+
const basePath = resolveTsconfigExtendsPath(path79.dirname(resolvedPath), parsed.extends);
|
|
30368
30483
|
if (basePath) {
|
|
30369
30484
|
inherited = await resolveTsconfigOptions(basePath, visited, depth + 1, projectRoot);
|
|
30370
30485
|
}
|
|
30371
30486
|
}
|
|
30372
|
-
const configDir =
|
|
30487
|
+
const configDir = path79.dirname(resolvedPath);
|
|
30373
30488
|
const declaringDir = toProjectRelativeDir(projectRoot, configDir);
|
|
30374
30489
|
const options = parsed.compilerOptions ?? {};
|
|
30375
|
-
const ownBaseUrl = typeof options.baseUrl === "string" ? toProjectRelativeDir(projectRoot,
|
|
30490
|
+
const ownBaseUrl = typeof options.baseUrl === "string" ? toProjectRelativeDir(projectRoot, path79.resolve(configDir, options.baseUrl)) : null;
|
|
30376
30491
|
const baseUrl = ownBaseUrl ?? inherited?.baseUrl ?? null;
|
|
30377
30492
|
const ownPaths = isRecord4(options.paths) ? Object.entries(options.paths).filter((entry) => Array.isArray(entry[1])).map(([pattern, targets]) => ({
|
|
30378
30493
|
pattern,
|
|
@@ -30401,7 +30516,7 @@ function createTsconfigResolver(baseUrl, mappings) {
|
|
|
30401
30516
|
}
|
|
30402
30517
|
}
|
|
30403
30518
|
if (baseUrl !== null) {
|
|
30404
|
-
candidates.push(normalizePath2(
|
|
30519
|
+
candidates.push(normalizePath2(path79.posix.join(baseUrl, normalizedSpecifier)));
|
|
30405
30520
|
}
|
|
30406
30521
|
return [...new Set(candidates.map((candidate) => candidate.replace(/^\.\//, "")))];
|
|
30407
30522
|
}
|
|
@@ -30421,7 +30536,7 @@ function matchPathPattern(pattern, specifier) {
|
|
|
30421
30536
|
}
|
|
30422
30537
|
function applyPathTarget(base, target, wildcard) {
|
|
30423
30538
|
const replaced = target.includes("*") ? target.replace("*", wildcard) : target;
|
|
30424
|
-
return normalizePath2(
|
|
30539
|
+
return normalizePath2(path79.posix.normalize(path79.posix.join(base, replaced)));
|
|
30425
30540
|
}
|
|
30426
30541
|
function stripJsonComments(source) {
|
|
30427
30542
|
let out = "";
|
|
@@ -30474,21 +30589,21 @@ function isRecord4(value) {
|
|
|
30474
30589
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30475
30590
|
}
|
|
30476
30591
|
async function writeGraph(projectRoot, graph) {
|
|
30477
|
-
const storageDir =
|
|
30478
|
-
const artifactsDir =
|
|
30592
|
+
const storageDir = path79.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
|
|
30593
|
+
const artifactsDir = path79.join(projectRoot, ".metaproject", "data", "gdgraph", "artifacts");
|
|
30479
30594
|
await mkdir22(storageDir, { recursive: true });
|
|
30480
30595
|
await mkdir22(artifactsDir, { recursive: true });
|
|
30481
|
-
await writeFile16(
|
|
30596
|
+
await writeFile16(path79.join(storageDir, "nodes.jsonl"), graph.nodes.map((node) => JSON.stringify(node)).join(`
|
|
30482
30597
|
`) + `
|
|
30483
30598
|
`, "utf8");
|
|
30484
|
-
await writeFile16(
|
|
30599
|
+
await writeFile16(path79.join(storageDir, "edges.jsonl"), graph.edges.map((edge) => JSON.stringify(edge)).join(`
|
|
30485
30600
|
`) + `
|
|
30486
30601
|
`, "utf8");
|
|
30487
|
-
await writeFile16(
|
|
30602
|
+
await writeFile16(path79.join(artifactsDir, "module-map.json"), JSON.stringify(buildModuleMap(graph), null, 2) + `
|
|
30488
30603
|
`, "utf8");
|
|
30489
30604
|
}
|
|
30490
30605
|
async function writeSummary(projectRoot, graph, collection) {
|
|
30491
|
-
const artifactsDir =
|
|
30606
|
+
const artifactsDir = path79.join(projectRoot, ".metaproject", "data", "gdgraph", "artifacts");
|
|
30492
30607
|
await mkdir22(artifactsDir, { recursive: true });
|
|
30493
30608
|
const unresolved = graph.edges.filter((edge) => edge.kind === "unresolved");
|
|
30494
30609
|
const imports = graph.edges.filter((edge) => edge.kind === "imports");
|
|
@@ -30503,7 +30618,7 @@ async function writeSummary(projectRoot, graph, collection) {
|
|
|
30503
30618
|
`);
|
|
30504
30619
|
const skippedList = collection.skippedDirectories.length > 0 ? collection.skippedDirectories.slice(0, 30).map((dir) => `- \`${dir}\``).join(`
|
|
30505
30620
|
`) : "- none";
|
|
30506
|
-
const summaryPath =
|
|
30621
|
+
const summaryPath = path79.join(artifactsDir, "summary.md");
|
|
30507
30622
|
const content = `# gdgraph Summary
|
|
30508
30623
|
|
|
30509
30624
|
## Stats
|
|
@@ -30584,7 +30699,7 @@ function groupBy(items, getKey) {
|
|
|
30584
30699
|
}
|
|
30585
30700
|
function unresolvedType(specifier) {
|
|
30586
30701
|
const stripped = stripImportSuffix(specifier);
|
|
30587
|
-
const extension =
|
|
30702
|
+
const extension = path79.posix.extname(stripped);
|
|
30588
30703
|
if (extension) {
|
|
30589
30704
|
return extension;
|
|
30590
30705
|
}
|
|
@@ -30594,13 +30709,13 @@ function unresolvedType(specifier) {
|
|
|
30594
30709
|
return "package";
|
|
30595
30710
|
}
|
|
30596
30711
|
function normalizePath2(value) {
|
|
30597
|
-
return value.split(
|
|
30712
|
+
return value.split(path79.sep).join("/");
|
|
30598
30713
|
}
|
|
30599
30714
|
|
|
30600
30715
|
// src/gdgraph/target.ts
|
|
30601
|
-
import
|
|
30716
|
+
import path80 from "path";
|
|
30602
30717
|
function normalizeTarget(target) {
|
|
30603
|
-
return target.replace(/^\.\//, "").split(
|
|
30718
|
+
return target.replace(/^\.\//, "").split(path80.sep).join("/");
|
|
30604
30719
|
}
|
|
30605
30720
|
function resolveGraphTarget(graph, target) {
|
|
30606
30721
|
const normalized = normalizeTarget(target);
|
|
@@ -30693,15 +30808,15 @@ init_config3();
|
|
|
30693
30808
|
|
|
30694
30809
|
// src/gdgraph/query.ts
|
|
30695
30810
|
import { readFile as readFile41 } from "fs/promises";
|
|
30696
|
-
import
|
|
30811
|
+
import path81 from "path";
|
|
30697
30812
|
async function loadGraph(projectRoot) {
|
|
30698
|
-
const storageDir =
|
|
30699
|
-
const nodes = await readJsonl(
|
|
30700
|
-
const edges = await readJsonl(
|
|
30701
|
-
const symbols = await readJsonl(
|
|
30702
|
-
const calls = await readJsonl(
|
|
30703
|
-
const wikiPages = await readJsonl(
|
|
30704
|
-
const describes = await readJsonl(
|
|
30813
|
+
const storageDir = path81.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
|
|
30814
|
+
const nodes = await readJsonl(path81.join(storageDir, "nodes.jsonl"));
|
|
30815
|
+
const edges = await readJsonl(path81.join(storageDir, "edges.jsonl"));
|
|
30816
|
+
const symbols = await readJsonl(path81.join(storageDir, "symbols.jsonl"));
|
|
30817
|
+
const calls = await readJsonl(path81.join(storageDir, "calls.jsonl"));
|
|
30818
|
+
const wikiPages = await readJsonl(path81.join(storageDir, "wiki-pages.jsonl"));
|
|
30819
|
+
const describes = await readJsonl(path81.join(storageDir, "describes.jsonl"));
|
|
30705
30820
|
const graph = { nodes, edges };
|
|
30706
30821
|
if (symbols.length > 0) {
|
|
30707
30822
|
graph.symbols = symbols;
|
|
@@ -30761,7 +30876,7 @@ async function bunfigPreloadRoots(projectRoot) {
|
|
|
30761
30876
|
const roots = new Set;
|
|
30762
30877
|
let text;
|
|
30763
30878
|
try {
|
|
30764
|
-
text = await readFile41(
|
|
30879
|
+
text = await readFile41(path81.join(projectRoot, "bunfig.toml"), "utf8");
|
|
30765
30880
|
} catch {
|
|
30766
30881
|
return roots;
|
|
30767
30882
|
}
|
|
@@ -30775,8 +30890,8 @@ async function bunfigPreloadRoots(projectRoot) {
|
|
|
30775
30890
|
if (raw.length === 0) {
|
|
30776
30891
|
continue;
|
|
30777
30892
|
}
|
|
30778
|
-
const absolute =
|
|
30779
|
-
const relative =
|
|
30893
|
+
const absolute = path81.resolve(projectRoot, raw);
|
|
30894
|
+
const relative = path81.relative(projectRoot, absolute).split(path81.sep).join("/");
|
|
30780
30895
|
roots.add(relative);
|
|
30781
30896
|
}
|
|
30782
30897
|
}
|
|
@@ -30849,7 +30964,7 @@ function canonicalCycle(cycle) {
|
|
|
30849
30964
|
|
|
30850
30965
|
// src/gdgraph/repomap.ts
|
|
30851
30966
|
import { mkdir as mkdir23, writeFile as writeFile17 } from "fs/promises";
|
|
30852
|
-
import
|
|
30967
|
+
import path82 from "path";
|
|
30853
30968
|
|
|
30854
30969
|
// src/gdgraph/pagerank.ts
|
|
30855
30970
|
function personalizedPageRank(nodes, edges, options) {
|
|
@@ -30960,7 +31075,7 @@ function overflowContent(required, missing, budget) {
|
|
|
30960
31075
|
`);
|
|
30961
31076
|
}
|
|
30962
31077
|
function repomapArtifactPath(cwd) {
|
|
30963
|
-
return
|
|
31078
|
+
return path82.join(cwd, ".metaproject", "data", "gdgraph", "artifacts", "repomap.md");
|
|
30964
31079
|
}
|
|
30965
31080
|
function buildRankEdges(graph, config) {
|
|
30966
31081
|
const edges = [];
|
|
@@ -31105,7 +31220,7 @@ function computeRepomap(graph, config, options = {}) {
|
|
|
31105
31220
|
async function writeRepomap(cwd, graph, config, options = {}) {
|
|
31106
31221
|
const result = computeRepomap(graph, config, options);
|
|
31107
31222
|
const artifactPath = repomapArtifactPath(cwd);
|
|
31108
|
-
await mkdir23(
|
|
31223
|
+
await mkdir23(path82.dirname(artifactPath), { recursive: true });
|
|
31109
31224
|
await writeFile17(artifactPath, result.content, "utf8");
|
|
31110
31225
|
return { ...result, path: artifactPath };
|
|
31111
31226
|
}
|
|
@@ -31188,12 +31303,12 @@ init_section_tombstone();
|
|
|
31188
31303
|
// src/forgetting/journal.ts
|
|
31189
31304
|
init_fs();
|
|
31190
31305
|
import { appendFile as appendFile5, mkdir as mkdir24, readFile as readFile42, stat as stat13 } from "fs/promises";
|
|
31191
|
-
import
|
|
31306
|
+
import path83 from "path";
|
|
31192
31307
|
function forgettingDataDir(cwd) {
|
|
31193
|
-
return
|
|
31308
|
+
return path83.join(cwd, ".metaproject", "data", "forgetting");
|
|
31194
31309
|
}
|
|
31195
31310
|
function deletionJournalPath(cwd) {
|
|
31196
|
-
return
|
|
31311
|
+
return path83.join(forgettingDataDir(cwd), "journal.jsonl");
|
|
31197
31312
|
}
|
|
31198
31313
|
async function readDeletionJournal(cwd) {
|
|
31199
31314
|
const file = deletionJournalPath(cwd);
|
|
@@ -31612,12 +31727,12 @@ __export(exports_service7, {
|
|
|
31612
31727
|
gateExitCode: () => gateExitCode,
|
|
31613
31728
|
readWikiFreshnessMetric: () => readWikiFreshnessMetric
|
|
31614
31729
|
});
|
|
31615
|
-
import
|
|
31730
|
+
import path103 from "path";
|
|
31616
31731
|
|
|
31617
31732
|
// src/health/config.ts
|
|
31618
31733
|
init_fs();
|
|
31619
31734
|
init_json();
|
|
31620
|
-
import
|
|
31735
|
+
import path84 from "path";
|
|
31621
31736
|
var DEFAULT_HEALTH_CONFIG = {
|
|
31622
31737
|
schemaVersion: 2,
|
|
31623
31738
|
ignore: {
|
|
@@ -31673,7 +31788,7 @@ var DEFAULT_HEALTH_CONFIG = {
|
|
|
31673
31788
|
}
|
|
31674
31789
|
};
|
|
31675
31790
|
function configPath2(cwd) {
|
|
31676
|
-
return
|
|
31791
|
+
return path84.join(cwd, ".metaproject", "health.config.json");
|
|
31677
31792
|
}
|
|
31678
31793
|
var STRICTEST_GATE = {
|
|
31679
31794
|
failOnPriorities: ["P0", "P1", "P2", "P3"],
|
|
@@ -31724,7 +31839,7 @@ async function loadHealthConfig(cwd) {
|
|
|
31724
31839
|
// src/health/run.ts
|
|
31725
31840
|
init_fs();
|
|
31726
31841
|
import { mkdir as mkdir28, writeFile as writeFile21 } from "fs/promises";
|
|
31727
|
-
import
|
|
31842
|
+
import path102 from "path";
|
|
31728
31843
|
|
|
31729
31844
|
// src/metrics/provenance.ts
|
|
31730
31845
|
async function collectGitProvenance(cwd) {
|
|
@@ -31824,12 +31939,12 @@ function computeGate2(input) {
|
|
|
31824
31939
|
}
|
|
31825
31940
|
|
|
31826
31941
|
// src/health/scopes.ts
|
|
31827
|
-
import
|
|
31942
|
+
import path87 from "path";
|
|
31828
31943
|
|
|
31829
31944
|
// src/health/util.ts
|
|
31830
31945
|
init_fs();
|
|
31831
31946
|
import { mkdir as mkdir25, readFile as readFile43, readdir as readdir15, writeFile as writeFile18 } from "fs/promises";
|
|
31832
|
-
import
|
|
31947
|
+
import path85 from "path";
|
|
31833
31948
|
var IGNORED_DIRS = new Set([
|
|
31834
31949
|
"node_modules",
|
|
31835
31950
|
".git",
|
|
@@ -31873,14 +31988,14 @@ async function toolVersion(command, cwd) {
|
|
|
31873
31988
|
}
|
|
31874
31989
|
}
|
|
31875
31990
|
function dataRoot3(cwd) {
|
|
31876
|
-
return
|
|
31991
|
+
return path85.join(cwd, ".metaproject", "data", "health");
|
|
31877
31992
|
}
|
|
31878
31993
|
async function writeRaw(cwd, source, content, stamp) {
|
|
31879
|
-
const dir =
|
|
31994
|
+
const dir = path85.join(dataRoot3(cwd), "raw", source);
|
|
31880
31995
|
await mkdir25(dir, { recursive: true });
|
|
31881
|
-
const file =
|
|
31996
|
+
const file = path85.join(dir, `${stamp}.log`);
|
|
31882
31997
|
await writeFile18(file, content, "utf8");
|
|
31883
|
-
return
|
|
31998
|
+
return path85.relative(cwd, file);
|
|
31884
31999
|
}
|
|
31885
32000
|
async function listSourceFiles(cwd, ignorePaths = []) {
|
|
31886
32001
|
const { files } = await listSourceFilesWithReasons(cwd, ignorePaths);
|
|
@@ -31900,7 +32015,7 @@ async function walk2(root, dir, out, incompleteReasons) {
|
|
|
31900
32015
|
try {
|
|
31901
32016
|
entries = await readdir15(dir, { withFileTypes: true });
|
|
31902
32017
|
} catch (error) {
|
|
31903
|
-
incompleteReasons.push(`${
|
|
32018
|
+
incompleteReasons.push(`${path85.relative(root, dir) || "."}: ${error instanceof Error ? error.message : String(error)}`);
|
|
31904
32019
|
return;
|
|
31905
32020
|
}
|
|
31906
32021
|
for (const entry of entries) {
|
|
@@ -31908,14 +32023,14 @@ async function walk2(root, dir, out, incompleteReasons) {
|
|
|
31908
32023
|
if (entry.isDirectory() && !IGNORED_DIRS.has(entry.name)) {}
|
|
31909
32024
|
continue;
|
|
31910
32025
|
}
|
|
31911
|
-
const abs =
|
|
32026
|
+
const abs = path85.join(dir, entry.name);
|
|
31912
32027
|
if (entry.isDirectory()) {
|
|
31913
32028
|
if (IGNORED_DIRS.has(entry.name)) {
|
|
31914
32029
|
continue;
|
|
31915
32030
|
}
|
|
31916
32031
|
await walk2(root, abs, out, incompleteReasons);
|
|
31917
|
-
} else if (entry.isFile() && SOURCE_EXT.has(
|
|
31918
|
-
out.push(
|
|
32032
|
+
} else if (entry.isFile() && SOURCE_EXT.has(path85.extname(entry.name))) {
|
|
32033
|
+
out.push(path85.relative(root, abs));
|
|
31919
32034
|
}
|
|
31920
32035
|
}
|
|
31921
32036
|
}
|
|
@@ -31930,7 +32045,7 @@ function moduleOfFile(file) {
|
|
|
31930
32045
|
return null;
|
|
31931
32046
|
}
|
|
31932
32047
|
function isSourceFile(file) {
|
|
31933
|
-
return SOURCE_EXT.has(
|
|
32048
|
+
return SOURCE_EXT.has(path85.extname(file));
|
|
31934
32049
|
}
|
|
31935
32050
|
function matchesAnyPattern(file, patterns) {
|
|
31936
32051
|
const normalized = file.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
@@ -32030,7 +32145,7 @@ function rankHotspots(files, churn, sourceAnalysis) {
|
|
|
32030
32145
|
// src/health/source-analysis.ts
|
|
32031
32146
|
init_fs();
|
|
32032
32147
|
import { readFile as readFile44 } from "fs/promises";
|
|
32033
|
-
import
|
|
32148
|
+
import path86 from "path";
|
|
32034
32149
|
|
|
32035
32150
|
// src/health/metrics/complexity.ts
|
|
32036
32151
|
var CONTROL_KEYWORDS = new Set([
|
|
@@ -32264,7 +32379,7 @@ async function analyzeSourceFiles(cwd, sourceFiles) {
|
|
|
32264
32379
|
return new Map(entries.filter((entry) => entry !== null));
|
|
32265
32380
|
}
|
|
32266
32381
|
async function analyzeSourceFile(cwd, file) {
|
|
32267
|
-
const abs =
|
|
32382
|
+
const abs = path86.join(cwd, file);
|
|
32268
32383
|
if (!await pathExists(abs)) {
|
|
32269
32384
|
return null;
|
|
32270
32385
|
}
|
|
@@ -32337,14 +32452,14 @@ async function computeMetrics(input) {
|
|
|
32337
32452
|
}
|
|
32338
32453
|
const components = new Map;
|
|
32339
32454
|
for (const file of sourceFiles) {
|
|
32340
|
-
const dir =
|
|
32455
|
+
const dir = path87.posix.dirname(file);
|
|
32341
32456
|
if (dir === "." || dir === moduleOfFile(file)) {
|
|
32342
32457
|
continue;
|
|
32343
32458
|
}
|
|
32344
32459
|
components.set(dir, [...components.get(dir) ?? [], file]);
|
|
32345
32460
|
}
|
|
32346
32461
|
for (const [name, files] of [...components.entries()].sort()) {
|
|
32347
|
-
const compFindings = findings.filter((f) => f.file &&
|
|
32462
|
+
const compFindings = findings.filter((f) => f.file && path87.posix.dirname(f.file) === name);
|
|
32348
32463
|
scopes.push(build("component", `component:${name}`, name, files, compFindings, averageCoverage(files, coverage)));
|
|
32349
32464
|
}
|
|
32350
32465
|
const findingFiles = findings.map((f) => f.file).filter((f) => Boolean(f));
|
|
@@ -32389,9 +32504,9 @@ function tally2(values) {
|
|
|
32389
32504
|
// src/health/baseline.ts
|
|
32390
32505
|
init_fs();
|
|
32391
32506
|
import { mkdir as mkdir26, readFile as readFile45, writeFile as writeFile19 } from "fs/promises";
|
|
32392
|
-
import
|
|
32507
|
+
import path88 from "path";
|
|
32393
32508
|
function baselinePath(cwd) {
|
|
32394
|
-
return
|
|
32509
|
+
return path88.join(cwd, ".metaproject", "health", "baselines", "scores.json");
|
|
32395
32510
|
}
|
|
32396
32511
|
async function loadBaseline(cwd) {
|
|
32397
32512
|
const file = baselinePath(cwd);
|
|
@@ -32423,7 +32538,7 @@ async function writeBaseline(cwd, metrics, generatedAt, selector) {
|
|
|
32423
32538
|
scopes[key] = value;
|
|
32424
32539
|
}
|
|
32425
32540
|
const file = baselinePath(cwd);
|
|
32426
|
-
await mkdir26(
|
|
32541
|
+
await mkdir26(path88.dirname(file), { recursive: true });
|
|
32427
32542
|
await writeFile19(file, `${JSON.stringify({ generatedAt, scopes }, null, 2)}
|
|
32428
32543
|
`, "utf8");
|
|
32429
32544
|
return updated;
|
|
@@ -32477,10 +32592,10 @@ async function getChurn(cwd, windowDays) {
|
|
|
32477
32592
|
|
|
32478
32593
|
// src/health/metrics/wiki-freshness.ts
|
|
32479
32594
|
import { readFile as readFile46, stat as stat14 } from "fs/promises";
|
|
32480
|
-
import
|
|
32595
|
+
import path89 from "path";
|
|
32481
32596
|
var DEFAULT_STALE_EVIDENCE_DAYS = 7;
|
|
32482
32597
|
function freshnessReportPath(cwd) {
|
|
32483
|
-
return
|
|
32598
|
+
return path89.join(cwd, ".metaproject", "data", "wiki", "freshness", "latest.json");
|
|
32484
32599
|
}
|
|
32485
32600
|
async function readWikiFreshnessMetric(cwd, options = {}) {
|
|
32486
32601
|
const file = freshnessReportPath(cwd);
|
|
@@ -32501,7 +32616,7 @@ async function readWikiFreshnessMetric(cwd, options = {}) {
|
|
|
32501
32616
|
} catch {
|
|
32502
32617
|
return {
|
|
32503
32618
|
status: "unreadable-report",
|
|
32504
|
-
reason: `${
|
|
32619
|
+
reason: `${path89.relative(cwd, file)} is not valid JSON; re-run \`keryx wiki freshness\`.`
|
|
32505
32620
|
};
|
|
32506
32621
|
}
|
|
32507
32622
|
const report = parsed;
|
|
@@ -32511,7 +32626,7 @@ async function readWikiFreshnessMetric(cwd, options = {}) {
|
|
|
32511
32626
|
if (pagesTotal === null || pagesFresh === null) {
|
|
32512
32627
|
return {
|
|
32513
32628
|
status: "unreadable-report",
|
|
32514
|
-
reason: `${
|
|
32629
|
+
reason: `${path89.relative(cwd, file)} is missing its totals; re-run \`keryx wiki freshness\`.`
|
|
32515
32630
|
};
|
|
32516
32631
|
}
|
|
32517
32632
|
const pagesUndecidable = numberOr3(totals.pagesUndecidable) ?? 0;
|
|
@@ -32565,12 +32680,12 @@ function renderWikiFreshnessLine(metric) {
|
|
|
32565
32680
|
}
|
|
32566
32681
|
|
|
32567
32682
|
// src/health/sources/helpers.ts
|
|
32568
|
-
import
|
|
32683
|
+
import path90 from "path";
|
|
32569
32684
|
import { existsSync as existsSync8 } from "fs";
|
|
32570
32685
|
class NoImportError extends Error {
|
|
32571
32686
|
}
|
|
32572
32687
|
function resolveBin(cwd, name) {
|
|
32573
|
-
const local =
|
|
32688
|
+
const local = path90.join(cwd, "node_modules", ".bin", name);
|
|
32574
32689
|
if (existsSync8(local)) {
|
|
32575
32690
|
return local;
|
|
32576
32691
|
}
|
|
@@ -32651,13 +32766,13 @@ async function getComplexityFindings(cwd, sourceFiles, config, sourceAnalysis) {
|
|
|
32651
32766
|
|
|
32652
32767
|
// src/health/metrics/coverage.ts
|
|
32653
32768
|
import { existsSync as existsSync9 } from "fs";
|
|
32654
|
-
import
|
|
32769
|
+
import path91 from "path";
|
|
32655
32770
|
var SUMMARY_PATHS = [
|
|
32656
32771
|
"coverage/coverage-summary.json",
|
|
32657
32772
|
"coverage/coverage-final.json"
|
|
32658
32773
|
];
|
|
32659
32774
|
async function getCoverage(cwd) {
|
|
32660
|
-
const summary = SUMMARY_PATHS.map((rel) =>
|
|
32775
|
+
const summary = SUMMARY_PATHS.map((rel) => path91.join(cwd, rel)).find((abs) => existsSync9(abs));
|
|
32661
32776
|
if (!summary) {
|
|
32662
32777
|
return { status: "missing", total: null, byFile: new Map };
|
|
32663
32778
|
}
|
|
@@ -32678,7 +32793,7 @@ async function getCoverage(cwd) {
|
|
|
32678
32793
|
total = pct;
|
|
32679
32794
|
continue;
|
|
32680
32795
|
}
|
|
32681
|
-
const relative =
|
|
32796
|
+
const relative = path91.isAbsolute(key) ? path91.relative(cwd, key) : key;
|
|
32682
32797
|
byFile.set(relative.replace(/\\/g, "/"), pct);
|
|
32683
32798
|
}
|
|
32684
32799
|
return { status: "available", total, byFile };
|
|
@@ -32811,10 +32926,10 @@ function renderWikiFreshness(metric) {
|
|
|
32811
32926
|
// src/health/skills.ts
|
|
32812
32927
|
init_fs();
|
|
32813
32928
|
import { readFile as readFile47 } from "fs/promises";
|
|
32814
|
-
import
|
|
32929
|
+
import path92 from "path";
|
|
32815
32930
|
var EMPTY = { skills: [], skillForFile: () => null };
|
|
32816
32931
|
async function loadSkillOwnership(cwd) {
|
|
32817
|
-
const manifestPath =
|
|
32932
|
+
const manifestPath = path92.join(cwd, ".metaproject", "metaproject.json");
|
|
32818
32933
|
if (!await pathExists(manifestPath)) {
|
|
32819
32934
|
return EMPTY;
|
|
32820
32935
|
}
|
|
@@ -32852,7 +32967,7 @@ function normalize(value) {
|
|
|
32852
32967
|
|
|
32853
32968
|
// src/health/sources/eslint.ts
|
|
32854
32969
|
import { existsSync as existsSync10 } from "fs";
|
|
32855
|
-
import
|
|
32970
|
+
import path93 from "path";
|
|
32856
32971
|
var CONFIG_FILES = [
|
|
32857
32972
|
".eslintrc",
|
|
32858
32973
|
".eslintrc.js",
|
|
@@ -32866,7 +32981,7 @@ var CONFIG_FILES = [
|
|
|
32866
32981
|
"eslint.config.ts"
|
|
32867
32982
|
];
|
|
32868
32983
|
function hasConfig(cwd) {
|
|
32869
|
-
return CONFIG_FILES.some((file) => existsSync10(
|
|
32984
|
+
return CONFIG_FILES.some((file) => existsSync10(path93.join(cwd, file)));
|
|
32870
32985
|
}
|
|
32871
32986
|
var eslintAdapter = {
|
|
32872
32987
|
id: "eslint",
|
|
@@ -32891,7 +33006,7 @@ var eslintAdapter = {
|
|
|
32891
33006
|
};
|
|
32892
33007
|
},
|
|
32893
33008
|
async import(ctx) {
|
|
32894
|
-
const report =
|
|
33009
|
+
const report = path93.join(ctx.cwd, "eslint-report.json");
|
|
32895
33010
|
if (!existsSync10(report)) {
|
|
32896
33011
|
throw new NoImportError("no eslint-report.json");
|
|
32897
33012
|
}
|
|
@@ -32918,7 +33033,7 @@ var eslintAdapter = {
|
|
|
32918
33033
|
}
|
|
32919
33034
|
const findings = [];
|
|
32920
33035
|
for (const file of data) {
|
|
32921
|
-
const relative =
|
|
33036
|
+
const relative = path93.isAbsolute(file.filePath) ? path93.relative(ctx.cwd, file.filePath) : file.filePath;
|
|
32922
33037
|
for (const message of file.messages ?? []) {
|
|
32923
33038
|
const isError = message.severity === 2;
|
|
32924
33039
|
findings.push(makeFinding({
|
|
@@ -32950,9 +33065,9 @@ var eslintAdapter = {
|
|
|
32950
33065
|
|
|
32951
33066
|
// src/health/sources/typescript.ts
|
|
32952
33067
|
import { existsSync as existsSync11 } from "fs";
|
|
32953
|
-
import
|
|
33068
|
+
import path94 from "path";
|
|
32954
33069
|
function hasTsconfig(cwd) {
|
|
32955
|
-
return existsSync11(
|
|
33070
|
+
return existsSync11(path94.join(cwd, "tsconfig.json"));
|
|
32956
33071
|
}
|
|
32957
33072
|
var typescriptAdapter = {
|
|
32958
33073
|
id: "typescript",
|
|
@@ -33028,7 +33143,7 @@ __export(exports_service6, {
|
|
|
33028
33143
|
});
|
|
33029
33144
|
import { existsSync as existsSync12 } from "fs";
|
|
33030
33145
|
import { readFile as readFile50, readdir as readdir16 } from "fs/promises";
|
|
33031
|
-
import
|
|
33146
|
+
import path99 from "path";
|
|
33032
33147
|
|
|
33033
33148
|
// src/lib/git-env.ts
|
|
33034
33149
|
var GIT_DISCOVERY_OVERRIDE_VARS = [
|
|
@@ -33053,7 +33168,7 @@ function withoutGitDiscoveryOverrides(env) {
|
|
|
33053
33168
|
init_fs();
|
|
33054
33169
|
init_guard();
|
|
33055
33170
|
import { readFile as readFile48 } from "fs/promises";
|
|
33056
|
-
import
|
|
33171
|
+
import path95 from "path";
|
|
33057
33172
|
|
|
33058
33173
|
// src/metrics/record.ts
|
|
33059
33174
|
var RELIABILITIES = new Set(["exact", "estimated", "unknown"]);
|
|
@@ -33068,7 +33183,7 @@ var RETRY_TYPES = new Set([
|
|
|
33068
33183
|
|
|
33069
33184
|
// src/metrics/lifecycle.ts
|
|
33070
33185
|
async function readArtifactPointer(root, expected) {
|
|
33071
|
-
const pointerFile =
|
|
33186
|
+
const pointerFile = path95.join(root, "latest.json");
|
|
33072
33187
|
if (!await pathExists(pointerFile))
|
|
33073
33188
|
return { status: "missing", pointer: null };
|
|
33074
33189
|
let pointer;
|
|
@@ -33077,7 +33192,7 @@ async function readArtifactPointer(root, expected) {
|
|
|
33077
33192
|
} catch {
|
|
33078
33193
|
return { status: "stale", pointer: null, reason: "latest pointer is invalid JSON" };
|
|
33079
33194
|
}
|
|
33080
|
-
const recordFile = pointer.record ?
|
|
33195
|
+
const recordFile = pointer.record ? path95.join(root, pointer.record) : null;
|
|
33081
33196
|
if (!recordFile || !isPathInside(root, recordFile) || !await pathExists(recordFile)) {
|
|
33082
33197
|
return { status: "stale", pointer, reason: "pointer record is missing" };
|
|
33083
33198
|
}
|
|
@@ -33093,9 +33208,9 @@ init_guard();
|
|
|
33093
33208
|
// src/testing/capability.ts
|
|
33094
33209
|
init_fs();
|
|
33095
33210
|
init_json();
|
|
33096
|
-
import
|
|
33211
|
+
import path96 from "path";
|
|
33097
33212
|
async function isTestingCapabilityEnabled(cwd, capability) {
|
|
33098
|
-
const manifestPath =
|
|
33213
|
+
const manifestPath = path96.join(cwd, ".metaproject", "metaproject.json");
|
|
33099
33214
|
if (!await pathExists(manifestPath)) {
|
|
33100
33215
|
return false;
|
|
33101
33216
|
}
|
|
@@ -33121,10 +33236,10 @@ async function isTestingCapabilityEnabled(cwd, capability) {
|
|
|
33121
33236
|
init_fs();
|
|
33122
33237
|
init_guard();
|
|
33123
33238
|
import { readFile as readFile49, mkdir as mkdir27, writeFile as writeFile20 } from "fs/promises";
|
|
33124
|
-
import
|
|
33239
|
+
import path97 from "path";
|
|
33125
33240
|
var COVERAGE_MAP_SCHEMA_VERSION = 1;
|
|
33126
33241
|
function coverageMapPath(cwd, cfg) {
|
|
33127
|
-
return
|
|
33242
|
+
return path97.isAbsolute(cfg.coverageMap.artifact) ? cfg.coverageMap.artifact : path97.join(cwd, cfg.coverageMap.artifact);
|
|
33128
33243
|
}
|
|
33129
33244
|
async function loadCoverageMap(cwd, cfg) {
|
|
33130
33245
|
const file = coverageMapPath(cwd, cfg);
|
|
@@ -33198,20 +33313,20 @@ function normalizePath4(file) {
|
|
|
33198
33313
|
}
|
|
33199
33314
|
|
|
33200
33315
|
// src/testing/selection.ts
|
|
33201
|
-
import
|
|
33316
|
+
import path98 from "path";
|
|
33202
33317
|
var TEST_FILE_RE = /(^|\/)(__tests__\/.*|.*\.(test|spec)\.[cm]?[tj]sx?$|e2e\/.*\.[cm]?[tj]sx?$|tests\/.*\.[cm]?[tj]sx?$)/;
|
|
33203
33318
|
function normalizePath5(file) {
|
|
33204
33319
|
return file.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
33205
33320
|
}
|
|
33206
33321
|
function relatedByNamingAndDirectory(target, testFiles) {
|
|
33207
33322
|
const normalized = normalizePath5(target);
|
|
33208
|
-
const ext =
|
|
33323
|
+
const ext = path98.extname(normalized);
|
|
33209
33324
|
const withoutExt = ext ? normalized.slice(0, -ext.length) : normalized;
|
|
33210
|
-
const base =
|
|
33211
|
-
const dir =
|
|
33325
|
+
const base = path98.basename(withoutExt);
|
|
33326
|
+
const dir = path98.dirname(normalized);
|
|
33212
33327
|
return testFiles.filter((file) => {
|
|
33213
|
-
const fileDir =
|
|
33214
|
-
const fileBase =
|
|
33328
|
+
const fileDir = path98.dirname(file);
|
|
33329
|
+
const fileBase = path98.basename(file);
|
|
33215
33330
|
return file.startsWith(`${withoutExt}.`) || file.includes(`${withoutExt}.`) || fileDir === dir && fileBase.startsWith(`${base}.`) || fileDir.startsWith(dir) && fileBase.includes(base);
|
|
33216
33331
|
}).sort();
|
|
33217
33332
|
}
|
|
@@ -33341,7 +33456,7 @@ var DEFAULT_TESTING_CONFIG = {
|
|
|
33341
33456
|
}
|
|
33342
33457
|
};
|
|
33343
33458
|
function testingDataRoot(cwd) {
|
|
33344
|
-
return
|
|
33459
|
+
return path99.join(cwd, ".metaproject", "data", "testing");
|
|
33345
33460
|
}
|
|
33346
33461
|
async function computeTestingContext(cwd) {
|
|
33347
33462
|
const { files, incompleteReasons } = await listProjectFiles(cwd);
|
|
@@ -33516,7 +33631,7 @@ async function runTesting(input) {
|
|
|
33516
33631
|
return runResult;
|
|
33517
33632
|
}
|
|
33518
33633
|
async function loadTestingContext(cwd) {
|
|
33519
|
-
const file =
|
|
33634
|
+
const file = path99.join(testingDataRoot(cwd), "context.json");
|
|
33520
33635
|
if (!await pathExists(file)) {
|
|
33521
33636
|
return null;
|
|
33522
33637
|
}
|
|
@@ -33527,18 +33642,18 @@ async function loadTestingContext(cwd) {
|
|
|
33527
33642
|
}
|
|
33528
33643
|
}
|
|
33529
33644
|
async function loadTestingReport(cwd) {
|
|
33530
|
-
const file =
|
|
33645
|
+
const file = path99.join(testingDataRoot(cwd), "artifacts", "latest.json");
|
|
33531
33646
|
if (!await pathExists(file)) {
|
|
33532
33647
|
return null;
|
|
33533
33648
|
}
|
|
33534
33649
|
try {
|
|
33535
33650
|
const latest = JSON.parse(await readFile50(file, "utf8"));
|
|
33536
33651
|
if (typeof latest.record === "string") {
|
|
33537
|
-
const pointer = await readArtifactPointer(
|
|
33652
|
+
const pointer = await readArtifactPointer(path99.join(testingDataRoot(cwd), "artifacts"), await collectGitProvenance(cwd));
|
|
33538
33653
|
if (pointer.status !== "fresh")
|
|
33539
33654
|
return null;
|
|
33540
|
-
const recordFile =
|
|
33541
|
-
if (!isPathInside(
|
|
33655
|
+
const recordFile = path99.join(testingDataRoot(cwd), "artifacts", latest.record);
|
|
33656
|
+
if (!isPathInside(path99.join(testingDataRoot(cwd), "artifacts"), recordFile))
|
|
33542
33657
|
return null;
|
|
33543
33658
|
if (!await pathExists(recordFile))
|
|
33544
33659
|
return null;
|
|
@@ -33585,28 +33700,28 @@ async function ensureContext(cwd) {
|
|
|
33585
33700
|
}
|
|
33586
33701
|
async function writeContext(cwd, context) {
|
|
33587
33702
|
const root = testingDataRoot(cwd);
|
|
33588
|
-
const rel = (p) =>
|
|
33703
|
+
const rel = (p) => path99.relative(cwd, p);
|
|
33589
33704
|
await mkdirContained(cwd, rel(root));
|
|
33590
|
-
await writeContained(cwd, rel(
|
|
33705
|
+
await writeContained(cwd, rel(path99.join(root, "context.json")), `${JSON.stringify(context, null, 2)}
|
|
33591
33706
|
`);
|
|
33592
|
-
await writeContained(cwd, rel(
|
|
33593
|
-
await writeContained(cwd, rel(
|
|
33707
|
+
await writeContained(cwd, rel(path99.join(root, "context.md")), renderContextMarkdown(context));
|
|
33708
|
+
await writeContained(cwd, rel(path99.join(root, "recommendations.md")), renderRecommendationsMarkdown(context));
|
|
33594
33709
|
}
|
|
33595
33710
|
async function writeReport(cwd, report) {
|
|
33596
33711
|
const root = testingDataRoot(cwd);
|
|
33597
|
-
const artifacts =
|
|
33598
|
-
const history =
|
|
33599
|
-
const rel = (p) =>
|
|
33712
|
+
const artifacts = path99.join(root, "artifacts");
|
|
33713
|
+
const history = path99.join(root, "history");
|
|
33714
|
+
const rel = (p) => path99.relative(cwd, p);
|
|
33600
33715
|
await mkdirContained(cwd, rel(artifacts));
|
|
33601
33716
|
await mkdirContained(cwd, rel(history));
|
|
33602
33717
|
const stamp = report.generatedAt.replace(/[:.]/g, "-");
|
|
33603
|
-
const json =
|
|
33604
|
-
const markdown =
|
|
33718
|
+
const json = path99.join(artifacts, "latest.json");
|
|
33719
|
+
const markdown = path99.join(artifacts, "latest.md");
|
|
33605
33720
|
const serialized = `${JSON.stringify(report, null, 2)}
|
|
33606
33721
|
`;
|
|
33607
33722
|
if (report.runId) {
|
|
33608
|
-
const runJson =
|
|
33609
|
-
const runMarkdown =
|
|
33723
|
+
const runJson = path99.join(artifacts, "runs", `${report.runId}.json`);
|
|
33724
|
+
const runMarkdown = path99.join(artifacts, "runs", `${report.runId}.md`);
|
|
33610
33725
|
if (await pathExists(runJson))
|
|
33611
33726
|
throw new Error(`immutable testing run already exists: ${report.runId}`);
|
|
33612
33727
|
await writeContained(cwd, rel(runJson), serialized);
|
|
@@ -33617,26 +33732,26 @@ async function writeReport(cwd, report) {
|
|
|
33617
33732
|
branch: report.provenance?.branch ?? null,
|
|
33618
33733
|
worktree: report.provenance?.worktree ?? null,
|
|
33619
33734
|
generated_at: report.generatedAt,
|
|
33620
|
-
record:
|
|
33735
|
+
record: path99.posix.join("runs", `${report.runId}.json`)
|
|
33621
33736
|
}, null, 2)}
|
|
33622
33737
|
`);
|
|
33623
33738
|
} else {
|
|
33624
33739
|
await writeContained(cwd, rel(json), serialized);
|
|
33625
33740
|
}
|
|
33626
33741
|
await writeContained(cwd, rel(markdown), renderReportMarkdown3(report));
|
|
33627
|
-
await writeContained(cwd, rel(
|
|
33742
|
+
await writeContained(cwd, rel(path99.join(history, `${stamp}.json`)), serialized);
|
|
33628
33743
|
return {
|
|
33629
|
-
markdownPath:
|
|
33630
|
-
jsonPath:
|
|
33744
|
+
markdownPath: path99.relative(cwd, markdown),
|
|
33745
|
+
jsonPath: path99.relative(cwd, json)
|
|
33631
33746
|
};
|
|
33632
33747
|
}
|
|
33633
33748
|
async function writeRawLog(cwd, raw) {
|
|
33634
|
-
const logs =
|
|
33635
|
-
const rel = (p) =>
|
|
33749
|
+
const logs = path99.join(testingDataRoot(cwd), "logs");
|
|
33750
|
+
const rel = (p) => path99.relative(cwd, p);
|
|
33636
33751
|
await mkdirContained(cwd, rel(logs));
|
|
33637
|
-
const latest =
|
|
33752
|
+
const latest = path99.join(logs, "latest.raw.log");
|
|
33638
33753
|
await writeContained(cwd, rel(latest), raw);
|
|
33639
|
-
return
|
|
33754
|
+
return path99.relative(cwd, latest);
|
|
33640
33755
|
}
|
|
33641
33756
|
async function listProjectFiles(cwd) {
|
|
33642
33757
|
const out = [];
|
|
@@ -33649,11 +33764,11 @@ async function walk3(root, dir, out, incompleteReasons) {
|
|
|
33649
33764
|
try {
|
|
33650
33765
|
entries = await readdir16(dir, { withFileTypes: true });
|
|
33651
33766
|
} catch (error) {
|
|
33652
|
-
incompleteReasons.push(`${normalizePath6(
|
|
33767
|
+
incompleteReasons.push(`${normalizePath6(path99.relative(root, dir)) || "."}: ${error instanceof Error ? error.message : String(error)}`);
|
|
33653
33768
|
return;
|
|
33654
33769
|
}
|
|
33655
33770
|
for (const entry of entries) {
|
|
33656
|
-
const abs =
|
|
33771
|
+
const abs = path99.join(dir, entry.name);
|
|
33657
33772
|
if (entry.isDirectory()) {
|
|
33658
33773
|
if (IGNORED_DIRS2.has(entry.name) || entry.name.startsWith(".tmp-")) {
|
|
33659
33774
|
continue;
|
|
@@ -33662,12 +33777,12 @@ async function walk3(root, dir, out, incompleteReasons) {
|
|
|
33662
33777
|
continue;
|
|
33663
33778
|
}
|
|
33664
33779
|
if (entry.isFile()) {
|
|
33665
|
-
out.push(normalizePath6(
|
|
33780
|
+
out.push(normalizePath6(path99.relative(root, abs)));
|
|
33666
33781
|
}
|
|
33667
33782
|
}
|
|
33668
33783
|
}
|
|
33669
33784
|
async function readPackageJson(cwd) {
|
|
33670
|
-
const file =
|
|
33785
|
+
const file = path99.join(cwd, "package.json");
|
|
33671
33786
|
if (!await pathExists(file)) {
|
|
33672
33787
|
return null;
|
|
33673
33788
|
}
|
|
@@ -33678,7 +33793,7 @@ async function readPackageJson(cwd) {
|
|
|
33678
33793
|
}
|
|
33679
33794
|
}
|
|
33680
33795
|
async function loadTestingConfig(cwd) {
|
|
33681
|
-
const file =
|
|
33796
|
+
const file = path99.join(cwd, ".metaproject", "testing.config.json");
|
|
33682
33797
|
if (!await pathExists(file)) {
|
|
33683
33798
|
return DEFAULT_TESTING_CONFIG;
|
|
33684
33799
|
}
|
|
@@ -33743,7 +33858,7 @@ function detectFrameworks(input) {
|
|
|
33743
33858
|
async function extractConventions(cwd, files) {
|
|
33744
33859
|
const conventions = new Set;
|
|
33745
33860
|
for (const file of files.slice(0, 40)) {
|
|
33746
|
-
const abs =
|
|
33861
|
+
const abs = path99.join(cwd, file);
|
|
33747
33862
|
if (!await pathExists(abs)) {
|
|
33748
33863
|
continue;
|
|
33749
33864
|
}
|
|
@@ -33873,7 +33988,7 @@ async function findTestsByImportedTargets(cwd, targets, testFiles) {
|
|
|
33873
33988
|
const targetKeys = new Set(targets.map((target) => modulePathKey(normalizePath6(target))));
|
|
33874
33989
|
const selected = new Set;
|
|
33875
33990
|
for (const testFile of testFiles) {
|
|
33876
|
-
const absoluteTest =
|
|
33991
|
+
const absoluteTest = path99.join(cwd, testFile);
|
|
33877
33992
|
if (!await pathExists(absoluteTest)) {
|
|
33878
33993
|
continue;
|
|
33879
33994
|
}
|
|
@@ -33907,10 +34022,10 @@ function resolveImportPath(cwd, testFile, importPath) {
|
|
|
33907
34022
|
if (!importPath.startsWith(".")) {
|
|
33908
34023
|
return null;
|
|
33909
34024
|
}
|
|
33910
|
-
const importerDir =
|
|
33911
|
-
const absoluteResolved =
|
|
33912
|
-
const relative =
|
|
33913
|
-
if (relative.startsWith(`..${
|
|
34025
|
+
const importerDir = path99.dirname(testFile);
|
|
34026
|
+
const absoluteResolved = path99.resolve(path99.join(cwd, importerDir), importPath);
|
|
34027
|
+
const relative = path99.relative(cwd, absoluteResolved);
|
|
34028
|
+
if (relative.startsWith(`..${path99.sep}`) || relative === "..") {
|
|
33914
34029
|
return null;
|
|
33915
34030
|
}
|
|
33916
34031
|
const relativeNormalized = normalizePath6(relative);
|
|
@@ -33962,13 +34077,13 @@ function resolveTestCommand(cwd, context, input) {
|
|
|
33962
34077
|
}
|
|
33963
34078
|
var BUN_LOCKFILES = ["bun.lock", "bun.lockb"];
|
|
33964
34079
|
function detectPackageManager(cwd) {
|
|
33965
|
-
if (resolveBunBin() && BUN_LOCKFILES.some((name) => pathExistsSync(
|
|
34080
|
+
if (resolveBunBin() && BUN_LOCKFILES.some((name) => pathExistsSync(path99.join(cwd, name)))) {
|
|
33966
34081
|
return "bun";
|
|
33967
34082
|
}
|
|
33968
|
-
if (Bun.which("pnpm") && pathExistsSync(
|
|
34083
|
+
if (Bun.which("pnpm") && pathExistsSync(path99.join(cwd, "pnpm-lock.yaml"))) {
|
|
33969
34084
|
return "pnpm";
|
|
33970
34085
|
}
|
|
33971
|
-
if (Bun.which("yarn") && pathExistsSync(
|
|
34086
|
+
if (Bun.which("yarn") && pathExistsSync(path99.join(cwd, "yarn.lock"))) {
|
|
33972
34087
|
return "yarn";
|
|
33973
34088
|
}
|
|
33974
34089
|
return "npm";
|
|
@@ -34308,7 +34423,7 @@ async function compatibleReportForHealth(ctx) {
|
|
|
34308
34423
|
|
|
34309
34424
|
// src/health/sources/dependency-audit.ts
|
|
34310
34425
|
import { existsSync as existsSync13 } from "fs";
|
|
34311
|
-
import
|
|
34426
|
+
import path100 from "path";
|
|
34312
34427
|
function auditSeverityToPriority(severity) {
|
|
34313
34428
|
if (severity === "critical" || severity === "high")
|
|
34314
34429
|
return "P0";
|
|
@@ -34427,7 +34542,7 @@ var LOCKFILE_COMMANDS = [
|
|
|
34427
34542
|
];
|
|
34428
34543
|
function auditCommand(cwd) {
|
|
34429
34544
|
for (const entry of LOCKFILE_COMMANDS) {
|
|
34430
|
-
if (!entry.lockfiles.some((name) => existsSync13(
|
|
34545
|
+
if (!entry.lockfiles.some((name) => existsSync13(path100.join(cwd, name))))
|
|
34431
34546
|
continue;
|
|
34432
34547
|
const bin = resolveBin(cwd, entry.bin);
|
|
34433
34548
|
if (bin)
|
|
@@ -34486,13 +34601,13 @@ var dependencyAuditAdapter = {
|
|
|
34486
34601
|
|
|
34487
34602
|
// src/health/sources/sonarqube.ts
|
|
34488
34603
|
import { existsSync as existsSync14 } from "fs";
|
|
34489
|
-
import
|
|
34604
|
+
import path101 from "path";
|
|
34490
34605
|
var REPORT_FILES = ["sonar-issues.json", ".metaproject/data/health/sonar-issues.json"];
|
|
34491
34606
|
function reportPath(cwd) {
|
|
34492
34607
|
const fromEnv = process.env.SONAR_ISSUES_FILE;
|
|
34493
34608
|
const candidates = fromEnv ? [fromEnv, ...REPORT_FILES] : REPORT_FILES;
|
|
34494
34609
|
for (const rel of candidates) {
|
|
34495
|
-
const abs =
|
|
34610
|
+
const abs = path101.isAbsolute(rel) ? rel : path101.join(cwd, rel);
|
|
34496
34611
|
if (existsSync14(abs)) {
|
|
34497
34612
|
return abs;
|
|
34498
34613
|
}
|
|
@@ -34576,7 +34691,7 @@ var sonarqubeAdapter = {
|
|
|
34576
34691
|
function relativizeComponent(component, cwd) {
|
|
34577
34692
|
const colon = component.indexOf(":");
|
|
34578
34693
|
const value = colon >= 0 ? component.slice(colon + 1) : component;
|
|
34579
|
-
return
|
|
34694
|
+
return path101.isAbsolute(value) ? path101.relative(cwd, value) : value;
|
|
34580
34695
|
}
|
|
34581
34696
|
|
|
34582
34697
|
// src/health/sources/index.ts
|
|
@@ -34913,19 +35028,19 @@ function filteredInfo(source, cfg) {
|
|
|
34913
35028
|
};
|
|
34914
35029
|
}
|
|
34915
35030
|
async function writeOutputs(cwd, report, config, stamp) {
|
|
34916
|
-
const artifacts =
|
|
34917
|
-
const history =
|
|
35031
|
+
const artifacts = path102.join(dataRoot3(cwd), "artifacts");
|
|
35032
|
+
const history = path102.join(dataRoot3(cwd), "history");
|
|
34918
35033
|
await mkdir28(artifacts, { recursive: true });
|
|
34919
35034
|
await mkdir28(history, { recursive: true });
|
|
34920
|
-
const markdown =
|
|
34921
|
-
const json =
|
|
34922
|
-
const historyJson =
|
|
35035
|
+
const markdown = path102.join(artifacts, "latest.md");
|
|
35036
|
+
const json = path102.join(artifacts, "latest.json");
|
|
35037
|
+
const historyJson = path102.join(history, `${stamp}.json`);
|
|
34923
35038
|
const serialized = `${JSON.stringify(report, null, 2)}
|
|
34924
35039
|
`;
|
|
34925
35040
|
await writeFile21(markdown, renderReportMarkdown2(report, config), "utf8");
|
|
34926
35041
|
if (report.runId) {
|
|
34927
|
-
const runJson =
|
|
34928
|
-
const runMarkdown =
|
|
35042
|
+
const runJson = path102.join(artifacts, "runs", `${report.runId}.json`);
|
|
35043
|
+
const runMarkdown = path102.join(artifacts, "runs", `${report.runId}.md`);
|
|
34929
35044
|
if (await pathExists(runJson))
|
|
34930
35045
|
throw new Error(`immutable health run already exists: ${report.runId}`);
|
|
34931
35046
|
await writeFileAtomic(runJson, serialized);
|
|
@@ -34936,7 +35051,7 @@ async function writeOutputs(cwd, report, config, stamp) {
|
|
|
34936
35051
|
branch: report.provenance?.branch ?? null,
|
|
34937
35052
|
worktree: report.provenance?.worktree ?? null,
|
|
34938
35053
|
generated_at: report.generatedAt,
|
|
34939
|
-
record:
|
|
35054
|
+
record: path102.posix.join("runs", `${report.runId}.json`)
|
|
34940
35055
|
}, null, 2)}
|
|
34941
35056
|
`);
|
|
34942
35057
|
} else {
|
|
@@ -34944,8 +35059,8 @@ async function writeOutputs(cwd, report, config, stamp) {
|
|
|
34944
35059
|
}
|
|
34945
35060
|
await writeFile21(historyJson, serialized, "utf8");
|
|
34946
35061
|
return {
|
|
34947
|
-
markdownPath:
|
|
34948
|
-
jsonPath:
|
|
35062
|
+
markdownPath: path102.relative(cwd, markdown),
|
|
35063
|
+
jsonPath: path102.relative(cwd, json)
|
|
34949
35064
|
};
|
|
34950
35065
|
}
|
|
34951
35066
|
async function resolveChanged(cwd, selector) {
|
|
@@ -34998,7 +35113,7 @@ function hasGateShape(value) {
|
|
|
34998
35113
|
return Array.isArray(report.metrics) && Array.isArray(report.sources) && Array.isArray(report.findings);
|
|
34999
35114
|
}
|
|
35000
35115
|
async function readLatest(cwd) {
|
|
35001
|
-
const file =
|
|
35116
|
+
const file = path103.join(dataRoot3(cwd), "artifacts", "latest.json");
|
|
35002
35117
|
if (!await pathExists(file)) {
|
|
35003
35118
|
return null;
|
|
35004
35119
|
}
|
|
@@ -35009,11 +35124,11 @@ async function readLatest(cwd) {
|
|
|
35009
35124
|
const latest = read.value;
|
|
35010
35125
|
const record = latest.record;
|
|
35011
35126
|
if (typeof record === "string") {
|
|
35012
|
-
const pointer = await readArtifactPointer(
|
|
35127
|
+
const pointer = await readArtifactPointer(path103.join(dataRoot3(cwd), "artifacts"), await collectGitProvenance(cwd));
|
|
35013
35128
|
if (pointer.status !== "fresh")
|
|
35014
35129
|
return null;
|
|
35015
|
-
const recordFile =
|
|
35016
|
-
if (!isPathInside(
|
|
35130
|
+
const recordFile = path103.join(dataRoot3(cwd), "artifacts", record);
|
|
35131
|
+
if (!isPathInside(path103.join(dataRoot3(cwd), "artifacts"), recordFile))
|
|
35017
35132
|
return null;
|
|
35018
35133
|
if (!await pathExists(recordFile))
|
|
35019
35134
|
return null;
|
|
@@ -35086,7 +35201,7 @@ function createCodeHealthService() {
|
|
|
35086
35201
|
return {
|
|
35087
35202
|
run: (input) => runHealth(input),
|
|
35088
35203
|
async status(input) {
|
|
35089
|
-
const enabled = await pathExists(
|
|
35204
|
+
const enabled = await pathExists(path103.join(input.cwd, ".metaproject", "health.config.json"));
|
|
35090
35205
|
const latest = await readLatest(input.cwd);
|
|
35091
35206
|
const project = latest?.metrics.find((m) => m.key === "project") ?? null;
|
|
35092
35207
|
const decliningScopes = latest ? latest.metrics.filter((m) => m.regression_score > 0).length : 0;
|
|
@@ -35244,10 +35359,10 @@ function renderEvidenceBlock(evidences, siblings) {
|
|
|
35244
35359
|
init_fs();
|
|
35245
35360
|
init_contained_write();
|
|
35246
35361
|
init_json();
|
|
35247
|
-
import
|
|
35362
|
+
import path104 from "path";
|
|
35248
35363
|
import { createHash as createHash17 } from "crypto";
|
|
35249
35364
|
function impactEvidenceDataRoot(root) {
|
|
35250
|
-
return
|
|
35365
|
+
return path104.join(root, ".metaproject", "data", "security", "impact-evidence");
|
|
35251
35366
|
}
|
|
35252
35367
|
function sanitizeSessionId(sessionId) {
|
|
35253
35368
|
const cleaned = sessionId.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
@@ -35259,7 +35374,7 @@ function sessionStateFilename(sessionId) {
|
|
|
35259
35374
|
return `${sanitized}-${suffix}.json`;
|
|
35260
35375
|
}
|
|
35261
35376
|
function sessionStatePath(root, sessionId) {
|
|
35262
|
-
return
|
|
35377
|
+
return path104.join(impactEvidenceDataRoot(root), "sessions", sessionStateFilename(sessionId));
|
|
35263
35378
|
}
|
|
35264
35379
|
async function loadSessionState(root, sessionId) {
|
|
35265
35380
|
const file = sessionStatePath(root, sessionId);
|
|
@@ -35278,11 +35393,11 @@ async function loadSessionState(root, sessionId) {
|
|
|
35278
35393
|
}
|
|
35279
35394
|
async function saveSessionState(root, sessionId, state) {
|
|
35280
35395
|
const file = sessionStatePath(root, sessionId);
|
|
35281
|
-
await writeContained(root,
|
|
35396
|
+
await writeContained(root, path104.relative(root, file), `${JSON.stringify(state, null, 2)}
|
|
35282
35397
|
`);
|
|
35283
35398
|
}
|
|
35284
35399
|
function logPath(root) {
|
|
35285
|
-
return
|
|
35400
|
+
return path104.join(impactEvidenceDataRoot(root), "log.jsonl");
|
|
35286
35401
|
}
|
|
35287
35402
|
async function appendLogRecord(root, record) {
|
|
35288
35403
|
const full = {
|
|
@@ -35293,7 +35408,7 @@ async function appendLogRecord(root, record) {
|
|
|
35293
35408
|
...record.detail !== undefined ? { detail: record.detail } : {}
|
|
35294
35409
|
};
|
|
35295
35410
|
const file = logPath(root);
|
|
35296
|
-
await appendContained(root,
|
|
35411
|
+
await appendContained(root, path104.relative(root, file), `${JSON.stringify(full)}
|
|
35297
35412
|
`);
|
|
35298
35413
|
return full;
|
|
35299
35414
|
}
|
|
@@ -35320,7 +35435,7 @@ init_command_risk();
|
|
|
35320
35435
|
init_shell_syntax();
|
|
35321
35436
|
init_fs();
|
|
35322
35437
|
init_service2();
|
|
35323
|
-
import
|
|
35438
|
+
import path105 from "path";
|
|
35324
35439
|
import { createHash as createHash18 } from "crypto";
|
|
35325
35440
|
import { realpathSync as realpathSync2 } from "fs";
|
|
35326
35441
|
function impactEvidenceHookClass(strict) {
|
|
@@ -35336,29 +35451,29 @@ function realpathNearestExisting(p) {
|
|
|
35336
35451
|
for (;; ) {
|
|
35337
35452
|
try {
|
|
35338
35453
|
const real = realpathSync2(current);
|
|
35339
|
-
return tail.length > 0 ?
|
|
35454
|
+
return tail.length > 0 ? path105.join(real, ...tail) : real;
|
|
35340
35455
|
} catch {
|
|
35341
|
-
const parent =
|
|
35456
|
+
const parent = path105.dirname(current);
|
|
35342
35457
|
if (parent === current) {
|
|
35343
|
-
return tail.length > 0 ?
|
|
35458
|
+
return tail.length > 0 ? path105.join(current, ...tail) : current;
|
|
35344
35459
|
}
|
|
35345
|
-
tail.unshift(
|
|
35460
|
+
tail.unshift(path105.basename(current));
|
|
35346
35461
|
current = parent;
|
|
35347
35462
|
}
|
|
35348
35463
|
}
|
|
35349
35464
|
}
|
|
35350
35465
|
function normalizeRequestFiles(root, files) {
|
|
35351
|
-
const rootReal = realpathNearestExisting(
|
|
35466
|
+
const rootReal = realpathNearestExisting(path105.resolve(root));
|
|
35352
35467
|
const normalized = [];
|
|
35353
35468
|
const rejected = [];
|
|
35354
35469
|
for (const file of files) {
|
|
35355
|
-
const lexicalAbsolute =
|
|
35470
|
+
const lexicalAbsolute = path105.isAbsolute(file) ? path105.resolve(file) : path105.resolve(rootReal, toPosix(file).replace(/^\.\//, ""));
|
|
35356
35471
|
const effective = realpathNearestExisting(lexicalAbsolute);
|
|
35357
35472
|
if (!isPathInside(rootReal, effective)) {
|
|
35358
35473
|
rejected.push(file);
|
|
35359
35474
|
continue;
|
|
35360
35475
|
}
|
|
35361
|
-
normalized.push(toPosix(
|
|
35476
|
+
normalized.push(toPosix(path105.relative(rootReal, effective)));
|
|
35362
35477
|
}
|
|
35363
35478
|
return { files: [...new Set(normalized)], rejected };
|
|
35364
35479
|
}
|
|
@@ -35644,7 +35759,7 @@ __export(exports_service8, {
|
|
|
35644
35759
|
createJobService: () => createJobService
|
|
35645
35760
|
});
|
|
35646
35761
|
import { copyFile, mkdir as mkdir30 } from "fs/promises";
|
|
35647
|
-
import
|
|
35762
|
+
import path108 from "path";
|
|
35648
35763
|
|
|
35649
35764
|
// src/job/types.ts
|
|
35650
35765
|
var JOB_INTENTS = ["implement", "analyze", "review", "custom"];
|
|
@@ -35785,15 +35900,15 @@ init_validator();
|
|
|
35785
35900
|
init_contracts();
|
|
35786
35901
|
init_fs();
|
|
35787
35902
|
import { appendFile as appendFile6, mkdir as mkdir29, readFile as readFile52, readdir as readdir17 } from "fs/promises";
|
|
35788
|
-
import
|
|
35903
|
+
import path107 from "path";
|
|
35789
35904
|
function jobsRoot(cwd) {
|
|
35790
|
-
return
|
|
35905
|
+
return path107.join(cwd, ".metaproject", "jobs");
|
|
35791
35906
|
}
|
|
35792
35907
|
function jobDir(cwd, name) {
|
|
35793
|
-
return
|
|
35908
|
+
return path107.join(jobsRoot(cwd), name);
|
|
35794
35909
|
}
|
|
35795
35910
|
function jobStatePath(cwd, name) {
|
|
35796
|
-
return
|
|
35911
|
+
return path107.join(jobDir(cwd, name), "state.json");
|
|
35797
35912
|
}
|
|
35798
35913
|
var JOB_NAME_PATTERN = /^[a-z0-9-]+$/;
|
|
35799
35914
|
function assertJobName(name) {
|
|
@@ -35830,12 +35945,12 @@ async function writeJob(cwd, name, state) {
|
|
|
35830
35945
|
`));
|
|
35831
35946
|
}
|
|
35832
35947
|
const file = jobStatePath(cwd, name);
|
|
35833
|
-
await mkdir29(
|
|
35948
|
+
await mkdir29(path107.dirname(file), { recursive: true });
|
|
35834
35949
|
await writeFileAtomic(file, `${JSON.stringify(state, null, 2)}
|
|
35835
35950
|
`);
|
|
35836
35951
|
}
|
|
35837
35952
|
async function appendJournal2(cwd, name, at, line) {
|
|
35838
|
-
await appendFile6(
|
|
35953
|
+
await appendFile6(path107.join(jobDir(cwd, name), "journal.md"), `- ${at} - ${line}
|
|
35839
35954
|
`, "utf8");
|
|
35840
35955
|
}
|
|
35841
35956
|
function renderJournal2(name, at) {
|
|
@@ -35856,7 +35971,7 @@ function assertDocumentType(raw) {
|
|
|
35856
35971
|
return raw;
|
|
35857
35972
|
}
|
|
35858
35973
|
function documentFileName(type, sourcePath) {
|
|
35859
|
-
const extension =
|
|
35974
|
+
const extension = path107.extname(sourcePath) || ".md";
|
|
35860
35975
|
return `${type}${extension}`;
|
|
35861
35976
|
}
|
|
35862
35977
|
|
|
@@ -35864,7 +35979,7 @@ function documentFileName(type, sourcePath) {
|
|
|
35864
35979
|
function createJobService(deps) {
|
|
35865
35980
|
const now = () => deps.now().toISOString();
|
|
35866
35981
|
function lockPath(cwd, name) {
|
|
35867
|
-
return
|
|
35982
|
+
return path108.join(jobsRoot(cwd), `.job-lock-${name}`);
|
|
35868
35983
|
}
|
|
35869
35984
|
async function mutate(cwd, name, run) {
|
|
35870
35985
|
assertJobName(name);
|
|
@@ -35913,20 +36028,20 @@ function createJobService(deps) {
|
|
|
35913
36028
|
},
|
|
35914
36029
|
plan: { steps: defaultPlan(intent) },
|
|
35915
36030
|
documentation: {
|
|
35916
|
-
job_path:
|
|
36031
|
+
job_path: path108.join(".metaproject", "jobs", name),
|
|
35917
36032
|
documents_created: []
|
|
35918
36033
|
},
|
|
35919
36034
|
metrics: { steps: [] },
|
|
35920
|
-
jobs_root:
|
|
36035
|
+
jobs_root: path108.join(".metaproject", "jobs"),
|
|
35921
36036
|
updated_at: createdAt
|
|
35922
36037
|
};
|
|
35923
36038
|
const first = firstOpenStep(state.plan.steps);
|
|
35924
36039
|
if (first) {
|
|
35925
36040
|
state.plan.current_step = first.id;
|
|
35926
36041
|
}
|
|
35927
|
-
await writeFileAtomic(
|
|
36042
|
+
await writeFileAtomic(path108.join(absolute, "journal.md"), renderJournal2(name, createdAt));
|
|
35928
36043
|
await writeJob(input.cwd, name, state);
|
|
35929
|
-
return { state, dir:
|
|
36044
|
+
return { state, dir: path108.relative(input.cwd, absolute) };
|
|
35930
36045
|
},
|
|
35931
36046
|
async status({ cwd, name }) {
|
|
35932
36047
|
assertJobName(name);
|
|
@@ -35938,7 +36053,7 @@ function createJobService(deps) {
|
|
|
35938
36053
|
}
|
|
35939
36054
|
return {
|
|
35940
36055
|
state,
|
|
35941
|
-
dir:
|
|
36056
|
+
dir: path108.join(".metaproject", "jobs", name),
|
|
35942
36057
|
stepsDone: state.plan.steps.filter((step) => isTerminalStep(step.status)).length,
|
|
35943
36058
|
stepsTotal: state.plan.steps.length,
|
|
35944
36059
|
nextStep: firstOpenStep(state.plan.steps),
|
|
@@ -35995,23 +36110,23 @@ function createJobService(deps) {
|
|
|
35995
36110
|
if (!input.file) {
|
|
35996
36111
|
throw new Error("Missing --file. Usage: keryx job document <name> --type <type> --file <path>");
|
|
35997
36112
|
}
|
|
35998
|
-
const source =
|
|
36113
|
+
const source = path108.isAbsolute(input.file) ? input.file : path108.join(input.cwd, input.file);
|
|
35999
36114
|
if (!await pathExists(source)) {
|
|
36000
36115
|
throw new Error(`--file not found: ${input.file}. Write the document first, then record it.`);
|
|
36001
36116
|
}
|
|
36002
36117
|
let recorded;
|
|
36003
36118
|
await mutate(input.cwd, input.name, async (state) => {
|
|
36004
36119
|
const fileName = documentFileName(type, source);
|
|
36005
|
-
const target =
|
|
36120
|
+
const target = path108.join(jobDir(input.cwd, state.job_name), fileName);
|
|
36006
36121
|
await copyFile(source, target);
|
|
36007
36122
|
state.documentation ??= {};
|
|
36008
|
-
state.documentation.job_path ??=
|
|
36123
|
+
state.documentation.job_path ??= path108.join(".metaproject", "jobs", state.job_name);
|
|
36009
36124
|
const created = state.documentation.documents_created ?? [];
|
|
36010
36125
|
state.documentation.documents_created = created.includes(fileName) ? created : [...created, fileName];
|
|
36011
36126
|
recorded = {
|
|
36012
36127
|
state,
|
|
36013
36128
|
document: fileName,
|
|
36014
|
-
path:
|
|
36129
|
+
path: path108.join(".metaproject", "jobs", state.job_name, fileName)
|
|
36015
36130
|
};
|
|
36016
36131
|
return { state, event: "document", detail: `${type} -> ${fileName}` };
|
|
36017
36132
|
});
|
|
@@ -36046,7 +36161,7 @@ function createJobService(deps) {
|
|
|
36046
36161
|
name: state.job_name,
|
|
36047
36162
|
phase: state.phase,
|
|
36048
36163
|
intent: state.intent,
|
|
36049
|
-
dir:
|
|
36164
|
+
dir: path108.join(".metaproject", "jobs", name),
|
|
36050
36165
|
stepsDone: state.plan.steps.filter((step) => isTerminalStep(step.status)).length,
|
|
36051
36166
|
stepsTotal: state.plan.steps.length,
|
|
36052
36167
|
nextStep: firstOpenStep(state.plan.steps)?.id ?? null
|
|
@@ -36151,12 +36266,12 @@ function normalizeWorkspaceReference(raw) {
|
|
|
36151
36266
|
// src/sac/fwk-service.ts
|
|
36152
36267
|
init_assembly();
|
|
36153
36268
|
import { appendFile as appendFile7, mkdir as mkdir32, open as open4, readFile as readFile55, rename as rename7, rm as rm6, stat as stat15, writeFile as writeFile22 } from "fs/promises";
|
|
36154
|
-
import
|
|
36269
|
+
import path112 from "path";
|
|
36155
36270
|
|
|
36156
36271
|
// src/sac/index.ts
|
|
36157
36272
|
import { access as access3, readFile as readFile53, realpath as realpath12 } from "fs/promises";
|
|
36158
36273
|
import { createHash as createHash19 } from "crypto";
|
|
36159
|
-
import
|
|
36274
|
+
import path109 from "path";
|
|
36160
36275
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
36161
36276
|
var idPattern = /^[a-z][a-z0-9-]{2,63}$/;
|
|
36162
36277
|
var subjectPattern = /^(?:user|team|service|agent):[a-z0-9][a-z0-9._-]{0,127}$/;
|
|
@@ -36174,21 +36289,21 @@ var normativeSchemaFiles = {
|
|
|
36174
36289
|
"review-decision": "review-decision.schema.json"
|
|
36175
36290
|
};
|
|
36176
36291
|
var normativeSchemas = new Map;
|
|
36177
|
-
var NORMATIVE_SCHEMA_DIR =
|
|
36292
|
+
var NORMATIVE_SCHEMA_DIR = path109.join("docs", "requirements", "shared-agent-context", "schemas");
|
|
36178
36293
|
async function resolveSacNormativeSchemaPath(fileName, searchFrom = [fileURLToPath3(new URL(".", import.meta.url)), process.cwd()]) {
|
|
36179
36294
|
const seen = new Set;
|
|
36180
36295
|
for (const start of searchFrom) {
|
|
36181
|
-
let dir =
|
|
36296
|
+
let dir = path109.resolve(start);
|
|
36182
36297
|
for (let i = 0;i < 10; i++) {
|
|
36183
36298
|
if (seen.has(dir))
|
|
36184
36299
|
break;
|
|
36185
36300
|
seen.add(dir);
|
|
36186
|
-
const candidate =
|
|
36301
|
+
const candidate = path109.join(dir, NORMATIVE_SCHEMA_DIR, fileName);
|
|
36187
36302
|
try {
|
|
36188
36303
|
await access3(candidate);
|
|
36189
36304
|
return candidate;
|
|
36190
36305
|
} catch {}
|
|
36191
|
-
const parent =
|
|
36306
|
+
const parent = path109.dirname(dir);
|
|
36192
36307
|
if (parent === dir)
|
|
36193
36308
|
break;
|
|
36194
36309
|
dir = parent;
|
|
@@ -36857,12 +36972,12 @@ class SacReferenceError extends Error {
|
|
|
36857
36972
|
code = "unsafe_workspace_reference";
|
|
36858
36973
|
}
|
|
36859
36974
|
async function resolveWorkspaceReference(input) {
|
|
36860
|
-
if (!workspacePathPattern.test(input.uri) ||
|
|
36975
|
+
if (!workspacePathPattern.test(input.uri) || path109.isAbsolute(input.uri) || /^[a-z][a-z0-9+.-]*:/i.test(input.uri) || input.uri.includes("\\"))
|
|
36861
36976
|
throw new SacReferenceError("unsafe workspace reference");
|
|
36862
|
-
const lexicalRoot =
|
|
36977
|
+
const lexicalRoot = path109.resolve(input.workspaceRoot);
|
|
36863
36978
|
const root = await realpath12(lexicalRoot);
|
|
36864
|
-
const candidate =
|
|
36865
|
-
if (candidate !== lexicalRoot && !candidate.startsWith(`${lexicalRoot}${
|
|
36979
|
+
const candidate = path109.resolve(lexicalRoot, input.uri.slice(2));
|
|
36980
|
+
if (candidate !== lexicalRoot && !candidate.startsWith(`${lexicalRoot}${path109.sep}`))
|
|
36866
36981
|
throw new SacReferenceError("workspace reference escapes root");
|
|
36867
36982
|
let resolved;
|
|
36868
36983
|
try {
|
|
@@ -36870,7 +36985,7 @@ async function resolveWorkspaceReference(input) {
|
|
|
36870
36985
|
} catch {
|
|
36871
36986
|
throw new SacReferenceError("workspace reference is not resolvable");
|
|
36872
36987
|
}
|
|
36873
|
-
if (resolved !== root && !resolved.startsWith(`${root}${
|
|
36988
|
+
if (resolved !== root && !resolved.startsWith(`${root}${path109.sep}`))
|
|
36874
36989
|
throw new SacReferenceError("workspace reference escapes root after realpath");
|
|
36875
36990
|
return candidate;
|
|
36876
36991
|
}
|
|
@@ -36926,16 +37041,16 @@ async function evaluateStrictSacGuard(input) {
|
|
|
36926
37041
|
init_fs();
|
|
36927
37042
|
import { mkdir as mkdir31, readdir as readdir18, readFile as readFile54 } from "fs/promises";
|
|
36928
37043
|
import { createHash as createHash20, randomUUID as randomUUID3 } from "crypto";
|
|
36929
|
-
import
|
|
37044
|
+
import path111 from "path";
|
|
36930
37045
|
|
|
36931
37046
|
// src/sac/secure-resource-read.ts
|
|
36932
37047
|
init_contained_read();
|
|
36933
37048
|
init_descriptor_read();
|
|
36934
|
-
import
|
|
37049
|
+
import path110 from "path";
|
|
36935
37050
|
function readWorkspaceFileNoFollow(workspaceRoot, absolutePath) {
|
|
36936
|
-
const relativePath =
|
|
36937
|
-
const components = relativePath.split(
|
|
36938
|
-
if (!relativePath ||
|
|
37051
|
+
const relativePath = path110.relative(workspaceRoot, absolutePath);
|
|
37052
|
+
const components = relativePath.split(path110.sep);
|
|
37053
|
+
if (!relativePath || path110.isAbsolute(relativePath) || components.some((component) => !component || component === "." || component === "..")) {
|
|
36939
37054
|
throw new Error("safe source path is not workspace-relative");
|
|
36940
37055
|
}
|
|
36941
37056
|
return readDescriptorChain(workspaceRoot, absolutePath, {
|
|
@@ -36962,8 +37077,8 @@ class WorkspaceService {
|
|
|
36962
37077
|
now;
|
|
36963
37078
|
constructor(options) {
|
|
36964
37079
|
this.options = options;
|
|
36965
|
-
this.root =
|
|
36966
|
-
this.storageRoot =
|
|
37080
|
+
this.root = path111.resolve(options.workspaceRoot);
|
|
37081
|
+
this.storageRoot = path111.resolve(options.storageRoot ?? path111.join(this.root, ".metaproject", "workspaces"));
|
|
36967
37082
|
this.now = options.now ?? (() => new Date);
|
|
36968
37083
|
}
|
|
36969
37084
|
async create(input) {
|
|
@@ -37288,13 +37403,13 @@ class WorkspaceService {
|
|
|
37288
37403
|
return parsed;
|
|
37289
37404
|
}
|
|
37290
37405
|
workspaceDir(id) {
|
|
37291
|
-
return
|
|
37406
|
+
return path111.join(this.storageRoot, id);
|
|
37292
37407
|
}
|
|
37293
37408
|
manifestPath(id) {
|
|
37294
|
-
return
|
|
37409
|
+
return path111.join(this.workspaceDir(id), "workspace.json");
|
|
37295
37410
|
}
|
|
37296
37411
|
lockPath(id) {
|
|
37297
|
-
return
|
|
37412
|
+
return path111.join(this.storageRoot, `.${id}.lock`);
|
|
37298
37413
|
}
|
|
37299
37414
|
timestamp() {
|
|
37300
37415
|
return this.now().toISOString();
|
|
@@ -38083,7 +38198,7 @@ function hasReportIntegrity(report) {
|
|
|
38083
38198
|
return reportHashPattern.test(reportDigest) && sha2565(body) === reportDigest;
|
|
38084
38199
|
}
|
|
38085
38200
|
async function resolvePolicySelection(workspaceRoot, canonicalFallback) {
|
|
38086
|
-
const configPath =
|
|
38201
|
+
const configPath = path112.join(workspaceRoot, ...policyExperimentConfigPath);
|
|
38087
38202
|
let configJson;
|
|
38088
38203
|
try {
|
|
38089
38204
|
const raw = await readFile55(configPath, "utf8").catch((error) => {
|
|
@@ -38281,9 +38396,9 @@ class FwkReadService {
|
|
|
38281
38396
|
const recordedAt = nowIso(now);
|
|
38282
38397
|
const id = `receipt-${randomUUID4().replace(/-/g, "").slice(0, 16)}`;
|
|
38283
38398
|
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"}` } : {} };
|
|
38284
|
-
const ledger =
|
|
38285
|
-
const checkpointPath =
|
|
38286
|
-
await mkdir32(
|
|
38399
|
+
const ledger = path112.join(this.options.canonical.workspaceRoot, ".metaproject", "context-operations", "access-receipts.jsonl");
|
|
38400
|
+
const checkpointPath = path112.join(path112.dirname(ledger), "access-receipts.checkpoint.json");
|
|
38401
|
+
await mkdir32(path112.dirname(ledger), { recursive: true, mode: 448 });
|
|
38287
38402
|
return withFileLock(`${ledger}.lock`, async () => {
|
|
38288
38403
|
const state = await resolveLedgerState(ledger, checkpointPath, this.options.verifyReceiptLedger ?? verifyAccessReceiptLedger);
|
|
38289
38404
|
const receipt = sealAccessReceipt(base, state.headHash);
|
|
@@ -38387,7 +38502,7 @@ function normalizeFwkResult(result) {
|
|
|
38387
38502
|
init_fs();
|
|
38388
38503
|
import { createHash as createHash30, randomUUID as randomUUID7 } from "crypto";
|
|
38389
38504
|
import { appendFile as appendFile8, mkdir as mkdir35, readdir as readdir21, readFile as readFile64 } from "fs/promises";
|
|
38390
|
-
import
|
|
38505
|
+
import path122 from "path";
|
|
38391
38506
|
|
|
38392
38507
|
// src/sac/trusted-wrap-up.ts
|
|
38393
38508
|
import { createHash as createHash24, randomUUID as randomUUID5 } from "crypto";
|
|
@@ -38459,7 +38574,7 @@ function bindingHash(owner, intent) {
|
|
|
38459
38574
|
// src/sac/session-wrap-up.ts
|
|
38460
38575
|
import { createHash as createHash26 } from "crypto";
|
|
38461
38576
|
import { mkdir as mkdir34, writeFile as writeFile23 } from "fs/promises";
|
|
38462
|
-
import
|
|
38577
|
+
import path116 from "path";
|
|
38463
38578
|
|
|
38464
38579
|
// src/session/store.ts
|
|
38465
38580
|
init_config_dir();
|
|
@@ -38471,12 +38586,12 @@ import {
|
|
|
38471
38586
|
renameSync as renameSync2,
|
|
38472
38587
|
writeFileSync as writeFileSync2
|
|
38473
38588
|
} from "fs";
|
|
38474
|
-
import
|
|
38589
|
+
import path115 from "path";
|
|
38475
38590
|
|
|
38476
38591
|
// src/session/paths.ts
|
|
38477
38592
|
import { existsSync as existsSync16 } from "fs";
|
|
38478
38593
|
import { homedir } from "os";
|
|
38479
|
-
import
|
|
38594
|
+
import path113 from "path";
|
|
38480
38595
|
function keryxDataDir(override) {
|
|
38481
38596
|
if (override !== undefined && override.length > 0) {
|
|
38482
38597
|
return override;
|
|
@@ -38488,22 +38603,22 @@ function keryxDataDir(override) {
|
|
|
38488
38603
|
const home = homedir();
|
|
38489
38604
|
if (process.platform === "win32") {
|
|
38490
38605
|
const appData = process.env.APPDATA;
|
|
38491
|
-
const base = appData !== undefined && appData.length > 0 ? appData :
|
|
38492
|
-
return
|
|
38606
|
+
const base = appData !== undefined && appData.length > 0 ? appData : path113.join(home, "AppData", "Roaming");
|
|
38607
|
+
return path113.join(base, "keryx");
|
|
38493
38608
|
}
|
|
38494
38609
|
const xdg = process.env.XDG_DATA_HOME;
|
|
38495
|
-
const base = xdg !== undefined && xdg.length > 0 ? xdg :
|
|
38496
|
-
return
|
|
38610
|
+
const base = xdg !== undefined && xdg.length > 0 ? xdg : path113.join(home, ".local", "share");
|
|
38611
|
+
return path113.join(base, "keryx");
|
|
38497
38612
|
}
|
|
38498
38613
|
function resolveProjectRoot2(cwd) {
|
|
38499
|
-
const abs =
|
|
38614
|
+
const abs = path113.resolve(cwd);
|
|
38500
38615
|
let dir = abs;
|
|
38501
38616
|
for (;; ) {
|
|
38502
|
-
const gitPath =
|
|
38617
|
+
const gitPath = path113.join(dir, ".git");
|
|
38503
38618
|
if (existsSync16(gitPath)) {
|
|
38504
38619
|
return dir;
|
|
38505
38620
|
}
|
|
38506
|
-
const parent =
|
|
38621
|
+
const parent = path113.dirname(dir);
|
|
38507
38622
|
if (parent === dir) {
|
|
38508
38623
|
break;
|
|
38509
38624
|
}
|
|
@@ -38512,12 +38627,12 @@ function resolveProjectRoot2(cwd) {
|
|
|
38512
38627
|
return abs;
|
|
38513
38628
|
}
|
|
38514
38629
|
function projectKeyFromPath(projectPath) {
|
|
38515
|
-
const abs =
|
|
38630
|
+
const abs = path113.resolve(projectPath);
|
|
38516
38631
|
const encoded = encodeURIComponent(abs);
|
|
38517
38632
|
if (encoded.length <= 200) {
|
|
38518
38633
|
return encoded;
|
|
38519
38634
|
}
|
|
38520
|
-
const base =
|
|
38635
|
+
const base = path113.basename(abs).replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 40);
|
|
38521
38636
|
let h = 0;
|
|
38522
38637
|
for (let i = 0;i < abs.length; i++) {
|
|
38523
38638
|
h = Math.imul(31, h) + abs.charCodeAt(i) | 0;
|
|
@@ -38527,17 +38642,17 @@ function projectKeyFromPath(projectPath) {
|
|
|
38527
38642
|
}
|
|
38528
38643
|
function projectSessionsDir(projectPath, dataDir) {
|
|
38529
38644
|
const key = projectKeyFromPath(resolveProjectRoot2(projectPath));
|
|
38530
|
-
return
|
|
38645
|
+
return path113.join(keryxDataDir(dataDir), "sessions", key);
|
|
38531
38646
|
}
|
|
38532
38647
|
function sessionDir(projectPath, sessionId, dataDir) {
|
|
38533
|
-
return
|
|
38648
|
+
return path113.join(projectSessionsDir(projectPath, dataDir), sessionId);
|
|
38534
38649
|
}
|
|
38535
38650
|
|
|
38536
38651
|
// src/session/slate.ts
|
|
38537
38652
|
init_fs();
|
|
38538
38653
|
init_assembly();
|
|
38539
38654
|
import { mkdir as mkdir33, readFile as readFile56, readdir as readdir19, rm as rm7, stat as stat16 } from "fs/promises";
|
|
38540
|
-
import
|
|
38655
|
+
import path114 from "path";
|
|
38541
38656
|
init_redact();
|
|
38542
38657
|
var SLATE_SEED_KINDS = [
|
|
38543
38658
|
"decision",
|
|
@@ -38552,7 +38667,7 @@ function isSlateSeedKind(value) {
|
|
|
38552
38667
|
}
|
|
38553
38668
|
var SEED_TEXT_MAX_LENGTH = 4000;
|
|
38554
38669
|
function slatePath(dir) {
|
|
38555
|
-
return
|
|
38670
|
+
return path114.join(dir, "slate.json");
|
|
38556
38671
|
}
|
|
38557
38672
|
function slateLockPath(dir) {
|
|
38558
38673
|
return `${slatePath(dir)}.lock`;
|
|
@@ -38782,11 +38897,11 @@ function listSessions(cwd, dataDir) {
|
|
|
38782
38897
|
if (name.startsWith(".")) {
|
|
38783
38898
|
continue;
|
|
38784
38899
|
}
|
|
38785
|
-
const summary = readSummaryFile(
|
|
38900
|
+
const summary = readSummaryFile(path115.join(root, name, "summary.json"));
|
|
38786
38901
|
if (summary === undefined) {
|
|
38787
38902
|
continue;
|
|
38788
38903
|
}
|
|
38789
|
-
if (
|
|
38904
|
+
if (path115.resolve(summary.projectPath) !== path115.resolve(projectPath)) {
|
|
38790
38905
|
continue;
|
|
38791
38906
|
}
|
|
38792
38907
|
out.push(summary);
|
|
@@ -38819,15 +38934,15 @@ async function readSessionSlate(cwd, sessionId, dataDir) {
|
|
|
38819
38934
|
}
|
|
38820
38935
|
function loadContext(cwd, sessionId, dataDir) {
|
|
38821
38936
|
const dir = sessionDir(resolveProjectRoot2(cwd), sessionId, dataDir);
|
|
38822
|
-
const contextPath =
|
|
38937
|
+
const contextPath = path115.join(dir, "context.jsonl");
|
|
38823
38938
|
if (existsSync17(contextPath)) {
|
|
38824
38939
|
return readJsonl2(contextPath);
|
|
38825
38940
|
}
|
|
38826
|
-
return readJsonl2(
|
|
38941
|
+
return readJsonl2(path115.join(dir, "transcript.jsonl"));
|
|
38827
38942
|
}
|
|
38828
38943
|
function loadArchive(cwd, sessionId, dataDir, onDegraded) {
|
|
38829
38944
|
const dir = sessionDir(resolveProjectRoot2(cwd), sessionId, dataDir);
|
|
38830
|
-
const archivePath =
|
|
38945
|
+
const archivePath = path115.join(dir, "archive.jsonl");
|
|
38831
38946
|
if (existsSync17(archivePath)) {
|
|
38832
38947
|
try {
|
|
38833
38948
|
const archive = readJsonl2(archivePath);
|
|
@@ -39011,7 +39126,7 @@ function sessionEvidenceRef(workspaceId, sessionId) {
|
|
|
39011
39126
|
}
|
|
39012
39127
|
async function resolveSessionWrapUp(input) {
|
|
39013
39128
|
const now = input.now ?? (() => new Date);
|
|
39014
|
-
const sessionId =
|
|
39129
|
+
const sessionId = path116.posix.basename(input.sourceRef, ".md");
|
|
39015
39130
|
const summary = findSession(input.cwd, sessionId);
|
|
39016
39131
|
if (summary === undefined || input.sourceRef !== sessionEvidenceRef(input.workspaceId, summary.id)) {
|
|
39017
39132
|
throw new SessionWrapUpError("session_not_found", `no session matching "${input.sourceRef}" in this project \u2014 use \`keryx sessions list\``);
|
|
@@ -39028,7 +39143,7 @@ async function resolveSessionWrapUp(input) {
|
|
|
39028
39143
|
throw new SessionWrapUpError("session_unreadable", `session "${summary.id}" could not be read: ${cause.message}`);
|
|
39029
39144
|
}
|
|
39030
39145
|
const relPath = sessionEvidenceRef(input.workspaceId, summary.id).slice(2);
|
|
39031
|
-
const evidenceDir =
|
|
39146
|
+
const evidenceDir = path116.dirname(relPath);
|
|
39032
39147
|
const slate = await readSessionSlate(input.cwd, summary.id);
|
|
39033
39148
|
const diff = await gitDiff(input.cwd);
|
|
39034
39149
|
const diffBody = diff.kind === "measured" ? diff.text : unmeasurableDiffBody(diff.detail);
|
|
@@ -39050,23 +39165,23 @@ async function resolveSessionWrapUp(input) {
|
|
|
39050
39165
|
""
|
|
39051
39166
|
].join(`
|
|
39052
39167
|
`);
|
|
39053
|
-
const wrapUpRelPath =
|
|
39054
|
-
const diffRelPath =
|
|
39055
|
-
const noticeRelPath =
|
|
39168
|
+
const wrapUpRelPath = path116.join(evidenceDir, `${summary.id}.wrap-up.md`);
|
|
39169
|
+
const diffRelPath = path116.join(evidenceDir, `${summary.id}.diff.txt`);
|
|
39170
|
+
const noticeRelPath = path116.join(evidenceDir, `${summary.id}.redaction.md`);
|
|
39056
39171
|
const floor = await applyEvidenceRedactionFloor(input.cwd, [
|
|
39057
|
-
{ name:
|
|
39058
|
-
{ name:
|
|
39059
|
-
{ name:
|
|
39172
|
+
{ name: path116.basename(relPath), content: markdown, path: relPath, source: "generated" },
|
|
39173
|
+
{ name: path116.basename(wrapUpRelPath), content: wrapUpMarkdown, path: wrapUpRelPath, source: "generated" },
|
|
39174
|
+
{ name: path116.basename(diffRelPath), content: diffBody, path: diffRelPath, source: "tool-output" }
|
|
39060
39175
|
]);
|
|
39061
39176
|
if (!floor.ok)
|
|
39062
39177
|
throw new SessionWrapUpError("security_denied", floor.reason);
|
|
39063
39178
|
const [safeSession, safeWrapUp, safeDiff] = floor.bodies;
|
|
39064
|
-
await mkdir34(
|
|
39065
|
-
await writeFile23(
|
|
39066
|
-
await writeFile23(
|
|
39067
|
-
await writeFile23(
|
|
39179
|
+
await mkdir34(path116.join(input.cwd, evidenceDir), { recursive: true });
|
|
39180
|
+
await writeFile23(path116.join(input.cwd, relPath), safeSession.content, "utf8");
|
|
39181
|
+
await writeFile23(path116.join(input.cwd, wrapUpRelPath), safeWrapUp.content, "utf8");
|
|
39182
|
+
await writeFile23(path116.join(input.cwd, diffRelPath), safeDiff.content, "utf8");
|
|
39068
39183
|
if (floor.notice !== undefined)
|
|
39069
|
-
await writeFile23(
|
|
39184
|
+
await writeFile23(path116.join(input.cwd, noticeRelPath), floor.notice, "utf8");
|
|
39070
39185
|
const observedAt = now().toISOString();
|
|
39071
39186
|
const evidence = [
|
|
39072
39187
|
{ kind: "wrap-up", uri: `./${wrapUpRelPath}`, revision: createHash26("sha256").update(safeWrapUp.content).digest("hex"), observedAt },
|
|
@@ -39089,13 +39204,13 @@ async function resolveSessionWrapUp(input) {
|
|
|
39089
39204
|
init_fs();
|
|
39090
39205
|
import { createHash as createHash27, randomBytes as randomBytes6 } from "crypto";
|
|
39091
39206
|
import { readFile as readFile57 } from "fs/promises";
|
|
39092
|
-
import
|
|
39207
|
+
import path117 from "path";
|
|
39093
39208
|
var CONFIRM_TOKEN_TTL_MS = 2 * 60000;
|
|
39094
39209
|
function confirmTokenPath2(cwd, workspaceId, proposalId) {
|
|
39095
|
-
return
|
|
39210
|
+
return path117.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.confirm-token.json`);
|
|
39096
39211
|
}
|
|
39097
39212
|
function confirmReceiptPath(cwd, workspaceId, proposalId, idempotencyKey) {
|
|
39098
|
-
return
|
|
39213
|
+
return path117.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${sha2566(idempotencyKey)}.confirm-receipt.json`);
|
|
39099
39214
|
}
|
|
39100
39215
|
function sha2566(text) {
|
|
39101
39216
|
return createHash27("sha256").update(text).digest("hex");
|
|
@@ -39136,21 +39251,21 @@ init_store();
|
|
|
39136
39251
|
init_config();
|
|
39137
39252
|
import { readFile as readFile59, readdir as readdir20 } from "fs/promises";
|
|
39138
39253
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
39139
|
-
import
|
|
39254
|
+
import path119 from "path";
|
|
39140
39255
|
|
|
39141
39256
|
// src/sac/proposal-evidence.ts
|
|
39142
39257
|
init_fs();
|
|
39143
39258
|
import { createHash as createHash28 } from "crypto";
|
|
39144
39259
|
import { readFile as readFile58, rm as rm8 } from "fs/promises";
|
|
39145
|
-
import
|
|
39260
|
+
import path118 from "path";
|
|
39146
39261
|
function proposalPath(cwd, workspaceId, proposalId) {
|
|
39147
|
-
return
|
|
39262
|
+
return path118.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
|
|
39148
39263
|
}
|
|
39149
39264
|
function ownerReceiptPath(cwd, owner, workspaceId, idempotencyKey) {
|
|
39150
|
-
return
|
|
39265
|
+
return path118.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-receipts`, `${idempotencyKey}.json`);
|
|
39151
39266
|
}
|
|
39152
39267
|
function proposalNotePath(cwd, workspaceId, proposalId) {
|
|
39153
|
-
return
|
|
39268
|
+
return path118.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.note.txt`);
|
|
39154
39269
|
}
|
|
39155
39270
|
async function readVerifiedProposalEvidence(cwd, workspaceId, proposalId) {
|
|
39156
39271
|
let proposal;
|
|
@@ -39164,7 +39279,7 @@ async function readVerifiedProposalEvidence(cwd, workspaceId, proposalId) {
|
|
|
39164
39279
|
return { ok: false, code: "no_evidence_to_write" };
|
|
39165
39280
|
let content;
|
|
39166
39281
|
try {
|
|
39167
|
-
content = await readFile58(
|
|
39282
|
+
content = await readFile58(path118.join(cwd, evidence.uri), "utf8");
|
|
39168
39283
|
} catch {
|
|
39169
39284
|
return { ok: false, code: "evidence_file_unreadable" };
|
|
39170
39285
|
}
|
|
@@ -39194,22 +39309,22 @@ function targetRelPath(targetRef) {
|
|
|
39194
39309
|
return targetRef.replace(/^\.\//, "");
|
|
39195
39310
|
}
|
|
39196
39311
|
function targetAbsolutePath(cwd, targetRef) {
|
|
39197
|
-
return
|
|
39312
|
+
return path118.join(cwd, ".metaproject", targetRelPath(targetRef));
|
|
39198
39313
|
}
|
|
39199
39314
|
function targetKey(targetRef) {
|
|
39200
39315
|
return digestOf2(targetRelPath(targetRef)).slice(0, 32);
|
|
39201
39316
|
}
|
|
39202
39317
|
function ownerTargetVersionPath(cwd, owner, workspaceId, targetRef) {
|
|
39203
|
-
return
|
|
39318
|
+
return path118.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-target-versions`, `${targetKey(targetRef)}.json`);
|
|
39204
39319
|
}
|
|
39205
39320
|
function ownerTargetLockPath(cwd, owner, targetRef) {
|
|
39206
|
-
return
|
|
39321
|
+
return path118.join(cwd, ".metaproject", "data", "sac", "target-locks", owner, `${targetKey(targetRef)}.lock`);
|
|
39207
39322
|
}
|
|
39208
39323
|
function ownerStagingDir(cwd, owner, workspaceId, idempotencyKey) {
|
|
39209
|
-
return
|
|
39324
|
+
return path118.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-staging`, digestOf2(idempotencyKey).slice(0, 32));
|
|
39210
39325
|
}
|
|
39211
39326
|
function ownerConflictDir(cwd, owner, workspaceId, idempotencyKey) {
|
|
39212
|
-
return
|
|
39327
|
+
return path118.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-conflicts`, digestOf2(idempotencyKey).slice(0, 32));
|
|
39213
39328
|
}
|
|
39214
39329
|
async function readJson2(file) {
|
|
39215
39330
|
try {
|
|
@@ -39280,7 +39395,7 @@ async function applyGuardedTargetWrite(input) {
|
|
|
39280
39395
|
staged: input.staged,
|
|
39281
39396
|
stagedAt: receipt.completedAt
|
|
39282
39397
|
};
|
|
39283
|
-
await writeFileAtomic(
|
|
39398
|
+
await writeFileAtomic(path118.join(ownerStagingDir(cwd, owner, intent.workspaceId, intent.idempotencyKey), "plan.json"), `${JSON.stringify(staged, null, 2)}
|
|
39284
39399
|
`);
|
|
39285
39400
|
const applied = await input.apply(input.staged);
|
|
39286
39401
|
if (!applied.ok) {
|
|
@@ -39306,15 +39421,15 @@ async function recoverStagedOwnerWrite(input) {
|
|
|
39306
39421
|
});
|
|
39307
39422
|
}
|
|
39308
39423
|
async function readStagedOwnerWrite(cwd, owner, workspaceId, idempotencyKey) {
|
|
39309
|
-
return readJson2(
|
|
39424
|
+
return readJson2(path118.join(ownerStagingDir(cwd, owner, workspaceId, idempotencyKey), "plan.json"));
|
|
39310
39425
|
}
|
|
39311
39426
|
async function recordConflict(input) {
|
|
39312
39427
|
const base = { targetRef: input.targetRef, expectedVersion: input.expectedVersion, currentVersion: input.currentVersion };
|
|
39313
39428
|
if (input.proposedContent === undefined)
|
|
39314
39429
|
return base;
|
|
39315
39430
|
const dir = ownerConflictDir(input.cwd, input.owner, input.intent.workspaceId, input.intent.idempotencyKey);
|
|
39316
|
-
await writeFileAtomic(
|
|
39317
|
-
const diffRef = `./workspaces/${input.intent.workspaceId}/${input.owner}-write-conflicts/${
|
|
39431
|
+
await writeFileAtomic(path118.join(dir, "proposed"), input.proposedContent);
|
|
39432
|
+
const diffRef = `./workspaces/${input.intent.workspaceId}/${input.owner}-write-conflicts/${path118.basename(dir)}/proposed`;
|
|
39318
39433
|
return { ...base, diffRef };
|
|
39319
39434
|
}
|
|
39320
39435
|
|
|
@@ -39364,7 +39479,7 @@ async function resolveWorkspaceModule(cwd, workspaceId) {
|
|
|
39364
39479
|
}
|
|
39365
39480
|
}
|
|
39366
39481
|
async function collectWikiDecisionEntries(cwd) {
|
|
39367
|
-
const dir =
|
|
39482
|
+
const dir = path119.join(cwd, ".metaproject", "wiki", "decisions");
|
|
39368
39483
|
let files;
|
|
39369
39484
|
try {
|
|
39370
39485
|
files = (await readdir20(dir)).filter((name) => name.endsWith(".md"));
|
|
@@ -39373,12 +39488,12 @@ async function collectWikiDecisionEntries(cwd) {
|
|
|
39373
39488
|
}
|
|
39374
39489
|
const entries = [];
|
|
39375
39490
|
for (const file of files) {
|
|
39376
|
-
const absolutePath =
|
|
39491
|
+
const absolutePath = path119.join(dir, file);
|
|
39377
39492
|
try {
|
|
39378
39493
|
const content = await readFile59(absolutePath, "utf8");
|
|
39379
39494
|
entries.push({
|
|
39380
39495
|
absolutePath,
|
|
39381
|
-
relativePath:
|
|
39496
|
+
relativePath: path119.posix.join("decisions", file),
|
|
39382
39497
|
type: extractHeaderField(content, "Type") ?? "decision",
|
|
39383
39498
|
title: extractTitle(content),
|
|
39384
39499
|
version: extractHeaderField(content, "Version") ?? null,
|
|
@@ -39600,7 +39715,7 @@ function createRealMemoryOwnerWriter(cwd, opts) {
|
|
|
39600
39715
|
init_service4();
|
|
39601
39716
|
init_guard();
|
|
39602
39717
|
import { readFile as readFile61 } from "fs/promises";
|
|
39603
|
-
import
|
|
39718
|
+
import path120 from "path";
|
|
39604
39719
|
function renderWrapUpDecisionPage(input) {
|
|
39605
39720
|
const note = input.note?.trim();
|
|
39606
39721
|
return `# ${input.title}
|
|
@@ -39641,7 +39756,7 @@ export is the source of truth for what actually happened.
|
|
|
39641
39756
|
`;
|
|
39642
39757
|
}
|
|
39643
39758
|
function wikiPageRelativePath(proposalId) {
|
|
39644
|
-
return
|
|
39759
|
+
return path120.posix.join("decisions", `sac-${proposalId}.md`);
|
|
39645
39760
|
}
|
|
39646
39761
|
function createRealWikiOwnerWriter(cwd, opts) {
|
|
39647
39762
|
const now = opts?.now ?? (() => new Date);
|
|
@@ -39649,7 +39764,7 @@ function createRealWikiOwnerWriter(cwd, opts) {
|
|
|
39649
39764
|
const relativePath = staged.relativePath;
|
|
39650
39765
|
const content = staged.content;
|
|
39651
39766
|
const history = await openWikiWriteContext(cwd, "sac proposal accept");
|
|
39652
|
-
await writeWikiPage(history,
|
|
39767
|
+
await writeWikiPage(history, path120.join(cwd, ".metaproject", "wiki", relativePath), content);
|
|
39653
39768
|
return { ok: true };
|
|
39654
39769
|
};
|
|
39655
39770
|
return {
|
|
@@ -39719,7 +39834,7 @@ init_guard();
|
|
|
39719
39834
|
import { createHash as createHash29 } from "crypto";
|
|
39720
39835
|
import { homedir as homedir2 } from "os";
|
|
39721
39836
|
import { readFile as readFile62, stat as stat17 } from "fs/promises";
|
|
39722
|
-
import
|
|
39837
|
+
import path121 from "path";
|
|
39723
39838
|
var VERSION = "0.1.0";
|
|
39724
39839
|
var PROJECT_SKILLS_DIR = ".metaproject/project-skills";
|
|
39725
39840
|
var PROJECT_SKILLS_MANIFEST_PATH = ".metaproject/metaproject.json";
|
|
@@ -39749,7 +39864,7 @@ async function assertProjectWritesContained(projectRoot, paths) {
|
|
|
39749
39864
|
}
|
|
39750
39865
|
}
|
|
39751
39866
|
async function createProjectSkill(projectRoot, options) {
|
|
39752
|
-
const metaprojectRoot =
|
|
39867
|
+
const metaprojectRoot = path121.join(projectRoot, ".metaproject");
|
|
39753
39868
|
if (!await pathExists(metaprojectRoot)) {
|
|
39754
39869
|
throw new Error("Metaproject is not initialized. Run: keryx init");
|
|
39755
39870
|
}
|
|
@@ -39760,7 +39875,7 @@ async function createProjectSkill(projectRoot, options) {
|
|
|
39760
39875
|
const skillName = projectSkillSlug(options.name ?? inferSkillName(options.target));
|
|
39761
39876
|
const format = options.format ?? "auto";
|
|
39762
39877
|
const relativeSkillPath = projectSkillPackagePath(moduleName, skillName);
|
|
39763
|
-
const packageRoot =
|
|
39878
|
+
const packageRoot = path121.join(projectRoot, relativeSkillPath);
|
|
39764
39879
|
await assertProjectWritesContained(projectRoot, projectSkillWritePaths(moduleName, skillName, format));
|
|
39765
39880
|
const origin = options.origin ? options.originContent !== undefined ? {
|
|
39766
39881
|
ref: options.origin.trim(),
|
|
@@ -39771,7 +39886,7 @@ async function createProjectSkill(projectRoot, options) {
|
|
|
39771
39886
|
const warnings = collectWarnings(evidence, format);
|
|
39772
39887
|
const files = filesForPackage(packageRoot, format);
|
|
39773
39888
|
if (!options.dryRun) {
|
|
39774
|
-
await withFileLock(
|
|
39889
|
+
await withFileLock(path121.join(projectRoot, PROJECT_SKILLS_LOCK_PATH), async () => {
|
|
39775
39890
|
await writeProjectSkillPackage({
|
|
39776
39891
|
projectRoot,
|
|
39777
39892
|
packageRoot,
|
|
@@ -39800,7 +39915,7 @@ async function createProjectSkill(projectRoot, options) {
|
|
|
39800
39915
|
name: skillName,
|
|
39801
39916
|
target: options.target,
|
|
39802
39917
|
skillPath: relativeSkillPath,
|
|
39803
|
-
files: files.map((filePath) => toPosix(
|
|
39918
|
+
files: files.map((filePath) => toPosix(path121.relative(projectRoot, filePath))),
|
|
39804
39919
|
warnings,
|
|
39805
39920
|
dryRun: options.dryRun === true
|
|
39806
39921
|
};
|
|
@@ -39809,9 +39924,9 @@ var MAX_SKILL_TARGET_LENGTH = 80;
|
|
|
39809
39924
|
function resolveOriginPath(ref, projectRoot) {
|
|
39810
39925
|
const trimmed = ref.trim();
|
|
39811
39926
|
if (trimmed === "~" || trimmed.startsWith("~/")) {
|
|
39812
|
-
return
|
|
39927
|
+
return path121.join(homedir2(), trimmed.slice(1));
|
|
39813
39928
|
}
|
|
39814
|
-
return
|
|
39929
|
+
return path121.resolve(projectRoot, trimmed);
|
|
39815
39930
|
}
|
|
39816
39931
|
function hashOriginContent(content) {
|
|
39817
39932
|
return `sha256:${createHash29("sha256").update(content).digest("hex")}`;
|
|
@@ -39849,16 +39964,16 @@ async function writeProjectSkillPackage({
|
|
|
39849
39964
|
}) {
|
|
39850
39965
|
const packageFormat = format === "single" ? "single" : "package";
|
|
39851
39966
|
const skillContent = renderProjectSkill({ moduleName, skillName, target, note, origin, evidence, packageFormat });
|
|
39852
|
-
const relativeSkillMdPath = toPosix(
|
|
39967
|
+
const relativeSkillMdPath = toPosix(path121.join(path121.relative(projectRoot, packageRoot), "SKILL.md"));
|
|
39853
39968
|
const guard = await guardOutput({ cwd: projectRoot, content: skillContent, target: "skill", source: "generated", path: relativeSkillMdPath });
|
|
39854
39969
|
const output = prepareOutputForPersistence(guard, skillContent);
|
|
39855
39970
|
if (!output.allowed) {
|
|
39856
39971
|
throw new Error(`Project skill blocked by the security gate: ${output.reason}`);
|
|
39857
39972
|
}
|
|
39858
|
-
const packageRel = toPosix(
|
|
39973
|
+
const packageRel = toPosix(path121.relative(projectRoot, packageRoot));
|
|
39859
39974
|
const write = (file, content) => writeContained(projectRoot, `${packageRel}/${file}`, content);
|
|
39860
39975
|
await write("SKILL.md", output.content);
|
|
39861
|
-
if (!await pathExists(
|
|
39976
|
+
if (!await pathExists(path121.join(packageRoot, "skill-changelog.md"))) {
|
|
39862
39977
|
await write("skill-changelog.md", renderSkillChangelog({ moduleName, skillName, target }));
|
|
39863
39978
|
}
|
|
39864
39979
|
if (packageFormat === "package") {
|
|
@@ -39868,10 +39983,10 @@ async function writeProjectSkillPackage({
|
|
|
39868
39983
|
}
|
|
39869
39984
|
}
|
|
39870
39985
|
async function collectEvidence(projectRoot, target) {
|
|
39871
|
-
const absoluteTarget =
|
|
39986
|
+
const absoluteTarget = path121.resolve(projectRoot, target);
|
|
39872
39987
|
const targetExists = await pathExists(absoluteTarget);
|
|
39873
39988
|
const targetKind = await classifyTarget(absoluteTarget, targetExists);
|
|
39874
|
-
const maybeRelativeTarget = targetExists ? toPosix(
|
|
39989
|
+
const maybeRelativeTarget = targetExists ? toPosix(path121.relative(projectRoot, absoluteTarget)) : undefined;
|
|
39875
39990
|
const graphArtifacts = await existingRelativePaths(projectRoot, [
|
|
39876
39991
|
".metaproject/data/gdgraph/artifacts/summary.md",
|
|
39877
39992
|
".metaproject/data/gdgraph/artifacts/module-map.json"
|
|
@@ -39901,7 +40016,7 @@ async function classifyTarget(absoluteTarget, targetExists) {
|
|
|
39901
40016
|
async function existingRelativePaths(projectRoot, candidates) {
|
|
39902
40017
|
const existing = [];
|
|
39903
40018
|
for (const candidate of candidates) {
|
|
39904
|
-
if (await pathExists(
|
|
40019
|
+
if (await pathExists(path121.join(projectRoot, candidate))) {
|
|
39905
40020
|
existing.push(candidate);
|
|
39906
40021
|
}
|
|
39907
40022
|
}
|
|
@@ -39928,17 +40043,17 @@ function collectWarnings(evidence, format) {
|
|
|
39928
40043
|
}
|
|
39929
40044
|
function filesForPackage(packageRoot, format) {
|
|
39930
40045
|
const base = [
|
|
39931
|
-
|
|
39932
|
-
|
|
40046
|
+
path121.join(packageRoot, "SKILL.md"),
|
|
40047
|
+
path121.join(packageRoot, "skill-changelog.md")
|
|
39933
40048
|
];
|
|
39934
40049
|
if (format === "single") {
|
|
39935
40050
|
return base;
|
|
39936
40051
|
}
|
|
39937
40052
|
return [
|
|
39938
40053
|
...base,
|
|
39939
|
-
|
|
39940
|
-
|
|
39941
|
-
|
|
40054
|
+
path121.join(packageRoot, "verification.md"),
|
|
40055
|
+
path121.join(packageRoot, "references", "context.md"),
|
|
40056
|
+
path121.join(packageRoot, "templates", "README.md")
|
|
39942
40057
|
];
|
|
39943
40058
|
}
|
|
39944
40059
|
function renderProjectSkill({
|
|
@@ -40166,7 +40281,7 @@ keryx skills verify ${moduleName}/${skillName}
|
|
|
40166
40281
|
`;
|
|
40167
40282
|
}
|
|
40168
40283
|
async function updateManifest(projectRoot, entry) {
|
|
40169
|
-
const manifestPath =
|
|
40284
|
+
const manifestPath = path121.join(projectRoot, PROJECT_SKILLS_MANIFEST_PATH);
|
|
40170
40285
|
const manifest = await readJsonFileOr(manifestPath, {});
|
|
40171
40286
|
manifest.modules ??= {};
|
|
40172
40287
|
manifest.modules.gdskills ??= {};
|
|
@@ -40180,8 +40295,8 @@ async function updateManifest(projectRoot, entry) {
|
|
|
40180
40295
|
`);
|
|
40181
40296
|
}
|
|
40182
40297
|
async function updateSkillsCatalog(projectRoot) {
|
|
40183
|
-
const manifestPath =
|
|
40184
|
-
const catalogPath =
|
|
40298
|
+
const manifestPath = path121.join(projectRoot, PROJECT_SKILLS_MANIFEST_PATH);
|
|
40299
|
+
const catalogPath = path121.join(projectRoot, PROJECT_SKILLS_CATALOG_PATH);
|
|
40185
40300
|
const manifest = await readJsonFileOr(manifestPath, {});
|
|
40186
40301
|
const registry = manifest.modules?.gdskills?.projectSkillRegistry ?? [];
|
|
40187
40302
|
const rows = registry.length > 0 ? registry.map(projectSkillCatalogRow).join(`
|
|
@@ -40221,7 +40336,7 @@ function inferModule(target) {
|
|
|
40221
40336
|
}
|
|
40222
40337
|
function inferSkillName(target) {
|
|
40223
40338
|
const normalized = target.trim().replace(/[#:]+/g, "/");
|
|
40224
|
-
const base =
|
|
40339
|
+
const base = path121.basename(normalized).replace(/\.[^.]+$/, "");
|
|
40225
40340
|
return base || "entity";
|
|
40226
40341
|
}
|
|
40227
40342
|
function projectSkillSlug(value) {
|
|
@@ -40326,7 +40441,7 @@ class ProposalLifecycleService {
|
|
|
40326
40441
|
now;
|
|
40327
40442
|
constructor(options) {
|
|
40328
40443
|
this.options = options;
|
|
40329
|
-
this.root =
|
|
40444
|
+
this.root = path122.resolve(options.workspaceRoot);
|
|
40330
40445
|
this.now = options.now ?? (() => new Date);
|
|
40331
40446
|
}
|
|
40332
40447
|
async create(input) {
|
|
@@ -40345,7 +40460,7 @@ class ProposalLifecycleService {
|
|
|
40345
40460
|
if (manifest.status === "archived")
|
|
40346
40461
|
throw new ProposalLifecycleError("guard_denied", "workspace is archived");
|
|
40347
40462
|
const file = this.proposalPath(workspaceId, proposal.id);
|
|
40348
|
-
await mkdir35(
|
|
40463
|
+
await mkdir35(path122.dirname(file), { recursive: true, mode: 448 });
|
|
40349
40464
|
return withFileLock(`${file}.lock`, async () => {
|
|
40350
40465
|
const consume = this.options.wrapUpAuthority.consume(input.wrapUp, { actor, workspaceId });
|
|
40351
40466
|
if (consume !== "ok")
|
|
@@ -40373,7 +40488,7 @@ class ProposalLifecycleService {
|
|
|
40373
40488
|
return this.options.workspaces.withAuthorizedActor({ actorContext: actor, workspaceId: input.workspaceId, action: "review", execute: async (manifest) => {
|
|
40374
40489
|
const proposal = await this.loadProposal(input.workspaceId, input.proposalId);
|
|
40375
40490
|
const ledger = this.ledgerPath(input.workspaceId);
|
|
40376
|
-
await mkdir35(
|
|
40491
|
+
await mkdir35(path122.dirname(ledger), { recursive: true, mode: 448 });
|
|
40377
40492
|
return withFileLock(`${ledger}.lock`, async () => {
|
|
40378
40493
|
const records = (await this.records(ledger)).filter((record) => record.proposalId === proposal.id);
|
|
40379
40494
|
const events = records.filter((record) => record.recordType === "proposal-transition");
|
|
@@ -40415,7 +40530,7 @@ class ProposalLifecycleService {
|
|
|
40415
40530
|
} });
|
|
40416
40531
|
}
|
|
40417
40532
|
async listProposedProposals(workspaceId) {
|
|
40418
|
-
const proposalsDir =
|
|
40533
|
+
const proposalsDir = path122.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals");
|
|
40419
40534
|
let entries;
|
|
40420
40535
|
try {
|
|
40421
40536
|
entries = (await readdir21(proposalsDir)).filter((name) => name.endsWith(".json"));
|
|
@@ -40427,7 +40542,7 @@ class ProposalLifecycleService {
|
|
|
40427
40542
|
const proposals = [];
|
|
40428
40543
|
for (const entry of entries) {
|
|
40429
40544
|
try {
|
|
40430
|
-
const parsed = JSON.parse(await readFile64(
|
|
40545
|
+
const parsed = JSON.parse(await readFile64(path122.join(proposalsDir, entry), "utf8"));
|
|
40431
40546
|
if (parsed.recordType === "proposal-created")
|
|
40432
40547
|
proposals.push(parsed);
|
|
40433
40548
|
} catch {}
|
|
@@ -40693,31 +40808,31 @@ class ProposalLifecycleService {
|
|
|
40693
40808
|
}
|
|
40694
40809
|
}
|
|
40695
40810
|
proposalPath(workspaceId, proposalId) {
|
|
40696
|
-
return
|
|
40811
|
+
return path122.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
|
|
40697
40812
|
}
|
|
40698
40813
|
decisionRef(proposalId, key) {
|
|
40699
40814
|
return `./proposals/${proposalId}.${hash(key)}.decision.json`;
|
|
40700
40815
|
}
|
|
40701
40816
|
decisionPath(workspaceId, proposalId, key) {
|
|
40702
|
-
return
|
|
40817
|
+
return path122.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.decision.json`);
|
|
40703
40818
|
}
|
|
40704
40819
|
approvalRef(proposalId, key) {
|
|
40705
40820
|
return `./proposals/${proposalId}.${hash(key)}.approval.json`;
|
|
40706
40821
|
}
|
|
40707
40822
|
approvalPath(workspaceId, proposalId, key) {
|
|
40708
|
-
return
|
|
40823
|
+
return path122.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.approval.json`);
|
|
40709
40824
|
}
|
|
40710
40825
|
writeResultPath(workspaceId, proposalId, key) {
|
|
40711
|
-
return
|
|
40826
|
+
return path122.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.write-result.json`);
|
|
40712
40827
|
}
|
|
40713
40828
|
intentRef(proposalId, key) {
|
|
40714
40829
|
return `./proposals/${proposalId}.${hash(key)}.write-intent.json`;
|
|
40715
40830
|
}
|
|
40716
40831
|
intentPath(workspaceId, proposalId, key) {
|
|
40717
|
-
return
|
|
40832
|
+
return path122.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.write-intent.json`);
|
|
40718
40833
|
}
|
|
40719
40834
|
attemptPath(workspaceId, proposalId, key) {
|
|
40720
|
-
return
|
|
40835
|
+
return path122.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.owner-write-attempt.json`);
|
|
40721
40836
|
}
|
|
40722
40837
|
async loadWriteResult(workspaceId, proposalId, key) {
|
|
40723
40838
|
try {
|
|
@@ -40744,7 +40859,7 @@ class ProposalLifecycleService {
|
|
|
40744
40859
|
}
|
|
40745
40860
|
}
|
|
40746
40861
|
ledgerPath(workspaceId) {
|
|
40747
|
-
return
|
|
40862
|
+
return path122.join(this.root, ".metaproject", "workspaces", workspaceId, "activity.jsonl");
|
|
40748
40863
|
}
|
|
40749
40864
|
timestamp() {
|
|
40750
40865
|
return this.now().toISOString();
|
|
@@ -40827,7 +40942,7 @@ function normalizeProposalLifecycleResult(value) {
|
|
|
40827
40942
|
// src/sac/collaboration-service.ts
|
|
40828
40943
|
import { appendFile as appendFile9, mkdir as mkdir36, readFile as readFile65 } from "fs/promises";
|
|
40829
40944
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
40830
|
-
import
|
|
40945
|
+
import path123 from "path";
|
|
40831
40946
|
class CollaborationServiceError extends Error {
|
|
40832
40947
|
code;
|
|
40833
40948
|
constructor(code, message) {
|
|
@@ -40842,7 +40957,7 @@ class CollaborationService {
|
|
|
40842
40957
|
this.input = input;
|
|
40843
40958
|
}
|
|
40844
40959
|
file(id) {
|
|
40845
|
-
return
|
|
40960
|
+
return path123.join(this.input.workspaceRoot, ".metaproject", "workspaces", id, "activity.jsonl");
|
|
40846
40961
|
}
|
|
40847
40962
|
async overview(input) {
|
|
40848
40963
|
const manifest = await this.input.workspaces.show(input);
|
|
@@ -40879,7 +40994,7 @@ class CollaborationService {
|
|
|
40879
40994
|
occurredAt: (this.input.now ?? (() => new Date))().toISOString(),
|
|
40880
40995
|
...suppliedHandoff ? { handoff: { ...suppliedHandoff, from: actor.subject } } : {}
|
|
40881
40996
|
});
|
|
40882
|
-
await mkdir36(
|
|
40997
|
+
await mkdir36(path123.dirname(this.file(manifest.id)), { recursive: true, mode: 448 });
|
|
40883
40998
|
await appendFile9(this.file(manifest.id), `${JSON.stringify(activity)}
|
|
40884
40999
|
`, { mode: 384 });
|
|
40885
41000
|
return normalizeCollaborationResult(activity);
|
|
@@ -40929,13 +41044,13 @@ function normalizeCollaborationResult(value) {
|
|
|
40929
41044
|
// src/session/external-slate.ts
|
|
40930
41045
|
init_fs();
|
|
40931
41046
|
import { mkdir as mkdir38, readdir as readdir22, readFile as readFile66 } from "fs/promises";
|
|
40932
|
-
import
|
|
41047
|
+
import path125 from "path";
|
|
40933
41048
|
|
|
40934
41049
|
// src/sac/machine-wrap-up.ts
|
|
40935
41050
|
init_fs();
|
|
40936
41051
|
import { createHash as createHash31, randomUUID as randomUUID10 } from "crypto";
|
|
40937
41052
|
import { mkdir as mkdir37 } from "fs/promises";
|
|
40938
|
-
import
|
|
41053
|
+
import path124 from "path";
|
|
40939
41054
|
|
|
40940
41055
|
// src/sac/workspace-resolve.ts
|
|
40941
41056
|
init_redact();
|
|
@@ -41076,11 +41191,11 @@ async function resolveMachineWrapUp(input) {
|
|
|
41076
41191
|
`;
|
|
41077
41192
|
const seedsJson = `${JSON.stringify(seedsForKind.map((seed) => ({ text: seed.text, source: describeSource(seed.source) })), null, 2)}
|
|
41078
41193
|
`;
|
|
41079
|
-
const evidenceRelBase =
|
|
41194
|
+
const evidenceRelBase = path124.posix.join(".metaproject", "workspaces", input.workspaceId, "machine-evidence");
|
|
41080
41195
|
const floor = await applyEvidenceRedactionFloor(input.cwd, [
|
|
41081
|
-
{ name: `${input.kind}.diff.txt`, content: diffBody, path:
|
|
41082
|
-
{ name: `${input.kind}.flow.json`, content: flowSnapshotJson, path:
|
|
41083
|
-
{ name: `${input.kind}.seeds.json`, content: seedsJson, path:
|
|
41196
|
+
{ name: `${input.kind}.diff.txt`, content: diffBody, path: path124.posix.join(evidenceRelBase, `${input.kind}.diff.txt`), source: "tool-output" },
|
|
41197
|
+
{ name: `${input.kind}.flow.json`, content: flowSnapshotJson, path: path124.posix.join(evidenceRelBase, `${input.kind}.flow.json`), source: "generated" },
|
|
41198
|
+
{ name: `${input.kind}.seeds.json`, content: seedsJson, path: path124.posix.join(evidenceRelBase, `${input.kind}.seeds.json`), source: "generated" }
|
|
41084
41199
|
]);
|
|
41085
41200
|
if (!floor.ok)
|
|
41086
41201
|
return { ok: false, code: "security_denied", detail: floor.reason };
|
|
@@ -41134,14 +41249,14 @@ ${safeSeeds.content}`;
|
|
|
41134
41249
|
}
|
|
41135
41250
|
summary = result.text.trim().length > 0 ? result.text.trim() : mechanicalSummary(summaryDiff, course);
|
|
41136
41251
|
}
|
|
41137
|
-
const evidenceDir =
|
|
41252
|
+
const evidenceDir = path124.join(input.cwd, ".metaproject", "workspaces", input.workspaceId, "machine-evidence");
|
|
41138
41253
|
await mkdir37(evidenceDir, { recursive: true });
|
|
41139
41254
|
const diffFile = `${input.kind}.${shortHash}.diff.txt`;
|
|
41140
41255
|
const flowFile = `${input.kind}.${shortHash}.flow.json`;
|
|
41141
41256
|
const seedsFile = `${input.kind}.${shortHash}.seeds.json`;
|
|
41142
|
-
await writeFileAtomic(
|
|
41143
|
-
await writeFileAtomic(
|
|
41144
|
-
await writeFileAtomic(
|
|
41257
|
+
await writeFileAtomic(path124.join(evidenceDir, diffFile), safeDiff.content);
|
|
41258
|
+
await writeFileAtomic(path124.join(evidenceDir, flowFile), safeFlow.content);
|
|
41259
|
+
await writeFileAtomic(path124.join(evidenceDir, seedsFile), safeSeeds.content);
|
|
41145
41260
|
const observedAt = now().toISOString();
|
|
41146
41261
|
const relBase = `./.metaproject/workspaces/${input.workspaceId}/machine-evidence`;
|
|
41147
41262
|
const evidence = [
|
|
@@ -41151,7 +41266,7 @@ ${safeSeeds.content}`;
|
|
|
41151
41266
|
];
|
|
41152
41267
|
if (floor.notice !== undefined) {
|
|
41153
41268
|
const noticeFile = `${input.kind}.${shortHash}.redaction.md`;
|
|
41154
|
-
await writeFileAtomic(
|
|
41269
|
+
await writeFileAtomic(path124.join(evidenceDir, noticeFile), floor.notice);
|
|
41155
41270
|
evidence.push({ kind: REDACTION_NOTICE_KIND, uri: `${relBase}/${noticeFile}`, revision: sha2567(floor.notice), observedAt });
|
|
41156
41271
|
}
|
|
41157
41272
|
return {
|
|
@@ -41170,18 +41285,18 @@ async function writeFlooredArchiveArtifact(params) {
|
|
|
41170
41285
|
{
|
|
41171
41286
|
name: params.filename,
|
|
41172
41287
|
content: params.content,
|
|
41173
|
-
path:
|
|
41288
|
+
path: path124.posix.join("slate-archive", params.filename),
|
|
41174
41289
|
source: "generated"
|
|
41175
41290
|
}
|
|
41176
41291
|
]);
|
|
41177
41292
|
if (!floor.ok)
|
|
41178
41293
|
return { ok: false, code: "security_denied", detail: floor.reason };
|
|
41179
41294
|
const body = floor.bodies[0];
|
|
41180
|
-
const archiveDir =
|
|
41295
|
+
const archiveDir = path124.join(params.dir, "slate-archive");
|
|
41181
41296
|
await mkdir37(archiveDir, { recursive: true });
|
|
41182
|
-
await writeFileAtomic(
|
|
41297
|
+
await writeFileAtomic(path124.join(archiveDir, params.filename), body.content);
|
|
41183
41298
|
if (floor.notice !== undefined) {
|
|
41184
|
-
await writeFileAtomic(
|
|
41299
|
+
await writeFileAtomic(path124.join(archiveDir, `${params.filename}${ARCHIVE_REDACTION_NOTICE_SUFFIX}`), floor.notice);
|
|
41185
41300
|
}
|
|
41186
41301
|
return { ok: true, altered: body.altered };
|
|
41187
41302
|
}
|
|
@@ -41217,9 +41332,9 @@ async function writeWrapUpOutcomeArtifact(cwd, dir, trigger, now, groups) {
|
|
|
41217
41332
|
return;
|
|
41218
41333
|
const refusalIso = now().toISOString();
|
|
41219
41334
|
const refusalFilename = `${refusalIso.replace(/[:.]/g, "-")}-wrap-up-outcome.json`;
|
|
41220
|
-
const archiveDir =
|
|
41335
|
+
const archiveDir = path124.join(dir, "slate-archive");
|
|
41221
41336
|
await mkdir37(archiveDir, { recursive: true });
|
|
41222
|
-
await writeFileAtomic(
|
|
41337
|
+
await writeFileAtomic(path124.join(archiveDir, refusalFilename), `${JSON.stringify({
|
|
41223
41338
|
recordType: "wrap-up-outcome",
|
|
41224
41339
|
trigger,
|
|
41225
41340
|
generatedAt: refusalIso,
|
|
@@ -41355,7 +41470,7 @@ async function runWrapUp(input) {
|
|
|
41355
41470
|
|
|
41356
41471
|
// src/session/external-slate.ts
|
|
41357
41472
|
function externalSlatesDir(cwd) {
|
|
41358
|
-
return
|
|
41473
|
+
return path125.join(cwd, ".keryx", "external-slates");
|
|
41359
41474
|
}
|
|
41360
41475
|
var EXTERNAL_SESSION_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
|
|
41361
41476
|
function assertValidExternalSessionId(externalSessionId) {
|
|
@@ -41365,14 +41480,14 @@ function assertValidExternalSessionId(externalSessionId) {
|
|
|
41365
41480
|
}
|
|
41366
41481
|
function externalSlatePath(cwd, externalSessionId) {
|
|
41367
41482
|
assertValidExternalSessionId(externalSessionId);
|
|
41368
|
-
return
|
|
41483
|
+
return path125.join(externalSlatesDir(cwd), `${externalSessionId}.json`);
|
|
41369
41484
|
}
|
|
41370
41485
|
function externalSlateLockPath(cwd, externalSessionId) {
|
|
41371
41486
|
return `${externalSlatePath(cwd, externalSessionId)}.lock`;
|
|
41372
41487
|
}
|
|
41373
41488
|
function externalSlateEvidenceDir(cwd, externalSessionId) {
|
|
41374
41489
|
assertValidExternalSessionId(externalSessionId);
|
|
41375
|
-
return
|
|
41490
|
+
return path125.join(externalSlatesDir(cwd), externalSessionId);
|
|
41376
41491
|
}
|
|
41377
41492
|
async function readExternalSlate(cwd, externalSessionId) {
|
|
41378
41493
|
try {
|
|
@@ -41478,12 +41593,12 @@ __export(exports_service10, {
|
|
|
41478
41593
|
runDoctor: () => runDoctor,
|
|
41479
41594
|
runValidate: () => runValidate
|
|
41480
41595
|
});
|
|
41481
|
-
import
|
|
41596
|
+
import path128 from "path";
|
|
41482
41597
|
import { readFile as readFile69 } from "fs/promises";
|
|
41483
41598
|
|
|
41484
41599
|
// src/standard/validate.ts
|
|
41485
41600
|
init_fs();
|
|
41486
|
-
import
|
|
41601
|
+
import path127 from "path";
|
|
41487
41602
|
import { readFile as readFile68 } from "fs/promises";
|
|
41488
41603
|
|
|
41489
41604
|
// src/standard/schemas.ts
|
|
@@ -41613,7 +41728,7 @@ var SCHEMA_REGISTRY2 = {
|
|
|
41613
41728
|
// src/standard/profiles.ts
|
|
41614
41729
|
init_fs();
|
|
41615
41730
|
init_entrypoint_targets();
|
|
41616
|
-
import
|
|
41731
|
+
import path126 from "path";
|
|
41617
41732
|
import { readFile as readFile67 } from "fs/promises";
|
|
41618
41733
|
var AGENT_MODULES = ["gdgraph", "gdctx", "gdskills", "gdwiki", "memory"];
|
|
41619
41734
|
var CI_MODULES = ["health", "testing"];
|
|
@@ -41638,7 +41753,7 @@ function enabledModuleKeys(manifest) {
|
|
|
41638
41753
|
}
|
|
41639
41754
|
async function rootEntrypointLinksIndex(cwd, manifest) {
|
|
41640
41755
|
for (const { path: name } of namedEntrypoints(manifest)) {
|
|
41641
|
-
const filePath =
|
|
41756
|
+
const filePath = path126.join(cwd, name);
|
|
41642
41757
|
if (!await pathExists(filePath)) {
|
|
41643
41758
|
continue;
|
|
41644
41759
|
}
|
|
@@ -41650,16 +41765,16 @@ async function rootEntrypointLinksIndex(cwd, manifest) {
|
|
|
41650
41765
|
return false;
|
|
41651
41766
|
}
|
|
41652
41767
|
async function minimalSatisfied(cwd) {
|
|
41653
|
-
const metaprojectRoot =
|
|
41768
|
+
const metaprojectRoot = path126.join(cwd, ".metaproject");
|
|
41654
41769
|
const requiredFiles = ["index.md", "README.md", "metaproject.json"];
|
|
41655
41770
|
const requiredDirs = ["modules", "rules", "skills", "data"];
|
|
41656
41771
|
for (const file of requiredFiles) {
|
|
41657
|
-
if (!await pathExists(
|
|
41772
|
+
if (!await pathExists(path126.join(metaprojectRoot, file))) {
|
|
41658
41773
|
return false;
|
|
41659
41774
|
}
|
|
41660
41775
|
}
|
|
41661
41776
|
for (const dir of requiredDirs) {
|
|
41662
|
-
if (!await pathExists(
|
|
41777
|
+
if (!await pathExists(path126.join(metaprojectRoot, dir))) {
|
|
41663
41778
|
return false;
|
|
41664
41779
|
}
|
|
41665
41780
|
}
|
|
@@ -41672,7 +41787,7 @@ async function ciSatisfied(cwd, manifest) {
|
|
|
41672
41787
|
return false;
|
|
41673
41788
|
}
|
|
41674
41789
|
for (const key of ciModules) {
|
|
41675
|
-
if (await pathExists(
|
|
41790
|
+
if (await pathExists(path126.join(cwd, ".metaproject", "data", key, "artifacts"))) {
|
|
41676
41791
|
return true;
|
|
41677
41792
|
}
|
|
41678
41793
|
}
|
|
@@ -41685,7 +41800,7 @@ async function evaluateProfiles(cwd, manifest) {
|
|
|
41685
41800
|
satisfied.push("minimal");
|
|
41686
41801
|
}
|
|
41687
41802
|
const hasAgentModule = AGENT_MODULES.some((key) => new Set(enabledModuleKeys(manifest)).has(key));
|
|
41688
|
-
const agent = minimal && hasAgentModule && await rootEntrypointLinksIndex(cwd, manifest) && await pathExists(
|
|
41803
|
+
const agent = minimal && hasAgentModule && await rootEntrypointLinksIndex(cwd, manifest) && await pathExists(path126.join(cwd, ".metaproject", "rules"));
|
|
41689
41804
|
if (agent) {
|
|
41690
41805
|
satisfied.push("agent");
|
|
41691
41806
|
}
|
|
@@ -41854,20 +41969,20 @@ var MANIFEST_TOP_LEVEL_SCHEMA = {
|
|
|
41854
41969
|
async function validateWorkspace2(cwd) {
|
|
41855
41970
|
const errors = [];
|
|
41856
41971
|
const warnings = [];
|
|
41857
|
-
const metaprojectRoot =
|
|
41972
|
+
const metaprojectRoot = path127.join(cwd, ".metaproject");
|
|
41858
41973
|
const requiredFiles = ["index.md", "README.md", "metaproject.json"];
|
|
41859
41974
|
for (const file of requiredFiles) {
|
|
41860
|
-
if (!await pathExists(
|
|
41975
|
+
if (!await pathExists(path127.join(metaprojectRoot, file))) {
|
|
41861
41976
|
errors.push(issue("missing-required-file", `Required file .metaproject/${file} is missing`, `Run \`keryx init\` to scaffold .metaproject/${file}.`));
|
|
41862
41977
|
}
|
|
41863
41978
|
}
|
|
41864
41979
|
const requiredDirs = ["modules", "rules", "skills", "data"];
|
|
41865
41980
|
for (const dir of requiredDirs) {
|
|
41866
|
-
if (!await pathExists(
|
|
41981
|
+
if (!await pathExists(path127.join(metaprojectRoot, dir))) {
|
|
41867
41982
|
errors.push(issue("missing-required-dir", `Required directory .metaproject/${dir}/ is missing`, `Run \`keryx init\` to create .metaproject/${dir}/.`));
|
|
41868
41983
|
}
|
|
41869
41984
|
}
|
|
41870
|
-
const manifestPath =
|
|
41985
|
+
const manifestPath = path127.join(metaprojectRoot, "metaproject.json");
|
|
41871
41986
|
if (!await pathExists(manifestPath)) {
|
|
41872
41987
|
return { ok: errors.length === 0, errors, warnings };
|
|
41873
41988
|
}
|
|
@@ -41899,7 +42014,7 @@ async function validateWorkspace2(cwd) {
|
|
|
41899
42014
|
if (typeof value !== "string") {
|
|
41900
42015
|
continue;
|
|
41901
42016
|
}
|
|
41902
|
-
if (!await pathExists(
|
|
42017
|
+
if (!await pathExists(path127.join(cwd, value))) {
|
|
41903
42018
|
errors.push(issue("missing-declared-path", `Declared path paths.${key} -> ${value} does not exist`, `Create ${value} or remove paths.${key} from metaproject.json.`));
|
|
41904
42019
|
}
|
|
41905
42020
|
}
|
|
@@ -41909,7 +42024,7 @@ async function validateWorkspace2(cwd) {
|
|
|
41909
42024
|
continue;
|
|
41910
42025
|
}
|
|
41911
42026
|
if (typeof entry.manifest === "string") {
|
|
41912
|
-
if (!await pathExists(
|
|
42027
|
+
if (!await pathExists(path127.join(cwd, entry.manifest))) {
|
|
41913
42028
|
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.`));
|
|
41914
42029
|
}
|
|
41915
42030
|
}
|
|
@@ -41918,14 +42033,14 @@ async function validateWorkspace2(cwd) {
|
|
|
41918
42033
|
if (typeof value !== "string") {
|
|
41919
42034
|
continue;
|
|
41920
42035
|
}
|
|
41921
|
-
if (!await pathExists(
|
|
42036
|
+
if (!await pathExists(path127.join(cwd, value))) {
|
|
41922
42037
|
const sink = field === "data" ? warnings : errors;
|
|
41923
42038
|
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.`));
|
|
41924
42039
|
}
|
|
41925
42040
|
}
|
|
41926
42041
|
}
|
|
41927
42042
|
for (const { path: name, scope } of namedEntrypoints(manifest)) {
|
|
41928
|
-
const filePath =
|
|
42043
|
+
const filePath = path127.join(cwd, name);
|
|
41929
42044
|
if (!await pathExists(filePath)) {
|
|
41930
42045
|
continue;
|
|
41931
42046
|
}
|
|
@@ -42925,7 +43040,7 @@ async function runDoctor(cwd) {
|
|
|
42925
43040
|
return validateWorkspace2(cwd);
|
|
42926
43041
|
}
|
|
42927
43042
|
async function readManifest(cwd) {
|
|
42928
|
-
const manifestPath =
|
|
43043
|
+
const manifestPath = path128.join(cwd, ".metaproject", "metaproject.json");
|
|
42929
43044
|
if (!await pathExists(manifestPath)) {
|
|
42930
43045
|
throw new Error("Metaproject is not initialized (missing .metaproject/metaproject.json). Run `keryx init` first.");
|
|
42931
43046
|
}
|