skillwiki 0.10.47 → 0.10.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-5JYOYMST.js → chunk-F7LXKP4T.js} +78 -1
- package/dist/{chunk-4SINVFR3.js → chunk-FXASPB3C.js} +84 -15
- package/dist/cli.js +283 -127
- package/dist/{managed-write-preflight-DWK3PJCO.js → managed-write-preflight-H7KVK2KI.js} +1 -1
- package/dist/skillwiki-mcp.js +2 -2
- package/package.json +1 -1
- package/skills/.claude-plugin/plugin.json +1 -1
- package/skills/.codex-plugin/plugin.json +1 -1
- package/skills/package.json +1 -1
- package/skills/proj-work/SKILL.md +8 -8
- package/skills/skills/proj-work/SKILL.md +8 -8
- package/skills/skills/using-skillwiki/SKILL.md +30 -20
- package/skills/skills/using-skillwiki/activation.md +2 -2
- package/skills/skills/wiki-gate-plan-mode/SKILL.md +8 -8
- package/skills/using-skillwiki/SKILL.md +30 -20
- package/skills/using-skillwiki/activation.md +2 -2
- package/skills/wiki-gate-plan-mode/SKILL.md +8 -8
package/dist/cli.js
CHANGED
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
scanConflictMarkerBlocksInText,
|
|
41
41
|
snapshotterHealthChecks,
|
|
42
42
|
upsertIndexEntry
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-F7LXKP4T.js";
|
|
44
44
|
import {
|
|
45
45
|
normalizeDistTag,
|
|
46
46
|
readCache,
|
|
@@ -56,6 +56,7 @@ import {
|
|
|
56
56
|
} from "./chunk-GAU4D25O.js";
|
|
57
57
|
import {
|
|
58
58
|
FLEET_REL_PATH,
|
|
59
|
+
REDACTED_MALFORMED_REFERENCE,
|
|
59
60
|
VAULT_COMMIT_PATHSPEC,
|
|
60
61
|
acquireOwnedSyncLock,
|
|
61
62
|
appendLastOp,
|
|
@@ -79,7 +80,9 @@ import {
|
|
|
79
80
|
loadFleetManifestAndHost,
|
|
80
81
|
markJournalSuperseded,
|
|
81
82
|
mergeTaxonomyConflict,
|
|
83
|
+
normalizeProjectSlug,
|
|
82
84
|
normalizeRemoteRoot,
|
|
85
|
+
parseActiveWorkPath,
|
|
83
86
|
parseDotenvFile,
|
|
84
87
|
parseDotenvText,
|
|
85
88
|
parseJournalEnv,
|
|
@@ -119,6 +122,7 @@ import {
|
|
|
119
122
|
runSyncUnlock,
|
|
120
123
|
runTagAudit,
|
|
121
124
|
runTopicMapCheck,
|
|
125
|
+
safeDiagnosticValue,
|
|
122
126
|
safeWritePage,
|
|
123
127
|
serializeJournalEnv,
|
|
124
128
|
snapshotMaintainedPageState,
|
|
@@ -127,7 +131,7 @@ import {
|
|
|
127
131
|
supersedeStaleReviewRequiredJournals,
|
|
128
132
|
taxonomyCommentForPage,
|
|
129
133
|
writeDotenv
|
|
130
|
-
} from "./chunk-
|
|
134
|
+
} from "./chunk-FXASPB3C.js";
|
|
131
135
|
import {
|
|
132
136
|
assertTargetInsideVault,
|
|
133
137
|
atomicWriteText,
|
|
@@ -166,17 +170,20 @@ import {
|
|
|
166
170
|
err,
|
|
167
171
|
extractFrontmatter,
|
|
168
172
|
isBlockedHost,
|
|
173
|
+
mapWithConcurrency,
|
|
169
174
|
ok,
|
|
170
175
|
readPage,
|
|
176
|
+
readPageCached,
|
|
171
177
|
redactSensitiveContent,
|
|
172
178
|
resolveReadOnlyVaultRoot,
|
|
173
179
|
scanSensitiveContent,
|
|
174
180
|
scanVault,
|
|
175
|
-
splitFrontmatter
|
|
181
|
+
splitFrontmatter,
|
|
182
|
+
vaultIoConcurrency
|
|
176
183
|
} from "./chunk-EVQASYII.js";
|
|
177
184
|
|
|
178
185
|
// src/cli.ts
|
|
179
|
-
import { join as
|
|
186
|
+
import { join as join39 } from "path";
|
|
180
187
|
import { Command } from "commander";
|
|
181
188
|
|
|
182
189
|
// src/utils/output.ts
|
|
@@ -2016,9 +2023,6 @@ function extractDate(filename) {
|
|
|
2016
2023
|
function extractSlugFromFilename(filename) {
|
|
2017
2024
|
return filename.replace(/^\d{4}-\d{2}-\d{2}-/, "").replace(/^(task|bug|idea|note|observation)-/, "").replace(/\.md$/, "");
|
|
2018
2025
|
}
|
|
2019
|
-
function extractProjectSlug(projectField) {
|
|
2020
|
-
return projectField.replace(/^\[\[/, "").replace(/\]\]$/, "").replace(/^"|"$/g, "");
|
|
2021
|
-
}
|
|
2022
2026
|
async function runClaim(input) {
|
|
2023
2027
|
if (!existsSync2(input.vault) || !statSync(input.vault).isDirectory()) {
|
|
2024
2028
|
return { exitCode: ExitCode.VAULT_PATH_INVALID, result: err("VAULT_PATH_INVALID", { path: input.vault }) };
|
|
@@ -2029,10 +2033,19 @@ async function runClaim(input) {
|
|
|
2029
2033
|
}
|
|
2030
2034
|
const content = await readFile5(absTranscript, "utf8");
|
|
2031
2035
|
const fm = extractFrontmatter(content);
|
|
2032
|
-
|
|
2033
|
-
if (
|
|
2034
|
-
|
|
2036
|
+
const explicitProject = fm.ok ? normalizeProjectSlug(fm.data.project) : void 0;
|
|
2037
|
+
if (input.project && explicitProject && explicitProject !== input.project) {
|
|
2038
|
+
return {
|
|
2039
|
+
exitCode: ExitCode.SCHEME_REJECTED,
|
|
2040
|
+
result: err("PROJECT_MISMATCH", {
|
|
2041
|
+
message: `--project ${input.project} does not match the capture's explicit project ${explicitProject}`,
|
|
2042
|
+
project: input.project,
|
|
2043
|
+
captureProject: explicitProject,
|
|
2044
|
+
transcript: input.transcript
|
|
2045
|
+
})
|
|
2046
|
+
};
|
|
2035
2047
|
}
|
|
2048
|
+
const projectSlug = explicitProject ?? input.project;
|
|
2036
2049
|
if (!projectSlug) {
|
|
2037
2050
|
return {
|
|
2038
2051
|
exitCode: ExitCode.SCHEME_REJECTED,
|
|
@@ -3525,10 +3538,10 @@ async function runRemove(input) {
|
|
|
3525
3538
|
const tombstonePath = await writeDeleteIntent(input.vault, intent);
|
|
3526
3539
|
await unlink2(join19(input.vault, relPath));
|
|
3527
3540
|
if (relPath.endsWith(".md") && !relPath.startsWith("raw/")) {
|
|
3528
|
-
const { readFile:
|
|
3541
|
+
const { readFile: readFile21 } = await import("fs/promises");
|
|
3529
3542
|
const { join: pathJoin } = await import("path");
|
|
3530
3543
|
const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-BJNZUPH6.js");
|
|
3531
|
-
const before = await
|
|
3544
|
+
const before = await readFile21(pathJoin(input.vault, "index.md"), "utf8").catch(() => "");
|
|
3532
3545
|
const fullTarget = relPath.replace(/\.md$/, "");
|
|
3533
3546
|
const bare = fullTarget.split("/").pop() ?? fullTarget;
|
|
3534
3547
|
const hadIndexEntry = before.includes(`[[${fullTarget}]]`) || before.includes(`[[${bare}]]`);
|
|
@@ -4161,11 +4174,148 @@ async function runTranscripts(input) {
|
|
|
4161
4174
|
return { exitCode: ExitCode.OK, result: ok({ transcripts, humanHint: hint }) };
|
|
4162
4175
|
}
|
|
4163
4176
|
|
|
4177
|
+
// src/commands/claims-audit.ts
|
|
4178
|
+
import { readFile as readFile10 } from "fs/promises";
|
|
4179
|
+
import { join as join23 } from "path";
|
|
4180
|
+
function safeProjectPresentation(raw) {
|
|
4181
|
+
if (safeDiagnosticValue(raw) === REDACTED_MALFORMED_REFERENCE) {
|
|
4182
|
+
return REDACTED_MALFORMED_REFERENCE;
|
|
4183
|
+
}
|
|
4184
|
+
return normalizeProjectSlug(raw) ?? REDACTED_MALFORMED_REFERENCE;
|
|
4185
|
+
}
|
|
4186
|
+
async function runClaimsAudit(input) {
|
|
4187
|
+
const scanResult = await scanVault(input.vault);
|
|
4188
|
+
if (!scanResult.ok) return { exitCode: ExitCode.VAULT_PATH_INVALID, result: scanResult };
|
|
4189
|
+
const activeTranscripts = scanResult.data.raw.filter((p) => p.relPath.startsWith("raw/transcripts/") && p.relPath.endsWith(".md")).sort((a, b) => a.relPath.localeCompare(b.relPath));
|
|
4190
|
+
const activePathSet = new Set(activeTranscripts.map((p) => p.relPath));
|
|
4191
|
+
const workItemDirs = /* @__PURE__ */ new Set();
|
|
4192
|
+
const specDirs = /* @__PURE__ */ new Set();
|
|
4193
|
+
for (const page of scanResult.data.workItems) {
|
|
4194
|
+
const slash = page.relPath.lastIndexOf("/");
|
|
4195
|
+
if (slash < 0) continue;
|
|
4196
|
+
const dir = page.relPath.slice(0, slash);
|
|
4197
|
+
if (!parseActiveWorkPath(dir)) continue;
|
|
4198
|
+
workItemDirs.add(dir);
|
|
4199
|
+
if (page.relPath.endsWith("/spec.md")) specDirs.add(dir);
|
|
4200
|
+
}
|
|
4201
|
+
const sortedDirs = [...workItemDirs].sort();
|
|
4202
|
+
const slugByDir = new Map(sortedDirs.map((dir) => [dir, parseActiveWorkPath(dir)?.project]));
|
|
4203
|
+
if (input.project) {
|
|
4204
|
+
const knownSlugs = new Set(
|
|
4205
|
+
[...slugByDir.values()].filter((slug) => Boolean(slug))
|
|
4206
|
+
);
|
|
4207
|
+
if (!knownSlugs.has(input.project)) {
|
|
4208
|
+
return {
|
|
4209
|
+
exitCode: ExitCode.PROJECT_NOT_FOUND,
|
|
4210
|
+
result: err("UNKNOWN_PROJECT", `Project "${input.project}" not found. Available: ${[...knownSlugs].sort().join(", ") || "(none)"}`)
|
|
4211
|
+
};
|
|
4212
|
+
}
|
|
4213
|
+
}
|
|
4214
|
+
const scopedSpecDirs = sortedDirs.filter((relDir) => {
|
|
4215
|
+
if (!specDirs.has(relDir)) return false;
|
|
4216
|
+
return !input.project || slugByDir.get(relDir) === input.project;
|
|
4217
|
+
});
|
|
4218
|
+
const claimSourceResults = await mapWithConcurrency(scopedSpecDirs, vaultIoConcurrency(), async (relDir) => {
|
|
4219
|
+
const specPath = join23(input.vault, relDir, "spec.md");
|
|
4220
|
+
try {
|
|
4221
|
+
const specText = await readFile10(specPath, "utf8");
|
|
4222
|
+
const fm = extractFrontmatter(specText);
|
|
4223
|
+
if (!fm.ok) return null;
|
|
4224
|
+
return {
|
|
4225
|
+
relDir,
|
|
4226
|
+
source: fm.data.source,
|
|
4227
|
+
sources: fm.data.sources,
|
|
4228
|
+
closes: fm.data.closes
|
|
4229
|
+
};
|
|
4230
|
+
} catch {
|
|
4231
|
+
return null;
|
|
4232
|
+
}
|
|
4233
|
+
});
|
|
4234
|
+
const claimIndex = collectClaimedTranscripts(
|
|
4235
|
+
claimSourceResults.filter((source) => source !== null)
|
|
4236
|
+
);
|
|
4237
|
+
const claimedByPath = claimIndex.claimedByPath;
|
|
4238
|
+
const transcriptMeta = /* @__PURE__ */ new Map();
|
|
4239
|
+
const transcriptEntries = await mapWithConcurrency(activeTranscripts, vaultIoConcurrency(), async (t) => {
|
|
4240
|
+
try {
|
|
4241
|
+
const text = await readPageCached(t);
|
|
4242
|
+
const fm = extractFrontmatter(text);
|
|
4243
|
+
if (!fm.ok) return null;
|
|
4244
|
+
const projectRaw = typeof fm.data.project === "string" ? fm.data.project.trim() : void 0;
|
|
4245
|
+
const workItemRaw = typeof fm.data.work_item === "string" ? fm.data.work_item.trim() : void 0;
|
|
4246
|
+
const meta = {};
|
|
4247
|
+
if (projectRaw) {
|
|
4248
|
+
meta.projectRaw = projectRaw;
|
|
4249
|
+
meta.project = normalizeProjectSlug(projectRaw);
|
|
4250
|
+
}
|
|
4251
|
+
if (workItemRaw) meta.workItem = workItemRaw;
|
|
4252
|
+
return [t.relPath, meta];
|
|
4253
|
+
} catch {
|
|
4254
|
+
return null;
|
|
4255
|
+
}
|
|
4256
|
+
});
|
|
4257
|
+
for (const entry of transcriptEntries) {
|
|
4258
|
+
if (entry) transcriptMeta.set(entry[0], entry[1]);
|
|
4259
|
+
}
|
|
4260
|
+
const findings = [];
|
|
4261
|
+
for (const d of claimIndex.diagnostics) {
|
|
4262
|
+
if (d.kind === "duplicate") {
|
|
4263
|
+
findings.push({ kind: "duplicate_claim", path: d.path, owners: d.owners });
|
|
4264
|
+
} else {
|
|
4265
|
+
findings.push({ kind: "malformed_claim_reference", relDir: d.relDir, field: d.field, value: d.value });
|
|
4266
|
+
}
|
|
4267
|
+
}
|
|
4268
|
+
for (const [path, owner] of claimedByPath) {
|
|
4269
|
+
if (!activePathSet.has(path)) {
|
|
4270
|
+
findings.push({ kind: "dangling_claim_reference", path, claimedBy: owner });
|
|
4271
|
+
}
|
|
4272
|
+
}
|
|
4273
|
+
for (const [path, owner] of claimedByPath) {
|
|
4274
|
+
const meta = transcriptMeta.get(path);
|
|
4275
|
+
const ownerProject = slugByDir.get(owner) ?? parseActiveWorkPath(owner)?.project;
|
|
4276
|
+
if (meta?.project && ownerProject !== meta.project) {
|
|
4277
|
+
findings.push({
|
|
4278
|
+
kind: "project_mismatch",
|
|
4279
|
+
path,
|
|
4280
|
+
captureProject: safeProjectPresentation(meta.projectRaw ?? ""),
|
|
4281
|
+
claimedByProject: ownerProject ?? "",
|
|
4282
|
+
claimedBy: owner
|
|
4283
|
+
});
|
|
4284
|
+
}
|
|
4285
|
+
}
|
|
4286
|
+
for (const t of activeTranscripts) {
|
|
4287
|
+
const meta = transcriptMeta.get(t.relPath);
|
|
4288
|
+
if (!meta?.workItem) continue;
|
|
4289
|
+
if (input.project && meta.project && meta.project !== input.project) continue;
|
|
4290
|
+
if (claimedByPath.has(t.relPath)) continue;
|
|
4291
|
+
findings.push({ kind: "work_item_unbacked_claim", path: t.relPath, workItem: safeDiagnosticValue(meta.workItem) });
|
|
4292
|
+
}
|
|
4293
|
+
const summary = {
|
|
4294
|
+
duplicate_claim: 0,
|
|
4295
|
+
malformed_claim_reference: 0,
|
|
4296
|
+
dangling_claim_reference: 0,
|
|
4297
|
+
project_mismatch: 0,
|
|
4298
|
+
work_item_unbacked_claim: 0
|
|
4299
|
+
};
|
|
4300
|
+
const hintLines = [];
|
|
4301
|
+
for (const f of findings) {
|
|
4302
|
+
summary[f.kind] += 1;
|
|
4303
|
+
if (f.kind === "duplicate_claim") hintLines.push(`duplicate_claim: ${f.path} \u2014 ${f.owners.join(", ")}`);
|
|
4304
|
+
else if (f.kind === "malformed_claim_reference") hintLines.push(`malformed_claim_reference: ${f.relDir} ${f.field}=${f.value}`);
|
|
4305
|
+
else if (f.kind === "dangling_claim_reference") hintLines.push(`dangling_claim_reference: ${f.path} \u2014 claimed by ${f.claimedBy}`);
|
|
4306
|
+
else if (f.kind === "project_mismatch") hintLines.push(`project_mismatch: ${f.path} \u2014 ${f.captureProject} claimed by ${f.claimedByProject}`);
|
|
4307
|
+
else hintLines.push(`work_item_unbacked_claim: ${f.path} \u2014 ${f.workItem}`);
|
|
4308
|
+
}
|
|
4309
|
+
if (hintLines.length === 0) hintLines.push("no claim-integrity findings");
|
|
4310
|
+
const humanHint = hintLines.join("\n");
|
|
4311
|
+
return { exitCode: ExitCode.OK, result: ok({ findings, summary, humanHint }) };
|
|
4312
|
+
}
|
|
4313
|
+
|
|
4164
4314
|
// src/commands/compound.ts
|
|
4165
4315
|
import { writeFile as writeFile6, mkdir as mkdir7, readdir as readdir6, unlink as unlink3 } from "fs/promises";
|
|
4166
|
-
import { join as
|
|
4316
|
+
import { join as join24 } from "path";
|
|
4167
4317
|
import { existsSync as existsSync7 } from "fs";
|
|
4168
|
-
import { readFile as
|
|
4318
|
+
import { readFile as readFile11 } from "fs/promises";
|
|
4169
4319
|
var RETRO_HEADING_RE = /^## \[(\d{4}-\d{2}-\d{2})(?:\s+[^\]]+)?\] retro \| loop cycle(?: (\d+))?: (.+)$/;
|
|
4170
4320
|
var FIELD_RE = {
|
|
4171
4321
|
improve: /^-\s+\*?\*?Improve:?\*?\*?\s*(.+)$/m,
|
|
@@ -4263,17 +4413,17 @@ function extractRetroFields(date, cycleName, block) {
|
|
|
4263
4413
|
};
|
|
4264
4414
|
}
|
|
4265
4415
|
async function runCompound(input) {
|
|
4266
|
-
const logPath =
|
|
4416
|
+
const logPath = join24(input.vault, "log.md");
|
|
4267
4417
|
let logText;
|
|
4268
4418
|
try {
|
|
4269
|
-
logText = await
|
|
4419
|
+
logText = await readFile11(logPath, "utf8");
|
|
4270
4420
|
} catch {
|
|
4271
4421
|
return { exitCode: ExitCode.FILE_NOT_FOUND, result: err("FILE_NOT_FOUND", { path: logPath }) };
|
|
4272
4422
|
}
|
|
4273
4423
|
const entries = parseRetroEntries(logText);
|
|
4274
4424
|
const promoted = [];
|
|
4275
4425
|
const skipped = [];
|
|
4276
|
-
const compoundDir =
|
|
4426
|
+
const compoundDir = join24(input.vault, "projects", input.project, "compound");
|
|
4277
4427
|
for (const entry of entries) {
|
|
4278
4428
|
const generalizeValue = entry.generalize.trim();
|
|
4279
4429
|
if (!/^yes/i.test(generalizeValue)) {
|
|
@@ -4281,7 +4431,7 @@ async function runCompound(input) {
|
|
|
4281
4431
|
continue;
|
|
4282
4432
|
}
|
|
4283
4433
|
const slug = slugify(entry.cycleName);
|
|
4284
|
-
const compoundPath =
|
|
4434
|
+
const compoundPath = join24(compoundDir, `${slug}.md`);
|
|
4285
4435
|
if (existsSync7(compoundPath)) {
|
|
4286
4436
|
skipped.push(entry.date);
|
|
4287
4437
|
continue;
|
|
@@ -4342,7 +4492,7 @@ async function runCompound(input) {
|
|
|
4342
4492
|
};
|
|
4343
4493
|
}
|
|
4344
4494
|
async function runCompoundDelete(input) {
|
|
4345
|
-
const projectDir =
|
|
4495
|
+
const projectDir = join24(input.vault, "projects", input.project);
|
|
4346
4496
|
if (!existsSync7(projectDir)) {
|
|
4347
4497
|
return {
|
|
4348
4498
|
exitCode: ExitCode.PROJECT_NOT_FOUND,
|
|
@@ -4350,7 +4500,7 @@ async function runCompoundDelete(input) {
|
|
|
4350
4500
|
};
|
|
4351
4501
|
}
|
|
4352
4502
|
const entryName = input.entry.replace(/\.md$/, "");
|
|
4353
|
-
const compoundPath =
|
|
4503
|
+
const compoundPath = join24(projectDir, "compound", `${entryName}.md`);
|
|
4354
4504
|
if (!existsSync7(compoundPath)) {
|
|
4355
4505
|
return {
|
|
4356
4506
|
exitCode: ExitCode.FILE_NOT_FOUND,
|
|
@@ -4384,7 +4534,7 @@ knowledge.md regenerated`
|
|
|
4384
4534
|
};
|
|
4385
4535
|
}
|
|
4386
4536
|
async function runCompoundList(input) {
|
|
4387
|
-
const compoundDir =
|
|
4537
|
+
const compoundDir = join24(input.vault, "projects", input.project, "compound");
|
|
4388
4538
|
if (!existsSync7(compoundDir)) {
|
|
4389
4539
|
return {
|
|
4390
4540
|
exitCode: ExitCode.OK,
|
|
@@ -4415,10 +4565,10 @@ could not read compound directory`
|
|
|
4415
4565
|
const entries = [];
|
|
4416
4566
|
for (const dirent of dirents) {
|
|
4417
4567
|
if (!dirent.isFile() || !dirent.name.endsWith(".md")) continue;
|
|
4418
|
-
const filePath =
|
|
4568
|
+
const filePath = join24(compoundDir, dirent.name);
|
|
4419
4569
|
let text;
|
|
4420
4570
|
try {
|
|
4421
|
-
text = await
|
|
4571
|
+
text = await readFile11(filePath, "utf8");
|
|
4422
4572
|
} catch {
|
|
4423
4573
|
continue;
|
|
4424
4574
|
}
|
|
@@ -4447,8 +4597,8 @@ no compound entries found`;
|
|
|
4447
4597
|
}
|
|
4448
4598
|
|
|
4449
4599
|
// src/commands/session-brief.ts
|
|
4450
|
-
import { mkdir as mkdir8, readFile as
|
|
4451
|
-
import { join as
|
|
4600
|
+
import { mkdir as mkdir8, readFile as readFile12, writeFile as writeFile7 } from "fs/promises";
|
|
4601
|
+
import { join as join25, relative, sep } from "path";
|
|
4452
4602
|
var MAX_WORDS = 900;
|
|
4453
4603
|
async function runSessionBrief(input) {
|
|
4454
4604
|
const { root: scanRoot } = resolveReadOnlyVaultRoot(input.vault);
|
|
@@ -4557,7 +4707,7 @@ async function resolveProject(input) {
|
|
|
4557
4707
|
const envProject = input.env?.SKILLWIKI_PROJECT;
|
|
4558
4708
|
if (envProject) return envProject;
|
|
4559
4709
|
const cwd = input.cwd ?? process.cwd();
|
|
4560
|
-
const projectDotenv = await readProjectSlug(
|
|
4710
|
+
const projectDotenv = await readProjectSlug(join25(cwd, ".skillwiki", ".env"));
|
|
4561
4711
|
if (projectDotenv) return projectDotenv;
|
|
4562
4712
|
const inferred = inferProjectFromPath(input.vault, cwd);
|
|
4563
4713
|
if (inferred) return inferred;
|
|
@@ -4566,7 +4716,7 @@ async function resolveProject(input) {
|
|
|
4566
4716
|
async function readProjectSlug(file) {
|
|
4567
4717
|
let text;
|
|
4568
4718
|
try {
|
|
4569
|
-
text = await
|
|
4719
|
+
text = await readFile12(file, "utf8");
|
|
4570
4720
|
} catch {
|
|
4571
4721
|
return void 0;
|
|
4572
4722
|
}
|
|
@@ -4657,7 +4807,7 @@ async function loadTrendDigests(typedPages) {
|
|
|
4657
4807
|
return out;
|
|
4658
4808
|
}
|
|
4659
4809
|
async function loadSessionPins(vault, project) {
|
|
4660
|
-
const text = await readIfExists(
|
|
4810
|
+
const text = await readIfExists(join25(vault, "meta", "session-pins.md"));
|
|
4661
4811
|
if (!text) return [];
|
|
4662
4812
|
const fm = extractFrontmatter(text);
|
|
4663
4813
|
if (!fm.ok) return [];
|
|
@@ -4776,7 +4926,7 @@ function satelliteHealthWarnings(warning) {
|
|
|
4776
4926
|
return warning ? [warning] : [];
|
|
4777
4927
|
}
|
|
4778
4928
|
async function loadHealthWarnings(vault) {
|
|
4779
|
-
const text = await readIfExists(
|
|
4929
|
+
const text = await readIfExists(join25(vault, ".skillwiki", "health.json"));
|
|
4780
4930
|
if (!text) return [];
|
|
4781
4931
|
try {
|
|
4782
4932
|
const parsed = JSON.parse(text);
|
|
@@ -4789,7 +4939,7 @@ async function loadHealthWarnings(vault) {
|
|
|
4789
4939
|
}
|
|
4790
4940
|
}
|
|
4791
4941
|
async function loadMemoryTopics(vault, project) {
|
|
4792
|
-
const text = await readIfExists(
|
|
4942
|
+
const text = await readIfExists(join25(vault, ".skillwiki", "memory", project, "topics.json"));
|
|
4793
4943
|
if (!text) return [];
|
|
4794
4944
|
try {
|
|
4795
4945
|
const parsed = JSON.parse(text);
|
|
@@ -4814,11 +4964,11 @@ async function loadMemoryTopics(vault, project) {
|
|
|
4814
4964
|
}
|
|
4815
4965
|
}
|
|
4816
4966
|
async function writeBriefArtifacts(vault, input) {
|
|
4817
|
-
const metaPath =
|
|
4818
|
-
const cacheMdPath =
|
|
4819
|
-
const cacheJsonPath =
|
|
4820
|
-
await mkdir8(
|
|
4821
|
-
await mkdir8(
|
|
4967
|
+
const metaPath = join25(vault, "meta", "latest-session-brief.md");
|
|
4968
|
+
const cacheMdPath = join25(vault, ".skillwiki", "session-brief.md");
|
|
4969
|
+
const cacheJsonPath = join25(vault, ".skillwiki", "session-brief.json");
|
|
4970
|
+
await mkdir8(join25(vault, "meta"), { recursive: true });
|
|
4971
|
+
await mkdir8(join25(vault, ".skillwiki"), { recursive: true });
|
|
4822
4972
|
const committed = renderCommittedBrief(input);
|
|
4823
4973
|
const previousComparable = comparableBrief(await readIfExists(metaPath));
|
|
4824
4974
|
const nextComparable = comparableBrief(committed);
|
|
@@ -4888,7 +5038,7 @@ function renderCommittedBrief(input) {
|
|
|
4888
5038
|
].filter((line) => line !== "").join("\n");
|
|
4889
5039
|
}
|
|
4890
5040
|
async function rebuildRootIndexProjection(vault) {
|
|
4891
|
-
const before = await readIfExists(
|
|
5041
|
+
const before = await readIfExists(join25(vault, "index.md"));
|
|
4892
5042
|
if (!before) return false;
|
|
4893
5043
|
const projection = await renderRootIndex({ vault, currentText: before });
|
|
4894
5044
|
if (!projection.ok) return false;
|
|
@@ -4898,7 +5048,7 @@ async function rebuildRootIndexProjection(vault) {
|
|
|
4898
5048
|
}
|
|
4899
5049
|
async function readIfExists(path) {
|
|
4900
5050
|
try {
|
|
4901
|
-
return await
|
|
5051
|
+
return await readFile12(path, "utf8");
|
|
4902
5052
|
} catch {
|
|
4903
5053
|
return "";
|
|
4904
5054
|
}
|
|
@@ -4940,14 +5090,14 @@ function dateFromPath(path) {
|
|
|
4940
5090
|
}
|
|
4941
5091
|
|
|
4942
5092
|
// src/commands/ingest.ts
|
|
4943
|
-
import { readFile as
|
|
4944
|
-
import { join as
|
|
5093
|
+
import { readFile as readFile14, open, unlink as unlink4, mkdir as mkdir10 } from "fs/promises";
|
|
5094
|
+
import { join as join27 } from "path";
|
|
4945
5095
|
import { createHash as createHash4 } from "crypto";
|
|
4946
5096
|
|
|
4947
5097
|
// src/commands/page-publish.ts
|
|
4948
5098
|
import { readFileSync as readFileSync12, realpathSync } from "fs";
|
|
4949
|
-
import { mkdir as mkdir9, readFile as
|
|
4950
|
-
import { dirname as dirname6, join as
|
|
5099
|
+
import { mkdir as mkdir9, readFile as readFile13 } from "fs/promises";
|
|
5100
|
+
import { dirname as dirname6, join as join26, resolve as resolve3 } from "path";
|
|
4951
5101
|
|
|
4952
5102
|
// src/utils/publication-approval.ts
|
|
4953
5103
|
import { createHash as createHash3 } from "crypto";
|
|
@@ -5240,7 +5390,7 @@ async function refreshProjectIndexForTarget(vault, projectSlugs, today) {
|
|
|
5240
5390
|
for (const slug of projectSlugs) {
|
|
5241
5391
|
const rendered = await renderProjectIndex(vault, slug, { today });
|
|
5242
5392
|
if (!rendered.ok) return rendered;
|
|
5243
|
-
const indexPath =
|
|
5393
|
+
const indexPath = join26(vault, rendered.data.index_path);
|
|
5244
5394
|
try {
|
|
5245
5395
|
await mkdir9(dirname6(indexPath), { recursive: true });
|
|
5246
5396
|
} catch (error) {
|
|
@@ -5249,7 +5399,7 @@ async function refreshProjectIndexForTarget(vault, projectSlugs, today) {
|
|
|
5249
5399
|
const written = await atomicWriteText(indexPath, rendered.data.text);
|
|
5250
5400
|
if (!written.ok) return written;
|
|
5251
5401
|
try {
|
|
5252
|
-
const visible = await
|
|
5402
|
+
const visible = await readFile13(indexPath, "utf8");
|
|
5253
5403
|
if (visible !== rendered.data.text) {
|
|
5254
5404
|
return err("WRITE_FAILED", { path: indexPath, message: "project index verification failed" });
|
|
5255
5405
|
}
|
|
@@ -5325,7 +5475,7 @@ function preparePagePublicationFromContent(input) {
|
|
|
5325
5475
|
async function preparePagePublication(input) {
|
|
5326
5476
|
let content;
|
|
5327
5477
|
try {
|
|
5328
|
-
content = await
|
|
5478
|
+
content = await readFile13(input.draftPath, "utf8");
|
|
5329
5479
|
} catch (error) {
|
|
5330
5480
|
return err("FILE_NOT_FOUND", { path: input.draftPath, message: String(error) });
|
|
5331
5481
|
}
|
|
@@ -5397,10 +5547,10 @@ async function runLockedPrimaryStages(input, vault, deps) {
|
|
|
5397
5547
|
ExitCode.VAULT_PATH_INVALID
|
|
5398
5548
|
);
|
|
5399
5549
|
}
|
|
5400
|
-
const schemaPath =
|
|
5550
|
+
const schemaPath = join26(vault, "SCHEMA.md");
|
|
5401
5551
|
let schemaText;
|
|
5402
5552
|
try {
|
|
5403
|
-
schemaText = await
|
|
5553
|
+
schemaText = await readFile13(schemaPath, "utf8");
|
|
5404
5554
|
} catch (error) {
|
|
5405
5555
|
return lockedFailure("schema", state, err("WRITE_FAILED", { message: String(error) }));
|
|
5406
5556
|
}
|
|
@@ -5430,8 +5580,8 @@ async function runLockedPrimaryStages(input, vault, deps) {
|
|
|
5430
5580
|
let visibleSchema;
|
|
5431
5581
|
try {
|
|
5432
5582
|
[visible, visibleSchema] = await Promise.all([
|
|
5433
|
-
|
|
5434
|
-
|
|
5583
|
+
readFile13(input.targetPath, "utf8"),
|
|
5584
|
+
readFile13(schemaPath, "utf8")
|
|
5435
5585
|
]);
|
|
5436
5586
|
} catch (error) {
|
|
5437
5587
|
return lockedFailure("verify", state, err("WRITE_FAILED", { message: String(error) }));
|
|
@@ -5535,17 +5685,17 @@ function renderPublicationLog(input, added) {
|
|
|
5535
5685
|
}
|
|
5536
5686
|
async function readPageChanged(targetPath, content) {
|
|
5537
5687
|
try {
|
|
5538
|
-
return ok(await
|
|
5688
|
+
return ok(await readFile13(targetPath, "utf8") !== content);
|
|
5539
5689
|
} catch (error) {
|
|
5540
5690
|
if (error.code === "ENOENT") return ok(true);
|
|
5541
5691
|
return err("WRITE_FAILED", { path: targetPath, message: String(error) });
|
|
5542
5692
|
}
|
|
5543
5693
|
}
|
|
5544
5694
|
async function previewPreparedPagePublication(input, vault) {
|
|
5545
|
-
const schemaPath =
|
|
5695
|
+
const schemaPath = join26(vault, "SCHEMA.md");
|
|
5546
5696
|
let schemaText;
|
|
5547
5697
|
try {
|
|
5548
|
-
schemaText = await
|
|
5698
|
+
schemaText = await readFile13(schemaPath, "utf8");
|
|
5549
5699
|
} catch (error) {
|
|
5550
5700
|
const result = err("FILE_NOT_FOUND", { path: schemaPath, message: String(error) });
|
|
5551
5701
|
return { exitCode: ExitCode.FILE_NOT_FOUND, result };
|
|
@@ -5557,10 +5707,10 @@ async function previewPreparedPagePublication(input, vault) {
|
|
|
5557
5707
|
if (!reconciled.ok) return { exitCode: errorExitCode(reconciled.error), result: reconciled };
|
|
5558
5708
|
const pageChanged = await readPageChanged(input.targetPath, input.page.content);
|
|
5559
5709
|
if (!pageChanged.ok) return { exitCode: errorExitCode(pageChanged.error), result: pageChanged };
|
|
5560
|
-
const indexPath =
|
|
5710
|
+
const indexPath = join26(vault, "index.md");
|
|
5561
5711
|
let indexText;
|
|
5562
5712
|
try {
|
|
5563
|
-
indexText = await
|
|
5713
|
+
indexText = await readFile13(indexPath, "utf8");
|
|
5564
5714
|
} catch (error) {
|
|
5565
5715
|
const result = err("FILE_NOT_FOUND", { path: indexPath, message: String(error) });
|
|
5566
5716
|
return { exitCode: ExitCode.FILE_NOT_FOUND, result };
|
|
@@ -5576,7 +5726,7 @@ async function previewPreparedPagePublication(input, vault) {
|
|
|
5576
5726
|
for (const projectSlug of projectSlugsForPublication(input.page.target, input.page.content)) {
|
|
5577
5727
|
const renderedProject = await renderProjectIndex(vault, projectSlug, { today: input.date });
|
|
5578
5728
|
if (!renderedProject.ok) return { exitCode: errorExitCode(renderedProject.error), result: renderedProject };
|
|
5579
|
-
const projectIndexPath =
|
|
5729
|
+
const projectIndexPath = join26(vault, renderedProject.data.index_path);
|
|
5580
5730
|
const projectIndexChanged = await readPageChanged(projectIndexPath, renderedProject.data.text);
|
|
5581
5731
|
if (!projectIndexChanged.ok) {
|
|
5582
5732
|
return { exitCode: errorExitCode(projectIndexChanged.error), result: projectIndexChanged };
|
|
@@ -5586,10 +5736,10 @@ async function previewPreparedPagePublication(input, vault) {
|
|
|
5586
5736
|
projectIndexPaths.push(renderedProject.data.index_path);
|
|
5587
5737
|
}
|
|
5588
5738
|
}
|
|
5589
|
-
const logPath =
|
|
5739
|
+
const logPath = join26(vault, "log.md");
|
|
5590
5740
|
let logText;
|
|
5591
5741
|
try {
|
|
5592
|
-
logText = await
|
|
5742
|
+
logText = await readFile13(logPath, "utf8");
|
|
5593
5743
|
} catch (error) {
|
|
5594
5744
|
const result = err("FILE_NOT_FOUND", { path: logPath, message: String(error) });
|
|
5595
5745
|
return { exitCode: ExitCode.FILE_NOT_FOUND, result };
|
|
@@ -5883,7 +6033,7 @@ function buildTypedContent(title, ingested, type, tags, rawRelPath, provenance)
|
|
|
5883
6033
|
}
|
|
5884
6034
|
async function resolveRawCapture(input) {
|
|
5885
6035
|
try {
|
|
5886
|
-
const existing = await
|
|
6036
|
+
const existing = await readFile14(input.path, "utf8");
|
|
5887
6037
|
const frontmatter = extractFrontmatter(existing);
|
|
5888
6038
|
if (!frontmatter.ok) {
|
|
5889
6039
|
return err("INGEST_VALIDATION_FAILED", {
|
|
@@ -6022,7 +6172,7 @@ async function runIngest(input, pagePublishDeps = defaultPagePublishDeps()) {
|
|
|
6022
6172
|
sourceContent = fetchResult.data.body;
|
|
6023
6173
|
} else {
|
|
6024
6174
|
try {
|
|
6025
|
-
sourceContent = await
|
|
6175
|
+
sourceContent = await readFile14(input.source, "utf8");
|
|
6026
6176
|
} catch {
|
|
6027
6177
|
return {
|
|
6028
6178
|
exitCode: ExitCode.FILE_NOT_FOUND,
|
|
@@ -6047,7 +6197,7 @@ async function runIngest(input, pagePublishDeps = defaultPagePublishDeps()) {
|
|
|
6047
6197
|
const rawRelPath = `raw/articles/${slug}.md`;
|
|
6048
6198
|
const typedDir = TYPE_DIR[input.type] ?? `${input.type}s`;
|
|
6049
6199
|
const typedRelPath = `${typedDir}/${slug}.md`;
|
|
6050
|
-
const rawAbsPath =
|
|
6200
|
+
const rawAbsPath = join27(input.vault, rawRelPath);
|
|
6051
6201
|
const identity = assessSourceIdentity({
|
|
6052
6202
|
rawPath: rawRelPath,
|
|
6053
6203
|
sourceUrl: sourceUrl ?? void 0,
|
|
@@ -6091,11 +6241,11 @@ async function runIngest(input, pagePublishDeps = defaultPagePublishDeps()) {
|
|
|
6091
6241
|
);
|
|
6092
6242
|
if (!input.dryRun) {
|
|
6093
6243
|
try {
|
|
6094
|
-
await mkdir10(
|
|
6244
|
+
await mkdir10(join27(input.vault, typedDir), { recursive: true });
|
|
6095
6245
|
} catch (error) {
|
|
6096
6246
|
return {
|
|
6097
6247
|
exitCode: ExitCode.WRITE_FAILED,
|
|
6098
|
-
result: err("WRITE_FAILED", { path:
|
|
6248
|
+
result: err("WRITE_FAILED", { path: join27(input.vault, typedDir), message: String(error) })
|
|
6099
6249
|
};
|
|
6100
6250
|
}
|
|
6101
6251
|
}
|
|
@@ -6149,11 +6299,11 @@ async function runIngest(input, pagePublishDeps = defaultPagePublishDeps()) {
|
|
|
6149
6299
|
preflight: pagePublishDeps.preflight,
|
|
6150
6300
|
mutate: async (receipt) => {
|
|
6151
6301
|
try {
|
|
6152
|
-
await mkdir10(
|
|
6302
|
+
await mkdir10(join27(input.vault, "raw", "articles"), { recursive: true });
|
|
6153
6303
|
} catch (error) {
|
|
6154
6304
|
return {
|
|
6155
6305
|
exitCode: ExitCode.WRITE_FAILED,
|
|
6156
|
-
result: err("WRITE_FAILED", { path:
|
|
6306
|
+
result: err("WRITE_FAILED", { path: join27(input.vault, "raw", "articles"), message: String(error) })
|
|
6157
6307
|
};
|
|
6158
6308
|
}
|
|
6159
6309
|
const rawWrite = await writeResolvedRaw({
|
|
@@ -6389,8 +6539,8 @@ ${body}`;
|
|
|
6389
6539
|
}
|
|
6390
6540
|
|
|
6391
6541
|
// src/commands/tag-reconcile.ts
|
|
6392
|
-
import { readFile as
|
|
6393
|
-
import { join as
|
|
6542
|
+
import { readFile as readFile15 } from "fs/promises";
|
|
6543
|
+
import { join as join28, posix } from "path";
|
|
6394
6544
|
var TYPED_TARGET_RE = /^(entities|concepts|comparisons|queries|meta)\/[a-z0-9][a-z0-9./_-]*\.md$/;
|
|
6395
6545
|
function errorExitCode2(error) {
|
|
6396
6546
|
switch (error) {
|
|
@@ -6433,7 +6583,7 @@ function asTagArray(frontmatter, path) {
|
|
|
6433
6583
|
async function readTagsFromFile(path) {
|
|
6434
6584
|
let text;
|
|
6435
6585
|
try {
|
|
6436
|
-
text = await
|
|
6586
|
+
text = await readFile15(path, "utf8");
|
|
6437
6587
|
} catch (error) {
|
|
6438
6588
|
if (error.code === "ENOENT") {
|
|
6439
6589
|
return { exitCode: ExitCode.FILE_NOT_FOUND, result: err("FILE_NOT_FOUND", { path }) };
|
|
@@ -6454,7 +6604,7 @@ async function resolveRequestedTags(input, page) {
|
|
|
6454
6604
|
result: err("INVALID_FRONTMATTER", { message: "explicit tags must be an array of strings" })
|
|
6455
6605
|
};
|
|
6456
6606
|
}
|
|
6457
|
-
const source = input.from ?? (explicit.length === 0 ?
|
|
6607
|
+
const source = input.from ?? (explicit.length === 0 ? join28(input.vault, page) : void 0);
|
|
6458
6608
|
if (!source) return { exitCode: ExitCode.OK, result: ok({ tags: [...new Set(explicit)].sort() }) };
|
|
6459
6609
|
const sourced = await readTagsFromFile(source);
|
|
6460
6610
|
if (!sourced.result.ok) return { exitCode: sourced.exitCode, result: sourced.result };
|
|
@@ -6465,7 +6615,7 @@ async function resolveRequestedTags(input, page) {
|
|
|
6465
6615
|
}
|
|
6466
6616
|
async function readSchema(schemaPath) {
|
|
6467
6617
|
try {
|
|
6468
|
-
return { exitCode: ExitCode.OK, result: ok(await
|
|
6618
|
+
return { exitCode: ExitCode.OK, result: ok(await readFile15(schemaPath, "utf8")) };
|
|
6469
6619
|
} catch (error) {
|
|
6470
6620
|
if (error.code === "ENOENT") {
|
|
6471
6621
|
return { exitCode: ExitCode.FILE_NOT_FOUND, result: err("FILE_NOT_FOUND", { path: schemaPath }) };
|
|
@@ -6493,7 +6643,7 @@ function previewResult(page, tags, reconciled, dryRun, filesChanged) {
|
|
|
6493
6643
|
};
|
|
6494
6644
|
}
|
|
6495
6645
|
async function reconcileTagsWhileLocked(input, page, tags, comment) {
|
|
6496
|
-
const schemaPath =
|
|
6646
|
+
const schemaPath = join28(input.vault, "SCHEMA.md");
|
|
6497
6647
|
const current = await readSchema(schemaPath);
|
|
6498
6648
|
if (!current.result.ok) return { exitCode: current.exitCode, result: current.result };
|
|
6499
6649
|
const next = reconcileTaxonomyDocument(current.result.data, { tags, comment });
|
|
@@ -6504,7 +6654,7 @@ async function reconcileTagsWhileLocked(input, page, tags, comment) {
|
|
|
6504
6654
|
}
|
|
6505
6655
|
let verifiedText;
|
|
6506
6656
|
try {
|
|
6507
|
-
verifiedText = await
|
|
6657
|
+
verifiedText = await readFile15(schemaPath, "utf8");
|
|
6508
6658
|
} catch (error) {
|
|
6509
6659
|
return {
|
|
6510
6660
|
exitCode: ExitCode.WRITE_FAILED,
|
|
@@ -6530,7 +6680,7 @@ async function runTagReconcile(input) {
|
|
|
6530
6680
|
const comment = taxonomyCommentForPage(page.data, date, input.reason);
|
|
6531
6681
|
if (!comment.ok) return { exitCode: ExitCode.SCHEME_REJECTED, result: comment };
|
|
6532
6682
|
if (!input.write) {
|
|
6533
|
-
const schema = await readSchema(
|
|
6683
|
+
const schema = await readSchema(join28(input.vault, "SCHEMA.md"));
|
|
6534
6684
|
if (!schema.result.ok) return { exitCode: schema.exitCode, result: schema.result };
|
|
6535
6685
|
const preview = reconcileTaxonomyDocument(schema.result.data, { tags, comment: comment.data });
|
|
6536
6686
|
return previewResult(page.data, tags, preview, true, []);
|
|
@@ -6583,8 +6733,8 @@ async function runTagReconcile(input) {
|
|
|
6583
6733
|
|
|
6584
6734
|
// src/commands/project-page-publish.ts
|
|
6585
6735
|
import { realpathSync as realpathSync4 } from "fs";
|
|
6586
|
-
import { mkdir as mkdir11, readFile as
|
|
6587
|
-
import { dirname as dirname9, join as
|
|
6736
|
+
import { mkdir as mkdir11, readFile as readFile16 } from "fs/promises";
|
|
6737
|
+
import { dirname as dirname9, join as join30, resolve as resolve5 } from "path";
|
|
6588
6738
|
|
|
6589
6739
|
// src/utils/architecture-page.ts
|
|
6590
6740
|
import { lstatSync, realpathSync as realpathSync2 } from "fs";
|
|
@@ -6745,7 +6895,7 @@ import {
|
|
|
6745
6895
|
writeFileSync as writeFileSync5
|
|
6746
6896
|
} from "fs";
|
|
6747
6897
|
import { homedir } from "os";
|
|
6748
|
-
import { dirname as dirname8, join as
|
|
6898
|
+
import { dirname as dirname8, join as join29 } from "path";
|
|
6749
6899
|
var PUBLICATION_JOURNAL_SCHEMA = "skillwiki-publication-operation-v1";
|
|
6750
6900
|
var PHASE_ORDER2 = [
|
|
6751
6901
|
"locked",
|
|
@@ -6774,16 +6924,16 @@ function vaultIdentity(vaultPath) {
|
|
|
6774
6924
|
return sha256Hex(real).slice(0, 16);
|
|
6775
6925
|
}
|
|
6776
6926
|
function publicationJournalRoot(home = process.env.HOME || homedir()) {
|
|
6777
|
-
return
|
|
6927
|
+
return join29(home, ".skillwiki", "publication-operations");
|
|
6778
6928
|
}
|
|
6779
6929
|
function resolveJournalPaths(vaultPath, operationId2, home = process.env.HOME || homedir()) {
|
|
6780
6930
|
const identity = vaultIdentity(vaultPath);
|
|
6781
6931
|
const rootDir = publicationJournalRoot(home);
|
|
6782
|
-
const vaultDir =
|
|
6932
|
+
const vaultDir = join29(rootDir, identity);
|
|
6783
6933
|
return {
|
|
6784
6934
|
rootDir,
|
|
6785
6935
|
vaultDir,
|
|
6786
|
-
journalPath:
|
|
6936
|
+
journalPath: join29(vaultDir, `${operationId2}.json`)
|
|
6787
6937
|
};
|
|
6788
6938
|
}
|
|
6789
6939
|
function ensurePrivateDir(dir) {
|
|
@@ -7068,7 +7218,7 @@ async function observeStage2(deps, stage) {
|
|
|
7068
7218
|
}
|
|
7069
7219
|
async function readPriorTargetSha(targetPath) {
|
|
7070
7220
|
try {
|
|
7071
|
-
const text = await
|
|
7221
|
+
const text = await readFile16(targetPath, "utf8");
|
|
7072
7222
|
return ok(sha256Hex(text));
|
|
7073
7223
|
} catch (error) {
|
|
7074
7224
|
if (error.code === "ENOENT") return ok("absent");
|
|
@@ -7093,7 +7243,7 @@ function validateLogNote(logNote) {
|
|
|
7093
7243
|
async function prepareProjectPagePublication(input) {
|
|
7094
7244
|
let content;
|
|
7095
7245
|
try {
|
|
7096
|
-
content = await
|
|
7246
|
+
content = await readFile16(input.draftPath, "utf8");
|
|
7097
7247
|
} catch (error) {
|
|
7098
7248
|
return err("FILE_NOT_FOUND", { path: input.draftPath, message: String(error) });
|
|
7099
7249
|
}
|
|
@@ -7202,10 +7352,10 @@ function phaseFailure2(stage, prepared, published, verified, cause, context = {}
|
|
|
7202
7352
|
};
|
|
7203
7353
|
}
|
|
7204
7354
|
async function previewProjectPagePublication(prepared, vault) {
|
|
7205
|
-
const schemaPath =
|
|
7355
|
+
const schemaPath = join30(vault, "SCHEMA.md");
|
|
7206
7356
|
let schemaText;
|
|
7207
7357
|
try {
|
|
7208
|
-
schemaText = await
|
|
7358
|
+
schemaText = await readFile16(schemaPath, "utf8");
|
|
7209
7359
|
} catch (error) {
|
|
7210
7360
|
return {
|
|
7211
7361
|
exitCode: ExitCode.FILE_NOT_FOUND,
|
|
@@ -7228,18 +7378,18 @@ async function previewProjectPagePublication(prepared, vault) {
|
|
|
7228
7378
|
}
|
|
7229
7379
|
let projectIndexChanged = true;
|
|
7230
7380
|
if (projectIndex.ok) {
|
|
7231
|
-
const indexPath =
|
|
7381
|
+
const indexPath = join30(vault, projectIndex.data.index_path);
|
|
7232
7382
|
try {
|
|
7233
|
-
const existing = await
|
|
7383
|
+
const existing = await readFile16(indexPath, "utf8");
|
|
7234
7384
|
projectIndexChanged = existing !== projectIndex.data.text || pageChanged;
|
|
7235
7385
|
} catch {
|
|
7236
7386
|
projectIndexChanged = true;
|
|
7237
7387
|
}
|
|
7238
7388
|
}
|
|
7239
|
-
const logPath =
|
|
7389
|
+
const logPath = join30(vault, "log.md");
|
|
7240
7390
|
let logAppended = true;
|
|
7241
7391
|
try {
|
|
7242
|
-
const logText = await
|
|
7392
|
+
const logText = await readFile16(logPath, "utf8");
|
|
7243
7393
|
logAppended = !logText.includes(`<!-- skillwiki-project-page-publish:${prepared.operationId} -->`);
|
|
7244
7394
|
} catch {
|
|
7245
7395
|
return {
|
|
@@ -7363,11 +7513,11 @@ async function runLockedStages(prepared, vault, deps, journalHome) {
|
|
|
7363
7513
|
if (journalHook) {
|
|
7364
7514
|
return { ok: false, exitCode: ExitCode.WRITE_FAILED, stage: "journal", state, cause: journalHook };
|
|
7365
7515
|
}
|
|
7366
|
-
const schemaPath =
|
|
7516
|
+
const schemaPath = join30(vault, "SCHEMA.md");
|
|
7367
7517
|
{
|
|
7368
7518
|
let schemaText;
|
|
7369
7519
|
try {
|
|
7370
|
-
schemaText = await
|
|
7520
|
+
schemaText = await readFile16(schemaPath, "utf8");
|
|
7371
7521
|
} catch (error) {
|
|
7372
7522
|
return {
|
|
7373
7523
|
ok: false,
|
|
@@ -7455,8 +7605,8 @@ async function runLockedStages(prepared, vault, deps, journalHome) {
|
|
|
7455
7605
|
let visibleSchema;
|
|
7456
7606
|
try {
|
|
7457
7607
|
[visible, visibleSchema] = await Promise.all([
|
|
7458
|
-
|
|
7459
|
-
|
|
7608
|
+
readFile16(prepared.targetPath, "utf8"),
|
|
7609
|
+
readFile16(schemaPath, "utf8")
|
|
7460
7610
|
]);
|
|
7461
7611
|
} catch (error) {
|
|
7462
7612
|
return {
|
|
@@ -7510,7 +7660,7 @@ async function runLockedStages(prepared, vault, deps, journalHome) {
|
|
|
7510
7660
|
cause: rendered
|
|
7511
7661
|
};
|
|
7512
7662
|
}
|
|
7513
|
-
const knowledgePath =
|
|
7663
|
+
const knowledgePath = join30(vault, rendered.data.index_path);
|
|
7514
7664
|
try {
|
|
7515
7665
|
await mkdir11(dirname9(knowledgePath), { recursive: true });
|
|
7516
7666
|
} catch (error) {
|
|
@@ -7535,7 +7685,7 @@ async function runLockedStages(prepared, vault, deps, journalHome) {
|
|
|
7535
7685
|
state.projectIndexChanged = knowledgeWrite.data.changed;
|
|
7536
7686
|
if (state.projectIndexChanged) state.changed.add(rendered.data.index_path);
|
|
7537
7687
|
try {
|
|
7538
|
-
const visibleIndex = await
|
|
7688
|
+
const visibleIndex = await readFile16(knowledgePath, "utf8");
|
|
7539
7689
|
if (visibleIndex !== rendered.data.text) {
|
|
7540
7690
|
return {
|
|
7541
7691
|
ok: false,
|
|
@@ -7909,7 +8059,7 @@ import { existsSync as existsSync9, mkdirSync as mkdirSync4, appendFileSync } fr
|
|
|
7909
8059
|
import { createHash as createHash5 } from "crypto";
|
|
7910
8060
|
import { execSync as execSync3, spawn } from "child_process";
|
|
7911
8061
|
import { platform as platform2 } from "os";
|
|
7912
|
-
import { join as
|
|
8062
|
+
import { join as join31, resolve as resolvePath } from "path";
|
|
7913
8063
|
var MAINTENANCE_SCHEMA_VERSION = 1;
|
|
7914
8064
|
var MAINTENANCE_COMMAND = "snapshot-maintenance journal clear-stale";
|
|
7915
8065
|
function canonicalize(p) {
|
|
@@ -7972,7 +8122,7 @@ async function runSnapshotMaintenanceDryRun(input) {
|
|
|
7972
8122
|
audit(makeAuditEvent(input, fleetLoad.hostId, now, "refusal", "MAINTENANCE_WRONG_WORKTREE"));
|
|
7973
8123
|
return { exitCode: ExitCode.PROTECTED_SNAPSHOTTER_WRITE_BLOCKED, result: refusalErr("MAINTENANCE_WRONG_WORKTREE", `requested path '${requested}' is not the configured snapshot worktree '${canonicalize(configuredWorktree)}'`) };
|
|
7974
8124
|
}
|
|
7975
|
-
if (!existsSync9(requested) || !existsSync9(
|
|
8125
|
+
if (!existsSync9(requested) || !existsSync9(join31(requested, ".git"))) {
|
|
7976
8126
|
audit(makeAuditEvent(input, fleetLoad.hostId, now, "refusal", "MAINTENANCE_MISSING_GIT_REPO"));
|
|
7977
8127
|
return { exitCode: ExitCode.PROTECTED_SNAPSHOTTER_WRITE_BLOCKED, result: refusalErr("MAINTENANCE_MISSING_GIT_REPO", `snapshot worktree is not a git repository: ${requested}`) };
|
|
7978
8128
|
}
|
|
@@ -8052,14 +8202,14 @@ async function resolveLiveVault(input) {
|
|
|
8052
8202
|
return resolved.ok ? canonicalize(resolved.data.path) : void 0;
|
|
8053
8203
|
}
|
|
8054
8204
|
function snapshotMaintenanceAuditLogPath(home) {
|
|
8055
|
-
const stateDir = platform2() === "darwin" ?
|
|
8056
|
-
return
|
|
8205
|
+
const stateDir = platform2() === "darwin" ? join31(home, "Library", "Application Support", "vault-sync") : join31(home, ".local", "state", "vault-sync");
|
|
8206
|
+
return join31(stateDir, "snapshot-maintenance-audit.jsonl");
|
|
8057
8207
|
}
|
|
8058
8208
|
function defaultAuditSink(home) {
|
|
8059
8209
|
return (event) => {
|
|
8060
8210
|
try {
|
|
8061
8211
|
const logPath = snapshotMaintenanceAuditLogPath(home);
|
|
8062
|
-
mkdirSync4(
|
|
8212
|
+
mkdirSync4(join31(logPath, ".."), { recursive: true });
|
|
8063
8213
|
appendFileSync(logPath, JSON.stringify(event) + "\n", { encoding: "utf8" });
|
|
8064
8214
|
} catch {
|
|
8065
8215
|
}
|
|
@@ -8220,7 +8370,7 @@ function releaseSnapshotFlock(handle) {
|
|
|
8220
8370
|
|
|
8221
8371
|
// src/commands/backup.ts
|
|
8222
8372
|
import { statSync as statSync3, readdirSync as readdirSync2, readFileSync as readFileSync15, mkdirSync as mkdirSync5, writeFileSync as writeFileSync6 } from "fs";
|
|
8223
|
-
import { join as
|
|
8373
|
+
import { join as join32, relative as relative3, dirname as dirname10 } from "path";
|
|
8224
8374
|
import { PutObjectCommand, HeadObjectCommand, ListObjectsV2Command, GetObjectCommand, DeleteObjectsCommand } from "@aws-sdk/client-s3";
|
|
8225
8375
|
|
|
8226
8376
|
// src/utils/s3-client.ts
|
|
@@ -8244,7 +8394,7 @@ var SKIP_DIRS = /* @__PURE__ */ new Set([".git", ".obsidian", "_archive", "node_
|
|
|
8244
8394
|
function* walkMarkdown(dir, base) {
|
|
8245
8395
|
for (const entry of readdirSync2(dir, { withFileTypes: true })) {
|
|
8246
8396
|
if (SKIP_DIRS.has(entry.name)) continue;
|
|
8247
|
-
const full =
|
|
8397
|
+
const full = join32(dir, entry.name);
|
|
8248
8398
|
if (entry.isDirectory()) {
|
|
8249
8399
|
yield* walkMarkdown(full, base);
|
|
8250
8400
|
} else if (entry.name.endsWith(".md")) {
|
|
@@ -8267,7 +8417,7 @@ async function runBackupSync(input) {
|
|
|
8267
8417
|
let failed = 0;
|
|
8268
8418
|
const files = [...walkMarkdown(input.vault, input.vault)];
|
|
8269
8419
|
for (const relPath of files) {
|
|
8270
|
-
const absPath =
|
|
8420
|
+
const absPath = join32(input.vault, relPath);
|
|
8271
8421
|
const localStat = statSync3(absPath);
|
|
8272
8422
|
let needsUpload = true;
|
|
8273
8423
|
try {
|
|
@@ -8343,7 +8493,7 @@ async function runBackupRestore(input) {
|
|
|
8343
8493
|
const objects = list.Contents ?? [];
|
|
8344
8494
|
for (const obj of objects) {
|
|
8345
8495
|
if (!obj.Key) continue;
|
|
8346
|
-
const localPath =
|
|
8496
|
+
const localPath = join32(target, obj.Key);
|
|
8347
8497
|
try {
|
|
8348
8498
|
const localStat = statSync3(localPath);
|
|
8349
8499
|
if (obj.LastModified && localStat.mtime > obj.LastModified) {
|
|
@@ -8390,8 +8540,8 @@ async function runBackupRestore(input) {
|
|
|
8390
8540
|
|
|
8391
8541
|
// src/commands/status.ts
|
|
8392
8542
|
import { existsSync as existsSync10, statSync as statSync4 } from "fs";
|
|
8393
|
-
import { readFile as
|
|
8394
|
-
import { join as
|
|
8543
|
+
import { readFile as readFile17 } from "fs/promises";
|
|
8544
|
+
import { join as join33 } from "path";
|
|
8395
8545
|
var FUSE_NO_MIRROR_NOTE = "FUSE vault with no read mirror - status scan may be slow";
|
|
8396
8546
|
async function runStatus(input) {
|
|
8397
8547
|
if (!existsSync10(input.vault)) {
|
|
@@ -8430,7 +8580,7 @@ async function runStatus(input) {
|
|
|
8430
8580
|
const compound = scan.data.compound.length;
|
|
8431
8581
|
let schemaVersion = "v1";
|
|
8432
8582
|
try {
|
|
8433
|
-
const schemaContent = await
|
|
8583
|
+
const schemaContent = await readFile17(join33(scanRoot, "SCHEMA.md"), "utf8");
|
|
8434
8584
|
const versionMatch = schemaContent.match(/version:\s*["']?([^"'\s\n]+)/i);
|
|
8435
8585
|
if (versionMatch) schemaVersion = versionMatch[1];
|
|
8436
8586
|
} catch {
|
|
@@ -8498,7 +8648,7 @@ async function runStatus(input) {
|
|
|
8498
8648
|
|
|
8499
8649
|
// src/commands/seed.ts
|
|
8500
8650
|
import { mkdir as mkdir12, writeFile as writeFile8, stat as stat4 } from "fs/promises";
|
|
8501
|
-
import { join as
|
|
8651
|
+
import { join as join34 } from "path";
|
|
8502
8652
|
var TODAY = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
8503
8653
|
var EXAMPLE_PAGES = {
|
|
8504
8654
|
"entities/example-project.md": `---
|
|
@@ -8567,29 +8717,29 @@ Real sources are immutable after ingestion \u2014 never edit them.
|
|
|
8567
8717
|
`;
|
|
8568
8718
|
async function runSeed(input) {
|
|
8569
8719
|
try {
|
|
8570
|
-
await stat4(
|
|
8720
|
+
await stat4(join34(input.vault, "SCHEMA.md"));
|
|
8571
8721
|
} catch {
|
|
8572
8722
|
return { exitCode: ExitCode.VAULT_PATH_INVALID, result: err("VAULT_PATH_INVALID", { root: input.vault, reason: "SCHEMA.md missing \u2014 run `skillwiki init` first" }) };
|
|
8573
8723
|
}
|
|
8574
8724
|
const created = [];
|
|
8575
8725
|
const skipped = [];
|
|
8576
8726
|
for (const [relPath, content] of Object.entries(EXAMPLE_PAGES)) {
|
|
8577
|
-
const absPath =
|
|
8727
|
+
const absPath = join34(input.vault, relPath);
|
|
8578
8728
|
try {
|
|
8579
8729
|
await stat4(absPath);
|
|
8580
8730
|
skipped.push(relPath);
|
|
8581
8731
|
} catch {
|
|
8582
|
-
await mkdir12(
|
|
8732
|
+
await mkdir12(join34(absPath, ".."), { recursive: true });
|
|
8583
8733
|
await writeFile8(absPath, content, "utf8");
|
|
8584
8734
|
created.push(relPath);
|
|
8585
8735
|
}
|
|
8586
8736
|
}
|
|
8587
|
-
const rawPath =
|
|
8737
|
+
const rawPath = join34(input.vault, "raw", "articles", "example-source.md");
|
|
8588
8738
|
try {
|
|
8589
8739
|
await stat4(rawPath);
|
|
8590
8740
|
skipped.push("raw/articles/example-source.md");
|
|
8591
8741
|
} catch {
|
|
8592
|
-
await mkdir12(
|
|
8742
|
+
await mkdir12(join34(rawPath, ".."), { recursive: true });
|
|
8593
8743
|
await writeFile8(rawPath, EXAMPLE_RAW, "utf8");
|
|
8594
8744
|
created.push("raw/articles/example-source.md");
|
|
8595
8745
|
}
|
|
@@ -8612,9 +8762,9 @@ async function runSeed(input) {
|
|
|
8612
8762
|
}
|
|
8613
8763
|
|
|
8614
8764
|
// src/commands/canvas.ts
|
|
8615
|
-
import { readFile as
|
|
8765
|
+
import { readFile as readFile18, writeFile as writeFile9 } from "fs/promises";
|
|
8616
8766
|
import { existsSync as existsSync11 } from "fs";
|
|
8617
|
-
import { join as
|
|
8767
|
+
import { join as join35 } from "path";
|
|
8618
8768
|
var NODE_WIDTH = 240;
|
|
8619
8769
|
var NODE_HEIGHT = 60;
|
|
8620
8770
|
var COLUMN_SPACING = 400;
|
|
@@ -8692,7 +8842,7 @@ function buildCanvasEdges(adjacency) {
|
|
|
8692
8842
|
return edges;
|
|
8693
8843
|
}
|
|
8694
8844
|
async function runCanvasGenerate(input) {
|
|
8695
|
-
const graphPath = input.graphPath ??
|
|
8845
|
+
const graphPath = input.graphPath ?? join35(input.vault, ".skillwiki", "graph.json");
|
|
8696
8846
|
if (!existsSync11(graphPath)) {
|
|
8697
8847
|
return {
|
|
8698
8848
|
exitCode: ExitCode.FILE_NOT_FOUND,
|
|
@@ -8704,7 +8854,7 @@ async function runCanvasGenerate(input) {
|
|
|
8704
8854
|
}
|
|
8705
8855
|
let raw;
|
|
8706
8856
|
try {
|
|
8707
|
-
raw = await
|
|
8857
|
+
raw = await readFile18(graphPath, "utf8");
|
|
8708
8858
|
} catch (e) {
|
|
8709
8859
|
return {
|
|
8710
8860
|
exitCode: ExitCode.FILE_NOT_FOUND,
|
|
@@ -8730,7 +8880,7 @@ async function runCanvasGenerate(input) {
|
|
|
8730
8880
|
const nodes = buildCanvasNodes(paths);
|
|
8731
8881
|
const edges = buildCanvasEdges(graph.adjacency);
|
|
8732
8882
|
const canvas = { nodes, edges };
|
|
8733
|
-
const outPath =
|
|
8883
|
+
const outPath = join35(input.vault, "vault-graph.canvas");
|
|
8734
8884
|
try {
|
|
8735
8885
|
await writeFile9(outPath, JSON.stringify(canvas, null, 2));
|
|
8736
8886
|
} catch (e) {
|
|
@@ -8765,11 +8915,11 @@ async function runSourceDisposition(input) {
|
|
|
8765
8915
|
|
|
8766
8916
|
// src/utils/source-disposal.ts
|
|
8767
8917
|
import { createHash as createHash6 } from "crypto";
|
|
8768
|
-
import { readFile as
|
|
8918
|
+
import { readFile as readFile20, unlink as unlink5 } from "fs/promises";
|
|
8769
8919
|
|
|
8770
8920
|
// src/utils/raw-asset-reference-index.ts
|
|
8771
|
-
import { readdir as readdir7, readFile as
|
|
8772
|
-
import { join as
|
|
8921
|
+
import { readdir as readdir7, readFile as readFile19 } from "fs/promises";
|
|
8922
|
+
import { join as join36, relative as relative4, sep as sep3 } from "path";
|
|
8773
8923
|
var PREVIEW_EXTENSIONS = /* @__PURE__ */ new Set(["png", "jpg", "jpeg", "gif", "webp", "svg", "bmp", "avif", "pdf", "mp3", "wav", "m4a", "mp4", "webm"]);
|
|
8774
8924
|
async function walkFiles(root, dir = root) {
|
|
8775
8925
|
let entries;
|
|
@@ -8780,7 +8930,7 @@ async function walkFiles(root, dir = root) {
|
|
|
8780
8930
|
}
|
|
8781
8931
|
const out = [];
|
|
8782
8932
|
for (const entry of entries) {
|
|
8783
|
-
const path =
|
|
8933
|
+
const path = join36(dir, entry.name);
|
|
8784
8934
|
if (entry.isDirectory()) out.push(...await walkFiles(root, path));
|
|
8785
8935
|
else if (entry.isFile()) out.push(relative4(root, path).split(sep3).join("/"));
|
|
8786
8936
|
}
|
|
@@ -8796,7 +8946,7 @@ function addInbound(map, target, source) {
|
|
|
8796
8946
|
map.set(target, refs);
|
|
8797
8947
|
}
|
|
8798
8948
|
async function buildRawAssetReferenceIndex(vault) {
|
|
8799
|
-
const assetRoot =
|
|
8949
|
+
const assetRoot = join36(vault, "raw", "assets");
|
|
8800
8950
|
const relativeAssets = await walkFiles(assetRoot);
|
|
8801
8951
|
const assets = relativeAssets.map((path) => `raw/assets/${path}`).sort((a, b) => a.localeCompare(b));
|
|
8802
8952
|
const assetSet = new Set(assets);
|
|
@@ -8812,7 +8962,7 @@ async function buildRawAssetReferenceIndex(vault) {
|
|
|
8812
8962
|
for (const page of scan.data.allMarkdown) {
|
|
8813
8963
|
let text;
|
|
8814
8964
|
try {
|
|
8815
|
-
text = await
|
|
8965
|
+
text = await readFile19(page.absPath, "utf8");
|
|
8816
8966
|
} catch {
|
|
8817
8967
|
continue;
|
|
8818
8968
|
}
|
|
@@ -8872,7 +9022,7 @@ async function planSourceDisposal(input) {
|
|
|
8872
9022
|
if (sensitive.length > 0) return err("SENSITIVE_CONTENT_DETECTED", { findings: sensitive });
|
|
8873
9023
|
const target = await resolveExistingRegularFileInsideVault(input.vault, input.rawPath);
|
|
8874
9024
|
if (!target.ok) return err("RAW_DISPOSAL_TARGET_INVALID", { path: input.rawPath, cause: target });
|
|
8875
|
-
const bytes = await
|
|
9025
|
+
const bytes = await readFile20(target.data);
|
|
8876
9026
|
const size = bytes.byteLength;
|
|
8877
9027
|
let typedReferences = [];
|
|
8878
9028
|
let otherReferences = [];
|
|
@@ -8996,7 +9146,7 @@ async function runSourceDisposal(input) {
|
|
|
8996
9146
|
import { existsSync as existsSync12, readFileSync as readFileSync16 } from "fs";
|
|
8997
9147
|
import { execSync as nodeExecSync } from "child_process";
|
|
8998
9148
|
import { hostname as nodeHostname, platform as nodePlatform } from "os";
|
|
8999
|
-
import { join as
|
|
9149
|
+
import { join as join37 } from "path";
|
|
9000
9150
|
var SSH_TIMEOUT_MS = 15e3;
|
|
9001
9151
|
var TIMER_UNIT = "agent-memory-trends.timer";
|
|
9002
9152
|
var SERVICE_UNIT = "agent-memory-trends.service";
|
|
@@ -9226,7 +9376,7 @@ async function runFleetHealth(input) {
|
|
|
9226
9376
|
const home = input.home ?? env.HOME ?? "";
|
|
9227
9377
|
const osHostname = input.osHostname ?? env.HOSTNAME ?? nodeHostname();
|
|
9228
9378
|
const vault = input.vault ?? env.WIKI_PATH;
|
|
9229
|
-
const file = input.file ?? (vault ?
|
|
9379
|
+
const file = input.file ?? (vault ? join37(vault, FLEET_REL_PATH) : void 0);
|
|
9230
9380
|
if (!file) {
|
|
9231
9381
|
return {
|
|
9232
9382
|
exitCode: ExitCode.NO_VAULT_CONFIGURED,
|
|
@@ -9311,14 +9461,14 @@ async function runFleetHealth(input) {
|
|
|
9311
9461
|
|
|
9312
9462
|
// src/utils/auto-commit.ts
|
|
9313
9463
|
import { existsSync as existsSync13 } from "fs";
|
|
9314
|
-
import { join as
|
|
9464
|
+
import { join as join38 } from "path";
|
|
9315
9465
|
async function postCommit(vault, exitCode) {
|
|
9316
9466
|
if (exitCode !== 0) return;
|
|
9317
9467
|
const home = process.env.HOME ?? "";
|
|
9318
9468
|
const dotenv = await parseDotenvFile(configPath(home));
|
|
9319
9469
|
const autoCommit = process.env.AUTO_COMMIT ?? dotenv["AUTO_COMMIT"];
|
|
9320
9470
|
if (autoCommit === "false") return;
|
|
9321
|
-
if (!existsSync13(
|
|
9471
|
+
if (!existsSync13(join38(vault, ".git"))) return;
|
|
9322
9472
|
const lastOps = readLastOp(vault);
|
|
9323
9473
|
if (lastOps.length === 0) return;
|
|
9324
9474
|
const porcelain = git(vault, ["status", "--porcelain", "--", ...VAULT_COMMIT_PATHSPEC]);
|
|
@@ -9479,7 +9629,7 @@ async function emitManagedVaultWrite(vault, command, mutate, opts) {
|
|
|
9479
9629
|
if (dirty) {
|
|
9480
9630
|
return emit(dirty, void 0, { postCommit: false });
|
|
9481
9631
|
}
|
|
9482
|
-
const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-
|
|
9632
|
+
const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-H7KVK2KI.js");
|
|
9483
9633
|
const run = await runManagedWriteTransaction2({
|
|
9484
9634
|
vault,
|
|
9485
9635
|
command,
|
|
@@ -9509,7 +9659,7 @@ program.command("validate <file>").description("validate vault page frontmatter
|
|
|
9509
9659
|
emit(await runValidate({ file, apply: !!opts.apply, vault }), vault);
|
|
9510
9660
|
});
|
|
9511
9661
|
program.command("graph").description("graph subcommands").command("build <vault>").option("--out <path>", "graph output path (default: <vault>/.skillwiki/graph.json)").option("--wiki <name>", "wiki profile name").action(async (vault, opts) => {
|
|
9512
|
-
const out = opts.out ??
|
|
9662
|
+
const out = opts.out ?? join39(vault, ".skillwiki", "graph.json");
|
|
9513
9663
|
return emitGuardedVaultWrite(vault, "graph build", () => runGraphBuild({ vault, out }));
|
|
9514
9664
|
});
|
|
9515
9665
|
var canvasCmd = program.command("canvas").description("manage Obsidian canvas files");
|
|
@@ -10124,6 +10274,12 @@ program.command("project-index <slug> [vault]").description("generate a knowledg
|
|
|
10124
10274
|
);
|
|
10125
10275
|
else emit(await runProjectIndex({ vault: v.vault, slug, apply: false, check: opts.check }), v.vault);
|
|
10126
10276
|
});
|
|
10277
|
+
var claimsCmd = program.command("claims").description("audit raw-transcript claim integrity (read-only)");
|
|
10278
|
+
claimsCmd.command("audit [vault]").description("report duplicate, malformed, dangling, project-mismatch, and work-item-unbacked claims (read-only)").option("--project <slug>", "scope findings to an exact project slug").option("--wiki <name>", "wiki profile name").action(async (vault, opts) => {
|
|
10279
|
+
const v = await resolveVaultArg(vault, opts.wiki);
|
|
10280
|
+
if (!v.ok) emit({ exitCode: v.exitCode, result: v.payload });
|
|
10281
|
+
else emit(await runClaimsAudit({ vault: v.vault, project: opts.project }), v.vault, { postCommit: false });
|
|
10282
|
+
});
|
|
10127
10283
|
var compoundCmd = program.command("compound").description("manage project compound entries");
|
|
10128
10284
|
compoundCmd.command("promote [vault]").description("promote retros with Generalize?: yes to compound entries").requiredOption("--project <slug>", "project slug (e.g., llm-wiki)").option("--dry-run", "preview promotions without writing files", false).option("--wiki <name>", "wiki profile name").action(async (vault, opts) => {
|
|
10129
10285
|
const v = await resolveVaultArg(vault, opts.wiki);
|