@iworkforces/tracelattice 2.0.8 → 2.1.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 (178) hide show
  1. package/README.md +89 -64
  2. package/dist/ServerConfig.d.ts +1 -1
  3. package/dist/ServerConfig.js.map +1 -1
  4. package/dist/cli.js +18 -73
  5. package/dist/cli.js.map +1 -1
  6. package/dist/config/ConfigLoader.d.ts +29 -26
  7. package/dist/config/ConfigLoader.d.ts.map +1 -1
  8. package/dist/config/ConfigLoader.js +40 -36
  9. package/dist/config/ConfigLoader.js.map +1 -1
  10. package/dist/contracts/PersistenceBackend.d.ts +7 -108
  11. package/dist/contracts/PersistenceBackend.d.ts.map +1 -1
  12. package/dist/contracts/PersistenceBackend.js +1 -6
  13. package/dist/contracts/calibrator.d.ts +6 -6
  14. package/dist/contracts/calibrator.d.ts.map +1 -1
  15. package/dist/contracts/ids.d.ts +1 -8
  16. package/dist/contracts/ids.d.ts.map +1 -1
  17. package/dist/contracts/ids.js +2 -3
  18. package/dist/contracts/ids.js.map +1 -1
  19. package/dist/contracts/interfaces.d.ts +4 -6
  20. package/dist/contracts/interfaces.d.ts.map +1 -1
  21. package/dist/contracts/persistence-work.d.ts +2 -3
  22. package/dist/contracts/persistence-work.d.ts.map +1 -1
  23. package/dist/core/HistoryManager.d.ts +12 -16
  24. package/dist/core/HistoryManager.d.ts.map +1 -1
  25. package/dist/core/HistoryManager.js +19 -40
  26. package/dist/core/HistoryManager.js.map +1 -1
  27. package/dist/core/IHistoryManager.d.ts +22 -30
  28. package/dist/core/IHistoryManager.d.ts.map +1 -1
  29. package/dist/core/InputNormalizer.d.ts +7 -24
  30. package/dist/core/InputNormalizer.d.ts.map +1 -1
  31. package/dist/core/InputNormalizer.js +3 -9
  32. package/dist/core/InputNormalizer.js.map +1 -1
  33. package/dist/core/PersistenceBuffer.d.ts +3 -20
  34. package/dist/core/PersistenceBuffer.d.ts.map +1 -1
  35. package/dist/core/PersistenceBuffer.js +1 -4
  36. package/dist/core/PersistenceBuffer.js.map +1 -1
  37. package/dist/core/PersistenceRestore.d.ts.map +1 -1
  38. package/dist/core/PersistenceRestore.js +4 -10
  39. package/dist/core/PersistenceRestore.js.map +1 -1
  40. package/dist/core/PersistenceWriter.d.ts.map +1 -1
  41. package/dist/core/PersistenceWriter.js +3 -12
  42. package/dist/core/PersistenceWriter.js.map +1 -1
  43. package/dist/core/SessionErrors.d.ts +0 -11
  44. package/dist/core/SessionErrors.d.ts.map +1 -1
  45. package/dist/core/SessionErrors.js +1 -14
  46. package/dist/core/SessionErrors.js.map +1 -1
  47. package/dist/core/SessionLock.d.ts +4 -5
  48. package/dist/core/SessionLock.d.ts.map +1 -1
  49. package/dist/core/SessionLock.js +5 -10
  50. package/dist/core/SessionLock.js.map +1 -1
  51. package/dist/core/SessionManager.d.ts +0 -2
  52. package/dist/core/SessionManager.d.ts.map +1 -1
  53. package/dist/core/SessionManager.js +3 -5
  54. package/dist/core/SessionManager.js.map +1 -1
  55. package/dist/core/SessionResetCoordinator.d.ts +10 -7
  56. package/dist/core/SessionResetCoordinator.d.ts.map +1 -1
  57. package/dist/core/SessionResetCoordinator.js +10 -28
  58. package/dist/core/SessionResetCoordinator.js.map +1 -1
  59. package/dist/core/ThoughtEvaluator.d.ts +5 -5
  60. package/dist/core/ThoughtEvaluator.d.ts.map +1 -1
  61. package/dist/core/ThoughtEvaluator.js +4 -40
  62. package/dist/core/ThoughtEvaluator.js.map +1 -1
  63. package/dist/core/ThoughtProcessor.d.ts +10 -3
  64. package/dist/core/ThoughtProcessor.d.ts.map +1 -1
  65. package/dist/core/ThoughtProcessor.js +34 -38
  66. package/dist/core/ThoughtProcessor.js.map +1 -1
  67. package/dist/core/VerificationOutcomeAdmission.d.ts.map +1 -1
  68. package/dist/core/VerificationOutcomeAdmission.js +5 -7
  69. package/dist/core/VerificationOutcomeAdmission.js.map +1 -1
  70. package/dist/core/evaluator/Calibrator.d.ts +1 -1
  71. package/dist/core/evaluator/Calibrator.d.ts.map +1 -1
  72. package/dist/core/evaluator/Calibrator.js +2 -5
  73. package/dist/core/evaluator/Calibrator.js.map +1 -1
  74. package/dist/core/evaluator/internals.d.ts +0 -4
  75. package/dist/core/evaluator/internals.d.ts.map +1 -1
  76. package/dist/core/evaluator/internals.js +1 -3
  77. package/dist/core/evaluator/internals.js.map +1 -1
  78. package/dist/core/graph/Edge.d.ts +1 -1
  79. package/dist/core/graph/EdgeEmitter.d.ts +2 -4
  80. package/dist/core/graph/EdgeEmitter.d.ts.map +1 -1
  81. package/dist/core/graph/EdgeEmitter.js +2 -4
  82. package/dist/core/graph/EdgeEmitter.js.map +1 -1
  83. package/dist/core/reasoning/OutcomeRecorder.d.ts +0 -1
  84. package/dist/core/reasoning/OutcomeRecorder.d.ts.map +1 -1
  85. package/dist/core/reasoning/OutcomeRecorder.js.map +1 -1
  86. package/dist/core/reasoning/strategies/SequentialStrategy.d.ts +3 -3
  87. package/dist/core/reasoning/strategies/SequentialStrategy.js.map +1 -1
  88. package/dist/core/thought.d.ts +2 -1
  89. package/dist/core/thought.d.ts.map +1 -1
  90. package/dist/errors.d.ts +4 -20
  91. package/dist/errors.d.ts.map +1 -1
  92. package/dist/errors.js +2 -28
  93. package/dist/errors.js.map +1 -1
  94. package/dist/lib.d.ts +13 -20
  95. package/dist/lib.d.ts.map +1 -1
  96. package/dist/lib.js +4 -7
  97. package/dist/lib.js.map +1 -1
  98. package/dist/logger/NullLogger.d.ts +9 -11
  99. package/dist/logger/NullLogger.d.ts.map +1 -1
  100. package/dist/logger/NullLogger.js.map +1 -1
  101. package/dist/persistence/FilePersistence.d.ts +3 -12
  102. package/dist/persistence/FilePersistence.d.ts.map +1 -1
  103. package/dist/persistence/FilePersistence.js +9 -61
  104. package/dist/persistence/FilePersistence.js.map +1 -1
  105. package/dist/persistence/FileSnapshotV2.d.ts +2 -2
  106. package/dist/persistence/FileSnapshotV2.js +2 -2
  107. package/dist/persistence/FileSnapshotV2.js.map +1 -1
  108. package/dist/persistence/FileWriter.d.ts +1 -0
  109. package/dist/persistence/FileWriter.d.ts.map +1 -1
  110. package/dist/persistence/FileWriter.js +3 -3
  111. package/dist/persistence/FileWriter.js.map +1 -1
  112. package/dist/persistence/MemoryPersistence.d.ts +5 -15
  113. package/dist/persistence/MemoryPersistence.d.ts.map +1 -1
  114. package/dist/persistence/MemoryPersistence.js +6 -40
  115. package/dist/persistence/MemoryPersistence.js.map +1 -1
  116. package/dist/persistence/PersistenceCodec.js +1 -3
  117. package/dist/persistence/PersistenceCodec.js.map +1 -1
  118. package/dist/persistence/PersistenceErrors.d.ts +0 -6
  119. package/dist/persistence/PersistenceErrors.d.ts.map +1 -1
  120. package/dist/persistence/PersistenceErrors.js +1 -9
  121. package/dist/persistence/PersistenceErrors.js.map +1 -1
  122. package/dist/persistence/PersistenceScope.d.ts.map +1 -1
  123. package/dist/persistence/PersistenceScope.js +2 -2
  124. package/dist/persistence/PersistenceScope.js.map +1 -1
  125. package/dist/persistence/SqlitePersistence.d.ts +3 -10
  126. package/dist/persistence/SqlitePersistence.d.ts.map +1 -1
  127. package/dist/persistence/SqlitePersistence.js +2 -26
  128. package/dist/persistence/SqlitePersistence.js.map +1 -1
  129. package/dist/persistence/SqliteSchemaV2.d.ts.map +1 -1
  130. package/dist/persistence/SqliteSchemaV2.js +3 -12
  131. package/dist/persistence/SqliteSchemaV2.js.map +1 -1
  132. package/dist/pool/ConnectionPool.d.ts +3 -12
  133. package/dist/pool/ConnectionPool.d.ts.map +1 -1
  134. package/dist/pool/ConnectionPool.js +5 -8
  135. package/dist/pool/ConnectionPool.js.map +1 -1
  136. package/dist/pool/IConnectionPool.d.ts +3 -9
  137. package/dist/pool/IConnectionPool.d.ts.map +1 -1
  138. package/dist/registry/BaseRegistry.d.ts +10 -2
  139. package/dist/registry/BaseRegistry.d.ts.map +1 -1
  140. package/dist/registry/BaseRegistry.js +128 -81
  141. package/dist/registry/BaseRegistry.js.map +1 -1
  142. package/dist/registry/SkillRegistry.d.ts +1 -7
  143. package/dist/registry/SkillRegistry.d.ts.map +1 -1
  144. package/dist/registry/SkillRegistry.js +0 -15
  145. package/dist/registry/SkillRegistry.js.map +1 -1
  146. package/dist/registry/ToolRegistry.d.ts +1 -9
  147. package/dist/registry/ToolRegistry.d.ts.map +1 -1
  148. package/dist/registry/ToolRegistry.js +0 -21
  149. package/dist/registry/ToolRegistry.js.map +1 -1
  150. package/dist/schema.d.ts +2 -1
  151. package/dist/schema.d.ts.map +1 -1
  152. package/dist/schema.js +3 -3
  153. package/dist/schema.js.map +1 -1
  154. package/dist/transport/BaseTransport.d.ts +0 -9
  155. package/dist/transport/BaseTransport.d.ts.map +1 -1
  156. package/dist/transport/BaseTransport.js +0 -11
  157. package/dist/transport/BaseTransport.js.map +1 -1
  158. package/dist/watchers/SkillWatcher.d.ts.map +1 -1
  159. package/dist/watchers/SkillWatcher.js +1 -1
  160. package/dist/watchers/SkillWatcher.js.map +1 -1
  161. package/package.json +1 -1
  162. package/dist/contracts/PersistenceBackend.js.map +0 -1
  163. package/dist/persistence/FileLegacyImport.d.ts +0 -2
  164. package/dist/persistence/FileLegacyImport.d.ts.map +0 -1
  165. package/dist/persistence/FileLegacyImport.js +0 -183
  166. package/dist/persistence/FileLegacyImport.js.map +0 -1
  167. package/dist/persistence/SessionScopedPersistence.d.ts +0 -4
  168. package/dist/persistence/SessionScopedPersistence.d.ts.map +0 -1
  169. package/dist/persistence/SessionScopedPersistence.js +0 -9
  170. package/dist/persistence/SessionScopedPersistence.js.map +0 -1
  171. package/dist/persistence/SqliteLegacyImport.d.ts +0 -14
  172. package/dist/persistence/SqliteLegacyImport.d.ts.map +0 -1
  173. package/dist/persistence/SqliteLegacyImport.js +0 -136
  174. package/dist/persistence/SqliteLegacyImport.js.map +0 -1
  175. package/dist/persistence/SqliteLegacySchema.d.ts +0 -15
  176. package/dist/persistence/SqliteLegacySchema.d.ts.map +0 -1
  177. package/dist/persistence/SqliteLegacySchema.js +0 -72
  178. package/dist/persistence/SqliteLegacySchema.js.map +0 -1
@@ -36,7 +36,6 @@ import type { LogLevel, Logger, LoggerOptions } from './StructuredLogger.js';
36
36
  * logger.warn('Or this warning');
37
37
  * logger.error('Or even this error');
38
38
  *
39
- * // Methods exist for compatibility but have no effect
40
39
  * logger.setLevel('debug');
41
40
  * const level = logger.getLevel(); // Returns 'error' (default)
42
41
  * ```
@@ -47,14 +46,14 @@ export declare class NullLogger implements Logger {
47
46
  *
48
47
  * @remarks
49
48
  * Since all messages are discarded, the level setting has no practical
50
- * effect. This property exists only for interface compatibility.
49
+ * effect. The value is retained to satisfy the logger contract.
51
50
  * @private
52
51
  */
53
52
  private _level;
54
53
  /**
55
54
  * Creates a new NullLogger instance.
56
55
  *
57
- * @param options - Configuration options (ignored, but accepted for interface compatibility)
56
+ * @param options - Configuration options used to initialize the logger contract
58
57
  *
59
58
  * @example
60
59
  * ```typescript
@@ -73,7 +72,7 @@ export declare class NullLogger implements Logger {
73
72
  /**
74
73
  * Log a debug message (no-op).
75
74
  *
76
- * This method exists for interface compatibility but does nothing.
75
+ * This logger discards the message.
77
76
  *
78
77
  * @param _message - Ignored
79
78
  * @param _meta - Ignored
@@ -82,7 +81,7 @@ export declare class NullLogger implements Logger {
82
81
  /**
83
82
  * Log an info message (no-op).
84
83
  *
85
- * This method exists for interface compatibility but does nothing.
84
+ * This logger discards the message.
86
85
  *
87
86
  * @param _message - Ignored
88
87
  * @param _meta - Ignored
@@ -91,7 +90,7 @@ export declare class NullLogger implements Logger {
91
90
  /**
92
91
  * Log a warning message (no-op).
93
92
  *
94
- * This method exists for interface compatibility but does nothing.
93
+ * This logger discards the message.
95
94
  *
96
95
  * @param _message - Ignored
97
96
  * @param _meta - Ignored
@@ -100,7 +99,7 @@ export declare class NullLogger implements Logger {
100
99
  /**
101
100
  * Log an error message (no-op).
102
101
  *
103
- * This method exists for interface compatibility but does nothing.
102
+ * This logger discards the message.
104
103
  *
105
104
  * @param _message - Ignored
106
105
  * @param _meta - Ignored
@@ -109,8 +108,8 @@ export declare class NullLogger implements Logger {
109
108
  /**
110
109
  * Sets the minimum log level (no-op).
111
110
  *
112
- * This method exists for interface compatibility but has no effect
113
- * since all messages are discarded anyway.
111
+ * The level is retained for `getLevel` and child loggers, but does not
112
+ * affect output because all messages are discarded.
114
113
  *
115
114
  * @param level - The new minimum log level (ignored)
116
115
  *
@@ -135,8 +134,7 @@ export declare class NullLogger implements Logger {
135
134
  /**
136
135
  * Creates a child null logger (returns a new NullLogger).
137
136
  *
138
- * This method exists for interface compatibility. It returns a new
139
- * `NullLogger` instance (not a child with extended context) since
137
+ * Returns a new `NullLogger` instance (not a child with extended context) since
140
138
  * context tracking is not applicable for a no-op logger.
141
139
  *
142
140
  * @param _context - Additional context (ignored)
@@ -1 +1 @@
1
- {"version":3,"file":"NullLogger.d.ts","sourceRoot":"","sources":["../../src/logger/NullLogger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,qBAAa,UAAW,YAAW,MAAM;IACxC;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAW;IAEzB;;;;;;;;;;;;;;;;;OAiBG;gBACS,OAAO,GAAE,aAAkB;IAIvC;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAE9D;;;;;;;OAOG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAE7D;;;;;;;OAOG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAE7D;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAE9D;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/B;;;;;;;;;;OAUG;IACH,QAAQ,IAAI,QAAQ;IAIpB;;;;;;;;;;;;;;;;OAgBG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU;CAGzC"}
1
+ {"version":3,"file":"NullLogger.d.ts","sourceRoot":"","sources":["../../src/logger/NullLogger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qBAAa,UAAW,YAAW,MAAM;IACxC;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAW;IAEzB;;;;;;;;;;;;;;;;;OAiBG;gBACS,OAAO,GAAE,aAAkB;IAIvC;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAE9D;;;;;;;OAOG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAE7D;;;;;;;OAOG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAE7D;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAE9D;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/B;;;;;;;;;;OAUG;IACH,QAAQ,IAAI,QAAQ;IAIpB;;;;;;;;;;;;;;;OAeG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU;CAGzC"}
@@ -1 +1 @@
1
- {"version":3,"file":"logger/NullLogger.js","sources":["../../src/logger/NullLogger.ts"],"sourcesContent":["/**\n * Null logger that discards all log messages.\n *\n * This logger implements the same interface as `StructuredLogger` but\n * silently discards all log messages. It's useful as a default/fallback\n * logger when logging is disabled or when no logger is provided.\n *\n * @module logger\n */\n\nimport type { LogLevel, Logger, LoggerOptions } from './StructuredLogger.js';\n\n/**\n * Null logger that discards all log messages.\n *\n * This class provides a no-op implementation of the logger interface.\n * All method calls are silent and have no effect, making it suitable\n * for use as a default logger when logging is disabled or not needed.\n *\n * @remarks\n * The `NullLogger` implements the same interface as `StructuredLogger`,\n * making them interchangeable. Use `NullLogger` when:\n * - You want to disable logging completely\n * - You need a logger placeholder that can be swapped later\n * - Testing components that don't need output\n * - Reducing overhead in performance-critical sections\n *\n * @example\n * ```typescript\n * import { NullLogger } from './logger/index.js';\n *\n * // Create a null logger\n * const logger = new NullLogger();\n *\n * // All log calls are silently discarded\n * logger.debug('This will not appear');\n * logger.info('Nor will this');\n * logger.warn('Or this warning');\n * logger.error('Or even this error');\n *\n * // Methods exist for compatibility but have no effect\n * logger.setLevel('debug');\n * const level = logger.getLevel(); // Returns 'error' (default)\n * ```\n */\nexport class NullLogger implements Logger {\n\t/**\n\t * Current minimum log level.\n\t *\n\t * @remarks\n\t * Since all messages are discarded, the level setting has no practical\n\t * effect. This property exists only for interface compatibility.\n\t * @private\n\t */\n\tprivate _level: LogLevel;\n\n\t/**\n\t * Creates a new NullLogger instance.\n\t *\n\t * @param options - Configuration options (ignored, but accepted for interface compatibility)\n\t *\n\t * @example\n\t * ```typescript\n\t * // Create a null logger\n\t * const logger1 = new NullLogger();\n\t *\n\t * // With options (ignored)\n\t * const logger2 = new NullLogger({\n\t * level: 'debug',\n\t * context: 'MyApp',\n\t * pretty: true\n\t * });\n\t * ```\n\t */\n\tconstructor(options: LoggerOptions = {}) {\n\t\tthis._level = options.level ?? 'error';\n\t}\n\n\t/**\n\t * Log a debug message (no-op).\n\t *\n\t * This method exists for interface compatibility but does nothing.\n\t *\n\t * @param _message - Ignored\n\t * @param _meta - Ignored\n\t */\n\tdebug(_message: string, _meta?: Record<string, unknown>): void {}\n\n\t/**\n\t * Log an info message (no-op).\n\t *\n\t * This method exists for interface compatibility but does nothing.\n\t *\n\t * @param _message - Ignored\n\t * @param _meta - Ignored\n\t */\n\tinfo(_message: string, _meta?: Record<string, unknown>): void {}\n\n\t/**\n\t * Log a warning message (no-op).\n\t *\n\t * This method exists for interface compatibility but does nothing.\n\t *\n\t * @param _message - Ignored\n\t * @param _meta - Ignored\n\t */\n\twarn(_message: string, _meta?: Record<string, unknown>): void {}\n\n\t/**\n\t * Log an error message (no-op).\n\t *\n\t * This method exists for interface compatibility but does nothing.\n\t *\n\t * @param _message - Ignored\n\t * @param _meta - Ignored\n\t */\n\terror(_message: string, _meta?: Record<string, unknown>): void {}\n\n\t/**\n\t * Sets the minimum log level (no-op).\n\t *\n\t * This method exists for interface compatibility but has no effect\n\t * since all messages are discarded anyway.\n\t *\n\t * @param level - The new minimum log level (ignored)\n\t *\n\t * @example\n\t * ```typescript\n\t * logger.setLevel('debug'); // No effect\n\t * ```\n\t */\n\tsetLevel(level: LogLevel): void {\n\t\tthis._level = level;\n\t}\n\n\t/**\n\t * Gets the current minimum log level.\n\t *\n\t * @returns The current log level (stored value, unused)\n\t *\n\t * @example\n\t * ```typescript\n\t * const currentLevel = logger.getLevel();\n\t * console.log(`Current level: ${currentLevel}`); // 'error' by default\n\t * ```\n\t */\n\tgetLevel(): LogLevel {\n\t\treturn this._level;\n\t}\n\n\t/**\n\t * Creates a child null logger (returns a new NullLogger).\n\t *\n\t * This method exists for interface compatibility. It returns a new\n\t * `NullLogger` instance (not a child with extended context) since\n\t * context tracking is not applicable for a no-op logger.\n\t *\n\t * @param _context - Additional context (ignored)\n\t * @returns A new NullLogger instance\n\t *\n\t * @example\n\t * ```typescript\n\t * const nullLogger = new NullLogger();\n\t * const childLogger = nullLogger.createChild('ChildModule');\n\t * // childLogger is also a NullLogger\n\t * ```\n\t */\n\tcreateChild(_context: string): NullLogger {\n\t\treturn new NullLogger({ level: this._level });\n\t}\n}\n"],"names":["NullLogger","options","_message","_meta","level","_context"],"mappings":"AA6CO,MAAMA;IASJ,OAAiB;IAoBzB,YAAYC,UAAyB,CAAC,CAAC,CAAE;QACxC,IAAI,CAAC,MAAM,GAAGA,QAAQ,KAAK,IAAI;IAChC;IAUA,MAAMC,QAAgB,EAAEC,KAA+B,EAAQ,CAAC;IAUhE,KAAKD,QAAgB,EAAEC,KAA+B,EAAQ,CAAC;IAU/D,KAAKD,QAAgB,EAAEC,KAA+B,EAAQ,CAAC;IAU/D,MAAMD,QAAgB,EAAEC,KAA+B,EAAQ,CAAC;IAehE,SAASC,KAAe,EAAQ;QAC/B,IAAI,CAAC,MAAM,GAAGA;IACf;IAaA,WAAqB;QACpB,OAAO,IAAI,CAAC,MAAM;IACnB;IAmBA,YAAYC,QAAgB,EAAc;QACzC,OAAO,IAAIL,WAAW;YAAE,OAAO,IAAI,CAAC,MAAM;QAAC;IAC5C;AACD"}
1
+ {"version":3,"file":"logger/NullLogger.js","sources":["../../src/logger/NullLogger.ts"],"sourcesContent":["/**\n * Null logger that discards all log messages.\n *\n * This logger implements the same interface as `StructuredLogger` but\n * silently discards all log messages. It's useful as a default/fallback\n * logger when logging is disabled or when no logger is provided.\n *\n * @module logger\n */\n\nimport type { LogLevel, Logger, LoggerOptions } from './StructuredLogger.js';\n\n/**\n * Null logger that discards all log messages.\n *\n * This class provides a no-op implementation of the logger interface.\n * All method calls are silent and have no effect, making it suitable\n * for use as a default logger when logging is disabled or not needed.\n *\n * @remarks\n * The `NullLogger` implements the same interface as `StructuredLogger`,\n * making them interchangeable. Use `NullLogger` when:\n * - You want to disable logging completely\n * - You need a logger placeholder that can be swapped later\n * - Testing components that don't need output\n * - Reducing overhead in performance-critical sections\n *\n * @example\n * ```typescript\n * import { NullLogger } from './logger/index.js';\n *\n * // Create a null logger\n * const logger = new NullLogger();\n *\n * // All log calls are silently discarded\n * logger.debug('This will not appear');\n * logger.info('Nor will this');\n * logger.warn('Or this warning');\n * logger.error('Or even this error');\n *\n * logger.setLevel('debug');\n * const level = logger.getLevel(); // Returns 'error' (default)\n * ```\n */\nexport class NullLogger implements Logger {\n\t/**\n\t * Current minimum log level.\n\t *\n\t * @remarks\n\t * Since all messages are discarded, the level setting has no practical\n\t * effect. The value is retained to satisfy the logger contract.\n\t * @private\n\t */\n\tprivate _level: LogLevel;\n\n\t/**\n\t * Creates a new NullLogger instance.\n\t *\n\t * @param options - Configuration options used to initialize the logger contract\n\t *\n\t * @example\n\t * ```typescript\n\t * // Create a null logger\n\t * const logger1 = new NullLogger();\n\t *\n\t * // With options (ignored)\n\t * const logger2 = new NullLogger({\n\t * level: 'debug',\n\t * context: 'MyApp',\n\t * pretty: true\n\t * });\n\t * ```\n\t */\n\tconstructor(options: LoggerOptions = {}) {\n\t\tthis._level = options.level ?? 'error';\n\t}\n\n\t/**\n\t * Log a debug message (no-op).\n\t *\n\t * This logger discards the message.\n\t *\n\t * @param _message - Ignored\n\t * @param _meta - Ignored\n\t */\n\tdebug(_message: string, _meta?: Record<string, unknown>): void {}\n\n\t/**\n\t * Log an info message (no-op).\n\t *\n\t * This logger discards the message.\n\t *\n\t * @param _message - Ignored\n\t * @param _meta - Ignored\n\t */\n\tinfo(_message: string, _meta?: Record<string, unknown>): void {}\n\n\t/**\n\t * Log a warning message (no-op).\n\t *\n\t * This logger discards the message.\n\t *\n\t * @param _message - Ignored\n\t * @param _meta - Ignored\n\t */\n\twarn(_message: string, _meta?: Record<string, unknown>): void {}\n\n\t/**\n\t * Log an error message (no-op).\n\t *\n\t * This logger discards the message.\n\t *\n\t * @param _message - Ignored\n\t * @param _meta - Ignored\n\t */\n\terror(_message: string, _meta?: Record<string, unknown>): void {}\n\n\t/**\n\t * Sets the minimum log level (no-op).\n\t *\n\t * The level is retained for `getLevel` and child loggers, but does not\n\t * affect output because all messages are discarded.\n\t *\n\t * @param level - The new minimum log level (ignored)\n\t *\n\t * @example\n\t * ```typescript\n\t * logger.setLevel('debug'); // No effect\n\t * ```\n\t */\n\tsetLevel(level: LogLevel): void {\n\t\tthis._level = level;\n\t}\n\n\t/**\n\t * Gets the current minimum log level.\n\t *\n\t * @returns The current log level (stored value, unused)\n\t *\n\t * @example\n\t * ```typescript\n\t * const currentLevel = logger.getLevel();\n\t * console.log(`Current level: ${currentLevel}`); // 'error' by default\n\t * ```\n\t */\n\tgetLevel(): LogLevel {\n\t\treturn this._level;\n\t}\n\n\t/**\n\t * Creates a child null logger (returns a new NullLogger).\n\t *\n\t * Returns a new `NullLogger` instance (not a child with extended context) since\n\t * context tracking is not applicable for a no-op logger.\n\t *\n\t * @param _context - Additional context (ignored)\n\t * @returns A new NullLogger instance\n\t *\n\t * @example\n\t * ```typescript\n\t * const nullLogger = new NullLogger();\n\t * const childLogger = nullLogger.createChild('ChildModule');\n\t * // childLogger is also a NullLogger\n\t * ```\n\t */\n\tcreateChild(_context: string): NullLogger {\n\t\treturn new NullLogger({ level: this._level });\n\t}\n}\n"],"names":["NullLogger","options","_message","_meta","level","_context"],"mappings":"AA4CO,MAAMA;IASJ,OAAiB;IAoBzB,YAAYC,UAAyB,CAAC,CAAC,CAAE;QACxC,IAAI,CAAC,MAAM,GAAGA,QAAQ,KAAK,IAAI;IAChC;IAUA,MAAMC,QAAgB,EAAEC,KAA+B,EAAQ,CAAC;IAUhE,KAAKD,QAAgB,EAAEC,KAA+B,EAAQ,CAAC;IAU/D,KAAKD,QAAgB,EAAEC,KAA+B,EAAQ,CAAC;IAU/D,MAAMD,QAAgB,EAAEC,KAA+B,EAAQ,CAAC;IAehE,SAASC,KAAe,EAAQ;QAC/B,IAAI,CAAC,MAAM,GAAGA;IACf;IAaA,WAAqB;QACpB,OAAO,IAAI,CAAC,MAAM;IACnB;IAkBA,YAAYC,QAAgB,EAAc;QACzC,OAAO,IAAIL,WAAW;YAAE,OAAO,IAAI,CAAC,MAAM;QAAC;IAC5C;AACD"}
@@ -1,5 +1,5 @@
1
1
  import type { IMetrics } from '../contracts/interfaces.js';
2
- import type { PersistenceConfig, SessionScopedPersistenceBackend } from '../contracts/PersistenceBackend.js';
2
+ import type { PersistenceConfig, PersistenceBackend } from '../contracts/PersistenceBackend.js';
3
3
  import { type BranchId, type SessionId } from '../contracts/ids.js';
4
4
  import type { Summary } from '../core/compression/Summary.js';
5
5
  import type { Edge } from '../core/graph/Edge.js';
@@ -9,7 +9,7 @@ type FilePersistenceOptions = NonNullable<PersistenceConfig['options']> & {
9
9
  readonly metrics?: IMetrics;
10
10
  readonly writerOperations?: FileWriterOperations;
11
11
  };
12
- export declare class FilePersistence implements SessionScopedPersistenceBackend {
12
+ export declare class FilePersistence implements PersistenceBackend {
13
13
  private readonly _dataDir;
14
14
  private readonly _maxHistorySize;
15
15
  private readonly _persistBranches;
@@ -17,36 +17,27 @@ export declare class FilePersistence implements SessionScopedPersistenceBackend
17
17
  private readonly _writer;
18
18
  constructor(options?: FilePersistenceOptions);
19
19
  static create(options?: FilePersistenceOptions): Promise<FilePersistence>;
20
- saveThought(thought: ThoughtData): Promise<void>;
21
20
  saveThoughtForSession(sessionId: SessionId, thought: ThoughtData): Promise<void>;
22
21
  private _saveThought;
23
- loadHistory(): Promise<ThoughtData[]>;
24
22
  loadHistoryForSession(sessionId: SessionId): Promise<ThoughtData[]>;
25
- saveBranch(branchId: BranchId, thoughts: ThoughtData[]): Promise<void>;
26
23
  saveBranchForSession(sessionId: SessionId, branchId: BranchId, thoughts: readonly ThoughtData[]): Promise<void>;
27
24
  private _saveBranch;
28
- deleteBranch(branchId: BranchId): Promise<void>;
29
25
  deleteBranchForSession(sessionId: SessionId, branchId: BranchId): Promise<void>;
30
- loadBranch(branchId: BranchId): Promise<ThoughtData[] | undefined>;
31
26
  loadBranchForSession(sessionId: SessionId, branchId: BranchId): Promise<ThoughtData[] | undefined>;
32
- listBranches(): Promise<BranchId[]>;
33
27
  listBranchesForSession(sessionId: SessionId): Promise<BranchId[]>;
34
28
  listSessions(): Promise<SessionId[]>;
35
- clear(): Promise<void>;
29
+ clearAll(): Promise<void>;
36
30
  clearSession(sessionId: SessionId): Promise<void>;
37
31
  saveEdges(sessionId: SessionId, edges: readonly Edge[]): Promise<void>;
38
32
  loadEdges(sessionId: SessionId): Promise<Edge[]>;
39
- listEdgeSessions(): Promise<SessionId[]>;
40
33
  saveSummaries(sessionId: SessionId, summaries: readonly Summary[]): Promise<void>;
41
34
  loadSummaries(sessionId: SessionId): Promise<Summary[]>;
42
35
  healthy(): Promise<boolean>;
43
36
  getDataDir(): string;
44
- getBranchIds(): Promise<string[]>;
45
37
  close(): Promise<void>;
46
38
  private _read;
47
39
  private _mutate;
48
40
  private _loadSnapshot;
49
- private _legacyArtifacts;
50
41
  private _measure;
51
42
  }
52
43
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"FilePersistence.d.ts","sourceRoot":"","sources":["../../src/persistence/FilePersistence.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FilePersistence.d.ts","sourceRoot":"","sources":["../../src/persistence/FilePersistence.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EACX,iBAAiB,EACjB,kBAAkB,EAClB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAe,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAStD,OAAO,EAGN,KAAK,oBAAoB,EACzB,MAAM,iBAAiB,CAAC;AAYzB,KAAK,sBAAsB,GAAG,WAAW,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC,GAAG;IACzE,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;CACjD,CAAC;AAIF,qBAAa,eAAgB,YAAW,kBAAkB;IACzD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAU;IAC3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuB;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;gBAEzB,OAAO,CAAC,EAAE,sBAAsB;WAWxB,MAAM,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,eAAe,CAAC;IAYzE,qBAAqB,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;YAM/E,YAAY;IA2Bb,qBAAqB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAQnE,oBAAoB,CAChC,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,SAAS,WAAW,EAAE,GAC9B,OAAO,CAAC,IAAI,CAAC;YAOF,WAAW;IAwCZ,sBAAsB,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAY/E,oBAAoB,CAChC,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,GAChB,OAAO,CAAC,WAAW,EAAE,GAAG,SAAS,CAAC;IAYxB,sBAAsB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAWjE,YAAY,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAIpC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzB,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAWjD,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAYtE,SAAS,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAOhD,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAcjF,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAQvD,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAUjC,UAAU,IAAI,MAAM;IAId,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAIrB,KAAK;YAQL,OAAO;YAaP,aAAa;YAeb,QAAQ;CAUtB"}
@@ -2,17 +2,12 @@ import { existsSync } from "node:fs";
2
2
  import { readFile, readdir } from "node:fs/promises";
3
3
  import { homedir } from "node:os";
4
4
  import { join } from "node:path";
5
- import { GLOBAL_SESSION_ID, asSessionId } from "../contracts/ids.js";
6
- import { PersistenceImportRequiredError } from "../errors.js";
5
+ import { asSessionId } from "../contracts/ids.js";
6
+ import { PersistenceCompatibilityError } from "../errors.js";
7
7
  import { EMPTY_FILE_SNAPSHOT_V2, parseFileSnapshotV2, serializeFileSnapshotV2, sessionsInSnapshot } from "./FileSnapshotV2.js";
8
- import { FileWriter, isFileNotFound } from "./FileWriter.js";
8
+ import { FILE_WRITER_LOCK_NAME, FileWriter } from "./FileWriter.js";
9
9
  import { assertBranchScope, assertEdgeScopes, assertPersistableThoughtCollections, assertPersistableThoughts, assertSummaryScopes, assertThoughtScope, compareCodePoint, parsePersistenceBranchId } from "./PersistenceScope.js";
10
10
  const SNAPSHOT_NAME = 'snapshot.json';
11
- const LEGACY_DIRECTORIES = [
12
- 'branches',
13
- 'edges',
14
- 'summaries'
15
- ];
16
11
  class FilePersistence {
17
12
  _dataDir;
18
13
  _maxHistorySize;
@@ -38,10 +33,6 @@ class FilePersistence {
38
33
  throw error;
39
34
  }
40
35
  }
41
- async saveThought(thought) {
42
- assertThoughtScope('saveThought', GLOBAL_SESSION_ID, thought);
43
- await this._saveThought(GLOBAL_SESSION_ID, thought);
44
- }
45
36
  async saveThoughtForSession(sessionId, thought) {
46
37
  const validatedSessionId = asSessionId(sessionId);
47
38
  assertThoughtScope('saveThoughtForSession', validatedSessionId, thought);
@@ -80,20 +71,12 @@ class FilePersistence {
80
71
  };
81
72
  });
82
73
  }
83
- async loadHistory() {
84
- return await this.loadHistoryForSession(GLOBAL_SESSION_ID);
85
- }
86
74
  async loadHistoryForSession(sessionId) {
87
75
  const validatedSessionId = asSessionId(sessionId);
88
76
  return await this._read('load_history', (snapshot)=>[
89
77
  ...snapshot.thoughts.find((record)=>record.sessionId === validatedSessionId)?.thoughts ?? []
90
78
  ]);
91
79
  }
92
- async saveBranch(branchId, thoughts) {
93
- const validatedBranchId = parsePersistenceBranchId(branchId, 'global/branches');
94
- assertBranchScope('saveBranch', GLOBAL_SESSION_ID, validatedBranchId, thoughts);
95
- await this._saveBranch(GLOBAL_SESSION_ID, validatedBranchId, thoughts);
96
- }
97
80
  async saveBranchForSession(sessionId, branchId, thoughts) {
98
81
  const validatedSessionId = asSessionId(sessionId);
99
82
  const validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);
@@ -138,9 +121,6 @@ class FilePersistence {
138
121
  ]
139
122
  }));
140
123
  }
141
- async deleteBranch(branchId) {
142
- await this.deleteBranchForSession(GLOBAL_SESSION_ID, branchId);
143
- }
144
124
  async deleteBranchForSession(sessionId, branchId) {
145
125
  if (!this._persistBranches) return;
146
126
  const validatedSessionId = asSessionId(sessionId);
@@ -150,9 +130,6 @@ class FilePersistence {
150
130
  branches: snapshot.branches.filter((record)=>record.sessionId !== validatedSessionId || record.branchId !== validatedBranchId)
151
131
  }));
152
132
  }
153
- async loadBranch(branchId) {
154
- return await this.loadBranchForSession(GLOBAL_SESSION_ID, branchId);
155
- }
156
133
  async loadBranchForSession(sessionId, branchId) {
157
134
  if (!this._persistBranches) return;
158
135
  const validatedSessionId = asSessionId(sessionId);
@@ -164,9 +141,6 @@ class FilePersistence {
164
141
  ];
165
142
  });
166
143
  }
167
- async listBranches() {
168
- return await this.listBranchesForSession(GLOBAL_SESSION_ID);
169
- }
170
144
  async listBranchesForSession(sessionId) {
171
145
  if (!this._persistBranches) return [];
172
146
  const validatedSessionId = asSessionId(sessionId);
@@ -175,8 +149,8 @@ class FilePersistence {
175
149
  async listSessions() {
176
150
  return await this._read('list_sessions', sessionsInSnapshot);
177
151
  }
178
- async clear() {
179
- await this._mutate('clear', ()=>EMPTY_FILE_SNAPSHOT_V2);
152
+ async clearAll() {
153
+ await this._mutate('clear_all', ()=>EMPTY_FILE_SNAPSHOT_V2);
180
154
  }
181
155
  async clearSession(sessionId) {
182
156
  const validatedSessionId = asSessionId(sessionId);
@@ -212,9 +186,6 @@ class FilePersistence {
212
186
  ...snapshot.edges.find((record)=>record.sessionId === validatedSessionId)?.edges ?? []
213
187
  ]);
214
188
  }
215
- async listEdgeSessions() {
216
- return await this._read('list_edge_sessions', (snapshot)=>snapshot.edges.map((record)=>record.sessionId).sort(compareCodePoint));
217
- }
218
189
  async saveSummaries(sessionId, summaries) {
219
190
  const validatedSessionId = asSessionId(sessionId);
220
191
  assertSummaryScopes(validatedSessionId, summaries);
@@ -251,9 +222,6 @@ class FilePersistence {
251
222
  getDataDir() {
252
223
  return this._dataDir;
253
224
  }
254
- async getBranchIds() {
255
- return await this.listBranches();
256
- }
257
225
  async close() {
258
226
  await this._writer.close();
259
227
  }
@@ -271,30 +239,10 @@ class FilePersistence {
271
239
  }
272
240
  async _loadSnapshot(dataDir) {
273
241
  const snapshotPath = join(dataDir, SNAPSHOT_NAME);
274
- try {
275
- return parseFileSnapshotV2(await readFile(snapshotPath, 'utf-8'), snapshotPath);
276
- } catch (error) {
277
- if (!isFileNotFound(error)) throw error;
278
- }
279
- const legacyArtifacts = await this._legacyArtifacts(dataDir);
280
- if (legacyArtifacts.length > 0) throw new PersistenceImportRequiredError(dataDir, legacyArtifacts);
281
- return EMPTY_FILE_SNAPSHOT_V2;
282
- }
283
- async _legacyArtifacts(dataDir) {
284
- const artifacts = [];
285
- try {
286
- await readFile(join(dataDir, 'history.json'), 'utf-8');
287
- artifacts.push('history.json');
288
- } catch (error) {
289
- if (!isFileNotFound(error)) throw error;
290
- }
291
- for (const directory of LEGACY_DIRECTORIES)try {
292
- const files = await readdir(join(dataDir, directory));
293
- artifacts.push(...files.filter((file)=>file.endsWith('.json')).map((file)=>`${directory}/${file}`));
294
- } catch (error) {
295
- if (!isFileNotFound(error)) throw error;
296
- }
297
- return artifacts.sort(compareCodePoint);
242
+ const layoutEntries = (await readdir(dataDir)).filter((entry)=>entry !== FILE_WRITER_LOCK_NAME);
243
+ if (0 === layoutEntries.length) return EMPTY_FILE_SNAPSHOT_V2;
244
+ if (1 !== layoutEntries.length || layoutEntries[0] !== SNAPSHOT_NAME) throw new PersistenceCompatibilityError(dataDir, 'directory does not match File v2 layout');
245
+ return parseFileSnapshotV2(await readFile(snapshotPath, 'utf-8'), snapshotPath);
298
246
  }
299
247
  async _measure(operation, action) {
300
248
  const startTime = Date.now();
@@ -1 +1 @@
1
- {"version":3,"file":"persistence/FilePersistence.js","sources":["../../src/persistence/FilePersistence.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { readFile, readdir } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { IMetrics } from '../contracts/interfaces.js';\nimport type {\n\tPersistenceConfig,\n\tSessionScopedPersistenceBackend,\n} from '../contracts/PersistenceBackend.js';\nimport { asSessionId, GLOBAL_SESSION_ID, type BranchId, type SessionId } from '../contracts/ids.js';\nimport type { Summary } from '../core/compression/Summary.js';\nimport type { Edge } from '../core/graph/Edge.js';\nimport type { ThoughtData } from '../core/thought.js';\nimport { PersistenceImportRequiredError } from '../errors.js';\nimport {\n\tEMPTY_FILE_SNAPSHOT_V2,\n\tparseFileSnapshotV2,\n\tserializeFileSnapshotV2,\n\tsessionsInSnapshot,\n} from './FileSnapshotV2.js';\nimport type { FileSnapshotV2 } from './FileSnapshotTypes.js';\nimport { FileWriter, isFileNotFound, type FileWriterOperations } from './FileWriter.js';\nimport {\n\tassertBranchScope,\n\tassertEdgeScopes,\n\tassertPersistableThoughtCollections,\n\tassertPersistableThoughts,\n\tassertSummaryScopes,\n\tassertThoughtScope,\n\tcompareCodePoint,\n\tparsePersistenceBranchId,\n} from './PersistenceScope.js';\n\ntype FilePersistenceOptions = NonNullable<PersistenceConfig['options']> & {\n\treadonly metrics?: IMetrics;\n\treadonly writerOperations?: FileWriterOperations;\n};\n\nconst SNAPSHOT_NAME = 'snapshot.json';\nconst LEGACY_DIRECTORIES = ['branches', 'edges', 'summaries'] as const;\n\nexport class FilePersistence implements SessionScopedPersistenceBackend {\n\tprivate readonly _dataDir: string;\n\tprivate readonly _maxHistorySize: number;\n\tprivate readonly _persistBranches: boolean;\n\tprivate readonly _metrics: IMetrics | undefined;\n\tprivate readonly _writer: FileWriter;\n\n\tconstructor(options?: FilePersistenceOptions) {\n\t\tconst defaultDataDir = existsSync('.claude/data')\n\t\t\t? '.claude/data'\n\t\t\t: join(homedir(), '.claude/data');\n\t\tthis._dataDir = options?.dataDir ?? defaultDataDir;\n\t\tthis._maxHistorySize = options?.maxHistorySize ?? 10000;\n\t\tthis._persistBranches = options?.persistBranches ?? true;\n\t\tthis._metrics = options?.metrics;\n\t\tthis._writer = new FileWriter(this._dataDir, options?.writerOperations);\n\t}\n\n\tpublic static async create(options?: FilePersistenceOptions): Promise<FilePersistence> {\n\t\tconst persistence = new FilePersistence(options);\n\t\ttry {\n\t\t\tawait persistence._writer.ready();\n\t\t\tawait persistence._writer.run(async (dataDir) => await persistence._loadSnapshot(dataDir));\n\t\t\treturn persistence;\n\t\t} catch (error) {\n\t\t\tawait persistence.close();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic async saveThought(thought: ThoughtData): Promise<void> {\n\t\tassertThoughtScope('saveThought', GLOBAL_SESSION_ID, thought);\n\t\tawait this._saveThought(GLOBAL_SESSION_ID, thought);\n\t}\n\n\tpublic async saveThoughtForSession(sessionId: SessionId, thought: ThoughtData): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertThoughtScope('saveThoughtForSession', validatedSessionId, thought);\n\t\tawait this._saveThought(validatedSessionId, thought);\n\t}\n\n\tprivate async _saveThought(sessionId: SessionId, thought: ThoughtData): Promise<void> {\n\t\tassertPersistableThoughts([thought], `${sessionId}/thoughts`);\n\t\tawait this._mutate('save_thought', (snapshot) => {\n\t\t\tconst current =\n\t\t\t\tsnapshot.thoughts.find((record) => record.sessionId === sessionId)?.thoughts ?? [];\n\t\t\tconst prospective = [...current, thought];\n\t\t\tassertPersistableThoughtCollections(\n\t\t\t\t[\n\t\t\t\t\t{ sessionId, thoughts: prospective },\n\t\t\t\t\t...snapshot.branches\n\t\t\t\t\t\t.filter((record) => record.sessionId === sessionId)\n\t\t\t\t\t\t.map((record) => ({ sessionId, thoughts: record.thoughts })),\n\t\t\t\t],\n\t\t\t\t`${sessionId}/thoughts`\n\t\t\t);\n\t\t\tconst retained =\n\t\t\t\tthis._maxHistorySize > 0 ? prospective.slice(-this._maxHistorySize) : prospective;\n\t\t\treturn {\n\t\t\t\t...snapshot,\n\t\t\t\tthoughts: [\n\t\t\t\t\t...snapshot.thoughts.filter((record) => record.sessionId !== sessionId),\n\t\t\t\t\t{ sessionId, thoughts: retained },\n\t\t\t\t],\n\t\t\t};\n\t\t});\n\t}\n\n\tpublic async loadHistory(): Promise<ThoughtData[]> {\n\t\treturn await this.loadHistoryForSession(GLOBAL_SESSION_ID);\n\t}\n\n\tpublic async loadHistoryForSession(sessionId: SessionId): Promise<ThoughtData[]> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\treturn await this._read('load_history', (snapshot) => [\n\t\t\t...(snapshot.thoughts.find((record) => record.sessionId === validatedSessionId)?.thoughts ??\n\t\t\t\t[]),\n\t\t]);\n\t}\n\n\tpublic async saveBranch(branchId: BranchId, thoughts: ThoughtData[]): Promise<void> {\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, 'global/branches');\n\t\tassertBranchScope('saveBranch', GLOBAL_SESSION_ID, validatedBranchId, thoughts);\n\t\tawait this._saveBranch(GLOBAL_SESSION_ID, validatedBranchId, thoughts);\n\t}\n\n\tpublic async saveBranchForSession(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId,\n\t\tthoughts: readonly ThoughtData[]\n\t): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\tassertBranchScope('saveBranchForSession', validatedSessionId, validatedBranchId, thoughts);\n\t\tawait this._saveBranch(validatedSessionId, validatedBranchId, thoughts);\n\t}\n\n\tprivate async _saveBranch(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId,\n\t\tthoughts: readonly ThoughtData[]\n\t): Promise<void> {\n\t\tassertPersistableThoughtCollections(\n\t\t\t[{ sessionId, thoughts }],\n\t\t\t`${sessionId}/branches/${branchId}`\n\t\t);\n\t\tif (!this._persistBranches) {\n\t\t\tawait this._writer.run(async (dataDir) => {\n\t\t\t\tconst snapshot = await this._loadSnapshot(dataDir);\n\t\t\t\tassertPersistableThoughtCollections(\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsessionId,\n\t\t\t\t\t\t\tthoughts:\n\t\t\t\t\t\t\t\tsnapshot.thoughts.find((record) => record.sessionId === sessionId)?.thoughts ?? [],\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...snapshot.branches\n\t\t\t\t\t\t\t.filter((record) => record.sessionId === sessionId)\n\t\t\t\t\t\t\t.map((record) => ({ sessionId, thoughts: record.thoughts })),\n\t\t\t\t\t\t{ sessionId, thoughts },\n\t\t\t\t\t],\n\t\t\t\t\t`${sessionId}/branches/${branchId}`\n\t\t\t\t);\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tawait this._mutate('save_branch', (snapshot) => ({\n\t\t\t...snapshot,\n\t\t\tbranches: [\n\t\t\t\t...snapshot.branches.filter(\n\t\t\t\t\t(record) => record.sessionId !== sessionId || record.branchId !== branchId\n\t\t\t\t),\n\t\t\t\t{ sessionId, branchId, thoughts: [...thoughts] },\n\t\t\t],\n\t\t}));\n\t}\n\n\tpublic async deleteBranch(branchId: BranchId): Promise<void> {\n\t\tawait this.deleteBranchForSession(GLOBAL_SESSION_ID, branchId);\n\t}\n\n\tpublic async deleteBranchForSession(sessionId: SessionId, branchId: BranchId): Promise<void> {\n\t\tif (!this._persistBranches) return;\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\tawait this._mutate('delete_branch', (snapshot) => ({\n\t\t\t...snapshot,\n\t\t\tbranches: snapshot.branches.filter(\n\t\t\t\t(record) => record.sessionId !== validatedSessionId || record.branchId !== validatedBranchId\n\t\t\t),\n\t\t}));\n\t}\n\n\tpublic async loadBranch(branchId: BranchId): Promise<ThoughtData[] | undefined> {\n\t\treturn await this.loadBranchForSession(GLOBAL_SESSION_ID, branchId);\n\t}\n\n\tpublic async loadBranchForSession(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId\n\t): Promise<ThoughtData[] | undefined> {\n\t\tif (!this._persistBranches) return undefined;\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\treturn await this._read('load_branch', (snapshot) => {\n\t\t\tconst thoughts = snapshot.branches.find(\n\t\t\t\t(record) => record.sessionId === validatedSessionId && record.branchId === validatedBranchId\n\t\t\t)?.thoughts;\n\t\t\treturn thoughts === undefined ? undefined : [...thoughts];\n\t\t});\n\t}\n\n\tpublic async listBranches(): Promise<BranchId[]> {\n\t\treturn await this.listBranchesForSession(GLOBAL_SESSION_ID);\n\t}\n\n\tpublic async listBranchesForSession(sessionId: SessionId): Promise<BranchId[]> {\n\t\tif (!this._persistBranches) return [];\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\treturn await this._read('list_branches', (snapshot) =>\n\t\t\tsnapshot.branches\n\t\t\t\t.filter((record) => record.sessionId === validatedSessionId)\n\t\t\t\t.map((record) => record.branchId)\n\t\t\t\t.sort(compareCodePoint)\n\t\t);\n\t}\n\n\tpublic async listSessions(): Promise<SessionId[]> {\n\t\treturn await this._read('list_sessions', sessionsInSnapshot);\n\t}\n\n\tpublic async clear(): Promise<void> {\n\t\tawait this._mutate('clear', () => EMPTY_FILE_SNAPSHOT_V2);\n\t}\n\n\tpublic async clearSession(sessionId: SessionId): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tawait this._mutate('clear_session', (snapshot) => ({\n\t\t\tversion: 2,\n\t\t\tthoughts: snapshot.thoughts.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\tbranches: snapshot.branches.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\tedges: snapshot.edges.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\tsummaries: snapshot.summaries.filter((record) => record.sessionId !== validatedSessionId),\n\t\t}));\n\t}\n\n\tpublic async saveEdges(sessionId: SessionId, edges: readonly Edge[]): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertEdgeScopes(validatedSessionId, edges);\n\t\tawait this._mutate('save_edges', (snapshot) => ({\n\t\t\t...snapshot,\n\t\t\tedges: [\n\t\t\t\t...snapshot.edges.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\t\t...(edges.length === 0 ? [] : [{ sessionId: validatedSessionId, edges: [...edges] }]),\n\t\t\t],\n\t\t}));\n\t}\n\n\tpublic async loadEdges(sessionId: SessionId): Promise<Edge[]> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\treturn await this._read('load_edges', (snapshot) => [\n\t\t\t...(snapshot.edges.find((record) => record.sessionId === validatedSessionId)?.edges ?? []),\n\t\t]);\n\t}\n\n\tpublic async listEdgeSessions(): Promise<SessionId[]> {\n\t\treturn await this._read('list_edge_sessions', (snapshot) =>\n\t\t\tsnapshot.edges.map((record) => record.sessionId).sort(compareCodePoint)\n\t\t);\n\t}\n\n\tpublic async saveSummaries(sessionId: SessionId, summaries: readonly Summary[]): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertSummaryScopes(validatedSessionId, summaries);\n\t\tawait this._mutate('save_summaries', (snapshot) => ({\n\t\t\t...snapshot,\n\t\t\tsummaries: [\n\t\t\t\t...snapshot.summaries.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\t\t...(summaries.length === 0\n\t\t\t\t\t? []\n\t\t\t\t\t: [{ sessionId: validatedSessionId, summaries: [...summaries] }]),\n\t\t\t],\n\t\t}));\n\t}\n\n\tpublic async loadSummaries(sessionId: SessionId): Promise<Summary[]> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\treturn await this._read('load_summaries', (snapshot) => [\n\t\t\t...(snapshot.summaries.find((record) => record.sessionId === validatedSessionId)?.summaries ??\n\t\t\t\t[]),\n\t\t]);\n\t}\n\n\tpublic async healthy(): Promise<boolean> {\n\t\ttry {\n\t\t\tawait this._writer.run(async (dataDir) => await this._loadSnapshot(dataDir));\n\t\t\treturn true;\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error) return false;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic getDataDir(): string {\n\t\treturn this._dataDir;\n\t}\n\n\tpublic async getBranchIds(): Promise<string[]> {\n\t\treturn await this.listBranches();\n\t}\n\n\tpublic async close(): Promise<void> {\n\t\tawait this._writer.close();\n\t}\n\n\tprivate async _read<T>(operation: string, select: (snapshot: FileSnapshotV2) => T): Promise<T> {\n\t\treturn await this._measure(\n\t\t\toperation,\n\t\t\tasync () =>\n\t\t\t\tawait this._writer.run(async (dataDir) => select(await this._loadSnapshot(dataDir)))\n\t\t);\n\t}\n\n\tprivate async _mutate(\n\t\toperation: string,\n\t\tmutate: (snapshot: FileSnapshotV2) => FileSnapshotV2\n\t): Promise<void> {\n\t\tawait this._measure(operation, async () => {\n\t\t\tawait this._writer.run(async (dataDir) => {\n\t\t\t\tconst snapshotPath = join(dataDir, SNAPSHOT_NAME);\n\t\t\t\tconst updated = mutate(await this._loadSnapshot(dataDir));\n\t\t\t\tawait this._writer.publish(snapshotPath, serializeFileSnapshotV2(updated, snapshotPath));\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate async _loadSnapshot(dataDir: string): Promise<FileSnapshotV2> {\n\t\tconst snapshotPath = join(dataDir, SNAPSHOT_NAME);\n\t\ttry {\n\t\t\treturn parseFileSnapshotV2(await readFile(snapshotPath, 'utf-8'), snapshotPath);\n\t\t} catch (error) {\n\t\t\tif (!isFileNotFound(error)) throw error;\n\t\t}\n\t\tconst legacyArtifacts = await this._legacyArtifacts(dataDir);\n\t\tif (legacyArtifacts.length > 0) {\n\t\t\tthrow new PersistenceImportRequiredError(dataDir, legacyArtifacts);\n\t\t}\n\t\treturn EMPTY_FILE_SNAPSHOT_V2;\n\t}\n\n\tprivate async _legacyArtifacts(dataDir: string): Promise<string[]> {\n\t\tconst artifacts: string[] = [];\n\t\ttry {\n\t\t\tawait readFile(join(dataDir, 'history.json'), 'utf-8');\n\t\t\tartifacts.push('history.json');\n\t\t} catch (error) {\n\t\t\tif (!isFileNotFound(error)) throw error;\n\t\t}\n\t\tfor (const directory of LEGACY_DIRECTORIES) {\n\t\t\ttry {\n\t\t\t\tconst files = await readdir(join(dataDir, directory));\n\t\t\t\tartifacts.push(\n\t\t\t\t\t...files.filter((file) => file.endsWith('.json')).map((file) => `${directory}/${file}`)\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tif (!isFileNotFound(error)) throw error;\n\t\t\t}\n\t\t}\n\t\treturn artifacts.sort(compareCodePoint);\n\t}\n\n\tprivate async _measure<T>(operation: string, action: () => Promise<T>): Promise<T> {\n\t\tconst startTime = Date.now();\n\t\ttry {\n\t\t\treturn await action();\n\t\t} finally {\n\t\t\tthis._metrics?.histogram('persistence_op_duration_seconds', (Date.now() - startTime) / 1000, {\n\t\t\t\toperation,\n\t\t\t});\n\t\t}\n\t}\n}\n"],"names":["SNAPSHOT_NAME","LEGACY_DIRECTORIES","FilePersistence","options","defaultDataDir","existsSync","join","homedir","FileWriter","persistence","dataDir","error","thought","assertThoughtScope","GLOBAL_SESSION_ID","sessionId","validatedSessionId","asSessionId","assertPersistableThoughts","snapshot","current","record","prospective","assertPersistableThoughtCollections","retained","branchId","thoughts","validatedBranchId","parsePersistenceBranchId","assertBranchScope","undefined","compareCodePoint","sessionsInSnapshot","EMPTY_FILE_SNAPSHOT_V2","edges","assertEdgeScopes","summaries","assertSummaryScopes","Error","operation","select","mutate","snapshotPath","updated","serializeFileSnapshotV2","parseFileSnapshotV2","readFile","isFileNotFound","legacyArtifacts","PersistenceImportRequiredError","artifacts","directory","files","readdir","file","action","startTime","Date"],"mappings":"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"}
1
+ {"version":3,"file":"persistence/FilePersistence.js","sources":["../../src/persistence/FilePersistence.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { readFile, readdir } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { IMetrics } from '../contracts/interfaces.js';\nimport type {\n\tPersistenceConfig,\n\tPersistenceBackend,\n} from '../contracts/PersistenceBackend.js';\nimport { asSessionId, type BranchId, type SessionId } from '../contracts/ids.js';\nimport type { Summary } from '../core/compression/Summary.js';\nimport type { Edge } from '../core/graph/Edge.js';\nimport type { ThoughtData } from '../core/thought.js';\nimport { PersistenceCompatibilityError } from '../errors.js';\nimport {\n\tEMPTY_FILE_SNAPSHOT_V2,\n\tparseFileSnapshotV2,\n\tserializeFileSnapshotV2,\n\tsessionsInSnapshot,\n} from './FileSnapshotV2.js';\nimport type { FileSnapshotV2 } from './FileSnapshotTypes.js';\nimport {\n\tFILE_WRITER_LOCK_NAME,\n\tFileWriter,\n\ttype FileWriterOperations,\n} from './FileWriter.js';\nimport {\n\tassertBranchScope,\n\tassertEdgeScopes,\n\tassertPersistableThoughtCollections,\n\tassertPersistableThoughts,\n\tassertSummaryScopes,\n\tassertThoughtScope,\n\tcompareCodePoint,\n\tparsePersistenceBranchId,\n} from './PersistenceScope.js';\n\ntype FilePersistenceOptions = NonNullable<PersistenceConfig['options']> & {\n\treadonly metrics?: IMetrics;\n\treadonly writerOperations?: FileWriterOperations;\n};\n\nconst SNAPSHOT_NAME = 'snapshot.json';\n\nexport class FilePersistence implements PersistenceBackend {\n\tprivate readonly _dataDir: string;\n\tprivate readonly _maxHistorySize: number;\n\tprivate readonly _persistBranches: boolean;\n\tprivate readonly _metrics: IMetrics | undefined;\n\tprivate readonly _writer: FileWriter;\n\n\tconstructor(options?: FilePersistenceOptions) {\n\t\tconst defaultDataDir = existsSync('.claude/data')\n\t\t\t? '.claude/data'\n\t\t\t: join(homedir(), '.claude/data');\n\t\tthis._dataDir = options?.dataDir ?? defaultDataDir;\n\t\tthis._maxHistorySize = options?.maxHistorySize ?? 10000;\n\t\tthis._persistBranches = options?.persistBranches ?? true;\n\t\tthis._metrics = options?.metrics;\n\t\tthis._writer = new FileWriter(this._dataDir, options?.writerOperations);\n\t}\n\n\tpublic static async create(options?: FilePersistenceOptions): Promise<FilePersistence> {\n\t\tconst persistence = new FilePersistence(options);\n\t\ttry {\n\t\t\tawait persistence._writer.ready();\n\t\t\tawait persistence._writer.run(async (dataDir) => await persistence._loadSnapshot(dataDir));\n\t\t\treturn persistence;\n\t\t} catch (error) {\n\t\t\tawait persistence.close();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic async saveThoughtForSession(sessionId: SessionId, thought: ThoughtData): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertThoughtScope('saveThoughtForSession', validatedSessionId, thought);\n\t\tawait this._saveThought(validatedSessionId, thought);\n\t}\n\n\tprivate async _saveThought(sessionId: SessionId, thought: ThoughtData): Promise<void> {\n\t\tassertPersistableThoughts([thought], `${sessionId}/thoughts`);\n\t\tawait this._mutate('save_thought', (snapshot) => {\n\t\t\tconst current =\n\t\t\t\tsnapshot.thoughts.find((record) => record.sessionId === sessionId)?.thoughts ?? [];\n\t\t\tconst prospective = [...current, thought];\n\t\t\tassertPersistableThoughtCollections(\n\t\t\t\t[\n\t\t\t\t\t{ sessionId, thoughts: prospective },\n\t\t\t\t\t...snapshot.branches\n\t\t\t\t\t\t.filter((record) => record.sessionId === sessionId)\n\t\t\t\t\t\t.map((record) => ({ sessionId, thoughts: record.thoughts })),\n\t\t\t\t],\n\t\t\t\t`${sessionId}/thoughts`\n\t\t\t);\n\t\t\tconst retained =\n\t\t\t\tthis._maxHistorySize > 0 ? prospective.slice(-this._maxHistorySize) : prospective;\n\t\t\treturn {\n\t\t\t\t...snapshot,\n\t\t\t\tthoughts: [\n\t\t\t\t\t...snapshot.thoughts.filter((record) => record.sessionId !== sessionId),\n\t\t\t\t\t{ sessionId, thoughts: retained },\n\t\t\t\t],\n\t\t\t};\n\t\t});\n\t}\n\n\tpublic async loadHistoryForSession(sessionId: SessionId): Promise<ThoughtData[]> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\treturn await this._read('load_history', (snapshot) => [\n\t\t\t...(snapshot.thoughts.find((record) => record.sessionId === validatedSessionId)?.thoughts ??\n\t\t\t\t[]),\n\t\t]);\n\t}\n\n\tpublic async saveBranchForSession(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId,\n\t\tthoughts: readonly ThoughtData[]\n\t): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\tassertBranchScope('saveBranchForSession', validatedSessionId, validatedBranchId, thoughts);\n\t\tawait this._saveBranch(validatedSessionId, validatedBranchId, thoughts);\n\t}\n\n\tprivate async _saveBranch(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId,\n\t\tthoughts: readonly ThoughtData[]\n\t): Promise<void> {\n\t\tassertPersistableThoughtCollections(\n\t\t\t[{ sessionId, thoughts }],\n\t\t\t`${sessionId}/branches/${branchId}`\n\t\t);\n\t\tif (!this._persistBranches) {\n\t\t\tawait this._writer.run(async (dataDir) => {\n\t\t\t\tconst snapshot = await this._loadSnapshot(dataDir);\n\t\t\t\tassertPersistableThoughtCollections(\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsessionId,\n\t\t\t\t\t\t\tthoughts:\n\t\t\t\t\t\t\t\tsnapshot.thoughts.find((record) => record.sessionId === sessionId)?.thoughts ?? [],\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...snapshot.branches\n\t\t\t\t\t\t\t.filter((record) => record.sessionId === sessionId)\n\t\t\t\t\t\t\t.map((record) => ({ sessionId, thoughts: record.thoughts })),\n\t\t\t\t\t\t{ sessionId, thoughts },\n\t\t\t\t\t],\n\t\t\t\t\t`${sessionId}/branches/${branchId}`\n\t\t\t\t);\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tawait this._mutate('save_branch', (snapshot) => ({\n\t\t\t...snapshot,\n\t\t\tbranches: [\n\t\t\t\t...snapshot.branches.filter(\n\t\t\t\t\t(record) => record.sessionId !== sessionId || record.branchId !== branchId\n\t\t\t\t),\n\t\t\t\t{ sessionId, branchId, thoughts: [...thoughts] },\n\t\t\t],\n\t\t}));\n\t}\n\n\tpublic async deleteBranchForSession(sessionId: SessionId, branchId: BranchId): Promise<void> {\n\t\tif (!this._persistBranches) return;\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\tawait this._mutate('delete_branch', (snapshot) => ({\n\t\t\t...snapshot,\n\t\t\tbranches: snapshot.branches.filter(\n\t\t\t\t(record) => record.sessionId !== validatedSessionId || record.branchId !== validatedBranchId\n\t\t\t),\n\t\t}));\n\t}\n\n\tpublic async loadBranchForSession(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId\n\t): Promise<ThoughtData[] | undefined> {\n\t\tif (!this._persistBranches) return undefined;\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\treturn await this._read('load_branch', (snapshot) => {\n\t\t\tconst thoughts = snapshot.branches.find(\n\t\t\t\t(record) => record.sessionId === validatedSessionId && record.branchId === validatedBranchId\n\t\t\t)?.thoughts;\n\t\t\treturn thoughts === undefined ? undefined : [...thoughts];\n\t\t});\n\t}\n\n\tpublic async listBranchesForSession(sessionId: SessionId): Promise<BranchId[]> {\n\t\tif (!this._persistBranches) return [];\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\treturn await this._read('list_branches', (snapshot) =>\n\t\t\tsnapshot.branches\n\t\t\t\t.filter((record) => record.sessionId === validatedSessionId)\n\t\t\t\t.map((record) => record.branchId)\n\t\t\t\t.sort(compareCodePoint)\n\t\t);\n\t}\n\n\tpublic async listSessions(): Promise<SessionId[]> {\n\t\treturn await this._read('list_sessions', sessionsInSnapshot);\n\t}\n\n\tpublic async clearAll(): Promise<void> {\n\t\tawait this._mutate('clear_all', () => EMPTY_FILE_SNAPSHOT_V2);\n\t}\n\n\tpublic async clearSession(sessionId: SessionId): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tawait this._mutate('clear_session', (snapshot) => ({\n\t\t\tversion: 2,\n\t\t\tthoughts: snapshot.thoughts.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\tbranches: snapshot.branches.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\tedges: snapshot.edges.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\tsummaries: snapshot.summaries.filter((record) => record.sessionId !== validatedSessionId),\n\t\t}));\n\t}\n\n\tpublic async saveEdges(sessionId: SessionId, edges: readonly Edge[]): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertEdgeScopes(validatedSessionId, edges);\n\t\tawait this._mutate('save_edges', (snapshot) => ({\n\t\t\t...snapshot,\n\t\t\tedges: [\n\t\t\t\t...snapshot.edges.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\t\t...(edges.length === 0 ? [] : [{ sessionId: validatedSessionId, edges: [...edges] }]),\n\t\t\t],\n\t\t}));\n\t}\n\n\tpublic async loadEdges(sessionId: SessionId): Promise<Edge[]> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\treturn await this._read('load_edges', (snapshot) => [\n\t\t\t...(snapshot.edges.find((record) => record.sessionId === validatedSessionId)?.edges ?? []),\n\t\t]);\n\t}\n\n\tpublic async saveSummaries(sessionId: SessionId, summaries: readonly Summary[]): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertSummaryScopes(validatedSessionId, summaries);\n\t\tawait this._mutate('save_summaries', (snapshot) => ({\n\t\t\t...snapshot,\n\t\t\tsummaries: [\n\t\t\t\t...snapshot.summaries.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\t\t...(summaries.length === 0\n\t\t\t\t\t? []\n\t\t\t\t\t: [{ sessionId: validatedSessionId, summaries: [...summaries] }]),\n\t\t\t],\n\t\t}));\n\t}\n\n\tpublic async loadSummaries(sessionId: SessionId): Promise<Summary[]> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\treturn await this._read('load_summaries', (snapshot) => [\n\t\t\t...(snapshot.summaries.find((record) => record.sessionId === validatedSessionId)?.summaries ??\n\t\t\t\t[]),\n\t\t]);\n\t}\n\n\tpublic async healthy(): Promise<boolean> {\n\t\ttry {\n\t\t\tawait this._writer.run(async (dataDir) => await this._loadSnapshot(dataDir));\n\t\t\treturn true;\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error) return false;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic getDataDir(): string {\n\t\treturn this._dataDir;\n\t}\n\n\tpublic async close(): Promise<void> {\n\t\tawait this._writer.close();\n\t}\n\n\tprivate async _read<T>(operation: string, select: (snapshot: FileSnapshotV2) => T): Promise<T> {\n\t\treturn await this._measure(\n\t\t\toperation,\n\t\t\tasync () =>\n\t\t\t\tawait this._writer.run(async (dataDir) => select(await this._loadSnapshot(dataDir)))\n\t\t);\n\t}\n\n\tprivate async _mutate(\n\t\toperation: string,\n\t\tmutate: (snapshot: FileSnapshotV2) => FileSnapshotV2\n\t): Promise<void> {\n\t\tawait this._measure(operation, async () => {\n\t\t\tawait this._writer.run(async (dataDir) => {\n\t\t\t\tconst snapshotPath = join(dataDir, SNAPSHOT_NAME);\n\t\t\t\tconst updated = mutate(await this._loadSnapshot(dataDir));\n\t\t\t\tawait this._writer.publish(snapshotPath, serializeFileSnapshotV2(updated, snapshotPath));\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate async _loadSnapshot(dataDir: string): Promise<FileSnapshotV2> {\n\t\tconst snapshotPath = join(dataDir, SNAPSHOT_NAME);\n\t\tconst layoutEntries = (await readdir(dataDir)).filter(\n\t\t\t(entry) => entry !== FILE_WRITER_LOCK_NAME\n\t\t);\n\t\tif (layoutEntries.length === 0) return EMPTY_FILE_SNAPSHOT_V2;\n\t\tif (layoutEntries.length !== 1 || layoutEntries[0] !== SNAPSHOT_NAME) {\n\t\t\tthrow new PersistenceCompatibilityError(\n\t\t\t\tdataDir,\n\t\t\t\t'directory does not match File v2 layout'\n\t\t\t);\n\t\t}\n\t\treturn parseFileSnapshotV2(await readFile(snapshotPath, 'utf-8'), snapshotPath);\n\t}\n\n\tprivate async _measure<T>(operation: string, action: () => Promise<T>): Promise<T> {\n\t\tconst startTime = Date.now();\n\t\ttry {\n\t\t\treturn await action();\n\t\t} finally {\n\t\t\tthis._metrics?.histogram('persistence_op_duration_seconds', (Date.now() - startTime) / 1000, {\n\t\t\t\toperation,\n\t\t\t});\n\t\t}\n\t}\n}\n"],"names":["SNAPSHOT_NAME","FilePersistence","options","defaultDataDir","existsSync","join","homedir","FileWriter","persistence","dataDir","error","sessionId","thought","validatedSessionId","asSessionId","assertThoughtScope","assertPersistableThoughts","snapshot","current","record","prospective","assertPersistableThoughtCollections","retained","branchId","thoughts","validatedBranchId","parsePersistenceBranchId","assertBranchScope","undefined","compareCodePoint","sessionsInSnapshot","EMPTY_FILE_SNAPSHOT_V2","edges","assertEdgeScopes","summaries","assertSummaryScopes","Error","operation","select","mutate","snapshotPath","updated","serializeFileSnapshotV2","layoutEntries","readdir","entry","FILE_WRITER_LOCK_NAME","PersistenceCompatibilityError","parseFileSnapshotV2","readFile","action","startTime","Date"],"mappings":"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"}
@@ -159,7 +159,7 @@ export declare const FileSnapshotV2Schema: v.StrictObjectSchema<{
159
159
  readonly merge_branch_ids: v.OptionalSchema<v.SchemaWithPipe<readonly [v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MaxLengthAction<string, 50, undefined>]>, undefined>, v.DescriptionAction<string[], "Branch IDs being merged into current context">]>, undefined>;
160
160
  readonly meta_observation: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.DescriptionAction<string, "Metacognitive observation about reasoning process">]>, undefined>;
161
161
  readonly reasoning_depth: v.OptionalSchema<v.SchemaWithPipe<readonly [v.PicklistSchema<["shallow", "moderate", "deep"], undefined>, v.DescriptionAction<"shallow" | "moderate" | "deep", "Effort signal: how deep reasoning should go">]>, undefined>;
162
- readonly session_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "Session ID must contain only letters, numbers, hyphens, and underscores">, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 100, undefined>, v.DescriptionAction<string, "Optional session identifier for state isolation. When provided, thought history, branches, and statistics are scoped to this session. Omitting preserves global behavior.">]>, undefined>;
162
+ readonly session_id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "Session ID must contain only letters, numbers, hyphens, and underscores">, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 100, undefined>, v.NotValueAction<string, "__global__", "Session ID '__global__' is retired; use an explicit named session">, v.DescriptionAction<string, "Required session identifier for state isolation. Thought history, branches, and statistics are scoped to this explicit named session.">]>;
163
163
  readonly reset_state: v.OptionalSchema<v.SchemaWithPipe<readonly [v.BooleanSchema<undefined>, v.DescriptionAction<boolean, "When true, clears all state for the target session before processing this thought. The thought is then processed as the first in a fresh session.">]>, undefined>;
164
164
  readonly tool_name: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.DescriptionAction<string, "Name of the tool being invoked (for tool_call thoughts)">]>, undefined>;
165
165
  readonly tool_arguments: v.OptionalSchema<v.SchemaWithPipe<readonly [v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, v.DescriptionAction<{
@@ -328,7 +328,7 @@ export declare const FileSnapshotV2Schema: v.StrictObjectSchema<{
328
328
  readonly merge_branch_ids: v.OptionalSchema<v.SchemaWithPipe<readonly [v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MaxLengthAction<string, 50, undefined>]>, undefined>, v.DescriptionAction<string[], "Branch IDs being merged into current context">]>, undefined>;
329
329
  readonly meta_observation: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.DescriptionAction<string, "Metacognitive observation about reasoning process">]>, undefined>;
330
330
  readonly reasoning_depth: v.OptionalSchema<v.SchemaWithPipe<readonly [v.PicklistSchema<["shallow", "moderate", "deep"], undefined>, v.DescriptionAction<"shallow" | "moderate" | "deep", "Effort signal: how deep reasoning should go">]>, undefined>;
331
- readonly session_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "Session ID must contain only letters, numbers, hyphens, and underscores">, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 100, undefined>, v.DescriptionAction<string, "Optional session identifier for state isolation. When provided, thought history, branches, and statistics are scoped to this session. Omitting preserves global behavior.">]>, undefined>;
331
+ readonly session_id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "Session ID must contain only letters, numbers, hyphens, and underscores">, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 100, undefined>, v.NotValueAction<string, "__global__", "Session ID '__global__' is retired; use an explicit named session">, v.DescriptionAction<string, "Required session identifier for state isolation. Thought history, branches, and statistics are scoped to this explicit named session.">]>;
332
332
  readonly reset_state: v.OptionalSchema<v.SchemaWithPipe<readonly [v.BooleanSchema<undefined>, v.DescriptionAction<boolean, "When true, clears all state for the target session before processing this thought. The thought is then processed as the first in a fresh session.">]>, undefined>;
333
333
  readonly tool_name: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.DescriptionAction<string, "Name of the tool being invoked (for tool_call thoughts)">]>, undefined>;
334
334
  readonly tool_arguments: v.OptionalSchema<v.SchemaWithPipe<readonly [v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, v.DescriptionAction<{
@@ -1,4 +1,4 @@
1
- import { GLOBAL_SESSION_ID, asSessionId } from "../contracts/ids.js";
1
+ import { asSessionId } from "../contracts/ids.js";
2
2
  import { SummarySchema } from "../core/compression/Summary.js";
3
3
  import { PersistenceCompatibilityError, PersistenceCorruptionError } from "../errors.js";
4
4
  import { EdgeSchema, SequentialThinkingSchema } from "../schema.js";
@@ -117,7 +117,7 @@ function sessionsInSnapshot(snapshot) {
117
117
  ].sort(compareCodePoint);
118
118
  }
119
119
  function sessionForThought(thought) {
120
- return thought.session_id ?? GLOBAL_SESSION_ID;
120
+ return asSessionId(thought.session_id);
121
121
  }
122
122
  export { EMPTY_FILE_SNAPSHOT_V2, FileSnapshotV2Schema, parseFileSnapshotV2, serializeFileSnapshotV2, sessionForThought, sessionsInSnapshot };
123
123
 
@@ -1 +1 @@
1
- {"version":3,"file":"persistence/FileSnapshotV2.js","sources":["../../src/persistence/FileSnapshotV2.ts"],"sourcesContent":["import * as v from 'valibot';\nimport type { SessionId } from '../contracts/ids.js';\nimport { asSessionId, GLOBAL_SESSION_ID } from '../contracts/ids.js';\nimport { SummarySchema } from '../core/compression/Summary.js';\nimport type { ThoughtData } from '../core/thought.js';\nimport { PersistenceCompatibilityError, PersistenceCorruptionError } from '../errors.js';\nimport { EdgeSchema, SequentialThinkingSchema } from '../schema.js';\nimport { parseEdge, parseSummary, parseThoughtData } from './PersistenceCodec.js';\nimport type { FileSnapshotV2 } from './FileSnapshotTypes.js';\nimport {\n\tcompareCodePoint,\n\tcompareCreatedThenId,\n\tparsePersistenceBranchId,\n} from './PersistenceScope.js';\nimport { validateFileSnapshotV2 } from './FileSnapshotValidation.js';\n\nconst SessionIdStringSchema = v.pipe(v.string(), v.regex(/^[A-Za-z0-9_-]{1,100}$/));\nconst BranchIdStringSchema = v.pipe(v.string(), v.regex(/^[A-Za-z0-9_-]{1,50}$/));\nconst ThoughtSessionV2Schema = v.strictObject({\n\tsessionId: SessionIdStringSchema,\n\tthoughts: v.array(SequentialThinkingSchema),\n});\nconst BranchRecordV2Schema = v.strictObject({\n\tsessionId: SessionIdStringSchema,\n\tbranchId: BranchIdStringSchema,\n\tthoughts: v.array(SequentialThinkingSchema),\n});\nconst EdgeSessionV2Schema = v.strictObject({\n\tsessionId: SessionIdStringSchema,\n\tedges: v.array(EdgeSchema),\n});\nconst SummarySessionV2Schema = v.strictObject({\n\tsessionId: SessionIdStringSchema,\n\tsummaries: v.array(SummarySchema),\n});\n\nexport const FileSnapshotV2Schema = v.strictObject({\n\tversion: v.literal(2),\n\tthoughts: v.array(ThoughtSessionV2Schema),\n\tbranches: v.array(BranchRecordV2Schema),\n\tedges: v.array(EdgeSessionV2Schema),\n\tsummaries: v.array(SummarySessionV2Schema),\n});\n\nexport const EMPTY_FILE_SNAPSHOT_V2: FileSnapshotV2 = {\n\tversion: 2,\n\tthoughts: [],\n\tbranches: [],\n\tedges: [],\n\tsummaries: [],\n};\n\nexport function parseFileSnapshotV2(content: string, sourcePath: string): FileSnapshotV2 {\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(content);\n\t} catch (error) {\n\t\tthrow new PersistenceCorruptionError(sourcePath, error);\n\t}\n\ttry {\n\t\tconst parsed = v.parse(FileSnapshotV2Schema, raw);\n\t\tconst snapshot: FileSnapshotV2 = {\n\t\t\tversion: 2,\n\t\t\tthoughts: parsed.thoughts.map((record) => ({\n\t\t\t\tsessionId: asSessionId(record.sessionId),\n\t\t\t\tthoughts: record.thoughts.map((thought) => parseThoughtData(thought, sourcePath)),\n\t\t\t})),\n\t\t\tbranches: parsed.branches.map((record) => ({\n\t\t\t\tsessionId: asSessionId(record.sessionId),\n\t\t\t\tbranchId: parsePersistenceBranchId(record.branchId, sourcePath),\n\t\t\t\tthoughts: record.thoughts.map((thought) => parseThoughtData(thought, sourcePath)),\n\t\t\t})),\n\t\t\tedges: parsed.edges.map((record) => ({\n\t\t\t\tsessionId: asSessionId(record.sessionId),\n\t\t\t\tedges: record.edges.map(parseEdge),\n\t\t\t})),\n\t\t\tsummaries: parsed.summaries.map((record) => ({\n\t\t\t\tsessionId: asSessionId(record.sessionId),\n\t\t\t\tsummaries: record.summaries.map((summary) => parseSummary(summary, sourcePath)),\n\t\t\t})),\n\t\t};\n\t\tvalidateFileSnapshotV2(snapshot, sourcePath);\n\t\treturn snapshot;\n\t} catch (error) {\n\t\tif (error instanceof PersistenceCompatibilityError) throw error;\n\t\tthrow new PersistenceCompatibilityError(sourcePath, 'document does not match File v2', error);\n\t}\n}\n\nexport function serializeFileSnapshotV2(snapshot: FileSnapshotV2, sourcePath: string): string {\n\tconst canonical: FileSnapshotV2 = {\n\t\tversion: 2,\n\t\tthoughts: [...snapshot.thoughts].sort((left, right) =>\n\t\t\tcompareCodePoint(left.sessionId, right.sessionId)\n\t\t),\n\t\tbranches: [...snapshot.branches].sort(\n\t\t\t(left, right) =>\n\t\t\t\tcompareCodePoint(left.sessionId, right.sessionId) ||\n\t\t\t\tcompareCodePoint(left.branchId, right.branchId)\n\t\t),\n\t\tedges: [...snapshot.edges]\n\t\t\t.sort((left, right) => compareCodePoint(left.sessionId, right.sessionId))\n\t\t\t.map((record) => ({ ...record, edges: [...record.edges].sort(compareCreatedThenId) })),\n\t\tsummaries: [...snapshot.summaries]\n\t\t\t.sort((left, right) => compareCodePoint(left.sessionId, right.sessionId))\n\t\t\t.map((record) => ({\n\t\t\t\t...record,\n\t\t\t\tsummaries: [...record.summaries].sort(compareCreatedThenId),\n\t\t\t})),\n\t};\n\tvalidateFileSnapshotV2(canonical, sourcePath);\n\treturn `${JSON.stringify(canonical, null, 2)}\\n`;\n}\n\nexport function sessionsInSnapshot(snapshot: FileSnapshotV2): SessionId[] {\n\tconst sessions = new Set<SessionId>();\n\tfor (const records of [\n\t\tsnapshot.thoughts,\n\t\tsnapshot.branches,\n\t\tsnapshot.edges,\n\t\tsnapshot.summaries,\n\t]) {\n\t\tfor (const record of records) sessions.add(record.sessionId);\n\t}\n\treturn [...sessions].sort(compareCodePoint);\n}\n\nexport function sessionForThought(thought: ThoughtData): SessionId {\n\treturn thought.session_id ?? GLOBAL_SESSION_ID;\n}\n"],"names":["SessionIdStringSchema","v","BranchIdStringSchema","ThoughtSessionV2Schema","SequentialThinkingSchema","BranchRecordV2Schema","EdgeSessionV2Schema","EdgeSchema","SummarySessionV2Schema","SummarySchema","FileSnapshotV2Schema","EMPTY_FILE_SNAPSHOT_V2","parseFileSnapshotV2","content","sourcePath","raw","JSON","error","PersistenceCorruptionError","parsed","snapshot","record","asSessionId","thought","parseThoughtData","parsePersistenceBranchId","parseEdge","summary","parseSummary","validateFileSnapshotV2","PersistenceCompatibilityError","serializeFileSnapshotV2","canonical","left","right","compareCodePoint","compareCreatedThenId","sessionsInSnapshot","sessions","Set","records","sessionForThought","GLOBAL_SESSION_ID"],"mappings":"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"}
1
+ {"version":3,"file":"persistence/FileSnapshotV2.js","sources":["../../src/persistence/FileSnapshotV2.ts"],"sourcesContent":["import * as v from 'valibot';\nimport type { SessionId } from '../contracts/ids.js';\nimport { asSessionId } from '../contracts/ids.js';\nimport { SummarySchema } from '../core/compression/Summary.js';\nimport type { ThoughtData } from '../core/thought.js';\nimport { PersistenceCompatibilityError, PersistenceCorruptionError } from '../errors.js';\nimport { EdgeSchema, SequentialThinkingSchema } from '../schema.js';\nimport { parseEdge, parseSummary, parseThoughtData } from './PersistenceCodec.js';\nimport type { FileSnapshotV2 } from './FileSnapshotTypes.js';\nimport {\n\tcompareCodePoint,\n\tcompareCreatedThenId,\n\tparsePersistenceBranchId,\n} from './PersistenceScope.js';\nimport { validateFileSnapshotV2 } from './FileSnapshotValidation.js';\n\nconst SessionIdStringSchema = v.pipe(v.string(), v.regex(/^[A-Za-z0-9_-]{1,100}$/));\nconst BranchIdStringSchema = v.pipe(v.string(), v.regex(/^[A-Za-z0-9_-]{1,50}$/));\nconst ThoughtSessionV2Schema = v.strictObject({\n\tsessionId: SessionIdStringSchema,\n\tthoughts: v.array(SequentialThinkingSchema),\n});\nconst BranchRecordV2Schema = v.strictObject({\n\tsessionId: SessionIdStringSchema,\n\tbranchId: BranchIdStringSchema,\n\tthoughts: v.array(SequentialThinkingSchema),\n});\nconst EdgeSessionV2Schema = v.strictObject({\n\tsessionId: SessionIdStringSchema,\n\tedges: v.array(EdgeSchema),\n});\nconst SummarySessionV2Schema = v.strictObject({\n\tsessionId: SessionIdStringSchema,\n\tsummaries: v.array(SummarySchema),\n});\n\nexport const FileSnapshotV2Schema = v.strictObject({\n\tversion: v.literal(2),\n\tthoughts: v.array(ThoughtSessionV2Schema),\n\tbranches: v.array(BranchRecordV2Schema),\n\tedges: v.array(EdgeSessionV2Schema),\n\tsummaries: v.array(SummarySessionV2Schema),\n});\n\nexport const EMPTY_FILE_SNAPSHOT_V2: FileSnapshotV2 = {\n\tversion: 2,\n\tthoughts: [],\n\tbranches: [],\n\tedges: [],\n\tsummaries: [],\n};\n\nexport function parseFileSnapshotV2(content: string, sourcePath: string): FileSnapshotV2 {\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(content);\n\t} catch (error) {\n\t\tthrow new PersistenceCorruptionError(sourcePath, error);\n\t}\n\ttry {\n\t\tconst parsed = v.parse(FileSnapshotV2Schema, raw);\n\t\tconst snapshot: FileSnapshotV2 = {\n\t\t\tversion: 2,\n\t\t\tthoughts: parsed.thoughts.map((record) => ({\n\t\t\t\tsessionId: asSessionId(record.sessionId),\n\t\t\t\tthoughts: record.thoughts.map((thought) => parseThoughtData(thought, sourcePath)),\n\t\t\t})),\n\t\t\tbranches: parsed.branches.map((record) => ({\n\t\t\t\tsessionId: asSessionId(record.sessionId),\n\t\t\t\tbranchId: parsePersistenceBranchId(record.branchId, sourcePath),\n\t\t\t\tthoughts: record.thoughts.map((thought) => parseThoughtData(thought, sourcePath)),\n\t\t\t})),\n\t\t\tedges: parsed.edges.map((record) => ({\n\t\t\t\tsessionId: asSessionId(record.sessionId),\n\t\t\t\tedges: record.edges.map(parseEdge),\n\t\t\t})),\n\t\t\tsummaries: parsed.summaries.map((record) => ({\n\t\t\t\tsessionId: asSessionId(record.sessionId),\n\t\t\t\tsummaries: record.summaries.map((summary) => parseSummary(summary, sourcePath)),\n\t\t\t})),\n\t\t};\n\t\tvalidateFileSnapshotV2(snapshot, sourcePath);\n\t\treturn snapshot;\n\t} catch (error) {\n\t\tif (error instanceof PersistenceCompatibilityError) throw error;\n\t\tthrow new PersistenceCompatibilityError(sourcePath, 'document does not match File v2', error);\n\t}\n}\n\nexport function serializeFileSnapshotV2(snapshot: FileSnapshotV2, sourcePath: string): string {\n\tconst canonical: FileSnapshotV2 = {\n\t\tversion: 2,\n\t\tthoughts: [...snapshot.thoughts].sort((left, right) =>\n\t\t\tcompareCodePoint(left.sessionId, right.sessionId)\n\t\t),\n\t\tbranches: [...snapshot.branches].sort(\n\t\t\t(left, right) =>\n\t\t\t\tcompareCodePoint(left.sessionId, right.sessionId) ||\n\t\t\t\tcompareCodePoint(left.branchId, right.branchId)\n\t\t),\n\t\tedges: [...snapshot.edges]\n\t\t\t.sort((left, right) => compareCodePoint(left.sessionId, right.sessionId))\n\t\t\t.map((record) => ({ ...record, edges: [...record.edges].sort(compareCreatedThenId) })),\n\t\tsummaries: [...snapshot.summaries]\n\t\t\t.sort((left, right) => compareCodePoint(left.sessionId, right.sessionId))\n\t\t\t.map((record) => ({\n\t\t\t\t...record,\n\t\t\t\tsummaries: [...record.summaries].sort(compareCreatedThenId),\n\t\t\t})),\n\t};\n\tvalidateFileSnapshotV2(canonical, sourcePath);\n\treturn `${JSON.stringify(canonical, null, 2)}\\n`;\n}\n\nexport function sessionsInSnapshot(snapshot: FileSnapshotV2): SessionId[] {\n\tconst sessions = new Set<SessionId>();\n\tfor (const records of [\n\t\tsnapshot.thoughts,\n\t\tsnapshot.branches,\n\t\tsnapshot.edges,\n\t\tsnapshot.summaries,\n\t]) {\n\t\tfor (const record of records) sessions.add(record.sessionId);\n\t}\n\treturn [...sessions].sort(compareCodePoint);\n}\n\nexport function sessionForThought(thought: ThoughtData): SessionId {\n\treturn asSessionId(thought.session_id);\n}\n"],"names":["SessionIdStringSchema","v","BranchIdStringSchema","ThoughtSessionV2Schema","SequentialThinkingSchema","BranchRecordV2Schema","EdgeSessionV2Schema","EdgeSchema","SummarySessionV2Schema","SummarySchema","FileSnapshotV2Schema","EMPTY_FILE_SNAPSHOT_V2","parseFileSnapshotV2","content","sourcePath","raw","JSON","error","PersistenceCorruptionError","parsed","snapshot","record","asSessionId","thought","parseThoughtData","parsePersistenceBranchId","parseEdge","summary","parseSummary","validateFileSnapshotV2","PersistenceCompatibilityError","serializeFileSnapshotV2","canonical","left","right","compareCodePoint","compareCreatedThenId","sessionsInSnapshot","sessions","Set","records","sessionForThought"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ export declare const FILE_WRITER_LOCK_NAME = ".tracelattice-writer.lock";
1
2
  export interface FileWriterOperations {
2
3
  readonly mkdir: (path: string) => Promise<void>;
3
4
  readonly mkdirExclusive: (path: string) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"FileWriter.d.ts","sourceRoot":"","sources":["../../src/persistence/FileWriter.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,QAAQ,CAAC,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,QAAQ,CAAC,kBAAkB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9E;AAED,eAAO,MAAM,wBAAwB,EAAE,oBAYtC,CAAC;AAEF,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEtD;AAkBD,qBAAa,UAAU;IACtB,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuB;IACnD,OAAO,CAAC,iBAAiB,CAA0C;IACnE,OAAO,CAAC,UAAU,CAAiC;IACnD,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,MAAM,CAAuB;gBAEzB,OAAO,EAAE,MAAM,EAAE,UAAU,GAAE,oBAA+C;IAK3E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,gBAAgB,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAgBjE,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BjE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB7B,OAAO,CAAC,aAAa;YAKP,iBAAiB;YA2BjB,yBAAyB;YAuBzB,iBAAiB;CAwB/B"}
1
+ {"version":3,"file":"FileWriter.d.ts","sourceRoot":"","sources":["../../src/persistence/FileWriter.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,qBAAqB,8BAA8B,CAAC;AAEjE,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,QAAQ,CAAC,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,QAAQ,CAAC,kBAAkB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9E;AAED,eAAO,MAAM,wBAAwB,EAAE,oBAYtC,CAAC;AAEF,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEtD;AAkBD,qBAAa,UAAU;IACtB,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuB;IACnD,OAAO,CAAC,iBAAiB,CAA0C;IACnE,OAAO,CAAC,UAAU,CAAiC;IACnD,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,MAAM,CAAuB;gBAEzB,OAAO,EAAE,MAAM,EAAE,UAAU,GAAE,oBAA+C;IAK3E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,gBAAgB,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAgBjE,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BjE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB7B,OAAO,CAAC,aAAa;YAKP,iBAAiB;YA2BjB,yBAAyB;YAuBzB,iBAAiB;CAwB/B"}
@@ -2,7 +2,7 @@ import { mkdir, realpath, rename, rmdir, unlink, writeFile } from "node:fs/promi
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { basename, dirname, join } from "node:path";
4
4
  import { PersistenceClosedError, PersistenceOwnershipError, PersistencePublicationError } from "../errors.js";
5
- const WRITER_LOCK_NAME = '.tracelattice-writer.lock';
5
+ const FILE_WRITER_LOCK_NAME = '.tracelattice-writer.lock';
6
6
  const nodeFileWriterOperations = {
7
7
  mkdir: async (path)=>{
8
8
  await mkdir(path, {
@@ -95,7 +95,7 @@ class FileWriter {
95
95
  async _acquireOwnership() {
96
96
  await this._operations.mkdir(this._configuredDataDir);
97
97
  const canonicalDataDir = await this._operations.realpath(this._configuredDataDir);
98
- const lockPath = join(canonicalDataDir, WRITER_LOCK_NAME);
98
+ const lockPath = join(canonicalDataDir, FILE_WRITER_LOCK_NAME);
99
99
  const markerName = `${process.pid}-${randomUUID()}.owner`;
100
100
  const markerPath = join(lockPath, markerName);
101
101
  try {
@@ -150,6 +150,6 @@ class FileWriter {
150
150
  }
151
151
  }
152
152
  }
153
- export { FileWriter, isFileNotFound, nodeFileWriterOperations };
153
+ export { FILE_WRITER_LOCK_NAME, FileWriter, isFileNotFound, nodeFileWriterOperations };
154
154
 
155
155
  //# sourceMappingURL=FileWriter.js.map