skillwiki 0.10.26 → 0.10.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -6,82 +6,39 @@ import {
6
6
  DEFAULT_NO_DECISION_STREAK,
7
7
  GateError,
8
8
  SATELLITE_STALE_MS,
9
- acquireLock,
10
- acquireOwnedSyncLock,
11
- appendLastOp,
12
- applyRawStructuralMove,
13
- assessSourceIdentity,
14
- buildDegradedReasons,
15
- buildRemoteObjectPath,
16
- clearLastOp,
17
9
  configPath,
18
10
  evaluateDirtyVolumeGate,
19
11
  evaluateSatelliteRunHealth,
20
- extractTaxonomy,
21
12
  findPlugin,
22
- fixPathTooLong,
23
- getCliSessionId,
24
- getSessionId,
25
13
  isFailedRunStatus,
26
- isValidRemoteDeleteCap,
27
14
  memoryAuthorityTiersRank,
28
- mergeTaxonomyConflict,
29
- normalizeRemoteRoot,
30
- planAndMaybePruneRemoteObjects,
31
- planRawStructuralMove,
32
- probeRemoteHealth,
33
15
  readCliPackageJson,
34
- readLastOp,
35
- readLock,
36
16
  readSatelliteLatestRunFromText,
37
- reconcileTaxonomyDocument,
38
- releaseLock,
39
- releaseOwnedSyncLock,
40
17
  renderIndexUpsert,
41
18
  renderProjectIndex,
42
- resolveInitTimePath,
43
- resolveRuntimePath,
44
- rewriteRawSourceReferences,
45
- runAudit,
46
19
  runConfigGet,
47
20
  runConfigList,
48
21
  runConfigPath,
49
22
  runConfigSet,
50
- runDedup,
51
23
  runDoctor,
52
- runFrontmatterFix,
53
24
  runGraphBuild,
54
- runIndexCheck,
55
- runIndexLinkFormat,
56
- runLinks,
57
- runLint,
58
25
  runLogAppend,
59
- runLogRotate,
60
26
  runMemoryImport,
61
27
  runMemoryIndex,
62
28
  runMemoryRecall,
63
29
  runMemoryReview,
64
30
  runMemoryTopics,
65
31
  runObserve,
66
- runOrphans,
67
- runPagesize,
68
32
  runProjectIndex,
69
33
  runQuery,
70
34
  runSkillwikiMcpStdio,
71
- runStale,
72
- runSyncLintDelta,
73
- runTagAudit,
74
- runTopicMapCheck,
75
35
  runValidate,
76
36
  runWritePreflight,
77
- safeWritePage,
78
37
  satelliteLatestRunPath,
79
38
  scanConflictMarkerBlocksInText,
80
- snapshotMaintainedPageState,
81
39
  snapshotterHealthChecks,
82
- taxonomyCommentForPage,
83
40
  upsertIndexEntry
84
- } from "./chunk-VXMHHXVP.js";
41
+ } from "./chunk-W7NPTDIU.js";
85
42
  import {
86
43
  normalizeDistTag,
87
44
  readCache,
@@ -92,44 +49,89 @@ import {
92
49
  import {
93
50
  UNMANAGED_END,
94
51
  UNMANAGED_START,
95
- assertTargetInsideVault,
96
- atomicWriteText,
97
- prepareTypedPage,
98
52
  renderRootIndex,
99
53
  writeRootIndexProjection
100
- } from "./chunk-QBZYEEBD.js";
54
+ } from "./chunk-OJVIND5D.js";
101
55
  import {
56
+ VAULT_COMMIT_PATHSPEC,
102
57
  runManagedWritePreflight,
103
- runManagedWriteTransaction
104
- } from "./chunk-BASWDOQB.js";
58
+ runManagedWriteTransaction,
59
+ runSyncLock,
60
+ runSyncPeers,
61
+ runSyncPull,
62
+ runSyncPush,
63
+ runSyncStatus,
64
+ runSyncUnlock,
65
+ stageVaultContentChanges
66
+ } from "./chunk-NOXDRIHM.js";
105
67
  import {
106
68
  FLEET_REL_PATH,
69
+ acquireOwnedSyncLock,
70
+ appendLastOp,
71
+ applyRawStructuralMove,
72
+ assessSourceIdentity,
73
+ buildRemoteObjectPath,
107
74
  canSupersedeJournal,
75
+ clearLastOp,
76
+ extractTaxonomy,
77
+ getCliSessionId,
108
78
  git,
109
79
  gitStrict,
110
80
  hasActiveGitSequencer,
111
81
  hasUnmergedPaths,
82
+ isValidRemoteDeleteCap,
112
83
  isWorktreeClean,
113
84
  listJournalOpIds,
114
85
  listReviewRequiredOps,
115
86
  loadFleetManifest,
116
87
  loadFleetManifestAndHost,
117
88
  markJournalSuperseded,
89
+ mergeTaxonomyConflict,
90
+ normalizeRemoteRoot,
118
91
  parseDotenvFile,
119
92
  parseDotenvText,
120
93
  parseJournalEnv,
94
+ planAndMaybePruneRemoteObjects,
95
+ planRawStructuralMove,
121
96
  profileKey,
122
97
  readJournal,
98
+ readLastOp,
99
+ reconcileTaxonomyDocument,
100
+ releaseOwnedSyncLock,
123
101
  resolveConfiguredSnapshotWorktree,
124
102
  resolveFleetHostId,
103
+ resolveInitTimePath,
104
+ resolveRuntimePath,
105
+ rewriteRawSourceReferences,
106
+ runAudit,
107
+ runDedup,
125
108
  runFleetContext,
126
109
  runFleetValidate,
127
- runVaultSyncPullHelper,
110
+ runFrontmatterFix,
111
+ runIndexCheck,
112
+ runIndexLinkFormat,
113
+ runLinks,
114
+ runLint,
115
+ runLogRotate,
116
+ runOrphans,
117
+ runPagesize,
118
+ runStale,
119
+ runSyncLintDelta,
120
+ runTagAudit,
121
+ runTopicMapCheck,
122
+ safeWritePage,
128
123
  serializeJournalEnv,
124
+ snapshotMaintainedPageState,
129
125
  snapshotterAliasForLocalHost,
130
126
  supersedeStaleReviewRequiredJournals,
127
+ taxonomyCommentForPage,
131
128
  writeDotenv
132
- } from "./chunk-PQG26AGJ.js";
129
+ } from "./chunk-5XQWYC5K.js";
130
+ import {
131
+ assertTargetInsideVault,
132
+ atomicWriteText,
133
+ prepareTypedPage
134
+ } from "./chunk-UI4SOWI2.js";
133
135
  import {
134
136
  applySourceDisposition,
135
137
  decodeSourceActionApproval,
@@ -137,7 +139,7 @@ import {
137
139
  inventorySources,
138
140
  planSourceDisposition,
139
141
  runSourcesPending
140
- } from "./chunk-EQPU2BPM.js";
142
+ } from "./chunk-23CR4YPL.js";
141
143
  import {
142
144
  authorizeRawOperation,
143
145
  buildSourceReferenceIndex,
@@ -153,15 +155,7 @@ import {
153
155
  resolveExistingRegularFileInsideVault,
154
156
  validateLogEvent,
155
157
  writeLogEvent
156
- } from "./chunk-QNTBNNEL.js";
157
- import {
158
- extractFrontmatter,
159
- readPage,
160
- redactSensitiveContent,
161
- scanSensitiveContent,
162
- scanVault,
163
- splitFrontmatter
164
- } from "./chunk-6ZDKTNLA.js";
158
+ } from "./chunk-SGZPIGGX.js";
165
159
  import {
166
160
  ExitCode,
167
161
  MetaSchema,
@@ -169,12 +163,18 @@ import {
169
163
  TypedKnowledgeSchema,
170
164
  detectSchema,
171
165
  err,
166
+ extractFrontmatter,
172
167
  isBlockedHost,
173
- ok
174
- } from "./chunk-C2DKFJFA.js";
168
+ ok,
169
+ readPage,
170
+ redactSensitiveContent,
171
+ scanSensitiveContent,
172
+ scanVault,
173
+ splitFrontmatter
174
+ } from "./chunk-RQARJ6HB.js";
175
175
 
176
176
  // src/cli.ts
177
- import { join as join39 } from "path";
177
+ import { join as join38 } from "path";
178
178
  import { Command } from "commander";
179
179
 
180
180
  // src/utils/output.ts
@@ -3348,7 +3348,7 @@ ${fmRewritten}
3348
3348
  }
3349
3349
  let indexUpdated = false;
3350
3350
  if (!isRaw) {
3351
- const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-FRWTZB5Y.js");
3351
+ const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-64WW36N3.js");
3352
3352
  const before = await readFile7(join18(input.vault, "index.md"), "utf8").catch(() => "");
3353
3353
  const fullTarget = relPath.replace(/\.md$/, "");
3354
3354
  const bare = fullTarget.split("/").pop() ?? fullTarget;
@@ -3468,7 +3468,7 @@ async function runRemove(input) {
3468
3468
  if (relPath.endsWith(".md") && !relPath.startsWith("raw/")) {
3469
3469
  const { readFile: readFile20 } = await import("fs/promises");
3470
3470
  const { join: pathJoin } = await import("path");
3471
- const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-FRWTZB5Y.js");
3471
+ const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-64WW36N3.js");
3472
3472
  const before = await readFile20(pathJoin(input.vault, "index.md"), "utf8").catch(() => "");
3473
3473
  const fullTarget = relPath.replace(/\.md$/, "");
3474
3474
  const bare = fullTarget.split("/").pop() ?? fullTarget;
@@ -7793,602 +7793,6 @@ async function runProjectPagePublish(input, deps = DEFAULT_DEPS3) {
7793
7793
  return publishPrepared(prepared.data, input.vault, deps, input.journalHome);
7794
7794
  }
7795
7795
 
7796
- // src/commands/sync.ts
7797
- import { existsSync as existsSync9 } from "fs";
7798
- import { join as join30 } from "path";
7799
- import { execFileSync as execFileSync3 } from "child_process";
7800
-
7801
- // src/utils/vault-git-pathspec.ts
7802
- var VAULT_GENERATED_COMMIT_PATHS = [
7803
- ".skillwiki/last-op.json",
7804
- ".skillwiki/memory",
7805
- ".skillwiki/memory-topics.json"
7806
- ];
7807
- var VAULT_GENERATED_COMMIT_EXCLUDES = [
7808
- ...VAULT_GENERATED_COMMIT_PATHS.map((path) => `:!${path}`)
7809
- ];
7810
- var VAULT_COMMIT_PATHSPEC = [".", ...VAULT_GENERATED_COMMIT_EXCLUDES];
7811
- function stageVaultContentChanges(vault) {
7812
- gitStrict(vault, ["add", "-A", "--", "."]);
7813
- for (const generatedPath of VAULT_GENERATED_COMMIT_PATHS) {
7814
- try {
7815
- gitStrict(vault, ["reset", "HEAD", "--", generatedPath]);
7816
- } catch (_e) {
7817
- }
7818
- }
7819
- }
7820
-
7821
- // src/commands/sync.ts
7822
- function parseDirtyPaths(porcelain) {
7823
- if (!porcelain) return [];
7824
- return porcelain.split("\n").map((line) => line.trimEnd()).filter((line) => line.length >= 4).map((line) => {
7825
- const payload = line.length >= 3 && line[2] === " " ? line.slice(3) : line.length >= 2 && line[1] === " " ? line.slice(2) : line;
7826
- const arrow = payload.lastIndexOf(" -> ");
7827
- return arrow >= 0 ? payload.slice(arrow + 4) : payload;
7828
- }).filter((path) => path.length > 0);
7829
- }
7830
- function splitNonEmptyLines(text) {
7831
- if (!text) return [];
7832
- return text.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
7833
- }
7834
- function isTrackedNotePath(path) {
7835
- if (!path.endsWith(".md")) return false;
7836
- return !/^\.(skillwiki|claude|obsidian|antigravitycli|playwright-cli)\//.test(path);
7837
- }
7838
- function refHasPath(vault, ref, path) {
7839
- try {
7840
- execFileSync3("git", ["cat-file", "-e", `${ref}:${path}`], {
7841
- cwd: vault,
7842
- stdio: ["pipe", "pipe", "pipe"]
7843
- });
7844
- return true;
7845
- } catch {
7846
- return false;
7847
- }
7848
- }
7849
- function runSyncStatus(input) {
7850
- const vault = input.vault;
7851
- const includeStashes = input.includeStashes ?? false;
7852
- if (!existsSync9(join30(vault, ".git"))) {
7853
- return {
7854
- exitCode: ExitCode.VAULT_PATH_INVALID,
7855
- result: ok({
7856
- is_git_repo: false,
7857
- dirty: 0,
7858
- ahead: 0,
7859
- behind: 0,
7860
- unpromoted_note_paths: 0,
7861
- unpromoted_note_examples: [],
7862
- last_commit: "never",
7863
- status: "not_a_repo",
7864
- humanHint: "not a git repository"
7865
- })
7866
- };
7867
- }
7868
- enableGitLongPathsOnWindows(vault);
7869
- const porcelain = git(vault, ["status", "--porcelain"]);
7870
- const dirty = porcelain ? porcelain.split("\n").filter((l) => l.trim().length > 0).length : 0;
7871
- const dirtyPaths = parseDirtyPaths(porcelain);
7872
- const untrackedPaths = splitNonEmptyLines(git(vault, ["ls-files", "--others", "--exclude-standard"]));
7873
- const revOutput = git(vault, ["rev-list", "--left-right", "--count", "origin/HEAD...HEAD"]);
7874
- let ahead = 0;
7875
- let behind = 0;
7876
- if (revOutput) {
7877
- const parts = revOutput.split(/\s+/);
7878
- behind = parseInt(parts[0], 10) || 0;
7879
- ahead = parseInt(parts[1], 10) || 0;
7880
- }
7881
- const tsRaw = git(vault, ["log", "-1", "--format=%ct"]);
7882
- let last_commit;
7883
- if (tsRaw) {
7884
- const ts = parseInt(tsRaw, 10);
7885
- if (!isNaN(ts) && ts > 0) {
7886
- last_commit = new Date(ts * 1e3).toISOString();
7887
- } else {
7888
- last_commit = "never";
7889
- }
7890
- } else {
7891
- last_commit = "never";
7892
- }
7893
- const remoteRef = git(vault, ["rev-parse", "--verify", "origin/main"]) ? "origin/main" : git(vault, ["rev-parse", "--verify", "origin/HEAD"]) ? "origin/HEAD" : "HEAD";
7894
- const unpromotedNoteAll = Array.from(/* @__PURE__ */ new Set([...dirtyPaths, ...untrackedPaths])).filter(isTrackedNotePath).filter((path) => !refHasPath(vault, remoteRef, path));
7895
- const unpromotedNoteExamples = unpromotedNoteAll.slice(0, 5);
7896
- const unpromotedNotePaths = unpromotedNoteAll.length;
7897
- let status;
7898
- if (dirty > 0) {
7899
- status = "dirty";
7900
- } else if (ahead > 0) {
7901
- status = "ahead";
7902
- } else if (behind > 0) {
7903
- status = "behind";
7904
- } else {
7905
- status = "clean";
7906
- }
7907
- const hintLines = [
7908
- `status: ${status}`,
7909
- `dirty: ${dirty}`,
7910
- `ahead: ${ahead}`,
7911
- `behind: ${behind}`,
7912
- `unpromoted_note_paths: ${unpromotedNotePaths}`,
7913
- `last_commit: ${last_commit}`
7914
- ];
7915
- const exitCode = status === "clean" ? ExitCode.OK : ExitCode.LINT_HAS_WARNINGS;
7916
- let stashes;
7917
- if (includeStashes) {
7918
- stashes = enumerateStashes(vault);
7919
- }
7920
- const output = {
7921
- is_git_repo: true,
7922
- dirty,
7923
- ahead,
7924
- behind,
7925
- unpromoted_note_paths: unpromotedNotePaths,
7926
- unpromoted_note_examples: unpromotedNoteExamples,
7927
- last_commit,
7928
- status,
7929
- humanHint: hintLines.join("\n")
7930
- };
7931
- if (stashes !== void 0) {
7932
- output.stashes = stashes;
7933
- }
7934
- if (input.includeRemoteHealth) {
7935
- const home = input.home ?? process.env.HOME ?? "";
7936
- const remote_health = probeRemoteHealth({
7937
- vaultPath: vault,
7938
- home,
7939
- s3Remote: input.s3Remote,
7940
- snapshotterAlias: input.snapshotterAlias,
7941
- checkSnapshotter: input.checkSnapshotter,
7942
- exec: input.execProbe
7943
- });
7944
- output.remote_health = remote_health;
7945
- const degraded = buildDegradedReasons(remote_health);
7946
- if (degraded.length > 0) {
7947
- output.degraded_reasons = degraded;
7948
- hintLines.push(`degraded_reasons: ${degraded.join(", ")}`);
7949
- output.humanHint = hintLines.join("\n");
7950
- }
7951
- }
7952
- return {
7953
- exitCode,
7954
- result: ok(output)
7955
- };
7956
- }
7957
- async function runSyncPush(input) {
7958
- const vault = input.vault;
7959
- if (!existsSync9(join30(vault, ".git"))) {
7960
- return {
7961
- exitCode: ExitCode.VAULT_PATH_INVALID,
7962
- result: err("NOT_A_GIT_REPO", { path: vault })
7963
- };
7964
- }
7965
- enableGitLongPathsOnWindows(vault);
7966
- let pathFixes = 0;
7967
- const pathFix = await fixPathTooLong({ vault });
7968
- if (pathFix.result.ok && pathFix.result.data.fixed.length > 0) {
7969
- pathFixes = pathFix.result.data.fixed.length;
7970
- appendLastOp(vault, {
7971
- operation: "lint-fix",
7972
- summary: `fixed ${pathFixes} long path(s)`,
7973
- files: pathFix.result.data.fixed.flatMap((f) => [f.from, f.to]),
7974
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
7975
- });
7976
- }
7977
- const porcelain = git(vault, ["status", "--porcelain"]);
7978
- const dirtyFiles = porcelain ? porcelain.split("\n").filter((l) => l.trim().length > 0) : [];
7979
- if (dirtyFiles.length === 0) {
7980
- return {
7981
- exitCode: ExitCode.OK,
7982
- result: ok({
7983
- files_committed: 0,
7984
- commit_message: "",
7985
- pushed: false,
7986
- path_fixes: pathFixes,
7987
- humanHint: "nothing to commit, working tree clean"
7988
- })
7989
- };
7990
- }
7991
- let delta = { full_errors: 0, base_errors: 0, new_errors: 0, resolved_errors: 0 };
7992
- const preferredBase = git(vault, ["rev-parse", "--verify", "origin/main"]) ? "origin/main" : git(vault, ["rev-parse", "--verify", "origin/HEAD"]) ? "origin/HEAD" : "";
7993
- if (preferredBase) {
7994
- const deltaResult = await runSyncLintDelta({ vault, baseRef: preferredBase });
7995
- if (!deltaResult.result.ok) {
7996
- return {
7997
- exitCode: ExitCode.LINT_HAS_ERRORS,
7998
- result: err("LINT_DELTA_UNAVAILABLE", {
7999
- message: "lint-delta evidence missing or failed \u2014 fail closed",
8000
- detail: deltaResult.result
8001
- })
8002
- };
8003
- }
8004
- delta = deltaResult.result.data;
8005
- if (delta.new_errors > 0) {
8006
- return {
8007
- exitCode: ExitCode.LINT_HAS_ERRORS,
8008
- result: err("LINT_NEW_ERRORS_BLOCK_PUSH", {
8009
- full_errors: delta.full_errors,
8010
- base_errors: delta.base_errors,
8011
- new_errors: delta.new_errors,
8012
- resolved_errors: delta.resolved_errors,
8013
- new_fingerprints: deltaResult.result.data.new_fingerprints
8014
- })
8015
- };
8016
- }
8017
- } else {
8018
- const lintResult = await runLint({ vault, days: 90, lines: 200, logThreshold: 500 });
8019
- if (lintResult.result.ok) {
8020
- const fullErrors = lintResult.result.data.summary.errors;
8021
- delta = { full_errors: fullErrors, base_errors: 0, new_errors: fullErrors, resolved_errors: 0 };
8022
- if (fullErrors > 0) {
8023
- const buckets = "by_severity" in lintResult.result.data ? lintResult.result.data.by_severity.error : [];
8024
- return {
8025
- exitCode: ExitCode.LINT_HAS_ERRORS,
8026
- result: err("LINT_ERRORS_BLOCK_PUSH", {
8027
- errors: fullErrors,
8028
- buckets,
8029
- message: "no origin base ref for delta; absolute lint errors block push"
8030
- })
8031
- };
8032
- }
8033
- } else {
8034
- delta = { full_errors: 0, base_errors: 0, new_errors: 0, resolved_errors: 0 };
8035
- }
8036
- }
8037
- try {
8038
- stageVaultContentChanges(vault);
8039
- } catch (e) {
8040
- return {
8041
- exitCode: ExitCode.SYNC_PUSH_FAILED,
8042
- result: err("GIT_ADD_FAILED", { message: String(e) })
8043
- };
8044
- }
8045
- const lastOps = readLastOp(vault);
8046
- let commitMessage;
8047
- if (lastOps.length > 0) {
8048
- commitMessage = lastOps.map((op) => `${op.operation}: ${op.summary} (${op.files.length} files)`).join("; ");
8049
- } else {
8050
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
8051
- commitMessage = `sync: vault update ${timestamp}`;
8052
- }
8053
- try {
8054
- gitStrict(vault, ["commit", "-m", commitMessage]);
8055
- } catch (e) {
8056
- return {
8057
- exitCode: ExitCode.SYNC_PUSH_FAILED,
8058
- result: err("GIT_COMMIT_FAILED", { message: String(e) })
8059
- };
8060
- }
8061
- clearLastOp(vault);
8062
- let pushed = false;
8063
- try {
8064
- gitStrict(vault, ["push", "origin", "HEAD"]);
8065
- pushed = true;
8066
- } catch (e) {
8067
- return {
8068
- exitCode: ExitCode.SYNC_PUSH_FAILED,
8069
- result: ok({
8070
- files_committed: dirtyFiles.length,
8071
- commit_message: commitMessage,
8072
- pushed: false,
8073
- path_fixes: pathFixes,
8074
- humanHint: `committed ${dirtyFiles.length} file(s)${pathFixes > 0 ? ` after ${pathFixes} long-path fix(es)` : ""} but push failed: ${String(e)}`
8075
- })
8076
- };
8077
- }
8078
- const inheritedNote = delta.full_errors > 0 ? `; lint full=${delta.full_errors} base=${delta.base_errors} new=${delta.new_errors} resolved=${delta.resolved_errors} (inherited debt only)` : `; lint full=0 new=0`;
8079
- return {
8080
- exitCode: ExitCode.OK,
8081
- result: ok({
8082
- files_committed: dirtyFiles.length,
8083
- commit_message: commitMessage,
8084
- pushed,
8085
- path_fixes: pathFixes,
8086
- lint_full_errors: delta.full_errors,
8087
- lint_base_errors: delta.base_errors,
8088
- lint_new_errors: delta.new_errors,
8089
- lint_resolved_errors: delta.resolved_errors,
8090
- humanHint: `committed and pushed ${dirtyFiles.length} file(s)${pathFixes > 0 ? ` after ${pathFixes} long-path fix(es)` : ""}${inheritedNote}`
8091
- })
8092
- };
8093
- }
8094
- function enumerateStashes(vault, nowMs = Date.now()) {
8095
- const output = git(vault, ["log", "--format=%gd%x09%H%x09%s%x09%ct", "-g", "stash"]);
8096
- if (!output) return [];
8097
- const stashes = [];
8098
- const lines = output.split("\n").filter((l) => l.trim().length > 0);
8099
- for (const line of lines) {
8100
- const parts = line.split(" ");
8101
- if (parts.length < 4) continue;
8102
- const ref = parts[0];
8103
- const oid = parts[1];
8104
- const message = parts[2];
8105
- const ctStr = parts[3];
8106
- const ct = parseInt(ctStr, 10);
8107
- if (isNaN(ct)) continue;
8108
- const age_minutes = Math.floor((nowMs - ct * 1e3) / (60 * 1e3));
8109
- stashes.push({ ref, oid, message, age_minutes });
8110
- }
8111
- return stashes;
8112
- }
8113
- function enableGitLongPathsOnWindows(vault) {
8114
- if (process.platform !== "win32") return;
8115
- git(vault, ["config", "core.longpaths", "true"]);
8116
- }
8117
- async function runSyncPull(input) {
8118
- const vault = input.vault;
8119
- if (!existsSync9(join30(vault, ".git"))) {
8120
- return {
8121
- exitCode: ExitCode.VAULT_PATH_INVALID,
8122
- result: err("NOT_A_GIT_REPO", { path: vault })
8123
- };
8124
- }
8125
- enableGitLongPathsOnWindows(vault);
8126
- const remoteUrl = git(vault, ["remote", "get-url", "origin"]);
8127
- if (!remoteUrl) {
8128
- return {
8129
- exitCode: ExitCode.SYNC_PULL_FAILED,
8130
- result: err("GIT_PULL_FAILED", { message: "no remote configured (origin)" })
8131
- };
8132
- }
8133
- const helper = await runVaultSyncPullHelper({ vault, remote: "origin", branch: "main" });
8134
- if (!helper.ok) {
8135
- if (helper.error === "PREFLIGHT_FAILED") {
8136
- return {
8137
- exitCode: ExitCode.PREFLIGHT_FAILED,
8138
- result: err("PREFLIGHT_FAILED", helper.detail)
8139
- };
8140
- }
8141
- return {
8142
- exitCode: ExitCode.SYNC_PULL_FAILED,
8143
- result: err("GIT_PULL_FAILED", helper.detail)
8144
- };
8145
- }
8146
- const fetched = true;
8147
- const pulled = helper.data.changed;
8148
- const conflicts = 0;
8149
- const autoResolved = 0;
8150
- let filesUpdated = 0;
8151
- if (helper.data.changed) {
8152
- const diffOutput = git(vault, ["diff", "--stat", `${helper.data.before_oid}..${helper.data.after_oid}`]);
8153
- if (diffOutput) {
8154
- const fileMatch = diffOutput.match(/(\d+) file[s]? changed/);
8155
- if (fileMatch) filesUpdated = parseInt(fileMatch[1], 10);
8156
- }
8157
- }
8158
- const pathFix = await fixPathTooLong({ vault });
8159
- const pathFixCount = pathFix.result.ok ? pathFix.result.data.fixed.length : 0;
8160
- let lintErrors = 0;
8161
- let lintWarnings = 0;
8162
- const lintResult = await runLint({ vault, days: 90, lines: 200, logThreshold: 500 });
8163
- if (lintResult.result.ok) {
8164
- lintErrors = lintResult.result.data.summary.errors;
8165
- lintWarnings = lintResult.result.data.summary.warnings;
8166
- }
8167
- const hintParts = [];
8168
- if (filesUpdated > 0) hintParts.push(`updated ${filesUpdated} file(s)`);
8169
- else hintParts.push(pulled ? "pulled via vault-sync helper" : "already up to date");
8170
- if (pathFixCount > 0) hintParts.push(`${pathFixCount} long path(s) fixed`);
8171
- if (lintErrors > 0) hintParts.push(`${lintErrors} lint error(s)`);
8172
- if (lintWarnings > 0) hintParts.push(`${lintWarnings} lint warning(s)`);
8173
- const exitCode = lintErrors > 0 ? ExitCode.LINT_HAS_ERRORS : lintWarnings > 0 ? ExitCode.LINT_HAS_WARNINGS : ExitCode.OK;
8174
- return {
8175
- exitCode,
8176
- result: ok({
8177
- fetched,
8178
- pulled,
8179
- files_updated: filesUpdated,
8180
- conflicts,
8181
- auto_resolved: autoResolved,
8182
- lint_errors: lintErrors,
8183
- lint_warnings: lintWarnings,
8184
- humanHint: hintParts.join(", ")
8185
- })
8186
- };
8187
- }
8188
- var STASH_RECENT_MINUTES = 120;
8189
- var MANAGED_WRITER_PATTERNS = [
8190
- ["wiki-push", /(?:^|[\s/\\])wiki-push(?:\.[a-z0-9_-]+)?(?:\s|$)/i],
8191
- ["rclone", /(?:^|[\s/\\])rclone(?:\.[a-z0-9_-]+)?(?:\s|$)/i],
8192
- ["vault-sync", /(?:^|[\s/\\])vault-sync(?:\.[a-z0-9_-]+)?(?:\s|$)/i]
8193
- ];
8194
- function classifyStash(ageMinutes, sessionId, currentSession) {
8195
- if (sessionId && sessionId === currentSession) return "self_or_local_recovery_stash";
8196
- if (sessionId && ageMinutes <= STASH_RECENT_MINUTES) return "recent_known_peer_stash";
8197
- if (ageMinutes > STASH_RECENT_MINUTES) return "stale_stash_backlog";
8198
- return "unknown_stash_ownership";
8199
- }
8200
- function classifyManagedWriterProcesses(snapshot, currentPid = process.pid) {
8201
- const kinds = /* @__PURE__ */ new Set();
8202
- let count2 = 0;
8203
- for (const line of snapshot.split(/\r?\n/)) {
8204
- const trimmed = line.trim();
8205
- if (!trimmed) continue;
8206
- let pid;
8207
- let processName = "";
8208
- const csvMatch = trimmed.match(/^"([^"]*)","(\d+)"(?:,|$)/);
8209
- if (csvMatch) {
8210
- processName = csvMatch[1];
8211
- pid = Number(csvMatch[2]);
8212
- } else {
8213
- const pidMatch = trimmed.match(/^(\d+)\s+(.*)$/);
8214
- if (!pidMatch) continue;
8215
- pid = Number(pidMatch[1]);
8216
- processName = pidMatch[2];
8217
- }
8218
- if (pid === currentPid) continue;
8219
- const kind = MANAGED_WRITER_PATTERNS.find(([, pattern]) => pattern.test(processName))?.[0];
8220
- if (!kind) continue;
8221
- count2 += 1;
8222
- kinds.add(kind);
8223
- }
8224
- return { count: count2, kinds: [...kinds].sort(), blocking: count2 > 0 };
8225
- }
8226
- function managedWriterSnapshot() {
8227
- try {
8228
- if (process.platform === "win32") {
8229
- return execFileSync3("tasklist", ["/FO", "CSV", "/NH"], {
8230
- encoding: "utf8",
8231
- stdio: ["pipe", "pipe", "pipe"]
8232
- });
8233
- }
8234
- return execFileSync3("ps", ["-axo", "pid=,command="], {
8235
- encoding: "utf8",
8236
- stdio: ["pipe", "pipe", "pipe"]
8237
- });
8238
- } catch {
8239
- return "";
8240
- }
8241
- }
8242
- function runSyncPeers(input) {
8243
- const vault = input.vault;
8244
- const currentSession = input.sessionId ?? getSessionId();
8245
- const locks = [];
8246
- const existingLock = readLock(vault);
8247
- if (existingLock) {
8248
- const self = existingLock.session_id === currentSession;
8249
- locks.push({ ...existingLock, is_self: self });
8250
- }
8251
- const allStashes = enumerateStashes(vault, input.nowMs);
8252
- const stashes = [];
8253
- const wikiSyncAudit = [];
8254
- const otherStashAudit = [];
8255
- for (const stash of allStashes) {
8256
- let actualMessage = stash.message;
8257
- const prefixMatch = stash.message.match(/^On [^:]+:\s*(.*)/);
8258
- if (prefixMatch) {
8259
- actualMessage = prefixMatch[1];
8260
- }
8261
- const match = actualMessage.match(/^wiki-sync:([^:]+):([^:]+):(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z):(.*)$/);
8262
- if (match) {
8263
- const session_id = match[1];
8264
- const cwd_hash = match[2];
8265
- const timestamp = match[3];
8266
- const summary = match[4];
8267
- stashes.push({
8268
- ref: stash.ref,
8269
- oid: stash.oid,
8270
- session_id,
8271
- cwd_hash,
8272
- timestamp,
8273
- summary,
8274
- age_minutes: stash.age_minutes
8275
- });
8276
- wikiSyncAudit.push({
8277
- ref: stash.ref,
8278
- oid: stash.oid,
8279
- age_minutes: stash.age_minutes,
8280
- classification: classifyStash(stash.age_minutes, session_id, currentSession),
8281
- format: "wiki-sync",
8282
- session_id
8283
- });
8284
- continue;
8285
- }
8286
- const vaultSyncMatch = actualMessage.match(/^vault-sync\s+op=([^\s]+)(?:\s+.*)?$/i);
8287
- const operationId2 = vaultSyncMatch?.[1];
8288
- const manualPeer = /^peer$/i.test(actualMessage.trim());
8289
- const format = operationId2 ? "vault-sync" : manualPeer ? "manual" : "unknown";
8290
- const classification = operationId2 ? stash.age_minutes <= STASH_RECENT_MINUTES ? "recent_known_peer_stash" : "stale_stash_backlog" : "unknown_stash_ownership";
8291
- otherStashAudit.push({
8292
- ref: stash.ref,
8293
- oid: stash.oid,
8294
- age_minutes: stash.age_minutes,
8295
- classification,
8296
- format,
8297
- ...operationId2 ? { operation_id: operationId2 } : {}
8298
- });
8299
- }
8300
- const stashAudit = [...wikiSyncAudit, ...otherStashAudit];
8301
- const managedWriters = classifyManagedWriterProcesses(
8302
- input.processSnapshot ?? managedWriterSnapshot()
8303
- );
8304
- const hintParts = [];
8305
- if (locks.length > 0) hintParts.push(`${locks.length} lock(s)`);
8306
- if (stashes.length > 0) hintParts.push(`${stashes.length} wiki-sync stash(es)`);
8307
- if (managedWriters.count > 0) hintParts.push(`${managedWriters.count} live writer overlap(s)`);
8308
- if (stashAudit.length > 0) hintParts.push(`${stashAudit.length} stash audit item(s)`);
8309
- const blocking = locks.some((lock) => !lock.is_self) || managedWriters.blocking || stashAudit.some((entry) => entry.classification === "recent_known_peer_stash");
8310
- const humanHint = hintParts.length > 0 ? hintParts.join(", ") : "no peers detected";
8311
- return {
8312
- exitCode: ExitCode.OK,
8313
- result: ok({
8314
- locks,
8315
- stashes,
8316
- stash_audit: stashAudit,
8317
- managed_writers: managedWriters,
8318
- blocking,
8319
- humanHint
8320
- })
8321
- };
8322
- }
8323
- function runSyncLock(input) {
8324
- const vault = input.vault;
8325
- if (!existsSync9(vault)) {
8326
- return {
8327
- exitCode: ExitCode.VAULT_PATH_INVALID,
8328
- result: err("VAULT_PATH_INVALID", { path: vault })
8329
- };
8330
- }
8331
- const result = acquireLock(vault, {
8332
- sessionId: input.sessionId,
8333
- summary: input.summary,
8334
- ttlMinutes: input.ttlMinutes,
8335
- force: input.force
8336
- });
8337
- if (result.ok) {
8338
- return {
8339
- exitCode: ExitCode.OK,
8340
- result: ok({
8341
- acquired: true,
8342
- lock: result.lock,
8343
- humanHint: `lock acquired for ${result.lock.summary} (expires ${result.lock.expires})`
8344
- })
8345
- };
8346
- } else {
8347
- return {
8348
- exitCode: ExitCode.SYNC_LOCK_HELD,
8349
- result: ok({
8350
- acquired: false,
8351
- lock: result.held,
8352
- held_by: result.held,
8353
- humanHint: `lock held by session ${result.held.session_id} (PID ${result.held.pid}) for ${result.held.summary}`
8354
- })
8355
- };
8356
- }
8357
- }
8358
- function runSyncUnlock(input) {
8359
- const vault = input.vault;
8360
- if (!existsSync9(vault)) {
8361
- return {
8362
- exitCode: ExitCode.VAULT_PATH_INVALID,
8363
- result: err("VAULT_PATH_INVALID", { path: vault })
8364
- };
8365
- }
8366
- const result = releaseLock(vault, { sessionId: input.sessionId, force: input.force });
8367
- let humanHint;
8368
- if (result.released && result.prior) {
8369
- humanHint = `lock force-released (was held by session ${result.prior.session_id}, PID ${result.prior.pid})`;
8370
- } else if (result.released) {
8371
- humanHint = "lock released";
8372
- } else {
8373
- humanHint = "lock not held by this session (no-op)";
8374
- }
8375
- const output = {
8376
- released: result.released,
8377
- humanHint
8378
- };
8379
- if (result.prior) {
8380
- output.prior = {
8381
- session_id: result.prior.session_id,
8382
- pid: result.prior.pid,
8383
- summary: result.prior.summary
8384
- };
8385
- }
8386
- return {
8387
- exitCode: ExitCode.OK,
8388
- result: ok(output)
8389
- };
8390
- }
8391
-
8392
7796
  // src/commands/sync-journal.ts
8393
7797
  function runSyncJournalList(input) {
8394
7798
  const byPhase = {};
@@ -8434,11 +7838,11 @@ function runSyncJournalClearStale(input) {
8434
7838
  }
8435
7839
 
8436
7840
  // src/commands/snapshot-maintenance.ts
8437
- import { existsSync as existsSync10, mkdirSync as mkdirSync4, appendFileSync } from "fs";
7841
+ import { existsSync as existsSync9, mkdirSync as mkdirSync4, appendFileSync } from "fs";
8438
7842
  import { createHash as createHash5 } from "crypto";
8439
7843
  import { execSync as execSync3, spawn } from "child_process";
8440
7844
  import { platform as platform2 } from "os";
8441
- import { join as join31, resolve as resolvePath2 } from "path";
7845
+ import { join as join30, resolve as resolvePath2 } from "path";
8442
7846
  var MAINTENANCE_SCHEMA_VERSION = 1;
8443
7847
  var MAINTENANCE_COMMAND = "snapshot-maintenance journal clear-stale";
8444
7848
  function canonicalize(p) {
@@ -8501,7 +7905,7 @@ async function runSnapshotMaintenanceDryRun(input) {
8501
7905
  audit(makeAuditEvent(input, fleetLoad.hostId, now, "refusal", "MAINTENANCE_WRONG_WORKTREE"));
8502
7906
  return { exitCode: ExitCode.PROTECTED_SNAPSHOTTER_WRITE_BLOCKED, result: refusalErr("MAINTENANCE_WRONG_WORKTREE", `requested path '${requested}' is not the configured snapshot worktree '${canonicalize(configuredWorktree)}'`) };
8503
7907
  }
8504
- if (!existsSync10(requested) || !existsSync10(join31(requested, ".git"))) {
7908
+ if (!existsSync9(requested) || !existsSync9(join30(requested, ".git"))) {
8505
7909
  audit(makeAuditEvent(input, fleetLoad.hostId, now, "refusal", "MAINTENANCE_MISSING_GIT_REPO"));
8506
7910
  return { exitCode: ExitCode.PROTECTED_SNAPSHOTTER_WRITE_BLOCKED, result: refusalErr("MAINTENANCE_MISSING_GIT_REPO", `snapshot worktree is not a git repository: ${requested}`) };
8507
7911
  }
@@ -8581,14 +7985,14 @@ async function resolveLiveVault(input) {
8581
7985
  return resolved.ok ? canonicalize(resolved.data.path) : void 0;
8582
7986
  }
8583
7987
  function snapshotMaintenanceAuditLogPath(home) {
8584
- const stateDir = platform2() === "darwin" ? join31(home, "Library", "Application Support", "vault-sync") : join31(home, ".local", "state", "vault-sync");
8585
- return join31(stateDir, "snapshot-maintenance-audit.jsonl");
7988
+ const stateDir = platform2() === "darwin" ? join30(home, "Library", "Application Support", "vault-sync") : join30(home, ".local", "state", "vault-sync");
7989
+ return join30(stateDir, "snapshot-maintenance-audit.jsonl");
8586
7990
  }
8587
7991
  function defaultAuditSink(home) {
8588
7992
  return (event) => {
8589
7993
  try {
8590
7994
  const logPath = snapshotMaintenanceAuditLogPath(home);
8591
- mkdirSync4(join31(logPath, ".."), { recursive: true });
7995
+ mkdirSync4(join30(logPath, ".."), { recursive: true });
8592
7996
  appendFileSync(logPath, JSON.stringify(event) + "\n", { encoding: "utf8" });
8593
7997
  } catch {
8594
7998
  }
@@ -8749,7 +8153,7 @@ function releaseSnapshotFlock(handle) {
8749
8153
 
8750
8154
  // src/commands/backup.ts
8751
8155
  import { statSync as statSync2, readdirSync as readdirSync2, readFileSync as readFileSync15, mkdirSync as mkdirSync5, writeFileSync as writeFileSync6 } from "fs";
8752
- import { join as join32, relative as relative3, dirname as dirname10 } from "path";
8156
+ import { join as join31, relative as relative3, dirname as dirname10 } from "path";
8753
8157
  import { PutObjectCommand, HeadObjectCommand, ListObjectsV2Command, GetObjectCommand, DeleteObjectsCommand } from "@aws-sdk/client-s3";
8754
8158
 
8755
8159
  // src/utils/s3-client.ts
@@ -8773,7 +8177,7 @@ var SKIP_DIRS = /* @__PURE__ */ new Set([".git", ".obsidian", "_archive", "node_
8773
8177
  function* walkMarkdown(dir, base) {
8774
8178
  for (const entry of readdirSync2(dir, { withFileTypes: true })) {
8775
8179
  if (SKIP_DIRS.has(entry.name)) continue;
8776
- const full = join32(dir, entry.name);
8180
+ const full = join31(dir, entry.name);
8777
8181
  if (entry.isDirectory()) {
8778
8182
  yield* walkMarkdown(full, base);
8779
8183
  } else if (entry.name.endsWith(".md")) {
@@ -8796,7 +8200,7 @@ async function runBackupSync(input) {
8796
8200
  let failed = 0;
8797
8201
  const files = [...walkMarkdown(input.vault, input.vault)];
8798
8202
  for (const relPath of files) {
8799
- const absPath = join32(input.vault, relPath);
8203
+ const absPath = join31(input.vault, relPath);
8800
8204
  const localStat = statSync2(absPath);
8801
8205
  let needsUpload = true;
8802
8206
  try {
@@ -8872,7 +8276,7 @@ async function runBackupRestore(input) {
8872
8276
  const objects = list.Contents ?? [];
8873
8277
  for (const obj of objects) {
8874
8278
  if (!obj.Key) continue;
8875
- const localPath = join32(target, obj.Key);
8279
+ const localPath = join31(target, obj.Key);
8876
8280
  try {
8877
8281
  const localStat = statSync2(localPath);
8878
8282
  if (obj.LastModified && localStat.mtime > obj.LastModified) {
@@ -8918,11 +8322,11 @@ async function runBackupRestore(input) {
8918
8322
  }
8919
8323
 
8920
8324
  // src/commands/status.ts
8921
- import { existsSync as existsSync11, statSync as statSync3 } from "fs";
8325
+ import { existsSync as existsSync10, statSync as statSync3 } from "fs";
8922
8326
  import { readFile as readFile16 } from "fs/promises";
8923
- import { join as join33 } from "path";
8327
+ import { join as join32 } from "path";
8924
8328
  async function runStatus(input) {
8925
- if (!existsSync11(input.vault)) {
8329
+ if (!existsSync10(input.vault)) {
8926
8330
  return { exitCode: ExitCode.VAULT_PATH_INVALID, result: err("VAULT_PATH_INVALID", { vault: input.vault }) };
8927
8331
  }
8928
8332
  const scan = await scanVault(input.vault);
@@ -8947,7 +8351,7 @@ async function runStatus(input) {
8947
8351
  const compound = scan.data.compound.length;
8948
8352
  let schemaVersion = "v1";
8949
8353
  try {
8950
- const schemaContent = await readFile16(join33(input.vault, "SCHEMA.md"), "utf8");
8354
+ const schemaContent = await readFile16(join32(input.vault, "SCHEMA.md"), "utf8");
8951
8355
  const versionMatch = schemaContent.match(/version:\s*["']?([^"'\s\n]+)/i);
8952
8356
  if (versionMatch) schemaVersion = versionMatch[1];
8953
8357
  } catch {
@@ -9008,7 +8412,7 @@ async function runStatus(input) {
9008
8412
 
9009
8413
  // src/commands/seed.ts
9010
8414
  import { mkdir as mkdir12, writeFile as writeFile8, stat as stat4 } from "fs/promises";
9011
- import { join as join34 } from "path";
8415
+ import { join as join33 } from "path";
9012
8416
  var TODAY = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
9013
8417
  var EXAMPLE_PAGES = {
9014
8418
  "entities/example-project.md": `---
@@ -9077,29 +8481,29 @@ Real sources are immutable after ingestion \u2014 never edit them.
9077
8481
  `;
9078
8482
  async function runSeed(input) {
9079
8483
  try {
9080
- await stat4(join34(input.vault, "SCHEMA.md"));
8484
+ await stat4(join33(input.vault, "SCHEMA.md"));
9081
8485
  } catch {
9082
8486
  return { exitCode: ExitCode.VAULT_PATH_INVALID, result: err("VAULT_PATH_INVALID", { root: input.vault, reason: "SCHEMA.md missing \u2014 run `skillwiki init` first" }) };
9083
8487
  }
9084
8488
  const created = [];
9085
8489
  const skipped = [];
9086
8490
  for (const [relPath, content] of Object.entries(EXAMPLE_PAGES)) {
9087
- const absPath = join34(input.vault, relPath);
8491
+ const absPath = join33(input.vault, relPath);
9088
8492
  try {
9089
8493
  await stat4(absPath);
9090
8494
  skipped.push(relPath);
9091
8495
  } catch {
9092
- await mkdir12(join34(absPath, ".."), { recursive: true });
8496
+ await mkdir12(join33(absPath, ".."), { recursive: true });
9093
8497
  await writeFile8(absPath, content, "utf8");
9094
8498
  created.push(relPath);
9095
8499
  }
9096
8500
  }
9097
- const rawPath = join34(input.vault, "raw", "articles", "example-source.md");
8501
+ const rawPath = join33(input.vault, "raw", "articles", "example-source.md");
9098
8502
  try {
9099
8503
  await stat4(rawPath);
9100
8504
  skipped.push("raw/articles/example-source.md");
9101
8505
  } catch {
9102
- await mkdir12(join34(rawPath, ".."), { recursive: true });
8506
+ await mkdir12(join33(rawPath, ".."), { recursive: true });
9103
8507
  await writeFile8(rawPath, EXAMPLE_RAW, "utf8");
9104
8508
  created.push("raw/articles/example-source.md");
9105
8509
  }
@@ -9123,8 +8527,8 @@ async function runSeed(input) {
9123
8527
 
9124
8528
  // src/commands/canvas.ts
9125
8529
  import { readFile as readFile17, writeFile as writeFile9 } from "fs/promises";
9126
- import { existsSync as existsSync12 } from "fs";
9127
- import { join as join35 } from "path";
8530
+ import { existsSync as existsSync11 } from "fs";
8531
+ import { join as join34 } from "path";
9128
8532
  var NODE_WIDTH = 240;
9129
8533
  var NODE_HEIGHT = 60;
9130
8534
  var COLUMN_SPACING = 400;
@@ -9202,8 +8606,8 @@ function buildCanvasEdges(adjacency) {
9202
8606
  return edges;
9203
8607
  }
9204
8608
  async function runCanvasGenerate(input) {
9205
- const graphPath = input.graphPath ?? join35(input.vault, ".skillwiki", "graph.json");
9206
- if (!existsSync12(graphPath)) {
8609
+ const graphPath = input.graphPath ?? join34(input.vault, ".skillwiki", "graph.json");
8610
+ if (!existsSync11(graphPath)) {
9207
8611
  return {
9208
8612
  exitCode: ExitCode.FILE_NOT_FOUND,
9209
8613
  result: err("FILE_NOT_FOUND", {
@@ -9240,7 +8644,7 @@ async function runCanvasGenerate(input) {
9240
8644
  const nodes = buildCanvasNodes(paths);
9241
8645
  const edges = buildCanvasEdges(graph.adjacency);
9242
8646
  const canvas = { nodes, edges };
9243
- const outPath = join35(input.vault, "vault-graph.canvas");
8647
+ const outPath = join34(input.vault, "vault-graph.canvas");
9244
8648
  try {
9245
8649
  await writeFile9(outPath, JSON.stringify(canvas, null, 2));
9246
8650
  } catch (e) {
@@ -9279,7 +8683,7 @@ import { readFile as readFile19, unlink as unlink5 } from "fs/promises";
9279
8683
 
9280
8684
  // src/utils/raw-asset-reference-index.ts
9281
8685
  import { readdir as readdir7, readFile as readFile18 } from "fs/promises";
9282
- import { join as join36, relative as relative4, sep as sep3 } from "path";
8686
+ import { join as join35, relative as relative4, sep as sep3 } from "path";
9283
8687
  var PREVIEW_EXTENSIONS = /* @__PURE__ */ new Set(["png", "jpg", "jpeg", "gif", "webp", "svg", "bmp", "avif", "pdf", "mp3", "wav", "m4a", "mp4", "webm"]);
9284
8688
  async function walkFiles(root, dir = root) {
9285
8689
  let entries;
@@ -9290,7 +8694,7 @@ async function walkFiles(root, dir = root) {
9290
8694
  }
9291
8695
  const out = [];
9292
8696
  for (const entry of entries) {
9293
- const path = join36(dir, entry.name);
8697
+ const path = join35(dir, entry.name);
9294
8698
  if (entry.isDirectory()) out.push(...await walkFiles(root, path));
9295
8699
  else if (entry.isFile()) out.push(relative4(root, path).split(sep3).join("/"));
9296
8700
  }
@@ -9306,7 +8710,7 @@ function addInbound(map, target, source) {
9306
8710
  map.set(target, refs);
9307
8711
  }
9308
8712
  async function buildRawAssetReferenceIndex(vault) {
9309
- const assetRoot = join36(vault, "raw", "assets");
8713
+ const assetRoot = join35(vault, "raw", "assets");
9310
8714
  const relativeAssets = await walkFiles(assetRoot);
9311
8715
  const assets = relativeAssets.map((path) => `raw/assets/${path}`).sort((a, b) => a.localeCompare(b));
9312
8716
  const assetSet = new Set(assets);
@@ -9503,10 +8907,10 @@ async function runSourceDisposal(input) {
9503
8907
  }
9504
8908
 
9505
8909
  // src/commands/fleet-health.ts
9506
- import { existsSync as existsSync13, readFileSync as readFileSync16 } from "fs";
8910
+ import { existsSync as existsSync12, readFileSync as readFileSync16 } from "fs";
9507
8911
  import { execSync as nodeExecSync } from "child_process";
9508
8912
  import { hostname as nodeHostname, platform as nodePlatform } from "os";
9509
- import { join as join37 } from "path";
8913
+ import { join as join36 } from "path";
9510
8914
  var SSH_TIMEOUT_MS = 15e3;
9511
8915
  var TIMER_UNIT = "agent-memory-trends.timer";
9512
8916
  var SERVICE_UNIT = "agent-memory-trends.service";
@@ -9603,7 +9007,7 @@ function applyServiceFailedOverlay(run, serviceFailed) {
9603
9007
  function probeLocal(vaultPath, deps) {
9604
9008
  const latestPath = satelliteLatestRunPath(vaultPath);
9605
9009
  let parsed = null;
9606
- if (existsSync13(latestPath)) {
9010
+ if (existsSync12(latestPath)) {
9607
9011
  try {
9608
9012
  const wire = readSatelliteLatestRunFromText(readFileSync16(latestPath, "utf8"));
9609
9013
  if (wire) {
@@ -9736,7 +9140,7 @@ async function runFleetHealth(input) {
9736
9140
  const home = input.home ?? env.HOME ?? "";
9737
9141
  const osHostname = input.osHostname ?? env.HOSTNAME ?? nodeHostname();
9738
9142
  const vault = input.vault ?? env.WIKI_PATH;
9739
- const file = input.file ?? (vault ? join37(vault, FLEET_REL_PATH) : void 0);
9143
+ const file = input.file ?? (vault ? join36(vault, FLEET_REL_PATH) : void 0);
9740
9144
  if (!file) {
9741
9145
  return {
9742
9146
  exitCode: ExitCode.NO_VAULT_CONFIGURED,
@@ -9820,15 +9224,15 @@ async function runFleetHealth(input) {
9820
9224
  }
9821
9225
 
9822
9226
  // src/utils/auto-commit.ts
9823
- import { existsSync as existsSync14 } from "fs";
9824
- import { join as join38 } from "path";
9227
+ import { existsSync as existsSync13 } from "fs";
9228
+ import { join as join37 } from "path";
9825
9229
  async function postCommit(vault, exitCode) {
9826
9230
  if (exitCode !== 0) return;
9827
9231
  const home = process.env.HOME ?? "";
9828
9232
  const dotenv = await parseDotenvFile(configPath(home));
9829
9233
  const autoCommit = process.env.AUTO_COMMIT ?? dotenv["AUTO_COMMIT"];
9830
9234
  if (autoCommit === "false") return;
9831
- if (!existsSync14(join38(vault, ".git"))) return;
9235
+ if (!existsSync13(join37(vault, ".git"))) return;
9832
9236
  const lastOps = readLastOp(vault);
9833
9237
  if (lastOps.length === 0) return;
9834
9238
  const porcelain = git(vault, ["status", "--porcelain", "--", ...VAULT_COMMIT_PATHSPEC]);
@@ -9852,9 +9256,9 @@ async function postCommit(vault, exitCode) {
9852
9256
  }
9853
9257
 
9854
9258
  // src/commands/write-preflight.ts
9855
- import { existsSync as existsSync15, readFileSync as readFileSync17, statSync as statSync4 } from "fs";
9259
+ import { existsSync as existsSync14, readFileSync as readFileSync17, statSync as statSync4 } from "fs";
9856
9260
  async function runWritePreflightCommand(input) {
9857
- if (!existsSync15(input.vault) || !statSync4(input.vault).isDirectory()) {
9261
+ if (!existsSync14(input.vault) || !statSync4(input.vault).isDirectory()) {
9858
9262
  return {
9859
9263
  exitCode: ExitCode.VAULT_PATH_INVALID,
9860
9264
  result: err(GateError.VAULT_PATH_INVALID, { path: input.vault })
@@ -9862,7 +9266,7 @@ async function runWritePreflightCommand(input) {
9862
9266
  }
9863
9267
  let priorText = input.priorArtifactText;
9864
9268
  if (input.priorArtifactFile) {
9865
- if (!existsSync15(input.priorArtifactFile)) {
9269
+ if (!existsSync14(input.priorArtifactFile)) {
9866
9270
  return {
9867
9271
  exitCode: ExitCode.FILE_NOT_FOUND,
9868
9272
  result: err("FILE_NOT_FOUND", { path: input.priorArtifactFile })
@@ -9982,7 +9386,7 @@ async function emitManagedVaultWrite(vault, command, mutate, opts) {
9982
9386
  if (dirty) {
9983
9387
  return emit(dirty, void 0, { postCommit: false });
9984
9388
  }
9985
- const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-4LPVMP42.js");
9389
+ const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-2FU5F56H.js");
9986
9390
  const run = await runManagedWriteTransaction2({
9987
9391
  vault,
9988
9392
  command,
@@ -10012,7 +9416,7 @@ program.command("validate <file>").description("validate vault page frontmatter
10012
9416
  emit(await runValidate({ file, apply: !!opts.apply, vault }), vault);
10013
9417
  });
10014
9418
  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) => {
10015
- const out = opts.out ?? join39(vault, ".skillwiki", "graph.json");
9419
+ const out = opts.out ?? join38(vault, ".skillwiki", "graph.json");
10016
9420
  return emitGuardedVaultWrite(vault, "graph build", () => runGraphBuild({ vault, out }));
10017
9421
  });
10018
9422
  var canvasCmd = program.command("canvas").description("manage Obsidian canvas files");