feat(session): add session store event-sourcing protobuf contracts - #501
Conversation
yordis
commented
Jul 24, 2026
- ADR#0035 decided the session store as a decider aggregate on NATS JetStream but deferred the concrete wire contracts to implementation follow-up; this supplies that event-sourcing schema so the store can be built on the existing decider substrate rather than the prior art's hand-rolled JetStream/KV persistence.
Realizes the event schema decided in ADR#0035 so the session store can be built on the decider substrate. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
PR SummaryMedium Risk Overview ADR#0035 is updated to match: proto path CI Proto ( Reviewed by Cursor Bugbot for commit e596bdd. Bugbot is set up for automated code reviews on this repo. Configure here. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThis PR adds the v1alpha1 session-event protobuf model, Rust codec and validation support, ADR and glossary documentation, feature-aware decoding tests, and CI checks for proto compatibility and generated bindings. ChangesSession Event Contracts
Proto CI Automation
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@proto/trogonai/session/sessions/v1/artifact.proto`:
- Around line 12-18: Replace LEGACY_REQUIRED with EXPLICIT for required contract
fields in proto/trogonai/session/sessions/v1/artifact.proto lines 12-18,
proto/trogonai/session/sessions/v1/digest.proto lines 11-13,
proto/trogonai/session/sessions/v1/tool_call.proto line 19, and
proto/trogonai/session/sessions/v1/message.proto lines 16-18. Add boundary
validation for these fields, preserving an exception only where ADR#0035
explicitly requires historical-event compatibility.
In `@proto/trogonai/session/sessions/v1/cascade_policy.proto`:
- Around line 8-15: Reject CASCADE_POLICY_UNSPECIFIED at the command/decider
boundary for both SubagentLinked and DelegationDispatched before either link
fact is written. Validate that cascade_policy is explicitly
CASCADE_POLICY_CASCADE_ON_PARENT_TERMINAL or CASCADE_POLICY_INDEPENDENT, while
preserving the existing missing-field presence validation.
In `@proto/trogonai/session/sessions/v1/file_changed.proto`:
- Around line 12-13: Update the file-change persistence writer/runtime
validation around FileChangeKind and previous_path to reject
FILE_CHANGE_KIND_UNSPECIFIED and require a non-empty previous_path whenever the
kind is RENAMED. Preserve valid non-rename events, and enforce these invariants
before persistence rather than relying on LEGACY_REQUIRED.
In `@proto/trogonai/session/sessions/v1/tool_call.proto`:
- Around line 10-13: The typed oneof values used for persisted message events
currently allow empty Default/Some constructions. Update the builders for
ToolCallResult and ContentBlock::...::new(...) to validate that their oneof kind
is populated with a valid non-empty value before appending or persisting; reject
empty ToolCallResult::default() and ContentBlock variants containing default
image references. Apply this across tool_call.proto lines 10-13 and
message.proto lines 31-37, preserving valid text, artifact, and other content
variants.
In `@proto/trogonai/session/sessions/v1/user_message_recorded.proto`:
- Around line 10-11: The concrete persisted event fields currently use
LEGACY_REQUIRED, which can reject historical events missing fields. In
user_message_recorded.proto lines 10-11, assistant_message_started.proto lines
10-12, assistant_message_completed.proto lines 12-13, tool_call_requested.proto
lines 8-12, tool_call_started.proto lines 8-10, tool_call_approved.proto lines
8-11, tool_call_completed.proto lines 10-13, tool_call_failed.proto lines 8-11,
artifact_recorded.proto lines 10-11, and file_changed.proto lines 10-12, replace
LEGACY_REQUIRED with explicit presence semantics; enforce any new requiredness
at the aggregate boundary instead of these event message definitions.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: a8290457-2aa2-4638-86be-22d6d406a0b1
⛔ Files ignored due to path filters (78)
rsworkspace/crates/platform/trogonai-proto/src/gen/mod.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.artifact.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.artifact.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.artifact_recorded.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.artifact_recorded.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.assistant_message_completed.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.assistant_message_completed.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.assistant_message_started.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.assistant_message_started.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.cascade_policy.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.compacted.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.compacted.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.delegation_dispatched.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.delegation_dispatched.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.digest.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.digest.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.events.__oneof.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.events.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.events.__view_oneof.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.events.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.execution_attempt_ended.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.execution_attempt_ended.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.execution_attempt_ready.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.execution_attempt_ready.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.execution_attempt_started.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.execution_attempt_started.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.execution_plan.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.execution_plan.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.file_change.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.file_changed.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.file_changed.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.message.__oneof.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.message.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.message.__view_oneof.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.message.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.mod.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.operation_outcome_recorded.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.operation_outcome_recorded.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.operation_reserved.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.operation_reserved.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_cancelled.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_cancelled.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_closed.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_closed.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_deleted.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_deleted.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_failed.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_failed.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_forked.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_forked.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_rewound.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_rewound.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_started.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_started.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.subagent_detached.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.subagent_detached.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.subagent_linked.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.subagent_linked.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.subagent_parent_terminated.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.subagent_parent_terminated.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.token_usage.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.token_usage.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call.__oneof.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call.__view_oneof.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call_approved.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call_approved.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call_completed.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call_completed.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call_failed.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call_failed.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call_requested.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call_requested.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call_started.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call_started.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.user_message_recorded.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.user_message_recorded.rsis excluded by!**/gen/**
📒 Files selected for processing (36)
proto/trogonai/session/sessions/v1/artifact.protoproto/trogonai/session/sessions/v1/artifact_recorded.protoproto/trogonai/session/sessions/v1/assistant_message_completed.protoproto/trogonai/session/sessions/v1/assistant_message_started.protoproto/trogonai/session/sessions/v1/cascade_policy.protoproto/trogonai/session/sessions/v1/compacted.protoproto/trogonai/session/sessions/v1/delegation_dispatched.protoproto/trogonai/session/sessions/v1/digest.protoproto/trogonai/session/sessions/v1/events.protoproto/trogonai/session/sessions/v1/execution_attempt_ended.protoproto/trogonai/session/sessions/v1/execution_attempt_ready.protoproto/trogonai/session/sessions/v1/execution_attempt_started.protoproto/trogonai/session/sessions/v1/execution_plan.protoproto/trogonai/session/sessions/v1/file_change.protoproto/trogonai/session/sessions/v1/file_changed.protoproto/trogonai/session/sessions/v1/message.protoproto/trogonai/session/sessions/v1/operation_outcome_recorded.protoproto/trogonai/session/sessions/v1/operation_reserved.protoproto/trogonai/session/sessions/v1/session_cancelled.protoproto/trogonai/session/sessions/v1/session_closed.protoproto/trogonai/session/sessions/v1/session_deleted.protoproto/trogonai/session/sessions/v1/session_failed.protoproto/trogonai/session/sessions/v1/session_forked.protoproto/trogonai/session/sessions/v1/session_rewound.protoproto/trogonai/session/sessions/v1/session_started.protoproto/trogonai/session/sessions/v1/subagent_detached.protoproto/trogonai/session/sessions/v1/subagent_linked.protoproto/trogonai/session/sessions/v1/subagent_parent_terminated.protoproto/trogonai/session/sessions/v1/token_usage.protoproto/trogonai/session/sessions/v1/tool_call.protoproto/trogonai/session/sessions/v1/tool_call_approved.protoproto/trogonai/session/sessions/v1/tool_call_completed.protoproto/trogonai/session/sessions/v1/tool_call_failed.protoproto/trogonai/session/sessions/v1/tool_call_requested.protoproto/trogonai/session/sessions/v1/tool_call_started.protoproto/trogonai/session/sessions/v1/user_message_recorded.proto
Code Coverage SummaryDetailsDiff against mainResults for commit: e596bdd Minimum allowed coverage is ♻️ This comment has been updated with latest results |
Audited the event set against the nine session-store research products; these facts (denied tool calls, failed/finished assistant turns, produced checkpoints, opaque reasoning, priced usage) were persisted there but missing here, and each must be a recorded fact so deterministic audit/cost/outcome projections rebuild from the log alone. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
A field-level audit of the event payloads against the nine research products and the platform-branch prior art surfaced recorded facts we were flattening or dropping; each added field must be on the log so deterministic projections (model-visible context, cost, file diffs, checkpoint restore, compaction effect) rebuild from it alone. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
proto/trogonai/session/sessions/v1/artifact.proto (2)
30-38: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy liftUse explicit presence across the new event contracts.
LEGACY_REQUIREDmakes omitted fields wire-invalid; useEXPLICITand perform semantic validation before persistence, unless ADR#0035 explicitly requires wire-required compatibility. (protobuf.dev)
proto/trogonai/session/sessions/v1/artifact.proto#L30-L38: change storage metadata fields to explicit presence and validate them conditionally.proto/trogonai/session/sessions/v1/artifact.proto#L44-L48: change required availability metadata to explicit presence and validate it before persistence.proto/trogonai/session/sessions/v1/token_usage.proto#L21-L23: validate amount and currency at the cost writer boundary.proto/trogonai/session/sessions/v1/message.proto#L26-L26: validate message timestamps without wire-required parsing.proto/trogonai/session/sessions/v1/message.proto#L55-L55: validate thinking content at event construction.proto/trogonai/session/sessions/v1/checkpoint.proto#L13-L19: validate complete checkpoint identity and digest before persistence.proto/trogonai/session/sessions/v1/execution_attempt_started.proto#L13-L16: validate session, attempt, plan digest, and attempt number before persistence.proto/trogonai/session/sessions/v1/execution_attempt_started.proto#L20-L21: validate host reference and digest before persistence.proto/trogonai/session/sessions/v1/checkpoint_produced.proto#L13-L15: validate the produced checkpoint fact before persistence.proto/trogonai/session/sessions/v1/checkpoint_produced.proto#L19-L19: validate the checkpoint sequence at the writer boundary.proto/trogonai/session/sessions/v1/session_forked.proto#L12-L14: validate fork identifiers and history base sequence before persistence.proto/trogonai/session/sessions/v1/session_forked.proto#L17-L17: validate the concrete fork reason before persistence.proto/trogonai/session/sessions/v1/compacted.proto#L16-L20: validate compaction identity, summary, and boundaries before persistence.proto/trogonai/session/sessions/v1/compacted.proto#L22-L22: validate the concrete compaction trigger before persistence.proto/trogonai/session/sessions/v1/assistant_message_completed.proto#L13-L15: validate completion facts before persistence.proto/trogonai/session/sessions/v1/assistant_message_failed.proto#L11-L13: validate failure facts before persistence.#!/bin/bash set -euo pipefail rg -n "LEGACY_REQUIRED" proto/trogonai/session/sessions/v1 rg -n "SessionEvent|CheckpointProduced|AssistantMessageCompleted|AssistantMessageFailed|Serialize|Parse" .🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@proto/trogonai/session/sessions/v1/artifact.proto` around lines 30 - 38, Replace LEGACY_REQUIRED with EXPLICIT for the artifact storage metadata and availability fields in proto/trogonai/session/sessions/v1/artifact.proto (lines 30-38 and 44-48), then add semantic validation before persistence. Apply the same presence and validation policy across proto/trogonai/session/sessions/v1/token_usage.proto (21-23), message.proto (26, 55), checkpoint.proto (13-19), execution_attempt_started.proto (13-16, 20-21), checkpoint_produced.proto (13-15, 19), session_forked.proto (12-14, 17), compacted.proto (16-20, 22), assistant_message_completed.proto (13-15), and assistant_message_failed.proto (11-13), validating each field group described by the corresponding event contract at construction, writer, or persistence boundaries; retain LEGACY_REQUIRED only where ADR#0035 explicitly requires wire compatibility.
37-48: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy liftMake degraded artifacts representable without stored-byte fields.
EXTERNAL_REFmeans only an external reference is kept, butstorage_refis part of the stored-byte key/description andcreated_atis marked required for the whole message, so a degraded artifact cannot round-trip unless synthetic storage metadata is invented. Makestorage_refandcreated_atopt-in/optional forEXTERNAL_REF, and require them forSTOREDplus validatestorage_refpresence for degraded references.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@proto/trogonai/session/sessions/v1/artifact.proto` around lines 37 - 48, Update the artifact fields storage_ref and created_at to use optional presence rather than unconditional LEGACY_REQUIRED. Add validation keyed by ArtifactSourceAvailability: STORED artifacts must provide both fields, while EXTERNAL_REF artifacts may omit created_at but must provide storage_ref.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@proto/trogonai/session/sessions/v1/artifact.proto`:
- Line 48: Validate enum values before appending persisted events; field
presence alone does not reject zero-valued UNSPECIFIED values. In
proto/trogonai/session/sessions/v1/artifact.proto:48 require availability to be
STORED or EXTERNAL_REF; apply equivalent concrete-value validation to the
message role in message.proto:18, fork reason in session_forked.proto:17,
compaction trigger in compacted.proto:22, finish reason in
assistant_message_completed.proto:15, and failure reason in
assistant_message_failed.proto:13.
- Around line 49-50: Sanitize the value assigned to ArtifactMetadata.source_url
before it is persisted, rejecting or redacting URLs containing userinfo or
signed/authentication query tokens. Prefer recording a non-sensitive managed
storage or reference key when available, while preserving empty values for
artifacts without a source URL.
In `@proto/trogonai/session/sessions/v1/assistant_message_completed.proto`:
- Around line 13-15: Update the completed-event append/validation flow for the
CanonicalMessage field to require MESSAGE_ROLE_ASSISTANT before accepting the
event. Reject or avoid appending messages with user, system, or tool roles,
while preserving existing handling for valid assistant messages.
In `@proto/trogonai/session/sessions/v1/compacted.proto`:
- Around line 19-20: Validate the compaction range during event construction
before emitting the marker, ensuring from_sequence is not greater than
to_sequence. Reject reversed ranges immediately and prevent them from reaching
the event log, while preserving valid ranges.
---
Outside diff comments:
In `@proto/trogonai/session/sessions/v1/artifact.proto`:
- Around line 30-38: Replace LEGACY_REQUIRED with EXPLICIT for the artifact
storage metadata and availability fields in
proto/trogonai/session/sessions/v1/artifact.proto (lines 30-38 and 44-48), then
add semantic validation before persistence. Apply the same presence and
validation policy across proto/trogonai/session/sessions/v1/token_usage.proto
(21-23), message.proto (26, 55), checkpoint.proto (13-19),
execution_attempt_started.proto (13-16, 20-21), checkpoint_produced.proto
(13-15, 19), session_forked.proto (12-14, 17), compacted.proto (16-20, 22),
assistant_message_completed.proto (13-15), and assistant_message_failed.proto
(11-13), validating each field group described by the corresponding event
contract at construction, writer, or persistence boundaries; retain
LEGACY_REQUIRED only where ADR#0035 explicitly requires wire compatibility.
- Around line 37-48: Update the artifact fields storage_ref and created_at to
use optional presence rather than unconditional LEGACY_REQUIRED. Add validation
keyed by ArtifactSourceAvailability: STORED artifacts must provide both fields,
while EXTERNAL_REF artifacts may omit created_at but must provide storage_ref.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 0e67c476-5933-462f-969f-3e390921ecde
⛔ Files ignored due to path filters (34)
rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.artifact.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.artifact.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.assistant_message_completed.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.assistant_message_completed.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.assistant_message_failed.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.assistant_message_failed.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.checkpoint.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.checkpoint.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.checkpoint_produced.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.checkpoint_produced.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.compacted.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.compacted.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.events.__oneof.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.events.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.events.__view_oneof.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.events.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.execution_attempt_started.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.execution_attempt_started.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.file_changed.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.file_changed.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.message.__oneof.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.message.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.message.__view_oneof.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.message.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.mod.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.operation_outcome_recorded.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_forked.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_forked.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.system_notice_recorded.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.system_notice_recorded.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.token_usage.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.token_usage.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call_denied.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call_denied.rsis excluded by!**/gen/**
📒 Files selected for processing (15)
proto/trogonai/session/sessions/v1/artifact.protoproto/trogonai/session/sessions/v1/assistant_message_completed.protoproto/trogonai/session/sessions/v1/assistant_message_failed.protoproto/trogonai/session/sessions/v1/checkpoint.protoproto/trogonai/session/sessions/v1/checkpoint_produced.protoproto/trogonai/session/sessions/v1/compacted.protoproto/trogonai/session/sessions/v1/events.protoproto/trogonai/session/sessions/v1/execution_attempt_started.protoproto/trogonai/session/sessions/v1/file_changed.protoproto/trogonai/session/sessions/v1/message.protoproto/trogonai/session/sessions/v1/operation_outcome_recorded.protoproto/trogonai/session/sessions/v1/session_forked.protoproto/trogonai/session/sessions/v1/system_notice_recorded.protoproto/trogonai/session/sessions/v1/token_usage.protoproto/trogonai/session/sessions/v1/tool_call_denied.proto
🚧 Files skipped from review as they are similar to previous changes (1)
- proto/trogonai/session/sessions/v1/operation_outcome_recorded.proto
A multi-lens critic pass over the live model surfaced the tool-call/operation-ledger join, Claude's pause_turn/refusal stop reasons, a first-class plan/todo fact, and a per-branch required-ness fix for degraded artifacts; recording each keeps audit, cost, and plan projections deterministic folds of the log. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Second convergence round found only consistency and fold-correctness refinements, no new domain: partial-turn cost on AssistantMessageFailed, explanatory detail on the failure-only ExecutionAttemptEnded, an intentional-detach reason, and the artifact claim-check moved onto the shared Digest value object used everywhere else. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Third convergence round collapsed to a single required-presence annotation plus naming parity, no new domain: size_bytes required-ness, a generic artifact_ref arm name, and timeout parity on the assistant failure enum. The event data model is converged against all nine research products and the platform prior art. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…k in glossary Pin one precise meaning per term so a wider audience reads the session relationships the same way: the entity is a child session (a full session, one run of an agent), 'subagent' is only its informal synonym, and delegation/cascade-policy/fork are named distinctly rather than collapsed into 'sub'. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/glossary/cascade-policy.md`:
- Around line 9-12: Update the CascadePolicy glossary text to distinguish the
protobuf wire default, CASCADE_POLICY_UNSPECIFIED, from the application-level
safe default CASCADE_ON_PARENT_TERMINAL. In the command-layer handling of
cascade policy, explicitly record CASCADE_ON_PARENT_TERMINAL when the policy is
unspecified rather than relying on an omitted enum field.
In `@docs/glossary/fork.md`:
- Around line 9-12: Update the fork definition in the glossary to remove the
claim that forks never reference the source ID. State that a fork has its own
identity while persisting or retaining the source session reference used to
compose the shared prefix during replay.
In `@proto/trogonai/session/sessions/v1/artifact.proto`:
- Around line 44-47: Update ArtifactRecorded validation before appending
artifact events to require the source oneof to be set, rejecting records where
both stored and external are unset while preserving valid StoredArtifact and
ExternalArtifact records.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 45ef69a9-b431-4bb2-91b2-99d42830779f
⛔ Files ignored due to path filters (37)
rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.artifact.__oneof.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.artifact.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.artifact.__view_oneof.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.artifact.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.assistant_message_completed.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.assistant_message_completed.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.assistant_message_failed.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.assistant_message_failed.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.events.__oneof.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.events.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.events.__view_oneof.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.events.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.execution_attempt_ended.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.execution_attempt_ended.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.message.__oneof.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.message.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.message.__view_oneof.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.message.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.mod.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_forked.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_forked.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_rewound.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.session_rewound.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.subagent_detached.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.subagent_detached.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.system_notice_recorded.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.system_notice_recorded.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.todo_updated.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.todo_updated.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.token_usage.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.token_usage.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call_failed.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call_failed.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call_requested.__view.rsis excluded by!**/gen/**rsworkspace/crates/platform/trogonai-proto/src/gen/trogonai.session.sessions.v1.tool_call_requested.rsis excluded by!**/gen/**
📒 Files selected for processing (21)
docs/glossary/cascade-policy.mddocs/glossary/child-session.mddocs/glossary/delegation.mddocs/glossary/fork.mddocs/glossary/index.mddocs/glossary/subagent.mdproto/trogonai/session/sessions/v1/artifact.protoproto/trogonai/session/sessions/v1/assistant_message_completed.protoproto/trogonai/session/sessions/v1/assistant_message_failed.protoproto/trogonai/session/sessions/v1/events.protoproto/trogonai/session/sessions/v1/execution_attempt_ended.protoproto/trogonai/session/sessions/v1/message.protoproto/trogonai/session/sessions/v1/session_forked.protoproto/trogonai/session/sessions/v1/session_rewound.protoproto/trogonai/session/sessions/v1/subagent_detached.protoproto/trogonai/session/sessions/v1/system_notice_recorded.protoproto/trogonai/session/sessions/v1/todo_updated.protoproto/trogonai/session/sessions/v1/token_usage.protoproto/trogonai/session/sessions/v1/tool_call.protoproto/trogonai/session/sessions/v1/tool_call_failed.protoproto/trogonai/session/sessions/v1/tool_call_requested.proto
🚧 Files skipped from review as they are similar to previous changes (8)
- proto/trogonai/session/sessions/v1/subagent_detached.proto
- proto/trogonai/session/sessions/v1/tool_call.proto
- proto/trogonai/session/sessions/v1/system_notice_recorded.proto
- proto/trogonai/session/sessions/v1/execution_attempt_ended.proto
- proto/trogonai/session/sessions/v1/session_forked.proto
- proto/trogonai/session/sessions/v1/token_usage.proto
- proto/trogonai/session/sessions/v1/events.proto
- proto/trogonai/session/sessions/v1/message.proto
The data model now speaks one precise vocabulary matching the glossary: SubagentLinked->ParentLinked, SubagentParentTerminated->ParentTerminated, SubagentDetached->DelegationDetached, so the entity is a child session and 'subagent' stays only an informal synonym in prose. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
… facts The command matrix demanded a model check the failed-turn event cannot carry by design, and nothing said which of the two persisted cascade-policy copies wins when the dispatch saga is repaired. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…wording A bounded seen-key set with no stated horizon lets a duplicate outlive it on an unbounded log, and the external arm's never-fetched claim contradicted its own fetch-evidence fields. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Nats-Msg-Id dedup is stream-wide, so an id derived from the idempotency key alone lets one session's append silently swallow another's; the proto CI also missed base-branch retargets, which change the breaking baseline. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…boundary Malformed transcript blocks and non-JSON tool input could reach the keep-forever log because the validator never descended into content arms; a systematic proto-vs-validator sweep closed six more unchecked required fields so the gap class is exhausted, not sampled. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
An unset timestamp field derefs to the default instance, so a missing occurrence time validated as Unix epoch; timestamps were the one required message type whose default passes a value check. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
The claim-check contract is sha256-only in v1alpha1, but any non-empty algorithm passed the boundary, including with an empty value. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit fc57d40. Configure here.
A sha256 over empty content is a valid digest, so a plan-less SessionStarted could become durable despite the plan being the session's binding contract. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
