LearnNewsExamplesServices
Frontmatter
id10714
titleCodex sandbox bootstrap probe for .neo-ai-data/sqlite access
stateClosed
labels
enhancementaitesting
assigneesneo-gpt
createdAtMay 4, 2026, 9:59 PM
updatedAtJun 7, 2026, 7:24 PM
githubUrlhttps://github.com/neomjs/neo/issues/10714
authorneo-opus-ada
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 3, 2026, 12:04 PM

Codex sandbox bootstrap probe for .neo-ai-data/sqlite access

Closed Backlog/active-chunk-9 enhancementaitesting
neo-opus-ada
neo-opus-ada commented on May 4, 2026, 9:59 PM

Context

Each Codex Desktop session that runs Playwright unit tests touching .neo-ai-data/sqlite hits SqliteError: unable to open database file at the test setup step (12 tests fail at new Database(DB_PATH) before any assertion runs). @neo-gpt resolves the friction manually each session by re-running with escalated sandbox permissions, but the muscle-memory pattern repeats per fresh-context session boot. Empirical anchor: this session's PR #10713 review on bridge-daemon spec — sandboxed run failed all 12 tests at SQLite open; escalated host run passed 12/12 at ~11.2s.

This is structurally the same shape as the Claude Code worktree bootstrap problem solved by ai/scripts/bootstrapWorktree.mjs (#10095 / #10591): per-harness session-init substrate that should be one script invocation, not muscle memory re-derived each session.

The target shape is diagnostic-first (not auto-fix): the sandbox permission model is the user's choice, but a clear early probe + actionable error message removes the cost of pattern-matching 12 pathless SQLite failures back to "oh, escalation."

The Problem

Codex Desktop's sandbox runs in sandbox_permissions=require_escalated mode by default. SQLite file creation through the symlinked .neo-ai-data/sqlite/ path is blocked in that mode. Playwright's test-runner doesn't surface a useful diagnostic — the failure is a generic SqliteError: unable to open database file repeated 12 times, with no path, no symlink-target context, and no recommendation.

Empirical pain points (per @neo-gpt's PR #10713 review session, 2026-05-04):

  • 12 generic failures instead of one probe + clear remediation message.
  • No path printed — the failing absolute path (/Users/Shared/codex/neomjs/neo/.neo-ai-data/sqlite/test-daemon-<id>.sqlite) and its symlink target (/Users/Shared/github/neomjs/neo/.neo-ai-data/sqlite/...) are invisible until the agent grep-traces the spec.
  • No escalation guidance — the agent must independently know Codex's sandbox permission model and the require_escalated workaround.
  • Per-session rediscovery — every fresh context loses the muscle memory; the cycle repeats.

The Architectural Reality

  • ai/scripts/bootstrapWorktree.mjs — existing precedent. Resolves Claude Code's gitignored-config + .neo-ai-data/ substrate gaps via a single CLI invocation. Symmetric concern for Codex.
  • test/playwright/unit/ai/scripts/bridge-daemon.spec.mjs:27 — failure site. The spec sets DB_PATH = '.neo-ai-data/sqlite/test-daemon-${testId}.sqlite' and calls new Database(DB_PATH). The fs.ensureDirSync(path.dirname(DB_PATH)) call before it succeeds; the file creation is what fails under sandbox.
  • Symlink topology in Codex's clone (per @neo-gpt empirical observation): /Users/Shared/codex/neomjs/neo/.neo-ai-data/sqlite -> /Users/Shared/github/neomjs/neo/.neo-ai-data/sqlite. The sandbox blocks write through the symlink target.
  • Repro scope (empirically observed): Playwright unit tests that create transient SQLite files under .neo-ai-data/sqlite AND spawn the bridge-daemon subprocess. Pure unit specs not touching .neo-ai-data/sqlite are not in scope per current evidence.

The Fix

Add a new ai/scripts/bootstrapCodexSandbox.mjs (or generic bootstrapHarness.mjs that dispatches by detected harness) sibling to bootstrapWorktree.mjs. The script:

  1. Probes sandbox SQLite reachability: create + open + delete a transient SQLite file at .neo-ai-data/sqlite/probe-<uuid>.sqlite. Same path shape as the bridge-daemon spec uses, so the probe matches the actual test-runner failure surface.
  2. Resolves symlink topology: if .neo-ai-data/sqlite is a symlink, log the canonical target. Helps the agent diagnose cross-clone reachability.
  3. On probe success: emit ✓ Codex sandbox SQLite probe: ok (or equivalent) and exit 0. Tests proceed normally.
  4. On probe failure: emit a structured diagnostic — failing logical path, physical symlink target, sandbox permission mode if detectable, and the canonical remediation step ("re-run with escalated permissions" or "remove symlink + use local path"). Exit non-zero.

The agent (or human user) sees ONE clear failure with actionable guidance, not 12 pathless repetitions.

Acceptance Criteria

  • ai/scripts/bootstrapCodexSandbox.mjs (or unified bootstrapHarness.mjs) exists.
  • Script probes .neo-ai-data/sqlite/ write-reachability via a transient SQLite create+open+delete cycle.
  • On probe success: exit 0 with confirmation message; no side effects on test state.
  • On probe failure: structured diagnostic output including (a) failing absolute path, (b) symlink target if any, (c) detected sandbox mode if available, (d) canonical remediation suggestion. Exit non-zero.
  • Idempotent: probe leaves no residual artifacts.
  • Documented in AGENTS_STARTUP.md §6 (or equivalent harness-bootstrap section) as a Codex-side prerequisite alongside the existing bootstrapWorktree.mjs for Claude Code.
  • Optional: surface as a pre-test-run hook (e.g., npm run test-unit:probe-first or invoked automatically by test-unit script).

Out of Scope

  • Auto-fixing the sandbox permission model. The escalation choice is the user's; this ticket is diagnostic-only. A separate ticket can pursue auto-escalation if warranted.
  • Generalizing to all harnesses' sandbox models. Non-Codex harnesses (Claude Code, Antigravity) have different sandbox semantics and aren't covered here. The generic bootstrapHarness.mjs framing is forward-compatible but this ticket's scope is Codex SQLite probe only.
  • Removing the .neo-ai-data/sqlite symlink entirely from Codex's clone. That would diverge from the cross-clone substrate unification pattern in bootstrapWorktree.mjs. Probe-and-diagnose preserves the symlink while making its failure mode actionable.
  • Unifying with bootstrapWorktree.mjs immediately. Initial shape can be sibling script; merging into a generic dispatcher is a follow-up if multiple harness-bootstrap scripts emerge.

Avoided Traps / Gold Standards Rejected

  • Rejected: auto-elevate sandbox permissions. The user's permission model is intentional; auto-bypassing it would violate operator trust. Diagnostic-first is the correct shape.
  • Rejected: catch-and-rethrow inside Playwright spec setup. Adding error handlers to every .spec.mjs would scatter the diagnostic concern across many files. Centralized probe-first is the right substrate.
  • Rejected: probe inside bootstrapWorktree.mjs. That script's responsibility is gitignored-config + symlink setup for Claude Code worktrees. Codex sandbox probe is a different concern (different harness, different failure mode); coupling them would dilute both.

Related

Empirical Anchor Source

@neo-gpt supplied the exact error path, symlink topology, and require_escalated sandbox permission model context via A2A on 2026-05-04 during PR #10713 cross-family review. This ticket would not exist without his per-session manual diagnosis being re-derivable into a substrate-level fix.

Origin Session ID: 7e52099b-9632-4c67-a2a1-4e1a1ad1c414

Retrieval Hint: query_raw_memories(query="Codex sandbox SQLite require_escalated bootstrap probe diagnostic harness session bootstrap symmetry bootstrapWorktree")

Contract Ledger

Target Surface Source of Authority Proposed Behavior Fallback / Edge Case Docs Evidence
ai/scripts/diagnostics/bootstrapCodexSandbox.mjs (new) #10714 + structural fast-path: diagnostics sibling pattern under ai/scripts/diagnostics/ Probe .neo-ai-data/sqlite by creating, opening, closing, and deleting a transient SQLite file with the same path shape as affected Codex unit-test runs. Success exits 0 with a concise confirmation. Failure exits non-zero and prints logical path, resolved physical path / symlink target when present, SQLite error code/message, and explicit Codex sandbox remediation guidance. Cleanup is attempted even after open failure. Script JSDoc usage block. Unit tests with injected success/failure paths; manual script run in the current checkout.
package.json script ai:bootstrap-codex-sandbox #10714 AC7 + existing ai:* script namespace Exposes the diagnostic as an explicit opt-in command. Does not hook into test-unit; agents run it when Codex sandbox SQLite access is in scope, avoiding routine test cost. AGENTS_STARTUP.md invocation guidance. Script lookup plus unit/command validation.
AGENTS_STARTUP.md Codex sandbox guidance #10714 AC6 + live AGENTS_STARTUP.md worktree-bootstrap section Documents when Codex agents should run the probe and how to interpret success/failure. Also keeps worktree-bootstrap path aligned to the live ai/scripts/migrations/bootstrapWorktree.mjs surface. Keeps Claude/Antigravity worktree bootstrap distinct from Codex sandbox diagnostics; no auto-escalation. AGENTS_STARTUP.md. Doc diff plus targeted grep for command/path.
tobiu referenced in commit b69ccdc - "feat(codex): add sandbox sqlite probe (#10714) (#12396) on Jun 3, 2026, 12:04 PM
tobiu closed this issue on Jun 3, 2026, 12:04 PM