Repository navigation
fix: persist runtime-owned settled-worker resume fences #19344
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c0a4916
1045909
4203db2
57d0ef6
6720908
7f36880
2197d23
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -109,6 +109,13 @@ export const WORKSPACE_SESSION_FIELD_DISPOSITION = { | |
| // the record's worktreeId on worktree and project removal. Moving a project between profiles runs | ||
| // removeSourceRepo, which has no owner scan, so these records leak there. | ||
| sleepingAgentSessionsByPaneKey: { onRepoRemoval: 'notRepoScoped', onTransfer: 'notTransferred' }, | ||
| // Why not transferred: the fence is a projection of the source profile's orchestration DB, and a | ||
| // transferred project carries no dispatch rows to re-derive it from. The destination runtime | ||
| // re-stamps whatever its own DB still claims on its first recovery pass. | ||
| legacyWorkerResumeFencesByPaneKey: { | ||
| onRepoRemoval: 'prunedByBespokeRule', | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Technical details# legacyWorkerResumeFencesByPaneKey has no bespoke repo-removal rule
## Affected sites
- src/main/orca-profiles/profile-project-session-field-disposition.ts:115 — classified `onRepoRemoval: 'prunedByBespokeRule'`
- src/main/orca-profiles/profile-project-session-state.ts — `removeRepoFromWorkspaceSession` has bespoke rules for `terminalSurfaceTombstonesByPaneKey` and `terminalPtyIncarnationsByPaneKey` but none for this field
## Required outcome
- A removed repo must not leave fence entries for its panes in the session, or the classification must say so honestly (`notRepoScoped` with a comment noting main's level-triggered rewrite owns the field's lifecycle).
## Suggested approach (optional)
- Mirror the `terminalPtyIncarnationsByPaneKey` rule: filter entries by `paneKey.slice(0, paneKey.lastIndexOf(':'))` against `removedTerminalTabIds`. Add a census test case so a future reclassification can't silently drop the rule. |
||
| onTransfer: 'notTransferred' | ||
| }, | ||
| terminalPtyIncarnationsByPaneKey: { | ||
| onRepoRemoval: 'prunedByBespokeRule', | ||
| onTransfer: 'copiedByBespokeRule' | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| import type { WorkspaceSessionState } from '../../shared/workspace-session-state-types' | ||
|
|
||
| // Old readers consume a derived record flag; only the runtime-authored set can retire it. | ||
| export function projectLegacyWorkerSession(session: WorkspaceSessionState): WorkspaceSessionState { | ||
| const fences = session.legacyWorkerResumeFencesByPaneKey | ||
| const records = session.sleepingAgentSessionsByPaneKey | ||
| if (fences === undefined || !records) { | ||
| return session | ||
| } | ||
| let projected: typeof records | undefined | ||
| for (const [paneKey, record] of Object.entries(records)) { | ||
| const fenced = fences[paneKey] === true | ||
| if (fenced === (record.automaticResumeBlockedBy === 'legacy-orchestration-worker')) { | ||
| continue | ||
| } | ||
| projected ??= { ...records } | ||
| if (fenced) { | ||
| projected[paneKey] = { ...record, automaticResumeBlockedBy: 'legacy-orchestration-worker' } | ||
| } else { | ||
| const { automaticResumeBlockedBy: _retired, ...unfenced } = record | ||
| projected[paneKey] = unfenced | ||
| } | ||
| } | ||
| return projected ? { ...session, sleepingAgentSessionsByPaneKey: projected } : session | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| import { projectLegacyWorkerSession } from '../legacy-worker-session-projection' | ||
| import type { PersistedState } from '../../../shared/persisted-state-types' | ||
| import type { WorkspaceSessionState } from '../../../shared/workspace-session-state-types' | ||
| import { sanitizeWorkspaceSessionTerminalRetirements } from '../../runtime/mobile-session-terminal-persistence-retirement' | ||
|
|
@@ -55,12 +56,12 @@ export class SessionHostPartitionOperations { | |
| getWorkspaceSession(hostId?: string | null): PersistedState['workspaceSession'] { | ||
| const resolved = resolveHostId(hostId) | ||
| if (resolved === LOCAL_EXECUTION_HOST_ID) { | ||
| return ( | ||
| return projectLegacyWorkerSession( | ||
| this[sessionHostPartitionOperationsContext].runtime.state.workspaceSession ?? | ||
| getDefaultWorkspaceSession() | ||
| getDefaultWorkspaceSession() | ||
|
Comment on lines
+59
to
+61
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
set -euo pipefail
rg -n -C 15 'function removeWorkspaceSessionOwner|removeWorkspaceSessionOwner\(' \
src/main/persistence
rg -n -C 8 'scheduleSave|workspaceSession =' \
src/main/persistence/loading-store/session-host-partitions.tsRepository: stablyai/orca Length of output: 23109 🤖 get_repo_knowledge executed:
Length of output: 18363 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- session-host-partitions.ts ---'
cat -n src/main/persistence/loading-store/session-host-partitions.ts | sed -n '1,175p'
printf '%s\n' '--- projection and field references ---'
rg -n -C 12 'projectLegacyWorkerSession|automaticResumeBlockedBy|cloneWorkspaceSessionState|deleteOwnerKeyedSessionFields' src/main/persistence
printf '%s\n' '--- save and persistence boundary references ---'
rg -n -C 10 'workspaceSessionsByHostId|workspaceSession|scheduleSave|serialize|persist|toJSON' src/main/persistence/loading-store src/main/persistence | head -n 500Repository: stablyai/orca Length of output: 50369 🏁 Script executed: #!/bin/bash
set -euo pipefail
cat -n src/main/persistence/loading-store/session-host-partitions.ts | sed -n '1,175p'
printf '\n--- symbols ---\n'
rg -n -C 15 'projectLegacyWorkerSession|automaticResumeBlockedBy|cloneWorkspaceSessionState|deleteOwnerKeyedSessionFields' src/main/persistence
printf '\n--- save boundary ---\n'
rg -n -C 10 'scheduleSave|writeStore|workspaceSessionsByHostId|workspaceSession' src/main/persistence/loading-store src/main/persistence | head -n 500Repository: stablyai/orca Length of output: 50369 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- session owner removal implementation ---'
cat -n src/main/persistence/restoring-sessions/session-owner-removal.ts | sed -n '1,180p'
printf '%s\n' '--- legacy projection definitions and callers ---'
rg -n -C 20 'projectLegacyWorkerSession|automaticResumeBlockedBy' src
printf '%s\n' '--- persistence writer definitions ---'
rg -n -C 20 'scheduleSave|workspaceSessionsByHostId|workspaceSession' src/main/persistence/loading-store src/main/persistence | tail -n 500Repository: stablyai/orca Length of output: 50370 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- session partition writes ---'
cat -n src/main/persistence/loading-store/session-host-partitions.ts | sed -n '174,360p'
printf '%s\n' '--- projection-related write helpers and callers ---'
rg -n -C 12 'preserveRuntimeAuthoredWorkspaceSessionFields|withoutRedundantGlobalFields|sanitizeWorkspaceSessionTerminalRetirements|setWorkspaceSession\(' src/main/persistence/loading-store src/main/persistence
printf '%s\n' '--- scheduleSave implementation ---'
cat -n src/main/persistence/loading-store/write-scheduling.ts | sed -n '1,180p'Repository: stablyai/orca Length of output: 50370 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- fence write tests around owner removal ---'
cat -n src/main/persistence/loading-store/store-runtime-authored-session-fences.test.ts | sed -n '180,280p'
printf '%s\n' '--- save scheduling and state flush ---'
cat -n src/main/persistence/loading-store/write-scheduling.ts | sed -n '1,120p'
rg -n -C 12 'flushOrThrow|scheduleSave|state\.workspaceSession|workspaceSessionsByHostId' src/main/persistence/loading-store/store.ts src/main/persistence/loading-store/store-runtime-state.ts src/main/persistence/loading-store 2>/dev/null | head -n 300Repository: stablyai/orca Length of output: 37189 Keep the compatibility projection out of the persisted session.
|
||
| ) | ||
| } | ||
| return ( | ||
| return projectLegacyWorkerSession( | ||
| this[sessionHostPartitionOperationsContext].runtime.state.workspaceSessionsByHostId?.[ | ||
| resolved | ||
| ] ?? getDefaultWorkspaceSession() | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
Repository: stablyai/orca
Length of output: 50370
🏁 Script executed:
Repository: stablyai/orca
Length of output: 47971
🤖 get_repo_knowledge executed:
get_repo_knowledge stablyai/orca /tmp/coderabbit-repo-knowledge/stablyai-orca-89dc44e4/learnings /tmp/coderabbit-repo-knowledge/stablyai-orca-89dc44e4/conventionsLength of output: 10408
Align the build evidence with the command.
When
out/main/index.jsexists,SKIP_BUILD=1makesglobalSetupreuse it. The recorded command therefore does not prove a fresh build. Record an explicitpnpm exec electron-vite build --mode e2estep in the evidence run, or revise the summary to describe reuse of an existing build.