Repository navigation
Conversation
Add SigningStrategy::BatchTailTimeout { batch_size, max_wait_ns }, which
closes a pending signing span at batch_size records or after max_wait_ns
since the oldest unsealed record, whichever comes first - ported from
ruvector-retrieval-receipt::batch_fill's hybrid policy (ADR-343), not
reused as a dependency, since SignedWitnessSink commits spans through
the WitnessSink trait rather than a standalone scheduler.
Resolves the gap ADR-347 deferred ("No wall-clock fill timeout in this
pass") and its Open Question 1: under plain BatchTail, a partially
filled span has no bound on how long it can stay unauthenticated if
arrivals stop.
Adds emit_batch_at/check_timeout_at/check_timeout/
next_timeout_deadline_ns/strategy. Checks for an already-stale pending
span before merging a new arrival into it, not after - merging first
would silently stretch a late arrival's own wait past max_wait_ns.
Purely additive: PerRecord and BatchTail are unchanged.
Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_015NaMrxfn7UW7J5ps5Uf2TV
…ions 10 new tests (45 -> 55 in the crate): construction errors, dense-arrival equivalence with plain BatchTail, deadline boundary cases, the opportunistic-seal-on-late-arrival ordering fix, honest-chain verification with forced partial seals, and a randomized property test (8 trials x 20 steps, xorshift64-seeded) asserting observed pending age never exceeds max_wait_ns + poll_tick while the signed chain still verifies end to end. Trial/step counts are kept modest: Ed25519 signing in this sandbox's unoptimized debug build runs far slower than release mode, and a larger sweep turned this from a unit test into a multi-minute run; the dedicated benchmark example covers the release-mode, larger-N regime. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_015NaMrxfn7UW7J5ps5Uf2TV
New cargo example (witness_signing_timeout_bench) with two real,
wall-clock measurements, each with an explicit numeric acceptance gate
defined before running:
1. Dense-burst overhead: 20,000 add+accept pairs, no idle gaps,
BatchTail{64} vs BatchTailTimeout{64, 5ms}. Gate: mean-latency and
signature-count delta within +/-10%.
2. Sparse-arrival worst-case latency: a 20-record burst well under
batch_size, then a real 15ms idle gap. Gate: BatchTail leaves the
burst permanently pending with no timeout concept at all;
BatchTailTimeout force-seals within max_wait_ns + poll_interval.
Three runs: both gates PASS on every run (dense overhead -1.4%/-0.2%/
-7.1%, i.e. no regression; sparse force-seal at 5.53-5.65ms against a
6ms bound). Prints an explicit ACCEPT/REJECT line.
Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_015NaMrxfn7UW7J5ps5Uf2TV
Records the design, guarantees, limits, alternatives considered, security/governance analysis, migration/rollback path, and rejection criteria for SigningStrategy::BatchTailTimeout. Answers ADR-347's Open Question 1 and its deferred "wall-clock BatchTail fill timeout" alternative directly. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_015NaMrxfn7UW7J5ps5Uf2TV
Hypothesis, capability discovery (MetaHarness/Darwin/Flywheel checked and found not wired into this checkout - documented honestly rather than assumed), architecture diagram, raw benchmark evidence across three runs, rejected alternatives, manual Darwin-style lineage, ruFlo production-path workflow, practical and long-horizon applications, and falsification criteria for the 2026-10-11 nightly run. Acceptance: ACCEPT. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_015NaMrxfn7UW7J5ps5Uf2TV
CI:
|
CI:
|
Summary
Nightly research run (2026-10-11) that implements the specific gap the previous nightly (ADR-347) deferred:
ruvector-agent-memory'sSignedWitnessSink::SigningStrategy::BatchTailhas no bound on how long a partially-filled signing span can stay unauthenticated if arrivals stop. ADR-347's own "Alternatives Considered" ("Wall-clockBatchTailfill timeout. Deferred.") and Open Question 1 named this directly.SigningStrategy::BatchTailTimeout { batch_size, max_wait_ns }, which closes a pending span atbatch_sizerecords or aftermax_wait_nssince the oldest unsealed record, whichever comes first — porting the hybrid count-or-timeout policyruvector-retrieval-receipt::batch_fillalready validated (ADR-343), adapted natively toSignedWitnessSinkrather than added as a new dependency.PerRecord/BatchTailare byte-for-byte unchanged; no new Cargo dependency, no new crate.Architecture
Files changed
crates/ruvector-agent-memory/src/witness_signing.rs— core implementation (new strategy variant,emit_batch_at/check_timeout_at/check_timeout/next_timeout_deadline_ns/strategy,WitnessSignerError::ZeroMaxWait).crates/ruvector-agent-memory/src/witness_signing_tests.rs— 10 new tests (45 → 55 in the crate), including a randomized bounded-latency property test.crates/ruvector-agent-memory/examples/witness_signing_timeout_bench.rs— new dedicated benchmark (dense-burst overhead + sparse-arrival bounded-latency, both real wall-clock measurements).docs/adr/ADR-348-bounded-witness-batch-fill-timeout.md+docs/adr/INDEX.md— design record.docs/research/nightly/2026-10-11-bounded-witness-batch-timeout/{README.md,gist.md}— full nightly report (capability discovery, benchmark evidence, rejected alternatives, Darwin-style lineage, applications, falsification criteria).Benchmark command
Real benchmark results (3 runs)
Dense-burst overhead (20,000 add+accept pairs,
batch_size=64, no idle gaps; threshold ±10%):BatchTail{64}meanBatchTailTimeout{64,5ms}meanSparse-arrival worst-case latency (20-record burst, real 15ms idle gap,
max_wait_ns=5ms, 1ms poll; bound = 6ms):BatchTailpending after gapBatchTailTimeoutsealed afterEvery run printed an explicit
Acceptance: ACCEPTfrom the benchmark binary itself.Full regression:
cargo test -p ruvector-agent-memory --lib→ 55/55 passing.cargo clippy -p ruvector-agent-memory --all-targets -- -D warnings→ clean.cargo fmt -p ruvector-agent-memory -- --check→ clean.Acceptance result
Darwin / Flywheel / MetaHarness
Checked before assuming availability:
npx metaharness --helpresolves (a scaffolding generator, not a runtime for this repo),npx ruvector harness doctor/darwin/flywheeldoes not resolve an executable in this checkout. Documented honestly in the nightly README rather than fabricating tool output; this run used a manual equivalent (explicit hypothesis, real baseline, bounded one-candidate evolution, pre-declared fitness gates, retained rejected alternatives in the ADR).Security review
No new cryptographic surface — a timeout-forced seal produces the same
SignPurpose::BatchTail-tagged span a count-triggered seal would, indistinguishable to a verifier. Wall clock isInstant-based (monotonic, immune to system-clock adjustment). "No witness, no mutation" ordering preserved. Full detail in ADR-348's Security/Governance/Failure Modes sections.Main limitations
check_timeouttick must actually be wired up in production, orBatchTailTimeoutsilently degrades toBatchTail's original behavior. This is documented as an operational obligation, not hidden.MemoryWitnessLog) sink, multi-issuer, or WASM/edge measurement — explicitly out of scope, listed as open items.Production recommendation
Land as-is (additive, opt-in, zero behavior change for existing callers). Before relying on the bound in a real deployment: pick a
max_wait_nsdefault, build the described ruFlo periodic-tick workflow, and extend verification to a durable sink.Generated by Claude Code