skillwiki 0.10.44 → 0.10.46

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.
@@ -6,7 +6,7 @@ import {
6
6
  import {
7
7
  renderRootIndex,
8
8
  writeRootIndexProjection
9
- } from "./chunk-NL2MUWNF.js";
9
+ } from "./chunk-GAU4D25O.js";
10
10
  import {
11
11
  CONFIG_KEYS,
12
12
  acquireOwnedSyncLock,
@@ -29,20 +29,21 @@ import {
29
29
  resolveVaultSyncPullHelper,
30
30
  resolveWikiS3Remote,
31
31
  runLint,
32
+ runManagedWriteTransaction,
32
33
  runStale,
33
34
  satelliteGateFromFleetLoad,
34
35
  snapshotterAliasForLocalHost,
35
36
  toUndirectedWeighted,
36
37
  writeDotenv
37
- } from "./chunk-NPHRDXHD.js";
38
+ } from "./chunk-4SINVFR3.js";
38
39
  import {
39
40
  atomicWriteText,
40
41
  prepareTypedPage
41
- } from "./chunk-CTN66CDX.js";
42
+ } from "./chunk-UHZBOOMK.js";
42
43
  import {
43
44
  eventPathFor,
44
45
  writeLogEvent
45
- } from "./chunk-RPZIGMMH.js";
46
+ } from "./chunk-PLUHIOCQ.js";
46
47
  import {
47
48
  CompoundSchema,
48
49
  ExitCode,
@@ -63,7 +64,7 @@ import {
63
64
  scanVault,
64
65
  splitFrontmatter,
65
66
  systemdPropertyFor
66
- } from "./chunk-APDMYPM6.js";
67
+ } from "./chunk-EVQASYII.js";
67
68
 
68
69
  // src/commands/log-append.ts
69
70
  import { readFile, stat } from "fs/promises";
@@ -609,11 +610,84 @@ function computeAdamicAdar(adj) {
609
610
  return out;
610
611
  }
611
612
 
613
+ // src/utils/protected-vault-write-guard.ts
614
+ import { resolve as resolvePath } from "path";
615
+ async function guardProtectedVaultWrite(input) {
616
+ const env = input.env ?? process.env;
617
+ const home = input.home ?? process.env.HOME ?? "";
618
+ const cwd = input.cwd ?? process.cwd();
619
+ const liveVaultPath = await resolveLiveVaultPath({ env, home, cwd });
620
+ const load = await loadFleetManifestAndHost({
621
+ vault: liveVaultPath ?? input.vault,
622
+ hostId: input.hostId,
623
+ env,
624
+ home,
625
+ cwd,
626
+ osHostname: input.osHostname ?? process.env.HOSTNAME,
627
+ user: input.user ?? process.env.USER
628
+ });
629
+ if (!load?.hostId || load.identityStatus !== "known") {
630
+ return { blocked: false };
631
+ }
632
+ const host = load.manifest.hosts[load.hostId];
633
+ if (!host || host.role !== "snapshotter" || host.protected !== true) {
634
+ return { blocked: false };
635
+ }
636
+ const targetVault = resolvePath(input.vault);
637
+ const canonicalLiveVault = liveVaultPath ? resolvePath(liveVaultPath) : void 0;
638
+ if (canonicalLiveVault && targetVault === canonicalLiveVault) {
639
+ return { blocked: false };
640
+ }
641
+ const canonicalSnapshotWorktree = resolvePath(
642
+ resolveConfiguredSnapshotWorktree(home) ?? "/root/wiki-git"
643
+ );
644
+ if (targetVault === canonicalSnapshotWorktree) {
645
+ return {
646
+ blocked: true,
647
+ exitCode: ExitCode.PROTECTED_SNAPSHOTTER_WRITE_BLOCKED,
648
+ result: err("PROTECTED_SNAPSHOTTER_WRITE_BLOCKED", {
649
+ host_id: load.hostId,
650
+ command: input.command,
651
+ reason: `refusing mutation of snapshot worktree '${canonicalSnapshotWorktree}' on protected snapshotter host '${load.hostId}'`,
652
+ guidance: canonicalLiveVault ? `Use the live vault path '${canonicalLiveVault}' for authoring. Keep snapshot worktrees read-only except explicit snapshot maintenance.` : "Use the live skillwiki vault path for authoring. Keep snapshot worktrees read-only except explicit snapshot maintenance."
653
+ })
654
+ };
655
+ }
656
+ if (canonicalLiveVault && targetVault !== canonicalLiveVault) {
657
+ return {
658
+ blocked: true,
659
+ exitCode: ExitCode.PROTECTED_SNAPSHOTTER_WRITE_BLOCKED,
660
+ result: err("PROTECTED_SNAPSHOTTER_WRITE_BLOCKED", {
661
+ host_id: load.hostId,
662
+ command: input.command,
663
+ reason: `refusing vault mutation outside the live vault path '${canonicalLiveVault}' on protected snapshotter host '${load.hostId}'`,
664
+ guidance: "Use the resolved live skillwiki vault path for authoring. Keep alternate vault roots and snapshot worktrees read-only unless explicitly approved."
665
+ })
666
+ };
667
+ }
668
+ return { blocked: false };
669
+ }
670
+ async function resolveLiveVaultPath(input) {
671
+ const resolved = await resolveRuntimePath({
672
+ flag: void 0,
673
+ envValue: input.env.WIKI_PATH,
674
+ wikiEnv: input.env.WIKI,
675
+ home: input.home,
676
+ cwd: input.cwd
677
+ });
678
+ return resolved.ok ? resolved.data.path : void 0;
679
+ }
680
+
612
681
  // src/commands/project-index.ts
613
682
  import { readdir, readFile as readFile4, mkdir as mkdir2 } from "fs/promises";
614
683
  import { join as join4, dirname as dirname2, basename } from "path";
684
+ var DEFAULT_DEPS = {
685
+ guardProtectedVaultWrite,
686
+ runManagedWriteTransaction
687
+ };
615
688
  var LAYER2_DIRS = ["entities", "concepts", "comparisons", "queries", "meta"];
616
689
  var PROJECT_LOCAL_DIRS = ["requirements", "work", "architecture", "history"];
690
+ var PROJECT_INDEX_STALE_EXIT_CODE = 3;
617
691
  async function scanMarkdownTree(rootAbs, rootRel) {
618
692
  const found = [];
619
693
  let entries;
@@ -787,8 +861,14 @@ Autogenerated by \`skillwiki project-index\` on ${today}.
787
861
  index_path: `projects/${slug}/knowledge.md`
788
862
  });
789
863
  }
790
- async function runProjectIndex(input) {
864
+ async function runProjectIndex(input, deps = DEFAULT_DEPS) {
791
865
  const slug = input.slug;
866
+ if (input.check && input.apply) {
867
+ return {
868
+ exitCode: ExitCode.USAGE,
869
+ result: err("USAGE", { message: "--check and --apply are mutually exclusive" })
870
+ };
871
+ }
792
872
  const projectDir = join4(input.vault, "projects", slug);
793
873
  const rendered = await renderProjectIndex(input.vault, slug);
794
874
  if (!rendered.ok) {
@@ -813,37 +893,100 @@ async function runProjectIndex(input) {
813
893
  stale = existingPages.size !== currentPages.size || [...currentPages].some((p) => !existingPages.has(p));
814
894
  } catch {
815
895
  }
816
- if (input.apply) {
817
- try {
818
- await mkdir2(dirname2(indexPath), { recursive: true });
819
- } catch (e) {
820
- return {
821
- exitCode: ExitCode.WRITE_FAILED,
822
- result: err("WRITE_FAILED", { file: indexPath, message: String(e) })
823
- };
824
- }
825
- const written = await atomicWriteText(indexPath, rendered.data.text);
826
- if (!written.ok) {
827
- return { exitCode: ExitCode.WRITE_FAILED, result: written };
828
- }
829
- }
830
- const action = input.apply ? `written ${entries.length} entries to ${indexPath}` : `${entries.length} entries found (use --apply to write)`;
831
- const staleHint = stale ? " (STALE \u2014 existing index outdated)" : existing ? " (up to date)" : "";
832
- return {
833
- exitCode: ExitCode.OK,
834
- result: ok({
835
- slug,
836
- entries,
837
- existing,
838
- stale,
839
- index_path: rendered.data.index_path,
840
- humanHint: `project: ${slug}
896
+ if (!input.apply) {
897
+ const action = `${entries.length} entries found (use --apply to write)`;
898
+ const staleHint = stale ? " (STALE \u2014 existing index outdated)" : existing ? " (up to date)" : "";
899
+ return {
900
+ exitCode: input.check && stale ? PROJECT_INDEX_STALE_EXIT_CODE : ExitCode.OK,
901
+ result: ok({
902
+ slug,
903
+ entries,
904
+ existing,
905
+ stale,
906
+ index_path: rendered.data.index_path,
907
+ humanHint: `project: ${slug}
841
908
  entries: ${entries.length}${staleHint}
842
909
  ${action}
843
910
 
844
911
  ${entries.map((e) => ` ${e.type}: [[${e.page.replace(/\.md$/, "")}]] \u2014 ${e.title}`).join("\n")}`
845
- })
846
- };
912
+ })
913
+ };
914
+ }
915
+ const guard = await deps.guardProtectedVaultWrite({
916
+ vault: input.vault,
917
+ command: "project-index --apply"
918
+ });
919
+ if (guard.blocked) {
920
+ return { exitCode: guard.exitCode, result: guard.result };
921
+ }
922
+ return deps.runManagedWriteTransaction({
923
+ vault: input.vault,
924
+ command: "project-index --apply",
925
+ allowImmutableRecord: false,
926
+ mutate: async (receipt) => {
927
+ const mutationVault = receipt.mutation_vault;
928
+ const mutationIndexPath = join4(mutationVault, "projects", slug, "knowledge.md");
929
+ try {
930
+ await mkdir2(dirname2(mutationIndexPath), { recursive: true });
931
+ } catch (e) {
932
+ return {
933
+ exitCode: ExitCode.WRITE_FAILED,
934
+ result: err("WRITE_FAILED", { file: mutationIndexPath, message: String(e) })
935
+ };
936
+ }
937
+ const written = await atomicWriteText(mutationIndexPath, rendered.data.text);
938
+ if (!written.ok) {
939
+ return { exitCode: ExitCode.WRITE_FAILED, result: written };
940
+ }
941
+ if (!written.data.changed) {
942
+ return {
943
+ exitCode: ExitCode.OK,
944
+ result: ok({
945
+ slug,
946
+ entries,
947
+ existing,
948
+ stale,
949
+ changed: false,
950
+ write_mode: receipt.mode,
951
+ index_path: rendered.data.index_path,
952
+ humanHint: `project: ${slug}
953
+ entries: ${entries.length} (up to date)
954
+ no write needed`
955
+ })
956
+ };
957
+ }
958
+ let installed = "";
959
+ try {
960
+ installed = await readFile4(mutationIndexPath, "utf8");
961
+ } catch (error) {
962
+ return {
963
+ exitCode: ExitCode.WRITE_FAILED,
964
+ result: err("WRITE_FAILED", { message: String(error) })
965
+ };
966
+ }
967
+ if (installed !== rendered.data.text) {
968
+ return {
969
+ exitCode: ExitCode.WRITE_FAILED,
970
+ result: err("WRITE_FAILED", { message: "installed knowledge.md differs from projection" })
971
+ };
972
+ }
973
+ return {
974
+ exitCode: ExitCode.OK,
975
+ result: ok({
976
+ slug,
977
+ entries,
978
+ existing,
979
+ stale,
980
+ changed: true,
981
+ write_mode: receipt.mode,
982
+ index_path: rendered.data.index_path,
983
+ humanHint: `project: ${slug}
984
+ entries: ${entries.length}
985
+ written ${entries.length} entries to ${mutationIndexPath}`
986
+ })
987
+ };
988
+ }
989
+ });
847
990
  }
848
991
 
849
992
  // src/commands/config.ts
@@ -4850,7 +4993,7 @@ async function runQuery(input) {
4850
4993
  }).filter((r) => r.score > 0).sort((a, b) => b.score - a.score || a.path.localeCompare(b.path)).slice(0, limit);
4851
4994
  let pendingSources;
4852
4995
  if (input.includePending) {
4853
- const { runSourcesPending } = await import("./sources-Z4VMD2YO.js");
4996
+ const { runSourcesPending } = await import("./sources-CMV5DKS5.js");
4854
4997
  const pending = await runSourcesPending({
4855
4998
  vault: input.vault,
4856
4999
  match: input.text,
@@ -5956,6 +6099,7 @@ export {
5956
6099
  runValidate,
5957
6100
  runGraphBuild,
5958
6101
  findPlugin,
6102
+ guardProtectedVaultWrite,
5959
6103
  renderProjectIndex,
5960
6104
  runProjectIndex,
5961
6105
  scanConflictMarkerBlocksInText,
@@ -74,6 +74,7 @@ function err(error, detail) {
74
74
  }
75
75
 
76
76
  // ../shared/src/schemas.ts
77
+ import { isAbsolute } from "path";
77
78
  import { z } from "zod";
78
79
  var isoDate = z.string().refine((s) => {
79
80
  if (!/^\d{4}-\d{2}-\d{2}$/.test(s)) return false;
@@ -205,7 +206,7 @@ var endpointName = z.string().min(1).regex(/^[A-Za-z0-9_.-]+$/, "must be a hostn
205
206
  var ipAddress = z.string().min(1).regex(/^[0-9a-fA-F:.]+$/, "must be an IP address token");
206
207
  var sshAlias = z.string().min(1).regex(/^[A-Za-z0-9_.@-]+$/, "must be an SSH alias token");
207
208
  var sshUser = z.string().min(1).regex(/^[A-Za-z0-9_.-]+$/, "must be an SSH user token");
208
- var absolutePath = z.string().min(1).regex(/^\//, "must be an absolute path");
209
+ var absolutePath = z.string().min(1).refine((value) => isAbsolute(value), "must be an absolute path");
209
210
  var FleetAccessProfileSchema = z.object({
210
211
  status: z.enum(["local", "configured", "planned", "absent", "unknown"]),
211
212
  ssh_aliases: z.array(sshAlias).optional(),
@@ -3,11 +3,11 @@ import {
3
3
  ROOT_INDEX_SECTION_ORDER,
4
4
  atomicWriteText,
5
5
  buildRootIndexUniverse
6
- } from "./chunk-CTN66CDX.js";
6
+ } from "./chunk-UHZBOOMK.js";
7
7
  import {
8
8
  err,
9
9
  ok
10
- } from "./chunk-APDMYPM6.js";
10
+ } from "./chunk-EVQASYII.js";
11
11
 
12
12
  // src/utils/index-projection.ts
13
13
  import { readFile } from "fs/promises";
@@ -6,7 +6,7 @@ import {
6
6
  readPage,
7
7
  scanSensitiveContent,
8
8
  splitFrontmatter
9
- } from "./chunk-APDMYPM6.js";
9
+ } from "./chunk-EVQASYII.js";
10
10
 
11
11
  // src/utils/log-events.ts
12
12
  import { mkdir, open, readFile, readdir } from "fs/promises";
@@ -8,7 +8,7 @@ import {
8
8
  readLogEvents,
9
9
  resolveExistingRegularFileInsideVault,
10
10
  writeLogEvent
11
- } from "./chunk-RPZIGMMH.js";
11
+ } from "./chunk-PLUHIOCQ.js";
12
12
  import {
13
13
  ExitCode,
14
14
  RawSourceSchema,
@@ -19,7 +19,7 @@ import {
19
19
  scanSensitiveContent,
20
20
  scanVault,
21
21
  splitFrontmatter
22
- } from "./chunk-APDMYPM6.js";
22
+ } from "./chunk-EVQASYII.js";
23
23
 
24
24
  // src/utils/source-lifecycle.ts
25
25
  import { basename } from "path";
@@ -8,7 +8,7 @@ import {
8
8
  ok,
9
9
  scanSensitiveContent,
10
10
  scanVault
11
- } from "./chunk-APDMYPM6.js";
11
+ } from "./chunk-EVQASYII.js";
12
12
 
13
13
  // src/utils/atomic-write.ts
14
14
  import { randomBytes } from "crypto";
package/dist/cli.js CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  evaluateDirtyVolumeGate,
12
12
  evaluateSatelliteRunHealth,
13
13
  findPlugin,
14
+ guardProtectedVaultWrite,
14
15
  isFailedRunStatus,
15
16
  memoryAuthorityTiersRank,
16
17
  readCliPackageJson,
@@ -39,7 +40,7 @@ import {
39
40
  scanConflictMarkerBlocksInText,
40
41
  snapshotterHealthChecks,
41
42
  upsertIndexEntry
42
- } from "./chunk-BUHQMIOD.js";
43
+ } from "./chunk-5JYOYMST.js";
43
44
  import {
44
45
  normalizeDistTag,
45
46
  readCache,
@@ -52,21 +53,10 @@ import {
52
53
  UNMANAGED_START,
53
54
  renderRootIndex,
54
55
  writeRootIndexProjection
55
- } from "./chunk-NL2MUWNF.js";
56
- import {
57
- VAULT_COMMIT_PATHSPEC,
58
- runManagedWritePreflight,
59
- runManagedWriteTransaction,
60
- runSyncLock,
61
- runSyncPeers,
62
- runSyncPull,
63
- runSyncPush,
64
- runSyncStatus,
65
- runSyncUnlock,
66
- stageVaultContentChanges
67
- } from "./chunk-JHHVTW7E.js";
56
+ } from "./chunk-GAU4D25O.js";
68
57
  import {
69
58
  FLEET_REL_PATH,
59
+ VAULT_COMMIT_PATHSPEC,
70
60
  acquireOwnedSyncLock,
71
61
  appendLastOp,
72
62
  applyRawStructuralMove,
@@ -74,6 +64,7 @@ import {
74
64
  buildRemoteObjectPath,
75
65
  canSupersedeJournal,
76
66
  clearLastOp,
67
+ collectClaimedTranscripts,
77
68
  extractTaxonomy,
78
69
  getCliSessionId,
79
70
  git,
@@ -114,25 +105,34 @@ import {
114
105
  runLinks,
115
106
  runLint,
116
107
  runLogRotate,
108
+ runManagedWritePreflight,
109
+ runManagedWriteTransaction,
117
110
  runOrphans,
118
111
  runPagesize,
119
112
  runStale,
120
113
  runSyncLintDelta,
114
+ runSyncLock,
115
+ runSyncPeers,
116
+ runSyncPull,
117
+ runSyncPush,
118
+ runSyncStatus,
119
+ runSyncUnlock,
121
120
  runTagAudit,
122
121
  runTopicMapCheck,
123
122
  safeWritePage,
124
123
  serializeJournalEnv,
125
124
  snapshotMaintainedPageState,
126
125
  snapshotterAliasForLocalHost,
126
+ stageVaultContentChanges,
127
127
  supersedeStaleReviewRequiredJournals,
128
128
  taxonomyCommentForPage,
129
129
  writeDotenv
130
- } from "./chunk-NPHRDXHD.js";
130
+ } from "./chunk-4SINVFR3.js";
131
131
  import {
132
132
  assertTargetInsideVault,
133
133
  atomicWriteText,
134
134
  prepareTypedPage
135
- } from "./chunk-CTN66CDX.js";
135
+ } from "./chunk-UHZBOOMK.js";
136
136
  import {
137
137
  applySourceDisposition,
138
138
  decodeSourceActionApproval,
@@ -140,7 +140,7 @@ import {
140
140
  inventorySources,
141
141
  planSourceDisposition,
142
142
  runSourcesPending
143
- } from "./chunk-DHGHISVY.js";
143
+ } from "./chunk-QNSD72FH.js";
144
144
  import {
145
145
  authorizeRawOperation,
146
146
  buildSourceReferenceIndex,
@@ -156,7 +156,7 @@ import {
156
156
  resolveExistingRegularFileInsideVault,
157
157
  validateLogEvent,
158
158
  writeLogEvent
159
- } from "./chunk-RPZIGMMH.js";
159
+ } from "./chunk-PLUHIOCQ.js";
160
160
  import {
161
161
  ExitCode,
162
162
  MetaSchema,
@@ -173,7 +173,7 @@ import {
173
173
  scanSensitiveContent,
174
174
  scanVault,
175
175
  splitFrontmatter
176
- } from "./chunk-APDMYPM6.js";
176
+ } from "./chunk-EVQASYII.js";
177
177
 
178
178
  // src/cli.ts
179
179
  import { join as join38 } from "path";
@@ -950,76 +950,6 @@ async function runInit(input) {
950
950
  // src/commands/index-rebuild.ts
951
951
  import { readFileSync as readFileSync2 } from "fs";
952
952
  import { join as join6 } from "path";
953
-
954
- // src/utils/protected-vault-write-guard.ts
955
- import { resolve as resolvePath } from "path";
956
- async function guardProtectedVaultWrite(input) {
957
- const env = input.env ?? process.env;
958
- const home = input.home ?? process.env.HOME ?? "";
959
- const cwd = input.cwd ?? process.cwd();
960
- const liveVaultPath = await resolveLiveVaultPath({ env, home, cwd });
961
- const load = await loadFleetManifestAndHost({
962
- vault: liveVaultPath ?? input.vault,
963
- hostId: input.hostId,
964
- env,
965
- home,
966
- cwd,
967
- osHostname: input.osHostname ?? process.env.HOSTNAME,
968
- user: input.user ?? process.env.USER
969
- });
970
- if (!load?.hostId || load.identityStatus !== "known") {
971
- return { blocked: false };
972
- }
973
- const host = load.manifest.hosts[load.hostId];
974
- if (!host || host.role !== "snapshotter" || host.protected !== true) {
975
- return { blocked: false };
976
- }
977
- const targetVault = resolvePath(input.vault);
978
- const canonicalLiveVault = liveVaultPath ? resolvePath(liveVaultPath) : void 0;
979
- if (canonicalLiveVault && targetVault === canonicalLiveVault) {
980
- return { blocked: false };
981
- }
982
- const canonicalSnapshotWorktree = resolvePath(
983
- resolveConfiguredSnapshotWorktree(home) ?? "/root/wiki-git"
984
- );
985
- if (targetVault === canonicalSnapshotWorktree) {
986
- return {
987
- blocked: true,
988
- exitCode: ExitCode.PROTECTED_SNAPSHOTTER_WRITE_BLOCKED,
989
- result: err("PROTECTED_SNAPSHOTTER_WRITE_BLOCKED", {
990
- host_id: load.hostId,
991
- command: input.command,
992
- reason: `refusing mutation of snapshot worktree '${canonicalSnapshotWorktree}' on protected snapshotter host '${load.hostId}'`,
993
- guidance: canonicalLiveVault ? `Use the live vault path '${canonicalLiveVault}' for authoring. Keep snapshot worktrees read-only except explicit snapshot maintenance.` : "Use the live skillwiki vault path for authoring. Keep snapshot worktrees read-only except explicit snapshot maintenance."
994
- })
995
- };
996
- }
997
- if (canonicalLiveVault && targetVault !== canonicalLiveVault) {
998
- return {
999
- blocked: true,
1000
- exitCode: ExitCode.PROTECTED_SNAPSHOTTER_WRITE_BLOCKED,
1001
- result: err("PROTECTED_SNAPSHOTTER_WRITE_BLOCKED", {
1002
- host_id: load.hostId,
1003
- command: input.command,
1004
- reason: `refusing vault mutation outside the live vault path '${canonicalLiveVault}' on protected snapshotter host '${load.hostId}'`,
1005
- guidance: "Use the resolved live skillwiki vault path for authoring. Keep alternate vault roots and snapshot worktrees read-only unless explicitly approved."
1006
- })
1007
- };
1008
- }
1009
- return { blocked: false };
1010
- }
1011
- async function resolveLiveVaultPath(input) {
1012
- const resolved = await resolveRuntimePath({
1013
- flag: void 0,
1014
- envValue: input.env.WIKI_PATH,
1015
- wikiEnv: input.env.WIKI,
1016
- home: input.home,
1017
- cwd: input.cwd
1018
- });
1019
- return resolved.ok ? resolved.data.path : void 0;
1020
- }
1021
-
1022
- // src/commands/index-rebuild.ts
1023
953
  async function runIndexRebuild(input) {
1024
954
  const projection = await renderRootIndex({ vault: input.vault });
1025
955
  if (!projection.ok) {
@@ -3477,7 +3407,7 @@ ${fmRewritten}
3477
3407
  }
3478
3408
  let indexUpdated = false;
3479
3409
  if (!isRaw) {
3480
- const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-RWF5M7U7.js");
3410
+ const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-BJNZUPH6.js");
3481
3411
  const before = await readFile7(join18(input.vault, "index.md"), "utf8").catch(() => "");
3482
3412
  const fullTarget = relPath.replace(/\.md$/, "");
3483
3413
  const bare = fullTarget.split("/").pop() ?? fullTarget;
@@ -3597,7 +3527,7 @@ async function runRemove(input) {
3597
3527
  if (relPath.endsWith(".md") && !relPath.startsWith("raw/")) {
3598
3528
  const { readFile: readFile20 } = await import("fs/promises");
3599
3529
  const { join: pathJoin } = await import("path");
3600
- const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-RWF5M7U7.js");
3530
+ const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-BJNZUPH6.js");
3601
3531
  const before = await readFile20(pathJoin(input.vault, "index.md"), "utf8").catch(() => "");
3602
3532
  const fullTarget = relPath.replace(/\.md$/, "");
3603
3533
  const bare = fullTarget.split("/").pop() ?? fullTarget;
@@ -4554,9 +4484,13 @@ async function runSessionBrief(input) {
4554
4484
  ...baseHealthWarnings,
4555
4485
  ...satelliteHealthWarnings(satelliteHealth)
4556
4486
  ];
4487
+ const claimed = collectClaimedTranscripts(
4488
+ workItems.map((w) => ({ relDir: w.path, source: w.source, sources: w.sources, closes: w.closes }))
4489
+ );
4557
4490
  const latestLogs = newest(transcripts.filter((t) => t.kind === "session-log"), 3);
4558
4491
  const unclaimedCaptures = newest(transcripts.filter((t) => {
4559
4492
  if (t.kind !== "task" && t.kind !== "bug") return false;
4493
+ if (claimed.claimedByPath.has(t.path)) return false;
4560
4494
  return !t.workItem && (!project || t.project === project);
4561
4495
  }), 5);
4562
4496
  const activeWork = newest(workItems.filter((w) => {
@@ -4697,7 +4631,10 @@ async function loadWorkItems(workItemPages) {
4697
4631
  summary: summarize(body),
4698
4632
  date: stringField(fm.data.updated) || stringField(fm.data.created) || dateFromPath(page.relPath),
4699
4633
  status: stringField(fm.data.status),
4700
- project: wikilinkSlug(fm.data.project)
4634
+ project: wikilinkSlug(fm.data.project),
4635
+ source: fm.data.source,
4636
+ sources: fm.data.sources,
4637
+ closes: fm.data.closes
4701
4638
  });
4702
4639
  }
4703
4640
  return out;
@@ -7972,11 +7909,11 @@ import { existsSync as existsSync9, mkdirSync as mkdirSync4, appendFileSync } fr
7972
7909
  import { createHash as createHash5 } from "crypto";
7973
7910
  import { execSync as execSync3, spawn } from "child_process";
7974
7911
  import { platform as platform2 } from "os";
7975
- import { join as join30, resolve as resolvePath2 } from "path";
7912
+ import { join as join30, resolve as resolvePath } from "path";
7976
7913
  var MAINTENANCE_SCHEMA_VERSION = 1;
7977
7914
  var MAINTENANCE_COMMAND = "snapshot-maintenance journal clear-stale";
7978
7915
  function canonicalize(p) {
7979
- return resolvePath2(p);
7916
+ return resolvePath(p);
7980
7917
  }
7981
7918
  function computeApprovalId(plan) {
7982
7919
  const eligible = [...plan.eligible_journals].sort((a, b) => a.operation_id.localeCompare(b.operation_id));
@@ -9542,7 +9479,7 @@ async function emitManagedVaultWrite(vault, command, mutate, opts) {
9542
9479
  if (dirty) {
9543
9480
  return emit(dirty, void 0, { postCommit: false });
9544
9481
  }
9545
- const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-EDEMCLVQ.js");
9482
+ const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-DWK3PJCO.js");
9546
9483
  const run = await runManagedWriteTransaction2({
9547
9484
  vault,
9548
9485
  command,
@@ -10173,7 +10110,11 @@ program.command("transcripts [vault]").description("list transcript files in raw
10173
10110
  if (!v.ok) emit({ exitCode: v.exitCode, result: v.payload });
10174
10111
  else emit(await runTranscripts({ vault: v.vault, since: opts.since }), v.vault);
10175
10112
  });
10176
- program.command("project-index <slug> [vault]").description("generate a knowledge index for a project workspace").option("--apply", "write knowledge.md to the project directory", false).option("--wiki <name>", "wiki profile name").action(async (slug, vault, opts) => {
10113
+ program.command("project-index <slug> [vault]").description("generate a knowledge index for a project workspace").option("--apply", "write knowledge.md to the project directory", false).option("--check", "check-only: exit 0 when the existing index is fresh, 3 when stale (no writes; mutually exclusive with --apply)", false).option("--wiki <name>", "wiki profile name").action(async (slug, vault, opts) => {
10114
+ if (opts.check && opts.apply) {
10115
+ emit({ exitCode: ExitCode.USAGE, result: err("USAGE", "--check and --apply are mutually exclusive") });
10116
+ return;
10117
+ }
10177
10118
  const v = await resolveVaultArg(vault, opts.wiki);
10178
10119
  if (!v.ok) emit({ exitCode: v.exitCode, result: v.payload });
10179
10120
  else if (opts.apply) return emitGuardedVaultWrite(
@@ -10181,7 +10122,7 @@ program.command("project-index <slug> [vault]").description("generate a knowledg
10181
10122
  "project-index --apply",
10182
10123
  () => runProjectIndex({ vault: v.vault, slug, apply: true })
10183
10124
  );
10184
- else emit(await runProjectIndex({ vault: v.vault, slug, apply: false }), v.vault);
10125
+ else emit(await runProjectIndex({ vault: v.vault, slug, apply: false, check: opts.check }), v.vault);
10185
10126
  });
10186
10127
  var compoundCmd = program.command("compound").description("manage project compound entries");
10187
10128
  compoundCmd.command("promote [vault]").description("promote retros with Generalize?: yes to compound entries").requiredOption("--project <slug>", "project slug (e.g., llm-wiki)").option("--dry-run", "preview promotions without writing files", false).option("--wiki <name>", "wiki profile name").action(async (vault, opts) => {
@@ -4,9 +4,9 @@ import {
4
4
  UNMANAGED_START,
5
5
  renderRootIndex,
6
6
  writeRootIndexProjection
7
- } from "./chunk-NL2MUWNF.js";
8
- import "./chunk-CTN66CDX.js";
9
- import "./chunk-APDMYPM6.js";
7
+ } from "./chunk-GAU4D25O.js";
8
+ import "./chunk-UHZBOOMK.js";
9
+ import "./chunk-EVQASYII.js";
10
10
  export {
11
11
  UNMANAGED_END,
12
12
  UNMANAGED_START,
@@ -2,11 +2,10 @@
2
2
  import {
3
3
  runManagedWritePreflight,
4
4
  runManagedWriteTransaction
5
- } from "./chunk-JHHVTW7E.js";
6
- import "./chunk-NPHRDXHD.js";
7
- import "./chunk-CTN66CDX.js";
8
- import "./chunk-RPZIGMMH.js";
9
- import "./chunk-APDMYPM6.js";
5
+ } from "./chunk-4SINVFR3.js";
6
+ import "./chunk-UHZBOOMK.js";
7
+ import "./chunk-PLUHIOCQ.js";
8
+ import "./chunk-EVQASYII.js";
10
9
  export {
11
10
  runManagedWritePreflight,
12
11
  runManagedWriteTransaction
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runSkillwikiMcpStdio
4
- } from "./chunk-BUHQMIOD.js";
4
+ } from "./chunk-5JYOYMST.js";
5
5
  import "./chunk-7I2TPIV5.js";
6
- import "./chunk-NL2MUWNF.js";
7
- import "./chunk-NPHRDXHD.js";
8
- import "./chunk-CTN66CDX.js";
9
- import "./chunk-RPZIGMMH.js";
10
- import "./chunk-APDMYPM6.js";
6
+ import "./chunk-GAU4D25O.js";
7
+ import "./chunk-4SINVFR3.js";
8
+ import "./chunk-UHZBOOMK.js";
9
+ import "./chunk-PLUHIOCQ.js";
10
+ import "./chunk-EVQASYII.js";
11
11
 
12
12
  // src/mcp-entry.ts
13
13
  runSkillwikiMcpStdio().catch((error) => {