Implement runtime causal verification, shape constraints, and policy handling (REQ-200/220/231/305) #3
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "refs/pull/3/head"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
End-to-end implementation of the runtime side of CBCL's verification model. Before this branch, dialects could declare causal protocols and shape constraints, but those declarations weren't enforced when messages arrived. This branch closes the gap: parse → causal verify → expand → shape check → apply effects, with policy-driven handling of
Unknownpredecessors, blame attribution on every rejection, and signature binding for the new fields.What this implements
cbcl-core/src/protocol.rsValid/Unknown/Violation) withmeet/join.CausalProtocol,StepDecl,NodeRef::{Single, Any, All}.verify_causalreads:caused-by, looks up predecessors in the store, returns the result.cbcl-core/src/store.rsThreadedMessageStore(per-thread G-Set CRDT, ADR-008 thread isolation).HashIndexfor O(1) lookup.CausalClosureBundlefor thread-history transfer.cbcl-core/src/policy.rsUnknownPredecessorPolicy::{Reject, Buffer { max_pending, ttl }}.apply_policyis a pure mapping.PendingQueueis the per-thread bounded buffer with TTL and re-evaluation.cbcl-core/src/blame.rsViolationErrorattribution on every rejection (causal and shape).cbcl-core/src/r5.rsr5_violations_with_ancestorsresolves inherited performatives.cbcl-core/src/clock.rsClocktrait,NoClock(default),SystemClock(std-gated).cbcl-core/src/agent.rsAgentowns the store, policy, pending queue, merge policy, and clock.evaluate_and_applyenforces the full pipeline before applying effects. ReturnsAgentOutcome::{Applied, CausalReject, Pending, Buffered, EvalError}.MergePolicy::{Conjunction, Disjunction}for multi-protocol composition.cbcl-core/src/canonical.rscausal_protocolandshapeswhen present, byte-identical to v1 when absent.CANONICAL_FORM_VERSIONconstant tracks bumps.cbcl-parser/src/pipeline.rsrun_pipeline_fullorchestrates the fail-closed receive path with policy-drivenPending/Bufferedoutcomes. Wrapped/dialect-scoped messages traverse to the innermost Simple before verification.Review history
This branch went through four rounds of review feedback. Each round's findings are addressed in their own commits, listed here so reviewers can audit incremental fixes in isolation:
Round 1 — initial review (4 findings)
ed060e8R5 protocol definedness honors inherited performatives9f3a3aePipeline reorders causal verify before evaluate (no shape masking)eb4195ePipeline appliesUnknownPredecessorPolicy(was treatingUnknownasValid)2e3b56aAgent::evaluate_and_applyenforces causal verification (was bypassing entirely)Round 2 — five findings on round-1 fixes
e8350fbReject signed dialects withcausal_protocol/shapes(stopgap, later replaced)c687434Aliascbcl→cbcl-basein install-time ancestor resolutiond608b10Pipeline iterates all protocols mentioning a performative (child protocols on inherited perfs)4a58a27Meta-validation passes registry ancestors72356e9Pipeline traverses wrappers to innermost SimpleRound 3 — three findings, ported to agent
362ee77Agent traverses wrappersfcfd681Agent iterates all installed protocols8feb746Agent re-evaluation filters to matching protocolsRound 4 — three low-severity polish items
5752b43Extractedinnermost_simpletoMessagemethode07e8feExplicit(Pending, Pending)arm inmerge_policy_outcomes5cd9c7bClock-aware buffer (evaluate_and_apply_at/step_at/expire(now))Self-review / follow-ups (post round-4 sign-off)
1d25319Bindcausal_protocol/shapesvia canonical signing form (replaces the round-2 stopgap)d762a14AddMergePolicy::{Conjunction, Disjunction}to Agentd54d062InjectClocktrait into Agent96c3085FixMergePolicy::Disjunction(Unknown, Violation) inconsistency — surfaced by my own re-review; the live and re-evaluation paths disagreed under disjunction, allowing buffered messages to be flushed asRejectby an unrelated protocol's verdictfc49712Pin canonical form via version constant + golden-bytes snapshots6651d6ePolishClock:SystemClockfalls back tou64::MAXon failure, clone test, eviction-is-pull-based docTesting
877 workspace tests passing across 16 binaries. Each finding ships with a regression test that demonstrates the bug on the unfixed code, so a future regression in any specific area surfaces immediately.
Migration / API notes
Public API additions:
PipelineResult::{Pending, Buffered}variants;PipelineContext::{new, with_policy}constructorsAgent::{with_policy, with_clock, with_merge_policy, evaluate_and_apply_at, step_at, expire, reevaluate_pending}AgentOutcomeenum (replacesResult<EvalResult, EvalError>fromevaluate_and_apply)MergePolicy::{Conjunction, Disjunction}Clocktrait,NoClock,SystemClock(std-gated)CANONICAL_FORM_VERSION(currently2); legacy dialects produce v1-identical bytesMessage::innermost_simple()Behavioural changes:
Agent::evaluate_and_applyreturn type changed toAgentOutcome— call sites that pattern-matchedResultneed updating.run_pipeline_fullnow requires apolicyfield onPipelineContext(use::new()for the defaultReject).Test plan
cargo test --workspace)main(merged via0be60d9)