Skip to content

feat(kernel): strand contract — cycle 0004#315

Merged
flyingrobots merged 11 commits intomainfrom
cycle/0004-strand-contract
Apr 4, 2026
Merged

feat(kernel): strand contract — cycle 0004#315
flyingrobots merged 11 commits intomainfrom
cycle/0004-strand-contract

Conversation

@flyingrobots
Copy link
Copy Markdown
Owner

@flyingrobots flyingrobots commented Apr 4, 2026

Summary

  • Define the strand as a first-class relation in Echo: Strand, BaseRef, SupportPin, DropReceipt, StrandRegistry types in warp-core/src/strand.rs
  • Ten normative invariants (INV-S1 through INV-S10) in docs/invariants/STRAND-CONTRACT.md
  • 26 tests passing (14 Rust integration + 12 shell assertions)

Design decisions

  • No StrandLifecycle field — strand exists in registry = live, not in registry = gone. Heads are the single source of truth for operational state.
  • Hard-delete drop with DropReceipt. No tombstone.
  • BaseRef pinned exactly: fork_tick = last included tick, commit_hash at fork_tick, boundary_hash = output boundary (state root after patch), provenance_ref for substrate-native lookups.
  • Dormant/Paused heads — strand heads never enter the live scheduler's runnable set (proven by integration test).
  • support_pins empty in v1 (INV-S9) — field exists to prevent future struct breakage.
  • Cardinality-1 writer heads in v1 — Vec for future multi-head, but v1 always length 1.

What this enables

  • warp-ttd can surface strand topology via LaneKind::STRAND and LaneRef.parentId
  • Foundation for strand settlement spec (KERNEL_strand-settlement, future cycle)
  • Foundation for time travel MVP (fork/compare/drop)

Test plan

  • INV-S2/S8: strand heads belong to child worldline, not base
  • INV-S4/S10: dormant strand heads excluded from RunnableWriterSet
  • INV-S5: base_ref fields internally consistent
  • INV-S7: child != base worldline
  • INV-S9: support_pins empty
  • Registry CRUD: insert, get, duplicate rejection, remove, list_by_base
  • Drop receipt carries correct fields
  • Invariant document exists with all ten INV codes

Closes cycle 0004.

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced strand contract: a new speculative execution capability with deterministic strand identifiers, immutable base references, and registry-based lifecycle management (create, list, remove operations).
  • Tests

    • Added 14 integration tests validating strand invariants, registry operations, and drop semantics.
  • Documentation

    • Added formal design specification, normative invariant documentation, and comprehensive test coverage reports for the strand contract.

Move KERNEL_strand-contract from up-next into
docs/design/0004-strand-contract/ with a full design doc.

Defines Strand, BaseRef, SupportPin, StrandLifecycle, StrandRegistry.
Six invariants (INV-S1 through INV-S6). TTD mapping to
LaneKind::STRAND and LaneRef.parentId. Implementation in
warp-core/src/strand.rs.
Address all MUST items from design review:

1. Kill lifecycle/head-state duplication. No StrandLifecycle field.
   Strand either exists in registry (live) or doesn't (dropped).
   Operational state derived from heads — single source of truth.

2. Hard-delete drop semantics. No tombstone, no Dropped state.
   drop_strand returns a DropReceipt (strand_id, child_worldline_id,
   final tick). get() returns None after drop.

3. Pin BaseRef exactly. fork_tick is last included tick. commit_hash
   is at fork_tick. boundary_hash is output boundary (state root
   after applying patch). All five fields same coordinate. Add
   provenance_ref for substrate-native lookups.

4. Add four invariants: INV-S7 (distinct worldlines), INV-S8 (head
   ownership), INV-S9 (empty support_pins in v1), INV-S10 (clean
   drop — no runnable heads remain).

5. Require integration test proving strand heads excluded from
   live scheduler runnable set.

6. Define create/drop atomicity with rollback sequence.

7. Document registry ordering, writer_heads cardinality-1 in v1,
   get/contains API surface.

8. Fix TTD mapping: LaneKind is type not lifecycle.
Add crates/warp-core/src/strand.rs with:
- StrandId (domain-separated hash, prefix "strand:")
- BaseRef (immutable fork coordinate with exact semantics)
- SupportPin (braid geometry placeholder, empty in v1)
- DropReceipt (hard-delete proof)
- Strand (relation descriptor, no lifecycle field)
- StrandRegistry (BTreeMap<StrandId, Strand> with CRUD)
- StrandError enum

Add integration tests (14 assertions, all passing on types/registry):
- INV-S2/S8: head ownership
- INV-S4/S10: dormant heads excluded from runnable set
- INV-S5: base_ref field consistency
- INV-S7: distinct worldlines
- INV-S9: empty support_pins
- Registry: insert, get, duplicate, remove, list_by_base

Shell invariant tests: 12/12 RED (invariant doc not yet written).
Write docs/invariants/STRAND-CONTRACT.md with ten normative
invariants (INV-S1 through INV-S10) covering immutable base_ref,
own heads, session scope, manual tick, complete base_ref, inherited
quantum, distinct worldlines, head ownership, empty support_pins,
and clean drop semantics.

All tests passing: 14 Rust integration tests + 12 shell assertions.
Retro and witness for cycle 0004. All 26 tests passing (14 Rust +
12 shell). Design review caught and fixed three issues: lifecycle/
head-state duplication, drop semantics inconsistency, and BaseRef
coordinate imprecision.

New debt: orchestrated create/drop operations not yet wired through
coordinator, LocalProvenanceStore lacks remove_worldline.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 4, 2026

Warning

Rate limit exceeded

@flyingrobots has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minutes and 17 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 1 minutes and 17 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 76366dc8-22d3-4e77-bb95-fc9608fd819d

📥 Commits

Reviewing files that changed from the base of the PR and between 5699133 and f3c6b2e.

📒 Files selected for processing (6)
  • crates/warp-core/src/strand.rs
  • crates/warp-core/tests/strand_contract_tests.rs
  • docs/method/backlog/asap/PLATFORM_WESLEY_protocol-consumer-cutover.md
  • docs/method/retro/0004-strand-contract/retro.md
  • docs/method/retro/0004-strand-contract/witness/rust-test-output.txt
  • scripts/tests/strand_contract_invariant_test.sh
📝 Walkthrough

Walkthrough

Introduces a new strand module to warp-core implementing a speculative execution contract. Adds deterministic StrandId generation, immutable BaseRef provenance tracking, session-scoped StrandRegistry with BTreeMap ordering, and core data types (Strand, DropReceipt, SupportPin, StrandError). Includes comprehensive integration tests validating invariants and registry operations, plus design and normative invariant documentation.

Changes

Cohort / File(s) Summary
Module Declaration
crates/warp-core/src/lib.rs
Exposed new public strand module at crate root.
Strand Implementation
crates/warp-core/src/strand.rs
Core strand contract logic: StrandId with BLAKE3 domain-separated hashing, BaseRef immutable provenance coordinate, SupportPin geometry pins, DropReceipt drop metadata, Strand entity with id/base/child/heads/pins, StrandError enum, and StrandRegistry BTreeMap-backed in-memory registry with deterministic iteration order and CRUD operations (insert, remove, get, contains, list_by_base, len, is_empty).
Integration Tests
crates/warp-core/tests/strand_contract_tests.rs
14 test cases validating strand invariants (S2/S4/S5/S7/S8/S9/S10), registry lifecycle (insert/remove/get/list operations), duplicate insertion failure, provenance fork semantics at unavailable ticks, and DropReceipt field correctness. All tests passing.
Design Documentation
docs/design/0004-strand-contract/design.md
Formal specification of strand semantics, ten invariants (INV-S1–INV-S10), BaseRef field agreement requirements, v1 hard constraints (empty support_pins), deterministic BTreeMap ordering, and module/test/API responsibilities.
Invariant Specification
docs/invariants/STRAND-CONTRACT.md
Normative RFC 2119 invariant spec (INV-S1–INV-S10) covering base_ref immutability/completeness, head independence, session scoping, manual tick control, construction-time validation, tick_quantum inheritance, child/base distinctness, strict head ownership, v1 support_pins constraint, and post-drop cleanup guarantees.
Shipment & Witness Documentation
docs/method/retro/0004-strand-contract/retro.md, docs/method/retro/0004-strand-contract/witness/rust-test-output.txt, docs/method/retro/0004-strand-contract/witness/shell-test-output.txt
Retro summary documenting delivered components, 14 passing Rust tests, 12 passing shell invariant assertions, outstanding debt items, and future improvement ideas.
Validation Script
scripts/tests/strand_contract_invariant_test.sh
Bash test harness validating invariant document existence, presence of all INV-S1–INV-S10 codes, and normative language ("MUST"). 12 passed, 0 failed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🧬 A strand splits forth from base worldline true,
With BLAKE3 hashing, deterministic and new.
BTreeMap holds strands in ordered array,
Speculative lanes where child heads play.
V1 pins stay empty—clean from the start. ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title 'feat(kernel): strand contract — cycle 0004' directly maps to the main change: introducing the strand contract as a first-class relation in warp-core with deterministic registry, ten invariants, and v1 lifecycle semantics.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cycle/0004-strand-contract

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: be444a7326

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +199 to +203
pub fn insert(&mut self, strand: Strand) -> Result<(), StrandError> {
if self.strands.contains_key(&strand.strand_id) {
return Err(StrandError::AlreadyExists(strand.strand_id));
}
self.strands.insert(strand.strand_id, strand);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reject invalid strand metadata during registry insert

StrandRegistry::insert only checks duplicate strand_id and accepts any other shape of Strand, so callers can register entries that violate the contract (for example child_worldline_id == base_ref.source_worldline_id, writer_heads from another worldline, or non-empty support_pins in v1). Because downstream code will treat registry contents as authoritative, this can silently corrupt strand topology/scheduling assumptions and break INV-S7/INV-S8/INV-S9 despite the module docs saying these invariants are enforced.

Useful? React with 👍 / 👎.

- Remove redundant `pub use echo_runtime_schema::HeadId` from strand.rs
  (already re-exported from lib.rs via head module)
- Add PartialEq + Eq derives to Strand struct (all fields support it)
- Add happy-path provenance fork integration test: commit 3 ticks,
  fork at tick 1, verify child has correct prefix length and base_ref
  fields match the provenance coordinate exactly
…ippy

Add invariant validation to StrandRegistry::insert:
- INV-S7: reject if child_worldline_id == source_worldline_id
- INV-S8: reject if any writer head belongs to wrong worldline
- INV-S9: reject if support_pins is non-empty in v1

Add StrandError::InvariantViolation variant.
Add 3 tests proving invalid strands are rejected.

Fix u64-to-u8 cast truncation warning in happy-path fork test
(use u8 loop variable with explicit u64 conversion).
@flyingrobots
Copy link
Copy Markdown
Owner Author

Fixed in 034592a: StrandRegistry::insert now validates INV-S7 (distinct worldlines), INV-S8 (head ownership), and INV-S9 (empty support_pins) before insertion. Invalid strands are rejected with StrandError::InvariantViolation. Added 3 tests proving rejection. Also fixed u64-to-u8 cast truncation that caused CI Clippy failures.

@flyingrobots
Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 4, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/warp-core/src/strand.rs`:
- Around line 205-208: The remove method currently returns Option<Strand> which
silently accepts missing IDs; change pub fn remove(&mut self, strand_id:
&StrandId) -> Option<Strand> to return Result<Strand, StrandError> and return
Err(StrandError::NotFound(*strand_id)) (or appropriate clone) when the id is
absent to match StrandError::NotFound; update all callers of
StrandRegistry::remove (or the remove function) to handle the Result error path
so drop failures are surfaced explicitly.
- Around line 224-229: Introduce a zero-allocation iterator API and make the
Vec-allocating API opt-in: add a new method (e.g., iter_by_base or
strands_by_base_iter) that returns an iterator over &Strand (signature like pub
fn iter_by_base<'a>(&'a self, base_worldline_id: &'a WorldlineId) -> impl
Iterator<Item = &'a Strand>) implemented as self.strands.values().filter(move
|s| &s.base_ref.source_worldline_id == base_worldline_id); then rewrite
list_by_base to be a thin wrapper that calls the new iterator and collects into
a Vec (keeping existing behavior for callers that need materialization). This
keeps the Strands map scanning lazy/zero-allocation for hot paths while
preserving the existing Vec-producing convenience API.
- Around line 133-144: The Strand struct currently exposes public fields
allowing invalid instances into the registry; add a Strand::validate_v1(&self)
-> Result<(), StrandError> that enforces INV-S7 (child_worldline_id !=
base_ref.source_worldline_id), v1 writer_heads cardinality == 1, and INV-S9
(support_pins.is_empty()), add a StrandError::InvariantViolation variant, call
validate_v1() from the registry insertion path (the code around the insertion
that currently only enforces ID uniqueness) and reject inserts on validation
failure, and either make Strand fields private with a validated constructor or
ensure all public construction sites call validate_v1(); note INV-S8 (writer
head membership) should be checked in validate_v1 once WriterHeadKey exposes a
worldline accessor.

In `@crates/warp-core/tests/strand_contract_tests.rs`:
- Around line 60-90: The tests currently use make_test_strand() which constructs
a perfectly valid Strand (with BaseRef, one writer_head and empty support_pins),
so INV-S2/S5/S7/S8/S9/cardinality checks only re-assert the fixture; change the
tests to either (A) stop calling these "contract-validation" tests or (B) add
negative and edge cases that exercise the real enforcement surface: create
Strand instances with invalid BaseRef/provenance (mismatched
provenance_ref.worldline_id or wrong commit_hash), with zero or multiple
writer_heads where cardinality forbids, with duplicate writer_heads, and with
non-empty support_pins that violate constraints, and then pass those instances
into the actual validation routine in warp_core::strand (e.g., call the module's
validate function such as validate_strand or Strand::validate) to assert the
validator rejects them rather than relying on the helper fixture.
- Around line 386-417: The test currently builds BaseRef from child_entry and
compares fields to the child copy; instead fetch the source entry via
store.entry(base_id, wt(1)) (e.g., let base_entry = store.entry(base_id,
wt(1)).expect(...)) and assert that base_entry.expected.commit_hash and
base_entry.expected.state_root equal the BaseRef.commit_hash and
BaseRef.boundary_hash respectively, and also assert
base_entry.expected.commit_hash/ state_root equal the
child_entry.expected.commit_hash/state_root to ensure fork() didn’t rewrite
those on the child; keep existing checks on BaseRef.provenance_ref.worldline_id,
worldline_tick, and commit_hash.

In `@docs/method/retro/0004-strand-contract/retro.md`:
- Around line 36-42: Update the playback table and surrounding prose in retro.md
to accurately reflect only the APIs and behaviors currently implemented and
tested: remove or reclassify any claims that "create_strand" or full drop
cleanup are delivered when they are not (per the later note that the
orchestrated create/drop API and provenance cleanup are future work), and
instead list only what the tests actually cover (e.g., that create_strand
returns the expected fields as verified by the 14 Rust tests, base_ref pinning
as shown by inv_s5, strand head states and exclusion from runnable set as shown
by inv_s4 and inv_s4_s10, and that drop-related behavior covered by
registry_remove and drop_receipt tests is limited to what those tests assert).
Ensure the table rows (create_strand, drop) and the explanatory lines around
them reference the actual test witnesses (inv_s4, inv_s5, inv_s4_s10,
registry_remove, drop_receipt, 14 Rust tests) and remove any forward-looking or
incorrect "delivered" wording, adding a short note that orchestrated create/drop
API and provenance cleanup remain future work.

In `@docs/method/retro/0004-strand-contract/witness/rust-test-output.txt`:
- Around line 2-18: The recorded test output is stale: rerun the test suite for
crates/warp-core (which now has 15 #[test] functions, including
provenance_fork_happy_path_child_has_correct_prefix) and update
docs/method/retro/0004-strand-contract/witness/rust-test-output.txt to reflect
the new output (should show "running 15 tests" and include the new test name and
the final summary of 15 passed); ensure the new file content exactly matches the
fresh cargo test output for the current branch.

In `@scripts/tests/strand_contract_invariant_test.sh`:
- Around line 38-40: The loop uses grep -q "${code}" which allows substring
matches (e.g., INV-S1 matching INV-S10); update the check so it only matches the
whole invariant token by anchoring the pattern or using
fixed-strings+line-anchoring against the invariant file: modify the assert call
that wraps grep -q (referencing the loop variable "${code}", the assert
invocation, and the "${invariant}" file) to use an anchored match (for example
grep with -x or a ^...$ regex or grep -F -x) so each code is matched exactly and
no false positives occur.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 54b5f288-3dfa-4ea4-a6e5-76b06746734f

📥 Commits

Reviewing files that changed from the base of the PR and between ebf3ee7 and 5699133.

📒 Files selected for processing (10)
  • crates/warp-core/src/lib.rs
  • crates/warp-core/src/strand.rs
  • crates/warp-core/tests/strand_contract_tests.rs
  • docs/design/0004-strand-contract/KERNEL_strand-contract.md
  • docs/design/0004-strand-contract/design.md
  • docs/invariants/STRAND-CONTRACT.md
  • docs/method/retro/0004-strand-contract/retro.md
  • docs/method/retro/0004-strand-contract/witness/rust-test-output.txt
  • docs/method/retro/0004-strand-contract/witness/shell-test-output.txt
  • scripts/tests/strand_contract_invariant_test.sh

Comment on lines +205 to +208
/// Removes a strand from the registry, returning it if it existed.
pub fn remove(&mut self, strand_id: &StrandId) -> Option<Strand> {
self.strands.remove(strand_id)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

remove silently accepts missing IDs; this weakens drop correctness.

Line 206 returns Option<Strand>, so a missing strand can be ignored accidentally. This is inconsistent with StrandError::NotFound (Lines 153-155) and makes drop-path failures easier to miss.

Proposed fix (explicit failure)
- pub fn remove(&mut self, strand_id: &StrandId) -> Option<Strand> {
-     self.strands.remove(strand_id)
- }
+ pub fn remove(&mut self, strand_id: &StrandId) -> Result<Strand, StrandError> {
+     self.strands
+         .remove(strand_id)
+         .ok_or(StrandError::NotFound(*strand_id))
+ }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// Removes a strand from the registry, returning it if it existed.
pub fn remove(&mut self, strand_id: &StrandId) -> Option<Strand> {
self.strands.remove(strand_id)
}
/// Removes a strand from the registry, returning it if it existed.
pub fn remove(&mut self, strand_id: &StrandId) -> Result<Strand, StrandError> {
self.strands
.remove(strand_id)
.ok_or(StrandError::NotFound(*strand_id))
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/warp-core/src/strand.rs` around lines 205 - 208, The remove method
currently returns Option<Strand> which silently accepts missing IDs; change pub
fn remove(&mut self, strand_id: &StrandId) -> Option<Strand> to return
Result<Strand, StrandError> and return Err(StrandError::NotFound(*strand_id))
(or appropriate clone) when the id is absent to match StrandError::NotFound;
update all callers of StrandRegistry::remove (or the remove function) to handle
the Result error path so drop failures are surfaced explicitly.

grep -q "INV-S1" would false-match INV-S10. Use anchored pattern
that matches heading format or spaced reference format.
…tor API, source-based BaseRef test

- StrandRegistry::remove now returns Result<Strand, StrandError>
  instead of Option, surfacing NotFound errors explicitly
- Add iter_by_base() zero-allocation iterator; list_by_base() is
  now a thin collect() wrapper
- Happy-path fork test now compares BaseRef against the SOURCE
  entry, not the child copy — catches incorrect rewrites by fork()
Retro playback table now accurately reflects 18 tests and notes
that orchestrated create/drop APIs are future work. Witness files
re-recorded from current branch.
@flyingrobots
Copy link
Copy Markdown
Owner Author

CodeRabbit Review — All Issues Addressed

# Severity File Issue Resolution Commit
1 Critical strand.rs Invariants not enforced at registry boundary Added INV-S7/S8/S9 validation in insert() 034592a
2 Critical strand_contract_invariant_test.sh grep -q "INV-S1" false-matches INV-S10 Anchored pattern matching c3416c5
3 Major strand.rs remove returns Option, silently accepts missing IDs Changed to Result<Strand, StrandError> with NotFound d6e4ecd
4 Major strand_contract_tests.rs Tests self-fulfilling through fixture Added 3 rejection tests (S7/S8/S9) driving real validation 034592a
5 Major strand_contract_tests.rs BaseRef compared against child copy, not source Now fetches source entry and compares against that d6e4ecd
6 Major retro.md Playback tables claim unshipped APIs Rewritten to reflect actual test coverage; future work noted f3c6b2e
7 Minor witness/rust-test-output.txt Stale (14 tests, now 18) Re-recorded from current branch f3c6b2e
8 Nit strand.rs list_by_base allocates on every call Added iter_by_base() zero-allocation iterator d6e4ecd

All 18 Rust tests + 12 shell assertions passing. Zero clippy warnings.

@flyingrobots
Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 4, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@flyingrobots flyingrobots merged commit be94aad into main Apr 4, 2026
30 checks passed
@flyingrobots flyingrobots deleted the cycle/0004-strand-contract branch April 4, 2026 19:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant