Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 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
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- **CheckpointStorePort wiring (P5 strangler)** — `CheckpointService`, `CheckpointController`, `MaterializeController`, and `WarpRuntime` now accept an optional `checkpointStore` parameter. When provided, checkpoint create/load operations delegate serialization to the port instead of calling serializers directly. Legacy codec-based paths remain as fallback. `WarpRuntime.open()` auto-constructs a `CborCheckpointStoreAdapter` when no explicit store is provided, matching the `patchJournal` auto-construction pattern.
- **The Method** — introduced `METHOD.md` as the development process framework. Filesystem-native backlog (`docs/method/backlog/`) with lane directories (`inbox/`, `asap/`, `up-next/`, `cool-ideas/`, `bad-code/`). Legend-prefixed filenames (`PROTO_`, `TRUST_`, `VIZ_`, `TUI_`, `DX_`, `PERF_`). Sequential cycle numbering (`docs/design/<NNNN-slug>/`). Dual-audience design docs (sponsor human + sponsor agent). Replaced B-number system entirely.
- **Backlog migration** — all 49 B-number and OG items migrated from `BACKLOG/` to `docs/method/backlog/` lanes. Tech debt journal (`.claude/bad_code.md`) split into 10 individual files in `bad-code/`. Cool ideas journal split into 13 individual files in `cool-ideas/`. `docs/release.md` moved to `docs/method/release.md`. `BACKLOG/` directory removed.

Expand Down
10 changes: 7 additions & 3 deletions docs/BEARING.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ analysis, 10 cohesive groups identified, no circular dependencies.

## What feels wrong?

- WorldlineSource is still a tagged object, not a subclass hierarchy.
- `defaultCodec.js` lives in `domain/utils/` but imports `cbor-x`
directly — a hexagonal boundary violation.
- ~~WorldlineSource~~ Shipped as WorldlineSelector hierarchy (cycle 0007).
- 20 domain services do serialization directly (`codec.encode()`/
`codec.decode()`). The fix is a two-stage boundary: artifact-level
ports (PatchJournalPort, CheckpointStorePort, etc.) that speak
domain types, backed by codec-owning adapters over the raw Git
ports. Strangler refactor, patches first.
See `NDNM_defaultcodec-to-infrastructure.md`.
- The two legends (CLEAN_CODE, NO_DOGS_NO_MASTERS) overlap
significantly. May need consolidation or clearer boundaries.
- JoinReducer is imported by 8 of 10 service clusters — it is the
Expand Down
234 changes: 234 additions & 0 deletions docs/design/0008-stream-architecture/stream-architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
# Cycle 0008 — Stream Architecture

**Sponsor (human):** James
**Sponsor (agent):** Claude
**Status:** DESIGN

## Hill

A developer can pipe domain objects through a composable stream
pipeline where encoding, persistence, and tree assembly are transforms
and sinks — never called directly by domain code. Semantic ports
remain for bounded single-artifact operations. Artifact records carry
runtime identity. The system is memory-bounded for unbounded datasets.

## The Rule

Streams are for scale. Ports are for meaning. Artifacts are the nouns.
Paths are infrastructure.

## Playback Questions

1. Does the pipeline produce byte-identical output to the legacy path?
2. Does a constrained-heap test complete for a dataset that would
otherwise OOM?
3. Do semantic ports still tell you WHAT is being persisted and WHAT
lifecycle rules apply?
4. Is CBOR vocabulary absent from domain nouns?
5. Does every artifact record class add runtime identity, not just a name?

## Non-Goals

- CborStream or any codec-named class in the domain
- Marker stream subclasses that don't add flow behavior
- Melting separate ports/services into one generic pipe
- Replacing bounded single-artifact reads with streams

---

## Architecture

### One Stream Container

```
WarpStream<T> — domain primitive
pipe / tee / mux / demux / drain / reduce / forEach / collect
[Symbol.asyncIterator]()
```

No domain subclasses. Identity lives on elements, not the container.

### Semantic Ports

Ports define what is being persisted and what lifecycle rules apply.
Bounded operations stay `Promise<T>`. Unbounded operations return or
accept `WarpStream<SemanticUnit>`.

**PatchJournalPort** (keep, extend)
```
writePatch(patch) → Promise<string> bounded write
readPatch(oid) → Promise<PatchV2> bounded read
scanPatchRange(...) → WarpStream<PatchEntry> unbounded scan (NEW)
```

**CheckpointStorePort** (collapse micro-methods)
```
writeCheckpoint(record) → Promise<CheckpointWriteResult> one call
readCheckpoint(sha) → Promise<CheckpointData> bounded read
```
Adapter internally streams artifacts through the pipeline.

**IndexStorePort** (NEW, streaming)
```
writeShards(stream) → Promise<string> WarpStream<IndexShard> → tree OID
scanShards(...) → WarpStream<IndexShard> unbounded read
```

**ProvenanceStorePort** (NEW, separate concept)
```
scanEntries(...) → WarpStream<ProvenanceEntry>
writeIndex(index) → Promise<string>
```
Own port. Physical colocation under checkpoint tree ≠ semantic
ownership. Checkpoint = recovery. Provenance = causal/query/verification.
Different jobs, different lifecycle, different consumers.

**StateHashService** (separate callable, not buried in adapter)
```
compute(state) → Promise<string>
```
Used by verification, comparison, detached checks, AND checkpoint
creation. Not exclusively inside writeCheckpoint().

### Artifact Records

Runtime identity on elements, not containers (P1/P7).

**CheckpointArtifact** — closed subclass family
```
CheckpointArtifact (abstract base)
common: checkpointRef, schemaVersion

StateArtifact extends CheckpointArtifact
payload: { state: WarpStateV5 }

FrontierArtifact extends CheckpointArtifact
payload: { frontier: Map<string, string> }

AppliedVVArtifact extends CheckpointArtifact
payload: { appliedVV: VersionVector }
```
No paths. No CBOR. No blob OIDs. No adapter trivia.

**IndexShard** — subtype family (not one generic class)
```
IndexShard (base)
common: indexFamily, shardId, schemaVersion

MetaShard extends IndexShard
payload: { nodeToGlobal, alive, nextLocalId }

EdgeShard extends IndexShard
payload: { direction, shardKey, buckets }

LabelShard extends IndexShard
payload: { labels: [string, number][] }

PropertyShard extends IndexShard
payload: { entries: [string, Record][] }
```
The code already treats shard families differently (isMetaShard,
isEdgeShard, classifyShards). One mega-shard class is just `any`
with better PR.

**PatchEntry** — `{ patch: PatchV2, sha: string }`

**ProvenanceEntry** — `{ nodeId, patchShas }`

### Path Mapping

Adapter owns it. Full stop. Domain produces artifact records.
Adapter maps to Git tree paths at the last responsible moment.

```
StateArtifact → 'state.cbor'
FrontierArtifact → 'frontier.cbor'
MetaShard → 'meta_XX.cbor'
EdgeShard → '{fwd|rev}_XX.cbor'
```

Static mapping table or instanceof dispatcher in the adapter.
No `.path()` on domain objects. Paths are storage convention.

Domain owns meaning. Adapter owns layout.

### Infrastructure Transforms

```
CborEncodeTransform artifact → [path, bytes]
CborDecodeTransform [path, bytes] → artifact
GitBlobWriteTransform [path, bytes] → [path, oid]
TreeAssemblerSink [path, oid] → finalize → treeOid
```

Encode → blobWrite → treeAssemble stays entirely in infrastructure.
CBOR is boundary vocabulary — never a domain noun.

### Pipeline Examples

```js
// Index write (unbounded, streaming)
await indexStore.writeShards(
WarpStream.from(builder.yieldShards())
);
// Adapter internally: stream → encode → blobWrite → treeAssemble

// Checkpoint write (bounded, one call)
await checkpointStore.writeCheckpoint({
state, frontier, appliedVV, stateHash, provenanceIndex
});
// Adapter internally: yield artifacts → encode → blobWrite → tree

// Patch scan (unbounded)
const patches = patchJournal.scanPatchRange(writerRef, fromSha, toSha);
for await (const entry of patches) {
reducer.apply(entry.patch);
}
```

### Ordering Guarantee

`WarpStream.mux()` interleaves by arrival order. Async completion
timing must not bleed into tree assembly. `TreeAssemblerSink` sorts
entries before `writeTree()`. Deterministic Git trees don't care
which blob write finished first.

---

## Migration Plan

### Phase 1 — Artifact records + streaming ports

- CheckpointArtifact family (StateArtifact, FrontierArtifact,
AppliedVVArtifact)
- IndexShard family (MetaShard, EdgeShard, LabelShard, PropertyShard)
- PatchEntry, ProvenanceEntry records
- IndexStorePort with writeShards/scanShards
- PatchJournalPort.scanPatchRange()
- StateHashService
- ProvenanceStorePort

### Phase 2 — Wire write paths

- CheckpointStorePort collapse → writeCheckpoint(record)
- Index builders: yieldShards() returns IndexShard subclass instances
- SyncProtocol: consume scanPatchRange() instead of loadPatchRange()

### Phase 3 — P5 cleanup

- Remove defaultCodec from all domain files
- Delete defaultCodec.js, canonicalCbor.js
- Expand tripwire to all migrated files

### Phase 4 — Memory-bounded witnesses

- Constrained-heap tests
- Naming audit for slurp APIs

---

## Accessibility / Localization / Agent-Inspectability

- **Agent-Inspectability**: Artifact records are `instanceof`-
dispatchable. WarpStream carries AbortSignal. Sink.consume()
returns typed results.
Loading
Loading