Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
228ad45
feat(codex): backfill managed-home sessions into the real Codex home …
brennanb2025 Jul 15, 2026
07afc8f
feat(codex): flag-gated system-default real-home routing scaffolding
brennanb2025 Jul 15, 2026
6d980bb
fix(codex): strip the daemon-inherited Orca CODEX_HOME override for r…
brennanb2025 Jul 15, 2026
64c76ae
fix(codex): harden one-time session backfill
brennanb2025 Jul 15, 2026
b0b63c6
test(codex): cover staged cross-volume install
brennanb2025 Jul 15, 2026
0c2a807
feat(codex): app-server trust-grant client, capability cache, and gra…
brennanb2025 Jul 15, 2026
eb5a76c
fix(codex): grant managed hook trust via codex app-server RPCs in ins…
brennanb2025 Jul 15, 2026
be366ab
test(codex): cover app-server trust grant client, cache, ledger, and …
brennanb2025 Jul 15, 2026
e800e94
test(codex): cover commit-message real-home override strip/preserve
brennanb2025 Jul 15, 2026
f52dd79
Merge trust-plumbing branch (codex app-server trust-grant client) int…
brennanb2025 Jul 15, 2026
c9837fe
test(codex): WSL grant-lane coverage — in-distro invocation and fallb…
brennanb2025 Jul 15, 2026
c3f37e5
feat(codex): real-home hook installer trusted via the codex app-serve…
brennanb2025 Jul 15, 2026
c668ab0
fix(codex): resolve the trust-grant entry without requiring electron
brennanb2025 Jul 15, 2026
6e4214a
fix(codex): keep session backfill off main thread
brennanb2025 Jul 15, 2026
5c68a50
fix(codex): harden app-server trust grant fallback
brennanb2025 Jul 15, 2026
e15425a
fix(codex): install cross-volume session backfill copies atomically
brennanb2025 Jul 15, 2026
442cde8
fix(codex): resolve grant entry from __dirname so plain-node CLI entr…
brennanb2025 Jul 15, 2026
d4f5493
fix(codex): harden trust grant reconciliation
brennanb2025 Jul 15, 2026
8f9da3e
fix(codex): restore trust config permissions on rollback
brennanb2025 Jul 15, 2026
ca1389b
Merge remote-tracking branch 'origin/brennanb2025/codex-trust-rpc-gra…
brennanb2025 Jul 15, 2026
5eb0750
fix(codex): harden real-home routing cleanup and retries
brennanb2025 Jul 15, 2026
1fcdc9a
Merge remote-tracking branch 'origin/brennanb2025/codex-trust-rpc-gra…
brennanb2025 Jul 15, 2026
1581e32
fix(codex): preserve unicode trust RPC responses
brennanb2025 Jul 15, 2026
b552e71
fix(codex): preserve remote env and complete real-home cleanup
brennanb2025 Jul 15, 2026
7b7fa4e
fix(codex): preserve real-home lane invariants
brennanb2025 Jul 15, 2026
ef7604c
Merge remote-tracking branch 'origin/brennanb2025/codex-trust-rpc-gra…
brennanb2025 Jul 15, 2026
65fb31c
test(terminal): isolate replacement idle reset assertion
brennanb2025 Jul 15, 2026
dda4c37
Merge remote-tracking branch 'origin/brennanb2025/codex-session-backf…
brennanb2025 Jul 15, 2026
60e8af9
fix(codex): preserve real-home dotfile links
brennanb2025 Jul 16, 2026
87db673
fix(codex): preserve verified trust grants across launch prep
brennanb2025 Jul 16, 2026
b412582
fix(codex): preserve dangling config symlinks on rollback
brennanb2025 Jul 16, 2026
caf6cac
fix(codex): don't revoke a just-granted WSL home on a false 'missing'…
brennanb2025 Jul 16, 2026
1f9ab94
test(codex): model codex config/batchWrite faithfully on Windows
brennanb2025 Jul 16, 2026
22dc271
feat(codex): collapse duplicate session listings across Codex roots
brennanb2025 Jul 16, 2026
2f41d62
feat(codex): background sqlite index heal for backfilled sessions
brennanb2025 Jul 16, 2026
2e3a282
Merge remote-tracking branch 'origin/brennanb2025/codex-trust-rpc-gra…
brennanb2025 Jul 16, 2026
ce25b23
Merge remote-tracking branch 'origin/brennanb2025/codex-real-home-pha…
brennanb2025 Jul 16, 2026
d74aa56
fix(codex): preserve session identity during dedup heal
brennanb2025 Jul 16, 2026
8ce03b4
fix(codex): harden real-home heal boundaries
brennanb2025 Jul 16, 2026
9ecaee7
fix(codex): fail closed on unsafe backfill install
brennanb2025 Jul 16, 2026
fe278b4
fix(ai-vault): preserve execution boundaries and reap children
brennanb2025 Jul 16, 2026
1f451e5
fix(codex): enforce real-home resume and heal boundaries
brennanb2025 Jul 16, 2026
18e7414
fix(codex): stop index heal before delayed spawn
brennanb2025 Jul 16, 2026
26e7ef6
fix(ai-vault): preserve resume env deletion through drag
brennanb2025 Jul 16, 2026
a3457c8
fix(codex): strip inherited Codex homes on mobile real-home resume
brennanb2025 Jul 16, 2026
b1a557f
fix(codex): gate session migration on real-home lane
brennanb2025 Jul 16, 2026
93791d5
fix(codex): stop session backfill after opt-out
brennanb2025 Jul 16, 2026
f29cb27
fix(codex): keep session heal failures retryable
brennanb2025 Jul 16, 2026
57f5dbe
fix(codex): keep session migration state recoverable
brennanb2025 Jul 16, 2026
b31658b
fix(codex): retry republished missing session heals
brennanb2025 Jul 16, 2026
362b625
Merge remote-tracking branch 'origin/main' into brennanb2025/codex-se…
brennanb2025 Jul 16, 2026
50b61c6
fix(codex): harden trust grant lifecycle
brennanb2025 Jul 16, 2026
25ccf90
test(codex): type child.stdout as PassThrough for oversized-output write
brennanb2025 Jul 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion build-plugins/plain-node-entry-guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ const PLAIN_NODE_ENTRY_NAMES = [
'daemon-entry',
'parcel-watcher-process-entry',
'computer-sidecar',
'agent-hooks/managed-agent-hook-controls'
'agent-hooks/managed-agent-hook-controls',
'codex/codex-app-server-grant-entry'
] as const

const ELECTRON_REQUIRE_RE = /require\(\s*["']electron["']\s*\)/
Expand Down
13 changes: 13 additions & 0 deletions config/tsconfig.cli.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,30 @@
"../src/main/antigravity/hook-service.ts",
"../src/main/claude/hook-settings.ts",
"../src/main/claude/hook-service.ts",
"../src/main/codex/codex-app-server-capability-cache.ts",
"../src/main/codex/codex-app-server-client.ts",
"../src/main/codex/codex-app-server-grant-bridge.ts",
"../src/main/codex/codex-app-server-grant-envelope.ts",
"../src/main/codex/codex-app-server-session.ts",
"../src/main/codex/codex-config-mirror.ts",
"../src/main/codex/codex-config-path-reference-rewrite.ts",
"../src/main/codex/codex-home-paths.ts",
"../src/main/codex/codex-hook-identity.ts",
"../src/main/codex/codex-hook-trust-grant.ts",
"../src/main/codex/codex-managed-trust-reconciliation.ts",
"../src/main/codex/codex-process-exit-deadline.ts",
"../src/main/codex/codex-trust-config-rollback.ts",
"../src/main/codex/codex-trust-grant-host.ts",
"../src/main/codex/codex-trust-grant-ledger.ts",
"../src/main/codex/codex-wsl-hook-install-plan.ts",
"../src/main/codex/config-settings-promotion.ts",
"../src/main/codex/config-toml-line-scan.ts",
"../src/main/codex/config-toml-trust.ts",
"../src/main/codex/hook-service.ts",
"../src/main/codex/hook-trust-promotion.ts",
"../src/main/codex-accounts/fs-utils.ts",
"../src/main/codex-accounts/wsl-codex-command.ts",
"../src/main/codex-cli/command.ts",
"../src/main/command-code/command-code-managed-script.ts",
"../src/main/command-code/hook-service.ts",
"../src/main/copilot/hook-service.ts",
Expand Down
6 changes: 6 additions & 0 deletions electron.vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,12 @@ export default defineConfig({
// Why: forked with ELECTRON_RUN_AS_NODE so @parcel/watcher faults
// can't take down the main process (issue #7547).
'parcel-watcher-process-entry': resolve('src/main/ipc/parcel-watcher-process-entry.ts'),
// Why: run under ELECTRON_RUN_AS_NODE while the caller blocks on
// spawnSync — codex app-server trust grants need a live event loop
// but must finish before a Codex pane launch proceeds.
'codex/codex-app-server-grant-entry': resolve(
'src/main/codex/codex-app-server-grant-entry.ts'
),
// Why: electron-vite cleans out/main in dev. The dev CLI imports
// this path for `orca agent hooks ...`, so it must survive rebuilds.
'agent-hooks/managed-agent-hook-controls': resolve(
Expand Down
32 changes: 32 additions & 0 deletions mobile/src/session/ai-vault-resume-launch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,36 @@ describe('buildMobileAiVaultResumeLaunch', () => {
agentArgs: '--model opus',
agentEnv: { ANTHROPIC_BASE_URL: 'http://localhost:3000' }
})
// Only bare real-home Codex resumes request env deletion.
expect(launch.envToDelete).toBeUndefined()
})

it('deletes inherited Codex homes when resuming a real-home session like desktop', () => {
// Regression: a user agentDefaultEnv CODEX_HOME (or a stale daemon-
// inherited home) must not reroute a bare real-home resume typed into the
// created pane; desktop already strips the pair at pane spawn.
const launch = buildMobileAiVaultResumeLaunch({
session: session({ agent: 'codex', sessionId: 'codex-1', codexHome: null }),
hostPlatform: 'darwin',
settings: {
agentDefaultEnv: { codex: { CODEX_HOME: '/Users/ada/.codex-pinned' } }
}
})
expect(launch.command).not.toContain('CODEX_HOME=')
expect(launch.envToDelete).toEqual(['CODEX_HOME', 'ORCA_CODEX_HOME'])
})

it('keeps managed-home Codex resumes free of env deletion', () => {
const launch = buildMobileAiVaultResumeLaunch({
session: session({
agent: 'codex',
sessionId: 'codex-1',
codexHome: '/Users/ada/.orca/codex-runtime-home/home'
}),
hostPlatform: 'darwin'
})
expect(launch.command).toContain("CODEX_HOME='/Users/ada/.orca/codex-runtime-home/home'")
expect(launch.envToDelete).toBeUndefined()
})
})

Expand All @@ -161,6 +191,7 @@ describe('resumeAiVaultSessionInTerminal', () => {
resumeAiVaultSessionInTerminal({ sendRequest }, 'worktree-1', {
command: 'claude --resume abc',
env: { ANTHROPIC_BASE_URL: 'http://localhost:3000' },
envToDelete: ['CODEX_HOME', 'ORCA_CODEX_HOME'],
launchConfig: {
agentCommand: 'claude',
agentArgs: '',
Expand All @@ -176,6 +207,7 @@ describe('resumeAiVaultSessionInTerminal', () => {
{
worktree: 'id:worktree-1',
env: { ANTHROPIC_BASE_URL: 'http://localhost:3000' },
envToDelete: ['CODEX_HOME', 'ORCA_CODEX_HOME'],
launchConfig: {
agentCommand: 'claude',
agentArgs: '',
Expand Down
11 changes: 9 additions & 2 deletions mobile/src/session/ai-vault-resume-launch.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type { AiVaultSession } from '../../../src/shared/ai-vault-types'
import {
buildAiVaultResumeCommand,
buildAiVaultResumeShellCommand
buildAiVaultResumeShellCommand,
realHomeCodexResumeEnvDeletion
} from '../../../src/shared/ai-vault-types'
import { isResumableTuiAgent } from '../../../src/shared/agent-session-resume'
import type { SleepingAgentLaunchConfig } from '../../../src/shared/agent-session-resume'
Expand Down Expand Up @@ -71,6 +72,7 @@ export type MobileAiVaultResumeSettings = {
export type MobileAiVaultResumeLaunch = {
command: string
env?: Record<string, string>
envToDelete?: string[]
launchConfig?: SleepingAgentLaunchConfig
launchAgent?: TuiAgent
}
Expand Down Expand Up @@ -111,6 +113,9 @@ export function buildMobileAiVaultResumeLaunch(args: {
shell
}),
...(startupPlan.env ? { env: startupPlan.env } : {}),
// Why: the resume command is typed into the created pane, so the bare
// real-home override must strip Codex homes at pane spawn like desktop.
...realHomeCodexResumeEnvDeletion(args.session),
launchConfig: startupPlan.launchConfig,
launchAgent: startupPlan.agent
}
Expand All @@ -122,7 +127,8 @@ export function buildMobileAiVaultResumeLaunch(args: {
hostPlatform: args.hostPlatform,
hostTerminalWindowsShell: args.hostTerminalWindowsShell,
commandOverride
})
}),
...realHomeCodexResumeEnvDeletion(args.session)
}
}

Expand Down Expand Up @@ -155,6 +161,7 @@ export async function resumeAiVaultSessionInTerminal(
{
worktree: `id:${worktreeId}`,
...(launch.env ? { env: launch.env } : {}),
...(launch.envToDelete ? { envToDelete: launch.envToDelete } : {}),
...(launch.launchConfig ? { launchConfig: launch.launchConfig } : {}),
...(launch.launchAgent ? { launchAgent: launch.launchAgent } : {}),
...(launch.clientMutationId ? { clientMutationId: launch.clientMutationId } : {})
Expand Down
11 changes: 9 additions & 2 deletions src/main/agent-hooks/installer-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
existsSync,
mkdirSync,
readFileSync,
statSync,
writeFileSync,
chmodSync,
copyFileSync,
Expand Down Expand Up @@ -353,7 +354,11 @@ function writeScriptWithAclRetry(scriptPath: string, content: string): void {
}
}

export function writeHooksJson(configPath: string, config: HooksConfig): void {
export function writeHooksJson(
configPath: string,
config: HooksConfig,
options?: { preserveMode?: boolean }
): void {
const dir = dirname(configPath)
mkdirSync(dir, { recursive: true })

Expand All @@ -368,6 +373,8 @@ export function writeHooksJson(configPath: string, config: HooksConfig): void {
// UUID suffix makes the tmp path unique per call.
const tmpPath = join(dir, `.${Date.now()}-${randomUUID()}.tmp`)
const serialized = `${JSON.stringify(config, null, 2)}\n`
const existingMode =
options?.preserveMode === true && existsSync(configPath) ? statSync(configPath).mode : undefined

// Why: skip the write (and therefore the .bak rotation) when the on-disk
// content is already identical. Without this, every install() rewrites the
Expand All @@ -386,7 +393,7 @@ export function writeHooksJson(configPath: string, config: HooksConfig): void {
}

try {
writeFileSync(tmpPath, serialized, 'utf-8')
writeFileSync(tmpPath, serialized, { encoding: 'utf-8', mode: existingMode })
// Why: single rolling backup — one file, no accumulation in ~/.claude.
// Protects against a merge-logic bug producing bad JSON; the original is
// always recoverable from <configPath>.bak until the next write.
Expand Down
Loading
Loading