feat(update): session-keyed transfers + progress events (agent, VA-97) #98

Merged
David merged 2 commits from feat/VA-97-update-progress-session into main 2026-07-01 03:08:32 +02:00
Owner

Agent half of the VS-77 / VA-97 co-design. Together with vervain-server VS-77 this fixes the confirmed root cause of #VA-96: the two proto crates had diverged, so the server only ever emitted the 52-byte hash form of AgentUpdate, which the agent decoded as an End (never a Begin). No session ever opened, every block was dropped ("no active session"), and each block's first two bytes were misread as a request id (the len=16382 in the VA-96 logs).

Builds on #VA-96 (merged): its DropBurst coalescer and the NoSession/HashMismatch split are evolved here to key on session_id.

Wire change (lockstep with vervain-server VS-77)

  • AgentUpdate (13): explicit kind byte instead of length. Begin = u16 cmd | u8 0 | u32 session_id | u64 total; End = u16 cmd | u8 1 | u32 session_id | 48-byte sha384.
  • AgentUpdateBlock (14): gains a u32 session_id header; the per-block ack echoes u16 cmd | u32 session_id.
  • New AgentUpdateProgress (32, agent -> server): session_id | phase | received | total | detail.

Agent behaviour

  • UpdateSession is keyed on session_id (+ stores total). Blocks whose id does not match the active transfer are rejected without touching it; an End only finalizes when its id matches.
  • net.rs emits progress at each boundary: session-start, throttled downloading (at most one event per 5%), verifying, applying, and restarting (flushed before execv, which never returns), plus failed on hash mismatch / apply error / stray-session block. Emission is best-effort and never aborts the transfer.

Tests

just check + full lib suite pass. New: session-mismatch rejection leaves the active transfer intact; End-with-no-matching-session is not a hash failure; proto round-trips for the new Begin/End/Block/Progress frames and phase codes.

Dependency

Co-designed with vervain-server VS-77, which ships the byte-identical wire layout. Land them together.

Agent half of the VS-77 / VA-97 co-design. Together with vervain-server VS-77 this fixes the confirmed root cause of #VA-96: the two proto crates had diverged, so the server only ever emitted the 52-byte hash form of `AgentUpdate`, which the agent decoded as an End (never a Begin). No session ever opened, every block was dropped ("no active session"), and each block's first two bytes were misread as a request id (the `len=16382` in the VA-96 logs). Builds on #VA-96 (merged): its DropBurst coalescer and the NoSession/HashMismatch split are evolved here to key on `session_id`. ## Wire change (lockstep with vervain-server VS-77) - `AgentUpdate` (13): explicit `kind` byte instead of length. Begin = `u16 cmd | u8 0 | u32 session_id | u64 total`; End = `u16 cmd | u8 1 | u32 session_id | 48-byte sha384`. - `AgentUpdateBlock` (14): gains a `u32 session_id` header; the per-block ack echoes `u16 cmd | u32 session_id`. - New `AgentUpdateProgress` (32, agent -> server): `session_id | phase | received | total | detail`. ## Agent behaviour - `UpdateSession` is keyed on `session_id` (+ stores `total`). Blocks whose id does not match the active transfer are rejected without touching it; an End only finalizes when its id matches. - `net.rs` emits progress at each boundary: session-start, throttled downloading (at most one event per 5%), verifying, applying, and restarting (flushed before `execv`, which never returns), plus failed on hash mismatch / apply error / stray-session block. Emission is best-effort and never aborts the transfer. ## Tests `just check` + full lib suite pass. New: session-mismatch rejection leaves the active transfer intact; End-with-no-matching-session is not a hash failure; proto round-trips for the new Begin/End/Block/Progress frames and phase codes. ## Dependency Co-designed with vervain-server VS-77, which ships the byte-identical wire layout. Land them together.
feat(update): session-keyed transfers + progress events (agent side)
Some checks failed
Check / fmt + clippy + tests (pull_request) Has been cancelled
2eeff88970
WIRE CHANGE (lockstep with vervain-server VS-77; the server crate `vervain-agent-proto` MUST match byte-for-byte):

- AgentUpdate (opcode 13) now discriminates Begin vs End by an explicit `kind` byte instead of by frame length. Begin carries `u32 session_id | u64 total`; End carries `u32 session_id | 48-byte sha384`. Length-based discrimination (plus a server that only ever emitted the 52-byte hash form) is the root cause of VA-96: every start marker decoded as an End, so no session ever opened and every block was dropped.
- AgentUpdateBlock (opcode 14) gains a `u32 session_id` header; the per-block ack echoes `u16 cmd | u32 session_id`.
- New AgentUpdateProgress (opcode 32, agent -> server): `session_id | phase | received | total | detail`, phases session-start/downloading/verifying/applying/restarting/failed.

Agent behaviour:

- UpdateSession stores `session_id` + `total`; the active session is keyed on `session_id`. Blocks whose id does not match the active transfer are rejected without touching it (BlockOutcome::SessionMismatch), and an End only finalizes when its id matches (VA-97 AC3/AC4).
- net.rs emits progress at each boundary: session-start on Begin, throttled downloading (at most one event per 5% of total), verifying + applying + restarting (flushed before execv, which never returns), and failed on hash mismatch / apply error / stray-session block. Emission is best-effort and never aborts the authoritative transfer.
- Reconciles with VA-96: the DropBurst coalescer now keys on session_id; a stray-session block surfaces one failed progress event per distinct id instead of a silent drop.

This is the agent half of the VS-77/VA-97 co-design that fixes the VA-96 root cause. It stacks on the VA-96 branch.

#VA-97

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Merge branch 'main' into feat/VA-97-update-progress-session
All checks were successful
Check / fmt + clippy + tests (pull_request) Successful in 5m32s
Create release / Create release from merged PR (pull_request) Has been skipped
86960f0e50
David scheduled this pull request to auto merge when all checks succeed 2026-07-01 03:03:04 +02:00
David merged commit 85507a4895 into main 2026-07-01 03:08:32 +02:00
David deleted branch feat/VA-97-update-progress-session 2026-07-01 03:08:32 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/vervain-agent!98
No description provided.