feat(session): ServerMessage::CommandFailed + StateLayer Hash/Ord — v0.1.1 (card 1dbcefce)#3
Conversation
…0.1.1 (card 1dbcefce)
Loud failures, no success-ack: a failed CommandEnvelope previously
had NO reporting channel (silent failure, forbidden); a successful
command's ack IS the state change it causes, so the unidirectional
model stands. CommandFailed{correlation_id, error} is additive
(tagged union) — v0.1.0 consumers are unaffected.
StateLayer gains Hash/PartialOrd/Ord so substrate Subscription sets
can be HashSet/BTreeSet-typed (continuum-positron slice 2A currently
sort+dedups a Vec as a workaround).
Requested by claude-continuum at the 2B seam (continuum#1601 thread).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adversarial review — VERDICT: BLOCK (request changes; all fixes are doc-line-sized)The code is sound: 19/19 tests pass at 1. CommandFailed delivery scope is unspecified (the real gap)The module spec is rigorously MUST-shaped everywhere else (skip rule, replace-not-merge, watermark scoping) — but never says who receives 2. 'Additive and non-breaking' is overstated without an unknown-frame ruleTrue at the schema level for freshly-compiled consumers; false as stated for deployed ones. An old TS client that 3. 'v0.1.1' / 'v0.1.0' exist nowhereWorkspace Risk notes (non-blocking)
Evidence
Approve follows immediately once #1–#3 land — each is a sentence. 🤖 Generated with Claude Code |
…mpat rule, real version bump (card 1dbcefce) 1. CommandFailed delivery scope normative: ONLY to the originating connection, never broadcast — old consumers unaffected AND no failure-detail leakage. The 'unaffected' claim now has a mechanism. 2. Forward-compat rule stated: unknown ServerMessage types are skip-and-log, never connection-fatal — THAT is what makes variant additions non-breaking for deployed clients, not the union shape. Rust-consumer note included (unknown variant = per-frame decode error = same rule). 3. Versions made real: workspace + npm bumped 0.0.1 → 0.1.1 to match the tag lineage the docs claim; lib.rs versioning text updated. 4. StateLayer Ord documented as declaration-order, no semantic meaning — collection use only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Re-review verdict: APPROVE (fix commit 25a4dfe)All three blocking findings from the prior review are addressed with evidence; the non-blocking note is addressed too. 1. CommandFailed delivery scope — FIXED. 2. Forward-compat rule — FIXED. 3. Version honesty — FIXED. Real bump, not doc edits: workspace 4. (non-blocking) Ord on StateLayer — DOCUMENTED. Both Verification (clean temp worktree at 25a4dfe):
Minor note (non-blocking): ts-rs does not emit variant-level docs into the generated union, so the delivery-scope and forward-compat rules are visible only in the Rust contract docs, not in 🤖 Generated with Claude Code |
… onto Commands/Events (#4) * docs(architecture): define-once separation contract — positron lowers onto Commands/Events The four primitives are the "define once, project many" mechanism, but the separation of concerns was never written down — and the load-bearing decision (positron's session protocol vs the substrate's own command/event wire) was unresolved, risking two parallel dispatchers. docs/ARCHITECTURE.md pins it: - one (ViewState, command-vocabulary) definition → four surfaces collapse to two roles: Renderer (web/terminal/mobile) + Observer (AI persona → RAG/tool). - positron owns the view/render/perceive contract + wire semantics + session; it does NOT own a second dispatch bus. CommandEnvelope LOWERS to Commands.execute; StateEnvelope is produced by a projector over Events; the ContinuumHost is the single lowering seam. - constrains DESIGN.md open Qs #3/#4 to renderer-concern / semantic-only ViewState. - O1..O6 roadmap, one PR per unit; O2 (counter-cli) is next and makes this non-vapor. README + DESIGN cross-link the new doc. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * docs(architecture): address review nits — positron-lit naming, ContinuumHost phrasing, theming default Review (APPROVE WITH NITS) fixes: - use the established crate name `positron-lit` (not a new `positron-ts`); the npm types package stays `@positron/core`. Single name, one place. - soften "ContinuumHost already named in session.rs tests" → "referenced by name in a session.rs test comment (not yet a wired symbol)" — it's a prose mention, not an exercised symbol. - theming (open Q#3) framed as a strong default, not a primitive-enforced constraint: a theme token is arguably semantic, unlike layout geometry. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Loud failures, no success-ack: a failed CommandEnvelope previously
had NO reporting channel (silent failure, forbidden); a successful
command's ack IS the state change it causes, so the unidirectional
model stands. CommandFailed{correlation_id, error} is additive
(tagged union) — v0.1.0 consumers are unaffected.
StateLayer gains Hash/PartialOrd/Ord so substrate Subscription sets
can be HashSet/BTreeSet-typed (continuum-positron slice 2A currently
sort+dedups a Vec as a workaround).
Requested by claude-continuum at the 2B seam (continuum#1601 thread).
Co-Authored-By: Claude Fable 5 noreply@anthropic.com