ZARA/1 device actions: define bounded replay horizon for at-most-once semantics #350
Closed
opened 2026-09-08 02:03:36 +00:00 by nsaspy
·
6 comments
No Branch/Tag specified
master
agent/pi-coder-plugin-2026-09-17
fix/android-remote-listener
ui/chat-message-bubbles
release/v0.1.1-alpha-20260908
fix/default-daemon-endpoint-20260908
ui/650-outrun-shell
fix/400-plugin-capability-composition
fix/tts-idle-cpu-spin
design/android-canonical-reference-2026-09-07
fixtures/voice-recordings
rage/core/388-tool-cancellation-r18
rage/core/388-tool-cancellation-r1
release/v0.1.0-alpha
rage/android/175-terminal-transcript-fence-r4
rage/core/324-expanded-history-sidebar-r2
rage/android/175-terminal-transcript-fence-r3
rage/android/175-focus-release-retry-r2
rage/android/175-focus-release-retry
ci/desktop-idle-cpu-budget
rage/android/175-terminal-transcript-fence-r2
rage/android/175-route-stop-retry-r3
rage/575-transient-send-backpressure-r3
rage/575-transient-send-backpressure-r2
rage/android/175-terminal-transcript-fence
rage/android/175-route-stop-retry-r2
rage/android/175-sink-self-close-r2
rage/android/175-route-stop-retry
rage/android/175-sink-self-close
rage/android/175-audio-focus-sync-loss-r2
rage/android/175-stock-voice-interop-r3
rage/android/175-stock-voice-interop-r2
rage/android/175-audio-focus-sync-loss
rage/android/175-recover-stack-current-4
rage/android/175-stock-voice-interop-r1
rage/android/175-recover-stack-current-2
rage/587-vulkan-current-master-r2
rage/587-dictation-vulkan-current2
rage/575-transient-send-backpressure-r1
tmp-do-not-use-587
tmp-do-not-use-587-2
tmp-do-not-use-587-3
tmp-do-not-use-587-4
rage/587-dictation-vulkan-current2-tree
fix/dictation-ggml-vulkan-rage587
rage/android-campaign-batch-20260906
rage/587-dictation-ggml-vulkan-current
rage/388-toolnode-forwarding-r17-current2
rage/587-dictation-ggml-vulkan-r1
rage/388-toolnode-forwarding-r17-current
rage/575-gateway-send-diagnostics-current
rage/178-device-action-json-depth-r7
rage/175-recorder-failure-precedence-r8
rage/175-terminal-capture-cleanup-r8
rage/175-playback-write-failure-cleanup-r8
rage/575-gateway-send-diagnostics
rage/388-toolnode-forwarding-r17
rage/575-stock-interop-diagnostics-r2
fix/dictate-whisper-cpp-vulkan
rage/575-stock-interop-diagnostics-r1
rage/324-expanded-history-sidebar-r1
rage/178-device-action-json-depth-r6
rage/388-plugin-cancellation-r16
rage/175-recorder-failure-precedence-r7
rage/175-terminal-capture-cleanup-r7
rage/175-playback-write-failure-cleanup-r7
rage/324-native-chrome-r1
rage/175-recorder-failure-precedence-r6
rage/175-terminal-capture-cleanup-r6
rage/175-playback-write-failure-cleanup-r6
rage/324-independent-geometry-r2
rage/175-close-resource-precedence
rage/178-device-action-json-depth-r5
rage/175-recorder-failure-precedence-r5
rage/175-terminal-capture-cleanup-r5
rage/175-playback-write-failure-cleanup-r5
rage/324-independent-geometry-r1
rage/324-screenshot-provenance-r1
rage/324-history-parity-r1
rage/178-device-action-json-depth-r4
rage/175-preserve-recorder-primary-failure-r2
rage/175-capture-terminal-failure-cleanup-r3
rage/175-playback-write-failure-cleanup-r4
rage/324-screenshot-ci-r1
rage/324-unified-copilot-r4
rage/175-capture-terminal-failure-cleanup-r2
rage/175-playback-write-failure-cleanup-r3
rage/324-unified-copilot-r3
rage/175-preserve-recorder-primary-failure
rage/175-capture-terminal-failure-cleanup
rage/178-device-action-json-depth-r3
rage/175-playback-write-failure-cleanup-r2
rage/178-voice-stream-json-depth-r5
rage/160-semantic-first-runtime-r2
rage/175-playback-write-failure-cleanup
rage/178-voice-stream-json-depth-r4
rage/324-unified-copilot-r2
rage/178-device-action-json-depth-r2
rage/178-voice-json-depth-r3
rage/178-voice-ack-json-depth-r3
rage/160-semantic-first-runtime
rage/492-device-action-replay-r6
rage/178-device-action-json-depth
rage/178-voice-json-depth-r2
rage/178-voice-ack-json-depth-r2
rage/178-voice-json-depth-bound
rage/178-voice-ack-json-depth
rage/178-voice-hello-json-depth
rage/178-device-json-depth-bound
rage/178-capability-json-depth-bound
rage/178-android-daemon-restart-stale-turn-r2
rage/492-device-action-replay-r5
rage/492-device-action-replay-r4
rage/178-android-daemon-restart-stale-turn-r1
rage/178-android-json-depth-bound-r2
rage/178-android-json-depth-bound-r1
rage/203-android-playback-session-invalidation-r3
rage/492-device-action-replay-r3
rage/178-android-audio-payload-bound-r4
rage/203-android-playback-session-invalidation-r2
rage/178-android-audio-payload-bound-r3
rage/492-device-action-replay-r2
rage/203-android-ui-close-runtime-ownership-r3
rage/203-android-playback-session-invalidation
rage/178-android-audio-payload-bound-r2
rage/203-android-ui-close-runtime-ownership-r2
rage/178-android-uri-intent-abuse-r4
rage/178-android-audio-payload-bound
rage/203-android-ui-close-runtime-ownership
rage/492-device-action-replay-r1
rage/178-android-uri-intent-abuse-r3
rage/178-android-no-raw-logging-r5
rage/492-device-action-replay-horizon
rage/218-normalizer-config-r4
rage/178-android-uri-intent-abuse-r2
rage/178-android-no-raw-logging-r4
rage/178-android-uri-intent-abuse-r1
rage/218-normalizer-config-r3
rage/178-android-no-raw-logging-r3
rage/178-android-prolog-lifecycle-r3
rage/178-android-no-raw-logging-r2
rage/178-android-prolog-lifecycle-r2
rage/178-android-principal-target-abuse-r2
rage/178-android-no-raw-logging-r1
rage/178-android-prolog-lifecycle-r1
rage/178-android-principal-target-abuse-r1
rage/178-android-device-action-replay-r4
rage/178-android-device-action-replay-r3
rage/178-android-capability-revocation-r3
rage/218-normalizer-config-r2
rage/178-android-trealla-result-overflow-r1
rage/178-android-device-action-replay-r2
rage/178-android-capability-revocation-r2
rage/178-android-auth-revocation-r2
rage/178-android-device-action-replay-r1
rage/178-android-capability-revocation-r1
rage/178-android-auth-revocation-r1
rage/178-android-reconnect-storm-r3
rage/218-normalizer-config-r1
rage/218-normalizer-config-status-r1
rage/324-unified-copilot-r1
rage/217-s1-mini-normalizer-r4
rage/178-android-reconnect-storm-r2
rage/178-reconnect-storm-red-proof
rage/217-s1-mini-normalizer-r3
rage/178-android-release-matrix-r1
rage/217-s1-mini-normalizer-r2
rage/203-android-recorder-failure-diagnostics-r3
rage/217-s1-mini-normalizer-r1
rage/203-android-assistant-role-loss-wiring-r3
rage/216-transcript-normalization-contract-r2
rage/203-android-recorder-failure-diagnostics-r2
rage/203-android-assistant-role-loss-wiring-r2
rage/216-transcript-normalization-contract-r1
rage/203-android-reconnect-scheduler-failure-r2
rage/388-plugin-tool-cancellation-r15
rage/203-android-reconnect-scheduler-failure
rage/203-android-voice-session-invalidation-r4
rage/203-android-voice-session-invalidation-r3
rage/203-android-ui-error-redaction-r3
rage/388-plugin-tool-cancellation-r14
rage/388-plugin-tool-cancellation-r13
rage/400-plugin-capability-composition-r1
rage/203-android-ui-error-redaction-r2
rage/388-plugin-tool-cancellation-r12
rage/203-android-audio-route-rollback-failure-r2
rage/325-atomic-durable-message-append
rage/203-android-state-store-temp-isolation-r2
rage/388-plugin-tool-cancellation-r11
rage/388-plugin-tool-cancellation-r10
rage/203-android-audio-route-rollback-failure
rage/203-android-recorder-failure-diagnostics
rage/203-android-voice-runtime-invalidation-r2
rage/203-android-assistant-role-loss-wiring
rage/203-android-voice-session-invalidation-r2
rage/203-android-ui-error-redaction
rage/388-plugin-tool-cancellation-r9
rage/203-android-state-store-temp-isolation
rage/203-android-connection-error-redaction
rage/203-android-assistant-role-loss-r3
rage/388-plugin-tool-cancellation-r8
rage/203-android-voice-runtime-invalidation-primitives
rage/203-android-assistant-role-loss-r2
rage/203-android-voice-diagnostic-redaction-r2
rage/388-plugin-tool-cancellation-r7
rage/203-android-assistant-role-loss
rage/203-android-voice-session-invalidation
rage/203-android-voice-diagnostic-redaction
rage/174-android-open-app-aliases
rage/388-plugin-tool-cancellation-r6
rage/203-android-assistant-shutdown-fence
rage/388-plugin-tool-cancellation-r5
rage/29-streaming-tts-provider-recovery-r10
rage/203-android-mic-permission-lifecycle
rage/203-android-audio-route-lifecycle
rage/175-android-audio-focus-lifecycle
rage/174-android-device-capabilities
rage/29-streaming-tts-provider-recovery-r9
rage/388-plugin-tool-cancellation-r4
rage/388-plugin-tool-cancellation-r3
rage/29-streaming-tts-provider-recovery-r8
rage/326-desktop-toggle
rage/388-plugin-tool-cancellation-r2
rage/388-plugin-tool-cancellation
rage/29-streaming-tts-current-r7
rage/29-streaming-tts-current-r6
rage/371-plugin-approval-current
rage/29-streaming-tts-current-r5
rage/371-plugin-approval-contract
rage/371-plugin-approval-red
rage/29-streaming-tts-current-r4
rage/196-ui-closed-runtime
rage/196-android-assistant-role
rage/29-streaming-tts-current-r3
rage/175-android-barge-in
rage/175-android-streamed-voice
rage/175-android-manual-voice
rage/29-streaming-tts-current-r2
rage/29-streaming-tts-current
rage/327-bounded-target-edit-distance-recovery-r2
rage/348-dash-prefixed-z85-cli-r2
rage/197-compose-first-usable
rage/348-dash-prefixed-z85-cli
rage/173-android-client-continuity
rage/327-bounded-target-edit-distance-recovery
rage/329-production-secure-listener
rage/329-merge-probe
rage/159-zara1-device-actions-current
docs/refresh-20260905
rage/159-zara1-device-actions-recovery
rage/324-unified-copilot
rage/173-android-auth
rage/327-bounded-target-edit-distance
research/unified-copilot-20260905
rage/133-desktop-daemon-default-regression
rage/133-daemon-default-regression
rage/13-open-app-allowlist-regression
rage/165-user-command-runtime
rage/315-route-backpressure-test-contract
rage/164-user-command-authoring
rage/163-user-command-compiler
rage/162-user-command-persistence
rage/309-prolog-config-recovery
docs/260-customization-wiki
rage/260-customization-diagnostics
rage/159-zara1-device-actions
rage/260-agent-loop-backend-registry
rage/260-backend-registry
rage/260-service-plugin-advice
backup/rage-260-service-plugin-advice-pre-android-merge-20260903
rage/android-172-cross-runtime-parity
rage/zara-004-config-durability
rage/260-prolog-command-advice
feature/long-horizon-tasks
rage/264-config-delta
rage/264-host-delta
rage/264-config-host-delta
rage/rebase-264-long-horizon-tasks
backup/rage-260-prolog-command-advice-pre-rebase-20260903
rage/android-172-resolver-parity
rage/260-python-user-hooks
rage/260-agent-loop-integration
rage/android-172-asset-staging
rage/android-172-native-adapter
rage/260-python-hooks-advice
rage/android-172-jni-bridge
rage/android-172-trealla-runtime
rage/260-hooks-prolog-config
rage/android-172-fixture-runner
fork/prolog-rlm-agentic-runtime
rage/android-172-normalized-results
rage/android-172-assets-v2
rage/core-246-todo-toggle-current
rage/android-172-assets
rage/core-246-todo-toggle-refresh
rage/android-172-portable-prolog-refresh
feature/agent-mode-core
rage/recover-259-run10
rage/android-172-portable-prolog
docs/244-merge-evidence
backup/feature-long-horizon-tasks-pre-rebase-20260902
feat/zara-031-context-management
docs/250-merge-evidence
rage/250-amd-stt-device-routing
rage/159-zara1-capability-advertisement
feat/unified-agent-tui
fix/discord-tools-bash
rage/158-api-service-providers
docs/249-merge-evidence
rage/249-latency-trace-checkpoint
fix/246-disable-todo-surface
codex/zara-discord-plugin-guidance
rage/157-execution-plans
rage/156-prolog-frames
rage/28-post-merge-evidence
perf/zara-027-streaming-llm-impl
rage/155-typed-slots
test/live-smoke-reasoning-budgets
feature/openrouter-rlm-directmode
rage/154-intentframe-contract
chore/backlog-import
rage/195-samsung-assistant-research
feat/android-app
research/aradr-local-tts-voice-cloning
feature/wake-words-edit-distance
perf/zara-027-streaming-llm
docs/134-reentry-assessment
rage/134-daemon-release-gate
rage/131-merge-closeout
docs/rage-130-merge-outcome
docs/rage-17-merge-outcome
fix/zara-016-llm-provider-contracts
build/flake-update-2026-08
rage/191-zara1-tool-approvals
rage/132-visible-stt-regression
codex/copilot-redesign
codex/default-daemon-cli
rage/132-transcript-events
rage/133-post-merge-evidence
rage/133-client-migration
rage/132-post-merge-evidence
rage/132-live-voice
rage/132-live-voice-zara1
rage/131-principal-isolation
rage/131-principal-scope
rage/130-curve-zap-security
rage/130-auth-security
docs/rage-129-merge-outcome
rage/129-zara1-protocol
rage/129-slice-e-lifecycle-red
rage/129-slice-e-endpoint-red
docs/rage-128-merge-outcome
rage/139-daemon
docs/full-feature-sweep
feature/mcp-client-support-current
remove-prolog-rlm
research/daemon-zeromq-voice-service
feature/autoresearch-bootstrap
agent/VAD-patch
agent/prolog-capability-reasoner
agent/whisper-cpp-vulkan-stt
agent/remove-pet-notification-spam
codex/service-plugin-runtime
agent/stt-backends
agent/fix-laptop-stt-quality
feature/prolog-rlm-integration
agent/fix-speaker-echo-loop
agent/stt-gpu-rocm-support
agent/fix-ubuntu-wayland-pets
feature/desktop-theme-contrast
fix/whisper-load-state
agent/mcp-client-support
fix/wake-model-readiness-debug
fix/wake-capture-failure-propagation
fix/wake-audio-health
agent/readme-current-zara
fix/desktop-conversation-migration-repair
agent/fix-voice-runtime-noise
feature/desktop-launch-surface
feature/quick-copilot
feature/conversation-full-chat
feature/desktop-shell
feature/runtime-host
feature/runtime-events
research/desktop-copilot
agent/overhaul-memory-forgetting
agent/fix-command-context-routing
agent/fix-streaming-vad-wake
agent/pets-post-merge-fixes
feature/pets
revert/wake-throughput
fix/wake-word-detection
fix/pulse-shared-mic-ci
fix/shared-mic-capture
feat/zara-timer-alarm-sounds
fix/zara-017-todo-correctness
fix/zara-015-prolog-engine-contract
fix/zara-018-ack-result-events
agent/readme-rewrite
fix/zara-014-wake-lifecycle
fix/zara-013-file-tool-sandbox
fix/zara-012-process-safety
fix/recover-zara-006-011-to-master
revert-36-fix/zara-005-dictation-lifecycle
revert-44-fix/zara-011-dictation-ordering
fix/zara-010-tts-contracts
fix/zara-011-dictation-ordering
fix/zara-007-intent-precedence
fix/zara-008-multi-tool-history
fix/zara-009-memory-fallback
fix/zara-006-timers
fix/zara-005-dictation-lifecycle
fix/zara-003-fail-closed-commands
fix/zara-004-prolog-config-overrides
agent/ci-test-gate
fix/zara-002-config-toml
fix/zara-001-wake-entrypoint
memory
cleanup
device-acceptance-661
v0.1.0-alpha
Labels
Clear labels
bug
Something isn't working
documentation
Improvements or additions to documentation
duplicate
This issue or pull request already exists
enhancement
New feature or request
good first issue
Good for newcomers
help wanted
Extra attention is needed
invalid
This doesn't seem right
question
Further information is requested
wontfix
This will not be worked on
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
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
nsaspy/zara#350
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Android #178 adversarial review found a shared ZARA/1 contract ambiguity that should stay Core-owned.
Current Android
ZaraTextClientActorbounds terminal device-action IDs to 256 entries. That satisfies bounded per-session resource use, but after eviction an oldaction_idcan no longer be distinguished locally from a fresh action. Meanwhile #159 requires duplicate side effects to follow the declared idempotency policy and also requires bounded per-session queues/rates/payloads.Please define the canonical replay contract rather than letting Android invent one:
at_most_onceapplies for the full authenticated session or a bounded replay horizon;Android will keep the existing bounded owner and will not add a second replay protocol or unbounded cache until this is specified. This does not block current #178 slices that only exercise stale-session and immediate duplicate replay behavior.
Core source analysis on canonical master
fd91a74e05e28371d903d44256d10c8a29ba5134:device.action.requestcarries only randomaction_id; there is no protocol-owned ordering/replay evidence.Selected contract direction for RED/TDD:
action_seqfor each authenticated ZARA/1session_id, starting at 1 and never supplied by the device/model.device.action.requestcarries both opaqueaction_id(correlation) andaction_seq(replay evidence).action_seqis immutable for that request.at_most_onceis guaranteed only inside a protocol-defined rolling window of 256 sequence numbers per authenticated session. Device keeps high-water + bounded seen window; duplicate seq inside the window fails closed without re-executing.action_seq <= high_water - 256is replay-ineligible and fails closed as expired/stale rather than being treated as fresh. This prevents cache eviction from reopening side effects.session_idis a new replay epoch: sequence restarts and prior-session actions remain invalid via existing stale-session fencing. Reconnect that preserves an authenticated session must preserve its replay state; session rotation resets it.best_effort(if retained by the closed idempotency enum) does not weaken session/deadline/target validation; only duplicate-side-effect guarantees differ.RED matrix before production: first seq accepted; immediate duplicate rejected; duplicate at window edge rejected; seq just outside window rejected as replay-expired; monotonic gap accepted; stale prior-session seq rejected after rotation; forged/decreasing/zero/non-int
action_seqfails protocol validation; server proves sequence is Core-generated and scoped to exact principal+session.I am keeping this generic/Core-owned and will not add an Android-specific replay path.
Core #492 wiring is now implemented on draft PR #524, exact candidate head
1983d22087f52683e50c95f886119b5aaf68f664(do not consume as canonical until exact-head CI is fully green/merged).Shared contract at this head:
device.action.request.body.action_seqis required, positive integer only; bool/zero/negative/non-int fail closed.ZaraZmqGatewayowns issuance from authenticated route/session state, starting at 1 and incrementing monotonically under the gateway lock.session_idcreates a new sequence epoch starting at 1.action_idremains correlation only; bounded replay classification remains the protocol-owned 256-sequence contract inzara/device_action_replay.py.android/**changes.TDD: CI #1742 is the pre-production wiring RED witness. Exact-head CI #1754 is running for the production candidate; both shared-mic lanes are already green, Core + Android gates are still in progress. Android should wait for the merged Core SHA before treating
action_seqas canonical.Core #492 recovered onto exact current master after sibling Android #522 advanced canonical. New authoritative draft is PR #526 at
6da79f56e02ae57e86049b91616e3d5c932f318a.Recovery is one coherent commit reusing the exact #524 / CI #1754 green Core blobs on top of master
7a6b3cf6a9f524e29dcd6da624ec76fd6c89e749; #522 was Android-only, so zero Core overlap and zeroandroid/**changes.Contract is unchanged: required positive
device.action.request.body.action_seq, server-owned monotonic per authenticated session starting at 1, session rotation resets the epoch, opaqueaction_idremains correlation, replay horizon remains 256 and fails closed for duplicate/expired evidence.Fresh exact-head CI #1757 is queued. Android should consume only after #526 is merged and the canonical merge SHA is posted here.
Core #492 exact-current recovery is now draft PR #529 at
86c054b111b5d9c16980c457f3b079c4ecd95c53, based on canonicalf8ba7eb9f891eddb54de71390dd942567a8866fdafter sibling Android #527. #527 is Android-only/non-overlapping; #529 reuses the exact six Core blobs that passed CI #1757 at prior candidate6da79f56e02ae57e86049b91616e3d5c932f318aand has zeroandroid/**changes. Fresh exact-head CI #1763 is in progress. Contract remains required positiveaction_seq, Core-owned monotonic per authenticated session starting at 1, 256-sequence replay horizon, fail-closed duplicate/expired evidence, opaqueaction_idfor correlation. Android should consume only after #529 is fully green and merged; canonical merge SHA will be posted here.Core #492 recovery refreshed again after sibling Android #530 advanced canonical master.
Authoritative draft remains PR #529, now exact head
c956d238c4d6d338d88eb1415e6d79e1fc8bb82don exact master23260e1598c85641effae3ec573ff66930cdc2f0. #530 is Android-only and does not overlap the six Core paths. Recovery reuses the exact six blob SHAs that passed full CI #1763 at the previous candidate; noandroid/**changes.Contract remains unchanged: required positive Core-owned
action_seq, monotonic per authenticated session from 1, session rotation resets epoch, opaqueaction_idremains correlation, replay horizon 256 with duplicate/expired evidence failing closed.Fresh exact-head CI #1776 is running. Android should treat
action_seqas canonical only after #529 merges and the canonical merge SHA is posted here.Core #492 is now canonical. PR #529 passed fresh exact-head CI #1776 fully green at
c956d238c4d6d338d88eb1415e6d79e1fc8bb82d(Core full suite,nix flake check, packaged Zara, Android unit/native/Trealla/debug APK/secret gate, Arch + Ubuntu shared-mic) and merged with expected-head protection.Canonical merge SHA:
c2d903fd5cf08e2d28e006cec021309142bf6834.Android can now consume the shared contract:
device.action.request.body.action_seq;action_idremains correlation only;No
android/**files were modified by the Core transaction.