gnosys 5.11.4 → 5.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (265) hide show
  1. package/dist/cli.js +377 -5162
  2. package/dist/index.js +542 -244
  3. package/dist/lib/addCommand.d.ts +9 -0
  4. package/dist/lib/addCommand.js +102 -0
  5. package/dist/lib/addStructuredCommand.d.ts +16 -0
  6. package/dist/lib/addStructuredCommand.js +103 -0
  7. package/dist/lib/ambiguityCommand.d.ts +4 -0
  8. package/dist/lib/ambiguityCommand.js +36 -0
  9. package/dist/lib/apiKeyVault.d.ts +78 -0
  10. package/dist/lib/apiKeyVault.js +447 -0
  11. package/dist/lib/archive.js +0 -2
  12. package/dist/lib/askCommand.d.ts +13 -0
  13. package/dist/lib/askCommand.js +145 -0
  14. package/dist/lib/attachCommand.d.ts +17 -0
  15. package/dist/lib/attachCommand.js +66 -0
  16. package/dist/lib/attachments.d.ts +43 -2
  17. package/dist/lib/attachments.js +81 -2
  18. package/dist/lib/audioExtract.js +4 -1
  19. package/dist/lib/auditCommand.d.ts +7 -0
  20. package/dist/lib/auditCommand.js +27 -0
  21. package/dist/lib/backupCommand.d.ts +6 -0
  22. package/dist/lib/backupCommand.js +54 -0
  23. package/dist/lib/bootstrapCommand.d.ts +15 -0
  24. package/dist/lib/bootstrapCommand.js +51 -0
  25. package/dist/lib/briefingCommand.d.ts +7 -0
  26. package/dist/lib/briefingCommand.js +92 -0
  27. package/dist/lib/centralizeCommand.d.ts +5 -0
  28. package/dist/lib/centralizeCommand.js +16 -0
  29. package/dist/lib/chat/choose.js +2 -2
  30. package/dist/lib/chatCommand.d.ts +12 -0
  31. package/dist/lib/chatCommand.js +46 -0
  32. package/dist/lib/checkCommand.d.ts +4 -0
  33. package/dist/lib/checkCommand.js +133 -0
  34. package/dist/lib/clientReadOverlay.d.ts +27 -0
  35. package/dist/lib/clientReadOverlay.js +76 -0
  36. package/dist/lib/clientReadResolve.d.ts +32 -0
  37. package/dist/lib/clientReadResolve.js +84 -0
  38. package/dist/lib/commitContextCommand.d.ts +9 -0
  39. package/dist/lib/commitContextCommand.js +142 -0
  40. package/dist/lib/config.d.ts +41 -48
  41. package/dist/lib/config.js +58 -57
  42. package/dist/lib/configCommand.d.ts +10 -0
  43. package/dist/lib/configCommand.js +321 -0
  44. package/dist/lib/connectCommand.d.ts +8 -0
  45. package/dist/lib/connectCommand.js +19 -0
  46. package/dist/lib/db.d.ts +68 -1
  47. package/dist/lib/db.js +385 -120
  48. package/dist/lib/dbWrite.d.ts +1 -1
  49. package/dist/lib/dearchiveCommand.d.ts +7 -0
  50. package/dist/lib/dearchiveCommand.js +41 -0
  51. package/dist/lib/discoverCommand.d.ts +9 -0
  52. package/dist/lib/discoverCommand.js +87 -0
  53. package/dist/lib/doctorCommand.d.ts +6 -0
  54. package/dist/lib/doctorCommand.js +256 -0
  55. package/dist/lib/docxExtract.js +1 -1
  56. package/dist/lib/dream.d.ts +50 -2
  57. package/dist/lib/dream.js +324 -30
  58. package/dist/lib/dreamCommand.d.ts +10 -0
  59. package/dist/lib/dreamCommand.js +195 -0
  60. package/dist/lib/dreamLaunchd.d.ts +2 -0
  61. package/dist/lib/dreamLaunchd.js +72 -0
  62. package/dist/lib/dreamLogCommand.d.ts +10 -0
  63. package/dist/lib/dreamLogCommand.js +58 -0
  64. package/dist/lib/dreamReport.d.ts +7 -0
  65. package/dist/lib/dreamReport.js +114 -0
  66. package/dist/lib/dreamRunLog.d.ts +121 -0
  67. package/dist/lib/dreamRunLog.js +234 -0
  68. package/dist/lib/embeddings.js +3 -3
  69. package/dist/lib/exportCommand.d.ts +18 -0
  70. package/dist/lib/exportCommand.js +101 -0
  71. package/dist/lib/exportProject.d.ts +3 -2
  72. package/dist/lib/exportProject.js +2 -1
  73. package/dist/lib/federated.js +1 -1
  74. package/dist/lib/fsearchCommand.d.ts +8 -0
  75. package/dist/lib/fsearchCommand.js +44 -0
  76. package/dist/lib/graphCommand.d.ts +4 -0
  77. package/dist/lib/graphCommand.js +68 -0
  78. package/dist/lib/helperGenerateCommand.d.ts +5 -0
  79. package/dist/lib/helperGenerateCommand.js +27 -0
  80. package/dist/lib/historyCommand.d.ts +5 -0
  81. package/dist/lib/historyCommand.js +51 -0
  82. package/dist/lib/hybridSearchCommand.d.ts +12 -0
  83. package/dist/lib/hybridSearchCommand.js +95 -0
  84. package/dist/lib/importCommand.d.ts +16 -0
  85. package/dist/lib/importCommand.js +89 -0
  86. package/dist/lib/importProject.js +2 -1
  87. package/dist/lib/importProjectCommand.d.ts +6 -0
  88. package/dist/lib/importProjectCommand.js +43 -0
  89. package/dist/lib/ingestCommand.d.ts +13 -0
  90. package/dist/lib/ingestCommand.js +95 -0
  91. package/dist/lib/installOutput.d.ts +36 -0
  92. package/dist/lib/installOutput.js +55 -0
  93. package/dist/lib/lensCommand.d.ts +20 -0
  94. package/dist/lib/lensCommand.js +61 -0
  95. package/dist/lib/lensing.d.ts +1 -0
  96. package/dist/lib/lensing.js +50 -9
  97. package/dist/lib/linksCommand.d.ts +7 -0
  98. package/dist/lib/linksCommand.js +48 -0
  99. package/dist/lib/listCommand.d.ts +8 -0
  100. package/dist/lib/listCommand.js +74 -0
  101. package/dist/lib/llm.d.ts +1 -1
  102. package/dist/lib/llm.js +27 -9
  103. package/dist/lib/localDiskCheck.d.ts +17 -0
  104. package/dist/lib/localDiskCheck.js +54 -0
  105. package/dist/lib/lock.d.ts +1 -1
  106. package/dist/lib/lock.js +5 -3
  107. package/dist/lib/machineConfig.d.ts +11 -1
  108. package/dist/lib/machineConfig.js +16 -0
  109. package/dist/lib/machineRegistry.d.ts +61 -0
  110. package/dist/lib/machineRegistry.js +80 -0
  111. package/dist/lib/maintainCommand.d.ts +8 -0
  112. package/dist/lib/maintainCommand.js +34 -0
  113. package/dist/lib/masterLease.d.ts +20 -0
  114. package/dist/lib/masterLease.js +68 -0
  115. package/dist/lib/migrate.js +0 -1
  116. package/dist/lib/migrateCommand.d.ts +7 -0
  117. package/dist/lib/migrateCommand.js +158 -0
  118. package/dist/lib/migrateDbCommand.d.ts +9 -0
  119. package/dist/lib/migrateDbCommand.js +94 -0
  120. package/dist/lib/modelValidation.d.ts +5 -0
  121. package/dist/lib/modelValidation.js +27 -0
  122. package/dist/lib/multimodalIngest.js +1 -1
  123. package/dist/lib/openrouterTiers.d.ts +29 -0
  124. package/dist/lib/openrouterTiers.js +113 -0
  125. package/dist/lib/platform.d.ts +0 -6
  126. package/dist/lib/platform.js +0 -28
  127. package/dist/lib/prefCommand.d.ts +10 -0
  128. package/dist/lib/prefCommand.js +118 -0
  129. package/dist/lib/projectsCommand.d.ts +8 -0
  130. package/dist/lib/projectsCommand.js +131 -0
  131. package/dist/lib/readCommand.d.ts +7 -0
  132. package/dist/lib/readCommand.js +63 -0
  133. package/dist/lib/recall.d.ts +3 -0
  134. package/dist/lib/recall.js +19 -4
  135. package/dist/lib/recallCommand.d.ts +11 -0
  136. package/dist/lib/recallCommand.js +112 -0
  137. package/dist/lib/reflectCommand.d.ts +8 -0
  138. package/dist/lib/reflectCommand.js +61 -0
  139. package/dist/lib/reindexCommand.d.ts +4 -0
  140. package/dist/lib/reindexCommand.js +34 -0
  141. package/dist/lib/reindexGraphCommand.d.ts +4 -0
  142. package/dist/lib/reindexGraphCommand.js +12 -0
  143. package/dist/lib/reinforceCommand.d.ts +8 -0
  144. package/dist/lib/reinforceCommand.js +40 -0
  145. package/dist/lib/remote.d.ts +5 -1
  146. package/dist/lib/remote.js +5 -1
  147. package/dist/lib/remoteWizard.d.ts +24 -5
  148. package/dist/lib/remoteWizard.js +308 -319
  149. package/dist/lib/restoreCommand.d.ts +5 -0
  150. package/dist/lib/restoreCommand.js +35 -0
  151. package/dist/lib/rulesGen.d.ts +8 -0
  152. package/dist/lib/rulesGen.js +16 -0
  153. package/dist/lib/sandboxStartCommand.d.ts +6 -0
  154. package/dist/lib/sandboxStartCommand.js +25 -0
  155. package/dist/lib/sandboxStatusCommand.d.ts +4 -0
  156. package/dist/lib/sandboxStatusCommand.js +24 -0
  157. package/dist/lib/sandboxStopCommand.d.ts +4 -0
  158. package/dist/lib/sandboxStopCommand.js +21 -0
  159. package/dist/lib/search.d.ts +0 -2
  160. package/dist/lib/search.js +0 -7
  161. package/dist/lib/searchCommand.d.ts +9 -0
  162. package/dist/lib/searchCommand.js +90 -0
  163. package/dist/lib/semanticSearchCommand.d.ts +8 -0
  164. package/dist/lib/semanticSearchCommand.js +52 -0
  165. package/dist/lib/setup/configSetRender.js +2 -0
  166. package/dist/lib/setup/providerGlyphs.d.ts +19 -0
  167. package/dist/lib/setup/providerGlyphs.js +42 -0
  168. package/dist/lib/setup/remoteRender.d.ts +31 -1
  169. package/dist/lib/setup/remoteRender.js +95 -4
  170. package/dist/lib/setup/sections/providers.d.ts +17 -0
  171. package/dist/lib/setup/sections/providers.js +307 -0
  172. package/dist/lib/setup/sections/routing.d.ts +2 -6
  173. package/dist/lib/setup/sections/routing.js +67 -82
  174. package/dist/lib/setup/sections/taskRoutingEditor.d.ts +13 -0
  175. package/dist/lib/setup/sections/taskRoutingEditor.js +139 -0
  176. package/dist/lib/setup/summary.d.ts +9 -0
  177. package/dist/lib/setup/summary.js +51 -37
  178. package/dist/lib/setup/ui/header.js +0 -1
  179. package/dist/lib/setup.d.ts +105 -15
  180. package/dist/lib/setup.js +747 -287
  181. package/dist/lib/setupKeys.d.ts +42 -0
  182. package/dist/lib/setupKeys.js +564 -0
  183. package/dist/lib/setupRemoteCommand.d.ts +4 -0
  184. package/dist/lib/setupRemoteCommand.js +28 -0
  185. package/dist/lib/setupRemotePullCommand.d.ts +5 -0
  186. package/dist/lib/setupRemotePullCommand.js +52 -0
  187. package/dist/lib/setupRemotePushCommand.d.ts +5 -0
  188. package/dist/lib/setupRemotePushCommand.js +57 -0
  189. package/dist/lib/setupRemoteResolveCommand.d.ts +4 -0
  190. package/dist/lib/setupRemoteResolveCommand.js +48 -0
  191. package/dist/lib/setupRemoteStatusCommand.d.ts +4 -0
  192. package/dist/lib/setupRemoteStatusCommand.js +73 -0
  193. package/dist/lib/setupRemoteSyncCommand.d.ts +6 -0
  194. package/dist/lib/setupRemoteSyncCommand.js +65 -0
  195. package/dist/lib/setupSyncProjectsCommand.d.ts +4 -0
  196. package/dist/lib/setupSyncProjectsCommand.js +292 -0
  197. package/dist/lib/staleCommand.d.ts +8 -0
  198. package/dist/lib/staleCommand.js +34 -0
  199. package/dist/lib/statsCommand.d.ts +6 -0
  200. package/dist/lib/statsCommand.js +142 -0
  201. package/dist/lib/statusCommand.d.ts +18 -0
  202. package/dist/lib/statusCommand.js +250 -0
  203. package/dist/lib/storesCommand.d.ts +2 -0
  204. package/dist/lib/storesCommand.js +4 -0
  205. package/dist/lib/syncClient.d.ts +41 -0
  206. package/dist/lib/syncClient.js +234 -0
  207. package/dist/lib/syncCommand.d.ts +6 -0
  208. package/dist/lib/syncCommand.js +57 -0
  209. package/dist/lib/syncDoctorCommand.d.ts +5 -0
  210. package/dist/lib/syncDoctorCommand.js +100 -0
  211. package/dist/lib/syncIngest.d.ts +30 -0
  212. package/dist/lib/syncIngest.js +175 -0
  213. package/dist/lib/syncIngestLaunchd.d.ts +8 -0
  214. package/dist/lib/syncIngestLaunchd.js +93 -0
  215. package/dist/lib/syncIngestStartup.d.ts +5 -0
  216. package/dist/lib/syncIngestStartup.js +29 -0
  217. package/dist/lib/syncIngestSystemd.d.ts +10 -0
  218. package/dist/lib/syncIngestSystemd.js +97 -0
  219. package/dist/lib/syncIngestTimer.d.ts +8 -0
  220. package/dist/lib/syncIngestTimer.js +27 -0
  221. package/dist/lib/syncIngestTimerCommand.d.ts +7 -0
  222. package/dist/lib/syncIngestTimerCommand.js +83 -0
  223. package/dist/lib/syncLock.d.ts +6 -0
  224. package/dist/lib/syncLock.js +74 -0
  225. package/dist/lib/syncSnapshot.d.ts +32 -0
  226. package/dist/lib/syncSnapshot.js +188 -0
  227. package/dist/lib/syncStaging.d.ts +79 -0
  228. package/dist/lib/syncStaging.js +237 -0
  229. package/dist/lib/tagsAddCommand.d.ts +8 -0
  230. package/dist/lib/tagsAddCommand.js +18 -0
  231. package/dist/lib/tagsCommand.d.ts +4 -0
  232. package/dist/lib/tagsCommand.js +16 -0
  233. package/dist/lib/timelineCommand.d.ts +7 -0
  234. package/dist/lib/timelineCommand.js +49 -0
  235. package/dist/lib/traceCommand.d.ts +6 -0
  236. package/dist/lib/traceCommand.js +39 -0
  237. package/dist/lib/traverseCommand.d.ts +6 -0
  238. package/dist/lib/traverseCommand.js +58 -0
  239. package/dist/lib/updateCommand.d.ts +13 -0
  240. package/dist/lib/updateCommand.js +67 -0
  241. package/dist/lib/updateStatusCommand.d.ts +5 -0
  242. package/dist/lib/updateStatusCommand.js +38 -0
  243. package/dist/lib/webAddCommand.d.ts +8 -0
  244. package/dist/lib/webAddCommand.js +55 -0
  245. package/dist/lib/webBuildCommand.d.ts +10 -0
  246. package/dist/lib/webBuildCommand.js +65 -0
  247. package/dist/lib/webBuildIndexCommand.d.ts +8 -0
  248. package/dist/lib/webBuildIndexCommand.js +37 -0
  249. package/dist/lib/webIndex.js +0 -1
  250. package/dist/lib/webIngestCommand.d.ts +11 -0
  251. package/dist/lib/webIngestCommand.js +51 -0
  252. package/dist/lib/webInitCommand.d.ts +9 -0
  253. package/dist/lib/webInitCommand.js +167 -0
  254. package/dist/lib/webRemoveCommand.d.ts +5 -0
  255. package/dist/lib/webRemoveCommand.js +41 -0
  256. package/dist/lib/webStatusCommand.d.ts +5 -0
  257. package/dist/lib/webStatusCommand.js +94 -0
  258. package/dist/lib/webUpdateCommand.d.ts +7 -0
  259. package/dist/lib/webUpdateCommand.js +72 -0
  260. package/dist/lib/workingSetCommand.d.ts +6 -0
  261. package/dist/lib/workingSetCommand.js +37 -0
  262. package/dist/sandbox/client.js +1 -1
  263. package/dist/sandbox/manager.js +1 -14
  264. package/dist/sandbox/server.js +3 -5
  265. package/package.json +6 -2
@@ -0,0 +1,79 @@
1
+ /**
2
+ * v13 hardened JSON staging for multi-machine sync.
3
+ *
4
+ * Clients write small JSON files under master-folder/.gnosys-staging/<machineId>/.
5
+ * Master ingest walks files ordered by ledger firstSeenAt (see GnosysDB.sync_staging_ledger).
6
+ */
7
+ import type { GnosysDB } from "./db.js";
8
+ /** Current staged-memory JSON schema version. */
9
+ export declare const STAGING_SCHEMA_VERSION = 1;
10
+ export declare const KNOWN_STAGING_SCHEMA_VERSIONS: Set<number>;
11
+ export declare const UNKNOWN_SCHEMA_MESSAGE = "Update your master machine to a newer version of Gnosys.";
12
+ export interface StagedMemoryPayload {
13
+ schemaVersion: number;
14
+ id: string;
15
+ title: string;
16
+ category: string;
17
+ content: string;
18
+ tags: string[];
19
+ project_id: string | null;
20
+ scope: string;
21
+ machineId: string;
22
+ writtenAt: string;
23
+ checksum: string;
24
+ }
25
+ export type StagedFileParseResult = {
26
+ ok: true;
27
+ payload: StagedMemoryPayload;
28
+ filePath: string;
29
+ } | {
30
+ ok: false;
31
+ filePath: string;
32
+ reason: string;
33
+ quarantine: boolean;
34
+ };
35
+ export declare function stagingRoot(masterPath: string): string;
36
+ export declare function machineStagingDir(masterPath: string, machineId: string): string;
37
+ export declare function clientPresencePath(masterPath: string, machineId: string): string;
38
+ export declare function failedQuarantineDir(masterPath: string, machineId: string): string;
39
+ export declare function buildStagingFileName(memoryUlid: string, unixMs?: number): string;
40
+ /** SHA-256 of canonical JSON body (all fields except checksum). */
41
+ export declare function stagingPayloadChecksum(body: Omit<StagedMemoryPayload, "checksum">): string;
42
+ export declare function buildStagedMemoryPayload(input: {
43
+ id: string;
44
+ title: string;
45
+ category: string;
46
+ content: string;
47
+ machineId: string;
48
+ tags?: string[];
49
+ project_id?: string | null;
50
+ scope?: string;
51
+ writtenAt?: string;
52
+ schemaVersion?: number;
53
+ }): StagedMemoryPayload;
54
+ /**
55
+ * Atomically write a staged memory JSON file (`.tmp` in the same directory, then rename).
56
+ * Returns the final file path relative to the machine staging dir.
57
+ */
58
+ export declare function writeStagedMemoryFile(masterPath: string, machineId: string, payload: StagedMemoryPayload): string;
59
+ export declare function parseStagedFile(filePath: string): StagedFileParseResult;
60
+ /** Move a bad staging file into machineId/failed/ (does not delete). */
61
+ export declare function quarantineStagingFile(filePath: string, masterPath: string, machineId: string): string;
62
+ /** Move stale `.tmp` files in a machine staging dir into `failed/`. */
63
+ export declare function quarantineStaleTmpFiles(masterPath: string, machineId: string): number;
64
+ export declare function countFailedStagingFiles(masterPath: string, machineId: string): number;
65
+ export interface StagingQueueEntry {
66
+ filePath: string;
67
+ fileName: string;
68
+ memoryUlid: string;
69
+ sortKey: string;
70
+ }
71
+ /**
72
+ * List pending `.json` staging files for a machine (excludes failed/, tmp, presence).
73
+ * Sort by ledger firstSeenAt when db is provided, else by filename timestamp prefix.
74
+ */
75
+ export declare function listPendingStagingQueue(masterPath: string, machineId: string, masterDb?: GnosysDB): StagingQueueEntry[];
76
+ /** Master read-back: memory row exists after ingest before deleting staging file. */
77
+ export declare function verifyMemoryExistsInDb(db: GnosysDB, memoryUlid: string): boolean;
78
+ /** Record first observation in the master ledger (idempotent upsert without clobbering status). */
79
+ export declare function observeStagingFile(masterDb: GnosysDB, machineId: string, fileName: string, memoryUlid: string | null): void;
@@ -0,0 +1,237 @@
1
+ /**
2
+ * v13 hardened JSON staging for multi-machine sync.
3
+ *
4
+ * Clients write small JSON files under master-folder/.gnosys-staging/<machineId>/.
5
+ * Master ingest walks files ordered by ledger firstSeenAt (see GnosysDB.sync_staging_ledger).
6
+ */
7
+ import { createHash, randomBytes } from "crypto";
8
+ import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, unlinkSync, } from "fs";
9
+ import path from "path";
10
+ import { atomicWriteFileSync } from "./atomicWrite.js";
11
+ /** Current staged-memory JSON schema version. */
12
+ export const STAGING_SCHEMA_VERSION = 1;
13
+ export const KNOWN_STAGING_SCHEMA_VERSIONS = new Set([STAGING_SCHEMA_VERSION]);
14
+ export const UNKNOWN_SCHEMA_MESSAGE = "Update your master machine to a newer version of Gnosys.";
15
+ const STAGING_DIR = ".gnosys-staging";
16
+ const FAILED_DIR = "failed";
17
+ const PRESENCE_FILE = ".presence.json";
18
+ export function stagingRoot(masterPath) {
19
+ return path.join(masterPath, STAGING_DIR);
20
+ }
21
+ export function machineStagingDir(masterPath, machineId) {
22
+ return path.join(stagingRoot(masterPath), machineId);
23
+ }
24
+ export function clientPresencePath(masterPath, machineId) {
25
+ return path.join(machineStagingDir(masterPath, machineId), PRESENCE_FILE);
26
+ }
27
+ export function failedQuarantineDir(masterPath, machineId) {
28
+ return path.join(machineStagingDir(masterPath, machineId), FAILED_DIR);
29
+ }
30
+ export function buildStagingFileName(memoryUlid, unixMs = Date.now()) {
31
+ return `${unixMs}-${memoryUlid}.json`;
32
+ }
33
+ /** SHA-256 of canonical JSON body (all fields except checksum). */
34
+ export function stagingPayloadChecksum(body) {
35
+ const canonical = JSON.stringify({
36
+ schemaVersion: body.schemaVersion,
37
+ id: body.id,
38
+ title: body.title,
39
+ category: body.category,
40
+ content: body.content,
41
+ tags: body.tags,
42
+ project_id: body.project_id,
43
+ scope: body.scope,
44
+ machineId: body.machineId,
45
+ writtenAt: body.writtenAt,
46
+ });
47
+ return createHash("sha256").update(canonical, "utf-8").digest("hex");
48
+ }
49
+ export function buildStagedMemoryPayload(input) {
50
+ const bodyWithoutChecksum = {
51
+ schemaVersion: input.schemaVersion ?? STAGING_SCHEMA_VERSION,
52
+ id: input.id,
53
+ title: input.title,
54
+ category: input.category,
55
+ content: input.content,
56
+ tags: input.tags ?? [],
57
+ project_id: input.project_id ?? null,
58
+ scope: input.scope ?? "project",
59
+ machineId: input.machineId,
60
+ writtenAt: input.writtenAt ?? new Date().toISOString(),
61
+ };
62
+ return {
63
+ ...bodyWithoutChecksum,
64
+ checksum: stagingPayloadChecksum(bodyWithoutChecksum),
65
+ };
66
+ }
67
+ /**
68
+ * Atomically write a staged memory JSON file (`.tmp` in the same directory, then rename).
69
+ * Returns the final file path relative to the machine staging dir.
70
+ */
71
+ export function writeStagedMemoryFile(masterPath, machineId, payload) {
72
+ const dir = machineStagingDir(masterPath, machineId);
73
+ mkdirSync(dir, { recursive: true });
74
+ const fileName = buildStagingFileName(payload.id);
75
+ const dest = path.join(dir, fileName);
76
+ const tmp = path.join(dir, `.${fileName}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`);
77
+ const data = JSON.stringify(payload, null, 2) + "\n";
78
+ try {
79
+ atomicWriteFileSync(tmp, data);
80
+ // read-back verify before rename (catches torn/partial writes on share)
81
+ const roundTrip = readFileSync(tmp, "utf-8");
82
+ const parsed = parseStagedFileContent(roundTrip, dest);
83
+ if (!parsed.ok) {
84
+ throw new Error(parsed.reason);
85
+ }
86
+ renameSync(tmp, dest);
87
+ return fileName;
88
+ }
89
+ catch (err) {
90
+ try {
91
+ if (existsSync(tmp))
92
+ unlinkSync(tmp);
93
+ }
94
+ catch {
95
+ // ignore
96
+ }
97
+ throw err;
98
+ }
99
+ }
100
+ function parseStagedFileContent(raw, filePath) {
101
+ let json;
102
+ try {
103
+ json = JSON.parse(raw);
104
+ }
105
+ catch {
106
+ return { ok: false, filePath, reason: "invalid JSON", quarantine: true };
107
+ }
108
+ if (!json || typeof json !== "object") {
109
+ return { ok: false, filePath, reason: "payload is not an object", quarantine: true };
110
+ }
111
+ const o = json;
112
+ const schemaVersion = typeof o.schemaVersion === "number" ? o.schemaVersion : -1;
113
+ if (!KNOWN_STAGING_SCHEMA_VERSIONS.has(schemaVersion)) {
114
+ return {
115
+ ok: false,
116
+ filePath,
117
+ reason: UNKNOWN_SCHEMA_MESSAGE,
118
+ quarantine: true,
119
+ };
120
+ }
121
+ const id = typeof o.id === "string" ? o.id : "";
122
+ const checksum = typeof o.checksum === "string" ? o.checksum : "";
123
+ const payload = {
124
+ schemaVersion,
125
+ id,
126
+ title: String(o.title ?? ""),
127
+ category: String(o.category ?? ""),
128
+ content: String(o.content ?? ""),
129
+ tags: Array.isArray(o.tags) ? o.tags.filter((t) => typeof t === "string") : [],
130
+ project_id: typeof o.project_id === "string" ? o.project_id : null,
131
+ scope: typeof o.scope === "string" ? o.scope : "project",
132
+ machineId: String(o.machineId ?? ""),
133
+ writtenAt: String(o.writtenAt ?? ""),
134
+ checksum,
135
+ };
136
+ const expected = stagingPayloadChecksum(payload);
137
+ if (!checksum || expected !== checksum) {
138
+ return { ok: false, filePath, reason: "checksum mismatch", quarantine: true };
139
+ }
140
+ if (!id) {
141
+ return { ok: false, filePath, reason: "missing memory id (ULID)", quarantine: true };
142
+ }
143
+ return { ok: true, payload, filePath };
144
+ }
145
+ export function parseStagedFile(filePath) {
146
+ try {
147
+ const raw = readFileSync(filePath, "utf-8");
148
+ return parseStagedFileContent(raw, filePath);
149
+ }
150
+ catch (err) {
151
+ return {
152
+ ok: false,
153
+ filePath,
154
+ reason: err instanceof Error ? err.message : String(err),
155
+ quarantine: true,
156
+ };
157
+ }
158
+ }
159
+ /** Move a bad staging file into machineId/failed/ (does not delete). */
160
+ export function quarantineStagingFile(filePath, masterPath, machineId) {
161
+ const failedDir = failedQuarantineDir(masterPath, machineId);
162
+ mkdirSync(failedDir, { recursive: true });
163
+ const base = path.basename(filePath);
164
+ const dest = path.join(failedDir, base);
165
+ if (existsSync(dest)) {
166
+ const stamped = `${Date.now()}-${base}`;
167
+ renameSync(filePath, path.join(failedDir, stamped));
168
+ return path.join(failedDir, stamped);
169
+ }
170
+ renameSync(filePath, dest);
171
+ return dest;
172
+ }
173
+ /** Move stale `.tmp` files in a machine staging dir into `failed/`. */
174
+ export function quarantineStaleTmpFiles(masterPath, machineId) {
175
+ const dir = machineStagingDir(masterPath, machineId);
176
+ if (!existsSync(dir))
177
+ return 0;
178
+ let moved = 0;
179
+ for (const name of readdirSync(dir)) {
180
+ if (!name.endsWith(".tmp"))
181
+ continue;
182
+ quarantineStagingFile(path.join(dir, name), masterPath, machineId);
183
+ moved++;
184
+ }
185
+ return moved;
186
+ }
187
+ export function countFailedStagingFiles(masterPath, machineId) {
188
+ const failedDir = failedQuarantineDir(masterPath, machineId);
189
+ if (!existsSync(failedDir))
190
+ return 0;
191
+ try {
192
+ return readdirSync(failedDir).filter((n) => n.endsWith(".json") || n.endsWith(".tmp")).length;
193
+ }
194
+ catch {
195
+ return 0;
196
+ }
197
+ }
198
+ /**
199
+ * List pending `.json` staging files for a machine (excludes failed/, tmp, presence).
200
+ * Sort by ledger firstSeenAt when db is provided, else by filename timestamp prefix.
201
+ */
202
+ export function listPendingStagingQueue(masterPath, machineId, masterDb) {
203
+ const dir = machineStagingDir(masterPath, machineId);
204
+ if (!existsSync(dir))
205
+ return [];
206
+ const entries = [];
207
+ for (const name of readdirSync(dir)) {
208
+ if (name === FAILED_DIR || name === PRESENCE_FILE || name.endsWith(".tmp"))
209
+ continue;
210
+ if (!name.endsWith(".json"))
211
+ continue;
212
+ const filePath = path.join(dir, name);
213
+ const ulid = name.replace(/^\d+-/, "").replace(/\.json$/, "");
214
+ const stagingKey = `${machineId}/${name}`;
215
+ const firstSeen = masterDb?.isAvailable() ? masterDb.getStagingLedgerFirstSeenAt(stagingKey) : null;
216
+ const sortKey = firstSeen ? `${firstSeen}\0${name}` : name;
217
+ entries.push({ filePath, fileName: name, memoryUlid: ulid, sortKey });
218
+ }
219
+ entries.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
220
+ return entries;
221
+ }
222
+ /** Master read-back: memory row exists after ingest before deleting staging file. */
223
+ export function verifyMemoryExistsInDb(db, memoryUlid) {
224
+ if (!db.isAvailable())
225
+ return false;
226
+ return db.getMemory(memoryUlid) !== null;
227
+ }
228
+ /** Record first observation in the master ledger (idempotent upsert without clobbering status). */
229
+ export function observeStagingFile(masterDb, machineId, fileName, memoryUlid) {
230
+ const stagingKey = `${machineId}/${fileName}`;
231
+ masterDb.recordStagingLedgerEntry({
232
+ stagingKey,
233
+ machineId,
234
+ memoryUlid,
235
+ firstSeenAt: new Date().toISOString(),
236
+ });
237
+ }
@@ -0,0 +1,8 @@
1
+ import type { GnosysResolver } from "./resolver.js";
2
+ export type TagsAddCommandOptions = {
3
+ category: string;
4
+ tag: string;
5
+ };
6
+ type GetResolver = () => Promise<GnosysResolver>;
7
+ export declare function runTagsAddCommand(getResolver: GetResolver, opts: TagsAddCommandOptions): Promise<void>;
8
+ export {};
@@ -0,0 +1,18 @@
1
+ import { GnosysTagRegistry } from "./tags.js";
2
+ export async function runTagsAddCommand(getResolver, opts) {
3
+ const resolver = await getResolver();
4
+ const writeTarget = resolver.getWriteTarget();
5
+ if (!writeTarget) {
6
+ console.error("No store found.");
7
+ process.exit(1);
8
+ }
9
+ const tagRegistry = new GnosysTagRegistry(writeTarget.store.getStorePath());
10
+ await tagRegistry.load();
11
+ const added = await tagRegistry.addTag(opts.category, opts.tag);
12
+ if (added) {
13
+ console.log(`Tag '${opts.tag}' added to category '${opts.category}'.`);
14
+ }
15
+ else {
16
+ console.log(`Tag '${opts.tag}' already exists in '${opts.category}'.`);
17
+ }
18
+ }
@@ -0,0 +1,4 @@
1
+ import type { GnosysResolver } from "./resolver.js";
2
+ type GetResolver = () => Promise<GnosysResolver>;
3
+ export declare function runTagsCommand(getResolver: GetResolver): Promise<void>;
4
+ export {};
@@ -0,0 +1,16 @@
1
+ import { GnosysTagRegistry } from "./tags.js";
2
+ export async function runTagsCommand(getResolver) {
3
+ const resolver = await getResolver();
4
+ const writeTarget = resolver.getWriteTarget();
5
+ if (!writeTarget) {
6
+ console.error("No store found.");
7
+ process.exit(1);
8
+ }
9
+ const tagRegistry = new GnosysTagRegistry(writeTarget.store.getStorePath());
10
+ await tagRegistry.load();
11
+ const registry = tagRegistry.getRegistry();
12
+ for (const [category, tags] of Object.entries(registry)) {
13
+ console.log(`\n${category}:`);
14
+ console.log(` ${tags.sort().join(", ")}`);
15
+ }
16
+ }
@@ -0,0 +1,7 @@
1
+ export type TimelineCommandOptions = {
2
+ period: string;
3
+ project?: string;
4
+ limitTitles: string;
5
+ json?: boolean;
6
+ };
7
+ export declare function runTimelineCommand(opts: TimelineCommandOptions): Promise<void>;
@@ -0,0 +1,49 @@
1
+ import { GnosysDB } from "./db.js";
2
+ import { groupDbByPeriod } from "./timeline.js";
3
+ function outputResult(json, data, humanFn) {
4
+ if (json) {
5
+ console.log(JSON.stringify(data, null, 2));
6
+ }
7
+ else {
8
+ humanFn();
9
+ }
10
+ }
11
+ export async function runTimelineCommand(opts) {
12
+ const centralDb = GnosysDB.openCentral();
13
+ if (!centralDb.isAvailable()) {
14
+ console.error("Central DB unavailable.");
15
+ process.exit(1);
16
+ }
17
+ try {
18
+ const memories = opts.project
19
+ ? centralDb.getMemoriesByProject(opts.project)
20
+ : centralDb.getActiveMemories();
21
+ if (memories.length === 0) {
22
+ outputResult(!!opts.json, { period: opts.period, count: 0, entries: [] }, () => {
23
+ console.log("No memories found.");
24
+ });
25
+ return;
26
+ }
27
+ const entries = groupDbByPeriod(memories, opts.period);
28
+ const titleLimit = Math.max(0, parseInt(opts.limitTitles, 10) || 5);
29
+ outputResult(!!opts.json, { period: opts.period, count: memories.length, entries }, () => {
30
+ console.log(`Knowledge Timeline (by ${opts.period}, ${memories.length} memories):\n`);
31
+ for (const entry of entries) {
32
+ const parts = [];
33
+ if (entry.created > 0)
34
+ parts.push(`${entry.created} created`);
35
+ if (entry.modified > 0)
36
+ parts.push(`${entry.modified} modified`);
37
+ console.log(` ${entry.period}: ${parts.join(", ")}`);
38
+ if (entry.titles.length > 0 && entry.titles.length <= titleLimit) {
39
+ for (const t of entry.titles) {
40
+ console.log(` + ${t}`);
41
+ }
42
+ }
43
+ }
44
+ });
45
+ }
46
+ finally {
47
+ centralDb.close();
48
+ }
49
+ }
@@ -0,0 +1,6 @@
1
+ export type TraceCommandOptions = {
2
+ maxFiles?: string;
3
+ projectId?: string;
4
+ json?: boolean;
5
+ };
6
+ export declare function runTraceCommand(directory: string, opts: TraceCommandOptions): Promise<void>;
@@ -0,0 +1,39 @@
1
+ export async function runTraceCommand(directory, opts) {
2
+ let db;
3
+ try {
4
+ const { traceCodebase } = await import("./trace.js");
5
+ const { GnosysDB: GnosysDBClass } = await import("./db.js");
6
+ const dbDir = GnosysDBClass.getCentralDbDir();
7
+ db = new GnosysDBClass(dbDir);
8
+ if (!db.isAvailable()) {
9
+ console.error("Error: GnosysDB not available. Install it with: npm install better-sqlite3");
10
+ process.exit(1);
11
+ }
12
+ const result = traceCodebase(db, directory, {
13
+ projectId: opts.projectId,
14
+ maxFiles: opts.maxFiles ? parseInt(opts.maxFiles, 10) : undefined,
15
+ });
16
+ if (opts.json) {
17
+ console.log(JSON.stringify(result, null, 2));
18
+ }
19
+ else {
20
+ console.log(`Trace complete:`);
21
+ console.log(` Files scanned: ${result.filesScanned}`);
22
+ console.log(` Functions found: ${result.functionsFound}`);
23
+ console.log(` Memories created: ${result.memoriesCreated}`);
24
+ console.log(` Relationships created: ${result.relationshipsCreated}`);
25
+ }
26
+ }
27
+ catch (err) {
28
+ if (opts.json) {
29
+ console.log(JSON.stringify({ ok: false, error: err instanceof Error ? err.message : String(err) }));
30
+ }
31
+ else {
32
+ console.error(`Trace failed: ${err instanceof Error ? err.message : err}`);
33
+ }
34
+ process.exit(1);
35
+ }
36
+ finally {
37
+ db?.close();
38
+ }
39
+ }
@@ -0,0 +1,6 @@
1
+ export type TraverseCommandOptions = {
2
+ depth?: string;
3
+ relTypes?: string;
4
+ json?: boolean;
5
+ };
6
+ export declare function runTraverseCommand(memoryId: string, opts: TraverseCommandOptions): Promise<void>;
@@ -0,0 +1,58 @@
1
+ export async function runTraverseCommand(memoryId, opts) {
2
+ let db;
3
+ try {
4
+ const { GnosysDB: GnosysDBClass } = await import("./db.js");
5
+ const { handleRequest } = await import("../sandbox/server.js");
6
+ const dbDir = GnosysDBClass.getCentralDbDir();
7
+ db = new GnosysDBClass(dbDir);
8
+ if (!db.isAvailable()) {
9
+ console.error("Error: GnosysDB not available. Install it with: npm install better-sqlite3");
10
+ process.exit(1);
11
+ }
12
+ const params = {
13
+ id: memoryId,
14
+ depth: opts.depth ? parseInt(opts.depth, 10) : 3,
15
+ };
16
+ if (opts.relTypes)
17
+ params.rel_types = opts.relTypes.split(",").map((s) => s.trim());
18
+ const res = handleRequest(db, {
19
+ id: "cli-traverse",
20
+ method: "traverse",
21
+ params,
22
+ });
23
+ if (!res.ok) {
24
+ if (opts.json) {
25
+ console.log(JSON.stringify({ ok: false, error: res.error }));
26
+ }
27
+ else {
28
+ console.error(`Traverse failed: ${res.error}`);
29
+ }
30
+ process.exit(1);
31
+ }
32
+ const result = res.result;
33
+ if (opts.json) {
34
+ console.log(JSON.stringify(result, null, 2));
35
+ }
36
+ else {
37
+ console.log(`Traversal from ${memoryId} (depth: ${result.depth}):`);
38
+ console.log(` Total nodes: ${result.total}\n`);
39
+ for (const node of result.nodes) {
40
+ const indent = " ".repeat(node.depth + 1);
41
+ const via = node.via_rel ? ` ← [${node.via_rel}] from ${node.via_from}` : " (root)";
42
+ console.log(`${indent}${node.id}: ${node.title} (conf: ${node.confidence.toFixed(2)})${via}`);
43
+ }
44
+ }
45
+ }
46
+ catch (err) {
47
+ if (opts.json) {
48
+ console.log(JSON.stringify({ ok: false, error: err instanceof Error ? err.message : String(err) }));
49
+ }
50
+ else {
51
+ console.error(`Traverse failed: ${err instanceof Error ? err.message : err}`);
52
+ }
53
+ process.exit(1);
54
+ }
55
+ finally {
56
+ db?.close();
57
+ }
58
+ }
@@ -0,0 +1,13 @@
1
+ import type { GnosysResolver } from "./resolver.js";
2
+ export type UpdateCommandOptions = {
3
+ title?: string;
4
+ status?: string;
5
+ confidence?: string;
6
+ relevance?: string;
7
+ supersedes?: string;
8
+ supersededBy?: string;
9
+ content?: string;
10
+ };
11
+ type GetResolver = () => Promise<GnosysResolver>;
12
+ export declare function runUpdateCommand(getResolver: GetResolver, memoryPath: string, opts: UpdateCommandOptions): Promise<void>;
13
+ export {};
@@ -0,0 +1,67 @@
1
+ import { GnosysDB } from "./db.js";
2
+ export async function runUpdateCommand(getResolver, memoryPath, opts) {
3
+ let memoryId;
4
+ let currentTitle;
5
+ let centralDb = null;
6
+ try {
7
+ centralDb = GnosysDB.openCentral();
8
+ }
9
+ catch {
10
+ /* handled below */
11
+ }
12
+ if (centralDb?.isAvailable()) {
13
+ const dbMem = centralDb.getMemory(memoryPath);
14
+ if (dbMem) {
15
+ memoryId = dbMem.id;
16
+ currentTitle = dbMem.title;
17
+ }
18
+ else {
19
+ const resolver = await getResolver();
20
+ const memory = await resolver.readMemory(memoryPath);
21
+ if (!memory?.frontmatter.id) {
22
+ console.error(`Memory not found: ${memoryPath}`);
23
+ centralDb?.close();
24
+ process.exit(1);
25
+ }
26
+ memoryId = memory.frontmatter.id;
27
+ currentTitle = memory.frontmatter.title || memoryPath;
28
+ }
29
+ }
30
+ else {
31
+ console.error("Central DB not available.");
32
+ process.exit(1);
33
+ }
34
+ const updates = {};
35
+ if (opts.title !== undefined)
36
+ updates.title = opts.title;
37
+ if (opts.status !== undefined)
38
+ updates.status = opts.status;
39
+ if (opts.confidence !== undefined)
40
+ updates.confidence = parseFloat(opts.confidence);
41
+ if (opts.relevance !== undefined)
42
+ updates.relevance = opts.relevance;
43
+ if (opts.supersedes !== undefined)
44
+ updates.supersedes = opts.supersedes;
45
+ if (opts.supersededBy !== undefined)
46
+ updates.superseded_by = opts.supersededBy;
47
+ const fullContent = opts.content
48
+ ? `# ${opts.title || currentTitle}\n\n${opts.content}`
49
+ : undefined;
50
+ try {
51
+ const { syncUpdateToDb } = await import("./dbWrite.js");
52
+ syncUpdateToDb(centralDb, memoryId, updates, fullContent);
53
+ if (opts.supersedes) {
54
+ syncUpdateToDb(centralDb, opts.supersedes, { superseded_by: memoryId, status: "superseded" });
55
+ console.log(`Cross-linked: ${opts.supersedes} marked as superseded.`);
56
+ }
57
+ }
58
+ finally {
59
+ centralDb?.close();
60
+ }
61
+ const changedFields = Object.keys(updates);
62
+ if (opts.content)
63
+ changedFields.push("content");
64
+ console.log(`Memory updated: ${opts.title || currentTitle}`);
65
+ console.log(`ID: ${memoryId}`);
66
+ console.log(`Changed: ${changedFields.join(", ")}`);
67
+ }
@@ -0,0 +1,5 @@
1
+ export type UpdateStatusCommandOptions = {
2
+ directory?: string;
3
+ project?: string;
4
+ };
5
+ export declare function runUpdateStatusCommand(opts: UpdateStatusCommandOptions): Promise<void>;
@@ -0,0 +1,38 @@
1
+ import { GnosysDB } from "./db.js";
2
+ export async function runUpdateStatusCommand(opts) {
3
+ let centralDb = null;
4
+ try {
5
+ centralDb = GnosysDB.openCentral();
6
+ if (!centralDb.isAvailable()) {
7
+ console.error("Central DB not available.");
8
+ process.exitCode = 1;
9
+ return;
10
+ }
11
+ const { detectCurrentProject } = await import("./federated.js");
12
+ const { generateStatusPrompt } = await import("./portfolio.js");
13
+ let pid = opts.project || null;
14
+ if (!pid)
15
+ pid = await detectCurrentProject(centralDb, opts.directory || undefined);
16
+ if (!pid) {
17
+ console.error("No project specified and none detected.");
18
+ process.exitCode = 1;
19
+ return;
20
+ }
21
+ const project = centralDb.getProject(pid);
22
+ if (!project) {
23
+ console.error(`Project not found: ${pid}`);
24
+ process.exitCode = 1;
25
+ return;
26
+ }
27
+ const prompt = generateStatusPrompt(project.name, project.working_directory);
28
+ console.log(prompt);
29
+ }
30
+ catch (err) {
31
+ console.error(`Error: ${err instanceof Error ? err.message : err}`);
32
+ process.exitCode = 1;
33
+ return;
34
+ }
35
+ finally {
36
+ centralDb?.close();
37
+ }
38
+ }
@@ -0,0 +1,8 @@
1
+ import type { GetWebStorePath } from "./webInitCommand.js";
2
+ export type WebAddCommandOptions = {
3
+ category?: string;
4
+ llm: boolean;
5
+ reindex: boolean;
6
+ json?: boolean;
7
+ };
8
+ export declare function runWebAddCommand(getWebStorePath: GetWebStorePath, url: string, opts: WebAddCommandOptions): Promise<void>;