@git-stunts/git-warp 12.3.0 → 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 (114) hide show
  1. package/README.md +5 -6
  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/warp-graph.js +6 -6
  6. package/package.json +1 -1
  7. package/src/domain/WarpGraph.js +5 -35
  8. package/src/domain/crdt/VersionVector.js +1 -1
  9. package/src/domain/entities/GraphNode.js +1 -6
  10. package/src/domain/errors/ForkError.js +1 -1
  11. package/src/domain/errors/IndexError.js +1 -1
  12. package/src/domain/errors/OperationAbortedError.js +1 -1
  13. package/src/domain/errors/PatchError.js +1 -1
  14. package/src/domain/errors/PersistenceError.js +45 -0
  15. package/src/domain/errors/QueryError.js +1 -1
  16. package/src/domain/errors/SchemaUnsupportedError.js +1 -1
  17. package/src/domain/errors/SyncError.js +1 -1
  18. package/src/domain/errors/TraversalError.js +1 -1
  19. package/src/domain/errors/TrustError.js +1 -1
  20. package/src/domain/errors/WormholeError.js +1 -1
  21. package/src/domain/errors/index.js +1 -0
  22. package/src/domain/services/AdjacencyNeighborProvider.js +1 -4
  23. package/src/domain/services/AnchorMessageCodec.js +1 -3
  24. package/src/domain/services/AuditMessageCodec.js +1 -5
  25. package/src/domain/services/AuditReceiptService.js +2 -17
  26. package/src/domain/services/AuditVerifierService.js +2 -7
  27. package/src/domain/services/BitmapIndexBuilder.js +6 -12
  28. package/src/domain/services/BitmapIndexReader.js +7 -20
  29. package/src/domain/services/BitmapNeighborProvider.js +1 -3
  30. package/src/domain/services/BoundaryTransitionRecord.js +6 -23
  31. package/src/domain/services/CheckpointMessageCodec.js +1 -6
  32. package/src/domain/services/CheckpointSerializerV5.js +8 -12
  33. package/src/domain/services/CheckpointService.js +9 -39
  34. package/src/domain/services/CommitDagTraversalService.js +1 -3
  35. package/src/domain/services/DagPathFinding.js +9 -59
  36. package/src/domain/services/DagTopology.js +4 -16
  37. package/src/domain/services/DagTraversal.js +7 -31
  38. package/src/domain/services/Frontier.js +4 -6
  39. package/src/domain/services/GitLogParser.js +1 -2
  40. package/src/domain/services/GraphTraversal.js +14 -114
  41. package/src/domain/services/HealthCheckService.js +3 -9
  42. package/src/domain/services/HookInstaller.js +2 -8
  43. package/src/domain/services/HttpSyncServer.js +24 -25
  44. package/src/domain/services/IncrementalIndexUpdater.js +4 -6
  45. package/src/domain/services/IndexRebuildService.js +6 -52
  46. package/src/domain/services/IndexStalenessChecker.js +2 -3
  47. package/src/domain/services/JoinReducer.js +39 -65
  48. package/src/domain/services/LogicalBitmapIndexBuilder.js +1 -2
  49. package/src/domain/services/LogicalIndexBuildService.js +2 -6
  50. package/src/domain/services/LogicalIndexReader.js +1 -2
  51. package/src/domain/services/LogicalTraversal.js +13 -64
  52. package/src/domain/services/MaterializedViewService.js +4 -18
  53. package/src/domain/services/MigrationService.js +1 -4
  54. package/src/domain/services/ObserverView.js +1 -7
  55. package/src/domain/services/PatchBuilderV2.js +6 -18
  56. package/src/domain/services/PatchMessageCodec.js +1 -6
  57. package/src/domain/services/PropertyIndexBuilder.js +1 -2
  58. package/src/domain/services/PropertyIndexReader.js +1 -4
  59. package/src/domain/services/ProvenanceIndex.js +5 -7
  60. package/src/domain/services/ProvenancePayload.js +1 -1
  61. package/src/domain/services/QueryBuilder.js +3 -16
  62. package/src/domain/services/StateDiff.js +3 -9
  63. package/src/domain/services/StateSerializerV5.js +10 -10
  64. package/src/domain/services/StreamingBitmapIndexBuilder.js +13 -41
  65. package/src/domain/services/SyncAuthService.js +5 -32
  66. package/src/domain/services/SyncController.js +5 -25
  67. package/src/domain/services/SyncProtocol.js +4 -8
  68. package/src/domain/services/SyncTrustGate.js +4 -9
  69. package/src/domain/services/TemporalQuery.js +9 -27
  70. package/src/domain/services/TranslationCost.js +2 -8
  71. package/src/domain/services/WarpStateIndexBuilder.js +2 -4
  72. package/src/domain/services/WormholeService.js +9 -25
  73. package/src/domain/trust/TrustCrypto.js +1 -5
  74. package/src/domain/trust/TrustEvaluator.js +1 -8
  75. package/src/domain/trust/TrustRecordService.js +5 -10
  76. package/src/domain/types/TickReceipt.js +3 -7
  77. package/src/domain/types/WarpTypes.js +1 -5
  78. package/src/domain/types/WarpTypesV2.js +1 -8
  79. package/src/domain/utils/CachedValue.js +1 -4
  80. package/src/domain/utils/MinHeap.js +3 -3
  81. package/src/domain/utils/RefLayout.js +26 -0
  82. package/src/domain/utils/WriterId.js +2 -7
  83. package/src/domain/utils/canonicalCbor.js +1 -1
  84. package/src/domain/utils/defaultCodec.js +1 -1
  85. package/src/domain/utils/parseCursorBlob.js +4 -4
  86. package/src/domain/warp/PatchSession.js +3 -8
  87. package/src/domain/warp/Writer.js +3 -12
  88. package/src/domain/warp/_wire.js +2 -2
  89. package/src/domain/warp/_wiredMethods.d.ts +5 -7
  90. package/src/domain/warp/checkpoint.methods.js +1 -1
  91. package/src/domain/warp/fork.methods.js +1 -5
  92. package/src/domain/warp/materializeAdvanced.methods.js +3 -3
  93. package/src/domain/warp/patch.methods.js +6 -8
  94. package/src/domain/warp/provenance.methods.js +5 -5
  95. package/src/domain/warp/query.methods.js +9 -18
  96. package/src/domain/warp/subscribe.methods.js +2 -8
  97. package/src/globals.d.ts +7 -0
  98. package/src/infrastructure/adapters/BunHttpAdapter.js +14 -18
  99. package/src/infrastructure/adapters/ConsoleLogger.js +2 -9
  100. package/src/infrastructure/adapters/DenoHttpAdapter.js +15 -15
  101. package/src/infrastructure/adapters/GitGraphAdapter.js +234 -58
  102. package/src/infrastructure/adapters/InMemoryGraphAdapter.js +9 -2
  103. package/src/infrastructure/adapters/NodeHttpAdapter.js +14 -14
  104. package/src/infrastructure/adapters/WebCryptoAdapter.js +1 -2
  105. package/src/ports/BlobPort.js +2 -2
  106. package/src/ports/HttpServerPort.js +24 -2
  107. package/src/ports/RefPort.js +2 -1
  108. package/src/visualization/renderers/ascii/box.js +1 -1
  109. package/src/visualization/renderers/ascii/check.js +1 -5
  110. package/src/visualization/renderers/ascii/history.js +1 -6
  111. package/src/visualization/renderers/ascii/path.js +4 -22
  112. package/src/visualization/renderers/ascii/progress.js +1 -4
  113. package/src/visualization/renderers/ascii/seek.js +1 -5
  114. package/src/visualization/renderers/ascii/table.js +1 -3
@@ -44,6 +44,28 @@ export { normalizeRawOp, lowerCanonicalOp } from './OpNormalizer.js';
44
44
  * always produces an empty Map for them.
45
45
  */
46
46
 
47
+ /**
48
+ * @typedef {Object} OpLike
49
+ * @property {string} type - Operation type discriminator
50
+ * @property {string} [node] - Node ID (for NodeAdd, NodeRemove, PropSet)
51
+ * @property {import('../crdt/Dot.js').Dot} [dot] - Dot identifier (for NodeAdd, EdgeAdd)
52
+ * @property {string[]} [observedDots] - Encoded dots to remove (for NodeRemove, EdgeRemove)
53
+ * @property {string} [from] - Source node ID (for EdgeAdd, EdgeRemove)
54
+ * @property {string} [to] - Target node ID (for EdgeAdd, EdgeRemove)
55
+ * @property {string} [label] - Edge label (for EdgeAdd, EdgeRemove)
56
+ * @property {string} [key] - Property key (for PropSet)
57
+ * @property {unknown} [value] - Property value (for PropSet)
58
+ * @property {string} [oid] - Blob object ID (for BlobValue)
59
+ */
60
+
61
+ /**
62
+ * @typedef {Object} PatchLike
63
+ * @property {string} writer - Writer ID who created this patch
64
+ * @property {number} lamport - Lamport timestamp of this patch
65
+ * @property {OpLike[]} ops - Ordered array of operations
66
+ * @property {Map<string, number>|Record<string, number>} context - Version vector context
67
+ */
68
+
47
69
  /**
48
70
  * Creates an empty V5 state with all CRDT structures initialized.
49
71
  *
@@ -82,16 +104,7 @@ export function createEmptyStateV5() {
82
104
  * clone the state first using `cloneStateV5()`.
83
105
  *
84
106
  * @param {WarpStateV5} state - The state to mutate. Modified in place.
85
- * @param {Object} op - The operation to apply
86
- * @param {string} op.type - One of: 'NodeAdd', 'NodeRemove', 'EdgeAdd', 'EdgeRemove', 'PropSet', 'BlobValue'
87
- * @param {string} [op.node] - Node ID (for NodeAdd, NodeRemove, PropSet)
88
- * @param {import('../crdt/Dot.js').Dot} [op.dot] - Dot identifier (for NodeAdd, EdgeAdd)
89
- * @param {string[]} [op.observedDots] - Encoded dots to remove (for NodeRemove, EdgeRemove)
90
- * @param {string} [op.from] - Source node ID (for EdgeAdd, EdgeRemove)
91
- * @param {string} [op.to] - Target node ID (for EdgeAdd, EdgeRemove)
92
- * @param {string} [op.label] - Edge label (for EdgeAdd, EdgeRemove)
93
- * @param {string} [op.key] - Property key (for PropSet)
94
- * @param {unknown} [op.value] - Property value (for PropSet)
107
+ * @param {OpLike} op - The operation to apply
95
108
  * @param {import('../utils/EventId.js').EventId} eventId - Event ID for causality tracking
96
109
  * @returns {void}
97
110
  */
@@ -349,7 +362,7 @@ export function applyOpV2(state, op, eventId) {
349
362
  * - EdgeRemove -> EdgeTombstone (CRDT tombstone semantics)
350
363
  * - All others pass through unchanged
351
364
  *
352
- * @const {Object<string, string>}
365
+ * @const {Record<string, string>}
353
366
  */
354
367
  const RECEIPT_OP_TYPE = {
355
368
  NodeAdd: 'NodeAdd',
@@ -376,9 +389,7 @@ const VALID_RECEIPT_OPS = new Set(OP_TYPES);
376
389
  * this add operation is effective or redundant (idempotent re-delivery).
377
390
  *
378
391
  * @param {import('../crdt/ORSet.js').ORSet} orset - The node OR-Set containing alive nodes
379
- * @param {Object} op - The NodeAdd operation
380
- * @param {string} op.node - The node ID being added
381
- * @param {import('../crdt/Dot.js').Dot} op.dot - The dot uniquely identifying this add event
392
+ * @param {{node: string, dot: import('../crdt/Dot.js').Dot}} op - The NodeAdd operation
382
393
  * @returns {{target: string, result: 'applied'|'redundant'}} Outcome with node ID as target
383
394
  */
384
395
  function nodeAddOutcome(orset, op) {
@@ -399,9 +410,7 @@ function nodeAddOutcome(orset, op) {
399
410
  * observed at the time the remove was issued.
400
411
  *
401
412
  * @param {import('../crdt/ORSet.js').ORSet} orset - The node OR-Set containing alive nodes
402
- * @param {Object} op - The NodeRemove operation
403
- * @param {string} [op.node] - The node ID being removed (may be absent for dot-only removes)
404
- * @param {string[]} op.observedDots - Array of encoded dots that were observed when the remove was issued
413
+ * @param {{node?: string, observedDots: string[] | Set<string>}} op - The NodeRemove operation
405
414
  * @returns {{target: string, result: 'applied'|'redundant'}} Outcome with node ID (or '*') as target
406
415
  */
407
416
  function nodeRemoveOutcome(orset, op) {
@@ -431,11 +440,7 @@ function nodeRemoveOutcome(orset, op) {
431
440
  * Unlike nodes, edges are keyed by the composite (from, to, label) tuple.
432
441
  *
433
442
  * @param {import('../crdt/ORSet.js').ORSet} orset - The edge OR-Set containing alive edges
434
- * @param {Object} op - The EdgeAdd operation
435
- * @param {string} op.from - Source node ID
436
- * @param {string} op.to - Target node ID
437
- * @param {string} op.label - Edge label
438
- * @param {import('../crdt/Dot.js').Dot} op.dot - The dot uniquely identifying this add event
443
+ * @param {{from: string, to: string, label: string, dot: import('../crdt/Dot.js').Dot}} op - The EdgeAdd operation
439
444
  * @param {string} edgeKey - Pre-encoded edge key (from\0to\0label format)
440
445
  * @returns {{target: string, result: 'applied'|'redundant'}} Outcome with encoded edge key as target
441
446
  */
@@ -460,11 +465,7 @@ function edgeAddOutcome(orset, op, edgeKey) {
460
465
  * otherwise falls back to '*' for wildcard/unknown targets.
461
466
  *
462
467
  * @param {import('../crdt/ORSet.js').ORSet} orset - The edge OR-Set containing alive edges
463
- * @param {Object} op - The EdgeRemove operation
464
- * @param {string} [op.from] - Source node ID (optional for computing target)
465
- * @param {string} [op.to] - Target node ID (optional for computing target)
466
- * @param {string} [op.label] - Edge label (optional for computing target)
467
- * @param {string[]} op.observedDots - Array of encoded dots that were observed when the remove was issued
468
+ * @param {{from?: string, to?: string, label?: string, observedDots: string[] | Set<string>}} op - The EdgeRemove operation
468
469
  * @returns {{target: string, result: 'applied'|'redundant'}} Outcome with encoded edge key (or '*') as target
469
470
  */
470
471
  function edgeRemoveOutcome(orset, op) {
@@ -535,9 +536,7 @@ function propOutcomeForKey(propMap, key, eventId) {
535
536
  * Determines the receipt outcome for a PropSet/NodePropSet operation.
536
537
  *
537
538
  * @param {Map<string, import('../crdt/LWW.js').LWWRegister<unknown>>} propMap
538
- * @param {Object} op
539
- * @param {string} op.node - Node ID owning the property
540
- * @param {string} op.key - Property key/name
539
+ * @param {{node: string, key: string}} op - The PropSet or NodePropSet operation
541
540
  * @param {import('../utils/EventId.js').EventId} eventId
542
541
  * @returns {{target: string, result: 'applied'|'superseded'|'redundant', reason?: string}}
543
542
  */
@@ -549,11 +548,7 @@ function propSetOutcome(propMap, op, eventId) {
549
548
  * Determines the receipt outcome for an EdgePropSet operation.
550
549
  *
551
550
  * @param {Map<string, import('../crdt/LWW.js').LWWRegister<unknown>>} propMap
552
- * @param {Object} op
553
- * @param {string} op.from
554
- * @param {string} op.to
555
- * @param {string} op.label
556
- * @param {string} op.key
551
+ * @param {{from: string, to: string, label: string, key: string}} op - The EdgePropSet operation
557
552
  * @param {import('../utils/EventId.js').EventId} eventId
558
553
  * @returns {{target: string, result: 'applied'|'superseded'|'redundant', reason?: string}}
559
554
  */
@@ -577,10 +572,7 @@ function foldPatchDot(frontier, writer, lamport) {
577
572
  /**
578
573
  * Merges a patch's context into state and folds the patch dot.
579
574
  * @param {WarpStateV5} state
580
- * @param {Object} patch
581
- * @param {string} patch.writer
582
- * @param {number} patch.lamport
583
- * @param {Map<string, number>|{[x: string]: number}} patch.context
575
+ * @param {{writer: string, lamport: number, context: Map<string, number>|Record<string, number>}} patch
584
576
  */
585
577
  function updateFrontierFromPatch(state, patch) {
586
578
  const contextVV = patch.context instanceof Map
@@ -594,11 +586,7 @@ function updateFrontierFromPatch(state, patch) {
594
586
  * Applies a patch to state without receipt collection (zero overhead).
595
587
  *
596
588
  * @param {WarpStateV5} state - The state to mutate in place
597
- * @param {Object} patch - The patch to apply
598
- * @param {string} patch.writer
599
- * @param {number} patch.lamport
600
- * @param {Array<{type: string, node?: string, dot?: import('../crdt/Dot.js').Dot, observedDots?: string[], from?: string, to?: string, label?: string, key?: string, value?: unknown, oid?: string}>} patch.ops
601
- * @param {Map<string, number>|{[x: string]: number}} patch.context
589
+ * @param {PatchLike} patch - The patch to apply
602
590
  * @param {string} patchSha - Git SHA of the patch commit
603
591
  * @returns {WarpStateV5} The mutated state
604
592
  */
@@ -819,11 +807,7 @@ function collectEdgeRemovals(diff, state, before) {
819
807
  * winner changes. Redundant ops produce no diff entries.
820
808
  *
821
809
  * @param {WarpStateV5} state - The state to mutate in place
822
- * @param {Object} patch - The patch to apply
823
- * @param {string} patch.writer
824
- * @param {number} patch.lamport
825
- * @param {Array<import('../types/WarpTypesV2.js').OpV2 | {type: string}>} patch.ops
826
- * @param {Map<string, number>|{[x: string]: number}} patch.context
810
+ * @param {PatchLike} patch - The patch to apply
827
811
  * @param {string} patchSha - Git SHA of the patch commit
828
812
  * @returns {{state: WarpStateV5, diff: import('../types/PatchDiff.js').PatchDiff}}
829
813
  */
@@ -847,11 +831,7 @@ export function applyWithDiff(state, patch, patchSha) {
847
831
  * Applies a patch to state with receipt collection for provenance tracking.
848
832
  *
849
833
  * @param {WarpStateV5} state - The state to mutate in place
850
- * @param {Object} patch - The patch to apply
851
- * @param {string} patch.writer
852
- * @param {number} patch.lamport
853
- * @param {Array<{type: string, node?: string, dot?: import('../crdt/Dot.js').Dot, observedDots?: string[], from?: string, to?: string, label?: string, key?: string, value?: unknown, oid?: string}>} patch.ops
854
- * @param {Map<string, number>|{[x: string]: number}} patch.context
834
+ * @param {PatchLike} patch - The patch to apply
855
835
  * @param {string} patchSha - Git SHA of the patch commit
856
836
  * @returns {{state: WarpStateV5, receipt: import('../types/TickReceipt.js').TickReceipt}}
857
837
  */
@@ -883,10 +863,10 @@ export function applyWithReceipt(state, patch, patchSha) {
883
863
  break;
884
864
  case 'PropSet':
885
865
  case 'NodePropSet':
886
- outcome = propSetOutcome(state.prop, /** @type {{node: string, key: string, value: *}} */ (canonOp), eventId);
866
+ outcome = propSetOutcome(state.prop, /** @type {{node: string, key: string, value: unknown}} */ (canonOp), eventId);
887
867
  break;
888
868
  case 'EdgePropSet':
889
- outcome = edgePropSetOutcome(state.prop, /** @type {{from: string, to: string, label: string, key: string, value: *}} */ (canonOp), eventId);
869
+ outcome = edgePropSetOutcome(state.prop, /** @type {{from: string, to: string, label: string, key: string, value: unknown}} */ (canonOp), eventId);
890
870
  break;
891
871
  default: {
892
872
  // Unknown or BlobValue — always applied
@@ -940,11 +920,7 @@ export function applyWithReceipt(state, patch, patchSha) {
940
920
  * clone the state first using `cloneStateV5()`.
941
921
  *
942
922
  * @param {WarpStateV5} state - The state to mutate. Modified in place.
943
- * @param {Object} patch - The patch to apply
944
- * @param {string} patch.writer - Writer ID who created this patch
945
- * @param {number} patch.lamport - Lamport timestamp of this patch
946
- * @param {Array<{type: string, node?: string, dot?: import('../crdt/Dot.js').Dot, observedDots?: string[], from?: string, to?: string, label?: string, key?: string, value?: unknown, oid?: string}>} patch.ops - Array of operations to apply
947
- * @param {Map<string, number>|{[x: string]: number}} patch.context - Version vector context (Map or serialized form)
923
+ * @param {PatchLike} patch - The patch to apply
948
924
  * @param {string} patchSha - The Git SHA of the patch commit (used for EventId creation)
949
925
  * @param {boolean} [collectReceipts=false] - When true, computes and returns receipt data
950
926
  * @returns {WarpStateV5|{state: WarpStateV5, receipt: import('../types/TickReceipt.js').TickReceipt}}
@@ -1053,11 +1029,9 @@ function mergeEdgeBirthEvent(a, b) {
1053
1029
  * - When `options.receipts` is true, returns a TickReceipt per patch for
1054
1030
  * provenance tracking and debugging.
1055
1031
  *
1056
- * @param {Array<{patch: {writer: string, lamport: number, ops: Array<{type: string, node?: string, dot?: import('../crdt/Dot.js').Dot, observedDots?: string[], from?: string, to?: string, label?: string, key?: string, value?: unknown, oid?: string}>, context: Map<string, number>|{[x: string]: number}}, sha: string}>} patches - Array of patch objects with their Git SHAs
1032
+ * @param {Array<{patch: PatchLike, sha: string}>} patches - Array of patch objects with their Git SHAs
1057
1033
  * @param {WarpStateV5} [initialState] - Optional starting state (for incremental materialization from checkpoint)
1058
- * @param {Object} [options] - Optional configuration
1059
- * @param {boolean} [options.receipts=false] - When true, collect and return TickReceipts
1060
- * @param {boolean} [options.trackDiff=false] - When true, collect and return PatchDiff
1034
+ * @param {{receipts?: boolean, trackDiff?: boolean}} [options] - Optional configuration
1061
1035
  * @returns {WarpStateV5|{state: WarpStateV5, receipts: import('../types/TickReceipt.js').TickReceipt[]}|{state: WarpStateV5, diff: import('../types/PatchDiff.js').PatchDiff}}
1062
1036
  * Returns state directly when no options;
1063
1037
  * returns {state, receipts} when receipts is true;
@@ -24,8 +24,7 @@ const MAX_LOCAL_ID = 1 << 24;
24
24
 
25
25
  export default class LogicalBitmapIndexBuilder {
26
26
  /**
27
- * @param {Object} [options]
28
- * @param {import('../../ports/CodecPort.js').default} [options.codec]
27
+ * @param {{ codec?: import('../../ports/CodecPort.js').default }} [options]
29
28
  */
30
29
  constructor({ codec } = {}) {
31
30
  this._codec = codec || defaultCodec;
@@ -17,9 +17,7 @@ import { nodeVisibleV5, edgeVisibleV5 } from './StateSerializerV5.js';
17
17
 
18
18
  export default class LogicalIndexBuildService {
19
19
  /**
20
- * @param {Object} [options]
21
- * @param {import('../../ports/CodecPort.js').default} [options.codec]
22
- * @param {import('../../ports/LoggerPort.js').default} [options.logger]
20
+ * @param {{ codec?: import('../../ports/CodecPort.js').default, logger?: import('../../ports/LoggerPort.js').default }} [options]
23
21
  */
24
22
  constructor({ codec, logger } = {}) {
25
23
  this._codec = codec || defaultCodec;
@@ -30,9 +28,7 @@ export default class LogicalIndexBuildService {
30
28
  * Builds a complete logical index from materialized state.
31
29
  *
32
30
  * @param {import('./JoinReducer.js').WarpStateV5} state
33
- * @param {Object} [options]
34
- * @param {Record<string, { nodeToGlobal: Record<string, number>, nextLocalId: number }>} [options.existingMeta] - Prior meta shards for ID stability
35
- * @param {Record<string, number>|Array<[string, number]>} [options.existingLabels] - Prior label registry for append-only stability
31
+ * @param {{ existingMeta?: Record<string, { nodeToGlobal: Record<string, number>, nextLocalId: number }>, existingLabels?: Record<string, number>|Array<[string, number]> }} [options]
36
32
  * @returns {{ tree: Record<string, Uint8Array>, receipt: Record<string, unknown> }}
37
33
  */
38
34
  build(state, options = {}) {
@@ -89,8 +89,7 @@ function classifyShards(items) {
89
89
 
90
90
  export default class LogicalIndexReader {
91
91
  /**
92
- * @param {Object} [options]
93
- * @param {import('../../ports/CodecPort.js').default} [options.codec]
92
+ * @param {{ codec?: import('../../ports/CodecPort.js').default }} [options]
94
93
  */
95
94
  constructor({ codec } = {}) {
96
95
  this._codec = codec || defaultCodec;
@@ -83,10 +83,7 @@ export default class LogicalTraversal {
83
83
  * multiple starts or no start at all (topologicalSort, commonAncestors).
84
84
  *
85
85
  * @private
86
- * @param {Object} opts - The traversal options
87
- * @param {'out'|'in'|'both'} [opts.dir] - Edge direction to follow
88
- * @param {string|string[]} [opts.labelFilter] - Edge label(s) to include
89
- * @param {number} [opts.maxDepth] - Maximum depth to traverse
86
+ * @param {{ dir?: 'out'|'in'|'both', labelFilter?: string|string[], maxDepth?: number }} opts - The traversal options
90
87
  * @returns {Promise<{engine: GraphTraversal, direction: 'out'|'in'|'both', options: {labels?: Set<string>}|undefined, depthLimit: number}>}
91
88
  * @throws {TraversalError} If the direction is invalid (INVALID_DIRECTION)
92
89
  * @throws {TraversalError} If the labelFilter is invalid (INVALID_LABEL_FILTER)
@@ -120,10 +117,7 @@ export default class LogicalTraversal {
120
117
  *
121
118
  * @private
122
119
  * @param {string} start - The starting node ID for traversal
123
- * @param {Object} opts - The traversal options
124
- * @param {'out'|'in'|'both'} [opts.dir] - Edge direction to follow
125
- * @param {string|string[]} [opts.labelFilter] - Edge label(s) to include
126
- * @param {number} [opts.maxDepth] - Maximum depth to traverse
120
+ * @param {{ dir?: 'out'|'in'|'both', labelFilter?: string|string[], maxDepth?: number }} opts - The traversal options
127
121
  * @returns {Promise<{engine: GraphTraversal, direction: 'out'|'in'|'both', options: {labels?: Set<string>}|undefined, depthLimit: number}>}
128
122
  * @throws {TraversalError} If the start node is not found (NODE_NOT_FOUND)
129
123
  * @throws {TraversalError} If the direction is invalid (INVALID_DIRECTION)
@@ -146,10 +140,7 @@ export default class LogicalTraversal {
146
140
  * Breadth-first traversal.
147
141
  *
148
142
  * @param {string} start - Starting node ID
149
- * @param {Object} [options] - Traversal options
150
- * @param {number} [options.maxDepth] - Maximum depth to traverse
151
- * @param {'out'|'in'|'both'} [options.dir] - Edge direction to follow
152
- * @param {string|string[]} [options.labelFilter] - Edge label(s) to include
143
+ * @param {{ maxDepth?: number, dir?: 'out'|'in'|'both', labelFilter?: string|string[] }} [options] - Traversal options
153
144
  * @returns {Promise<string[]>} Node IDs in visit order
154
145
  * @throws {TraversalError} If the start node is not found or direction is invalid
155
146
  */
@@ -169,10 +160,7 @@ export default class LogicalTraversal {
169
160
  * Depth-first traversal (pre-order).
170
161
  *
171
162
  * @param {string} start - Starting node ID
172
- * @param {Object} [options] - Traversal options
173
- * @param {number} [options.maxDepth] - Maximum depth to traverse
174
- * @param {'out'|'in'|'both'} [options.dir] - Edge direction to follow
175
- * @param {string|string[]} [options.labelFilter] - Edge label(s) to include
163
+ * @param {{ maxDepth?: number, dir?: 'out'|'in'|'both', labelFilter?: string|string[] }} [options] - Traversal options
176
164
  * @returns {Promise<string[]>} Node IDs in visit order
177
165
  * @throws {TraversalError} If the start node is not found or direction is invalid
178
166
  */
@@ -193,10 +181,7 @@ export default class LogicalTraversal {
193
181
  *
194
182
  * @param {string} from - Source node ID
195
183
  * @param {string} to - Target node ID
196
- * @param {Object} [options] - Traversal options
197
- * @param {number} [options.maxDepth] - Maximum search depth
198
- * @param {'out'|'in'|'both'} [options.dir] - Edge direction to follow
199
- * @param {string|string[]} [options.labelFilter] - Edge label(s) to include
184
+ * @param {{ maxDepth?: number, dir?: 'out'|'in'|'both', labelFilter?: string|string[] }} [options] - Traversal options
200
185
  * @returns {Promise<{found: boolean, path: string[], length: number}>}
201
186
  * When `found` is true, `path` contains the node IDs from `from` to `to` and
202
187
  * `length` is the hop count. When `found` is false, `path` is empty and `length` is -1.
@@ -219,9 +204,7 @@ export default class LogicalTraversal {
219
204
  * Connected component (undirected by default).
220
205
  *
221
206
  * @param {string} start - Starting node ID
222
- * @param {Object} [options] - Traversal options
223
- * @param {number} [options.maxDepth] - Maximum depth to traverse (default: 1000)
224
- * @param {string|string[]} [options.labelFilter] - Edge label(s) to include
207
+ * @param {{ maxDepth?: number, labelFilter?: string|string[] }} [options] - Traversal options
225
208
  * @returns {Promise<string[]>} Node IDs in visit order
226
209
  * @throws {TraversalError} If the start node is not found
227
210
  */
@@ -236,11 +219,7 @@ export default class LogicalTraversal {
236
219
  *
237
220
  * @param {string} from - Source node ID
238
221
  * @param {string} to - Target node ID
239
- * @param {Object} [options] - Traversal options
240
- * @param {number} [options.maxDepth] - Maximum search depth
241
- * @param {'out'|'in'|'both'} [options.dir] - Edge direction to follow
242
- * @param {string|string[]} [options.labelFilter] - Edge label(s) to include
243
- * @param {AbortSignal} [options.signal] - Abort signal
222
+ * @param {{ maxDepth?: number, dir?: 'out'|'in'|'both', labelFilter?: string|string[], signal?: AbortSignal }} [options] - Traversal options
244
223
  * @returns {Promise<{reachable: boolean}>}
245
224
  */
246
225
  async isReachable(from, to, options = {}) {
@@ -262,12 +241,7 @@ export default class LogicalTraversal {
262
241
  *
263
242
  * @param {string} from - Source node ID
264
243
  * @param {string} to - Target node ID
265
- * @param {Object} [options] - Traversal options
266
- * @param {'out'|'in'|'both'} [options.dir] - Edge direction to follow
267
- * @param {string|string[]} [options.labelFilter] - Edge label(s) to include
268
- * @param {(from: string, to: string, label: string) => number | Promise<number>} [options.weightFn] - Edge weight function
269
- * @param {(nodeId: string) => number | Promise<number>} [options.nodeWeightFn] - Node weight function (mutually exclusive with weightFn)
270
- * @param {AbortSignal} [options.signal] - Abort signal
244
+ * @param {{ dir?: 'out'|'in'|'both', labelFilter?: string|string[], weightFn?: (from: string, to: string, label: string) => number | Promise<number>, nodeWeightFn?: (nodeId: string) => number | Promise<number>, signal?: AbortSignal }} [options] - Traversal options
271
245
  * @returns {Promise<{path: string[], totalCost: number}>}
272
246
  * @throws {TraversalError} code 'NO_PATH' if unreachable
273
247
  * @throws {TraversalError} code 'E_WEIGHT_FN_CONFLICT' if both weightFn and nodeWeightFn provided
@@ -292,13 +266,7 @@ export default class LogicalTraversal {
292
266
  *
293
267
  * @param {string} from - Source node ID
294
268
  * @param {string} to - Target node ID
295
- * @param {Object} [options] - Traversal options
296
- * @param {'out'|'in'|'both'} [options.dir] - Edge direction to follow
297
- * @param {string|string[]} [options.labelFilter] - Edge label(s) to include
298
- * @param {(from: string, to: string, label: string) => number | Promise<number>} [options.weightFn] - Edge weight function
299
- * @param {(nodeId: string) => number | Promise<number>} [options.nodeWeightFn] - Node weight function (mutually exclusive with weightFn)
300
- * @param {(nodeId: string, goalId: string) => number} [options.heuristicFn] - Heuristic function
301
- * @param {AbortSignal} [options.signal] - Abort signal
269
+ * @param {{ dir?: 'out'|'in'|'both', labelFilter?: string|string[], weightFn?: (from: string, to: string, label: string) => number | Promise<number>, nodeWeightFn?: (nodeId: string) => number | Promise<number>, heuristicFn?: (nodeId: string, goalId: string) => number, signal?: AbortSignal }} [options] - Traversal options
302
270
  * @returns {Promise<{path: string[], totalCost: number, nodesExplored: number}>}
303
271
  * @throws {TraversalError} code 'NO_PATH' if unreachable
304
272
  * @throws {TraversalError} code 'E_WEIGHT_FN_CONFLICT' if both weightFn and nodeWeightFn provided
@@ -326,13 +294,7 @@ export default class LogicalTraversal {
326
294
  *
327
295
  * @param {string} from - Source node ID
328
296
  * @param {string} to - Target node ID
329
- * @param {Object} [options] - Traversal options
330
- * @param {string|string[]} [options.labelFilter] - Edge label(s) to include
331
- * @param {(from: string, to: string, label: string) => number | Promise<number>} [options.weightFn] - Edge weight function
332
- * @param {(nodeId: string) => number | Promise<number>} [options.nodeWeightFn] - Node weight function (mutually exclusive with weightFn)
333
- * @param {(nodeId: string, goalId: string) => number} [options.forwardHeuristic] - Forward heuristic
334
- * @param {(nodeId: string, goalId: string) => number} [options.backwardHeuristic] - Backward heuristic
335
- * @param {AbortSignal} [options.signal] - Abort signal
297
+ * @param {{ labelFilter?: string|string[], weightFn?: (from: string, to: string, label: string) => number | Promise<number>, nodeWeightFn?: (nodeId: string) => number | Promise<number>, forwardHeuristic?: (nodeId: string, goalId: string) => number, backwardHeuristic?: (nodeId: string, goalId: string) => number, signal?: AbortSignal }} [options] - Traversal options
336
298
  * @returns {Promise<{path: string[], totalCost: number, nodesExplored: number}>}
337
299
  * @throws {TraversalError} code 'NO_PATH' if unreachable
338
300
  * @throws {TraversalError} code 'E_WEIGHT_FN_CONFLICT' if both weightFn and nodeWeightFn provided
@@ -365,11 +327,7 @@ export default class LogicalTraversal {
365
327
  * Topological sort (Kahn's algorithm).
366
328
  *
367
329
  * @param {string|string[]} start - One or more start nodes
368
- * @param {Object} [options] - Traversal options
369
- * @param {'out'|'in'|'both'} [options.dir] - Edge direction to follow
370
- * @param {string|string[]} [options.labelFilter] - Edge label(s) to include
371
- * @param {boolean} [options.throwOnCycle] - Whether to throw on cycle detection
372
- * @param {AbortSignal} [options.signal] - Abort signal
330
+ * @param {{ dir?: 'out'|'in'|'both', labelFilter?: string|string[], throwOnCycle?: boolean, signal?: AbortSignal }} [options] - Traversal options
373
331
  * @returns {Promise<{sorted: string[], hasCycle: boolean}>}
374
332
  * @throws {TraversalError} code 'ERR_GRAPH_HAS_CYCLES' if throwOnCycle and cycle found
375
333
  * @throws {TraversalError} code 'NODE_NOT_FOUND' if a start node does not exist
@@ -405,11 +363,7 @@ export default class LogicalTraversal {
405
363
  * Direction is fixed to 'in' (backward BFS).
406
364
  *
407
365
  * @param {string[]} nodes - Nodes to find common ancestors of
408
- * @param {Object} [options] - Traversal options
409
- * @param {number} [options.maxDepth] - Maximum search depth
410
- * @param {string|string[]} [options.labelFilter] - Edge label(s) to include
411
- * @param {number} [options.maxResults] - Maximum number of results
412
- * @param {AbortSignal} [options.signal] - Abort signal
366
+ * @param {{ maxDepth?: number, labelFilter?: string|string[], maxResults?: number, signal?: AbortSignal }} [options] - Traversal options
413
367
  * @returns {Promise<{ancestors: string[]}>}
414
368
  * @throws {TraversalError} code 'NODE_NOT_FOUND' if a node does not exist
415
369
  */
@@ -443,12 +397,7 @@ export default class LogicalTraversal {
443
397
  *
444
398
  * @param {string} from - Source node ID
445
399
  * @param {string} to - Target node ID
446
- * @param {Object} [options] - Traversal options
447
- * @param {'out'|'in'|'both'} [options.dir] - Edge direction to follow
448
- * @param {string|string[]} [options.labelFilter] - Edge label(s) to include
449
- * @param {(from: string, to: string, label: string) => number | Promise<number>} [options.weightFn] - Edge weight function
450
- * @param {(nodeId: string) => number | Promise<number>} [options.nodeWeightFn] - Node weight function (mutually exclusive with weightFn)
451
- * @param {AbortSignal} [options.signal] - Abort signal
400
+ * @param {{ dir?: 'out'|'in'|'both', labelFilter?: string|string[], weightFn?: (from: string, to: string, label: string) => number | Promise<number>, nodeWeightFn?: (nodeId: string) => number | Promise<number>, signal?: AbortSignal }} [options] - Traversal options
452
401
  * @returns {Promise<{path: string[], totalCost: number}>}
453
402
  * @throws {TraversalError} code 'ERR_GRAPH_HAS_CYCLES' if graph has cycles
454
403
  * @throws {TraversalError} code 'NO_PATH' if unreachable
@@ -207,11 +207,7 @@ function canonicalizeNeighborSignatures(edges) {
207
207
  /**
208
208
  * Compares bitmap index neighbors against ground-truth adjacency for one node.
209
209
  *
210
- * @param {Object} params
211
- * @param {string} params.nodeId
212
- * @param {string} params.direction
213
- * @param {LogicalIndex} params.logicalIndex
214
- * @param {Map<string, Array<{neighborId: string, label: string}>>} params.truthMap
210
+ * @param {{ nodeId: string, direction: string, logicalIndex: LogicalIndex, truthMap: Map<string, Array<{neighborId: string, label: string}>> }} params
215
211
  * @returns {VerifyError|null}
216
212
  */
217
213
  function compareNodeDirection({ nodeId, direction, logicalIndex, truthMap }) {
@@ -232,9 +228,7 @@ function compareNodeDirection({ nodeId, direction, logicalIndex, truthMap }) {
232
228
 
233
229
  export default class MaterializedViewService {
234
230
  /**
235
- * @param {Object} [options]
236
- * @param {import('../../ports/CodecPort.js').default} [options.codec]
237
- * @param {import('../../ports/LoggerPort.js').default} [options.logger]
231
+ * @param {{ codec?: import('../../ports/CodecPort.js').default, logger?: import('../../ports/LoggerPort.js').default }} [options]
238
232
  */
239
233
  constructor({ codec, logger } = {}) {
240
234
  this._codec = codec || defaultCodec;
@@ -308,10 +302,7 @@ export default class MaterializedViewService {
308
302
  /**
309
303
  * Applies a PatchDiff incrementally to an existing index tree.
310
304
  *
311
- * @param {Object} params
312
- * @param {Record<string, Uint8Array>} params.existingTree
313
- * @param {import('../types/PatchDiff.js').PatchDiff} params.diff
314
- * @param {import('./JoinReducer.js').WarpStateV5} params.state
305
+ * @param {{ existingTree: Record<string, Uint8Array>, diff: import('../types/PatchDiff.js').PatchDiff, state: import('./JoinReducer.js').WarpStateV5 }} params
315
306
  * @returns {BuildResult}
316
307
  */
317
308
  applyDiff({ existingTree, diff, state }) {
@@ -345,12 +336,7 @@ export default class MaterializedViewService {
345
336
  * Verifies index integrity by sampling alive nodes and comparing
346
337
  * bitmap neighbor queries against adjacency-based ground truth.
347
338
  *
348
- * @param {Object} params
349
- * @param {import('./JoinReducer.js').WarpStateV5} params.state
350
- * @param {LogicalIndex} params.logicalIndex
351
- * @param {Object} [params.options]
352
- * @param {number} [params.options.seed] - PRNG seed for reproducible sampling
353
- * @param {number} [params.options.sampleRate] - Fraction of nodes to check (>0 and <=1, default 0.1)
339
+ * @param {{ state: import('./JoinReducer.js').WarpStateV5, logicalIndex: LogicalIndex, options?: { seed?: number, sampleRate?: number } }} params
354
340
  * @returns {VerifyResult}
355
341
  */
356
342
  verifyIndex({ state, logicalIndex, options = {} }) {
@@ -13,10 +13,7 @@ import { createVersionVector, vvIncrement } from '../crdt/VersionVector.js';
13
13
  * writer, rebuilds the ORSet structures, and copies only properties belonging
14
14
  * to visible nodes (dropping dangling props from deleted nodes).
15
15
  *
16
- * @param {Object} v4State - The V4 materialized state (visible projection)
17
- * @param {Map<string, {value: boolean}>} v4State.nodeAlive - V4 node alive map
18
- * @param {Map<string, {value: boolean}>} v4State.edgeAlive - V4 edge alive map
19
- * @param {Map<string, import('../crdt/LWW.js').LWWRegister<unknown>>} v4State.prop - V4 property map
16
+ * @param {{ nodeAlive: Map<string, {value: boolean}>, edgeAlive: Map<string, {value: boolean}>, prop: Map<string, import('../crdt/LWW.js').LWWRegister<unknown>> }} v4State - The V4 materialized state (visible projection)
20
17
  * @param {string} migrationWriterId - Writer ID to use for synthetic dots
21
18
  * @returns {import('./JoinReducer.js').WarpStateV5} The migrated V5 state
22
19
  */
@@ -156,13 +156,7 @@ export default class ObserverView {
156
156
  /**
157
157
  * Creates a new ObserverView.
158
158
  *
159
- * @param {Object} options
160
- * @param {string} options.name - Observer name
161
- * @param {Object} options.config - Observer configuration
162
- * @param {string|string[]} options.config.match - Glob pattern(s) for visible nodes
163
- * @param {string[]} [options.config.expose] - Property keys to include
164
- * @param {string[]} [options.config.redact] - Property keys to exclude (takes precedence over expose)
165
- * @param {import('../WarpGraph.js').default} options.graph - The source WarpGraph instance
159
+ * @param {{ name: string, config: { match: string|string[], expose?: string[], redact?: string[] }, graph: import('../WarpGraph.js').default }} options
166
160
  */
167
161
  constructor({ name, config, graph }) {
168
162
  /** @type {string} */
@@ -99,19 +99,7 @@ export class PatchBuilderV2 {
99
99
  /**
100
100
  * Creates a new PatchBuilderV2.
101
101
  *
102
- * @param {Object} options
103
- * @param {import('../../ports/GraphPersistencePort.js').default} options.persistence - Git adapter
104
- * (uses CommitPort + RefPort + BlobPort + TreePort methods)
105
- * @param {string} options.graphName - Graph namespace
106
- * @param {string} options.writerId - This writer's ID
107
- * @param {number} options.lamport - Lamport timestamp for this patch
108
- * @param {import('../crdt/VersionVector.js').VersionVector} options.versionVector - Current version vector
109
- * @param {Function} options.getCurrentState - Function that returns the current materialized state
110
- * @param {string|null} [options.expectedParentSha] - Expected parent SHA for race detection
111
- * @param {Function|null} [options.onCommitSuccess] - Callback invoked after successful commit
112
- * @param {'reject'|'cascade'|'warn'} [options.onDeleteWithData='warn'] - Policy when deleting a node with attached data
113
- * @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for serialization
114
- * @param {import('../../ports/LoggerPort.js').default} [options.logger] - Logger for non-fatal warnings
102
+ * @param {{ persistence: import('../../ports/GraphPersistencePort.js').default, graphName: string, writerId: string, lamport: number, versionVector: import('../crdt/VersionVector.js').VersionVector, getCurrentState: () => import('../services/JoinReducer.js').WarpStateV5 | null, expectedParentSha?: string|null, onCommitSuccess?: ((result: {patch: import('../types/WarpTypesV2.js').PatchV2, sha: string}) => void | Promise<void>)|null, onDeleteWithData?: 'reject'|'cascade'|'warn', codec?: import('../../ports/CodecPort.js').default, logger?: import('../../ports/LoggerPort.js').default }} options
115
103
  */
116
104
  constructor({ persistence, graphName, writerId, lamport, versionVector, getCurrentState, expectedParentSha = null, onCommitSuccess = null, onDeleteWithData = 'warn', codec, logger }) {
117
105
  /** @type {import('../../ports/GraphPersistencePort.js').default & import('../../ports/RefPort.js').default & import('../../ports/CommitPort.js').default & import('../../ports/BlobPort.js').default & import('../../ports/TreePort.js').default} */
@@ -129,8 +117,8 @@ export class PatchBuilderV2 {
129
117
  /** @type {import('../crdt/VersionVector.js').VersionVector} */
130
118
  this._vv = vvClone(versionVector); // Clone to track local increments
131
119
 
132
- /** @type {Function} */
133
- this._getCurrentState = getCurrentState; // Function to get current materialized state
120
+ /** @type {() => import('../services/JoinReducer.js').WarpStateV5 | null} */
121
+ this._getCurrentState = getCurrentState;
134
122
 
135
123
  /**
136
124
  * Snapshot of state captured at construction time (C4).
@@ -540,7 +528,7 @@ export class PatchBuilderV2 {
540
528
  * only sets the `_content` property — it does not create the node.
541
529
  *
542
530
  * @param {string} nodeId - The node ID to attach content to
543
- * @param {Buffer|string} content - The content to attach
531
+ * @param {Uint8Array|string} content - The content to attach
544
532
  * @returns {Promise<PatchBuilderV2>} This builder instance for method chaining
545
533
  */
546
534
  async attachContent(nodeId, content) {
@@ -561,7 +549,7 @@ export class PatchBuilderV2 {
561
549
  * @param {string} from - Source node ID
562
550
  * @param {string} to - Target node ID
563
551
  * @param {string} label - Edge label
564
- * @param {Buffer|string} content - The content to attach
552
+ * @param {Uint8Array|string} content - The content to attach
565
553
  * @returns {Promise<PatchBuilderV2>} This builder instance for method chaining
566
554
  */
567
555
  async attachEdgeContent(from, to, label, content) {
@@ -732,7 +720,7 @@ export class PatchBuilderV2 {
732
720
 
733
721
  // 6. Encode patch as CBOR and write as a Git blob
734
722
  const patchCbor = this._codec.encode(patch);
735
- const patchBlobOid = await this._persistence.writeBlob(/** @type {Buffer} */ (patchCbor));
723
+ const patchBlobOid = await this._persistence.writeBlob(patchCbor);
736
724
 
737
725
  // 7. Create tree with the patch blob + any content blobs (deduplicated)
738
726
  // Format for mktree: "mode type oid\tpath"
@@ -25,12 +25,7 @@ import {
25
25
  /**
26
26
  * Encodes a patch commit message.
27
27
  *
28
- * @param {Object} options - The patch message options
29
- * @param {string} options.graph - The graph name
30
- * @param {string} options.writer - The writer ID
31
- * @param {number} options.lamport - The Lamport timestamp (must be a positive integer)
32
- * @param {string} options.patchOid - The OID of the patch blob
33
- * @param {number} [options.schema=2] - The schema version (defaults to 2 for new messages)
28
+ * @param {{ graph: string, writer: string, lamport: number, patchOid: string, schema?: number }} options - The patch message options
34
29
  * @returns {string} The encoded commit message
35
30
  * @throws {Error} If any validation fails
36
31
  *
@@ -12,8 +12,7 @@ import computeShardKey from '../utils/shardKey.js';
12
12
 
13
13
  export default class PropertyIndexBuilder {
14
14
  /**
15
- * @param {Object} [options]
16
- * @param {import('../../ports/CodecPort.js').default} [options.codec]
15
+ * @param {{ codec?: import('../../ports/CodecPort.js').default }} [options]
17
16
  */
18
17
  constructor({ codec } = {}) {
19
18
  this._codec = codec || defaultCodec;
@@ -12,10 +12,7 @@ import LRUCache from '../utils/LRUCache.js';
12
12
 
13
13
  export default class PropertyIndexReader {
14
14
  /**
15
- * @param {Object} [options]
16
- * @param {import('../../ports/IndexStoragePort.js').default} [options.storage]
17
- * @param {import('../../ports/CodecPort.js').default} [options.codec]
18
- * @param {number} [options.maxCachedShards=64]
15
+ * @param {{ storage?: import('../../ports/IndexStoragePort.js').default, codec?: import('../../ports/CodecPort.js').default, maxCachedShards?: number }} [options]
19
16
  */
20
17
  constructor({ storage, codec, maxCachedShards = 64 } = /** @type {{ storage?: import('../../ports/IndexStoragePort.js').default, codec?: import('../../ports/CodecPort.js').default, maxCachedShards?: number }} */ ({})) {
21
18
  this._storage = storage;
@@ -242,9 +242,8 @@ class ProvenanceIndex {
242
242
  * The serialized format is a sorted array of [entityId, sortedShas[]] pairs
243
243
  * for deterministic output.
244
244
  *
245
- * @param {Object} [options]
246
- * @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for serialization
247
- * @returns {Buffer|Uint8Array} CBOR-encoded index
245
+ * @param {{ codec?: import('../../ports/CodecPort.js').default }} [options]
246
+ * @returns {Uint8Array} CBOR-encoded index
248
247
  */
249
248
  serialize({ codec } = {}) {
250
249
  const c = codec || defaultCodec;
@@ -268,9 +267,8 @@ class ProvenanceIndex {
268
267
  /**
269
268
  * Deserializes an index from CBOR format.
270
269
  *
271
- * @param {Buffer} buffer - CBOR-encoded index
272
- * @param {Object} [options]
273
- * @param {import('../../ports/CodecPort.js').default} [options.codec] - Codec for deserialization
270
+ * @param {Uint8Array} buffer - CBOR-encoded index
271
+ * @param {{ codec?: import('../../ports/CodecPort.js').default }} [options]
274
272
  * @returns {ProvenanceIndex} The deserialized index
275
273
  * @throws {Error} If the buffer contains an unsupported version
276
274
  */
@@ -293,7 +291,7 @@ class ProvenanceIndex {
293
291
  /**
294
292
  * Returns a JSON-serializable representation of this index.
295
293
  *
296
- * @returns {Object} Object with version and entries array
294
+ * @returns {{version: number, entries: Array<[string, string[]]>}} Object with version and entries array
297
295
  */
298
296
  toJSON() {
299
297
  return { version: 1, entries: this.#sortedEntries() };