✨ Execute concurrent terminal panes through a replaceable provider (#730) - #738

Open
taras wants to merge 15 commits into
agent/issue-729-terminal-gridfrom
agent/issue-730-terminal-execution
Open

✨ Execute concurrent terminal panes through a replaceable provider (#730)#738
taras wants to merge 15 commits into
agent/issue-729-terminal-gridfrom
agent/issue-730-terminal-execution

Conversation

@taras

@tarastaras commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes#730. Second implementation Story under Quest #717, stacked on #733.

Base is agent/issue-729-terminal-grid, not main, as the Story's verification stack directs. Branched from 97be06321cbdf08d84ef53dbefb88407f54326fe, the reviewed head of #733.

Why

#729 froze the language: an author can write a terminal grid, and every runtime can validate one. Nothing could run one. This Story makes a grid execute, through a boundary a host replaces — so the document keeps one lifecycle contract whether the presentation is tmux, a controlled test surface, or something native later.

What changes

Before: a valid <Terminal.Grid> derived its layout and refused, because nothing could present it.

After: it runs. Core takes the run's one foreground-terminal lease, flushes root output, prepares the composite while it stays hidden, starts every pane concurrently, and attaches only once every pane has actually started.

<Terminal.Grid columns={2}>
<Terminaltitle="Agent">…</Terminal>
<Terminaltitle="Shell" />
</Terminal.Grid>

How it works

lease → flush → prepare (hidden) → panes start concurrently
→ readiness barrier → attach → panes settle independently
→ reader closes → teardown → lease released

packages/runtime/terminal.ts is the replaceable seam. The request is provider-neutral — columns, rows, and the authored panes with their derived positions — and names no terminal, socket, process or window. Middleware may observe, narrow, refuse, wrap or delegate. Presentation never decides an outcome: update() receives states core has already settled on, and its return value is ignored.

packages/core/src/terminal/authority.ts mints one-use pane claims for one request's ordinals. A claim admits one interactive operation at a time on its pane and holds that pane's readiness latch. Two claims do not contend, which is what lets panes stay interactive together.

packages/core/src/terminal/pane.ts is the seam anything interactive inside a pane reaches, so it runs as that pane's owner instead of competing for the root lease. Absence means "not in a pane".

packages/core/src/terminal/grid.ts owns the lifecycle. The lease and the composite are both scope-owned, so success, failure and cancellation all release the terminal and destroy exactly the composite that was prepared — there is no path that skips teardown.

Review guide

Start with:packages/core/tests/terminal-grid.test.ts

Then review:

  1. packages/runtime/terminal.ts — the boundary and what a handler may do.
  2. packages/core/src/terminal/authority.ts — claims, contention, the readiness latch.
  3. packages/core/src/terminal/grid.ts — the ordering, and where teardown is registered.
  4. packages/core/src/expand.tspaneWork(), which is where a pane's isolation is established.

Look carefully at:

  • The order in runTerminalGrid(). ensure(() => composite.destroy()) is registered before any pane starts, so a composite that was prepared is owed a destroy even if the next line fails.
  • The attached flag. Before the barrier a pane failure fails the whole grid closed; after it, the failure is that pane's status and its siblings keep running.
  • paneWork()'s paired branch: ActiveLoop.set(undefined), a derived env, containedLedger(), and undefined for the return body are the four things that make a pane a scope rather than a region.

What must stay true

  • Nothing is shown before every pane has started — enforced by racing the readiness barrier against startup failure, checked by the TG9 ordering row, which was verified by deleting the barrier: it fails without it.
  • A prepared composite is always destroyed exactly once — enforced by scope-owned ensure, checked by TG12 and by the controlled composite refusing a second destroy.
  • Presentation decides nothing — enforced by update() returning void and claims never leaving core, checked by the middleware rows in the provider suite.
  • A pane's later bindings stay in that pane — enforced by a derived environment, checked by the TG6 document row asserting the sibling and the document after the grid still see the binding unresolved.

How to verify it

deno task test packages/core/tests/terminal-grid.test.ts
deno task test packages/runtime/tests/terminal-provider.test.ts
deno task test packages/core/tests/terminal-grid-structure.test.ts
  • TG8 proves one claim admits one interactive operation at a time and two claims do not contend; it fails if a pane admitted twice, or if two panes serialized.
  • TG9 proves nothing attaches until every pane reports a spawn, and that a pane which settles without one fails startup; it fails if a grid attached early or presented a pane that never started.
  • TG10 proves a pane can fail after attach while a sibling is provably still live, and the grid reports the first failed authored ordinal.
  • TG12/TG13 prove close and parent cancellation both destroy the composite exactly once, and that a pane cancelled by the close is closed rather than failed.
  • TG6/TG7 prove pane scope and output routing through the real execute() path.
  • The provider suite proves the boundary refuses with nothing installed, and that middleware can observe, narrow, refuse and wrap without being able to authorize.

Whole Deno core suite: 350 passed. Runtime suite: 14 passed.

Scope

Included

  • The provider boundary, the terminal authority and pane claims, the readiness latch, the pane seam, and the grid lifecycle.
  • Pane scope isolation, pane output routing, concurrent start, atomic attach, independent settlement, close and cancellation teardown.

Not included — this Story is not finished

These acceptance points landed in later commits on this branch, and the section
that once said durability was absent is no longer true:

  • Durability and replay (TG15–TG17) are implemented. The grid is one durable
    child and each pane is its own durable child allocated in authored ordinal
    order. A completed region replays its exact retained result — successful and
    contained-failed alike — contacting no provider and running no pane content,
    shell or launcher. An interrupted region rebuilds a fresh composite. The
    layout is recorded in the parent coroutine before the lease and before any
    provider is contacted, and a malformed retained layout refuses there.
  • TG17 is scoped to what a continuation can actually change. A continuation
    executes the retained root, so pane count, order and form cannot differ and
    are proved retained-and-honoured rather than refused; columns and each
    title reach the grid through props, which are not restored, and each refuses
    independently with zero provider observation.
  • durableSpawn was repaired to make any of this possible: its task now
    outlives the call, and a cancelled child records why it stopped (DEC-040) so
    a deliberately halted region is never revived while an interrupted one
    resumes.

What remains outside this PR:

  • TG14's bounded teardown proof belongs to the tmux provider Story; the
    controlled provider cannot exercise it.
  • TG5 and Agent-session contention in TG11 belong to the native-launch
    Story, as the issue states.
  • One known gap: a run interrupted while reader-close teardown is awaiting
    a pane whose own finalizer is slow
    leaves that pane recorded as unwound
    rather than closed, so a resumed run re-enters it. Reader close is now
    cooperative — panes are asked to stop and record closed themselves rather
    than being halted — which removes caller-cancelled panes from the ordinary
    close path, but the blocked-finalizer overlap is not yet covered by a
    regression.

Intentionally unchanged

  • No tmux command, multiplexer, or real terminal anywhere in this change.

New abstractions

  • TerminalProvider / TerminalComposite exist because a grid's presentation has to be replaceable; the controlled provider and the future tmux adapter are the two concrete uses.

  • TerminalPaneClaim exists because pane terminal ownership must be unforgeable and per-ordinal; consumed by the grid and by the pane seam.

  • PaneTerminal exists because interactive work inside a pane must not compete for the root lease; consumed by the suite's controlled interactive child now and by <Session.Launch> in Launch native Agent sessions in independent terminal panes #731.

  • Each new abstraction has multiple concrete uses or a clear justification.

  • No speculative functionality is included.

Risks and limitations

  • Incomplete Story, stated above. Durability and replay are absent.
  • Five rows from ✨ Describe terminal grids as executable document structure (#729) #733 moved into this Story's suite. The move was authorized explicitly rather than assumed, and every claim they made is still asserted — against the provider request, which is stronger evidence than reading a layout off a refusal's cause.
  • A stray <Break> inside a pane fails the pane rather than printing as it would at the root. That is consistent with the pane-settlement contract, but it is a behavioural difference worth a reviewer's eye.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

The replaceable seam a terminal grid executes through, before any of the
execution that uses it.
`packages/runtime/terminal.ts` is the contextual provider: `prepare()`
builds the whole composite while it stays hidden, `attach()` shows it once
every pane is ready, and `destroy()` gives the root terminal back. The
request is provider-neutral — columns, rows, and the authored panes with
their derived positions — and names no terminal, socket, process or window.
Middleware may observe, narrow, refuse, wrap or delegate; presentation
never decides an outcome, so `update()` receives states core has already
settled on.
`packages/core/src/terminal/authority.ts` mints one-use pane claims for one
request's ordinals. A claim admits one interactive operation at a time on
its pane and holds that pane's readiness latch. Two claims do not contend,
which is what lets panes stay interactive together.
`packages/core/src/terminal/pane.ts` is the seam interactive work inside a
pane reaches for, so it runs as that pane's owner instead of competing for
the root foreground lease. Absence means "not in a pane".
Evidence: `packages/runtime/tests/terminal-provider.test.ts`, 11 rows.
`runTerminalGrid()` owns the lifecycle the reader sees: it takes the run's
one foreground-terminal lease, flushes root output, prepares the composite
while it stays hidden, starts every pane concurrently, and attaches only
once every pane has reported a spawn through its claim.
Ordering is the contract. The lease and the composite are both scope-owned,
so success, failure and cancellation all release the terminal and destroy
exactly the composite that was prepared — there is no path that skips
teardown. A pane that settles without ever reporting a spawn fails startup
rather than being presented as a running pane. Before the barrier a pane
failure fails the whole grid closed; after it, the failure is that pane's
status and its siblings keep running. Close cancels a live pane as `closed`,
which is not a failed pane, and the grid fails with the first failed pane in
authored order.
`display()` and an `onUpdate` hook complete the provider surface: a pane's
rendered text goes to that pane, and a suite reacts to a state the grid
decided rather than waiting and hoping.
Evidence: `packages/core/tests/terminal-grid.test.ts` (15 rows) and
`packages/runtime/tests/terminal-provider.test.ts` (11 rows). The readiness
barrier row was verified by removing the barrier: it fails without it.
`<Terminal.Grid>` now executes. Each authored pane becomes a concurrent
child of the grid: a self-closing pane runs the host's default shell
through its claim, and a paired pane expands its own content in a scope of
its own.
A pane inherits the bindings, providers, configuration and working
directory visible where the grid was written, and keeps everything it
creates afterwards. Its `<Break>` has no loop to exit, its `<Return>` has
no enclosing value body to claim, and its checked failures settle the pane
rather than reaching the root or a sibling. A pane's rendered text is
displayed in that pane; the grid itself renders `""`, so the root output
holds what surrounds the grid and no pane display at all.
#729's five execution-dependent rows move here, where they assert the
layout against the request the provider actually receives rather than
reading it off a refusal's cause — the structural suite keeps the grammar,
placement and pure-layout rows it owns. Moving them was authorized rather
than assumed.
Evidence: 22 rows in `packages/core/tests/terminal-grid.test.ts` and 11 in
`packages/runtime/tests/terminal-provider.test.ts`; the whole Deno core
(350) and runtime (14) suites pass.
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown

PR #738: ✨ Execute concurrent terminal panes through a replaceable provider (#730)

26 files, +5399 / -226

Scope

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

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

🟡 26 files changed. Are all changes related?

🟡 New abstraction files: packages/core/src/terminal/provider-api.ts. Verify 3+ consumers.

Structural

Oxlint structural signals:

  • no-unnecessary-type-assertion ×11: packages/core/src/terminal/journal.ts, packages/durable-streams/retained.ts, packages/durable-streams/combinators.ts (+2)
  • no-unused-vars ×7: packages/core/src/expand.ts

Slop

  • packages/durable-streams/combinators.ts:168 (removed)

Oxlint slop signals:

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

Static Analysis

Oxlint: 43 diagnostics across 5 files (12 rules)
Density: 0.008 violations/added-line

no-unnecessary-type-assertion (11): packages/core/src/terminal/journal.ts, packages/durable-streams/retained.ts, packages/durable-streams/combinators.ts (+2)
no-unsafe-type-assertion (9): packages/durable-streams/combinators.ts, packages/durable-streams/retained.ts, packages/core/src/expand.ts
no-unused-vars (7): packages/core/src/expand.ts
no-base-to-string (4): packages/core/src/expand.ts
no-floating-promises (3): packages/core/src/terminal/grid.ts
no-inferrable-types (2): packages/core/src/expand.ts
unbound-method (2): packages/core/src/expand.ts
no-shadow (1): packages/core/src/expand.ts
no-useless-fallback-in-spread (1): packages/core/src/expand.ts
no-unnecessary-type-parameters (1): packages/durable-streams/retained.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.

`paneWork()` never read the grid element it was handed. Its caller has it,
and a pane's own diagnostics are positioned at the pane.

@github-actionsgithub-actionsBot 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 10 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

),
0,
// The pane's own ledger: a checked failure settles this pane and
// cannot reach the root or a sibling.

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
// cannot reach the root or a sibling.

// and a host with no terminal refuses here — before any pane has done work.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

Comment threadpackages/core/src/terminal/grid.ts Outdated
yield* pane.run(claim, composite);
if (!readiness.acknowledged) {
// Settled without ever starting: that is a startup failure even
// though the work itself raised nothing.

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
// though the work itself raised nothing.

attached = true;

// The composite stays visible after its panes settle. The reader leaving is
// what finishes the grid, not the last pane exiting.

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
// what finishes the grid, not the last pane exiting.

Comment threadpackages/runtime/terminal.ts Outdated
export const TerminalProvider: Api<TerminalProviderHandler> = createApi<TerminalProviderHandler>(
"runtime.terminalProvider",
{
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

Comment threadpackages/runtime/terminal.ts Outdated
}
log.events.push(`attach:${generation}`);
},
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

Comment threadpackages/runtime/terminal.ts Outdated
log.events.push(`state:${generation}:${ordinal}:${state}`);
options.onUpdate?.(ordinal, state);
},
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

…#730)
Restores the authority boundary on the `AgentProviders` handshake, and puts
each pane on its own durable child coroutine.
**The boundary.** `TerminalGrids` is routing and only routing: `open()`
answers `unknown` and core throws the answer away, so middleware may
observe, narrow, refuse, wrap or delegate but can never authorize. The
capability that takes the leases, mints pane claims and settles a grid is a
non-contextual authority delivered straight to the registered provider
through a one-use install handshake. Core mints one identity-bearing request
per expansion; presenting a copy, a rebuilt lookalike, a changed request, an
already-presented one, or one from a superseded installation generation
authorizes nothing, and a handler that answers without presenting settles
nothing.
**Durable children.** Each pane is a durable child of the grid, allocated in
authored order, so a pane's identity follows its ordinal rather than the
order the runtime scheduled it in. The layout is recorded in the parent
coroutine before the lease and before any provider is contacted.
**Ordering.** A pane that settles before attach keeps the status it settled
to instead of being overwritten with `running`, and simultaneous startup
failures are selected by authored ordinal rather than by whichever rejected
first. Each pane also expands under a counter of its own, so two concurrent
panes cannot take block identities that depend on which ran first.
`durableSpawn` could not be used: the task it returns is spawned inside the
ephemeral effect's own scope, which closes as the effect resolves, so
awaiting it throws `halted`. It has no call sites or tests upstream.
`durableAll` is the exercised primitive and is what the panes and the grid
child use.
Evidence: 30 rows in `packages/core/tests/terminal-grid.test.ts` and 10 in
`packages/runtime/tests/terminal-provider.test.ts`; core 349, runtime 15.

@github-actionsgithub-actionsBot 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 9 redundant comments. Inline suggestions to remove them below.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.

attached = true;

// The composite stays visible after its panes settle. The reader leaving is
// what finishes the grid, not the last pane exiting.

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
// what finishes the grid, not the last pane exiting.

yield* pane.run(claim, composite);
if (!readiness.acknowledged) {
// Settled without ever starting: a startup failure even though the work
// itself raised nothing.

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
// itself raised nothing.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

`durableSpawn` returned a task spawned inside the `ephemeral` effect's own
scope, and that scope closed as the effect resolved — so every
`yield* task` threw `halted`. It had no call sites and no tests. It now
starts the child in the routine's own scope, so the task outlives the call
and can be awaited or halted by whoever asked for it.
A retained `Close(cancelled)` meant one thing to the code and two things in
practice. Under `durableRace` and `durableAll` it is a race loser or a
fail-fast sibling, and the same combinator cancels it again — those keep
DEC-024 exactly. Under `durableSpawn` nobody cancels it a second time, so
suspending hung the resumed run forever. `runDurableChild` now takes an
explicit `CancelledChildPolicy`, fixed at each combinator's call site and
never chosen by a caller. Resuming uses a new internal
`ReplayIndex.reopen()`, which forgets one coroutine's retained Close while
keeping its yields — so the child continues its own history rather than
restarting, and the divergence guard stops reading the remaining effects as
a coroutine continuing past its own close. Neither it nor `disableReplay` is
exported.
DEC-039 records the policy and marks DEC-024's invariant as superseded in
part: it assumed every cancelled child belongs to race or all.
The grid uses the repaired primitive: the whole grid is one durable child,
each pane is its own durable child allocated in authored ordinal order, and
each pane task is observed outside its child — so a replayed pane's retained
outcome publishes its status and satisfies the readiness barrier without
entering a body, a shell, or a launcher.
Evidence: 9 rows in `packages/durable-streams/tests/durable-spawn.test.ts`
(lifetime, completed replay, interrupted resume, retained-history
continuation, and both combinators keeping their own policy); 30 rows in
`packages/core/tests/terminal-grid.test.ts`. durable-streams 32, core 349,
runtime 15.

@github-actionsgithub-actionsBot 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 15 redundant comments. Inline suggestions to remove them below.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

return (function* (): Operation<Task<RetainedPaneOutcome>> {
const durable = yield* DurableContext.get();
if (durable === undefined) {
// No journal behind this run: an ordinary spawned child.

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
// No journal behind this run: an ordinary spawned child.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

Two decisions exposed while implementing #730, and no implementation.
**DEC-040 — a cancelled child records why.** DEC-039's `"resume"` fired on
every retained `Close(cancelled)` under an incomplete parent, which revives
work a caller deliberately halted: the record of a deliberate `task.halt()`
and the record of an interrupted run are the same event. The cancelled close
now carries `cancellation: "caller"` or `"unwound"`, written by whichever
path cancelled the child, and `"resume"` continues only `"unwound"`. A
deliberate stop suspends, which is DEC-024's reproduction argument applied
to a caller instead of a combinator; a legacy record with no reason reads as
`"caller"`, because refusing to revive is the safe direction. The reason is
retained evidence, not authority: nothing outside `runDurableChild` reads
it, and no caller chooses a policy.
Terminal grids need nothing wider. A grid halts its pane tasks at close, so
those retain `"caller"` — and the grid child completes, so a resumed run
short-circuits the region and never reaches them. The case that must resume,
an interrupted run, unwinds and retains `"unwound"`.
**TG17 narrows to the resolved layout.** A continuation executes the root the
journal retained; the supplied source is not read, compared or refused
(proved in #722). A grid's authored structure — pane count, order, form — is
therefore fixed for the life of a journal and cannot differ between runs, so
comparing it compares a value with itself, which is why the refusal never
fired. What a fixed retained document still resolves differently is
`columns` and each `title`, through prop-borne values, since props are not
restored. Those refuse before the lease and before provider contact.
Authored-structure change is a root-definition compatibility question, not a
grid one. Root-definition authority is preserved rather than overridden by a
pre-replay comparison against the current file, and the versioned root
boundary that would refuse a changed source stays open work.
**DEC-040.** A cancelled Close now records why: `cancellation: "caller"`
when the owner halts the task `durableSpawn` returned, `"unwound"` for
anything involuntary. `durableSpawn` resumes only `"unwound"`; a deliberate
stop suspends until the caller's deterministic control flow halts it again,
and a record with no reason reads as `"caller"` so nothing legacy is
revived. `durableAll` and `durableRace` keep DEC-024 whatever the reason
says.
The halt is intercepted without changing the public `Task` surface: the
returned task carries every member the real one defines, copied with its
prototype, and only `halt` is replaced. A proxy cannot do this — a task's
members are read-only and non-configurable, so a `get` trap is required to
hand back exactly what the target holds.
The reason had to survive three boundaries that were dropping it: the
protocol parser, the observable copy, and — the one that actually mattered —
`detachResult`, which froze every cancellation down to `{ status }`.
**TG15.** The harness's `attached` and `pastGrid` signals are now separate,
and a run that expects its grid to complete waits for the sibling *after*
the grid before halting the root at `<Hold />`. That is what leaves a
completed grid child under an incomplete root, which is the only state in
which a completed region can be observed replaying at all. Both a successful
grid and a contained failed one replay their exact retained result with no
provider, pane content, shell or launcher work, and each row asserts the
grid child genuinely recorded a terminal close. No timeouts.
**TG17.** Prop-borne `columns` and `title` change independently against one
fixed retained document — the only things a fixed retained root can still
resolve differently — and each refuses with zero provider observation. For
supplied-file changes to pane count, order and form, the continuation opens
the retained structure rather than the file's, asserted request-for-request.
The retained record carries every authored pane's ordinal, title, form and
derived position.
`readLayout()` parses totally: the layout object and every pane field, with
missing, extra, mistyped, out-of-position and self-inconsistent records all
refused rather than half-read.
Evidence: durable-spawn 14 rows, terminal-grid 36 rows, structural 13,
provider 10. Packages: durable-streams 33, core 349, runtime 15,
workflow 172.
#730)
**The harness cannot pass a hung replay any more.** `runInterrupted()` had a
1500ms timer racing its signals, so a replay that hung returned a
DocumentRun that looked finished; it also slept a fixed 5ms to let records
land. Both are gone. It now waits only on events the run produced:
`attached`, `pastGrid`, and a new `panesSettled` for the rows that read pane
records — a pane's status is published only after its durable child returned,
so counting settled panes is also counting durable pane closes. A replay
that hangs now reaches none of them and hangs the row.
**TG15's failed case is a real contained failure.** A pane that fails before
attachment fails the whole region, so the old document could not both fail
and continue. The failing pane is now a shell that starts, waits for
attachment, and only then exits badly — contained as that pane's status,
with the grid settling as failed and the document carrying on. Both runs
capture the printed errors, and the row asserts the replayed run produced
the same ones, reached `PAST_THE_GRID`, and did no provider, pane, shell or
launcher work.
**DEC-040 gets boundary tests where the evidence actually travels.**
`parse.test.ts` round-trips both reasons to the same bytes, keeps a legacy
absence absent, and refuses an unrecognised reason at `$.result.cancellation`.
`retained.test.ts` proves retention and `consumable()` carry both reasons,
leave a legacy absence absent, drop an unrecognised one to the safe default,
and that the reason reaches the replay index. The DEC-040 rows in
`durable-spawn.test.ts` no longer coordinate by delay: a child says when it
is running, and the caller says when it has halted.
**Malformed retained layouts** are covered by replaying a real journal with
only its layout entry replaced — a missing member, an extra one, a mistyped
one, a pane out of position, and a record that disagrees with itself. Each
refuses with zero provider observation.
The `durableSpawn` doc comment no longer says every retained cancellation is
an interrupted run.
The DEC-040 block still slept where it meant to synchronise — my previous
replacements silently failed to match after the file was reformatted, so
none of them landed. The block is rewritten rather than patched.
Every row now waits on something the run reported. A shared `living()` child
resolves a `started` signal and then suspends, so each row halts or unwinds a
child that is provably live rather than one a delay happened to reach. The
caller resolves `halted` after performing its deliberate halt, so a run is
interrupted only once both facts — the deliberate stop and the interruption —
are in the journal.
Non-revival is established by control flow rather than by waiting: the
resumed run reaches its own `task.halt()` and says so, and a revived child
would have recorded its mark before the caller could get there. The
legacy-absence row signals once the child has been asked for and the request
returned. No new timeout, and `sleep` stays imported because the lifetime
rows above still use it deliberately.
`retained.test.ts` drops the cast and the row it supported: rejecting an
unrecognised reason is the parser's, proved there, and retention proves only
that `"caller"`, `"unwound"` and a legacy absence survive.

@github-actionsgithub-actionsBot 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 11 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

// neither can begin while the other holds it.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

// grid covers it up.
yield* flushOutput();

// Routed, and the answer thrown away.

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
// Routed, and the answer thrown away.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.


const grid = createTerminalGridClaims(request);
// Nothing new is admitted once teardown begins, so a pane that was about to
// start an interactive child is refused rather than racing the close.

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
// start an interactive child is refused rather than racing the close.

// to schedule it in. Each task is observed *outside* its child: a replayed
// completed pane returns its retained outcome without entering a body, a
// shell, or a launcher, and that outcome is what publishes its status and
// satisfies the readiness barrier.

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
// satisfies the readiness barrier.

…730)
**`Symbol.asyncDispose` bypassed the deliberate-stop evidence.** The task
`durableSpawn` returns copied it from the original unchanged, so
`await using` — or an explicit `task[Symbol.asyncDispose]()` — recorded
`cancellation: "unwound"` and the next run revived the child. `halt()` and
the async dispose are the same decision spelled two ways, and both are now
observed. Awaiting a task is not a stop and is left exactly as it was. A
regression disposes a live task, asserts the retained reason is `"caller"`,
resumes the journal, and proves the body is not entered again.
**Reader close no longer halts panes.** It asks them to stop: a pane races
its work against a close signal, settles as `closed`, and records that
outcome as its own. Nothing on the ordinary close path is a caller-cancelled
child any more, so a resumed run restores a pane the reader closed rather
than finding a cancelled child it must either re-enter or wait on forever.
Statuses are published before anything is awaited, so a pane with slow
finalizers cannot delay the outcome the grid already knows.
**§6.21 now agrees with architecture.md and TG17.** Partial replay compares
the resolved layout — columns and titles. Pane count, order and form come
from the retained root and cannot diverge within a continuation, so a
changed supplied file is ignored in favour of the retained structure;
refusing a changed authored structure is a root-definition boundary this
specification does not yet define.
DEC-040 is unchanged and nothing deliberately stopped is revived.

@github-actionsgithub-actionsBot 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 18 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

*destroy() {
// Destroying twice would make the record say a composite was taken down
// more times than it was built, which is exactly the ordering claim a
// suite reads this log 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
// suite reads this log for.

@github-actionsgithub-actionsBot 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 20 redundant comments. Inline suggestions to remove them below.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

},
ready() {
// Idempotent by construction: readiness is a fact about the pane, and a
// provider that reports the same spawn twice has not started two panes.

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 that reports the same spawn twice has not started two panes.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

const cancellation = members.get("cancellation");
if (cancellation === undefined) {
// A record written before this evidence existed. DEC-040 reads the
// absence as a deliberate stop, so nothing it left behind is revived.

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
// absence as a deliberate stop, so nothing it left behind is revived.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

*destroy() {
// Destroying twice would make the record say a composite was taken down
// more times than it was built, which is exactly the ordering claim a
// suite reads this log 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
// suite reads this log for.

@taras
tarasforce-pushed the agent/issue-730-terminal-execution branch from 8f85400 to eb92602CompareSeptember 2, 2026 22:38

@github-actionsgithub-actionsBot 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 9 redundant comments. Inline suggestions to remove them below.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

}
for (const [index] of work.entries()) {
// Awaited, not halted. Each pane settles on the close signal and records
// the outcome it reached, which is what a resumed run reads.

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 outcome it reached, which is what a resumed run reads.

// the reader leaves, this settles as `closed` straight away and the work
// comes down in the enclosing scope's own teardown — so a pane whose
// finalizers are slow cannot hold up the outcome the grid already knows,
// and the record a resumed run reads is written either way.

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
// and the record a resumed run reads is written either way.

return (function* (): Operation<Task<RetainedPaneOutcome>> {
const durable = yield* DurableContext.get();
if (durable === undefined) {
// No journal behind this run: an ordinary spawned child.

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
// No journal behind this run: an ordinary spawned child.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

Implements the amendment at 1833870 without revising it.
**The live handshake.** `composite.closed()` settling now only *proposes* the
boundary. The grid's durable child publishes that proposal and waits; the
owner awaiting the child acknowledges it; and only then does the grid seal
admission and ask its panes to close. The handshake is one live rendezvous —
no provider identity, nothing journaled.
**Committing an outcome before the scope finishes unwinding.** A durable
child can now declare its terminal value, and `runDurableChild` records that
value if the child never reaches a normal ending. That is the piece the
contract needs: the grid commits its retained record as the boundary is
crossed, and each pane live at that moment commits `closed`, so a
cancellation arriving while pane and provider finalizers are still running
records what close decided rather than a cancellation. Committing is live
state; it reaches the journal only as the ordinary `Close`. A child that
returns or throws normally overrides it, and a child that never committed
still records the cancellation it actually reached — DEC-040 untouched.
Cancellation stays deferred because Effection completes a child's teardown —
pane finalizers, provider destroy, terminal restoration, lease release, the
`Close` append and the task's settlement — before the halt reaches the owner.
**Pane work stays inside its ordinal-derived durable child.** Reader close
asks the pane to close; it never halts the pane's durable task. The pane
commits `closed`, stops its live nested work through its own scope, and
settles only once that work and its finalizers have settled.
No durable closing marker was added, and completed replay is unchanged.

@github-actionsgithub-actionsBot 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 11 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

// neither can begin while the other holds it.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

// grid covers it up.
yield* flushOutput();

// Routed, and the answer thrown away.

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
// Routed, and the answer thrown away.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.


const grid = createTerminalGridClaims(request);
// Nothing new is admitted once teardown begins, so a pane that was about to
// start an interactive child is refused rather than racing the close.

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
// start an interactive child is refused rather than racing the close.

Implements architecture 1833870 at the owner boundary. The grid's durable
child now runs in a scope of its own — a child of the owner's, so it inherits
every context the document runs under, and its own so that tearing the owner
down does not reach it first. A finalizer registered after that scope exists
runs before it is destroyed, and that is the cancellation-deferred await: once
the owner has acknowledged the provider's close proposal, the grid and its panes
finish teardown and append their ordinary completed Close records, and only then
does the cancellation carry on to the parent.
Removes the exported CommitOutcome/durableSpawn(commit) API. Cancellation is
never turned into success inside runDurableChild; durableSpawnIn only says where
a child lives, and grants nothing a caller does not already have.
TG19 proves the ordering with signals alone: a live pane arms a blocking
finalizer, the reader leaves, the finalizer is entered and held, cancellation
begins, the finalizer is released, and the run ends with the composite destroyed,
a completed grid Close retained, the live pane retained as closed — and the
sibling after the grid never reached. The continuation then replays past it with
no provider, no pane body and no finalizer re-entered.
TG6 isolates paired-pane sequencing on its own: the reader leaves only once the
pane's second component has run.
The production lifecycle is unchanged. TG19 now reads counters and journal
records rather than a log's shape.
The controlled composite keeps live resource counters — composites prepared,
composites attached, shells started — each raised when it takes something and
lowered when it gives it back, however it left. TG19 reads them once while a
pane finalizer is blocked, so it knows they went up, and again when the
cancellation has completed, so it knows they came back down.
The harness now says when a blocked finalizer *leaves*, not only when it is
entered: a finalizer that was entered and then cancelled reaches the first hook
and never the second. And after every interrupted run it takes the foreground
lease and gives it back twice — the first proves the grid returned it, the
second proves the harness did.
TG19 adds: one grid Close(ok) retaining close: "reader"; two pane Closes, both
completed, with no cancellation recorded at either level; the finalizer entered
and left exactly once; destroy:0 exactly once. The first-attempt claim that no
following sibling ran and the replay tripwires are unchanged.
Every one of these was broken on purpose and re-run: dropping any of the three
counter releases, the deferral, the finalizer-exit hook, or double-logging
destroy fails TG19, and a second holder of the foreground lease is refused.
Sign up for freeto 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

@taras
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

✨ Execute concurrent terminal panes through a replaceable provider (#730) - #738

Open
taras wants to merge 15 commits into
agent/issue-729-terminal-gridfrom
agent/issue-730-terminal-execution
Open

✨ Execute concurrent terminal panes through a replaceable provider (#730)#738
taras wants to merge 15 commits into
agent/issue-729-terminal-gridfrom
agent/issue-730-terminal-execution

Conversation

@taras

@tarastaras commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes#730. Second implementation Story under Quest #717, stacked on #733.

Base is agent/issue-729-terminal-grid, not main, as the Story's verification stack directs. Branched from 97be06321cbdf08d84ef53dbefb88407f54326fe, the reviewed head of #733.

Why

#729 froze the language: an author can write a terminal grid, and every runtime can validate one. Nothing could run one. This Story makes a grid execute, through a boundary a host replaces — so the document keeps one lifecycle contract whether the presentation is tmux, a controlled test surface, or something native later.

What changes

Before: a valid <Terminal.Grid> derived its layout and refused, because nothing could present it.

After: it runs. Core takes the run's one foreground-terminal lease, flushes root output, prepares the composite while it stays hidden, starts every pane concurrently, and attaches only once every pane has actually started.

<Terminal.Grid columns={2}>
<Terminaltitle="Agent">…</Terminal>
<Terminaltitle="Shell" />
</Terminal.Grid>

How it works

lease → flush → prepare (hidden) → panes start concurrently
→ readiness barrier → attach → panes settle independently
→ reader closes → teardown → lease released

packages/runtime/terminal.ts is the replaceable seam. The request is provider-neutral — columns, rows, and the authored panes with their derived positions — and names no terminal, socket, process or window. Middleware may observe, narrow, refuse, wrap or delegate. Presentation never decides an outcome: update() receives states core has already settled on, and its return value is ignored.

packages/core/src/terminal/authority.ts mints one-use pane claims for one request's ordinals. A claim admits one interactive operation at a time on its pane and holds that pane's readiness latch. Two claims do not contend, which is what lets panes stay interactive together.

packages/core/src/terminal/pane.ts is the seam anything interactive inside a pane reaches, so it runs as that pane's owner instead of competing for the root lease. Absence means "not in a pane".

packages/core/src/terminal/grid.ts owns the lifecycle. The lease and the composite are both scope-owned, so success, failure and cancellation all release the terminal and destroy exactly the composite that was prepared — there is no path that skips teardown.

Review guide

Start with:packages/core/tests/terminal-grid.test.ts

Then review:

  1. packages/runtime/terminal.ts — the boundary and what a handler may do.
  2. packages/core/src/terminal/authority.ts — claims, contention, the readiness latch.
  3. packages/core/src/terminal/grid.ts — the ordering, and where teardown is registered.
  4. packages/core/src/expand.tspaneWork(), which is where a pane's isolation is established.

Look carefully at:

  • The order in runTerminalGrid(). ensure(() => composite.destroy()) is registered before any pane starts, so a composite that was prepared is owed a destroy even if the next line fails.
  • The attached flag. Before the barrier a pane failure fails the whole grid closed; after it, the failure is that pane's status and its siblings keep running.
  • paneWork()'s paired branch: ActiveLoop.set(undefined), a derived env, containedLedger(), and undefined for the return body are the four things that make a pane a scope rather than a region.

What must stay true

  • Nothing is shown before every pane has started — enforced by racing the readiness barrier against startup failure, checked by the TG9 ordering row, which was verified by deleting the barrier: it fails without it.
  • A prepared composite is always destroyed exactly once — enforced by scope-owned ensure, checked by TG12 and by the controlled composite refusing a second destroy.
  • Presentation decides nothing — enforced by update() returning void and claims never leaving core, checked by the middleware rows in the provider suite.
  • A pane's later bindings stay in that pane — enforced by a derived environment, checked by the TG6 document row asserting the sibling and the document after the grid still see the binding unresolved.

How to verify it

deno task test packages/core/tests/terminal-grid.test.ts
deno task test packages/runtime/tests/terminal-provider.test.ts
deno task test packages/core/tests/terminal-grid-structure.test.ts
  • TG8 proves one claim admits one interactive operation at a time and two claims do not contend; it fails if a pane admitted twice, or if two panes serialized.
  • TG9 proves nothing attaches until every pane reports a spawn, and that a pane which settles without one fails startup; it fails if a grid attached early or presented a pane that never started.
  • TG10 proves a pane can fail after attach while a sibling is provably still live, and the grid reports the first failed authored ordinal.
  • TG12/TG13 prove close and parent cancellation both destroy the composite exactly once, and that a pane cancelled by the close is closed rather than failed.
  • TG6/TG7 prove pane scope and output routing through the real execute() path.
  • The provider suite proves the boundary refuses with nothing installed, and that middleware can observe, narrow, refuse and wrap without being able to authorize.

Whole Deno core suite: 350 passed. Runtime suite: 14 passed.

Scope

Included

  • The provider boundary, the terminal authority and pane claims, the readiness latch, the pane seam, and the grid lifecycle.
  • Pane scope isolation, pane output routing, concurrent start, atomic attach, independent settlement, close and cancellation teardown.

Not included — this Story is not finished

These acceptance points landed in later commits on this branch, and the section
that once said durability was absent is no longer true:

  • Durability and replay (TG15–TG17) are implemented. The grid is one durable
    child and each pane is its own durable child allocated in authored ordinal
    order. A completed region replays its exact retained result — successful and
    contained-failed alike — contacting no provider and running no pane content,
    shell or launcher. An interrupted region rebuilds a fresh composite. The
    layout is recorded in the parent coroutine before the lease and before any
    provider is contacted, and a malformed retained layout refuses there.
  • TG17 is scoped to what a continuation can actually change. A continuation
    executes the retained root, so pane count, order and form cannot differ and
    are proved retained-and-honoured rather than refused; columns and each
    title reach the grid through props, which are not restored, and each refuses
    independently with zero provider observation.
  • durableSpawn was repaired to make any of this possible: its task now
    outlives the call, and a cancelled child records why it stopped (DEC-040) so
    a deliberately halted region is never revived while an interrupted one
    resumes.

What remains outside this PR:

  • TG14's bounded teardown proof belongs to the tmux provider Story; the
    controlled provider cannot exercise it.
  • TG5 and Agent-session contention in TG11 belong to the native-launch
    Story, as the issue states.
  • One known gap: a run interrupted while reader-close teardown is awaiting
    a pane whose own finalizer is slow
    leaves that pane recorded as unwound
    rather than closed, so a resumed run re-enters it. Reader close is now
    cooperative — panes are asked to stop and record closed themselves rather
    than being halted — which removes caller-cancelled panes from the ordinary
    close path, but the blocked-finalizer overlap is not yet covered by a
    regression.

Intentionally unchanged

  • No tmux command, multiplexer, or real terminal anywhere in this change.

New abstractions

  • TerminalProvider / TerminalComposite exist because a grid's presentation has to be replaceable; the controlled provider and the future tmux adapter are the two concrete uses.

  • TerminalPaneClaim exists because pane terminal ownership must be unforgeable and per-ordinal; consumed by the grid and by the pane seam.

  • PaneTerminal exists because interactive work inside a pane must not compete for the root lease; consumed by the suite's controlled interactive child now and by <Session.Launch> in Launch native Agent sessions in independent terminal panes #731.

  • Each new abstraction has multiple concrete uses or a clear justification.

  • No speculative functionality is included.

Risks and limitations

  • Incomplete Story, stated above. Durability and replay are absent.
  • Five rows from ✨ Describe terminal grids as executable document structure (#729) #733 moved into this Story's suite. The move was authorized explicitly rather than assumed, and every claim they made is still asserted — against the provider request, which is stronger evidence than reading a layout off a refusal's cause.
  • A stray <Break> inside a pane fails the pane rather than printing as it would at the root. That is consistent with the pane-settlement contract, but it is a behavioural difference worth a reviewer's eye.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

The replaceable seam a terminal grid executes through, before any of the
execution that uses it.
`packages/runtime/terminal.ts` is the contextual provider: `prepare()`
builds the whole composite while it stays hidden, `attach()` shows it once
every pane is ready, and `destroy()` gives the root terminal back. The
request is provider-neutral — columns, rows, and the authored panes with
their derived positions — and names no terminal, socket, process or window.
Middleware may observe, narrow, refuse, wrap or delegate; presentation
never decides an outcome, so `update()` receives states core has already
settled on.
`packages/core/src/terminal/authority.ts` mints one-use pane claims for one
request's ordinals. A claim admits one interactive operation at a time on
its pane and holds that pane's readiness latch. Two claims do not contend,
which is what lets panes stay interactive together.
`packages/core/src/terminal/pane.ts` is the seam interactive work inside a
pane reaches for, so it runs as that pane's owner instead of competing for
the root foreground lease. Absence means "not in a pane".
Evidence: `packages/runtime/tests/terminal-provider.test.ts`, 11 rows.
`runTerminalGrid()` owns the lifecycle the reader sees: it takes the run's
one foreground-terminal lease, flushes root output, prepares the composite
while it stays hidden, starts every pane concurrently, and attaches only
once every pane has reported a spawn through its claim.
Ordering is the contract. The lease and the composite are both scope-owned,
so success, failure and cancellation all release the terminal and destroy
exactly the composite that was prepared — there is no path that skips
teardown. A pane that settles without ever reporting a spawn fails startup
rather than being presented as a running pane. Before the barrier a pane
failure fails the whole grid closed; after it, the failure is that pane's
status and its siblings keep running. Close cancels a live pane as `closed`,
which is not a failed pane, and the grid fails with the first failed pane in
authored order.
`display()` and an `onUpdate` hook complete the provider surface: a pane's
rendered text goes to that pane, and a suite reacts to a state the grid
decided rather than waiting and hoping.
Evidence: `packages/core/tests/terminal-grid.test.ts` (15 rows) and
`packages/runtime/tests/terminal-provider.test.ts` (11 rows). The readiness
barrier row was verified by removing the barrier: it fails without it.
`<Terminal.Grid>` now executes. Each authored pane becomes a concurrent
child of the grid: a self-closing pane runs the host's default shell
through its claim, and a paired pane expands its own content in a scope of
its own.
A pane inherits the bindings, providers, configuration and working
directory visible where the grid was written, and keeps everything it
creates afterwards. Its `<Break>` has no loop to exit, its `<Return>` has
no enclosing value body to claim, and its checked failures settle the pane
rather than reaching the root or a sibling. A pane's rendered text is
displayed in that pane; the grid itself renders `""`, so the root output
holds what surrounds the grid and no pane display at all.
#729's five execution-dependent rows move here, where they assert the
layout against the request the provider actually receives rather than
reading it off a refusal's cause — the structural suite keeps the grammar,
placement and pure-layout rows it owns. Moving them was authorized rather
than assumed.
Evidence: 22 rows in `packages/core/tests/terminal-grid.test.ts` and 11 in
`packages/runtime/tests/terminal-provider.test.ts`; the whole Deno core
(350) and runtime (14) suites pass.
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown

PR #738: ✨ Execute concurrent terminal panes through a replaceable provider (#730)

26 files, +5399 / -226

Scope

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

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

🟡 26 files changed. Are all changes related?

🟡 New abstraction files: packages/core/src/terminal/provider-api.ts. Verify 3+ consumers.

Structural

Oxlint structural signals:

  • no-unnecessary-type-assertion ×11: packages/core/src/terminal/journal.ts, packages/durable-streams/retained.ts, packages/durable-streams/combinators.ts (+2)
  • no-unused-vars ×7: packages/core/src/expand.ts

Slop

  • packages/durable-streams/combinators.ts:168 (removed)

Oxlint slop signals:

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

Static Analysis

Oxlint: 43 diagnostics across 5 files (12 rules)
Density: 0.008 violations/added-line

no-unnecessary-type-assertion (11): packages/core/src/terminal/journal.ts, packages/durable-streams/retained.ts, packages/durable-streams/combinators.ts (+2)
no-unsafe-type-assertion (9): packages/durable-streams/combinators.ts, packages/durable-streams/retained.ts, packages/core/src/expand.ts
no-unused-vars (7): packages/core/src/expand.ts
no-base-to-string (4): packages/core/src/expand.ts
no-floating-promises (3): packages/core/src/terminal/grid.ts
no-inferrable-types (2): packages/core/src/expand.ts
unbound-method (2): packages/core/src/expand.ts
no-shadow (1): packages/core/src/expand.ts
no-useless-fallback-in-spread (1): packages/core/src/expand.ts
no-unnecessary-type-parameters (1): packages/durable-streams/retained.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.

`paneWork()` never read the grid element it was handed. Its caller has it,
and a pane's own diagnostics are positioned at the pane.

@github-actionsgithub-actionsBot 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 10 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

),
0,
// The pane's own ledger: a checked failure settles this pane and
// cannot reach the root or a sibling.

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
// cannot reach the root or a sibling.

// and a host with no terminal refuses here — before any pane has done work.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

Comment threadpackages/core/src/terminal/grid.ts Outdated
yield* pane.run(claim, composite);
if (!readiness.acknowledged) {
// Settled without ever starting: that is a startup failure even
// though the work itself raised nothing.

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
// though the work itself raised nothing.

attached = true;

// The composite stays visible after its panes settle. The reader leaving is
// what finishes the grid, not the last pane exiting.

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
// what finishes the grid, not the last pane exiting.

Comment threadpackages/runtime/terminal.ts Outdated
export const TerminalProvider: Api<TerminalProviderHandler> = createApi<TerminalProviderHandler>(
"runtime.terminalProvider",
{
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

Comment threadpackages/runtime/terminal.ts Outdated
}
log.events.push(`attach:${generation}`);
},
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

Comment threadpackages/runtime/terminal.ts Outdated
log.events.push(`state:${generation}:${ordinal}:${state}`);
options.onUpdate?.(ordinal, state);
},
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

…#730)
Restores the authority boundary on the `AgentProviders` handshake, and puts
each pane on its own durable child coroutine.
**The boundary.** `TerminalGrids` is routing and only routing: `open()`
answers `unknown` and core throws the answer away, so middleware may
observe, narrow, refuse, wrap or delegate but can never authorize. The
capability that takes the leases, mints pane claims and settles a grid is a
non-contextual authority delivered straight to the registered provider
through a one-use install handshake. Core mints one identity-bearing request
per expansion; presenting a copy, a rebuilt lookalike, a changed request, an
already-presented one, or one from a superseded installation generation
authorizes nothing, and a handler that answers without presenting settles
nothing.
**Durable children.** Each pane is a durable child of the grid, allocated in
authored order, so a pane's identity follows its ordinal rather than the
order the runtime scheduled it in. The layout is recorded in the parent
coroutine before the lease and before any provider is contacted.
**Ordering.** A pane that settles before attach keeps the status it settled
to instead of being overwritten with `running`, and simultaneous startup
failures are selected by authored ordinal rather than by whichever rejected
first. Each pane also expands under a counter of its own, so two concurrent
panes cannot take block identities that depend on which ran first.
`durableSpawn` could not be used: the task it returns is spawned inside the
ephemeral effect's own scope, which closes as the effect resolves, so
awaiting it throws `halted`. It has no call sites or tests upstream.
`durableAll` is the exercised primitive and is what the panes and the grid
child use.
Evidence: 30 rows in `packages/core/tests/terminal-grid.test.ts` and 10 in
`packages/runtime/tests/terminal-provider.test.ts`; core 349, runtime 15.

@github-actionsgithub-actionsBot 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 9 redundant comments. Inline suggestions to remove them below.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.

attached = true;

// The composite stays visible after its panes settle. The reader leaving is
// what finishes the grid, not the last pane exiting.

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
// what finishes the grid, not the last pane exiting.

yield* pane.run(claim, composite);
if (!readiness.acknowledged) {
// Settled without ever starting: a startup failure even though the work
// itself raised nothing.

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
// itself raised nothing.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

`durableSpawn` returned a task spawned inside the `ephemeral` effect's own
scope, and that scope closed as the effect resolved — so every
`yield* task` threw `halted`. It had no call sites and no tests. It now
starts the child in the routine's own scope, so the task outlives the call
and can be awaited or halted by whoever asked for it.
A retained `Close(cancelled)` meant one thing to the code and two things in
practice. Under `durableRace` and `durableAll` it is a race loser or a
fail-fast sibling, and the same combinator cancels it again — those keep
DEC-024 exactly. Under `durableSpawn` nobody cancels it a second time, so
suspending hung the resumed run forever. `runDurableChild` now takes an
explicit `CancelledChildPolicy`, fixed at each combinator's call site and
never chosen by a caller. Resuming uses a new internal
`ReplayIndex.reopen()`, which forgets one coroutine's retained Close while
keeping its yields — so the child continues its own history rather than
restarting, and the divergence guard stops reading the remaining effects as
a coroutine continuing past its own close. Neither it nor `disableReplay` is
exported.
DEC-039 records the policy and marks DEC-024's invariant as superseded in
part: it assumed every cancelled child belongs to race or all.
The grid uses the repaired primitive: the whole grid is one durable child,
each pane is its own durable child allocated in authored ordinal order, and
each pane task is observed outside its child — so a replayed pane's retained
outcome publishes its status and satisfies the readiness barrier without
entering a body, a shell, or a launcher.
Evidence: 9 rows in `packages/durable-streams/tests/durable-spawn.test.ts`
(lifetime, completed replay, interrupted resume, retained-history
continuation, and both combinators keeping their own policy); 30 rows in
`packages/core/tests/terminal-grid.test.ts`. durable-streams 32, core 349,
runtime 15.

@github-actionsgithub-actionsBot 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 15 redundant comments. Inline suggestions to remove them below.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

return (function* (): Operation<Task<RetainedPaneOutcome>> {
const durable = yield* DurableContext.get();
if (durable === undefined) {
// No journal behind this run: an ordinary spawned child.

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
// No journal behind this run: an ordinary spawned child.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

Two decisions exposed while implementing #730, and no implementation.
**DEC-040 — a cancelled child records why.** DEC-039's `"resume"` fired on
every retained `Close(cancelled)` under an incomplete parent, which revives
work a caller deliberately halted: the record of a deliberate `task.halt()`
and the record of an interrupted run are the same event. The cancelled close
now carries `cancellation: "caller"` or `"unwound"`, written by whichever
path cancelled the child, and `"resume"` continues only `"unwound"`. A
deliberate stop suspends, which is DEC-024's reproduction argument applied
to a caller instead of a combinator; a legacy record with no reason reads as
`"caller"`, because refusing to revive is the safe direction. The reason is
retained evidence, not authority: nothing outside `runDurableChild` reads
it, and no caller chooses a policy.
Terminal grids need nothing wider. A grid halts its pane tasks at close, so
those retain `"caller"` — and the grid child completes, so a resumed run
short-circuits the region and never reaches them. The case that must resume,
an interrupted run, unwinds and retains `"unwound"`.
**TG17 narrows to the resolved layout.** A continuation executes the root the
journal retained; the supplied source is not read, compared or refused
(proved in #722). A grid's authored structure — pane count, order, form — is
therefore fixed for the life of a journal and cannot differ between runs, so
comparing it compares a value with itself, which is why the refusal never
fired. What a fixed retained document still resolves differently is
`columns` and each `title`, through prop-borne values, since props are not
restored. Those refuse before the lease and before provider contact.
Authored-structure change is a root-definition compatibility question, not a
grid one. Root-definition authority is preserved rather than overridden by a
pre-replay comparison against the current file, and the versioned root
boundary that would refuse a changed source stays open work.
**DEC-040.** A cancelled Close now records why: `cancellation: "caller"`
when the owner halts the task `durableSpawn` returned, `"unwound"` for
anything involuntary. `durableSpawn` resumes only `"unwound"`; a deliberate
stop suspends until the caller's deterministic control flow halts it again,
and a record with no reason reads as `"caller"` so nothing legacy is
revived. `durableAll` and `durableRace` keep DEC-024 whatever the reason
says.
The halt is intercepted without changing the public `Task` surface: the
returned task carries every member the real one defines, copied with its
prototype, and only `halt` is replaced. A proxy cannot do this — a task's
members are read-only and non-configurable, so a `get` trap is required to
hand back exactly what the target holds.
The reason had to survive three boundaries that were dropping it: the
protocol parser, the observable copy, and — the one that actually mattered —
`detachResult`, which froze every cancellation down to `{ status }`.
**TG15.** The harness's `attached` and `pastGrid` signals are now separate,
and a run that expects its grid to complete waits for the sibling *after*
the grid before halting the root at `<Hold />`. That is what leaves a
completed grid child under an incomplete root, which is the only state in
which a completed region can be observed replaying at all. Both a successful
grid and a contained failed one replay their exact retained result with no
provider, pane content, shell or launcher work, and each row asserts the
grid child genuinely recorded a terminal close. No timeouts.
**TG17.** Prop-borne `columns` and `title` change independently against one
fixed retained document — the only things a fixed retained root can still
resolve differently — and each refuses with zero provider observation. For
supplied-file changes to pane count, order and form, the continuation opens
the retained structure rather than the file's, asserted request-for-request.
The retained record carries every authored pane's ordinal, title, form and
derived position.
`readLayout()` parses totally: the layout object and every pane field, with
missing, extra, mistyped, out-of-position and self-inconsistent records all
refused rather than half-read.
Evidence: durable-spawn 14 rows, terminal-grid 36 rows, structural 13,
provider 10. Packages: durable-streams 33, core 349, runtime 15,
workflow 172.
#730)
**The harness cannot pass a hung replay any more.** `runInterrupted()` had a
1500ms timer racing its signals, so a replay that hung returned a
DocumentRun that looked finished; it also slept a fixed 5ms to let records
land. Both are gone. It now waits only on events the run produced:
`attached`, `pastGrid`, and a new `panesSettled` for the rows that read pane
records — a pane's status is published only after its durable child returned,
so counting settled panes is also counting durable pane closes. A replay
that hangs now reaches none of them and hangs the row.
**TG15's failed case is a real contained failure.** A pane that fails before
attachment fails the whole region, so the old document could not both fail
and continue. The failing pane is now a shell that starts, waits for
attachment, and only then exits badly — contained as that pane's status,
with the grid settling as failed and the document carrying on. Both runs
capture the printed errors, and the row asserts the replayed run produced
the same ones, reached `PAST_THE_GRID`, and did no provider, pane, shell or
launcher work.
**DEC-040 gets boundary tests where the evidence actually travels.**
`parse.test.ts` round-trips both reasons to the same bytes, keeps a legacy
absence absent, and refuses an unrecognised reason at `$.result.cancellation`.
`retained.test.ts` proves retention and `consumable()` carry both reasons,
leave a legacy absence absent, drop an unrecognised one to the safe default,
and that the reason reaches the replay index. The DEC-040 rows in
`durable-spawn.test.ts` no longer coordinate by delay: a child says when it
is running, and the caller says when it has halted.
**Malformed retained layouts** are covered by replaying a real journal with
only its layout entry replaced — a missing member, an extra one, a mistyped
one, a pane out of position, and a record that disagrees with itself. Each
refuses with zero provider observation.
The `durableSpawn` doc comment no longer says every retained cancellation is
an interrupted run.
The DEC-040 block still slept where it meant to synchronise — my previous
replacements silently failed to match after the file was reformatted, so
none of them landed. The block is rewritten rather than patched.
Every row now waits on something the run reported. A shared `living()` child
resolves a `started` signal and then suspends, so each row halts or unwinds a
child that is provably live rather than one a delay happened to reach. The
caller resolves `halted` after performing its deliberate halt, so a run is
interrupted only once both facts — the deliberate stop and the interruption —
are in the journal.
Non-revival is established by control flow rather than by waiting: the
resumed run reaches its own `task.halt()` and says so, and a revived child
would have recorded its mark before the caller could get there. The
legacy-absence row signals once the child has been asked for and the request
returned. No new timeout, and `sleep` stays imported because the lifetime
rows above still use it deliberately.
`retained.test.ts` drops the cast and the row it supported: rejecting an
unrecognised reason is the parser's, proved there, and retention proves only
that `"caller"`, `"unwound"` and a legacy absence survive.

@github-actionsgithub-actionsBot 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 11 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

// neither can begin while the other holds it.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

// grid covers it up.
yield* flushOutput();

// Routed, and the answer thrown away.

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
// Routed, and the answer thrown away.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.


const grid = createTerminalGridClaims(request);
// Nothing new is admitted once teardown begins, so a pane that was about to
// start an interactive child is refused rather than racing the close.

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
// start an interactive child is refused rather than racing the close.

// to schedule it in. Each task is observed *outside* its child: a replayed
// completed pane returns its retained outcome without entering a body, a
// shell, or a launcher, and that outcome is what publishes its status and
// satisfies the readiness barrier.

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
// satisfies the readiness barrier.

…730)
**`Symbol.asyncDispose` bypassed the deliberate-stop evidence.** The task
`durableSpawn` returns copied it from the original unchanged, so
`await using` — or an explicit `task[Symbol.asyncDispose]()` — recorded
`cancellation: "unwound"` and the next run revived the child. `halt()` and
the async dispose are the same decision spelled two ways, and both are now
observed. Awaiting a task is not a stop and is left exactly as it was. A
regression disposes a live task, asserts the retained reason is `"caller"`,
resumes the journal, and proves the body is not entered again.
**Reader close no longer halts panes.** It asks them to stop: a pane races
its work against a close signal, settles as `closed`, and records that
outcome as its own. Nothing on the ordinary close path is a caller-cancelled
child any more, so a resumed run restores a pane the reader closed rather
than finding a cancelled child it must either re-enter or wait on forever.
Statuses are published before anything is awaited, so a pane with slow
finalizers cannot delay the outcome the grid already knows.
**§6.21 now agrees with architecture.md and TG17.** Partial replay compares
the resolved layout — columns and titles. Pane count, order and form come
from the retained root and cannot diverge within a continuation, so a
changed supplied file is ignored in favour of the retained structure;
refusing a changed authored structure is a root-definition boundary this
specification does not yet define.
DEC-040 is unchanged and nothing deliberately stopped is revived.

@github-actionsgithub-actionsBot 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 18 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

*destroy() {
// Destroying twice would make the record say a composite was taken down
// more times than it was built, which is exactly the ordering claim a
// suite reads this log 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
// suite reads this log for.

@github-actionsgithub-actionsBot 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 20 redundant comments. Inline suggestions to remove them below.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

},
ready() {
// Idempotent by construction: readiness is a fact about the pane, and a
// provider that reports the same spawn twice has not started two panes.

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 that reports the same spawn twice has not started two panes.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

const cancellation = members.get("cancellation");
if (cancellation === undefined) {
// A record written before this evidence existed. DEC-040 reads the
// absence as a deliberate stop, so nothing it left behind is revived.

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
// absence as a deliberate stop, so nothing it left behind is revived.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

*destroy() {
// Destroying twice would make the record say a composite was taken down
// more times than it was built, which is exactly the ordering claim a
// suite reads this log 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
// suite reads this log for.

@taras
tarasforce-pushed the agent/issue-730-terminal-execution branch from 8f85400 to eb92602CompareSeptember 2, 2026 22:38

@github-actionsgithub-actionsBot 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 9 redundant comments. Inline suggestions to remove them below.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

}
for (const [index] of work.entries()) {
// Awaited, not halted. Each pane settles on the close signal and records
// the outcome it reached, which is what a resumed run reads.

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 outcome it reached, which is what a resumed run reads.

// the reader leaves, this settles as `closed` straight away and the work
// comes down in the enclosing scope's own teardown — so a pane whose
// finalizers are slow cannot hold up the outcome the grid already knows,
// and the record a resumed run reads is written either way.

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
// and the record a resumed run reads is written either way.

return (function* (): Operation<Task<RetainedPaneOutcome>> {
const durable = yield* DurableContext.get();
if (durable === undefined) {
// No journal behind this run: an ordinary spawned child.

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
// No journal behind this run: an ordinary spawned child.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

Implements the amendment at 1833870 without revising it.
**The live handshake.** `composite.closed()` settling now only *proposes* the
boundary. The grid's durable child publishes that proposal and waits; the
owner awaiting the child acknowledges it; and only then does the grid seal
admission and ask its panes to close. The handshake is one live rendezvous —
no provider identity, nothing journaled.
**Committing an outcome before the scope finishes unwinding.** A durable
child can now declare its terminal value, and `runDurableChild` records that
value if the child never reaches a normal ending. That is the piece the
contract needs: the grid commits its retained record as the boundary is
crossed, and each pane live at that moment commits `closed`, so a
cancellation arriving while pane and provider finalizers are still running
records what close decided rather than a cancellation. Committing is live
state; it reaches the journal only as the ordinary `Close`. A child that
returns or throws normally overrides it, and a child that never committed
still records the cancellation it actually reached — DEC-040 untouched.
Cancellation stays deferred because Effection completes a child's teardown —
pane finalizers, provider destroy, terminal restoration, lease release, the
`Close` append and the task's settlement — before the halt reaches the owner.
**Pane work stays inside its ordinal-derived durable child.** Reader close
asks the pane to close; it never halts the pane's durable task. The pane
commits `closed`, stops its live nested work through its own scope, and
settles only once that work and its finalizers have settled.
No durable closing marker was added, and completed replay is unchanged.

@github-actionsgithub-actionsBot 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 11 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

// neither can begin while the other holds it.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

// grid covers it up.
yield* flushOutput();

// Routed, and the answer thrown away.

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
// Routed, and the answer thrown away.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.


const grid = createTerminalGridClaims(request);
// Nothing new is admitted once teardown begins, so a pane that was about to
// start an interactive child is refused rather than racing the close.

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
// start an interactive child is refused rather than racing the close.

Implements architecture 1833870 at the owner boundary. The grid's durable
child now runs in a scope of its own — a child of the owner's, so it inherits
every context the document runs under, and its own so that tearing the owner
down does not reach it first. A finalizer registered after that scope exists
runs before it is destroyed, and that is the cancellation-deferred await: once
the owner has acknowledged the provider's close proposal, the grid and its panes
finish teardown and append their ordinary completed Close records, and only then
does the cancellation carry on to the parent.
Removes the exported CommitOutcome/durableSpawn(commit) API. Cancellation is
never turned into success inside runDurableChild; durableSpawnIn only says where
a child lives, and grants nothing a caller does not already have.
TG19 proves the ordering with signals alone: a live pane arms a blocking
finalizer, the reader leaves, the finalizer is entered and held, cancellation
begins, the finalizer is released, and the run ends with the composite destroyed,
a completed grid Close retained, the live pane retained as closed — and the
sibling after the grid never reached. The continuation then replays past it with
no provider, no pane body and no finalizer re-entered.
TG6 isolates paired-pane sequencing on its own: the reader leaves only once the
pane's second component has run.
The production lifecycle is unchanged. TG19 now reads counters and journal
records rather than a log's shape.
The controlled composite keeps live resource counters — composites prepared,
composites attached, shells started — each raised when it takes something and
lowered when it gives it back, however it left. TG19 reads them once while a
pane finalizer is blocked, so it knows they went up, and again when the
cancellation has completed, so it knows they came back down.
The harness now says when a blocked finalizer *leaves*, not only when it is
entered: a finalizer that was entered and then cancelled reaches the first hook
and never the second. And after every interrupted run it takes the foreground
lease and gives it back twice — the first proves the grid returned it, the
second proves the harness did.
TG19 adds: one grid Close(ok) retaining close: "reader"; two pane Closes, both
completed, with no cancellation recorded at either level; the finalizer entered
and left exactly once; destroy:0 exactly once. The first-attempt claim that no
following sibling ran and the replay tripwires are unchanged.
Every one of these was broken on purpose and re-run: dropping any of the three
counter releases, the deferral, the finalizer-exit hook, or double-logging
destroy fails TG19, and a second holder of the foreground lease is refused.
Sign up for freeto 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

@taras
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

✨ Execute concurrent terminal panes through a replaceable provider (#730) - #738

Open
taras wants to merge 15 commits into
agent/issue-729-terminal-gridfrom
agent/issue-730-terminal-execution
Open

✨ Execute concurrent terminal panes through a replaceable provider (#730)#738
taras wants to merge 15 commits into
agent/issue-729-terminal-gridfrom
agent/issue-730-terminal-execution

Conversation

@taras

@tarastaras commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes#730. Second implementation Story under Quest #717, stacked on #733.

Base is agent/issue-729-terminal-grid, not main, as the Story's verification stack directs. Branched from 97be06321cbdf08d84ef53dbefb88407f54326fe, the reviewed head of #733.

Why

#729 froze the language: an author can write a terminal grid, and every runtime can validate one. Nothing could run one. This Story makes a grid execute, through a boundary a host replaces — so the document keeps one lifecycle contract whether the presentation is tmux, a controlled test surface, or something native later.

What changes

Before: a valid <Terminal.Grid> derived its layout and refused, because nothing could present it.

After: it runs. Core takes the run's one foreground-terminal lease, flushes root output, prepares the composite while it stays hidden, starts every pane concurrently, and attaches only once every pane has actually started.

<Terminal.Grid columns={2}>
<Terminaltitle="Agent">…</Terminal>
<Terminaltitle="Shell" />
</Terminal.Grid>

How it works

lease → flush → prepare (hidden) → panes start concurrently
→ readiness barrier → attach → panes settle independently
→ reader closes → teardown → lease released

packages/runtime/terminal.ts is the replaceable seam. The request is provider-neutral — columns, rows, and the authored panes with their derived positions — and names no terminal, socket, process or window. Middleware may observe, narrow, refuse, wrap or delegate. Presentation never decides an outcome: update() receives states core has already settled on, and its return value is ignored.

packages/core/src/terminal/authority.ts mints one-use pane claims for one request's ordinals. A claim admits one interactive operation at a time on its pane and holds that pane's readiness latch. Two claims do not contend, which is what lets panes stay interactive together.

packages/core/src/terminal/pane.ts is the seam anything interactive inside a pane reaches, so it runs as that pane's owner instead of competing for the root lease. Absence means "not in a pane".

packages/core/src/terminal/grid.ts owns the lifecycle. The lease and the composite are both scope-owned, so success, failure and cancellation all release the terminal and destroy exactly the composite that was prepared — there is no path that skips teardown.

Review guide

Start with:packages/core/tests/terminal-grid.test.ts

Then review:

  1. packages/runtime/terminal.ts — the boundary and what a handler may do.
  2. packages/core/src/terminal/authority.ts — claims, contention, the readiness latch.
  3. packages/core/src/terminal/grid.ts — the ordering, and where teardown is registered.
  4. packages/core/src/expand.tspaneWork(), which is where a pane's isolation is established.

Look carefully at:

  • The order in runTerminalGrid(). ensure(() => composite.destroy()) is registered before any pane starts, so a composite that was prepared is owed a destroy even if the next line fails.
  • The attached flag. Before the barrier a pane failure fails the whole grid closed; after it, the failure is that pane's status and its siblings keep running.
  • paneWork()'s paired branch: ActiveLoop.set(undefined), a derived env, containedLedger(), and undefined for the return body are the four things that make a pane a scope rather than a region.

What must stay true

  • Nothing is shown before every pane has started — enforced by racing the readiness barrier against startup failure, checked by the TG9 ordering row, which was verified by deleting the barrier: it fails without it.
  • A prepared composite is always destroyed exactly once — enforced by scope-owned ensure, checked by TG12 and by the controlled composite refusing a second destroy.
  • Presentation decides nothing — enforced by update() returning void and claims never leaving core, checked by the middleware rows in the provider suite.
  • A pane's later bindings stay in that pane — enforced by a derived environment, checked by the TG6 document row asserting the sibling and the document after the grid still see the binding unresolved.

How to verify it

deno task test packages/core/tests/terminal-grid.test.ts
deno task test packages/runtime/tests/terminal-provider.test.ts
deno task test packages/core/tests/terminal-grid-structure.test.ts
  • TG8 proves one claim admits one interactive operation at a time and two claims do not contend; it fails if a pane admitted twice, or if two panes serialized.
  • TG9 proves nothing attaches until every pane reports a spawn, and that a pane which settles without one fails startup; it fails if a grid attached early or presented a pane that never started.
  • TG10 proves a pane can fail after attach while a sibling is provably still live, and the grid reports the first failed authored ordinal.
  • TG12/TG13 prove close and parent cancellation both destroy the composite exactly once, and that a pane cancelled by the close is closed rather than failed.
  • TG6/TG7 prove pane scope and output routing through the real execute() path.
  • The provider suite proves the boundary refuses with nothing installed, and that middleware can observe, narrow, refuse and wrap without being able to authorize.

Whole Deno core suite: 350 passed. Runtime suite: 14 passed.

Scope

Included

  • The provider boundary, the terminal authority and pane claims, the readiness latch, the pane seam, and the grid lifecycle.
  • Pane scope isolation, pane output routing, concurrent start, atomic attach, independent settlement, close and cancellation teardown.

Not included — this Story is not finished

These acceptance points landed in later commits on this branch, and the section
that once said durability was absent is no longer true:

  • Durability and replay (TG15–TG17) are implemented. The grid is one durable
    child and each pane is its own durable child allocated in authored ordinal
    order. A completed region replays its exact retained result — successful and
    contained-failed alike — contacting no provider and running no pane content,
    shell or launcher. An interrupted region rebuilds a fresh composite. The
    layout is recorded in the parent coroutine before the lease and before any
    provider is contacted, and a malformed retained layout refuses there.
  • TG17 is scoped to what a continuation can actually change. A continuation
    executes the retained root, so pane count, order and form cannot differ and
    are proved retained-and-honoured rather than refused; columns and each
    title reach the grid through props, which are not restored, and each refuses
    independently with zero provider observation.
  • durableSpawn was repaired to make any of this possible: its task now
    outlives the call, and a cancelled child records why it stopped (DEC-040) so
    a deliberately halted region is never revived while an interrupted one
    resumes.

What remains outside this PR:

  • TG14's bounded teardown proof belongs to the tmux provider Story; the
    controlled provider cannot exercise it.
  • TG5 and Agent-session contention in TG11 belong to the native-launch
    Story, as the issue states.
  • One known gap: a run interrupted while reader-close teardown is awaiting
    a pane whose own finalizer is slow
    leaves that pane recorded as unwound
    rather than closed, so a resumed run re-enters it. Reader close is now
    cooperative — panes are asked to stop and record closed themselves rather
    than being halted — which removes caller-cancelled panes from the ordinary
    close path, but the blocked-finalizer overlap is not yet covered by a
    regression.

Intentionally unchanged

  • No tmux command, multiplexer, or real terminal anywhere in this change.

New abstractions

  • TerminalProvider / TerminalComposite exist because a grid's presentation has to be replaceable; the controlled provider and the future tmux adapter are the two concrete uses.

  • TerminalPaneClaim exists because pane terminal ownership must be unforgeable and per-ordinal; consumed by the grid and by the pane seam.

  • PaneTerminal exists because interactive work inside a pane must not compete for the root lease; consumed by the suite's controlled interactive child now and by <Session.Launch> in Launch native Agent sessions in independent terminal panes #731.

  • Each new abstraction has multiple concrete uses or a clear justification.

  • No speculative functionality is included.

Risks and limitations

  • Incomplete Story, stated above. Durability and replay are absent.
  • Five rows from ✨ Describe terminal grids as executable document structure (#729) #733 moved into this Story's suite. The move was authorized explicitly rather than assumed, and every claim they made is still asserted — against the provider request, which is stronger evidence than reading a layout off a refusal's cause.
  • A stray <Break> inside a pane fails the pane rather than printing as it would at the root. That is consistent with the pane-settlement contract, but it is a behavioural difference worth a reviewer's eye.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

The replaceable seam a terminal grid executes through, before any of the
execution that uses it.
`packages/runtime/terminal.ts` is the contextual provider: `prepare()`
builds the whole composite while it stays hidden, `attach()` shows it once
every pane is ready, and `destroy()` gives the root terminal back. The
request is provider-neutral — columns, rows, and the authored panes with
their derived positions — and names no terminal, socket, process or window.
Middleware may observe, narrow, refuse, wrap or delegate; presentation
never decides an outcome, so `update()` receives states core has already
settled on.
`packages/core/src/terminal/authority.ts` mints one-use pane claims for one
request's ordinals. A claim admits one interactive operation at a time on
its pane and holds that pane's readiness latch. Two claims do not contend,
which is what lets panes stay interactive together.
`packages/core/src/terminal/pane.ts` is the seam interactive work inside a
pane reaches for, so it runs as that pane's owner instead of competing for
the root foreground lease. Absence means "not in a pane".
Evidence: `packages/runtime/tests/terminal-provider.test.ts`, 11 rows.
`runTerminalGrid()` owns the lifecycle the reader sees: it takes the run's
one foreground-terminal lease, flushes root output, prepares the composite
while it stays hidden, starts every pane concurrently, and attaches only
once every pane has reported a spawn through its claim.
Ordering is the contract. The lease and the composite are both scope-owned,
so success, failure and cancellation all release the terminal and destroy
exactly the composite that was prepared — there is no path that skips
teardown. A pane that settles without ever reporting a spawn fails startup
rather than being presented as a running pane. Before the barrier a pane
failure fails the whole grid closed; after it, the failure is that pane's
status and its siblings keep running. Close cancels a live pane as `closed`,
which is not a failed pane, and the grid fails with the first failed pane in
authored order.
`display()` and an `onUpdate` hook complete the provider surface: a pane's
rendered text goes to that pane, and a suite reacts to a state the grid
decided rather than waiting and hoping.
Evidence: `packages/core/tests/terminal-grid.test.ts` (15 rows) and
`packages/runtime/tests/terminal-provider.test.ts` (11 rows). The readiness
barrier row was verified by removing the barrier: it fails without it.
`<Terminal.Grid>` now executes. Each authored pane becomes a concurrent
child of the grid: a self-closing pane runs the host's default shell
through its claim, and a paired pane expands its own content in a scope of
its own.
A pane inherits the bindings, providers, configuration and working
directory visible where the grid was written, and keeps everything it
creates afterwards. Its `<Break>` has no loop to exit, its `<Return>` has
no enclosing value body to claim, and its checked failures settle the pane
rather than reaching the root or a sibling. A pane's rendered text is
displayed in that pane; the grid itself renders `""`, so the root output
holds what surrounds the grid and no pane display at all.
#729's five execution-dependent rows move here, where they assert the
layout against the request the provider actually receives rather than
reading it off a refusal's cause — the structural suite keeps the grammar,
placement and pure-layout rows it owns. Moving them was authorized rather
than assumed.
Evidence: 22 rows in `packages/core/tests/terminal-grid.test.ts` and 11 in
`packages/runtime/tests/terminal-provider.test.ts`; the whole Deno core
(350) and runtime (14) suites pass.
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown

PR #738: ✨ Execute concurrent terminal panes through a replaceable provider (#730)

26 files, +5399 / -226

Scope

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

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

🟡 26 files changed. Are all changes related?

🟡 New abstraction files: packages/core/src/terminal/provider-api.ts. Verify 3+ consumers.

Structural

Oxlint structural signals:

  • no-unnecessary-type-assertion ×11: packages/core/src/terminal/journal.ts, packages/durable-streams/retained.ts, packages/durable-streams/combinators.ts (+2)
  • no-unused-vars ×7: packages/core/src/expand.ts

Slop

  • packages/durable-streams/combinators.ts:168 (removed)

Oxlint slop signals:

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

Static Analysis

Oxlint: 43 diagnostics across 5 files (12 rules)
Density: 0.008 violations/added-line

no-unnecessary-type-assertion (11): packages/core/src/terminal/journal.ts, packages/durable-streams/retained.ts, packages/durable-streams/combinators.ts (+2)
no-unsafe-type-assertion (9): packages/durable-streams/combinators.ts, packages/durable-streams/retained.ts, packages/core/src/expand.ts
no-unused-vars (7): packages/core/src/expand.ts
no-base-to-string (4): packages/core/src/expand.ts
no-floating-promises (3): packages/core/src/terminal/grid.ts
no-inferrable-types (2): packages/core/src/expand.ts
unbound-method (2): packages/core/src/expand.ts
no-shadow (1): packages/core/src/expand.ts
no-useless-fallback-in-spread (1): packages/core/src/expand.ts
no-unnecessary-type-parameters (1): packages/durable-streams/retained.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.

`paneWork()` never read the grid element it was handed. Its caller has it,
and a pane's own diagnostics are positioned at the pane.

@github-actionsgithub-actionsBot 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 10 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

),
0,
// The pane's own ledger: a checked failure settles this pane and
// cannot reach the root or a sibling.

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
// cannot reach the root or a sibling.

// and a host with no terminal refuses here — before any pane has done work.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

Comment threadpackages/core/src/terminal/grid.ts Outdated
yield* pane.run(claim, composite);
if (!readiness.acknowledged) {
// Settled without ever starting: that is a startup failure even
// though the work itself raised nothing.

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
// though the work itself raised nothing.

attached = true;

// The composite stays visible after its panes settle. The reader leaving is
// what finishes the grid, not the last pane exiting.

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
// what finishes the grid, not the last pane exiting.

Comment threadpackages/runtime/terminal.ts Outdated
export const TerminalProvider: Api<TerminalProviderHandler> = createApi<TerminalProviderHandler>(
"runtime.terminalProvider",
{
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

Comment threadpackages/runtime/terminal.ts Outdated
}
log.events.push(`attach:${generation}`);
},
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

Comment threadpackages/runtime/terminal.ts Outdated
log.events.push(`state:${generation}:${ordinal}:${state}`);
options.onUpdate?.(ordinal, state);
},
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

…#730)
Restores the authority boundary on the `AgentProviders` handshake, and puts
each pane on its own durable child coroutine.
**The boundary.** `TerminalGrids` is routing and only routing: `open()`
answers `unknown` and core throws the answer away, so middleware may
observe, narrow, refuse, wrap or delegate but can never authorize. The
capability that takes the leases, mints pane claims and settles a grid is a
non-contextual authority delivered straight to the registered provider
through a one-use install handshake. Core mints one identity-bearing request
per expansion; presenting a copy, a rebuilt lookalike, a changed request, an
already-presented one, or one from a superseded installation generation
authorizes nothing, and a handler that answers without presenting settles
nothing.
**Durable children.** Each pane is a durable child of the grid, allocated in
authored order, so a pane's identity follows its ordinal rather than the
order the runtime scheduled it in. The layout is recorded in the parent
coroutine before the lease and before any provider is contacted.
**Ordering.** A pane that settles before attach keeps the status it settled
to instead of being overwritten with `running`, and simultaneous startup
failures are selected by authored ordinal rather than by whichever rejected
first. Each pane also expands under a counter of its own, so two concurrent
panes cannot take block identities that depend on which ran first.
`durableSpawn` could not be used: the task it returns is spawned inside the
ephemeral effect's own scope, which closes as the effect resolves, so
awaiting it throws `halted`. It has no call sites or tests upstream.
`durableAll` is the exercised primitive and is what the panes and the grid
child use.
Evidence: 30 rows in `packages/core/tests/terminal-grid.test.ts` and 10 in
`packages/runtime/tests/terminal-provider.test.ts`; core 349, runtime 15.

@github-actionsgithub-actionsBot 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 9 redundant comments. Inline suggestions to remove them below.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.

attached = true;

// The composite stays visible after its panes settle. The reader leaving is
// what finishes the grid, not the last pane exiting.

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
// what finishes the grid, not the last pane exiting.

yield* pane.run(claim, composite);
if (!readiness.acknowledged) {
// Settled without ever starting: a startup failure even though the work
// itself raised nothing.

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
// itself raised nothing.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

`durableSpawn` returned a task spawned inside the `ephemeral` effect's own
scope, and that scope closed as the effect resolved — so every
`yield* task` threw `halted`. It had no call sites and no tests. It now
starts the child in the routine's own scope, so the task outlives the call
and can be awaited or halted by whoever asked for it.
A retained `Close(cancelled)` meant one thing to the code and two things in
practice. Under `durableRace` and `durableAll` it is a race loser or a
fail-fast sibling, and the same combinator cancels it again — those keep
DEC-024 exactly. Under `durableSpawn` nobody cancels it a second time, so
suspending hung the resumed run forever. `runDurableChild` now takes an
explicit `CancelledChildPolicy`, fixed at each combinator's call site and
never chosen by a caller. Resuming uses a new internal
`ReplayIndex.reopen()`, which forgets one coroutine's retained Close while
keeping its yields — so the child continues its own history rather than
restarting, and the divergence guard stops reading the remaining effects as
a coroutine continuing past its own close. Neither it nor `disableReplay` is
exported.
DEC-039 records the policy and marks DEC-024's invariant as superseded in
part: it assumed every cancelled child belongs to race or all.
The grid uses the repaired primitive: the whole grid is one durable child,
each pane is its own durable child allocated in authored ordinal order, and
each pane task is observed outside its child — so a replayed pane's retained
outcome publishes its status and satisfies the readiness barrier without
entering a body, a shell, or a launcher.
Evidence: 9 rows in `packages/durable-streams/tests/durable-spawn.test.ts`
(lifetime, completed replay, interrupted resume, retained-history
continuation, and both combinators keeping their own policy); 30 rows in
`packages/core/tests/terminal-grid.test.ts`. durable-streams 32, core 349,
runtime 15.

@github-actionsgithub-actionsBot 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 15 redundant comments. Inline suggestions to remove them below.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

return (function* (): Operation<Task<RetainedPaneOutcome>> {
const durable = yield* DurableContext.get();
if (durable === undefined) {
// No journal behind this run: an ordinary spawned child.

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
// No journal behind this run: an ordinary spawned child.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

Two decisions exposed while implementing #730, and no implementation.
**DEC-040 — a cancelled child records why.** DEC-039's `"resume"` fired on
every retained `Close(cancelled)` under an incomplete parent, which revives
work a caller deliberately halted: the record of a deliberate `task.halt()`
and the record of an interrupted run are the same event. The cancelled close
now carries `cancellation: "caller"` or `"unwound"`, written by whichever
path cancelled the child, and `"resume"` continues only `"unwound"`. A
deliberate stop suspends, which is DEC-024's reproduction argument applied
to a caller instead of a combinator; a legacy record with no reason reads as
`"caller"`, because refusing to revive is the safe direction. The reason is
retained evidence, not authority: nothing outside `runDurableChild` reads
it, and no caller chooses a policy.
Terminal grids need nothing wider. A grid halts its pane tasks at close, so
those retain `"caller"` — and the grid child completes, so a resumed run
short-circuits the region and never reaches them. The case that must resume,
an interrupted run, unwinds and retains `"unwound"`.
**TG17 narrows to the resolved layout.** A continuation executes the root the
journal retained; the supplied source is not read, compared or refused
(proved in #722). A grid's authored structure — pane count, order, form — is
therefore fixed for the life of a journal and cannot differ between runs, so
comparing it compares a value with itself, which is why the refusal never
fired. What a fixed retained document still resolves differently is
`columns` and each `title`, through prop-borne values, since props are not
restored. Those refuse before the lease and before provider contact.
Authored-structure change is a root-definition compatibility question, not a
grid one. Root-definition authority is preserved rather than overridden by a
pre-replay comparison against the current file, and the versioned root
boundary that would refuse a changed source stays open work.
**DEC-040.** A cancelled Close now records why: `cancellation: "caller"`
when the owner halts the task `durableSpawn` returned, `"unwound"` for
anything involuntary. `durableSpawn` resumes only `"unwound"`; a deliberate
stop suspends until the caller's deterministic control flow halts it again,
and a record with no reason reads as `"caller"` so nothing legacy is
revived. `durableAll` and `durableRace` keep DEC-024 whatever the reason
says.
The halt is intercepted without changing the public `Task` surface: the
returned task carries every member the real one defines, copied with its
prototype, and only `halt` is replaced. A proxy cannot do this — a task's
members are read-only and non-configurable, so a `get` trap is required to
hand back exactly what the target holds.
The reason had to survive three boundaries that were dropping it: the
protocol parser, the observable copy, and — the one that actually mattered —
`detachResult`, which froze every cancellation down to `{ status }`.
**TG15.** The harness's `attached` and `pastGrid` signals are now separate,
and a run that expects its grid to complete waits for the sibling *after*
the grid before halting the root at `<Hold />`. That is what leaves a
completed grid child under an incomplete root, which is the only state in
which a completed region can be observed replaying at all. Both a successful
grid and a contained failed one replay their exact retained result with no
provider, pane content, shell or launcher work, and each row asserts the
grid child genuinely recorded a terminal close. No timeouts.
**TG17.** Prop-borne `columns` and `title` change independently against one
fixed retained document — the only things a fixed retained root can still
resolve differently — and each refuses with zero provider observation. For
supplied-file changes to pane count, order and form, the continuation opens
the retained structure rather than the file's, asserted request-for-request.
The retained record carries every authored pane's ordinal, title, form and
derived position.
`readLayout()` parses totally: the layout object and every pane field, with
missing, extra, mistyped, out-of-position and self-inconsistent records all
refused rather than half-read.
Evidence: durable-spawn 14 rows, terminal-grid 36 rows, structural 13,
provider 10. Packages: durable-streams 33, core 349, runtime 15,
workflow 172.
#730)
**The harness cannot pass a hung replay any more.** `runInterrupted()` had a
1500ms timer racing its signals, so a replay that hung returned a
DocumentRun that looked finished; it also slept a fixed 5ms to let records
land. Both are gone. It now waits only on events the run produced:
`attached`, `pastGrid`, and a new `panesSettled` for the rows that read pane
records — a pane's status is published only after its durable child returned,
so counting settled panes is also counting durable pane closes. A replay
that hangs now reaches none of them and hangs the row.
**TG15's failed case is a real contained failure.** A pane that fails before
attachment fails the whole region, so the old document could not both fail
and continue. The failing pane is now a shell that starts, waits for
attachment, and only then exits badly — contained as that pane's status,
with the grid settling as failed and the document carrying on. Both runs
capture the printed errors, and the row asserts the replayed run produced
the same ones, reached `PAST_THE_GRID`, and did no provider, pane, shell or
launcher work.
**DEC-040 gets boundary tests where the evidence actually travels.**
`parse.test.ts` round-trips both reasons to the same bytes, keeps a legacy
absence absent, and refuses an unrecognised reason at `$.result.cancellation`.
`retained.test.ts` proves retention and `consumable()` carry both reasons,
leave a legacy absence absent, drop an unrecognised one to the safe default,
and that the reason reaches the replay index. The DEC-040 rows in
`durable-spawn.test.ts` no longer coordinate by delay: a child says when it
is running, and the caller says when it has halted.
**Malformed retained layouts** are covered by replaying a real journal with
only its layout entry replaced — a missing member, an extra one, a mistyped
one, a pane out of position, and a record that disagrees with itself. Each
refuses with zero provider observation.
The `durableSpawn` doc comment no longer says every retained cancellation is
an interrupted run.
The DEC-040 block still slept where it meant to synchronise — my previous
replacements silently failed to match after the file was reformatted, so
none of them landed. The block is rewritten rather than patched.
Every row now waits on something the run reported. A shared `living()` child
resolves a `started` signal and then suspends, so each row halts or unwinds a
child that is provably live rather than one a delay happened to reach. The
caller resolves `halted` after performing its deliberate halt, so a run is
interrupted only once both facts — the deliberate stop and the interruption —
are in the journal.
Non-revival is established by control flow rather than by waiting: the
resumed run reaches its own `task.halt()` and says so, and a revived child
would have recorded its mark before the caller could get there. The
legacy-absence row signals once the child has been asked for and the request
returned. No new timeout, and `sleep` stays imported because the lifetime
rows above still use it deliberately.
`retained.test.ts` drops the cast and the row it supported: rejecting an
unrecognised reason is the parser's, proved there, and retention proves only
that `"caller"`, `"unwound"` and a legacy absence survive.

@github-actionsgithub-actionsBot 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 11 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

// neither can begin while the other holds it.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

// grid covers it up.
yield* flushOutput();

// Routed, and the answer thrown away.

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
// Routed, and the answer thrown away.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.


const grid = createTerminalGridClaims(request);
// Nothing new is admitted once teardown begins, so a pane that was about to
// start an interactive child is refused rather than racing the close.

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
// start an interactive child is refused rather than racing the close.

// to schedule it in. Each task is observed *outside* its child: a replayed
// completed pane returns its retained outcome without entering a body, a
// shell, or a launcher, and that outcome is what publishes its status and
// satisfies the readiness barrier.

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
// satisfies the readiness barrier.

…730)
**`Symbol.asyncDispose` bypassed the deliberate-stop evidence.** The task
`durableSpawn` returns copied it from the original unchanged, so
`await using` — or an explicit `task[Symbol.asyncDispose]()` — recorded
`cancellation: "unwound"` and the next run revived the child. `halt()` and
the async dispose are the same decision spelled two ways, and both are now
observed. Awaiting a task is not a stop and is left exactly as it was. A
regression disposes a live task, asserts the retained reason is `"caller"`,
resumes the journal, and proves the body is not entered again.
**Reader close no longer halts panes.** It asks them to stop: a pane races
its work against a close signal, settles as `closed`, and records that
outcome as its own. Nothing on the ordinary close path is a caller-cancelled
child any more, so a resumed run restores a pane the reader closed rather
than finding a cancelled child it must either re-enter or wait on forever.
Statuses are published before anything is awaited, so a pane with slow
finalizers cannot delay the outcome the grid already knows.
**§6.21 now agrees with architecture.md and TG17.** Partial replay compares
the resolved layout — columns and titles. Pane count, order and form come
from the retained root and cannot diverge within a continuation, so a
changed supplied file is ignored in favour of the retained structure;
refusing a changed authored structure is a root-definition boundary this
specification does not yet define.
DEC-040 is unchanged and nothing deliberately stopped is revived.

@github-actionsgithub-actionsBot 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 18 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

*destroy() {
// Destroying twice would make the record say a composite was taken down
// more times than it was built, which is exactly the ordering claim a
// suite reads this log 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
// suite reads this log for.

@github-actionsgithub-actionsBot 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 20 redundant comments. Inline suggestions to remove them below.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

},
ready() {
// Idempotent by construction: readiness is a fact about the pane, and a
// provider that reports the same spawn twice has not started two panes.

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 that reports the same spawn twice has not started two panes.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

const cancellation = members.get("cancellation");
if (cancellation === undefined) {
// A record written before this evidence existed. DEC-040 reads the
// absence as a deliberate stop, so nothing it left behind is revived.

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
// absence as a deliberate stop, so nothing it left behind is revived.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

*destroy() {
// Destroying twice would make the record say a composite was taken down
// more times than it was built, which is exactly the ordering claim a
// suite reads this log 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
// suite reads this log for.

@taras
tarasforce-pushed the agent/issue-730-terminal-execution branch from 8f85400 to eb92602CompareSeptember 2, 2026 22:38

@github-actionsgithub-actionsBot 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 9 redundant comments. Inline suggestions to remove them below.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

}
for (const [index] of work.entries()) {
// Awaited, not halted. Each pane settles on the close signal and records
// the outcome it reached, which is what a resumed run reads.

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 outcome it reached, which is what a resumed run reads.

// the reader leaves, this settles as `closed` straight away and the work
// comes down in the enclosing scope's own teardown — so a pane whose
// finalizers are slow cannot hold up the outcome the grid already knows,
// and the record a resumed run reads is written either way.

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
// and the record a resumed run reads is written either way.

return (function* (): Operation<Task<RetainedPaneOutcome>> {
const durable = yield* DurableContext.get();
if (durable === undefined) {
// No journal behind this run: an ordinary spawned child.

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
// No journal behind this run: an ordinary spawned child.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

Implements the amendment at 1833870 without revising it.
**The live handshake.** `composite.closed()` settling now only *proposes* the
boundary. The grid's durable child publishes that proposal and waits; the
owner awaiting the child acknowledges it; and only then does the grid seal
admission and ask its panes to close. The handshake is one live rendezvous —
no provider identity, nothing journaled.
**Committing an outcome before the scope finishes unwinding.** A durable
child can now declare its terminal value, and `runDurableChild` records that
value if the child never reaches a normal ending. That is the piece the
contract needs: the grid commits its retained record as the boundary is
crossed, and each pane live at that moment commits `closed`, so a
cancellation arriving while pane and provider finalizers are still running
records what close decided rather than a cancellation. Committing is live
state; it reaches the journal only as the ordinary `Close`. A child that
returns or throws normally overrides it, and a child that never committed
still records the cancellation it actually reached — DEC-040 untouched.
Cancellation stays deferred because Effection completes a child's teardown —
pane finalizers, provider destroy, terminal restoration, lease release, the
`Close` append and the task's settlement — before the halt reaches the owner.
**Pane work stays inside its ordinal-derived durable child.** Reader close
asks the pane to close; it never halts the pane's durable task. The pane
commits `closed`, stops its live nested work through its own scope, and
settles only once that work and its finalizers have settled.
No durable closing marker was added, and completed replay is unchanged.

@github-actionsgithub-actionsBot 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 11 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

// neither can begin while the other holds it.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

// grid covers it up.
yield* flushOutput();

// Routed, and the answer thrown away.

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
// Routed, and the answer thrown away.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.


const grid = createTerminalGridClaims(request);
// Nothing new is admitted once teardown begins, so a pane that was about to
// start an interactive child is refused rather than racing the close.

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
// start an interactive child is refused rather than racing the close.

Implements architecture 1833870 at the owner boundary. The grid's durable
child now runs in a scope of its own — a child of the owner's, so it inherits
every context the document runs under, and its own so that tearing the owner
down does not reach it first. A finalizer registered after that scope exists
runs before it is destroyed, and that is the cancellation-deferred await: once
the owner has acknowledged the provider's close proposal, the grid and its panes
finish teardown and append their ordinary completed Close records, and only then
does the cancellation carry on to the parent.
Removes the exported CommitOutcome/durableSpawn(commit) API. Cancellation is
never turned into success inside runDurableChild; durableSpawnIn only says where
a child lives, and grants nothing a caller does not already have.
TG19 proves the ordering with signals alone: a live pane arms a blocking
finalizer, the reader leaves, the finalizer is entered and held, cancellation
begins, the finalizer is released, and the run ends with the composite destroyed,
a completed grid Close retained, the live pane retained as closed — and the
sibling after the grid never reached. The continuation then replays past it with
no provider, no pane body and no finalizer re-entered.
TG6 isolates paired-pane sequencing on its own: the reader leaves only once the
pane's second component has run.
The production lifecycle is unchanged. TG19 now reads counters and journal
records rather than a log's shape.
The controlled composite keeps live resource counters — composites prepared,
composites attached, shells started — each raised when it takes something and
lowered when it gives it back, however it left. TG19 reads them once while a
pane finalizer is blocked, so it knows they went up, and again when the
cancellation has completed, so it knows they came back down.
The harness now says when a blocked finalizer *leaves*, not only when it is
entered: a finalizer that was entered and then cancelled reaches the first hook
and never the second. And after every interrupted run it takes the foreground
lease and gives it back twice — the first proves the grid returned it, the
second proves the harness did.
TG19 adds: one grid Close(ok) retaining close: "reader"; two pane Closes, both
completed, with no cancellation recorded at either level; the finalizer entered
and left exactly once; destroy:0 exactly once. The first-attempt claim that no
following sibling ran and the replay tripwires are unchanged.
Every one of these was broken on purpose and re-run: dropping any of the three
counter releases, the deferral, the finalizer-exit hook, or double-logging
destroy fails TG19, and a second holder of the foreground lease is refused.
Sign up for freeto 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

@taras
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

✨ Execute concurrent terminal panes through a replaceable provider (#730) - #738

Open
taras wants to merge 15 commits into
agent/issue-729-terminal-gridfrom
agent/issue-730-terminal-execution
Open

✨ Execute concurrent terminal panes through a replaceable provider (#730)#738
taras wants to merge 15 commits into
agent/issue-729-terminal-gridfrom
agent/issue-730-terminal-execution

Conversation

@taras

@tarastaras commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes#730. Second implementation Story under Quest #717, stacked on #733.

Base is agent/issue-729-terminal-grid, not main, as the Story's verification stack directs. Branched from 97be06321cbdf08d84ef53dbefb88407f54326fe, the reviewed head of #733.

Why

#729 froze the language: an author can write a terminal grid, and every runtime can validate one. Nothing could run one. This Story makes a grid execute, through a boundary a host replaces — so the document keeps one lifecycle contract whether the presentation is tmux, a controlled test surface, or something native later.

What changes

Before: a valid <Terminal.Grid> derived its layout and refused, because nothing could present it.

After: it runs. Core takes the run's one foreground-terminal lease, flushes root output, prepares the composite while it stays hidden, starts every pane concurrently, and attaches only once every pane has actually started.

<Terminal.Grid columns={2}>
<Terminaltitle="Agent">…</Terminal>
<Terminaltitle="Shell" />
</Terminal.Grid>

How it works

lease → flush → prepare (hidden) → panes start concurrently
→ readiness barrier → attach → panes settle independently
→ reader closes → teardown → lease released

packages/runtime/terminal.ts is the replaceable seam. The request is provider-neutral — columns, rows, and the authored panes with their derived positions — and names no terminal, socket, process or window. Middleware may observe, narrow, refuse, wrap or delegate. Presentation never decides an outcome: update() receives states core has already settled on, and its return value is ignored.

packages/core/src/terminal/authority.ts mints one-use pane claims for one request's ordinals. A claim admits one interactive operation at a time on its pane and holds that pane's readiness latch. Two claims do not contend, which is what lets panes stay interactive together.

packages/core/src/terminal/pane.ts is the seam anything interactive inside a pane reaches, so it runs as that pane's owner instead of competing for the root lease. Absence means "not in a pane".

packages/core/src/terminal/grid.ts owns the lifecycle. The lease and the composite are both scope-owned, so success, failure and cancellation all release the terminal and destroy exactly the composite that was prepared — there is no path that skips teardown.

Review guide

Start with:packages/core/tests/terminal-grid.test.ts

Then review:

  1. packages/runtime/terminal.ts — the boundary and what a handler may do.
  2. packages/core/src/terminal/authority.ts — claims, contention, the readiness latch.
  3. packages/core/src/terminal/grid.ts — the ordering, and where teardown is registered.
  4. packages/core/src/expand.tspaneWork(), which is where a pane's isolation is established.

Look carefully at:

  • The order in runTerminalGrid(). ensure(() => composite.destroy()) is registered before any pane starts, so a composite that was prepared is owed a destroy even if the next line fails.
  • The attached flag. Before the barrier a pane failure fails the whole grid closed; after it, the failure is that pane's status and its siblings keep running.
  • paneWork()'s paired branch: ActiveLoop.set(undefined), a derived env, containedLedger(), and undefined for the return body are the four things that make a pane a scope rather than a region.

What must stay true

  • Nothing is shown before every pane has started — enforced by racing the readiness barrier against startup failure, checked by the TG9 ordering row, which was verified by deleting the barrier: it fails without it.
  • A prepared composite is always destroyed exactly once — enforced by scope-owned ensure, checked by TG12 and by the controlled composite refusing a second destroy.
  • Presentation decides nothing — enforced by update() returning void and claims never leaving core, checked by the middleware rows in the provider suite.
  • A pane's later bindings stay in that pane — enforced by a derived environment, checked by the TG6 document row asserting the sibling and the document after the grid still see the binding unresolved.

How to verify it

deno task test packages/core/tests/terminal-grid.test.ts
deno task test packages/runtime/tests/terminal-provider.test.ts
deno task test packages/core/tests/terminal-grid-structure.test.ts
  • TG8 proves one claim admits one interactive operation at a time and two claims do not contend; it fails if a pane admitted twice, or if two panes serialized.
  • TG9 proves nothing attaches until every pane reports a spawn, and that a pane which settles without one fails startup; it fails if a grid attached early or presented a pane that never started.
  • TG10 proves a pane can fail after attach while a sibling is provably still live, and the grid reports the first failed authored ordinal.
  • TG12/TG13 prove close and parent cancellation both destroy the composite exactly once, and that a pane cancelled by the close is closed rather than failed.
  • TG6/TG7 prove pane scope and output routing through the real execute() path.
  • The provider suite proves the boundary refuses with nothing installed, and that middleware can observe, narrow, refuse and wrap without being able to authorize.

Whole Deno core suite: 350 passed. Runtime suite: 14 passed.

Scope

Included

  • The provider boundary, the terminal authority and pane claims, the readiness latch, the pane seam, and the grid lifecycle.
  • Pane scope isolation, pane output routing, concurrent start, atomic attach, independent settlement, close and cancellation teardown.

Not included — this Story is not finished

These acceptance points landed in later commits on this branch, and the section
that once said durability was absent is no longer true:

  • Durability and replay (TG15–TG17) are implemented. The grid is one durable
    child and each pane is its own durable child allocated in authored ordinal
    order. A completed region replays its exact retained result — successful and
    contained-failed alike — contacting no provider and running no pane content,
    shell or launcher. An interrupted region rebuilds a fresh composite. The
    layout is recorded in the parent coroutine before the lease and before any
    provider is contacted, and a malformed retained layout refuses there.
  • TG17 is scoped to what a continuation can actually change. A continuation
    executes the retained root, so pane count, order and form cannot differ and
    are proved retained-and-honoured rather than refused; columns and each
    title reach the grid through props, which are not restored, and each refuses
    independently with zero provider observation.
  • durableSpawn was repaired to make any of this possible: its task now
    outlives the call, and a cancelled child records why it stopped (DEC-040) so
    a deliberately halted region is never revived while an interrupted one
    resumes.

What remains outside this PR:

  • TG14's bounded teardown proof belongs to the tmux provider Story; the
    controlled provider cannot exercise it.
  • TG5 and Agent-session contention in TG11 belong to the native-launch
    Story, as the issue states.
  • One known gap: a run interrupted while reader-close teardown is awaiting
    a pane whose own finalizer is slow
    leaves that pane recorded as unwound
    rather than closed, so a resumed run re-enters it. Reader close is now
    cooperative — panes are asked to stop and record closed themselves rather
    than being halted — which removes caller-cancelled panes from the ordinary
    close path, but the blocked-finalizer overlap is not yet covered by a
    regression.

Intentionally unchanged

  • No tmux command, multiplexer, or real terminal anywhere in this change.

New abstractions

  • TerminalProvider / TerminalComposite exist because a grid's presentation has to be replaceable; the controlled provider and the future tmux adapter are the two concrete uses.

  • TerminalPaneClaim exists because pane terminal ownership must be unforgeable and per-ordinal; consumed by the grid and by the pane seam.

  • PaneTerminal exists because interactive work inside a pane must not compete for the root lease; consumed by the suite's controlled interactive child now and by <Session.Launch> in Launch native Agent sessions in independent terminal panes #731.

  • Each new abstraction has multiple concrete uses or a clear justification.

  • No speculative functionality is included.

Risks and limitations

  • Incomplete Story, stated above. Durability and replay are absent.
  • Five rows from ✨ Describe terminal grids as executable document structure (#729) #733 moved into this Story's suite. The move was authorized explicitly rather than assumed, and every claim they made is still asserted — against the provider request, which is stronger evidence than reading a layout off a refusal's cause.
  • A stray <Break> inside a pane fails the pane rather than printing as it would at the root. That is consistent with the pane-settlement contract, but it is a behavioural difference worth a reviewer's eye.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

The replaceable seam a terminal grid executes through, before any of the
execution that uses it.
`packages/runtime/terminal.ts` is the contextual provider: `prepare()`
builds the whole composite while it stays hidden, `attach()` shows it once
every pane is ready, and `destroy()` gives the root terminal back. The
request is provider-neutral — columns, rows, and the authored panes with
their derived positions — and names no terminal, socket, process or window.
Middleware may observe, narrow, refuse, wrap or delegate; presentation
never decides an outcome, so `update()` receives states core has already
settled on.
`packages/core/src/terminal/authority.ts` mints one-use pane claims for one
request's ordinals. A claim admits one interactive operation at a time on
its pane and holds that pane's readiness latch. Two claims do not contend,
which is what lets panes stay interactive together.
`packages/core/src/terminal/pane.ts` is the seam interactive work inside a
pane reaches for, so it runs as that pane's owner instead of competing for
the root foreground lease. Absence means "not in a pane".
Evidence: `packages/runtime/tests/terminal-provider.test.ts`, 11 rows.
`runTerminalGrid()` owns the lifecycle the reader sees: it takes the run's
one foreground-terminal lease, flushes root output, prepares the composite
while it stays hidden, starts every pane concurrently, and attaches only
once every pane has reported a spawn through its claim.
Ordering is the contract. The lease and the composite are both scope-owned,
so success, failure and cancellation all release the terminal and destroy
exactly the composite that was prepared — there is no path that skips
teardown. A pane that settles without ever reporting a spawn fails startup
rather than being presented as a running pane. Before the barrier a pane
failure fails the whole grid closed; after it, the failure is that pane's
status and its siblings keep running. Close cancels a live pane as `closed`,
which is not a failed pane, and the grid fails with the first failed pane in
authored order.
`display()` and an `onUpdate` hook complete the provider surface: a pane's
rendered text goes to that pane, and a suite reacts to a state the grid
decided rather than waiting and hoping.
Evidence: `packages/core/tests/terminal-grid.test.ts` (15 rows) and
`packages/runtime/tests/terminal-provider.test.ts` (11 rows). The readiness
barrier row was verified by removing the barrier: it fails without it.
`<Terminal.Grid>` now executes. Each authored pane becomes a concurrent
child of the grid: a self-closing pane runs the host's default shell
through its claim, and a paired pane expands its own content in a scope of
its own.
A pane inherits the bindings, providers, configuration and working
directory visible where the grid was written, and keeps everything it
creates afterwards. Its `<Break>` has no loop to exit, its `<Return>` has
no enclosing value body to claim, and its checked failures settle the pane
rather than reaching the root or a sibling. A pane's rendered text is
displayed in that pane; the grid itself renders `""`, so the root output
holds what surrounds the grid and no pane display at all.
#729's five execution-dependent rows move here, where they assert the
layout against the request the provider actually receives rather than
reading it off a refusal's cause — the structural suite keeps the grammar,
placement and pure-layout rows it owns. Moving them was authorized rather
than assumed.
Evidence: 22 rows in `packages/core/tests/terminal-grid.test.ts` and 11 in
`packages/runtime/tests/terminal-provider.test.ts`; the whole Deno core
(350) and runtime (14) suites pass.
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown

PR #738: ✨ Execute concurrent terminal panes through a replaceable provider (#730)

26 files, +5399 / -226

Scope

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

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

🟡 26 files changed. Are all changes related?

🟡 New abstraction files: packages/core/src/terminal/provider-api.ts. Verify 3+ consumers.

Structural

Oxlint structural signals:

  • no-unnecessary-type-assertion ×11: packages/core/src/terminal/journal.ts, packages/durable-streams/retained.ts, packages/durable-streams/combinators.ts (+2)
  • no-unused-vars ×7: packages/core/src/expand.ts

Slop

  • packages/durable-streams/combinators.ts:168 (removed)

Oxlint slop signals:

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

Static Analysis

Oxlint: 43 diagnostics across 5 files (12 rules)
Density: 0.008 violations/added-line

no-unnecessary-type-assertion (11): packages/core/src/terminal/journal.ts, packages/durable-streams/retained.ts, packages/durable-streams/combinators.ts (+2)
no-unsafe-type-assertion (9): packages/durable-streams/combinators.ts, packages/durable-streams/retained.ts, packages/core/src/expand.ts
no-unused-vars (7): packages/core/src/expand.ts
no-base-to-string (4): packages/core/src/expand.ts
no-floating-promises (3): packages/core/src/terminal/grid.ts
no-inferrable-types (2): packages/core/src/expand.ts
unbound-method (2): packages/core/src/expand.ts
no-shadow (1): packages/core/src/expand.ts
no-useless-fallback-in-spread (1): packages/core/src/expand.ts
no-unnecessary-type-parameters (1): packages/durable-streams/retained.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.

`paneWork()` never read the grid element it was handed. Its caller has it,
and a pane's own diagnostics are positioned at the pane.

@github-actionsgithub-actionsBot 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 10 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

),
0,
// The pane's own ledger: a checked failure settles this pane and
// cannot reach the root or a sibling.

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
// cannot reach the root or a sibling.

// and a host with no terminal refuses here — before any pane has done work.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

Comment threadpackages/core/src/terminal/grid.ts Outdated
yield* pane.run(claim, composite);
if (!readiness.acknowledged) {
// Settled without ever starting: that is a startup failure even
// though the work itself raised nothing.

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
// though the work itself raised nothing.

attached = true;

// The composite stays visible after its panes settle. The reader leaving is
// what finishes the grid, not the last pane exiting.

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
// what finishes the grid, not the last pane exiting.

Comment threadpackages/runtime/terminal.ts Outdated
export const TerminalProvider: Api<TerminalProviderHandler> = createApi<TerminalProviderHandler>(
"runtime.terminalProvider",
{
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

Comment threadpackages/runtime/terminal.ts Outdated
}
log.events.push(`attach:${generation}`);
},
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

Comment threadpackages/runtime/terminal.ts Outdated
log.events.push(`state:${generation}:${ordinal}:${state}`);
options.onUpdate?.(ordinal, state);
},
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

…#730)
Restores the authority boundary on the `AgentProviders` handshake, and puts
each pane on its own durable child coroutine.
**The boundary.** `TerminalGrids` is routing and only routing: `open()`
answers `unknown` and core throws the answer away, so middleware may
observe, narrow, refuse, wrap or delegate but can never authorize. The
capability that takes the leases, mints pane claims and settles a grid is a
non-contextual authority delivered straight to the registered provider
through a one-use install handshake. Core mints one identity-bearing request
per expansion; presenting a copy, a rebuilt lookalike, a changed request, an
already-presented one, or one from a superseded installation generation
authorizes nothing, and a handler that answers without presenting settles
nothing.
**Durable children.** Each pane is a durable child of the grid, allocated in
authored order, so a pane's identity follows its ordinal rather than the
order the runtime scheduled it in. The layout is recorded in the parent
coroutine before the lease and before any provider is contacted.
**Ordering.** A pane that settles before attach keeps the status it settled
to instead of being overwritten with `running`, and simultaneous startup
failures are selected by authored ordinal rather than by whichever rejected
first. Each pane also expands under a counter of its own, so two concurrent
panes cannot take block identities that depend on which ran first.
`durableSpawn` could not be used: the task it returns is spawned inside the
ephemeral effect's own scope, which closes as the effect resolves, so
awaiting it throws `halted`. It has no call sites or tests upstream.
`durableAll` is the exercised primitive and is what the panes and the grid
child use.
Evidence: 30 rows in `packages/core/tests/terminal-grid.test.ts` and 10 in
`packages/runtime/tests/terminal-provider.test.ts`; core 349, runtime 15.

@github-actionsgithub-actionsBot 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 9 redundant comments. Inline suggestions to remove them below.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.

attached = true;

// The composite stays visible after its panes settle. The reader leaving is
// what finishes the grid, not the last pane exiting.

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
// what finishes the grid, not the last pane exiting.

yield* pane.run(claim, composite);
if (!readiness.acknowledged) {
// Settled without ever starting: a startup failure even though the work
// itself raised nothing.

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
// itself raised nothing.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

`durableSpawn` returned a task spawned inside the `ephemeral` effect's own
scope, and that scope closed as the effect resolved — so every
`yield* task` threw `halted`. It had no call sites and no tests. It now
starts the child in the routine's own scope, so the task outlives the call
and can be awaited or halted by whoever asked for it.
A retained `Close(cancelled)` meant one thing to the code and two things in
practice. Under `durableRace` and `durableAll` it is a race loser or a
fail-fast sibling, and the same combinator cancels it again — those keep
DEC-024 exactly. Under `durableSpawn` nobody cancels it a second time, so
suspending hung the resumed run forever. `runDurableChild` now takes an
explicit `CancelledChildPolicy`, fixed at each combinator's call site and
never chosen by a caller. Resuming uses a new internal
`ReplayIndex.reopen()`, which forgets one coroutine's retained Close while
keeping its yields — so the child continues its own history rather than
restarting, and the divergence guard stops reading the remaining effects as
a coroutine continuing past its own close. Neither it nor `disableReplay` is
exported.
DEC-039 records the policy and marks DEC-024's invariant as superseded in
part: it assumed every cancelled child belongs to race or all.
The grid uses the repaired primitive: the whole grid is one durable child,
each pane is its own durable child allocated in authored ordinal order, and
each pane task is observed outside its child — so a replayed pane's retained
outcome publishes its status and satisfies the readiness barrier without
entering a body, a shell, or a launcher.
Evidence: 9 rows in `packages/durable-streams/tests/durable-spawn.test.ts`
(lifetime, completed replay, interrupted resume, retained-history
continuation, and both combinators keeping their own policy); 30 rows in
`packages/core/tests/terminal-grid.test.ts`. durable-streams 32, core 349,
runtime 15.

@github-actionsgithub-actionsBot 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 15 redundant comments. Inline suggestions to remove them below.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

return (function* (): Operation<Task<RetainedPaneOutcome>> {
const durable = yield* DurableContext.get();
if (durable === undefined) {
// No journal behind this run: an ordinary spawned child.

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
// No journal behind this run: an ordinary spawned child.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

Two decisions exposed while implementing #730, and no implementation.
**DEC-040 — a cancelled child records why.** DEC-039's `"resume"` fired on
every retained `Close(cancelled)` under an incomplete parent, which revives
work a caller deliberately halted: the record of a deliberate `task.halt()`
and the record of an interrupted run are the same event. The cancelled close
now carries `cancellation: "caller"` or `"unwound"`, written by whichever
path cancelled the child, and `"resume"` continues only `"unwound"`. A
deliberate stop suspends, which is DEC-024's reproduction argument applied
to a caller instead of a combinator; a legacy record with no reason reads as
`"caller"`, because refusing to revive is the safe direction. The reason is
retained evidence, not authority: nothing outside `runDurableChild` reads
it, and no caller chooses a policy.
Terminal grids need nothing wider. A grid halts its pane tasks at close, so
those retain `"caller"` — and the grid child completes, so a resumed run
short-circuits the region and never reaches them. The case that must resume,
an interrupted run, unwinds and retains `"unwound"`.
**TG17 narrows to the resolved layout.** A continuation executes the root the
journal retained; the supplied source is not read, compared or refused
(proved in #722). A grid's authored structure — pane count, order, form — is
therefore fixed for the life of a journal and cannot differ between runs, so
comparing it compares a value with itself, which is why the refusal never
fired. What a fixed retained document still resolves differently is
`columns` and each `title`, through prop-borne values, since props are not
restored. Those refuse before the lease and before provider contact.
Authored-structure change is a root-definition compatibility question, not a
grid one. Root-definition authority is preserved rather than overridden by a
pre-replay comparison against the current file, and the versioned root
boundary that would refuse a changed source stays open work.
**DEC-040.** A cancelled Close now records why: `cancellation: "caller"`
when the owner halts the task `durableSpawn` returned, `"unwound"` for
anything involuntary. `durableSpawn` resumes only `"unwound"`; a deliberate
stop suspends until the caller's deterministic control flow halts it again,
and a record with no reason reads as `"caller"` so nothing legacy is
revived. `durableAll` and `durableRace` keep DEC-024 whatever the reason
says.
The halt is intercepted without changing the public `Task` surface: the
returned task carries every member the real one defines, copied with its
prototype, and only `halt` is replaced. A proxy cannot do this — a task's
members are read-only and non-configurable, so a `get` trap is required to
hand back exactly what the target holds.
The reason had to survive three boundaries that were dropping it: the
protocol parser, the observable copy, and — the one that actually mattered —
`detachResult`, which froze every cancellation down to `{ status }`.
**TG15.** The harness's `attached` and `pastGrid` signals are now separate,
and a run that expects its grid to complete waits for the sibling *after*
the grid before halting the root at `<Hold />`. That is what leaves a
completed grid child under an incomplete root, which is the only state in
which a completed region can be observed replaying at all. Both a successful
grid and a contained failed one replay their exact retained result with no
provider, pane content, shell or launcher work, and each row asserts the
grid child genuinely recorded a terminal close. No timeouts.
**TG17.** Prop-borne `columns` and `title` change independently against one
fixed retained document — the only things a fixed retained root can still
resolve differently — and each refuses with zero provider observation. For
supplied-file changes to pane count, order and form, the continuation opens
the retained structure rather than the file's, asserted request-for-request.
The retained record carries every authored pane's ordinal, title, form and
derived position.
`readLayout()` parses totally: the layout object and every pane field, with
missing, extra, mistyped, out-of-position and self-inconsistent records all
refused rather than half-read.
Evidence: durable-spawn 14 rows, terminal-grid 36 rows, structural 13,
provider 10. Packages: durable-streams 33, core 349, runtime 15,
workflow 172.
#730)
**The harness cannot pass a hung replay any more.** `runInterrupted()` had a
1500ms timer racing its signals, so a replay that hung returned a
DocumentRun that looked finished; it also slept a fixed 5ms to let records
land. Both are gone. It now waits only on events the run produced:
`attached`, `pastGrid`, and a new `panesSettled` for the rows that read pane
records — a pane's status is published only after its durable child returned,
so counting settled panes is also counting durable pane closes. A replay
that hangs now reaches none of them and hangs the row.
**TG15's failed case is a real contained failure.** A pane that fails before
attachment fails the whole region, so the old document could not both fail
and continue. The failing pane is now a shell that starts, waits for
attachment, and only then exits badly — contained as that pane's status,
with the grid settling as failed and the document carrying on. Both runs
capture the printed errors, and the row asserts the replayed run produced
the same ones, reached `PAST_THE_GRID`, and did no provider, pane, shell or
launcher work.
**DEC-040 gets boundary tests where the evidence actually travels.**
`parse.test.ts` round-trips both reasons to the same bytes, keeps a legacy
absence absent, and refuses an unrecognised reason at `$.result.cancellation`.
`retained.test.ts` proves retention and `consumable()` carry both reasons,
leave a legacy absence absent, drop an unrecognised one to the safe default,
and that the reason reaches the replay index. The DEC-040 rows in
`durable-spawn.test.ts` no longer coordinate by delay: a child says when it
is running, and the caller says when it has halted.
**Malformed retained layouts** are covered by replaying a real journal with
only its layout entry replaced — a missing member, an extra one, a mistyped
one, a pane out of position, and a record that disagrees with itself. Each
refuses with zero provider observation.
The `durableSpawn` doc comment no longer says every retained cancellation is
an interrupted run.
The DEC-040 block still slept where it meant to synchronise — my previous
replacements silently failed to match after the file was reformatted, so
none of them landed. The block is rewritten rather than patched.
Every row now waits on something the run reported. A shared `living()` child
resolves a `started` signal and then suspends, so each row halts or unwinds a
child that is provably live rather than one a delay happened to reach. The
caller resolves `halted` after performing its deliberate halt, so a run is
interrupted only once both facts — the deliberate stop and the interruption —
are in the journal.
Non-revival is established by control flow rather than by waiting: the
resumed run reaches its own `task.halt()` and says so, and a revived child
would have recorded its mark before the caller could get there. The
legacy-absence row signals once the child has been asked for and the request
returned. No new timeout, and `sleep` stays imported because the lifetime
rows above still use it deliberately.
`retained.test.ts` drops the cast and the row it supported: rejecting an
unrecognised reason is the parser's, proved there, and retention proves only
that `"caller"`, `"unwound"` and a legacy absence survive.

@github-actionsgithub-actionsBot 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 11 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

// neither can begin while the other holds it.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

// grid covers it up.
yield* flushOutput();

// Routed, and the answer thrown away.

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
// Routed, and the answer thrown away.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.


const grid = createTerminalGridClaims(request);
// Nothing new is admitted once teardown begins, so a pane that was about to
// start an interactive child is refused rather than racing the close.

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
// start an interactive child is refused rather than racing the close.

// to schedule it in. Each task is observed *outside* its child: a replayed
// completed pane returns its retained outcome without entering a body, a
// shell, or a launcher, and that outcome is what publishes its status and
// satisfies the readiness barrier.

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
// satisfies the readiness barrier.

…730)
**`Symbol.asyncDispose` bypassed the deliberate-stop evidence.** The task
`durableSpawn` returns copied it from the original unchanged, so
`await using` — or an explicit `task[Symbol.asyncDispose]()` — recorded
`cancellation: "unwound"` and the next run revived the child. `halt()` and
the async dispose are the same decision spelled two ways, and both are now
observed. Awaiting a task is not a stop and is left exactly as it was. A
regression disposes a live task, asserts the retained reason is `"caller"`,
resumes the journal, and proves the body is not entered again.
**Reader close no longer halts panes.** It asks them to stop: a pane races
its work against a close signal, settles as `closed`, and records that
outcome as its own. Nothing on the ordinary close path is a caller-cancelled
child any more, so a resumed run restores a pane the reader closed rather
than finding a cancelled child it must either re-enter or wait on forever.
Statuses are published before anything is awaited, so a pane with slow
finalizers cannot delay the outcome the grid already knows.
**§6.21 now agrees with architecture.md and TG17.** Partial replay compares
the resolved layout — columns and titles. Pane count, order and form come
from the retained root and cannot diverge within a continuation, so a
changed supplied file is ignored in favour of the retained structure;
refusing a changed authored structure is a root-definition boundary this
specification does not yet define.
DEC-040 is unchanged and nothing deliberately stopped is revived.

@github-actionsgithub-actionsBot 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 18 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

*destroy() {
// Destroying twice would make the record say a composite was taken down
// more times than it was built, which is exactly the ordering claim a
// suite reads this log 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
// suite reads this log for.

@github-actionsgithub-actionsBot 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 20 redundant comments. Inline suggestions to remove them below.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

},
ready() {
// Idempotent by construction: readiness is a fact about the pane, and a
// provider that reports the same spawn twice has not started two panes.

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 that reports the same spawn twice has not started two panes.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

const cancellation = members.get("cancellation");
if (cancellation === undefined) {
// A record written before this evidence existed. DEC-040 reads the
// absence as a deliberate stop, so nothing it left behind is revived.

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
// absence as a deliberate stop, so nothing it left behind is revived.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

*destroy() {
// Destroying twice would make the record say a composite was taken down
// more times than it was built, which is exactly the ordering claim a
// suite reads this log 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
// suite reads this log for.

@taras
tarasforce-pushed the agent/issue-730-terminal-execution branch from 8f85400 to eb92602CompareSeptember 2, 2026 22:38

@github-actionsgithub-actionsBot 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 9 redundant comments. Inline suggestions to remove them below.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

}
for (const [index] of work.entries()) {
// Awaited, not halted. Each pane settles on the close signal and records
// the outcome it reached, which is what a resumed run reads.

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 outcome it reached, which is what a resumed run reads.

// the reader leaves, this settles as `closed` straight away and the work
// comes down in the enclosing scope's own teardown — so a pane whose
// finalizers are slow cannot hold up the outcome the grid already knows,
// and the record a resumed run reads is written either way.

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
// and the record a resumed run reads is written either way.

return (function* (): Operation<Task<RetainedPaneOutcome>> {
const durable = yield* DurableContext.get();
if (durable === undefined) {
// No journal behind this run: an ordinary spawned child.

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
// No journal behind this run: an ordinary spawned child.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

Implements the amendment at 1833870 without revising it.
**The live handshake.** `composite.closed()` settling now only *proposes* the
boundary. The grid's durable child publishes that proposal and waits; the
owner awaiting the child acknowledges it; and only then does the grid seal
admission and ask its panes to close. The handshake is one live rendezvous —
no provider identity, nothing journaled.
**Committing an outcome before the scope finishes unwinding.** A durable
child can now declare its terminal value, and `runDurableChild` records that
value if the child never reaches a normal ending. That is the piece the
contract needs: the grid commits its retained record as the boundary is
crossed, and each pane live at that moment commits `closed`, so a
cancellation arriving while pane and provider finalizers are still running
records what close decided rather than a cancellation. Committing is live
state; it reaches the journal only as the ordinary `Close`. A child that
returns or throws normally overrides it, and a child that never committed
still records the cancellation it actually reached — DEC-040 untouched.
Cancellation stays deferred because Effection completes a child's teardown —
pane finalizers, provider destroy, terminal restoration, lease release, the
`Close` append and the task's settlement — before the halt reaches the owner.
**Pane work stays inside its ordinal-derived durable child.** Reader close
asks the pane to close; it never halts the pane's durable task. The pane
commits `closed`, stops its live nested work through its own scope, and
settles only once that work and its finalizers have settled.
No durable closing marker was added, and completed replay is unchanged.

@github-actionsgithub-actionsBot 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 11 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

// neither can begin while the other holds it.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

// grid covers it up.
yield* flushOutput();

// Routed, and the answer thrown away.

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
// Routed, and the answer thrown away.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.


const grid = createTerminalGridClaims(request);
// Nothing new is admitted once teardown begins, so a pane that was about to
// start an interactive child is refused rather than racing the close.

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
// start an interactive child is refused rather than racing the close.

Implements architecture 1833870 at the owner boundary. The grid's durable
child now runs in a scope of its own — a child of the owner's, so it inherits
every context the document runs under, and its own so that tearing the owner
down does not reach it first. A finalizer registered after that scope exists
runs before it is destroyed, and that is the cancellation-deferred await: once
the owner has acknowledged the provider's close proposal, the grid and its panes
finish teardown and append their ordinary completed Close records, and only then
does the cancellation carry on to the parent.
Removes the exported CommitOutcome/durableSpawn(commit) API. Cancellation is
never turned into success inside runDurableChild; durableSpawnIn only says where
a child lives, and grants nothing a caller does not already have.
TG19 proves the ordering with signals alone: a live pane arms a blocking
finalizer, the reader leaves, the finalizer is entered and held, cancellation
begins, the finalizer is released, and the run ends with the composite destroyed,
a completed grid Close retained, the live pane retained as closed — and the
sibling after the grid never reached. The continuation then replays past it with
no provider, no pane body and no finalizer re-entered.
TG6 isolates paired-pane sequencing on its own: the reader leaves only once the
pane's second component has run.
The production lifecycle is unchanged. TG19 now reads counters and journal
records rather than a log's shape.
The controlled composite keeps live resource counters — composites prepared,
composites attached, shells started — each raised when it takes something and
lowered when it gives it back, however it left. TG19 reads them once while a
pane finalizer is blocked, so it knows they went up, and again when the
cancellation has completed, so it knows they came back down.
The harness now says when a blocked finalizer *leaves*, not only when it is
entered: a finalizer that was entered and then cancelled reaches the first hook
and never the second. And after every interrupted run it takes the foreground
lease and gives it back twice — the first proves the grid returned it, the
second proves the harness did.
TG19 adds: one grid Close(ok) retaining close: "reader"; two pane Closes, both
completed, with no cancellation recorded at either level; the finalizer entered
and left exactly once; destroy:0 exactly once. The first-attempt claim that no
following sibling ran and the replay tripwires are unchanged.
Every one of these was broken on purpose and re-run: dropping any of the three
counter releases, the deferral, the finalizer-exit hook, or double-logging
destroy fails TG19, and a second holder of the foreground lease is refused.
Sign up for freeto 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

@taras
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

✨ Execute concurrent terminal panes through a replaceable provider (#730) - #738

Open
taras wants to merge 15 commits into
agent/issue-729-terminal-gridfrom
agent/issue-730-terminal-execution
Open

✨ Execute concurrent terminal panes through a replaceable provider (#730)#738
taras wants to merge 15 commits into
agent/issue-729-terminal-gridfrom
agent/issue-730-terminal-execution

Conversation

@taras

@tarastaras commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes#730. Second implementation Story under Quest #717, stacked on #733.

Base is agent/issue-729-terminal-grid, not main, as the Story's verification stack directs. Branched from 97be06321cbdf08d84ef53dbefb88407f54326fe, the reviewed head of #733.

Why

#729 froze the language: an author can write a terminal grid, and every runtime can validate one. Nothing could run one. This Story makes a grid execute, through a boundary a host replaces — so the document keeps one lifecycle contract whether the presentation is tmux, a controlled test surface, or something native later.

What changes

Before: a valid <Terminal.Grid> derived its layout and refused, because nothing could present it.

After: it runs. Core takes the run's one foreground-terminal lease, flushes root output, prepares the composite while it stays hidden, starts every pane concurrently, and attaches only once every pane has actually started.

<Terminal.Grid columns={2}>
<Terminaltitle="Agent">…</Terminal>
<Terminaltitle="Shell" />
</Terminal.Grid>

How it works

lease → flush → prepare (hidden) → panes start concurrently
→ readiness barrier → attach → panes settle independently
→ reader closes → teardown → lease released

packages/runtime/terminal.ts is the replaceable seam. The request is provider-neutral — columns, rows, and the authored panes with their derived positions — and names no terminal, socket, process or window. Middleware may observe, narrow, refuse, wrap or delegate. Presentation never decides an outcome: update() receives states core has already settled on, and its return value is ignored.

packages/core/src/terminal/authority.ts mints one-use pane claims for one request's ordinals. A claim admits one interactive operation at a time on its pane and holds that pane's readiness latch. Two claims do not contend, which is what lets panes stay interactive together.

packages/core/src/terminal/pane.ts is the seam anything interactive inside a pane reaches, so it runs as that pane's owner instead of competing for the root lease. Absence means "not in a pane".

packages/core/src/terminal/grid.ts owns the lifecycle. The lease and the composite are both scope-owned, so success, failure and cancellation all release the terminal and destroy exactly the composite that was prepared — there is no path that skips teardown.

Review guide

Start with:packages/core/tests/terminal-grid.test.ts

Then review:

  1. packages/runtime/terminal.ts — the boundary and what a handler may do.
  2. packages/core/src/terminal/authority.ts — claims, contention, the readiness latch.
  3. packages/core/src/terminal/grid.ts — the ordering, and where teardown is registered.
  4. packages/core/src/expand.tspaneWork(), which is where a pane's isolation is established.

Look carefully at:

  • The order in runTerminalGrid(). ensure(() => composite.destroy()) is registered before any pane starts, so a composite that was prepared is owed a destroy even if the next line fails.
  • The attached flag. Before the barrier a pane failure fails the whole grid closed; after it, the failure is that pane's status and its siblings keep running.
  • paneWork()'s paired branch: ActiveLoop.set(undefined), a derived env, containedLedger(), and undefined for the return body are the four things that make a pane a scope rather than a region.

What must stay true

  • Nothing is shown before every pane has started — enforced by racing the readiness barrier against startup failure, checked by the TG9 ordering row, which was verified by deleting the barrier: it fails without it.
  • A prepared composite is always destroyed exactly once — enforced by scope-owned ensure, checked by TG12 and by the controlled composite refusing a second destroy.
  • Presentation decides nothing — enforced by update() returning void and claims never leaving core, checked by the middleware rows in the provider suite.
  • A pane's later bindings stay in that pane — enforced by a derived environment, checked by the TG6 document row asserting the sibling and the document after the grid still see the binding unresolved.

How to verify it

deno task test packages/core/tests/terminal-grid.test.ts
deno task test packages/runtime/tests/terminal-provider.test.ts
deno task test packages/core/tests/terminal-grid-structure.test.ts
  • TG8 proves one claim admits one interactive operation at a time and two claims do not contend; it fails if a pane admitted twice, or if two panes serialized.
  • TG9 proves nothing attaches until every pane reports a spawn, and that a pane which settles without one fails startup; it fails if a grid attached early or presented a pane that never started.
  • TG10 proves a pane can fail after attach while a sibling is provably still live, and the grid reports the first failed authored ordinal.
  • TG12/TG13 prove close and parent cancellation both destroy the composite exactly once, and that a pane cancelled by the close is closed rather than failed.
  • TG6/TG7 prove pane scope and output routing through the real execute() path.
  • The provider suite proves the boundary refuses with nothing installed, and that middleware can observe, narrow, refuse and wrap without being able to authorize.

Whole Deno core suite: 350 passed. Runtime suite: 14 passed.

Scope

Included

  • The provider boundary, the terminal authority and pane claims, the readiness latch, the pane seam, and the grid lifecycle.
  • Pane scope isolation, pane output routing, concurrent start, atomic attach, independent settlement, close and cancellation teardown.

Not included — this Story is not finished

These acceptance points landed in later commits on this branch, and the section
that once said durability was absent is no longer true:

  • Durability and replay (TG15–TG17) are implemented. The grid is one durable
    child and each pane is its own durable child allocated in authored ordinal
    order. A completed region replays its exact retained result — successful and
    contained-failed alike — contacting no provider and running no pane content,
    shell or launcher. An interrupted region rebuilds a fresh composite. The
    layout is recorded in the parent coroutine before the lease and before any
    provider is contacted, and a malformed retained layout refuses there.
  • TG17 is scoped to what a continuation can actually change. A continuation
    executes the retained root, so pane count, order and form cannot differ and
    are proved retained-and-honoured rather than refused; columns and each
    title reach the grid through props, which are not restored, and each refuses
    independently with zero provider observation.
  • durableSpawn was repaired to make any of this possible: its task now
    outlives the call, and a cancelled child records why it stopped (DEC-040) so
    a deliberately halted region is never revived while an interrupted one
    resumes.

What remains outside this PR:

  • TG14's bounded teardown proof belongs to the tmux provider Story; the
    controlled provider cannot exercise it.
  • TG5 and Agent-session contention in TG11 belong to the native-launch
    Story, as the issue states.
  • One known gap: a run interrupted while reader-close teardown is awaiting
    a pane whose own finalizer is slow
    leaves that pane recorded as unwound
    rather than closed, so a resumed run re-enters it. Reader close is now
    cooperative — panes are asked to stop and record closed themselves rather
    than being halted — which removes caller-cancelled panes from the ordinary
    close path, but the blocked-finalizer overlap is not yet covered by a
    regression.

Intentionally unchanged

  • No tmux command, multiplexer, or real terminal anywhere in this change.

New abstractions

  • TerminalProvider / TerminalComposite exist because a grid's presentation has to be replaceable; the controlled provider and the future tmux adapter are the two concrete uses.

  • TerminalPaneClaim exists because pane terminal ownership must be unforgeable and per-ordinal; consumed by the grid and by the pane seam.

  • PaneTerminal exists because interactive work inside a pane must not compete for the root lease; consumed by the suite's controlled interactive child now and by <Session.Launch> in Launch native Agent sessions in independent terminal panes #731.

  • Each new abstraction has multiple concrete uses or a clear justification.

  • No speculative functionality is included.

Risks and limitations

  • Incomplete Story, stated above. Durability and replay are absent.
  • Five rows from ✨ Describe terminal grids as executable document structure (#729) #733 moved into this Story's suite. The move was authorized explicitly rather than assumed, and every claim they made is still asserted — against the provider request, which is stronger evidence than reading a layout off a refusal's cause.
  • A stray <Break> inside a pane fails the pane rather than printing as it would at the root. That is consistent with the pane-settlement contract, but it is a behavioural difference worth a reviewer's eye.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

The replaceable seam a terminal grid executes through, before any of the
execution that uses it.
`packages/runtime/terminal.ts` is the contextual provider: `prepare()`
builds the whole composite while it stays hidden, `attach()` shows it once
every pane is ready, and `destroy()` gives the root terminal back. The
request is provider-neutral — columns, rows, and the authored panes with
their derived positions — and names no terminal, socket, process or window.
Middleware may observe, narrow, refuse, wrap or delegate; presentation
never decides an outcome, so `update()` receives states core has already
settled on.
`packages/core/src/terminal/authority.ts` mints one-use pane claims for one
request's ordinals. A claim admits one interactive operation at a time on
its pane and holds that pane's readiness latch. Two claims do not contend,
which is what lets panes stay interactive together.
`packages/core/src/terminal/pane.ts` is the seam interactive work inside a
pane reaches for, so it runs as that pane's owner instead of competing for
the root foreground lease. Absence means "not in a pane".
Evidence: `packages/runtime/tests/terminal-provider.test.ts`, 11 rows.
`runTerminalGrid()` owns the lifecycle the reader sees: it takes the run's
one foreground-terminal lease, flushes root output, prepares the composite
while it stays hidden, starts every pane concurrently, and attaches only
once every pane has reported a spawn through its claim.
Ordering is the contract. The lease and the composite are both scope-owned,
so success, failure and cancellation all release the terminal and destroy
exactly the composite that was prepared — there is no path that skips
teardown. A pane that settles without ever reporting a spawn fails startup
rather than being presented as a running pane. Before the barrier a pane
failure fails the whole grid closed; after it, the failure is that pane's
status and its siblings keep running. Close cancels a live pane as `closed`,
which is not a failed pane, and the grid fails with the first failed pane in
authored order.
`display()` and an `onUpdate` hook complete the provider surface: a pane's
rendered text goes to that pane, and a suite reacts to a state the grid
decided rather than waiting and hoping.
Evidence: `packages/core/tests/terminal-grid.test.ts` (15 rows) and
`packages/runtime/tests/terminal-provider.test.ts` (11 rows). The readiness
barrier row was verified by removing the barrier: it fails without it.
`<Terminal.Grid>` now executes. Each authored pane becomes a concurrent
child of the grid: a self-closing pane runs the host's default shell
through its claim, and a paired pane expands its own content in a scope of
its own.
A pane inherits the bindings, providers, configuration and working
directory visible where the grid was written, and keeps everything it
creates afterwards. Its `<Break>` has no loop to exit, its `<Return>` has
no enclosing value body to claim, and its checked failures settle the pane
rather than reaching the root or a sibling. A pane's rendered text is
displayed in that pane; the grid itself renders `""`, so the root output
holds what surrounds the grid and no pane display at all.
#729's five execution-dependent rows move here, where they assert the
layout against the request the provider actually receives rather than
reading it off a refusal's cause — the structural suite keeps the grammar,
placement and pure-layout rows it owns. Moving them was authorized rather
than assumed.
Evidence: 22 rows in `packages/core/tests/terminal-grid.test.ts` and 11 in
`packages/runtime/tests/terminal-provider.test.ts`; the whole Deno core
(350) and runtime (14) suites pass.
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown

PR #738: ✨ Execute concurrent terminal panes through a replaceable provider (#730)

26 files, +5399 / -226

Scope

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

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

🟡 26 files changed. Are all changes related?

🟡 New abstraction files: packages/core/src/terminal/provider-api.ts. Verify 3+ consumers.

Structural

Oxlint structural signals:

  • no-unnecessary-type-assertion ×11: packages/core/src/terminal/journal.ts, packages/durable-streams/retained.ts, packages/durable-streams/combinators.ts (+2)
  • no-unused-vars ×7: packages/core/src/expand.ts

Slop

  • packages/durable-streams/combinators.ts:168 (removed)

Oxlint slop signals:

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

Static Analysis

Oxlint: 43 diagnostics across 5 files (12 rules)
Density: 0.008 violations/added-line

no-unnecessary-type-assertion (11): packages/core/src/terminal/journal.ts, packages/durable-streams/retained.ts, packages/durable-streams/combinators.ts (+2)
no-unsafe-type-assertion (9): packages/durable-streams/combinators.ts, packages/durable-streams/retained.ts, packages/core/src/expand.ts
no-unused-vars (7): packages/core/src/expand.ts
no-base-to-string (4): packages/core/src/expand.ts
no-floating-promises (3): packages/core/src/terminal/grid.ts
no-inferrable-types (2): packages/core/src/expand.ts
unbound-method (2): packages/core/src/expand.ts
no-shadow (1): packages/core/src/expand.ts
no-useless-fallback-in-spread (1): packages/core/src/expand.ts
no-unnecessary-type-parameters (1): packages/durable-streams/retained.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.

`paneWork()` never read the grid element it was handed. Its caller has it,
and a pane's own diagnostics are positioned at the pane.

@github-actionsgithub-actionsBot 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 10 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

),
0,
// The pane's own ledger: a checked failure settles this pane and
// cannot reach the root or a sibling.

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
// cannot reach the root or a sibling.

// and a host with no terminal refuses here — before any pane has done work.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

Comment threadpackages/core/src/terminal/grid.ts Outdated
yield* pane.run(claim, composite);
if (!readiness.acknowledged) {
// Settled without ever starting: that is a startup failure even
// though the work itself raised nothing.

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
// though the work itself raised nothing.

attached = true;

// The composite stays visible after its panes settle. The reader leaving is
// what finishes the grid, not the last pane exiting.

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
// what finishes the grid, not the last pane exiting.

Comment threadpackages/runtime/terminal.ts Outdated
export const TerminalProvider: Api<TerminalProviderHandler> = createApi<TerminalProviderHandler>(
"runtime.terminalProvider",
{
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

Comment threadpackages/runtime/terminal.ts Outdated
}
log.events.push(`attach:${generation}`);
},
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

Comment threadpackages/runtime/terminal.ts Outdated
log.events.push(`state:${generation}:${ordinal}:${state}`);
options.onUpdate?.(ordinal, state);
},
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

…#730)
Restores the authority boundary on the `AgentProviders` handshake, and puts
each pane on its own durable child coroutine.
**The boundary.** `TerminalGrids` is routing and only routing: `open()`
answers `unknown` and core throws the answer away, so middleware may
observe, narrow, refuse, wrap or delegate but can never authorize. The
capability that takes the leases, mints pane claims and settles a grid is a
non-contextual authority delivered straight to the registered provider
through a one-use install handshake. Core mints one identity-bearing request
per expansion; presenting a copy, a rebuilt lookalike, a changed request, an
already-presented one, or one from a superseded installation generation
authorizes nothing, and a handler that answers without presenting settles
nothing.
**Durable children.** Each pane is a durable child of the grid, allocated in
authored order, so a pane's identity follows its ordinal rather than the
order the runtime scheduled it in. The layout is recorded in the parent
coroutine before the lease and before any provider is contacted.
**Ordering.** A pane that settles before attach keeps the status it settled
to instead of being overwritten with `running`, and simultaneous startup
failures are selected by authored ordinal rather than by whichever rejected
first. Each pane also expands under a counter of its own, so two concurrent
panes cannot take block identities that depend on which ran first.
`durableSpawn` could not be used: the task it returns is spawned inside the
ephemeral effect's own scope, which closes as the effect resolves, so
awaiting it throws `halted`. It has no call sites or tests upstream.
`durableAll` is the exercised primitive and is what the panes and the grid
child use.
Evidence: 30 rows in `packages/core/tests/terminal-grid.test.ts` and 10 in
`packages/runtime/tests/terminal-provider.test.ts`; core 349, runtime 15.

@github-actionsgithub-actionsBot 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 9 redundant comments. Inline suggestions to remove them below.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.

attached = true;

// The composite stays visible after its panes settle. The reader leaving is
// what finishes the grid, not the last pane exiting.

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
// what finishes the grid, not the last pane exiting.

yield* pane.run(claim, composite);
if (!readiness.acknowledged) {
// Settled without ever starting: a startup failure even though the work
// itself raised nothing.

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
// itself raised nothing.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

`durableSpawn` returned a task spawned inside the `ephemeral` effect's own
scope, and that scope closed as the effect resolved — so every
`yield* task` threw `halted`. It had no call sites and no tests. It now
starts the child in the routine's own scope, so the task outlives the call
and can be awaited or halted by whoever asked for it.
A retained `Close(cancelled)` meant one thing to the code and two things in
practice. Under `durableRace` and `durableAll` it is a race loser or a
fail-fast sibling, and the same combinator cancels it again — those keep
DEC-024 exactly. Under `durableSpawn` nobody cancels it a second time, so
suspending hung the resumed run forever. `runDurableChild` now takes an
explicit `CancelledChildPolicy`, fixed at each combinator's call site and
never chosen by a caller. Resuming uses a new internal
`ReplayIndex.reopen()`, which forgets one coroutine's retained Close while
keeping its yields — so the child continues its own history rather than
restarting, and the divergence guard stops reading the remaining effects as
a coroutine continuing past its own close. Neither it nor `disableReplay` is
exported.
DEC-039 records the policy and marks DEC-024's invariant as superseded in
part: it assumed every cancelled child belongs to race or all.
The grid uses the repaired primitive: the whole grid is one durable child,
each pane is its own durable child allocated in authored ordinal order, and
each pane task is observed outside its child — so a replayed pane's retained
outcome publishes its status and satisfies the readiness barrier without
entering a body, a shell, or a launcher.
Evidence: 9 rows in `packages/durable-streams/tests/durable-spawn.test.ts`
(lifetime, completed replay, interrupted resume, retained-history
continuation, and both combinators keeping their own policy); 30 rows in
`packages/core/tests/terminal-grid.test.ts`. durable-streams 32, core 349,
runtime 15.

@github-actionsgithub-actionsBot 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 15 redundant comments. Inline suggestions to remove them below.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

return (function* (): Operation<Task<RetainedPaneOutcome>> {
const durable = yield* DurableContext.get();
if (durable === undefined) {
// No journal behind this run: an ordinary spawned child.

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
// No journal behind this run: an ordinary spawned child.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

Two decisions exposed while implementing #730, and no implementation.
**DEC-040 — a cancelled child records why.** DEC-039's `"resume"` fired on
every retained `Close(cancelled)` under an incomplete parent, which revives
work a caller deliberately halted: the record of a deliberate `task.halt()`
and the record of an interrupted run are the same event. The cancelled close
now carries `cancellation: "caller"` or `"unwound"`, written by whichever
path cancelled the child, and `"resume"` continues only `"unwound"`. A
deliberate stop suspends, which is DEC-024's reproduction argument applied
to a caller instead of a combinator; a legacy record with no reason reads as
`"caller"`, because refusing to revive is the safe direction. The reason is
retained evidence, not authority: nothing outside `runDurableChild` reads
it, and no caller chooses a policy.
Terminal grids need nothing wider. A grid halts its pane tasks at close, so
those retain `"caller"` — and the grid child completes, so a resumed run
short-circuits the region and never reaches them. The case that must resume,
an interrupted run, unwinds and retains `"unwound"`.
**TG17 narrows to the resolved layout.** A continuation executes the root the
journal retained; the supplied source is not read, compared or refused
(proved in #722). A grid's authored structure — pane count, order, form — is
therefore fixed for the life of a journal and cannot differ between runs, so
comparing it compares a value with itself, which is why the refusal never
fired. What a fixed retained document still resolves differently is
`columns` and each `title`, through prop-borne values, since props are not
restored. Those refuse before the lease and before provider contact.
Authored-structure change is a root-definition compatibility question, not a
grid one. Root-definition authority is preserved rather than overridden by a
pre-replay comparison against the current file, and the versioned root
boundary that would refuse a changed source stays open work.
**DEC-040.** A cancelled Close now records why: `cancellation: "caller"`
when the owner halts the task `durableSpawn` returned, `"unwound"` for
anything involuntary. `durableSpawn` resumes only `"unwound"`; a deliberate
stop suspends until the caller's deterministic control flow halts it again,
and a record with no reason reads as `"caller"` so nothing legacy is
revived. `durableAll` and `durableRace` keep DEC-024 whatever the reason
says.
The halt is intercepted without changing the public `Task` surface: the
returned task carries every member the real one defines, copied with its
prototype, and only `halt` is replaced. A proxy cannot do this — a task's
members are read-only and non-configurable, so a `get` trap is required to
hand back exactly what the target holds.
The reason had to survive three boundaries that were dropping it: the
protocol parser, the observable copy, and — the one that actually mattered —
`detachResult`, which froze every cancellation down to `{ status }`.
**TG15.** The harness's `attached` and `pastGrid` signals are now separate,
and a run that expects its grid to complete waits for the sibling *after*
the grid before halting the root at `<Hold />`. That is what leaves a
completed grid child under an incomplete root, which is the only state in
which a completed region can be observed replaying at all. Both a successful
grid and a contained failed one replay their exact retained result with no
provider, pane content, shell or launcher work, and each row asserts the
grid child genuinely recorded a terminal close. No timeouts.
**TG17.** Prop-borne `columns` and `title` change independently against one
fixed retained document — the only things a fixed retained root can still
resolve differently — and each refuses with zero provider observation. For
supplied-file changes to pane count, order and form, the continuation opens
the retained structure rather than the file's, asserted request-for-request.
The retained record carries every authored pane's ordinal, title, form and
derived position.
`readLayout()` parses totally: the layout object and every pane field, with
missing, extra, mistyped, out-of-position and self-inconsistent records all
refused rather than half-read.
Evidence: durable-spawn 14 rows, terminal-grid 36 rows, structural 13,
provider 10. Packages: durable-streams 33, core 349, runtime 15,
workflow 172.
#730)
**The harness cannot pass a hung replay any more.** `runInterrupted()` had a
1500ms timer racing its signals, so a replay that hung returned a
DocumentRun that looked finished; it also slept a fixed 5ms to let records
land. Both are gone. It now waits only on events the run produced:
`attached`, `pastGrid`, and a new `panesSettled` for the rows that read pane
records — a pane's status is published only after its durable child returned,
so counting settled panes is also counting durable pane closes. A replay
that hangs now reaches none of them and hangs the row.
**TG15's failed case is a real contained failure.** A pane that fails before
attachment fails the whole region, so the old document could not both fail
and continue. The failing pane is now a shell that starts, waits for
attachment, and only then exits badly — contained as that pane's status,
with the grid settling as failed and the document carrying on. Both runs
capture the printed errors, and the row asserts the replayed run produced
the same ones, reached `PAST_THE_GRID`, and did no provider, pane, shell or
launcher work.
**DEC-040 gets boundary tests where the evidence actually travels.**
`parse.test.ts` round-trips both reasons to the same bytes, keeps a legacy
absence absent, and refuses an unrecognised reason at `$.result.cancellation`.
`retained.test.ts` proves retention and `consumable()` carry both reasons,
leave a legacy absence absent, drop an unrecognised one to the safe default,
and that the reason reaches the replay index. The DEC-040 rows in
`durable-spawn.test.ts` no longer coordinate by delay: a child says when it
is running, and the caller says when it has halted.
**Malformed retained layouts** are covered by replaying a real journal with
only its layout entry replaced — a missing member, an extra one, a mistyped
one, a pane out of position, and a record that disagrees with itself. Each
refuses with zero provider observation.
The `durableSpawn` doc comment no longer says every retained cancellation is
an interrupted run.
The DEC-040 block still slept where it meant to synchronise — my previous
replacements silently failed to match after the file was reformatted, so
none of them landed. The block is rewritten rather than patched.
Every row now waits on something the run reported. A shared `living()` child
resolves a `started` signal and then suspends, so each row halts or unwinds a
child that is provably live rather than one a delay happened to reach. The
caller resolves `halted` after performing its deliberate halt, so a run is
interrupted only once both facts — the deliberate stop and the interruption —
are in the journal.
Non-revival is established by control flow rather than by waiting: the
resumed run reaches its own `task.halt()` and says so, and a revived child
would have recorded its mark before the caller could get there. The
legacy-absence row signals once the child has been asked for and the request
returned. No new timeout, and `sleep` stays imported because the lifetime
rows above still use it deliberately.
`retained.test.ts` drops the cast and the row it supported: rejecting an
unrecognised reason is the parser's, proved there, and retention proves only
that `"caller"`, `"unwound"` and a legacy absence survive.

@github-actionsgithub-actionsBot 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 11 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

// neither can begin while the other holds it.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

// grid covers it up.
yield* flushOutput();

// Routed, and the answer thrown away.

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
// Routed, and the answer thrown away.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.


const grid = createTerminalGridClaims(request);
// Nothing new is admitted once teardown begins, so a pane that was about to
// start an interactive child is refused rather than racing the close.

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
// start an interactive child is refused rather than racing the close.

// to schedule it in. Each task is observed *outside* its child: a replayed
// completed pane returns its retained outcome without entering a body, a
// shell, or a launcher, and that outcome is what publishes its status and
// satisfies the readiness barrier.

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
// satisfies the readiness barrier.

…730)
**`Symbol.asyncDispose` bypassed the deliberate-stop evidence.** The task
`durableSpawn` returns copied it from the original unchanged, so
`await using` — or an explicit `task[Symbol.asyncDispose]()` — recorded
`cancellation: "unwound"` and the next run revived the child. `halt()` and
the async dispose are the same decision spelled two ways, and both are now
observed. Awaiting a task is not a stop and is left exactly as it was. A
regression disposes a live task, asserts the retained reason is `"caller"`,
resumes the journal, and proves the body is not entered again.
**Reader close no longer halts panes.** It asks them to stop: a pane races
its work against a close signal, settles as `closed`, and records that
outcome as its own. Nothing on the ordinary close path is a caller-cancelled
child any more, so a resumed run restores a pane the reader closed rather
than finding a cancelled child it must either re-enter or wait on forever.
Statuses are published before anything is awaited, so a pane with slow
finalizers cannot delay the outcome the grid already knows.
**§6.21 now agrees with architecture.md and TG17.** Partial replay compares
the resolved layout — columns and titles. Pane count, order and form come
from the retained root and cannot diverge within a continuation, so a
changed supplied file is ignored in favour of the retained structure;
refusing a changed authored structure is a root-definition boundary this
specification does not yet define.
DEC-040 is unchanged and nothing deliberately stopped is revived.

@github-actionsgithub-actionsBot 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 18 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

*destroy() {
// Destroying twice would make the record say a composite was taken down
// more times than it was built, which is exactly the ordering claim a
// suite reads this log 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
// suite reads this log for.

@github-actionsgithub-actionsBot 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 20 redundant comments. Inline suggestions to remove them below.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

},
ready() {
// Idempotent by construction: readiness is a fact about the pane, and a
// provider that reports the same spawn twice has not started two panes.

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 that reports the same spawn twice has not started two panes.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

const cancellation = members.get("cancellation");
if (cancellation === undefined) {
// A record written before this evidence existed. DEC-040 reads the
// absence as a deliberate stop, so nothing it left behind is revived.

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
// absence as a deliberate stop, so nothing it left behind is revived.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

*destroy() {
// Destroying twice would make the record say a composite was taken down
// more times than it was built, which is exactly the ordering claim a
// suite reads this log 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
// suite reads this log for.

@taras
tarasforce-pushed the agent/issue-730-terminal-execution branch from 8f85400 to eb92602CompareSeptember 2, 2026 22:38

@github-actionsgithub-actionsBot 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 9 redundant comments. Inline suggestions to remove them below.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

}
for (const [index] of work.entries()) {
// Awaited, not halted. Each pane settles on the close signal and records
// the outcome it reached, which is what a resumed run reads.

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 outcome it reached, which is what a resumed run reads.

// the reader leaves, this settles as `closed` straight away and the work
// comes down in the enclosing scope's own teardown — so a pane whose
// finalizers are slow cannot hold up the outcome the grid already knows,
// and the record a resumed run reads is written either way.

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
// and the record a resumed run reads is written either way.

return (function* (): Operation<Task<RetainedPaneOutcome>> {
const durable = yield* DurableContext.get();
if (durable === undefined) {
// No journal behind this run: an ordinary spawned child.

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
// No journal behind this run: an ordinary spawned child.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

Implements the amendment at 1833870 without revising it.
**The live handshake.** `composite.closed()` settling now only *proposes* the
boundary. The grid's durable child publishes that proposal and waits; the
owner awaiting the child acknowledges it; and only then does the grid seal
admission and ask its panes to close. The handshake is one live rendezvous —
no provider identity, nothing journaled.
**Committing an outcome before the scope finishes unwinding.** A durable
child can now declare its terminal value, and `runDurableChild` records that
value if the child never reaches a normal ending. That is the piece the
contract needs: the grid commits its retained record as the boundary is
crossed, and each pane live at that moment commits `closed`, so a
cancellation arriving while pane and provider finalizers are still running
records what close decided rather than a cancellation. Committing is live
state; it reaches the journal only as the ordinary `Close`. A child that
returns or throws normally overrides it, and a child that never committed
still records the cancellation it actually reached — DEC-040 untouched.
Cancellation stays deferred because Effection completes a child's teardown —
pane finalizers, provider destroy, terminal restoration, lease release, the
`Close` append and the task's settlement — before the halt reaches the owner.
**Pane work stays inside its ordinal-derived durable child.** Reader close
asks the pane to close; it never halts the pane's durable task. The pane
commits `closed`, stops its live nested work through its own scope, and
settles only once that work and its finalizers have settled.
No durable closing marker was added, and completed replay is unchanged.

@github-actionsgithub-actionsBot 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 11 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

// neither can begin while the other holds it.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

// grid covers it up.
yield* flushOutput();

// Routed, and the answer thrown away.

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
// Routed, and the answer thrown away.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.


const grid = createTerminalGridClaims(request);
// Nothing new is admitted once teardown begins, so a pane that was about to
// start an interactive child is refused rather than racing the close.

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
// start an interactive child is refused rather than racing the close.

Implements architecture 1833870 at the owner boundary. The grid's durable
child now runs in a scope of its own — a child of the owner's, so it inherits
every context the document runs under, and its own so that tearing the owner
down does not reach it first. A finalizer registered after that scope exists
runs before it is destroyed, and that is the cancellation-deferred await: once
the owner has acknowledged the provider's close proposal, the grid and its panes
finish teardown and append their ordinary completed Close records, and only then
does the cancellation carry on to the parent.
Removes the exported CommitOutcome/durableSpawn(commit) API. Cancellation is
never turned into success inside runDurableChild; durableSpawnIn only says where
a child lives, and grants nothing a caller does not already have.
TG19 proves the ordering with signals alone: a live pane arms a blocking
finalizer, the reader leaves, the finalizer is entered and held, cancellation
begins, the finalizer is released, and the run ends with the composite destroyed,
a completed grid Close retained, the live pane retained as closed — and the
sibling after the grid never reached. The continuation then replays past it with
no provider, no pane body and no finalizer re-entered.
TG6 isolates paired-pane sequencing on its own: the reader leaves only once the
pane's second component has run.
The production lifecycle is unchanged. TG19 now reads counters and journal
records rather than a log's shape.
The controlled composite keeps live resource counters — composites prepared,
composites attached, shells started — each raised when it takes something and
lowered when it gives it back, however it left. TG19 reads them once while a
pane finalizer is blocked, so it knows they went up, and again when the
cancellation has completed, so it knows they came back down.
The harness now says when a blocked finalizer *leaves*, not only when it is
entered: a finalizer that was entered and then cancelled reaches the first hook
and never the second. And after every interrupted run it takes the foreground
lease and gives it back twice — the first proves the grid returned it, the
second proves the harness did.
TG19 adds: one grid Close(ok) retaining close: "reader"; two pane Closes, both
completed, with no cancellation recorded at either level; the finalizer entered
and left exactly once; destroy:0 exactly once. The first-attempt claim that no
following sibling ran and the replay tripwires are unchanged.
Every one of these was broken on purpose and re-run: dropping any of the three
counter releases, the deferral, the finalizer-exit hook, or double-logging
destroy fails TG19, and a second holder of the foreground lease is refused.
Sign up for freeto 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

@taras
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

✨ Execute concurrent terminal panes through a replaceable provider (#730) - #738

Open
taras wants to merge 15 commits into
agent/issue-729-terminal-gridfrom
agent/issue-730-terminal-execution
Open

✨ Execute concurrent terminal panes through a replaceable provider (#730)#738
taras wants to merge 15 commits into
agent/issue-729-terminal-gridfrom
agent/issue-730-terminal-execution

Conversation

@taras

@tarastaras commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes#730. Second implementation Story under Quest #717, stacked on #733.

Base is agent/issue-729-terminal-grid, not main, as the Story's verification stack directs. Branched from 97be06321cbdf08d84ef53dbefb88407f54326fe, the reviewed head of #733.

Why

#729 froze the language: an author can write a terminal grid, and every runtime can validate one. Nothing could run one. This Story makes a grid execute, through a boundary a host replaces — so the document keeps one lifecycle contract whether the presentation is tmux, a controlled test surface, or something native later.

What changes

Before: a valid <Terminal.Grid> derived its layout and refused, because nothing could present it.

After: it runs. Core takes the run's one foreground-terminal lease, flushes root output, prepares the composite while it stays hidden, starts every pane concurrently, and attaches only once every pane has actually started.

<Terminal.Grid columns={2}>
<Terminaltitle="Agent">…</Terminal>
<Terminaltitle="Shell" />
</Terminal.Grid>

How it works

lease → flush → prepare (hidden) → panes start concurrently
→ readiness barrier → attach → panes settle independently
→ reader closes → teardown → lease released

packages/runtime/terminal.ts is the replaceable seam. The request is provider-neutral — columns, rows, and the authored panes with their derived positions — and names no terminal, socket, process or window. Middleware may observe, narrow, refuse, wrap or delegate. Presentation never decides an outcome: update() receives states core has already settled on, and its return value is ignored.

packages/core/src/terminal/authority.ts mints one-use pane claims for one request's ordinals. A claim admits one interactive operation at a time on its pane and holds that pane's readiness latch. Two claims do not contend, which is what lets panes stay interactive together.

packages/core/src/terminal/pane.ts is the seam anything interactive inside a pane reaches, so it runs as that pane's owner instead of competing for the root lease. Absence means "not in a pane".

packages/core/src/terminal/grid.ts owns the lifecycle. The lease and the composite are both scope-owned, so success, failure and cancellation all release the terminal and destroy exactly the composite that was prepared — there is no path that skips teardown.

Review guide

Start with:packages/core/tests/terminal-grid.test.ts

Then review:

  1. packages/runtime/terminal.ts — the boundary and what a handler may do.
  2. packages/core/src/terminal/authority.ts — claims, contention, the readiness latch.
  3. packages/core/src/terminal/grid.ts — the ordering, and where teardown is registered.
  4. packages/core/src/expand.tspaneWork(), which is where a pane's isolation is established.

Look carefully at:

  • The order in runTerminalGrid(). ensure(() => composite.destroy()) is registered before any pane starts, so a composite that was prepared is owed a destroy even if the next line fails.
  • The attached flag. Before the barrier a pane failure fails the whole grid closed; after it, the failure is that pane's status and its siblings keep running.
  • paneWork()'s paired branch: ActiveLoop.set(undefined), a derived env, containedLedger(), and undefined for the return body are the four things that make a pane a scope rather than a region.

What must stay true

  • Nothing is shown before every pane has started — enforced by racing the readiness barrier against startup failure, checked by the TG9 ordering row, which was verified by deleting the barrier: it fails without it.
  • A prepared composite is always destroyed exactly once — enforced by scope-owned ensure, checked by TG12 and by the controlled composite refusing a second destroy.
  • Presentation decides nothing — enforced by update() returning void and claims never leaving core, checked by the middleware rows in the provider suite.
  • A pane's later bindings stay in that pane — enforced by a derived environment, checked by the TG6 document row asserting the sibling and the document after the grid still see the binding unresolved.

How to verify it

deno task test packages/core/tests/terminal-grid.test.ts
deno task test packages/runtime/tests/terminal-provider.test.ts
deno task test packages/core/tests/terminal-grid-structure.test.ts
  • TG8 proves one claim admits one interactive operation at a time and two claims do not contend; it fails if a pane admitted twice, or if two panes serialized.
  • TG9 proves nothing attaches until every pane reports a spawn, and that a pane which settles without one fails startup; it fails if a grid attached early or presented a pane that never started.
  • TG10 proves a pane can fail after attach while a sibling is provably still live, and the grid reports the first failed authored ordinal.
  • TG12/TG13 prove close and parent cancellation both destroy the composite exactly once, and that a pane cancelled by the close is closed rather than failed.
  • TG6/TG7 prove pane scope and output routing through the real execute() path.
  • The provider suite proves the boundary refuses with nothing installed, and that middleware can observe, narrow, refuse and wrap without being able to authorize.

Whole Deno core suite: 350 passed. Runtime suite: 14 passed.

Scope

Included

  • The provider boundary, the terminal authority and pane claims, the readiness latch, the pane seam, and the grid lifecycle.
  • Pane scope isolation, pane output routing, concurrent start, atomic attach, independent settlement, close and cancellation teardown.

Not included — this Story is not finished

These acceptance points landed in later commits on this branch, and the section
that once said durability was absent is no longer true:

  • Durability and replay (TG15–TG17) are implemented. The grid is one durable
    child and each pane is its own durable child allocated in authored ordinal
    order. A completed region replays its exact retained result — successful and
    contained-failed alike — contacting no provider and running no pane content,
    shell or launcher. An interrupted region rebuilds a fresh composite. The
    layout is recorded in the parent coroutine before the lease and before any
    provider is contacted, and a malformed retained layout refuses there.
  • TG17 is scoped to what a continuation can actually change. A continuation
    executes the retained root, so pane count, order and form cannot differ and
    are proved retained-and-honoured rather than refused; columns and each
    title reach the grid through props, which are not restored, and each refuses
    independently with zero provider observation.
  • durableSpawn was repaired to make any of this possible: its task now
    outlives the call, and a cancelled child records why it stopped (DEC-040) so
    a deliberately halted region is never revived while an interrupted one
    resumes.

What remains outside this PR:

  • TG14's bounded teardown proof belongs to the tmux provider Story; the
    controlled provider cannot exercise it.
  • TG5 and Agent-session contention in TG11 belong to the native-launch
    Story, as the issue states.
  • One known gap: a run interrupted while reader-close teardown is awaiting
    a pane whose own finalizer is slow
    leaves that pane recorded as unwound
    rather than closed, so a resumed run re-enters it. Reader close is now
    cooperative — panes are asked to stop and record closed themselves rather
    than being halted — which removes caller-cancelled panes from the ordinary
    close path, but the blocked-finalizer overlap is not yet covered by a
    regression.

Intentionally unchanged

  • No tmux command, multiplexer, or real terminal anywhere in this change.

New abstractions

  • TerminalProvider / TerminalComposite exist because a grid's presentation has to be replaceable; the controlled provider and the future tmux adapter are the two concrete uses.

  • TerminalPaneClaim exists because pane terminal ownership must be unforgeable and per-ordinal; consumed by the grid and by the pane seam.

  • PaneTerminal exists because interactive work inside a pane must not compete for the root lease; consumed by the suite's controlled interactive child now and by <Session.Launch> in Launch native Agent sessions in independent terminal panes #731.

  • Each new abstraction has multiple concrete uses or a clear justification.

  • No speculative functionality is included.

Risks and limitations

  • Incomplete Story, stated above. Durability and replay are absent.
  • Five rows from ✨ Describe terminal grids as executable document structure (#729) #733 moved into this Story's suite. The move was authorized explicitly rather than assumed, and every claim they made is still asserted — against the provider request, which is stronger evidence than reading a layout off a refusal's cause.
  • A stray <Break> inside a pane fails the pane rather than printing as it would at the root. That is consistent with the pane-settlement contract, but it is a behavioural difference worth a reviewer's eye.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

The replaceable seam a terminal grid executes through, before any of the
execution that uses it.
`packages/runtime/terminal.ts` is the contextual provider: `prepare()`
builds the whole composite while it stays hidden, `attach()` shows it once
every pane is ready, and `destroy()` gives the root terminal back. The
request is provider-neutral — columns, rows, and the authored panes with
their derived positions — and names no terminal, socket, process or window.
Middleware may observe, narrow, refuse, wrap or delegate; presentation
never decides an outcome, so `update()` receives states core has already
settled on.
`packages/core/src/terminal/authority.ts` mints one-use pane claims for one
request's ordinals. A claim admits one interactive operation at a time on
its pane and holds that pane's readiness latch. Two claims do not contend,
which is what lets panes stay interactive together.
`packages/core/src/terminal/pane.ts` is the seam interactive work inside a
pane reaches for, so it runs as that pane's owner instead of competing for
the root foreground lease. Absence means "not in a pane".
Evidence: `packages/runtime/tests/terminal-provider.test.ts`, 11 rows.
`runTerminalGrid()` owns the lifecycle the reader sees: it takes the run's
one foreground-terminal lease, flushes root output, prepares the composite
while it stays hidden, starts every pane concurrently, and attaches only
once every pane has reported a spawn through its claim.
Ordering is the contract. The lease and the composite are both scope-owned,
so success, failure and cancellation all release the terminal and destroy
exactly the composite that was prepared — there is no path that skips
teardown. A pane that settles without ever reporting a spawn fails startup
rather than being presented as a running pane. Before the barrier a pane
failure fails the whole grid closed; after it, the failure is that pane's
status and its siblings keep running. Close cancels a live pane as `closed`,
which is not a failed pane, and the grid fails with the first failed pane in
authored order.
`display()` and an `onUpdate` hook complete the provider surface: a pane's
rendered text goes to that pane, and a suite reacts to a state the grid
decided rather than waiting and hoping.
Evidence: `packages/core/tests/terminal-grid.test.ts` (15 rows) and
`packages/runtime/tests/terminal-provider.test.ts` (11 rows). The readiness
barrier row was verified by removing the barrier: it fails without it.
`<Terminal.Grid>` now executes. Each authored pane becomes a concurrent
child of the grid: a self-closing pane runs the host's default shell
through its claim, and a paired pane expands its own content in a scope of
its own.
A pane inherits the bindings, providers, configuration and working
directory visible where the grid was written, and keeps everything it
creates afterwards. Its `<Break>` has no loop to exit, its `<Return>` has
no enclosing value body to claim, and its checked failures settle the pane
rather than reaching the root or a sibling. A pane's rendered text is
displayed in that pane; the grid itself renders `""`, so the root output
holds what surrounds the grid and no pane display at all.
#729's five execution-dependent rows move here, where they assert the
layout against the request the provider actually receives rather than
reading it off a refusal's cause — the structural suite keeps the grammar,
placement and pure-layout rows it owns. Moving them was authorized rather
than assumed.
Evidence: 22 rows in `packages/core/tests/terminal-grid.test.ts` and 11 in
`packages/runtime/tests/terminal-provider.test.ts`; the whole Deno core
(350) and runtime (14) suites pass.
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown

PR #738: ✨ Execute concurrent terminal panes through a replaceable provider (#730)

26 files, +5399 / -226

Scope

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

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

🟡 26 files changed. Are all changes related?

🟡 New abstraction files: packages/core/src/terminal/provider-api.ts. Verify 3+ consumers.

Structural

Oxlint structural signals:

  • no-unnecessary-type-assertion ×11: packages/core/src/terminal/journal.ts, packages/durable-streams/retained.ts, packages/durable-streams/combinators.ts (+2)
  • no-unused-vars ×7: packages/core/src/expand.ts

Slop

  • packages/durable-streams/combinators.ts:168 (removed)

Oxlint slop signals:

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

Static Analysis

Oxlint: 43 diagnostics across 5 files (12 rules)
Density: 0.008 violations/added-line

no-unnecessary-type-assertion (11): packages/core/src/terminal/journal.ts, packages/durable-streams/retained.ts, packages/durable-streams/combinators.ts (+2)
no-unsafe-type-assertion (9): packages/durable-streams/combinators.ts, packages/durable-streams/retained.ts, packages/core/src/expand.ts
no-unused-vars (7): packages/core/src/expand.ts
no-base-to-string (4): packages/core/src/expand.ts
no-floating-promises (3): packages/core/src/terminal/grid.ts
no-inferrable-types (2): packages/core/src/expand.ts
unbound-method (2): packages/core/src/expand.ts
no-shadow (1): packages/core/src/expand.ts
no-useless-fallback-in-spread (1): packages/core/src/expand.ts
no-unnecessary-type-parameters (1): packages/durable-streams/retained.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.

`paneWork()` never read the grid element it was handed. Its caller has it,
and a pane's own diagnostics are positioned at the pane.

@github-actionsgithub-actionsBot 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 10 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

),
0,
// The pane's own ledger: a checked failure settles this pane and
// cannot reach the root or a sibling.

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
// cannot reach the root or a sibling.

// and a host with no terminal refuses here — before any pane has done work.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

Comment threadpackages/core/src/terminal/grid.ts Outdated
yield* pane.run(claim, composite);
if (!readiness.acknowledged) {
// Settled without ever starting: that is a startup failure even
// though the work itself raised nothing.

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
// though the work itself raised nothing.

attached = true;

// The composite stays visible after its panes settle. The reader leaving is
// what finishes the grid, not the last pane exiting.

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
// what finishes the grid, not the last pane exiting.

Comment threadpackages/runtime/terminal.ts Outdated
export const TerminalProvider: Api<TerminalProviderHandler> = createApi<TerminalProviderHandler>(
"runtime.terminalProvider",
{
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

Comment threadpackages/runtime/terminal.ts Outdated
}
log.events.push(`attach:${generation}`);
},
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

Comment threadpackages/runtime/terminal.ts Outdated
log.events.push(`state:${generation}:${ordinal}:${state}`);
options.onUpdate?.(ordinal, state);
},
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

…#730)
Restores the authority boundary on the `AgentProviders` handshake, and puts
each pane on its own durable child coroutine.
**The boundary.** `TerminalGrids` is routing and only routing: `open()`
answers `unknown` and core throws the answer away, so middleware may
observe, narrow, refuse, wrap or delegate but can never authorize. The
capability that takes the leases, mints pane claims and settles a grid is a
non-contextual authority delivered straight to the registered provider
through a one-use install handshake. Core mints one identity-bearing request
per expansion; presenting a copy, a rebuilt lookalike, a changed request, an
already-presented one, or one from a superseded installation generation
authorizes nothing, and a handler that answers without presenting settles
nothing.
**Durable children.** Each pane is a durable child of the grid, allocated in
authored order, so a pane's identity follows its ordinal rather than the
order the runtime scheduled it in. The layout is recorded in the parent
coroutine before the lease and before any provider is contacted.
**Ordering.** A pane that settles before attach keeps the status it settled
to instead of being overwritten with `running`, and simultaneous startup
failures are selected by authored ordinal rather than by whichever rejected
first. Each pane also expands under a counter of its own, so two concurrent
panes cannot take block identities that depend on which ran first.
`durableSpawn` could not be used: the task it returns is spawned inside the
ephemeral effect's own scope, which closes as the effect resolves, so
awaiting it throws `halted`. It has no call sites or tests upstream.
`durableAll` is the exercised primitive and is what the panes and the grid
child use.
Evidence: 30 rows in `packages/core/tests/terminal-grid.test.ts` and 10 in
`packages/runtime/tests/terminal-provider.test.ts`; core 349, runtime 15.

@github-actionsgithub-actionsBot 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 9 redundant comments. Inline suggestions to remove them below.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.

attached = true;

// The composite stays visible after its panes settle. The reader leaving is
// what finishes the grid, not the last pane exiting.

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
// what finishes the grid, not the last pane exiting.

yield* pane.run(claim, composite);
if (!readiness.acknowledged) {
// Settled without ever starting: a startup failure even though the work
// itself raised nothing.

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
// itself raised nothing.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

`durableSpawn` returned a task spawned inside the `ephemeral` effect's own
scope, and that scope closed as the effect resolved — so every
`yield* task` threw `halted`. It had no call sites and no tests. It now
starts the child in the routine's own scope, so the task outlives the call
and can be awaited or halted by whoever asked for it.
A retained `Close(cancelled)` meant one thing to the code and two things in
practice. Under `durableRace` and `durableAll` it is a race loser or a
fail-fast sibling, and the same combinator cancels it again — those keep
DEC-024 exactly. Under `durableSpawn` nobody cancels it a second time, so
suspending hung the resumed run forever. `runDurableChild` now takes an
explicit `CancelledChildPolicy`, fixed at each combinator's call site and
never chosen by a caller. Resuming uses a new internal
`ReplayIndex.reopen()`, which forgets one coroutine's retained Close while
keeping its yields — so the child continues its own history rather than
restarting, and the divergence guard stops reading the remaining effects as
a coroutine continuing past its own close. Neither it nor `disableReplay` is
exported.
DEC-039 records the policy and marks DEC-024's invariant as superseded in
part: it assumed every cancelled child belongs to race or all.
The grid uses the repaired primitive: the whole grid is one durable child,
each pane is its own durable child allocated in authored ordinal order, and
each pane task is observed outside its child — so a replayed pane's retained
outcome publishes its status and satisfies the readiness barrier without
entering a body, a shell, or a launcher.
Evidence: 9 rows in `packages/durable-streams/tests/durable-spawn.test.ts`
(lifetime, completed replay, interrupted resume, retained-history
continuation, and both combinators keeping their own policy); 30 rows in
`packages/core/tests/terminal-grid.test.ts`. durable-streams 32, core 349,
runtime 15.

@github-actionsgithub-actionsBot 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 15 redundant comments. Inline suggestions to remove them below.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

return (function* (): Operation<Task<RetainedPaneOutcome>> {
const durable = yield* DurableContext.get();
if (durable === undefined) {
// No journal behind this run: an ordinary spawned child.

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
// No journal behind this run: an ordinary spawned child.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

Two decisions exposed while implementing #730, and no implementation.
**DEC-040 — a cancelled child records why.** DEC-039's `"resume"` fired on
every retained `Close(cancelled)` under an incomplete parent, which revives
work a caller deliberately halted: the record of a deliberate `task.halt()`
and the record of an interrupted run are the same event. The cancelled close
now carries `cancellation: "caller"` or `"unwound"`, written by whichever
path cancelled the child, and `"resume"` continues only `"unwound"`. A
deliberate stop suspends, which is DEC-024's reproduction argument applied
to a caller instead of a combinator; a legacy record with no reason reads as
`"caller"`, because refusing to revive is the safe direction. The reason is
retained evidence, not authority: nothing outside `runDurableChild` reads
it, and no caller chooses a policy.
Terminal grids need nothing wider. A grid halts its pane tasks at close, so
those retain `"caller"` — and the grid child completes, so a resumed run
short-circuits the region and never reaches them. The case that must resume,
an interrupted run, unwinds and retains `"unwound"`.
**TG17 narrows to the resolved layout.** A continuation executes the root the
journal retained; the supplied source is not read, compared or refused
(proved in #722). A grid's authored structure — pane count, order, form — is
therefore fixed for the life of a journal and cannot differ between runs, so
comparing it compares a value with itself, which is why the refusal never
fired. What a fixed retained document still resolves differently is
`columns` and each `title`, through prop-borne values, since props are not
restored. Those refuse before the lease and before provider contact.
Authored-structure change is a root-definition compatibility question, not a
grid one. Root-definition authority is preserved rather than overridden by a
pre-replay comparison against the current file, and the versioned root
boundary that would refuse a changed source stays open work.
**DEC-040.** A cancelled Close now records why: `cancellation: "caller"`
when the owner halts the task `durableSpawn` returned, `"unwound"` for
anything involuntary. `durableSpawn` resumes only `"unwound"`; a deliberate
stop suspends until the caller's deterministic control flow halts it again,
and a record with no reason reads as `"caller"` so nothing legacy is
revived. `durableAll` and `durableRace` keep DEC-024 whatever the reason
says.
The halt is intercepted without changing the public `Task` surface: the
returned task carries every member the real one defines, copied with its
prototype, and only `halt` is replaced. A proxy cannot do this — a task's
members are read-only and non-configurable, so a `get` trap is required to
hand back exactly what the target holds.
The reason had to survive three boundaries that were dropping it: the
protocol parser, the observable copy, and — the one that actually mattered —
`detachResult`, which froze every cancellation down to `{ status }`.
**TG15.** The harness's `attached` and `pastGrid` signals are now separate,
and a run that expects its grid to complete waits for the sibling *after*
the grid before halting the root at `<Hold />`. That is what leaves a
completed grid child under an incomplete root, which is the only state in
which a completed region can be observed replaying at all. Both a successful
grid and a contained failed one replay their exact retained result with no
provider, pane content, shell or launcher work, and each row asserts the
grid child genuinely recorded a terminal close. No timeouts.
**TG17.** Prop-borne `columns` and `title` change independently against one
fixed retained document — the only things a fixed retained root can still
resolve differently — and each refuses with zero provider observation. For
supplied-file changes to pane count, order and form, the continuation opens
the retained structure rather than the file's, asserted request-for-request.
The retained record carries every authored pane's ordinal, title, form and
derived position.
`readLayout()` parses totally: the layout object and every pane field, with
missing, extra, mistyped, out-of-position and self-inconsistent records all
refused rather than half-read.
Evidence: durable-spawn 14 rows, terminal-grid 36 rows, structural 13,
provider 10. Packages: durable-streams 33, core 349, runtime 15,
workflow 172.
#730)
**The harness cannot pass a hung replay any more.** `runInterrupted()` had a
1500ms timer racing its signals, so a replay that hung returned a
DocumentRun that looked finished; it also slept a fixed 5ms to let records
land. Both are gone. It now waits only on events the run produced:
`attached`, `pastGrid`, and a new `panesSettled` for the rows that read pane
records — a pane's status is published only after its durable child returned,
so counting settled panes is also counting durable pane closes. A replay
that hangs now reaches none of them and hangs the row.
**TG15's failed case is a real contained failure.** A pane that fails before
attachment fails the whole region, so the old document could not both fail
and continue. The failing pane is now a shell that starts, waits for
attachment, and only then exits badly — contained as that pane's status,
with the grid settling as failed and the document carrying on. Both runs
capture the printed errors, and the row asserts the replayed run produced
the same ones, reached `PAST_THE_GRID`, and did no provider, pane, shell or
launcher work.
**DEC-040 gets boundary tests where the evidence actually travels.**
`parse.test.ts` round-trips both reasons to the same bytes, keeps a legacy
absence absent, and refuses an unrecognised reason at `$.result.cancellation`.
`retained.test.ts` proves retention and `consumable()` carry both reasons,
leave a legacy absence absent, drop an unrecognised one to the safe default,
and that the reason reaches the replay index. The DEC-040 rows in
`durable-spawn.test.ts` no longer coordinate by delay: a child says when it
is running, and the caller says when it has halted.
**Malformed retained layouts** are covered by replaying a real journal with
only its layout entry replaced — a missing member, an extra one, a mistyped
one, a pane out of position, and a record that disagrees with itself. Each
refuses with zero provider observation.
The `durableSpawn` doc comment no longer says every retained cancellation is
an interrupted run.
The DEC-040 block still slept where it meant to synchronise — my previous
replacements silently failed to match after the file was reformatted, so
none of them landed. The block is rewritten rather than patched.
Every row now waits on something the run reported. A shared `living()` child
resolves a `started` signal and then suspends, so each row halts or unwinds a
child that is provably live rather than one a delay happened to reach. The
caller resolves `halted` after performing its deliberate halt, so a run is
interrupted only once both facts — the deliberate stop and the interruption —
are in the journal.
Non-revival is established by control flow rather than by waiting: the
resumed run reaches its own `task.halt()` and says so, and a revived child
would have recorded its mark before the caller could get there. The
legacy-absence row signals once the child has been asked for and the request
returned. No new timeout, and `sleep` stays imported because the lifetime
rows above still use it deliberately.
`retained.test.ts` drops the cast and the row it supported: rejecting an
unrecognised reason is the parser's, proved there, and retention proves only
that `"caller"`, `"unwound"` and a legacy absence survive.

@github-actionsgithub-actionsBot 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 11 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

// neither can begin while the other holds it.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

// grid covers it up.
yield* flushOutput();

// Routed, and the answer thrown away.

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
// Routed, and the answer thrown away.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.


const grid = createTerminalGridClaims(request);
// Nothing new is admitted once teardown begins, so a pane that was about to
// start an interactive child is refused rather than racing the close.

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
// start an interactive child is refused rather than racing the close.

// to schedule it in. Each task is observed *outside* its child: a replayed
// completed pane returns its retained outcome without entering a body, a
// shell, or a launcher, and that outcome is what publishes its status and
// satisfies the readiness barrier.

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
// satisfies the readiness barrier.

…730)
**`Symbol.asyncDispose` bypassed the deliberate-stop evidence.** The task
`durableSpawn` returns copied it from the original unchanged, so
`await using` — or an explicit `task[Symbol.asyncDispose]()` — recorded
`cancellation: "unwound"` and the next run revived the child. `halt()` and
the async dispose are the same decision spelled two ways, and both are now
observed. Awaiting a task is not a stop and is left exactly as it was. A
regression disposes a live task, asserts the retained reason is `"caller"`,
resumes the journal, and proves the body is not entered again.
**Reader close no longer halts panes.** It asks them to stop: a pane races
its work against a close signal, settles as `closed`, and records that
outcome as its own. Nothing on the ordinary close path is a caller-cancelled
child any more, so a resumed run restores a pane the reader closed rather
than finding a cancelled child it must either re-enter or wait on forever.
Statuses are published before anything is awaited, so a pane with slow
finalizers cannot delay the outcome the grid already knows.
**§6.21 now agrees with architecture.md and TG17.** Partial replay compares
the resolved layout — columns and titles. Pane count, order and form come
from the retained root and cannot diverge within a continuation, so a
changed supplied file is ignored in favour of the retained structure;
refusing a changed authored structure is a root-definition boundary this
specification does not yet define.
DEC-040 is unchanged and nothing deliberately stopped is revived.

@github-actionsgithub-actionsBot 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 18 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

*destroy() {
// Destroying twice would make the record say a composite was taken down
// more times than it was built, which is exactly the ordering claim a
// suite reads this log 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
// suite reads this log for.

@github-actionsgithub-actionsBot 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 20 redundant comments. Inline suggestions to remove them below.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

},
ready() {
// Idempotent by construction: readiness is a fact about the pane, and a
// provider that reports the same spawn twice has not started two panes.

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 that reports the same spawn twice has not started two panes.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

const cancellation = members.get("cancellation");
if (cancellation === undefined) {
// A record written before this evidence existed. DEC-040 reads the
// absence as a deliberate stop, so nothing it left behind is revived.

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
// absence as a deliberate stop, so nothing it left behind is revived.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

*destroy() {
// Destroying twice would make the record say a composite was taken down
// more times than it was built, which is exactly the ordering claim a
// suite reads this log 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
// suite reads this log for.

@taras
tarasforce-pushed the agent/issue-730-terminal-execution branch from 8f85400 to eb92602CompareSeptember 2, 2026 22:38

@github-actionsgithub-actionsBot 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 9 redundant comments. Inline suggestions to remove them below.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

}
for (const [index] of work.entries()) {
// Awaited, not halted. Each pane settles on the close signal and records
// the outcome it reached, which is what a resumed run reads.

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 outcome it reached, which is what a resumed run reads.

// the reader leaves, this settles as `closed` straight away and the work
// comes down in the enclosing scope's own teardown — so a pane whose
// finalizers are slow cannot hold up the outcome the grid already knows,
// and the record a resumed run reads is written either way.

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
// and the record a resumed run reads is written either way.

return (function* (): Operation<Task<RetainedPaneOutcome>> {
const durable = yield* DurableContext.get();
if (durable === undefined) {
// No journal behind this run: an ordinary spawned child.

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
// No journal behind this run: an ordinary spawned child.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

Implements the amendment at 1833870 without revising it.
**The live handshake.** `composite.closed()` settling now only *proposes* the
boundary. The grid's durable child publishes that proposal and waits; the
owner awaiting the child acknowledges it; and only then does the grid seal
admission and ask its panes to close. The handshake is one live rendezvous —
no provider identity, nothing journaled.
**Committing an outcome before the scope finishes unwinding.** A durable
child can now declare its terminal value, and `runDurableChild` records that
value if the child never reaches a normal ending. That is the piece the
contract needs: the grid commits its retained record as the boundary is
crossed, and each pane live at that moment commits `closed`, so a
cancellation arriving while pane and provider finalizers are still running
records what close decided rather than a cancellation. Committing is live
state; it reaches the journal only as the ordinary `Close`. A child that
returns or throws normally overrides it, and a child that never committed
still records the cancellation it actually reached — DEC-040 untouched.
Cancellation stays deferred because Effection completes a child's teardown —
pane finalizers, provider destroy, terminal restoration, lease release, the
`Close` append and the task's settlement — before the halt reaches the owner.
**Pane work stays inside its ordinal-derived durable child.** Reader close
asks the pane to close; it never halts the pane's durable task. The pane
commits `closed`, stops its live nested work through its own scope, and
settles only once that work and its finalizers have settled.
No durable closing marker was added, and completed replay is unchanged.

@github-actionsgithub-actionsBot 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 11 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

// neither can begin while the other holds it.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

// grid covers it up.
yield* flushOutput();

// Routed, and the answer thrown away.

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
// Routed, and the answer thrown away.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.


const grid = createTerminalGridClaims(request);
// Nothing new is admitted once teardown begins, so a pane that was about to
// start an interactive child is refused rather than racing the close.

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
// start an interactive child is refused rather than racing the close.

Implements architecture 1833870 at the owner boundary. The grid's durable
child now runs in a scope of its own — a child of the owner's, so it inherits
every context the document runs under, and its own so that tearing the owner
down does not reach it first. A finalizer registered after that scope exists
runs before it is destroyed, and that is the cancellation-deferred await: once
the owner has acknowledged the provider's close proposal, the grid and its panes
finish teardown and append their ordinary completed Close records, and only then
does the cancellation carry on to the parent.
Removes the exported CommitOutcome/durableSpawn(commit) API. Cancellation is
never turned into success inside runDurableChild; durableSpawnIn only says where
a child lives, and grants nothing a caller does not already have.
TG19 proves the ordering with signals alone: a live pane arms a blocking
finalizer, the reader leaves, the finalizer is entered and held, cancellation
begins, the finalizer is released, and the run ends with the composite destroyed,
a completed grid Close retained, the live pane retained as closed — and the
sibling after the grid never reached. The continuation then replays past it with
no provider, no pane body and no finalizer re-entered.
TG6 isolates paired-pane sequencing on its own: the reader leaves only once the
pane's second component has run.
The production lifecycle is unchanged. TG19 now reads counters and journal
records rather than a log's shape.
The controlled composite keeps live resource counters — composites prepared,
composites attached, shells started — each raised when it takes something and
lowered when it gives it back, however it left. TG19 reads them once while a
pane finalizer is blocked, so it knows they went up, and again when the
cancellation has completed, so it knows they came back down.
The harness now says when a blocked finalizer *leaves*, not only when it is
entered: a finalizer that was entered and then cancelled reaches the first hook
and never the second. And after every interrupted run it takes the foreground
lease and gives it back twice — the first proves the grid returned it, the
second proves the harness did.
TG19 adds: one grid Close(ok) retaining close: "reader"; two pane Closes, both
completed, with no cancellation recorded at either level; the finalizer entered
and left exactly once; destroy:0 exactly once. The first-attempt claim that no
following sibling ran and the replay tripwires are unchanged.
Every one of these was broken on purpose and re-run: dropping any of the three
counter releases, the deferral, the finalizer-exit hook, or double-logging
destroy fails TG19, and a second holder of the foreground lease is refused.
Sign up for freeto 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

@taras
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

✨ Execute concurrent terminal panes through a replaceable provider (#730) - #738

Open
taras wants to merge 15 commits into
agent/issue-729-terminal-gridfrom
agent/issue-730-terminal-execution
Open

✨ Execute concurrent terminal panes through a replaceable provider (#730)#738
taras wants to merge 15 commits into
agent/issue-729-terminal-gridfrom
agent/issue-730-terminal-execution

Conversation

@taras

@tarastaras commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes#730. Second implementation Story under Quest #717, stacked on #733.

Base is agent/issue-729-terminal-grid, not main, as the Story's verification stack directs. Branched from 97be06321cbdf08d84ef53dbefb88407f54326fe, the reviewed head of #733.

Why

#729 froze the language: an author can write a terminal grid, and every runtime can validate one. Nothing could run one. This Story makes a grid execute, through a boundary a host replaces — so the document keeps one lifecycle contract whether the presentation is tmux, a controlled test surface, or something native later.

What changes

Before: a valid <Terminal.Grid> derived its layout and refused, because nothing could present it.

After: it runs. Core takes the run's one foreground-terminal lease, flushes root output, prepares the composite while it stays hidden, starts every pane concurrently, and attaches only once every pane has actually started.

<Terminal.Grid columns={2}>
<Terminaltitle="Agent">…</Terminal>
<Terminaltitle="Shell" />
</Terminal.Grid>

How it works

lease → flush → prepare (hidden) → panes start concurrently
→ readiness barrier → attach → panes settle independently
→ reader closes → teardown → lease released

packages/runtime/terminal.ts is the replaceable seam. The request is provider-neutral — columns, rows, and the authored panes with their derived positions — and names no terminal, socket, process or window. Middleware may observe, narrow, refuse, wrap or delegate. Presentation never decides an outcome: update() receives states core has already settled on, and its return value is ignored.

packages/core/src/terminal/authority.ts mints one-use pane claims for one request's ordinals. A claim admits one interactive operation at a time on its pane and holds that pane's readiness latch. Two claims do not contend, which is what lets panes stay interactive together.

packages/core/src/terminal/pane.ts is the seam anything interactive inside a pane reaches, so it runs as that pane's owner instead of competing for the root lease. Absence means "not in a pane".

packages/core/src/terminal/grid.ts owns the lifecycle. The lease and the composite are both scope-owned, so success, failure and cancellation all release the terminal and destroy exactly the composite that was prepared — there is no path that skips teardown.

Review guide

Start with:packages/core/tests/terminal-grid.test.ts

Then review:

  1. packages/runtime/terminal.ts — the boundary and what a handler may do.
  2. packages/core/src/terminal/authority.ts — claims, contention, the readiness latch.
  3. packages/core/src/terminal/grid.ts — the ordering, and where teardown is registered.
  4. packages/core/src/expand.tspaneWork(), which is where a pane's isolation is established.

Look carefully at:

  • The order in runTerminalGrid(). ensure(() => composite.destroy()) is registered before any pane starts, so a composite that was prepared is owed a destroy even if the next line fails.
  • The attached flag. Before the barrier a pane failure fails the whole grid closed; after it, the failure is that pane's status and its siblings keep running.
  • paneWork()'s paired branch: ActiveLoop.set(undefined), a derived env, containedLedger(), and undefined for the return body are the four things that make a pane a scope rather than a region.

What must stay true

  • Nothing is shown before every pane has started — enforced by racing the readiness barrier against startup failure, checked by the TG9 ordering row, which was verified by deleting the barrier: it fails without it.
  • A prepared composite is always destroyed exactly once — enforced by scope-owned ensure, checked by TG12 and by the controlled composite refusing a second destroy.
  • Presentation decides nothing — enforced by update() returning void and claims never leaving core, checked by the middleware rows in the provider suite.
  • A pane's later bindings stay in that pane — enforced by a derived environment, checked by the TG6 document row asserting the sibling and the document after the grid still see the binding unresolved.

How to verify it

deno task test packages/core/tests/terminal-grid.test.ts
deno task test packages/runtime/tests/terminal-provider.test.ts
deno task test packages/core/tests/terminal-grid-structure.test.ts
  • TG8 proves one claim admits one interactive operation at a time and two claims do not contend; it fails if a pane admitted twice, or if two panes serialized.
  • TG9 proves nothing attaches until every pane reports a spawn, and that a pane which settles without one fails startup; it fails if a grid attached early or presented a pane that never started.
  • TG10 proves a pane can fail after attach while a sibling is provably still live, and the grid reports the first failed authored ordinal.
  • TG12/TG13 prove close and parent cancellation both destroy the composite exactly once, and that a pane cancelled by the close is closed rather than failed.
  • TG6/TG7 prove pane scope and output routing through the real execute() path.
  • The provider suite proves the boundary refuses with nothing installed, and that middleware can observe, narrow, refuse and wrap without being able to authorize.

Whole Deno core suite: 350 passed. Runtime suite: 14 passed.

Scope

Included

  • The provider boundary, the terminal authority and pane claims, the readiness latch, the pane seam, and the grid lifecycle.
  • Pane scope isolation, pane output routing, concurrent start, atomic attach, independent settlement, close and cancellation teardown.

Not included — this Story is not finished

These acceptance points landed in later commits on this branch, and the section
that once said durability was absent is no longer true:

  • Durability and replay (TG15–TG17) are implemented. The grid is one durable
    child and each pane is its own durable child allocated in authored ordinal
    order. A completed region replays its exact retained result — successful and
    contained-failed alike — contacting no provider and running no pane content,
    shell or launcher. An interrupted region rebuilds a fresh composite. The
    layout is recorded in the parent coroutine before the lease and before any
    provider is contacted, and a malformed retained layout refuses there.
  • TG17 is scoped to what a continuation can actually change. A continuation
    executes the retained root, so pane count, order and form cannot differ and
    are proved retained-and-honoured rather than refused; columns and each
    title reach the grid through props, which are not restored, and each refuses
    independently with zero provider observation.
  • durableSpawn was repaired to make any of this possible: its task now
    outlives the call, and a cancelled child records why it stopped (DEC-040) so
    a deliberately halted region is never revived while an interrupted one
    resumes.

What remains outside this PR:

  • TG14's bounded teardown proof belongs to the tmux provider Story; the
    controlled provider cannot exercise it.
  • TG5 and Agent-session contention in TG11 belong to the native-launch
    Story, as the issue states.
  • One known gap: a run interrupted while reader-close teardown is awaiting
    a pane whose own finalizer is slow
    leaves that pane recorded as unwound
    rather than closed, so a resumed run re-enters it. Reader close is now
    cooperative — panes are asked to stop and record closed themselves rather
    than being halted — which removes caller-cancelled panes from the ordinary
    close path, but the blocked-finalizer overlap is not yet covered by a
    regression.

Intentionally unchanged

  • No tmux command, multiplexer, or real terminal anywhere in this change.

New abstractions

  • TerminalProvider / TerminalComposite exist because a grid's presentation has to be replaceable; the controlled provider and the future tmux adapter are the two concrete uses.

  • TerminalPaneClaim exists because pane terminal ownership must be unforgeable and per-ordinal; consumed by the grid and by the pane seam.

  • PaneTerminal exists because interactive work inside a pane must not compete for the root lease; consumed by the suite's controlled interactive child now and by <Session.Launch> in Launch native Agent sessions in independent terminal panes #731.

  • Each new abstraction has multiple concrete uses or a clear justification.

  • No speculative functionality is included.

Risks and limitations

  • Incomplete Story, stated above. Durability and replay are absent.
  • Five rows from ✨ Describe terminal grids as executable document structure (#729) #733 moved into this Story's suite. The move was authorized explicitly rather than assumed, and every claim they made is still asserted — against the provider request, which is stronger evidence than reading a layout off a refusal's cause.
  • A stray <Break> inside a pane fails the pane rather than printing as it would at the root. That is consistent with the pane-settlement contract, but it is a behavioural difference worth a reviewer's eye.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

The replaceable seam a terminal grid executes through, before any of the
execution that uses it.
`packages/runtime/terminal.ts` is the contextual provider: `prepare()`
builds the whole composite while it stays hidden, `attach()` shows it once
every pane is ready, and `destroy()` gives the root terminal back. The
request is provider-neutral — columns, rows, and the authored panes with
their derived positions — and names no terminal, socket, process or window.
Middleware may observe, narrow, refuse, wrap or delegate; presentation
never decides an outcome, so `update()` receives states core has already
settled on.
`packages/core/src/terminal/authority.ts` mints one-use pane claims for one
request's ordinals. A claim admits one interactive operation at a time on
its pane and holds that pane's readiness latch. Two claims do not contend,
which is what lets panes stay interactive together.
`packages/core/src/terminal/pane.ts` is the seam interactive work inside a
pane reaches for, so it runs as that pane's owner instead of competing for
the root foreground lease. Absence means "not in a pane".
Evidence: `packages/runtime/tests/terminal-provider.test.ts`, 11 rows.
`runTerminalGrid()` owns the lifecycle the reader sees: it takes the run's
one foreground-terminal lease, flushes root output, prepares the composite
while it stays hidden, starts every pane concurrently, and attaches only
once every pane has reported a spawn through its claim.
Ordering is the contract. The lease and the composite are both scope-owned,
so success, failure and cancellation all release the terminal and destroy
exactly the composite that was prepared — there is no path that skips
teardown. A pane that settles without ever reporting a spawn fails startup
rather than being presented as a running pane. Before the barrier a pane
failure fails the whole grid closed; after it, the failure is that pane's
status and its siblings keep running. Close cancels a live pane as `closed`,
which is not a failed pane, and the grid fails with the first failed pane in
authored order.
`display()` and an `onUpdate` hook complete the provider surface: a pane's
rendered text goes to that pane, and a suite reacts to a state the grid
decided rather than waiting and hoping.
Evidence: `packages/core/tests/terminal-grid.test.ts` (15 rows) and
`packages/runtime/tests/terminal-provider.test.ts` (11 rows). The readiness
barrier row was verified by removing the barrier: it fails without it.
`<Terminal.Grid>` now executes. Each authored pane becomes a concurrent
child of the grid: a self-closing pane runs the host's default shell
through its claim, and a paired pane expands its own content in a scope of
its own.
A pane inherits the bindings, providers, configuration and working
directory visible where the grid was written, and keeps everything it
creates afterwards. Its `<Break>` has no loop to exit, its `<Return>` has
no enclosing value body to claim, and its checked failures settle the pane
rather than reaching the root or a sibling. A pane's rendered text is
displayed in that pane; the grid itself renders `""`, so the root output
holds what surrounds the grid and no pane display at all.
#729's five execution-dependent rows move here, where they assert the
layout against the request the provider actually receives rather than
reading it off a refusal's cause — the structural suite keeps the grammar,
placement and pure-layout rows it owns. Moving them was authorized rather
than assumed.
Evidence: 22 rows in `packages/core/tests/terminal-grid.test.ts` and 11 in
`packages/runtime/tests/terminal-provider.test.ts`; the whole Deno core
(350) and runtime (14) suites pass.
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown

PR #738: ✨ Execute concurrent terminal panes through a replaceable provider (#730)

26 files, +5399 / -226

Scope

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

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

🟡 26 files changed. Are all changes related?

🟡 New abstraction files: packages/core/src/terminal/provider-api.ts. Verify 3+ consumers.

Structural

Oxlint structural signals:

  • no-unnecessary-type-assertion ×11: packages/core/src/terminal/journal.ts, packages/durable-streams/retained.ts, packages/durable-streams/combinators.ts (+2)
  • no-unused-vars ×7: packages/core/src/expand.ts

Slop

  • packages/durable-streams/combinators.ts:168 (removed)

Oxlint slop signals:

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

Static Analysis

Oxlint: 43 diagnostics across 5 files (12 rules)
Density: 0.008 violations/added-line

no-unnecessary-type-assertion (11): packages/core/src/terminal/journal.ts, packages/durable-streams/retained.ts, packages/durable-streams/combinators.ts (+2)
no-unsafe-type-assertion (9): packages/durable-streams/combinators.ts, packages/durable-streams/retained.ts, packages/core/src/expand.ts
no-unused-vars (7): packages/core/src/expand.ts
no-base-to-string (4): packages/core/src/expand.ts
no-floating-promises (3): packages/core/src/terminal/grid.ts
no-inferrable-types (2): packages/core/src/expand.ts
unbound-method (2): packages/core/src/expand.ts
no-shadow (1): packages/core/src/expand.ts
no-useless-fallback-in-spread (1): packages/core/src/expand.ts
no-unnecessary-type-parameters (1): packages/durable-streams/retained.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.

`paneWork()` never read the grid element it was handed. Its caller has it,
and a pane's own diagnostics are positioned at the pane.

@github-actionsgithub-actionsBot 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 10 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

),
0,
// The pane's own ledger: a checked failure settles this pane and
// cannot reach the root or a sibling.

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
// cannot reach the root or a sibling.

// and a host with no terminal refuses here — before any pane has done work.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

Comment threadpackages/core/src/terminal/grid.ts Outdated
yield* pane.run(claim, composite);
if (!readiness.acknowledged) {
// Settled without ever starting: that is a startup failure even
// though the work itself raised nothing.

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
// though the work itself raised nothing.

attached = true;

// The composite stays visible after its panes settle. The reader leaving is
// what finishes the grid, not the last pane exiting.

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
// what finishes the grid, not the last pane exiting.

Comment threadpackages/runtime/terminal.ts Outdated
export const TerminalProvider: Api<TerminalProviderHandler> = createApi<TerminalProviderHandler>(
"runtime.terminalProvider",
{
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

Comment threadpackages/runtime/terminal.ts Outdated
}
log.events.push(`attach:${generation}`);
},
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

Comment threadpackages/runtime/terminal.ts Outdated
log.events.push(`state:${generation}:${ordinal}:${state}`);
options.onUpdate?.(ordinal, state);
},
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

…#730)
Restores the authority boundary on the `AgentProviders` handshake, and puts
each pane on its own durable child coroutine.
**The boundary.** `TerminalGrids` is routing and only routing: `open()`
answers `unknown` and core throws the answer away, so middleware may
observe, narrow, refuse, wrap or delegate but can never authorize. The
capability that takes the leases, mints pane claims and settles a grid is a
non-contextual authority delivered straight to the registered provider
through a one-use install handshake. Core mints one identity-bearing request
per expansion; presenting a copy, a rebuilt lookalike, a changed request, an
already-presented one, or one from a superseded installation generation
authorizes nothing, and a handler that answers without presenting settles
nothing.
**Durable children.** Each pane is a durable child of the grid, allocated in
authored order, so a pane's identity follows its ordinal rather than the
order the runtime scheduled it in. The layout is recorded in the parent
coroutine before the lease and before any provider is contacted.
**Ordering.** A pane that settles before attach keeps the status it settled
to instead of being overwritten with `running`, and simultaneous startup
failures are selected by authored ordinal rather than by whichever rejected
first. Each pane also expands under a counter of its own, so two concurrent
panes cannot take block identities that depend on which ran first.
`durableSpawn` could not be used: the task it returns is spawned inside the
ephemeral effect's own scope, which closes as the effect resolves, so
awaiting it throws `halted`. It has no call sites or tests upstream.
`durableAll` is the exercised primitive and is what the panes and the grid
child use.
Evidence: 30 rows in `packages/core/tests/terminal-grid.test.ts` and 10 in
`packages/runtime/tests/terminal-provider.test.ts`; core 349, runtime 15.

@github-actionsgithub-actionsBot 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 9 redundant comments. Inline suggestions to remove them below.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.

attached = true;

// The composite stays visible after its panes settle. The reader leaving is
// what finishes the grid, not the last pane exiting.

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
// what finishes the grid, not the last pane exiting.

yield* pane.run(claim, composite);
if (!readiness.acknowledged) {
// Settled without ever starting: a startup failure even though the work
// itself raised nothing.

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
// itself raised nothing.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

`durableSpawn` returned a task spawned inside the `ephemeral` effect's own
scope, and that scope closed as the effect resolved — so every
`yield* task` threw `halted`. It had no call sites and no tests. It now
starts the child in the routine's own scope, so the task outlives the call
and can be awaited or halted by whoever asked for it.
A retained `Close(cancelled)` meant one thing to the code and two things in
practice. Under `durableRace` and `durableAll` it is a race loser or a
fail-fast sibling, and the same combinator cancels it again — those keep
DEC-024 exactly. Under `durableSpawn` nobody cancels it a second time, so
suspending hung the resumed run forever. `runDurableChild` now takes an
explicit `CancelledChildPolicy`, fixed at each combinator's call site and
never chosen by a caller. Resuming uses a new internal
`ReplayIndex.reopen()`, which forgets one coroutine's retained Close while
keeping its yields — so the child continues its own history rather than
restarting, and the divergence guard stops reading the remaining effects as
a coroutine continuing past its own close. Neither it nor `disableReplay` is
exported.
DEC-039 records the policy and marks DEC-024's invariant as superseded in
part: it assumed every cancelled child belongs to race or all.
The grid uses the repaired primitive: the whole grid is one durable child,
each pane is its own durable child allocated in authored ordinal order, and
each pane task is observed outside its child — so a replayed pane's retained
outcome publishes its status and satisfies the readiness barrier without
entering a body, a shell, or a launcher.
Evidence: 9 rows in `packages/durable-streams/tests/durable-spawn.test.ts`
(lifetime, completed replay, interrupted resume, retained-history
continuation, and both combinators keeping their own policy); 30 rows in
`packages/core/tests/terminal-grid.test.ts`. durable-streams 32, core 349,
runtime 15.

@github-actionsgithub-actionsBot 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 15 redundant comments. Inline suggestions to remove them below.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

return (function* (): Operation<Task<RetainedPaneOutcome>> {
const durable = yield* DurableContext.get();
if (durable === undefined) {
// No journal behind this run: an ordinary spawned child.

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
// No journal behind this run: an ordinary spawned child.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

Two decisions exposed while implementing #730, and no implementation.
**DEC-040 — a cancelled child records why.** DEC-039's `"resume"` fired on
every retained `Close(cancelled)` under an incomplete parent, which revives
work a caller deliberately halted: the record of a deliberate `task.halt()`
and the record of an interrupted run are the same event. The cancelled close
now carries `cancellation: "caller"` or `"unwound"`, written by whichever
path cancelled the child, and `"resume"` continues only `"unwound"`. A
deliberate stop suspends, which is DEC-024's reproduction argument applied
to a caller instead of a combinator; a legacy record with no reason reads as
`"caller"`, because refusing to revive is the safe direction. The reason is
retained evidence, not authority: nothing outside `runDurableChild` reads
it, and no caller chooses a policy.
Terminal grids need nothing wider. A grid halts its pane tasks at close, so
those retain `"caller"` — and the grid child completes, so a resumed run
short-circuits the region and never reaches them. The case that must resume,
an interrupted run, unwinds and retains `"unwound"`.
**TG17 narrows to the resolved layout.** A continuation executes the root the
journal retained; the supplied source is not read, compared or refused
(proved in #722). A grid's authored structure — pane count, order, form — is
therefore fixed for the life of a journal and cannot differ between runs, so
comparing it compares a value with itself, which is why the refusal never
fired. What a fixed retained document still resolves differently is
`columns` and each `title`, through prop-borne values, since props are not
restored. Those refuse before the lease and before provider contact.
Authored-structure change is a root-definition compatibility question, not a
grid one. Root-definition authority is preserved rather than overridden by a
pre-replay comparison against the current file, and the versioned root
boundary that would refuse a changed source stays open work.
**DEC-040.** A cancelled Close now records why: `cancellation: "caller"`
when the owner halts the task `durableSpawn` returned, `"unwound"` for
anything involuntary. `durableSpawn` resumes only `"unwound"`; a deliberate
stop suspends until the caller's deterministic control flow halts it again,
and a record with no reason reads as `"caller"` so nothing legacy is
revived. `durableAll` and `durableRace` keep DEC-024 whatever the reason
says.
The halt is intercepted without changing the public `Task` surface: the
returned task carries every member the real one defines, copied with its
prototype, and only `halt` is replaced. A proxy cannot do this — a task's
members are read-only and non-configurable, so a `get` trap is required to
hand back exactly what the target holds.
The reason had to survive three boundaries that were dropping it: the
protocol parser, the observable copy, and — the one that actually mattered —
`detachResult`, which froze every cancellation down to `{ status }`.
**TG15.** The harness's `attached` and `pastGrid` signals are now separate,
and a run that expects its grid to complete waits for the sibling *after*
the grid before halting the root at `<Hold />`. That is what leaves a
completed grid child under an incomplete root, which is the only state in
which a completed region can be observed replaying at all. Both a successful
grid and a contained failed one replay their exact retained result with no
provider, pane content, shell or launcher work, and each row asserts the
grid child genuinely recorded a terminal close. No timeouts.
**TG17.** Prop-borne `columns` and `title` change independently against one
fixed retained document — the only things a fixed retained root can still
resolve differently — and each refuses with zero provider observation. For
supplied-file changes to pane count, order and form, the continuation opens
the retained structure rather than the file's, asserted request-for-request.
The retained record carries every authored pane's ordinal, title, form and
derived position.
`readLayout()` parses totally: the layout object and every pane field, with
missing, extra, mistyped, out-of-position and self-inconsistent records all
refused rather than half-read.
Evidence: durable-spawn 14 rows, terminal-grid 36 rows, structural 13,
provider 10. Packages: durable-streams 33, core 349, runtime 15,
workflow 172.
#730)
**The harness cannot pass a hung replay any more.** `runInterrupted()` had a
1500ms timer racing its signals, so a replay that hung returned a
DocumentRun that looked finished; it also slept a fixed 5ms to let records
land. Both are gone. It now waits only on events the run produced:
`attached`, `pastGrid`, and a new `panesSettled` for the rows that read pane
records — a pane's status is published only after its durable child returned,
so counting settled panes is also counting durable pane closes. A replay
that hangs now reaches none of them and hangs the row.
**TG15's failed case is a real contained failure.** A pane that fails before
attachment fails the whole region, so the old document could not both fail
and continue. The failing pane is now a shell that starts, waits for
attachment, and only then exits badly — contained as that pane's status,
with the grid settling as failed and the document carrying on. Both runs
capture the printed errors, and the row asserts the replayed run produced
the same ones, reached `PAST_THE_GRID`, and did no provider, pane, shell or
launcher work.
**DEC-040 gets boundary tests where the evidence actually travels.**
`parse.test.ts` round-trips both reasons to the same bytes, keeps a legacy
absence absent, and refuses an unrecognised reason at `$.result.cancellation`.
`retained.test.ts` proves retention and `consumable()` carry both reasons,
leave a legacy absence absent, drop an unrecognised one to the safe default,
and that the reason reaches the replay index. The DEC-040 rows in
`durable-spawn.test.ts` no longer coordinate by delay: a child says when it
is running, and the caller says when it has halted.
**Malformed retained layouts** are covered by replaying a real journal with
only its layout entry replaced — a missing member, an extra one, a mistyped
one, a pane out of position, and a record that disagrees with itself. Each
refuses with zero provider observation.
The `durableSpawn` doc comment no longer says every retained cancellation is
an interrupted run.
The DEC-040 block still slept where it meant to synchronise — my previous
replacements silently failed to match after the file was reformatted, so
none of them landed. The block is rewritten rather than patched.
Every row now waits on something the run reported. A shared `living()` child
resolves a `started` signal and then suspends, so each row halts or unwinds a
child that is provably live rather than one a delay happened to reach. The
caller resolves `halted` after performing its deliberate halt, so a run is
interrupted only once both facts — the deliberate stop and the interruption —
are in the journal.
Non-revival is established by control flow rather than by waiting: the
resumed run reaches its own `task.halt()` and says so, and a revived child
would have recorded its mark before the caller could get there. The
legacy-absence row signals once the child has been asked for and the request
returned. No new timeout, and `sleep` stays imported because the lifetime
rows above still use it deliberately.
`retained.test.ts` drops the cast and the row it supported: rejecting an
unrecognised reason is the parser's, proved there, and retention proves only
that `"caller"`, `"unwound"` and a legacy absence survive.

@github-actionsgithub-actionsBot 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 11 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

// neither can begin while the other holds it.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

// grid covers it up.
yield* flushOutput();

// Routed, and the answer thrown away.

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
// Routed, and the answer thrown away.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.


const grid = createTerminalGridClaims(request);
// Nothing new is admitted once teardown begins, so a pane that was about to
// start an interactive child is refused rather than racing the close.

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
// start an interactive child is refused rather than racing the close.

// to schedule it in. Each task is observed *outside* its child: a replayed
// completed pane returns its retained outcome without entering a body, a
// shell, or a launcher, and that outcome is what publishes its status and
// satisfies the readiness barrier.

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
// satisfies the readiness barrier.

…730)
**`Symbol.asyncDispose` bypassed the deliberate-stop evidence.** The task
`durableSpawn` returns copied it from the original unchanged, so
`await using` — or an explicit `task[Symbol.asyncDispose]()` — recorded
`cancellation: "unwound"` and the next run revived the child. `halt()` and
the async dispose are the same decision spelled two ways, and both are now
observed. Awaiting a task is not a stop and is left exactly as it was. A
regression disposes a live task, asserts the retained reason is `"caller"`,
resumes the journal, and proves the body is not entered again.
**Reader close no longer halts panes.** It asks them to stop: a pane races
its work against a close signal, settles as `closed`, and records that
outcome as its own. Nothing on the ordinary close path is a caller-cancelled
child any more, so a resumed run restores a pane the reader closed rather
than finding a cancelled child it must either re-enter or wait on forever.
Statuses are published before anything is awaited, so a pane with slow
finalizers cannot delay the outcome the grid already knows.
**§6.21 now agrees with architecture.md and TG17.** Partial replay compares
the resolved layout — columns and titles. Pane count, order and form come
from the retained root and cannot diverge within a continuation, so a
changed supplied file is ignored in favour of the retained structure;
refusing a changed authored structure is a root-definition boundary this
specification does not yet define.
DEC-040 is unchanged and nothing deliberately stopped is revived.

@github-actionsgithub-actionsBot 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 18 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

*destroy() {
// Destroying twice would make the record say a composite was taken down
// more times than it was built, which is exactly the ordering claim a
// suite reads this log 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
// suite reads this log for.

@github-actionsgithub-actionsBot 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 20 redundant comments. Inline suggestions to remove them below.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

},
ready() {
// Idempotent by construction: readiness is a fact about the pane, and a
// provider that reports the same spawn twice has not started two panes.

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 that reports the same spawn twice has not started two panes.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

const cancellation = members.get("cancellation");
if (cancellation === undefined) {
// A record written before this evidence existed. DEC-040 reads the
// absence as a deliberate stop, so nothing it left behind is revived.

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
// absence as a deliberate stop, so nothing it left behind is revived.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

*destroy() {
// Destroying twice would make the record say a composite was taken down
// more times than it was built, which is exactly the ordering claim a
// suite reads this log 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
// suite reads this log for.

@taras
tarasforce-pushed the agent/issue-730-terminal-execution branch from 8f85400 to eb92602CompareSeptember 2, 2026 22:38

@github-actionsgithub-actionsBot 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 9 redundant comments. Inline suggestions to remove them below.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

}
for (const [index] of work.entries()) {
// Awaited, not halted. Each pane settles on the close signal and records
// the outcome it reached, which is what a resumed run reads.

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 outcome it reached, which is what a resumed run reads.

// the reader leaves, this settles as `closed` straight away and the work
// comes down in the enclosing scope's own teardown — so a pane whose
// finalizers are slow cannot hold up the outcome the grid already knows,
// and the record a resumed run reads is written either way.

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
// and the record a resumed run reads is written either way.

return (function* (): Operation<Task<RetainedPaneOutcome>> {
const durable = yield* DurableContext.get();
if (durable === undefined) {
// No journal behind this run: an ordinary spawned child.

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
// No journal behind this run: an ordinary spawned child.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

Implements the amendment at 1833870 without revising it.
**The live handshake.** `composite.closed()` settling now only *proposes* the
boundary. The grid's durable child publishes that proposal and waits; the
owner awaiting the child acknowledges it; and only then does the grid seal
admission and ask its panes to close. The handshake is one live rendezvous —
no provider identity, nothing journaled.
**Committing an outcome before the scope finishes unwinding.** A durable
child can now declare its terminal value, and `runDurableChild` records that
value if the child never reaches a normal ending. That is the piece the
contract needs: the grid commits its retained record as the boundary is
crossed, and each pane live at that moment commits `closed`, so a
cancellation arriving while pane and provider finalizers are still running
records what close decided rather than a cancellation. Committing is live
state; it reaches the journal only as the ordinary `Close`. A child that
returns or throws normally overrides it, and a child that never committed
still records the cancellation it actually reached — DEC-040 untouched.
Cancellation stays deferred because Effection completes a child's teardown —
pane finalizers, provider destroy, terminal restoration, lease release, the
`Close` append and the task's settlement — before the halt reaches the owner.
**Pane work stays inside its ordinal-derived durable child.** Reader close
asks the pane to close; it never halts the pane's durable task. The pane
commits `closed`, stops its live nested work through its own scope, and
settles only once that work and its finalizers have settled.
No durable closing marker was added, and completed replay is unchanged.

@github-actionsgithub-actionsBot 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 11 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

// neither can begin while the other holds it.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

// grid covers it up.
yield* flushOutput();

// Routed, and the answer thrown away.

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
// Routed, and the answer thrown away.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.


const grid = createTerminalGridClaims(request);
// Nothing new is admitted once teardown begins, so a pane that was about to
// start an interactive child is refused rather than racing the close.

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
// start an interactive child is refused rather than racing the close.

Implements architecture 1833870 at the owner boundary. The grid's durable
child now runs in a scope of its own — a child of the owner's, so it inherits
every context the document runs under, and its own so that tearing the owner
down does not reach it first. A finalizer registered after that scope exists
runs before it is destroyed, and that is the cancellation-deferred await: once
the owner has acknowledged the provider's close proposal, the grid and its panes
finish teardown and append their ordinary completed Close records, and only then
does the cancellation carry on to the parent.
Removes the exported CommitOutcome/durableSpawn(commit) API. Cancellation is
never turned into success inside runDurableChild; durableSpawnIn only says where
a child lives, and grants nothing a caller does not already have.
TG19 proves the ordering with signals alone: a live pane arms a blocking
finalizer, the reader leaves, the finalizer is entered and held, cancellation
begins, the finalizer is released, and the run ends with the composite destroyed,
a completed grid Close retained, the live pane retained as closed — and the
sibling after the grid never reached. The continuation then replays past it with
no provider, no pane body and no finalizer re-entered.
TG6 isolates paired-pane sequencing on its own: the reader leaves only once the
pane's second component has run.
The production lifecycle is unchanged. TG19 now reads counters and journal
records rather than a log's shape.
The controlled composite keeps live resource counters — composites prepared,
composites attached, shells started — each raised when it takes something and
lowered when it gives it back, however it left. TG19 reads them once while a
pane finalizer is blocked, so it knows they went up, and again when the
cancellation has completed, so it knows they came back down.
The harness now says when a blocked finalizer *leaves*, not only when it is
entered: a finalizer that was entered and then cancelled reaches the first hook
and never the second. And after every interrupted run it takes the foreground
lease and gives it back twice — the first proves the grid returned it, the
second proves the harness did.
TG19 adds: one grid Close(ok) retaining close: "reader"; two pane Closes, both
completed, with no cancellation recorded at either level; the finalizer entered
and left exactly once; destroy:0 exactly once. The first-attempt claim that no
following sibling ran and the replay tripwires are unchanged.
Every one of these was broken on purpose and re-run: dropping any of the three
counter releases, the deferral, the finalizer-exit hook, or double-logging
destroy fails TG19, and a second holder of the foreground lease is refused.
Sign up for freeto 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

@taras
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

✨ Execute concurrent terminal panes through a replaceable provider (#730) - #738

Open
taras wants to merge 15 commits into
agent/issue-729-terminal-gridfrom
agent/issue-730-terminal-execution
Open

✨ Execute concurrent terminal panes through a replaceable provider (#730)#738
taras wants to merge 15 commits into
agent/issue-729-terminal-gridfrom
agent/issue-730-terminal-execution

Conversation

@taras

@tarastaras commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes#730. Second implementation Story under Quest #717, stacked on #733.

Base is agent/issue-729-terminal-grid, not main, as the Story's verification stack directs. Branched from 97be06321cbdf08d84ef53dbefb88407f54326fe, the reviewed head of #733.

Why

#729 froze the language: an author can write a terminal grid, and every runtime can validate one. Nothing could run one. This Story makes a grid execute, through a boundary a host replaces — so the document keeps one lifecycle contract whether the presentation is tmux, a controlled test surface, or something native later.

What changes

Before: a valid <Terminal.Grid> derived its layout and refused, because nothing could present it.

After: it runs. Core takes the run's one foreground-terminal lease, flushes root output, prepares the composite while it stays hidden, starts every pane concurrently, and attaches only once every pane has actually started.

<Terminal.Grid columns={2}>
<Terminaltitle="Agent">…</Terminal>
<Terminaltitle="Shell" />
</Terminal.Grid>

How it works

lease → flush → prepare (hidden) → panes start concurrently
→ readiness barrier → attach → panes settle independently
→ reader closes → teardown → lease released

packages/runtime/terminal.ts is the replaceable seam. The request is provider-neutral — columns, rows, and the authored panes with their derived positions — and names no terminal, socket, process or window. Middleware may observe, narrow, refuse, wrap or delegate. Presentation never decides an outcome: update() receives states core has already settled on, and its return value is ignored.

packages/core/src/terminal/authority.ts mints one-use pane claims for one request's ordinals. A claim admits one interactive operation at a time on its pane and holds that pane's readiness latch. Two claims do not contend, which is what lets panes stay interactive together.

packages/core/src/terminal/pane.ts is the seam anything interactive inside a pane reaches, so it runs as that pane's owner instead of competing for the root lease. Absence means "not in a pane".

packages/core/src/terminal/grid.ts owns the lifecycle. The lease and the composite are both scope-owned, so success, failure and cancellation all release the terminal and destroy exactly the composite that was prepared — there is no path that skips teardown.

Review guide

Start with:packages/core/tests/terminal-grid.test.ts

Then review:

  1. packages/runtime/terminal.ts — the boundary and what a handler may do.
  2. packages/core/src/terminal/authority.ts — claims, contention, the readiness latch.
  3. packages/core/src/terminal/grid.ts — the ordering, and where teardown is registered.
  4. packages/core/src/expand.tspaneWork(), which is where a pane's isolation is established.

Look carefully at:

  • The order in runTerminalGrid(). ensure(() => composite.destroy()) is registered before any pane starts, so a composite that was prepared is owed a destroy even if the next line fails.
  • The attached flag. Before the barrier a pane failure fails the whole grid closed; after it, the failure is that pane's status and its siblings keep running.
  • paneWork()'s paired branch: ActiveLoop.set(undefined), a derived env, containedLedger(), and undefined for the return body are the four things that make a pane a scope rather than a region.

What must stay true

  • Nothing is shown before every pane has started — enforced by racing the readiness barrier against startup failure, checked by the TG9 ordering row, which was verified by deleting the barrier: it fails without it.
  • A prepared composite is always destroyed exactly once — enforced by scope-owned ensure, checked by TG12 and by the controlled composite refusing a second destroy.
  • Presentation decides nothing — enforced by update() returning void and claims never leaving core, checked by the middleware rows in the provider suite.
  • A pane's later bindings stay in that pane — enforced by a derived environment, checked by the TG6 document row asserting the sibling and the document after the grid still see the binding unresolved.

How to verify it

deno task test packages/core/tests/terminal-grid.test.ts
deno task test packages/runtime/tests/terminal-provider.test.ts
deno task test packages/core/tests/terminal-grid-structure.test.ts
  • TG8 proves one claim admits one interactive operation at a time and two claims do not contend; it fails if a pane admitted twice, or if two panes serialized.
  • TG9 proves nothing attaches until every pane reports a spawn, and that a pane which settles without one fails startup; it fails if a grid attached early or presented a pane that never started.
  • TG10 proves a pane can fail after attach while a sibling is provably still live, and the grid reports the first failed authored ordinal.
  • TG12/TG13 prove close and parent cancellation both destroy the composite exactly once, and that a pane cancelled by the close is closed rather than failed.
  • TG6/TG7 prove pane scope and output routing through the real execute() path.
  • The provider suite proves the boundary refuses with nothing installed, and that middleware can observe, narrow, refuse and wrap without being able to authorize.

Whole Deno core suite: 350 passed. Runtime suite: 14 passed.

Scope

Included

  • The provider boundary, the terminal authority and pane claims, the readiness latch, the pane seam, and the grid lifecycle.
  • Pane scope isolation, pane output routing, concurrent start, atomic attach, independent settlement, close and cancellation teardown.

Not included — this Story is not finished

These acceptance points landed in later commits on this branch, and the section
that once said durability was absent is no longer true:

  • Durability and replay (TG15–TG17) are implemented. The grid is one durable
    child and each pane is its own durable child allocated in authored ordinal
    order. A completed region replays its exact retained result — successful and
    contained-failed alike — contacting no provider and running no pane content,
    shell or launcher. An interrupted region rebuilds a fresh composite. The
    layout is recorded in the parent coroutine before the lease and before any
    provider is contacted, and a malformed retained layout refuses there.
  • TG17 is scoped to what a continuation can actually change. A continuation
    executes the retained root, so pane count, order and form cannot differ and
    are proved retained-and-honoured rather than refused; columns and each
    title reach the grid through props, which are not restored, and each refuses
    independently with zero provider observation.
  • durableSpawn was repaired to make any of this possible: its task now
    outlives the call, and a cancelled child records why it stopped (DEC-040) so
    a deliberately halted region is never revived while an interrupted one
    resumes.

What remains outside this PR:

  • TG14's bounded teardown proof belongs to the tmux provider Story; the
    controlled provider cannot exercise it.
  • TG5 and Agent-session contention in TG11 belong to the native-launch
    Story, as the issue states.
  • One known gap: a run interrupted while reader-close teardown is awaiting
    a pane whose own finalizer is slow
    leaves that pane recorded as unwound
    rather than closed, so a resumed run re-enters it. Reader close is now
    cooperative — panes are asked to stop and record closed themselves rather
    than being halted — which removes caller-cancelled panes from the ordinary
    close path, but the blocked-finalizer overlap is not yet covered by a
    regression.

Intentionally unchanged

  • No tmux command, multiplexer, or real terminal anywhere in this change.

New abstractions

  • TerminalProvider / TerminalComposite exist because a grid's presentation has to be replaceable; the controlled provider and the future tmux adapter are the two concrete uses.

  • TerminalPaneClaim exists because pane terminal ownership must be unforgeable and per-ordinal; consumed by the grid and by the pane seam.

  • PaneTerminal exists because interactive work inside a pane must not compete for the root lease; consumed by the suite's controlled interactive child now and by <Session.Launch> in Launch native Agent sessions in independent terminal panes #731.

  • Each new abstraction has multiple concrete uses or a clear justification.

  • No speculative functionality is included.

Risks and limitations

  • Incomplete Story, stated above. Durability and replay are absent.
  • Five rows from ✨ Describe terminal grids as executable document structure (#729) #733 moved into this Story's suite. The move was authorized explicitly rather than assumed, and every claim they made is still asserted — against the provider request, which is stronger evidence than reading a layout off a refusal's cause.
  • A stray <Break> inside a pane fails the pane rather than printing as it would at the root. That is consistent with the pane-settlement contract, but it is a behavioural difference worth a reviewer's eye.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

The replaceable seam a terminal grid executes through, before any of the
execution that uses it.
`packages/runtime/terminal.ts` is the contextual provider: `prepare()`
builds the whole composite while it stays hidden, `attach()` shows it once
every pane is ready, and `destroy()` gives the root terminal back. The
request is provider-neutral — columns, rows, and the authored panes with
their derived positions — and names no terminal, socket, process or window.
Middleware may observe, narrow, refuse, wrap or delegate; presentation
never decides an outcome, so `update()` receives states core has already
settled on.
`packages/core/src/terminal/authority.ts` mints one-use pane claims for one
request's ordinals. A claim admits one interactive operation at a time on
its pane and holds that pane's readiness latch. Two claims do not contend,
which is what lets panes stay interactive together.
`packages/core/src/terminal/pane.ts` is the seam interactive work inside a
pane reaches for, so it runs as that pane's owner instead of competing for
the root foreground lease. Absence means "not in a pane".
Evidence: `packages/runtime/tests/terminal-provider.test.ts`, 11 rows.
`runTerminalGrid()` owns the lifecycle the reader sees: it takes the run's
one foreground-terminal lease, flushes root output, prepares the composite
while it stays hidden, starts every pane concurrently, and attaches only
once every pane has reported a spawn through its claim.
Ordering is the contract. The lease and the composite are both scope-owned,
so success, failure and cancellation all release the terminal and destroy
exactly the composite that was prepared — there is no path that skips
teardown. A pane that settles without ever reporting a spawn fails startup
rather than being presented as a running pane. Before the barrier a pane
failure fails the whole grid closed; after it, the failure is that pane's
status and its siblings keep running. Close cancels a live pane as `closed`,
which is not a failed pane, and the grid fails with the first failed pane in
authored order.
`display()` and an `onUpdate` hook complete the provider surface: a pane's
rendered text goes to that pane, and a suite reacts to a state the grid
decided rather than waiting and hoping.
Evidence: `packages/core/tests/terminal-grid.test.ts` (15 rows) and
`packages/runtime/tests/terminal-provider.test.ts` (11 rows). The readiness
barrier row was verified by removing the barrier: it fails without it.
`<Terminal.Grid>` now executes. Each authored pane becomes a concurrent
child of the grid: a self-closing pane runs the host's default shell
through its claim, and a paired pane expands its own content in a scope of
its own.
A pane inherits the bindings, providers, configuration and working
directory visible where the grid was written, and keeps everything it
creates afterwards. Its `<Break>` has no loop to exit, its `<Return>` has
no enclosing value body to claim, and its checked failures settle the pane
rather than reaching the root or a sibling. A pane's rendered text is
displayed in that pane; the grid itself renders `""`, so the root output
holds what surrounds the grid and no pane display at all.
#729's five execution-dependent rows move here, where they assert the
layout against the request the provider actually receives rather than
reading it off a refusal's cause — the structural suite keeps the grammar,
placement and pure-layout rows it owns. Moving them was authorized rather
than assumed.
Evidence: 22 rows in `packages/core/tests/terminal-grid.test.ts` and 11 in
`packages/runtime/tests/terminal-provider.test.ts`; the whole Deno core
(350) and runtime (14) suites pass.
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown

PR #738: ✨ Execute concurrent terminal panes through a replaceable provider (#730)

26 files, +5399 / -226

Scope

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

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

🟡 26 files changed. Are all changes related?

🟡 New abstraction files: packages/core/src/terminal/provider-api.ts. Verify 3+ consumers.

Structural

Oxlint structural signals:

  • no-unnecessary-type-assertion ×11: packages/core/src/terminal/journal.ts, packages/durable-streams/retained.ts, packages/durable-streams/combinators.ts (+2)
  • no-unused-vars ×7: packages/core/src/expand.ts

Slop

  • packages/durable-streams/combinators.ts:168 (removed)

Oxlint slop signals:

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

Static Analysis

Oxlint: 43 diagnostics across 5 files (12 rules)
Density: 0.008 violations/added-line

no-unnecessary-type-assertion (11): packages/core/src/terminal/journal.ts, packages/durable-streams/retained.ts, packages/durable-streams/combinators.ts (+2)
no-unsafe-type-assertion (9): packages/durable-streams/combinators.ts, packages/durable-streams/retained.ts, packages/core/src/expand.ts
no-unused-vars (7): packages/core/src/expand.ts
no-base-to-string (4): packages/core/src/expand.ts
no-floating-promises (3): packages/core/src/terminal/grid.ts
no-inferrable-types (2): packages/core/src/expand.ts
unbound-method (2): packages/core/src/expand.ts
no-shadow (1): packages/core/src/expand.ts
no-useless-fallback-in-spread (1): packages/core/src/expand.ts
no-unnecessary-type-parameters (1): packages/durable-streams/retained.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.

`paneWork()` never read the grid element it was handed. Its caller has it,
and a pane's own diagnostics are positioned at the pane.

@github-actionsgithub-actionsBot 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 10 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

),
0,
// The pane's own ledger: a checked failure settles this pane and
// cannot reach the root or a sibling.

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
// cannot reach the root or a sibling.

// and a host with no terminal refuses here — before any pane has done work.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

Comment threadpackages/core/src/terminal/grid.ts Outdated
yield* pane.run(claim, composite);
if (!readiness.acknowledged) {
// Settled without ever starting: that is a startup failure even
// though the work itself raised nothing.

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
// though the work itself raised nothing.

attached = true;

// The composite stays visible after its panes settle. The reader leaving is
// what finishes the grid, not the last pane exiting.

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
// what finishes the grid, not the last pane exiting.

Comment threadpackages/runtime/terminal.ts Outdated
export const TerminalProvider: Api<TerminalProviderHandler> = createApi<TerminalProviderHandler>(
"runtime.terminalProvider",
{
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

Comment threadpackages/runtime/terminal.ts Outdated
}
log.events.push(`attach:${generation}`);
},
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

Comment threadpackages/runtime/terminal.ts Outdated
log.events.push(`state:${generation}:${ordinal}:${state}`);
options.onUpdate?.(ordinal, state);
},
// deno-lint-ignore require-yield

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
// deno-lint-ignore require-yield

…#730)
Restores the authority boundary on the `AgentProviders` handshake, and puts
each pane on its own durable child coroutine.
**The boundary.** `TerminalGrids` is routing and only routing: `open()`
answers `unknown` and core throws the answer away, so middleware may
observe, narrow, refuse, wrap or delegate but can never authorize. The
capability that takes the leases, mints pane claims and settles a grid is a
non-contextual authority delivered straight to the registered provider
through a one-use install handshake. Core mints one identity-bearing request
per expansion; presenting a copy, a rebuilt lookalike, a changed request, an
already-presented one, or one from a superseded installation generation
authorizes nothing, and a handler that answers without presenting settles
nothing.
**Durable children.** Each pane is a durable child of the grid, allocated in
authored order, so a pane's identity follows its ordinal rather than the
order the runtime scheduled it in. The layout is recorded in the parent
coroutine before the lease and before any provider is contacted.
**Ordering.** A pane that settles before attach keeps the status it settled
to instead of being overwritten with `running`, and simultaneous startup
failures are selected by authored ordinal rather than by whichever rejected
first. Each pane also expands under a counter of its own, so two concurrent
panes cannot take block identities that depend on which ran first.
`durableSpawn` could not be used: the task it returns is spawned inside the
ephemeral effect's own scope, which closes as the effect resolves, so
awaiting it throws `halted`. It has no call sites or tests upstream.
`durableAll` is the exercised primitive and is what the panes and the grid
child use.
Evidence: 30 rows in `packages/core/tests/terminal-grid.test.ts` and 10 in
`packages/runtime/tests/terminal-provider.test.ts`; core 349, runtime 15.

@github-actionsgithub-actionsBot 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 9 redundant comments. Inline suggestions to remove them below.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.

attached = true;

// The composite stays visible after its panes settle. The reader leaving is
// what finishes the grid, not the last pane exiting.

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
// what finishes the grid, not the last pane exiting.

yield* pane.run(claim, composite);
if (!readiness.acknowledged) {
// Settled without ever starting: a startup failure even though the work
// itself raised nothing.

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
// itself raised nothing.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

`durableSpawn` returned a task spawned inside the `ephemeral` effect's own
scope, and that scope closed as the effect resolved — so every
`yield* task` threw `halted`. It had no call sites and no tests. It now
starts the child in the routine's own scope, so the task outlives the call
and can be awaited or halted by whoever asked for it.
A retained `Close(cancelled)` meant one thing to the code and two things in
practice. Under `durableRace` and `durableAll` it is a race loser or a
fail-fast sibling, and the same combinator cancels it again — those keep
DEC-024 exactly. Under `durableSpawn` nobody cancels it a second time, so
suspending hung the resumed run forever. `runDurableChild` now takes an
explicit `CancelledChildPolicy`, fixed at each combinator's call site and
never chosen by a caller. Resuming uses a new internal
`ReplayIndex.reopen()`, which forgets one coroutine's retained Close while
keeping its yields — so the child continues its own history rather than
restarting, and the divergence guard stops reading the remaining effects as
a coroutine continuing past its own close. Neither it nor `disableReplay` is
exported.
DEC-039 records the policy and marks DEC-024's invariant as superseded in
part: it assumed every cancelled child belongs to race or all.
The grid uses the repaired primitive: the whole grid is one durable child,
each pane is its own durable child allocated in authored ordinal order, and
each pane task is observed outside its child — so a replayed pane's retained
outcome publishes its status and satisfies the readiness barrier without
entering a body, a shell, or a launcher.
Evidence: 9 rows in `packages/durable-streams/tests/durable-spawn.test.ts`
(lifetime, completed replay, interrupted resume, retained-history
continuation, and both combinators keeping their own policy); 30 rows in
`packages/core/tests/terminal-grid.test.ts`. durable-streams 32, core 349,
runtime 15.

@github-actionsgithub-actionsBot 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 15 redundant comments. Inline suggestions to remove them below.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

return (function* (): Operation<Task<RetainedPaneOutcome>> {
const durable = yield* DurableContext.get();
if (durable === undefined) {
// No journal behind this run: an ordinary spawned child.

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
// No journal behind this run: an ordinary spawned child.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

Two decisions exposed while implementing #730, and no implementation.
**DEC-040 — a cancelled child records why.** DEC-039's `"resume"` fired on
every retained `Close(cancelled)` under an incomplete parent, which revives
work a caller deliberately halted: the record of a deliberate `task.halt()`
and the record of an interrupted run are the same event. The cancelled close
now carries `cancellation: "caller"` or `"unwound"`, written by whichever
path cancelled the child, and `"resume"` continues only `"unwound"`. A
deliberate stop suspends, which is DEC-024's reproduction argument applied
to a caller instead of a combinator; a legacy record with no reason reads as
`"caller"`, because refusing to revive is the safe direction. The reason is
retained evidence, not authority: nothing outside `runDurableChild` reads
it, and no caller chooses a policy.
Terminal grids need nothing wider. A grid halts its pane tasks at close, so
those retain `"caller"` — and the grid child completes, so a resumed run
short-circuits the region and never reaches them. The case that must resume,
an interrupted run, unwinds and retains `"unwound"`.
**TG17 narrows to the resolved layout.** A continuation executes the root the
journal retained; the supplied source is not read, compared or refused
(proved in #722). A grid's authored structure — pane count, order, form — is
therefore fixed for the life of a journal and cannot differ between runs, so
comparing it compares a value with itself, which is why the refusal never
fired. What a fixed retained document still resolves differently is
`columns` and each `title`, through prop-borne values, since props are not
restored. Those refuse before the lease and before provider contact.
Authored-structure change is a root-definition compatibility question, not a
grid one. Root-definition authority is preserved rather than overridden by a
pre-replay comparison against the current file, and the versioned root
boundary that would refuse a changed source stays open work.
**DEC-040.** A cancelled Close now records why: `cancellation: "caller"`
when the owner halts the task `durableSpawn` returned, `"unwound"` for
anything involuntary. `durableSpawn` resumes only `"unwound"`; a deliberate
stop suspends until the caller's deterministic control flow halts it again,
and a record with no reason reads as `"caller"` so nothing legacy is
revived. `durableAll` and `durableRace` keep DEC-024 whatever the reason
says.
The halt is intercepted without changing the public `Task` surface: the
returned task carries every member the real one defines, copied with its
prototype, and only `halt` is replaced. A proxy cannot do this — a task's
members are read-only and non-configurable, so a `get` trap is required to
hand back exactly what the target holds.
The reason had to survive three boundaries that were dropping it: the
protocol parser, the observable copy, and — the one that actually mattered —
`detachResult`, which froze every cancellation down to `{ status }`.
**TG15.** The harness's `attached` and `pastGrid` signals are now separate,
and a run that expects its grid to complete waits for the sibling *after*
the grid before halting the root at `<Hold />`. That is what leaves a
completed grid child under an incomplete root, which is the only state in
which a completed region can be observed replaying at all. Both a successful
grid and a contained failed one replay their exact retained result with no
provider, pane content, shell or launcher work, and each row asserts the
grid child genuinely recorded a terminal close. No timeouts.
**TG17.** Prop-borne `columns` and `title` change independently against one
fixed retained document — the only things a fixed retained root can still
resolve differently — and each refuses with zero provider observation. For
supplied-file changes to pane count, order and form, the continuation opens
the retained structure rather than the file's, asserted request-for-request.
The retained record carries every authored pane's ordinal, title, form and
derived position.
`readLayout()` parses totally: the layout object and every pane field, with
missing, extra, mistyped, out-of-position and self-inconsistent records all
refused rather than half-read.
Evidence: durable-spawn 14 rows, terminal-grid 36 rows, structural 13,
provider 10. Packages: durable-streams 33, core 349, runtime 15,
workflow 172.
#730)
**The harness cannot pass a hung replay any more.** `runInterrupted()` had a
1500ms timer racing its signals, so a replay that hung returned a
DocumentRun that looked finished; it also slept a fixed 5ms to let records
land. Both are gone. It now waits only on events the run produced:
`attached`, `pastGrid`, and a new `panesSettled` for the rows that read pane
records — a pane's status is published only after its durable child returned,
so counting settled panes is also counting durable pane closes. A replay
that hangs now reaches none of them and hangs the row.
**TG15's failed case is a real contained failure.** A pane that fails before
attachment fails the whole region, so the old document could not both fail
and continue. The failing pane is now a shell that starts, waits for
attachment, and only then exits badly — contained as that pane's status,
with the grid settling as failed and the document carrying on. Both runs
capture the printed errors, and the row asserts the replayed run produced
the same ones, reached `PAST_THE_GRID`, and did no provider, pane, shell or
launcher work.
**DEC-040 gets boundary tests where the evidence actually travels.**
`parse.test.ts` round-trips both reasons to the same bytes, keeps a legacy
absence absent, and refuses an unrecognised reason at `$.result.cancellation`.
`retained.test.ts` proves retention and `consumable()` carry both reasons,
leave a legacy absence absent, drop an unrecognised one to the safe default,
and that the reason reaches the replay index. The DEC-040 rows in
`durable-spawn.test.ts` no longer coordinate by delay: a child says when it
is running, and the caller says when it has halted.
**Malformed retained layouts** are covered by replaying a real journal with
only its layout entry replaced — a missing member, an extra one, a mistyped
one, a pane out of position, and a record that disagrees with itself. Each
refuses with zero provider observation.
The `durableSpawn` doc comment no longer says every retained cancellation is
an interrupted run.
The DEC-040 block still slept where it meant to synchronise — my previous
replacements silently failed to match after the file was reformatted, so
none of them landed. The block is rewritten rather than patched.
Every row now waits on something the run reported. A shared `living()` child
resolves a `started` signal and then suspends, so each row halts or unwinds a
child that is provably live rather than one a delay happened to reach. The
caller resolves `halted` after performing its deliberate halt, so a run is
interrupted only once both facts — the deliberate stop and the interruption —
are in the journal.
Non-revival is established by control flow rather than by waiting: the
resumed run reaches its own `task.halt()` and says so, and a revived child
would have recorded its mark before the caller could get there. The
legacy-absence row signals once the child has been asked for and the request
returned. No new timeout, and `sleep` stays imported because the lifetime
rows above still use it deliberately.
`retained.test.ts` drops the cast and the row it supported: rejecting an
unrecognised reason is the parser's, proved there, and retention proves only
that `"caller"`, `"unwound"` and a legacy absence survive.

@github-actionsgithub-actionsBot 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 11 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

// neither can begin while the other holds it.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

// grid covers it up.
yield* flushOutput();

// Routed, and the answer thrown away.

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
// Routed, and the answer thrown away.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.


const grid = createTerminalGridClaims(request);
// Nothing new is admitted once teardown begins, so a pane that was about to
// start an interactive child is refused rather than racing the close.

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
// start an interactive child is refused rather than racing the close.

// to schedule it in. Each task is observed *outside* its child: a replayed
// completed pane returns its retained outcome without entering a body, a
// shell, or a launcher, and that outcome is what publishes its status and
// satisfies the readiness barrier.

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
// satisfies the readiness barrier.

…730)
**`Symbol.asyncDispose` bypassed the deliberate-stop evidence.** The task
`durableSpawn` returns copied it from the original unchanged, so
`await using` — or an explicit `task[Symbol.asyncDispose]()` — recorded
`cancellation: "unwound"` and the next run revived the child. `halt()` and
the async dispose are the same decision spelled two ways, and both are now
observed. Awaiting a task is not a stop and is left exactly as it was. A
regression disposes a live task, asserts the retained reason is `"caller"`,
resumes the journal, and proves the body is not entered again.
**Reader close no longer halts panes.** It asks them to stop: a pane races
its work against a close signal, settles as `closed`, and records that
outcome as its own. Nothing on the ordinary close path is a caller-cancelled
child any more, so a resumed run restores a pane the reader closed rather
than finding a cancelled child it must either re-enter or wait on forever.
Statuses are published before anything is awaited, so a pane with slow
finalizers cannot delay the outcome the grid already knows.
**§6.21 now agrees with architecture.md and TG17.** Partial replay compares
the resolved layout — columns and titles. Pane count, order and form come
from the retained root and cannot diverge within a continuation, so a
changed supplied file is ignored in favour of the retained structure;
refusing a changed authored structure is a root-definition boundary this
specification does not yet define.
DEC-040 is unchanged and nothing deliberately stopped is revived.

@github-actionsgithub-actionsBot 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 18 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

*destroy() {
// Destroying twice would make the record say a composite was taken down
// more times than it was built, which is exactly the ordering claim a
// suite reads this log 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
// suite reads this log for.

@github-actionsgithub-actionsBot 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 20 redundant comments. Inline suggestions to remove them below.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

},
ready() {
// Idempotent by construction: readiness is a fact about the pane, and a
// provider that reports the same spawn twice has not started two panes.

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 that reports the same spawn twice has not started two panes.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.

if (!replayIndex.hasClose(childId)) {
// (e.g., a cancelled child being replayed via suspend()). A child that
// resumed from a retained cancelled Close is the exception: the record it
// reached this time is the one that describes the work that actually ran.

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
// reached this time is the one that describes the work that actually ran.

const cancellation = members.get("cancellation");
if (cancellation === undefined) {
// A record written before this evidence existed. DEC-040 reads the
// absence as a deliberate stop, so nothing it left behind is revived.

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
// absence as a deliberate stop, so nothing it left behind is revived.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

*destroy() {
// Destroying twice would make the record say a composite was taken down
// more times than it was built, which is exactly the ordering claim a
// suite reads this log 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
// suite reads this log for.

@taras
tarasforce-pushed the agent/issue-730-terminal-execution branch from 8f85400 to eb92602CompareSeptember 2, 2026 22:38

@github-actionsgithub-actionsBot 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 9 redundant comments. Inline suggestions to remove them below.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.

}
for (const [index] of work.entries()) {
// Awaited, not halted. Each pane settles on the close signal and records
// the outcome it reached, which is what a resumed run reads.

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 outcome it reached, which is what a resumed run reads.

// the reader leaves, this settles as `closed` straight away and the work
// comes down in the enclosing scope's own teardown — so a pane whose
// finalizers are slow cannot hold up the outcome the grid already knows,
// and the record a resumed run reads is written either way.

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
// and the record a resumed run reads is written either way.

return (function* (): Operation<Task<RetainedPaneOutcome>> {
const durable = yield* DurableContext.get();
if (durable === undefined) {
// No journal behind this run: an ordinary spawned child.

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
// No journal behind this run: an ordinary spawned child.

// deno-lint-ignore require-yield
*install(call: TerminalProviderCall): Operation<unknown> {
if (call.intent === "install") {
// Reaching the terminal means no registered provider consumed 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
// Reaching the terminal means no registered provider consumed it.

throw new TerminalProviderInstallError(`Unknown terminal provider "${call.name}"`);
}
// Object identity, not shape: a request rebuilt with the same members
// describes the same ask and authorizes nothing.

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
// describes the same ask and authorizes nothing.

return { status: "cancelled" };
// The reason travels with the copy: a resumed spawned region reads it to tell
// a deliberate stop from an interrupted run (DEC-040), and dropping it here
// would make every retained cancellation look deliberate.

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
// would make every retained cancellation look deliberate.

Comment threadpackages/runtime/terminal.ts Outdated
}
// 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.

Implements the amendment at 1833870 without revising it.
**The live handshake.** `composite.closed()` settling now only *proposes* the
boundary. The grid's durable child publishes that proposal and waits; the
owner awaiting the child acknowledges it; and only then does the grid seal
admission and ask its panes to close. The handshake is one live rendezvous —
no provider identity, nothing journaled.
**Committing an outcome before the scope finishes unwinding.** A durable
child can now declare its terminal value, and `runDurableChild` records that
value if the child never reaches a normal ending. That is the piece the
contract needs: the grid commits its retained record as the boundary is
crossed, and each pane live at that moment commits `closed`, so a
cancellation arriving while pane and provider finalizers are still running
records what close decided rather than a cancellation. Committing is live
state; it reaches the journal only as the ordinary `Close`. A child that
returns or throws normally overrides it, and a child that never committed
still records the cancellation it actually reached — DEC-040 untouched.
Cancellation stays deferred because Effection completes a child's teardown —
pane finalizers, provider destroy, terminal restoration, lease release, the
`Close` append and the task's settlement — before the halt reaches the owner.
**Pane work stays inside its ordinal-derived durable child.** Reader close
asks the pane to close; it never halts the pane's durable task. The pane
commits `closed`, stops its live nested work through its own scope, and
settles only once that work and its finalizers have settled.
No durable closing marker was added, and completed replay is unchanged.

@github-actionsgithub-actionsBot 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 11 redundant comments. Inline suggestions to remove them below.

},
// The grid renders nothing into the document: what a pane shows belongs to
// that pane, and the sibling after `</Terminal.Grid>` renders to the root
// again only once the provider has restored 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
// again only once the provider has restored it.

// Recorded in this coroutine, before the lease and before any provider is
// contacted: a resumed run whose grid changed is refused while nothing has
// been opened. It cannot live inside the grid child, because a completed
// child never runs.

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
// child never runs.

*run(claim, composite) {
yield* scoped(function* () {
// A pane is not inside the loop the grid was written in, so a <Break>
// in its content has no loop to exit and says so.

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
// in its content has no loop to exit and says so.

const siteEnv = yield* env;
// Starts from what the grid site can see and keeps its own writes: a
// binding this pane makes is visible to later work in this pane and to
// nothing else.

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
// nothing else.

containedLedger(site.checkedFailures),
site.authority,
// No enclosing value body: a <Return> written in a pane cannot claim
// one outside the grid.

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
// one outside the grid.


// The one foreground-terminal lease, taken before any provider is asked for
// anything. A root <Session.Launch> and a grid contend for exactly this, so
// neither can begin while the other holds 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
// neither can begin while the other holds it.

// neither can begin while the other holds it.
yield* reserveTerminal();
// Everything the document has produced so far reaches the reader before the
// grid covers it up.

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
// grid covers it up.

// grid covers it up.
yield* flushOutput();

// Routed, and the answer thrown away.

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
// Routed, and the answer thrown away.

): Operation<RetainedGrid> {
return scoped(function* (): Operation<RetainedGrid> {
// Registered before a single pane starts: a composite that was presented is
// owed a destroy even if the next line is what fails.

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
// owed a destroy even if the next line is what fails.


const grid = createTerminalGridClaims(request);
// Nothing new is admitted once teardown begins, so a pane that was about to
// start an interactive child is refused rather than racing the close.

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
// start an interactive child is refused rather than racing the close.

Implements architecture 1833870 at the owner boundary. The grid's durable
child now runs in a scope of its own — a child of the owner's, so it inherits
every context the document runs under, and its own so that tearing the owner
down does not reach it first. A finalizer registered after that scope exists
runs before it is destroyed, and that is the cancellation-deferred await: once
the owner has acknowledged the provider's close proposal, the grid and its panes
finish teardown and append their ordinary completed Close records, and only then
does the cancellation carry on to the parent.
Removes the exported CommitOutcome/durableSpawn(commit) API. Cancellation is
never turned into success inside runDurableChild; durableSpawnIn only says where
a child lives, and grants nothing a caller does not already have.
TG19 proves the ordering with signals alone: a live pane arms a blocking
finalizer, the reader leaves, the finalizer is entered and held, cancellation
begins, the finalizer is released, and the run ends with the composite destroyed,
a completed grid Close retained, the live pane retained as closed — and the
sibling after the grid never reached. The continuation then replays past it with
no provider, no pane body and no finalizer re-entered.
TG6 isolates paired-pane sequencing on its own: the reader leaves only once the
pane's second component has run.
The production lifecycle is unchanged. TG19 now reads counters and journal
records rather than a log's shape.
The controlled composite keeps live resource counters — composites prepared,
composites attached, shells started — each raised when it takes something and
lowered when it gives it back, however it left. TG19 reads them once while a
pane finalizer is blocked, so it knows they went up, and again when the
cancellation has completed, so it knows they came back down.
The harness now says when a blocked finalizer *leaves*, not only when it is
entered: a finalizer that was entered and then cancelled reaches the first hook
and never the second. And after every interrupted run it takes the foreground
lease and gives it back twice — the first proves the grid returned it, the
second proves the harness did.
TG19 adds: one grid Close(ok) retaining close: "reader"; two pane Closes, both
completed, with no cancellation recorded at either level; the finalizer entered
and left exactly once; destroy:0 exactly once. The first-attempt claim that no
following sibling ran and the replay tripwires are unchanged.
Every one of these was broken on purpose and re-run: dropping any of the three
counter releases, the deferral, the finalizer-exit hook, or double-logging
destroy fails TG19, and a second holder of the foreground lease is refused.
Sign up for freeto 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

@taras