Skip to content

fix: preserve abort interrupt provenance#710

Merged
Astro-Han merged 1 commit into
devfrom
codex/fix-abort-provenance
May 18, 2026
Merged

fix: preserve abort interrupt provenance#710
Astro-Han merged 1 commit into
devfrom
codex/fix-abort-provenance

Conversation

@Astro-Han

Copy link
Copy Markdown
Owner

Summary

Preserve abort provenance in the minimal diagnostic paths needed for first-turn tool interruption triage.

  • Allow renderer session.action.abort diagnostics through the desktop sanitizer with only source, mode, and result.
  • Annotate runner interrupts that previously reached onInterrupt without source metadata.
  • Give SessionRunState scope-close interruptions a session-specific fallback source.

Why

The GPT-5.5 first-submit interruption logs narrowed the failure to a runner/session interruption, but the exported diagnostics could not identify who triggered the abort. The renderer already emitted abort diagnostics, but the main-process sanitizer dropped them. On the backend side, direct runner cancel and scope-driven fiber interruption could still arrive at onInterrupt with no provenance.

This PR does not try to change prompt execution behavior. It only makes the next exported session tell us whether the interruption came from the renderer abort path, an unattributed runner cancel, or the session run-state scope closing.

Related Issue

No GitHub issue yet. This came from user-provided diagnostic logs for recurring first-turn tool aborts.

Human Review Status

Pending. A human should make the final merge decision after reviewing the final diff and verification evidence.

Review Focus

Please focus on whether the new provenance labels are stable and specific enough for future exported-session debugging, especially the distinction between runner.cancel_without_meta, runner.interrupt_without_meta, session.run_state.finalizer, and session.run_state.scope.

Risk Notes

Low behavior risk. The change does not alter which runs are cancelled or when they are cancelled; it only attaches metadata to existing interrupt paths and allows an already-emitted renderer abort event through sanitization. No visible UI change.

How To Verify

Renderer sanitizer test: bun --cwd packages/desktop-electron test src/main/renderer-diagnostics-sanitize.test.ts -> 6 pass, 0 fail
Runner/run-state tests: bun --cwd packages/opencode test test/effect/runner.test.ts test/session/run-state.test.ts -> 31 pass, 0 fail
Desktop Electron typecheck: bun --cwd packages/desktop-electron typecheck -> pass
Opencode typecheck: bun --cwd packages/opencode typecheck -> pass
Diff check: git diff --check -> pass

Screenshots or Recordings

Not applicable. No visible UI change.

Checklist

  • Human review status is stated above as pending, approved, or not required
  • I linked the related issue, or stated why there is no issue
  • This PR has exactly one type label (bug, enhancement, task, or documentation), at least one primary routing label (app, ui, platform, harness, or ci), and exactly one priority label (P0 to P3), or I requested maintainer labeling
  • I described the review focus and any meaningful risks
  • I listed the relevant verification steps and the key result for each
  • I did not introduce unrelated refactors, dependencies, generated files, or file changes beyond the stated scope
  • I manually checked visible UI or copy changes when needed, with screenshots or recordings
  • I considered macOS and Windows impact for platform, packaging, updater, signing, paths, shell, or permissions changes
  • I called out docs, release notes, dependencies, permissions, credentials, deletion behavior, generated content, or local file changes when relevant
  • I reviewed the final diff for unrelated changes and suspicious dependency changes
  • I am targeting dev, and my PR title and commit messages use Conventional Commits in English

@Astro-Han Astro-Han added bug Something isn't working P2 Medium priority harness Model harness, prompts, tool descriptions, and session mechanics labels May 18, 2026
@coderabbitai

coderabbitai Bot commented May 18, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@Astro-Han has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 57 minutes and 28 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4a3c37ea-8675-4882-8c1f-fd094e57afb4

📥 Commits

Reviewing files that changed from the base of the PR and between 94b4792 and 29e76b3.

📒 Files selected for processing (6)
  • packages/desktop-electron/src/main/renderer-diagnostics-sanitize.test.ts
  • packages/desktop-electron/src/main/renderer-diagnostics-sanitize.ts
  • packages/opencode/src/effect/runner.ts
  • packages/opencode/src/session/run-state.ts
  • packages/opencode/test/effect/runner.test.ts
  • packages/opencode/test/session/run-state.test.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-abort-provenance

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the platform Electron shell, OS integration, packaging, updater, signing, paths, and permissions label May 18, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested priority: P2 (includes user-path files (packages/desktop-electron/src/main/renderer-diagnostics-sanitize.test.ts, packages/desktop-electron/src/main/renderer-diagnostics-sanitize.ts)).

P1/P0 are reserved for maintainer confirmation. Please relabel manually if this is a release blocker, security issue, data-loss risk, or updater/runtime failure.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces metadata tracking for session interruptions and cancellations by adding a fallback mechanism to the Runner utility. This ensures that interrupts occurring without explicit metadata, such as those triggered by scope closure, are correctly annotated with a source, reason, and timestamp. Additionally, the diagnostics sanitizer was updated to include the session.action.abort event, and new tests were added to verify the behavior of the interruption logic and the run-state finalizer. I have no feedback to provide.

@Astro-Han Astro-Han merged commit 7b004b4 into dev May 18, 2026
35 checks passed
@Astro-Han Astro-Han deleted the codex/fix-abort-provenance branch May 18, 2026 02:35
Astro-Han added a commit that referenced this pull request May 18, 2026
Port upstream PR anomalyco/opencode#25114's `changed` byte-comparison gate to both `Config.update` and `Config.updateGlobal` so that a no-op config write no longer tears down running instances.

## Root cause

Without the gate, `Config.update` (project) and `Config.updateGlobal` (global) call `Instance.dispose()` / `Instance.disposeAll()` on every write. A write of identical bytes — e.g., a UI mount that re-emits the existing setting — still disposes every running instance, which closes each `SessionRunState` scope mid-turn. The user sees the active assistant turn end with `MessageAbortedError` plus an `Tool execution aborted` tool result, and has to resend.

Upstream fixed the same class of bug in opencode commit `a9d399699` ("Prevent Model response Interruption when opening settings dialog"). The fix is not in PawWork's `dev` history (`git branch -a --contains a9d399699` returns only `remotes/upstream/dev`). This PR ports just the `changed` gate, not the broader anomalyco/opencode#25475 instance-lifecycle decoupling refactor.

## Change boundary

`packages/opencode/src/config/config.ts` only. `Config.update` and `Config.updateGlobal` now compute a `changed: boolean` from byte comparison; `writeConfigTextAtomic` / `fs.writeFileString`, `Instance.dispose()` / `invalidate()` only fire when `changed` is true. `updateGlobal` keeps a `!fileExisted` clause so the seed-migration path still materializes the file on a fresh install.

Regression test: `no-op global config write does not rewrite the file` in `test/config/pawwork-global-config.test.ts`. Uses a sentinel mtime — if the gate ever regresses, the second `saveGlobal` would rewrite the file and bump mtime past the sentinel, failing the test.

## Verification

```
typecheck: bun --cwd packages/opencode run typecheck — pass
targeted tests: bun --cwd packages/opencode test test/config/pawwork-global-config.test.ts test/config/config.test.ts — 154 pass, 0 fail
CI: typecheck, unit-opencode, smoke-macos-arm64, e2e-artifacts all green
```

## Review follow-ups

- Reviewer flagged a P2: if the disk config is updated externally and our write happens to produce bytes identical to disk, `changed=false` skips `invalidate()` and the in-memory `cachedGlobal` may lag disk. Push back: PawWork is single-instance (`requestSingleInstanceLock`), upstream `a9d399699` and #25475 both accept the same trade-off, and decoupling cache refresh from instance dispose is closer to a #25475-scale refactor than to this PR's "remove one known trigger" boundary. No follow-up opened. See PR comment for full reasoning.

## Residual risk

Low. Behavior only suppresses dispose when the write would have produced identical bytes; any real config change still disposes as before. No public API change, no platform-specific concern.

## Related

Candidate mitigation for #721. Deliberately not a closing keyword: post-#710 abort diagnostics on the next user reproduction will confirm or refute whether the silent writer was the actual trigger in the reported cases.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working harness Model harness, prompts, tool descriptions, and session mechanics P2 Medium priority platform Electron shell, OS integration, packaging, updater, signing, paths, and permissions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant