@git-stunts/git-warp 12.2.1 → 12.4.1

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 (121) hide show
  1. package/README.md +5 -5
  2. package/bin/cli/commands/info.js +1 -5
  3. package/bin/cli/infrastructure.js +6 -9
  4. package/bin/cli/shared.js +8 -0
  5. package/bin/presenters/text.js +10 -3
  6. package/bin/warp-graph.js +6 -6
  7. package/package.json +1 -1
  8. package/src/domain/WarpGraph.js +5 -35
  9. package/src/domain/crdt/ORSet.js +3 -0
  10. package/src/domain/crdt/VersionVector.js +1 -1
  11. package/src/domain/entities/GraphNode.js +1 -6
  12. package/src/domain/errors/ForkError.js +1 -1
  13. package/src/domain/errors/IndexError.js +1 -1
  14. package/src/domain/errors/OperationAbortedError.js +1 -1
  15. package/src/domain/errors/PatchError.js +1 -1
  16. package/src/domain/errors/PersistenceError.js +45 -0
  17. package/src/domain/errors/QueryError.js +1 -1
  18. package/src/domain/errors/SchemaUnsupportedError.js +1 -1
  19. package/src/domain/errors/SyncError.js +1 -1
  20. package/src/domain/errors/TraversalError.js +1 -1
  21. package/src/domain/errors/TrustError.js +1 -1
  22. package/src/domain/errors/WormholeError.js +1 -1
  23. package/src/domain/errors/index.js +1 -0
  24. package/src/domain/services/AdjacencyNeighborProvider.js +1 -4
  25. package/src/domain/services/AnchorMessageCodec.js +1 -3
  26. package/src/domain/services/AuditMessageCodec.js +1 -5
  27. package/src/domain/services/AuditReceiptService.js +4 -18
  28. package/src/domain/services/AuditVerifierService.js +3 -7
  29. package/src/domain/services/BitmapIndexBuilder.js +6 -12
  30. package/src/domain/services/BitmapIndexReader.js +7 -20
  31. package/src/domain/services/BitmapNeighborProvider.js +1 -3
  32. package/src/domain/services/BoundaryTransitionRecord.js +7 -23
  33. package/src/domain/services/CheckpointMessageCodec.js +6 -6
  34. package/src/domain/services/CheckpointSerializerV5.js +8 -12
  35. package/src/domain/services/CheckpointService.js +28 -40
  36. package/src/domain/services/CommitDagTraversalService.js +1 -3
  37. package/src/domain/services/DagPathFinding.js +9 -59
  38. package/src/domain/services/DagTopology.js +4 -16
  39. package/src/domain/services/DagTraversal.js +7 -31
  40. package/src/domain/services/Frontier.js +4 -6
  41. package/src/domain/services/GitLogParser.js +1 -2
  42. package/src/domain/services/GraphTraversal.js +14 -114
  43. package/src/domain/services/HealthCheckService.js +3 -9
  44. package/src/domain/services/HookInstaller.js +2 -8
  45. package/src/domain/services/HttpSyncServer.js +24 -25
  46. package/src/domain/services/IncrementalIndexUpdater.js +4 -6
  47. package/src/domain/services/IndexRebuildService.js +6 -52
  48. package/src/domain/services/IndexStalenessChecker.js +2 -3
  49. package/src/domain/services/JoinReducer.js +200 -100
  50. package/src/domain/services/KeyCodec.js +48 -0
  51. package/src/domain/services/LogicalBitmapIndexBuilder.js +1 -2
  52. package/src/domain/services/LogicalIndexBuildService.js +2 -6
  53. package/src/domain/services/LogicalIndexReader.js +1 -2
  54. package/src/domain/services/LogicalTraversal.js +13 -64
  55. package/src/domain/services/MaterializedViewService.js +5 -19
  56. package/src/domain/services/MessageSchemaDetector.js +35 -5
  57. package/src/domain/services/MigrationService.js +1 -4
  58. package/src/domain/services/ObserverView.js +1 -7
  59. package/src/domain/services/OpNormalizer.js +79 -0
  60. package/src/domain/services/PatchBuilderV2.js +67 -38
  61. package/src/domain/services/PatchMessageCodec.js +1 -6
  62. package/src/domain/services/PropertyIndexBuilder.js +1 -2
  63. package/src/domain/services/PropertyIndexReader.js +1 -4
  64. package/src/domain/services/ProvenanceIndex.js +5 -7
  65. package/src/domain/services/ProvenancePayload.js +1 -1
  66. package/src/domain/services/QueryBuilder.js +3 -16
  67. package/src/domain/services/StateDiff.js +3 -9
  68. package/src/domain/services/StateSerializerV5.js +10 -10
  69. package/src/domain/services/StreamingBitmapIndexBuilder.js +13 -41
  70. package/src/domain/services/SyncAuthService.js +8 -32
  71. package/src/domain/services/SyncController.js +5 -25
  72. package/src/domain/services/SyncProtocol.js +10 -13
  73. package/src/domain/services/SyncTrustGate.js +4 -9
  74. package/src/domain/services/TemporalQuery.js +9 -27
  75. package/src/domain/services/TranslationCost.js +2 -8
  76. package/src/domain/services/WarpMessageCodec.js +2 -0
  77. package/src/domain/services/WarpStateIndexBuilder.js +2 -4
  78. package/src/domain/services/WormholeService.js +9 -25
  79. package/src/domain/trust/TrustCrypto.js +9 -10
  80. package/src/domain/trust/TrustEvaluator.js +1 -8
  81. package/src/domain/trust/TrustRecordService.js +5 -10
  82. package/src/domain/types/TickReceipt.js +9 -11
  83. package/src/domain/types/WarpTypes.js +1 -5
  84. package/src/domain/types/WarpTypesV2.js +78 -13
  85. package/src/domain/utils/CachedValue.js +1 -4
  86. package/src/domain/utils/MinHeap.js +3 -3
  87. package/src/domain/utils/RefLayout.js +26 -0
  88. package/src/domain/utils/WriterId.js +2 -7
  89. package/src/domain/utils/canonicalCbor.js +1 -1
  90. package/src/domain/utils/defaultClock.js +1 -0
  91. package/src/domain/utils/defaultCodec.js +1 -1
  92. package/src/domain/utils/parseCursorBlob.js +4 -4
  93. package/src/domain/warp/PatchSession.js +3 -8
  94. package/src/domain/warp/Writer.js +9 -12
  95. package/src/domain/warp/_wire.js +2 -2
  96. package/src/domain/warp/_wiredMethods.d.ts +5 -7
  97. package/src/domain/warp/checkpoint.methods.js +1 -1
  98. package/src/domain/warp/fork.methods.js +2 -6
  99. package/src/domain/warp/materializeAdvanced.methods.js +3 -3
  100. package/src/domain/warp/patch.methods.js +8 -8
  101. package/src/domain/warp/provenance.methods.js +5 -5
  102. package/src/domain/warp/query.methods.js +9 -18
  103. package/src/domain/warp/subscribe.methods.js +2 -8
  104. package/src/globals.d.ts +7 -0
  105. package/src/infrastructure/adapters/BunHttpAdapter.js +14 -18
  106. package/src/infrastructure/adapters/ConsoleLogger.js +2 -9
  107. package/src/infrastructure/adapters/DenoHttpAdapter.js +15 -15
  108. package/src/infrastructure/adapters/GitGraphAdapter.js +234 -58
  109. package/src/infrastructure/adapters/InMemoryGraphAdapter.js +9 -2
  110. package/src/infrastructure/adapters/NodeHttpAdapter.js +14 -14
  111. package/src/infrastructure/adapters/WebCryptoAdapter.js +1 -2
  112. package/src/ports/BlobPort.js +2 -2
  113. package/src/ports/HttpServerPort.js +24 -2
  114. package/src/ports/RefPort.js +2 -1
  115. package/src/visualization/renderers/ascii/box.js +1 -1
  116. package/src/visualization/renderers/ascii/check.js +1 -5
  117. package/src/visualization/renderers/ascii/history.js +1 -6
  118. package/src/visualization/renderers/ascii/path.js +4 -22
  119. package/src/visualization/renderers/ascii/progress.js +1 -4
  120. package/src/visualization/renderers/ascii/seek.js +1 -5
  121. package/src/visualization/renderers/ascii/table.js +1 -3
@@ -29,7 +29,7 @@ const DEFAULT_MAX_CACHED_SHARDS = 100;
29
29
  * Computes a SHA-256 checksum of the given data.
30
30
  * Used to verify shard integrity on load.
31
31
  *
32
- * @param {Object} data - The data object to checksum
32
+ * @param {Record<string, unknown>} data - The data object to checksum
33
33
  * @param {number} version - Shard version (1 uses JSON.stringify, 2+ uses canonicalStringify)
34
34
  * @param {import('../../ports/CryptoPort.js').default} crypto - CryptoPort instance
35
35
  * @returns {Promise<string>} Hex-encoded SHA-256 hash
@@ -82,16 +82,9 @@ const computeChecksum = async (data, version, crypto) => {
82
82
  export default class BitmapIndexReader {
83
83
  /**
84
84
  * Creates a BitmapIndexReader instance.
85
- * @param {Object} options
86
- * @param {IndexStoragePort} options.storage - Storage adapter for reading index data
87
- * @param {boolean} [options.strict=true] - If true, throw errors on validation failures; if false, log warnings and return empty shards
88
- * @param {import('../../ports/LoggerPort.js').default} [options.logger] - Logger for structured logging.
89
- * Defaults to NoOpLogger (no logging).
90
- * @param {number} [options.maxCachedShards=100] - Maximum number of shards to keep in the LRU cache.
91
- * When exceeded, least recently used shards are evicted to free memory.
92
- * @param {import('../../ports/CryptoPort.js').default} [options.crypto] - CryptoPort instance for checksum verification.
85
+ * @param {{ storage: IndexStoragePort, strict?: boolean, logger?: import('../../ports/LoggerPort.js').default, maxCachedShards?: number, crypto?: import('../../ports/CryptoPort.js').default }} options
93
86
  */
94
- constructor({ storage, strict = true, logger = nullLogger, maxCachedShards = DEFAULT_MAX_CACHED_SHARDS, crypto } = /** @type {{ storage: IndexStoragePort, strict?: boolean, logger?: LoggerPort, maxCachedShards?: number, crypto?: CryptoPort }} */ ({})) {
87
+ constructor({ storage, strict = true, logger = nullLogger, maxCachedShards = DEFAULT_MAX_CACHED_SHARDS, crypto }) {
95
88
  if (!storage) {
96
89
  throw new Error('BitmapIndexReader requires a storage adapter');
97
90
  }
@@ -321,10 +314,7 @@ export default class BitmapIndexReader {
321
314
  /**
322
315
  * Handles validation/corruption errors based on strict mode.
323
316
  * @param {ShardCorruptionError|ShardValidationError} err - The error to handle
324
- * @param {Object} context - Error context
325
- * @param {string} context.path - Shard path
326
- * @param {string} context.oid - Object ID
327
- * @param {string} context.format - 'json' or 'bitmap'
317
+ * @param {{ path: string, oid: string, format: string }} context - Error context
328
318
  * @returns {Record<string, string | number> | import('../utils/roaring.js').RoaringBitmapSubset} Empty shard (non-strict mode only)
329
319
  * @throws {ShardCorruptionError|ShardValidationError} In strict mode
330
320
  * @private
@@ -356,7 +346,7 @@ export default class BitmapIndexReader {
356
346
 
357
347
  /**
358
348
  * Parses and validates a shard buffer.
359
- * @param {Buffer} buffer - Raw shard buffer
349
+ * @param {Uint8Array} buffer - Raw shard buffer
360
350
  * @param {string} path - Shard path (for error context)
361
351
  * @param {string} oid - Object ID (for error context)
362
352
  * @returns {Promise<Record<string, string | number>>} The validated data from the shard
@@ -373,7 +363,7 @@ export default class BitmapIndexReader {
373
363
  * Loads raw buffer from storage.
374
364
  * @param {string} path - Shard path
375
365
  * @param {string} oid - Object ID
376
- * @returns {Promise<Buffer>} Raw buffer
366
+ * @returns {Promise<Uint8Array>} Raw buffer
377
367
  * @throws {ShardLoadError} When storage.readBlob fails
378
368
  * @private
379
369
  */
@@ -413,10 +403,7 @@ export default class BitmapIndexReader {
413
403
  * Attempts to handle a shard error based on its type.
414
404
  * Returns handled result for validation/corruption errors, null otherwise.
415
405
  * @param {unknown} err - The error to handle
416
- * @param {Object} context - Error context
417
- * @param {string} context.path - Shard path
418
- * @param {string} context.oid - Object ID
419
- * @param {string} context.format - 'json' or 'bitmap'
406
+ * @param {{ path: string, oid: string, format: string }} context - Error context
420
407
  * @returns {Record<string, string | number> | import('../utils/roaring.js').RoaringBitmapSubset | null} Handled result or null if error should be re-thrown
421
408
  * @private
422
409
  */
@@ -59,9 +59,7 @@ function dedupSorted(edges) {
59
59
 
60
60
  export default class BitmapNeighborProvider extends NeighborProviderPort {
61
61
  /**
62
- * @param {Object} params
63
- * @param {BitmapIndexReader} [params.indexReader] - For commit DAG mode
64
- * @param {LogicalIndex} [params.logicalIndex] - For logical graph mode
62
+ * @param {{ indexReader?: BitmapIndexReader, logicalIndex?: LogicalIndex }} params
65
63
  */
66
64
  constructor({ indexReader, logicalIndex }) {
67
65
  super();
@@ -77,13 +77,7 @@ const BTR_VERSION = 1;
77
77
  *
78
78
  * This ensures all fields are covered and the encoding is deterministic.
79
79
  *
80
- * @param {Object} fields - BTR fields to authenticate
81
- * @param {number} fields.version - BTR format version
82
- * @param {string} fields.h_in - Hash of input state
83
- * @param {string} fields.h_out - Hash of output state
84
- * @param {Uint8Array} fields.U_0 - Serialized initial state
85
- * @param {Array<unknown>} fields.P - Serialized provenance payload
86
- * @param {string} fields.t - ISO timestamp
80
+ * @param {{ version: number, h_in: string, h_out: string, U_0: Uint8Array, P: Array<unknown>, t: string }} fields - BTR fields to authenticate
87
81
  * @param {string|Uint8Array} key - HMAC key
88
82
  * @param {{ crypto: import('../../ports/CryptoPort.js').default, codec?: import('../../ports/CodecPort.js').default }} deps - Dependencies
89
83
  * @returns {Promise<string>} Hex-encoded HMAC tag
@@ -151,11 +145,7 @@ async function computeHmac(fields, key, { crypto, codec }) {
151
145
  *
152
146
  * @param {import('./JoinReducer.js').WarpStateV5} initialState - The input state U_0
153
147
  * @param {ProvenancePayload} payload - The provenance payload P
154
- * @param {Object} options - BTR creation options
155
- * @param {string|Uint8Array} options.key - HMAC key for authentication
156
- * @param {string} [options.timestamp] - ISO timestamp (defaults to now)
157
- * @param {import('../../ports/CryptoPort.js').default} options.crypto - CryptoPort instance
158
- * @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for serialization
148
+ * @param {{ key: string|Uint8Array, timestamp?: string, crypto: import('../../ports/CryptoPort.js').default, codec?: import('../../ports/CodecPort.js').default }} options - BTR creation options
159
149
  * @returns {Promise<BTR>} The created BTR
160
150
  * @throws {TypeError} If payload is not a ProvenancePayload
161
151
  */
@@ -164,6 +154,7 @@ export async function createBTR(initialState, payload, options) {
164
154
  throw new TypeError('payload must be a ProvenancePayload');
165
155
  }
166
156
 
157
+ // eslint-disable-next-line no-restricted-syntax -- wall-clock default for BTR timestamp
167
158
  const { key, timestamp = new Date().toISOString(), crypto, codec } = options;
168
159
 
169
160
  // Validate HMAC key is not empty/falsy
@@ -245,9 +236,7 @@ async function verifyHmac(btr, key, { crypto, codec }) {
245
236
  * Verifies replay produces expected h_out.
246
237
  *
247
238
  * @param {BTR} btr - The BTR to verify
248
- * @param {Object} [deps] - Dependencies
249
- * @param {import('../../ports/CryptoPort.js').default} [deps.crypto] - CryptoPort instance
250
- * @param {import('../../ports/CodecPort.js').default} [deps.codec] - Codec
239
+ * @param {{ crypto?: import('../../ports/CryptoPort.js').default, codec?: import('../../ports/CodecPort.js').default }} [deps] - Dependencies
251
240
  * @returns {Promise<string|null>} Error message if replay mismatch, null if valid
252
241
  * @private
253
242
  */
@@ -275,10 +264,7 @@ async function verifyReplayHash(btr, { crypto, codec } = {}) {
275
264
  *
276
265
  * @param {BTR} btr - The BTR to verify
277
266
  * @param {string|Uint8Array} key - HMAC key
278
- * @param {Object} [options] - Verification options
279
- * @param {boolean} [options.verifyReplay=false] - Also verify replay produces h_out
280
- * @param {import('../../ports/CryptoPort.js').default} [options.crypto] - CryptoPort instance
281
- * @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for serialization
267
+ * @param {{ verifyReplay?: boolean, crypto?: import('../../ports/CryptoPort.js').default, codec?: import('../../ports/CodecPort.js').default }} [options] - Verification options
282
268
  * @returns {Promise<VerificationResult>} Verification result with valid flag and optional reason
283
269
  */
284
270
  export async function verifyBTR(btr, key, options = {}) {
@@ -367,8 +353,7 @@ function deserializeInitialState(U_0, { codec } = {}) {
367
353
  * enabling byte-for-byte comparison of BTRs.
368
354
  *
369
355
  * @param {BTR} btr - The BTR to serialize
370
- * @param {Object} [options]
371
- * @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for serialization
356
+ * @param {{ codec?: import('../../ports/CodecPort.js').default }} [options]
372
357
  * @returns {Uint8Array} CBOR-encoded BTR
373
358
  */
374
359
  export function serializeBTR(btr, { codec } = {}) {
@@ -388,8 +373,7 @@ export function serializeBTR(btr, { codec } = {}) {
388
373
  * Deserializes a BTR from CBOR bytes.
389
374
  *
390
375
  * @param {Uint8Array} bytes - CBOR-encoded BTR
391
- * @param {Object} [options]
392
- * @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for deserialization
376
+ * @param {{ codec?: import('../../ports/CodecPort.js').default }} [options]
393
377
  * @returns {BTR} The deserialized BTR
394
378
  * @throws {Error} If the bytes are not valid CBOR or missing required fields
395
379
  */
@@ -5,6 +5,11 @@
5
5
  * materialized graph state. See {@link module:domain/services/WarpMessageCodec}
6
6
  * for the facade that re-exports all codec functions.
7
7
  *
8
+ * **Schema namespace note:** Checkpoint schema versions (2, 3, 4) are
9
+ * distinct from patch schema versions (PATCH_SCHEMA_V2, PATCH_SCHEMA_V3).
10
+ * See {@link module:domain/services/CheckpointService} for named constants
11
+ * `CHECKPOINT_SCHEMA_STANDARD` and `CHECKPOINT_SCHEMA_INDEX_TREE`.
12
+ *
8
13
  * @module domain/services/CheckpointMessageCodec
9
14
  */
10
15
 
@@ -25,12 +30,7 @@ import {
25
30
  /**
26
31
  * Encodes a checkpoint commit message.
27
32
  *
28
- * @param {Object} options - The checkpoint message options
29
- * @param {string} options.graph - The graph name
30
- * @param {string} options.stateHash - The SHA-256 hash of the materialized state
31
- * @param {string} options.frontierOid - The OID of the frontier blob
32
- * @param {string} options.indexOid - The OID of the index tree
33
- * @param {number} [options.schema=2] - The schema version (defaults to 2 for new messages)
33
+ * @param {{ graph: string, stateHash: string, frontierOid: string, indexOid: string, schema?: number }} options - The checkpoint message options
34
34
  * @returns {string} The encoded commit message
35
35
  * @throws {Error} If any validation fails
36
36
  *
@@ -35,9 +35,8 @@ import { createEmptyStateV5 } from './JoinReducer.js';
35
35
  * }
36
36
  *
37
37
  * @param {import('./JoinReducer.js').WarpStateV5} state
38
- * @param {Object} [options]
39
- * @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for serialization
40
- * @returns {Buffer|Uint8Array} CBOR-encoded full state
38
+ * @param {{ codec?: import('../../ports/CodecPort.js').default }} [options]
39
+ * @returns {Uint8Array} CBOR-encoded full state
41
40
  */
42
41
  export function serializeFullStateV5(state, { codec } = {}) {
43
42
  const c = codec || defaultCodec;
@@ -84,9 +83,8 @@ export function serializeFullStateV5(state, { codec } = {}) {
84
83
  /**
85
84
  * Deserializes full V5 state. Used for resume.
86
85
  *
87
- * @param {Buffer|Uint8Array} buffer - CBOR-encoded full state
88
- * @param {Object} [options]
89
- * @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for deserialization
86
+ * @param {Uint8Array} buffer - CBOR-encoded full state
87
+ * @param {{ codec?: import('../../ports/CodecPort.js').default }} [options]
90
88
  * @returns {import('./JoinReducer.js').WarpStateV5}
91
89
  */
92
90
  // eslint-disable-next-line complexity
@@ -169,9 +167,8 @@ export function computeAppliedVV(state) {
169
167
  * Serializes appliedVV to CBOR format.
170
168
  *
171
169
  * @param {Map<string, number>} vv - Version vector (Map<writerId, counter>)
172
- * @param {Object} [options]
173
- * @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for serialization
174
- * @returns {Buffer|Uint8Array} CBOR-encoded version vector
170
+ * @param {{ codec?: import('../../ports/CodecPort.js').default }} [options]
171
+ * @returns {Uint8Array} CBOR-encoded version vector
175
172
  */
176
173
  export function serializeAppliedVV(vv, { codec } = {}) {
177
174
  const c = codec || defaultCodec;
@@ -182,9 +179,8 @@ export function serializeAppliedVV(vv, { codec } = {}) {
182
179
  /**
183
180
  * Deserializes appliedVV from CBOR format.
184
181
  *
185
- * @param {Buffer|Uint8Array} buffer - CBOR-encoded version vector
186
- * @param {Object} [options]
187
- * @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for deserialization
182
+ * @param {Uint8Array} buffer - CBOR-encoded version vector
183
+ * @param {{ codec?: import('../../ports/CodecPort.js').default }} [options]
188
184
  * @returns {Map<string, number>} Version vector
189
185
  */
190
186
  export function deserializeAppliedVV(buffer, { codec } = {}) {
@@ -28,6 +28,24 @@ import { cloneStateV5, reduceV5 } from './JoinReducer.js';
28
28
  import { encodeEdgeKey, encodePropKey, CONTENT_PROPERTY_KEY, decodePropKey, isEdgePropKey, decodeEdgePropKey } from './KeyCodec.js';
29
29
  import { ProvenanceIndex } from './ProvenanceIndex.js';
30
30
 
31
+ // ============================================================================
32
+ // Checkpoint Schema Constants
33
+ // ============================================================================
34
+
35
+ /**
36
+ * Standard checkpoint schema — full V5 state without index tree.
37
+ * Distinct from the patch schema namespace (PATCH_SCHEMA_V2/V3).
38
+ * @type {number}
39
+ */
40
+ export const CHECKPOINT_SCHEMA_STANDARD = 2;
41
+
42
+ /**
43
+ * Index-tree checkpoint schema — full V5 state with bitmap index tree.
44
+ * Distinct from the patch schema namespace (PATCH_SCHEMA_V2/V3).
45
+ * @type {number}
46
+ */
47
+ export const CHECKPOINT_SCHEMA_INDEX_TREE = 4;
48
+
31
49
  // ============================================================================
32
50
  // Internal Helpers
33
51
  // ============================================================================
@@ -91,17 +109,7 @@ function partitionTreeOids(rawOids) {
91
109
  * └── provenanceIndex.cbor # Optional: node-to-patchSha index (HG/IO/2)
92
110
  * ```
93
111
  *
94
- * @param {Object} options - Checkpoint creation options
95
- * @param {import('../../ports/GraphPersistencePort.js').default & import('../../ports/BlobPort.js').default & import('../../ports/TreePort.js').default & import('../../ports/CommitPort.js').default} options.persistence - Git persistence adapter
96
- * @param {string} options.graphName - Name of the graph
97
- * @param {import('./JoinReducer.js').WarpStateV5} options.state - The V5 state to checkpoint
98
- * @param {import('./Frontier.js').Frontier} options.frontier - Writer frontier map
99
- * @param {string[]} [options.parents=[]] - Parent commit SHAs (typically prior checkpoint or patch commits)
100
- * @param {boolean} [options.compact=true] - Whether to compact tombstoned dots before saving
101
- * @param {import('./ProvenanceIndex.js').ProvenanceIndex} [options.provenanceIndex] - Optional provenance index to persist
102
- * @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for CBOR serialization
103
- * @param {import('../../ports/CryptoPort.js').default} [options.crypto] - CryptoPort for state hash computation
104
- * @param {Record<string, Uint8Array>} [options.indexTree] - Optional materialized view index tree (triggers schema 4)
112
+ * @param {{ persistence: import('../../ports/GraphPersistencePort.js').default & import('../../ports/BlobPort.js').default & import('../../ports/TreePort.js').default & import('../../ports/CommitPort.js').default, graphName: string, state: import('./JoinReducer.js').WarpStateV5, frontier: import('./Frontier.js').Frontier, parents?: string[], compact?: boolean, provenanceIndex?: import('./ProvenanceIndex.js').ProvenanceIndex, codec?: import('../../ports/CodecPort.js').default, crypto?: import('../../ports/CryptoPort.js').default, indexTree?: Record<string, Uint8Array> }} options - Checkpoint creation options
105
113
  * @returns {Promise<string>} The checkpoint commit SHA
106
114
  */
107
115
  export async function create({ persistence, graphName, state, frontier, parents = [], compact = true, provenanceIndex, codec, crypto, indexTree }) {
@@ -120,17 +128,7 @@ export async function create({ persistence, graphName, state, frontier, parents
120
128
  * └── provenanceIndex.cbor # Optional: node-to-patchSha index (HG/IO/2)
121
129
  * ```
122
130
  *
123
- * @param {Object} options - Checkpoint creation options
124
- * @param {import('../../ports/GraphPersistencePort.js').default & import('../../ports/BlobPort.js').default & import('../../ports/TreePort.js').default & import('../../ports/CommitPort.js').default} options.persistence - Git persistence adapter
125
- * @param {string} options.graphName - Name of the graph
126
- * @param {import('./JoinReducer.js').WarpStateV5} options.state - The V5 state to checkpoint
127
- * @param {import('./Frontier.js').Frontier} options.frontier - Writer frontier map
128
- * @param {string[]} [options.parents=[]] - Parent commit SHAs
129
- * @param {boolean} [options.compact=true] - Whether to compact tombstoned dots before saving
130
- * @param {import('./ProvenanceIndex.js').ProvenanceIndex} [options.provenanceIndex] - Optional provenance index to persist
131
- * @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for CBOR serialization
132
- * @param {import('../../ports/CryptoPort.js').default} [options.crypto] - CryptoPort for state hash computation
133
- * @param {Record<string, Uint8Array>} [options.indexTree] - Optional materialized view index tree (triggers schema 4)
131
+ * @param {{ persistence: import('../../ports/GraphPersistencePort.js').default & import('../../ports/BlobPort.js').default & import('../../ports/TreePort.js').default & import('../../ports/CommitPort.js').default, graphName: string, state: import('./JoinReducer.js').WarpStateV5, frontier: import('./Frontier.js').Frontier, parents?: string[], compact?: boolean, provenanceIndex?: import('./ProvenanceIndex.js').ProvenanceIndex, codec?: import('../../ports/CodecPort.js').default, crypto?: import('../../ports/CryptoPort.js').default, indexTree?: Record<string, Uint8Array> }} options - Checkpoint creation options
134
132
  * @returns {Promise<string>} The checkpoint commit SHA
135
133
  */
136
134
  export async function createV5({
@@ -169,15 +167,15 @@ export async function createV5({
169
167
  const appliedVVBuffer = serializeAppliedVV(appliedVV, { codec: /** @type {import('../../ports/CodecPort.js').default} */ (codec) });
170
168
 
171
169
  // 6. Write blobs to git
172
- const stateBlobOid = await persistence.writeBlob(/** @type {Buffer} */ (stateBuffer));
173
- const frontierBlobOid = await persistence.writeBlob(/** @type {Buffer} */ (frontierBuffer));
174
- const appliedVVBlobOid = await persistence.writeBlob(/** @type {Buffer} */ (appliedVVBuffer));
170
+ const stateBlobOid = await persistence.writeBlob(stateBuffer);
171
+ const frontierBlobOid = await persistence.writeBlob(frontierBuffer);
172
+ const appliedVVBlobOid = await persistence.writeBlob(appliedVVBuffer);
175
173
 
176
174
  // 6b. Optionally serialize and write provenance index
177
175
  let provenanceIndexBlobOid = null;
178
176
  if (provenanceIndex) {
179
177
  const provenanceIndexBuffer = provenanceIndex.serialize({ codec });
180
- provenanceIndexBlobOid = await persistence.writeBlob(/** @type {Buffer} */ (provenanceIndexBuffer));
178
+ provenanceIndexBlobOid = await persistence.writeBlob(provenanceIndexBuffer);
181
179
  }
182
180
 
183
181
  // 6c. Optionally write index subtree (schema 4)
@@ -244,7 +242,7 @@ export async function createV5({
244
242
  indexOid: treeOid,
245
243
  // Schema 3 was used for edge-property-aware patches but is never emitted
246
244
  // by checkpoint creation. Schema 4 indicates an index tree is present.
247
- schema: indexTree ? 4 : 2,
245
+ schema: indexTree ? CHECKPOINT_SCHEMA_INDEX_TREE : CHECKPOINT_SCHEMA_STANDARD,
248
246
  });
249
247
 
250
248
  // 9. Create the checkpoint commit
@@ -275,8 +273,7 @@ export async function createV5({
275
273
  *
276
274
  * @param {import('../../ports/GraphPersistencePort.js').default & import('../../ports/BlobPort.js').default & import('../../ports/TreePort.js').default & import('../../ports/CommitPort.js').default} persistence - Git persistence adapter
277
275
  * @param {string} checkpointSha - The checkpoint commit SHA to load
278
- * @param {Object} [options] - Load options
279
- * @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for CBOR deserialization
276
+ * @param {{ codec?: import('../../ports/CodecPort.js').default }} [options] - Load options
280
277
  * @returns {Promise<{state: import('./JoinReducer.js').WarpStateV5, frontier: import('./Frontier.js').Frontier, stateHash: string, schema: number, appliedVV: Map<string, number>|null, provenanceIndex?: import('./ProvenanceIndex.js').ProvenanceIndex, indexShardOids: Record<string, string>|null}>} The loaded checkpoint data
281
278
  * @throws {Error} If checkpoint is schema:1 (migration required)
282
279
  */
@@ -357,13 +354,7 @@ export async function loadCheckpoint(persistence, checkpointSha, { codec } = {})
357
354
  * Only supports schema:2 checkpoints. Schema:1 checkpoints will cause
358
355
  * loadCheckpoint to throw an error.
359
356
  *
360
- * @param {Object} options - Materialization options
361
- * @param {import('../../ports/GraphPersistencePort.js').default & import('../../ports/BlobPort.js').default & import('../../ports/TreePort.js').default & import('../../ports/CommitPort.js').default} options.persistence - Git persistence adapter
362
- * @param {string} options.graphName - Name of the graph
363
- * @param {string} options.checkpointSha - The schema:2 checkpoint commit SHA to start from
364
- * @param {import('./Frontier.js').Frontier} options.targetFrontier - The target frontier to materialize to
365
- * @param {Function} options.patchLoader - Async function to load patches: (writerId, fromSha, toSha) => Array<{patch, sha}>
366
- * @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for CBOR deserialization
357
+ * @param {{ persistence: import('../../ports/GraphPersistencePort.js').default & import('../../ports/BlobPort.js').default & import('../../ports/TreePort.js').default & import('../../ports/CommitPort.js').default, graphName: string, checkpointSha: string, targetFrontier: import('./Frontier.js').Frontier, patchLoader: (writerId: string, fromSha: string|null, toSha: string) => Promise<Array<{patch: import('../types/WarpTypesV2.js').PatchV2, sha: string}>>, codec?: import('../../ports/CodecPort.js').default }} options - Materialization options
367
358
  * @returns {Promise<import('./JoinReducer.js').WarpStateV5>} The materialized V5 state at targetFrontier
368
359
  * @throws {Error} If checkpoint is schema:1 (migration required)
369
360
  * @throws {Error} If checkpoint is missing required blobs (state.cbor, frontier.cbor)
@@ -412,10 +403,7 @@ export async function materializeIncremental({
412
403
  * Creates ORSet-based state with synthetic dots for all visible elements.
413
404
  * This is used when loading a v5 checkpoint for incremental materialization.
414
405
  *
415
- * @param {Object} visibleProjection - The checkpoint's visible projection
416
- * @param {string[]} visibleProjection.nodes - Visible node IDs
417
- * @param {Array<{from: string, to: string, label: string}>} visibleProjection.edges - Visible edges
418
- * @param {Array<{node: string, key: string, value: unknown}>} visibleProjection.props - Visible properties
406
+ * @param {{ nodes: string[], edges: Array<{from: string, to: string, label: string}>, props: Array<{node: string, key: string, value: unknown}> }} visibleProjection - The checkpoint's visible projection
419
407
  * @returns {import('./JoinReducer.js').WarpStateV5} Reconstructed WarpStateV5
420
408
  * @public
421
409
  */
@@ -35,9 +35,7 @@ export default class CommitDagTraversalService {
35
35
  /**
36
36
  * Creates a new CommitDagTraversalService.
37
37
  *
38
- * @param {Object} options
39
- * @param {import('./BitmapIndexReader.js').default} options.indexReader - Index reader for O(1) lookups
40
- * @param {import('../../ports/LoggerPort.js').default} [options.logger] - Logger instance
38
+ * @param {{ indexReader: import('./BitmapIndexReader.js').default, logger?: import('../../ports/LoggerPort.js').default }} options
41
39
  */
42
40
  constructor({ indexReader, logger = nullLogger }) {
43
41
  if (!indexReader) {
@@ -37,11 +37,9 @@ export default class DagPathFinding {
37
37
  /**
38
38
  * Creates a new DagPathFinding service.
39
39
  *
40
- * @param {Object} options
41
- * @param {import('./BitmapIndexReader.js').default} options.indexReader - Index reader for O(1) lookups
42
- * @param {import('../../ports/LoggerPort.js').default} [options.logger] - Logger instance
40
+ * @param {{ indexReader: import('./BitmapIndexReader.js').default, logger?: import('../../ports/LoggerPort.js').default }} options
43
41
  */
44
- constructor(/** @type {{ indexReader: import('./BitmapIndexReader.js').default, logger?: import('../../ports/LoggerPort.js').default }} */ { indexReader, logger = nullLogger } = /** @type {{ indexReader: import('./BitmapIndexReader.js').default }} */ ({})) {
42
+ constructor(/** @type {{ indexReader: import('./BitmapIndexReader.js').default, logger?: import('../../ports/LoggerPort.js').default }} */ { indexReader, logger = nullLogger }) {
45
43
  if (!indexReader) {
46
44
  throw new Error('DagPathFinding requires an indexReader');
47
45
  }
@@ -56,12 +54,7 @@ export default class DagPathFinding {
56
54
  * Returns the first path found, which is guaranteed to be a shortest path
57
55
  * (in terms of number of edges) due to BFS's level-order exploration.
58
56
  *
59
- * @param {Object} options - Path finding options
60
- * @param {string} options.from - Source node SHA
61
- * @param {string} options.to - Target node SHA
62
- * @param {number} [options.maxNodes=100000] - Maximum nodes to visit
63
- * @param {number} [options.maxDepth=1000] - Maximum path length
64
- * @param {AbortSignal} [options.signal] - Optional AbortSignal for cancellation
57
+ * @param {{ from: string, to: string, maxNodes?: number, maxDepth?: number, signal?: AbortSignal }} options - Path finding options
65
58
  * @returns {Promise<{found: boolean, path: string[], length: number}>} Path result
66
59
  */
67
60
  async findPath({
@@ -114,11 +107,7 @@ export default class DagPathFinding {
114
107
  /**
115
108
  * Finds the shortest path between two nodes using bidirectional BFS.
116
109
  *
117
- * @param {Object} options - Path finding options
118
- * @param {string} options.from - Source node SHA
119
- * @param {string} options.to - Target node SHA
120
- * @param {number} [options.maxDepth=1000] - Maximum search depth per direction
121
- * @param {AbortSignal} [options.signal] - Optional AbortSignal for cancellation
110
+ * @param {{ from: string, to: string, maxDepth?: number, signal?: AbortSignal }} options - Path finding options
122
111
  * @returns {Promise<{found: boolean, path: string[], length: number}>} Path result
123
112
  */
124
113
  async shortestPath({ from, to, maxDepth = DEFAULT_MAX_DEPTH, signal }) {
@@ -197,12 +186,7 @@ export default class DagPathFinding {
197
186
  /**
198
187
  * Finds shortest path using Dijkstra's algorithm with custom edge weights.
199
188
  *
200
- * @param {Object} options - Path finding options
201
- * @param {string} options.from - Starting SHA
202
- * @param {string} options.to - Target SHA
203
- * @param {(from: string, to: string) => number|Promise<number>} [options.weightProvider] - Async callback `(fromSha, toSha) => number`
204
- * @param {string} [options.direction='children'] - Edge direction: 'children' or 'parents'
205
- * @param {AbortSignal} [options.signal] - Optional AbortSignal for cancellation
189
+ * @param {{ from: string, to: string, weightProvider?: (from: string, to: string) => number|Promise<number>, direction?: string, signal?: AbortSignal }} options - Path finding options
206
190
  * @returns {Promise<{path: string[], totalCost: number}>} Path and cost
207
191
  * @throws {TraversalError} With code 'NO_PATH' if no path exists
208
192
  */
@@ -274,13 +258,7 @@ export default class DagPathFinding {
274
258
  /**
275
259
  * Finds shortest path using A* algorithm with heuristic guidance.
276
260
  *
277
- * @param {Object} options - Path finding options
278
- * @param {string} options.from - Starting SHA
279
- * @param {string} options.to - Target SHA
280
- * @param {(from: string, to: string) => number|Promise<number>} [options.weightProvider] - Async callback `(fromSha, toSha) => number`
281
- * @param {(sha: string, target: string) => number} [options.heuristicProvider] - Callback `(sha, targetSha) => number`
282
- * @param {string} [options.direction='children'] - Edge direction: 'children' or 'parents'
283
- * @param {AbortSignal} [options.signal] - Optional AbortSignal for cancellation
261
+ * @param {{ from: string, to: string, weightProvider?: (from: string, to: string) => number|Promise<number>, heuristicProvider?: (sha: string, target: string) => number, direction?: string, signal?: AbortSignal }} options - Path finding options
284
262
  * @returns {Promise<{path: string[], totalCost: number, nodesExplored: number}>} Path result
285
263
  * @throws {TraversalError} With code 'NO_PATH' if no path exists
286
264
  */
@@ -364,13 +342,7 @@ export default class DagPathFinding {
364
342
  /**
365
343
  * Bi-directional A* search - meets in the middle from both ends.
366
344
  *
367
- * @param {Object} options - Path finding options
368
- * @param {string} options.from - Starting SHA
369
- * @param {string} options.to - Target SHA
370
- * @param {(from: string, to: string) => number|Promise<number>} [options.weightProvider] - Async callback `(fromSha, toSha) => number`
371
- * @param {(sha: string, target: string) => number} [options.forwardHeuristic] - Callback for forward search
372
- * @param {(sha: string, target: string) => number} [options.backwardHeuristic] - Callback for backward search
373
- * @param {AbortSignal} [options.signal] - Optional AbortSignal for cancellation
345
+ * @param {{ from: string, to: string, weightProvider?: (from: string, to: string) => number|Promise<number>, forwardHeuristic?: (sha: string, target: string) => number, backwardHeuristic?: (sha: string, target: string) => number, signal?: AbortSignal }} options - Path finding options
374
346
  * @returns {Promise<{path: string[], totalCost: number, nodesExplored: number}>} Path result
375
347
  * @throws {TraversalError} With code 'NO_PATH' if no path exists
376
348
  */
@@ -462,18 +434,7 @@ export default class DagPathFinding {
462
434
  /**
463
435
  * Expands the forward frontier by one node in bidirectional A*.
464
436
  *
465
- * @param {Object} state - Forward expansion state
466
- * @param {import('../utils/MinHeap.js').default<string>} state.fwdHeap
467
- * @param {Set<string>} state.fwdVisited
468
- * @param {Map<string, number>} state.fwdGScore
469
- * @param {Map<string, string>} state.fwdPrevious
470
- * @param {Set<string>} state.bwdVisited
471
- * @param {Map<string, number>} state.bwdGScore
472
- * @param {(from: string, to: string) => number|Promise<number>} state.weightProvider
473
- * @param {(sha: string, target: string) => number} state.forwardHeuristic
474
- * @param {string} state.to
475
- * @param {number} state.mu
476
- * @param {string|null} state.meetingPoint
437
+ * @param {{ fwdHeap: import('../utils/MinHeap.js').default<string>, fwdVisited: Set<string>, fwdGScore: Map<string, number>, fwdPrevious: Map<string, string>, bwdVisited: Set<string>, bwdGScore: Map<string, number>, weightProvider: (from: string, to: string) => number|Promise<number>, forwardHeuristic: (sha: string, target: string) => number, to: string, mu: number, meetingPoint: string|null }} state - Forward expansion state
477
438
  * @returns {Promise<{explored: number, mu: number, meetingPoint: string|null}>}
478
439
  * @private
479
440
  */
@@ -535,18 +496,7 @@ export default class DagPathFinding {
535
496
  /**
536
497
  * Expands the backward frontier by one node in bidirectional A*.
537
498
  *
538
- * @param {Object} state - Backward expansion state
539
- * @param {import('../utils/MinHeap.js').default<string>} state.bwdHeap
540
- * @param {Set<string>} state.bwdVisited
541
- * @param {Map<string, number>} state.bwdGScore
542
- * @param {Map<string, string>} state.bwdNext
543
- * @param {Set<string>} state.fwdVisited
544
- * @param {Map<string, number>} state.fwdGScore
545
- * @param {(from: string, to: string) => number|Promise<number>} state.weightProvider
546
- * @param {(sha: string, target: string) => number} state.backwardHeuristic
547
- * @param {string} state.from
548
- * @param {number} state.mu
549
- * @param {string|null} state.meetingPoint
499
+ * @param {{ bwdHeap: import('../utils/MinHeap.js').default<string>, bwdVisited: Set<string>, bwdGScore: Map<string, number>, bwdNext: Map<string, string>, fwdVisited: Set<string>, fwdGScore: Map<string, number>, weightProvider: (from: string, to: string) => number|Promise<number>, backwardHeuristic: (sha: string, target: string) => number, from: string, mu: number, meetingPoint: string|null }} state - Backward expansion state
550
500
  * @returns {Promise<{explored: number, mu: number, meetingPoint: string|null}>}
551
501
  * @private
552
502
  */
@@ -32,12 +32,9 @@ export default class DagTopology {
32
32
  /**
33
33
  * Creates a new DagTopology service.
34
34
  *
35
- * @param {Object} options
36
- * @param {import('./BitmapIndexReader.js').default} options.indexReader - Index reader for O(1) lookups
37
- * @param {import('../../ports/LoggerPort.js').default} [options.logger] - Logger instance
38
- * @param {import('./DagTraversal.js').default} [options.traversal] - Traversal service for ancestor enumeration
35
+ * @param {{ indexReader: import('./BitmapIndexReader.js').default, logger?: import('../../ports/LoggerPort.js').default, traversal?: import('./DagTraversal.js').default }} options
39
36
  */
40
- constructor(/** @type {{ indexReader: import('./BitmapIndexReader.js').default, logger?: import('../../ports/LoggerPort.js').default, traversal?: import('./DagTraversal.js').default }} */ { indexReader, logger = nullLogger, traversal } = /** @type {{ indexReader: import('./BitmapIndexReader.js').default }} */ ({})) {
37
+ constructor({ indexReader, logger = nullLogger, traversal }) {
41
38
  if (!indexReader) {
42
39
  throw new Error('DagTopology requires an indexReader');
43
40
  }
@@ -67,11 +64,7 @@ export default class DagTopology {
67
64
  * An ancestor is "common" if it can be reached by following parent edges
68
65
  * from ALL of the input nodes.
69
66
  *
70
- * @param {Object} options - Common ancestor options
71
- * @param {string[]} options.shas - Array of node SHAs
72
- * @param {number} [options.maxResults=100] - Maximum ancestors to return
73
- * @param {number} [options.maxDepth=1000] - Maximum depth to search
74
- * @param {AbortSignal} [options.signal] - Optional AbortSignal for cancellation
67
+ * @param {{ shas: string[], maxResults?: number, maxDepth?: number, signal?: AbortSignal }} options - Common ancestor options
75
68
  * @returns {Promise<string[]>} Array of common ancestor SHAs
76
69
  */
77
70
  async commonAncestors({ shas, maxResults = 100, maxDepth = DEFAULT_MAX_DEPTH, signal }) {
@@ -119,12 +112,7 @@ export default class DagTopology {
119
112
  * Topological order ensures that for every directed edge A -> B, node A
120
113
  * is yielded before node B.
121
114
  *
122
- * @param {Object} options - Topological sort options
123
- * @param {string} options.start - Starting node SHA
124
- * @param {number} [options.maxNodes=100000] - Maximum nodes to yield
125
- * @param {TraversalDirection} [options.direction='forward'] - Direction
126
- * @param {boolean} [options.throwOnCycle=false] - If true, throws on cycle detection
127
- * @param {AbortSignal} [options.signal] - Optional AbortSignal for cancellation
115
+ * @param {{ start: string, maxNodes?: number, direction?: TraversalDirection, throwOnCycle?: boolean, signal?: AbortSignal }} options - Topological sort options
128
116
  * @yields {{sha: string, depth: number, parent: null}} Nodes in topological order
129
117
  * @throws {TraversalError} With code 'CYCLE_DETECTED' if throwOnCycle is true
130
118
  */
@@ -39,11 +39,9 @@ export default class DagTraversal {
39
39
  /**
40
40
  * Creates a new DagTraversal service.
41
41
  *
42
- * @param {Object} options
43
- * @param {import('./BitmapIndexReader.js').default} options.indexReader - Index reader for O(1) lookups
44
- * @param {import('../../ports/LoggerPort.js').default} [options.logger] - Logger instance
42
+ * @param {{ indexReader: import('./BitmapIndexReader.js').default, logger?: import('../../ports/LoggerPort.js').default }} options
45
43
  */
46
- constructor(/** @type {{ indexReader: import('./BitmapIndexReader.js').default, logger?: import('../../ports/LoggerPort.js').default }} */ { indexReader, logger = nullLogger } = /** @type {{ indexReader: import('./BitmapIndexReader.js').default }} */ ({})) {
44
+ constructor({ indexReader, logger = nullLogger }) {
47
45
  if (!indexReader) {
48
46
  throw new Error('DagTraversal requires an indexReader');
49
47
  }
@@ -73,12 +71,7 @@ export default class DagTraversal {
73
71
  * moving to depth N+1. This guarantees that nodes are yielded in order of
74
72
  * increasing distance from the start node.
75
73
  *
76
- * @param {Object} options - Traversal options
77
- * @param {string} options.start - Starting node SHA
78
- * @param {number} [options.maxNodes=100000] - Maximum nodes to visit
79
- * @param {number} [options.maxDepth=1000] - Maximum depth to traverse
80
- * @param {TraversalDirection} [options.direction='forward'] - Traversal direction
81
- * @param {AbortSignal} [options.signal] - Optional AbortSignal for cancellation
74
+ * @param {{ start: string, maxNodes?: number, maxDepth?: number, direction?: TraversalDirection, signal?: AbortSignal }} options - Traversal options
82
75
  * @yields {TraversalNode} Nodes in BFS order
83
76
  */
84
77
  async *bfs({
@@ -127,12 +120,7 @@ export default class DagTraversal {
127
120
  *
128
121
  * DFS explores as far as possible along each branch before backtracking.
129
122
  *
130
- * @param {Object} options - Traversal options
131
- * @param {string} options.start - Starting node SHA
132
- * @param {number} [options.maxNodes=100000] - Maximum nodes to visit
133
- * @param {number} [options.maxDepth=1000] - Maximum depth to traverse
134
- * @param {TraversalDirection} [options.direction='forward'] - Traversal direction
135
- * @param {AbortSignal} [options.signal] - Optional AbortSignal for cancellation
123
+ * @param {{ start: string, maxNodes?: number, maxDepth?: number, direction?: TraversalDirection, signal?: AbortSignal }} options - Traversal options
136
124
  * @yields {TraversalNode} Nodes in DFS pre-order
137
125
  */
138
126
  async *dfs({
@@ -180,11 +168,7 @@ export default class DagTraversal {
180
168
  /**
181
169
  * Yields all ancestors of a node (transitive closure going backwards).
182
170
  *
183
- * @param {Object} options - Traversal options
184
- * @param {string} options.sha - Starting node SHA
185
- * @param {number} [options.maxNodes=100000] - Maximum ancestor nodes to yield
186
- * @param {number} [options.maxDepth=1000] - Maximum generations to traverse
187
- * @param {AbortSignal} [options.signal] - Optional AbortSignal for cancellation
171
+ * @param {{ sha: string, maxNodes?: number, maxDepth?: number, signal?: AbortSignal }} options - Traversal options
188
172
  * @yields {TraversalNode} Ancestor nodes in BFS order
189
173
  */
190
174
  async *ancestors({ sha, maxNodes = DEFAULT_MAX_NODES, maxDepth = DEFAULT_MAX_DEPTH, signal }) {
@@ -194,11 +178,7 @@ export default class DagTraversal {
194
178
  /**
195
179
  * Yields all descendants of a node (transitive closure going forwards).
196
180
  *
197
- * @param {Object} options - Traversal options
198
- * @param {string} options.sha - Starting node SHA
199
- * @param {number} [options.maxNodes=100000] - Maximum descendant nodes to yield
200
- * @param {number} [options.maxDepth=1000] - Maximum generations to traverse
201
- * @param {AbortSignal} [options.signal] - Optional AbortSignal for cancellation
181
+ * @param {{ sha: string, maxNodes?: number, maxDepth?: number, signal?: AbortSignal }} options - Traversal options
202
182
  * @yields {TraversalNode} Descendant nodes in BFS order
203
183
  */
204
184
  async *descendants({ sha, maxNodes = DEFAULT_MAX_NODES, maxDepth = DEFAULT_MAX_DEPTH, signal }) {
@@ -211,11 +191,7 @@ export default class DagTraversal {
211
191
  * Delegates to the path-finding service's findPath if one is set,
212
192
  * otherwise performs its own BFS-based reachability check.
213
193
  *
214
- * @param {Object} options - Reachability options
215
- * @param {string} options.from - Source node SHA
216
- * @param {string} options.to - Target node SHA
217
- * @param {number} [options.maxDepth=1000] - Maximum search depth
218
- * @param {AbortSignal} [options.signal] - Optional AbortSignal for cancellation
194
+ * @param {{ from: string, to: string, maxDepth?: number, signal?: AbortSignal }} options - Reachability options
219
195
  * @returns {Promise<boolean>} True if a path exists
220
196
  */
221
197
  async isReachable({ from, to, maxDepth = DEFAULT_MAX_DEPTH, signal }) {