Skip to content

refactor(runtime): remove obsolete permission mode compatibility path - #5300

Open
chinawch007 wants to merge 2 commits into
apache:mainfrom
chinawch007:refactor/remove-permission-mode-compat-4795
Open

chinawch007 wants to merge 2 commits into
apache:mainfrom
chinawch007:refactor/remove-permission-mode-compat-4795

Conversation

@chinawch007

@chinawch007 chinawch007 commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #4795

Remove the unused SessionManager.setPermissionMode wrapper, its legacy-store fallback, and the equally unused SessionManager.setExecutionBoundaryKind entry point. Both could bypass the versioned configuration authority. Desktop and CLI retain their permission controls through session.configuration.updatetransitionSessionConfiguration.

  • Remove the unversioned boundary-write requirement from Runtime's SessionStore, obsolete helpers, and unused test stubs. Preserve the shared transition policy and Storage transaction implementation.
  • Move behavioral coverage onto configuration authority: permission widening/narrowing, descendant shell revocation, Deep Research label cleanup, and pending Interaction rejection. Split stale configuration revisions and concurrent boundary changes into deterministic tests that assert their distinct errors and preserve committed state.
  • Keep the two configuration capabilities optional in Runtime because production SessionAuthorityStore already requires both; optionality supports lightweight test stores that do not mutate configuration. Document the paired capability and atomic revision/configuration/boundary contract. Test each missing capability independently, without redundant combined cases or write probes.

This removes internal APIs without changing production permission-switching behavior. Same-configuration updates retain their existing no-op semantics. Historical mode_change writes were removed in #4879; current boundary logging remains unchanged.

Verification

Passed locally at b844456f0 after rebuilding:

  • npm run lint, npm run format:check, npm run build, and npm run typecheck.
  • knip --workspace apps/desktop and knip --workspace packages/ui, using the installed repository binary.
  • 559 tests passed, 0 failed across nine compiled test files: Runtime session-manager, runtime-kernel-interaction, session-manager-terminal-ledger, and runtime-event-read-model; Host session-catalog-coordinator and execution-model-composition; Storage sqlite-session-metadata-store; CLI runtime-host-session-driver; Desktop runtime-host-client-uds. These include the real Host permission regressions for ordinary Turns and active Goal continuations.

Not run: the full workspace test suite or manual Desktop interaction. Behavioral tests protect existing semantics; this API removal does not introduce a failing-before behavior fix, so the corresponding checklist item remains unchecked.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex implemented the cleanup and review follow-up, migrated and extended tests, ran verification, and drafted this description. Affected commits include Generated-by: Codex; retain the trailer in the final squash commit.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@github-actions github-actions Bot added the effort/M Under 500 readable lines label Sep 14, 2026
Remove SessionManager.setPermissionMode, its legacy-store fallback, and
helpers used only by that path. Production Desktop and CLI permission
changes continue through the versioned configuration authority.

Migrate concurrency, Deep Research cleanup, and pending Interaction tests
to transitionSessionConfiguration. Document the paired optional Store
capabilities and verify missing capabilities reject without fallback writes.

Fixes apache#4795

Generated-by: Codex
@chinawch007
chinawch007 force-pushed the refactor/remove-permission-mode-compat-4795 branch from 5d5e674 to 1d845e4 Compare September 14, 2026 12:36

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for picking this up. Reviewed at head 1d845e4. I re-verified the premise on current main: SessionManager.setPermissionMode has no production caller (Desktop sessions:setPermissionMode and the CLI driver both go through session.configuration.updatetransitionSessionConfiguration), and the removed legacy fallback was not a faithful mirror of the authority (no revision fence, no archived check, non-atomic header + boundary writes). So the removal is a real entropy reduction, and transitionSessionConfiguration covers every check the deleted helpers had. Both production paths are unaffected. Lint, format and the compiled session-manager suite (191/191) pass on this head; the migrated tests also pass on main, which matches what the description says.

Two things I'd like to see before this lands, both about the one authority acceptance criterion in #4795:

  1. setExecutionBoundaryKind is the same shape as the path this PR deletes. packages/runtime/src/session-manager.ts:1653-1688 derives a permissionMode itself and persists it through store.setExecutionBoundaryKind(...), which in sqlite-session-metadata-store.ts:4889-4899 patches permissionMode and labels into the header with no version fence, and without the deep-research cleanup, archived check or revision check that transitionSessionConfiguration applies. It also has zero production callers (the only non-test caller, run-command-core.ts:343, resolves to RuntimeHostRunRuntime, which forwards to the driver's configuration update). The test file now promotes it to a 'direct' route, which gives it a longer life. By the issue's own standard I think it should go in the same change, or the PR should say why it can't (I couldn't find a blocker: same file, same policy, same caller count).

  2. The description says capabilities stay optional, but not why. The reason is checkable and worth writing down: SessionAuthorityStore already requires readHeaderRecordSnapshot and updateSessionConfiguration, the only production store implements both, and optionality only serves a handful of test fixtures. Making them required would also touch relocateSessionWorkspace, which shares requireSessionConfigurationStore, so keeping them optional here is the right scope. Saying that answers the review item in #4795 instead of stepping around it.

Line-level notes are inline. One small correction for the description: the migrated tests pass on main unchanged, so the "fail without it" box should stay unticked, which is fine for a pure removal.

AI assistance: I used Claude Code to survey callers and run the ablation; every finding above was checked by me against the code and the test run.

// Either the configuration revision or the boundary revision can fence
// the stale request, depending on when its snapshot was observed.
if (
route === 'configuration' &&

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2. With each request reading its own snapshot inside update(), the two requests are no longer guaranteed to observe the same revision, so the assertion accepts either SessionConfigurationRevisionConflictError or operation_conflict. Those map to different client-visible outcomes at the Host (configurationSuccess(revisionConflict) vs configurationFailure), so the test no longer pins which one a stale request gets. The old 'legacy' route was deterministic. Suggest reading both snapshots before Promise.allSettled so both requests share one expectedRevision, then asserting the revision-conflict branch only. (The comment above about both requests observing Explore also no longer matches the code.)

for (const capability of missing) {
Object.defineProperty(store, capability, { value: undefined });
}
store.updateHeader = async () => assert.fail('Must not fall back to header writes');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3. requireSessionConfigurationStore is a single if (!a || !b), so the three missing-capability cases exercise the same throw; the third is the union of the first two. One case is enough. The two assert.fail probes are also unreachable now: transitionSessionConfiguration throws at its first line before any store write could happen. The valuable part of this block is that fallback writes are forbidden, and one case says that.

Comment thread packages/runtime/src/session-manager.ts Outdated
readHeaderRecordSnapshot?(sessionId: string): Promise<VersionedSessionHeader>;
/**
* Atomically check the expected revision and commit configuration, execution
* boundary and the new revision. Requires readHeaderRecordSnapshot.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3. This second paragraph restates the first (capabilities may be absent, no unversioned fallback). The first paragraph is the one that answers #4795; this one can go.

Comment thread packages/runtime/src/session-manager.ts Outdated
return headerToSummary(next);
}

async setExecutionBoundaryKind(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

See the top-level comment: this method persists permissionMode outside transitionSessionConfiguration with none of its checks and has no production caller. Same shape as the path this PR removes.

Remove the unused SessionManager boundary setter and its unversioned
Store requirement. Migrate descendant revocation and admission checks
to configuration authority and remove obsolete direct-route fixtures.

Split stale configuration revisions from gated concurrent boundary
conflicts, asserting each error precisely. Simplify capability tests
and explain Runtime optionality alongside the atomic Store contract.

Refs apache#4795

Generated-by: Codex
@chinawch007

Copy link
Copy Markdown
Contributor Author

Overall review

#5300 (review)

Thanks for checking this. I agree that retaining SessionManager.setExecutionBoundaryKind leaves the same architectural problem in place. The follow-up (b844456f0) removes that method as well as the unversioned write requirement from Runtime's SessionStore. The shared transition policy and Storage transaction implementation remain intact; Desktop and CLI still use the configuration operation.

I migrated the descendant shell-revocation and missing-admission-authority tests to transitionSessionConfiguration, kept the configuration-path read/write/network revocation cases, and removed the obsolete direct-route cases and their unused fixture. The direct-only same-mode Explore reset is no longer an API to preserve; the production configuration path's no-op semantics are unchanged.

The revised description now explains why the Store capabilities remain optional: production SessionAuthorityStore already requires both, while lightweight Runtime test stores do not all need configuration mutation. I also left the “fail without it” box unchecked, as discussed.

After rebuilding, all 559 affected tests passed. Full lint, format, build, typecheck, and Desktop/UI knip checks also passed. The full workspace test suite and manual Desktop interaction were not run. Codex assisted with the implementation, verification, and drafting these replies; the follow-up commit retains its Generated-by: Codex trailer.

Concurrent update errors

#5300 (comment)

Agreed that accepting either error obscured the test contract. I split this into two deterministic cases:

  • Commit a widening, then reuse the original snapshot and strictly assert SessionConfigurationRevisionConflictError, including expected/actual revisions and unchanged committed state.
  • Use a shared configuration snapshot and gate both initial boundary reads until both requests have observed the same Explore boundary. Then strictly assert that the losing request gets the boundary operation_conflict, without stopping the active Turn or revoking its shells. A fresh retry remains blocked as narrowing until the Turn settles.

One detail I found when implementing the suggestion: pre-reading the configuration snapshot alone does not guarantee a configuration-revision error. Inside the serialized commit, the boundary revision is checked before the second configuration-revision check. The explicit read gate fixes that interleaving, while the separate stale-snapshot case pins the revision-conflict result. No production error ordering or Host mapping changed.

Missing Store capabilities

#5300 (comment)

Removed the redundant “both missing” case and both assert.fail write probes. I retained the two individual missing-capability cases because they specify that each method is required: checking only one method in a future change should not silently weaken the contract. Each case now only asserts operation_unavailable and unchanged header/revision/boundary state.

Store contract comments

#5300 (comment)

Combined the comments into one contract block. It explains the paired capabilities, why Runtime keeps them optional despite the production authority requiring them, and the absence of a fallback. I retained the atomic expected-revision/configuration/boundary requirement because that is a separate implementation obligation, rather than a restatement of optionality.

Remaining boundary setter

#5300 (comment)

Removed SessionManager.setExecutionBoundaryKind and its requirement on Runtime's Store contract. The remaining useful tests now exercise transitionSessionConfiguration; duplicate direct-route cases and the unused AtomicBoundaryMemorySessionStore are gone. Storage's transaction primitive and the shared permission-transition policy remain in place.

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

Labels

effort/M Under 500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(storage): Remove the obsolete SessionManager.setPermissionMode compatibility path

2 participants