You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## Related Issue
No linked issue — maintainer-authored reliability and API work.
## Problem
Five separate gaps:
- A wire journal repair that fails (disk full, backup write refused)
left the journal corrupted, and the next `appendRecord` wrote behind the
corrupted tail. Callers of `flush()` saw success.
- Subagent turns opened in the transcript with no prompt, so the reader
could not see what the subagent was asked to do.
- A running foreground task could only be cancelled, never moved to the
background, over the server API.
- In the VS Code extension, two concurrent opens of the same session for
one view each wrapped the SDK session, so every streamed event was
delivered twice.
- Denying the OpenAI Codex consent page ended as `OpenAI Codex login
failed` after first prompting for the redirect URL, and the web sign-in
page waited out its full TTL.
## What changed
- `repairWireJournal` reports `repaired` / `failed`. `WireService` keeps
the failed repair pending, retries it before the next append, and
rethrows a `RECORDS_WRITE_FAILED` `WireError` from `flush()` when it
still fails, so nothing is appended behind a corrupted tail.
- `turn.started` now carries the prompt for `system_trigger` /
`subagent` origins, and the cold-path grouping folds the opening input
onto that turn. Search extraction still filters those messages out.
- New `POST /api/v1/sessions/{session_id}/tasks/{task_id}:detach`
action, answering `{ detached, status }`. The bash and subagent tools
report a user-initiated detach distinctly from a timeout detach, and
process tasks carry their parent tool call id.
- `PythinkerRuntime` serializes open / attach / detach per webview id,
so concurrent callers cannot both miss the session map.
- The OpenAI Codex callback distinguishes `error=access_denied` from
every other dead end. The CLI reports it as cancelled, and
`CodexLoginFlow` moves the attempt to `cancelled` with a reason instead
of waiting for expiry — the web sign-in page already renders that state.
## Checklist
- [x] I have read the
[CONTRIBUTING](https://github.com/PyModel/pythinker-code/blob/main/CONTRIBUTING.md)
document.
- [ ] I have linked a related issue (external PRs: the issue must have a
maintainer's `/approve`).
- [x] I have added tests that prove my feature works.
- [x] Ran `gen-changesets` skill, or this PR needs no changeset.
- [x] Ran `gen-docs` skill, or this PR needs no doc update.
## Risk
- Risk level: medium. Boundaries touched: session journal persistence,
the tasks REST surface, the VS Code session runtime, and the OAuth
callback.
- The journal change makes a previously silent failure loud: `flush()`
can now reject where it used to resolve. That is the intent — the
alternative is losing the record.
- The detach action is additive; `:cancel` keeps its behavior and its
error codes.
- No new dependency and no lockfile change.
## Verification
All exited 0:
- `pnpm run typecheck`
- `pnpm run lint` (0 errors, pre-existing warnings only)
- `pnpm test` — 1,218 files passed, 12 skipped; 20,522 tests passed, 3
expected fail, 79 skipped, 2 todo
- `pnpm run build`, `pnpm run build:web`, `pnpm run check:web`
- `pnpm sherif`, `node scripts/check-nix-workspace.mjs` (18 workspaces)
- `pnpm -C apps/vscode run typecheck`, `pnpm -C apps/vscode test` (18
files / 369 tests)
Each new guard was proven by mutation — reverting it fails the test that
covers it:
- dropping the `system_trigger`/`subagent` case from
`isDisplayablePromptOrigin` → 1 failure in `loop.test.ts`
- collapsing the per-view serialization → 3 failures in
`pythinker-runtime.test.ts`
- settling the callback with `null` instead of the denial → 1 failure in
`openai-codex-oauth.test.ts`
- folding the denial back into the timeout branch → 1 failure in
`codexLogin.test.ts`
`packages/transcript` and `packages/protocol` are web build inputs, so
`dist-web` was rebuilt; only `.web-bundle-manifest.json` changed.
## Rollback and review
- Rollback: revert the single commit; every change is additive or behind
a new branch.
- Residual risk: the journal `flush()` rejection is a new failure
surface for callers that previously ignored a silent loss.
- Human review wanted on the journal repair retry and the tasks route
split.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Foreground tasks can now be detached into the background.
- Background tasks and pending questions appear in the client’s
background-task panel.
- Subagent prompts and attachments display correctly in transcripts.
- Task details can retain parent tool-call information.
- **Bug Fixes**
- Prevented duplicated streaming output during concurrent session opens.
- Improved recovery from session journal write failures.
- Codex sign-in denials now appear as cancelled.
- Improved task detachment behavior and status reporting.
- **Documentation**
- Documented task detachment and updated background-task guidance.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Add a task detach action to the server API. Call `POST /api/v1/sessions/{session_id}/tasks/{task_id}:detach` to move a running foreground task to the background.
0 commit comments