Skip to content

fix(run): apply the non-interactive deny rules to resumed sessions - #44559

Closed
gitRasheed wants to merge 2 commits into
anomalyco:devfrom
gitRasheed:fix/run-permission-hangs
Closed

gitRasheed wants to merge 2 commits into
anomalyco:devfrom
gitRasheed:fix/run-permission-hangs

Conversation

@gitRasheed

@gitRasheed gitRasheed commented Aug 24, 2026 •

Copy link
Copy Markdown
Contributor

Issue for this PR

Closes #44556

Type of change

  • Bug fix

What does this PR do?

Headless opencode run adds deny rules for question, plan_enter and plan_exit only when creating a session. The --session, --continue and --fork paths return first, so sessions created elsewhere, including over HTTP, can resume with the question tool enabled. A question then blocks on a Deferred with no server-side timeout. --auto only handles permission.asked, while questions use the unhandled question.asked channel.

This applies the same rules to resumed and forked sessions before prompting via session.update; the server merges rulesets and the evaluator takes the last match, so the appended rules win. The update is skipped when the ruleset already ends with these rules, and a failed read or update aborts the run. Interactive resumes are unchanged.

How did you verify your code works?

id=$(curl -s -X POST "$OPENCODE_URL/session" -H 'content-type: application/json' -d '{}' | jq -r .id)
opencode run --auto --session "$id" "use the question tool"   # hangs unpatched, completes patched

Two subprocess tests in test/cli/run/permission-resume.test.ts resume an HTTP-created session: one asserts the deny rules land last, the other has the model call the question tool and asserts the run completes. Both fail unpatched; suite and typecheck pass.

Screenshots / recordings

Not a UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

The deny rules for question, plan_enter and plan_exit were applied only
when run created the session itself. The --session, --continue and
--fork paths returned without them, so a session created elsewhere
resumed with the question tool live, and an asked question blocked the
run forever with no server-side timeout: --auto answers only
permission.asked and question.asked has no handler.

Resumed and forked sessions now receive the same rules before
prompting. The update is skipped when the ruleset already ends with
exactly these rules, so repeated resumes do not grow it, and a failed
read or update aborts the run instead of proceeding without the rules.
Interactive resumes are unchanged.
@gitRasheed
gitRasheed force-pushed the fix/run-permission-hangs branch from 5932b99 to 932f644 Compare August 24, 2026 00:10
@Enough1122

Copy link
Copy Markdown

AI code review — automated review for reference, author can ignore or act on any point.

Overall: real bug, right fix — resuming an externally created session without re-applying the non-interactive denies leaves question live and hangs the run, and the tail-match idempotence plus the hang-regression test are well thought out. Two things to verify:

  1. packages/opencode/src/cli/cmd/run.ts:473 — sdk.session.update({ sessionID: info.id, permission: [...rules] }): if update replaces the session's permission array rather than appending, this wipes whatever rules were already configured on the resumed session (user allows/denies made over HTTP or a prior interactive run). The integration test can't tell the difference because the fixture session starts with an empty permission list. If the API replaces, send [...(current.data.permission ?? []), ...rules]; if it appends, consider a one-line comment saying so, since the tail-skip logic below silently depends on it.

  2. packages/opencode/src/cli/cmd/run.ts:474 — if (updated.error) die(...) lacks the return used three lines up (return die("failed to read the resumed session")). Fine if die is typed never, but if its type widened anywhere in this file's helpers, control would fall through to return info and mask the failure. Making both call sites consistent removes the doubt.

Minor: sessions resumed across CLI versions with changed rule sets will accumulate stale deny tails (acknowledged in the comment as harmless — agree, since last-wins ordering makes them inert). The duplicated-rule scenario might deserve a tiny assertion in the second test so future refactors of the tail check don't silently regress idempotence.

@github-actions

Copy link
Copy Markdown
Contributor

Automated PR Cleanup

Thank you for contributing to opencode.

Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions.

This PR was closed because it matched the following cleanup criteria:

  • The PR was created more than 1 month ago
  • The PR had fewer than 2 positive reactions
  • Positive reactions are counted as thumbs-up, heart, celebration, or rocket reactions on the PR

PRs created within the last month are not affected by this cleanup.

If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate.

Thanks again for taking the time to contribute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

run --session hangs when the model uses the question tool on an externally created session

2 participants