Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
392d4fc
feat: WorldlineSelector class hierarchy — RED→GREEN
flyingrobots Apr 4, 2026
7dd54eb
refactor: migrate Worldline/Observer/QueryController to WorldlineSele…
flyingrobots Apr 4, 2026
924e62e
fix: resolve tsc errors from WorldlineSelector migration
flyingrobots Apr 4, 2026
9cbf41c
fix: address self-review — toDTO ceiling, double-clone, registry seal
flyingrobots Apr 4, 2026
9b1a827
docs: defaultCodec → infrastructure design (P5 fix)
flyingrobots Apr 4, 2026
3052bc0
docs: redesign defaultCodec migration — inject at root, no shim
flyingrobots Apr 4, 2026
22a0098
docs: rewrite defaultCodec backlog item — the real P5 violation
flyingrobots Apr 4, 2026
1e76c48
docs: cycle 0007 retro — partial (WorldlineSelector shipped, defaultC…
flyingrobots Apr 4, 2026
6860653
docs: correct defaultCodec fix — dissolve, don't relocate
flyingrobots Apr 4, 2026
18ea06b
docs: two-stage boundary for P5 codec dissolution
flyingrobots Apr 4, 2026
ca2db85
docs: add cool ideas from P5 codec dissolution planning
flyingrobots Apr 4, 2026
4cf9ed9
test: add hex tripwire + golden fixture for patch serialization (RED)
flyingrobots Apr 4, 2026
a28d81a
feat: add PatchJournalPort + CborPatchJournalAdapter
flyingrobots Apr 4, 2026
1da9e42
refactor: wire PatchBuilderV2 through PatchJournalPort
flyingrobots Apr 4, 2026
2b53d1a
refactor: wire SyncProtocol through PatchJournalPort
flyingrobots Apr 4, 2026
359ea14
refactor: remove defaultCodec from Writer + wire patchJournal through…
flyingrobots Apr 4, 2026
6955db8
fix: add eslint-disable for untyped WarpRuntime _patchJournal access
flyingrobots Apr 4, 2026
5756abe
fix: wire patchJournal into 6 test files missing it after PatchJourna…
flyingrobots Apr 4, 2026
412c6f6
test: extend tripwire + golden fixture for checkpoint serialization (…
flyingrobots Apr 4, 2026
39cb85b
feat: add CheckpointStorePort + CborCheckpointStoreAdapter
flyingrobots Apr 4, 2026
3520de2
feat: wire CheckpointStorePort through checkpoint create/load pipeline
flyingrobots Apr 4, 2026
b5da62a
refactor: scope checkpoint tripwire to CheckpointService only
flyingrobots Apr 4, 2026
e71bc56
docs: stream architecture cycle proposal + P5 progress update
flyingrobots Apr 4, 2026
c197d4c
feat: WarpStream + Transform + Sink — composable async stream primitives
flyingrobots Apr 4, 2026
825ef6d
test: WarpStream core tests — 40 tests covering full API surface
flyingrobots Apr 4, 2026
a95ad58
feat: infrastructure stream adapters + pipeline integration tests
flyingrobots Apr 4, 2026
8fabdce
feat: LogicalBitmapIndexBuilder.yieldShards() — stream-compatible output
flyingrobots Apr 4, 2026
1bc79ed
docs: cycle 0008 — stream architecture design doc + backlog items
flyingrobots Apr 4, 2026
69d98df
docs: rewrite cycle 0008 design — ports for meaning, streams for scale
flyingrobots Apr 4, 2026
d854d61
docs: finalize cycle 0008 design — all six rulings locked
flyingrobots Apr 4, 2026
4a42421
feat: artifact record classes — CheckpointArtifact, IndexShard, Patch…
flyingrobots Apr 4, 2026
1b2e614
feat: PatchJournalPort.scanPatchRange() → WarpStream<PatchEntry>
flyingrobots Apr 4, 2026
7d5af95
refactor: collapse CheckpointStorePort to writeCheckpoint/readCheckpoint
flyingrobots Apr 4, 2026
1bee37f
refactor: wire SyncProtocol.processSyncRequest to use scanPatchRange
flyingrobots Apr 4, 2026
8f79554
feat: IndexShard records in yieldShards() + IndexShardEncodeTransform
flyingrobots Apr 4, 2026
3134b31
feat: PropertyIndexBuilder.yieldShards() emitting PropertyShard records
flyingrobots Apr 4, 2026
590a7c7
feat: LogicalIndexBuildService.buildStream() — WarpStream of IndexSha…
flyingrobots Apr 4, 2026
b7f6af2
chore: Phase 3 cleanup — CHANGELOG, delete canonicalCbor (dead code)
flyingrobots Apr 4, 2026
9aeeb52
fix: three bugs in WarpStream — tee cache leak, demux error swallowin…
flyingrobots Apr 4, 2026
bf9eccf
fix: add constructor validation for required dependencies
flyingrobots Apr 4, 2026
6e95376
fix: address review issues — double-iteration, null guards, detached …
flyingrobots Apr 4, 2026
b1b687e
fix: address CodeRabbit review — encryption guard, required patchJour…
flyingrobots Apr 4, 2026
7c88755
fix: eliminate all tsc errors in source files (61 errors across 12 fi…
flyingrobots Apr 4, 2026
d72d97d
fix: tsc zero — 144 errors eliminated across 26 files
flyingrobots Apr 4, 2026
097fa3d
fix: add WorldlineSelector classes to type-surface manifest
flyingrobots Apr 4, 2026
d2d8d8d
docs: lock TRAVERSAL-TRUTH invariant
flyingrobots Apr 4, 2026
5cb8e1d
docs: add language specifiers to fenced code blocks in stream-archite…
flyingrobots Apr 4, 2026
88ba040
fix: reject empty IndexShard shardKey (CodeRabbit round 2)
flyingrobots Apr 4, 2026
86ff6dd
fix: change pseudocode fences from js/ts to text in design docs
flyingrobots Apr 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix: add constructor validation for required dependencies
- CborPatchJournalAdapter: validate codec, blobPort
- CborCheckpointStoreAdapter: validate codec, blobPort
- CborEncodeTransform: validate codec
- CborDecodeTransform: validate codec
- GitBlobWriteTransform: validate blobPort
- TreeAssemblerSink: validate treePort
- IndexShardEncodeTransform: validate codec
- Sink.consume(): validate source param
- PatchBuilderV2: replace generic Error with PersistenceError (E_MISSING_JOURNAL)
- CheckpointStorePort: remove misleading treeOid from CheckpointWriteResult
  • Loading branch information
flyingrobots committed Apr 4, 2026
commit bf9eccfc3775d3ec0f8db3be214d6ce85d9592ff
12 changes: 7 additions & 5 deletions src/domain/WarpRuntime.js
Original file line number Diff line number Diff line change
Expand Up @@ -575,11 +575,13 @@ export default class WarpRuntime {
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

// Auto-construct StateHashService from codec + crypto
graph._stateHashService = new StateHashService({
codec: graph._codec,
crypto: graph._crypto,
});
// Auto-construct StateHashService from codec + crypto (only when crypto is available)
if (graph._crypto) {
graph._stateHashService = new StateHashService({
codec: graph._codec,
crypto: graph._crypto,
});
}

// Validate migration boundary
await graph._validateMigrationBoundary();
Expand Down
3 changes: 2 additions & 1 deletion src/domain/services/PatchBuilderV2.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import WriterError from '../errors/WriterError.js';
import { isStreamingInput, normalizeToAsyncIterable } from '../utils/streamUtils.js';
import { canonicalStringify } from '../utils/canonicalStringify.js';
import PatchError from '../errors/PatchError.js';
import PersistenceError from '../errors/PersistenceError.js';

/**
* Inspects materialized state for edges and properties attached to a node.
Expand Down Expand Up @@ -983,7 +984,7 @@ export class PatchBuilderV2 {

// 6. Persist patch via PatchJournalPort (adapter owns encoding).
if (this._patchJournal === null || this._patchJournal === undefined) {
throw new Error('patchJournal is required for committing patches');
throw new PersistenceError('patchJournal is required for committing patches', 'E_MISSING_JOURNAL');
}
const patchBlobOid = await this._patchJournal.writePatch(patch);
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Expand Down
16 changes: 10 additions & 6 deletions src/domain/services/index/LogicalIndexBuildService.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,21 @@ export default class LogicalIndexBuildService {
buildStream(state, options = {}) {
const { indexBuilder, propBuilder } = this._populateBuilders(state, options);

// Collect shards once — generators yield fresh iterators on each call,
// so calling yieldShards() twice would re-iterate all bitmaps.
const indexShards = [...indexBuilder.yieldShards()];
const receiptShard = indexShards.find((s) => s instanceof ReceiptShard);
if (!receiptShard) {
throw new Error('LogicalIndexBuildService: index builder did not emit a ReceiptShard');
}

// Merge both builders' shard streams
const stream = WarpStream.mux(
WarpStream.from(indexBuilder.yieldShards()),
WarpStream.from(indexShards),
WarpStream.from(propBuilder.yieldShards()),
);
Comment on lines +67 to +79
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

buildStream() still buffers the bitmap side up front.

const indexShards = [...indexBuilder.yieldShards()] materializes every index shard just to find the ReceiptShard. On large graphs that puts the full bitmap build back in memory and delays the first emitted chunk, so this API loses the stream-first scaling benefit it was introduced for. Please expose the receipt separately from LogicalBitmapIndexBuilder, or derive it without collecting the whole iterator.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/domain/services/index/LogicalIndexBuildService.js` around lines 67 - 79,
buildStream() currently materializes all shards via const indexShards =
[...indexBuilder.yieldShards()] to locate a ReceiptShard, which buffers the
entire bitmap stream; change this so we do not collect the whole iterator:
either add an explicit accessor on LogicalBitmapIndexBuilder to return the
ReceiptShard (e.g., getReceiptShard()) and use that, or iterate the
yieldShards() iterator lazily (use a for..of over indexBuilder.yieldShards() to
find the first instance of ReceiptShard, emitting or queuing non-receipt shards
as you go) and only buffer what’s necessary; update the code that uses
receiptShard, indexBuilder.yieldShards(), WarpStream.mux and
propBuilder.yieldShards() accordingly so you no longer create indexShards =
[...].


// Extract receipt from the index builder (it's deterministic, no need to decode)
const shards = [...indexBuilder.yieldShards()];
const receiptShard = /** @type {ReceiptShard} */ (shards.find((s) => s instanceof ReceiptShard));

return { stream, receipt: receiptShard };
return { stream, receipt: /** @type {ReceiptShard} */ (receiptShard) };
}

/**
Expand Down
7 changes: 7 additions & 0 deletions src/domain/services/state/StateHashService.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { projectStateV5 } from './StateSerializerV5.js';
import WarpError from '../../errors/WarpError.js';

/**
* Computes canonical state hashes for verification, comparison,
Expand All @@ -21,6 +22,12 @@ export default class StateHashService {
* }} deps
*/
constructor({ codec, crypto }) {
if (codec === undefined || codec === null) {
throw new WarpError('StateHashService requires a codec', 'E_MISSING_DEPENDENCY');
}
if (crypto === undefined || crypto === null) {
throw new WarpError('StateHashService requires a crypto adapter', 'E_MISSING_DEPENDENCY');
}
/** @type {import('../../../ports/CodecPort.js').default} */
this._codec = codec;
/** @type {import('../../../ports/CryptoPort.js').default} */
Expand Down
3 changes: 3 additions & 0 deletions src/domain/stream/Sink.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export default class Sink {
* @returns {Promise<R>} The accumulated result
*/
async consume(source) {
if (source === null || source === undefined) {
throw new WarpError('Sink.consume() requires a source', 'E_INVALID_SOURCE');
}
for await (const item of source) {
await this._accept(item);
}
Expand Down
7 changes: 6 additions & 1 deletion src/infrastructure/adapters/CborCheckpointStoreAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ export class CborCheckpointStoreAdapter extends CheckpointStorePort {
*/
constructor({ codec, blobPort }) {
super();
if (codec === null || codec === undefined) {
throw new WarpError('CborCheckpointStoreAdapter requires a codec', 'E_INVALID_DEPENDENCY');
}
if (blobPort === null || blobPort === undefined) {
throw new WarpError('CborCheckpointStoreAdapter requires a blobPort', 'E_INVALID_DEPENDENCY');
}
/** @type {import('../../ports/CodecPort.js').default} */
this._codec = codec;
/** @type {import('../../ports/BlobPort.js').default} */
Expand Down Expand Up @@ -63,7 +69,6 @@ export class CborCheckpointStoreAdapter extends CheckpointStorePort {

const oids = await Promise.all(writes);
return {
treeOid: '', // Caller assembles tree (CheckpointService owns commit creation)
stateBlobOid: oids[0],
frontierBlobOid: oids[1],
appliedVVBlobOid: oids[2],
Expand Down
4 changes: 4 additions & 0 deletions src/infrastructure/adapters/CborDecodeTransform.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Transform from '../../domain/stream/Transform.js';
import WarpError from '../../domain/errors/WarpError.js';

/**
* Stream transform that CBOR-decodes the value component of [path, bytes] entries.
Expand All @@ -16,6 +17,9 @@ export class CborDecodeTransform extends Transform {
*/
constructor(codec) {
super();
if (codec === null || codec === undefined) {
throw new WarpError('CborDecodeTransform requires a codec', 'E_INVALID_DEPENDENCY');
}
/** @type {import('../../ports/CodecPort.js').default} */
this._codec = codec;
}
Expand Down
6 changes: 6 additions & 0 deletions src/infrastructure/adapters/CborPatchJournalAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ export class CborPatchJournalAdapter extends PatchJournalPort {
*/
constructor({ codec, blobPort, commitPort, patchBlobStorage }) {
super();
if (codec === null || codec === undefined) {
throw new WarpError('CborPatchJournalAdapter requires a codec', 'E_INVALID_DEPENDENCY');
}
if (blobPort === null || blobPort === undefined) {
throw new WarpError('CborPatchJournalAdapter requires a blobPort', 'E_INVALID_DEPENDENCY');
}
/** @type {import('../../ports/CodecPort.js').default} */
this._codec = codec;
/** @type {import('../../ports/BlobPort.js').default} */
Expand Down
4 changes: 4 additions & 0 deletions src/infrastructure/adapters/GitBlobWriteTransform.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Transform from '../../domain/stream/Transform.js';
import WarpError from '../../domain/errors/WarpError.js';

/**
* Stream transform that writes the bytes component of [path, bytes] entries
Expand All @@ -17,6 +18,9 @@ export class GitBlobWriteTransform extends Transform {
*/
constructor(blobPort) {
super();
if (blobPort === null || blobPort === undefined) {
throw new WarpError('GitBlobWriteTransform requires a blobPort', 'E_INVALID_DEPENDENCY');
}
/** @type {import('../../ports/BlobPort.js').default} */
this._blobPort = blobPort;
}
Expand Down
3 changes: 3 additions & 0 deletions src/infrastructure/adapters/IndexShardEncodeTransform.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ export class IndexShardEncodeTransform extends Transform {
*/
constructor(codec) {
super();
if (codec === null || codec === undefined) {
throw new WarpError('IndexShardEncodeTransform requires a codec', 'E_INVALID_DEPENDENCY');
}
/** @type {import('../../ports/CodecPort.js').default} */
this._codec = codec;
}
Expand Down
4 changes: 4 additions & 0 deletions src/infrastructure/adapters/TreeAssemblerSink.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Sink from '../../domain/stream/Sink.js';
import WarpError from '../../domain/errors/WarpError.js';

/**
* Stream sink that accumulates [path, oid] entries and assembles them
Expand All @@ -17,6 +18,9 @@ export class TreeAssemblerSink extends Sink {
*/
constructor(treePort) {
super();
if (treePort === null || treePort === undefined) {
throw new WarpError('TreeAssemblerSink requires a treePort', 'E_INVALID_DEPENDENCY');
}
/** @type {import('../../ports/TreePort.js').default} */
this._treePort = treePort;
/** @type {string[]} mktree-formatted entries */
Expand Down
1 change: 0 additions & 1 deletion src/ports/CheckpointStorePort.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import WarpError from '../domain/errors/WarpError.js';

/**
* @typedef {{
* treeOid: string,
* stateBlobOid: string,
* frontierBlobOid: string,
* appliedVVBlobOid: string,
Expand Down