{"_id":"@bensigo/plato-codex-runner","_rev":"3-4cec01bcabef191aa81a4fb7c8b5b0cc","name":"@bensigo/plato-codex-runner","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.0":{"name":"@bensigo/plato-codex-runner","version":"0.1.0","_id":"@bensigo/plato-codex-runner@0.1.0","maintainers":[{"name":"bensigo","email":"egweybensigo@gmail.com"}],"bin":{"codex-runner":"dist/src/cli.js"},"dist":{"shasum":"55f3a804003bed3a32f02f09287806e10da36b86","tarball":"https://registry.npmjs.org/@bensigo/plato-codex-runner/-/plato-codex-runner-0.1.0.tgz","fileCount":32,"integrity":"sha512-lqvsTiDlgoCStbnbc1aGXNEJWKg2Z1fvzo3FawhCTE/I6t+l4x4799hajsQw407sVsbtjytSOvfA51QKjqKR1w==","signatures":[{"sig":"MEQCIHdrjc7z5cKFiPx1bSwYTyjhB05I0mtQQaqvY7IkP1FxAiAiUL8Sb4lXcBuJdmJqn/rmb+NTRGhAPoJOFB+KT+BRJg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":162790},"main":"./dist/src/index.js","type":"module","_from":"file:bensigo-plato-codex-runner-0.1.0.tgz","types":"./dist/src/index.d.ts","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/src/index.js","default":"./dist/src/index.js"}},"scripts":{"dev":"echo 'codex-runner dev not wired yet'","lint":"oxlint .","test":"vitest run","build":"tsc --project tsconfig.json","typecheck":"tsc --project tsconfig.json --noEmit"},"_npmUser":{"name":"bensigo","email":"egweybensigo@gmail.com"},"_resolved":"/private/var/folders/8r/cpk3gflx5cv3hys1x7nvkhwc0000gn/T/b2943c2a1ed4d65e44c4a96fc2c6a4d3/bensigo-plato-codex-runner-0.1.0.tgz","_integrity":"sha512-lqvsTiDlgoCStbnbc1aGXNEJWKg2Z1fvzo3FawhCTE/I6t+l4x4799hajsQw407sVsbtjytSOvfA51QKjqKR1w==","_npmVersion":"10.9.4","description":"`@bensigo/plato-codex-runner` is a service inside the Plato monorepo. It owns the lifecycle of Codex-backed execution from queueing through worktree setup, runtime checks, session start, interruption, resume, and event capture.","directories":{},"_nodeVersion":"22.21.1","dependencies":{"@bensigo/plato-db":"0.1.0","@openai/codex-sdk":"^0.123.0","@bensigo/plato-config":"0.1.0","@bensigo/plato-orchestration":"0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"oxlint":"^1.60.0","vitest":"^4.1.4","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/plato-codex-runner_0.1.0_1777302546712_0.0012362561816019468","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@bensigo/plato-codex-runner","version":"0.1.1","_id":"@bensigo/plato-codex-runner@0.1.1","maintainers":[{"name":"bensigo","email":"egweybensigo@gmail.com"}],"bin":{"codex-runner":"dist/src/cli.js"},"dist":{"shasum":"345c3d2887d1353b3cdff95120431531cc89935b","tarball":"https://registry.npmjs.org/@bensigo/plato-codex-runner/-/plato-codex-runner-0.1.1.tgz","fileCount":32,"integrity":"sha512-j0r/TvY2q+8CTdr5JPmLosQSNg86xuVvXk/ElAkLk8m06kD1mqMpEWXfd+/zavuOSdTp9w/3Vggk+5dyBRsKcA==","signatures":[{"sig":"MEYCIQCxWyDxaIsa3eKilZj2kJttJjAsqpGW9rBJze/CaRkZagIhAJ8SgwDZKKZVAM19jX+dXmAGaCgmPjBRiujVaD0/Pes2","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":163311},"main":"./dist/src/index.js","type":"module","_from":"file:bensigo-plato-codex-runner-0.1.1.tgz","types":"./dist/src/index.d.ts","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/src/index.js","default":"./dist/src/index.js"}},"scripts":{"dev":"echo 'codex-runner dev not wired yet'","lint":"oxlint .","test":"vitest run","build":"tsc --project tsconfig.json","typecheck":"tsc --project tsconfig.json --noEmit"},"_npmUser":{"name":"bensigo","email":"egweybensigo@gmail.com"},"_resolved":"/private/var/folders/8r/cpk3gflx5cv3hys1x7nvkhwc0000gn/T/a6ff2207fb7f4b57db5cd74ae09bb300/bensigo-plato-codex-runner-0.1.1.tgz","_integrity":"sha512-j0r/TvY2q+8CTdr5JPmLosQSNg86xuVvXk/ElAkLk8m06kD1mqMpEWXfd+/zavuOSdTp9w/3Vggk+5dyBRsKcA==","_npmVersion":"10.9.4","description":"`@bensigo/plato-codex-runner` is a service inside the Plato monorepo. It owns the lifecycle of Codex-backed execution from queueing through worktree setup, runtime checks, session start, interruption, resume, and event capture.","directories":{},"_nodeVersion":"22.21.1","dependencies":{"@bensigo/plato-db":"0.1.0","@openai/codex-sdk":"^0.123.0","@bensigo/plato-config":"0.1.0","@bensigo/plato-orchestration":"0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"oxlint":"^1.60.0","vitest":"^4.1.4","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/plato-codex-runner_0.1.1_1777303139322_0.8764950538068903","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@bensigo/plato-codex-runner","version":"0.1.2","type":"module","publishConfig":{"access":"public"},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/src/index.js","default":"./dist/src/index.js"}},"main":"./dist/src/index.js","types":"./dist/src/index.d.ts","bin":{"codex-runner":"dist/src/cli.js"},"devDependencies":{"@types/node":"^25.6.0","oxlint":"^1.60.0","vitest":"^4.1.4"},"dependencies":{"@openai/codex":"^0.125.0","@openai/codex-sdk":"^0.123.0","@bensigo/plato-db":"0.1.0","@bensigo/plato-orchestration":"0.1.0","@bensigo/plato-config":"0.1.0"},"scripts":{"build":"tsc --project tsconfig.json","dev":"echo 'codex-runner dev not wired yet'","lint":"oxlint .","test":"vitest run","typecheck":"tsc --project tsconfig.json --noEmit"},"_id":"@bensigo/plato-codex-runner@0.1.2","description":"`@bensigo/plato-codex-runner` is a service inside the Plato monorepo. It owns the lifecycle of Codex-backed execution from queueing through worktree setup, runtime checks, session start, interruption, resume, and event capture.","_integrity":"sha512-/3D/RSn8fhVItA7CsARMtJjnj68qErPzVM9wNS0sSlw+kNz6y2lK+RK1HXckOJGym0gRsCJm2/Z71gH3jPkBUQ==","_resolved":"/private/var/folders/8r/cpk3gflx5cv3hys1x7nvkhwc0000gn/T/62abcc79eb713f79cbbe50e956985cd3/bensigo-plato-codex-runner-0.1.2.tgz","_from":"file:bensigo-plato-codex-runner-0.1.2.tgz","_nodeVersion":"22.21.1","_npmVersion":"10.9.4","dist":{"integrity":"sha512-/3D/RSn8fhVItA7CsARMtJjnj68qErPzVM9wNS0sSlw+kNz6y2lK+RK1HXckOJGym0gRsCJm2/Z71gH3jPkBUQ==","shasum":"084dd69ca35f45cc69b9b7e136286b9746a78d76","tarball":"https://registry.npmjs.org/@bensigo/plato-codex-runner/-/plato-codex-runner-0.1.2.tgz","fileCount":32,"unpackedSize":164700,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDmZnjwgEXwqhtdMYVqqSy37+EHGzn++7Wg8O/J5as12wIhANcMgn+PcRV2zd8jj4ntehAoLrgbmFwxaFfTK4ZaXLjM"}]},"_npmUser":{"name":"bensigo","email":"egweybensigo@gmail.com"},"directories":{},"maintainers":[{"name":"bensigo","email":"egweybensigo@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/plato-codex-runner_0.1.2_1777303598290_0.41122208673079386"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-27T15:09:06.587Z","modified":"2026-04-27T15:26:38.600Z","0.1.0":"2026-04-27T15:09:06.846Z","0.1.1":"2026-04-27T15:18:59.516Z","0.1.2":"2026-04-27T15:26:38.505Z"},"description":"`@bensigo/plato-codex-runner` is a service inside the Plato monorepo. It owns the lifecycle of Codex-backed execution from queueing through worktree setup, runtime checks, session start, interruption, resume, and event capture.","maintainers":[{"name":"bensigo","email":"egweybensigo@gmail.com"}],"readme":"# Codex Runner\n\n`@bensigo/plato-codex-runner` is a service inside the Plato monorepo. It owns the lifecycle of Codex-backed execution from queueing through worktree setup, runtime checks, session start, interruption, resume, and event capture.\n\nThis package is not the whole project and should not describe the whole monorepo. Its job is narrower: provide the Codex execution backend that lets Plato ask for agent work in a predictable way and recover what happened later.\n\nIn the larger Plato product, this service is one execution substrate for a future multi-agent orchestration flow. Plato's end goal is to help personal agents such as Hermes or OpenClaw decompose larger tasks into smaller subtasks, spawn multiple worker agents in parallel, and coordinate their results into one final outcome. Product-facing orchestration contracts live in `@bensigo/plato-orchestration`; `codex-runner` adapts Codex-backed execution behind that neutral boundary.\n\n## What The Service Owns\n\n- task admission and priority ordering\n- explicit task lifecycle state\n- git worktree isolation per task\n- Codex runtime readiness checks and bootstrap\n- agent session adapters for Codex-backed execution\n- structured event logs for task and session history\n- interruption and resume without losing the original worktree\n\n## Current Shape\n\nThe current codebase already exercises a concrete slice of this design:\n\n- `CodexRunnerService` queues tasks, schedules work when capacity exists, and persists task state.\n- `GitWorktreeManager` creates a dedicated branch and worktree under `.plato/worktrees/<taskId>`.\n- `DefaultCodexRuntimeManager` verifies that the `codex` runtime is available and can install it when missing.\n- `CodexSdkBackedAgentSession` provides the Codex-SDK-backed execution path while normalizing events into the runner stream.\n- SQLite-backed task and session stores provide durable runner state through the shared `@bensigo/plato-db` foundation.\n- File-backed log streaming still provides the ordered event trail used for inspection and recovery.\n- `@bensigo/plato-config` provides local Codex auth configuration so real operator runs can pass user-provided OpenAI credentials into the Codex SDK.\n- `CodexRunnerAgentRuntime` adapts `CodexRunnerService` to the agent-agnostic `@bensigo/plato-orchestration` runtime contract.\n\n## Task Lifecycle\n\nRunner tasks use explicit states rather than hidden flags:\n\n- `queued`\n- `running`\n- `awaiting_approval`\n- `interrupted`\n- `completed`\n- `failed`\n\nThe key invariant is that task state, active session identity, and worktree location stay understandable after failures or interrupts. If a task is interrupted, the worktree path should still exist in the persisted record so the task can resume in place.\n\n## Event Model\n\nThe runner treats logs as structured events first, text second. Current events include:\n\n- runtime checks and installation events\n- task queue, start, interrupt, resume, complete, and failure events\n- task reconciliation events emitted during startup recovery\n- session start, output, and exit events\n\nThat event stream is the service's audit trail. Other parts of Plato should be able to reconstruct what happened to a task without scraping terminal text.\n\n## Orchestration Boundary\n\n`@bensigo/plato-orchestration` owns neutral task, graph, event, result, and agent runtime contracts. MCP and other caller-facing surfaces should depend on that package instead of importing `CodexRunnerService` directly.\n\n`CodexRunnerAgentRuntime` is this package's adapter for that boundary. It maps Plato-level `workspacePath` and orchestration graph inputs to the runner's `repoPath` and task graph APIs, then maps runner records and events back to neutral orchestration records with `execution: { runtimeId, backend: \"codex\" }`.\n\nThe caller-facing CLI/MCP runtime bootstrap lives in `apps/plato-cli/src/bootstrap.ts`.\nThat app-level composition opens the existing operator runtime, wraps the runner\nservice in `CodexRunnerAgentRuntime`, and registers it with\n`TaskOrchestrationService`. The runner package exports its service, adapter, and\noperator runtime pieces for that bootstrap, while product handlers continue to\nspeak only orchestration contracts.\n\n## What Codex Runner Is Becoming\n\nThe longer-term role of this workspace is to be one of Plato's core execution services for agent work:\n\n- a stable Codex backend contract for submitting and inspecting tasks\n- strong isolation between tasks via git worktrees\n- resumable execution that preserves debugging context\n- adapters around side effects so scheduling and lifecycle rules remain unit-testable\n\nThe next product step beyond this package is not \"more Codex surface\" in the abstract. It is caller-facing orchestration over the neutral `@bensigo/plato-orchestration` boundary so future agent backends can plug in without reshaping Plato's product model.\n\n## Task Graphs\n\n`CodexRunnerService.createTaskGraph()` is the durable admission path for submitting one parent task with one or more child tasks. The parent and children are persisted through the store as one graph operation before scheduling begins, and each child is recorded with a `subtask` decomposition that points back to the parent task id. Children can also declare `dependencyTaskIds`; the scheduler only starts queued graph workers after every declared prerequisite has completed.\n\nOperators can inspect graph state with `getTaskGraph(taskId)` or `codex-runner graph status <taskId>`. Passing either a parent id or child id returns the parent, immediate children, dependencies, and aggregate graph state. Parent-scoped graph lifecycle events are emitted when the graph is created and when child tasks complete or fail. Worker/dependency events are emitted on child task streams when a dependency is satisfied, when a worker starts, or when a failed prerequisite blocks a dependent worker.\n\nThe CLI accepts `--max-concurrent-tasks <n>` on `start` and `graph start` to tune how many runner tasks may be active at once for that operator runtime.\n\n## Codex Auth Configuration\n\nBefore running real Codex-backed tasks, operators can configure local Codex auth:\n\n```sh\ncodex-runner config status\nprintf '%s' \"$OPENAI_API_KEY\" | codex-runner config set-openai-key --api-key-stdin\n# or: codex-runner config set-openai-key --api-key-env OPENAI_API_KEY\ncodex-runner config auth-chatgpt\ncodex-runner config auth-chatgpt --device-code\ncodex-runner config clear-openai-key\n```\n\nConfig defaults to `~/.plato/config.json`, with MVP local secret fallback storage at `~/.plato/secrets.json`. OpenAI API keys are stored in Plato's local secret fallback and passed to the Codex SDK as API-key auth.\n\nChatGPT subscription auth follows the OpenClaw-style split route: `chatgpt_oauth` is distinct from `openai_api_key`, and the login flow is owned by Codex app-server. `auth-chatgpt` starts `codex app-server`, calls `account/login/start` with browser OAuth by default, or `chatgptDeviceCode` when `--device-code` is passed, then stores only safe account metadata in Plato config. Codex persists and refreshes the OAuth tokens in its own auth store.\n\nAs the service grows, keep the domain language centered on `task`, `session`, `worktree`, `interrupt`, and `resume`. Those concepts are already the backbone of the implementation and should stay visible in the public API.\n\n## Startup Recovery\n\n`CodexRunnerService.reconcileRunningTasks()` is the startup recovery entrypoint for durable runner state. It scans persisted `running` tasks, checks the active session record, and reconciles orphaned tasks with missing or terminal sessions into `interrupted` or `failed`.\n\nRecovery preserves the stored `worktreePath`, clears the stale active session pointer, and appends a `task.reconciled` event so operators can see that the state changed during reconciliation rather than during normal session exit handling.\n\n## Development Notes\n\n- Install dependencies from the repo root with `pnpm install`.\n- Run tests with `pnpm --filter @bensigo/plato-codex-runner test`.\n- Run adapter tests with `pnpm --filter @bensigo/plato-codex-runner test -- codex-agent-runtime.test.ts`.\n- Run type-checking with `pnpm --filter @bensigo/plato-codex-runner typecheck`.\n\nImplementation rules for agents and contributors in this workspace live in [AGENTS.md](/Users/macbook/work/plato/services/codex-runner/AGENTS.md).\n","readmeFilename":"README.md"}