Skip to content

[AI-1762] §2.6: activate envelope-sourced transcript for hosted app-server - #624

Merged
realtonyyoung merged 2 commits into
mainfrom
tonyyoung/ai-1762-activation
Aug 19, 2026
Merged

realtonyyoung merged 2 commits into
mainfrom
tonyyoung/ai-1762-activation

Conversation

@realtonyyoung

Copy link
Copy Markdown
Collaborator

What

Flips the hosted-Codex app-server path from the dormant hook-sourced transcript to the live envelope source. One envelopeSourced decision in StartAppServerAsync now drives all four coupled facts so they can never desync:

  • the guard-1 marker (BuildEnv → KCAP_HOSTED_APPSERVER, stands the rollout watcher down),
  • the runtime's envelope emission (emitEnvelopeTranscript),
  • the deferred first turn behind the source claim (deferFirstTurn),
  • the forwarder wiring (Transcript: runtime on HostedRuntimeStart).

Why it's a 4-value flip, not new machinery

Everything downstream is already built + merged and keys off these values:

Scope + safety

  • Reviewers only, for now. UsesAppServer stays active && IsReviewFlow; the interactive routing flip is deliberately the LAST step (after §2.6 lifecycle + §2.7), so interactive stays on PTY.
  • Opt-in. Gated behind codex.transport=app-server (default pty) — a default daemon is byte-unchanged.
  • Server-before-CLI. Requires a server carrying [AI-3814] app: Keep background command status working across navigation #1530 (source-claim hub) + Name the repository a hosted session runs in #1547 (guard-2); the source-claim fails closed against an old server.
  • Cert-gated. [AI-2110] (the live cert) validates this before app-server becomes the default.

Tests

Only the dormant-marker factory test inverts — it now asserts the marker is stamped, the Transcript is wired, and the first turn is deferred. Runtime (19), orchestrator forwarding (8), and source-claim (4) tests pass unchanged, confirming the built path activates end-to-end.

Part of AI-1762.

…erver

Flip the app-server path from the dormant hook-sourced transcript to the live
envelope source. One envelopeSourced decision in StartAppServerAsync now drives all
four coupled facts so they can never desync: the guard-1 marker (BuildEnv →
KCAP_HOSTED_APPSERVER, stands the rollout watcher down), the runtime's envelope
emission (emitEnvelopeTranscript), the deferred first turn behind the source claim
(deferFirstTurn), and the forwarder wiring (Transcript: runtime on HostedRuntimeStart).

Everything downstream was already built and merged and keys off these: the
orchestrator drains the runtime's envelopes through AcpTranscriptForwarder and, seeing
RequiresSourceClaimBeforeFirstTurn, runs source-claim → BeginFirstTurn → confirm
(#612); guard-2 refuses any stray hook write server-side (#1547); death-close is the
existing finalize → EndAgentSession, and the 60-min rollout-idle fallback disengages
automatically because the stamped marker suppresses the hook's watcher (#617). So this
is a four-value flip in one method, not new machinery.

Scope: this activates the app-server path, which today is reviewers only (UsesAppServer
stays `active && IsReviewFlow`) — the interactive routing flip is deliberately the LAST
step, after §2.6 lifecycle + §2.7. Gated behind codex.transport=app-server (default
pty), so a default daemon is byte-unchanged; requires a server carrying #1530/#1547
(server-before-CLI); and AI-2110's live cert validates it before app-server becomes the
default. Only the dormant-marker factory test inverts (now asserts the marker is
stamped, the Transcript is wired, and the first turn is deferred).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@linear-code

linear-code Bot commented Aug 19, 2026

Copy link
Copy Markdown

AI-1762

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Activate envelope transcripts for hosted Codex app-server

✨ Enhancement 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Activates envelope-sourced transcripts for hosted Codex app-server review sessions.
• Couples marker stamping, envelope emission, first-turn deferral, and transcript forwarding.
• Verifies activated launches suppress hook ingestion and require source claims.
Diagram

sequenceDiagram
    participant F as Runtime Factory
    participant R as App Server Runtime
    participant H as Hook Watcher
    participant O as Orchestrator
    participant S as Server ACP API
    participant T as Transcript Forwarder
    F->>R: Start envelope mode
    F->>H: Stamp guard marker
    H-->>H: Suppress hook ingestion
    F-->>O: Return runtime and transcript
    O->>S: Claim transcript source
    S-->>O: Acknowledge claim
    O->>R: Begin first turn
    R-->>T: Emit envelopes
    T->>S: Forward transcript events
Loading
High-Level Assessment

The PR’s single envelopeSourced decision is the appropriate approach because marker stamping, envelope emission, first-turn deferral, and forwarder wiring form one invariant. Setting these independently would permit unsafe partial activation, while introducing a separate policy abstraction would add unnecessary complexity for a route already gated by transport selection and review-flow scope.

Files changed (2) +21 / -10

Enhancement (1) +12 / -6
CodexHostedAgentRuntimeFactory.csActivate envelope-sourced hosted app-server sessions +12/-6

Activate envelope-sourced hosted app-server sessions

• Introduces one envelopeSourced decision that stamps the hook-suppression marker, enables runtime envelope emission, and defers the first turn. The runtime is also exposed as the transcript source so the orchestrator performs source claiming and forwards its envelopes.

src/Capacitor.Cli.Daemon/Harness/Codex/CodexHostedAgentRuntimeFactory.cs

Tests (1) +9 / -4
CodexHostedAgentRuntimeFactoryTests.csVerify hosted app-server envelope activation +9/-4

Verify hosted app-server envelope activation

• Replaces the dormant-launch expectation with assertions that activated launches stamp KCAP_HOSTED_APPSERVER, expose a transcript source, and require a source claim before the first turn.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Codex/CodexHostedAgentRuntimeFactoryTests.cs

@qodo-code-review

qodo-code-review Bot commented Aug 19, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Test comment restates assertions ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The added comment narrates the marker, transcript, and first-turn outcomes that the test name and
assertions already express. This violates the requirement that comments remain concise and explain
only non-obvious rationale or constraints.
Code

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Codex/CodexHostedAgentRuntimeFactoryTests.cs[R163-165]

+        // Activation: a real app-server launch stamps the KCAP_HOSTED_APPSERVER marker (guard-1 stands the
+        // rollout watcher down), carries a Transcript for the forwarder to drain, and defers the first turn
+        // behind the source claim.
Evidence
PR Compliance ID 9 requires comments to be concise and focused on non-obvious reasons. The added
comment merely enumerates the marker, transcript, and deferred-turn outcomes asserted by the test.

CLAUDE.md: Keep Comments Concise and Focused on the Non-Obvious Why; Avoid Linear Issue Numbers in Comments
test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Codex/CodexHostedAgentRuntimeFactoryTests.cs[163-165]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The activation comment restates the behavior already documented by the test name and verified by its assertions.

## Issue Context
Comments should capture non-obvious rationale or constraints rather than narrating ordinary test behavior.

## Fix Focus Areas
- test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Codex/CodexHostedAgentRuntimeFactoryTests.cs[163-165]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Canceled launch dispatches first turn ✓ Resolved 🐞 Bug ☼ Reliability
Description
Enabling deferred first turns exposes a path where StartForwarderAfterBind detects a
canceled/finalized agent and returns, but the caller still invokes BeginFirstTurnAsync, which
unseals and dispatches the held prompt before observing the canceled token. This can send
turn/start after finalization has begun, causing unwanted work and racing process teardown.
Code

src/Capacitor.Cli.Daemon/Harness/Codex/CodexHostedAgentRuntimeFactory.cs[110]

+            deferFirstTurn: envelopeSourced,
Evidence
StartForwarderAfterBind returns when the ACP token is canceled or the agent is absent, but its
caller proceeds unconditionally to BeginFirstTurnAsync. That method calls _dispatcher.Unseal()
before its token-aware await; Unseal immediately pumps the queue, while runtime disposal only
faults the dispatcher later after cancellation and child teardown, allowing the held turn/start to
race with finalization.

src/Capacitor.Cli.Daemon/Services/AgentOrchestrator.cs[3723-3731]
src/Capacitor.Cli.Daemon/Services/AgentOrchestrator.cs[3815-3822]
src/Capacitor.Cli.Daemon/Harness/Codex/CodexAppServerHostedAgentRuntime.cs[294-302]
src/Capacitor.Cli.Daemon/Harness/Codex/CodexTurnInputDispatcher.cs[57-65]
src/Capacitor.Cli.Daemon/Harness/Codex/CodexAppServerHostedAgentRuntime.cs[578-590]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A finalized or canceled envelope-sourced launch can still unseal and dispatch its deferred first turn. `StartForwarderAfterBind` returns early on cancellation without communicating that result, and `BeginFirstTurnAsync` unseals before checking its cancellation token.

## Issue Context
The PR activates `deferFirstTurn` for hosted Codex app-server sessions. Ensure a canceled source-claim sequence cannot release the held prompt, including when cancellation was already detected during forwarder setup.

## Fix Focus Areas
- src/Capacitor.Cli.Daemon/Services/AgentOrchestrator.cs[3723-3766]
- src/Capacitor.Cli.Daemon/Services/AgentOrchestrator.cs[3815-3822]
- src/Capacitor.Cli.Daemon/Harness/Codex/CodexAppServerHostedAgentRuntime.cs[294-302]
- src/Capacitor.Cli.Daemon/Harness/Codex/CodexTurnInputDispatcher.cs[57-65]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
Review mode: ⚖️ Balanced: This is a behavioral activation on a hosted app-server transcript lifecycle, changing marker stamping, envelope emission, first-turn ordering, and forwarding wiring; despite the small diff, it has meaningful integration and rollout risk.

Grey Divider

Tip of the day
💡 Did you know, you can show, collapse, or hide each part of a finding: code, evidence, and all

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@realtonyyoung

Copy link
Copy Markdown
Collaborator Author

Two-vendor review complete: Copilot clean, Kiro clean / ship-ready. Kiro raised one non-blocking resilience item — a daemon crash between spawning Codex and BeginFirstTurnAsync could strand the sealed first turn (the orphaned child won't self-terminate since guard-1 suppresses the idle-fallback watcher). It's pre-existing from the deferred-first-turn machinery (#612), newly activated here, and Kiro explicitly flagged it as a follow-up rather than a blocker. Filed as AI-2115 (spawn-side first-turn deadline). No code change needed for this PR.

…turn (qodo)

qodo reliability bug (latent in #612, armed by this activation): a launch that
finalized during the source-claim / forwarder setup could still release the held
first turn. StartForwarderAfterBind aborts silently when finalize cancelled acpCts
and/or removed the agent, but StartEnvelopeSourcedSessionAsync then called
BeginFirstTurnAsync unconditionally, and BeginFirstTurnAsync unsealed the dispatcher
(sending turn/start) BEFORE observing its token — so turn/start could race the
teardown.

Two-part fix: BeginFirstTurnAsync now ThrowIfCancellationRequested BEFORE Unseal (the
dispatch runs on CancellationToken.None and can't be recalled, so this is the only
safe gate); and StartEnvelopeSourcedSessionAsync re-checks the SAME liveness
StartForwarderAfterBind guards on (cancelled OR agent-removed) before dispatching, so
the agent-removed-but-token-live arm is covered too. Both land in the OCE/return arms
that already tear down or log-and-abort. Added Cancelled_BeginFirstTurn_does_not_
dispatch_the_held_turn. Also trimmed the activation test comment qodo flagged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@realtonyyoung
realtonyyoung merged commit ed81ec6 into main Aug 19, 2026
5 checks passed
@realtonyyoung
realtonyyoung deleted the tonyyoung/ai-1762-activation branch August 19, 2026 22:55
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.

1 participant