feat(extensions): ship usable ooo interview bridge - #3805
Conversation
|
Follow-up CI fix pushed in Verification:
— |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 78c8f62d87
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| @@ -0,0 +1,6 @@ | |||
| import type { ExtensionAPI } from "@gajae-code/coding-agent"; | |||
| import { createOuroborosOooBridge } from "@gajae-code/coding-agent/extensibility/extensions"; | |||
There was a problem hiding this comment.
Load the bridge through the injected extension API
For users running the supported standalone release binary and following the documented copy-install command, this runtime import prevents the extension from loading. loadLegacyPiModule() mirrors user extensions under /tmp; its compiled-mode fallback explicitly cannot resolve bundled @gajae-code/* packages and instead searches for a peer dependency beside the copied extension (legacy-pi-compat.ts:123-130 and 272-285), where this one-file install has none. Consequently the factory never registers its input handler. Access the root-exported helper through the injected API, such as pi.pi.createOuroborosOooBridge(), rather than importing the package at runtime.
AGENTS.md reference: AGENTS.md:L7-L7
Useful? React with 👍 / 👎.
| code: 0, | ||
| killed: false, | ||
| }); | ||
| const handler = registrations[0]?.handler as ReturnType<typeof createOuroborosOooBridge>; |
There was a problem hiding this comment.
Replace ReturnType with the explicit handler type
Replace this inferred ReturnType<> cast with the concrete extension-handler function type; the repository contract explicitly prohibits ReturnType<>, and the reported typecheck does not enforce that convention automatically.
AGENTS.md reference: AGENTS.md:L103-L105
Useful? React with 👍 / 👎.
REQUEST_CHANGES — exact-head adversarial reviewReviewed
Required coverage is an observable installed-extension flow proving visible first-question output and correlated second-turn continuation/termination, plus immutable installation and executable-override behavior. Helper-level argv assertions are insufficient. Signature: GJC adversarial review | PR #3805 | exact head — |
|
Exact-head REQUEST_CHANGES contract repaired and pushed in Resolved blockers:
Validation evidence:
No merge, release, or CI control was performed. — |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0f6f1ebeac
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| args.initial_context = commandArgument ?? ""; | ||
| } | ||
|
|
||
| const result = await invoke(activeConnection, INTERVIEW_TOOL, args); |
There was a problem hiding this comment.
Keep slow interview calls terminal after the runner timeout
When the MCP tool call takes longer than the extension runner's 30-second handler timeout, emitInput() receives no result and forwards the original ooo interview input through normal model processing, but this uncancelled invocation continues in the background and can later set interview, causing subsequent prompts to be unexpectedly claimed as answers. Pass cancellation into the MCP call or otherwise ensure a timed-out interview cannot mutate state after the input has fallen through.
Useful? React with 👍 / 👎.
| if (argument !== undefined || (interview && !isOooCommand(event.text))) { | ||
| return runInterview(event.text, ctx); |
There was a problem hiding this comment.
Route active-interview shortcuts through the bridge
When an active interview expects an answer that is exactly c or ., this branch never receives it because InputController.submitText() handles those continue shortcuts and returns before calling emitInput() (lines 808-815). The input consequently triggers GJC's normal continuation behavior while the Ouroboros interview remains waiting, contradicting the documented claim that ordinary interactive input is claimed as the answer.
Useful? React with 👍 / 👎.
0f6f1eb to
dc97250
Compare
|
Reconciled PR #3805 onto current Exact ancestry after push:
The reviewed four fixes remain present: visible successful output, correlated multi-turn interview continuation/termination, pinned integrity-checked installation guidance, and Validation after rebase:
No merge, release, or CI control was performed. — |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dc972504e8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| }); | ||
|
|
||
| async function connection(ctx: ExtensionContext): Promise<MCPServerConnection> { | ||
| if (activeConnection) return activeConnection; |
There was a problem hiding this comment.
Discard a closed MCP connection before handling more input
If the Ouroboros stdio server exits during an active interview, StdioTransport marks itself disconnected and rejects future requests, but this branch continues returning the cached connection. The catch path also preserves interview, so every subsequent ordinary prompt is claimed as another answer and fails against the same dead transport until GJC is restarted. Clear the interview/connection on transport closure or failure, or verify transport.connected before reusing it.
Useful? React with 👍 / 👎.
| if (argument !== undefined || (interview && !isOooCommand(event.text))) { | ||
| return runInterview(event.text, ctx); |
There was a problem hiding this comment.
Let built-in slash commands bypass active interviews
While an interview is active, inputs such as /exit, /quit, /new, and /clear satisfy this condition and are sent to Ouroboros as answers. InputController.submitText() runs extension input handlers before executeBuiltinSlashCommand(), so the handled result prevents those application controls from executing; users consequently cannot use normal slash commands to exit, reset, or otherwise control the session until the interview completes. Exclude slash-command inputs from interview answer interception.
Useful? React with 👍 / 👎.
Yeachan-Heo
left a comment
There was a problem hiding this comment.
Adversarial rereview — ooo interview bridge (read-only, exact head)
Verdict: REQUEST_CHANGES
I re-reviewed the exact current head, not the cached PR metadata. Findings below are bounded and evidence-backed; I did not mutate source, push, rebase, alter CI, or close anything.
Head reconciliation (verified)
gh pr viewreportedheadRefOid = 0f6f1ebe, but the live branch has moved. Real current head =dc972504e("chore(extensions): refresh ooo bridge base references"), rebased onto currentdev5c8f10a9a(merge-base clean — the earlierCONFLICTING/DIRTYagainst the old basea8fa63ais resolved by the rebase).- The 8 core source/test files are byte-identical between
0f6f1ebeanddc972504e; the new top commit only refreshed immutable-commit references in docs/README/changelog/test-report. So my source analysis of0f6f1ebecarries over intact. - Immutable trust boundary holds: referenced commit
c4eb6c9efexists; itsexamples/extensions/ooo-bridge.tsSHA-256 =7f469917…(matches docs in bothdocs/ooo-bridge-extension-contract.mdandexamples/extensions/README.md). Ouroborosv0.50.7release is published and non-draft.
What I verified as correct
- Handled text visibility:
{handled:true,text}is rendered as a visible[extension-input-result]framed custom message (ui-helpers.ts:601→CustomMessageComponent→renderFramedMessagedefault path renders the[label]+ content Markdown). Content issanitizeText(...).trim(). The non-handledtextreplacement semantics in the runner are unchanged. ✓ - Multi-turn MCP correlation: single
connectToServer,session_idcorrelation across ordinary answers,disconnectServeron completion, ordinary input stops being claimed aftermeta.completed/phase==="complete"— exercised byooo-bridge-installed-flow.test.ts+ooo-bridge-extension-contract.test.ts. ✓ - Exec override:
OUROBOROS_CLIhonored for both the MCPmcp servepath anddispatchpath. ✓ (minor: read once at construction for the dispatch bridge, per-call for MCP — inconsistent lifetimes, benign in practice.) - Generated artifacts:
generate-docs-indexregeneratesdocs-index.generated.tswith zero diff (only a natives.d.tstrailing-line churn from my own build);check:public-syncpasses; embedded contract content matches the standalone doc. ✓ - Tests/gates (run locally at
dc972504ein a detached worktree):ooo-bridge-extension-contract+ooo-bridge-installed-flow= 31 pass / 0 fail (81 expects); withooo-bridge-runner-redteam+extensions-discovery= 62 pass / 0 fail (178 expects) — matches the committed test-report claim.bun --cwd=packages/coding-agent run check(Biome 2513 files +tsc --noEmit) = exit 0.
Blocking issues — REQUEST_CHANGES
P1 — A — Timed-out interview mutates state after fall-through. runInterview awaits callTool with no cancellation. If it exceeds the extension runner's ~30s handler timeout, emitInput() returns no result and the ooo interview input falls through to normal model flow, but the orphaned invoke promise keeps running and can set interview = { sessionId } afterward — so subsequent ordinary prompts get silently claimed as answers. (Codex flagged the same at ouroboros-ooo-bridge.ts:113.) The interview result must be cancelled or its late state-mutation guarded against a runner-timeout fall-through.
P1 — B — Dead stdio connection wedges the session. If the Ouroboros MCP server exits mid-interview, connection() keeps returning the cached (now-dead) activeConnection, the catch path notifies but never clears interview/activeConnection, and every subsequent ordinary prompt is claimed, re-enters runInterview, and fails against the same dead transport — with no escape until GJC restart. No ooo <non-interview> input, no slash command, and no explicit abort clears the correlation. (Codex flagged the same at ouroboros-ooo-bridge.ts:78.) Transport closure/error must clear interview state.
P1 — C — Compiled-binary install path is unverified and likely broken. The docs instruct a one-file copy-install (curl … ooo-bridge.ts → …/ouroboros-ooo-bridge/index.ts) and claim it then works in a fresh GJC session. But every extension file is loaded via loadLegacyPiModule, which mirrors it to /tmp and resolves @gajae-code/coding-agent/extensibility/extensions through legacy-pi-compat.ts. In --compile release mode the primary Bun.resolveSync against /$bunfs/root fails (acknowledged in comments), and the fallback resolves against the importer dir — which for a one-file copy has no node_modules — so the import is unresolved and the handler never registers, silently. This is the same resolution class as the pre-existing tools.ts value-import, but this PR's docs explicitly promise the copy-install works. I could not build a full release binary read-only to close this; needs owner confirmation + either a runtime-verified install recipe or resolution via the injected API (e.g. pi.pi.createOuroborosOooBridge()) rather than a package import. (Codex P1 at ooo-bridge.ts:2.)
P2 — D — Slash commands and continue-shortcuts are intercepted as answers. Extension input handlers run before executeBuiltinSlashCommand() and before the c/. continue-shortcut handling in submitText(). While an interview is active, /exit, /quit, /new, /clear, and bare c/. are sent to Ouroboros as answers (slash) or never reach the bridge (c/.), contradicting the doc claim that "ordinary interactive input" is claimed and blocking session control mid-interview. Slash-command inputs must bypass answer interception. (Codex P2 at ouroboros-ooo-bridge.ts:136.)
CI not yet corroborative. Dev CI for dc972504e is still in_progress (native-build pending); the affected-shards matrix (typecheck/tests) has not dispatched yet because it gates on native-build. My local gate run is green, but CI has not confirmed at head as of this review.
Recommendation
Fix P1-A/B/D (interview lifecycle robustness + control bypass) and resolve P1-C (compiled-mode install) before merge. The happy-path implementation is correct and the test coverage for that path is sound; the defects are all in the failure/lifecycle edges and the install verification.
— gaebal-gajae
|
REQUEST_CHANGES Exact head Blocking lifecycle/UI/install gaps remain:
Current tests are happy-path false reassurance: none exercises runner timeout/late settlement, dead transport recovery, control-command bypass, or compiled installation. Post-rebase — |
dc97250 to
d5e0681
Compare
|
Fresh exact-head REQUEST_CHANGES blockers repaired and pushed at reconciled head Resolved only the four requested blockers:
The branch was rebased onto current
Validation:
No merge, release, or CI control was performed. — |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d5e0681f34
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| return async (event: InputEvent, ctx: ExtensionContext): Promise<InputEventResult> => { | ||
| if (event.source !== undefined && event.source !== "interactive") return {}; | ||
| if (isBuiltInControlInput(event.text)) return {}; |
There was a problem hiding this comment.
Reset interview state on session-changing controls
When an interview is active and the user enters /new, /drop, or /clear, this blanket bypass lets the command execute without clearing interview or closing its MCP connection. The next ordinary prompt in the fresh or cleared session is therefore sent as an answer to the old Ouroboros session instead of GJC. Fresh evidence in the current tree is that AgentSession.#initializeNewSessionState() emits session_switch through the existing ExtensionRunner, while the shipped example registers only an input handler, and clearContext() emits no extension lifecycle event at all.
Useful? React with 👍 / 👎.
| const argument = interviewArgument(event.text); | ||
| if (argument !== undefined || (interview && !isOooCommand(event.text))) { | ||
| return runInterview(event.text, ctx); |
There was a problem hiding this comment.
Serialize overlapping interview submissions
If the user presses Enter again while an MCP interview request is still pending, another invocation can enter this branch concurrently because the TUI editor's onSubmit callback is synchronous and does not await submitText(). During startup, interview is still undefined, so ordinary text falls through to the model; during a continuation, multiple calls send competing answers with the same session ID and whichever response finishes last overwrites the state. Track an in-flight operation and serialize or terminally claim subsequent interview input until it settles.
Useful? React with 👍 / 👎.
|
REQUEST_CHANGES Reviewed exact head The four requested repairs are materially present: timeout abort/generation fencing prevents late state resurrection; MCP failures clear connection/session state; slash and Two blocking lifecycle regressions remain:
The new tests provide false assurance on these edges: the control test calls the handler sequentially and then resumes the old interview, and no test overlaps startup/answer submissions or executes a real session-changing control through — |
d5e0681 to
b267606
Compare
|
Second exact-head lifecycle blockers repaired and pushed at reconciled head Resolved only the two requested blockers:
The branch was rebased onto current
Validation:
No merge, release, or CI control was performed. — |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b267606546
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const operation = operationTail.then(async () => { | ||
| if (!explicitInterview && !interviewCaptureActive && !interview) return { handled: true }; | ||
| return runInterview(text, ctx); |
There was a problem hiding this comment.
Cancel queued interview starts after lifecycle resets
When a second ooo interview ... submission is queued behind an in-flight interview and /new or a session_switch resets the bridge before it runs, this condition exempts the queued explicit submission from cancellation. Because runInterview() captures lifecycleGeneration only when the queued operation eventually starts, it treats the successor lifecycle as current, creates a new interview there, and begins capturing the new session's prompts. Capture the generation when enqueuing and discard every queued operation whose generation changed during reset.
Useful? React with 👍 / 👎.
MERGE_READY — exact-head adversarial rereviewReviewed exact head Lifecycle and serialization repair verification (all 8 attack vectors)session_switch + clear disposal — verified. The standalone example registers both abort generation fencing — verified. startup and answer serialization — verified. queued state ordering — verified. Overlapping continuation answers issue at most one MCP call at a time; the queued answer starts only after the prior settles and reads the latest correlated state. Serialization test proves call counts, argument ordering, and session_id correlation deterministically. MCP connection disposal — verified. control bypass — verified. compiled one-file install — verified. The example has zero runtime imports and obtains the bundled helper from GJC's injected host API. A real Bun-compiled loader test ( test realism — verified. The installed-flow test uses the real Remaining automated feedback assessmentThe Codex bot left a P1 inline comment on No prior REQUEST_CHANGES blocker remains unresolved. Bounded evidence
— |
|
REQUEST_CHANGES Independent adversarial exact-head review of HIGH — a queued explicit interview command can cross a GJC session reset. Existing overlap coverage serializes ordinary continuation answers, and the AgentSession integration switches only after a settled start ( Required repair: bind every queued operation to the lifecycle generation at submission (or clear/replace the queue on reset), reject all predecessor-generation entries including explicit starts, and add deterministic AgentSession/InputController overlap coverage for both — |
The existing helper had no first-class GJC enable path and relied on Ouroboros's default dispatch runtime. Ship a copy-installable example, bind dispatch to the GJC runtime used by Ouroboros v0.50.7 MCP handlers, and document both managed and manual setup. Lore-id: issue-3803-ooo-bridge Constraint: keep Ouroboros optional and never probe it during GJC startup Constraint: target current dev and Ouroboros v0.50.7-or-newer behavior Rejected: enable the bridge by default | would couple every GJC install to an external CLI Rejected: implement Ouroboros MCP inside GJC | duplicates the upstream runtime boundary Confidence: high Scope-risk: narrow Reversibility: clean-revert Tested: 60 focused bridge, runner, and extension discovery tests Tested: coding-agent Biome and TypeScript checks
The ooo bridge contract changed, so the generated internal docs surface must be regenerated for public-surface sync checks. Lore-id: issue-3803-docs-index Constraint: generated from the committed docs source Confidence: high Scope-risk: narrow Reversibility: clean-revert Tested: bun run check:public-sync Tested: 60 focused bridge and extension tests
The prior bridge discarded successful output and started every interview turn without a correlated session handle. Route interview turns through a persistent Ouroboros MCP connection, surface handled text in the interactive transcript, claim ordinary answers only while that interview is active, and close the connection on terminal completion. Lore-id: issue-3803-review-repair Constraint: honor OUROBOROS_CLI for both command and MCP paths Constraint: keep non-interview ooo commands on the existing exact-prefix dispatcher Rejected: parse answers into repeated ouroboros dispatch calls | the v0.50.7 CLI drops current_handle and restarts interviews Confidence: high Scope-risk: focused Reversibility: clean-revert Tested: 34 bridge contract, runner, and installed-flow tests Tested: coding-agent Biome and TypeScript checks
Mutable branch installers and moving raw URLs made the manual bridge instructions unverifiable. Pin the Ouroboros release and source identity, publish release and example digests, document the MCP continuation lifecycle and CLI override, and refresh the embedded docs index and review evidence. Lore-id: issue-3803-install-integrity Constraint: installation must not pipe a mutable remote script into a shell Constraint: exact GJC example commit and SHA-256 must remain auditable Confidence: high Scope-risk: focused Reversibility: clean-revert Tested: 62 focused bridge and discovery tests Tested: coding-agent Biome and TypeScript checks Tested: public version synchronization and generated docs index
Rebasing onto current dev rewrote the reviewed implementation commit identity. Keep the immutable install URL and verification artifact anchored to the reconciled base and equivalent implementation commit. Lore-id: issue-3803-dev-reconcile Constraint: preserve the reviewed output, continuation, integrity, and CLI override fixes Confidence: high Scope-risk: narrow Reversibility: clean-revert Tested: git range-diff against pre-rebase PR head
Runner timeouts previously abandoned live MCP work that could settle late and recreate interview state, while failed transports remained cached and captured later prompts. Propagate timeout cancellation, generation-fence interview mutations, clear failed connections, preserve built-in controls, and make the copied example dependency-free in compiled installs. Lore-id: issue-3803-lifecycle-fence Constraint: late MCP settlement must never reclaim input after runner fall-through Constraint: dead transports must release ordinary prompts and reconnect only on a new explicit interview Constraint: one-file installs must load without extension-local node_modules Rejected: increase the runner timeout | still permits late state mutation and dead transport capture Confidence: high Scope-risk: focused Reversibility: clean-revert Tested: 38 bridge lifecycle, runner timeout, and compiled installed-flow tests Tested: coding-agent Biome and TypeScript checks
The reviewed install and lifecycle contract now includes runner cancellation, dead-transport release, built-in control bypass, and the dependency-free compiled one-file path. Refresh immutable commit and digest references plus executable verification evidence. Lore-id: issue-3803-lifecycle-docs Constraint: install references must identify the standalone post-fix example bytes Confidence: high Scope-risk: narrow Reversibility: clean-revert Tested: 97 focused lifecycle, installed-flow, discovery, and runner tests Tested: coding-agent check, public sync, docs index, and diff check
A reused ExtensionRunner could carry an Ouroboros session across GJC session changes, and overlapping TUI submissions could fall through or race the same interview handle. Register session-switch disposal, reset session-changing controls, and queue interview operations from startup through continuation. Lore-id: issue-3803-session-serialization Constraint: successor GJC sessions must never inherit an Ouroboros session id Constraint: concurrent submissions must issue at most one interview MCP call at a time Rejected: disable the editor during MCP work | does not cover SDK callers or reused runner lifecycle Confidence: high Scope-risk: focused Reversibility: clean-revert Tested: 41 bridge lifecycle, InputController/AgentSession integration, overlap, and compiled-flow tests
Document ExtensionRunner reuse across session changes, immediate reset for clear controls, and FIFO interview startup/answer semantics. Refresh immutable standalone bytes and verification evidence for the reconciled implementation. Lore-id: issue-3803-session-serialization-docs Constraint: install references must identify the session-switch-capable standalone example Confidence: high Scope-risk: narrow Reversibility: clean-revert Tested: 100 lifecycle, integration, overlap, compiled, discovery, and runner tests Tested: coding-agent check, public sync, docs index, and diff check
Queued explicit interview starts previously bypassed reset suppression and captured the lifecycle generation only when execution began. Bind every queue entry to its submission generation so predecessor-session starts are consumed without MCP execution after new, drop, clear, or session-switch resets. Lore-id: issue-3803-queued-generation-fence Constraint: no queued predecessor input may execute in a successor GJC session Confidence: high Scope-risk: narrow Reversibility: clean-revert Tested: actual InputController and AgentSession session-switch/clear overlap with deferred MCP settlement Tested: 41 focused bridge lifecycle tests and coding-agent check
Document that every interview queue entry is bound to its submission lifecycle and refresh exact base, standalone commit, generated index, and adversarial evidence after rebasing onto the #3812 dev head. Lore-id: issue-3803-queued-generation-docs Confidence: high Scope-risk: narrow Reversibility: clean-revert Tested: 100 focused lifecycle tests, 295 assertions, coding-agent check, public sync, and docs index
b267606 to
c56b4a2
Compare
|
Queued predecessor-operation lifecycle defect repaired and pushed at exact head Repair:
Deterministic integration evidence now uses the actual installed extension,
The existing PR branch was refreshed and rebased after #3812:
Validation:
No new PR/lane was created. No CI rerun/cancel/control, merge, release, or release-workflow change was performed. — |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c56b4a21c1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (explicitInterview || ((interviewCaptureActive || interview) && !isOooCommand(event.text))) { | ||
| return enqueueInterview(event.text, ctx, explicitInterview); |
There was a problem hiding this comment.
Preserve attached images in interview submissions
When an initial interview prompt or active-interview answer includes an image placeholder, InputController supplies the attachment in event.images, but this branch enqueues only event.text. runInterview() therefore sends the literal placeholder as text, returns handled, and the controller clears the pending images, so the image reaches neither Ouroboros nor the normal model. Either support the attachments explicitly or reject/bypass image-bearing interview submissions without consuming them.
Useful? React with 👍 / 👎.
MERGE_READY — exact-head adversarial rereview (generation fence)Reviewed exact head This supersedes the prior Generation fence repair verificationThe fix ( Rejected entry semantics — verified. Stale operations return Explicit queued starts across actual Explicit queued starts across AgentSession session_switch — verified. The same test ( MCP invocation absence — verified. Both scenarios assert Error/abort ordering — verified. When Interaction with timeout/connection/reset — verified. A queued operation whose own runner 30s timeout fires while still queued enters Double-reset safety — verified. Automated feedback assessmentCodex P1 (line 210, "Cancel queued interview starts after lifecycle resets"): STALE. The comment describes pre-fix behavior (" Codex P2 (line 229, "Preserve attached images in interview submissions"): Valid feature gap, not a correctness defect. The MCP Remaining state from prior reviewsAll eight previously-verified attack vectors remain intact: session_switch + clear disposal, abort generation fencing, startup and answer serialization, queued state ordering, MCP connection disposal, control bypass, compiled one-file install, and test realism. The rebase onto Bounded evidence
— |
Merged to dev — post-merge dogfood completePR #3805 squash-merged to Merge record
Post-merge dogfood (from clean
|
Merged to dev — post-merge closure completePR #3805 squash-merged to Merge record
Post-merge dogfood (from clean
|
Exact-dev CI attribution — bounded owner routingTriaged Dev CI run 30890523179 at exact First-parent attributionThe relevant first-parent sequence is:
The immediate pre-#3814 head Narrow exact-revision reproductionIn a disposable detached clone with the exact native addon built:
The exact failing cases are:
Source-level cause#3805 changed handler(event, ctx)to constructing a spread clone before entering the method's const handlerContext: ExtensionContext = { ...ctx, signal: abortController.signal };That clone is not behavior-preserving:
Ownership boundaryThese failures belong to the #3805 ExtensionRunner context/signal change, not PR #3665's Rust NotificationServer callback delivery or shell pipeline process-group ownership. No #3665 repair or rebase should absorb this regression, and no #3814 animation change should be altered for it. The bounded repair belongs to the existing #3805 / issue #3803 owner lane: preserve the live context's lazy getters and identity semantics while overlaying the per-handler abort signal, with these three regressions retained as focused acceptance coverage. No branch was changed or pushed, and no workflow was rerun or cancelled. — |
Summary
ooo-bridge.tsexample extension with user-level and project-level enable commandsouroboros dispatch --runtime gjcsoooo interviewreaches Ouroboros v0.50.7's GJC MCP-backed skill dispatcherouroboros setup --runtime gjc, manual GJC installation, graceful failure modes, and the distinction from native/skill:deep-interviewCloses #3803.
Community sources:
15340108862455808911534014083462860841Latest-release grounding
origin/devata8fa63a599e9fa3d0189e48bfce778a36353ccddv0.50.7, commitcb658aa819bfabafecbbe91bc36327f10691171b--runtime gjcbinds shared MCP handler compositionVerification
bun test packages/coding-agent/test/ooo-bridge-extension-contract.test.ts packages/coding-agent/test/ooo-bridge-runner-redteam.test.ts packages/coding-agent/test/extensions-discovery.test.ts— 60 pass, 0 failbun --cwd=packages/coding-agent run check— Biome clean, TypeScript noEmit cleangit diff --check— cleangjc ultragoal review --spec <approved-plan> --executor-qa-json <qa-report> --mode review-only --json— no findings, artifact validation passed—
[repo owner's gaebal-gajae (clawdbot) 🦞]