skillwiki 0.10.110 → 0.10.112

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.
Files changed (45) hide show
  1. package/dist/chunk-25OXNFDV.js +133 -0
  2. package/dist/{chunk-R2DJ7IJ5.js → chunk-7POLZOFY.js} +44 -375
  3. package/dist/chunk-ABRYBO4T.js +275 -0
  4. package/dist/{chunk-6X6PPQNI.js → chunk-APKDTEVV.js} +280 -446
  5. package/dist/{chunk-5MV5SSRM.js → chunk-CKQPUHM2.js} +5 -3
  6. package/dist/chunk-DOHWNPAZ.js +60 -0
  7. package/dist/chunk-EE7W3GLA.js +55 -0
  8. package/dist/chunk-FCA3RRNF.js +60 -0
  9. package/dist/{chunk-KX5Y3GSX.js → chunk-IR2DI4Y5.js} +5 -3
  10. package/dist/chunk-K3M6OSUW.js +77 -0
  11. package/dist/{chunk-WPJHDRTP.js → chunk-KJG2CSYD.js} +12 -57
  12. package/dist/chunk-LOVLZNLX.js +111 -0
  13. package/dist/chunk-OSL4J7GF.js +32 -0
  14. package/dist/{chunk-QU2CKXM4.js → chunk-Q6EZF37H.js} +91 -199
  15. package/dist/chunk-QESNTTVY.js +50 -0
  16. package/dist/{chunk-NA3TZ4JN.js → chunk-RR6VDWSI.js} +8 -6
  17. package/dist/chunk-SKOLE6US.js +126 -0
  18. package/dist/chunk-TKX6PSWZ.js +344 -0
  19. package/dist/chunk-ZRGZBAVS.js +98 -0
  20. package/dist/cli.js +359 -305
  21. package/dist/{index-projection-6XGESSHV.js → index-projection-UNZG5UJZ.js} +5 -3
  22. package/dist/journal-5IW3TZ5F.js +13 -0
  23. package/dist/{managed-write-preflight-JPOBVVSU.js → managed-write-preflight-L7IRQ76C.js} +7 -4
  24. package/dist/mcp-auth-env-X5MI5IX6.js +25 -0
  25. package/dist/migrate-RO4BJP5T.js +22 -0
  26. package/dist/mirror-H5BTBAON.js +151 -0
  27. package/dist/ready-S7F53Q2D.js +9 -0
  28. package/dist/runtime-VMFYW2K3.js +20 -0
  29. package/dist/skillwiki-mcp.js +14 -7
  30. package/dist/sources-AOYP6ROO.js +10 -0
  31. package/dist/upload-HTE62TOV.js +14 -0
  32. package/dist/watcher-MGHQD3UI.js +526 -0
  33. package/docs/clip-outbox.md +119 -0
  34. package/package.json +5 -1
  35. package/skills/.claude-plugin/plugin.json +1 -1
  36. package/skills/.codex-plugin/plugin.json +1 -1
  37. package/skills/.cursor-plugin/plugin.json +1 -1
  38. package/skills/package.json +1 -1
  39. package/skills/skills/using-skillwiki/SKILL.md +1 -1
  40. package/skills/skills/wiki-init/SKILL.md +3 -0
  41. package/skills/using-skillwiki/SKILL.md +1 -1
  42. package/skills/wiki-init/SKILL.md +3 -0
  43. package/templates/launchd/com.karlchow.skillwiki-clip-outbox.plist +12 -13
  44. package/templates/launchd/com.karlchow.skillwiki-mirror-sse.plist +20 -0
  45. package/dist/sources-CLOF5VAT.js +0 -9
package/dist/cli.js CHANGED
@@ -1,15 +1,17 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ buildDeleteIntent,
4
+ normalizeVaultRelPath,
5
+ pathToIntentFilename,
6
+ writeDeleteIntent
7
+ } from "./chunk-QESNTTVY.js";
2
8
  import {
3
9
  CAPTURE_HYGIENE_CONTRACT,
4
- CLIP_NOT_CONFIGURED,
5
10
  DEFAULT_CAPTURE_BUDGET,
6
11
  DEFAULT_DIRTY_VOLUME_THRESHOLD,
7
12
  DEFAULT_MCP_URL,
8
13
  DEFAULT_NO_DECISION_STREAK,
9
14
  GateError,
10
- MCP_HOST_ID_ENV,
11
- MCP_TOKEN_ENV,
12
- MCP_URL_ENV,
13
15
  PUSH_NOT_IN_PROFILE,
14
16
  SATELLITE_STALE_MS,
15
17
  buildVectorIndex,
@@ -22,18 +24,13 @@ import {
22
24
  guardProtectedVaultWrite,
23
25
  isEventLedgerPath,
24
26
  isFailedRunStatus,
25
- loadClipOutboxConfig,
26
- mcpAuthFromEnv,
27
27
  measureDirtyVolume,
28
28
  memoryAuthorityTiersRank,
29
- mergeMcpAuthIntoEnv,
30
- nonEmptyEnvValue,
31
29
  pruneVectorIndex,
32
30
  readCliPackageJson,
33
31
  readSatelliteLatestRunAt,
34
32
  readSatelliteLatestRunFromText,
35
33
  readVaultSyncConfig,
36
- redactMcpSecret,
37
34
  reindexPageInVectorIndex,
38
35
  renderIndexUpsert,
39
36
  renderProjectIndex,
@@ -67,7 +64,15 @@ import {
67
64
  upsertIndexEntry,
68
65
  vectorIndexStatus,
69
66
  withMcpClient
70
- } from "./chunk-6X6PPQNI.js";
67
+ } from "./chunk-APKDTEVV.js";
68
+ import {
69
+ applySourceDisposition,
70
+ decodeSourceActionApproval,
71
+ encodeSourceActionApproval,
72
+ inventorySources,
73
+ planSourceDisposition,
74
+ runSourcesPending
75
+ } from "./chunk-RR6VDWSI.js";
71
76
  import {
72
77
  normalizeDistTag,
73
78
  readCache,
@@ -80,7 +85,7 @@ import {
80
85
  UNMANAGED_START,
81
86
  renderRootIndex,
82
87
  writeRootIndexProjection
83
- } from "./chunk-KX5Y3GSX.js";
88
+ } from "./chunk-IR2DI4Y5.js";
84
89
  import {
85
90
  FLEET_REL_PATH,
86
91
  REDACTED_MALFORMED_REFERENCE,
@@ -120,13 +125,10 @@ import {
120
125
  normalizeProjectSlug,
121
126
  normalizeRemoteRoot,
122
127
  parseActiveWorkPath,
123
- parseDotenvFile,
124
- parseDotenvText,
125
128
  parseJournalEnv,
126
129
  planAndMaybePruneRemoteObjects,
127
130
  planRawStructuralMove,
128
131
  probeS3Reachability,
129
- profileKey,
130
132
  readJournal,
131
133
  readLastOp,
132
134
  readSkillWikiConfig,
@@ -137,7 +139,6 @@ import {
137
139
  resolveFleetHostId,
138
140
  resolveInitTimePath,
139
141
  resolveRuntimePath,
140
- resolveSkillwikiHome,
141
142
  resolveWikiS3Remote,
142
143
  rewriteRawSourceReferences,
143
144
  runAudit,
@@ -171,22 +172,8 @@ import {
171
172
  snapshotterAliasForLocalHost,
172
173
  stageVaultContentChanges,
173
174
  supersedeStaleReviewRequiredJournals,
174
- taxonomyCommentForPage,
175
- writeDotenv
176
- } from "./chunk-QU2CKXM4.js";
177
- import {
178
- assertTargetInsideVault,
179
- atomicWriteText,
180
- prepareTypedPage
181
- } from "./chunk-WPJHDRTP.js";
182
- import {
183
- applySourceDisposition,
184
- decodeSourceActionApproval,
185
- encodeSourceActionApproval,
186
- inventorySources,
187
- planSourceDisposition,
188
- runSourcesPending
189
- } from "./chunk-NA3TZ4JN.js";
175
+ taxonomyCommentForPage
176
+ } from "./chunk-Q6EZF37H.js";
190
177
  import {
191
178
  authorizeRawOperation,
192
179
  buildSourceReferenceIndex,
@@ -203,31 +190,67 @@ import {
203
190
  resolveExistingRegularFileInsideVault,
204
191
  validateLogEvent,
205
192
  writeLogEvent
206
- } from "./chunk-5MV5SSRM.js";
193
+ } from "./chunk-CKQPUHM2.js";
194
+ import {
195
+ assertTargetInsideVault,
196
+ prepareTypedPage
197
+ } from "./chunk-KJG2CSYD.js";
207
198
  import {
208
- ExitCode,
209
- MetaSchema,
210
- RawSourceSchema,
211
- TypedKnowledgeSchema,
212
- detectSchema,
213
- err,
214
199
  extractFrontmatter,
215
- isBlockedHost,
216
200
  mapWithConcurrency,
217
- ok,
218
201
  readPage,
219
202
  readPageCached,
220
203
  redactSensitiveContent,
221
204
  resolveReadOnlyVaultRoot,
222
- resolveSessionKind,
223
205
  scanSensitiveContent,
224
206
  scanVault,
225
207
  splitFrontmatter,
226
208
  vaultIoConcurrency
227
- } from "./chunk-R2DJ7IJ5.js";
209
+ } from "./chunk-TKX6PSWZ.js";
210
+ import {
211
+ MCP_HOST_ID_ENV,
212
+ MCP_TOKEN_ENV,
213
+ MCP_URL_ENV,
214
+ mcpAuthFromEnv,
215
+ mergeMcpAuthIntoEnv,
216
+ nonEmptyEnvValue,
217
+ redactMcpSecret
218
+ } from "./chunk-DOHWNPAZ.js";
219
+ import {
220
+ CLIP_MIGRATION_HINT,
221
+ refreshInstalledClipPlist
222
+ } from "./chunk-25OXNFDV.js";
223
+ import {
224
+ atomicWriteText
225
+ } from "./chunk-EE7W3GLA.js";
226
+ import {
227
+ CLIP_NOT_CONFIGURED,
228
+ loadClipOutboxConfig
229
+ } from "./chunk-ABRYBO4T.js";
230
+ import {
231
+ runFetchGuard,
232
+ runFetchGuardSync
233
+ } from "./chunk-LOVLZNLX.js";
234
+ import {
235
+ parseDotenvFile,
236
+ parseDotenvText,
237
+ profileKey,
238
+ resolveSkillwikiHome,
239
+ writeDotenv
240
+ } from "./chunk-SKOLE6US.js";
241
+ import {
242
+ ExitCode,
243
+ MetaSchema,
244
+ RawSourceSchema,
245
+ TypedKnowledgeSchema,
246
+ detectSchema,
247
+ err,
248
+ ok,
249
+ resolveSessionKind
250
+ } from "./chunk-7POLZOFY.js";
228
251
 
229
252
  // src/cli.ts
230
- import { join as join45 } from "path";
253
+ import { join as join44 } from "path";
231
254
  import { Command } from "commander";
232
255
 
233
256
  // src/utils/output.ts
@@ -343,48 +366,6 @@ async function runHash(input) {
343
366
  };
344
367
  }
345
368
 
346
- // src/commands/fetch-guard.ts
347
- var REDACT_PARAMS = /* @__PURE__ */ new Set(["api_key", "token", "key", "auth", "password", "secret", "access_token"]);
348
- var PATH_TOKEN_RE = /[A-Fa-f0-9]{32,}|[A-Za-z0-9_\-]{40,}/g;
349
- function runFetchGuard(input) {
350
- return Promise.resolve(runFetchGuardSync(input));
351
- }
352
- function runFetchGuardSync(input) {
353
- let u;
354
- try {
355
- u = new URL(input.url);
356
- } catch {
357
- return { exitCode: ExitCode.MALFORMED_URL, result: err("MALFORMED_URL", { url: input.url }) };
358
- }
359
- const sanitized = sanitizeUrl(u);
360
- if (u.protocol !== "https:") {
361
- return {
362
- exitCode: ExitCode.SCHEME_REJECTED,
363
- result: err("SCHEME_REJECTED", { sanitized_url: sanitized, scheme: u.protocol })
364
- };
365
- }
366
- if (isBlockedHost(u.hostname)) {
367
- return {
368
- exitCode: ExitCode.HOST_BLOCKED,
369
- result: err("HOST_BLOCKED", { sanitized_url: sanitized, host: u.hostname })
370
- };
371
- }
372
- return { exitCode: ExitCode.OK, result: ok({ allowed: true, sanitized_url: sanitized, humanHint: `ALLOWED: ${sanitized}` }) };
373
- }
374
- function sanitizeUrl(u) {
375
- const clone = new URL(u.toString());
376
- if (clone.username || clone.password) {
377
- clone.username = "";
378
- clone.password = "";
379
- }
380
- for (const k of Array.from(clone.searchParams.keys())) {
381
- if (REDACT_PARAMS.has(k.toLowerCase())) clone.searchParams.set(k, "REDACTED");
382
- }
383
- let s = clone.toString();
384
- s = s.replace(PATH_TOKEN_RE, "REDACTED");
385
- return s;
386
- }
387
-
388
369
  // src/commands/eval.ts
389
370
  import { execFileSync } from "child_process";
390
371
  import { existsSync, mkdtempSync, rmSync } from "fs";
@@ -3604,14 +3585,117 @@ async function runClipOutboxStatus(home) {
3604
3585
  result: ok({ enabled: false, humanHint: CLIP_NOT_CONFIGURED })
3605
3586
  };
3606
3587
  }
3588
+ const { readJournal: readJournal2 } = await import("./journal-5IW3TZ5F.js");
3589
+ let queue;
3590
+ try {
3591
+ queue = (await readJournal2(resolved.config.stateRoot)).map(({ captureId, state, reason, attempts }) => ({ captureId, state, reason, attempts }));
3592
+ } catch {
3593
+ return { exitCode: ExitCode.PREFLIGHT_FAILED, result: err("PREFLIGHT_FAILED", { message: "clip journal unreadable; retain it for attended recovery" }) };
3594
+ }
3607
3595
  return {
3608
3596
  exitCode: ExitCode.OK,
3609
3597
  result: ok({
3610
3598
  enabled: true,
3611
- humanHint: `clip-outbox enabled root=${resolved.config.root} mode=${resolved.config.mode}`
3599
+ queue,
3600
+ humanHint: [`clip-outbox enabled root=${resolved.config.root} mode=${resolved.config.mode}`, ...queue.map((e) => `${e.captureId}: ${e.state}${e.reason ? ` (${e.reason})` : ""}; attempts=${e.attempts ?? 0}`)].join("\n")
3612
3601
  })
3613
3602
  };
3614
3603
  }
3604
+ async function runClipOutboxInstall(input) {
3605
+ try {
3606
+ const { migrateClipOutbox } = await import("./migrate-RO4BJP5T.js");
3607
+ return { exitCode: ExitCode.OK, result: ok(await migrateClipOutbox(input)) };
3608
+ } catch (e) {
3609
+ return { exitCode: ExitCode.PREFLIGHT_FAILED, result: err("PREFLIGHT_FAILED", { message: e instanceof Error ? e.message : "clip migration failed" }) };
3610
+ }
3611
+ }
3612
+ async function runClipOutboxWatch(home) {
3613
+ const resolved = await loadClipOutboxConfig(home);
3614
+ if (!resolved.ok || !resolved.enabled) return { exitCode: ExitCode.INVALID_CONFIG_VALUE, result: err("INVALID_CONFIG_VALUE", { message: resolved.ok ? CLIP_NOT_CONFIGURED : resolved.message }) };
3615
+ if (process.platform !== "darwin") return { exitCode: ExitCode.PREFLIGHT_FAILED, result: err("PREFLIGHT_FAILED", { message: "clip-outbox watch requires macOS FSEvents" }) };
3616
+ let client;
3617
+ try {
3618
+ const { S3Client: S3Client3 } = await import("@aws-sdk/client-s3");
3619
+ const { loadClipCredentials, validateRuntime } = await import("./runtime-VMFYW2K3.js");
3620
+ const { createS3CreateOnlyPut, parseDestination } = await import("./upload-HTE62TOV.js");
3621
+ const { postReadyHint } = await import("./ready-S7F53Q2D.js");
3622
+ const { startClipWorker } = await import("./watcher-MGHQD3UI.js");
3623
+ const cfg = resolved.config;
3624
+ const credentials = await loadClipCredentials(home, cfg);
3625
+ await validateRuntime(home, cfg, credentials.s3.endpoint);
3626
+ const destination = parseDestination(cfg.destination);
3627
+ client = new S3Client3({ endpoint: credentials.s3.endpoint, region: credentials.s3.region, credentials: credentials.s3, forcePathStyle: true, maxAttempts: 1 });
3628
+ let finish;
3629
+ const done = new Promise((r) => {
3630
+ finish = r;
3631
+ });
3632
+ let failed = false;
3633
+ const worker = await startClipWorker(cfg, {
3634
+ put: createS3CreateOnlyPut({ client, bucket: destination.bucket, prefix: destination.prefix }),
3635
+ ready: (hint) => postReadyHint({ url: cfg.readyUrl, token: credentials.readyToken, hint }),
3636
+ validate: () => validateRuntime(home, cfg, credentials.s3.endpoint),
3637
+ onError: () => {
3638
+ failed = true;
3639
+ finish();
3640
+ }
3641
+ });
3642
+ process.once("SIGTERM", finish);
3643
+ process.once("SIGINT", finish);
3644
+ try {
3645
+ await done;
3646
+ } finally {
3647
+ process.removeListener("SIGTERM", finish);
3648
+ process.removeListener("SIGINT", finish);
3649
+ await worker.stop();
3650
+ }
3651
+ return failed ? { exitCode: ExitCode.PREFLIGHT_FAILED, result: err("PREFLIGHT_FAILED", { message: "clip worker stopped; inspect configuration and retained journal" }) } : { exitCode: ExitCode.OK, result: ok({ humanHint: "Clip worker stopped; snapshots and journal retained." }) };
3652
+ } catch {
3653
+ return { exitCode: ExitCode.PREFLIGHT_FAILED, result: err("PREFLIGHT_FAILED", { message: "clip worker startup failed; check configuration, protected credential references, conditional-create evidence and worker lock" }) };
3654
+ } finally {
3655
+ client?.destroy();
3656
+ }
3657
+ }
3658
+ async function runClipOutboxMirrorWatch(home) {
3659
+ const resolved = await loadClipOutboxConfig(home);
3660
+ if (!resolved.ok || !resolved.enabled) return { exitCode: ExitCode.INVALID_CONFIG_VALUE, result: err("INVALID_CONFIG_VALUE", { message: resolved.ok ? CLIP_NOT_CONFIGURED : resolved.message }) };
3661
+ let client;
3662
+ const abort = new AbortController();
3663
+ try {
3664
+ const { S3Client: S3Client3 } = await import("@aws-sdk/client-s3");
3665
+ const { loadClipCredentials, validateRuntime } = await import("./runtime-VMFYW2K3.js");
3666
+ const { createS3GetObject, eventsUrlFromMcp, parseDestinationForMirror, startMirrorListener } = await import("./mirror-H5BTBAON.js");
3667
+ const { resolveMcpAuthEnv } = await import("./mcp-auth-env-X5MI5IX6.js");
3668
+ const cfg = resolved.config;
3669
+ const credentials = await loadClipCredentials(home, cfg);
3670
+ await validateRuntime(home, cfg, credentials.s3.endpoint);
3671
+ const auth = await resolveMcpAuthEnv({ home });
3672
+ if (!auth.url || !auth.token) throw new Error("MCP bearer required for inbound SSE");
3673
+ const destination = parseDestinationForMirror(cfg.destination);
3674
+ client = new S3Client3({ endpoint: credentials.s3.endpoint, region: credentials.s3.region, credentials: credentials.s3, forcePathStyle: true, maxAttempts: 1 });
3675
+ const done = new Promise((resolve9) => {
3676
+ abort.signal.addEventListener("abort", () => resolve9(), { once: true });
3677
+ });
3678
+ process.once("SIGTERM", () => abort.abort());
3679
+ process.once("SIGINT", () => abort.abort());
3680
+ await Promise.race([
3681
+ startMirrorListener({
3682
+ home,
3683
+ config: cfg,
3684
+ eventsUrl: eventsUrlFromMcp(auth.url),
3685
+ mcpToken: auth.token,
3686
+ getObject: createS3GetObject({ client, bucket: destination.bucket, prefix: destination.prefix, maxBytes: cfg.maxBundleBytes }),
3687
+ signal: abort.signal
3688
+ }),
3689
+ done
3690
+ ]);
3691
+ return { exitCode: ExitCode.OK, result: ok({ humanHint: "Inbound SSE listener stopped." }) };
3692
+ } catch {
3693
+ return { exitCode: ExitCode.PREFLIGHT_FAILED, result: err("PREFLIGHT_FAILED", { message: "inbound SSE listener startup failed; check MCP bearer, clip credentials, frozen mirror and wiki-push isolation" }) };
3694
+ } finally {
3695
+ abort.abort();
3696
+ client?.destroy();
3697
+ }
3698
+ }
3615
3699
 
3616
3700
  // src/commands/connect.ts
3617
3701
  import { chmod, mkdir as mkdir5, readFile as readFile6, stat as stat3 } from "fs/promises";
@@ -3922,50 +4006,8 @@ async function runConnect(input) {
3922
4006
  }
3923
4007
 
3924
4008
  // src/commands/archive.ts
3925
- import { rename as rename2, mkdir as mkdir7, readFile as readFile8 } from "fs/promises";
3926
- import { join as join20, dirname as dirname5 } from "path";
3927
-
3928
- // src/utils/delete-intent.ts
3929
- import { mkdir as mkdir6, writeFile as writeFile4, readdir as readdir4, readFile as readFile7 } from "fs/promises";
3930
- import { join as join19 } from "path";
3931
- var DELETE_INTENT_SCHEMA = "vault-delete-intent/v1";
3932
- var DELETE_INTENT_DIR = "meta/delete-intents";
3933
- function normalizeVaultRelPath(path) {
3934
- const p = path.replace(/\\/g, "/").replace(/^\/+/, "");
3935
- if (!p || p.includes("..") || p.startsWith(".git/")) {
3936
- throw new Error(`invalid vault-relative path: ${path}`);
3937
- }
3938
- return p;
3939
- }
3940
- function pathToIntentFilename(path) {
3941
- const p = normalizeVaultRelPath(path);
3942
- return `${p.replace(/\//g, "__")}.json`;
3943
- }
3944
- function intentHostId() {
3945
- return process.env.SKILLWIKI_HOST_ID ?? process.env.AGENT_HOST_ID ?? "unknown";
3946
- }
3947
- function buildDeleteIntent(input) {
3948
- return {
3949
- schema: DELETE_INTENT_SCHEMA,
3950
- path: normalizeVaultRelPath(input.path),
3951
- action: input.action,
3952
- created: input.created ?? (/* @__PURE__ */ new Date()).toISOString(),
3953
- host: input.host ?? intentHostId(),
3954
- actor: input.actor,
3955
- reason: input.reason,
3956
- source: input.source,
3957
- expires: input.expires ?? null
3958
- };
3959
- }
3960
- async function writeDeleteIntent(vault, intent) {
3961
- const dir = join19(vault, DELETE_INTENT_DIR);
3962
- await mkdir6(dir, { recursive: true });
3963
- const rel = `${DELETE_INTENT_DIR}/${pathToIntentFilename(intent.path)}`;
3964
- await writeFile4(join19(vault, rel), JSON.stringify(intent, null, 2) + "\n", "utf8");
3965
- return rel;
3966
- }
3967
-
3968
- // src/commands/archive.ts
4009
+ import { rename as rename2, mkdir as mkdir6, readFile as readFile7 } from "fs/promises";
4010
+ import { join as join19, dirname as dirname5 } from "path";
3969
4011
  function countWikilinks(body, slug) {
3970
4012
  const escaped = slug.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3971
4013
  const re = new RegExp(`\\[\\[${escaped}(?:[|#][^\\]]*)?\\]\\]`, "g");
@@ -4001,7 +4043,7 @@ async function runArchive(input) {
4001
4043
  const slug = relPath.replace(/\.md$/, "").split("/").pop();
4002
4044
  const rawArchive = isRaw ? lifecycleDestination(relPath, "archive") : void 0;
4003
4045
  if (rawArchive && !rawArchive.ok) return { exitCode: ExitCode.USAGE, result: rawArchive };
4004
- const archivePath = isRaw ? rawArchive.data : join20("_archive", relPath).replace(/\\/g, "/");
4046
+ const archivePath = isRaw ? rawArchive.data : join19("_archive", relPath).replace(/\\/g, "/");
4005
4047
  const remoteRoot = normalizeRemoteRoot(input.remote);
4006
4048
  const remoteObjectPath = buildRemoteObjectPath(remoteRoot, relPath);
4007
4049
  let cascade;
@@ -4031,7 +4073,7 @@ async function runArchive(input) {
4031
4073
  const indexRefs = [];
4032
4074
  if (!isRaw) {
4033
4075
  try {
4034
- const idx = await readFile8(join20(input.vault, "index.md"), "utf8");
4076
+ const idx = await readFile7(join19(input.vault, "index.md"), "utf8");
4035
4077
  idx.split("\n").forEach((line, i) => {
4036
4078
  if (line.includes(`[[${slug}]]`)) indexRefs.push({ line: i + 1, text: line });
4037
4079
  });
@@ -4089,8 +4131,8 @@ async function runArchive(input) {
4089
4131
  const rewrittenCascadePages = [];
4090
4132
  if ((input.cascade || isRaw) && input.apply && cascade) {
4091
4133
  for (const ref of cascade.source_array_refs) {
4092
- const absPath = join20(input.vault, ref.page);
4093
- const text = await readFile8(absPath, "utf8");
4134
+ const absPath = join19(input.vault, ref.page);
4135
+ const text = await readFile7(absPath, "utf8");
4094
4136
  if (!arraysEqual(ref.sources_after, ref.sources_before)) {
4095
4137
  let updated;
4096
4138
  if (isRaw) {
@@ -4116,8 +4158,8 @@ ${fmRewritten}
4116
4158
  if (isRaw) {
4117
4159
  for (const ref of cascade.citation_refs) {
4118
4160
  if (cascade.source_array_refs.some((sourceRef) => sourceRef.page === ref.page)) continue;
4119
- const absPath = join20(input.vault, ref.page);
4120
- const original = await readFile8(absPath, "utf8");
4161
+ const absPath = join19(input.vault, ref.page);
4162
+ const original = await readFile7(absPath, "utf8");
4121
4163
  const updated = rewriteRawSourceReferences(original, relPath, archivePath).text;
4122
4164
  if (updated !== original) {
4123
4165
  const write = await safeWritePage(absPath, updated);
@@ -4128,13 +4170,13 @@ ${fmRewritten}
4128
4170
  }
4129
4171
  }
4130
4172
  if (!isRaw) {
4131
- await mkdir7(dirname5(join20(input.vault, archivePath)), { recursive: true });
4132
- await rename2(join20(input.vault, relPath), join20(input.vault, archivePath));
4173
+ await mkdir6(dirname5(join19(input.vault, archivePath)), { recursive: true });
4174
+ await rename2(join19(input.vault, relPath), join19(input.vault, archivePath));
4133
4175
  }
4134
4176
  let indexUpdated = false;
4135
4177
  if (!isRaw) {
4136
- const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-6XGESSHV.js");
4137
- const before = await readFile8(join20(input.vault, "index.md"), "utf8").catch(() => "");
4178
+ const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-UNZG5UJZ.js");
4179
+ const before = await readFile7(join19(input.vault, "index.md"), "utf8").catch(() => "");
4138
4180
  const fullTarget = relPath.replace(/\.md$/, "");
4139
4181
  const bare = fullTarget.split("/").pop() ?? fullTarget;
4140
4182
  const hadIndexEntry = before.includes(`[[${fullTarget}]]`) || before.includes(`[[${bare}]]`);
@@ -4188,7 +4230,7 @@ ${fmRewritten}
4188
4230
 
4189
4231
  // src/commands/remove.ts
4190
4232
  import { unlink as unlink2, access } from "fs/promises";
4191
- import { join as join21 } from "path";
4233
+ import { join as join20 } from "path";
4192
4234
  async function pathExists(abs) {
4193
4235
  try {
4194
4236
  await access(abs);
@@ -4214,7 +4256,7 @@ async function runRemove(input) {
4214
4256
  if (!relPath) {
4215
4257
  try {
4216
4258
  const candidate = normalizeVaultRelPath(input.page);
4217
- if (await pathExists(join21(input.vault, candidate))) {
4259
+ if (await pathExists(join20(input.vault, candidate))) {
4218
4260
  relPath = candidate;
4219
4261
  }
4220
4262
  } catch {
@@ -4252,12 +4294,12 @@ async function runRemove(input) {
4252
4294
  reason: input.reason
4253
4295
  });
4254
4296
  const tombstonePath = await writeDeleteIntent(input.vault, intent);
4255
- await unlink2(join21(input.vault, relPath));
4297
+ await unlink2(join20(input.vault, relPath));
4256
4298
  if (relPath.endsWith(".md") && !relPath.startsWith("raw/")) {
4257
- const { readFile: readFile24 } = await import("fs/promises");
4299
+ const { readFile: readFile23 } = await import("fs/promises");
4258
4300
  const { join: pathJoin } = await import("path");
4259
- const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-6XGESSHV.js");
4260
- const before = await readFile24(pathJoin(input.vault, "index.md"), "utf8").catch(() => "");
4301
+ const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-UNZG5UJZ.js");
4302
+ const before = await readFile23(pathJoin(input.vault, "index.md"), "utf8").catch(() => "");
4261
4303
  const fullTarget = relPath.replace(/\.md$/, "");
4262
4304
  const bare = fullTarget.split("/").pop() ?? fullTarget;
4263
4305
  const hadIndexEntry = before.includes(`[[${fullTarget}]]`) || before.includes(`[[${bare}]]`);
@@ -4606,7 +4648,7 @@ ${migratedBody}${newFooter}`;
4606
4648
 
4607
4649
  // src/commands/update.ts
4608
4650
  import { execSync } from "child_process";
4609
- import { join as join22 } from "path";
4651
+ import { join as join21 } from "path";
4610
4652
  function parseCoreSemver(version) {
4611
4653
  const m = version.match(/^(\d+)\.(\d+)\.(\d+)/);
4612
4654
  if (!m) return null;
@@ -4650,6 +4692,8 @@ function migrationNotesForUpgrade(previousVersion, newVersion) {
4650
4692
  "- frozen-leaf hosts write via HTTP MCP only; do not local-write raw/transcripts/ or vault git"
4651
4693
  );
4652
4694
  }
4695
+ const next = parseCoreSemver(newVersion);
4696
+ if (next && isAtLeast(next, 0, 10, 111)) notes.push(CLIP_MIGRATION_HINT);
4653
4697
  return notes;
4654
4698
  }
4655
4699
  function resolveGlobalSkillsRoot() {
@@ -4658,7 +4702,7 @@ function resolveGlobalSkillsRoot() {
4658
4702
  encoding: "utf8",
4659
4703
  timeout: 5e3
4660
4704
  }).trim();
4661
- return join22(globalRoot, "skillwiki", "skills");
4705
+ return join21(globalRoot, "skillwiki", "skills");
4662
4706
  } catch {
4663
4707
  return null;
4664
4708
  }
@@ -4686,7 +4730,7 @@ async function runUpdate(input) {
4686
4730
  const pkg2 = readCliPackageJson();
4687
4731
  const currentVersion = pkg2.version;
4688
4732
  const tag = normalizeDistTag(input.distTag);
4689
- const target = join22(input.home, ".claude", "skills");
4733
+ const target = join21(input.home, ".claude", "skills");
4690
4734
  let latest;
4691
4735
  try {
4692
4736
  latest = execSync(`npm view skillwiki@${tag} version`, {
@@ -4719,7 +4763,8 @@ async function runUpdate(input) {
4719
4763
  version_warnings: [],
4720
4764
  skills_refreshed: false,
4721
4765
  deferred_to_plugin: false,
4722
- humanHint: `Already on npm@${tag}: v${currentVersion}`
4766
+ humanHint: `Already on npm@${tag}: v${currentVersion}
4767
+ ${CLIP_MIGRATION_HINT}`
4723
4768
  })
4724
4769
  };
4725
4770
  }
@@ -4750,6 +4795,12 @@ async function runUpdate(input) {
4750
4795
  for (const line of migrationNotesForUpgrade(currentVersion, latest)) {
4751
4796
  hintLines.push(line);
4752
4797
  }
4798
+ try {
4799
+ const clipHint = await refreshInstalledClipPlist(input.home);
4800
+ if (clipHint) hintLines.push(clipHint);
4801
+ } catch (e) {
4802
+ hintLines.push(`clip plist refresh skipped: ${e instanceof Error ? e.message : "migration failed"}`);
4803
+ }
4753
4804
  return {
4754
4805
  exitCode: ExitCode.OK,
4755
4806
  result: ok({
@@ -4767,13 +4818,13 @@ async function runUpdate(input) {
4767
4818
  // src/commands/self-update.ts
4768
4819
  import { execSync as execSync2 } from "child_process";
4769
4820
  import { existsSync as existsSync8, readFileSync as readFileSync11 } from "fs";
4770
- import { join as join23 } from "path";
4821
+ import { join as join22 } from "path";
4771
4822
  var DEFAULT_SOURCE_ROOT_SUFFIX = "/Desktop/code/llm-wiki";
4772
4823
  async function runSelfUpdate(input) {
4773
4824
  const currentVersion = readCliPackageJson().version;
4774
4825
  const sourceRoot = input.sourceRoot ?? `${input.home}${DEFAULT_SOURCE_ROOT_SUFFIX}`;
4775
4826
  const distTag = normalizeDistTag(input.distTag);
4776
- const localPkgPath = join23(sourceRoot, "packages", "cli", "package.json");
4827
+ const localPkgPath = join22(sourceRoot, "packages", "cli", "package.json");
4777
4828
  const hasLocalSource = existsSync8(localPkgPath);
4778
4829
  if (input.check) {
4779
4830
  let availableVersion = null;
@@ -4905,21 +4956,21 @@ async function runSelfUpdate(input) {
4905
4956
  }
4906
4957
 
4907
4958
  // src/commands/transcripts.ts
4908
- import { readdir as readdir5, stat as stat4, readFile as readFile10 } from "fs/promises";
4909
- import { join as join24 } from "path";
4959
+ import { readdir as readdir4, stat as stat4, readFile as readFile9 } from "fs/promises";
4960
+ import { join as join23 } from "path";
4910
4961
  async function runTranscripts(input) {
4911
- const dir = join24(input.vault, "raw", "transcripts");
4962
+ const dir = join23(input.vault, "raw", "transcripts");
4912
4963
  let entries;
4913
4964
  try {
4914
- entries = await readdir5(dir, { withFileTypes: true });
4965
+ entries = await readdir4(dir, { withFileTypes: true });
4915
4966
  } catch {
4916
4967
  return { exitCode: ExitCode.VAULT_PATH_INVALID, result: { ok: false, error: "VAULT_PATH_INVALID", detail: `raw/transcripts/ not found: ${dir}` } };
4917
4968
  }
4918
4969
  const transcripts = [];
4919
4970
  for (const entry of entries) {
4920
4971
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
4921
- const filePath = join24(dir, entry.name);
4922
- const content = await readFile10(filePath, "utf8");
4972
+ const filePath = join23(dir, entry.name);
4973
+ const content = await readFile9(filePath, "utf8");
4923
4974
  const fm = extractFrontmatter(content);
4924
4975
  if (!fm.ok) continue;
4925
4976
  const ingested = typeof fm.data.ingested === "string" ? fm.data.ingested : "";
@@ -4936,8 +4987,8 @@ async function runTranscripts(input) {
4936
4987
  }
4937
4988
 
4938
4989
  // src/commands/claims-audit.ts
4939
- import { readFile as readFile11 } from "fs/promises";
4940
- import { join as join25 } from "path";
4990
+ import { readFile as readFile10 } from "fs/promises";
4991
+ import { join as join24 } from "path";
4941
4992
  function safeProjectPresentation(raw) {
4942
4993
  if (safeDiagnosticValue(raw) === REDACTED_MALFORMED_REFERENCE) {
4943
4994
  return REDACTED_MALFORMED_REFERENCE;
@@ -4977,9 +5028,9 @@ async function runClaimsAudit(input) {
4977
5028
  return !input.project || slugByDir.get(relDir) === input.project;
4978
5029
  });
4979
5030
  const claimSourceResults = await mapWithConcurrency(scopedSpecDirs, vaultIoConcurrency(), async (relDir) => {
4980
- const specPath = join25(input.vault, relDir, "spec.md");
5031
+ const specPath = join24(input.vault, relDir, "spec.md");
4981
5032
  try {
4982
- const specText = await readFile11(specPath, "utf8");
5033
+ const specText = await readFile10(specPath, "utf8");
4983
5034
  const fm = extractFrontmatter(specText);
4984
5035
  if (!fm.ok) return null;
4985
5036
  return {
@@ -5073,10 +5124,10 @@ async function runClaimsAudit(input) {
5073
5124
  }
5074
5125
 
5075
5126
  // src/commands/compound.ts
5076
- import { writeFile as writeFile6, mkdir as mkdir8, readdir as readdir6, unlink as unlink3 } from "fs/promises";
5077
- import { join as join26 } from "path";
5127
+ import { writeFile as writeFile5, mkdir as mkdir7, readdir as readdir5, unlink as unlink3 } from "fs/promises";
5128
+ import { join as join25 } from "path";
5078
5129
  import { existsSync as existsSync9 } from "fs";
5079
- import { readFile as readFile12 } from "fs/promises";
5130
+ import { readFile as readFile11 } from "fs/promises";
5080
5131
  var RETRO_HEADING_RE = /^## \[(\d{4}-\d{2}-\d{2})(?:\s+[^\]]+)?\] retro \| loop cycle(?: (\d+))?: (.+)$/;
5081
5132
  var FIELD_RE = {
5082
5133
  improve: /^-\s+\*?\*?Improve:?\*?\*?\s*(.+)$/m,
@@ -5174,17 +5225,17 @@ function extractRetroFields(date, cycleName, block) {
5174
5225
  };
5175
5226
  }
5176
5227
  async function runCompound(input) {
5177
- const logPath = join26(input.vault, "log.md");
5228
+ const logPath = join25(input.vault, "log.md");
5178
5229
  let logText;
5179
5230
  try {
5180
- logText = await readFile12(logPath, "utf8");
5231
+ logText = await readFile11(logPath, "utf8");
5181
5232
  } catch {
5182
5233
  return { exitCode: ExitCode.FILE_NOT_FOUND, result: err("FILE_NOT_FOUND", { path: logPath }) };
5183
5234
  }
5184
5235
  const entries = parseRetroEntries(logText);
5185
5236
  const promoted = [];
5186
5237
  const skipped = [];
5187
- const compoundDir = join26(input.vault, "projects", input.project, "compound");
5238
+ const compoundDir = join25(input.vault, "projects", input.project, "compound");
5188
5239
  for (const entry of entries) {
5189
5240
  const generalizeValue = entry.generalize.trim();
5190
5241
  if (!/^yes/i.test(generalizeValue)) {
@@ -5192,7 +5243,7 @@ async function runCompound(input) {
5192
5243
  continue;
5193
5244
  }
5194
5245
  const slug = slugify(entry.cycleName);
5195
- const compoundPath = join26(compoundDir, `${slug}.md`);
5246
+ const compoundPath = join25(compoundDir, `${slug}.md`);
5196
5247
  if (existsSync9(compoundPath)) {
5197
5248
  skipped.push(entry.date);
5198
5249
  continue;
@@ -5232,9 +5283,9 @@ async function runCompound(input) {
5232
5283
  const content = frontmatter + "\n" + body;
5233
5284
  if (!input.dryRun) {
5234
5285
  if (!existsSync9(compoundDir)) {
5235
- await mkdir8(compoundDir, { recursive: true });
5286
+ await mkdir7(compoundDir, { recursive: true });
5236
5287
  }
5237
- await writeFile6(compoundPath, content, "utf8");
5288
+ await writeFile5(compoundPath, content, "utf8");
5238
5289
  }
5239
5290
  promoted.push(`${slug}.md`);
5240
5291
  }
@@ -5253,7 +5304,7 @@ async function runCompound(input) {
5253
5304
  };
5254
5305
  }
5255
5306
  async function runCompoundDelete(input) {
5256
- const projectDir = join26(input.vault, "projects", input.project);
5307
+ const projectDir = join25(input.vault, "projects", input.project);
5257
5308
  if (!existsSync9(projectDir)) {
5258
5309
  return {
5259
5310
  exitCode: ExitCode.PROJECT_NOT_FOUND,
@@ -5261,7 +5312,7 @@ async function runCompoundDelete(input) {
5261
5312
  };
5262
5313
  }
5263
5314
  const entryName = input.entry.replace(/\.md$/, "");
5264
- const compoundPath = join26(projectDir, "compound", `${entryName}.md`);
5315
+ const compoundPath = join25(projectDir, "compound", `${entryName}.md`);
5265
5316
  if (!existsSync9(compoundPath)) {
5266
5317
  return {
5267
5318
  exitCode: ExitCode.FILE_NOT_FOUND,
@@ -5295,7 +5346,7 @@ knowledge.md regenerated`
5295
5346
  };
5296
5347
  }
5297
5348
  async function runCompoundList(input) {
5298
- const compoundDir = join26(input.vault, "projects", input.project, "compound");
5349
+ const compoundDir = join25(input.vault, "projects", input.project, "compound");
5299
5350
  if (!existsSync9(compoundDir)) {
5300
5351
  return {
5301
5352
  exitCode: ExitCode.OK,
@@ -5310,7 +5361,7 @@ no compound directory found`
5310
5361
  }
5311
5362
  let dirents;
5312
5363
  try {
5313
- dirents = await readdir6(compoundDir, { withFileTypes: true });
5364
+ dirents = await readdir5(compoundDir, { withFileTypes: true });
5314
5365
  } catch {
5315
5366
  return {
5316
5367
  exitCode: ExitCode.OK,
@@ -5326,10 +5377,10 @@ could not read compound directory`
5326
5377
  const entries = [];
5327
5378
  for (const dirent of dirents) {
5328
5379
  if (!dirent.isFile() || !dirent.name.endsWith(".md")) continue;
5329
- const filePath = join26(compoundDir, dirent.name);
5380
+ const filePath = join25(compoundDir, dirent.name);
5330
5381
  let text;
5331
5382
  try {
5332
- text = await readFile12(filePath, "utf8");
5383
+ text = await readFile11(filePath, "utf8");
5333
5384
  } catch {
5334
5385
  continue;
5335
5386
  }
@@ -5358,8 +5409,8 @@ no compound entries found`;
5358
5409
  }
5359
5410
 
5360
5411
  // src/commands/session-brief.ts
5361
- import { mkdir as mkdir9, readFile as readFile13, writeFile as writeFile7 } from "fs/promises";
5362
- import { join as join27, relative, sep } from "path";
5412
+ import { mkdir as mkdir8, readFile as readFile12, writeFile as writeFile6 } from "fs/promises";
5413
+ import { join as join26, relative, sep } from "path";
5363
5414
  var MAX_WORDS = 900;
5364
5415
  async function runSessionBrief(input) {
5365
5416
  const { root: scanRoot } = resolveReadOnlyVaultRoot(input.vault);
@@ -5473,7 +5524,7 @@ async function resolveProject(input) {
5473
5524
  const envProject = input.env?.SKILLWIKI_PROJECT;
5474
5525
  if (envProject) return envProject;
5475
5526
  const cwd = input.cwd ?? process.cwd();
5476
- const projectDotenv = await readProjectSlug(join27(cwd, ".skillwiki", ".env"));
5527
+ const projectDotenv = await readProjectSlug(join26(cwd, ".skillwiki", ".env"));
5477
5528
  if (projectDotenv) return projectDotenv;
5478
5529
  const inferred = inferProjectFromPath(input.vault, cwd);
5479
5530
  if (inferred) return inferred;
@@ -5482,7 +5533,7 @@ async function resolveProject(input) {
5482
5533
  async function readProjectSlug(file) {
5483
5534
  let text;
5484
5535
  try {
5485
- text = await readFile13(file, "utf8");
5536
+ text = await readFile12(file, "utf8");
5486
5537
  } catch {
5487
5538
  return void 0;
5488
5539
  }
@@ -5573,7 +5624,7 @@ async function loadTrendPages(typedPages, pathPattern) {
5573
5624
  return out;
5574
5625
  }
5575
5626
  async function loadSessionPins(vault, project) {
5576
- const text = await readIfExists(join27(vault, "meta", "session-pins.md"));
5627
+ const text = await readIfExists(join26(vault, "meta", "session-pins.md"));
5577
5628
  if (!text) return [];
5578
5629
  const fm = extractFrontmatter(text);
5579
5630
  if (!fm.ok) return [];
@@ -5719,7 +5770,7 @@ function satelliteHealthWarning(health) {
5719
5770
  return null;
5720
5771
  }
5721
5772
  async function loadHealthWarnings(vault) {
5722
- const text = await readIfExists(join27(vault, ".skillwiki", "health.json"));
5773
+ const text = await readIfExists(join26(vault, ".skillwiki", "health.json"));
5723
5774
  if (!text) return [];
5724
5775
  try {
5725
5776
  const parsed = JSON.parse(text);
@@ -5732,7 +5783,7 @@ async function loadHealthWarnings(vault) {
5732
5783
  }
5733
5784
  }
5734
5785
  async function loadMemoryTopics(vault, project) {
5735
- const text = await readIfExists(join27(vault, ".skillwiki", "memory", project, "topics.json"));
5786
+ const text = await readIfExists(join26(vault, ".skillwiki", "memory", project, "topics.json"));
5736
5787
  if (!text) return [];
5737
5788
  try {
5738
5789
  const parsed = JSON.parse(text);
@@ -5757,18 +5808,18 @@ async function loadMemoryTopics(vault, project) {
5757
5808
  }
5758
5809
  }
5759
5810
  async function writeBriefArtifacts(vault, input) {
5760
- const metaPath = join27(vault, "meta", "latest-session-brief.md");
5761
- const cacheMdPath = join27(vault, ".skillwiki", "session-brief.md");
5762
- const cacheJsonPath = join27(vault, ".skillwiki", "session-brief.json");
5763
- await mkdir9(join27(vault, "meta"), { recursive: true });
5764
- await mkdir9(join27(vault, ".skillwiki"), { recursive: true });
5811
+ const metaPath = join26(vault, "meta", "latest-session-brief.md");
5812
+ const cacheMdPath = join26(vault, ".skillwiki", "session-brief.md");
5813
+ const cacheJsonPath = join26(vault, ".skillwiki", "session-brief.json");
5814
+ await mkdir8(join26(vault, "meta"), { recursive: true });
5815
+ await mkdir8(join26(vault, ".skillwiki"), { recursive: true });
5765
5816
  const committed = renderCommittedBrief(input);
5766
5817
  const previousComparable = comparableBrief(await readIfExists(metaPath));
5767
5818
  const nextComparable = comparableBrief(committed);
5768
5819
  const materialChange = previousComparable !== nextComparable;
5769
- await writeFile7(metaPath, committed, "utf8");
5770
- await writeFile7(cacheMdPath, input.brief, "utf8");
5771
- await writeFile7(cacheJsonPath, `${JSON.stringify({
5820
+ await writeFile6(metaPath, committed, "utf8");
5821
+ await writeFile6(cacheMdPath, input.brief, "utf8");
5822
+ await writeFile6(cacheJsonPath, `${JSON.stringify({
5772
5823
  project: input.project,
5773
5824
  brief: input.brief,
5774
5825
  word_count: input.wordCount,
@@ -5834,7 +5885,7 @@ function renderCommittedBrief(input) {
5834
5885
  ].filter((line) => line !== "").join("\n");
5835
5886
  }
5836
5887
  async function rebuildRootIndexProjection(vault) {
5837
- const before = await readIfExists(join27(vault, "index.md"));
5888
+ const before = await readIfExists(join26(vault, "index.md"));
5838
5889
  if (!before) return false;
5839
5890
  const projection = await renderRootIndex({ vault, currentText: before });
5840
5891
  if (!projection.ok) return false;
@@ -5844,7 +5895,7 @@ async function rebuildRootIndexProjection(vault) {
5844
5895
  }
5845
5896
  async function readIfExists(path) {
5846
5897
  try {
5847
- return await readFile13(path, "utf8");
5898
+ return await readFile12(path, "utf8");
5848
5899
  } catch {
5849
5900
  return "";
5850
5901
  }
@@ -5886,14 +5937,14 @@ function dateFromPath(path) {
5886
5937
  }
5887
5938
 
5888
5939
  // src/commands/ingest.ts
5889
- import { readFile as readFile16, open, unlink as unlink4, mkdir as mkdir11 } from "fs/promises";
5890
- import { join as join32 } from "path";
5940
+ import { readFile as readFile15, open, unlink as unlink4, mkdir as mkdir10 } from "fs/promises";
5941
+ import { join as join31 } from "path";
5891
5942
  import { createHash as createHash5 } from "crypto";
5892
5943
 
5893
5944
  // src/commands/page-publish.ts
5894
5945
  import { readFileSync as readFileSync13, realpathSync as realpathSync2 } from "fs";
5895
- import { mkdir as mkdir10, readFile as readFile15 } from "fs/promises";
5896
- import { dirname as dirname8, join as join31, resolve as resolve4 } from "path";
5946
+ import { mkdir as mkdir9, readFile as readFile14 } from "fs/promises";
5947
+ import { dirname as dirname8, join as join30, resolve as resolve4 } from "path";
5897
5948
 
5898
5949
  // src/utils/publication-approval.ts
5899
5950
  import { createHash as createHash4 } from "crypto";
@@ -6121,8 +6172,8 @@ function redactApprovalTokens(text) {
6121
6172
  }
6122
6173
 
6123
6174
  // src/publish/pipeline.ts
6124
- import { readFile as readFile14 } from "fs/promises";
6125
- import { dirname as dirname7, join as join30, resolve as resolve3 } from "path";
6175
+ import { readFile as readFile13 } from "fs/promises";
6176
+ import { dirname as dirname7, join as join29, resolve as resolve3 } from "path";
6126
6177
 
6127
6178
  // src/utils/publication-operation-journal.ts
6128
6179
  import {
@@ -6135,7 +6186,7 @@ import {
6135
6186
  unlinkSync,
6136
6187
  writeFileSync as writeFileSync5
6137
6188
  } from "fs";
6138
- import { dirname as dirname6, join as join28 } from "path";
6189
+ import { dirname as dirname6, join as join27 } from "path";
6139
6190
  var PUBLICATION_JOURNAL_SCHEMA = "skillwiki-publication-operation-v1";
6140
6191
  var PHASE_ORDER2 = [
6141
6192
  "locked",
@@ -6164,16 +6215,16 @@ function vaultIdentity(vaultPath) {
6164
6215
  return sha256Hex(real).slice(0, 16);
6165
6216
  }
6166
6217
  function publicationJournalRoot(home = resolveSkillwikiHome()) {
6167
- return join28(resolveSkillwikiHome(home), ".skillwiki", "publication-operations");
6218
+ return join27(resolveSkillwikiHome(home), ".skillwiki", "publication-operations");
6168
6219
  }
6169
6220
  function resolveJournalPaths(vaultPath, operationId2, home = resolveSkillwikiHome()) {
6170
6221
  const identity = vaultIdentity(vaultPath);
6171
6222
  const rootDir = publicationJournalRoot(home);
6172
- const vaultDir = join28(rootDir, identity);
6223
+ const vaultDir = join27(rootDir, identity);
6173
6224
  return {
6174
6225
  rootDir,
6175
6226
  vaultDir,
6176
- journalPath: join28(vaultDir, `${operationId2}.json`)
6227
+ journalPath: join27(vaultDir, `${operationId2}.json`)
6177
6228
  };
6178
6229
  }
6179
6230
  function ensurePrivateDir(dir) {
@@ -6394,7 +6445,7 @@ function completePublicationJournal(input) {
6394
6445
  }
6395
6446
 
6396
6447
  // src/publish/hold-gates.ts
6397
- import { join as join29 } from "path";
6448
+ import { join as join28 } from "path";
6398
6449
  function evaluateSchemaGate(content, target, publisherKind) {
6399
6450
  const frontmatter = extractFrontmatter(content);
6400
6451
  if (!frontmatter.ok) return false;
@@ -6430,7 +6481,7 @@ function evaluateSchemaGate(content, target, publisherKind) {
6430
6481
  return false;
6431
6482
  }
6432
6483
  function evaluateBrokenWikilinkGate(body, scan, ownTarget) {
6433
- const draftPage = { absPath: join29(scan.root, ownTarget), relPath: ownTarget };
6484
+ const draftPage = { absPath: join28(scan.root, ownTarget), relPath: ownTarget };
6434
6485
  const resolver = buildWikilinkResolver([...scan.allMarkdown, draftPage]);
6435
6486
  const wikilinks = extractBodyWikilinks(body);
6436
6487
  for (const link of wikilinks) {
@@ -6617,7 +6668,7 @@ function phaseAtLeast(current, needed) {
6617
6668
  }
6618
6669
  async function readPageChanged(targetPath, content) {
6619
6670
  try {
6620
- return ok(await readFile14(targetPath, "utf8") !== content);
6671
+ return ok(await readFile13(targetPath, "utf8") !== content);
6621
6672
  } catch (error) {
6622
6673
  if (error.code === "ENOENT") return ok(true);
6623
6674
  return err("WRITE_FAILED", { path: targetPath, message: String(error) });
@@ -6625,7 +6676,7 @@ async function readPageChanged(targetPath, content) {
6625
6676
  }
6626
6677
  async function readPriorTargetSha(targetPath) {
6627
6678
  try {
6628
- const text = await readFile14(targetPath, "utf8");
6679
+ const text = await readFile13(targetPath, "utf8");
6629
6680
  return ok(sha256Hex(text));
6630
6681
  } catch (error) {
6631
6682
  if (error.code === "ENOENT") return ok("absent");
@@ -6658,10 +6709,10 @@ function successReceipt(strategy, prepared, details) {
6658
6709
  };
6659
6710
  }
6660
6711
  async function runPipelinePreview(strategy, prepared, vault) {
6661
- const schemaPath = join30(vault, "SCHEMA.md");
6712
+ const schemaPath = join29(vault, "SCHEMA.md");
6662
6713
  let schemaText;
6663
6714
  try {
6664
- schemaText = await readFile14(schemaPath, "utf8");
6715
+ schemaText = await readFile13(schemaPath, "utf8");
6665
6716
  } catch (error) {
6666
6717
  const result = err("FILE_NOT_FOUND", { path: schemaPath, message: String(error) });
6667
6718
  return { exitCode: ExitCode.FILE_NOT_FOUND, result };
@@ -6685,10 +6736,10 @@ async function runPipelinePreview(strategy, prepared, vault) {
6685
6736
  if (!indices.ok) {
6686
6737
  return { exitCode: indices.exitCode, result: indices.result };
6687
6738
  }
6688
- const logPath = join30(vault, "log.md");
6739
+ const logPath = join29(vault, "log.md");
6689
6740
  let logAppended;
6690
6741
  try {
6691
- const logText = await readFile14(logPath, "utf8");
6742
+ const logText = await readFile13(logPath, "utf8");
6692
6743
  const marker = strategy.publisherKind === "page" ? `<!-- skillwiki-page-publish:${prepared.operationId} -->` : `<!-- skillwiki-project-page-publish:${prepared.operationId} -->`;
6693
6744
  logAppended = !logText.includes(marker);
6694
6745
  } catch (error) {
@@ -6779,10 +6830,10 @@ async function runPipelineLockedPrimaryStages(strategy, prepared, vault, deps, j
6779
6830
  return { ok: false, exitCode: ExitCode.WRITE_FAILED, stage: "journal", state, cause: journalHook };
6780
6831
  }
6781
6832
  }
6782
- const schemaPath = join30(vault, "SCHEMA.md");
6833
+ const schemaPath = join29(vault, "SCHEMA.md");
6783
6834
  let schemaText;
6784
6835
  try {
6785
- schemaText = await readFile14(schemaPath, "utf8");
6836
+ schemaText = await readFile13(schemaPath, "utf8");
6786
6837
  } catch (error) {
6787
6838
  return {
6788
6839
  ok: false,
@@ -6831,8 +6882,8 @@ async function runPipelineLockedPrimaryStages(strategy, prepared, vault, deps, j
6831
6882
  if (!strategy.usesJournal || !phaseAtLeast(currentPhase, "page")) {
6832
6883
  if (strategy.publisherKind === "project-page") {
6833
6884
  try {
6834
- const { mkdir: mkdir14 } = await import("fs/promises");
6835
- await mkdir14(dirname7(prepared.targetPath), { recursive: true });
6885
+ const { mkdir: mkdir13 } = await import("fs/promises");
6886
+ await mkdir13(dirname7(prepared.targetPath), { recursive: true });
6836
6887
  } catch (error) {
6837
6888
  return {
6838
6889
  ok: false,
@@ -6880,8 +6931,8 @@ async function runPipelineLockedPrimaryStages(strategy, prepared, vault, deps, j
6880
6931
  let visibleSchema;
6881
6932
  try {
6882
6933
  [visible, visibleSchema] = await Promise.all([
6883
- readFile14(prepared.targetPath, "utf8"),
6884
- readFile14(schemaPath, "utf8")
6934
+ readFile13(prepared.targetPath, "utf8"),
6935
+ readFile13(schemaPath, "utf8")
6885
6936
  ]);
6886
6937
  } catch (error) {
6887
6938
  return {
@@ -7273,16 +7324,16 @@ async function refreshProjectIndexForTarget(vault, projectSlugs, today) {
7273
7324
  for (const slug of projectSlugs) {
7274
7325
  const rendered = await renderProjectIndex(vault, slug, { today });
7275
7326
  if (!rendered.ok) return rendered;
7276
- const indexPath = join31(vault, rendered.data.index_path);
7327
+ const indexPath = join30(vault, rendered.data.index_path);
7277
7328
  try {
7278
- await mkdir10(dirname8(indexPath), { recursive: true });
7329
+ await mkdir9(dirname8(indexPath), { recursive: true });
7279
7330
  } catch (error) {
7280
7331
  return err("WRITE_FAILED", { path: indexPath, message: String(error) });
7281
7332
  }
7282
7333
  const written = await atomicWriteText(indexPath, rendered.data.text);
7283
7334
  if (!written.ok) return written;
7284
7335
  try {
7285
- const visible = await readFile15(indexPath, "utf8");
7336
+ const visible = await readFile14(indexPath, "utf8");
7286
7337
  if (visible !== rendered.data.text) {
7287
7338
  return err("WRITE_FAILED", { path: indexPath, message: "project index verification failed" });
7288
7339
  }
@@ -7383,7 +7434,7 @@ function preparePagePublicationFromContent(input) {
7383
7434
  async function preparePagePublication(input) {
7384
7435
  let content;
7385
7436
  try {
7386
- content = await readFile15(input.draftPath, "utf8");
7437
+ content = await readFile14(input.draftPath, "utf8");
7387
7438
  } catch (error) {
7388
7439
  return err("FILE_NOT_FOUND", { path: input.draftPath, message: String(error) });
7389
7440
  }
@@ -7471,10 +7522,10 @@ var PAGE_PUBLISH_STRATEGY = {
7471
7522
  return void 0;
7472
7523
  },
7473
7524
  async previewIndices(prepared, vault, pageChanged) {
7474
- const indexPath = join31(vault, "index.md");
7525
+ const indexPath = join30(vault, "index.md");
7475
7526
  let indexText;
7476
7527
  try {
7477
- indexText = await readFile15(indexPath, "utf8");
7528
+ indexText = await readFile14(indexPath, "utf8");
7478
7529
  } catch (error) {
7479
7530
  const result = err("FILE_NOT_FOUND", { path: indexPath, message: String(error) });
7480
7531
  return { ok: false, exitCode: ExitCode.FILE_NOT_FOUND, result };
@@ -7492,7 +7543,7 @@ var PAGE_PUBLISH_STRATEGY = {
7492
7543
  if (!renderedProject.ok) {
7493
7544
  return { ok: false, exitCode: errorExitCode(renderedProject.error), result: renderedProject };
7494
7545
  }
7495
- const projectIndexPath = join31(vault, renderedProject.data.index_path);
7546
+ const projectIndexPath = join30(vault, renderedProject.data.index_path);
7496
7547
  const projectIndexChanged = await readPageChanged(projectIndexPath, renderedProject.data.text);
7497
7548
  if (!projectIndexChanged.ok) {
7498
7549
  return { ok: false, exitCode: errorExitCode(projectIndexChanged.error), result: projectIndexChanged };
@@ -7680,7 +7731,7 @@ function buildTypedContent(title, ingested, type, tags, rawRelPath, provenance)
7680
7731
  }
7681
7732
  async function resolveRawCapture(input) {
7682
7733
  try {
7683
- const existing = await readFile16(input.path, "utf8");
7734
+ const existing = await readFile15(input.path, "utf8");
7684
7735
  const frontmatter = extractFrontmatter(existing);
7685
7736
  if (!frontmatter.ok) {
7686
7737
  return err("INGEST_VALIDATION_FAILED", {
@@ -7819,7 +7870,7 @@ async function runIngest(input, pagePublishDeps = defaultPagePublishDeps()) {
7819
7870
  sourceContent = fetchResult.data.body;
7820
7871
  } else {
7821
7872
  try {
7822
- sourceContent = await readFile16(input.source, "utf8");
7873
+ sourceContent = await readFile15(input.source, "utf8");
7823
7874
  } catch {
7824
7875
  return {
7825
7876
  exitCode: ExitCode.FILE_NOT_FOUND,
@@ -7844,7 +7895,7 @@ async function runIngest(input, pagePublishDeps = defaultPagePublishDeps()) {
7844
7895
  const rawRelPath = `raw/articles/${slug}.md`;
7845
7896
  const typedDir = TYPE_DIR[input.type] ?? `${input.type}s`;
7846
7897
  const typedRelPath = `${typedDir}/${slug}.md`;
7847
- const rawAbsPath = join32(input.vault, rawRelPath);
7898
+ const rawAbsPath = join31(input.vault, rawRelPath);
7848
7899
  const identity = assessSourceIdentity({
7849
7900
  rawPath: rawRelPath,
7850
7901
  sourceUrl: sourceUrl ?? void 0,
@@ -7888,11 +7939,11 @@ async function runIngest(input, pagePublishDeps = defaultPagePublishDeps()) {
7888
7939
  );
7889
7940
  if (!input.dryRun) {
7890
7941
  try {
7891
- await mkdir11(join32(input.vault, typedDir), { recursive: true });
7942
+ await mkdir10(join31(input.vault, typedDir), { recursive: true });
7892
7943
  } catch (error) {
7893
7944
  return {
7894
7945
  exitCode: ExitCode.WRITE_FAILED,
7895
- result: err("WRITE_FAILED", { path: join32(input.vault, typedDir), message: String(error) })
7946
+ result: err("WRITE_FAILED", { path: join31(input.vault, typedDir), message: String(error) })
7896
7947
  };
7897
7948
  }
7898
7949
  }
@@ -7946,11 +7997,11 @@ async function runIngest(input, pagePublishDeps = defaultPagePublishDeps()) {
7946
7997
  preflight: pagePublishDeps.preflight,
7947
7998
  mutate: async (receipt) => {
7948
7999
  try {
7949
- await mkdir11(join32(input.vault, "raw", "articles"), { recursive: true });
8000
+ await mkdir10(join31(input.vault, "raw", "articles"), { recursive: true });
7950
8001
  } catch (error) {
7951
8002
  return {
7952
8003
  exitCode: ExitCode.WRITE_FAILED,
7953
- result: err("WRITE_FAILED", { path: join32(input.vault, "raw", "articles"), message: String(error) })
8004
+ result: err("WRITE_FAILED", { path: join31(input.vault, "raw", "articles"), message: String(error) })
7954
8005
  };
7955
8006
  }
7956
8007
  const rawWrite = await writeResolvedRaw({
@@ -8186,8 +8237,8 @@ ${body}`;
8186
8237
  }
8187
8238
 
8188
8239
  // src/commands/tag-reconcile.ts
8189
- import { readFile as readFile17 } from "fs/promises";
8190
- import { join as join33, posix } from "path";
8240
+ import { readFile as readFile16 } from "fs/promises";
8241
+ import { join as join32, posix } from "path";
8191
8242
  var TYPED_TARGET_RE = /^(entities|concepts|comparisons|queries|meta)\/[a-z0-9][a-z0-9./_-]*\.md$/;
8192
8243
  function errorExitCode2(error) {
8193
8244
  switch (error) {
@@ -8230,7 +8281,7 @@ function asTagArray(frontmatter, path) {
8230
8281
  async function readTagsFromFile(path) {
8231
8282
  let text;
8232
8283
  try {
8233
- text = await readFile17(path, "utf8");
8284
+ text = await readFile16(path, "utf8");
8234
8285
  } catch (error) {
8235
8286
  if (error.code === "ENOENT") {
8236
8287
  return { exitCode: ExitCode.FILE_NOT_FOUND, result: err("FILE_NOT_FOUND", { path }) };
@@ -8251,7 +8302,7 @@ async function resolveRequestedTags(input, page) {
8251
8302
  result: err("INVALID_FRONTMATTER", { message: "explicit tags must be an array of strings" })
8252
8303
  };
8253
8304
  }
8254
- const source = input.from ?? (explicit.length === 0 ? join33(input.vault, page) : void 0);
8305
+ const source = input.from ?? (explicit.length === 0 ? join32(input.vault, page) : void 0);
8255
8306
  if (!source) return { exitCode: ExitCode.OK, result: ok({ tags: [...new Set(explicit)].sort() }) };
8256
8307
  const sourced = await readTagsFromFile(source);
8257
8308
  if (!sourced.result.ok) return { exitCode: sourced.exitCode, result: sourced.result };
@@ -8262,7 +8313,7 @@ async function resolveRequestedTags(input, page) {
8262
8313
  }
8263
8314
  async function readSchema(schemaPath) {
8264
8315
  try {
8265
- return { exitCode: ExitCode.OK, result: ok(await readFile17(schemaPath, "utf8")) };
8316
+ return { exitCode: ExitCode.OK, result: ok(await readFile16(schemaPath, "utf8")) };
8266
8317
  } catch (error) {
8267
8318
  if (error.code === "ENOENT") {
8268
8319
  return { exitCode: ExitCode.FILE_NOT_FOUND, result: err("FILE_NOT_FOUND", { path: schemaPath }) };
@@ -8290,7 +8341,7 @@ function previewResult(page, tags, reconciled, dryRun, filesChanged) {
8290
8341
  };
8291
8342
  }
8292
8343
  async function reconcileTagsWhileLocked(input, page, tags, comment) {
8293
- const schemaPath = join33(input.vault, "SCHEMA.md");
8344
+ const schemaPath = join32(input.vault, "SCHEMA.md");
8294
8345
  const current = await readSchema(schemaPath);
8295
8346
  if (!current.result.ok) return { exitCode: current.exitCode, result: current.result };
8296
8347
  const next = reconcileTaxonomyDocument(current.result.data, { tags, comment });
@@ -8301,7 +8352,7 @@ async function reconcileTagsWhileLocked(input, page, tags, comment) {
8301
8352
  }
8302
8353
  let verifiedText;
8303
8354
  try {
8304
- verifiedText = await readFile17(schemaPath, "utf8");
8355
+ verifiedText = await readFile16(schemaPath, "utf8");
8305
8356
  } catch (error) {
8306
8357
  return {
8307
8358
  exitCode: ExitCode.WRITE_FAILED,
@@ -8327,7 +8378,7 @@ async function runTagReconcile(input) {
8327
8378
  const comment = taxonomyCommentForPage(page.data, date, input.reason);
8328
8379
  if (!comment.ok) return { exitCode: ExitCode.SCHEME_REJECTED, result: comment };
8329
8380
  if (!input.write) {
8330
- const schema = await readSchema(join33(input.vault, "SCHEMA.md"));
8381
+ const schema = await readSchema(join32(input.vault, "SCHEMA.md"));
8331
8382
  if (!schema.result.ok) return { exitCode: schema.exitCode, result: schema.result };
8332
8383
  const preview = reconcileTaxonomyDocument(schema.result.data, { tags, comment: comment.data });
8333
8384
  return previewResult(page.data, tags, preview, true, []);
@@ -8380,8 +8431,8 @@ async function runTagReconcile(input) {
8380
8431
 
8381
8432
  // src/commands/project-page-publish.ts
8382
8433
  import { realpathSync as realpathSync4 } from "fs";
8383
- import { mkdir as mkdir12, readFile as readFile18 } from "fs/promises";
8384
- import { dirname as dirname10, join as join34, resolve as resolve6 } from "path";
8434
+ import { mkdir as mkdir11, readFile as readFile17 } from "fs/promises";
8435
+ import { dirname as dirname10, join as join33, resolve as resolve6 } from "path";
8385
8436
 
8386
8437
  // src/utils/architecture-page.ts
8387
8438
  import { lstatSync, realpathSync as realpathSync3 } from "fs";
@@ -8553,7 +8604,7 @@ function validateLogNote(logNote) {
8553
8604
  async function prepareProjectPagePublication(input) {
8554
8605
  let content;
8555
8606
  try {
8556
- content = await readFile18(input.draftPath, "utf8");
8607
+ content = await readFile17(input.draftPath, "utf8");
8557
8608
  } catch (error) {
8558
8609
  return err("FILE_NOT_FOUND", { path: input.draftPath, message: String(error) });
8559
8610
  }
@@ -8686,9 +8737,9 @@ var PROJECT_PAGE_PUBLISH_STRATEGY = {
8686
8737
  async updateIndicesLocked(prepared, vault, state, observe) {
8687
8738
  const rendered = await renderProjectIndex(vault, prepared.page.project, { today: prepared.date });
8688
8739
  if (!rendered.ok) return rendered;
8689
- const knowledgePath = join34(vault, rendered.data.index_path);
8740
+ const knowledgePath = join33(vault, rendered.data.index_path);
8690
8741
  try {
8691
- await mkdir12(dirname10(knowledgePath), { recursive: true });
8742
+ await mkdir11(dirname10(knowledgePath), { recursive: true });
8692
8743
  } catch (error) {
8693
8744
  return err("WRITE_FAILED", { message: String(error) });
8694
8745
  }
@@ -8697,7 +8748,7 @@ var PROJECT_PAGE_PUBLISH_STRATEGY = {
8697
8748
  state.projectIndexUpdated = knowledgeWrite.data.changed;
8698
8749
  if (state.projectIndexUpdated) state.changed.add(rendered.data.index_path);
8699
8750
  try {
8700
- const visibleIndex = await readFile18(knowledgePath, "utf8");
8751
+ const visibleIndex = await readFile17(knowledgePath, "utf8");
8701
8752
  if (visibleIndex !== rendered.data.text) {
8702
8753
  return err("WRITE_FAILED", { message: "project knowledge.md verification failed" });
8703
8754
  }
@@ -8717,9 +8768,9 @@ var PROJECT_PAGE_PUBLISH_STRATEGY = {
8717
8768
  }
8718
8769
  let projectIndexChanged = true;
8719
8770
  if (projectIndex.ok) {
8720
- const indexPath = join34(vault, projectIndex.data.index_path);
8771
+ const indexPath = join33(vault, projectIndex.data.index_path);
8721
8772
  try {
8722
- const existing = await readFile18(indexPath, "utf8");
8773
+ const existing = await readFile17(indexPath, "utf8");
8723
8774
  projectIndexChanged = existing !== projectIndex.data.text || pageChanged;
8724
8775
  } catch {
8725
8776
  projectIndexChanged = true;
@@ -8879,7 +8930,7 @@ import { existsSync as existsSync11, writeFileSync as writeFileSync6, mkdirSync
8879
8930
  import { createHash as createHash6 } from "crypto";
8880
8931
  import { execSync as execSync3, spawn } from "child_process";
8881
8932
  import { platform as platform2 } from "os";
8882
- import { join as join35, resolve as resolvePath } from "path";
8933
+ import { join as join34, resolve as resolvePath } from "path";
8883
8934
  var MAINTENANCE_SCHEMA_VERSION = 1;
8884
8935
  var MAINTENANCE_COMMAND = "snapshot-maintenance journal clear-stale";
8885
8936
  var REPAIR_COMMAND = "snapshot-maintenance projection-conflict repair";
@@ -8944,7 +8995,7 @@ async function runSnapshotMaintenanceDryRun(input) {
8944
8995
  audit(makeAuditEvent(input, fleetLoad.hostId, now, "refusal", "MAINTENANCE_WRONG_WORKTREE"));
8945
8996
  return { exitCode: ExitCode.PROTECTED_SNAPSHOTTER_WRITE_BLOCKED, result: refusalErr("MAINTENANCE_WRONG_WORKTREE", `requested path '${requested}' is not the configured snapshot worktree '${canonicalize(configuredWorktree)}'`) };
8946
8997
  }
8947
- if (!existsSync11(requested) || !existsSync11(join35(requested, ".git"))) {
8998
+ if (!existsSync11(requested) || !existsSync11(join34(requested, ".git"))) {
8948
8999
  audit(makeAuditEvent(input, fleetLoad.hostId, now, "refusal", "MAINTENANCE_MISSING_GIT_REPO"));
8949
9000
  return { exitCode: ExitCode.PROTECTED_SNAPSHOTTER_WRITE_BLOCKED, result: refusalErr("MAINTENANCE_MISSING_GIT_REPO", `snapshot worktree is not a git repository: ${requested}`) };
8950
9001
  }
@@ -9024,14 +9075,14 @@ async function resolveLiveVault(input) {
9024
9075
  return resolved.ok ? canonicalize(resolved.data.path) : void 0;
9025
9076
  }
9026
9077
  function snapshotMaintenanceAuditLogPath(home) {
9027
- const stateDir = platform2() === "darwin" ? join35(home, "Library", "Application Support", "vault-sync") : join35(home, ".local", "state", "vault-sync");
9028
- return join35(stateDir, "snapshot-maintenance-audit.jsonl");
9078
+ const stateDir = platform2() === "darwin" ? join34(home, "Library", "Application Support", "vault-sync") : join34(home, ".local", "state", "vault-sync");
9079
+ return join34(stateDir, "snapshot-maintenance-audit.jsonl");
9029
9080
  }
9030
9081
  function defaultAuditSink(home) {
9031
9082
  return (event) => {
9032
9083
  try {
9033
9084
  const logPath = snapshotMaintenanceAuditLogPath(home);
9034
- mkdirSync4(join35(logPath, ".."), { recursive: true });
9085
+ mkdirSync4(join34(logPath, ".."), { recursive: true });
9035
9086
  appendFileSync(logPath, JSON.stringify(event) + "\n", { encoding: "utf8" });
9036
9087
  } catch {
9037
9088
  }
@@ -9179,9 +9230,9 @@ function nonMergeSequencerActive(repo) {
9179
9230
  const gitDir = git(repo, ["rev-parse", "--absolute-git-dir"]);
9180
9231
  if (!gitDir) return false;
9181
9232
  for (const m of ["CHERRY_PICK_HEAD", "REVERT_HEAD"]) {
9182
- if (existsSync11(join35(gitDir, m))) return true;
9233
+ if (existsSync11(join34(gitDir, m))) return true;
9183
9234
  }
9184
- return existsSync11(join35(gitDir, "rebase-merge")) || existsSync11(join35(gitDir, "rebase-apply"));
9235
+ return existsSync11(join34(gitDir, "rebase-merge")) || existsSync11(join34(gitDir, "rebase-apply"));
9185
9236
  }
9186
9237
  function extraUnmergedPaths(unmerged) {
9187
9238
  const allow = new Set(PROJECTION_CONFLICT_ALLOWLIST);
@@ -9220,7 +9271,7 @@ async function authorizeRepairContext(input) {
9220
9271
  audit(makeAuditEvent(input, fleetLoad.hostId, now, "refusal", "MAINTENANCE_WRONG_WORKTREE", void 0, REPAIR_COMMAND));
9221
9272
  return { exitCode: ExitCode.PROTECTED_SNAPSHOTTER_WRITE_BLOCKED, result: refusalErr("MAINTENANCE_WRONG_WORKTREE", `requested path '${requested}' is not the configured snapshot worktree '${canonicalize(configuredWorktree)}'`) };
9222
9273
  }
9223
- if (!existsSync11(requested) || !existsSync11(join35(requested, ".git"))) {
9274
+ if (!existsSync11(requested) || !existsSync11(join34(requested, ".git"))) {
9224
9275
  audit(makeAuditEvent(input, fleetLoad.hostId, now, "refusal", "MAINTENANCE_MISSING_GIT_REPO", void 0, REPAIR_COMMAND));
9225
9276
  return { exitCode: ExitCode.PROTECTED_SNAPSHOTTER_WRITE_BLOCKED, result: refusalErr("MAINTENANCE_MISSING_GIT_REPO", `snapshot worktree is not a git repository: ${requested}`) };
9226
9277
  }
@@ -9321,8 +9372,8 @@ async function performProjectionRepair(input, plan, audit, now) {
9321
9372
  return { exitCode: ExitCode.WRITE_FAILED, result: rendered };
9322
9373
  }
9323
9374
  try {
9324
- writeFileSync6(join35(plan.snapshot_worktree, "index.md"), rendered.data.index);
9325
- writeFileSync6(join35(plan.snapshot_worktree, "log.md"), rendered.data.log);
9375
+ writeFileSync6(join34(plan.snapshot_worktree, "index.md"), rendered.data.index);
9376
+ writeFileSync6(join34(plan.snapshot_worktree, "log.md"), rendered.data.log);
9326
9377
  gitStrict(plan.snapshot_worktree, ["add", "--", "index.md", "log.md"]);
9327
9378
  gitStrict(plan.snapshot_worktree, [
9328
9379
  "commit",
@@ -9430,7 +9481,7 @@ function releaseSnapshotFlock(handle) {
9430
9481
 
9431
9482
  // src/commands/backup.ts
9432
9483
  import { statSync as statSync3, readdirSync as readdirSync2, readFileSync as readFileSync15, mkdirSync as mkdirSync5, writeFileSync as writeFileSync7 } from "fs";
9433
- import { join as join36, relative as relative3, dirname as dirname11 } from "path";
9484
+ import { join as join35, relative as relative3, dirname as dirname11 } from "path";
9434
9485
  import { PutObjectCommand, HeadObjectCommand, ListObjectsV2Command, GetObjectCommand, DeleteObjectsCommand } from "@aws-sdk/client-s3";
9435
9486
 
9436
9487
  // src/utils/s3-client.ts
@@ -9454,7 +9505,7 @@ var SKIP_DIRS = /* @__PURE__ */ new Set([".git", ".obsidian", "_archive", "node_
9454
9505
  function* walkMarkdown(dir, base) {
9455
9506
  for (const entry of readdirSync2(dir, { withFileTypes: true })) {
9456
9507
  if (SKIP_DIRS.has(entry.name)) continue;
9457
- const full = join36(dir, entry.name);
9508
+ const full = join35(dir, entry.name);
9458
9509
  if (entry.isDirectory()) {
9459
9510
  yield* walkMarkdown(full, base);
9460
9511
  } else if (entry.name.endsWith(".md")) {
@@ -9477,7 +9528,7 @@ async function runBackupSync(input) {
9477
9528
  let failed = 0;
9478
9529
  const files = [...walkMarkdown(input.vault, input.vault)];
9479
9530
  for (const relPath of files) {
9480
- const absPath = join36(input.vault, relPath);
9531
+ const absPath = join35(input.vault, relPath);
9481
9532
  const localStat = statSync3(absPath);
9482
9533
  let needsUpload = true;
9483
9534
  try {
@@ -9553,7 +9604,7 @@ async function runBackupRestore(input) {
9553
9604
  const objects = list.Contents ?? [];
9554
9605
  for (const obj of objects) {
9555
9606
  if (!obj.Key) continue;
9556
- const localPath = join36(target, obj.Key);
9607
+ const localPath = join35(target, obj.Key);
9557
9608
  try {
9558
9609
  const localStat = statSync3(localPath);
9559
9610
  if (obj.LastModified && localStat.mtime > obj.LastModified) {
@@ -9600,8 +9651,8 @@ async function runBackupRestore(input) {
9600
9651
 
9601
9652
  // src/commands/status.ts
9602
9653
  import { existsSync as existsSync12, statSync as statSync4 } from "fs";
9603
- import { readFile as readFile19 } from "fs/promises";
9604
- import { join as join37 } from "path";
9654
+ import { readFile as readFile18 } from "fs/promises";
9655
+ import { join as join36 } from "path";
9605
9656
  var FUSE_NO_MIRROR_NOTE = "FUSE vault with no read mirror - status scan may be slow";
9606
9657
  async function runStatus(input) {
9607
9658
  if (!existsSync12(input.vault)) {
@@ -9640,7 +9691,7 @@ async function runStatus(input) {
9640
9691
  const compound = scan.data.compound.length;
9641
9692
  let schemaVersion = "v1";
9642
9693
  try {
9643
- const schemaContent = await readFile19(join37(scanRoot, "SCHEMA.md"), "utf8");
9694
+ const schemaContent = await readFile18(join36(scanRoot, "SCHEMA.md"), "utf8");
9644
9695
  const versionMatch = schemaContent.match(/version:\s*["']?([^"'\s\n]+)/i);
9645
9696
  if (versionMatch) schemaVersion = versionMatch[1];
9646
9697
  } catch {
@@ -9708,13 +9759,13 @@ async function runStatus(input) {
9708
9759
 
9709
9760
  // src/commands/copy-status.ts
9710
9761
  import { existsSync as existsSync13, realpathSync as realpathSync5 } from "fs";
9711
- import { isAbsolute as isAbsolute2, join as join39, relative as relative5, resolve as resolve8 } from "path";
9762
+ import { isAbsolute as isAbsolute2, join as join38, relative as relative5, resolve as resolve8 } from "path";
9712
9763
 
9713
9764
  // src/utils/fetch-projection.ts
9714
- import { isAbsolute, join as join38, resolve as resolve7 } from "path";
9765
+ import { isAbsolute, join as join37, resolve as resolve7 } from "path";
9715
9766
  function inspectConfiguredFetchProjection(home) {
9716
9767
  if (!home) return { configured: false };
9717
- const config = readSkillWikiConfig(join38(home, ".skillwiki", ".env"));
9768
+ const config = readSkillWikiConfig(join37(home, ".skillwiki", ".env"));
9718
9769
  const configured = config["vault_sync.fetch_projection"];
9719
9770
  if (!configured || configured === "none") return { configured: false };
9720
9771
  if (!isAbsolute(configured)) {
@@ -9725,7 +9776,7 @@ function inspectConfiguredFetchProjection(home) {
9725
9776
 
9726
9777
  // src/utils/live-drift.ts
9727
9778
  import { createHash as createHash7 } from "crypto";
9728
- import { readFile as readFile20 } from "fs/promises";
9779
+ import { readFile as readFile19 } from "fs/promises";
9729
9780
  import { relative as relative4, sep as sep3 } from "path";
9730
9781
 
9731
9782
  // src/utils/git-promotion.ts
@@ -9770,7 +9821,7 @@ async function measureAuthoritativeLiveDrift(liveVault, projection) {
9770
9821
  const rel = relative4(liveVault, page.absPath).split(sep3).join("/");
9771
9822
  if (!isGitPromotablePath(rel)) continue;
9772
9823
  livePromotable.add(rel);
9773
- const bytes = await readFile20(page.absPath);
9824
+ const bytes = await readFile19(page.absPath);
9774
9825
  if (projectionBlobs.get(rel) !== gitBlobOid(bytes)) content += 1;
9775
9826
  }
9776
9827
  for (const rel of projectionBlobs.keys()) {
@@ -9965,7 +10016,7 @@ function defaultCopyStatusDeps(input) {
9965
10016
  const projectionWarning = selection.configured ? `configured fetch projection ignored for Git status; using live vault${projectionProblem ? ` (${projectionProblem})` : ""}` : void 0;
9966
10017
  const invalidProjectionDetail = projectionProblem ?? "configured fetch projection is not a git repository";
9967
10018
  const gitRootProblem = () => {
9968
- if (!existsSync13(join39(gitVault, ".git"))) {
10019
+ if (!existsSync13(join38(gitVault, ".git"))) {
9969
10020
  return "vault is not a git repository";
9970
10021
  }
9971
10022
  return void 0;
@@ -10045,7 +10096,7 @@ function defaultCopyStatusDeps(input) {
10045
10096
  detail: projectionProblem ?? "live drift requires a configured fetch projection"
10046
10097
  };
10047
10098
  }
10048
- if (!existsSync13(join39(configuredProjection, ".git"))) {
10099
+ if (!existsSync13(join38(configuredProjection, ".git"))) {
10049
10100
  return {
10050
10101
  unknown: true,
10051
10102
  reason_code: "fetch_projection_invalid",
@@ -10065,8 +10116,8 @@ async function runCopyStatusCommand(input) {
10065
10116
  }
10066
10117
 
10067
10118
  // src/commands/seed.ts
10068
- import { mkdir as mkdir13, writeFile as writeFile8, stat as stat5 } from "fs/promises";
10069
- import { join as join40 } from "path";
10119
+ import { mkdir as mkdir12, writeFile as writeFile7, stat as stat5 } from "fs/promises";
10120
+ import { join as join39 } from "path";
10070
10121
  var TODAY = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
10071
10122
  var EXAMPLE_PAGES = {
10072
10123
  "entities/example-project.md": `---
@@ -10135,30 +10186,30 @@ Real sources are immutable after ingestion \u2014 never edit them.
10135
10186
  `;
10136
10187
  async function runSeed(input) {
10137
10188
  try {
10138
- await stat5(join40(input.vault, "SCHEMA.md"));
10189
+ await stat5(join39(input.vault, "SCHEMA.md"));
10139
10190
  } catch {
10140
10191
  return { exitCode: ExitCode.VAULT_PATH_INVALID, result: err("VAULT_PATH_INVALID", { root: input.vault, reason: "SCHEMA.md missing \u2014 run `skillwiki init` first" }) };
10141
10192
  }
10142
10193
  const created = [];
10143
10194
  const skipped = [];
10144
10195
  for (const [relPath, content] of Object.entries(EXAMPLE_PAGES)) {
10145
- const absPath = join40(input.vault, relPath);
10196
+ const absPath = join39(input.vault, relPath);
10146
10197
  try {
10147
10198
  await stat5(absPath);
10148
10199
  skipped.push(relPath);
10149
10200
  } catch {
10150
- await mkdir13(join40(absPath, ".."), { recursive: true });
10151
- await writeFile8(absPath, content, "utf8");
10201
+ await mkdir12(join39(absPath, ".."), { recursive: true });
10202
+ await writeFile7(absPath, content, "utf8");
10152
10203
  created.push(relPath);
10153
10204
  }
10154
10205
  }
10155
- const rawPath = join40(input.vault, "raw", "articles", "example-source.md");
10206
+ const rawPath = join39(input.vault, "raw", "articles", "example-source.md");
10156
10207
  try {
10157
10208
  await stat5(rawPath);
10158
10209
  skipped.push("raw/articles/example-source.md");
10159
10210
  } catch {
10160
- await mkdir13(join40(rawPath, ".."), { recursive: true });
10161
- await writeFile8(rawPath, EXAMPLE_RAW, "utf8");
10211
+ await mkdir12(join39(rawPath, ".."), { recursive: true });
10212
+ await writeFile7(rawPath, EXAMPLE_RAW, "utf8");
10162
10213
  created.push("raw/articles/example-source.md");
10163
10214
  }
10164
10215
  if (created.length > 0) {
@@ -10180,9 +10231,9 @@ async function runSeed(input) {
10180
10231
  }
10181
10232
 
10182
10233
  // src/commands/canvas.ts
10183
- import { readFile as readFile21, writeFile as writeFile9 } from "fs/promises";
10234
+ import { readFile as readFile20, writeFile as writeFile8 } from "fs/promises";
10184
10235
  import { existsSync as existsSync14 } from "fs";
10185
- import { join as join41 } from "path";
10236
+ import { join as join40 } from "path";
10186
10237
  var NODE_WIDTH = 240;
10187
10238
  var NODE_HEIGHT = 60;
10188
10239
  var COLUMN_SPACING = 400;
@@ -10260,7 +10311,7 @@ function buildCanvasEdges(adjacency) {
10260
10311
  return edges;
10261
10312
  }
10262
10313
  async function runCanvasGenerate(input) {
10263
- const graphPath = input.graphPath ?? join41(input.vault, ".skillwiki", "graph.json");
10314
+ const graphPath = input.graphPath ?? join40(input.vault, ".skillwiki", "graph.json");
10264
10315
  if (!existsSync14(graphPath)) {
10265
10316
  return {
10266
10317
  exitCode: ExitCode.FILE_NOT_FOUND,
@@ -10272,7 +10323,7 @@ async function runCanvasGenerate(input) {
10272
10323
  }
10273
10324
  let raw;
10274
10325
  try {
10275
- raw = await readFile21(graphPath, "utf8");
10326
+ raw = await readFile20(graphPath, "utf8");
10276
10327
  } catch (e) {
10277
10328
  return {
10278
10329
  exitCode: ExitCode.FILE_NOT_FOUND,
@@ -10298,9 +10349,9 @@ async function runCanvasGenerate(input) {
10298
10349
  const nodes = buildCanvasNodes(paths);
10299
10350
  const edges = buildCanvasEdges(graph.adjacency);
10300
10351
  const canvas = { nodes, edges };
10301
- const outPath = join41(input.vault, "vault-graph.canvas");
10352
+ const outPath = join40(input.vault, "vault-graph.canvas");
10302
10353
  try {
10303
- await writeFile9(outPath, JSON.stringify(canvas, null, 2));
10354
+ await writeFile8(outPath, JSON.stringify(canvas, null, 2));
10304
10355
  } catch (e) {
10305
10356
  return {
10306
10357
  exitCode: ExitCode.WRITE_FAILED,
@@ -10443,22 +10494,22 @@ async function runSourceDisposition(input) {
10443
10494
 
10444
10495
  // src/utils/source-disposal.ts
10445
10496
  import { createHash as createHash8 } from "crypto";
10446
- import { readFile as readFile23, unlink as unlink5 } from "fs/promises";
10497
+ import { readFile as readFile22, unlink as unlink5 } from "fs/promises";
10447
10498
 
10448
10499
  // src/utils/raw-asset-reference-index.ts
10449
- import { readdir as readdir7, readFile as readFile22 } from "fs/promises";
10450
- import { join as join42, relative as relative6, sep as sep4 } from "path";
10500
+ import { readdir as readdir6, readFile as readFile21 } from "fs/promises";
10501
+ import { join as join41, relative as relative6, sep as sep4 } from "path";
10451
10502
  var PREVIEW_EXTENSIONS = /* @__PURE__ */ new Set(["png", "jpg", "jpeg", "gif", "webp", "svg", "bmp", "avif", "pdf", "mp3", "wav", "m4a", "mp4", "webm"]);
10452
10503
  async function walkFiles(root, dir = root) {
10453
10504
  let entries;
10454
10505
  try {
10455
- entries = await readdir7(dir, { withFileTypes: true });
10506
+ entries = await readdir6(dir, { withFileTypes: true });
10456
10507
  } catch {
10457
10508
  return [];
10458
10509
  }
10459
10510
  const out = [];
10460
10511
  for (const entry of entries) {
10461
- const path = join42(dir, entry.name);
10512
+ const path = join41(dir, entry.name);
10462
10513
  if (entry.isDirectory()) out.push(...await walkFiles(root, path));
10463
10514
  else if (entry.isFile()) out.push(relative6(root, path).split(sep4).join("/"));
10464
10515
  }
@@ -10474,7 +10525,7 @@ function addInbound(map, target, source) {
10474
10525
  map.set(target, refs);
10475
10526
  }
10476
10527
  async function buildRawAssetReferenceIndex(vault) {
10477
- const assetRoot = join42(vault, "raw", "assets");
10528
+ const assetRoot = join41(vault, "raw", "assets");
10478
10529
  const relativeAssets = await walkFiles(assetRoot);
10479
10530
  const assets = relativeAssets.map((path) => `raw/assets/${path}`).sort((a, b) => a.localeCompare(b));
10480
10531
  const assetSet = new Set(assets);
@@ -10490,7 +10541,7 @@ async function buildRawAssetReferenceIndex(vault) {
10490
10541
  for (const page of scan.data.allMarkdown) {
10491
10542
  let text;
10492
10543
  try {
10493
- text = await readFile22(page.absPath, "utf8");
10544
+ text = await readFile21(page.absPath, "utf8");
10494
10545
  } catch {
10495
10546
  continue;
10496
10547
  }
@@ -10550,7 +10601,7 @@ async function planSourceDisposal(input) {
10550
10601
  if (sensitive.length > 0) return err("SENSITIVE_CONTENT_DETECTED", { findings: sensitive });
10551
10602
  const target = await resolveExistingRegularFileInsideVault(input.vault, input.rawPath);
10552
10603
  if (!target.ok) return err("RAW_DISPOSAL_TARGET_INVALID", { path: input.rawPath, cause: target });
10553
- const bytes = await readFile23(target.data);
10604
+ const bytes = await readFile22(target.data);
10554
10605
  const size = bytes.byteLength;
10555
10606
  let typedReferences = [];
10556
10607
  let otherReferences = [];
@@ -10674,7 +10725,7 @@ async function runSourceDisposal(input) {
10674
10725
  import { existsSync as existsSync15, readFileSync as readFileSync16 } from "fs";
10675
10726
  import { execSync as nodeExecSync } from "child_process";
10676
10727
  import { hostname as nodeHostname, platform as nodePlatform } from "os";
10677
- import { join as join43 } from "path";
10728
+ import { join as join42 } from "path";
10678
10729
  var SSH_TIMEOUT_MS = 15e3;
10679
10730
  var TIMER_UNIT = "agent-memory-trends.timer";
10680
10731
  var SERVICE_UNIT = "agent-memory-trends.service";
@@ -10904,7 +10955,7 @@ async function runFleetHealth(input) {
10904
10955
  const home = resolveSkillwikiHome(input.home, env);
10905
10956
  const osHostname = input.osHostname ?? env.HOSTNAME ?? nodeHostname();
10906
10957
  const vault = input.vault ?? env.WIKI_PATH;
10907
- const file = input.file ?? (vault ? join43(vault, FLEET_REL_PATH) : void 0);
10958
+ const file = input.file ?? (vault ? join42(vault, FLEET_REL_PATH) : void 0);
10908
10959
  if (!file) {
10909
10960
  return {
10910
10961
  exitCode: ExitCode.NO_VAULT_CONFIGURED,
@@ -10989,7 +11040,7 @@ async function runFleetHealth(input) {
10989
11040
 
10990
11041
  // src/utils/auto-commit.ts
10991
11042
  import { existsSync as existsSync16 } from "fs";
10992
- import { isAbsolute as isAbsolute3, join as join44, normalize } from "path";
11043
+ import { isAbsolute as isAbsolute3, join as join43, normalize } from "path";
10993
11044
  function isValidLastOpPath(file) {
10994
11045
  if (!file || typeof file !== "string") return false;
10995
11046
  const trimmed = file.trim();
@@ -11010,7 +11061,7 @@ async function postCommit(vault, exitCode) {
11010
11061
  const dotenv = await parseDotenvFile(configPath(home));
11011
11062
  const autoCommit = process.env.AUTO_COMMIT ?? dotenv["AUTO_COMMIT"];
11012
11063
  if (autoCommit === "false") return;
11013
- if (!existsSync16(join44(vault, ".git"))) return;
11064
+ if (!existsSync16(join43(vault, ".git"))) return;
11014
11065
  const lastOps = readLastOp(vault);
11015
11066
  if (lastOps.length === 0) return;
11016
11067
  const porcelain = git(vault, ["status", "--porcelain", "--", ...VAULT_COMMIT_PATHSPEC]);
@@ -11058,8 +11109,8 @@ function preflight(error) {
11058
11109
  }
11059
11110
  async function runMcpAuthIssueHost(input) {
11060
11111
  const isTty = input.isTty ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
11061
- const readFile24 = input.readFile ?? readFileSync17;
11062
- const writeFile10 = input.writeFile ?? writeFileSync8;
11112
+ const readFile23 = input.readFile ?? readFileSync17;
11113
+ const writeFile9 = input.writeFile ?? writeFileSync8;
11063
11114
  const stderrWrite = input.stderrWrite ?? ((s) => {
11064
11115
  process.stderr.write(s);
11065
11116
  });
@@ -11073,7 +11124,7 @@ async function runMcpAuthIssueHost(input) {
11073
11124
  if (write && !isTty) return preflight("NO_TTY");
11074
11125
  let yamlText = "";
11075
11126
  try {
11076
- yamlText = readFile24(mapPath, "utf8");
11127
+ yamlText = readFile23(mapPath, "utf8");
11077
11128
  } catch (error) {
11078
11129
  if (!isEnoent(error)) throw error;
11079
11130
  }
@@ -11095,7 +11146,7 @@ async function runMcpAuthIssueHost(input) {
11095
11146
  const appended = appendHostHash(yamlText, hashHex, hostId, granted.vaults);
11096
11147
  if ("error" in appended) return preflight(appended.error);
11097
11148
  try {
11098
- writeFile10(mapPath, appended.yaml, { encoding: "utf8", mode: 416 });
11149
+ writeFile9(mapPath, appended.yaml, { encoding: "utf8", mode: 416 });
11099
11150
  } catch (error) {
11100
11151
  if (isEnoent(error)) {
11101
11152
  return { exitCode: ExitCode.FILE_NOT_FOUND, result: err("FILE_NOT_FOUND") };
@@ -11255,7 +11306,7 @@ async function emitManagedVaultWrite(vault, command, mutate, opts) {
11255
11306
  if (dirty) {
11256
11307
  return emit(dirty, void 0, { postCommit: false });
11257
11308
  }
11258
- const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-JPOBVVSU.js");
11309
+ const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-L7IRQ76C.js");
11259
11310
  const run = await runManagedWriteTransaction2({
11260
11311
  vault,
11261
11312
  command,
@@ -11285,7 +11336,7 @@ program.command("validate <file>").description("validate vault page frontmatter
11285
11336
  emit(await runValidate({ file, apply: !!opts.apply, vault }), vault);
11286
11337
  });
11287
11338
  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) => {
11288
- const out = opts.out ?? join45(vault, ".skillwiki", "graph.json");
11339
+ const out = opts.out ?? join44(vault, ".skillwiki", "graph.json");
11289
11340
  return emitGuardedVaultWrite(vault, "graph build", () => runGraphBuild({ vault, out }));
11290
11341
  });
11291
11342
  var canvasCmd = program.command("canvas").description("manage Obsidian canvas files");
@@ -11901,6 +11952,9 @@ program.command("doctor").description("diagnose skillwiki setup issues").option(
11901
11952
  })));
11902
11953
  var clipOutboxCmd = program.command("clip-outbox").description("dedicated file-level web-clip outbox");
11903
11954
  clipOutboxCmd.command("status").description("show whether the clip-outbox channel is configured").action(async () => emit(await runClipOutboxStatus(resolveSkillwikiHome())));
11955
+ clipOutboxCmd.command("watch").description("run the enabled dedicated outbox worker using macOS FSEvents").action(async () => emit(await runClipOutboxWatch(resolveSkillwikiHome())));
11956
+ clipOutboxCmd.command("mirror-watch").description("copy admitted raw/articles and raw/assets from storage into the frozen mirror using MCP SSE").action(async () => emit(await runClipOutboxMirrorWatch(resolveSkillwikiHome())));
11957
+ clipOutboxCmd.command("install-or-migrate").description("refresh the packaged launchd plist without enabling the channel").option("--load", "attended clip watcher bootstrap; requires existing enabled=true", false).option("--load-mirror", "attended inbound SSE bootstrap; requires existing enabled=true; never auto-loaded on upgrade", false).option("--conditional-create-proven", "attest the deployed SeaweedFS If-None-Match:* race test passed", false).action(async (opts) => emit(await runClipOutboxInstall({ home: resolveSkillwikiHome(), load: opts.load, loadMirror: opts.loadMirror, conditionalCreateProven: opts.conditionalCreateProven })));
11904
11958
  program.command("connect").description(CONNECT_DESCRIPTION).option("--from-file <path>", "chat-attached env file (not Drive / \u4E91\u76D8)").option("--from-stdin", "read env file from stdin (no echo)").option("--dry-run", "validate without writing ~/.skillwiki/.env").option("--force", "overwrite a different existing token").action(async (opts) => emit(await runConnect({
11905
11959
  home: resolveSkillwikiHome(),
11906
11960
  fromFile: opts.fromFile,