@c4a/context-cli 0.5.29-beta.29 → 0.5.33-alpha.2
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/cli.js +1654 -883
- package/package.json +1 -1
- package/plugin/commands/compile.md +1 -1
- package/plugin/skills/skill-compile-judge/SKILL.md +1 -0
package/cli.js
CHANGED
|
@@ -8905,11 +8905,35 @@ function validateCompile(value) {
|
|
|
8905
8905
|
}
|
|
8906
8906
|
return compile;
|
|
8907
8907
|
}
|
|
8908
|
-
|
|
8909
|
-
|
|
8910
|
-
|
|
8911
|
-
|
|
8908
|
+
function validateRender(value) {
|
|
8909
|
+
if (value === undefined)
|
|
8910
|
+
return;
|
|
8911
|
+
if (!value || typeof value !== "object") {
|
|
8912
|
+
throw new Error(`config.yaml: render must be an object`);
|
|
8913
|
+
}
|
|
8914
|
+
const r = value;
|
|
8915
|
+
const render = {};
|
|
8916
|
+
if (r.obsidian_mode !== undefined) {
|
|
8917
|
+
if (typeof r.obsidian_mode !== "boolean") {
|
|
8918
|
+
throw new Error(`config.yaml: render.obsidian_mode must be boolean`);
|
|
8919
|
+
}
|
|
8920
|
+
render.obsidian_mode = r.obsidian_mode;
|
|
8912
8921
|
}
|
|
8922
|
+
if (r.used_by !== undefined) {
|
|
8923
|
+
if (typeof r.used_by !== "boolean") {
|
|
8924
|
+
throw new Error(`config.yaml: render.used_by must be boolean`);
|
|
8925
|
+
}
|
|
8926
|
+
render.used_by = r.used_by;
|
|
8927
|
+
}
|
|
8928
|
+
return render;
|
|
8929
|
+
}
|
|
8930
|
+
function normalizeRenderConfig(value) {
|
|
8931
|
+
return {
|
|
8932
|
+
obsidian_mode: value?.obsidian_mode ?? DEFAULT_RENDER_CONFIG.obsidian_mode,
|
|
8933
|
+
used_by: value?.used_by ?? DEFAULT_RENDER_CONFIG.used_by
|
|
8934
|
+
};
|
|
8935
|
+
}
|
|
8936
|
+
async function parseConfigFile(configPath, options) {
|
|
8913
8937
|
const raw = await readFile(configPath, "utf8");
|
|
8914
8938
|
let parsed;
|
|
8915
8939
|
try {
|
|
@@ -8918,7 +8942,16 @@ async function loadConfig(ctxDir) {
|
|
|
8918
8942
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
8919
8943
|
throw new Error(`config.yaml parse failed: ${msg}`);
|
|
8920
8944
|
}
|
|
8921
|
-
|
|
8945
|
+
if (parsed === null && !options.requireWorkspace)
|
|
8946
|
+
return {};
|
|
8947
|
+
return validateConfigRoot(parsed, configPath);
|
|
8948
|
+
}
|
|
8949
|
+
async function loadConfig(ctxDir) {
|
|
8950
|
+
const configPath = join(ctxDir, "config.yaml");
|
|
8951
|
+
if (!existsSync(configPath)) {
|
|
8952
|
+
throw new Error(`config.yaml not found at ${configPath}`);
|
|
8953
|
+
}
|
|
8954
|
+
const doc = await parseConfigFile(configPath, { requireWorkspace: true });
|
|
8922
8955
|
const result = {
|
|
8923
8956
|
workspace: validateWorkspace(doc)
|
|
8924
8957
|
};
|
|
@@ -8939,12 +8972,28 @@ async function loadConfig(ctxDir) {
|
|
|
8939
8972
|
if (compile !== undefined) {
|
|
8940
8973
|
result.compile = compile;
|
|
8941
8974
|
}
|
|
8975
|
+
const render = validateRender(doc.render);
|
|
8976
|
+
if (render !== undefined) {
|
|
8977
|
+
result.render = render;
|
|
8978
|
+
}
|
|
8942
8979
|
return result;
|
|
8943
8980
|
}
|
|
8944
|
-
|
|
8981
|
+
async function loadRenderConfig(ctxDir) {
|
|
8982
|
+
const configPath = join(ctxDir, "config.yaml");
|
|
8983
|
+
if (!existsSync(configPath)) {
|
|
8984
|
+
return { ...DEFAULT_RENDER_CONFIG };
|
|
8985
|
+
}
|
|
8986
|
+
const doc = await parseConfigFile(configPath, { requireWorkspace: false });
|
|
8987
|
+
return normalizeRenderConfig(validateRender(doc.render));
|
|
8988
|
+
}
|
|
8989
|
+
var import_yaml, VALID_TRUSTS, DEFAULT_RENDER_CONFIG;
|
|
8945
8990
|
var init_config = __esm(() => {
|
|
8946
8991
|
import_yaml = __toESM(require_dist(), 1);
|
|
8947
8992
|
VALID_TRUSTS = ["private", "company", "public"];
|
|
8993
|
+
DEFAULT_RENDER_CONFIG = Object.freeze({
|
|
8994
|
+
obsidian_mode: false,
|
|
8995
|
+
used_by: true
|
|
8996
|
+
});
|
|
8948
8997
|
});
|
|
8949
8998
|
|
|
8950
8999
|
// src/lib/errors.ts
|
|
@@ -29389,7 +29438,7 @@ async function syncEvidenceManifestsForSource(ctxDir, source2, now = new Date) {
|
|
|
29389
29438
|
if (await evidenceManifestModeForSource(ctxDir, source2) === "none")
|
|
29390
29439
|
return;
|
|
29391
29440
|
for (const snapshot of source2.snapshots) {
|
|
29392
|
-
if (
|
|
29441
|
+
if (await readEvidenceManifest(ctxDir, source2.id, snapshot.content_hash))
|
|
29393
29442
|
continue;
|
|
29394
29443
|
const manifest = await buildEvidenceManifestForSnapshot({ ctxDir, source: source2, snapshot, now });
|
|
29395
29444
|
if (manifest)
|
|
@@ -29425,23 +29474,35 @@ async function sourceSnapshotForManifest(input) {
|
|
|
29425
29474
|
return null;
|
|
29426
29475
|
const source2 = parsed.sources.map(asSourceEntry).find((entry) => entry?.id === input.sourceId);
|
|
29427
29476
|
const wantedHash = normalizeStoredHash(input.snapshotHash);
|
|
29428
|
-
const
|
|
29429
|
-
|
|
29477
|
+
const matchingSnapshots = source2?.snapshots.map(asSnapshotEntry).filter((candidate) => candidate !== null && normalizeStoredHash(candidate.content_hash) === wantedHash) ?? [];
|
|
29478
|
+
const snapshot = selectLatestEvidenceSnapshot(matchingSnapshots);
|
|
29479
|
+
return source2 !== undefined && snapshot !== null ? { source: source2, snapshot } : null;
|
|
29430
29480
|
}
|
|
29431
|
-
async function
|
|
29432
|
-
const resolved = await sourceSnapshotForManifest({ ctxDir, sourceId, snapshotHash });
|
|
29433
|
-
if (resolved === null)
|
|
29434
|
-
return null;
|
|
29481
|
+
async function rebuildEvidenceManifestFromSnapshot(ctxDir, source2, snapshot) {
|
|
29435
29482
|
const manifest = await buildEvidenceManifestForSnapshot({
|
|
29436
29483
|
ctxDir,
|
|
29437
|
-
source:
|
|
29438
|
-
snapshot
|
|
29484
|
+
source: source2,
|
|
29485
|
+
snapshot
|
|
29439
29486
|
});
|
|
29440
29487
|
if (manifest === null)
|
|
29441
29488
|
return null;
|
|
29442
29489
|
await writeEvidenceManifest(ctxDir, manifest);
|
|
29443
29490
|
return manifest;
|
|
29444
29491
|
}
|
|
29492
|
+
function optionalSnapshotField(value) {
|
|
29493
|
+
return value === undefined || value.length === 0 ? undefined : value;
|
|
29494
|
+
}
|
|
29495
|
+
function cachedManifestMatchesSnapshot(ctxDir, manifest, snapshot) {
|
|
29496
|
+
if (optionalSnapshotField(manifest.snapshot_file) !== optionalSnapshotField(snapshot.file))
|
|
29497
|
+
return false;
|
|
29498
|
+
if (optionalSnapshotField(manifest.snapshot_dir) !== optionalSnapshotField(snapshot.dir))
|
|
29499
|
+
return false;
|
|
29500
|
+
if (manifest.captured_at !== snapshot.captured_at)
|
|
29501
|
+
return false;
|
|
29502
|
+
if (manifest.snapshot_file !== undefined && !existsSync4(join6(ctxDir, manifest.snapshot_file)))
|
|
29503
|
+
return false;
|
|
29504
|
+
return true;
|
|
29505
|
+
}
|
|
29445
29506
|
async function readCachedEvidenceManifest(path3) {
|
|
29446
29507
|
if (!existsSync4(path3))
|
|
29447
29508
|
return null;
|
|
@@ -29452,6 +29513,7 @@ async function readCachedEvidenceManifest(path3) {
|
|
|
29452
29513
|
}
|
|
29453
29514
|
async function readEvidenceManifest(ctxDir, sourceId, snapshotHash) {
|
|
29454
29515
|
const path3 = evidenceManifestPath(ctxDir, sourceId, snapshotHash);
|
|
29516
|
+
const currentSnapshot = await sourceSnapshotForManifest({ ctxDir, sourceId, snapshotHash });
|
|
29455
29517
|
let parsed;
|
|
29456
29518
|
try {
|
|
29457
29519
|
parsed = await readCachedEvidenceManifest(path3);
|
|
@@ -29459,10 +29521,10 @@ async function readEvidenceManifest(ctxDir, sourceId, snapshotHash) {
|
|
|
29459
29521
|
parsed = null;
|
|
29460
29522
|
}
|
|
29461
29523
|
if (parsed === null) {
|
|
29462
|
-
return
|
|
29524
|
+
return currentSnapshot === null ? null : rebuildEvidenceManifestFromSnapshot(ctxDir, currentSnapshot.source, currentSnapshot.snapshot);
|
|
29463
29525
|
}
|
|
29464
29526
|
if (parsed.source_id !== sourceId || normalizeStoredHash(parsed.snapshot_content_hash) !== normalizeStoredHash(snapshotHash)) {
|
|
29465
|
-
const rebuilt = await
|
|
29527
|
+
const rebuilt = currentSnapshot === null ? null : await rebuildEvidenceManifestFromSnapshot(ctxDir, currentSnapshot.source, currentSnapshot.snapshot);
|
|
29466
29528
|
if (rebuilt !== null)
|
|
29467
29529
|
return rebuilt;
|
|
29468
29530
|
throw new ContextError(ExitCode.WorkspaceStateError, "evidence-manifest identity mismatch", {
|
|
@@ -29479,6 +29541,9 @@ async function readEvidenceManifest(ctxDir, sourceId, snapshotHash) {
|
|
|
29479
29541
|
}]
|
|
29480
29542
|
});
|
|
29481
29543
|
}
|
|
29544
|
+
if (currentSnapshot !== null && !cachedManifestMatchesSnapshot(ctxDir, parsed, currentSnapshot.snapshot)) {
|
|
29545
|
+
return rebuildEvidenceManifestFromSnapshot(ctxDir, currentSnapshot.source, currentSnapshot.snapshot);
|
|
29546
|
+
}
|
|
29482
29547
|
return parsed;
|
|
29483
29548
|
}
|
|
29484
29549
|
async function readLatestEvidenceManifest(ctxDir, source2) {
|
|
@@ -31763,7 +31828,9 @@ function splitFrontmatter2(markdown) {
|
|
|
31763
31828
|
}
|
|
31764
31829
|
return {
|
|
31765
31830
|
frontmatter: parsed,
|
|
31766
|
-
body: normalized.slice(bodyIndex)
|
|
31831
|
+
body: normalized.slice(bodyIndex),
|
|
31832
|
+
bodyLineOffset: normalized.slice(0, bodyIndex).split(`
|
|
31833
|
+
`).length - 1
|
|
31767
31834
|
};
|
|
31768
31835
|
}
|
|
31769
31836
|
function toTemporalValue(value) {
|
|
@@ -31883,25 +31950,54 @@ function parseContainsList(lines, startIndex, rootSlug) {
|
|
|
31883
31950
|
}
|
|
31884
31951
|
return { entries, edges, nextIndex: index2 };
|
|
31885
31952
|
}
|
|
31886
|
-
function
|
|
31887
|
-
const heading2 =
|
|
31953
|
+
function parseAutoBlockHeading(line, expectedLevel) {
|
|
31954
|
+
const heading2 = /^(#{2,6})\s+(.+?)\s*$/.exec(line);
|
|
31888
31955
|
if (!heading2)
|
|
31889
|
-
return
|
|
31890
|
-
const level = heading2[1]?.length ??
|
|
31891
|
-
|
|
31956
|
+
return null;
|
|
31957
|
+
const level = heading2[1]?.length ?? 0;
|
|
31958
|
+
if (level !== expectedLevel)
|
|
31959
|
+
return null;
|
|
31960
|
+
const title = (heading2[2] ?? "").trim();
|
|
31961
|
+
const kind = AUTO_BLOCK_TITLES.get(title);
|
|
31962
|
+
return kind === undefined ? null : { level, title, kind };
|
|
31963
|
+
}
|
|
31964
|
+
function autoBlockOpenPattern(kind) {
|
|
31965
|
+
return new RegExp(`^<!--\\s+c4a:auto-block\\s+${kind}\\s+-->$`);
|
|
31966
|
+
}
|
|
31967
|
+
function consumeAutoBlock(lines, startIndex, expectedLevel, lineOffset = 0) {
|
|
31968
|
+
const heading2 = parseAutoBlockHeading(lines[startIndex] ?? "", expectedLevel);
|
|
31969
|
+
if (heading2 === null)
|
|
31970
|
+
return { matched: false, nextIndex: startIndex };
|
|
31971
|
+
const openIndex = skipBlankLines(lines, startIndex + 1);
|
|
31972
|
+
const opening = lines[openIndex]?.trim() ?? "";
|
|
31973
|
+
if (!autoBlockOpenPattern(heading2.kind).test(opening)) {
|
|
31974
|
+
return { matched: false, nextIndex: startIndex };
|
|
31975
|
+
}
|
|
31976
|
+
let index2 = openIndex + 1;
|
|
31892
31977
|
while (index2 < lines.length) {
|
|
31893
31978
|
const line = lines[index2] ?? "";
|
|
31894
|
-
|
|
31895
|
-
|
|
31896
|
-
|
|
31979
|
+
if (line.trim() === AUTO_BLOCK_CLOSE) {
|
|
31980
|
+
index2 += 1;
|
|
31981
|
+
while (index2 < lines.length && (lines[index2]?.trim() ?? "") === "")
|
|
31982
|
+
index2 += 1;
|
|
31983
|
+
return { matched: true, nextIndex: index2 };
|
|
31984
|
+
}
|
|
31897
31985
|
const nextHeading = /^(#{1,6})\s+/.exec(line);
|
|
31898
|
-
if (nextHeading && (nextHeading[1]?.length ?? 0) <= level)
|
|
31986
|
+
if (nextHeading && (nextHeading[1]?.length ?? 0) <= heading2.level) {
|
|
31899
31987
|
break;
|
|
31988
|
+
}
|
|
31900
31989
|
index2 += 1;
|
|
31901
31990
|
}
|
|
31902
|
-
|
|
31903
|
-
|
|
31904
|
-
|
|
31991
|
+
return {
|
|
31992
|
+
matched: false,
|
|
31993
|
+
nextIndex: startIndex,
|
|
31994
|
+
issue: {
|
|
31995
|
+
code: "render-auto-block-unclosed",
|
|
31996
|
+
kind: heading2.kind,
|
|
31997
|
+
title: heading2.title,
|
|
31998
|
+
line: lineOffset + openIndex + 1
|
|
31999
|
+
}
|
|
32000
|
+
};
|
|
31905
32001
|
}
|
|
31906
32002
|
function assertNoLegacySectionMarker(line) {
|
|
31907
32003
|
if (!isLegacySectionOpenComment(line))
|
|
@@ -31964,7 +32060,7 @@ function parseFrontmatterNode(lines, index2) {
|
|
|
31964
32060
|
}
|
|
31965
32061
|
return { node: node3, nextIndex: fmEnd + 1 };
|
|
31966
32062
|
}
|
|
31967
|
-
function parseNodeBlock(lines, startIndex, headingLevel) {
|
|
32063
|
+
function parseNodeBlock(lines, startIndex, headingLevel, lineOffset = 0) {
|
|
31968
32064
|
const headingEnd = consumeExpectedHeading(lines, startIndex, headingLevel);
|
|
31969
32065
|
const frontmatter = parseFrontmatterNode(lines, headingEnd);
|
|
31970
32066
|
const node3 = frontmatter.node;
|
|
@@ -31973,6 +32069,7 @@ function parseNodeBlock(lines, startIndex, headingLevel) {
|
|
|
31973
32069
|
const bodyLines = [];
|
|
31974
32070
|
const containsList = [];
|
|
31975
32071
|
const children = [];
|
|
32072
|
+
const renderAutoBlockIssues = [];
|
|
31976
32073
|
const childLevel = headingLevel + 1;
|
|
31977
32074
|
const childHeadingPattern = new RegExp(`^#{${childLevel}}\\s+.+`);
|
|
31978
32075
|
while (index2 < lines.length) {
|
|
@@ -31987,7 +32084,7 @@ function parseNodeBlock(lines, startIndex, headingLevel) {
|
|
|
31987
32084
|
if (childHeadingPattern.test(currentLine)) {
|
|
31988
32085
|
const peek = peekIsFrontmatterAfterHeading(lines, index2);
|
|
31989
32086
|
if (peek) {
|
|
31990
|
-
const childResult = parseNodeBlock(lines, index2, childLevel);
|
|
32087
|
+
const childResult = parseNodeBlock(lines, index2, childLevel, lineOffset);
|
|
31991
32088
|
children.push(childResult.parsed);
|
|
31992
32089
|
index2 = childResult.nextIndex;
|
|
31993
32090
|
continue;
|
|
@@ -32005,8 +32102,12 @@ function parseNodeBlock(lines, startIndex, headingLevel) {
|
|
|
32005
32102
|
index2 = listParsed.nextIndex;
|
|
32006
32103
|
continue;
|
|
32007
32104
|
}
|
|
32008
|
-
|
|
32009
|
-
|
|
32105
|
+
const autoBlock = consumeAutoBlock(lines, index2, headingLevel + 1, lineOffset);
|
|
32106
|
+
if (autoBlock.issue !== undefined) {
|
|
32107
|
+
renderAutoBlockIssues.push(autoBlock.issue);
|
|
32108
|
+
}
|
|
32109
|
+
if (autoBlock.matched) {
|
|
32110
|
+
index2 = autoBlock.nextIndex;
|
|
32010
32111
|
continue;
|
|
32011
32112
|
}
|
|
32012
32113
|
if (isSectionGroupHeading(currentLine, headingLevel + 1)) {
|
|
@@ -32042,11 +32143,14 @@ function parseNodeBlock(lines, startIndex, headingLevel) {
|
|
|
32042
32143
|
parsed: {
|
|
32043
32144
|
node: node3,
|
|
32044
32145
|
headingLevel,
|
|
32146
|
+
startLine: lineOffset + startIndex + 1,
|
|
32147
|
+
endLine: lineOffset + index2,
|
|
32045
32148
|
body: body2,
|
|
32046
32149
|
sections,
|
|
32047
32150
|
children,
|
|
32048
32151
|
containsEdges,
|
|
32049
|
-
containsList
|
|
32152
|
+
containsList,
|
|
32153
|
+
...renderAutoBlockIssues.length > 0 ? { renderAutoBlockIssues } : {}
|
|
32050
32154
|
},
|
|
32051
32155
|
nextIndex: index2
|
|
32052
32156
|
};
|
|
@@ -32079,7 +32183,7 @@ function parsePlainSubHeadingEdges(body2, parentSlug, parentLevel) {
|
|
|
32079
32183
|
if (level <= parentLevel)
|
|
32080
32184
|
continue;
|
|
32081
32185
|
const title = (match[2] ?? "").trim();
|
|
32082
|
-
if (title.length === 0 || level === parentLevel + 1 && (title
|
|
32186
|
+
if (title.length === 0 || level === parentLevel + 1 && (AUTO_BLOCK_EXCLUDED_CONTAINS_TITLES.has(title) || SECTION_GROUP_TITLES.has(title)))
|
|
32083
32187
|
continue;
|
|
32084
32188
|
if (peekIsFrontmatterAfterHeading(lines, i))
|
|
32085
32189
|
continue;
|
|
@@ -32106,7 +32210,7 @@ function parseNodeMarkdown(markdown) {
|
|
|
32106
32210
|
return parsed;
|
|
32107
32211
|
}
|
|
32108
32212
|
function parseRootNodeFrontmatterFirst(normalized) {
|
|
32109
|
-
const { frontmatter, body: body2 } = splitFrontmatter2(normalized);
|
|
32213
|
+
const { frontmatter, body: body2, bodyLineOffset } = splitFrontmatter2(normalized);
|
|
32110
32214
|
const node3 = parseNodeRecord(frontmatter);
|
|
32111
32215
|
const nodeIssues = validateKnowledgeNode(node3);
|
|
32112
32216
|
if (nodeIssues.length > 0) {
|
|
@@ -32117,7 +32221,9 @@ function parseRootNodeFrontmatterFirst(normalized) {
|
|
|
32117
32221
|
let index2 = 0;
|
|
32118
32222
|
while (index2 < lines.length && (lines[index2]?.trim() ?? "") === "")
|
|
32119
32223
|
index2 += 1;
|
|
32224
|
+
let rootStartLine = 1;
|
|
32120
32225
|
if ((lines[index2] ?? "").startsWith("# ")) {
|
|
32226
|
+
rootStartLine = bodyLineOffset + index2 + 1;
|
|
32121
32227
|
index2 += 1;
|
|
32122
32228
|
while (index2 < lines.length && (lines[index2]?.trim() ?? "") === "")
|
|
32123
32229
|
index2 += 1;
|
|
@@ -32126,12 +32232,13 @@ function parseRootNodeFrontmatterFirst(normalized) {
|
|
|
32126
32232
|
const bodyLines = [];
|
|
32127
32233
|
const containsList = [];
|
|
32128
32234
|
const children = [];
|
|
32235
|
+
const renderAutoBlockIssues = [];
|
|
32129
32236
|
const childLevel = 2;
|
|
32130
32237
|
while (index2 < lines.length) {
|
|
32131
32238
|
const currentLine = lines[index2] ?? "";
|
|
32132
32239
|
assertNoLegacySectionMarker(currentLine);
|
|
32133
32240
|
if (new RegExp(`^#{${childLevel}}\\s+.+`).test(currentLine) && peekIsFrontmatterAfterHeading(lines, index2)) {
|
|
32134
|
-
const childResult = parseNodeBlock(lines, index2, childLevel);
|
|
32241
|
+
const childResult = parseNodeBlock(lines, index2, childLevel, bodyLineOffset);
|
|
32135
32242
|
children.push(childResult.parsed);
|
|
32136
32243
|
index2 = childResult.nextIndex;
|
|
32137
32244
|
continue;
|
|
@@ -32148,8 +32255,12 @@ function parseRootNodeFrontmatterFirst(normalized) {
|
|
|
32148
32255
|
index2 = listParsed.nextIndex;
|
|
32149
32256
|
continue;
|
|
32150
32257
|
}
|
|
32151
|
-
|
|
32152
|
-
|
|
32258
|
+
const autoBlock = consumeAutoBlock(lines, index2, 2, bodyLineOffset);
|
|
32259
|
+
if (autoBlock.issue !== undefined) {
|
|
32260
|
+
renderAutoBlockIssues.push(autoBlock.issue);
|
|
32261
|
+
}
|
|
32262
|
+
if (autoBlock.matched) {
|
|
32263
|
+
index2 = autoBlock.nextIndex;
|
|
32153
32264
|
continue;
|
|
32154
32265
|
}
|
|
32155
32266
|
if (isSectionGroupHeading(currentLine, 2)) {
|
|
@@ -32184,20 +32295,33 @@ function parseRootNodeFrontmatterFirst(normalized) {
|
|
|
32184
32295
|
return {
|
|
32185
32296
|
node: node3,
|
|
32186
32297
|
headingLevel: 1,
|
|
32298
|
+
startLine: rootStartLine,
|
|
32299
|
+
endLine: bodyLineOffset + lines.length,
|
|
32187
32300
|
body: bodyText,
|
|
32188
32301
|
sections,
|
|
32189
32302
|
children,
|
|
32190
32303
|
containsEdges,
|
|
32191
|
-
containsList
|
|
32304
|
+
containsList,
|
|
32305
|
+
...renderAutoBlockIssues.length > 0 ? { renderAutoBlockIssues } : {}
|
|
32192
32306
|
};
|
|
32193
32307
|
}
|
|
32194
|
-
var import_yaml10;
|
|
32308
|
+
var import_yaml10, AUTO_BLOCK_TITLES, AUTO_BLOCK_EXCLUDED_CONTAINS_TITLES, AUTO_BLOCK_CLOSE = "<!-- /c4a:auto-block -->";
|
|
32195
32309
|
var init_nodeParser = __esm(() => {
|
|
32196
32310
|
init_normalize();
|
|
32197
32311
|
init_nodeDisplayGroups();
|
|
32198
32312
|
init_nodeParserSections();
|
|
32199
32313
|
init_knowledge();
|
|
32200
32314
|
import_yaml10 = __toESM(require_dist(), 1);
|
|
32315
|
+
AUTO_BLOCK_TITLES = new Map([
|
|
32316
|
+
["Depends On", "depends_on"],
|
|
32317
|
+
["External Dependencies", "external_dependencies"],
|
|
32318
|
+
["Used By", "used_by"],
|
|
32319
|
+
["Related", "related"]
|
|
32320
|
+
]);
|
|
32321
|
+
AUTO_BLOCK_EXCLUDED_CONTAINS_TITLES = new Set([
|
|
32322
|
+
"Contains",
|
|
32323
|
+
...AUTO_BLOCK_TITLES.keys()
|
|
32324
|
+
]);
|
|
32201
32325
|
});
|
|
32202
32326
|
|
|
32203
32327
|
// src/lib/nodeRenderer.ts
|
|
@@ -32347,8 +32471,67 @@ function renderContainsList(entries, headingLevel) {
|
|
|
32347
32471
|
return lines.join(`
|
|
32348
32472
|
`);
|
|
32349
32473
|
}
|
|
32350
|
-
function
|
|
32474
|
+
function normalizeRenderOptions(options) {
|
|
32475
|
+
return {
|
|
32476
|
+
nodeLinkMode: options?.nodeLinkMode ?? "md",
|
|
32477
|
+
usedBy: options?.usedBy ?? true
|
|
32478
|
+
};
|
|
32479
|
+
}
|
|
32480
|
+
function formatVersionLabel(value) {
|
|
32481
|
+
const label = String(value);
|
|
32482
|
+
return label.startsWith("v") ? label : `v${label}`;
|
|
32483
|
+
}
|
|
32484
|
+
function formatVersionAnnotation(entry) {
|
|
32485
|
+
if (entry.valid_from !== undefined && entry.valid_until !== undefined) {
|
|
32486
|
+
return ` — from ${formatVersionLabel(entry.valid_from)} before ${formatVersionLabel(entry.valid_until)}`;
|
|
32487
|
+
}
|
|
32488
|
+
if (entry.valid_from !== undefined) {
|
|
32489
|
+
return ` — since ${formatVersionLabel(entry.valid_from)}`;
|
|
32490
|
+
}
|
|
32491
|
+
if (entry.valid_until !== undefined) {
|
|
32492
|
+
return ` — before ${formatVersionLabel(entry.valid_until)}`;
|
|
32493
|
+
}
|
|
32494
|
+
return "";
|
|
32495
|
+
}
|
|
32496
|
+
function formatNodeLink(link2, mode) {
|
|
32497
|
+
if (mode === "wiki" && link2.wikiTarget !== undefined && link2.wikiTarget.length > 0) {
|
|
32498
|
+
return `[[${link2.wikiTarget}|${link2.title}]]`;
|
|
32499
|
+
}
|
|
32500
|
+
return `[${link2.title}](${link2.href})`;
|
|
32501
|
+
}
|
|
32502
|
+
function renderAutoBlock(headingTitle, kind, headingLevel, lines) {
|
|
32503
|
+
if (lines.length === 0)
|
|
32504
|
+
return "";
|
|
32505
|
+
const hashes = "#".repeat(headingLevel);
|
|
32506
|
+
return [
|
|
32507
|
+
`${hashes} ${headingTitle}`,
|
|
32508
|
+
"",
|
|
32509
|
+
`<!-- c4a:auto-block ${kind} -->`,
|
|
32510
|
+
...lines,
|
|
32511
|
+
"<!-- /c4a:auto-block -->"
|
|
32512
|
+
].join(`
|
|
32513
|
+
`);
|
|
32514
|
+
}
|
|
32515
|
+
function renderNodeRelationBlock(headingTitle, kind, entries, headingLevel, linkMode) {
|
|
32516
|
+
if (entries === undefined || entries.length === 0)
|
|
32517
|
+
return "";
|
|
32518
|
+
const lines = [...entries].sort((left, right) => left.slug.localeCompare(right.slug)).map((entry) => `- ${formatNodeLink(entry, linkMode)}${formatVersionAnnotation(entry)}`);
|
|
32519
|
+
return renderAutoBlock(headingTitle, kind, headingLevel, lines);
|
|
32520
|
+
}
|
|
32521
|
+
function renderExternalDependencyBlock(entries, headingLevel) {
|
|
32522
|
+
if (entries === undefined || entries.length === 0)
|
|
32523
|
+
return "";
|
|
32524
|
+
const lines = [...entries].sort((left, right) => left.package.localeCompare(right.package)).map((entry) => {
|
|
32525
|
+
const version2 = entry.version_constraint !== undefined ? ` \`${entry.version_constraint}\`` : "";
|
|
32526
|
+
return `- \`${entry.package}\`${version2}${formatVersionAnnotation(entry)}`;
|
|
32527
|
+
});
|
|
32528
|
+
return renderAutoBlock("External Dependencies", "external_dependencies", headingLevel, lines);
|
|
32529
|
+
}
|
|
32530
|
+
function renderRelatedList(nodeSlug, sections, headingLevel, containsList = [], graphEdges = [], relatedLinks = new Map, renderOptions, excludedRelatedSlugs = []) {
|
|
32531
|
+
const options = normalizeRenderOptions(renderOptions);
|
|
32351
32532
|
const contained = new Set(containsList.map((entry) => entry.slug));
|
|
32533
|
+
for (const slug of excludedRelatedSlugs)
|
|
32534
|
+
contained.add(slug);
|
|
32352
32535
|
for (const edge2 of graphEdges) {
|
|
32353
32536
|
if (edge2.type !== "contains")
|
|
32354
32537
|
continue;
|
|
@@ -32367,26 +32550,25 @@ function renderRelatedList(nodeSlug, sections, headingLevel, containsList = [],
|
|
|
32367
32550
|
related.set(slug, [...related.get(slug) ?? [], section.id]);
|
|
32368
32551
|
}
|
|
32369
32552
|
}
|
|
32370
|
-
for (const edge2 of graphEdges) {
|
|
32371
|
-
if (edge2.type === "contains")
|
|
32372
|
-
continue;
|
|
32373
|
-
const target = edge2.from === nodeSlug ? edge2.to : null;
|
|
32374
|
-
if (!target || contained.has(target))
|
|
32375
|
-
continue;
|
|
32376
|
-
const label = `align:${edge2.type}`;
|
|
32377
|
-
related.set(target, [...related.get(target) ?? [], label]);
|
|
32378
|
-
}
|
|
32379
32553
|
if (related.size === 0)
|
|
32380
32554
|
return "";
|
|
32381
|
-
const
|
|
32382
|
-
const lines = [`${hashes} Related`, ""];
|
|
32555
|
+
const lines = [];
|
|
32383
32556
|
for (const [slug] of [...related.entries()].sort(([left], [right]) => left.localeCompare(right))) {
|
|
32384
32557
|
const link2 = relatedLinks.get(slug);
|
|
32385
|
-
const renderedTarget = link2 ?
|
|
32558
|
+
const renderedTarget = link2 ? formatNodeLink(link2, options.nodeLinkMode) : `\`${slug}\``;
|
|
32386
32559
|
lines.push(`- ${renderedTarget}`);
|
|
32387
32560
|
}
|
|
32388
|
-
return lines
|
|
32389
|
-
|
|
32561
|
+
return renderAutoBlock("Related", "related", headingLevel, lines);
|
|
32562
|
+
}
|
|
32563
|
+
function renderRelationBlocks(input, headingLevel) {
|
|
32564
|
+
const options = normalizeRenderOptions(input.renderOptions);
|
|
32565
|
+
const blocks = [
|
|
32566
|
+
renderNodeRelationBlock("Depends On", "depends_on", input.dependsOn, headingLevel, options.nodeLinkMode),
|
|
32567
|
+
renderExternalDependencyBlock(input.externalDependencies, headingLevel),
|
|
32568
|
+
...options.usedBy ? [renderNodeRelationBlock("Used By", "used_by", input.usedBy, headingLevel, options.nodeLinkMode)] : [],
|
|
32569
|
+
renderRelatedList(input.node.id, input.sections, headingLevel, input.containsList, input.graphEdges, input.relatedLinks, input.renderOptions, [...(input.dependsOn ?? []).map((entry) => entry.slug), ...(input.usedBy ?? []).map((entry) => entry.slug)])
|
|
32570
|
+
];
|
|
32571
|
+
return blocks.filter((block) => block.length > 0);
|
|
32390
32572
|
}
|
|
32391
32573
|
function renderedBody(input) {
|
|
32392
32574
|
if (input.body !== undefined && input.body.trim().length > 0) {
|
|
@@ -32412,13 +32594,13 @@ function renderNodeMarkdown(input) {
|
|
|
32412
32594
|
parts.push("", renderChildNodeBlock({
|
|
32413
32595
|
...child,
|
|
32414
32596
|
graphEdges: input.graphEdges ?? [],
|
|
32415
|
-
...input.relatedLinks !== undefined ? { relatedLinks: input.relatedLinks } : {}
|
|
32597
|
+
...input.relatedLinks !== undefined ? { relatedLinks: input.relatedLinks } : {},
|
|
32598
|
+
...input.renderOptions !== undefined ? { renderOptions: input.renderOptions } : {}
|
|
32416
32599
|
}, 2));
|
|
32417
32600
|
}
|
|
32418
32601
|
}
|
|
32419
|
-
const
|
|
32420
|
-
|
|
32421
|
-
parts.push("", related);
|
|
32602
|
+
for (const block of renderRelationBlocks(input, 2)) {
|
|
32603
|
+
parts.push("", block);
|
|
32422
32604
|
}
|
|
32423
32605
|
return `${parts.join(`
|
|
32424
32606
|
`).replace(/\n{3,}/g, `
|
|
@@ -32445,13 +32627,13 @@ function renderChildNodeBlock(input, headingLevel) {
|
|
|
32445
32627
|
parts.push("", renderChildNodeBlock({
|
|
32446
32628
|
...child,
|
|
32447
32629
|
graphEdges: input.graphEdges ?? [],
|
|
32448
|
-
...input.relatedLinks !== undefined ? { relatedLinks: input.relatedLinks } : {}
|
|
32630
|
+
...input.relatedLinks !== undefined ? { relatedLinks: input.relatedLinks } : {},
|
|
32631
|
+
...input.renderOptions !== undefined ? { renderOptions: input.renderOptions } : {}
|
|
32449
32632
|
}, headingLevel + 1));
|
|
32450
32633
|
}
|
|
32451
32634
|
}
|
|
32452
|
-
const
|
|
32453
|
-
|
|
32454
|
-
parts.push("", related);
|
|
32635
|
+
for (const block of renderRelationBlocks(input, headingLevel + 1)) {
|
|
32636
|
+
parts.push("", block);
|
|
32455
32637
|
}
|
|
32456
32638
|
return parts.join(`
|
|
32457
32639
|
`);
|
|
@@ -32488,15 +32670,15 @@ function flatSlugForNestedSlug(slug) {
|
|
|
32488
32670
|
return pkg && leaf ? `${pkg}-${leaf}` : null;
|
|
32489
32671
|
}
|
|
32490
32672
|
|
|
32491
|
-
// src/mdrive/
|
|
32673
|
+
// src/mdrive/externalDeps.ts
|
|
32492
32674
|
import { existsSync as existsSync9 } from "node:fs";
|
|
32493
32675
|
import { readFile as readFile10, readdir as readdir2, rm as rm2 } from "node:fs/promises";
|
|
32494
32676
|
import { join as join10, relative as relative3, resolve as resolve3 } from "node:path";
|
|
32495
32677
|
function knowledgeRoot(ctxDir) {
|
|
32496
32678
|
return join10(ctxDir, "knowledge");
|
|
32497
32679
|
}
|
|
32498
|
-
function
|
|
32499
|
-
return join10(knowledgeRoot(ctxDir), "
|
|
32680
|
+
function externalDepsPath(ctxDir) {
|
|
32681
|
+
return join10(knowledgeRoot(ctxDir), "_external.yaml");
|
|
32500
32682
|
}
|
|
32501
32683
|
function toPosixPath(value) {
|
|
32502
32684
|
return value.replace(/\\/g, "/");
|
|
@@ -32507,11 +32689,262 @@ function relativeToKnowledge(ctxDir, path3) {
|
|
|
32507
32689
|
function isTemporalValue(value) {
|
|
32508
32690
|
return typeof value === "string" || typeof value === "number";
|
|
32509
32691
|
}
|
|
32692
|
+
function isExternalDep(value) {
|
|
32693
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
32694
|
+
return false;
|
|
32695
|
+
const dep = value;
|
|
32696
|
+
return typeof dep.from === "string" && typeof dep.package === "string" && (dep.version_constraint === undefined || typeof dep.version_constraint === "string") && (dep.valid_from === undefined || isTemporalValue(dep.valid_from)) && (dep.valid_until === undefined || isTemporalValue(dep.valid_until));
|
|
32697
|
+
}
|
|
32698
|
+
function cleanExternalDep(dep, sourcePath) {
|
|
32699
|
+
return {
|
|
32700
|
+
from: dep.from,
|
|
32701
|
+
package: dep.package,
|
|
32702
|
+
...dep.version_constraint !== undefined ? { version_constraint: dep.version_constraint } : {},
|
|
32703
|
+
...dep.valid_from !== undefined ? { valid_from: dep.valid_from } : {},
|
|
32704
|
+
...dep.valid_until !== undefined ? { valid_until: dep.valid_until } : {},
|
|
32705
|
+
...sourcePath !== undefined ? { source_path: sourcePath } : {}
|
|
32706
|
+
};
|
|
32707
|
+
}
|
|
32708
|
+
function externalSortKey(dep) {
|
|
32709
|
+
return [
|
|
32710
|
+
dep.from,
|
|
32711
|
+
dep.package,
|
|
32712
|
+
dep.version_constraint ?? "",
|
|
32713
|
+
String(dep.valid_from ?? ""),
|
|
32714
|
+
String(dep.valid_until ?? "")
|
|
32715
|
+
].join(":");
|
|
32716
|
+
}
|
|
32717
|
+
async function atomicWriteYaml(path3, value) {
|
|
32718
|
+
await atomicWriteFile(path3, import_yaml12.default.stringify(value));
|
|
32719
|
+
}
|
|
32720
|
+
function includeTarget(ctxDir, includePath) {
|
|
32721
|
+
if (includePath.startsWith("/") || includePath.length === 0) {
|
|
32722
|
+
return { filePath: includePath, error: "include path must be relative to knowledge/" };
|
|
32723
|
+
}
|
|
32724
|
+
const root2 = resolve3(knowledgeRoot(ctxDir));
|
|
32725
|
+
const target = resolve3(root2, includePath);
|
|
32726
|
+
if (target !== root2 && !target.startsWith(`${root2}/`)) {
|
|
32727
|
+
return { filePath: target, error: "include path must stay under knowledge/" };
|
|
32728
|
+
}
|
|
32729
|
+
return { filePath: target };
|
|
32730
|
+
}
|
|
32731
|
+
async function readExternalFile(ctxDir, filePath) {
|
|
32732
|
+
const parsed = import_yaml12.default.parse(await readFile10(filePath, "utf8"));
|
|
32733
|
+
const relativePath = relativeToKnowledge(ctxDir, filePath);
|
|
32734
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
32735
|
+
return { filePath, relativePath, includes: [], externals: [], rawExternals: [] };
|
|
32736
|
+
}
|
|
32737
|
+
const file = parsed;
|
|
32738
|
+
if (file.schema_version !== 1) {
|
|
32739
|
+
return { filePath, relativePath, includes: [], externals: [], rawExternals: [] };
|
|
32740
|
+
}
|
|
32741
|
+
const includes = Array.isArray(file.includes) ? file.includes.filter((item) => typeof item === "string") : [];
|
|
32742
|
+
const rawExternals = Array.isArray(file.externals) ? file.externals : [];
|
|
32743
|
+
const externals = rawExternals.filter(isExternalDep).map((dep) => cleanExternalDep(dep, relativePath));
|
|
32744
|
+
return { filePath, relativePath, includes, externals, rawExternals };
|
|
32745
|
+
}
|
|
32746
|
+
async function inspectExternalDeps(ctxDir) {
|
|
32747
|
+
const rootPath = externalDepsPath(ctxDir);
|
|
32748
|
+
const issues = [];
|
|
32749
|
+
const files = [];
|
|
32750
|
+
const visited = new Set;
|
|
32751
|
+
const stack = new Set;
|
|
32752
|
+
const referencedIncludes = new Set;
|
|
32753
|
+
const visit2 = async (filePath, viaInclude) => {
|
|
32754
|
+
const relativePath = relativeToKnowledge(ctxDir, filePath);
|
|
32755
|
+
if (stack.has(filePath)) {
|
|
32756
|
+
issues.push({
|
|
32757
|
+
code: "external-include-cycle",
|
|
32758
|
+
message: `external include cycle detected at "${relativePath}"`,
|
|
32759
|
+
path: viaInclude ?? relativePath
|
|
32760
|
+
});
|
|
32761
|
+
return;
|
|
32762
|
+
}
|
|
32763
|
+
if (visited.has(filePath))
|
|
32764
|
+
return;
|
|
32765
|
+
if (!existsSync9(filePath)) {
|
|
32766
|
+
issues.push({
|
|
32767
|
+
code: "external-include-missing",
|
|
32768
|
+
message: `external include "${viaInclude ?? relativePath}" does not exist`,
|
|
32769
|
+
path: viaInclude ?? relativePath
|
|
32770
|
+
});
|
|
32771
|
+
return;
|
|
32772
|
+
}
|
|
32773
|
+
visited.add(filePath);
|
|
32774
|
+
stack.add(filePath);
|
|
32775
|
+
const file = await readExternalFile(ctxDir, filePath);
|
|
32776
|
+
files.push(file);
|
|
32777
|
+
const includeSeenInFile = new Set;
|
|
32778
|
+
for (const includePath of file.includes) {
|
|
32779
|
+
if (includeSeenInFile.has(includePath)) {
|
|
32780
|
+
issues.push({
|
|
32781
|
+
code: "external-include-duplicate",
|
|
32782
|
+
message: `external include "${includePath}" is declared more than once`,
|
|
32783
|
+
path: file.relativePath
|
|
32784
|
+
});
|
|
32785
|
+
}
|
|
32786
|
+
includeSeenInFile.add(includePath);
|
|
32787
|
+
referencedIncludes.add(includePath);
|
|
32788
|
+
const target = includeTarget(ctxDir, includePath);
|
|
32789
|
+
if (target.error) {
|
|
32790
|
+
issues.push({
|
|
32791
|
+
code: "external-include-outside-knowledge",
|
|
32792
|
+
message: target.error,
|
|
32793
|
+
path: file.relativePath
|
|
32794
|
+
});
|
|
32795
|
+
continue;
|
|
32796
|
+
}
|
|
32797
|
+
await visit2(target.filePath, includePath);
|
|
32798
|
+
}
|
|
32799
|
+
stack.delete(filePath);
|
|
32800
|
+
};
|
|
32801
|
+
if (existsSync9(rootPath)) {
|
|
32802
|
+
await visit2(rootPath);
|
|
32803
|
+
}
|
|
32804
|
+
const entityRoot = join10(knowledgeRoot(ctxDir), "entity");
|
|
32805
|
+
if (existsSync9(entityRoot)) {
|
|
32806
|
+
const entries = await readdir2(entityRoot, { withFileTypes: true });
|
|
32807
|
+
for (const entry of entries) {
|
|
32808
|
+
if (!entry.isDirectory())
|
|
32809
|
+
continue;
|
|
32810
|
+
const packageExternalPath = join10(entityRoot, entry.name, "_external.yaml");
|
|
32811
|
+
const includePath = `entity/${entry.name}/_external.yaml`;
|
|
32812
|
+
if (existsSync9(packageExternalPath) && !referencedIncludes.has(includePath)) {
|
|
32813
|
+
issues.push({
|
|
32814
|
+
code: "external-include-unreachable",
|
|
32815
|
+
message: `external file "${includePath}" exists but is not included by knowledge/_external.yaml`,
|
|
32816
|
+
path: includePath
|
|
32817
|
+
});
|
|
32818
|
+
}
|
|
32819
|
+
}
|
|
32820
|
+
}
|
|
32821
|
+
return {
|
|
32822
|
+
files,
|
|
32823
|
+
externals: files.flatMap((file) => file.externals),
|
|
32824
|
+
issues
|
|
32825
|
+
};
|
|
32826
|
+
}
|
|
32827
|
+
async function loadExternalDeps(ctxDir) {
|
|
32828
|
+
return (await inspectExternalDeps(ctxDir)).externals;
|
|
32829
|
+
}
|
|
32830
|
+
async function readRootExternalFile(ctxDir) {
|
|
32831
|
+
const path3 = externalDepsPath(ctxDir);
|
|
32832
|
+
if (!existsSync9(path3))
|
|
32833
|
+
return { schema_version: 1, includes: [], externals: [] };
|
|
32834
|
+
const parsed = import_yaml12.default.parse(await readFile10(path3, "utf8"));
|
|
32835
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
32836
|
+
return { schema_version: 1, includes: [], externals: [] };
|
|
32837
|
+
const file = parsed;
|
|
32838
|
+
return {
|
|
32839
|
+
schema_version: 1,
|
|
32840
|
+
includes: Array.isArray(file.includes) ? file.includes.filter((item) => typeof item === "string") : [],
|
|
32841
|
+
externals: Array.isArray(file.externals) ? file.externals.filter(isExternalDep).map((dep) => cleanExternalDep(dep)) : []
|
|
32842
|
+
};
|
|
32843
|
+
}
|
|
32844
|
+
async function writeExternalFile(ctxDir, relativePath, deps, includes = []) {
|
|
32845
|
+
const path3 = join10(knowledgeRoot(ctxDir), relativePath);
|
|
32846
|
+
const file = {
|
|
32847
|
+
schema_version: 1,
|
|
32848
|
+
...includes.length > 0 ? { includes: [...includes].sort() } : {},
|
|
32849
|
+
externals: [...deps].map((dep) => cleanExternalDep(dep)).sort((left, right) => externalSortKey(left).localeCompare(externalSortKey(right)))
|
|
32850
|
+
};
|
|
32851
|
+
await atomicWriteYaml(path3, file);
|
|
32852
|
+
}
|
|
32853
|
+
async function syncRootIncludes(ctxDir, packageIncludes) {
|
|
32854
|
+
const root2 = await readRootExternalFile(ctxDir);
|
|
32855
|
+
const rootIncludes = new Set((root2.includes ?? []).filter((include) => !/^entity\/[^/]+\/_external\.yaml$/u.test(include)));
|
|
32856
|
+
for (const include of packageIncludes)
|
|
32857
|
+
rootIncludes.add(include);
|
|
32858
|
+
await writeExternalFile(ctxDir, "_external.yaml", root2.externals, [...rootIncludes]);
|
|
32859
|
+
}
|
|
32860
|
+
function shouldKeepExistingDep(dep, options) {
|
|
32861
|
+
if (options.fromOwners !== undefined) {
|
|
32862
|
+
return !options.fromOwners.has(ownerSlugForPackageScopedPath(dep.from));
|
|
32863
|
+
}
|
|
32864
|
+
if (options.fromOwner !== undefined) {
|
|
32865
|
+
return dep.from !== options.fromOwner && !dep.from.startsWith(`${options.fromOwner}/`);
|
|
32866
|
+
}
|
|
32867
|
+
if (options.fromPrefix !== undefined)
|
|
32868
|
+
return !dep.from.startsWith(options.fromPrefix);
|
|
32869
|
+
return false;
|
|
32870
|
+
}
|
|
32871
|
+
async function replaceExternalDepsInternal(ctxDir, deps, options = {}) {
|
|
32872
|
+
const inspection = await inspectExternalDeps(ctxDir);
|
|
32873
|
+
const byPath = new Map;
|
|
32874
|
+
const includesByPath = new Map;
|
|
32875
|
+
for (const file of inspection.files) {
|
|
32876
|
+
const kept = file.externals.filter((dep) => shouldKeepExistingDep(dep, options));
|
|
32877
|
+
byPath.set(file.relativePath, kept);
|
|
32878
|
+
includesByPath.set(file.relativePath, file.includes);
|
|
32879
|
+
}
|
|
32880
|
+
for (const dep of deps) {
|
|
32881
|
+
const relativePath = externalDepRelativePath(dep);
|
|
32882
|
+
const bucket = byPath.get(relativePath) ?? [];
|
|
32883
|
+
byPath.set(relativePath, [...bucket, cleanExternalDep(dep)]);
|
|
32884
|
+
}
|
|
32885
|
+
const packageIncludes = new Set;
|
|
32886
|
+
for (const [relativePath, nextDeps] of byPath) {
|
|
32887
|
+
const includes = includesByPath.get(relativePath) ?? [];
|
|
32888
|
+
const isPackageExternalFile = /^entity\/[^/]+\/_external\.yaml$/u.test(relativePath);
|
|
32889
|
+
if (relativePath === "_external.yaml") {
|
|
32890
|
+
const root2 = await readRootExternalFile(ctxDir);
|
|
32891
|
+
await writeExternalFile(ctxDir, "_external.yaml", nextDeps, root2.includes ?? []);
|
|
32892
|
+
continue;
|
|
32893
|
+
}
|
|
32894
|
+
if (nextDeps.length === 0) {
|
|
32895
|
+
if (isPackageExternalFile && includes.length === 0) {
|
|
32896
|
+
await rm2(join10(knowledgeRoot(ctxDir), relativePath), { force: true });
|
|
32897
|
+
} else {
|
|
32898
|
+
await writeExternalFile(ctxDir, relativePath, [], includes);
|
|
32899
|
+
}
|
|
32900
|
+
continue;
|
|
32901
|
+
}
|
|
32902
|
+
if (isPackageExternalFile)
|
|
32903
|
+
packageIncludes.add(relativePath);
|
|
32904
|
+
await writeExternalFile(ctxDir, relativePath, nextDeps, includes);
|
|
32905
|
+
}
|
|
32906
|
+
for (const [relativePath, nextDeps] of byPath) {
|
|
32907
|
+
const includes = includesByPath.get(relativePath) ?? [];
|
|
32908
|
+
if (/^entity\/[^/]+\/_external\.yaml$/u.test(relativePath) && (nextDeps.length > 0 || includes.length > 0)) {
|
|
32909
|
+
packageIncludes.add(relativePath);
|
|
32910
|
+
}
|
|
32911
|
+
}
|
|
32912
|
+
await syncRootIncludes(ctxDir, packageIncludes);
|
|
32913
|
+
return deps.length;
|
|
32914
|
+
}
|
|
32915
|
+
async function replaceExternalDepsForOwners(ctxDir, deps, owners) {
|
|
32916
|
+
return replaceExternalDepsInternal(ctxDir, deps, { fromOwners: owners });
|
|
32917
|
+
}
|
|
32918
|
+
var import_yaml12;
|
|
32919
|
+
var init_externalDeps = __esm(() => {
|
|
32920
|
+
init_atomicWrite();
|
|
32921
|
+
import_yaml12 = __toESM(require_dist(), 1);
|
|
32922
|
+
});
|
|
32923
|
+
|
|
32924
|
+
// src/mdrive/graphEdges.ts
|
|
32925
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
32926
|
+
import { readFile as readFile11, readdir as readdir3, rm as rm3 } from "node:fs/promises";
|
|
32927
|
+
import { join as join11, relative as relative4, resolve as resolve4 } from "node:path";
|
|
32928
|
+
function knowledgeRoot2(ctxDir) {
|
|
32929
|
+
return join11(ctxDir, "knowledge");
|
|
32930
|
+
}
|
|
32931
|
+
function graphEdgesPath(ctxDir) {
|
|
32932
|
+
return join11(knowledgeRoot2(ctxDir), "_edges.yaml");
|
|
32933
|
+
}
|
|
32934
|
+
function toPosixPath2(value) {
|
|
32935
|
+
return value.replace(/\\/g, "/");
|
|
32936
|
+
}
|
|
32937
|
+
function relativeToKnowledge2(ctxDir, path3) {
|
|
32938
|
+
return toPosixPath2(relative4(knowledgeRoot2(ctxDir), path3));
|
|
32939
|
+
}
|
|
32940
|
+
function isTemporalValue2(value) {
|
|
32941
|
+
return typeof value === "string" || typeof value === "number";
|
|
32942
|
+
}
|
|
32510
32943
|
function isStoredEdge(value) {
|
|
32511
32944
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
32512
32945
|
return false;
|
|
32513
32946
|
const edge2 = value;
|
|
32514
|
-
return typeof edge2.type === "string" && edge2.type === EdgeType2.depends_on && typeof edge2.from === "string" && typeof edge2.to === "string" && typeof edge2.grounding === "string" && (edge2.note === undefined || typeof edge2.note === "string") && (edge2.valid_from === undefined ||
|
|
32947
|
+
return typeof edge2.type === "string" && edge2.type === EdgeType2.depends_on && typeof edge2.from === "string" && typeof edge2.to === "string" && typeof edge2.grounding === "string" && (edge2.note === undefined || typeof edge2.note === "string") && (edge2.valid_from === undefined || isTemporalValue2(edge2.valid_from)) && (edge2.valid_until === undefined || isTemporalValue2(edge2.valid_until));
|
|
32515
32948
|
}
|
|
32516
32949
|
function cleanStoredEdge(edge2, sourcePath) {
|
|
32517
32950
|
return {
|
|
@@ -32525,23 +32958,23 @@ function cleanStoredEdge(edge2, sourcePath) {
|
|
|
32525
32958
|
...sourcePath !== undefined ? { source_path: sourcePath } : {}
|
|
32526
32959
|
};
|
|
32527
32960
|
}
|
|
32528
|
-
async function
|
|
32529
|
-
await atomicWriteFile(path3,
|
|
32961
|
+
async function atomicWriteYaml2(path3, value) {
|
|
32962
|
+
await atomicWriteFile(path3, import_yaml13.default.stringify(value));
|
|
32530
32963
|
}
|
|
32531
|
-
function
|
|
32964
|
+
function includeTarget2(ctxDir, includePath) {
|
|
32532
32965
|
if (includePath.startsWith("/") || includePath.length === 0) {
|
|
32533
32966
|
return { filePath: includePath, error: "include path must be relative to knowledge/" };
|
|
32534
32967
|
}
|
|
32535
|
-
const root2 =
|
|
32536
|
-
const target =
|
|
32968
|
+
const root2 = resolve4(knowledgeRoot2(ctxDir));
|
|
32969
|
+
const target = resolve4(root2, includePath);
|
|
32537
32970
|
if (target !== root2 && !target.startsWith(`${root2}/`)) {
|
|
32538
32971
|
return { filePath: target, error: "include path must stay under knowledge/" };
|
|
32539
32972
|
}
|
|
32540
32973
|
return { filePath: target };
|
|
32541
32974
|
}
|
|
32542
32975
|
async function readEdgeFile(ctxDir, filePath) {
|
|
32543
|
-
const parsed =
|
|
32544
|
-
const relativePath =
|
|
32976
|
+
const parsed = import_yaml13.default.parse(await readFile11(filePath, "utf8"));
|
|
32977
|
+
const relativePath = relativeToKnowledge2(ctxDir, filePath);
|
|
32545
32978
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
32546
32979
|
return { filePath, relativePath, includes: [], edges: [], rawEdges: [] };
|
|
32547
32980
|
}
|
|
@@ -32562,7 +32995,7 @@ async function inspectKnowledgeGraphEdges(ctxDir) {
|
|
|
32562
32995
|
const stack = new Set;
|
|
32563
32996
|
const referencedIncludes = new Set;
|
|
32564
32997
|
const visit2 = async (filePath, viaInclude) => {
|
|
32565
|
-
const relativePath =
|
|
32998
|
+
const relativePath = relativeToKnowledge2(ctxDir, filePath);
|
|
32566
32999
|
if (stack.has(filePath)) {
|
|
32567
33000
|
issues.push({
|
|
32568
33001
|
code: "edge-include-cycle",
|
|
@@ -32573,7 +33006,7 @@ async function inspectKnowledgeGraphEdges(ctxDir) {
|
|
|
32573
33006
|
}
|
|
32574
33007
|
if (visited.has(filePath))
|
|
32575
33008
|
return;
|
|
32576
|
-
if (!
|
|
33009
|
+
if (!existsSync10(filePath)) {
|
|
32577
33010
|
issues.push({
|
|
32578
33011
|
code: "edge-include-missing",
|
|
32579
33012
|
message: `edge include "${viaInclude ?? relativePath}" does not exist`,
|
|
@@ -32596,7 +33029,7 @@ async function inspectKnowledgeGraphEdges(ctxDir) {
|
|
|
32596
33029
|
}
|
|
32597
33030
|
includeSeenInFile.add(includePath);
|
|
32598
33031
|
referencedIncludes.add(includePath);
|
|
32599
|
-
const target =
|
|
33032
|
+
const target = includeTarget2(ctxDir, includePath);
|
|
32600
33033
|
if (target.error) {
|
|
32601
33034
|
issues.push({
|
|
32602
33035
|
code: "edge-include-outside-knowledge",
|
|
@@ -32609,18 +33042,18 @@ async function inspectKnowledgeGraphEdges(ctxDir) {
|
|
|
32609
33042
|
}
|
|
32610
33043
|
stack.delete(filePath);
|
|
32611
33044
|
};
|
|
32612
|
-
if (
|
|
33045
|
+
if (existsSync10(rootPath)) {
|
|
32613
33046
|
await visit2(rootPath);
|
|
32614
33047
|
}
|
|
32615
|
-
const entityRoot =
|
|
32616
|
-
if (
|
|
32617
|
-
const entries = await
|
|
33048
|
+
const entityRoot = join11(knowledgeRoot2(ctxDir), "entity");
|
|
33049
|
+
if (existsSync10(entityRoot)) {
|
|
33050
|
+
const entries = await readdir3(entityRoot, { withFileTypes: true });
|
|
32618
33051
|
for (const entry of entries) {
|
|
32619
33052
|
if (!entry.isDirectory())
|
|
32620
33053
|
continue;
|
|
32621
|
-
const packageEdgePath =
|
|
33054
|
+
const packageEdgePath = join11(entityRoot, entry.name, "_edges.yaml");
|
|
32622
33055
|
const includePath = `entity/${entry.name}/_edges.yaml`;
|
|
32623
|
-
if (
|
|
33056
|
+
if (existsSync10(packageEdgePath) && !referencedIncludes.has(includePath)) {
|
|
32624
33057
|
issues.push({
|
|
32625
33058
|
code: "edge-include-unreachable",
|
|
32626
33059
|
message: `edge file "${includePath}" exists but is not included by knowledge/_edges.yaml`,
|
|
@@ -32660,9 +33093,9 @@ function edgeSortKey(edge2) {
|
|
|
32660
33093
|
}
|
|
32661
33094
|
async function readRootGraphEdgesFile(ctxDir) {
|
|
32662
33095
|
const path3 = graphEdgesPath(ctxDir);
|
|
32663
|
-
if (!
|
|
33096
|
+
if (!existsSync10(path3))
|
|
32664
33097
|
return { schema_version: 1, includes: [], edges: [] };
|
|
32665
|
-
const parsed =
|
|
33098
|
+
const parsed = import_yaml13.default.parse(await readFile11(path3, "utf8"));
|
|
32666
33099
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
32667
33100
|
return { schema_version: 1, includes: [], edges: [] };
|
|
32668
33101
|
const file = parsed;
|
|
@@ -32673,15 +33106,15 @@ async function readRootGraphEdgesFile(ctxDir) {
|
|
|
32673
33106
|
};
|
|
32674
33107
|
}
|
|
32675
33108
|
async function writeEdgeFile(ctxDir, relativePath, edges, includes = []) {
|
|
32676
|
-
const path3 =
|
|
33109
|
+
const path3 = join11(knowledgeRoot2(ctxDir), relativePath);
|
|
32677
33110
|
const file = {
|
|
32678
33111
|
schema_version: 1,
|
|
32679
33112
|
...includes.length > 0 ? { includes: [...includes].sort() } : {},
|
|
32680
33113
|
edges: [...edges].map((edge2) => cleanStoredEdge(edge2)).sort((left, right) => edgeSortKey(left).localeCompare(edgeSortKey(right)))
|
|
32681
33114
|
};
|
|
32682
|
-
await
|
|
33115
|
+
await atomicWriteYaml2(path3, file);
|
|
32683
33116
|
}
|
|
32684
|
-
async function
|
|
33117
|
+
async function syncRootIncludes2(ctxDir, packageIncludes) {
|
|
32685
33118
|
const root2 = await readRootGraphEdgesFile(ctxDir);
|
|
32686
33119
|
const rootIncludes = new Set((root2.includes ?? []).filter((include) => !/^entity\/[^/]+\/_edges\.yaml$/u.test(include)));
|
|
32687
33120
|
for (const include of packageIncludes)
|
|
@@ -32750,7 +33183,7 @@ async function replaceCodeGraphEdges(ctxDir, grounding, edges) {
|
|
|
32750
33183
|
}
|
|
32751
33184
|
if (nextEdges.length === 0) {
|
|
32752
33185
|
if (isPackageEdgeFile && includes.length === 0) {
|
|
32753
|
-
await
|
|
33186
|
+
await rm3(join11(knowledgeRoot2(ctxDir), relativePath), { force: true });
|
|
32754
33187
|
} else {
|
|
32755
33188
|
await writeEdgeFile(ctxDir, relativePath, [], includes);
|
|
32756
33189
|
}
|
|
@@ -32766,7 +33199,7 @@ async function replaceCodeGraphEdges(ctxDir, grounding, edges) {
|
|
|
32766
33199
|
packageIncludes.add(relativePath);
|
|
32767
33200
|
}
|
|
32768
33201
|
}
|
|
32769
|
-
await
|
|
33202
|
+
await syncRootIncludes2(ctxDir, packageIncludes);
|
|
32770
33203
|
return written;
|
|
32771
33204
|
}
|
|
32772
33205
|
async function writeKnowledgeGraphEdgeFiles(ctxDir, edges) {
|
|
@@ -32792,7 +33225,7 @@ async function writeKnowledgeGraphEdgeFiles(ctxDir, edges) {
|
|
|
32792
33225
|
}
|
|
32793
33226
|
if (bucket.length === 0) {
|
|
32794
33227
|
if (isPackageEdgeFile && includes.length === 0) {
|
|
32795
|
-
await
|
|
33228
|
+
await rm3(join11(knowledgeRoot2(ctxDir), relativePath), { force: true });
|
|
32796
33229
|
} else {
|
|
32797
33230
|
await writeEdgeFile(ctxDir, relativePath, [], includes);
|
|
32798
33231
|
}
|
|
@@ -32808,7 +33241,7 @@ async function writeKnowledgeGraphEdgeFiles(ctxDir, edges) {
|
|
|
32808
33241
|
packageIncludes.add(relativePath);
|
|
32809
33242
|
}
|
|
32810
33243
|
}
|
|
32811
|
-
await
|
|
33244
|
+
await syncRootIncludes2(ctxDir, packageIncludes);
|
|
32812
33245
|
}
|
|
32813
33246
|
async function renameKnowledgeGraphEdgeNode(ctxDir, from, to) {
|
|
32814
33247
|
const existing = await loadKnowledgeGraphEdges(ctxDir);
|
|
@@ -32847,31 +33280,31 @@ async function removeKnowledgeGraphEdgesForNodes(ctxDir, slugs) {
|
|
|
32847
33280
|
}
|
|
32848
33281
|
return removed;
|
|
32849
33282
|
}
|
|
32850
|
-
var
|
|
33283
|
+
var import_yaml13;
|
|
32851
33284
|
var init_graphEdges = __esm(() => {
|
|
32852
33285
|
init_atomicWrite();
|
|
32853
33286
|
init_knowledge();
|
|
32854
|
-
|
|
33287
|
+
import_yaml13 = __toESM(require_dist(), 1);
|
|
32855
33288
|
});
|
|
32856
33289
|
|
|
32857
33290
|
// src/mdrive/shared.ts
|
|
32858
|
-
import { existsSync as
|
|
32859
|
-
import { mkdir as mkdir5, readFile as
|
|
32860
|
-
import { dirname as dirname6, join as
|
|
32861
|
-
function
|
|
33291
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
33292
|
+
import { mkdir as mkdir5, readFile as readFile12, readdir as readdir4, rm as rm4 } from "node:fs/promises";
|
|
33293
|
+
import { dirname as dirname6, join as join12, relative as relative5 } from "node:path";
|
|
33294
|
+
function toPosixPath3(value) {
|
|
32862
33295
|
return value.replace(/\\/g, "/");
|
|
32863
33296
|
}
|
|
32864
|
-
function
|
|
32865
|
-
return
|
|
33297
|
+
function knowledgeRoot3(ctxDir) {
|
|
33298
|
+
return join12(ctxDir, "knowledge");
|
|
32866
33299
|
}
|
|
32867
33300
|
function knowledgeDir(ctxDir, type) {
|
|
32868
|
-
return
|
|
33301
|
+
return join12(knowledgeRoot3(ctxDir), type);
|
|
32869
33302
|
}
|
|
32870
33303
|
function knowledgeFilePath(ctxDir, type, slug) {
|
|
32871
|
-
return
|
|
33304
|
+
return join12(knowledgeDir(ctxDir, type), `${slug}.md`);
|
|
32872
33305
|
}
|
|
32873
33306
|
function slugFromKnowledgeRelativePath(relativePath) {
|
|
32874
|
-
const normalized =
|
|
33307
|
+
const normalized = toPosixPath3(relativePath);
|
|
32875
33308
|
const parts = normalized.split("/");
|
|
32876
33309
|
if (parts.length === 2 && parts[1]?.endsWith(".md")) {
|
|
32877
33310
|
return parts[1].slice(0, -3);
|
|
@@ -32882,7 +33315,7 @@ function slugFromKnowledgeRelativePath(relativePath) {
|
|
|
32882
33315
|
return null;
|
|
32883
33316
|
}
|
|
32884
33317
|
function typeFromKnowledgeRelativePath(relativePath) {
|
|
32885
|
-
const [type] =
|
|
33318
|
+
const [type] = toPosixPath3(relativePath).split("/");
|
|
32886
33319
|
return NODE_TYPES.includes(type) ? type : null;
|
|
32887
33320
|
}
|
|
32888
33321
|
function derivedContainsEdgeForFile(file) {
|
|
@@ -32908,30 +33341,115 @@ async function atomicWriteText(path3, content3) {
|
|
|
32908
33341
|
await atomicWriteFile(path3, content3);
|
|
32909
33342
|
}
|
|
32910
33343
|
function ctxDirFromKnowledgeFilePath(filePath) {
|
|
32911
|
-
const marker = `${
|
|
32912
|
-
const normalized =
|
|
33344
|
+
const marker = `${toPosixPath3("/knowledge/")}`;
|
|
33345
|
+
const normalized = toPosixPath3(filePath);
|
|
32913
33346
|
const index2 = normalized.lastIndexOf(marker);
|
|
32914
33347
|
return index2 >= 0 ? normalized.slice(0, index2) : null;
|
|
32915
33348
|
}
|
|
32916
33349
|
async function buildRenderWorkspaceContext(ctxDir, files) {
|
|
32917
|
-
const graphEdges = await
|
|
33350
|
+
const [graphEdges, externalDeps, renderConfig] = await Promise.all([
|
|
33351
|
+
loadKnowledgeGraphEdges(ctxDir),
|
|
33352
|
+
loadExternalDeps(ctxDir),
|
|
33353
|
+
loadRenderConfig(ctxDir)
|
|
33354
|
+
]);
|
|
32918
33355
|
const workspaceFiles = files ?? await readWorkspaceNodeFiles(ctxDir);
|
|
32919
|
-
|
|
33356
|
+
return buildRenderWorkspaceContextFromData({
|
|
33357
|
+
files: workspaceFiles,
|
|
33358
|
+
graphEdges,
|
|
33359
|
+
externalDeps,
|
|
33360
|
+
renderOptions: {
|
|
33361
|
+
nodeLinkMode: renderConfig.obsidian_mode ? "wiki" : "md",
|
|
33362
|
+
usedBy: renderConfig.used_by
|
|
33363
|
+
}
|
|
33364
|
+
});
|
|
33365
|
+
}
|
|
33366
|
+
function buildRenderWorkspaceContextFromData(input) {
|
|
33367
|
+
const locatedNodes = flattenWorkspaceNodes(input.files);
|
|
33368
|
+
const anchorsByFile = new Map(input.files.map((file) => [file.filePath, computeNodeAnchorsForFile(file.root)]));
|
|
32920
33369
|
const relatedLinksByFile = new Map;
|
|
32921
|
-
|
|
33370
|
+
const relationEntriesByFile = new Map;
|
|
33371
|
+
for (const file of input.files) {
|
|
32922
33372
|
const links = new Map;
|
|
32923
33373
|
for (const target of locatedNodes) {
|
|
32924
|
-
const
|
|
32925
|
-
links.set(target.parsed.node.id, {
|
|
33374
|
+
const targetAnchors = anchorsByFile.get(target.filePath) ?? new Map;
|
|
33375
|
+
links.set(target.parsed.node.id, {
|
|
33376
|
+
title: target.parsed.node.title,
|
|
33377
|
+
href: markdownHrefForLocatedNode(file.filePath, target, targetAnchors),
|
|
33378
|
+
wikiTarget: wikiTargetForLocatedNode(target, targetAnchors)
|
|
33379
|
+
});
|
|
32926
33380
|
}
|
|
32927
33381
|
relatedLinksByFile.set(file.filePath, links);
|
|
33382
|
+
relationEntriesByFile.set(file.filePath, buildRelationEntriesByNodeSlug(flattenNodeTree(file.root, file.filePath, file.relativePath), input.graphEdges, input.externalDeps, links));
|
|
32928
33383
|
}
|
|
32929
33384
|
return {
|
|
32930
|
-
graphEdges,
|
|
32931
|
-
workspaceContains:
|
|
32932
|
-
relatedLinksByFile
|
|
33385
|
+
graphEdges: [...input.graphEdges],
|
|
33386
|
+
workspaceContains: input.files.flatMap((file) => file.root.containsEdges),
|
|
33387
|
+
relatedLinksByFile,
|
|
33388
|
+
relationEntriesByFile,
|
|
33389
|
+
renderOptions: input.renderOptions
|
|
32933
33390
|
};
|
|
32934
33391
|
}
|
|
33392
|
+
function computeNodeAnchorsForFile(root2) {
|
|
33393
|
+
const counts = new Map;
|
|
33394
|
+
const anchors = new Map;
|
|
33395
|
+
const claim = (title) => {
|
|
33396
|
+
const base = slugify(title);
|
|
33397
|
+
const seen = (counts.get(base) ?? 0) + 1;
|
|
33398
|
+
counts.set(base, seen);
|
|
33399
|
+
return seen === 1 ? base : `${base}-${seen}`;
|
|
33400
|
+
};
|
|
33401
|
+
const visit2 = (node3) => {
|
|
33402
|
+
anchors.set(node3.node.id, claim(node3.node.title));
|
|
33403
|
+
for (const child of node3.children)
|
|
33404
|
+
visit2(child);
|
|
33405
|
+
};
|
|
33406
|
+
visit2(root2);
|
|
33407
|
+
return anchors;
|
|
33408
|
+
}
|
|
33409
|
+
function markdownHrefForLocatedNode(fromFilePath, target, targetAnchors) {
|
|
33410
|
+
const anchor = targetAnchors.get(target.parsed.node.id);
|
|
33411
|
+
if (target.filePath === fromFilePath) {
|
|
33412
|
+
return anchor !== undefined ? `#${anchor}` : "";
|
|
33413
|
+
}
|
|
33414
|
+
const href = buildContainsHref(fromFilePath, target.filePath);
|
|
33415
|
+
return target.path.length > 0 && anchor !== undefined ? `${href}#${anchor}` : href;
|
|
33416
|
+
}
|
|
33417
|
+
function wikiTargetForLocatedNode(target, targetAnchors) {
|
|
33418
|
+
const base = toPosixPath3(target.relativePath).replace(/\.md$/u, "");
|
|
33419
|
+
const anchor = targetAnchors.get(target.parsed.node.id);
|
|
33420
|
+
return target.path.length > 0 && anchor !== undefined ? `${base}#${anchor}` : base;
|
|
33421
|
+
}
|
|
33422
|
+
function relationLink(links, slug) {
|
|
33423
|
+
return links.get(slug) ?? { title: slug, href: `${slug}.md`, wikiTarget: slug };
|
|
33424
|
+
}
|
|
33425
|
+
function toNodeRelationEntry(links, slug, edge2) {
|
|
33426
|
+
return {
|
|
33427
|
+
slug,
|
|
33428
|
+
...relationLink(links, slug),
|
|
33429
|
+
...edge2.valid_from !== undefined ? { valid_from: edge2.valid_from } : {},
|
|
33430
|
+
...edge2.valid_until !== undefined ? { valid_until: edge2.valid_until } : {}
|
|
33431
|
+
};
|
|
33432
|
+
}
|
|
33433
|
+
function toExternalDependencyEntry(dep) {
|
|
33434
|
+
return {
|
|
33435
|
+
package: dep.package,
|
|
33436
|
+
...dep.version_constraint !== undefined ? { version_constraint: dep.version_constraint } : {},
|
|
33437
|
+
...dep.valid_from !== undefined ? { valid_from: dep.valid_from } : {},
|
|
33438
|
+
...dep.valid_until !== undefined ? { valid_until: dep.valid_until } : {}
|
|
33439
|
+
};
|
|
33440
|
+
}
|
|
33441
|
+
function buildRelationEntriesByNodeSlug(nodesInFile, graphEdges, externalDeps, links) {
|
|
33442
|
+
const bySlug = new Map;
|
|
33443
|
+
for (const node3 of nodesInFile) {
|
|
33444
|
+
const slug = node3.parsed.node.id;
|
|
33445
|
+
bySlug.set(slug, {
|
|
33446
|
+
dependsOn: graphEdges.filter((edge2) => edge2.type === "depends_on" && edge2.from === slug).map((edge2) => toNodeRelationEntry(links, edge2.to, edge2)),
|
|
33447
|
+
usedBy: graphEdges.filter((edge2) => edge2.type === "depends_on" && edge2.to === slug).map((edge2) => toNodeRelationEntry(links, edge2.from, edge2)),
|
|
33448
|
+
externalDependencies: externalDeps.filter((dep) => dep.from === slug).map(toExternalDependencyEntry)
|
|
33449
|
+
});
|
|
33450
|
+
}
|
|
33451
|
+
return bySlug;
|
|
33452
|
+
}
|
|
32935
33453
|
function collectTreeSlugs(root2, out2 = new Set) {
|
|
32936
33454
|
out2.add(root2.node.id);
|
|
32937
33455
|
for (const child of root2.children) {
|
|
@@ -32963,27 +33481,79 @@ function collectCurrentContainsEdges(root2) {
|
|
|
32963
33481
|
visit2(root2);
|
|
32964
33482
|
return edges;
|
|
32965
33483
|
}
|
|
33484
|
+
function attachRelationInputs(input, filePath, context) {
|
|
33485
|
+
const relations = context.relationEntriesByFile.get(filePath)?.get(input.node.id);
|
|
33486
|
+
const relatedLinks = context.relatedLinksByFile.get(filePath);
|
|
33487
|
+
const output = {
|
|
33488
|
+
...input,
|
|
33489
|
+
...relations !== undefined ? {
|
|
33490
|
+
dependsOn: relations.dependsOn,
|
|
33491
|
+
usedBy: relations.usedBy,
|
|
33492
|
+
externalDependencies: relations.externalDependencies
|
|
33493
|
+
} : {},
|
|
33494
|
+
renderOptions: context.renderOptions
|
|
33495
|
+
};
|
|
33496
|
+
if (relatedLinks !== undefined) {
|
|
33497
|
+
output.relatedLinks = relatedLinks;
|
|
33498
|
+
}
|
|
33499
|
+
if (input.children !== undefined) {
|
|
33500
|
+
output.children = input.children.map((child) => attachRelationInputs(child, filePath, context));
|
|
33501
|
+
}
|
|
33502
|
+
return output;
|
|
33503
|
+
}
|
|
33504
|
+
function collectRenderInputSlugs(input, out2 = new Set) {
|
|
33505
|
+
out2.add(input.node.id);
|
|
33506
|
+
for (const child of input.children ?? []) {
|
|
33507
|
+
collectRenderInputSlugs(child, out2);
|
|
33508
|
+
}
|
|
33509
|
+
return out2;
|
|
33510
|
+
}
|
|
33511
|
+
function collectRenderInputChildContains(input) {
|
|
33512
|
+
const edges = [];
|
|
33513
|
+
const visit2 = (current) => {
|
|
33514
|
+
for (const child of current.children ?? []) {
|
|
33515
|
+
edges.push({
|
|
33516
|
+
type: "contains",
|
|
33517
|
+
from: current.node.id,
|
|
33518
|
+
to: child.node.id,
|
|
33519
|
+
grounding: "document"
|
|
33520
|
+
});
|
|
33521
|
+
visit2(child);
|
|
33522
|
+
}
|
|
33523
|
+
};
|
|
33524
|
+
visit2(input);
|
|
33525
|
+
return edges;
|
|
33526
|
+
}
|
|
33527
|
+
function renderNodeInputForFile(filePath, input, context) {
|
|
33528
|
+
const rootSlugs = collectRenderInputSlugs(input);
|
|
33529
|
+
const workspaceContains = context.workspaceContains.filter((edge2) => !rootSlugs.has(edge2.from));
|
|
33530
|
+
const rootContains = collectRenderInputChildContains(input);
|
|
33531
|
+
const decorated = attachRelationInputs({
|
|
33532
|
+
...input,
|
|
33533
|
+
graphEdges: [...context.graphEdges, ...workspaceContains, ...rootContains, ...input.graphEdges ?? []]
|
|
33534
|
+
}, filePath, context);
|
|
33535
|
+
return renderNodeMarkdown(decorated);
|
|
33536
|
+
}
|
|
32966
33537
|
async function renderRootForFile(filePath, root2, renderContext) {
|
|
32967
33538
|
const ctxDir = ctxDirFromKnowledgeFilePath(filePath);
|
|
32968
|
-
|
|
32969
|
-
|
|
32970
|
-
|
|
32971
|
-
|
|
32972
|
-
});
|
|
33539
|
+
if (renderContext === undefined && ctxDir === null) {
|
|
33540
|
+
throw new ContextError(ExitCode.WorkspaceStateError, "renderRootForFile requires a knowledge file path or an explicit render context", { category: "schema-invalid" });
|
|
33541
|
+
}
|
|
33542
|
+
const context = renderContext ?? await buildRenderWorkspaceContext(ctxDir);
|
|
32973
33543
|
const rootSlugs = collectTreeSlugs(root2);
|
|
32974
33544
|
const workspaceContains = context.workspaceContains.filter((edge2) => !rootSlugs.has(edge2.from));
|
|
32975
33545
|
const rootContains = collectCurrentContainsEdges(root2);
|
|
32976
|
-
|
|
33546
|
+
const decorated = attachRelationInputs({
|
|
32977
33547
|
...root2,
|
|
32978
|
-
graphEdges: [...context.graphEdges, ...workspaceContains, ...rootContains]
|
|
32979
|
-
|
|
32980
|
-
|
|
33548
|
+
graphEdges: [...context.graphEdges, ...workspaceContains, ...rootContains]
|
|
33549
|
+
}, filePath, context);
|
|
33550
|
+
return renderNodeMarkdown(decorated);
|
|
32981
33551
|
}
|
|
32982
33552
|
async function atomicRewriteRootFile(filePath, root2, nextFilePath, renderContext) {
|
|
32983
33553
|
const destination = nextFilePath ?? filePath;
|
|
32984
33554
|
await atomicWriteText(destination, await renderRootForFile(destination, root2, renderContext));
|
|
32985
|
-
if (destination !== filePath &&
|
|
32986
|
-
await
|
|
33555
|
+
if (destination !== filePath && existsSync11(filePath)) {
|
|
33556
|
+
await rm4(filePath);
|
|
32987
33557
|
}
|
|
32988
33558
|
}
|
|
32989
33559
|
async function writeStandaloneNodeFile(ctxDir, root2, renderContext) {
|
|
@@ -32993,7 +33563,7 @@ async function writeStandaloneNodeFile(ctxDir, root2, renderContext) {
|
|
|
32993
33563
|
return filePath;
|
|
32994
33564
|
}
|
|
32995
33565
|
function buildContainsHref(fromFilePath, toFilePath) {
|
|
32996
|
-
return
|
|
33566
|
+
return toPosixPath3(relative5(dirname6(fromFilePath), toFilePath));
|
|
32997
33567
|
}
|
|
32998
33568
|
function buildContainsEntry(fromFilePath, targetFilePath, targetSlug, targetTitle) {
|
|
32999
33569
|
return {
|
|
@@ -33006,25 +33576,25 @@ async function readWorkspaceNodeFiles(ctxDir) {
|
|
|
33006
33576
|
const files = [];
|
|
33007
33577
|
for (const type of NODE_TYPES) {
|
|
33008
33578
|
const dir = knowledgeDir(ctxDir, type);
|
|
33009
|
-
if (!
|
|
33579
|
+
if (!existsSync11(dir))
|
|
33010
33580
|
continue;
|
|
33011
|
-
const entries = await
|
|
33581
|
+
const entries = await readdir4(dir, { withFileTypes: true });
|
|
33012
33582
|
for (const entry of entries) {
|
|
33013
33583
|
if (entry.isFile()) {
|
|
33014
33584
|
if (!entry.name.endsWith(".md") || KNOWLEDGE_IGNORED_FILES.has(entry.name))
|
|
33015
33585
|
continue;
|
|
33016
|
-
files.push(await readWorkspaceNodeFile(ctxDir,
|
|
33586
|
+
files.push(await readWorkspaceNodeFile(ctxDir, join12(dir, entry.name)));
|
|
33017
33587
|
continue;
|
|
33018
33588
|
}
|
|
33019
33589
|
if (!entry.isDirectory())
|
|
33020
33590
|
continue;
|
|
33021
|
-
const nestedDir =
|
|
33022
|
-
const nestedEntries = await
|
|
33591
|
+
const nestedDir = join12(dir, entry.name);
|
|
33592
|
+
const nestedEntries = await readdir4(nestedDir, { withFileTypes: true });
|
|
33023
33593
|
for (const nestedEntry of nestedEntries) {
|
|
33024
33594
|
if (!nestedEntry.isFile() || !nestedEntry.name.endsWith(".md") || KNOWLEDGE_IGNORED_FILES.has(nestedEntry.name)) {
|
|
33025
33595
|
continue;
|
|
33026
33596
|
}
|
|
33027
|
-
files.push(await readWorkspaceNodeFile(ctxDir,
|
|
33597
|
+
files.push(await readWorkspaceNodeFile(ctxDir, join12(nestedDir, nestedEntry.name)));
|
|
33028
33598
|
}
|
|
33029
33599
|
}
|
|
33030
33600
|
}
|
|
@@ -33036,8 +33606,8 @@ async function readWorkspaceNodeFiles(ctxDir) {
|
|
|
33036
33606
|
return files;
|
|
33037
33607
|
}
|
|
33038
33608
|
async function readWorkspaceNodeFile(ctxDir, filePath) {
|
|
33039
|
-
const relativePath =
|
|
33040
|
-
const content3 = await
|
|
33609
|
+
const relativePath = toPosixPath3(relative5(knowledgeRoot3(ctxDir), filePath));
|
|
33610
|
+
const content3 = await readFile12(filePath, "utf8");
|
|
33041
33611
|
let root2;
|
|
33042
33612
|
try {
|
|
33043
33613
|
root2 = parseNodeMarkdown(content3);
|
|
@@ -33195,15 +33765,17 @@ var init_shared = __esm(() => {
|
|
|
33195
33765
|
init_nodeParser();
|
|
33196
33766
|
init_nodeRenderer();
|
|
33197
33767
|
init_normalize();
|
|
33768
|
+
init_config();
|
|
33198
33769
|
init_exitCode();
|
|
33199
33770
|
init_knowledge();
|
|
33771
|
+
init_externalDeps();
|
|
33200
33772
|
init_graphEdges();
|
|
33201
33773
|
KNOWLEDGE_IGNORED_FILES = new Set(["_index.md", "changelog.md"]);
|
|
33202
33774
|
});
|
|
33203
33775
|
|
|
33204
33776
|
// src/incremental/sectionFingerprints.ts
|
|
33205
|
-
import { readFile as
|
|
33206
|
-
import { join as
|
|
33777
|
+
import { readFile as readFile13 } from "node:fs/promises";
|
|
33778
|
+
import { join as join13 } from "node:path";
|
|
33207
33779
|
function isRecord4(value) {
|
|
33208
33780
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
33209
33781
|
}
|
|
@@ -33270,7 +33842,7 @@ function isRawBlocksCache(value) {
|
|
|
33270
33842
|
async function loadRawBlocks(path3) {
|
|
33271
33843
|
let raw;
|
|
33272
33844
|
try {
|
|
33273
|
-
raw = await
|
|
33845
|
+
raw = await readFile13(path3, "utf8");
|
|
33274
33846
|
} catch (err2) {
|
|
33275
33847
|
const code3 = err2.code;
|
|
33276
33848
|
if (code3 === "ENOENT")
|
|
@@ -33350,7 +33922,7 @@ function normalizeHeadingTitle(value) {
|
|
|
33350
33922
|
return normalizeMarkdown(value).trim().replace(/\s+/gu, " ");
|
|
33351
33923
|
}
|
|
33352
33924
|
async function anchorForBlock(ctxDir, snapshotFile, block) {
|
|
33353
|
-
const raw = await
|
|
33925
|
+
const raw = await readFile13(join13(ctxDir, snapshotFile), "utf8");
|
|
33354
33926
|
const anchors = extractAnchors(stripFrontmatter(raw));
|
|
33355
33927
|
if (anchors.length === 0)
|
|
33356
33928
|
return "document";
|
|
@@ -33449,7 +34021,7 @@ function fingerprintEntry(input) {
|
|
|
33449
34021
|
async function loadSectionFingerprints(path3) {
|
|
33450
34022
|
let raw;
|
|
33451
34023
|
try {
|
|
33452
|
-
raw = await
|
|
34024
|
+
raw = await readFile13(path3, "utf8");
|
|
33453
34025
|
} catch (err2) {
|
|
33454
34026
|
const code3 = err2.code;
|
|
33455
34027
|
if (code3 === "ENOENT")
|
|
@@ -33691,9 +34263,9 @@ var init_sectionFingerprints = __esm(() => {
|
|
|
33691
34263
|
});
|
|
33692
34264
|
|
|
33693
34265
|
// src/incremental/sourceDigests.ts
|
|
33694
|
-
import { existsSync as
|
|
33695
|
-
import { readFile as
|
|
33696
|
-
import { join as
|
|
34266
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
34267
|
+
import { readFile as readFile14 } from "node:fs/promises";
|
|
34268
|
+
import { join as join14 } from "node:path";
|
|
33697
34269
|
function sortJson4(value) {
|
|
33698
34270
|
if (Array.isArray(value))
|
|
33699
34271
|
return value.map(sortJson4);
|
|
@@ -33767,8 +34339,8 @@ async function buildSourceDigests(input) {
|
|
|
33767
34339
|
rawBlocks.unknown_inputs.push(unknown2);
|
|
33768
34340
|
continue;
|
|
33769
34341
|
}
|
|
33770
|
-
const rawPath =
|
|
33771
|
-
if (!
|
|
34342
|
+
const rawPath = join14(input.ctxDir, snapshot.file);
|
|
34343
|
+
if (!existsSync12(rawPath)) {
|
|
33772
34344
|
const unknown2 = unknownInput(source2.id, "snapshot-file-not-found", snapshot.file);
|
|
33773
34345
|
sourceDigests.unknown_inputs.push(unknown2);
|
|
33774
34346
|
rawBlocks.unknown_inputs.push(unknown2);
|
|
@@ -33776,7 +34348,7 @@ async function buildSourceDigests(input) {
|
|
|
33776
34348
|
}
|
|
33777
34349
|
let raw;
|
|
33778
34350
|
try {
|
|
33779
|
-
raw = await
|
|
34351
|
+
raw = await readFile14(rawPath, "utf8");
|
|
33780
34352
|
} catch {
|
|
33781
34353
|
const unknown2 = unknownInput(source2.id, "snapshot-file-read-failed", snapshot.file);
|
|
33782
34354
|
sourceDigests.unknown_inputs.push(unknown2);
|
|
@@ -34007,257 +34579,6 @@ var init_nodeClassification = __esm(() => {
|
|
|
34007
34579
|
]);
|
|
34008
34580
|
});
|
|
34009
34581
|
|
|
34010
|
-
// src/mdrive/externalDeps.ts
|
|
34011
|
-
import { existsSync as existsSync12 } from "node:fs";
|
|
34012
|
-
import { readFile as readFile14, readdir as readdir4, rm as rm4 } from "node:fs/promises";
|
|
34013
|
-
import { join as join14, relative as relative5, resolve as resolve4 } from "node:path";
|
|
34014
|
-
function knowledgeRoot3(ctxDir) {
|
|
34015
|
-
return join14(ctxDir, "knowledge");
|
|
34016
|
-
}
|
|
34017
|
-
function externalDepsPath(ctxDir) {
|
|
34018
|
-
return join14(knowledgeRoot3(ctxDir), "_external.yaml");
|
|
34019
|
-
}
|
|
34020
|
-
function toPosixPath3(value) {
|
|
34021
|
-
return value.replace(/\\/g, "/");
|
|
34022
|
-
}
|
|
34023
|
-
function relativeToKnowledge2(ctxDir, path3) {
|
|
34024
|
-
return toPosixPath3(relative5(knowledgeRoot3(ctxDir), path3));
|
|
34025
|
-
}
|
|
34026
|
-
function isTemporalValue2(value) {
|
|
34027
|
-
return typeof value === "string" || typeof value === "number";
|
|
34028
|
-
}
|
|
34029
|
-
function isExternalDep(value) {
|
|
34030
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
34031
|
-
return false;
|
|
34032
|
-
const dep = value;
|
|
34033
|
-
return typeof dep.from === "string" && typeof dep.package === "string" && (dep.version_constraint === undefined || typeof dep.version_constraint === "string") && (dep.valid_from === undefined || isTemporalValue2(dep.valid_from)) && (dep.valid_until === undefined || isTemporalValue2(dep.valid_until));
|
|
34034
|
-
}
|
|
34035
|
-
function cleanExternalDep(dep, sourcePath) {
|
|
34036
|
-
return {
|
|
34037
|
-
from: dep.from,
|
|
34038
|
-
package: dep.package,
|
|
34039
|
-
...dep.version_constraint !== undefined ? { version_constraint: dep.version_constraint } : {},
|
|
34040
|
-
...dep.valid_from !== undefined ? { valid_from: dep.valid_from } : {},
|
|
34041
|
-
...dep.valid_until !== undefined ? { valid_until: dep.valid_until } : {},
|
|
34042
|
-
...sourcePath !== undefined ? { source_path: sourcePath } : {}
|
|
34043
|
-
};
|
|
34044
|
-
}
|
|
34045
|
-
function externalSortKey(dep) {
|
|
34046
|
-
return [
|
|
34047
|
-
dep.from,
|
|
34048
|
-
dep.package,
|
|
34049
|
-
dep.version_constraint ?? "",
|
|
34050
|
-
String(dep.valid_from ?? ""),
|
|
34051
|
-
String(dep.valid_until ?? "")
|
|
34052
|
-
].join(":");
|
|
34053
|
-
}
|
|
34054
|
-
async function atomicWriteYaml2(path3, value) {
|
|
34055
|
-
await atomicWriteFile(path3, import_yaml13.default.stringify(value));
|
|
34056
|
-
}
|
|
34057
|
-
function includeTarget2(ctxDir, includePath) {
|
|
34058
|
-
if (includePath.startsWith("/") || includePath.length === 0) {
|
|
34059
|
-
return { filePath: includePath, error: "include path must be relative to knowledge/" };
|
|
34060
|
-
}
|
|
34061
|
-
const root2 = resolve4(knowledgeRoot3(ctxDir));
|
|
34062
|
-
const target = resolve4(root2, includePath);
|
|
34063
|
-
if (target !== root2 && !target.startsWith(`${root2}/`)) {
|
|
34064
|
-
return { filePath: target, error: "include path must stay under knowledge/" };
|
|
34065
|
-
}
|
|
34066
|
-
return { filePath: target };
|
|
34067
|
-
}
|
|
34068
|
-
async function readExternalFile(ctxDir, filePath) {
|
|
34069
|
-
const parsed = import_yaml13.default.parse(await readFile14(filePath, "utf8"));
|
|
34070
|
-
const relativePath = relativeToKnowledge2(ctxDir, filePath);
|
|
34071
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
34072
|
-
return { filePath, relativePath, includes: [], externals: [], rawExternals: [] };
|
|
34073
|
-
}
|
|
34074
|
-
const file = parsed;
|
|
34075
|
-
if (file.schema_version !== 1) {
|
|
34076
|
-
return { filePath, relativePath, includes: [], externals: [], rawExternals: [] };
|
|
34077
|
-
}
|
|
34078
|
-
const includes = Array.isArray(file.includes) ? file.includes.filter((item) => typeof item === "string") : [];
|
|
34079
|
-
const rawExternals = Array.isArray(file.externals) ? file.externals : [];
|
|
34080
|
-
const externals = rawExternals.filter(isExternalDep).map((dep) => cleanExternalDep(dep, relativePath));
|
|
34081
|
-
return { filePath, relativePath, includes, externals, rawExternals };
|
|
34082
|
-
}
|
|
34083
|
-
async function inspectExternalDeps(ctxDir) {
|
|
34084
|
-
const rootPath = externalDepsPath(ctxDir);
|
|
34085
|
-
const issues = [];
|
|
34086
|
-
const files = [];
|
|
34087
|
-
const visited = new Set;
|
|
34088
|
-
const stack = new Set;
|
|
34089
|
-
const referencedIncludes = new Set;
|
|
34090
|
-
const visit2 = async (filePath, viaInclude) => {
|
|
34091
|
-
const relativePath = relativeToKnowledge2(ctxDir, filePath);
|
|
34092
|
-
if (stack.has(filePath)) {
|
|
34093
|
-
issues.push({
|
|
34094
|
-
code: "external-include-cycle",
|
|
34095
|
-
message: `external include cycle detected at "${relativePath}"`,
|
|
34096
|
-
path: viaInclude ?? relativePath
|
|
34097
|
-
});
|
|
34098
|
-
return;
|
|
34099
|
-
}
|
|
34100
|
-
if (visited.has(filePath))
|
|
34101
|
-
return;
|
|
34102
|
-
if (!existsSync12(filePath)) {
|
|
34103
|
-
issues.push({
|
|
34104
|
-
code: "external-include-missing",
|
|
34105
|
-
message: `external include "${viaInclude ?? relativePath}" does not exist`,
|
|
34106
|
-
path: viaInclude ?? relativePath
|
|
34107
|
-
});
|
|
34108
|
-
return;
|
|
34109
|
-
}
|
|
34110
|
-
visited.add(filePath);
|
|
34111
|
-
stack.add(filePath);
|
|
34112
|
-
const file = await readExternalFile(ctxDir, filePath);
|
|
34113
|
-
files.push(file);
|
|
34114
|
-
const includeSeenInFile = new Set;
|
|
34115
|
-
for (const includePath of file.includes) {
|
|
34116
|
-
if (includeSeenInFile.has(includePath)) {
|
|
34117
|
-
issues.push({
|
|
34118
|
-
code: "external-include-duplicate",
|
|
34119
|
-
message: `external include "${includePath}" is declared more than once`,
|
|
34120
|
-
path: file.relativePath
|
|
34121
|
-
});
|
|
34122
|
-
}
|
|
34123
|
-
includeSeenInFile.add(includePath);
|
|
34124
|
-
referencedIncludes.add(includePath);
|
|
34125
|
-
const target = includeTarget2(ctxDir, includePath);
|
|
34126
|
-
if (target.error) {
|
|
34127
|
-
issues.push({
|
|
34128
|
-
code: "external-include-outside-knowledge",
|
|
34129
|
-
message: target.error,
|
|
34130
|
-
path: file.relativePath
|
|
34131
|
-
});
|
|
34132
|
-
continue;
|
|
34133
|
-
}
|
|
34134
|
-
await visit2(target.filePath, includePath);
|
|
34135
|
-
}
|
|
34136
|
-
stack.delete(filePath);
|
|
34137
|
-
};
|
|
34138
|
-
if (existsSync12(rootPath)) {
|
|
34139
|
-
await visit2(rootPath);
|
|
34140
|
-
}
|
|
34141
|
-
const entityRoot = join14(knowledgeRoot3(ctxDir), "entity");
|
|
34142
|
-
if (existsSync12(entityRoot)) {
|
|
34143
|
-
const entries = await readdir4(entityRoot, { withFileTypes: true });
|
|
34144
|
-
for (const entry of entries) {
|
|
34145
|
-
if (!entry.isDirectory())
|
|
34146
|
-
continue;
|
|
34147
|
-
const packageExternalPath = join14(entityRoot, entry.name, "_external.yaml");
|
|
34148
|
-
const includePath = `entity/${entry.name}/_external.yaml`;
|
|
34149
|
-
if (existsSync12(packageExternalPath) && !referencedIncludes.has(includePath)) {
|
|
34150
|
-
issues.push({
|
|
34151
|
-
code: "external-include-unreachable",
|
|
34152
|
-
message: `external file "${includePath}" exists but is not included by knowledge/_external.yaml`,
|
|
34153
|
-
path: includePath
|
|
34154
|
-
});
|
|
34155
|
-
}
|
|
34156
|
-
}
|
|
34157
|
-
}
|
|
34158
|
-
return {
|
|
34159
|
-
files,
|
|
34160
|
-
externals: files.flatMap((file) => file.externals),
|
|
34161
|
-
issues
|
|
34162
|
-
};
|
|
34163
|
-
}
|
|
34164
|
-
async function loadExternalDeps(ctxDir) {
|
|
34165
|
-
return (await inspectExternalDeps(ctxDir)).externals;
|
|
34166
|
-
}
|
|
34167
|
-
async function readRootExternalFile(ctxDir) {
|
|
34168
|
-
const path3 = externalDepsPath(ctxDir);
|
|
34169
|
-
if (!existsSync12(path3))
|
|
34170
|
-
return { schema_version: 1, includes: [], externals: [] };
|
|
34171
|
-
const parsed = import_yaml13.default.parse(await readFile14(path3, "utf8"));
|
|
34172
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
34173
|
-
return { schema_version: 1, includes: [], externals: [] };
|
|
34174
|
-
const file = parsed;
|
|
34175
|
-
return {
|
|
34176
|
-
schema_version: 1,
|
|
34177
|
-
includes: Array.isArray(file.includes) ? file.includes.filter((item) => typeof item === "string") : [],
|
|
34178
|
-
externals: Array.isArray(file.externals) ? file.externals.filter(isExternalDep).map((dep) => cleanExternalDep(dep)) : []
|
|
34179
|
-
};
|
|
34180
|
-
}
|
|
34181
|
-
async function writeExternalFile(ctxDir, relativePath, deps, includes = []) {
|
|
34182
|
-
const path3 = join14(knowledgeRoot3(ctxDir), relativePath);
|
|
34183
|
-
const file = {
|
|
34184
|
-
schema_version: 1,
|
|
34185
|
-
...includes.length > 0 ? { includes: [...includes].sort() } : {},
|
|
34186
|
-
externals: [...deps].map((dep) => cleanExternalDep(dep)).sort((left, right) => externalSortKey(left).localeCompare(externalSortKey(right)))
|
|
34187
|
-
};
|
|
34188
|
-
await atomicWriteYaml2(path3, file);
|
|
34189
|
-
}
|
|
34190
|
-
async function syncRootIncludes2(ctxDir, packageIncludes) {
|
|
34191
|
-
const root2 = await readRootExternalFile(ctxDir);
|
|
34192
|
-
const rootIncludes = new Set((root2.includes ?? []).filter((include) => !/^entity\/[^/]+\/_external\.yaml$/u.test(include)));
|
|
34193
|
-
for (const include of packageIncludes)
|
|
34194
|
-
rootIncludes.add(include);
|
|
34195
|
-
await writeExternalFile(ctxDir, "_external.yaml", root2.externals, [...rootIncludes]);
|
|
34196
|
-
}
|
|
34197
|
-
function shouldKeepExistingDep(dep, options) {
|
|
34198
|
-
if (options.fromOwners !== undefined) {
|
|
34199
|
-
return !options.fromOwners.has(ownerSlugForPackageScopedPath(dep.from));
|
|
34200
|
-
}
|
|
34201
|
-
if (options.fromOwner !== undefined) {
|
|
34202
|
-
return dep.from !== options.fromOwner && !dep.from.startsWith(`${options.fromOwner}/`);
|
|
34203
|
-
}
|
|
34204
|
-
if (options.fromPrefix !== undefined)
|
|
34205
|
-
return !dep.from.startsWith(options.fromPrefix);
|
|
34206
|
-
return false;
|
|
34207
|
-
}
|
|
34208
|
-
async function replaceExternalDepsInternal(ctxDir, deps, options = {}) {
|
|
34209
|
-
const inspection = await inspectExternalDeps(ctxDir);
|
|
34210
|
-
const byPath = new Map;
|
|
34211
|
-
const includesByPath = new Map;
|
|
34212
|
-
for (const file of inspection.files) {
|
|
34213
|
-
const kept = file.externals.filter((dep) => shouldKeepExistingDep(dep, options));
|
|
34214
|
-
byPath.set(file.relativePath, kept);
|
|
34215
|
-
includesByPath.set(file.relativePath, file.includes);
|
|
34216
|
-
}
|
|
34217
|
-
for (const dep of deps) {
|
|
34218
|
-
const relativePath = externalDepRelativePath(dep);
|
|
34219
|
-
const bucket = byPath.get(relativePath) ?? [];
|
|
34220
|
-
byPath.set(relativePath, [...bucket, cleanExternalDep(dep)]);
|
|
34221
|
-
}
|
|
34222
|
-
const packageIncludes = new Set;
|
|
34223
|
-
for (const [relativePath, nextDeps] of byPath) {
|
|
34224
|
-
const includes = includesByPath.get(relativePath) ?? [];
|
|
34225
|
-
const isPackageExternalFile = /^entity\/[^/]+\/_external\.yaml$/u.test(relativePath);
|
|
34226
|
-
if (relativePath === "_external.yaml") {
|
|
34227
|
-
const root2 = await readRootExternalFile(ctxDir);
|
|
34228
|
-
await writeExternalFile(ctxDir, "_external.yaml", nextDeps, root2.includes ?? []);
|
|
34229
|
-
continue;
|
|
34230
|
-
}
|
|
34231
|
-
if (nextDeps.length === 0) {
|
|
34232
|
-
if (isPackageExternalFile && includes.length === 0) {
|
|
34233
|
-
await rm4(join14(knowledgeRoot3(ctxDir), relativePath), { force: true });
|
|
34234
|
-
} else {
|
|
34235
|
-
await writeExternalFile(ctxDir, relativePath, [], includes);
|
|
34236
|
-
}
|
|
34237
|
-
continue;
|
|
34238
|
-
}
|
|
34239
|
-
if (isPackageExternalFile)
|
|
34240
|
-
packageIncludes.add(relativePath);
|
|
34241
|
-
await writeExternalFile(ctxDir, relativePath, nextDeps, includes);
|
|
34242
|
-
}
|
|
34243
|
-
for (const [relativePath, nextDeps] of byPath) {
|
|
34244
|
-
const includes = includesByPath.get(relativePath) ?? [];
|
|
34245
|
-
if (/^entity\/[^/]+\/_external\.yaml$/u.test(relativePath) && (nextDeps.length > 0 || includes.length > 0)) {
|
|
34246
|
-
packageIncludes.add(relativePath);
|
|
34247
|
-
}
|
|
34248
|
-
}
|
|
34249
|
-
await syncRootIncludes2(ctxDir, packageIncludes);
|
|
34250
|
-
return deps.length;
|
|
34251
|
-
}
|
|
34252
|
-
async function replaceExternalDepsForOwners(ctxDir, deps, owners) {
|
|
34253
|
-
return replaceExternalDepsInternal(ctxDir, deps, { fromOwners: owners });
|
|
34254
|
-
}
|
|
34255
|
-
var import_yaml13;
|
|
34256
|
-
var init_externalDeps = __esm(() => {
|
|
34257
|
-
init_atomicWrite();
|
|
34258
|
-
import_yaml13 = __toESM(require_dist(), 1);
|
|
34259
|
-
});
|
|
34260
|
-
|
|
34261
34582
|
// src/code/codeProjectionHelpers.ts
|
|
34262
34583
|
function stringField2(row, fields) {
|
|
34263
34584
|
for (const field of fields) {
|
|
@@ -37746,7 +38067,7 @@ function safeTimestamp(value) {
|
|
|
37746
38067
|
return value.replace(/[:.]/g, "-");
|
|
37747
38068
|
}
|
|
37748
38069
|
function sourceArchiveRelPath(sourceId, droppedAt) {
|
|
37749
|
-
return
|
|
38070
|
+
return toPosixPath3(join23("archive", "sources", safePathSegment(sourceId), safeTimestamp(droppedAt)));
|
|
37750
38071
|
}
|
|
37751
38072
|
function archiveAbsPath(ctxDir, relPath) {
|
|
37752
38073
|
return join23(ctxDir, relPath);
|
|
@@ -37769,7 +38090,7 @@ async function addArchiveEntry(input) {
|
|
|
37769
38090
|
const kind = await pathKind(fromAbs);
|
|
37770
38091
|
if (!kind)
|
|
37771
38092
|
return;
|
|
37772
|
-
const toRel =
|
|
38093
|
+
const toRel = toPosixPath3(join23(input.archivePath, "raw", input.rel));
|
|
37773
38094
|
const toAbs = join23(input.ctxDir, toRel);
|
|
37774
38095
|
await mkdir12(dirname11(toAbs), { recursive: true });
|
|
37775
38096
|
await cp(fromAbs, toAbs, { recursive: kind === "dir" });
|
|
@@ -37792,8 +38113,8 @@ async function createDropArchive(input) {
|
|
|
37792
38113
|
}
|
|
37793
38114
|
const knowledgeBefore = [];
|
|
37794
38115
|
for (const filePath of input.touchedKnowledgeFiles) {
|
|
37795
|
-
const rel =
|
|
37796
|
-
const toRel =
|
|
38116
|
+
const rel = toPosixPath3(relative6(input.ctxDir, filePath));
|
|
38117
|
+
const toRel = toPosixPath3(join23(archivePath, "knowledge", "before", rel));
|
|
37797
38118
|
const toAbs = join23(input.ctxDir, toRel);
|
|
37798
38119
|
await mkdir12(dirname11(toAbs), { recursive: true });
|
|
37799
38120
|
await cp(filePath, toAbs);
|
|
@@ -37873,7 +38194,7 @@ async function walkArchive(absPath, relPath = "") {
|
|
|
37873
38194
|
return { files: 0, bytes: 0, rawFiles: 0, knowledgeFiles: 0 };
|
|
37874
38195
|
const s = await stat(absPath);
|
|
37875
38196
|
if (s.isFile()) {
|
|
37876
|
-
const normalized =
|
|
38197
|
+
const normalized = toPosixPath3(relPath);
|
|
37877
38198
|
return {
|
|
37878
38199
|
files: 1,
|
|
37879
38200
|
bytes: s.size,
|
|
@@ -37970,7 +38291,7 @@ async function summarizeRestoredSourceArchives(ctxDir) {
|
|
|
37970
38291
|
for (const archiveDir of await readdir10(sourceRoot, { withFileTypes: true })) {
|
|
37971
38292
|
if (!archiveDir.isDirectory())
|
|
37972
38293
|
continue;
|
|
37973
|
-
const archivePath =
|
|
38294
|
+
const archivePath = toPosixPath3(join23("archive", "sources", sourceDir.name, archiveDir.name));
|
|
37974
38295
|
const manifest = await readDropArchiveManifest(join23(sourceRoot, archiveDir.name, "manifest.yaml"));
|
|
37975
38296
|
if (!manifest || !restoredSourceIds.has(manifest.source_id))
|
|
37976
38297
|
continue;
|
|
@@ -41407,11 +41728,11 @@ async function hydrateSourceOwnershipPreviews(ctxDir, ownership) {
|
|
|
41407
41728
|
}));
|
|
41408
41729
|
return changed ? { ...ownership, sources } : ownership;
|
|
41409
41730
|
}
|
|
41410
|
-
async function
|
|
41731
|
+
async function latestSnapshotsBySourceId(ctxDir) {
|
|
41411
41732
|
const sources = await loadSources(ctxDir);
|
|
41412
41733
|
return new Map(sources.sources.flatMap((source2) => {
|
|
41413
41734
|
const latest = selectLatestSnapshot(source2.snapshots);
|
|
41414
|
-
return latest === null ? [] : [[source2.id, latest
|
|
41735
|
+
return latest === null ? [] : [[source2.id, latest]];
|
|
41415
41736
|
}));
|
|
41416
41737
|
}
|
|
41417
41738
|
function compactSourceOwnership(ownership) {
|
|
@@ -41525,8 +41846,8 @@ async function readFreshCurrentSourceOwnership(ctxDir, input = {}) {
|
|
|
41525
41846
|
const ownership = await readCurrentSourceOwnership(ctxDir, input);
|
|
41526
41847
|
if (ownership === null)
|
|
41527
41848
|
return null;
|
|
41528
|
-
const
|
|
41529
|
-
const stale = staleOwnershipSourceIds(ownership,
|
|
41849
|
+
const latestSnapshots = await latestSnapshotsBySourceId(ctxDir);
|
|
41850
|
+
const stale = staleOwnershipSourceIds(ctxDir, ownership, latestSnapshots);
|
|
41530
41851
|
if (stale.length === 0)
|
|
41531
41852
|
return ownership;
|
|
41532
41853
|
const refreshed = await refreshStaleSourceOwnership(ctxDir, ownership);
|
|
@@ -41550,11 +41871,19 @@ function publishedSourceOwnershipSummary(record) {
|
|
|
41550
41871
|
block_count: record.ownership.summary.blocks
|
|
41551
41872
|
};
|
|
41552
41873
|
}
|
|
41553
|
-
function staleOwnershipSourceIds(ownership,
|
|
41554
|
-
return ownership.sources.filter((source2) =>
|
|
41555
|
-
|
|
41556
|
-
|
|
41557
|
-
|
|
41874
|
+
function staleOwnershipSourceIds(ctxDir, ownership, latestSnapshots) {
|
|
41875
|
+
return ownership.sources.filter((source2) => sourceOwnershipNeedsRefresh(ctxDir, source2, latestSnapshots.get(source2.source_id))).map((source2) => source2.source_id);
|
|
41876
|
+
}
|
|
41877
|
+
function sourceOwnershipNeedsRefresh(ctxDir, source2, latest) {
|
|
41878
|
+
if (source2.snapshot_hash === undefined || latest === undefined)
|
|
41879
|
+
return true;
|
|
41880
|
+
if (source2.snapshot_hash !== latest.content_hash)
|
|
41881
|
+
return true;
|
|
41882
|
+
if (latest.file !== undefined && source2.file !== latest.file)
|
|
41883
|
+
return true;
|
|
41884
|
+
if (!existsSync28(join31(ctxDir, source2.file)))
|
|
41885
|
+
return true;
|
|
41886
|
+
return source2.blocks.some((block) => !existsSync28(join31(ctxDir, block.file)));
|
|
41558
41887
|
}
|
|
41559
41888
|
function summarizeOwnershipSources(sources) {
|
|
41560
41889
|
const blocks = sources.flatMap((source2) => source2.blocks);
|
|
@@ -41650,14 +41979,17 @@ function refreshedOwnershipBlock(input) {
|
|
|
41650
41979
|
async function refreshStaleSourceOwnership(ctxDir, ownership) {
|
|
41651
41980
|
const sourceFile = await loadSources(ctxDir);
|
|
41652
41981
|
const sourceById = new Map(sourceFile.sources.map((source2) => [source2.id, source2]));
|
|
41653
|
-
const
|
|
41982
|
+
const latestSnapshots = new Map(sourceFile.sources.flatMap((source2) => {
|
|
41983
|
+
const latest = selectLatestSnapshot(source2.snapshots);
|
|
41984
|
+
return latest === null ? [] : [[source2.id, latest]];
|
|
41985
|
+
}));
|
|
41654
41986
|
const refreshedSources = [];
|
|
41655
41987
|
let changed = false;
|
|
41656
41988
|
for (const source2 of ownership.sources) {
|
|
41657
|
-
const
|
|
41658
|
-
if (
|
|
41989
|
+
const latest = latestSnapshots.get(source2.source_id);
|
|
41990
|
+
if (latest === undefined || source2.snapshot_hash === undefined)
|
|
41659
41991
|
return null;
|
|
41660
|
-
if (source2
|
|
41992
|
+
if (!sourceOwnershipNeedsRefresh(ctxDir, source2, latest)) {
|
|
41661
41993
|
refreshedSources.push(source2);
|
|
41662
41994
|
continue;
|
|
41663
41995
|
}
|
|
@@ -41668,7 +42000,7 @@ async function refreshStaleSourceOwnership(ctxDir, ownership) {
|
|
|
41668
42000
|
const after = await readLatestEvidenceManifest(ctxDir, entry);
|
|
41669
42001
|
if (before === null || after === null)
|
|
41670
42002
|
return null;
|
|
41671
|
-
const file = after.snapshot_file ?? source2.file;
|
|
42003
|
+
const file = after.snapshot_file ?? latest.file ?? source2.file;
|
|
41672
42004
|
const body2 = await readEvidenceBody(ctxDir, file, entry);
|
|
41673
42005
|
const blocks = [];
|
|
41674
42006
|
for (const match of matchEvidenceBlocks(before, after)) {
|
|
@@ -41680,19 +42012,19 @@ async function refreshStaleSourceOwnership(ctxDir, ownership) {
|
|
|
41680
42012
|
previous: previous3,
|
|
41681
42013
|
after: match.after,
|
|
41682
42014
|
file,
|
|
41683
|
-
snapshotHash:
|
|
42015
|
+
snapshotHash: latest.content_hash,
|
|
41684
42016
|
...textPreview !== undefined ? { textPreview } : {}
|
|
41685
42017
|
}) : ownershipFromHeadingPeer({
|
|
41686
42018
|
source: source2,
|
|
41687
42019
|
block: match.after,
|
|
41688
42020
|
file,
|
|
41689
|
-
snapshotHash:
|
|
42021
|
+
snapshotHash: latest.content_hash,
|
|
41690
42022
|
...textPreview !== undefined ? { textPreview } : {}
|
|
41691
42023
|
}));
|
|
41692
42024
|
}
|
|
41693
42025
|
refreshedSources.push({
|
|
41694
42026
|
source_id: source2.source_id,
|
|
41695
|
-
snapshot_hash:
|
|
42027
|
+
snapshot_hash: latest.content_hash,
|
|
41696
42028
|
file,
|
|
41697
42029
|
blocks
|
|
41698
42030
|
});
|
|
@@ -42192,6 +42524,363 @@ var init_verifyPromotionCleanup = __esm(() => {
|
|
|
42192
42524
|
NAVIGATION_LINK_LABEL_RE = /(?:related|references?|links?|docs?|documents?|navigation|相关|关联|参考|文档|链接|导航|入口|资料)/iu;
|
|
42193
42525
|
});
|
|
42194
42526
|
|
|
42527
|
+
// src/mdrive/verifyWorkspaceReader.ts
|
|
42528
|
+
import { existsSync as existsSync29 } from "node:fs";
|
|
42529
|
+
import { readdir as readdir14, readFile as readFile36 } from "node:fs/promises";
|
|
42530
|
+
import { join as join33, relative as relative9 } from "node:path";
|
|
42531
|
+
function isIgnoredKnowledgeMarkdown(name) {
|
|
42532
|
+
return name === "_index.md" || name === "changelog.md";
|
|
42533
|
+
}
|
|
42534
|
+
async function pushUnsupportedNestedMarkdownIssues(root2, dir, issues, depth = 0) {
|
|
42535
|
+
if (depth > MAX_UNSUPPORTED_NESTED_SCAN_DEPTH) {
|
|
42536
|
+
issues.push({
|
|
42537
|
+
severity: "error",
|
|
42538
|
+
code: "file-layout-unsupported",
|
|
42539
|
+
message: "knowledge node files nested under this directory are too deep to scan safely",
|
|
42540
|
+
path: relative9(root2, dir).replace(/\\/g, "/")
|
|
42541
|
+
});
|
|
42542
|
+
return;
|
|
42543
|
+
}
|
|
42544
|
+
const entries = await readdir14(dir, { withFileTypes: true });
|
|
42545
|
+
for (const entry of entries) {
|
|
42546
|
+
const filePath = join33(dir, entry.name);
|
|
42547
|
+
if (entry.isSymbolicLink())
|
|
42548
|
+
continue;
|
|
42549
|
+
if (entry.isDirectory()) {
|
|
42550
|
+
await pushUnsupportedNestedMarkdownIssues(root2, filePath, issues, depth + 1);
|
|
42551
|
+
continue;
|
|
42552
|
+
}
|
|
42553
|
+
if (!entry.isFile() || !entry.name.endsWith(".md") || isIgnoredKnowledgeMarkdown(entry.name))
|
|
42554
|
+
continue;
|
|
42555
|
+
const relativePath = relative9(root2, filePath).replace(/\\/g, "/");
|
|
42556
|
+
issues.push({
|
|
42557
|
+
severity: "error",
|
|
42558
|
+
code: "file-layout-unsupported",
|
|
42559
|
+
message: "knowledge node files must live at knowledge/<type>/<slug>.md or knowledge/<type>/<package>/<slug>.md",
|
|
42560
|
+
path: relativePath
|
|
42561
|
+
});
|
|
42562
|
+
}
|
|
42563
|
+
}
|
|
42564
|
+
async function readParsedKnowledgeFile(root2, filePath) {
|
|
42565
|
+
const relativePath = relative9(root2, filePath).replace(/\\/g, "/");
|
|
42566
|
+
try {
|
|
42567
|
+
const rootNode = parseNodeMarkdown(await readFile36(filePath, "utf8"));
|
|
42568
|
+
const expectedSlug = slugFromKnowledgeRelativePath(relativePath);
|
|
42569
|
+
if (expectedSlug !== null && expectedSlug.includes("/") && rootNode.node.id === expectedSlug) {
|
|
42570
|
+
const parentSlug = expectedSlug.split("/")[0];
|
|
42571
|
+
if (parentSlug) {
|
|
42572
|
+
const edge2 = {
|
|
42573
|
+
type: "contains",
|
|
42574
|
+
from: parentSlug,
|
|
42575
|
+
to: expectedSlug,
|
|
42576
|
+
grounding: "directory",
|
|
42577
|
+
...rootNode.node.valid_from !== undefined ? { valid_from: rootNode.node.valid_from } : {},
|
|
42578
|
+
...rootNode.node.valid_until !== undefined ? { valid_until: rootNode.node.valid_until } : {}
|
|
42579
|
+
};
|
|
42580
|
+
rootNode.containsEdges = [edge2, ...rootNode.containsEdges];
|
|
42581
|
+
}
|
|
42582
|
+
}
|
|
42583
|
+
return { filePath, relativePath, root: rootNode };
|
|
42584
|
+
} catch (error) {
|
|
42585
|
+
return {
|
|
42586
|
+
severity: "error",
|
|
42587
|
+
code: "parse-error",
|
|
42588
|
+
message: error instanceof Error ? error.message : String(error),
|
|
42589
|
+
path: relativePath
|
|
42590
|
+
};
|
|
42591
|
+
}
|
|
42592
|
+
}
|
|
42593
|
+
function pushRenderAutoBlockIssues(node3, relativePath, issues) {
|
|
42594
|
+
for (const issue of node3.renderAutoBlockIssues ?? []) {
|
|
42595
|
+
issues.push({
|
|
42596
|
+
severity: "error",
|
|
42597
|
+
code: issue.code,
|
|
42598
|
+
message: `renderer auto-block "${issue.title}" is missing its closing sentinel`,
|
|
42599
|
+
path: relativePath,
|
|
42600
|
+
slug: node3.node.id,
|
|
42601
|
+
line: issue.line,
|
|
42602
|
+
next_action: "Run context compile --close after fixing the unclosed c4a:auto-block sentinel."
|
|
42603
|
+
});
|
|
42604
|
+
}
|
|
42605
|
+
for (const child of node3.children) {
|
|
42606
|
+
pushRenderAutoBlockIssues(child, relativePath, issues);
|
|
42607
|
+
}
|
|
42608
|
+
}
|
|
42609
|
+
async function collectParsedWorkspace(ctxDir) {
|
|
42610
|
+
const files = [];
|
|
42611
|
+
const issues = [];
|
|
42612
|
+
const root2 = knowledgeRoot3(ctxDir);
|
|
42613
|
+
if (existsSync29(root2)) {
|
|
42614
|
+
const entries = await readdir14(root2, { withFileTypes: true });
|
|
42615
|
+
for (const entry of entries) {
|
|
42616
|
+
if (entry.isDirectory() && entry.name === "concept") {
|
|
42617
|
+
issues.push({
|
|
42618
|
+
severity: "error",
|
|
42619
|
+
code: "concept-directory-not-allowed",
|
|
42620
|
+
message: "knowledge/concept is not supported; use knowledge/entity with the term tag for named concepts",
|
|
42621
|
+
path: "knowledge/concept"
|
|
42622
|
+
});
|
|
42623
|
+
}
|
|
42624
|
+
}
|
|
42625
|
+
}
|
|
42626
|
+
for (const type of NODE_TYPES) {
|
|
42627
|
+
const dir = join33(root2, type);
|
|
42628
|
+
if (!existsSync29(dir))
|
|
42629
|
+
continue;
|
|
42630
|
+
const entries = await readdir14(dir, { withFileTypes: true });
|
|
42631
|
+
for (const entry of entries) {
|
|
42632
|
+
if (entry.isFile()) {
|
|
42633
|
+
if (!entry.name.endsWith(".md") || isIgnoredKnowledgeMarkdown(entry.name))
|
|
42634
|
+
continue;
|
|
42635
|
+
const parsed = await readParsedKnowledgeFile(root2, join33(dir, entry.name));
|
|
42636
|
+
if ("root" in parsed) {
|
|
42637
|
+
files.push(parsed);
|
|
42638
|
+
pushRenderAutoBlockIssues(parsed.root, parsed.relativePath, issues);
|
|
42639
|
+
} else
|
|
42640
|
+
issues.push(parsed);
|
|
42641
|
+
continue;
|
|
42642
|
+
}
|
|
42643
|
+
if (!entry.isDirectory())
|
|
42644
|
+
continue;
|
|
42645
|
+
const nestedDir = join33(dir, entry.name);
|
|
42646
|
+
const nestedEntries = await readdir14(nestedDir, { withFileTypes: true });
|
|
42647
|
+
for (const nestedEntry of nestedEntries) {
|
|
42648
|
+
if (nestedEntry.isDirectory()) {
|
|
42649
|
+
await pushUnsupportedNestedMarkdownIssues(root2, join33(nestedDir, nestedEntry.name), issues);
|
|
42650
|
+
continue;
|
|
42651
|
+
}
|
|
42652
|
+
if (!nestedEntry.isFile() || !nestedEntry.name.endsWith(".md") || isIgnoredKnowledgeMarkdown(nestedEntry.name)) {
|
|
42653
|
+
continue;
|
|
42654
|
+
}
|
|
42655
|
+
const parsed = await readParsedKnowledgeFile(root2, join33(nestedDir, nestedEntry.name));
|
|
42656
|
+
if ("root" in parsed) {
|
|
42657
|
+
files.push(parsed);
|
|
42658
|
+
pushRenderAutoBlockIssues(parsed.root, parsed.relativePath, issues);
|
|
42659
|
+
} else
|
|
42660
|
+
issues.push(parsed);
|
|
42661
|
+
}
|
|
42662
|
+
}
|
|
42663
|
+
}
|
|
42664
|
+
return { files, issues };
|
|
42665
|
+
}
|
|
42666
|
+
function collectAllNodes(files) {
|
|
42667
|
+
return flattenWorkspaceNodes(files.map((file) => ({
|
|
42668
|
+
filePath: file.filePath,
|
|
42669
|
+
relativePath: file.relativePath,
|
|
42670
|
+
root: file.root
|
|
42671
|
+
})));
|
|
42672
|
+
}
|
|
42673
|
+
var MAX_UNSUPPORTED_NESTED_SCAN_DEPTH = 8;
|
|
42674
|
+
var init_verifyWorkspaceReader = __esm(() => {
|
|
42675
|
+
init_nodeParser();
|
|
42676
|
+
init_knowledge();
|
|
42677
|
+
init_shared();
|
|
42678
|
+
});
|
|
42679
|
+
|
|
42680
|
+
// src/mdrive/verifyRenderBlocks.ts
|
|
42681
|
+
import { readFile as readFile37 } from "node:fs/promises";
|
|
42682
|
+
import { dirname as dirname13, join as join34, resolve as resolve9 } from "node:path";
|
|
42683
|
+
function headingKind(line) {
|
|
42684
|
+
const match = /^(#{2,6})\s+(.+?)\s*$/u.exec(line);
|
|
42685
|
+
if (!match)
|
|
42686
|
+
return null;
|
|
42687
|
+
return AUTO_BLOCK_TITLES2.get((match[2] ?? "").trim()) ?? null;
|
|
42688
|
+
}
|
|
42689
|
+
function findBlockHeadingStart(lines, openIndex, kind) {
|
|
42690
|
+
let cursor = openIndex - 1;
|
|
42691
|
+
while (cursor >= 0 && (lines[cursor]?.trim() ?? "") === "")
|
|
42692
|
+
cursor -= 1;
|
|
42693
|
+
return cursor >= 0 && headingKind(lines[cursor] ?? "") === kind ? cursor : openIndex;
|
|
42694
|
+
}
|
|
42695
|
+
function extractAutoBlockSlices(markdown) {
|
|
42696
|
+
const lines = markdown.replace(/\r\n?/g, `
|
|
42697
|
+
`).split(`
|
|
42698
|
+
`);
|
|
42699
|
+
const occurrences = new Map;
|
|
42700
|
+
const blocks = [];
|
|
42701
|
+
for (let index2 = 0;index2 < lines.length; index2 += 1) {
|
|
42702
|
+
const open2 = AUTO_BLOCK_OPEN.exec((lines[index2] ?? "").trim());
|
|
42703
|
+
if (!open2)
|
|
42704
|
+
continue;
|
|
42705
|
+
const kind = open2[1];
|
|
42706
|
+
let closeIndex = index2 + 1;
|
|
42707
|
+
while (closeIndex < lines.length && (lines[closeIndex]?.trim() ?? "") !== AUTO_BLOCK_CLOSE2) {
|
|
42708
|
+
closeIndex += 1;
|
|
42709
|
+
}
|
|
42710
|
+
if (closeIndex >= lines.length)
|
|
42711
|
+
continue;
|
|
42712
|
+
const start2 = findBlockHeadingStart(lines, index2, kind);
|
|
42713
|
+
const occurrence = (occurrences.get(kind) ?? 0) + 1;
|
|
42714
|
+
occurrences.set(kind, occurrence);
|
|
42715
|
+
blocks.push({
|
|
42716
|
+
key: `${kind}:${occurrence}`,
|
|
42717
|
+
kind,
|
|
42718
|
+
line: start2 + 1,
|
|
42719
|
+
text: lines.slice(start2, closeIndex + 1).join(`
|
|
42720
|
+
`)
|
|
42721
|
+
});
|
|
42722
|
+
index2 = closeIndex;
|
|
42723
|
+
}
|
|
42724
|
+
return blocks;
|
|
42725
|
+
}
|
|
42726
|
+
function blockMap(blocks) {
|
|
42727
|
+
return new Map(blocks.map((block) => [block.key, block]));
|
|
42728
|
+
}
|
|
42729
|
+
function issuePath(file) {
|
|
42730
|
+
return file.relativePath;
|
|
42731
|
+
}
|
|
42732
|
+
function slugForLine(root2, line) {
|
|
42733
|
+
let match = root2.node.id;
|
|
42734
|
+
const visit2 = (node3) => {
|
|
42735
|
+
if (node3.startLine !== undefined && line < node3.startLine)
|
|
42736
|
+
return;
|
|
42737
|
+
if (node3.endLine !== undefined && line > node3.endLine)
|
|
42738
|
+
return;
|
|
42739
|
+
match = node3.node.id;
|
|
42740
|
+
for (const child of node3.children) {
|
|
42741
|
+
visit2(child);
|
|
42742
|
+
}
|
|
42743
|
+
};
|
|
42744
|
+
visit2(root2);
|
|
42745
|
+
return match;
|
|
42746
|
+
}
|
|
42747
|
+
function pushStaleIssue(file, current, expected, issues) {
|
|
42748
|
+
const block = current ?? expected;
|
|
42749
|
+
if (block === undefined)
|
|
42750
|
+
return;
|
|
42751
|
+
issues.push({
|
|
42752
|
+
severity: "error",
|
|
42753
|
+
code: "render-block-stale",
|
|
42754
|
+
message: `renderer auto-block ${block.key} is stale; rerun context compile --close to regenerate it`,
|
|
42755
|
+
path: issuePath(file),
|
|
42756
|
+
slug: slugForLine(file.root, block.line),
|
|
42757
|
+
line: block.line,
|
|
42758
|
+
next_action: "Run context compile --close to regenerate renderer-owned relation blocks."
|
|
42759
|
+
});
|
|
42760
|
+
}
|
|
42761
|
+
function isExternalHref(href) {
|
|
42762
|
+
return /^[a-z][a-z0-9+.-]*:/iu.test(href) || href.startsWith("//");
|
|
42763
|
+
}
|
|
42764
|
+
function targetKey(filePath, anchor) {
|
|
42765
|
+
const resolved = resolve9(filePath);
|
|
42766
|
+
return anchor !== undefined && anchor.length > 0 ? `${resolved}#${anchor}` : resolved;
|
|
42767
|
+
}
|
|
42768
|
+
function markdownHrefTarget(filePath, href) {
|
|
42769
|
+
if (isExternalHref(href))
|
|
42770
|
+
return null;
|
|
42771
|
+
const beforeQuery = href.split("?")[0] ?? "";
|
|
42772
|
+
const hashIndex = beforeQuery.indexOf("#");
|
|
42773
|
+
const pathPart = hashIndex >= 0 ? beforeQuery.slice(0, hashIndex) : beforeQuery;
|
|
42774
|
+
const anchor = hashIndex >= 0 ? beforeQuery.slice(hashIndex + 1) : undefined;
|
|
42775
|
+
const targetPath = pathPart.length === 0 ? filePath : resolve9(dirname13(filePath), pathPart);
|
|
42776
|
+
return targetKey(targetPath, anchor);
|
|
42777
|
+
}
|
|
42778
|
+
function wikiHrefTarget(ctxDir, target) {
|
|
42779
|
+
const hashIndex = target.indexOf("#");
|
|
42780
|
+
const rawPathPart = hashIndex >= 0 ? target.slice(0, hashIndex) : target;
|
|
42781
|
+
const anchor = hashIndex >= 0 ? target.slice(hashIndex + 1) : undefined;
|
|
42782
|
+
const pathPart = rawPathPart.replace(/^\/+/u, "");
|
|
42783
|
+
const markdownPath = pathPart.endsWith(".md") ? pathPart : `${pathPart}.md`;
|
|
42784
|
+
return targetKey(join34(knowledgeRoot3(ctxDir), markdownPath), anchor);
|
|
42785
|
+
}
|
|
42786
|
+
function validRenderNodeTargets(files) {
|
|
42787
|
+
const targets = new Set;
|
|
42788
|
+
for (const file of files) {
|
|
42789
|
+
targets.add(targetKey(file.filePath));
|
|
42790
|
+
const anchors = computeNodeAnchorsForFile(file.root);
|
|
42791
|
+
for (const anchor of anchors.values()) {
|
|
42792
|
+
targets.add(targetKey(file.filePath, anchor));
|
|
42793
|
+
}
|
|
42794
|
+
}
|
|
42795
|
+
return targets;
|
|
42796
|
+
}
|
|
42797
|
+
function pushBrokenHrefIssues(ctxDir, file, block, validTargets, issues) {
|
|
42798
|
+
if (block.kind === "external_dependencies")
|
|
42799
|
+
return;
|
|
42800
|
+
const lines = block.text.split(`
|
|
42801
|
+
`);
|
|
42802
|
+
for (let offset = 0;offset < lines.length; offset += 1) {
|
|
42803
|
+
const line = lines[offset] ?? "";
|
|
42804
|
+
for (const match of line.matchAll(MARKDOWN_LINK)) {
|
|
42805
|
+
const href = match[1] ?? "";
|
|
42806
|
+
const target = markdownHrefTarget(file.filePath, href);
|
|
42807
|
+
if (target === null || validTargets.has(target))
|
|
42808
|
+
continue;
|
|
42809
|
+
issues.push({
|
|
42810
|
+
severity: "error",
|
|
42811
|
+
code: "render-block-href-broken",
|
|
42812
|
+
message: `renderer auto-block link target "${href}" does not exist`,
|
|
42813
|
+
path: issuePath(file),
|
|
42814
|
+
slug: slugForLine(file.root, block.line + offset),
|
|
42815
|
+
line: block.line + offset,
|
|
42816
|
+
next_action: "Run context compile --close to regenerate relation block links after fixing the target Node."
|
|
42817
|
+
});
|
|
42818
|
+
}
|
|
42819
|
+
for (const match of line.matchAll(WIKI_LINK)) {
|
|
42820
|
+
const target = match[1] ?? "";
|
|
42821
|
+
const fileTarget = wikiHrefTarget(ctxDir, target);
|
|
42822
|
+
if (validTargets.has(fileTarget))
|
|
42823
|
+
continue;
|
|
42824
|
+
issues.push({
|
|
42825
|
+
severity: "error",
|
|
42826
|
+
code: "render-block-href-broken",
|
|
42827
|
+
message: `renderer auto-block wiki target "${target}" does not exist`,
|
|
42828
|
+
path: issuePath(file),
|
|
42829
|
+
slug: slugForLine(file.root, block.line + offset),
|
|
42830
|
+
line: block.line + offset,
|
|
42831
|
+
next_action: "Run context compile --close to regenerate relation block links after fixing the target Node."
|
|
42832
|
+
});
|
|
42833
|
+
}
|
|
42834
|
+
}
|
|
42835
|
+
}
|
|
42836
|
+
async function detectRenderBlockIssues(ctxDir, files, issues) {
|
|
42837
|
+
const renderContext = await buildRenderWorkspaceContext(ctxDir, files);
|
|
42838
|
+
const validTargets = validRenderNodeTargets(files);
|
|
42839
|
+
for (const file of files) {
|
|
42840
|
+
const current = extractAutoBlockSlices(await readFile37(file.filePath, "utf8"));
|
|
42841
|
+
const expected = extractAutoBlockSlices(await renderRootForFile(file.filePath, file.root, renderContext));
|
|
42842
|
+
const currentByKey = blockMap(current);
|
|
42843
|
+
const expectedByKey = blockMap(expected);
|
|
42844
|
+
const keys = new Set([...currentByKey.keys(), ...expectedByKey.keys()]);
|
|
42845
|
+
for (const key of [...keys].sort()) {
|
|
42846
|
+
const currentBlock = currentByKey.get(key);
|
|
42847
|
+
const expectedBlock = expectedByKey.get(key);
|
|
42848
|
+
if (currentBlock?.text === expectedBlock?.text)
|
|
42849
|
+
continue;
|
|
42850
|
+
pushStaleIssue(file, currentBlock, expectedBlock, issues);
|
|
42851
|
+
}
|
|
42852
|
+
for (const block of current) {
|
|
42853
|
+
pushBrokenHrefIssues(ctxDir, file, block, validTargets, issues);
|
|
42854
|
+
}
|
|
42855
|
+
}
|
|
42856
|
+
}
|
|
42857
|
+
async function assertNoUnclosedRenderAutoBlocks(ctxDir) {
|
|
42858
|
+
const { issues } = await collectParsedWorkspace(ctxDir);
|
|
42859
|
+
const unclosed = issues.filter((issue) => issue.code === "render-auto-block-unclosed");
|
|
42860
|
+
if (unclosed.length === 0)
|
|
42861
|
+
return;
|
|
42862
|
+
throw new ContextError(ExitCode.WorkspaceStateError, "unclosed renderer auto-block sentinel", {
|
|
42863
|
+
category: "schema-invalid",
|
|
42864
|
+
issues: unclosed
|
|
42865
|
+
});
|
|
42866
|
+
}
|
|
42867
|
+
var AUTO_BLOCK_TITLES2, AUTO_BLOCK_CLOSE2 = "<!-- /c4a:auto-block -->", AUTO_BLOCK_OPEN, MARKDOWN_LINK, WIKI_LINK;
|
|
42868
|
+
var init_verifyRenderBlocks = __esm(() => {
|
|
42869
|
+
init_errors();
|
|
42870
|
+
init_exitCode();
|
|
42871
|
+
init_shared();
|
|
42872
|
+
init_verifyWorkspaceReader();
|
|
42873
|
+
AUTO_BLOCK_TITLES2 = new Map([
|
|
42874
|
+
["Depends On", "depends_on"],
|
|
42875
|
+
["External Dependencies", "external_dependencies"],
|
|
42876
|
+
["Used By", "used_by"],
|
|
42877
|
+
["Related", "related"]
|
|
42878
|
+
]);
|
|
42879
|
+
AUTO_BLOCK_OPEN = /^<!--\s+c4a:auto-block\s+(depends_on|external_dependencies|used_by|related)\s+-->$/u;
|
|
42880
|
+
MARKDOWN_LINK = /\[[^\]]+\]\(([^)]+)\)/gu;
|
|
42881
|
+
WIKI_LINK = /\[\[([^|\]]+)(?:\|[^\]]+)?\]\]/gu;
|
|
42882
|
+
});
|
|
42883
|
+
|
|
42195
42884
|
// src/mdrive/verifyGraphRules.ts
|
|
42196
42885
|
function edgeIssuePath(edge2) {
|
|
42197
42886
|
return edge2.source_path ? `knowledge/${edge2.source_path}` : "knowledge/_edges.yaml";
|
|
@@ -42859,8 +43548,8 @@ var init_alignPlan = __esm(() => {
|
|
|
42859
43548
|
});
|
|
42860
43549
|
|
|
42861
43550
|
// src/evidence/ref.ts
|
|
42862
|
-
import { readFile as
|
|
42863
|
-
import { join as
|
|
43551
|
+
import { readFile as readFile38 } from "node:fs/promises";
|
|
43552
|
+
import { join as join35 } from "node:path";
|
|
42864
43553
|
function createSourceRefResolutionCache() {
|
|
42865
43554
|
return {
|
|
42866
43555
|
manifests: new Map,
|
|
@@ -42952,7 +43641,7 @@ async function rawForManifestUncached(ctxDir, manifest) {
|
|
|
42952
43641
|
if (!manifest.snapshot_file)
|
|
42953
43642
|
return null;
|
|
42954
43643
|
try {
|
|
42955
|
-
const raw = await
|
|
43644
|
+
const raw = await readFile38(join35(ctxDir, manifest.snapshot_file), "utf8");
|
|
42956
43645
|
if (manifest.source_type === "note")
|
|
42957
43646
|
return readNoteMetadata(raw)?.body ?? stripCaptureFrontmatter(raw);
|
|
42958
43647
|
return stripCaptureFrontmatter(raw);
|
|
@@ -43401,9 +44090,9 @@ var init_ref = __esm(() => {
|
|
|
43401
44090
|
});
|
|
43402
44091
|
|
|
43403
44092
|
// src/mdrive/verifyCodeSourceRefs.ts
|
|
43404
|
-
import { existsSync as
|
|
43405
|
-
import { readFile as
|
|
43406
|
-
import { join as
|
|
44093
|
+
import { existsSync as existsSync30 } from "node:fs";
|
|
44094
|
+
import { readFile as readFile39 } from "node:fs/promises";
|
|
44095
|
+
import { join as join36 } from "node:path";
|
|
43407
44096
|
function codeSourceRefNextAction(code3) {
|
|
43408
44097
|
if (code3 === "code-source-ref-stale")
|
|
43409
44098
|
return "Rerun context compile --code <slug> so generated Sections match the current raw code snapshot.";
|
|
@@ -43435,17 +44124,17 @@ function sourceSlug2(source2, snapshot) {
|
|
|
43435
44124
|
}
|
|
43436
44125
|
function snapshotDir2(ctxDir, source2, snapshot) {
|
|
43437
44126
|
if (snapshot.dir)
|
|
43438
|
-
return
|
|
44127
|
+
return join36(ctxDir, snapshot.dir);
|
|
43439
44128
|
const slug = sourceSlug2(source2, snapshot);
|
|
43440
44129
|
const id2 = snapshot.snapshot_id;
|
|
43441
44130
|
if (!slug || !id2)
|
|
43442
44131
|
return null;
|
|
43443
|
-
return
|
|
44132
|
+
return join36(ctxDir, "raw", "aspect", "code", slug, id2);
|
|
43444
44133
|
}
|
|
43445
44134
|
async function readJsonl(path9) {
|
|
43446
|
-
if (!
|
|
44135
|
+
if (!existsSync30(path9))
|
|
43447
44136
|
return [];
|
|
43448
|
-
const text5 = await
|
|
44137
|
+
const text5 = await readFile39(path9, "utf8");
|
|
43449
44138
|
const rows = [];
|
|
43450
44139
|
for (const line of text5.split(/\r?\n/u)) {
|
|
43451
44140
|
if (line.trim().length === 0)
|
|
@@ -43478,11 +44167,11 @@ async function loadCodeSnapshotRecords(ctxDir, source2) {
|
|
|
43478
44167
|
const dir = snapshotDir2(ctxDir, source2, snapshot);
|
|
43479
44168
|
if (!dir)
|
|
43480
44169
|
continue;
|
|
43481
|
-
records.symbols.push(...annotateRows(await readJsonl(
|
|
43482
|
-
records.digests.push(...annotateRows(await readJsonl(
|
|
43483
|
-
records.packages.push(...annotateRows(await readJsonl(
|
|
43484
|
-
records.sourceFiles.push(...annotateRows(await readJsonl(
|
|
43485
|
-
records.edges.push(...annotateRows(await readJsonl(
|
|
44170
|
+
records.symbols.push(...annotateRows(await readJsonl(join36(dir, "symbols.jsonl")), snapshot));
|
|
44171
|
+
records.digests.push(...annotateRows(await readJsonl(join36(dir, "digests.jsonl")), snapshot));
|
|
44172
|
+
records.packages.push(...annotateRows(await readJsonl(join36(dir, "packages.jsonl")), snapshot));
|
|
44173
|
+
records.sourceFiles.push(...annotateRows(await readJsonl(join36(dir, "source-files.jsonl")), snapshot));
|
|
44174
|
+
records.edges.push(...annotateRows(await readJsonl(join36(dir, "edges.jsonl")), snapshot));
|
|
43486
44175
|
}
|
|
43487
44176
|
return {
|
|
43488
44177
|
symbols: records.symbols,
|
|
@@ -43930,141 +44619,6 @@ var init_verifySourceRules = __esm(() => {
|
|
|
43930
44619
|
init_verifySourceRefs();
|
|
43931
44620
|
});
|
|
43932
44621
|
|
|
43933
|
-
// src/mdrive/verifyWorkspaceReader.ts
|
|
43934
|
-
import { existsSync as existsSync30 } from "node:fs";
|
|
43935
|
-
import { readdir as readdir14, readFile as readFile38 } from "node:fs/promises";
|
|
43936
|
-
import { join as join35, relative as relative9 } from "node:path";
|
|
43937
|
-
function isIgnoredKnowledgeMarkdown(name) {
|
|
43938
|
-
return name === "_index.md" || name === "changelog.md";
|
|
43939
|
-
}
|
|
43940
|
-
async function pushUnsupportedNestedMarkdownIssues(root2, dir, issues, depth = 0) {
|
|
43941
|
-
if (depth > MAX_UNSUPPORTED_NESTED_SCAN_DEPTH) {
|
|
43942
|
-
issues.push({
|
|
43943
|
-
severity: "error",
|
|
43944
|
-
code: "file-layout-unsupported",
|
|
43945
|
-
message: "knowledge node files nested under this directory are too deep to scan safely",
|
|
43946
|
-
path: relative9(root2, dir).replace(/\\/g, "/")
|
|
43947
|
-
});
|
|
43948
|
-
return;
|
|
43949
|
-
}
|
|
43950
|
-
const entries = await readdir14(dir, { withFileTypes: true });
|
|
43951
|
-
for (const entry of entries) {
|
|
43952
|
-
const filePath = join35(dir, entry.name);
|
|
43953
|
-
if (entry.isSymbolicLink())
|
|
43954
|
-
continue;
|
|
43955
|
-
if (entry.isDirectory()) {
|
|
43956
|
-
await pushUnsupportedNestedMarkdownIssues(root2, filePath, issues, depth + 1);
|
|
43957
|
-
continue;
|
|
43958
|
-
}
|
|
43959
|
-
if (!entry.isFile() || !entry.name.endsWith(".md") || isIgnoredKnowledgeMarkdown(entry.name))
|
|
43960
|
-
continue;
|
|
43961
|
-
const relativePath = relative9(root2, filePath).replace(/\\/g, "/");
|
|
43962
|
-
issues.push({
|
|
43963
|
-
severity: "error",
|
|
43964
|
-
code: "file-layout-unsupported",
|
|
43965
|
-
message: "knowledge node files must live at knowledge/<type>/<slug>.md or knowledge/<type>/<package>/<slug>.md",
|
|
43966
|
-
path: relativePath
|
|
43967
|
-
});
|
|
43968
|
-
}
|
|
43969
|
-
}
|
|
43970
|
-
async function readParsedKnowledgeFile(root2, filePath) {
|
|
43971
|
-
const relativePath = relative9(root2, filePath).replace(/\\/g, "/");
|
|
43972
|
-
try {
|
|
43973
|
-
const rootNode = parseNodeMarkdown(await readFile38(filePath, "utf8"));
|
|
43974
|
-
const expectedSlug = slugFromKnowledgeRelativePath(relativePath);
|
|
43975
|
-
if (expectedSlug !== null && expectedSlug.includes("/") && rootNode.node.id === expectedSlug) {
|
|
43976
|
-
const parentSlug = expectedSlug.split("/")[0];
|
|
43977
|
-
if (parentSlug) {
|
|
43978
|
-
const edge2 = {
|
|
43979
|
-
type: "contains",
|
|
43980
|
-
from: parentSlug,
|
|
43981
|
-
to: expectedSlug,
|
|
43982
|
-
grounding: "directory",
|
|
43983
|
-
...rootNode.node.valid_from !== undefined ? { valid_from: rootNode.node.valid_from } : {},
|
|
43984
|
-
...rootNode.node.valid_until !== undefined ? { valid_until: rootNode.node.valid_until } : {}
|
|
43985
|
-
};
|
|
43986
|
-
rootNode.containsEdges = [edge2, ...rootNode.containsEdges];
|
|
43987
|
-
}
|
|
43988
|
-
}
|
|
43989
|
-
return { filePath, relativePath, root: rootNode };
|
|
43990
|
-
} catch (error) {
|
|
43991
|
-
return {
|
|
43992
|
-
severity: "error",
|
|
43993
|
-
code: "parse-error",
|
|
43994
|
-
message: error instanceof Error ? error.message : String(error),
|
|
43995
|
-
path: relativePath
|
|
43996
|
-
};
|
|
43997
|
-
}
|
|
43998
|
-
}
|
|
43999
|
-
async function collectParsedWorkspace(ctxDir) {
|
|
44000
|
-
const files = [];
|
|
44001
|
-
const issues = [];
|
|
44002
|
-
const root2 = knowledgeRoot2(ctxDir);
|
|
44003
|
-
if (existsSync30(root2)) {
|
|
44004
|
-
const entries = await readdir14(root2, { withFileTypes: true });
|
|
44005
|
-
for (const entry of entries) {
|
|
44006
|
-
if (entry.isDirectory() && entry.name === "concept") {
|
|
44007
|
-
issues.push({
|
|
44008
|
-
severity: "error",
|
|
44009
|
-
code: "concept-directory-not-allowed",
|
|
44010
|
-
message: "knowledge/concept is not supported; use knowledge/entity with the term tag for named concepts",
|
|
44011
|
-
path: "knowledge/concept"
|
|
44012
|
-
});
|
|
44013
|
-
}
|
|
44014
|
-
}
|
|
44015
|
-
}
|
|
44016
|
-
for (const type of NODE_TYPES) {
|
|
44017
|
-
const dir = join35(root2, type);
|
|
44018
|
-
if (!existsSync30(dir))
|
|
44019
|
-
continue;
|
|
44020
|
-
const entries = await readdir14(dir, { withFileTypes: true });
|
|
44021
|
-
for (const entry of entries) {
|
|
44022
|
-
if (entry.isFile()) {
|
|
44023
|
-
if (!entry.name.endsWith(".md") || isIgnoredKnowledgeMarkdown(entry.name))
|
|
44024
|
-
continue;
|
|
44025
|
-
const parsed = await readParsedKnowledgeFile(root2, join35(dir, entry.name));
|
|
44026
|
-
if ("root" in parsed)
|
|
44027
|
-
files.push(parsed);
|
|
44028
|
-
else
|
|
44029
|
-
issues.push(parsed);
|
|
44030
|
-
continue;
|
|
44031
|
-
}
|
|
44032
|
-
if (!entry.isDirectory())
|
|
44033
|
-
continue;
|
|
44034
|
-
const nestedDir = join35(dir, entry.name);
|
|
44035
|
-
const nestedEntries = await readdir14(nestedDir, { withFileTypes: true });
|
|
44036
|
-
for (const nestedEntry of nestedEntries) {
|
|
44037
|
-
if (nestedEntry.isDirectory()) {
|
|
44038
|
-
await pushUnsupportedNestedMarkdownIssues(root2, join35(nestedDir, nestedEntry.name), issues);
|
|
44039
|
-
continue;
|
|
44040
|
-
}
|
|
44041
|
-
if (!nestedEntry.isFile() || !nestedEntry.name.endsWith(".md") || isIgnoredKnowledgeMarkdown(nestedEntry.name)) {
|
|
44042
|
-
continue;
|
|
44043
|
-
}
|
|
44044
|
-
const parsed = await readParsedKnowledgeFile(root2, join35(nestedDir, nestedEntry.name));
|
|
44045
|
-
if ("root" in parsed)
|
|
44046
|
-
files.push(parsed);
|
|
44047
|
-
else
|
|
44048
|
-
issues.push(parsed);
|
|
44049
|
-
}
|
|
44050
|
-
}
|
|
44051
|
-
}
|
|
44052
|
-
return { files, issues };
|
|
44053
|
-
}
|
|
44054
|
-
function collectAllNodes(files) {
|
|
44055
|
-
return flattenWorkspaceNodes(files.map((file) => ({
|
|
44056
|
-
filePath: file.filePath,
|
|
44057
|
-
relativePath: file.relativePath,
|
|
44058
|
-
root: file.root
|
|
44059
|
-
})));
|
|
44060
|
-
}
|
|
44061
|
-
var MAX_UNSUPPORTED_NESTED_SCAN_DEPTH = 8;
|
|
44062
|
-
var init_verifyWorkspaceReader = __esm(() => {
|
|
44063
|
-
init_nodeParser();
|
|
44064
|
-
init_knowledge();
|
|
44065
|
-
init_shared();
|
|
44066
|
-
});
|
|
44067
|
-
|
|
44068
44622
|
// src/mdrive/verify.ts
|
|
44069
44623
|
function okFromIssues(issues) {
|
|
44070
44624
|
return issues.every((issue) => issue.severity !== "error");
|
|
@@ -44137,6 +44691,7 @@ async function mdriveVerifyWorkspace(input) {
|
|
|
44137
44691
|
}
|
|
44138
44692
|
await detectDanglingGraphEdges(input.ctxDir, new Set(slugMap.keys()), issues);
|
|
44139
44693
|
await detectExternalDepIssues(input.ctxDir, new Set(slugMap.keys()), issues);
|
|
44694
|
+
await detectRenderBlockIssues(input.ctxDir, files, issues);
|
|
44140
44695
|
const currentOwnership = await readCurrentSourceOwnership(input.ctxDir);
|
|
44141
44696
|
const allowedSourcelessSlugs = alignedNoWritePlaceholderSlugs(currentOwnership);
|
|
44142
44697
|
for (const file of files) {
|
|
@@ -44225,6 +44780,7 @@ var init_verify = __esm(() => {
|
|
|
44225
44780
|
init_verifyCoverage();
|
|
44226
44781
|
init_verifyExternalRules();
|
|
44227
44782
|
init_verifyPromotionCleanup();
|
|
44783
|
+
init_verifyRenderBlocks();
|
|
44228
44784
|
init_verifyGraphRules();
|
|
44229
44785
|
init_verifyNodeRules();
|
|
44230
44786
|
init_verifySchemaRules();
|
|
@@ -44254,8 +44810,15 @@ var init_sectionDetail = __esm(() => {
|
|
|
44254
44810
|
});
|
|
44255
44811
|
|
|
44256
44812
|
// src/reconcile/sourceSupport.ts
|
|
44813
|
+
function orderedListMarkerSpans(text5) {
|
|
44814
|
+
return [...text5.matchAll(ORDERED_LIST_MARKER_RE)].map((match) => ({
|
|
44815
|
+
start: (match.index ?? 0) + match[0].indexOf(match[1]),
|
|
44816
|
+
end: (match.index ?? 0) + match[0].indexOf(match[1]) + match[1].length
|
|
44817
|
+
}));
|
|
44818
|
+
}
|
|
44257
44819
|
function numbersIn(text5) {
|
|
44258
|
-
|
|
44820
|
+
const markerSpans = orderedListMarkerSpans(text5);
|
|
44821
|
+
return [...text5.matchAll(NUMBER_RE)].filter((match) => !markerSpans.some((span) => (match.index ?? 0) >= span.start && (match.index ?? 0) + match[0].length <= span.end)).map((match) => match[0]);
|
|
44259
44822
|
}
|
|
44260
44823
|
function normalizedToken(value) {
|
|
44261
44824
|
return normalizeMarkdown(value).trim().toLowerCase();
|
|
@@ -44745,7 +45308,7 @@ function weakSourceSupportGuidance(action, verdict) {
|
|
|
44745
45308
|
}
|
|
44746
45309
|
return " Key facts match, but this action rewrites or reanchors existing knowledge and requires direct support; choose source_ref/source_refs from the prepared evidence, split the claim, or ask the user before choosing a different final action.";
|
|
44747
45310
|
}
|
|
44748
|
-
var DEFAULT_THRESHOLDS, CJK_ONLY_RE, CJK_CHAR_RE, URL_RE2, TRAILING_URL_PUNCTUATION_RE, TRAILING_HARD_TERM_PUNCTUATION_RE, TRACKING_QUERY_PARAM_RE, EN_URL_REFERENCE_LABEL_RE, CJK_URL_REFERENCE_LABEL_RE, CONSTRAINT_PATTERNS, PLACEHOLDER_ANCHOR_PARTS;
|
|
45311
|
+
var NUMBER_RE, ORDERED_LIST_MARKER_RE, DEFAULT_THRESHOLDS, CJK_ONLY_RE, CJK_CHAR_RE, URL_RE2, TRAILING_URL_PUNCTUATION_RE, TRAILING_HARD_TERM_PUNCTUATION_RE, TRACKING_QUERY_PARAM_RE, EN_URL_REFERENCE_LABEL_RE, CJK_URL_REFERENCE_LABEL_RE, CONSTRAINT_PATTERNS, PLACEHOLDER_ANCHOR_PARTS;
|
|
44749
45312
|
var init_sourceSupport = __esm(() => {
|
|
44750
45313
|
init_normalize();
|
|
44751
45314
|
init_sectionDetail();
|
|
@@ -44753,6 +45316,8 @@ var init_sourceSupport = __esm(() => {
|
|
|
44753
45316
|
init_ref();
|
|
44754
45317
|
init_rawBlocks();
|
|
44755
45318
|
init_terms();
|
|
45319
|
+
NUMBER_RE = /\b\d+(?:\.\d+)*\b/gu;
|
|
45320
|
+
ORDERED_LIST_MARKER_RE = /(?:^|\n)[ \t]{0,3}(\d{1,3})(?:[.)]|[、.。])(?=[ \t]+)/gu;
|
|
44756
45321
|
DEFAULT_THRESHOLDS = { supported: 0.75, weak: 0.5 };
|
|
44757
45322
|
CJK_ONLY_RE = /^[\u4e00-\u9fff]+$/u;
|
|
44758
45323
|
CJK_CHAR_RE = /[\u4e00-\u9fff]/gu;
|
|
@@ -45011,8 +45576,8 @@ var init_dropSemantic = __esm(() => {
|
|
|
45011
45576
|
});
|
|
45012
45577
|
|
|
45013
45578
|
// src/reconcile/evidence.ts
|
|
45014
|
-
import { readFile as
|
|
45015
|
-
import { join as
|
|
45579
|
+
import { readFile as readFile40 } from "node:fs/promises";
|
|
45580
|
+
import { join as join37 } from "node:path";
|
|
45016
45581
|
function sourceRefAliasIndex(sourceRef) {
|
|
45017
45582
|
const match = /^src-(\d+)#/u.exec(sourceRef.trim());
|
|
45018
45583
|
return match ? Number(match[1]) - 1 : null;
|
|
@@ -45112,7 +45677,7 @@ async function evidenceSpansForSnapshotSourceRef(input) {
|
|
|
45112
45677
|
if (combinedEvidenceBlockHash(manifestBlocks) !== sourceRefHash) {
|
|
45113
45678
|
throw new Error(`${input.action} source_ref "${input.sourceRef}" does not match the cited evidence block hash`);
|
|
45114
45679
|
}
|
|
45115
|
-
const raw = await
|
|
45680
|
+
const raw = await readFile40(join37(input.ctxDir, input.snapshot.file), "utf8");
|
|
45116
45681
|
const note = input.source.type === "note" ? readNoteMetadata(raw) : undefined;
|
|
45117
45682
|
const body2 = note !== undefined ? note.body : stripCaptureFrontmatter(raw);
|
|
45118
45683
|
const spans = extractRawBlocks(body2).flatMap((block) => {
|
|
@@ -45152,7 +45717,7 @@ async function evidenceSpansForSnapshotSourceRange(input) {
|
|
|
45152
45717
|
if (rangeHash === null) {
|
|
45153
45718
|
throw new Error(`${input.action} source_ref "${input.sourceRef}" does not overlap a reliable raw block`);
|
|
45154
45719
|
}
|
|
45155
|
-
const raw = await
|
|
45720
|
+
const raw = await readFile40(join37(input.ctxDir, input.snapshot.file), "utf8");
|
|
45156
45721
|
const note = input.source.type === "note" ? readNoteMetadata(raw) : undefined;
|
|
45157
45722
|
const body2 = note !== undefined ? note.body : stripCaptureFrontmatter(raw);
|
|
45158
45723
|
const minLine = Math.min(...manifestBlocks.map((block) => block.line_start));
|
|
@@ -45347,13 +45912,13 @@ var init_evidence = __esm(() => {
|
|
|
45347
45912
|
import { existsSync as existsSync31 } from "node:fs";
|
|
45348
45913
|
import { execFile as execFile2 } from "node:child_process";
|
|
45349
45914
|
import { promisify as promisify3 } from "node:util";
|
|
45350
|
-
import { readFile as
|
|
45915
|
+
import { readFile as readFile41 } from "node:fs/promises";
|
|
45351
45916
|
import { relative as relative10 } from "node:path";
|
|
45352
45917
|
function changelogPath(ctxDir) {
|
|
45353
|
-
return `${
|
|
45918
|
+
return `${knowledgeRoot3(ctxDir)}/changelog.md`;
|
|
45354
45919
|
}
|
|
45355
45920
|
function indexPath(ctxDir) {
|
|
45356
|
-
return `${
|
|
45921
|
+
return `${knowledgeRoot3(ctxDir)}/_index.md`;
|
|
45357
45922
|
}
|
|
45358
45923
|
async function mdriveWorkspaceStats(input) {
|
|
45359
45924
|
const nodes = flattenWorkspaceNodes(await readWorkspaceNodeFiles(input.ctxDir));
|
|
@@ -45422,7 +45987,7 @@ async function mdriveWorkspaceRebuildIndex(input) {
|
|
|
45422
45987
|
}
|
|
45423
45988
|
async function mdriveWorkspaceAppendChangelog(input) {
|
|
45424
45989
|
const path9 = changelogPath(input.ctxDir);
|
|
45425
|
-
const existing = existsSync31(path9) ? await
|
|
45990
|
+
const existing = existsSync31(path9) ? await readFile41(path9, "utf8") : `# Knowledge Changelog
|
|
45426
45991
|
|
|
45427
45992
|
`;
|
|
45428
45993
|
const trimmed = existing.endsWith(`
|
|
@@ -45433,7 +45998,7 @@ async function mdriveWorkspaceAppendChangelog(input) {
|
|
|
45433
45998
|
}
|
|
45434
45999
|
async function mdriveWorkspaceRebuildChangelog(input) {
|
|
45435
46000
|
const workspaceRoot = workspaceRootFromCtxDir(input.ctxDir);
|
|
45436
|
-
const relKnowledgePath = relative10(workspaceRoot,
|
|
46001
|
+
const relKnowledgePath = relative10(workspaceRoot, knowledgeRoot3(input.ctxDir));
|
|
45437
46002
|
try {
|
|
45438
46003
|
const { stdout } = await execFileAsync2("git", [
|
|
45439
46004
|
"-C",
|
|
@@ -45461,16 +46026,11 @@ ${entries.join(`
|
|
|
45461
46026
|
}
|
|
45462
46027
|
}
|
|
45463
46028
|
async function mdriveWorkspaceCompact(input) {
|
|
46029
|
+
await assertNoUnclosedRenderAutoBlocks(input.ctxDir);
|
|
45464
46030
|
const files = await readWorkspaceNodeFiles(input.ctxDir);
|
|
45465
|
-
const graphEdges = await loadKnowledgeGraphEdges(input.ctxDir);
|
|
45466
46031
|
const renderContext = await buildRenderWorkspaceContext(input.ctxDir, files);
|
|
45467
46032
|
for (const file of files) {
|
|
45468
|
-
|
|
45469
|
-
await atomicWriteText(file.filePath, renderNodeMarkdown({
|
|
45470
|
-
...file.root,
|
|
45471
|
-
graphEdges,
|
|
45472
|
-
...relatedLinks !== undefined ? { relatedLinks } : {}
|
|
45473
|
-
}));
|
|
46033
|
+
await atomicRewriteRootFile(file.filePath, file.root, undefined, renderContext);
|
|
45474
46034
|
}
|
|
45475
46035
|
}
|
|
45476
46036
|
async function canonicalizeSourceRefsInNode(ctxDir, node3, cache) {
|
|
@@ -45508,38 +46068,31 @@ async function mdriveWorkspaceCanonicalizeSourceRefs(input) {
|
|
|
45508
46068
|
}
|
|
45509
46069
|
if (updates === 0)
|
|
45510
46070
|
return 0;
|
|
45511
|
-
const graphEdges = await loadKnowledgeGraphEdges(input.ctxDir);
|
|
45512
46071
|
const renderContext = await buildRenderWorkspaceContext(input.ctxDir, files);
|
|
45513
46072
|
for (const file of files) {
|
|
45514
46073
|
if (!changed.has(file.filePath))
|
|
45515
46074
|
continue;
|
|
45516
|
-
|
|
45517
|
-
await atomicWriteText(file.filePath, renderNodeMarkdown({
|
|
45518
|
-
...file.root,
|
|
45519
|
-
graphEdges,
|
|
45520
|
-
...relatedLinks !== undefined ? { relatedLinks } : {}
|
|
45521
|
-
}));
|
|
46075
|
+
await atomicRewriteRootFile(file.filePath, file.root, undefined, renderContext);
|
|
45522
46076
|
}
|
|
45523
46077
|
return updates;
|
|
45524
46078
|
}
|
|
45525
46079
|
var execFileAsync2;
|
|
45526
46080
|
var init_workspace = __esm(() => {
|
|
45527
46081
|
init_normalize();
|
|
45528
|
-
init_nodeRenderer();
|
|
45529
46082
|
init_workspaceLayout();
|
|
45530
46083
|
init_ref();
|
|
45531
46084
|
init_shared();
|
|
45532
|
-
|
|
46085
|
+
init_verifyRenderBlocks();
|
|
45533
46086
|
execFileAsync2 = promisify3(execFile2);
|
|
45534
46087
|
});
|
|
45535
46088
|
|
|
45536
46089
|
// src/workflow/workflowOutputPaths.ts
|
|
45537
|
-
import { join as
|
|
46090
|
+
import { join as join43 } from "node:path";
|
|
45538
46091
|
function workflowOutputDir(ctxDir, kind) {
|
|
45539
|
-
return
|
|
46092
|
+
return join43(ctxDir, "output", kind);
|
|
45540
46093
|
}
|
|
45541
46094
|
function workflowOutputPath(ctxDir, kind, fileName) {
|
|
45542
|
-
return
|
|
46095
|
+
return join43(workflowOutputDir(ctxDir, kind), fileName);
|
|
45543
46096
|
}
|
|
45544
46097
|
function workflowOutputPathForFile(ctxDir, fileName) {
|
|
45545
46098
|
return workflowOutputPath(ctxDir, workflowOutputKindForFile(fileName), fileName);
|
|
@@ -45586,13 +46139,13 @@ var init_dropPlanPayload = __esm(() => {
|
|
|
45586
46139
|
|
|
45587
46140
|
// src/workflow/compileKnowledgeState.ts
|
|
45588
46141
|
import { existsSync as existsSync36 } from "node:fs";
|
|
45589
|
-
import { readFile as
|
|
45590
|
-
import { join as
|
|
46142
|
+
import { readFile as readFile49 } from "node:fs/promises";
|
|
46143
|
+
import { join as join46 } from "node:path";
|
|
45591
46144
|
async function readLastCompileAt(ctxDir) {
|
|
45592
|
-
const path9 =
|
|
46145
|
+
const path9 = join46(ctxDir, "knowledge", "changelog.md");
|
|
45593
46146
|
if (!existsSync36(path9))
|
|
45594
46147
|
return null;
|
|
45595
|
-
const lines = (await
|
|
46148
|
+
const lines = (await readFile49(path9, "utf8")).split(`
|
|
45596
46149
|
`).filter((line) => line.includes("[compile]"));
|
|
45597
46150
|
for (let index2 = lines.length - 1;index2 >= 0; index2 -= 1) {
|
|
45598
46151
|
const stamp = /@\s*([0-9]{4}-[0-9]{2}-[0-9]{2}(?:T[0-9:.+-]+Z?)?)/u.exec(lines[index2] ?? "")?.[1];
|
|
@@ -45909,7 +46462,7 @@ function ignoredLocatorChangeFromDiff(input) {
|
|
|
45909
46462
|
}
|
|
45910
46463
|
|
|
45911
46464
|
// src/workflow/compileChangesRaw.ts
|
|
45912
|
-
import { readFile as
|
|
46465
|
+
import { readFile as readFile50 } from "node:fs/promises";
|
|
45913
46466
|
function isRecord15(value) {
|
|
45914
46467
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
45915
46468
|
}
|
|
@@ -45923,7 +46476,7 @@ function isRawBlocksCache2(value) {
|
|
|
45923
46476
|
return Object.values(value.snapshots).every((snapshot) => isRecord15(snapshot) && typeof snapshot.source_id === "string" && typeof snapshot.snapshot_file === "string" && typeof snapshot.content_hash === "string" && typeof snapshot.hash_id === "string" && typeof snapshot.structure_hash === "string" && Array.isArray(snapshot.blocks) && snapshot.blocks.every(isRawBlock2));
|
|
45924
46477
|
}
|
|
45925
46478
|
async function readJsonFile2(path9) {
|
|
45926
|
-
return JSON.parse(await
|
|
46479
|
+
return JSON.parse(await readFile50(path9, "utf8"));
|
|
45927
46480
|
}
|
|
45928
46481
|
async function loadRawBlocks2(path9) {
|
|
45929
46482
|
let parsed;
|
|
@@ -46506,10 +47059,10 @@ var init_node2 = __esm(() => {
|
|
|
46506
47059
|
// src/workflow/coverage.ts
|
|
46507
47060
|
import { createHash as createHash8 } from "node:crypto";
|
|
46508
47061
|
import { existsSync as existsSync37 } from "node:fs";
|
|
46509
|
-
import { mkdir as mkdir22, readFile as
|
|
46510
|
-
import { dirname as
|
|
47062
|
+
import { mkdir as mkdir22, readFile as readFile51 } from "node:fs/promises";
|
|
47063
|
+
import { dirname as dirname17, join as join47 } from "node:path";
|
|
46511
47064
|
function coverageStatePath(ctxDir) {
|
|
46512
|
-
return
|
|
47065
|
+
return join47(ctxDir, "output", "workflows", "_coverage", "workspace", "coverage-state.json");
|
|
46513
47066
|
}
|
|
46514
47067
|
function shortHash3(value) {
|
|
46515
47068
|
return createHash8("sha256").update(value).digest("hex").slice(0, 16);
|
|
@@ -46666,7 +47219,7 @@ async function readCoverageStateFile(ctxDir) {
|
|
|
46666
47219
|
if (!existsSync37(path9))
|
|
46667
47220
|
return emptyState();
|
|
46668
47221
|
try {
|
|
46669
|
-
const parsed = JSON.parse(await
|
|
47222
|
+
const parsed = JSON.parse(await readFile51(path9, "utf8"));
|
|
46670
47223
|
if (parsed.schema_version !== COVERAGE_STATE_SCHEMA_VERSION || !Array.isArray(parsed.candidates)) {
|
|
46671
47224
|
throw coverageStateInvalid("coverage state is invalid or uses an unsupported schema version");
|
|
46672
47225
|
}
|
|
@@ -46727,7 +47280,7 @@ function mergeDispositions(existing, incoming) {
|
|
|
46727
47280
|
}
|
|
46728
47281
|
async function writeCoverageStateFile(ctxDir, state) {
|
|
46729
47282
|
const path9 = coverageStatePath(ctxDir);
|
|
46730
|
-
await mkdir22(
|
|
47283
|
+
await mkdir22(dirname17(path9), { recursive: true });
|
|
46731
47284
|
await atomicWriteFile(path9, `${JSON.stringify(state, null, 2)}
|
|
46732
47285
|
`);
|
|
46733
47286
|
}
|
|
@@ -47571,6 +48124,12 @@ async function computeCompileChanges(options) {
|
|
|
47571
48124
|
}
|
|
47572
48125
|
const alignNodes = alignResult.nodes;
|
|
47573
48126
|
const sourcesFile = await loadSources(options.ctxDir);
|
|
48127
|
+
const inputSummary = await buildWorkspaceInputSummary({ ctxDir: options.ctxDir, workspaceRoot: paths.workspaceRoot, sourcesFile });
|
|
48128
|
+
const cacheRead = await readIncrementalCache({
|
|
48129
|
+
workspaceRoot,
|
|
48130
|
+
...options.cacheHome !== undefined ? { cacheHome: options.cacheHome } : {},
|
|
48131
|
+
inputSummary
|
|
48132
|
+
});
|
|
47574
48133
|
const sourcesById = new Map(sourcesFile.sources.map((source2) => [source2.id, source2]));
|
|
47575
48134
|
const ignoredSources = await compileIgnoredSourceIds({ ctxDir: options.ctxDir, explicit: options.ignoreSourceIds ?? [] });
|
|
47576
48135
|
const finalizedOwnership = await readCurrentSourceOwnership(options.ctxDir, {
|
|
@@ -47619,6 +48178,18 @@ async function computeCompileChanges(options) {
|
|
|
47619
48178
|
await writeCompileState({ paths, output: output2, now });
|
|
47620
48179
|
return output2;
|
|
47621
48180
|
}
|
|
48181
|
+
const cacheNeedsRebuild = cacheRead.status !== "ready" && cacheRead.status !== "missing";
|
|
48182
|
+
if (options.writeState === false && cacheNeedsRebuild) {
|
|
48183
|
+
const unknown2 = globalUnknownNodes(alignNodes, sourceIdsByNode, cacheRead.reason);
|
|
48184
|
+
return createCompileChangesOutput({
|
|
48185
|
+
now,
|
|
48186
|
+
nodes: unknown2.nodes,
|
|
48187
|
+
sourcesChecked: 0,
|
|
48188
|
+
sourcesUnchanged: 0,
|
|
48189
|
+
sourcesContentChanged: 0,
|
|
48190
|
+
unknownInputs: unknown2.unknownInputs
|
|
48191
|
+
});
|
|
48192
|
+
}
|
|
47622
48193
|
let rawBlocksResult = await loadRawBlocks2(paths.rawBlocks);
|
|
47623
48194
|
let fingerprintResult = await loadSectionFingerprints(paths.sectionFingerprints);
|
|
47624
48195
|
const knowledgeState = await readCompileKnowledgeState(options.ctxDir);
|
|
@@ -47638,7 +48209,7 @@ async function computeCompileChanges(options) {
|
|
|
47638
48209
|
}
|
|
47639
48210
|
let noPriorFingerprints = fingerprintResult.status === "unknown-input" && fingerprintResult.reason === "section-fingerprints-missing";
|
|
47640
48211
|
const needsFingerprints = alignNodes.some((node3) => knowledgeState.state.sectionNodeSlugs.has(node3.slug));
|
|
47641
|
-
if (options.writeState !== false && shouldSelfHealCache({ rawBlocksResult, fingerprintResult, needsFingerprints })) {
|
|
48212
|
+
if (options.writeState !== false && (cacheNeedsRebuild || shouldSelfHealCache({ rawBlocksResult, fingerprintResult, needsFingerprints }))) {
|
|
47642
48213
|
try {
|
|
47643
48214
|
await rebuildWorkspaceIncrementalCache({
|
|
47644
48215
|
ctxDir: options.ctxDir,
|
|
@@ -48735,8 +49306,8 @@ var init_fullTextPaging = __esm(() => {
|
|
|
48735
49306
|
|
|
48736
49307
|
// src/workflow/compileFinalizedContext.ts
|
|
48737
49308
|
import { existsSync as existsSync44 } from "node:fs";
|
|
48738
|
-
import { readFile as
|
|
48739
|
-
import { join as
|
|
49309
|
+
import { readFile as readFile56 } from "node:fs/promises";
|
|
49310
|
+
import { join as join54 } from "node:path";
|
|
48740
49311
|
function finalizedContextSourceIds(ownership, slug) {
|
|
48741
49312
|
const evidenceSources = new Set;
|
|
48742
49313
|
const contextSources = new Set;
|
|
@@ -48790,11 +49361,11 @@ function entryRole(block, slug) {
|
|
|
48790
49361
|
return "unresolved";
|
|
48791
49362
|
}
|
|
48792
49363
|
async function rawBody(ctxDir, file, source2) {
|
|
48793
|
-
const path9 =
|
|
49364
|
+
const path9 = join54(ctxDir, file);
|
|
48794
49365
|
if (!existsSync44(path9))
|
|
48795
49366
|
return null;
|
|
48796
49367
|
try {
|
|
48797
|
-
const raw = (await
|
|
49368
|
+
const raw = (await readFile56(path9, "utf8")).replace(/\r\n/g, `
|
|
48798
49369
|
`);
|
|
48799
49370
|
if (source2?.type === "note") {
|
|
48800
49371
|
const note = readNoteMetadata(raw);
|
|
@@ -49382,8 +49953,8 @@ var init_compileRuntimeHints = __esm(() => {
|
|
|
49382
49953
|
});
|
|
49383
49954
|
|
|
49384
49955
|
// src/workflow/compileContext.ts
|
|
49385
|
-
import { readFile as
|
|
49386
|
-
import { join as
|
|
49956
|
+
import { readFile as readFile57 } from "node:fs/promises";
|
|
49957
|
+
import { join as join55 } from "node:path";
|
|
49387
49958
|
function compileAlignNodeFromKnowledge(node3) {
|
|
49388
49959
|
return {
|
|
49389
49960
|
slug: node3.id,
|
|
@@ -49586,7 +50157,7 @@ async function readChangedBlockSnippet(ctxDir, block, source2, aliasIndex2) {
|
|
|
49586
50157
|
if (file.length === 0)
|
|
49587
50158
|
return fallback;
|
|
49588
50159
|
try {
|
|
49589
|
-
const raw = await
|
|
50160
|
+
const raw = await readFile57(join55(ctxDir, file), "utf8");
|
|
49590
50161
|
let note;
|
|
49591
50162
|
if (source2?.type === "note") {
|
|
49592
50163
|
try {
|
|
@@ -51028,8 +51599,8 @@ var init_locatedNodeSources = __esm(() => {
|
|
|
51028
51599
|
|
|
51029
51600
|
// src/reconcile/prepareCompileArchiveCandidates.ts
|
|
51030
51601
|
import { existsSync as existsSync45 } from "node:fs";
|
|
51031
|
-
import { readdir as readdir21, readFile as
|
|
51032
|
-
import { join as
|
|
51602
|
+
import { readdir as readdir21, readFile as readFile58 } from "node:fs/promises";
|
|
51603
|
+
import { join as join56 } from "node:path";
|
|
51033
51604
|
function sourceIdForSection3(nodeSources, sourceRef) {
|
|
51034
51605
|
const index2 = sourceRefAliasIndex(sourceRef);
|
|
51035
51606
|
if (index2 === null || index2 < 0)
|
|
@@ -51044,7 +51615,7 @@ async function readDropArchiveManifest2(path9) {
|
|
|
51044
51615
|
if (!existsSync45(path9))
|
|
51045
51616
|
return null;
|
|
51046
51617
|
try {
|
|
51047
|
-
const parsed = import_yaml29.default.parse(await
|
|
51618
|
+
const parsed = import_yaml29.default.parse(await readFile58(path9, "utf8"));
|
|
51048
51619
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) && parsed.kind === "source-drop" && typeof parsed.source_id === "string") {
|
|
51049
51620
|
return parsed;
|
|
51050
51621
|
}
|
|
@@ -51086,31 +51657,31 @@ async function restoredArchiveCandidatesForNode(ctxDir, targetNode) {
|
|
|
51086
51657
|
const restoredSourceIds = new Set(sourcesFile.sources.filter((source2) => source2.status === "active" && typeof source2.restored_at === "string").map((source2) => source2.id));
|
|
51087
51658
|
if (restoredSourceIds.size === 0)
|
|
51088
51659
|
return [];
|
|
51089
|
-
const sourcesRoot =
|
|
51660
|
+
const sourcesRoot = join56(ctxDir, "archive", "sources");
|
|
51090
51661
|
if (!existsSync45(sourcesRoot))
|
|
51091
51662
|
return [];
|
|
51092
51663
|
const out2 = [];
|
|
51093
51664
|
for (const sourceDir of await readdir21(sourcesRoot, { withFileTypes: true })) {
|
|
51094
51665
|
if (!sourceDir.isDirectory())
|
|
51095
51666
|
continue;
|
|
51096
|
-
const sourceRoot =
|
|
51667
|
+
const sourceRoot = join56(sourcesRoot, sourceDir.name);
|
|
51097
51668
|
for (const archiveDir of await readdir21(sourceRoot, { withFileTypes: true })) {
|
|
51098
51669
|
if (!archiveDir.isDirectory())
|
|
51099
51670
|
continue;
|
|
51100
51671
|
const archivePath = `archive/sources/${sourceDir.name}/${archiveDir.name}`;
|
|
51101
|
-
const manifest = await readDropArchiveManifest2(
|
|
51672
|
+
const manifest = await readDropArchiveManifest2(join56(ctxDir, archivePath, "manifest.yaml"));
|
|
51102
51673
|
if (!manifest || !restoredSourceIds.has(manifest.source_id))
|
|
51103
51674
|
continue;
|
|
51104
51675
|
const knowledgeBefore = Array.isArray(manifest.knowledge_before) ? manifest.knowledge_before : [];
|
|
51105
51676
|
for (const relPath of knowledgeBefore) {
|
|
51106
51677
|
if (!isSafeRelativePath(relPath))
|
|
51107
51678
|
continue;
|
|
51108
|
-
const absPath =
|
|
51679
|
+
const absPath = join56(ctxDir, relPath);
|
|
51109
51680
|
if (!existsSync45(absPath))
|
|
51110
51681
|
continue;
|
|
51111
51682
|
let parsed;
|
|
51112
51683
|
try {
|
|
51113
|
-
parsed = parseNodeMarkdown(await
|
|
51684
|
+
parsed = parseNodeMarkdown(await readFile58(absPath, "utf8"));
|
|
51114
51685
|
} catch {
|
|
51115
51686
|
continue;
|
|
51116
51687
|
}
|
|
@@ -51291,7 +51862,7 @@ function defaultDecisionForCompileDraftAction(input) {
|
|
|
51291
51862
|
|
|
51292
51863
|
// src/mdrive/section.ts
|
|
51293
51864
|
import { existsSync as existsSync46 } from "node:fs";
|
|
51294
|
-
import { join as
|
|
51865
|
+
import { join as join57 } from "node:path";
|
|
51295
51866
|
function locateNode(ctxDir, nodeSlug) {
|
|
51296
51867
|
return readWorkspaceNodeFiles(ctxDir).then((files) => findLocatedNode(flattenWorkspaceNodes(files), nodeSlug));
|
|
51297
51868
|
}
|
|
@@ -51519,7 +52090,7 @@ async function resolveSourceRefCandidates(input) {
|
|
|
51519
52090
|
const latest = await getLatestSnapshot(input.ctxDir, sourceId);
|
|
51520
52091
|
if (!latest?.file)
|
|
51521
52092
|
continue;
|
|
51522
|
-
const fullPath =
|
|
52093
|
+
const fullPath = join57(input.ctxDir, latest.file);
|
|
51523
52094
|
if (existsSync46(fullPath))
|
|
51524
52095
|
candidateFiles.push({ sourceId, path: fullPath });
|
|
51525
52096
|
}
|
|
@@ -52623,9 +53194,11 @@ var init_agentHintRegistry = __esm(() => {
|
|
|
52623
53194
|
"align-entity-tag-term-mixed-with-a-b",
|
|
52624
53195
|
"align-finalize-node-without-citation-evidence",
|
|
52625
53196
|
"align-finalize-patch-invalid",
|
|
53197
|
+
"align-block-preview-truncated",
|
|
52626
53198
|
"align-ownership-patch-base-digest-stale",
|
|
52627
53199
|
"align-ownership-patch-invalid",
|
|
52628
53200
|
"align-segments-required",
|
|
53201
|
+
"align-segments-source-mapping",
|
|
52629
53202
|
"align-scope-name-entity-warning",
|
|
52630
53203
|
"align-structure-decision-invalid",
|
|
52631
53204
|
"align-workflow-review-pending",
|
|
@@ -53123,14 +53696,14 @@ var init_agentHints = __esm(() => {
|
|
|
53123
53696
|
// src/workflow/outputArchive.ts
|
|
53124
53697
|
import { existsSync as existsSync47 } from "node:fs";
|
|
53125
53698
|
import { copyFile as copyFile3, mkdir as mkdir24, readdir as readdir22, realpath as realpath2, rename as rename5, unlink as unlink4 } from "node:fs/promises";
|
|
53126
|
-
import { dirname as
|
|
53699
|
+
import { dirname as dirname21, isAbsolute as isAbsolute6, join as join58, relative as relative14, resolve as resolve13 } from "node:path";
|
|
53127
53700
|
function archiveStamp(now) {
|
|
53128
53701
|
return now.toISOString().replace(/[:.]/g, "-");
|
|
53129
53702
|
}
|
|
53130
53703
|
async function uniqueArchiveDir(ctxDir, category, now) {
|
|
53131
|
-
const archiveRoot =
|
|
53704
|
+
const archiveRoot = join58(ctxDir, "output", "archive");
|
|
53132
53705
|
await mkdir24(archiveRoot, { recursive: true });
|
|
53133
|
-
const base =
|
|
53706
|
+
const base = join58(archiveRoot, `${archiveStamp(now)}-${category}`);
|
|
53134
53707
|
if (!existsSync47(base))
|
|
53135
53708
|
return base;
|
|
53136
53709
|
for (let index2 = 2;; index2 += 1) {
|
|
@@ -53147,7 +53720,7 @@ function normalizeOutputRelPath(name) {
|
|
|
53147
53720
|
return normalized;
|
|
53148
53721
|
}
|
|
53149
53722
|
async function listOutputFiles(outputDir, relDir = "") {
|
|
53150
|
-
const dir =
|
|
53723
|
+
const dir = join58(outputDir, relDir);
|
|
53151
53724
|
const entries = await readdir22(dir, { withFileTypes: true }).catch(() => []);
|
|
53152
53725
|
const out2 = [];
|
|
53153
53726
|
for (const entry of entries) {
|
|
@@ -53172,7 +53745,7 @@ function patternMatches(pattern, relPath) {
|
|
|
53172
53745
|
async function listMatchingOutputFiles(ctxDir, patterns) {
|
|
53173
53746
|
if (patterns.length === 0)
|
|
53174
53747
|
return [];
|
|
53175
|
-
const outputDir =
|
|
53748
|
+
const outputDir = join58(ctxDir, "output");
|
|
53176
53749
|
return (await listOutputFiles(outputDir)).filter((relPath) => patterns.some((pattern) => patternMatches(pattern, relPath)));
|
|
53177
53750
|
}
|
|
53178
53751
|
function uniqueNames(names) {
|
|
@@ -53180,7 +53753,7 @@ function uniqueNames(names) {
|
|
|
53180
53753
|
}
|
|
53181
53754
|
async function uniqueExternalCopies(ctxDir, copies) {
|
|
53182
53755
|
const out2 = new Map;
|
|
53183
|
-
const realCtxDir = await realpath2(ctxDir).catch(() =>
|
|
53756
|
+
const realCtxDir = await realpath2(ctxDir).catch(() => resolve13(ctxDir));
|
|
53184
53757
|
for (const copy of copies) {
|
|
53185
53758
|
const to = normalizeOutputRelPath(copy.to);
|
|
53186
53759
|
if (to.length === 0 || !existsSync47(copy.from))
|
|
@@ -53189,7 +53762,7 @@ async function uniqueExternalCopies(ctxDir, copies) {
|
|
|
53189
53762
|
throw new Error(`archive copyExternal.from must be an absolute path: ${copy.from}`);
|
|
53190
53763
|
}
|
|
53191
53764
|
const realFrom = await realpath2(copy.from);
|
|
53192
|
-
const rel =
|
|
53765
|
+
const rel = relative14(realCtxDir, realFrom);
|
|
53193
53766
|
if (rel === "" || rel.startsWith("..") || isAbsolute6(rel)) {
|
|
53194
53767
|
throw new Error(`archive copyExternal.from must stay inside the workspace: ${copy.from}`);
|
|
53195
53768
|
}
|
|
@@ -53206,31 +53779,31 @@ async function safeMove(src, dest) {
|
|
|
53206
53779
|
}
|
|
53207
53780
|
}
|
|
53208
53781
|
async function archiveOutputArtifacts(options) {
|
|
53209
|
-
const outputDir =
|
|
53782
|
+
const outputDir = join58(options.ctxDir, "output");
|
|
53210
53783
|
const move = uniqueNames([
|
|
53211
53784
|
...options.move ?? [],
|
|
53212
53785
|
...await listMatchingOutputFiles(options.ctxDir, options.movePatterns ?? [])
|
|
53213
|
-
]).filter((name) => existsSync47(
|
|
53786
|
+
]).filter((name) => existsSync47(join58(outputDir, name)));
|
|
53214
53787
|
const copy = uniqueNames([
|
|
53215
53788
|
...options.copy ?? [],
|
|
53216
53789
|
...await listMatchingOutputFiles(options.ctxDir, options.copyPatterns ?? [])
|
|
53217
|
-
]).filter((name) => existsSync47(
|
|
53790
|
+
]).filter((name) => existsSync47(join58(outputDir, name)) && !move.includes(name));
|
|
53218
53791
|
const copyExternal = (await uniqueExternalCopies(options.ctxDir, options.copyExternal ?? [])).filter((entry) => !move.includes(entry.to) && !copy.includes(entry.to));
|
|
53219
53792
|
if (move.length === 0 && copy.length === 0 && copyExternal.length === 0)
|
|
53220
53793
|
return null;
|
|
53221
53794
|
const archiveDir = await uniqueArchiveDir(options.ctxDir, options.category, options.now ?? new Date);
|
|
53222
53795
|
await mkdir24(archiveDir, { recursive: true });
|
|
53223
53796
|
for (const name of copy) {
|
|
53224
|
-
await mkdir24(
|
|
53225
|
-
await copyFile3(
|
|
53797
|
+
await mkdir24(dirname21(join58(archiveDir, name)), { recursive: true });
|
|
53798
|
+
await copyFile3(join58(outputDir, name), join58(archiveDir, name));
|
|
53226
53799
|
}
|
|
53227
53800
|
for (const entry of copyExternal) {
|
|
53228
|
-
await mkdir24(
|
|
53229
|
-
await copyFile3(entry.from,
|
|
53801
|
+
await mkdir24(dirname21(join58(archiveDir, entry.to)), { recursive: true });
|
|
53802
|
+
await copyFile3(entry.from, join58(archiveDir, entry.to));
|
|
53230
53803
|
}
|
|
53231
53804
|
for (const name of move) {
|
|
53232
|
-
await mkdir24(
|
|
53233
|
-
await safeMove(
|
|
53805
|
+
await mkdir24(dirname21(join58(archiveDir, name)), { recursive: true });
|
|
53806
|
+
await safeMove(join58(outputDir, name), join58(archiveDir, name));
|
|
53234
53807
|
}
|
|
53235
53808
|
return { archiveDir, moved: move, copied: [...copy, ...copyExternal.map((entry) => entry.to)] };
|
|
53236
53809
|
}
|
|
@@ -53238,9 +53811,9 @@ var init_outputArchive = () => {};
|
|
|
53238
53811
|
|
|
53239
53812
|
// src/workflow/compileCloseFinalizedNodes.ts
|
|
53240
53813
|
import { existsSync as existsSync48 } from "node:fs";
|
|
53241
|
-
import { join as
|
|
53814
|
+
import { join as join59 } from "node:path";
|
|
53242
53815
|
function finalizedNodePath(ctxDir, node3) {
|
|
53243
|
-
return
|
|
53816
|
+
return join59(ctxDir, "knowledge", node3.type, `${node3.slug}.md`);
|
|
53244
53817
|
}
|
|
53245
53818
|
function noWriteContextSources(node3) {
|
|
53246
53819
|
return [...new Set([
|
|
@@ -53337,8 +53910,8 @@ var init_compileCloseFinalizedNodes = __esm(() => {
|
|
|
53337
53910
|
|
|
53338
53911
|
// src/workflow/compileCloseDebt.ts
|
|
53339
53912
|
import { existsSync as existsSync49 } from "node:fs";
|
|
53340
|
-
import { readFile as
|
|
53341
|
-
import { join as
|
|
53913
|
+
import { readFile as readFile59, readdir as readdir23 } from "node:fs/promises";
|
|
53914
|
+
import { join as join60 } from "node:path";
|
|
53342
53915
|
function coverageDebtItems(status) {
|
|
53343
53916
|
return status.candidates.filter((candidate) => candidate.status === "unresolved" && candidate.coverage_type !== "context").map((candidate) => ({
|
|
53344
53917
|
debt_type: "coverage",
|
|
@@ -53419,23 +53992,23 @@ async function orphanKnowledgeDebtItems(ctxDir) {
|
|
|
53419
53992
|
return out2;
|
|
53420
53993
|
}
|
|
53421
53994
|
async function readWorkflowPayloadFiles(ctxDir, payloadBaseName) {
|
|
53422
|
-
const root2 =
|
|
53995
|
+
const root2 = join60(ctxDir, "output", "workflows");
|
|
53423
53996
|
if (!existsSync49(root2))
|
|
53424
53997
|
return [];
|
|
53425
53998
|
const out2 = [];
|
|
53426
53999
|
for (const workflowEntry of await readdir23(root2, { withFileTypes: true })) {
|
|
53427
54000
|
if (!workflowEntry.isDirectory())
|
|
53428
54001
|
continue;
|
|
53429
|
-
const workflowDir =
|
|
54002
|
+
const workflowDir = join60(root2, workflowEntry.name);
|
|
53430
54003
|
for (const scopeEntry of await readdir23(workflowDir, { withFileTypes: true }).catch(() => [])) {
|
|
53431
54004
|
if (!scopeEntry.isDirectory())
|
|
53432
54005
|
continue;
|
|
53433
|
-
const scopeDir =
|
|
54006
|
+
const scopeDir = join60(workflowDir, scopeEntry.name);
|
|
53434
54007
|
for (const format of ["json", "yaml"]) {
|
|
53435
|
-
const path9 =
|
|
54008
|
+
const path9 = join60(scopeDir, `${payloadBaseName}.${format}`);
|
|
53436
54009
|
if (!existsSync49(path9))
|
|
53437
54010
|
continue;
|
|
53438
|
-
const body2 = await
|
|
54011
|
+
const body2 = await readFile59(path9, "utf8");
|
|
53439
54012
|
out2.push(format === "json" ? JSON.parse(body2) : import_yaml30.default.parse(body2));
|
|
53440
54013
|
}
|
|
53441
54014
|
}
|
|
@@ -53460,7 +54033,7 @@ var init_compileCloseDebt = __esm(() => {
|
|
|
53460
54033
|
});
|
|
53461
54034
|
|
|
53462
54035
|
// src/workflow/compileCloseDraftScratch.ts
|
|
53463
|
-
import { readFile as
|
|
54036
|
+
import { readFile as readFile60 } from "node:fs/promises";
|
|
53464
54037
|
async function hasOnlyNoopCompileDraft(input) {
|
|
53465
54038
|
if (input.draftPaths.length === 0)
|
|
53466
54039
|
return false;
|
|
@@ -53474,7 +54047,7 @@ async function hasOnlyNoopDraftScratch(input) {
|
|
|
53474
54047
|
const current = await mdriveNodeShow({ ctxDir: input.ctxDir, slug: input.node }).catch(() => null);
|
|
53475
54048
|
const sections = new Map((current?.sections ?? []).map((section) => [section.id, section]));
|
|
53476
54049
|
for (const draftPath of input.draftPaths) {
|
|
53477
|
-
const draft = normalizeCompileDraftInput(import_yaml31.default.parse(await
|
|
54050
|
+
const draft = normalizeCompileDraftInput(import_yaml31.default.parse(await readFile60(draftPath, "utf8")));
|
|
53478
54051
|
if (!isRecord21(draft) || !Array.isArray(draft.actions))
|
|
53479
54052
|
return false;
|
|
53480
54053
|
for (const action of draft.actions) {
|
|
@@ -53531,28 +54104,28 @@ var init_compileCloseDraftScratch = __esm(() => {
|
|
|
53531
54104
|
|
|
53532
54105
|
// src/workflow/compileClose.ts
|
|
53533
54106
|
import { existsSync as existsSync50 } from "node:fs";
|
|
53534
|
-
import { readFile as
|
|
53535
|
-
import { join as
|
|
54107
|
+
import { readFile as readFile61, readdir as readdir24, rm as rm17 } from "node:fs/promises";
|
|
54108
|
+
import { join as join61 } from "node:path";
|
|
53536
54109
|
function knowledgePath(ctxDir, name) {
|
|
53537
|
-
return
|
|
54110
|
+
return join61(ctxDir, "knowledge", name);
|
|
53538
54111
|
}
|
|
53539
54112
|
async function snapshotFile(path9) {
|
|
53540
|
-
return existsSync50(path9) ? { path: path9, content: await
|
|
54113
|
+
return existsSync50(path9) ? { path: path9, content: await readFile61(path9, "utf8") } : { path: path9 };
|
|
53541
54114
|
}
|
|
53542
54115
|
async function snapshotCompileCloseFiles(ctxDir) {
|
|
53543
54116
|
const paths = new Set([
|
|
53544
54117
|
knowledgePath(ctxDir, "_index.md"),
|
|
53545
54118
|
knowledgePath(ctxDir, "changelog.md"),
|
|
53546
|
-
|
|
54119
|
+
join61(ctxDir, "knowledge", "_edges.yaml")
|
|
53547
54120
|
]);
|
|
53548
54121
|
for (const type of NODE_TYPES) {
|
|
53549
|
-
const dir =
|
|
54122
|
+
const dir = join61(ctxDir, "knowledge", type);
|
|
53550
54123
|
if (!existsSync50(dir))
|
|
53551
54124
|
continue;
|
|
53552
54125
|
const entries = await readdir24(dir, { withFileTypes: true });
|
|
53553
54126
|
for (const entry of entries) {
|
|
53554
54127
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
53555
|
-
paths.add(
|
|
54128
|
+
paths.add(join61(dir, entry.name));
|
|
53556
54129
|
}
|
|
53557
54130
|
}
|
|
53558
54131
|
}
|
|
@@ -53573,7 +54146,7 @@ async function readLastCompileAt2(ctxDir) {
|
|
|
53573
54146
|
const changelog = knowledgePath(ctxDir, "changelog.md");
|
|
53574
54147
|
if (!existsSync50(changelog))
|
|
53575
54148
|
return null;
|
|
53576
|
-
const lines = (await
|
|
54149
|
+
const lines = (await readFile61(changelog, "utf8")).split(`
|
|
53577
54150
|
`).filter((line) => line.includes("[compile]"));
|
|
53578
54151
|
for (let index2 = lines.length - 1;index2 >= 0; index2 -= 1) {
|
|
53579
54152
|
const stamp = /@\s*([0-9]{4}-[0-9]{2}-[0-9]{2}(?:T[0-9:.+-]+Z?)?)/u.exec(lines[index2] ?? "")?.[1];
|
|
@@ -53617,7 +54190,7 @@ async function compileDraftScratchEntries(ctxDir) {
|
|
|
53617
54190
|
continue;
|
|
53618
54191
|
const match = /^compile\.(.+)\.draft\.(?:json|ya?ml)$/u.exec(entry.name);
|
|
53619
54192
|
if (match?.[1])
|
|
53620
|
-
out2.push({ slug: match[1], path:
|
|
54193
|
+
out2.push({ slug: match[1], path: join61(outputDir, entry.name) });
|
|
53621
54194
|
}
|
|
53622
54195
|
return out2;
|
|
53623
54196
|
}
|
|
@@ -53932,6 +54505,7 @@ async function compileCloseInner(options) {
|
|
|
53932
54505
|
pendingCompileNodes: beforeCache.state.pending_compile.nodes ?? []
|
|
53933
54506
|
});
|
|
53934
54507
|
await assertNoUnownedSourceOwnership(options.ctxDir);
|
|
54508
|
+
await assertNoUnclosedRenderAutoBlocks(options.ctxDir);
|
|
53935
54509
|
const coverageStatus = await readAndPruneCoverageWorkspaceStatus(options.ctxDir);
|
|
53936
54510
|
const retractedNodes = await retractRemovedFinalizedNodes(options.ctxDir);
|
|
53937
54511
|
const createdContainerDomains = await ensureFinalizedContainerDomains(options.ctxDir, now);
|
|
@@ -54055,6 +54629,7 @@ var init_compileClose = __esm(() => {
|
|
|
54055
54629
|
init_temporal();
|
|
54056
54630
|
init_workspaceLayout();
|
|
54057
54631
|
init_verify();
|
|
54632
|
+
init_verifyRenderBlocks();
|
|
54058
54633
|
init_ledger();
|
|
54059
54634
|
init_semanticLedgerGc();
|
|
54060
54635
|
init_workspace();
|
|
@@ -56008,7 +56583,7 @@ var init_prepareRefresh = __esm(() => {
|
|
|
56008
56583
|
});
|
|
56009
56584
|
|
|
56010
56585
|
// src/reconcile/prepare.ts
|
|
56011
|
-
import { readFile as
|
|
56586
|
+
import { readFile as readFile62 } from "node:fs/promises";
|
|
56012
56587
|
async function ensureRetrievalIndex2(input) {
|
|
56013
56588
|
const read = await readRetrievalIndex(input);
|
|
56014
56589
|
if (read.status === "ready" && read.index)
|
|
@@ -56042,7 +56617,7 @@ async function prepareRetrieval(input) {
|
|
|
56042
56617
|
async function readJsonOrYaml(path9) {
|
|
56043
56618
|
let raw;
|
|
56044
56619
|
try {
|
|
56045
|
-
raw = await
|
|
56620
|
+
raw = await readFile62(path9, "utf8");
|
|
56046
56621
|
} catch (error) {
|
|
56047
56622
|
if (error.code === "ENOENT") {
|
|
56048
56623
|
throw new ContextError(ExitCode.UserError, `file not found: ${path9}`, {
|
|
@@ -56163,7 +56738,7 @@ var init_prepare = __esm(() => {
|
|
|
56163
56738
|
|
|
56164
56739
|
// src/cli.ts
|
|
56165
56740
|
import { existsSync as existsSync54, readFileSync as readFileSync3, realpathSync as realpathSync2 } from "node:fs";
|
|
56166
|
-
import { dirname as
|
|
56741
|
+
import { dirname as dirname28, join as join70 } from "node:path";
|
|
56167
56742
|
import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL3 } from "node:url";
|
|
56168
56743
|
|
|
56169
56744
|
// ../../node_modules/.bun/commander@11.1.0/node_modules/commander/esm.mjs
|
|
@@ -57080,6 +57655,7 @@ function verifyIssueAgentView(issue) {
|
|
|
57080
57655
|
location: semanticIssueLocation(issue),
|
|
57081
57656
|
...issue.slug !== undefined ? { node_slug: issue.slug } : {},
|
|
57082
57657
|
...issue.sectionId !== undefined ? { section_id: issue.sectionId } : {},
|
|
57658
|
+
...issue.line !== undefined ? { line: issue.line } : {},
|
|
57083
57659
|
...issue.next_action !== undefined ? { next_action: issue.next_action } : {}
|
|
57084
57660
|
};
|
|
57085
57661
|
}
|
|
@@ -62132,7 +62708,7 @@ init_exitCode();
|
|
|
62132
62708
|
var import_yaml25 = __toESM(require_dist(), 1);
|
|
62133
62709
|
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
62134
62710
|
import { mkdir as mkdir21, writeFile as writeFile16 } from "node:fs/promises";
|
|
62135
|
-
import { dirname as
|
|
62711
|
+
import { dirname as dirname16, resolve as resolve11 } from "node:path";
|
|
62136
62712
|
|
|
62137
62713
|
// src/workflow/dropApply.ts
|
|
62138
62714
|
init_atomicWrite();
|
|
@@ -62143,8 +62719,8 @@ init_graphEdges();
|
|
|
62143
62719
|
init_verify();
|
|
62144
62720
|
init_ledger();
|
|
62145
62721
|
import { existsSync as existsSync32 } from "node:fs";
|
|
62146
|
-
import { cp as cp2, mkdir as mkdir18, readFile as
|
|
62147
|
-
import { dirname as
|
|
62722
|
+
import { cp as cp2, mkdir as mkdir18, readFile as readFile42, rm as rm11 } from "node:fs/promises";
|
|
62723
|
+
import { dirname as dirname14, join as join40, relative as relative12 } from "node:path";
|
|
62148
62724
|
|
|
62149
62725
|
// src/reconcile/sectionValidation.ts
|
|
62150
62726
|
init_sectionMount();
|
|
@@ -62226,7 +62802,7 @@ init_workspace();
|
|
|
62226
62802
|
init_exitCode();
|
|
62227
62803
|
var import_yaml21 = __toESM(require_dist(), 1);
|
|
62228
62804
|
import { writeFile as writeFile14 } from "node:fs/promises";
|
|
62229
|
-
import { join as
|
|
62805
|
+
import { join as join38 } from "node:path";
|
|
62230
62806
|
function nowIso4(now = new Date) {
|
|
62231
62807
|
return now.toISOString();
|
|
62232
62808
|
}
|
|
@@ -62295,7 +62871,7 @@ async function markSourceDropped(input) {
|
|
|
62295
62871
|
...input.archivePath !== undefined ? { archive_path: input.archivePath } : {}
|
|
62296
62872
|
} : s)
|
|
62297
62873
|
};
|
|
62298
|
-
await writeFile14(
|
|
62874
|
+
await writeFile14(join38(ctxDir, "raw", "_sources.yaml"), import_yaml21.default.stringify(next), "utf8");
|
|
62299
62875
|
await mdriveWorkspaceAppendChangelog({
|
|
62300
62876
|
ctxDir,
|
|
62301
62877
|
entry: `[drop] source=${sourceId} reason=${reason} affected-nodes=${affectedNodes} affected-sections=${affectedSections} @ ${droppedAt}`
|
|
@@ -62308,7 +62884,7 @@ init_sectionFingerprints();
|
|
|
62308
62884
|
init_errors();
|
|
62309
62885
|
init_sourceRef();
|
|
62310
62886
|
var import_yaml22 = __toESM(require_dist(), 1);
|
|
62311
|
-
import { isAbsolute as isAbsolute5, join as
|
|
62887
|
+
import { isAbsolute as isAbsolute5, join as join39, relative as relative11, resolve as resolve10 } from "node:path";
|
|
62312
62888
|
init_sources();
|
|
62313
62889
|
init_shared();
|
|
62314
62890
|
init_graphEdges();
|
|
@@ -62360,16 +62936,16 @@ function normalizeSnapshotPath(input) {
|
|
|
62360
62936
|
const cwd = input.cwd ?? process.cwd();
|
|
62361
62937
|
const candidates = new Set;
|
|
62362
62938
|
const addAbs = (path9) => {
|
|
62363
|
-
const rel =
|
|
62939
|
+
const rel = toPosixPath3(relative11(ctxDir, path9));
|
|
62364
62940
|
if (!rel.startsWith("../") && rel !== ".." && !isAbsolute5(rel)) {
|
|
62365
62941
|
candidates.add(rel);
|
|
62366
62942
|
}
|
|
62367
62943
|
};
|
|
62368
|
-
addAbs(isAbsolute5(target) ? target :
|
|
62944
|
+
addAbs(isAbsolute5(target) ? target : resolve10(cwd, target));
|
|
62369
62945
|
if (!isAbsolute5(target)) {
|
|
62370
|
-
addAbs(
|
|
62946
|
+
addAbs(resolve10(ctxDir, target));
|
|
62371
62947
|
if (target.startsWith(".context/")) {
|
|
62372
|
-
addAbs(
|
|
62948
|
+
addAbs(resolve10(join39(ctxDir, ".."), target));
|
|
62373
62949
|
}
|
|
62374
62950
|
}
|
|
62375
62951
|
for (const rel of candidates) {
|
|
@@ -62948,7 +63524,7 @@ function buildDropScopeByItem(plan, decisions) {
|
|
|
62948
63524
|
async function snapshotTextFile(path9) {
|
|
62949
63525
|
if (!existsSync32(path9))
|
|
62950
63526
|
return { path: path9, existed: false };
|
|
62951
|
-
return { path: path9, existed: true, content: await
|
|
63527
|
+
return { path: path9, existed: true, content: await readFile42(path9, "utf8") };
|
|
62952
63528
|
}
|
|
62953
63529
|
async function restoreTextFile(snapshot) {
|
|
62954
63530
|
if (!snapshot.existed) {
|
|
@@ -62959,21 +63535,21 @@ async function restoreTextFile(snapshot) {
|
|
|
62959
63535
|
}
|
|
62960
63536
|
async function restoreRawEntries(input) {
|
|
62961
63537
|
for (const entry of input.entries) {
|
|
62962
|
-
const fromAbs =
|
|
62963
|
-
const toAbs =
|
|
63538
|
+
const fromAbs = join40(input.ctxDir, entry.to);
|
|
63539
|
+
const toAbs = join40(input.ctxDir, entry.from);
|
|
62964
63540
|
if (!existsSync32(fromAbs))
|
|
62965
63541
|
continue;
|
|
62966
|
-
await mkdir18(
|
|
63542
|
+
await mkdir18(dirname14(toAbs), { recursive: true });
|
|
62967
63543
|
await cp2(fromAbs, toAbs, { recursive: entry.kind === "dir", force: true });
|
|
62968
63544
|
}
|
|
62969
63545
|
}
|
|
62970
63546
|
async function restoreKnowledgeBefore(input) {
|
|
62971
63547
|
for (const filePath of input.touchedKnowledgeFiles) {
|
|
62972
63548
|
const rel = relative12(input.ctxDir, filePath);
|
|
62973
|
-
const archivedPath =
|
|
63549
|
+
const archivedPath = join40(input.ctxDir, input.archivePath, "knowledge", "before", rel);
|
|
62974
63550
|
if (!existsSync32(archivedPath))
|
|
62975
63551
|
continue;
|
|
62976
|
-
await mkdir18(
|
|
63552
|
+
await mkdir18(dirname14(filePath), { recursive: true });
|
|
62977
63553
|
await cp2(archivedPath, filePath, { force: true });
|
|
62978
63554
|
}
|
|
62979
63555
|
}
|
|
@@ -62987,11 +63563,11 @@ async function restoreDropApplyFailure(input) {
|
|
|
62987
63563
|
await restoreTextFile(input.sourcesBefore);
|
|
62988
63564
|
await restoreTextFile(input.changelogBefore);
|
|
62989
63565
|
await restoreTextFile(input.ledgerBefore);
|
|
62990
|
-
await rm11(
|
|
63566
|
+
await rm11(join40(input.ctxDir, input.archivePath), { recursive: true, force: true });
|
|
62991
63567
|
}
|
|
62992
63568
|
async function commitDropPlanWrites(input) {
|
|
62993
|
-
const sourcesBefore = await snapshotTextFile(
|
|
62994
|
-
const changelogBefore = await snapshotTextFile(
|
|
63569
|
+
const sourcesBefore = await snapshotTextFile(join40(input.ctxDir, "raw", "_sources.yaml"));
|
|
63570
|
+
const changelogBefore = await snapshotTextFile(join40(input.ctxDir, "knowledge", "changelog.md"));
|
|
62995
63571
|
const ledgerBefore = await snapshotTextFile(semanticLedgerPath2(input.ctxDir));
|
|
62996
63572
|
const plannedArchivePath = sourceArchiveRelPath(input.source.id, input.droppedAt);
|
|
62997
63573
|
let archive;
|
|
@@ -63181,7 +63757,7 @@ async function applyDropPlan(input) {
|
|
|
63181
63757
|
removeDroppedContextSources({ files, sourceId: plan.source_id, deletedFiles, touchedFiles });
|
|
63182
63758
|
markGraphEdgeNeighborsForArchivedNodes({ plan, nodes, archivedSlugs, deletedFiles, touchedFiles });
|
|
63183
63759
|
const targetAfterByItem = collectDropTargetSnapshots(nodes, semanticDecisions);
|
|
63184
|
-
const graphEdgesPath2 =
|
|
63760
|
+
const graphEdgesPath2 = join40(input.ctxDir, "knowledge", "_edges.yaml");
|
|
63185
63761
|
const touchedKnowledgeFiles = new Set([...touchedFiles, ...deletedFiles]);
|
|
63186
63762
|
if (archivedSlugs.size > 0 && existsSync32(graphEdgesPath2)) {
|
|
63187
63763
|
touchedKnowledgeFiles.add(graphEdgesPath2);
|
|
@@ -63219,8 +63795,8 @@ init_verify();
|
|
|
63219
63795
|
init_workspace();
|
|
63220
63796
|
init_exitCode();
|
|
63221
63797
|
import { existsSync as existsSync34 } from "node:fs";
|
|
63222
|
-
import { cp as cp3, mkdir as mkdir19, readFile as
|
|
63223
|
-
import { dirname as
|
|
63798
|
+
import { cp as cp3, mkdir as mkdir19, readFile as readFile46, readdir as readdir15, rm as rm12 } from "node:fs/promises";
|
|
63799
|
+
import { dirname as dirname15, join as join42 } from "node:path";
|
|
63224
63800
|
|
|
63225
63801
|
// src/code/codeProjectionFreshness.ts
|
|
63226
63802
|
init_errors();
|
|
@@ -63233,11 +63809,13 @@ init_verify();
|
|
|
63233
63809
|
init_exitCode();
|
|
63234
63810
|
|
|
63235
63811
|
// src/code/codeProjection.ts
|
|
63812
|
+
init_config();
|
|
63236
63813
|
init_sourceRef();
|
|
63237
63814
|
init_externalDeps();
|
|
63238
63815
|
init_graphEdges();
|
|
63239
63816
|
init_shared();
|
|
63240
|
-
import { readFile as
|
|
63817
|
+
import { readFile as readFile45 } from "node:fs/promises";
|
|
63818
|
+
import { relative as relative13 } from "node:path";
|
|
63241
63819
|
|
|
63242
63820
|
// src/code/codeProjectionBuild.ts
|
|
63243
63821
|
init_cliFeedback();
|
|
@@ -63254,8 +63832,8 @@ init_sources();
|
|
|
63254
63832
|
init_exitCode();
|
|
63255
63833
|
var import_yaml23 = __toESM(require_dist(), 1);
|
|
63256
63834
|
import { existsSync as existsSync33 } from "node:fs";
|
|
63257
|
-
import { readFile as
|
|
63258
|
-
import { join as
|
|
63835
|
+
import { readFile as readFile43 } from "node:fs/promises";
|
|
63836
|
+
import { join as join41 } from "node:path";
|
|
63259
63837
|
|
|
63260
63838
|
// src/code/codeSnapshotVersioning.ts
|
|
63261
63839
|
init_src();
|
|
@@ -63466,15 +64044,15 @@ function snapshotSemanticId3(snapshot) {
|
|
|
63466
64044
|
}
|
|
63467
64045
|
function snapshotDir3(ctxDir, source2, snapshot) {
|
|
63468
64046
|
if (snapshot.dir)
|
|
63469
|
-
return
|
|
64047
|
+
return join41(ctxDir, snapshot.dir);
|
|
63470
64048
|
const slug = sourceSlugFor2(source2, snapshot);
|
|
63471
64049
|
const id2 = snapshot.snapshot_id;
|
|
63472
64050
|
if (!slug || !id2)
|
|
63473
64051
|
return null;
|
|
63474
|
-
return
|
|
64052
|
+
return join41(ctxDir, "raw", "aspect", "code", slug, id2);
|
|
63475
64053
|
}
|
|
63476
64054
|
async function readStructuredFile(path9) {
|
|
63477
|
-
const text5 = await
|
|
64055
|
+
const text5 = await readFile43(path9, "utf8");
|
|
63478
64056
|
const parsed = import_yaml23.default.parse(text5);
|
|
63479
64057
|
return isRecord12(parsed) ? parsed : {};
|
|
63480
64058
|
}
|
|
@@ -63484,7 +64062,7 @@ async function readStructuredFileIfExists(path9) {
|
|
|
63484
64062
|
return readStructuredFile(path9);
|
|
63485
64063
|
}
|
|
63486
64064
|
async function readJsonl2(path9) {
|
|
63487
|
-
const text5 = await
|
|
64065
|
+
const text5 = await readFile43(path9, "utf8");
|
|
63488
64066
|
const rows = [];
|
|
63489
64067
|
for (const line of text5.split(/\r?\n/u)) {
|
|
63490
64068
|
if (line.trim().length === 0)
|
|
@@ -63510,15 +64088,15 @@ async function loadOneSnapshot(ctxDir, source2, snapshot) {
|
|
|
63510
64088
|
source_id: source2.id
|
|
63511
64089
|
});
|
|
63512
64090
|
}
|
|
63513
|
-
const files = Object.fromEntries(BETA9_CODE_SNAPSHOT_FILES.flatMap((fileName) => existsSync33(
|
|
63514
|
-
const sourceFile = await readStructuredFileIfExists(
|
|
63515
|
-
const manifest = await readStructuredFileIfExists(
|
|
63516
|
-
const meta = await readStructuredFileIfExists(
|
|
63517
|
-
const digests = await readJsonlIfExists(
|
|
63518
|
-
const sourceFiles = await readJsonlIfExists(
|
|
63519
|
-
const packages = await readJsonlIfExists(
|
|
63520
|
-
const symbols = await readJsonlIfExists(
|
|
63521
|
-
const edges = await readJsonlIfExists(
|
|
64091
|
+
const files = Object.fromEntries(BETA9_CODE_SNAPSHOT_FILES.flatMap((fileName) => existsSync33(join41(dir, fileName)) ? [[fileName, true]] : []));
|
|
64092
|
+
const sourceFile = await readStructuredFileIfExists(join41(dir, "source.yaml"));
|
|
64093
|
+
const manifest = await readStructuredFileIfExists(join41(dir, "manifest.json"));
|
|
64094
|
+
const meta = await readStructuredFileIfExists(join41(dir, "_meta.yaml"));
|
|
64095
|
+
const digests = await readJsonlIfExists(join41(dir, "digests.jsonl"));
|
|
64096
|
+
const sourceFiles = await readJsonlIfExists(join41(dir, "source-files.jsonl"));
|
|
64097
|
+
const packages = await readJsonlIfExists(join41(dir, "packages.jsonl"));
|
|
64098
|
+
const symbols = await readJsonlIfExists(join41(dir, "symbols.jsonl"));
|
|
64099
|
+
const edges = await readJsonlIfExists(join41(dir, "edges.jsonl"));
|
|
63522
64100
|
validateCodeSnapshotSchema({
|
|
63523
64101
|
files,
|
|
63524
64102
|
...sourceFile !== undefined ? { source: sourceFile } : {},
|
|
@@ -63621,7 +64199,7 @@ init_sourceRef();
|
|
|
63621
64199
|
init_sources();
|
|
63622
64200
|
init_knowledge();
|
|
63623
64201
|
init_exitCode();
|
|
63624
|
-
import { readFile as
|
|
64202
|
+
import { readFile as readFile44 } from "node:fs/promises";
|
|
63625
64203
|
var SECTION_ORDER = new Map(SECTION_RENDER_ORDER.map((kind, index2) => [kind, index2]));
|
|
63626
64204
|
function visibleVersion(value) {
|
|
63627
64205
|
return value === undefined ? undefined : `v${String(value).replace(/^v/u, "")}`;
|
|
@@ -63784,7 +64362,7 @@ function assertNoGeneratedDrift(draft, sections) {
|
|
|
63784
64362
|
}
|
|
63785
64363
|
async function renderedNodePlan(draft) {
|
|
63786
64364
|
const sections = finalizeNodeSections(draft);
|
|
63787
|
-
const current = draft.existingPath ? await
|
|
64365
|
+
const current = draft.existingPath ? await readFile44(draft.existingPath, "utf8").catch(() => "") : "";
|
|
63788
64366
|
assertNoGeneratedDrift(draft, sections);
|
|
63789
64367
|
const input = {
|
|
63790
64368
|
node: draft.node,
|
|
@@ -64285,21 +64863,120 @@ async function buildCodeProjectionDraftState(ctxDir, sourceSlug3) {
|
|
|
64285
64863
|
async function buildCodeProjectionPlan(ctxDir, sourceSlug3) {
|
|
64286
64864
|
return renderCodeProjectionPlanFromState(await buildCodeProjectionDraftState(ctxDir, sourceSlug3));
|
|
64287
64865
|
}
|
|
64866
|
+
function parsedRootFromRenderInput(input, headingLevel = 1) {
|
|
64867
|
+
return {
|
|
64868
|
+
node: input.node,
|
|
64869
|
+
headingLevel,
|
|
64870
|
+
body: input.body ?? "",
|
|
64871
|
+
sections: [...input.sections],
|
|
64872
|
+
children: (input.children ?? []).map((child) => parsedRootFromRenderInput(child, headingLevel + 1)),
|
|
64873
|
+
containsEdges: [],
|
|
64874
|
+
containsList: []
|
|
64875
|
+
};
|
|
64876
|
+
}
|
|
64877
|
+
function projectedWorkspaceFileFromInput(ctxDir, filePath, input) {
|
|
64878
|
+
const relativePath = toPosixPath3(relative13(knowledgeRoot3(ctxDir), filePath));
|
|
64879
|
+
const root2 = parsedRootFromRenderInput(input);
|
|
64880
|
+
const expectedSlug = slugFromKnowledgeRelativePath(relativePath);
|
|
64881
|
+
if (expectedSlug !== null && expectedSlug.includes("/") && root2.node.id === expectedSlug) {
|
|
64882
|
+
const parentSlug = expectedSlug.split("/")[0];
|
|
64883
|
+
root2.containsEdges = [{
|
|
64884
|
+
type: "contains",
|
|
64885
|
+
from: parentSlug,
|
|
64886
|
+
to: expectedSlug,
|
|
64887
|
+
grounding: "directory",
|
|
64888
|
+
...root2.node.valid_from !== undefined ? { valid_from: root2.node.valid_from } : {},
|
|
64889
|
+
...root2.node.valid_until !== undefined ? { valid_until: root2.node.valid_until } : {}
|
|
64890
|
+
}];
|
|
64891
|
+
}
|
|
64892
|
+
return { filePath, relativePath, root: root2 };
|
|
64893
|
+
}
|
|
64894
|
+
async function projectedWorkspaceFiles(ctxDir, rendered) {
|
|
64895
|
+
const byPath = new Map((await readWorkspaceNodeFiles(ctxDir)).map((file) => [file.filePath, file]));
|
|
64896
|
+
for (const item of rendered.values()) {
|
|
64897
|
+
const filePath = knowledgeFilePath(ctxDir, item.input.node.type, item.input.node.id);
|
|
64898
|
+
byPath.set(filePath, projectedWorkspaceFileFromInput(ctxDir, filePath, item.input));
|
|
64899
|
+
}
|
|
64900
|
+
return [...byPath.values()];
|
|
64901
|
+
}
|
|
64902
|
+
async function projectedRenderContext(plan) {
|
|
64903
|
+
const [files, currentEdges, currentExternals, renderConfig] = await Promise.all([
|
|
64904
|
+
projectedWorkspaceFiles(plan.state.ctxDir, plan.rendered),
|
|
64905
|
+
loadKnowledgeGraphEdges(plan.state.ctxDir),
|
|
64906
|
+
loadExternalDeps(plan.state.ctxDir),
|
|
64907
|
+
loadRenderConfig(plan.state.ctxDir)
|
|
64908
|
+
]);
|
|
64909
|
+
const codeGroundings = new Set(plan.source_slugs.map((slug) => `code:${slug}`));
|
|
64910
|
+
const graphEdges = [
|
|
64911
|
+
...currentEdges.filter((edge2) => !codeGroundings.has(edge2.grounding ?? "")),
|
|
64912
|
+
...plan.state.edges
|
|
64913
|
+
];
|
|
64914
|
+
const externalOwners = new Set;
|
|
64915
|
+
for (const node3 of plan.nodes)
|
|
64916
|
+
externalOwners.add(ownerSlugForPackageScopedPath(node3.slug));
|
|
64917
|
+
for (const dep of plan.state.externals)
|
|
64918
|
+
externalOwners.add(ownerSlugForPackageScopedPath(dep.from));
|
|
64919
|
+
const externalDeps = [
|
|
64920
|
+
...currentExternals.filter((dep) => !externalOwners.has(ownerSlugForPackageScopedPath(dep.from))),
|
|
64921
|
+
...plan.state.externals
|
|
64922
|
+
];
|
|
64923
|
+
return buildRenderWorkspaceContextFromData({
|
|
64924
|
+
files,
|
|
64925
|
+
graphEdges,
|
|
64926
|
+
externalDeps,
|
|
64927
|
+
renderOptions: {
|
|
64928
|
+
nodeLinkMode: renderConfig.obsidian_mode ? "wiki" : "md",
|
|
64929
|
+
usedBy: renderConfig.used_by
|
|
64930
|
+
}
|
|
64931
|
+
});
|
|
64932
|
+
}
|
|
64288
64933
|
async function renderCodeProjectionPlanFromState(state) {
|
|
64289
64934
|
const rendered = new Map;
|
|
64290
|
-
const
|
|
64935
|
+
const pending = [];
|
|
64291
64936
|
for (const draft of [...state.nodeDrafts.values()].sort((left, right) => left.node.id.localeCompare(right.node.id))) {
|
|
64292
64937
|
const result = await renderedNodePlan(draft);
|
|
64293
|
-
|
|
64294
|
-
|
|
64295
|
-
nodes.push({
|
|
64938
|
+
const filePath = knowledgeFilePath(state.ctxDir, result.input.node.type, result.input.node.id);
|
|
64939
|
+
pending.push({
|
|
64296
64940
|
slug: draft.node.id,
|
|
64297
|
-
|
|
64298
|
-
|
|
64941
|
+
input: result.input,
|
|
64942
|
+
current: await readFile45(filePath, "utf8").catch(() => ""),
|
|
64943
|
+
filePath
|
|
64944
|
+
});
|
|
64945
|
+
rendered.set(draft.node.id, { input: result.input, rendered: result.rendered });
|
|
64946
|
+
}
|
|
64947
|
+
const initialPlan = {
|
|
64948
|
+
action: "code-align",
|
|
64949
|
+
sources: [...new Set([...state.nodeDrafts.values()].map((draft) => draft.source.source.id))].sort(),
|
|
64950
|
+
source_slugs: [...new Set([...state.nodeDrafts.values()].map((draft) => draft.source.sourceSlug))].sort(),
|
|
64951
|
+
nodes: pending.map((item) => ({
|
|
64952
|
+
slug: item.input.node.id,
|
|
64953
|
+
title: item.input.node.title,
|
|
64954
|
+
section_count: item.input.sections.length,
|
|
64955
|
+
code_section_count: item.input.sections.filter((section) => parseCodeSourceRef(section.source_ref) !== null).length,
|
|
64956
|
+
diff: "unchanged",
|
|
64957
|
+
...item.input.node.valid_from !== undefined ? { valid_from: item.input.node.valid_from } : {},
|
|
64958
|
+
...item.input.node.valid_until !== undefined ? { valid_until: item.input.node.valid_until } : {}
|
|
64959
|
+
})),
|
|
64960
|
+
edge_count: state.edges.length,
|
|
64961
|
+
external_count: state.externals.length,
|
|
64962
|
+
warnings: state.warnings,
|
|
64963
|
+
rendered,
|
|
64964
|
+
state
|
|
64965
|
+
};
|
|
64966
|
+
const renderContext = await projectedRenderContext(initialPlan);
|
|
64967
|
+
const nodes = [];
|
|
64968
|
+
for (const item of pending) {
|
|
64969
|
+
const renderedText = renderNodeInputForFile(item.filePath, item.input, renderContext);
|
|
64970
|
+
rendered.set(item.slug, { input: item.input, rendered: renderedText });
|
|
64971
|
+
const codeSections = item.input.sections.filter((section) => parseCodeSourceRef(section.source_ref) !== null);
|
|
64972
|
+
nodes.push({
|
|
64973
|
+
slug: item.input.node.id,
|
|
64974
|
+
title: item.input.node.title,
|
|
64975
|
+
section_count: item.input.sections.length,
|
|
64299
64976
|
code_section_count: codeSections.length,
|
|
64300
|
-
diff:
|
|
64301
|
-
...
|
|
64302
|
-
...
|
|
64977
|
+
diff: item.current.length === 0 ? "create" : item.current === renderedText ? "unchanged" : "update",
|
|
64978
|
+
...item.input.node.valid_from !== undefined ? { valid_from: item.input.node.valid_from } : {},
|
|
64979
|
+
...item.input.node.valid_until !== undefined ? { valid_until: item.input.node.valid_until } : {}
|
|
64303
64980
|
});
|
|
64304
64981
|
}
|
|
64305
64982
|
return {
|
|
@@ -64322,7 +64999,7 @@ async function writeProjectedNodes(plan, ctxDir) {
|
|
|
64322
64999
|
for (const [slug, rendered] of plan.rendered) {
|
|
64323
65000
|
const filePath = knowledgeFilePath(ctxDir, rendered.input.node.type, slug);
|
|
64324
65001
|
await ensureKnowledgeTypeDir(ctxDir, rendered.input.node.type);
|
|
64325
|
-
const current = await
|
|
65002
|
+
const current = await readFile45(filePath, "utf8").catch(() => "");
|
|
64326
65003
|
if (current === rendered.rendered)
|
|
64327
65004
|
continue;
|
|
64328
65005
|
await atomicWriteText(filePath, rendered.rendered);
|
|
@@ -64789,35 +65466,35 @@ function applyCodeDropToNode(input) {
|
|
|
64789
65466
|
async function snapshotTextFile2(path9) {
|
|
64790
65467
|
if (!existsSync34(path9))
|
|
64791
65468
|
return { path: path9, existed: false };
|
|
64792
|
-
return { path: path9, existed: true, content: await
|
|
65469
|
+
return { path: path9, existed: true, content: await readFile46(path9, "utf8") };
|
|
64793
65470
|
}
|
|
64794
65471
|
async function restoreTextFile2(snapshot) {
|
|
64795
65472
|
if (!snapshot.existed) {
|
|
64796
65473
|
await rm12(snapshot.path, { force: true });
|
|
64797
65474
|
return;
|
|
64798
65475
|
}
|
|
64799
|
-
await mkdir19(
|
|
65476
|
+
await mkdir19(dirname15(snapshot.path), { recursive: true });
|
|
64800
65477
|
await atomicWriteFile(snapshot.path, snapshot.content ?? "");
|
|
64801
65478
|
}
|
|
64802
65479
|
async function restoreRawEntries2(ctxDir, entries) {
|
|
64803
65480
|
for (const entry of entries) {
|
|
64804
|
-
const fromAbs =
|
|
64805
|
-
const toAbs =
|
|
65481
|
+
const fromAbs = join42(ctxDir, entry.to);
|
|
65482
|
+
const toAbs = join42(ctxDir, entry.from);
|
|
64806
65483
|
if (!existsSync34(fromAbs))
|
|
64807
65484
|
continue;
|
|
64808
|
-
await mkdir19(
|
|
65485
|
+
await mkdir19(dirname15(toAbs), { recursive: true });
|
|
64809
65486
|
await cp3(fromAbs, toAbs, { recursive: entry.kind === "dir", force: true });
|
|
64810
65487
|
}
|
|
64811
65488
|
}
|
|
64812
65489
|
async function collectPotentialSideEffectFiles(ctxDir) {
|
|
64813
65490
|
const paths = new Set([
|
|
64814
|
-
|
|
64815
|
-
|
|
64816
|
-
|
|
64817
|
-
|
|
64818
|
-
|
|
65491
|
+
join42(ctxDir, "raw", "_sources.yaml"),
|
|
65492
|
+
join42(ctxDir, "knowledge", "changelog.md"),
|
|
65493
|
+
join42(ctxDir, "knowledge", "_index.md"),
|
|
65494
|
+
join42(ctxDir, "knowledge", "_edges.yaml"),
|
|
65495
|
+
join42(ctxDir, "knowledge", "_external.yaml")
|
|
64819
65496
|
]);
|
|
64820
|
-
const entityRoot =
|
|
65497
|
+
const entityRoot = join42(ctxDir, "knowledge", "entity");
|
|
64821
65498
|
let entries = [];
|
|
64822
65499
|
try {
|
|
64823
65500
|
entries = await readdir15(entityRoot, { withFileTypes: true });
|
|
@@ -64829,8 +65506,8 @@ async function collectPotentialSideEffectFiles(ctxDir) {
|
|
|
64829
65506
|
for (const entry of entries) {
|
|
64830
65507
|
if (!entry.isDirectory())
|
|
64831
65508
|
continue;
|
|
64832
|
-
paths.add(
|
|
64833
|
-
paths.add(
|
|
65509
|
+
paths.add(join42(entityRoot, entry.name, "_edges.yaml"));
|
|
65510
|
+
paths.add(join42(entityRoot, entry.name, "_external.yaml"));
|
|
64834
65511
|
}
|
|
64835
65512
|
return paths;
|
|
64836
65513
|
}
|
|
@@ -64838,7 +65515,7 @@ async function restoreCodeDropFailure(input) {
|
|
|
64838
65515
|
for (const snapshot of input.snapshots)
|
|
64839
65516
|
await restoreTextFile2(snapshot);
|
|
64840
65517
|
await restoreRawEntries2(input.ctxDir, input.rawEntries);
|
|
64841
|
-
await rm12(
|
|
65518
|
+
await rm12(join42(input.ctxDir, input.archivePath), { recursive: true, force: true });
|
|
64842
65519
|
}
|
|
64843
65520
|
async function applyCodeSourceDropPlan(input) {
|
|
64844
65521
|
const plan = parseDropPlan(input.plan);
|
|
@@ -64886,7 +65563,7 @@ async function applyCodeSourceDropPlan(input) {
|
|
|
64886
65563
|
const sideEffectFiles = await collectPotentialSideEffectFiles(input.ctxDir);
|
|
64887
65564
|
const snapshotPaths = new Set([...touchedFiles, ...deletedFiles, ...sideEffectFiles]);
|
|
64888
65565
|
const snapshots = await Promise.all([...snapshotPaths].map((path9) => snapshotTextFile2(path9)));
|
|
64889
|
-
const knowledgeRoot4 =
|
|
65566
|
+
const knowledgeRoot4 = join42(input.ctxDir, "knowledge");
|
|
64890
65567
|
const touchedKnowledgeFiles = [...snapshotPaths].filter((path9) => path9.startsWith(knowledgeRoot4) && existsSync34(path9));
|
|
64891
65568
|
const plannedArchivePath = sourceArchiveRelPath(source2.id, droppedAt);
|
|
64892
65569
|
let archive;
|
|
@@ -64899,6 +65576,8 @@ async function applyCodeSourceDropPlan(input) {
|
|
|
64899
65576
|
touchedKnowledgeFiles,
|
|
64900
65577
|
plan
|
|
64901
65578
|
});
|
|
65579
|
+
await replaceCodeGraphEdges(input.ctxDir, `code:${codeSourceSlug(source2)}`, []);
|
|
65580
|
+
await replaceExternalDepsForOwners(input.ctxDir, [], owners);
|
|
64902
65581
|
const renderContext = touchedFiles.size > 0 ? await buildRenderWorkspaceContext(input.ctxDir, files.filter((file) => !deletedFiles.has(file.filePath))) : undefined;
|
|
64903
65582
|
for (const filePath of touchedFiles) {
|
|
64904
65583
|
if (deletedFiles.has(filePath))
|
|
@@ -64909,8 +65588,6 @@ async function applyCodeSourceDropPlan(input) {
|
|
|
64909
65588
|
}
|
|
64910
65589
|
for (const filePath of deletedFiles)
|
|
64911
65590
|
await rm12(filePath, { force: true });
|
|
64912
|
-
await replaceCodeGraphEdges(input.ctxDir, `code:${codeSourceSlug(source2)}`, []);
|
|
64913
|
-
await replaceExternalDepsForOwners(input.ctxDir, [], owners);
|
|
64914
65591
|
await mdriveWorkspaceRebuildIndex({ ctxDir: input.ctxDir });
|
|
64915
65592
|
await removeActiveRawEntries(input.ctxDir, archive.rawEntries);
|
|
64916
65593
|
const dropped = await markSourceDropped({
|
|
@@ -64967,8 +65644,8 @@ init_exitCode();
|
|
|
64967
65644
|
init_workflowPayloadStore();
|
|
64968
65645
|
var import_yaml24 = __toESM(require_dist(), 1);
|
|
64969
65646
|
import { createHash as createHash7 } from "node:crypto";
|
|
64970
|
-
import { mkdir as mkdir20, readdir as readdir16, readFile as
|
|
64971
|
-
import { join as
|
|
65647
|
+
import { mkdir as mkdir20, readdir as readdir16, readFile as readFile47, rm as rm13, writeFile as writeFile15 } from "node:fs/promises";
|
|
65648
|
+
import { join as join44 } from "node:path";
|
|
64972
65649
|
var IMMUTABLE_REVIEW_SCHEMA_VERSION = "reconcile.review-artifact.v1";
|
|
64973
65650
|
function shortHash2(value) {
|
|
64974
65651
|
return createHash7("sha256").update(value).digest("hex").slice(0, 16);
|
|
@@ -64977,7 +65654,7 @@ function deriveReviewId(input) {
|
|
|
64977
65654
|
return `rv_${shortHash2(`${input.scopeId}\x00${input.prepareDigest}\x00${input.decisionsDigest}`)}`;
|
|
64978
65655
|
}
|
|
64979
65656
|
function reviewArtifactPath(input) {
|
|
64980
|
-
return
|
|
65657
|
+
return join44(workflowScopePath(input.ctxDir, input.workflowId, input.scopeId), `review.${input.reviewId}.yaml`);
|
|
64981
65658
|
}
|
|
64982
65659
|
function isRecord13(value) {
|
|
64983
65660
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -65032,12 +65709,12 @@ async function removeSupersededReviewArtifacts(scopeDir, keepFileName) {
|
|
|
65032
65709
|
return;
|
|
65033
65710
|
throw err2;
|
|
65034
65711
|
}
|
|
65035
|
-
await Promise.all(entries.filter((entry) => /^review\.rv_[a-f0-9]{16}\.ya?ml$/u.test(entry) && entry !== keepFileName).map((entry) => rm13(
|
|
65712
|
+
await Promise.all(entries.filter((entry) => /^review\.rv_[a-f0-9]{16}\.ya?ml$/u.test(entry) && entry !== keepFileName).map((entry) => rm13(join44(scopeDir, entry), { force: true })));
|
|
65036
65713
|
}
|
|
65037
65714
|
async function readArtifactFile(path9) {
|
|
65038
65715
|
let parsed;
|
|
65039
65716
|
try {
|
|
65040
|
-
parsed = import_yaml24.default.parse(await
|
|
65717
|
+
parsed = import_yaml24.default.parse(await readFile47(path9, "utf8"));
|
|
65041
65718
|
} catch {
|
|
65042
65719
|
return null;
|
|
65043
65720
|
}
|
|
@@ -65056,7 +65733,7 @@ async function readReadyReviewArtifacts(input) {
|
|
|
65056
65733
|
}
|
|
65057
65734
|
const out2 = [];
|
|
65058
65735
|
for (const entry of entries.filter((name) => /^review\.rv_[a-f0-9]{16}\.ya?ml$/u.test(name)).sort()) {
|
|
65059
|
-
const path9 =
|
|
65736
|
+
const path9 = join44(dir, entry);
|
|
65060
65737
|
const artifact = await readArtifactFile(path9);
|
|
65061
65738
|
if (artifact !== null && artifact.ready_to_apply === true)
|
|
65062
65739
|
out2.push({ artifact, path: path9 });
|
|
@@ -65091,7 +65768,7 @@ function dropPlanOutputPath(ctxDir, plan, format) {
|
|
|
65091
65768
|
return workflowOutputPath(ctxDir, "drop", `drop.${safeFilePart(plan.source_id)}.plan.${format === "yaml" ? "yaml" : "json"}`);
|
|
65092
65769
|
}
|
|
65093
65770
|
async function saveTextFile(path9, body2) {
|
|
65094
|
-
await mkdir21(
|
|
65771
|
+
await mkdir21(dirname16(path9), { recursive: true });
|
|
65095
65772
|
await writeFile16(path9, body2, "utf8");
|
|
65096
65773
|
}
|
|
65097
65774
|
function assertDropPlanSaveFlags(flags2) {
|
|
@@ -65108,7 +65785,7 @@ async function saveDropPlanOutputs(input) {
|
|
|
65108
65785
|
await saveTextFile(path9, input.output);
|
|
65109
65786
|
saved.push(path9);
|
|
65110
65787
|
} else if (typeof input.saveOutput === "string") {
|
|
65111
|
-
const path9 =
|
|
65788
|
+
const path9 = resolve11(input.saveOutput);
|
|
65112
65789
|
await saveTextFile(path9, input.output);
|
|
65113
65790
|
saved.push(path9);
|
|
65114
65791
|
}
|
|
@@ -65513,8 +66190,8 @@ init_temporal();
|
|
|
65513
66190
|
init_knowledge();
|
|
65514
66191
|
init_archive();
|
|
65515
66192
|
import { existsSync as existsSync39 } from "node:fs";
|
|
65516
|
-
import { readdir as readdir18, readFile as
|
|
65517
|
-
import { dirname as
|
|
66193
|
+
import { readdir as readdir18, readFile as readFile53, stat as stat3 } from "node:fs/promises";
|
|
66194
|
+
import { dirname as dirname19, join as join49, resolve as resolve12 } from "node:path";
|
|
65518
66195
|
|
|
65519
66196
|
// src/reconcile/status.ts
|
|
65520
66197
|
init_workspaceCache();
|
|
@@ -65527,8 +66204,8 @@ init_noteStatus();
|
|
|
65527
66204
|
init_ledger();
|
|
65528
66205
|
var import_yaml26 = __toESM(require_dist(), 1);
|
|
65529
66206
|
import { existsSync as existsSync35 } from "node:fs";
|
|
65530
|
-
import { readdir as readdir17, readFile as
|
|
65531
|
-
import { join as
|
|
66207
|
+
import { readdir as readdir17, readFile as readFile48 } from "node:fs/promises";
|
|
66208
|
+
import { join as join45 } from "node:path";
|
|
65532
66209
|
|
|
65533
66210
|
// src/reconcile/staleDecisions.ts
|
|
65534
66211
|
init_sectionFingerprints();
|
|
@@ -65583,11 +66260,11 @@ async function findStaleSemanticDecisions(ctxDir) {
|
|
|
65583
66260
|
latestByTarget.set(`${record.target.node}\x00${record.target.section_id}`, record);
|
|
65584
66261
|
}
|
|
65585
66262
|
const stale = [];
|
|
65586
|
-
for (const [
|
|
66263
|
+
for (const [targetKey2, record] of latestByTarget) {
|
|
65587
66264
|
const target = record.target;
|
|
65588
66265
|
if (!target?.node || !target.section_id)
|
|
65589
66266
|
continue;
|
|
65590
|
-
const currentTargetHash = currentTargetHashes.get(
|
|
66267
|
+
const currentTargetHash = currentTargetHashes.get(targetKey2) ?? null;
|
|
65591
66268
|
if (currentTargetHash === null) {
|
|
65592
66269
|
continue;
|
|
65593
66270
|
}
|
|
@@ -65602,7 +66279,7 @@ async function findStaleSemanticDecisions(ctxDir) {
|
|
|
65602
66279
|
});
|
|
65603
66280
|
if (reuse.kind !== "stale")
|
|
65604
66281
|
continue;
|
|
65605
|
-
if (await isDeterministicHeadingHousekeeping(ctxDir, record, currentSections.get(
|
|
66282
|
+
if (await isDeterministicHeadingHousekeeping(ctxDir, record, currentSections.get(targetKey2)))
|
|
65606
66283
|
continue;
|
|
65607
66284
|
stale.push({
|
|
65608
66285
|
id: record.id,
|
|
@@ -65621,10 +66298,10 @@ function isRecord14(value) {
|
|
|
65621
66298
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
65622
66299
|
}
|
|
65623
66300
|
async function parseLastCompile(ctxDir) {
|
|
65624
|
-
const path9 =
|
|
66301
|
+
const path9 = join45(ctxDir, "knowledge", "changelog.md");
|
|
65625
66302
|
if (!existsSync35(path9))
|
|
65626
66303
|
return null;
|
|
65627
|
-
const lines = (await
|
|
66304
|
+
const lines = (await readFile48(path9, "utf8")).split(`
|
|
65628
66305
|
`).filter((line) => line.includes("[compile]"));
|
|
65629
66306
|
for (let index2 = lines.length - 1;index2 >= 0; index2 -= 1) {
|
|
65630
66307
|
const stamp = /@\s*([0-9]{4}-[0-9]{2}-[0-9]{2}(?:T[0-9:.+-]+Z?)?)/.exec(lines[index2] ?? "")?.[1];
|
|
@@ -65644,13 +66321,13 @@ async function refreshedSourcesPendingCompile(ctxDir) {
|
|
|
65644
66321
|
}).map((source2) => source2.id).sort();
|
|
65645
66322
|
}
|
|
65646
66323
|
async function pendingQuestionFiles(ctxDir) {
|
|
65647
|
-
const outputDir =
|
|
66324
|
+
const outputDir = join45(ctxDir, "output");
|
|
65648
66325
|
if (!existsSync35(outputDir))
|
|
65649
66326
|
return { count: 0, files: [] };
|
|
65650
66327
|
const files = [];
|
|
65651
66328
|
let count = 0;
|
|
65652
66329
|
const visit2 = async (relDir) => {
|
|
65653
|
-
const absDir =
|
|
66330
|
+
const absDir = join45(outputDir, relDir);
|
|
65654
66331
|
for (const entry of await readdir17(absDir, { withFileTypes: true })) {
|
|
65655
66332
|
const relPath = relDir.length > 0 ? `${relDir}/${entry.name}` : entry.name;
|
|
65656
66333
|
if (entry.isDirectory()) {
|
|
@@ -65662,7 +66339,7 @@ async function pendingQuestionFiles(ctxDir) {
|
|
|
65662
66339
|
if (relDir.length === 0 || !entry.isFile() || !SEMANTIC_REVIEW_OUTPUT_FILE_RE.test(entry.name))
|
|
65663
66340
|
continue;
|
|
65664
66341
|
const rel = `output/${relPath}`;
|
|
65665
|
-
const raw = await
|
|
66342
|
+
const raw = await readFile48(join45(outputDir, relPath), "utf8");
|
|
65666
66343
|
let parsed;
|
|
65667
66344
|
try {
|
|
65668
66345
|
parsed = entry.name.endsWith(".json") ? JSON.parse(raw) : import_yaml26.default.parse(raw);
|
|
@@ -65940,11 +66617,11 @@ init_errors();
|
|
|
65940
66617
|
init_exitCode();
|
|
65941
66618
|
var import_yaml27 = __toESM(require_dist(), 1);
|
|
65942
66619
|
import { existsSync as existsSync38 } from "node:fs";
|
|
65943
|
-
import { mkdir as mkdir23, readFile as
|
|
65944
|
-
import { dirname as
|
|
66620
|
+
import { mkdir as mkdir23, readFile as readFile52 } from "node:fs/promises";
|
|
66621
|
+
import { dirname as dirname18, join as join48 } from "node:path";
|
|
65945
66622
|
var ALIGN_DECISION_LEDGER_SCHEMA_VERSION = "decisions.align.v1";
|
|
65946
66623
|
function alignDecisionLedgerPath(ctxDir) {
|
|
65947
|
-
return
|
|
66624
|
+
return join48(ctxDir, "decisions", "align.yaml");
|
|
65948
66625
|
}
|
|
65949
66626
|
function isRecord16(value) {
|
|
65950
66627
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -66006,7 +66683,7 @@ async function readAlignDecisionLedger(ctxDir) {
|
|
|
66006
66683
|
const path9 = alignDecisionLedgerPath(ctxDir);
|
|
66007
66684
|
if (!existsSync38(path9))
|
|
66008
66685
|
return { schema_version: ALIGN_DECISION_LEDGER_SCHEMA_VERSION, decisions: [] };
|
|
66009
|
-
return parseLedger(import_yaml27.default.parse(await
|
|
66686
|
+
return parseLedger(import_yaml27.default.parse(await readFile52(path9, "utf8")));
|
|
66010
66687
|
}
|
|
66011
66688
|
function recordSupersedeKey(record) {
|
|
66012
66689
|
return `${record.scope}\x00${record.node_slug}`;
|
|
@@ -66056,7 +66733,7 @@ async function appendAlignDecisionLedger(input) {
|
|
|
66056
66733
|
]
|
|
66057
66734
|
};
|
|
66058
66735
|
const path9 = alignDecisionLedgerPath(input.ctxDir);
|
|
66059
|
-
await mkdir23(
|
|
66736
|
+
await mkdir23(dirname18(path9), { recursive: true });
|
|
66060
66737
|
await atomicWriteFile(path9, import_yaml27.default.stringify(next));
|
|
66061
66738
|
return next;
|
|
66062
66739
|
}
|
|
@@ -66116,7 +66793,7 @@ async function collectKnowledgeFiles(dir, nested) {
|
|
|
66116
66793
|
for (const e of entries) {
|
|
66117
66794
|
if (e.name === "_index.md")
|
|
66118
66795
|
continue;
|
|
66119
|
-
const full =
|
|
66796
|
+
const full = join49(dir, e.name);
|
|
66120
66797
|
if (e.isFile() && e.name.endsWith(".md")) {
|
|
66121
66798
|
files.push(full);
|
|
66122
66799
|
} else if (e.isDirectory() && nested) {
|
|
@@ -66132,7 +66809,7 @@ async function hasLikelySourceCode(root2, depth = 0) {
|
|
|
66132
66809
|
for (const entry of entries) {
|
|
66133
66810
|
if (entry.name.startsWith(".") && entry.name !== ".github")
|
|
66134
66811
|
continue;
|
|
66135
|
-
const full =
|
|
66812
|
+
const full = join49(root2, entry.name);
|
|
66136
66813
|
if (entry.isFile() && SOURCE_CODE_EXT_RE.test(entry.name))
|
|
66137
66814
|
return true;
|
|
66138
66815
|
if (entry.isDirectory() && !SOURCE_SCAN_SKIP_DIRS.has(entry.name)) {
|
|
@@ -66163,9 +66840,9 @@ function isKnowledgeType(v) {
|
|
|
66163
66840
|
return KNOWLEDGE_TYPES.includes(v);
|
|
66164
66841
|
}
|
|
66165
66842
|
async function parseLastCompileTime(ctxDir) {
|
|
66166
|
-
const path9 =
|
|
66843
|
+
const path9 = join49(ctxDir, "knowledge", "changelog.md");
|
|
66167
66844
|
if (existsSync39(path9)) {
|
|
66168
|
-
const body2 = await
|
|
66845
|
+
const body2 = await readFile53(path9, "utf8");
|
|
66169
66846
|
const compileLines = body2.split(`
|
|
66170
66847
|
`).filter((line) => line.includes("[compile]"));
|
|
66171
66848
|
for (let index2 = compileLines.length - 1;index2 >= 0; index2 -= 1) {
|
|
@@ -66228,13 +66905,13 @@ function latestCaptureFromSources(file) {
|
|
|
66228
66905
|
return { capture, drop, hasActiveRaw, hasAspectCode, totalSnapshots };
|
|
66229
66906
|
}
|
|
66230
66907
|
function detectGitRepo(cwd, ctxDir) {
|
|
66231
|
-
const roots = [
|
|
66908
|
+
const roots = [resolve12(cwd), workspaceLocationFromCtxDir(ctxDir).workspaceRoot];
|
|
66232
66909
|
for (const start2 of roots) {
|
|
66233
66910
|
let dir = start2;
|
|
66234
66911
|
while (true) {
|
|
66235
|
-
if (existsSync39(
|
|
66912
|
+
if (existsSync39(join49(dir, ".git")))
|
|
66236
66913
|
return true;
|
|
66237
|
-
const parent =
|
|
66914
|
+
const parent = dirname19(dir);
|
|
66238
66915
|
if (parent === dir)
|
|
66239
66916
|
break;
|
|
66240
66917
|
dir = parent;
|
|
@@ -66261,9 +66938,9 @@ async function collectWorkspaceStats(input) {
|
|
|
66261
66938
|
let latestKnowledgeUpdated = null;
|
|
66262
66939
|
let totalSections = 0;
|
|
66263
66940
|
for (const root2 of KNOWLEDGE_ROOTS) {
|
|
66264
|
-
const files = await collectKnowledgeFiles(
|
|
66941
|
+
const files = await collectKnowledgeFiles(join49(ctxDir, "knowledge", root2.dir), root2.nested);
|
|
66265
66942
|
for (const path9 of files) {
|
|
66266
|
-
const text5 = await
|
|
66943
|
+
const text5 = await readFile53(path9, "utf8");
|
|
66267
66944
|
const typeField = parseFrontmatterField(text5, "type");
|
|
66268
66945
|
if (!typeField || !isKnowledgeType(typeField))
|
|
66269
66946
|
continue;
|
|
@@ -66757,12 +67434,12 @@ init_cliFeedback();
|
|
|
66757
67434
|
import { existsSync as existsSync42 } from "node:fs";
|
|
66758
67435
|
import { readdir as readdir19, rm as rm15 } from "node:fs/promises";
|
|
66759
67436
|
import { homedir as homedir2 } from "node:os";
|
|
66760
|
-
import { join as
|
|
67437
|
+
import { join as join52 } from "node:path";
|
|
66761
67438
|
|
|
66762
67439
|
// src/commands/doctorWorkspace.ts
|
|
66763
67440
|
import { existsSync as existsSync41 } from "node:fs";
|
|
66764
|
-
import { readFile as
|
|
66765
|
-
import { join as
|
|
67441
|
+
import { readFile as readFile55 } from "node:fs/promises";
|
|
67442
|
+
import { join as join51 } from "node:path";
|
|
66766
67443
|
init_cliFeedback();
|
|
66767
67444
|
init_verify();
|
|
66768
67445
|
|
|
@@ -66776,8 +67453,8 @@ init_sourceSupport();
|
|
|
66776
67453
|
init_evidence();
|
|
66777
67454
|
init_ledger();
|
|
66778
67455
|
import { existsSync as existsSync40 } from "node:fs";
|
|
66779
|
-
import { readFile as
|
|
66780
|
-
import { join as
|
|
67456
|
+
import { readFile as readFile54 } from "node:fs/promises";
|
|
67457
|
+
import { join as join50 } from "node:path";
|
|
66781
67458
|
function numbersIn2(text5) {
|
|
66782
67459
|
return text5.match(/\b\d+(?:\.\d+)*\b/gu) ?? [];
|
|
66783
67460
|
}
|
|
@@ -66816,10 +67493,10 @@ async function latestSourceRefText(input) {
|
|
|
66816
67493
|
const snapshot = findSnapshotByHashPrefix(source2.snapshots, parsedSource.snapshotHash) ?? selectLatestSnapshot(source2.snapshots);
|
|
66817
67494
|
if (!snapshot?.file)
|
|
66818
67495
|
return null;
|
|
66819
|
-
const fullPath =
|
|
67496
|
+
const fullPath = join50(input.ctxDir, snapshot.file);
|
|
66820
67497
|
if (!existsSync40(fullPath))
|
|
66821
67498
|
return null;
|
|
66822
|
-
const raw = await
|
|
67499
|
+
const raw = await readFile54(fullPath, "utf8");
|
|
66823
67500
|
if (!sourceRefRangeOverlapsEvidenceBlock(raw, parsed.lineStart, parsed.lineEnd))
|
|
66824
67501
|
return null;
|
|
66825
67502
|
return { sourceId, text: sourceRefRangeText(raw, parsed.lineStart, parsed.lineEnd) };
|
|
@@ -66927,7 +67604,7 @@ init_cache();
|
|
|
66927
67604
|
init_workspaceLayout();
|
|
66928
67605
|
import { constants as constants3 } from "node:fs";
|
|
66929
67606
|
import { access as access2, stat as stat4 } from "node:fs/promises";
|
|
66930
|
-
import { dirname as
|
|
67607
|
+
import { dirname as dirname20 } from "node:path";
|
|
66931
67608
|
async function assertRetrievalCacheWritable(ctxDir) {
|
|
66932
67609
|
const workspaceRoot = workspaceRootFromCtxDir(ctxDir);
|
|
66933
67610
|
const paths = await getIncrementalCachePaths({ workspaceRoot });
|
|
@@ -66953,7 +67630,7 @@ async function nearestExistingPath(target) {
|
|
|
66953
67630
|
const code3 = typeof err2 === "object" && err2 !== null && "code" in err2 ? String(err2.code) : "";
|
|
66954
67631
|
if (code3 !== "ENOENT")
|
|
66955
67632
|
return current;
|
|
66956
|
-
const parent =
|
|
67633
|
+
const parent = dirname20(current);
|
|
66957
67634
|
if (parent === current)
|
|
66958
67635
|
return current;
|
|
66959
67636
|
current = parent;
|
|
@@ -67315,11 +67992,11 @@ function notApplicableIssue2(path9, message) {
|
|
|
67315
67992
|
};
|
|
67316
67993
|
}
|
|
67317
67994
|
async function hasCompileEntry(ctxDir) {
|
|
67318
|
-
const changelogPath2 =
|
|
67995
|
+
const changelogPath2 = join51(ctxDir, "knowledge", "changelog.md");
|
|
67319
67996
|
if (!existsSync41(changelogPath2))
|
|
67320
67997
|
return false;
|
|
67321
67998
|
try {
|
|
67322
|
-
return (await
|
|
67999
|
+
return (await readFile55(changelogPath2, "utf8")).split(`
|
|
67323
68000
|
`).some((line) => line.includes("[compile]"));
|
|
67324
68001
|
} catch {
|
|
67325
68002
|
return false;
|
|
@@ -67699,19 +68376,19 @@ async function cleanClaudePluginCache(opts = {}) {
|
|
|
67699
68376
|
for (const mp of marketplaces) {
|
|
67700
68377
|
if (!mp.isDirectory())
|
|
67701
68378
|
continue;
|
|
67702
|
-
const mpDir =
|
|
68379
|
+
const mpDir = join52(cacheRoot, mp.name);
|
|
67703
68380
|
const plugins = await readdir19(mpDir, { withFileTypes: true });
|
|
67704
68381
|
for (const pl of plugins) {
|
|
67705
68382
|
if (!pl.isDirectory())
|
|
67706
68383
|
continue;
|
|
67707
|
-
const plDir =
|
|
68384
|
+
const plDir = join52(mpDir, pl.name);
|
|
67708
68385
|
const versions = await readdir19(plDir, { withFileTypes: true });
|
|
67709
68386
|
for (const ver of versions) {
|
|
67710
68387
|
if (!ver.isDirectory())
|
|
67711
68388
|
continue;
|
|
67712
68389
|
scanned += 1;
|
|
67713
|
-
const verDir =
|
|
67714
|
-
const markerPath =
|
|
68390
|
+
const verDir = join52(plDir, ver.name);
|
|
68391
|
+
const markerPath = join52(verDir, ORPHAN_MARKER);
|
|
67715
68392
|
if (!existsSync42(markerPath))
|
|
67716
68393
|
continue;
|
|
67717
68394
|
const label = `${mp.name}/${pl.name}/${ver.name}`;
|
|
@@ -67743,7 +68420,7 @@ function resolveClaudePluginCacheRoot(opts) {
|
|
|
67743
68420
|
if (explicitRoot)
|
|
67744
68421
|
return explicitRoot;
|
|
67745
68422
|
const home = opts.home ?? process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV] ?? homedir2();
|
|
67746
|
-
return
|
|
68423
|
+
return join52(home, ".claude", "plugins", "cache");
|
|
67747
68424
|
}
|
|
67748
68425
|
async function isEmptyDir(dir) {
|
|
67749
68426
|
try {
|
|
@@ -67775,7 +68452,7 @@ init_errors();
|
|
|
67775
68452
|
init_cliFeedback();
|
|
67776
68453
|
import { existsSync as existsSync43 } from "node:fs";
|
|
67777
68454
|
import { readdir as readdir20, rm as rm16 } from "node:fs/promises";
|
|
67778
|
-
import { join as
|
|
68455
|
+
import { join as join53 } from "node:path";
|
|
67779
68456
|
init_cache();
|
|
67780
68457
|
init_workspaceCache();
|
|
67781
68458
|
init_cache2();
|
|
@@ -67930,7 +68607,7 @@ async function countFiles2(dir) {
|
|
|
67930
68607
|
return 0;
|
|
67931
68608
|
let count = 0;
|
|
67932
68609
|
for (const entry of await readdir20(dir, { withFileTypes: true })) {
|
|
67933
|
-
const full =
|
|
68610
|
+
const full = join53(dir, entry.name);
|
|
67934
68611
|
count += entry.isDirectory() ? await countFiles2(full) : 1;
|
|
67935
68612
|
}
|
|
67936
68613
|
return count;
|
|
@@ -67946,7 +68623,7 @@ async function cleanAllRetrievalCache() {
|
|
|
67946
68623
|
}
|
|
67947
68624
|
async function inspectAllRetrievalCache() {
|
|
67948
68625
|
const cacheHome = resolveCacheHome();
|
|
67949
|
-
const cacheRoot =
|
|
68626
|
+
const cacheRoot = join53(cacheHome, "retrieval");
|
|
67950
68627
|
const projectIds = existsSync43(cacheRoot) ? (await readdir20(cacheRoot, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort() : [];
|
|
67951
68628
|
const files = await countFiles2(cacheRoot);
|
|
67952
68629
|
return { cacheRoot, projects: projectIds.length, files, projectIds };
|
|
@@ -70561,8 +71238,8 @@ function weakSupportWarning(input) {
|
|
|
70561
71238
|
item_id: input.decision.item_id,
|
|
70562
71239
|
severity: "warning",
|
|
70563
71240
|
code: "weak-source-support",
|
|
70564
|
-
message: `proposed keep_separate
|
|
70565
|
-
next_action: "Review the cited evidence if the content looks surprising; missing hard facts
|
|
71241
|
+
message: `proposed keep_separate has low lexical source_support but no missing hard facts: ${formatSupportDiagnostic(input.diagnostic)}.`,
|
|
71242
|
+
next_action: "Review the cited evidence if the content looks surprising; semantic judge/user/delegated acceptance may proceed, but missing hard facts remain errors."
|
|
70566
71243
|
};
|
|
70567
71244
|
}
|
|
70568
71245
|
function supportConfirmationQuestion(input) {
|
|
@@ -70652,6 +71329,9 @@ function questionPrompt(decision) {
|
|
|
70652
71329
|
return "Please confirm how this knowledge should be handled.";
|
|
70653
71330
|
return "Please confirm the proposed semantic reconciliation.";
|
|
70654
71331
|
}
|
|
71332
|
+
function judgeAcceptsLowLexicalSupport(input) {
|
|
71333
|
+
return input.decision.action === "keep_separate" && input.decision.judge_support_verdict === "supported" && input.changedSourceRef === false && input.diagnostic !== null && input.diagnostic.missingHardTerms.length === 0 && (input.diagnostic.verdict === "weak" || input.diagnostic.verdict === "unsupported");
|
|
71334
|
+
}
|
|
70655
71335
|
function questionFromDecision(decision, index2, summary) {
|
|
70656
71336
|
return {
|
|
70657
71337
|
question_id: `q-${String(index2 + 1).padStart(3, "0")}`,
|
|
@@ -70957,11 +71637,16 @@ function reviewSemanticDecisions(input) {
|
|
|
70957
71637
|
for (const prior of priorResults) {
|
|
70958
71638
|
const diagnostic = supportDiagnosticFromItem({ decision: prior.decision, item: prior.item });
|
|
70959
71639
|
const changedSourceRef = sourceRefChangedFromPreparedSupport({ decision: prior.decision, item: prior.item });
|
|
71640
|
+
const judgeAcceptedLowLexical = judgeAcceptsLowLexicalSupport({
|
|
71641
|
+
decision: prior.decision,
|
|
71642
|
+
diagnostic,
|
|
71643
|
+
changedSourceRef
|
|
71644
|
+
});
|
|
70960
71645
|
const weakAllowed = allowsWeakSourceSupport({
|
|
70961
71646
|
decision: prior.decision,
|
|
70962
71647
|
allowDelegatedDecisions: input.allowDelegatedDecisions
|
|
70963
|
-
});
|
|
70964
|
-
if (diagnostic
|
|
71648
|
+
}) || judgeAcceptedLowLexical;
|
|
71649
|
+
if (diagnostic !== null && (diagnostic.verdict === "weak" || judgeAcceptedLowLexical) && prior.decision.action === "keep_separate" && !changedSourceRef && weakAllowed) {
|
|
70965
71650
|
issues.push(weakSupportWarning({
|
|
70966
71651
|
decision: prior.decision,
|
|
70967
71652
|
diagnostic
|
|
@@ -71138,7 +71823,7 @@ init_ledger();
|
|
|
71138
71823
|
import { existsSync as existsSync51 } from "node:fs";
|
|
71139
71824
|
import { cp as cp4, mkdir as mkdir25, mkdtemp as mkdtemp2, rm as rm18 } from "node:fs/promises";
|
|
71140
71825
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
71141
|
-
import { dirname as
|
|
71826
|
+
import { dirname as dirname22, join as join62 } from "node:path";
|
|
71142
71827
|
|
|
71143
71828
|
// src/reconcile/applyPreflight.ts
|
|
71144
71829
|
init_sources();
|
|
@@ -71461,11 +72146,11 @@ async function propagateOmitCoverageSkips(input) {
|
|
|
71461
72146
|
}
|
|
71462
72147
|
}
|
|
71463
72148
|
async function createApplyRollbackSnapshot(ctxDir) {
|
|
71464
|
-
const tmpDir = await mkdtemp2(
|
|
71465
|
-
const knowledgePath2 =
|
|
72149
|
+
const tmpDir = await mkdtemp2(join62(tmpdir2(), "c4a-reconcile-apply-"));
|
|
72150
|
+
const knowledgePath2 = join62(ctxDir, "knowledge");
|
|
71466
72151
|
const ledgerPath = semanticLedgerPath2(ctxDir);
|
|
71467
|
-
const knowledgeBackup =
|
|
71468
|
-
const ledgerBackup =
|
|
72152
|
+
const knowledgeBackup = join62(tmpDir, "knowledge");
|
|
72153
|
+
const ledgerBackup = join62(tmpDir, "semantic.yaml");
|
|
71469
72154
|
const knowledgeExisted = existsSync51(knowledgePath2);
|
|
71470
72155
|
const ledgerExisted = existsSync51(ledgerPath);
|
|
71471
72156
|
if (knowledgeExisted)
|
|
@@ -71475,7 +72160,7 @@ async function createApplyRollbackSnapshot(ctxDir) {
|
|
|
71475
72160
|
return { ctxDir, tmpDir, knowledgeExisted, ledgerExisted, knowledgeBackup, ledgerBackup };
|
|
71476
72161
|
}
|
|
71477
72162
|
async function restoreApplyRollbackSnapshot(snapshot) {
|
|
71478
|
-
const knowledgePath2 =
|
|
72163
|
+
const knowledgePath2 = join62(snapshot.ctxDir, "knowledge");
|
|
71479
72164
|
if (snapshot.knowledgeExisted) {
|
|
71480
72165
|
await rm18(knowledgePath2, { recursive: true, force: true });
|
|
71481
72166
|
await cp4(snapshot.knowledgeBackup, knowledgePath2, { recursive: true });
|
|
@@ -71484,7 +72169,7 @@ async function restoreApplyRollbackSnapshot(snapshot) {
|
|
|
71484
72169
|
}
|
|
71485
72170
|
const ledgerPath = semanticLedgerPath2(snapshot.ctxDir);
|
|
71486
72171
|
if (snapshot.ledgerExisted) {
|
|
71487
|
-
await mkdir25(
|
|
72172
|
+
await mkdir25(dirname22(ledgerPath), { recursive: true });
|
|
71488
72173
|
await cp4(snapshot.ledgerBackup, ledgerPath);
|
|
71489
72174
|
} else {
|
|
71490
72175
|
await rm18(ledgerPath, { force: true });
|
|
@@ -71865,7 +72550,7 @@ init_compile();
|
|
|
71865
72550
|
init_cliFeedback();
|
|
71866
72551
|
init_errors();
|
|
71867
72552
|
var import_yaml32 = __toESM(require_dist(), 1);
|
|
71868
|
-
import { resolve as
|
|
72553
|
+
import { resolve as resolve14 } from "node:path";
|
|
71869
72554
|
init_structuredInput();
|
|
71870
72555
|
init_exitCode();
|
|
71871
72556
|
function isRecord28(value) {
|
|
@@ -71946,7 +72631,7 @@ function saveOutputPath(value, flag) {
|
|
|
71946
72631
|
flag
|
|
71947
72632
|
});
|
|
71948
72633
|
}
|
|
71949
|
-
return
|
|
72634
|
+
return resolve14(value);
|
|
71950
72635
|
}
|
|
71951
72636
|
function requireWorkspace2(ctxDir, command) {
|
|
71952
72637
|
if (!ctxDir) {
|
|
@@ -72338,7 +73023,7 @@ init_exitCode();
|
|
|
72338
73023
|
init_currentWorkflow();
|
|
72339
73024
|
init_workflowOutputPaths();
|
|
72340
73025
|
import { mkdir as mkdir26, writeFile as writeFile17 } from "node:fs/promises";
|
|
72341
|
-
import { dirname as
|
|
73026
|
+
import { dirname as dirname23 } from "node:path";
|
|
72342
73027
|
function familyForReconcileMode(mode) {
|
|
72343
73028
|
if (mode === "compile")
|
|
72344
73029
|
return "compile";
|
|
@@ -72442,14 +73127,14 @@ function reviewOutputFile(input) {
|
|
|
72442
73127
|
return workflowOutputPath(input.ctxDir, input.context.mode, `${input.context.mode}.review.${ext}`);
|
|
72443
73128
|
}
|
|
72444
73129
|
async function saveOutput(path9, body2) {
|
|
72445
|
-
await mkdir26(
|
|
73130
|
+
await mkdir26(dirname23(path9), { recursive: true });
|
|
72446
73131
|
await writeFile17(path9, body2, "utf8");
|
|
72447
73132
|
}
|
|
72448
73133
|
|
|
72449
73134
|
// src/commands/workflowCommandUtils.ts
|
|
72450
73135
|
var import_yaml33 = __toESM(require_dist(), 1);
|
|
72451
|
-
import { mkdir as mkdir27, readFile as
|
|
72452
|
-
import { dirname as
|
|
73136
|
+
import { mkdir as mkdir27, readFile as readFile63, writeFile as writeFile18 } from "node:fs/promises";
|
|
73137
|
+
import { dirname as dirname24 } from "node:path";
|
|
72453
73138
|
init_errors();
|
|
72454
73139
|
init_cliFeedback();
|
|
72455
73140
|
init_structuredInput();
|
|
@@ -72473,7 +73158,7 @@ function writeSchemaOutput(value, format) {
|
|
|
72473
73158
|
async function readStructuredInput2(path9) {
|
|
72474
73159
|
let raw;
|
|
72475
73160
|
try {
|
|
72476
|
-
raw = path9 === "-" ? await readStdinText() : await
|
|
73161
|
+
raw = path9 === "-" ? await readStdinText() : await readFile63(path9, "utf8");
|
|
72477
73162
|
} catch (error) {
|
|
72478
73163
|
if (error.code === "ENOENT") {
|
|
72479
73164
|
throw new ContextError(ExitCode.UserError, `file not found: ${path9}`, {
|
|
@@ -72488,7 +73173,7 @@ async function readStructuredInput2(path9) {
|
|
|
72488
73173
|
async function writeWorkflowPayload(input) {
|
|
72489
73174
|
assertWorkflowOutputFileName(input.fileName);
|
|
72490
73175
|
const outputPath = workflowOutputPathForFile(input.ctxDir, input.fileName);
|
|
72491
|
-
await mkdir27(
|
|
73176
|
+
await mkdir27(dirname24(outputPath), { recursive: true });
|
|
72492
73177
|
const body2 = input.format === "json" ? `${JSON.stringify(input.payload, null, 2)}
|
|
72493
73178
|
` : import_yaml33.default.stringify(input.payload);
|
|
72494
73179
|
await writeFile18(outputPath, body2, "utf8");
|
|
@@ -72953,7 +73638,7 @@ function renderReconcileApplyFeedbackBody(result) {
|
|
|
72953
73638
|
init_errors();
|
|
72954
73639
|
init_nodeRenderer();
|
|
72955
73640
|
var import_yaml34 = __toESM(require_dist(), 1);
|
|
72956
|
-
import { readFile as
|
|
73641
|
+
import { readFile as readFile66 } from "node:fs/promises";
|
|
72957
73642
|
init_knowledge();
|
|
72958
73643
|
init_exitCode();
|
|
72959
73644
|
init_edge2();
|
|
@@ -72962,8 +73647,8 @@ init_edge2();
|
|
|
72962
73647
|
init_knowledge();
|
|
72963
73648
|
init_nodeParser();
|
|
72964
73649
|
import { existsSync as existsSync52 } from "node:fs";
|
|
72965
|
-
import { readdir as readdir25, readFile as
|
|
72966
|
-
import { join as
|
|
73650
|
+
import { readdir as readdir25, readFile as readFile64 } from "node:fs/promises";
|
|
73651
|
+
import { join as join63 } from "node:path";
|
|
72967
73652
|
function collectGlossaryFromParsedTree(parsed, glossary, allowedTypes) {
|
|
72968
73653
|
const type = parsed.node.type;
|
|
72969
73654
|
if (allowedTypes.has(type)) {
|
|
@@ -72986,8 +73671,8 @@ function normalizeGlossaryTerm(value) {
|
|
|
72986
73671
|
return value.normalize("NFC").trim().toLowerCase();
|
|
72987
73672
|
}
|
|
72988
73673
|
function resolveKnowledgeRoot(path9) {
|
|
72989
|
-
if (existsSync52(
|
|
72990
|
-
return
|
|
73674
|
+
if (existsSync52(join63(path9, "knowledge"))) {
|
|
73675
|
+
return join63(path9, "knowledge");
|
|
72991
73676
|
}
|
|
72992
73677
|
return path9;
|
|
72993
73678
|
}
|
|
@@ -72995,7 +73680,7 @@ async function readGlossaryFiles(dir) {
|
|
|
72995
73680
|
if (!existsSync52(dir))
|
|
72996
73681
|
return [];
|
|
72997
73682
|
const entries = await readdir25(dir, { withFileTypes: true });
|
|
72998
|
-
return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".md") && entry.name !== "_index.md" && entry.name !== "changelog.md").map((entry) =>
|
|
73683
|
+
return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".md") && entry.name !== "_index.md" && entry.name !== "changelog.md").map((entry) => join63(dir, entry.name));
|
|
72999
73684
|
}
|
|
73000
73685
|
async function buildGlossary(path9, options = {}) {
|
|
73001
73686
|
const knowledgeRoot4 = resolveKnowledgeRoot(path9);
|
|
@@ -73003,9 +73688,9 @@ async function buildGlossary(path9, options = {}) {
|
|
|
73003
73688
|
const allowedTypes = new Set(targets);
|
|
73004
73689
|
const glossary = [];
|
|
73005
73690
|
for (const type of targets) {
|
|
73006
|
-
const files = await readGlossaryFiles(
|
|
73691
|
+
const files = await readGlossaryFiles(join63(knowledgeRoot4, type));
|
|
73007
73692
|
for (const file of files) {
|
|
73008
|
-
const parsed = parseNodeMarkdown(await
|
|
73693
|
+
const parsed = parseNodeMarkdown(await readFile64(file, "utf8"));
|
|
73009
73694
|
if (parsed.node.type !== type)
|
|
73010
73695
|
continue;
|
|
73011
73696
|
collectGlossaryFromParsedTree(parsed, glossary, allowedTypes);
|
|
@@ -73071,7 +73756,7 @@ init_query();
|
|
|
73071
73756
|
// src/commands/mdriveSection.ts
|
|
73072
73757
|
init_errors();
|
|
73073
73758
|
init_cliFeedback();
|
|
73074
|
-
import { readFile as
|
|
73759
|
+
import { readFile as readFile65 } from "node:fs/promises";
|
|
73075
73760
|
init_knowledge();
|
|
73076
73761
|
init_exitCode();
|
|
73077
73762
|
init_section();
|
|
@@ -73084,7 +73769,7 @@ async function readSourceRefText(options) {
|
|
|
73084
73769
|
category: ErrorCategory.UserInputInvalid
|
|
73085
73770
|
});
|
|
73086
73771
|
}
|
|
73087
|
-
return hasText ? String(options.text) : await
|
|
73772
|
+
return hasText ? String(options.text) : await readFile65(String(options.textFile), "utf8");
|
|
73088
73773
|
}
|
|
73089
73774
|
function registerMdriveSectionCommands(mdrive, deps) {
|
|
73090
73775
|
const section = mdrive.command("section").description("Section primitives");
|
|
@@ -73189,7 +73874,7 @@ function optionalChoice(value, choices, label) {
|
|
|
73189
73874
|
}
|
|
73190
73875
|
async function readStructuredInput3(path9, label = "--input") {
|
|
73191
73876
|
const value = requireString2(path9, label);
|
|
73192
|
-
const raw = value === "-" ? await readStdinText() : await
|
|
73877
|
+
const raw = value === "-" ? await readStdinText() : await readFile66(value, "utf8");
|
|
73193
73878
|
return import_yaml34.default.parse(raw);
|
|
73194
73879
|
}
|
|
73195
73880
|
function asRecord2(input, label) {
|
|
@@ -73618,8 +74303,8 @@ init_cliFeedback();
|
|
|
73618
74303
|
init_errors();
|
|
73619
74304
|
var import_yaml35 = __toESM(require_dist(), 1);
|
|
73620
74305
|
import { existsSync as existsSync53 } from "node:fs";
|
|
73621
|
-
import { lstat as lstat2, mkdir as mkdir28, readFile as
|
|
73622
|
-
import { dirname as
|
|
74306
|
+
import { lstat as lstat2, mkdir as mkdir28, readFile as readFile67, readdir as readdir26, realpath as realpath3, rename as rename6, writeFile as writeFile19 } from "node:fs/promises";
|
|
74307
|
+
import { dirname as dirname25, isAbsolute as isAbsolute7, join as join64, relative as relative15 } from "node:path";
|
|
73623
74308
|
init_workspaceLayout();
|
|
73624
74309
|
init_section();
|
|
73625
74310
|
init_exitCode();
|
|
@@ -73675,7 +74360,7 @@ function normalizeWorkspacePath(input) {
|
|
|
73675
74360
|
async function assertRealPathInside(ctxDir, targetPath) {
|
|
73676
74361
|
const rootReal = await realpath3(ctxDir);
|
|
73677
74362
|
const targetReal = await realpath3(targetPath);
|
|
73678
|
-
const rel =
|
|
74363
|
+
const rel = relative15(rootReal, targetReal);
|
|
73679
74364
|
if (rel === "" || !rel.startsWith("..") && !isAbsolute7(rel))
|
|
73680
74365
|
return;
|
|
73681
74366
|
throw new ContextError(ExitCode.UserError, "workspace path resolves outside the context data root", {
|
|
@@ -73683,7 +74368,7 @@ async function assertRealPathInside(ctxDir, targetPath) {
|
|
|
73683
74368
|
});
|
|
73684
74369
|
}
|
|
73685
74370
|
function resolveWorkspacePath(ctxDir, relPath) {
|
|
73686
|
-
return relPath === "." ? ctxDir :
|
|
74371
|
+
return relPath === "." ? ctxDir : join64(ctxDir, relPath);
|
|
73687
74372
|
}
|
|
73688
74373
|
function pathKind2(stats) {
|
|
73689
74374
|
if (stats.isFile())
|
|
@@ -73791,7 +74476,7 @@ async function searchWorkspace(input) {
|
|
|
73791
74476
|
if (hits.length >= input.maxResults || entry.kind !== "file")
|
|
73792
74477
|
continue;
|
|
73793
74478
|
const abs = resolveWorkspacePath(input.ctxDir, entry.path);
|
|
73794
|
-
const content3 = await
|
|
74479
|
+
const content3 = await readFile67(abs, "utf8");
|
|
73795
74480
|
if (!isProbablyText(content3))
|
|
73796
74481
|
continue;
|
|
73797
74482
|
const lines = content3.replace(/\r\n/g, `
|
|
@@ -73844,7 +74529,7 @@ async function writeWorkspaceFile(input) {
|
|
|
73844
74529
|
path: input.relPath
|
|
73845
74530
|
});
|
|
73846
74531
|
}
|
|
73847
|
-
await mkdir28(
|
|
74532
|
+
await mkdir28(dirname25(destination), { recursive: true });
|
|
73848
74533
|
const tmpPath = `${destination}.workspace-tmp-${process.pid}-${Date.now()}`;
|
|
73849
74534
|
await writeFile19(tmpPath, input.content, "utf8");
|
|
73850
74535
|
await assertRealPathInside(input.ctxDir, tmpPath);
|
|
@@ -73873,11 +74558,11 @@ async function readResolveRefText(ctxDir, options) {
|
|
|
73873
74558
|
return String(options.text);
|
|
73874
74559
|
const file = String(options.textFile);
|
|
73875
74560
|
try {
|
|
73876
|
-
return await
|
|
74561
|
+
return await readFile67(file, "utf8");
|
|
73877
74562
|
} catch (error) {
|
|
73878
74563
|
if (error.code !== "ENOENT" || isAbsolute7(file))
|
|
73879
74564
|
throw error;
|
|
73880
|
-
return await
|
|
74565
|
+
return await readFile67(resolveWorkspacePath(ctxDir, normalizeWorkspacePath(file)), "utf8");
|
|
73881
74566
|
}
|
|
73882
74567
|
}
|
|
73883
74568
|
function registerWorkspaceCommands(program2) {
|
|
@@ -73901,7 +74586,7 @@ function registerWorkspaceCommands(program2) {
|
|
|
73901
74586
|
path: relPath
|
|
73902
74587
|
});
|
|
73903
74588
|
}
|
|
73904
|
-
const content3 = await
|
|
74589
|
+
const content3 = await readFile67(absPath, "utf8");
|
|
73905
74590
|
const format = assertChoice3(options.format, READ_FORMATS, "--format");
|
|
73906
74591
|
if (format === "json") {
|
|
73907
74592
|
process.stdout.write(`${JSON.stringify({
|
|
@@ -74450,6 +75135,7 @@ function compactAlignSegments(record, value) {
|
|
|
74450
75135
|
}
|
|
74451
75136
|
var LARGE_WINDOW_BLOCK_THRESHOLD = 12;
|
|
74452
75137
|
var WINDOW_PREVIEW_LIMIT = 1;
|
|
75138
|
+
var FULL_TEXT_METADATA_TOKEN_BUFFER = 100;
|
|
74453
75139
|
var SOURCE_WINDOW_SELECTOR_RE = /^(src-[1-9]\d*):([1-9]\d*)$/u;
|
|
74454
75140
|
var ALIGN_BLOCKS_SELECTION_POLICY = {
|
|
74455
75141
|
id: "align-blocks-v1",
|
|
@@ -74484,6 +75170,16 @@ function blockLineRange(block) {
|
|
|
74484
75170
|
return;
|
|
74485
75171
|
return `L${block.line_start}-L${block.line_end}`;
|
|
74486
75172
|
}
|
|
75173
|
+
function normalizedPreviewBasis(value) {
|
|
75174
|
+
return value.replace(/\s+/g, " ").trim();
|
|
75175
|
+
}
|
|
75176
|
+
function blockBodyText(block) {
|
|
75177
|
+
return typeof block.body_text === "string" && block.body_text.length > 0 ? block.body_text : undefined;
|
|
75178
|
+
}
|
|
75179
|
+
function fullTextTokenEstimate(block, bodyText) {
|
|
75180
|
+
const storedEstimate = typeof block.token_estimate === "number" && Number.isFinite(block.token_estimate) ? Math.max(0, block.token_estimate) : 0;
|
|
75181
|
+
return Math.max(storedEstimate, estimateTokenCount(bodyText));
|
|
75182
|
+
}
|
|
74487
75183
|
function alignBlockRows(value) {
|
|
74488
75184
|
if (!isRecord29(value))
|
|
74489
75185
|
return [];
|
|
@@ -74492,6 +75188,8 @@ function alignBlockRows(value) {
|
|
|
74492
75188
|
const locator = isRecord29(block.stable_locator_hint) ? block.stable_locator_hint : {};
|
|
74493
75189
|
const ordinal = typeof locator.ordinal_in_source === "number" ? locator.ordinal_in_source : index2 + 1;
|
|
74494
75190
|
const textPreview = previewText2(block.text_preview, 220);
|
|
75191
|
+
const bodyText = blockBodyText(block);
|
|
75192
|
+
const textPreviewTruncated = bodyText !== undefined && textPreview !== undefined ? normalizedPreviewBasis(bodyText).length > textPreview.length : undefined;
|
|
74495
75193
|
const signals = blockSignalLabels(block, textPreview);
|
|
74496
75194
|
const lineRange2 = blockLineRange(block);
|
|
74497
75195
|
return {
|
|
@@ -74507,7 +75205,13 @@ function alignBlockRows(value) {
|
|
|
74507
75205
|
ordinal_in_source: ordinal,
|
|
74508
75206
|
signal_labels: signals,
|
|
74509
75207
|
signal_score: signals.length,
|
|
74510
|
-
...textPreview !== undefined ? { text_preview: textPreview } : {}
|
|
75208
|
+
...textPreview !== undefined ? { text_preview: textPreview } : {},
|
|
75209
|
+
...bodyText !== undefined ? {
|
|
75210
|
+
body_text: bodyText,
|
|
75211
|
+
full_text_available: true,
|
|
75212
|
+
full_text_token_estimate: fullTextTokenEstimate(block, bodyText),
|
|
75213
|
+
text_preview_truncated: textPreviewTruncated === true
|
|
75214
|
+
} : {}
|
|
74511
75215
|
};
|
|
74512
75216
|
}));
|
|
74513
75217
|
}
|
|
@@ -74640,7 +75344,7 @@ function blockDetailContext(blocks) {
|
|
|
74640
75344
|
...sameHeadingPath2 ? { heading_path: first.heading_path } : {}
|
|
74641
75345
|
};
|
|
74642
75346
|
}
|
|
74643
|
-
function blockDetailRow(block, context) {
|
|
75347
|
+
function blockDetailRow(block, context, options) {
|
|
74644
75348
|
return {
|
|
74645
75349
|
...context.source === undefined ? { source_alias: block.source_alias, source_id: block.source_id } : {},
|
|
74646
75350
|
block_id: block.block_id,
|
|
@@ -74652,11 +75356,25 @@ function blockDetailRow(block, context) {
|
|
|
74652
75356
|
block_locator_id: block.block_locator_id,
|
|
74653
75357
|
block_ordinal: block.ordinal_in_source,
|
|
74654
75358
|
...block.signal_labels.length > 0 ? { signal_labels: block.signal_labels, signal_score: block.signal_score } : {},
|
|
74655
|
-
...block.text_preview !== undefined ? { text_preview: block.text_preview } : {}
|
|
75359
|
+
...block.text_preview !== undefined ? { text_preview: block.text_preview } : {},
|
|
75360
|
+
...block.full_text_available === true ? {
|
|
75361
|
+
full_text_available: true,
|
|
75362
|
+
...block.full_text_token_estimate !== undefined ? { full_text_token_estimate: block.full_text_token_estimate } : {},
|
|
75363
|
+
text_preview_truncated: block.text_preview_truncated === true
|
|
75364
|
+
} : {},
|
|
75365
|
+
...options.includeFullText && block.body_text !== undefined ? {
|
|
75366
|
+
body_text: block.body_text,
|
|
75367
|
+
full_text_included: true
|
|
75368
|
+
} : {}
|
|
74656
75369
|
};
|
|
74657
75370
|
}
|
|
74658
|
-
function blockDetailItems(blocks, context) {
|
|
74659
|
-
|
|
75371
|
+
function blockDetailItems(blocks, context, options) {
|
|
75372
|
+
const singleBlock = blocks.length === 1 ? blocks[0] : undefined;
|
|
75373
|
+
const includeFullText = singleBlock?.body_text !== undefined && (singleBlock.full_text_token_estimate ?? blockTokenEstimate(singleBlock)) + FULL_TEXT_METADATA_TOKEN_BUFFER <= options.tokenBudget;
|
|
75374
|
+
return blocks.map((block) => ({
|
|
75375
|
+
block,
|
|
75376
|
+
row: blockDetailRow(block, context, { includeFullText: includeFullText && block === singleBlock })
|
|
75377
|
+
}));
|
|
74660
75378
|
}
|
|
74661
75379
|
function blockTokenEstimate(block) {
|
|
74662
75380
|
return typeof block.token_estimate === "number" && Number.isFinite(block.token_estimate) ? Math.max(0, block.token_estimate) : 0;
|
|
@@ -74683,6 +75401,27 @@ function alignBlocksHowToExplore(input) {
|
|
|
74683
75401
|
]
|
|
74684
75402
|
});
|
|
74685
75403
|
}
|
|
75404
|
+
function alignBlockPreviewHints(input) {
|
|
75405
|
+
const truncated = input.items.filter((item) => item.text_preview_truncated === true && typeof item.body_text !== "string");
|
|
75406
|
+
const first = truncated[0];
|
|
75407
|
+
if (first === undefined)
|
|
75408
|
+
return;
|
|
75409
|
+
const ordinal = typeof first.block_ordinal === "number" ? first.block_ordinal : undefined;
|
|
75410
|
+
const estimate = typeof first.full_text_token_estimate === "number" ? first.full_text_token_estimate : input.tokenBudget;
|
|
75411
|
+
return [{
|
|
75412
|
+
code: "align-block-preview-truncated",
|
|
75413
|
+
severity: "warning",
|
|
75414
|
+
message: `${truncated.length} shown block preview(s) are truncated while full block text is available.`,
|
|
75415
|
+
next_action: "Narrow to a single block with --range <ordinal>:<ordinal> so the blocks view can include body_text before drafting decisions.",
|
|
75416
|
+
...ordinal !== undefined ? {
|
|
75417
|
+
command: alignBlocksCommand(input.record, {
|
|
75418
|
+
...input.options,
|
|
75419
|
+
range: `${ordinal}:${ordinal}`,
|
|
75420
|
+
tokenBudget: String(Math.max(input.tokenBudget, estimate + FULL_TEXT_METADATA_TOKEN_BUFFER))
|
|
75421
|
+
})
|
|
75422
|
+
} : {}
|
|
75423
|
+
}];
|
|
75424
|
+
}
|
|
74686
75425
|
function compactAlignSegmentBlocks(record, value, options) {
|
|
74687
75426
|
const windows = alignWindowRows(value);
|
|
74688
75427
|
const selectedWindow = typeof options.windowId === "string" ? resolveWindowSelector(windows, options.windowId) : undefined;
|
|
@@ -74699,8 +75438,8 @@ function compactAlignSegmentBlocks(record, value, options) {
|
|
|
74699
75438
|
const range = parseOrdinalRange(options.range);
|
|
74700
75439
|
const blocks = alignBlockRows(value).filter((block) => (options.sourceId === undefined || block.source_id === options.sourceId) && (windowBlockIds === undefined || typeof block.block_id === "string" && windowBlockIds.has(block.block_id)) && headingMatches(block.heading_path, options.heading) && (range === undefined || block.ordinal_in_source >= range.start && block.ordinal_in_source <= range.end));
|
|
74701
75440
|
const detailContext = blockDetailContext(blocks);
|
|
74702
|
-
const detailItems = blockDetailItems(blocks, detailContext);
|
|
74703
75441
|
const tokenBudget = parseTokenBudgetOption(options.tokenBudget);
|
|
75442
|
+
const detailItems = blockDetailItems(blocks, detailContext, { tokenBudget });
|
|
74704
75443
|
const window2 = buildTokenBudgetWindow({
|
|
74705
75444
|
entries: detailItems.map((item) => ({
|
|
74706
75445
|
item: item.row,
|
|
@@ -74712,6 +75451,7 @@ function compactAlignSegmentBlocks(record, value, options) {
|
|
|
74712
75451
|
howToExplore: alignBlocksHowToExplore({ record, blocks, options, tokenBudget }),
|
|
74713
75452
|
previewItem: (row) => row
|
|
74714
75453
|
});
|
|
75454
|
+
const agentHints = alignBlockPreviewHints({ record, items: window2.items, options, tokenBudget });
|
|
74715
75455
|
return {
|
|
74716
75456
|
mode: "detail",
|
|
74717
75457
|
filters: compactFilters(options),
|
|
@@ -74731,7 +75471,8 @@ function compactAlignSegmentBlocks(record, value, options) {
|
|
|
74731
75471
|
counts: {
|
|
74732
75472
|
matched_blocks: blocks.length,
|
|
74733
75473
|
shown_blocks: window2.items.length
|
|
74734
|
-
}
|
|
75474
|
+
},
|
|
75475
|
+
...agentHints !== undefined ? { agent_hints: agentHints } : {}
|
|
74735
75476
|
};
|
|
74736
75477
|
}
|
|
74737
75478
|
function compactAlignSegmentSourceMapping(value, options) {
|
|
@@ -77127,6 +77868,13 @@ function formatDraftPlanHeadline(result) {
|
|
|
77127
77868
|
function shellQuote2(value) {
|
|
77128
77869
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
77129
77870
|
}
|
|
77871
|
+
function formatDraftPatchHeadline(result) {
|
|
77872
|
+
const counts = actionCounts(result);
|
|
77873
|
+
return `${counts.total} actions parsed; draft patched; re-prepare required`;
|
|
77874
|
+
}
|
|
77875
|
+
function compileDraftPrepareCommand(slug) {
|
|
77876
|
+
return `context compile --draft ${shellQuote2(slug)} --plan --prepare --view summary --format json`;
|
|
77877
|
+
}
|
|
77130
77878
|
function draftPlanBody(input) {
|
|
77131
77879
|
const { ctxDir, slug, saved, hints, draftDigest, result } = input;
|
|
77132
77880
|
const draftPath = workflowOutputPath(ctxDir, "compile", `compile.${slug}.draft.yaml`);
|
|
@@ -77164,7 +77912,7 @@ function draftPlanBody(input) {
|
|
|
77164
77912
|
lines.push("- continue: `/context:compile`");
|
|
77165
77913
|
if (draftDigest !== undefined) {
|
|
77166
77914
|
lines.push(`- revise: \`context compile --draft-patch ${shellQuote2(slug)} --input - --plan\``);
|
|
77167
|
-
lines.push(`- prepare saved draft:
|
|
77915
|
+
lines.push(`- prepare saved draft: \`${compileDraftPrepareCommand(slug)}\``);
|
|
77168
77916
|
lines.push(`- primitive: \`context reconcile prepare --mode compile --node ${shellQuote2(slug)} --view summary --format json\``);
|
|
77169
77917
|
} else if (saved) {
|
|
77170
77918
|
lines.push(`- saved draft: \`${draftPath}\``);
|
|
@@ -77478,7 +78226,7 @@ init_generationPolicy();
|
|
|
77478
78226
|
var import_yaml38 = __toESM(require_dist(), 1);
|
|
77479
78227
|
import { createHash as createHash9 } from "node:crypto";
|
|
77480
78228
|
import { mkdir as mkdir29, writeFile as writeFile20 } from "node:fs/promises";
|
|
77481
|
-
import { dirname as
|
|
78229
|
+
import { dirname as dirname26 } from "node:path";
|
|
77482
78230
|
|
|
77483
78231
|
// src/workflow/alignCandidates.ts
|
|
77484
78232
|
init_rawBlocks();
|
|
@@ -77779,7 +78527,7 @@ async function writeAlignSegments(options) {
|
|
|
77779
78527
|
const payload = await buildAlignSegments(options);
|
|
77780
78528
|
if (options.dryRun !== true) {
|
|
77781
78529
|
const outPath = options.outputPath ?? workflowOutputPath(options.ctxDir, "align", "align.segments.yaml");
|
|
77782
|
-
await mkdir29(
|
|
78530
|
+
await mkdir29(dirname26(outPath), { recursive: true });
|
|
77783
78531
|
await writeFile20(outPath, import_yaml38.default.stringify(payload), "utf8");
|
|
77784
78532
|
}
|
|
77785
78533
|
return payload;
|
|
@@ -79320,6 +80068,12 @@ var ALIGN_WORKFLOW_FORBIDDEN_FIELDS = [
|
|
|
79320
80068
|
];
|
|
79321
80069
|
var termTags = TERM_TAG_VALUES;
|
|
79322
80070
|
var entityTags = [...ENTITY_TAG_A_VALUES, ...ENTITY_TAG_B_VALUES, ...termTags];
|
|
80071
|
+
var entityTagGroups = {
|
|
80072
|
+
tag_a: ENTITY_TAG_A_VALUES,
|
|
80073
|
+
tag_b: ENTITY_TAG_B_VALUES,
|
|
80074
|
+
standalone: termTags,
|
|
80075
|
+
allowed_shapes: ["one tag_a", "one tag_b", "one tag_a plus one tag_b", "standalone only"]
|
|
80076
|
+
};
|
|
79323
80077
|
var TERM_ENTITY_NOTES = [
|
|
79324
80078
|
"Node type order: action first only when scale plus process evidence both pass; otherwise concrete/term entity; otherwise child-bearing domain; otherwise no Node.",
|
|
79325
80079
|
"Classify the Node by evidence referent, not by source title or heading. Source title/heading is ordinary evidence and does not automatically become node.title, aliases[], or slug.",
|
|
@@ -79569,6 +80323,7 @@ var SCHEMAS = {
|
|
|
79569
80323
|
consumer: "CLI ledger reducer",
|
|
79570
80324
|
role: "One transactional batch of candidate ledger operations.",
|
|
79571
80325
|
enums: enums(),
|
|
80326
|
+
entity_tag_groups: entityTagGroups,
|
|
79572
80327
|
required: ["batch_id", "ops"],
|
|
79573
80328
|
forbidden_fields: ALIGN_WORKFLOW_FORBIDDEN_FIELDS,
|
|
79574
80329
|
example: {
|
|
@@ -79659,6 +80414,7 @@ var SCHEMAS = {
|
|
|
79659
80414
|
consumer: "next Discovery batch / CLI aggregate / LLM resolution",
|
|
79660
80415
|
role: "Current rolling candidate snapshot, not the operation stream.",
|
|
79661
80416
|
enums: enums(),
|
|
80417
|
+
entity_tag_groups: entityTagGroups,
|
|
79662
80418
|
required: ["schema_version", "last_batch_id", "candidates", "block_dispositions"],
|
|
79663
80419
|
forbidden_fields: ALIGN_WORKFLOW_FORBIDDEN_FIELDS,
|
|
79664
80420
|
example: {
|
|
@@ -79749,6 +80505,7 @@ var SCHEMAS = {
|
|
|
79749
80505
|
consumer: "CLI finalize",
|
|
79750
80506
|
role: "Final Node structure, depends_on edges, planned Sections, and block ownership.",
|
|
79751
80507
|
enums: enums(),
|
|
80508
|
+
entity_tag_groups: entityTagGroups,
|
|
79752
80509
|
mount_matrix: sectionMountMatrix(),
|
|
79753
80510
|
required: ["schema_version", "nodes", "sections", "edges", "block_ownership"],
|
|
79754
80511
|
forbidden_fields: ALIGN_WORKFLOW_FORBIDDEN_FIELDS,
|
|
@@ -80778,7 +81535,7 @@ init_sourceOwnership();
|
|
|
80778
81535
|
init_workflowOutputPaths();
|
|
80779
81536
|
var import_yaml39 = __toESM(require_dist(), 1);
|
|
80780
81537
|
import { mkdir as mkdir30, writeFile as writeFile21 } from "node:fs/promises";
|
|
80781
|
-
import { dirname as
|
|
81538
|
+
import { dirname as dirname27 } from "node:path";
|
|
80782
81539
|
function lineRange2(block) {
|
|
80783
81540
|
return `L${block.line_start}-L${block.line_end}`;
|
|
80784
81541
|
}
|
|
@@ -80838,7 +81595,7 @@ function renderMarkdown2(input) {
|
|
|
80838
81595
|
async function renderStructureDecisionProposal(input) {
|
|
80839
81596
|
const path9 = workflowOutputPath(input.ctxDir, "align", "align.propose.md");
|
|
80840
81597
|
const debugPath = workflowOutputPath(input.ctxDir, "align", "align.propose.yaml");
|
|
80841
|
-
await mkdir30(
|
|
81598
|
+
await mkdir30(dirname27(path9), { recursive: true });
|
|
80842
81599
|
await writeFile21(path9, renderMarkdown2(input), "utf8");
|
|
80843
81600
|
await writeFile21(debugPath, import_yaml39.default.stringify({
|
|
80844
81601
|
schema_version: input.decision.schema_version,
|
|
@@ -83314,7 +84071,7 @@ async function runDraftPatch(input) {
|
|
|
83314
84071
|
scopeId: nodeRunIdForSlug(input.slug),
|
|
83315
84072
|
draft: normalizedDraft
|
|
83316
84073
|
});
|
|
83317
|
-
const
|
|
84074
|
+
const prepareCommand = compileDraftPrepareCommand(result.slug);
|
|
83318
84075
|
const outputHints = [...patch.agent_hints ?? [], ...result.agent_hints ?? []];
|
|
83319
84076
|
if (compileChangesFormat(input.options.format) === "json") {
|
|
83320
84077
|
writeJson3({
|
|
@@ -83331,7 +84088,7 @@ async function runDraftPatch(input) {
|
|
|
83331
84088
|
},
|
|
83332
84089
|
action_counts: draftActionCounts(normalizedDraft),
|
|
83333
84090
|
agent_hints: outputHints,
|
|
83334
|
-
next_command:
|
|
84091
|
+
next_command: prepareCommand
|
|
83335
84092
|
});
|
|
83336
84093
|
return;
|
|
83337
84094
|
}
|
|
@@ -83339,7 +84096,7 @@ async function runDraftPatch(input) {
|
|
|
83339
84096
|
symbol: outputHints.some((hint) => hint.severity === "warning" || hint.severity === "error") ? "⚠" : "✓",
|
|
83340
84097
|
action: "patched",
|
|
83341
84098
|
subject: input.slug,
|
|
83342
|
-
headline:
|
|
84099
|
+
headline: formatDraftPatchHeadline(result),
|
|
83343
84100
|
body: [
|
|
83344
84101
|
workflowSummaryLine(current),
|
|
83345
84102
|
...draftPlanBody({
|
|
@@ -83351,7 +84108,7 @@ async function runDraftPatch(input) {
|
|
|
83351
84108
|
result
|
|
83352
84109
|
})
|
|
83353
84110
|
],
|
|
83354
|
-
next:
|
|
84111
|
+
next: prepareCommand
|
|
83355
84112
|
}));
|
|
83356
84113
|
}
|
|
83357
84114
|
async function draftFromSavedSession(input) {
|
|
@@ -84124,7 +84881,7 @@ function registerWorkflowCommands(program2) {
|
|
|
84124
84881
|
init_cliFeedback();
|
|
84125
84882
|
init_errors();
|
|
84126
84883
|
import { lstat as lstat3, readdir as readdir27 } from "node:fs/promises";
|
|
84127
|
-
import { isAbsolute as isAbsolute8, join as
|
|
84884
|
+
import { isAbsolute as isAbsolute8, join as join65, relative as relative16, resolve as resolve15 } from "node:path";
|
|
84128
84885
|
|
|
84129
84886
|
// src/lib/pathFreeAgentHintWorkflowInventory.ts
|
|
84130
84887
|
var AGENT_HINT_EMITTER_WORKFLOW_INVENTORY = [
|
|
@@ -84881,6 +85638,13 @@ var AGENT_HINT_EMITTER_INVENTORY = [
|
|
|
84881
85638
|
handles: ["edge_owner", "node_slug", "issue_code"],
|
|
84882
85639
|
notes: "Graph verify next actions route to compile close, compile --code, or edge repair."
|
|
84883
85640
|
},
|
|
85641
|
+
{
|
|
85642
|
+
source: "src/mdrive/verifyRenderBlocks.ts",
|
|
85643
|
+
family: "mdrive render-block verify",
|
|
85644
|
+
policy: "semantic",
|
|
85645
|
+
handles: ["node_slug", "issue_code", "line"],
|
|
85646
|
+
notes: "Render-block verify next actions route to compile close or target Node repair without storage probing."
|
|
85647
|
+
},
|
|
84884
85648
|
{
|
|
84885
85649
|
source: "src/mdrive/verifySourceRules.ts",
|
|
84886
85650
|
family: "mdrive source verify",
|
|
@@ -84895,6 +85659,13 @@ var AGENT_HINT_EMITTER_INVENTORY = [
|
|
|
84895
85659
|
handles: ["issue_code", "next_action"],
|
|
84896
85660
|
notes: "Verify issue type exposes next_action as a semantic repair field."
|
|
84897
85661
|
},
|
|
85662
|
+
{
|
|
85663
|
+
source: "src/mdrive/verifyWorkspaceReader.ts",
|
|
85664
|
+
family: "mdrive workspace reader verify",
|
|
85665
|
+
policy: "semantic",
|
|
85666
|
+
handles: ["node_slug", "issue_code", "line"],
|
|
85667
|
+
notes: "Reader-surfaced render-block issues use semantic Node and line handles."
|
|
85668
|
+
},
|
|
84898
85669
|
{
|
|
84899
85670
|
source: "src/reconcile/prepare.ts",
|
|
84900
85671
|
family: "reconcile prepare",
|
|
@@ -84974,9 +85745,9 @@ function writeJson4(value) {
|
|
|
84974
85745
|
`);
|
|
84975
85746
|
}
|
|
84976
85747
|
function workspacePath(ctxDir, relPath, label) {
|
|
84977
|
-
const base =
|
|
84978
|
-
const path9 =
|
|
84979
|
-
const pathRelativeToBase =
|
|
85748
|
+
const base = resolve15(ctxDir);
|
|
85749
|
+
const path9 = resolve15(base, relPath);
|
|
85750
|
+
const pathRelativeToBase = relative16(base, path9);
|
|
84980
85751
|
if (pathRelativeToBase.startsWith("..") || isAbsolute8(pathRelativeToBase)) {
|
|
84981
85752
|
throw new ContextError(ExitCode.UserError, "debug path resolved outside the context workspace", {
|
|
84982
85753
|
category: ErrorCategory.UserInputInvalid,
|
|
@@ -85112,11 +85883,11 @@ async function debugSourceRawPath(ctx, options) {
|
|
|
85112
85883
|
function workspaceStorageRoots(ctxDir) {
|
|
85113
85884
|
return {
|
|
85114
85885
|
ctxDir,
|
|
85115
|
-
raw:
|
|
85116
|
-
knowledge:
|
|
85117
|
-
output:
|
|
85118
|
-
archive:
|
|
85119
|
-
decisions:
|
|
85886
|
+
raw: join65(ctxDir, "raw"),
|
|
85887
|
+
knowledge: join65(ctxDir, "knowledge"),
|
|
85888
|
+
output: join65(ctxDir, "output"),
|
|
85889
|
+
archive: join65(ctxDir, "archive"),
|
|
85890
|
+
decisions: join65(ctxDir, "decisions"),
|
|
85120
85891
|
user_cache: workspaceUserCacheRoot(ctxDir)
|
|
85121
85892
|
};
|
|
85122
85893
|
}
|
|
@@ -85207,7 +85978,7 @@ async function knowledgeNodeTypeDirs(ctxDir) {
|
|
|
85207
85978
|
async function inspectNodeObject(ctxDir, slug) {
|
|
85208
85979
|
const typeDirs = await knowledgeNodeTypeDirs(ctxDir);
|
|
85209
85980
|
const candidates = await Promise.all(typeDirs.map((type) => {
|
|
85210
|
-
const relPath =
|
|
85981
|
+
const relPath = join65("knowledge", type, `${slug}.md`);
|
|
85211
85982
|
return inspectWorkspacePath(ctxDir, relPath, relPath);
|
|
85212
85983
|
}));
|
|
85213
85984
|
return {
|
|
@@ -85223,7 +85994,7 @@ function safeArchiveSourceSegment(value) {
|
|
|
85223
85994
|
async function inspectArchiveObject(ctx, archiveId) {
|
|
85224
85995
|
const ctxDir = requireContext2(ctx, "debug storage inspect");
|
|
85225
85996
|
const source2 = (ctx.sources?.sources ?? []).find((entry) => entry.id === archiveId);
|
|
85226
|
-
const directRel =
|
|
85997
|
+
const directRel = join65("archive", "sources", safeArchiveSourceSegment(archiveId));
|
|
85227
85998
|
const paths = [
|
|
85228
85999
|
...source2?.archive_path !== undefined ? [await inspectWorkspacePath(ctxDir, source2.archive_path, "source.archive_path")] : [],
|
|
85229
86000
|
await inspectWorkspacePath(ctxDir, directRel, directRel)
|
|
@@ -85271,7 +86042,7 @@ async function walkForFileName(root2, fileName, out2 = []) {
|
|
|
85271
86042
|
throw error;
|
|
85272
86043
|
}
|
|
85273
86044
|
for (const entry of entries) {
|
|
85274
|
-
const child =
|
|
86045
|
+
const child = join65(root2, entry.name);
|
|
85275
86046
|
if (entry.isDirectory()) {
|
|
85276
86047
|
await walkForFileName(child, fileName, out2);
|
|
85277
86048
|
} else if (entry.isFile() && entry.name === fileName) {
|
|
@@ -85281,7 +86052,7 @@ async function walkForFileName(root2, fileName, out2 = []) {
|
|
|
85281
86052
|
return out2;
|
|
85282
86053
|
}
|
|
85283
86054
|
async function inspectReviewObject(ctxDir, reviewId) {
|
|
85284
|
-
const matches = await walkForFileName(
|
|
86055
|
+
const matches = await walkForFileName(join65(ctxDir, "output", "workflows"), `review.${reviewId}.yaml`);
|
|
85285
86056
|
return {
|
|
85286
86057
|
object: `review:${reviewId}`,
|
|
85287
86058
|
kind: "review",
|
|
@@ -85291,7 +86062,7 @@ async function inspectReviewObject(ctxDir, reviewId) {
|
|
|
85291
86062
|
}
|
|
85292
86063
|
async function inspectWorkflowObject(ctxDir, workflowId) {
|
|
85293
86064
|
const current = await readCurrentWorkflow(ctxDir);
|
|
85294
|
-
const workflowRoot = workspacePath(ctxDir,
|
|
86065
|
+
const workflowRoot = workspacePath(ctxDir, join65("output", "workflows", safePathSegment2(workflowId)), "workflow output root");
|
|
85295
86066
|
const currentMatches = current.status === "ready" && current.state.workflow_id === workflowId;
|
|
85296
86067
|
return {
|
|
85297
86068
|
object: `workflow:${workflowId}`,
|
|
@@ -85445,10 +86216,10 @@ async function buildDebugSnapshot(ctx) {
|
|
|
85445
86216
|
manifest: cache.manifest
|
|
85446
86217
|
},
|
|
85447
86218
|
counts: {
|
|
85448
|
-
raw_entries: await countDirectEntries(
|
|
85449
|
-
knowledge_entries: await countDirectEntries(
|
|
85450
|
-
output_entries: await countDirectEntries(
|
|
85451
|
-
archive_entries: await countDirectEntries(
|
|
86219
|
+
raw_entries: await countDirectEntries(join65(ctxDir, "raw")),
|
|
86220
|
+
knowledge_entries: await countDirectEntries(join65(ctxDir, "knowledge")),
|
|
86221
|
+
output_entries: await countDirectEntries(join65(ctxDir, "output")),
|
|
86222
|
+
archive_entries: await countDirectEntries(join65(ctxDir, "archive"))
|
|
85452
86223
|
}
|
|
85453
86224
|
};
|
|
85454
86225
|
}
|
|
@@ -85522,11 +86293,11 @@ init_errors();
|
|
|
85522
86293
|
init_cliFeedback();
|
|
85523
86294
|
init_config();
|
|
85524
86295
|
init_errors();
|
|
85525
|
-
import { join as
|
|
86296
|
+
import { join as join69 } from "node:path";
|
|
85526
86297
|
|
|
85527
86298
|
// src/build/llms.ts
|
|
85528
86299
|
import { writeFile as writeFile22 } from "node:fs/promises";
|
|
85529
|
-
import { join as
|
|
86300
|
+
import { join as join67 } from "node:path";
|
|
85530
86301
|
|
|
85531
86302
|
// src/build/renderKnowledge.ts
|
|
85532
86303
|
init_nodeRenderer();
|
|
@@ -85609,7 +86380,7 @@ init_nodeRenderer();
|
|
|
85609
86380
|
init_exitCode();
|
|
85610
86381
|
init_knowledge();
|
|
85611
86382
|
import { mkdir as mkdir31 } from "node:fs/promises";
|
|
85612
|
-
import { join as
|
|
86383
|
+
import { join as join66 } from "node:path";
|
|
85613
86384
|
var MAX_TIMESTAMP_COLLISION_ATTEMPTS = 60;
|
|
85614
86385
|
var SUMMARY_MAX_LENGTH = 160;
|
|
85615
86386
|
var NODE_TYPE_ORDER = [NodeType2.domain, NodeType2.entity, NodeType2.action];
|
|
@@ -85636,11 +86407,11 @@ function isFsCode(error, code3) {
|
|
|
85636
86407
|
return typeof error === "object" && error !== null && "code" in error && error.code === code3;
|
|
85637
86408
|
}
|
|
85638
86409
|
async function createTimestampedPackageDir(outputRoot, packageName2, now) {
|
|
85639
|
-
const packageRoot =
|
|
86410
|
+
const packageRoot = join66(outputRoot, packageName2);
|
|
85640
86411
|
await mkdir31(packageRoot, { recursive: true });
|
|
85641
86412
|
for (let offsetSeconds = 0;offsetSeconds < MAX_TIMESTAMP_COLLISION_ATTEMPTS; offsetSeconds += 1) {
|
|
85642
86413
|
const candidateTime = new Date(now.getTime() + offsetSeconds * 1000);
|
|
85643
|
-
const candidate =
|
|
86414
|
+
const candidate = join66(packageRoot, formatBuildTimestamp(candidateTime));
|
|
85644
86415
|
try {
|
|
85645
86416
|
await mkdir31(candidate);
|
|
85646
86417
|
return candidate;
|
|
@@ -85716,10 +86487,10 @@ function renderLlmsIndex(input) {
|
|
|
85716
86487
|
}
|
|
85717
86488
|
async function writeLlmsPackage(input) {
|
|
85718
86489
|
const packageDir = await createTimestampedPackageDir(input.outputRoot, "llms-pkg", input.now);
|
|
85719
|
-
await writeFile22(
|
|
86490
|
+
await writeFile22(join67(packageDir, "llms.txt"), renderLlmsIndex(input), "utf8");
|
|
85720
86491
|
await Promise.all(input.nodes.map(async (node3) => {
|
|
85721
86492
|
const parsed = node3.located.parsed.node;
|
|
85722
|
-
await writeFile22(
|
|
86493
|
+
await writeFile22(join67(packageDir, buildNodeFileName(parsed)), renderExportNodeMarkdown({ node: parsed, sections: node3.activeSections }), "utf8");
|
|
85723
86494
|
}));
|
|
85724
86495
|
return {
|
|
85725
86496
|
packageDir,
|
|
@@ -85729,7 +86500,7 @@ async function writeLlmsPackage(input) {
|
|
|
85729
86500
|
|
|
85730
86501
|
// src/build/skillsPack.ts
|
|
85731
86502
|
import { mkdir as mkdir32, writeFile as writeFile23 } from "node:fs/promises";
|
|
85732
|
-
import { join as
|
|
86503
|
+
import { join as join68 } from "node:path";
|
|
85733
86504
|
var KNOWLEDGE_QUERY_PROCEDURE = [
|
|
85734
86505
|
"1. For a named topic, read the matching wiki file directly from `wikis/`.",
|
|
85735
86506
|
"2. For a broad question, grep `wikis/` with relevant keywords, then read the matching wiki files.",
|
|
@@ -85790,23 +86561,23 @@ function renderKnowledgeQuerySkill() {
|
|
|
85790
86561
|
}
|
|
85791
86562
|
async function writeSkillsPack(input) {
|
|
85792
86563
|
const packageDir = await createTimestampedPackageDir(input.outputRoot, "skills-pkg", input.now);
|
|
85793
|
-
const guidesDir =
|
|
85794
|
-
const skillsDir =
|
|
85795
|
-
const wikisDir =
|
|
86564
|
+
const guidesDir = join68(packageDir, "guides");
|
|
86565
|
+
const skillsDir = join68(packageDir, "skills");
|
|
86566
|
+
const wikisDir = join68(packageDir, "wikis");
|
|
85796
86567
|
await Promise.all([
|
|
85797
86568
|
mkdir32(guidesDir, { recursive: true }),
|
|
85798
86569
|
mkdir32(skillsDir, { recursive: true }),
|
|
85799
86570
|
mkdir32(wikisDir, { recursive: true }),
|
|
85800
|
-
mkdir32(
|
|
85801
|
-
mkdir32(
|
|
86571
|
+
mkdir32(join68(packageDir, "rules"), { recursive: true }),
|
|
86572
|
+
mkdir32(join68(packageDir, "integrations"), { recursive: true })
|
|
85802
86573
|
]);
|
|
85803
86574
|
await Promise.all([
|
|
85804
|
-
writeFile23(
|
|
85805
|
-
writeFile23(
|
|
86575
|
+
writeFile23(join68(guidesDir, "AGENTS.md"), renderAgentsGuide2(input), "utf8"),
|
|
86576
|
+
writeFile23(join68(skillsDir, "knowledge-query.md"), renderKnowledgeQuerySkill(), "utf8")
|
|
85806
86577
|
]);
|
|
85807
86578
|
await Promise.all(input.nodes.map(async (node3) => {
|
|
85808
86579
|
const parsed = node3.located.parsed.node;
|
|
85809
|
-
await writeFile23(
|
|
86580
|
+
await writeFile23(join68(wikisDir, buildNodeFileName(parsed)), renderExportNodeMarkdown({ node: parsed, sections: node3.activeSections }), "utf8");
|
|
85810
86581
|
}));
|
|
85811
86582
|
return {
|
|
85812
86583
|
packageDir,
|
|
@@ -85888,7 +86659,7 @@ async function collectExportNodes(ctxDir) {
|
|
|
85888
86659
|
return {
|
|
85889
86660
|
config,
|
|
85890
86661
|
nodes,
|
|
85891
|
-
outputRoot:
|
|
86662
|
+
outputRoot: join69(ctxDir, "output")
|
|
85892
86663
|
};
|
|
85893
86664
|
}
|
|
85894
86665
|
async function buildKnowledgePackage(input) {
|
|
@@ -86049,7 +86820,7 @@ function cmdVerifyWorkspace(opts = {}) {
|
|
|
86049
86820
|
subject: "knowledge",
|
|
86050
86821
|
headline: `${result.issues.length} issues (${errors3} error, ${warnings} warning)`,
|
|
86051
86822
|
body: [
|
|
86052
|
-
...result.issues.map((issue2) => `[${issue2.severity}] ${issue2.code}${issue2.slug ? ` node=${issue2.slug}` : ""}${issue2.sectionId ? ` section=${issue2.sectionId}` : ""}: ${issue2.message}`),
|
|
86823
|
+
...result.issues.map((issue2) => `[${issue2.severity}] ${issue2.code}${issue2.slug ? ` node=${issue2.slug}` : ""}${issue2.sectionId ? ` section=${issue2.sectionId}` : ""}${issue2.line ? ` line=${issue2.line}` : ""}: ${issue2.message}`),
|
|
86053
86824
|
...verifyHintLines(result)
|
|
86054
86825
|
]
|
|
86055
86826
|
}));
|
|
@@ -86676,14 +87447,14 @@ function inferErrorCategory(message) {
|
|
|
86676
87447
|
}
|
|
86677
87448
|
function readPackageVersion() {
|
|
86678
87449
|
try {
|
|
86679
|
-
let dir =
|
|
87450
|
+
let dir = dirname28(fileURLToPath5(import.meta.url));
|
|
86680
87451
|
for (let i = 0;i < 8; i++) {
|
|
86681
|
-
const pkg =
|
|
87452
|
+
const pkg = join70(dir, "package.json");
|
|
86682
87453
|
if (existsSync54(pkg)) {
|
|
86683
87454
|
const parsed = JSON.parse(readFileSync3(pkg, "utf8"));
|
|
86684
87455
|
return parsed.version ?? "unknown";
|
|
86685
87456
|
}
|
|
86686
|
-
const parent =
|
|
87457
|
+
const parent = dirname28(dir);
|
|
86687
87458
|
if (parent === dir)
|
|
86688
87459
|
break;
|
|
86689
87460
|
dir = parent;
|