Skip to content

Implement Hive runtime structural upgrades#21

Merged
christopherkarani merged 4 commits intomasterfrom
0218
Feb 20, 2026
Merged

Implement Hive runtime structural upgrades#21
christopherkarani merged 4 commits intomasterfrom
0218

Conversation

@christopherkarani
Copy link
Owner

  • Summary
    • Introduce new persistent data structures, runtime indexing, native queues, mmap checkpoints, and signpost instrumentation so Hive can fork, checkpoint, and profile safely before phase-based rollout.
    • Replace the global store backing map, join barrier logic, and memory recall with deterministic HAMT, bitset barriers, and BM25 inverted index respectively, plus add C-backed MPSC queues and mmap checkpoint support with new instrumentation hooks.
  • Testing
    • Not run (not requested)

@christopherkarani
Copy link
Owner Author

@claude review

@claude
Copy link

claude bot commented Feb 19, 2026

Claude finished @christopherkarani's task in 2m 54s —— View job


PR Review: Implement Hive runtime structural upgrades

Tasks:

  • Gather context and read changed files
  • Review new data structures (HiveBitset, HiveInvertedIndex)
  • Review HiveRuntime.swift changes
  • Review HiveGraphBuilder.swift changes
  • Review HiveCachePolicy.swift
  • Review schema/store/memory changes
  • Review test coverage
  • Check for spec compliance issues
  • Post final review

This is a substantial PR adding meaningful capabilities. The core ideas are sound, but there are several correctness and maintainability concerns worth addressing before merge.


Critical Issues

1. Accidentally committed claude-mem CLAUDE.md files

29 of the 50 changed files are CLAUDE.md files containing only <claude-mem-context> boilerplate with "No recent activity". The majority of these are in locations that don't belong in the repo:

  • ~/.claude/CLAUDE.md and ~/.claude/plans/CLAUDE.md — home directory, outside repo
  • https:/github.com/christopherkarani/Swarm (README/CLAUDE.md — not a real path
  • Sources/HiveSwarm/CLAUDE.md, Sources/Wax/CLAUDE.md, Sources/WaxCore/CLAUDE.md, etc. — directories that don't contain any Swift source

These all read:

<claude-mem-context>
# Recent Activity

*No recent activity*
</claude-mem-context>

These should be removed. They bloat the PR noise, obscure the real changes, and commit tooling artifacts that have no business being in version control. Fix this →

2. HiveSchemaRegistry() constructed on every cache key computation

In HiveCachePolicy.swift:131:

private static func storeHashKey(store: HiveStoreView<Schema>) -> String {
    var hasher = SHA256()
    if let registry = try? HiveSchemaRegistry<Schema>() {  // ← allocated every call
        for spec in registry.sortedChannelSpecs where spec.scope == .global {

storeHashKey is called once per node lookup and once per node store, every superstep. Constructing and throwing away a HiveSchemaRegistry on each call is wasteful. The registry is already available in HiveRuntime via self.registry — it should be threaded through, or the key provider should be given registry access at construction time, not per-call.

3. forkAttempt is ~180 lines of near-duplicate code

forkAttempt (HiveRuntime.swift:1074–1253) is structurally identical to the existing single-attempt run loop. Any bug fix applied to runAttempt must be manually replicated in forkAttempt. Consider extracting the inner step loop into a shared helper, or making runAttempt accept an optional sourceCheckpointID parameter. As-is, this is a maintenance landmine.


Correctness Issues

4. HiveNodeCache.lookup leaves expired entries in place

HiveCachePolicy.swift:173:

if let expiry = entry.expiresAt, nowNanoseconds > expiry { return nil }

Expired entries are returned as nil but remain in entries. They count against maxEntries and can push out valid entries during eviction. The expired entry should be removed on access, or a separate expiry sweep should run on store(...).

5. TTL nanosecond conversion can overflow

HiveCachePolicy.swift:76:

let ttlNs = UInt64(ttl.components.seconds) * 1_000_000_000
    + UInt64(max(0, ttl.components.attoseconds / 1_000_000_000))

UInt64(ttl.components.seconds) * 1_000_000_000 overflows for durations greater than ~18 years. This is unlikely in practice but should use checked arithmetic (&*) or a reasonable cap. The attoseconds conversion also discards precision unnecessarily — attoseconds / 1_000_000_000 converts attoseconds to nanoseconds, but ttl.components.attoseconds is already the sub-second component in attoseconds — the math is correct but max(0, ...) is dead code since Duration components are always non-negative.

6. HiveInvertedIndex.query silently truncates Double scores to Float

HiveInvertedIndex.swift:85:

.map { (docID: $0.key, score: Float($0.value)) }

The internal computation is in Double for precision. Truncating to Float loses ~7 decimal digits of precision. This matters for determinism when comparing scores in tie-breaking. The return type should be Double, or the truncation should happen at the display layer.

7. Cache key provider errors are silently swallowed

HiveRuntime.swift (cache lookup):

let cacheKey = try? cachePolicy.keyProvider.cacheKey(forNode: task.nodeID, store: cachePreStoreView)

try? means a broken or misconfigured HiveCacheKeyProviding silently disables caching entirely. The error should at minimum be logged via environment.logger, or the runtime should surface it as a warning event.

8. fork ignores retry policy

The fork public API does not have a retry variant. If the fork encounters a transient failure, there's no retry loop — the task throws immediately. The existing run method has runWithRetry / runWithCheckpointAndRetry counterparts. fork has none. If retry is intentionally unsupported for forks, this should be documented.

9. HiveStateSnapshot.nextNodes can contain duplicates

HiveRuntime.swift:

nextNodes: state.frontier.map(\.seed.nodeID),

A node can appear multiple times in the frontier (e.g., scheduled by both a router and a static edge). nextNodes should deduplicate, or the documentation should note that duplicates are possible.


Design / Minor Issues

10. HiveCachePolicy.channels(_:maxEntries:) allocates JSONEncoder per channel per call

HiveCachePolicy.swift:122:

if let data = try? JSONEncoder().encode(AnySendableWrapper(value)) {

This allocates a new JSONEncoder for every channel in the key computation, every time the cache key is requested. A shared encoder instance would help.

11. HiveBarrierTopicChannels.swiftSwift.max disambiguation

HiveBarrierTopicChannels.swift:

let normalizedMaxValuesPerTopic = Swift.max(1, maxValuesPerTopic)

Good fix — the explicit Swift.max disambiguation avoids ambiguity when HiveReducer.max() is in scope. This is a correct and welcome change.

12. staticLayersByNodeID / maxStaticDepth appear unused by the runtime

These new fields are computed during compilation and stored in CompiledHiveGraph, but the runtime doesn't currently use them to schedule or prioritize tasks. This is fine as forward-looking API, but consider marking them internal rather than public until the scheduling code lands, to avoid locking down the API surface prematurely.

13. AGENTS.md WaxMCP protocol section

The added mandatory WaxMCP rules reference tools (wax_remember, wax_recall, etc.) that are not part of the Hive SDK. This belongs in a separate developer tooling document, not in AGENTS.md which is consumed by agents working on the codebase itself. Consider separating tooling conventions from agent coding conventions.


Test Coverage Gaps

Feature Tests Present Gap
HiveBitset ✅ 3 tests Missing: insert out-of-bounds, wordCount: 0
HiveInvertedIndex ✅ via MemoryStore tests Missing: direct unit tests, remove on nonexistent doc
Static layer analysis ✅ 3 tests Good coverage
HiveCachePolicy / HiveNodeCache ❌ None LRU eviction, TTL expiry, cache hit/miss in runtime
Deferred nodes (HiveNodeOptions.deferred) ❌ None Deferred execution ordering
fork ❌ None Fork from checkpoint, fork inheriting state
getState ❌ None In-memory vs checkpoint fallback
Ephemeral channel reset ❌ None Reset after superstep

Summary

The core structural changes — bitset join barriers, BM25 recall, static layer analysis, deferred nodes, and cache policy — are well-conceived. The implementation quality is generally good. The main concerns are:

  1. Remove the accidental claude-mem CLAUDE.md files — they dominate the diff and should not be committed
  2. Fix the expired cache entry bug — entries should be evicted on access
  3. Factor out the duplicated fork loop — maintainability risk
  4. Add tests for cache, deferred nodes, and fork
    | PR branch: 0218

@christopherkarani
Copy link
Owner Author

@claude make fixes, add tests

@claude
Copy link

claude bot commented Feb 20, 2026

Claude finished @christopherkarani's task in 7m 6s —— View job


Fixes and tests applied

Tasks:

  • Read source files to understand current code
  • Remove accidentally committed CLAUDE.md files (21 files removed)
  • Fix expired cache entries not removed on access
  • Fix TTL nanosecond overflow
  • Fix HiveInvertedIndex Double→Float score truncation
  • Fix JSONEncoder allocated per channel per call
  • Add HiveCachePolicy / HiveNodeCache tests (8 tests)
  • Add HiveInvertedIndex unit tests (11 tests)
  • Add HiveBitset edge case tests (4 tests)
  • Commit and push changes

Changes in commit d83aba2

Bug fixes (HiveCachePolicy.swift):

  • Expired entries are now removed from entries on lookup rather than left in place. Previously they counted against maxEntries and could displace valid entries during LRU eviction.
  • lruTTL nanosecond conversion no longer overflows: seconds are capped to 9 billion (≈285 years) before multiplying, with wrapping arithmetic for defense-in-depth.
  • JSONEncoder is now a module-level private let _sharedCacheKeyEncoder instead of being allocated on every channel in every key computation call.

Bug fix (HiveInvertedIndex.swift + HiveMemoryTypes.swift + HiveRAGWaxStore.swift):

  • query(terms:limit:) return type changed from Float to Double — preserves full BM25 score precision and fixes determinism in tie-breaking.
  • HiveMemoryItem.score updated to Double? for consistency.
  • HiveRAGWaxStore internal scoring updated from Float to Double.

Removed files:

  • 21 accidentally committed claude-mem CLAUDE.md files from Sources/HiveSwarm/, Sources/Wax/, Sources/WaxCore/, Sources/WaxMCPServer/, Wax/Sources/WaxMCPServer/, https:/, and ~/.claude/ paths.

New tests:

  • HiveInvertedIndexTests.swift — 11 tests: empty index, empty terms, limit zero, single doc, Double precision assertion, remove nonexistent (no-op), remove existing, posting list cleanup, upsert overwrite, limit respected, tie-breaking lexicographic order, term frequency scoring.
  • HiveNodeCacheTests.swift — 8 tests: miss, hit, TTL expiry with entry removal, valid before expiry, LRU eviction ordering, overwrite, expired entries count, overflow safety of lruTTL factory.
  • HiveBitsetTests.swift additions — 4 tests: wordCount:0 produces empty/no-op, out-of-bounds insert is no-op, out-of-bounds contains returns false, bitCapacity:0 clamps to one word.

Not addressed (complexity too high for this pass):

  • forkAttempt code duplication (~180 lines) — requires careful refactoring of the step loop shared with runAttempt; left for a focused follow-up.
  • HiveSchemaRegistry() constructed per cache key call — requires threading the registry through the static key helpers; the per-call cost is modest (registry is a value type) and the fix needs design review.
  • Silent swallowing of try? cache key provider errors — requires access to environment.logger from a static context; worth a follow-up but not a correctness blocker.
    | PR branch: 0218

- Remove 21 accidentally committed claude-mem CLAUDE.md files from
  Sources/HiveSwarm, Sources/Wax, Sources/WaxCore, Sources/WaxMCPServer,
  Wax/Sources/WaxMCPServer, https:/, and ~/.claude paths

- HiveCachePolicy: remove expired cache entries on lookup (bug fix)
  Previously, expired entries were returned as nil but stayed in `entries`,
  counting against maxEntries and displacing valid entries via LRU eviction

- HiveCachePolicy: fix UInt64 overflow in lruTTL nanosecond conversion
  Cap seconds to 9 billion before multiplying, use wrapping arithmetic

- HiveCachePolicy: use shared JSONEncoder instead of per-call allocation
  Avoids constructing a new JSONEncoder for every channel on every key
  computation

- HiveInvertedIndex: return Double scores instead of Float
  Truncating Double BM25 scores to Float lost ~7 decimal digits of
  precision relevant to deterministic tie-breaking

- HiveMemoryTypes / HiveRAGWaxStore: propagate Float→Double change
  HiveMemoryItem.score and HiveRAGWaxStore's internal scoring both
  updated to Double for consistency

- Add HiveInvertedIndexTests: 11 tests covering empty index, term/limit
  edge cases, upsert/remove, duplicate key replacement, limit, tie-breaking,
  and score ordering

- Add HiveNodeCacheTests: 8 tests covering miss, hit, TTL expiry with
  entry removal, LRU eviction, overwrite, and lruTTL overflow safety

- Extend HiveBitsetTests: 4 new edge-case tests for wordCount:0,
  out-of-bounds insert/contains, and bitCapacity:0 clamping

Co-authored-by: Christopher Karani <christopherkarani@users.noreply.github.com>
@christopherkarani
Copy link
Owner Author

@claude Review

@claude
Copy link

claude bot commented Feb 20, 2026

Claude finished @christopherkarani's task in 4m 38s —— View job


PR Review: Implement Hive runtime structural upgrades

Tasks:

  • Gather context
  • Read key changed files
  • Review data structures (HiveBitset, HiveInvertedIndex)
  • Review HiveCachePolicy
  • Review HiveRuntime changes (fork, deferred, cache integration)
  • Review HiveGraphBuilder static layer analysis
  • Review test coverage
  • Post final review

This review covers the current state of the PR after the two previous fix passes. The core architectural additions are sound; the remaining issues are primarily in the cache integration.


Critical Correctness Issues

1. Cache hits do not update LRU order — eviction is broken

HiveRuntime.swift:1773:

guard var nodeCache = state.nodeCaches[task.nodeID] else { continue }
guard let cachedOutput = nodeCache.lookup(key: cacheKey, policy: cachePolicy, nowNanoseconds: cacheNowNs)
    else { continue }
cachedResultsByTaskIndex[index] = cachedOutput

nodeCache is a value copy — mutations inside lookup (specifically the lastUsedOrder &+= 1 update on line 183 of HiveCachePolicy.swift) are applied to the local copy and immediately discarded. The updated nodeCache is never written back to state.nodeCaches. As a result, cache hits never advance LRU order — the LRU algorithm degrades to effectively FIFO/random eviction. The same bug exists at the store path (line 1902), though there the mutation is correctly persisted via updatedNodeCaches.

Fix: after the lookup loop, write mutated caches back into state.nodeCaches for any hit. Fix this →

2. storeHashKey produces a trivial constant key if HiveSchemaRegistry() fails

HiveCachePolicy.swift:130-144:

private static func storeHashKey(store: HiveStoreView<Schema>) -> String {
    var hasher = SHA256()
    if let registry = try? HiveSchemaRegistry<Schema>() {  // ← fails silently
        for spec in registry.sortedChannelSpecs where spec.scope == .global { ... }
    }
    return hasher.finalize().compactMap { ... }.joined()
}

If HiveSchemaRegistry() throws (malformed schema, channel ID collision, etc.), the body is skipped and the SHA256 of an empty input is returned — a constant, always-identical key. Every node using .lru() or .lruTTL() would then share the same key, causing every superstep to incorrectly return the very first cached result as a hit. This is silent data corruption, not just a performance miss.

The previous session flagged the per-call allocation as waste; the correctness consequence of the silent failure was not addressed. Fix this →

3. HiveStateSnapshot.nextNodes can have duplicate node IDs (unfixed from previous review)

HiveRuntime.swift:184 (and 203):

nextNodes: state.frontier.map(\.seed.nodeID),

A node can appear more than once in the frontier (scheduled by both a static edge and a router). The nextNodes array will contain duplicates. Callers who use nextNodes to determine what runs next may see incorrect data. A .map followed by a Set.sorted would fix this deterministically. Fix this →


Design Issues

4. forkAttempt is still ~160 lines of near-verbatim duplication (acknowledged unfixed)

The forkAttempt body (lines 1077–1249) mirrors runAttempt almost exactly. The only structural difference is the state loading preamble: fork loads a specific checkpoint and mutates state.runID, whereas runAttempt goes through resolveBaselineState and processes input writes. The event emission, step execution, cancellation handling, interrupt handling, and streaming events are character-for-character copies.

Any bug fixed in runAttempt's step loop must be manually replicated in forkAttempt. The LRU bug above (issue #1) exists in both functions independently. A shared inner loop helper accepting an already-loaded ThreadState would eliminate this class of divergence.

5. try? cache key errors still silently disable caching with no log

HiveRuntime.swift:1771:

let cacheKey = try? cachePolicy.keyProvider.cacheKey(forNode: task.nodeID, store: cachePreStoreView)

A misconfigured or broken HiveCacheKeyProviding silently skips caching for all nodes in every superstep. There's no log, no event, and no way for the operator to know caching is disabled. This was flagged in the previous review and remains. At minimum, the error should be sent to environment.logger.

6. HiveSchemaRegistry<Schema>() is allocated on every storeHashKey call

Even in the non-failure case, this allocates a fresh registry value on each cache key computation (once per node per lookup, once per node per store). The registry is already available on HiveRuntime as self.registry; it cannot currently be threaded through HiveCachePolicy's static helpers because they're not instance methods. The cleanest fix is to make storeHashKey accept a registry or a list of specs as a parameter.


What's in Good Shape

HiveBitset: Clean and correct. wordCount:0 produces a genuinely empty bitset (no words), all out-of-bounds operations are no-ops, and Equatable conformance is derived correctly from the word array. The tests added in the previous pass cover the edge cases well.

HiveInvertedIndex: The BM25 scoring formula is correct. The Double score precision fix from the previous session is properly carried through to HiveMemoryItem.score and HiveRAGWaxStore. Tie-breaking via HiveOrdering.lexicographicallyPrecedes ensures determinism. The query returns > 0 scores — IDF is always positive with this formula, so the filter is safe.

computeStaticLayers: Kahn's algorithm is implemented correctly with stable lexicographic ordering of the frontier. Cycle detection (visitedCount != nodes.count) is correct. Join edges are correctly excluded from the DAG analysis (only static edges are used). Tests cover diamond DAGs, cycle detection, and router-only loops.

Cache policy factories: The lruTTL overflow fix (capped seconds, wrapping arithmetic) from the previous session is correct. _sharedCacheKeyEncoder as a module-level let avoids per-call allocation.

HiveReducer+Standard additions: appendNonNil, setUnion, and dictionaryMerge are well-typed and follow the existing reducer pattern. dictionaryMerge processes keys in lexicographic order for determinism — important for Hive's BSP model.

Deferred node scheduling (HiveNodeOptions.deferred): The frontier promotion logic (lines 762-768 in runAttempt and equivalently in resumeAttempt and forkAttempt) is correct: deferred nodes are promoted only when the main frontier is exhausted.

HiveNodeCache LRU eviction: The O(n) evictLRU is appropriate for the expected small cache sizes (default 128 entries). The expired-entry-removal-on-access fix from the previous session is correct. Overwrites of existing keys correctly don't grow the entry count.


Remaining Test Gaps

Feature Status
Cache hit LRU update (issue #1) ❌ No test demonstrates LRU update on hit
fork from checkpoint with live step execution ❌ No integration test
getState with checkpoint fallback ❌ No test
HiveNodeOptions.deferred end-to-end ❌ No integration test
Ephemeral channel reset after superstep ❌ No test
HiveCachePolicy.channels with unknown channel IDs ❌ No test

Summary

The critical item before merge is issue #1 (cache hits discarding LRU updates) — this makes the LRU eviction policy non-functional for hit traffic. Issue #2 (empty hash on registry failure) is a silent correctness hazard that should also be addressed. Issue #3 (duplicate nextNodes) is a minor API contract bug.

The forkAttempt duplication (issue #4) is a maintenance risk but doesn't produce incorrect output at runtime.
| PR branch: 0218

@christopherkarani
Copy link
Owner Author

@claude fix all issues close all gaps

@claude
Copy link

claude bot commented Feb 20, 2026

Claude finished @christopherkarani's task in 6s —— View job


Fixes applied and test gaps closed

All issues from the previous two reviews have been addressed in commit 8cdb3d0.


Changes made

HiveCachePolicy.swift — Issues #2 + #6

storeHashKey no longer constructs HiveSchemaRegistry<Schema>() on every cache key computation. The sorted global specs are now captured once at factory time inside lru() and lruTTL(). This eliminates both the per-call allocation and the silent-constant-hash bug: previously a failed registry construction produced an empty SHA256 hash, causing every superstep to look like a cache hit. The degraded case (empty spec list) now produces a per-nodeID constant key — no cross-node collisions, but less store-content discrimination.

HiveRuntime.swift — Issues #1, #3, #4, #5

  • Scaffold Hive workspace and plans #1 (LRU writeback): In the cache lookup loop of executeStep, nodeCache was a value-type copy that was mutated inside lookup() but never written back, silently discarding all lastUsedOrder updates (and expired-entry removals). The loop now writes state.nodeCaches[task.nodeID] = nodeCache after every lookup — hits and misses — so LRU eviction works correctly.

  • feat: ensure deterministic event streaming under backpressure #3 (nextNodes dedup): Both getState code paths now call the new deduplicatedNextNodes(from:) helper that deduplicates via Set and sorts lexicographically, preventing duplicate entries when a node is scheduled by both a static edge and a router.

  • fix: ensure hive runtime obeys deterministic retries/cancellation #4 (forkAttempt duplication): Extracted executeRunLoop (lines 898–1054) from runAttempt, resumeAttempt, and forkAttempt, eliminating ~209 lines of near-verbatim code. Two parameters encode the behavioral differences: firstStepResume (resume payload for first step) and clearInterruptionAfterFirstStep (used by resumeAttempt). Error handling semantics are preserved exactly: RuntimeCancellation is caught inside executeRunLoop and returns .cancelled; all other errors propagate to callers.

  • Phase8 #5 (silent cache key errors): try? replaced with do/catch + environment.logger.debug(...) so cache key provider failures are visible in logs rather than silently disabling caching.

New test file: HiveRuntimeCacheAndForkTests.swift

Test Covers
testCache_HitSkipsNodeExecution End-to-end: cache hit skips node re-execution
testCache_LRUWritebackPreservesOrder LRU order persists across hits; correct entry evicted
testCachePolicy_ChannelsUnknownIDs Unknown channel IDs degrade gracefully, no crash
testGetState_CheckpointFallback getState loads from checkpoint when no in-memory state
testGetState_NilWhenNoState getState returns nil when thread never ran
testDeferredNodes_ExecuteAfterMainFrontier Deferred nodes run after main frontier is exhausted
testEphemeralChannel_ResetsAfterSuperstep Ephemeral channels reset to initial value after each superstep
testFork_RunsFromCheckpointToCompletion Fork loads checkpoint and runs new thread to completion
testGetState_NextNodesDeduplication nextNodes deduplicates nodes appearing multiple times in frontier

Remaining items (not addressed)

None of the issues from the previous reviews remain open. The one item previously marked "too complex for this pass" (HiveSchemaRegistry threading) is resolved by the factory-time capture approach in lru()/lruTTL().
| PR branch: 0218

Critical fixes:
- LRU writeback: write mutated nodeCache back to state.nodeCaches after every
  lookup so lastUsedOrder updates (and expired-entry removals) are not silently
  discarded (fixes cache hit LRU ordering and eviction correctness)
- storeHashKey silent failure: capture sortedGlobalSpecs at factory time in
  lru()/lruTTL() instead of constructing HiveSchemaRegistry per call; avoids
  per-call allocation AND the constant-hash bug when registry construction fails
- nextNodes deduplication: HiveStateSnapshot.nextNodes now deduplicates and
  sorts via deduplicatedNextNodes(from:) helper (fixes duplicate nodes when
  scheduled by both a router and a static edge)
- Log cache key errors: replace try? with do/catch + environment.logger.debug
  so cache key provider failures are surfaced rather than silently disabled

Refactoring:
- Extract shared executeRunLoop helper from runAttempt/resumeAttempt/forkAttempt
  eliminating ~209 lines of near-verbatim duplication; firstStepResume and
  clearInterruptionAfterFirstStep parameters encode the two behavioral differences

New tests (HiveRuntimeCacheAndForkTests.swift):
- testCache_HitSkipsNodeExecution: end-to-end cache hit skips re-execution
- testCache_LRUWritebackPreservesOrder: LRU order persists across hits
- testCachePolicy_ChannelsUnknownIDs: unknown channel IDs degrade gracefully
- testGetState_CheckpointFallback: getState loads from checkpoint when no
  in-memory state exists
- testGetState_NilWhenNoState: getState returns nil when thread never ran
- testDeferredNodes_ExecuteAfterMainFrontier: deferred nodes run after main
  frontier is exhausted
- testEphemeralChannel_ResetsAfterSuperstep: ephemeral channels reset to
  initial value after each superstep commit
- testFork_RunsFromCheckpointToCompletion: fork loads checkpoint and runs
  new thread to completion
- testGetState_NextNodesDeduplication: nextNodes deduplicates nodes that
  appear multiple times in frontier

Co-authored-by: Christopher Karani <christopherkarani@users.noreply.github.com>
@christopherkarani christopherkarani merged commit dc9f3d4 into master Feb 20, 2026
1 check failed
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