Skip to content

✨ Launch Codex sessions with <Session.Launch> (#755) - #764

Open
taras wants to merge 22 commits into
agent/issue-717-terminal-packagesfrom
agent/issue-755-codex-native-launch
Open

✨ Launch Codex sessions with <Session.Launch> (#755)#764
taras wants to merge 22 commits into
agent/issue-717-terminal-packagesfrom
agent/issue-755-codex-native-launch

Conversation

@taras

@taras taras commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Closes #755. Stacked on the final #717 Grid/Pane infrastructure in #771.

Why

XMD knew the codex resume <identity> command shape but could not safely advertise Codex for <Session.Launch>. It had not established that the identity returned by the ACP adapter names the exact conversation resumed by the native Codex UI.

What changes

Codex becomes a supported native-launch product beside Claude, both at the root and inside a grid pane:

<Grid columns={2}>
  <Pane title="Codex">
    <Agent name="codex">
      <Session.Launch session="implementor">
        Implement the accepted plan.
      </Session.Launch>
    </Agent>
  </Pane>
  <Pane title="Claude">
    <Agent name="claude">
      <Session.Launch session="reviewer">Review the result.</Session.Launch>
    </Agent>
  </Pane>
</Grid>

A new Codex conversation receives one announced, fixed, tool-free codex-materialization.v1 turn. The authored instructions remain the first native user task. XMD then releases ACP ownership and opens codex resume <exact-provider-identity> in the selected terminal.

Identity and continuation contract

  • The native identity comes only from the provider response, never from ACP session IDs, request echoes, UUID shape, transcript inspection, a picker, or --last.
  • session-route.v3 and the launch journal retain matching accounts of the original executable observation.
  • A later live executable is admitted independently by stable adapter protocol, requested capability, positive CLI shape, and host profile. Version and digest remain audit evidence, not a same-build lock.
  • Native resume, ACP reattachment, incomplete replay, and concurrent-winner adoption use the exact retained identity without allocating or substituting another conversation.
  • Live ACP reattachment confirms the provider returns the retained identity before a Session returns or a Prompt is submitted.
  • Missing identity, identity disagreement, incompatible protocol or host, ownership conflict, unsafe materialization, or unproved cleanup fails closed.
  • Completed replay performs no observation, materialization, ACP work, or native launch.

Grid composition

Distinct Claude and Codex panes launch concurrently through their selected pane workers. The root foreground launcher is not entered, and no pane identity enters Agent requests, session keys, routes, durable phases, or diagnostics. Cancellation waits for native settlement and pane quiescence.

#781 renamed the final surface and packages to <Grid>/<Pane>, @executablemd/grid, and @executablemd/grid-tmux. This PR retains only Codex certification as its purpose; rebasing onto the current #771 head must preserve the accepted Grid/Pane names without changing the identity contract above.

Review and evidence

Start with DEC-018, Codex native-launch preparation, session-route.v3, and provider-native continuation. Then inspect the mixed Claude/Codex grid evidence and vendored adapter/ACPX provenance.

The focused suites cover adapter protocol and vendor provenance, native launch and routes, provider continuation, core launch journals, live ACP reconnect, pane-native routing, mixed-grid execution, and changed-release continuation. The opt-in real-provider documents remain frozen evidence because they spend account model turns.

The delivery head has passed the Deno, Node, and Bun matrices, package publication checks, build and smoke checks, and the clean composability proof. The independently tracked intermittent Bun resolver failure remains #778.

Scope

Included: Codex advertisement, provider-returned identity, one-turn materialization, V3 routes, native and ACP continuation, replay, cross-compatible-release admission, terminal notification, and mixed-grid evidence.

Excluded: Claude identity behavior, new grid lifecycle or tmux mechanics, transcript capture, <Session.Launch> result capture, and additional working directories.

The admitted real-provider host envelope is macOS arm64. Other host pairs refuse until independently proved.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Found 7 redundant comments. Inline suggestions to remove them below.

Comment thread packages/acp/src/native-launch.ts Outdated
codex: {
launcher: "codex",
// Codex creates the conversation through ACP and reports what it is called.
// XMD supplies nothing here and accepts only that assertion.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// XMD supplies nothing here and accepts only that assertion.

Comment thread packages/acp/src/native-launch.ts Outdated
//
// The first thing the Codex ACP adapter consults when deciding which
// Codex to run, so the build that creates the session through ACP is the
// build the native UI then resumes it with.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// build the native UI then resumes it with.

Comment thread packages/acp/src/native-launch.ts Outdated
// resume <id>` reads rollouts — so a thread ACP created and nothing has
// spoken in is refused by name. One turn closes exactly that gap and
// nothing else, which is why the prompt asks for an acknowledgement and
// forbids the work the session was prepared for.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// forbids the work the session was prepared for.

// child of a build nothing has observed, which is the one thing a bound
// session may not talk to. Nothing on that path needs the answer: a
// client-native session is created by a native process, and where ACP does
// serve one, the establishment itself reports being unable to.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// serve one, the establishment itself reports being unable to.

Comment thread packages/acp/src/provider.ts Outdated
if (route.schema !== "session-route.v3") {
// Constructed before any build was recorded. A build observed now says
// which build is installed today, not which one issued this identity, so
// there is nothing to compare and nothing to continue.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// there is nothing to compare and nothing to continue.

Comment thread packages/acp/src/provider.ts Outdated
}
const agentCommand = agentCommandOf(prepared);
// An existing managed entry, or a durable record ACPX already kept, is
// provider state — and existing history is never reclassified.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// provider state — and existing history is never reclassified.

// established placement has one of its own.
// established placement has one of its own. A build alone does not
// defer anything — a session the provider names is still constructed
// by this ensure, bound to the build that names it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// by this ensure, bound to the build that names it.

@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown

PR #764: ✨ Launch Codex sessions with <Session.Launch> (#755)

90 files, +20491 / -3874

Scope

🔴 PR has 24365 lines changed. Split into focused PRs.

🟡 24365 lines changed. PRs under 400 receive more thorough review.

🟡 90 files changed. Are all changes related?

🟡 Changes span 14 directories.

🟡 PR mixes config and source changes.

Structural

🟡 Type declarations with no consumers: LaunchPhase, ExecutableRefusal.
Symbol Declared at Refs in diff Why flagged
LaunchPhase packages/core/src/agent/launch.ts:37 1 referenced ≤1× within the added diff (pre-existing usages not counted)
ExecutableRefusal packages/runtime/executable-observer.ts:35 1 referenced ≤1× within the added diff (pre-existing usages not counted)

Oxlint structural signals:

  • no-unused-vars ×14: packages/core/src/agent/launch-owner.ts, packages/acp/src/provider.ts, packages/core/src/expand.ts (+1)
  • no-redundant-type-constituents ×12: packages/terminal-tmux/src/pane-channel.ts, packages/acp/tests/fixtures/claude-native-to-acp-proof.ts, packages/acp/tests/fixtures/codex-native-launch-proof.ts (+4)
  • no-empty-function ×5: packages/terminal-tmux/src/pane-worker.ts, packages/terminal/src/native-launcher.ts, packages/acp/src/provider.ts (+1)
  • no-unnecessary-type-assertion ×3: packages/acp/tests/helpers.ts, packages/core/src/expand.ts
  • no-unnecessary-type-arguments ×1: packages/terminal-tmux/src/pane-channel.ts

Slop

  • packages/acp/src/provider.ts:1202 (removed)
  • packages/acp/src/provider.ts:1876 (removed)
  • packages/terminal-tmux/src/provider.ts:414 (removed)
  • packages/terminal-tmux/src/tmux-grid.ts:286 (removed)
  • packages/terminal/src/controlled-composite.ts:158 (removed)
  • packages/terminal/src/controlled-composite.ts:164 (removed)

Oxlint slop signals:

  • no-console ×3: packages/cli/src/cli.ts
  • no-inferrable-types ×2: packages/core/src/expand.ts

Static Analysis

Oxlint: 124 diagnostics across 23 files (26 rules)
Density: 0.006 violations/added-line

consistent-function-scoping (16): packages/acp/tests/fixtures/codex-native-launch-proof.ts, packages/terminal-tmux/src/pane-worker.ts, packages/test-agent/src/provider.ts (+1)
no-unused-vars (14): packages/core/src/agent/launch-owner.ts, packages/acp/src/provider.ts, packages/core/src/expand.ts (+1)
no-unsafe-type-assertion (13): packages/acp/tests/helpers.ts, packages/acp/tests/fixtures/claude-native-to-acp-proof.ts, packages/cli/src/cli.ts (+5)
no-floating-promises (12): packages/test-agent/tests/fixtures/terminal-grid-worker.ts, packages/terminal-tmux/src/pane-channel.ts, packages/acp/tests/fixtures/claude-native-to-acp-proof.ts (+5)
no-redundant-type-constituents (12): packages/terminal-tmux/src/pane-channel.ts, packages/acp/tests/fixtures/claude-native-to-acp-proof.ts, packages/acp/tests/fixtures/codex-native-launch-proof.ts (+4)
unbound-method (10): packages/acp/tests/helpers.ts, packages/core/src/agent/launch-authority.ts, packages/acp/tests/fixtures/terminal-screen.ts (+3)
no-shadow (5): packages/runtime/deno-executable-observer.ts, packages/terminal/src/posix-launcher.ts, packages/acp/src/provider.ts (+1)
no-empty-function (5): packages/terminal-tmux/src/pane-worker.ts, packages/terminal/src/native-launcher.ts, packages/acp/src/provider.ts (+1)
no-underscore-dangle (4): packages/terminal-tmux/src/pane-protocol.ts
no-useless-spread (4): packages/terminal-tmux/src/pane-channel.ts, packages/acp/src/provider.ts, packages/acp/tests/helpers.ts
no-base-to-string (4): packages/core/src/expand.ts
no-control-regex (3): packages/acp/tests/fixtures/claude-native-launch-proof.ts, packages/acp/tests/fixtures/claude-native-to-acp-proof.ts, packages/acp/tests/fixtures/codex-native-launch-proof.ts
no-console (3): packages/cli/src/cli.ts
no-unnecessary-type-assertion (3): packages/acp/tests/helpers.ts, packages/core/src/expand.ts
consistent-return (3): packages/terminal-tmux/src/pane-channel.ts, packages/cli/src/cli.ts, packages/terminal-tmux/src/attach-client.ts
no-useless-escape (2): packages/acp/tests/fixtures/codex-native-launch-proof.ts, packages/acp/src/native-launch.ts
no-inferrable-types (2): packages/core/src/expand.ts
prefer-string-starts-ends-with (1): packages/acp/src/native-launch.ts
no-array-sort (1): packages/acp/src/native-launch.ts
no-new-array (1): packages/acp/tests/fixtures/terminal-screen.ts
no-useless-fallback-in-spread (1): packages/core/src/expand.ts
no-unmodified-loop-condition (1): packages/cli/src/cli.ts
no-unnecessary-type-arguments (1): packages/terminal-tmux/src/pane-channel.ts
no-unnecessary-template-expression (1): packages/acp/src/provider.ts
restrict-template-expressions (1): packages/core/src/expand.ts
no-implied-eval (1): packages/core/src/expand.ts

Correctness

No extraneous code patterns detected.

taras and others added 15 commits September 7, 2026 04:42
An advertised adapter name selected a command shape and, by omission,
authorized acting on a session a native UI may be in. DEC-017 makes the
authority a point — adapter, capability, exact reported version, host OS
and architecture — so one real-CLI proof admits exactly what it proved.

The host states the machine as a value beside the coordinator, route
store and observer, so shared provider and session assembly never detects
the runtime it happens to be on.
A native launch acknowledged ownership quiescence whenever `stop()` on its
scope succeeded. A launch that completed naturally tore itself down first, so
a finalizer that failed on the way reached the owner as a crash while `stop()`
afterwards succeeded against an already-settled scope — proof that the scope is
settled now, never that the cleanup which failed had succeeded. The session was
released idle with an unproved child behind it.

The invocation now suspends once the native child settles, so the one teardown
there is happens under the one call that reports it. Quiescence is still
withheld unless the child settled, every finalizer of that invocation
completed, and the provider holds no handle; otherwise the exclusion is
released with the record left active, and the next acquisition is refused as
session-recovery-required before any spawn, ensure, allocation or route work.
The original cleanup failure is what the launch caller observes.
An exact-version compatibility point admitted a capability from the release
string an executable happened to print. That is the wrong evidence twice: a
release name says nothing about which operations a build declares, and pinning
one refuses every later build that declares the same shape.

Admission is now four exact facts — the adapter's own versioned protocol, the
capability being asked for, the profile its observer returned, and the host's
platform and architecture. An Agent registry name or a launcher command admits
nothing. The two Claude capabilities are read independently, so neither is ever
inferred from the other having been proved.

The host-owned observer is generalized: it resolves and canonicalizes the
launcher, requires an executable regular file, hashes it once, and asks that
same exact path whatever read-only queries the adapter declared, returning
settled status and captured output. It knows no provider and parses nothing.
Reading Claude's `--help` structurally — caller-supplied identity, exact
resume, private-file instructions — stays in the adapter, so additive options,
prose and wrapping do not change the answer.

Version becomes optional evidence beside the digest rather than a gate. A build
that will not name its release, names it in words this adapter does not
recognize, or names several is bound by its bytes alone. Build equality is
asymmetric: the digest decides, a retained release is a claim the live build
must still make, and a record that named none is not rewritten when one appears.
The help probe read flag spellings. `--session-id <name>`, `--resume <url>`
and `--system-prompt-file <text>` all satisfied it, so a build that accepts
the spelling and means something else by it was admitted for native launch —
and the launch would then hand a UUID to an option that takes a name.

Each declaration is now parsed into its spellings, its value placeholder,
whether that value is required, and its own description. Chosen identity
needs the sole `--session-id` to require a UUID. Exact resume needs the sole
`--resume` to name session identity, either in its placeholder or, for the
uncommitted `[value]` spelling Claude ships today, in that entry's own words.
Private instructions need a file-valued `--system-prompt-file`, or the
`--system-prompt[-file]` family spelling inside a parsed entry. Product is
read from dedicated unindented lines, so a compatibility claim or a quoted
usage example no longer says what this executable is.

Two entries declaring one spelling is unreadable, not a choice between them.
Three surfaces that say the opposite of the contract were admitted by it.
`Resume a conversation by URL; session ID is not supported` contained both
words the read looked for. `Inline text; file paths are not supported` was
accepted from a description while its argument was `<text>`. `Claude Code
compatibility wrapper` began a line with the product name.

Prose is now read one clause at a time, and a clause that withdraws what it
states admits nothing: a sentence states one thing, and its neighbours are
not it. A generic `[value]` resume needs the phrase saying the argument is
what the conversation is named by, not two words scattered through it. The
private instruction file is decided by the argument alone, since a
description explains a value rather than changing it. A product line names
its subject and then describes it, so words running on into a longer name
have named something else.

The 2.1.241 and 2.1.263 surfaces, additive options, wrapping and unrelated
prose are unchanged, and no version is consulted.
A route's `ExecutableBuildBindingV1` was a release lock: every continuation
held the live observation against the retained one, so upgrading Claude
stranded every session the previous build had opened. It is now immutable
audit evidence — written once at first publication, never rewritten, and never
compared with a live build.

What authorizes acting on an existing session is what the installed executable
independently proves: the route's stable adapter protocol, the capability the
work needs, the shape its own probe recognizes, and this host. Which build
accepted the identity first is history, and history is not a capability.

Removes the four live-vs-retained comparisons (attachment, native resume,
concurrent winner, replay) and the `buildDrift` helper they shared. The one
remaining comparison stays: a route and its prepared journal are two durable
accounts of a single observation, so a difference between them is still a
replay that cannot say which session it is resuming.

Tier XR takes a 2.1.261 session to a 2.1.263 build across native resume, ACP
attachment, prepared-only replay, detached replay, a concurrently published
winner, and a build reporting no release — each asserting the exact retained
identity, unchanged audit evidence, no allocation or republication, and the
live executable's own path. XR7 and XR8 hold the fail-closed boundary that a
release change is not a protocol change.
A V2 construction route fixes the stable protocol its identity was published
under through its provider, agent and launcher contract. Continuation read that
protocol off whatever adapter happened to be registered under the launcher
instead, so an adapter declaring another protocol — beside a host policy that
had proved exactly that protocol, for that capability, in that shape, on this
machine — could adopt a session it never constructed. ACP attachment also never
held the route's retained launcher to the live adapter at all.

The pin is compiled in and reachable through no host-supplied dependency, and it
is asked before the executable is observed: which conversation this is was never
a question about a build. Native resume, ACP attachment, concurrent-winner
adoption and both incomplete replay phases now require the live adapter's
launcher and protocol to be the ones the retained contract names, and the
independent admission of the current executable's capability, shape and host
follows it. A refusal observes nothing, allocates nothing, launches, ensures,
prompts and constructs nothing, and leaves the route and the journal exactly as
their first publication left them.

Executable bindings stay what they became: immutable audit evidence, and a
cross-check between two durable accounts of one observation — never a live
same-build gate. The source contracts that still described them as one are
reconciled.

Evidence: XR9 takes an injected adapter speaking another protocol, with the host
policy admitting that protocol, through native continuation, ACP attachment,
both replay phases and concurrent-winner adoption, and asserts the executable is
never even observed. XR10 refuses an attachment whose retained launcher is not
the live adapter's. Planting each seam's absence back one at a time fails only
that seam's case, and reading the pin off the adapter fails both cases and
nothing else.
An empty route read settles nothing: a concurrent publication is only
revealed by publishing. Until now a run whose read found no route fell
straight through to observing the executable, allocating an identity and
writing a candidate, and asked whether it could account for the protocol
only after meeting the winner — having already acted on behalf of a
session it was never entitled to construct.

The pin is now asked twice from one reading. Prospectively, before any
observation or allocation, against the live adapter's launcher; and
again of the record that actually won, whose route may differ from the
candidate's. The legacy V1 path is untouched.

Reconcile the remaining same-build continuation wording across the
touched source set. A retained binding is immutable audit evidence and
is only ever held to the prepared journal derived from the same
observation, never to a build installed later.
`packages/terminal` is created by this stack's extraction commit, which was
authored while the repository pinned `@effectionx/node` 0.2.4. Main has since
moved to 0.2.5 (#748). A file a commit creates conflicts with nothing, so the
rebase carried the stale pin forward beside a root that now asks for 0.2.5, and
`deno task setup` refused: the frozen lockfile carries no `npm:@effectionx/node@0.2.4`
specifier for a workspace member to resolve through.

The pin now matches the one every other package and the root already use. The
0.2.4 entries that remain in `deno.lock` are `@effectionx/process@0.8.1`'s own
transitive dependency, and they are present on main unchanged. No other
dependency version moves.
Three call sites this stack added kept compiling against surfaces main has
since changed. Each pair of edits touched different lines, so the rebase merged
both sides without a conflict and the mismatch only surfaced under `deno check`.

`xmd plan` used to settle a whole agent stack through a local three-argument
helper. Main replaced that with the authorship-only resolver, which takes two
arguments because the command starts no program, so the terminal-grid installer
this stack threaded through no longer has a parameter to occupy. `xmd run` is
unchanged and still installs it: the installer reaches `installRunAgentStack`
through `resolveAgentStack`, which is the one path with a terminal to give away.

The syntax suite's two terminal-grid rows still named `syntaxCatalog` and the
local `parseCatalog`, which main renamed to `syntaxSymbols` and `parseSymbols`.
Only the names move; both rows assert the same origins, authored forms,
descriptions and reserved-name exclusions they always did.

The launcher suite imported `reap` from the provider-neutral contract after this
stack split the module in two. `reap` ends a POSIX child, so it comes from
`posix-launcher.ts` beside `installForegroundLauncher`, and the contract import
keeps only what a consumer that never reaches a process needs.
The rebase reintroduced fourteen listeners the ownership rule refuses: a
raw `once()` in the POSIX launcher's spawned callback, subscriptions whose
`ensure()` was yielded after them — itself a suspension an owner can be
halted in — removals hidden behind a helper the pairing cannot be read
from, a self-removing socket handler a cancelled scope never reaches, and
three process signals registered under a computed name.

Every one of them now names its receiver, event and handler on both sides,
with the removal established before the subscription or held by a `finally`
around it. The launcher keeps its inline exit/error race, its complete
reap and a spawned callback that fires exactly once: the handler comes off
when the start arrives and again on every way out, so a cancelled or failed
launch publishes no readiness at all. `usePaneChannels` remembers each
accepted socket with the handler it carries and detaches every one of them
at teardown, including a socket that closed on its own.

FL10 reads the child's own listener counts after delivery, after a startup
failure and after cancellation, then replays `spawn` on it: restore the raw
`once()` and the row fails. TW14 already held the tmux half, and fails if
the new channel detach is removed.

Terminal-grid TG3 expects the catalog version main's Syntax v2 migration
publishes.

Co-Authored-By: Claude <noreply@anthropic.com>
@taras
taras force-pushed the agent/issue-755-codex-native-launch branch from 24551e8 to 44826a9 Compare September 7, 2026 11:42

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Found 14 redundant comments. Inline suggestions to remove them below.

useMachineSessions(),
// The machine, read at the one place that is actually running on it. A
// native capability is admitted for an exact OS and architecture, so
// those cross from here as values rather than being detected below.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// those cross from here as values rather than being detected below.

Comment thread packages/cli/src/deno.ts
useMachineSessions(),
// The machine, read at the one place that is actually running on it. A
// native capability is admitted for an exact OS and architecture, so
// those cross from here as values rather than being detected below.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// those cross from here as values rather than being detected below.

if (typeof code !== "number") {
// A child that produced no status did not answer, whatever it wrote on the
// way. Reporting output beside an unknown status would invite reading it as
// an answer.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// an answer.

child.on("exit", onExit);
// Established before the subscriptions and naming every one of them:
// entering an ensure() is itself a suspension, so a scope halted while it
// registers unwinds with nothing on it at all.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// registers unwinds with nothing on it at all.

live.add(socket);
closable++;
const onSocketClose = (): void => {
// A socket that closed is nobody's to close again.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// A socket that closed is nobody's to close again.

// child inherits this process's, so a pane collapsing it to `{}` started
// the program with no environment whatsoever — no `TERM`, so no colour, and
// no `PATH` or `HOME` either. An environment that *is* supplied crosses
// exactly, gaining nothing ambient.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// exactly, gaining nothing ambient.

// tmux sends its first record immediately on attach, so a handler
// attached after `exec()` returns is attached after that record could
// already have been forwarded. Nothing about the parsing below changes —
// the stream is still read and classified exactly as before.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// the stream is still read and classified exactly as before.

}
// The default shell starts: a suite that says nothing about a pane
// wants a pane that works, and one that never reported a spawn would
// hang the readiness barrier instead.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// hang the readiness barrier instead.

} finally {
// Counted down however the shell left — returned, thrown, or
// cancelled — because a shell a suite can still find is a shell the
// provider is still holding.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// provider is still holding.

started.once("spawn", () => spawned());
// reports having started. Off on arrival and off again in the `finally`,
// so one start is reported exactly once and a launch that was cancelled or
// never started reports none at all.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Redundant comment — restates what the code does.

Suggested change
// never started reports none at all.

@taras
taras changed the base branch from agent/issue-732-tmux-grid to agent/issue-717-terminal-packages September 7, 2026 11:46
@taras
taras marked this pull request as ready for review September 7, 2026 11:51
@taras taras changed the title Launch Codex sessions with <Session.Launch> (#755) 🔒 Admit native Agent capabilities by proved protocol shape (#717) Sep 7, 2026
@taras taras changed the title 🔒 Admit native Agent capabilities by proved protocol shape (#717) ✨ Launch Codex sessions with <Session.Launch> (#755) Sep 7, 2026
Include the extracted terminal package in SYN47's explicit published payload closure and assert its lifecycle subpath resolves to the staged file. Production manifests already declare the dependency; preserve canonical workspace imports and the no-reexport package boundary.
Normalize Linux ps's no-terminal spelling to the existing process-interface marker without changing real device names or holder proofs. Declare the extracted terminal packages only in the private root test host, keeping provider dependencies out of the neutral domain. Freeze both boundaries with regressions; regenerate the two pnpm workspace links through setup.
Run the native-grid TestAgent harness through a focused subprocess entry that installs the compiler and invokes the real worker. Keep ACPX, controller transport, scenarios, journal, lifecycle, public CLI dispatch coverage, and the 20-second document deadlines intact. Require the GN2 journey to complete successfully as well as checking retained identity.
@taras

taras commented Sep 8, 2026

Copy link
Copy Markdown
Owner Author

Product-contract sequencing update: #717 now requires the unshipped public grid surface to be <Grid>/<Pane> in @executablemd/grid and @executablemd/grid-tmux; #781 owns that amendment from exact #717 base a73b2d6d53cdaaac286044c69590f9f07eb9083d.

This PR remains solely the #755 Codex native-launch certification. Do not add the Grid/Pane implementation as a new PR purpose and do not merge against the rejected Terminal-named base. After #781 produces an accepted #717 head, rebase this Codex work onto it, resolve its component/package/test references to the new canonical names, and preserve all reviewed Codex identity, materialization, cross-release, ownership, privacy, replay, and teardown behavior.

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.

Launch Codex sessions with <Session.Launch>

1 participant