Skip to content

code-mode: release acknowledged terminal observations#29401

Closed
cconger wants to merge 1 commit into
cconger/code-mode-runtime-compact-03j-client-cell-identityfrom
cconger/code-mode-runtime-compact-03k-release-terminal-observation
Closed

code-mode: release acknowledged terminal observations#29401
cconger wants to merge 1 commit into
cconger/code-mode-runtime-compact-03j-client-cell-identityfrom
cconger/code-mode-runtime-compact-03k-release-terminal-observation

Conversation

@cconger

@cconger cconger commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Why

An ObserveOutcome::Yielded value is implicitly acknowledged by the next generation. ObserveOutcome::Completed and ObserveOutcome::Terminated have no successor, so their replay payload otherwise remains retained until the session ends.

What

  • Add ReleaseObservationRequest { cell_id, generation } and release_observation(ReleaseObservationRequest) -> Result<(), String> to the wire/session contract.
  • Allow release only when the retained ObserveOutcome is Completed or Terminated.
  • Do not release Yielded or Missing outcomes; reject them as non-terminal.
  • Reject pending, failed, or future generations.
  • Make repeated or older releases idempotent.
  • Replace released terminal output with a lightweight generation tombstone.
  • Have Core send the acknowledgement only after reading a terminal ObserveOutcome.
  • Preserve the result and log a warning if release fails.

Host/Core wire sequence

sequenceDiagram
    participant Core
    participant Host
    Core->>Host: ObserveRequest { cell_id, generation, ... }
    Host-->>Core: ObserveOutcome::Completed or ::Terminated
    Core->>Core: consume terminal outcome
    Core->>Host: ReleaseObservationRequest { cell_id, generation }
    Host->>Host: replace payload with generation tombstone
    Host-->>Core: Result<(), String>
    opt release returns Err(String)
        Core->>Core: warn; consumed outcome remains valid
    end
Loading

Stack boundary

release_observation(ReleaseObservationRequest) acknowledges transport delivery of terminal output. It is separate from resume(PendingGeneration), which advances a pausable runtime frontier.

Validation

  • just test -p codex-code-mode
  • just test -p codex-code-mode-protocol
  • Focused Core regression verifies release after terminal result consumption.

Stack parent: #29398.

@cconger cconger force-pushed the cconger/code-mode-runtime-compact-03j-client-cell-identity branch from ed0bc3b to ba7fa7b Compare June 22, 2026 06:48
@cconger cconger force-pushed the cconger/code-mode-runtime-compact-03k-release-terminal-observation branch from ea2eb64 to c3c7e84 Compare June 22, 2026 06:48
@cconger cconger force-pushed the cconger/code-mode-runtime-compact-03j-client-cell-identity branch from ba7fa7b to 846a04a Compare June 22, 2026 06:53
@cconger cconger force-pushed the cconger/code-mode-runtime-compact-03k-release-terminal-observation branch from c3c7e84 to 63a5d00 Compare June 22, 2026 06:53
@cconger cconger force-pushed the cconger/code-mode-runtime-compact-03j-client-cell-identity branch from 846a04a to 8ec0e02 Compare June 22, 2026 07:02
@cconger cconger force-pushed the cconger/code-mode-runtime-compact-03k-release-terminal-observation branch 2 times, most recently from 3986a35 to ec57b61 Compare June 22, 2026 07:09
@cconger cconger force-pushed the cconger/code-mode-runtime-compact-03j-client-cell-identity branch 2 times, most recently from 12fe361 to 74b9705 Compare June 22, 2026 07:22
@cconger cconger force-pushed the cconger/code-mode-runtime-compact-03k-release-terminal-observation branch from ec57b61 to 4f4da26 Compare June 22, 2026 07:22
@cconger cconger force-pushed the cconger/code-mode-runtime-compact-03j-client-cell-identity branch from 74b9705 to aaa1d51 Compare June 22, 2026 07:49
@cconger cconger force-pushed the cconger/code-mode-runtime-compact-03k-release-terminal-observation branch from 4f4da26 to 735f23f Compare June 22, 2026 07:49
@cconger cconger force-pushed the cconger/code-mode-runtime-compact-03j-client-cell-identity branch from aaa1d51 to ffe72de Compare June 22, 2026 08:37
@cconger cconger force-pushed the cconger/code-mode-runtime-compact-03k-release-terminal-observation branch from 735f23f to 1d6187f Compare June 22, 2026 08:37
@cconger cconger force-pushed the cconger/code-mode-runtime-compact-03k-release-terminal-observation branch from 1d6187f to 82f86d9 Compare June 22, 2026 08:56
@cconger cconger force-pushed the cconger/code-mode-runtime-compact-03j-client-cell-identity branch from ffe72de to e7f4fc2 Compare June 22, 2026 08:56
request.cell_id
)
})?;
if !matches!(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A yielded generation also has no successor after wait(... terminate: true) no? should we retire this too?

if is_terminal
&& let Err(error) = self
.session()?
.release_observation(codex_code_mode::ReleaseObservationRequest {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This destructive ack happens before Core commits N + 1. This is racy

request: ReleaseObservationRequest,
) -> Result<(), String> {
let mut observations = self.observations.lock().await;
let Some(record) = observations.get(&request.cell_id) else {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None cannot be an idempotent old release here because released generations remain as tombstones. This accepts any generation for an unknown or never-observed cell and hides wire desync. Should we reject this case instead?

@cconger cconger closed this Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants