Context
Operator ruling 2026-09-03: "reload => default action is recreate … MUST BE THERE BY DEFAULT."
Measured on a downstream workspace that overrides nothing: a focused pane's header carries [maximize, close] — no reload node at all. The pane implements no dockReload(), and the workspace overrides no factory, which is precisely the case the default is meant to serve.
The Problem
The ruling is not new. It was given on 2026-08-31 and is recorded in a peer's session memory as: "reload must have a default engine behavior — recreate — rather than existing only for panes implementing dockReload()", with "#17966 is required default behavior, not optional polish." #17966's title carries it: "Default reload fallback: engine-owned recreate when a pane lacks dockReload()".
Its six ACs do not. They cover the two-phase transaction's safety only — phase-1 refusal leaves the live pane untouched, phase-2 preserves slot and action identities, destroy-after-live ordering, reconciler interaction after recreate, teardown mid-transaction. Every one was met, and the ticket closed legitimately via merged PR #17996 ("A user-triggered pane recreate amends the never-destroyed guarantee" — the ADR 0029 §2.6 amendment). The ruling was never encoded as an AC, so nothing failed when the default did not ship. That is the process half of this ticket, and it is worth naming: a ruling that lives in a title and a memory is not a gate.
What shipped is a consumer hook, deliberately and with documentation. The Contract Ledger on #17966 records resolveFreshPane as a "New consumer hook" whose fallback "returns null — recreate unsupported", and hasDockRecreateFallback() as "Prototype-derived — is the capability wired". #18014 AC-7 then scoped the factory to a single host: "Workstation's fresh-pane factory bypasses paneCache … resolveFreshPane always creates independently."
So a workspace that overrides nothing has no recreate capability, and syncDockReloadAction correctly hides reload.
The consumer-hook rationale is real and must survive any fix. From the hook's own JSDoc: an option on resolvePane "would be silently ignored and hand back the very instance the recreate is meant to replace." A distinct hook cannot be accidentally satisfied by a cache. The open question is therefore not "remove the hook" but "what can the engine mint without one".
The Architectural Reality
src/dashboard/dock/Workspace.mjs:3651 — resolveFreshPane(itemId, item) { return null }, the honest declining default.
:3671 — hasDockRecreateFallback() { return this.resolveFreshPane !== Workspace.prototype.resolveFreshPane }. Prototype identity, so the base implementation is excluded by construction: the engine can never be its own fallback under this predicate.
Workspace#syncDockReloadAction — hidden = typeof carrier !== 'function' && !this.hasDockRecreateFallback(); hides only when neither delegation nor fallback can serve the item.
LayoutAdapter.mjs projects reload with a CONSTANT hidden: true (stable-instance discipline), revealed only by that post-settle sweep.
- Withdrawn actions carry no DOM node (#18015), so the absence is invisible to inspection.
The Fix
Give the engine a default resolveFreshPane that mints a pane from the item's own persisted record — item is already the hook's second argument — so hasDockRecreateFallback() answers true without a host override, while a host override stays authoritative and dockReload() delegation keeps priority.
The design question to answer before implementing: what does the engine recreate FROM? The item catalog record, versus the pane's own config snapshot, versus a module reference. Whichever is chosen must not resolve through any live-instance cache — that is the exact trap the current hook shape exists to prevent — and hasDockRecreateFallback() must stop being prototype-identity-derived once the base can serve.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
Workspace#resolveFreshPane |
src/dashboard/dock/Workspace.mjs:3651 |
engine default mints from the item record instead of returning null |
a host override wins unchanged |
JSDoc |
identity arm: the minted pane is never the live instance |
Workspace#hasDockRecreateFallback |
:3671 |
no longer prototype-identity-derived; true when the base can serve |
false only if the engine genuinely cannot mint |
JSDoc |
visibility arm on a bare workspace |
Workspace#handleDockReloadAction |
Workspace.mjs |
unchanged — delegation first, recreate second |
no live pane → honest error |
JSDoc |
#17966's delegation-priority mutation stays green |
| ADR 0029 §2.6 |
learn/agentos/decisions/0029-docking-design.md |
unchanged — user-triggered only; automatic recreation still forbidden |
— |
the record |
existing amendment stands |
Decision Record impact
aligned-with ADR 0029 §2.6 — the user-triggered recreate exception already exists and is conditioned on the two-phase guarantee; this ticket widens who can serve it, not when it may run. Successor to #17966 (closed, PR merged): not a reopen.
Acceptance Criteria
Out of Scope
- Lock and pop-out defaults — the sibling successor filed alongside this one.
- Automatic (non-user-triggered) recreation: still forbidden by ADR 0029 §2.6.
- Changing what
dockReload() means for panes that implement it.
Avoided Traps
- Reopening #17966. Its ACs were met and it had a merged PR. The gap is that the ruling lived in the title rather than in an AC — a successor is the correct instrument.
- Serving recreate through an option on
resolvePane. Named and rejected in the hook's own JSDoc: consumers that do not implement it hand back the cached instance the recreate exists to replace, silently.
- Leaving capability derived from prototype identity once a base exists. The predicate would answer
false for every consumer while the engine can in fact serve — the defect this ticket is about, one layer up.
Related
- #17966 (closed, PR #17996 merged) — the two-phase transaction and the ADR §2.6 amendment; its title carries the ruling its ACs omitted.
- #18014 AC-7 (closed) — scoped the fresh-pane factory to a single host.
- #18039 (closed) — reload lost after a rail round trip (the sweep now walks the settled shell).
- #17948 / PR #17974 — the reload action itself, merged delegation-only.
- Sibling successor: lock + pop-out defaults, #18148.
Live latest-open sweep: checked the latest 25 open issues at 2026-09-02T22:12Z; A2A in-flight claim sweep over the most recent 12 messages at 22:14Z — no equivalent ticket and no competing claim.
Origin Session ID: a5db4dc8-310d-4702-9bfa-3780d32e932b
Retrieval Hint: "engine-owned recreate default resolveFreshPane hasDockRecreateFallback prototype identity reload hidden bare workspace"
Context
Operator ruling 2026-09-03: "reload => default action is recreate … MUST BE THERE BY DEFAULT."
Measured on a downstream workspace that overrides nothing: a focused pane's header carries
[maximize, close]— no reload node at all. The pane implements nodockReload(), and the workspace overrides no factory, which is precisely the case the default is meant to serve.The Problem
The ruling is not new. It was given on 2026-08-31 and is recorded in a peer's session memory as: "reload must have a default engine behavior — recreate — rather than existing only for panes implementing
dockReload()", with "#17966 is required default behavior, not optional polish." #17966's title carries it: "Default reload fallback: engine-owned recreate when a pane lacksdockReload()".Its six ACs do not. They cover the two-phase transaction's safety only — phase-1 refusal leaves the live pane untouched, phase-2 preserves slot and action identities, destroy-after-live ordering, reconciler interaction after recreate, teardown mid-transaction. Every one was met, and the ticket closed legitimately via merged PR #17996 ("A user-triggered pane recreate amends the never-destroyed guarantee" — the ADR 0029 §2.6 amendment). The ruling was never encoded as an AC, so nothing failed when the default did not ship. That is the process half of this ticket, and it is worth naming: a ruling that lives in a title and a memory is not a gate.
What shipped is a consumer hook, deliberately and with documentation. The Contract Ledger on #17966 records
resolveFreshPaneas a "New consumer hook" whose fallback "returnsnull— recreate unsupported", andhasDockRecreateFallback()as "Prototype-derived — is the capability wired". #18014 AC-7 then scoped the factory to a single host: "Workstation's fresh-pane factory bypassespaneCache…resolveFreshPanealways creates independently."So a workspace that overrides nothing has no recreate capability, and
syncDockReloadActioncorrectly hides reload.The consumer-hook rationale is real and must survive any fix. From the hook's own JSDoc: an option on
resolvePane"would be silently ignored and hand back the very instance the recreate is meant to replace." A distinct hook cannot be accidentally satisfied by a cache. The open question is therefore not "remove the hook" but "what can the engine mint without one".The Architectural Reality
src/dashboard/dock/Workspace.mjs:3651—resolveFreshPane(itemId, item) { return null }, the honest declining default.:3671—hasDockRecreateFallback() { return this.resolveFreshPane !== Workspace.prototype.resolveFreshPane }. Prototype identity, so the base implementation is excluded by construction: the engine can never be its own fallback under this predicate.Workspace#syncDockReloadAction—hidden = typeof carrier !== 'function' && !this.hasDockRecreateFallback(); hides only when neither delegation nor fallback can serve the item.LayoutAdapter.mjsprojects reload with a CONSTANThidden: true(stable-instance discipline), revealed only by that post-settle sweep.The Fix
Give the engine a default
resolveFreshPanethat mints a pane from the item's own persisted record —itemis already the hook's second argument — sohasDockRecreateFallback()answerstruewithout a host override, while a host override stays authoritative anddockReload()delegation keeps priority.The design question to answer before implementing: what does the engine recreate FROM? The item catalog record, versus the pane's own config snapshot, versus a
modulereference. Whichever is chosen must not resolve through any live-instance cache — that is the exact trap the current hook shape exists to prevent — andhasDockRecreateFallback()must stop being prototype-identity-derived once the base can serve.Contract Ledger Matrix
Workspace#resolveFreshPanesrc/dashboard/dock/Workspace.mjs:3651nullWorkspace#hasDockRecreateFallback:3671truewhen the base can servefalseonly if the engine genuinely cannot mintWorkspace#handleDockReloadActionWorkspace.mjslearn/agentos/decisions/0029-docking-design.mdDecision Record impact
aligned-with ADR 0029 §2.6— the user-triggered recreate exception already exists and is conditioned on the two-phase guarantee; this ticket widens who can serve it, not when it may run. Successor to #17966 (closed, PR merged): not a reopen.Acceptance Criteria
Neo.dashboard.dock.Workspacesubclass that overrides nothing projects a reachablereloadon a focused pane whose card implements nodockReload().live-instancerefusal stays red-proof.resolveFreshPanestill wins, anddockReload()delegation still preempts recreate; both mutation-proven, with #17966's delegation-priority arm green.Out of Scope
dockReload()means for panes that implement it.Avoided Traps
resolvePane. Named and rejected in the hook's own JSDoc: consumers that do not implement it hand back the cached instance the recreate exists to replace, silently.falsefor every consumer while the engine can in fact serve — the defect this ticket is about, one layer up.Related
Live latest-open sweep: checked the latest 25 open issues at 2026-09-02T22:12Z; A2A in-flight claim sweep over the most recent 12 messages at 22:14Z — no equivalent ticket and no competing claim.
Origin Session ID: a5db4dc8-310d-4702-9bfa-3780d32e932b
Retrieval Hint: "engine-owned recreate default resolveFreshPane hasDockRecreateFallback prototype identity reload hidden bare workspace"