@git-stunts/git-warp 11.2.1 → 11.3.3

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 (111) hide show
  1. package/bin/cli/commands/check.js +2 -2
  2. package/bin/cli/commands/doctor/checks.js +12 -12
  3. package/bin/cli/commands/doctor/index.js +2 -2
  4. package/bin/cli/commands/doctor/types.js +1 -1
  5. package/bin/cli/commands/history.js +12 -5
  6. package/bin/cli/commands/install-hooks.js +5 -5
  7. package/bin/cli/commands/materialize.js +2 -2
  8. package/bin/cli/commands/patch.js +142 -0
  9. package/bin/cli/commands/path.js +4 -4
  10. package/bin/cli/commands/query.js +54 -13
  11. package/bin/cli/commands/registry.js +4 -0
  12. package/bin/cli/commands/seek.js +17 -11
  13. package/bin/cli/commands/tree.js +230 -0
  14. package/bin/cli/commands/trust.js +3 -3
  15. package/bin/cli/commands/verify-audit.js +8 -7
  16. package/bin/cli/commands/view.js +6 -5
  17. package/bin/cli/infrastructure.js +26 -12
  18. package/bin/cli/shared.js +2 -2
  19. package/bin/cli/types.js +19 -8
  20. package/bin/presenters/index.js +35 -9
  21. package/bin/presenters/json.js +14 -12
  22. package/bin/presenters/text.js +155 -33
  23. package/index.d.ts +82 -22
  24. package/package.json +3 -2
  25. package/src/domain/WarpGraph.js +4 -1
  26. package/src/domain/crdt/ORSet.js +8 -8
  27. package/src/domain/errors/EmptyMessageError.js +2 -2
  28. package/src/domain/errors/ForkError.js +1 -1
  29. package/src/domain/errors/IndexError.js +1 -1
  30. package/src/domain/errors/OperationAbortedError.js +1 -1
  31. package/src/domain/errors/QueryError.js +1 -1
  32. package/src/domain/errors/SchemaUnsupportedError.js +1 -1
  33. package/src/domain/errors/ShardCorruptionError.js +2 -2
  34. package/src/domain/errors/ShardLoadError.js +2 -2
  35. package/src/domain/errors/ShardValidationError.js +4 -4
  36. package/src/domain/errors/StorageError.js +2 -2
  37. package/src/domain/errors/SyncError.js +1 -1
  38. package/src/domain/errors/TraversalError.js +1 -1
  39. package/src/domain/errors/TrustError.js +1 -1
  40. package/src/domain/errors/WarpError.js +2 -2
  41. package/src/domain/errors/WormholeError.js +1 -1
  42. package/src/domain/services/AuditReceiptService.js +6 -6
  43. package/src/domain/services/AuditVerifierService.js +52 -38
  44. package/src/domain/services/BitmapIndexBuilder.js +3 -3
  45. package/src/domain/services/BitmapIndexReader.js +28 -19
  46. package/src/domain/services/BoundaryTransitionRecord.js +18 -17
  47. package/src/domain/services/CheckpointSerializerV5.js +17 -16
  48. package/src/domain/services/CheckpointService.js +2 -2
  49. package/src/domain/services/CommitDagTraversalService.js +13 -13
  50. package/src/domain/services/DagPathFinding.js +7 -7
  51. package/src/domain/services/DagTopology.js +1 -1
  52. package/src/domain/services/DagTraversal.js +1 -1
  53. package/src/domain/services/HealthCheckService.js +1 -1
  54. package/src/domain/services/HookInstaller.js +1 -1
  55. package/src/domain/services/HttpSyncServer.js +92 -41
  56. package/src/domain/services/IndexRebuildService.js +7 -7
  57. package/src/domain/services/IndexStalenessChecker.js +4 -3
  58. package/src/domain/services/JoinReducer.js +11 -11
  59. package/src/domain/services/LogicalTraversal.js +1 -1
  60. package/src/domain/services/MessageCodecInternal.js +1 -1
  61. package/src/domain/services/MigrationService.js +1 -1
  62. package/src/domain/services/ObserverView.js +8 -8
  63. package/src/domain/services/PatchBuilderV2.js +42 -26
  64. package/src/domain/services/ProvenanceIndex.js +1 -1
  65. package/src/domain/services/ProvenancePayload.js +1 -1
  66. package/src/domain/services/QueryBuilder.js +3 -3
  67. package/src/domain/services/StateDiff.js +14 -11
  68. package/src/domain/services/StateSerializerV5.js +2 -2
  69. package/src/domain/services/StreamingBitmapIndexBuilder.js +26 -24
  70. package/src/domain/services/SyncAuthService.js +3 -2
  71. package/src/domain/services/SyncProtocol.js +25 -11
  72. package/src/domain/services/TemporalQuery.js +9 -6
  73. package/src/domain/services/TranslationCost.js +7 -5
  74. package/src/domain/services/WormholeService.js +16 -7
  75. package/src/domain/trust/TrustCanonical.js +3 -3
  76. package/src/domain/trust/TrustEvaluator.js +18 -3
  77. package/src/domain/trust/TrustRecordService.js +30 -23
  78. package/src/domain/trust/TrustStateBuilder.js +21 -8
  79. package/src/domain/trust/canonical.js +6 -6
  80. package/src/domain/types/TickReceipt.js +1 -1
  81. package/src/domain/types/WarpErrors.js +45 -0
  82. package/src/domain/types/WarpOptions.js +29 -0
  83. package/src/domain/types/WarpPersistence.js +41 -0
  84. package/src/domain/types/WarpTypes.js +2 -2
  85. package/src/domain/types/WarpTypesV2.js +2 -2
  86. package/src/domain/utils/MinHeap.js +6 -5
  87. package/src/domain/utils/canonicalStringify.js +5 -4
  88. package/src/domain/utils/roaring.js +31 -5
  89. package/src/domain/warp/PatchSession.js +9 -18
  90. package/src/domain/warp/_wiredMethods.d.ts +199 -45
  91. package/src/domain/warp/checkpoint.methods.js +5 -1
  92. package/src/domain/warp/fork.methods.js +2 -2
  93. package/src/domain/warp/materialize.methods.js +55 -5
  94. package/src/domain/warp/materializeAdvanced.methods.js +15 -4
  95. package/src/domain/warp/patch.methods.js +54 -29
  96. package/src/domain/warp/provenance.methods.js +5 -3
  97. package/src/domain/warp/query.methods.js +6 -5
  98. package/src/domain/warp/sync.methods.js +16 -11
  99. package/src/globals.d.ts +64 -0
  100. package/src/infrastructure/adapters/BunHttpAdapter.js +14 -9
  101. package/src/infrastructure/adapters/CasSeekCacheAdapter.js +9 -4
  102. package/src/infrastructure/adapters/DenoHttpAdapter.js +5 -6
  103. package/src/infrastructure/adapters/GitGraphAdapter.js +14 -12
  104. package/src/infrastructure/adapters/NodeHttpAdapter.js +2 -2
  105. package/src/infrastructure/adapters/WebCryptoAdapter.js +2 -2
  106. package/src/visualization/layouts/converters.js +2 -2
  107. package/src/visualization/layouts/elkAdapter.js +1 -1
  108. package/src/visualization/layouts/elkLayout.js +10 -7
  109. package/src/visualization/layouts/index.js +1 -1
  110. package/src/visualization/renderers/ascii/seek.js +16 -6
  111. package/src/visualization/renderers/svg/index.js +1 -1
@@ -30,9 +30,35 @@
30
30
  */
31
31
  const NOT_CHECKED = Symbol('NOT_CHECKED');
32
32
 
33
+ /**
34
+ * Shape of the lazily-loaded roaring module after ESM/CJS unwrapping.
35
+ * Uses Function instead of typeof import('roaring').RoaringBitmap32 to avoid
36
+ * duplicate import() references that crash Deno's JSR rewriter (deno_ast
37
+ * overlapping TextChange bug). The single import() reference lives on
38
+ * getRoaringBitmap32()'s @returns tag.
39
+ * @typedef {Object} RoaringModule
40
+ * @property {Function & { isNativelyInstalled?: () => boolean }} RoaringBitmap32
41
+ * @property {{ RoaringBitmap32: Function }} [default]
42
+ * @property {boolean} [isNativelyInstalled]
43
+ */
44
+
45
+ /**
46
+ * Minimum structural contract of a RoaringBitmap32 as used by bitmap index code.
47
+ * Named "Subset" because it only covers methods actually called by index builders/readers.
48
+ * Using import('roaring').RoaringBitmap32 directly fails under checkJs + skipLibCheck
49
+ * because tsc doesn't fully resolve inherited methods from ReadonlyRoaringBitmap32.
50
+ * @typedef {Object} RoaringBitmapSubset
51
+ * @property {number} size
52
+ * @property {function(number): void} add
53
+ * @property {function(number): boolean} has
54
+ * @property {function(Iterable<number>): void} orInPlace
55
+ * @property {function(boolean): Uint8Array} serialize
56
+ * @property {function(): number[]} toArray
57
+ */
58
+
33
59
  /**
34
60
  * Cached reference to the loaded roaring module.
35
- * @type {any} // TODO(ts-cleanup): type lazy singleton
61
+ * @type {RoaringModule | null}
36
62
  * @private
37
63
  */
38
64
  let roaringModule = null;
@@ -51,7 +77,7 @@ let nativeAvailability = NOT_CHECKED;
51
77
  * Uses a top-level-await-friendly pattern with dynamic import.
52
78
  * The module is cached after first load.
53
79
  *
54
- * @returns {any} The roaring module exports
80
+ * @returns {RoaringModule} The roaring module exports
55
81
  * @throws {Error} If the roaring package is not installed or fails to load
56
82
  * @private
57
83
  */
@@ -67,7 +93,7 @@ function loadRoaring() {
67
93
  * This is called automatically via top-level await when the module is imported,
68
94
  * but can also be called manually with a pre-loaded module for testing.
69
95
  *
70
- * @param {Object} [mod] - Pre-loaded roaring module (for testing/DI)
96
+ * @param {RoaringModule} [mod] - Pre-loaded roaring module (for testing/DI)
71
97
  * @returns {Promise<void>}
72
98
  */
73
99
  export async function initRoaring(mod) {
@@ -76,7 +102,7 @@ export async function initRoaring(mod) {
76
102
  return;
77
103
  }
78
104
  if (!roaringModule) {
79
- roaringModule = await import('roaring');
105
+ roaringModule = /** @type {RoaringModule} */ (await import('roaring'));
80
106
  // Handle both ESM default export and CJS module.exports
81
107
  if (roaringModule.default && roaringModule.default.RoaringBitmap32) {
82
108
  roaringModule = roaringModule.default;
@@ -116,7 +142,7 @@ try {
116
142
  * const intersection = RoaringBitmap32.and(a, b); // [2, 3]
117
143
  */
118
144
  export function getRoaringBitmap32() {
119
- return loadRoaring().RoaringBitmap32;
145
+ return /** @type {typeof import('roaring').RoaringBitmap32} */ (loadRoaring().RoaringBitmap32);
120
146
  }
121
147
 
122
148
  /**
@@ -120,7 +120,7 @@ export class PatchSession {
120
120
  *
121
121
  * @param {string} nodeId - The node ID
122
122
  * @param {string} key - Property key
123
- * @param {*} value - Property value (must be JSON-serializable)
123
+ * @param {unknown} value - Property value (must be JSON-serializable)
124
124
  * @returns {this} This session for chaining
125
125
  * @throws {Error} If this session has already been committed
126
126
  */
@@ -137,7 +137,7 @@ export class PatchSession {
137
137
  * @param {string} to - Target node ID
138
138
  * @param {string} label - Edge label/type
139
139
  * @param {string} key - Property key
140
- * @param {*} value - Property value (must be JSON-serializable)
140
+ * @param {unknown} value - Property value (must be JSON-serializable)
141
141
  * @returns {this} This session for chaining
142
142
  * @throws {Error} If this session has already been committed
143
143
  */
@@ -194,23 +194,14 @@ export class PatchSession {
194
194
  const sha = await this._builder.commit();
195
195
  this._committed = true;
196
196
  return sha;
197
- } catch (/** @type {any} */ err) { // TODO(ts-cleanup): type error
198
- // Check if it's a concurrent commit error from PatchBuilderV2
199
- if (err.message?.includes('Concurrent commit detected') ||
200
- err.message?.includes('has advanced')) {
201
- throw new WriterError(
202
- 'WRITER_REF_ADVANCED',
203
- err.message,
204
- err
205
- );
197
+ } catch (err) {
198
+ const errMsg = err instanceof Error ? err.message : String(err);
199
+ const cause = err instanceof Error ? err : undefined;
200
+ if (errMsg.includes('Concurrent commit detected') ||
201
+ errMsg.includes('has advanced')) {
202
+ throw new WriterError('WRITER_REF_ADVANCED', errMsg, cause);
206
203
  }
207
-
208
- // Wrap other errors
209
- throw new WriterError(
210
- 'PERSIST_WRITE_FAILED',
211
- `Failed to persist patch: ${err.message}`,
212
- err
213
- );
204
+ throw new WriterError('PERSIST_WRITE_FAILED', `Failed to persist patch: ${errMsg}`, cause);
214
205
  }
215
206
  }
216
207
 
@@ -5,10 +5,153 @@
5
5
  * via wireWarpMethods(). This declaration file makes them visible to tsc.
6
6
  */
7
7
 
8
- /* eslint-disable @typescript-eslint/no-explicit-any */
9
-
10
8
  import type { PatchBuilderV2 } from '../services/PatchBuilderV2.js';
11
9
  import type { Writer } from './Writer.js';
10
+ import type { WarpStateV5 } from '../services/JoinReducer.js';
11
+ import type { PatchV2 } from '../types/WarpTypesV2.js';
12
+ import type { StateDiffResult } from '../services/StateDiff.js';
13
+ import type { TickReceipt } from '../types/TickReceipt.js';
14
+
15
+ /**
16
+ * Observer configuration for view creation and translation cost.
17
+ */
18
+ interface ObserverConfig {
19
+ match: string;
20
+ expose?: string[];
21
+ redact?: string[];
22
+ }
23
+
24
+ /**
25
+ * Translation cost result.
26
+ */
27
+ interface TranslationCostResult {
28
+ cost: number;
29
+ breakdown: { nodeLoss: number; edgeLoss: number; propLoss: number };
30
+ }
31
+
32
+ /**
33
+ * Lightweight status snapshot.
34
+ */
35
+ interface WarpGraphStatus {
36
+ cachedState: 'fresh' | 'stale' | 'none';
37
+ patchesSinceCheckpoint: number;
38
+ tombstoneRatio: number;
39
+ writers: number;
40
+ frontier: Record<string, string>;
41
+ }
42
+
43
+ /**
44
+ * Sync request message.
45
+ */
46
+ interface SyncRequest {
47
+ type: 'sync-request';
48
+ frontier: Record<string, string>;
49
+ }
50
+
51
+ /**
52
+ * Sync response message.
53
+ */
54
+ interface SyncResponse {
55
+ type: 'sync-response';
56
+ frontier: Record<string, string>;
57
+ patches: Array<{ writerId: string; sha: string; patch: unknown }>;
58
+ }
59
+
60
+ /**
61
+ * Result of applySyncResponse().
62
+ */
63
+ interface ApplySyncResult {
64
+ state: WarpStateV5;
65
+ frontier: Map<string, number>;
66
+ applied: number;
67
+ }
68
+
69
+ /**
70
+ * Sync options for syncWith().
71
+ */
72
+ interface SyncWithOptions {
73
+ path?: string;
74
+ retries?: number;
75
+ baseDelayMs?: number;
76
+ maxDelayMs?: number;
77
+ timeoutMs?: number;
78
+ signal?: AbortSignal;
79
+ onStatus?: (event: {
80
+ type: string;
81
+ attempt: number;
82
+ durationMs?: number;
83
+ status?: number;
84
+ error?: Error;
85
+ }) => void;
86
+ auth?: { secret: string; keyId?: string };
87
+ /** Auto-materialize after sync; when true, result includes `state` */
88
+ materialize?: boolean;
89
+ }
90
+
91
+ /**
92
+ * GC execution result.
93
+ */
94
+ interface GCExecuteResult {
95
+ nodesCompacted: number;
96
+ edgesCompacted: number;
97
+ tombstonesRemoved: number;
98
+ durationMs: number;
99
+ }
100
+
101
+ /**
102
+ * GC metrics.
103
+ */
104
+ interface GCMetrics {
105
+ nodeCount: number;
106
+ edgeCount: number;
107
+ tombstoneCount: number;
108
+ tombstoneRatio: number;
109
+ patchesSinceCompaction: number;
110
+ lastCompactionTime: number;
111
+ }
112
+
113
+ /**
114
+ * Result of maybeRunGC().
115
+ */
116
+ interface MaybeGCResult {
117
+ ran: boolean;
118
+ result: GCExecuteResult | null;
119
+ reasons: string[];
120
+ }
121
+
122
+ /**
123
+ * Join receipt from CRDT merge.
124
+ */
125
+ interface JoinReceipt {
126
+ nodesAdded: number;
127
+ nodesRemoved: number;
128
+ edgesAdded: number;
129
+ edgesRemoved: number;
130
+ propsChanged: number;
131
+ frontierMerged: boolean;
132
+ }
133
+
134
+ /**
135
+ * Wormhole edge.
136
+ */
137
+ interface WormholeEdge {
138
+ fromSha: string;
139
+ toSha: string;
140
+ writerId: string;
141
+ payload: unknown;
142
+ patchCount: number;
143
+ }
144
+
145
+ /**
146
+ * Checkpoint data returned by _loadLatestCheckpoint.
147
+ */
148
+ interface CheckpointData {
149
+ state: WarpStateV5;
150
+ frontier: Map<string, string>;
151
+ stateHash: string;
152
+ schema: number;
153
+ provenanceIndex?: unknown;
154
+ }
12
155
 
13
156
  export {};
14
157
 
@@ -16,85 +159,96 @@ declare module '../WarpGraph.js' {
16
159
  export default interface WarpGraph {
17
160
  // ── query.methods.js ──────────────────────────────────────────────────
18
161
  hasNode(nodeId: string): Promise<boolean>;
19
- getNodeProps(nodeId: string): Promise<Map<string, any> | null>;
20
- getEdgeProps(from: string, to: string, label: string): Promise<Record<string, any> | null>;
162
+ getNodeProps(nodeId: string): Promise<Map<string, unknown> | null>;
163
+ getEdgeProps(from: string, to: string, label: string): Promise<Record<string, unknown> | null>;
21
164
  neighbors(nodeId: string, direction?: 'outgoing' | 'incoming' | 'both', edgeLabel?: string): Promise<Array<{ nodeId: string; label: string; direction: 'outgoing' | 'incoming' }>>;
22
- getStateSnapshot(): Promise<any>;
165
+ getStateSnapshot(): Promise<WarpStateV5 | null>;
23
166
  getNodes(): Promise<string[]>;
24
- getEdges(): Promise<Array<{ from: string; to: string; label: string; props: Record<string, any> }>>;
167
+ getEdges(): Promise<Array<{ from: string; to: string; label: string; props: Record<string, unknown> }>>;
25
168
  getPropertyCount(): Promise<number>;
26
- query(): any;
27
- observer(name: string, config: any): Promise<any>;
28
- translationCost(configA: any, configB: any): Promise<{ cost: number; breakdown: { nodeLoss: number; edgeLoss: number; propLoss: number } }>;
169
+ query(): import('../services/QueryBuilder.js').default;
170
+ observer(name: string, config: ObserverConfig): Promise<import('../services/ObserverView.js').default>;
171
+ translationCost(configA: ObserverConfig, configB: ObserverConfig): Promise<TranslationCostResult>;
29
172
 
30
173
  // ── subscribe.methods.js ──────────────────────────────────────────────
31
- subscribe(options: { onChange: Function; onError?: Function; replay?: boolean }): { unsubscribe: () => void };
32
- watch(pattern: string, options: { onChange: Function; onError?: Function; poll?: number }): { unsubscribe: () => void };
33
- _notifySubscribers(diff: any, currentState: any): void;
174
+ subscribe(options: { onChange: (diff: StateDiffResult) => void; onError?: (error: Error) => void; replay?: boolean }): { unsubscribe: () => void };
175
+ watch(pattern: string, options: { onChange: (diff: StateDiffResult) => void; onError?: (error: Error) => void; poll?: number }): { unsubscribe: () => void };
176
+ _notifySubscribers(diff: StateDiffResult, currentState: WarpStateV5): void;
34
177
 
35
178
  // ── provenance.methods.js ─────────────────────────────────────────────
36
179
  patchesFor(entityId: string): Promise<string[]>;
37
- materializeSlice(nodeId: string, options?: any): Promise<any>;
180
+ materializeSlice(nodeId: string, options?: { receipts?: boolean }): Promise<{ state: WarpStateV5; patchCount: number; receipts?: TickReceipt[] }>;
181
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- internal method; `any` avoids breaking provenance.methods.js callers
38
182
  _computeBackwardCone(nodeId: string): Promise<Map<string, any>>;
39
- loadPatchBySha(sha: string): Promise<any>;
40
- _loadPatchBySha(sha: string): Promise<any>;
41
- _loadPatchesBySha(shas: string[]): Promise<Array<{ patch: any; sha: string }>>;
42
- _sortPatchesCausally(patches: any[]): any[];
183
+ loadPatchBySha(sha: string): Promise<{ patch: PatchV2; sha: string }>;
184
+ _loadPatchBySha(sha: string): Promise<{ patch: PatchV2; sha: string }>;
185
+ _loadPatchesBySha(shas: string[]): Promise<Array<{ patch: PatchV2; sha: string }>>;
186
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- internal method; `any` avoids breaking provenance.methods.js callers
187
+ _sortPatchesCausally(patches: Array<{ patch: any; sha: string }>): Array<{ patch: any; sha: string }>;
43
188
 
44
189
  // ── fork.methods.js ───────────────────────────────────────────────────
45
190
  fork(options: { from: string; at: string; forkName?: string; forkWriterId?: string }): Promise<WarpGraph>;
46
- createWormhole(fromSha: string, toSha: string): Promise<{ fromSha: string; toSha: string; writerId: string; payload: any; patchCount: number }>;
191
+ createWormhole(fromSha: string, toSha: string): Promise<WormholeEdge>;
47
192
  _isAncestor(ancestorSha: string, descendantSha: string): Promise<boolean>;
48
193
  _relationToCheckpointHead(ckHead: string, incomingSha: string): Promise<string>;
49
- _validatePatchAgainstCheckpoint(writerId: string, incomingSha: string, checkpoint: any): Promise<void>;
194
+ _validatePatchAgainstCheckpoint(writerId: string, incomingSha: string, checkpoint: unknown): Promise<void>;
50
195
 
51
196
  // ── sync.methods.js ───────────────────────────────────────────────────
52
197
  getFrontier(): Promise<Map<string, string>>;
53
198
  hasFrontierChanged(): Promise<boolean>;
54
- status(): Promise<any>;
55
- createSyncRequest(): Promise<any>;
56
- processSyncRequest(request: any): Promise<any>;
57
- applySyncResponse(response: any): any;
58
- syncNeeded(remoteFrontier: any): Promise<boolean>;
59
- syncWith(remote: any, options?: any): Promise<any>;
60
- serve(options?: any): Promise<any>;
199
+ status(): Promise<WarpGraphStatus>;
200
+ createSyncRequest(): Promise<SyncRequest>;
201
+ processSyncRequest(request: SyncRequest): Promise<SyncResponse>;
202
+ applySyncResponse(response: SyncResponse): ApplySyncResult;
203
+ syncNeeded(remoteFrontier: Map<string, string>): Promise<boolean>;
204
+ syncWith(remote: string | WarpGraph, options?: SyncWithOptions): Promise<{ applied: number; attempts: number; state?: WarpStateV5 }>;
205
+ serve(options: {
206
+ port: number;
207
+ host?: string;
208
+ path?: string;
209
+ maxRequestBytes?: number;
210
+ httpPort: unknown;
211
+ auth?: unknown;
212
+ allowedWriters?: string[];
213
+ }): Promise<{ close(): Promise<void>; url: string }>;
61
214
 
62
215
  // ── checkpoint.methods.js ─────────────────────────────────────────────
63
216
  createCheckpoint(): Promise<string>;
64
217
  syncCoverage(): Promise<void>;
65
- _loadLatestCheckpoint(): Promise<any>;
66
- _loadPatchesSince(checkpoint: any): Promise<any[]>;
218
+ _loadLatestCheckpoint(): Promise<CheckpointData | null>;
219
+ _loadPatchesSince(checkpoint: CheckpointData): Promise<Array<{ patch: PatchV2; sha: string }>>;
67
220
  _validateMigrationBoundary(): Promise<void>;
68
221
  _hasSchema1Patches(): Promise<boolean>;
69
- _maybeRunGC(state: any): any;
70
- maybeRunGC(): any;
71
- runGC(): any;
72
- getGCMetrics(): any;
222
+ _maybeRunGC(state: WarpStateV5): void;
223
+ maybeRunGC(): MaybeGCResult;
224
+ runGC(): GCExecuteResult;
225
+ getGCMetrics(): GCMetrics | null;
73
226
 
74
227
  // ── patch.methods.js ──────────────────────────────────────────────────
75
228
  createPatch(): Promise<PatchBuilderV2>;
76
229
  patch(build: (p: PatchBuilderV2) => void | Promise<void>): Promise<string>;
77
230
  _nextLamport(): Promise<{ lamport: number; parentSha: string | null }>;
78
- _loadWriterPatches(writerId: string, stopAtSha?: string | null): Promise<Array<{ patch: import('../types/WarpTypesV2.js').PatchV2; sha: string }>>;
79
- getWriterPatches(writerId: string, stopAtSha?: string | null): Promise<Array<{ patch: import('../types/WarpTypesV2.js').PatchV2; sha: string }>>;
80
- _onPatchCommitted(writerId: string, opts?: { patch?: any; sha?: string }): Promise<void>;
231
+ _loadWriterPatches(writerId: string, stopAtSha?: string | null): Promise<Array<{ patch: PatchV2; sha: string }>>;
232
+ getWriterPatches(writerId: string, stopAtSha?: string | null): Promise<Array<{ patch: PatchV2; sha: string }>>;
233
+ _onPatchCommitted(writerId: string, opts?: { patch?: PatchV2; sha?: string }): Promise<void>;
81
234
  writer(writerId?: string): Promise<Writer>;
82
- createWriter(opts?: any): Promise<Writer>;
235
+ createWriter(opts?: { persist?: 'config' | 'none'; alias?: string }): Promise<Writer>;
83
236
  _ensureFreshState(): Promise<void>;
84
237
  discoverWriters(): Promise<string[]>;
85
238
  discoverTicks(): Promise<{ ticks: number[]; maxTick: number; perWriter: Map<string, { ticks: number[]; tipSha: string | null; tickShas: Record<number, string> }> }>;
86
- join(otherState: any): any;
87
- _frontierEquals(a: any, b: any): boolean;
239
+ join(otherState: WarpStateV5): { state: WarpStateV5; receipt: JoinReceipt };
240
+ _frontierEquals(a: Map<string, number>, b: Map<string, number>): boolean;
88
241
 
89
242
  // ── materialize.methods.js ────────────────────────────────────────────
90
- materialize(options?: any): Promise<any>;
91
- _materializeGraph(): Promise<any>;
243
+ materialize(options: { receipts: true; ceiling?: number | null }): Promise<{ state: WarpStateV5; receipts: TickReceipt[] }>;
244
+ materialize(options?: { receipts?: false; ceiling?: number | null }): Promise<WarpStateV5>;
245
+ _materializeGraph(): Promise<{ state: WarpStateV5; stateHash: string; adjacency: unknown }>;
92
246
 
93
247
  // ── materializeAdvanced.methods.js ────────────────────────────────────
94
- _resolveCeiling(options: any): any;
95
- _buildAdjacency(state: any): any;
96
- _setMaterializedState(state: any): Promise<{ state: any; stateHash: string; adjacency: any }>;
97
- _materializeWithCeiling(ceiling: any, collectReceipts: boolean, t0: number): Promise<any>;
98
- materializeAt(checkpointSha: string): Promise<any>;
248
+ _resolveCeiling(options?: { ceiling?: number | null }): number | null;
249
+ _buildAdjacency(state: WarpStateV5): { outgoing: Map<string, Array<{ neighborId: string; label: string }>>; incoming: Map<string, Array<{ neighborId: string; label: string }>> };
250
+ _setMaterializedState(state: WarpStateV5): Promise<{ state: WarpStateV5; stateHash: string; adjacency: unknown }>;
251
+ _materializeWithCeiling(ceiling: number, collectReceipts: boolean, t0: number): Promise<WarpStateV5 | { state: WarpStateV5; receipts: TickReceipt[] }>;
252
+ materializeAt(checkpointSha: string): Promise<WarpStateV5>;
99
253
  }
100
254
  }
@@ -16,6 +16,8 @@ import { shouldRunGC, executeGC } from '../services/GCPolicy.js';
16
16
  import { collectGCMetrics } from '../services/GCMetrics.js';
17
17
  import { computeAppliedVV } from '../services/CheckpointSerializerV5.js';
18
18
 
19
+ /** @typedef {import('../types/WarpPersistence.js').CorePersistence} CorePersistence */
20
+
19
21
  /**
20
22
  * Creates a checkpoint of the current graph state.
21
23
  *
@@ -59,8 +61,10 @@ export async function createCheckpoint() {
59
61
  }
60
62
 
61
63
  // 4. Call CheckpointService.create() with provenance index if available
64
+ /** @type {CorePersistence} */
65
+ const persistence = this._persistence;
62
66
  const checkpointSha = await createCheckpointCommit({
63
- persistence: /** @type {any} */ (this._persistence), // TODO(ts-cleanup): narrow port type
67
+ persistence,
64
68
  graphName: this._graphName,
65
69
  state,
66
70
  frontier,
@@ -201,13 +201,13 @@ export async function createWormhole(fromSha, toSha) {
201
201
  const t0 = this._clock.now();
202
202
 
203
203
  try {
204
- const wormhole = await createWormholeImpl(/** @type {any} */ ({ // TODO(ts-cleanup): needs options type
204
+ const wormhole = await createWormholeImpl({
205
205
  persistence: this._persistence,
206
206
  graphName: this._graphName,
207
207
  fromSha,
208
208
  toSha,
209
209
  codec: this._codec,
210
- }));
210
+ });
211
211
 
212
212
  this._logTiming('createWormhole', t0, {
213
213
  metrics: `${wormhole.patchCount} patches from=${fromSha.slice(0, 7)} to=${toSha.slice(0, 7)}`,
@@ -9,6 +9,47 @@
9
9
  import { reduceV5, createEmptyStateV5, cloneStateV5 } from '../services/JoinReducer.js';
10
10
  import { ProvenanceIndex } from '../services/ProvenanceIndex.js';
11
11
  import { diffStates, isEmptyDiff } from '../services/StateDiff.js';
12
+ import { decodePatchMessage, detectMessageKind } from '../services/WarpMessageCodec.js';
13
+
14
+ /**
15
+ * Scans the checkpoint frontier's tip commits for the maximum observed Lamport tick.
16
+ * Updates `graph._maxObservedLamport` in-place; best-effort (skips unreadable commits).
17
+ *
18
+ * @param {import('../WarpGraph.js').default} graph
19
+ * @param {Map<string, string>} frontier
20
+ * @returns {Promise<void>}
21
+ */
22
+ async function scanFrontierForMaxLamport(graph, frontier) {
23
+ for (const tipSha of frontier.values()) {
24
+ try {
25
+ const msg = await graph._persistence.showNode(tipSha);
26
+ if (detectMessageKind(msg) === 'patch') {
27
+ const { lamport } = decodePatchMessage(msg);
28
+ if (lamport > graph._maxObservedLamport) {
29
+ graph._maxObservedLamport = lamport;
30
+ }
31
+ }
32
+ } catch {
33
+ // best-effort: skip unreadable frontier commits
34
+ }
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Scans a list of patch entries for the maximum observed Lamport tick.
40
+ * Updates `graph._maxObservedLamport` in-place.
41
+ *
42
+ * @param {import('../WarpGraph.js').default} graph
43
+ * @param {Array<{patch: {lamport?: number}}>} patches
44
+ */
45
+ function scanPatchesForMaxLamport(graph, patches) {
46
+ for (const { patch } of patches) {
47
+ const tick = patch.lamport ?? 0;
48
+ if (tick > graph._maxObservedLamport) {
49
+ graph._maxObservedLamport = tick;
50
+ }
51
+ }
52
+ }
12
53
 
13
54
  /**
14
55
  * Materializes the current graph state.
@@ -63,17 +104,24 @@ export async function materialize(options) {
63
104
  // If checkpoint exists, use incremental materialization
64
105
  if (checkpoint?.schema === 2 || checkpoint?.schema === 3) {
65
106
  const patches = await this._loadPatchesSince(checkpoint);
107
+ // Update max observed Lamport so _nextLamport() issues globally-monotonic ticks.
108
+ // Read the checkpoint frontier's tip commit messages to capture the pre-checkpoint max,
109
+ // then scan the incremental patches for anything newer.
110
+ if (checkpoint.frontier instanceof Map) {
111
+ await scanFrontierForMaxLamport(this, checkpoint.frontier);
112
+ }
113
+ scanPatchesForMaxLamport(this, patches);
66
114
  if (collectReceipts) {
67
- const result = /** @type {{state: import('../services/JoinReducer.js').WarpStateV5, receipts: import('../types/TickReceipt.js').TickReceipt[]}} */ (reduceV5(/** @type {any} */ (patches), /** @type {import('../services/JoinReducer.js').WarpStateV5} */ (checkpoint.state), { receipts: true })); // TODO(ts-cleanup): type patch array
115
+ const result = /** @type {{state: import('../services/JoinReducer.js').WarpStateV5, receipts: import('../types/TickReceipt.js').TickReceipt[]}} */ (reduceV5(/** @type {Parameters<typeof reduceV5>[0]} */ (patches), checkpoint.state, { receipts: true }));
68
116
  state = result.state;
69
117
  receipts = result.receipts;
70
118
  } else {
71
- state = /** @type {import('../services/JoinReducer.js').WarpStateV5} */ (reduceV5(/** @type {any} */ (patches), /** @type {import('../services/JoinReducer.js').WarpStateV5} */ (checkpoint.state))); // TODO(ts-cleanup): type patch array
119
+ state = /** @type {import('../services/JoinReducer.js').WarpStateV5} */ (reduceV5(/** @type {Parameters<typeof reduceV5>[0]} */ (patches), checkpoint.state));
72
120
  }
73
121
  patchCount = patches.length;
74
122
 
75
123
  // Build provenance index: start from checkpoint index if present, then add new patches
76
- const ckPI = /** @type {any} */ (checkpoint).provenanceIndex; // TODO(ts-cleanup): type checkpoint cast
124
+ const ckPI = /** @type {{provenanceIndex?: import('../services/ProvenanceIndex.js').ProvenanceIndex}} */ (checkpoint).provenanceIndex;
77
125
  this._provenanceIndex = ckPI
78
126
  ? ckPI.clone()
79
127
  : new ProvenanceIndex();
@@ -109,13 +157,15 @@ export async function materialize(options) {
109
157
  receipts = [];
110
158
  }
111
159
  } else {
160
+ // Update max observed Lamport from all loaded patches.
161
+ scanPatchesForMaxLamport(this, allPatches);
112
162
  // 5. Reduce all patches to state
113
163
  if (collectReceipts) {
114
- const result = /** @type {{state: import('../services/JoinReducer.js').WarpStateV5, receipts: import('../types/TickReceipt.js').TickReceipt[]}} */ (reduceV5(/** @type {any} */ (allPatches), undefined, { receipts: true })); // TODO(ts-cleanup): type patch array
164
+ const result = /** @type {{state: import('../services/JoinReducer.js').WarpStateV5, receipts: import('../types/TickReceipt.js').TickReceipt[]}} */ (reduceV5(/** @type {Parameters<typeof reduceV5>[0]} */ (allPatches), undefined, { receipts: true }));
115
165
  state = result.state;
116
166
  receipts = result.receipts;
117
167
  } else {
118
- state = /** @type {import('../services/JoinReducer.js').WarpStateV5} */ (reduceV5(/** @type {any} */ (allPatches))); // TODO(ts-cleanup): type patch array
168
+ state = /** @type {import('../services/JoinReducer.js').WarpStateV5} */ (reduceV5(/** @type {Parameters<typeof reduceV5>[0]} */ (allPatches)));
119
169
  }
120
170
  patchCount = allPatches.length;
121
171
 
@@ -18,6 +18,15 @@ import { serializeFullStateV5, deserializeFullStateV5 } from '../services/Checkp
18
18
  import { buildSeekCacheKey } from '../utils/seekCacheKey.js';
19
19
  import { materializeIncremental } from '../services/CheckpointService.js';
20
20
  import { createFrontier, updateFrontier } from '../services/Frontier.js';
21
+
22
+ /** @typedef {import('../types/WarpPersistence.js').CorePersistence} CorePersistence */
23
+ /** @typedef {import('../services/JoinReducer.js').WarpStateV5} WarpStateV5 */
24
+
25
+ /**
26
+ * @typedef {{ outgoing: Map<string, Array<{neighborId: string, label: string}>>, incoming: Map<string, Array<{neighborId: string, label: string}>> }} AdjacencyMap
27
+ * @typedef {{ state: WarpStateV5, stateHash: string, adjacency: AdjacencyMap }} MaterializedResult
28
+ */
29
+
21
30
  import { buildWriterRef } from '../utils/RefLayout.js';
22
31
  import { decodePatchMessage, detectMessageKind } from '../services/WarpMessageCodec.js';
23
32
 
@@ -97,7 +106,7 @@ export function _buildAdjacency(state) {
97
106
  *
98
107
  * @this {import('../WarpGraph.js').default}
99
108
  * @param {import('../services/JoinReducer.js').WarpStateV5} state
100
- * @returns {Promise<{state: any, stateHash: string, adjacency: any}>}
109
+ * @returns {Promise<MaterializedResult>}
101
110
  * @private
102
111
  */
103
112
  export async function _setMaterializedState(state) {
@@ -226,11 +235,11 @@ export async function _materializeWithCeiling(ceiling, collectReceipts, t0) {
226
235
  receipts = [];
227
236
  }
228
237
  } else if (collectReceipts) {
229
- const result = /** @type {{state: import('../services/JoinReducer.js').WarpStateV5, receipts: import('../types/TickReceipt.js').TickReceipt[]}} */ (reduceV5(/** @type {any} */ (allPatches), undefined, { receipts: true })); // TODO(ts-cleanup): type patch array
238
+ const result = /** @type {{state: import('../services/JoinReducer.js').WarpStateV5, receipts: import('../types/TickReceipt.js').TickReceipt[]}} */ (reduceV5(/** @type {Parameters<typeof reduceV5>[0]} */ (allPatches), undefined, { receipts: true }));
230
239
  state = result.state;
231
240
  receipts = result.receipts;
232
241
  } else {
233
- state = /** @type {import('../services/JoinReducer.js').WarpStateV5} */ (reduceV5(/** @type {any} */ (allPatches))); // TODO(ts-cleanup): type patch array
242
+ state = /** @type {import('../services/JoinReducer.js').WarpStateV5} */ (reduceV5(/** @type {Parameters<typeof reduceV5>[0]} */ (allPatches)));
234
243
  }
235
244
 
236
245
  this._provenanceIndex = new ProvenanceIndex();
@@ -326,8 +335,10 @@ export async function materializeAt(checkpointSha) {
326
335
  };
327
336
 
328
337
  // 4. Call materializeIncremental with the checkpoint and target frontier
338
+ /** @type {CorePersistence} */
339
+ const persistence = this._persistence;
329
340
  const state = await materializeIncremental({
330
- persistence: /** @type {any} */ (this._persistence), // TODO(ts-cleanup): narrow port type
341
+ persistence,
331
342
  graphName: this._graphName,
332
343
  checkpointSha,
333
344
  targetFrontier,