Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 23 additions & 0 deletions .agent/CONTINUITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Project continuity

## 2026-07-18: guided Codex CLI dry-run backend

- Added a first-party `codex-cli` backend so an operator's saved ChatGPT Codex login can power
planning, implementation, and review without copying credentials into a repository container.
- The controller owns every Codex argument. Configuration may name only the Codex executable and
model; extra CLI arguments and environment pass-through are rejected.
- Codex 0.145.0 or newer is required because the adapter uses permission profiles and a fixed set of
current feature-disable controls. Model-run commands receive only minimal runtime reads and the
temporary workspace, with network disabled and credential-like workspace files denied. User
config, project instruction injection, rules, hooks, apps, web search, subagents, and shell
snapshots are disabled for each run. Repository-local Codex skills are refused and execution uses
an empty isolated `HOME`; only `CODEX_HOME` remains visible to the CLI process for saved auth.
- Planning and review receive a read-only workspace. Implementation receives workspace write.
Leftovers still performs its own Git metadata checks, canonical diff gates, offline container
verification, independent review, telemetry validation, and cleanup proof.
- `leftovers setup codex` creates a new mode-0600 dry-run config only after the operator confirms the
repository AI policy, SPDX license, offline test argv, and quota envelope. It detects but does not
install Python, Git, Codex, `gh`, or Docker/Podman, and it does not install a scheduler.
- The Codex CLI backend remains lower assurance than a fresh VM/microVM and is intentionally blocked
from `draft-pr` mode. A later publication PR should add a sealed approval/resume boundary before
reconsidering that restriction.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ __pycache__/
dist/
build/
.leftovers/
.agent/
.agent/*
!.agent/CONTINUITY.md
*.log
28 changes: 23 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ review—not more unsolicited pull requests.
runs too close to reset are rejected.
- Planning and implementation prompt contracts, fresh independent review, and deterministic
controller-rendered draft-PR text from verified evidence.
- Guided, owner-only Codex CLI setup plus a first-party execute-only adapter that uses a saved Codex
login, strict structured output, least-privilege permission profiles, and provider usage receipts.
- Docker/Podman command construction with no GitHub credential in the worker.
- Offline operator-curated verification commands plus structural rename/file-mode, dependency,
license, secret, size, and forbidden-path gates.
Expand Down Expand Up @@ -78,6 +80,20 @@ or broker cutoff when the provider supports one.

## Quick start

For the shortest supported execute-only path with a ChatGPT Codex plan, run the guided wizard:

```sh
leftovers --config config/leftovers.toml setup codex
```

It checks Python, Git, a read-only GitHub discovery token, Codex login/version/model, `gh`, the
container runtime, and the local sandbox image; asks the operator to confirm the allowlisted
repository, AI policy, license, offline test argv, and quota allocation; and creates a new owner-only
config in `dry-run` mode. It does not install packages, copy tokens, overwrite a config, schedule
runs, or enable publication. See [`docs/CODEX_CLI.md`](docs/CODEX_CLI.md).

For a generic container provider adapter:

1. Copy and curate the example configuration:

```sh
Expand Down Expand Up @@ -119,11 +135,12 @@ or broker cutoff when the provider supports one.
PYTHONPATH=src python3 -m leftovers --config config/leftovers.toml run --execute
```

Execution requires the configured agent command and container runtime. The stock sandbox image does
not embed a model provider or credentials; derive a provider-specific image or use a trusted host
CLI with its own sandbox. No runnable provider adapter ships in v0.1, and the host option is
explicitly lower assurance. See [`docs/AGENT_ADAPTERS.md`](docs/AGENT_ADAPTERS.md) for the exact
stdin/result-file contract and credential tradeoffs.
Execution requires the configured agent and container runtime. The stock sandbox image does not
embed a model provider or credentials. The first-party Codex CLI backend is execute-only and uses
the host CLI's saved login plus least-privilege permission profiles; generic providers still require
a reviewed adapter image or trusted host CLI. Host and Codex CLI backends remain lower assurance and
cannot enable draft publication. See [`docs/AGENT_ADAPTERS.md`](docs/AGENT_ADAPTERS.md) for the exact
contract and credential tradeoffs.

## Prove the control plane before using it

Expand Down Expand Up @@ -218,6 +235,7 @@ remaining v0.1 gaps in [`SECURITY.md`](SECURITY.md) before enabling writes.
- [`PROTOCOL.md`](PROTOCOL.md): prompt/result contracts and state invariants.
- [`SECURITY.md`](SECURITY.md): threat model, hard gates, and assurance limits.
- [`docs/AGENT_ADAPTERS.md`](docs/AGENT_ADAPTERS.md): provider adapter contract and v0.1 limits.
- [`docs/CODEX_CLI.md`](docs/CODEX_CLI.md): guided Codex setup, execution boundary, and limits.
- [`docs/OPERATIONS.md`](docs/OPERATIONS.md): activation, scheduler installation, and recovery.
- [`docs/TELEMETRY.md`](docs/TELEMETRY.md): exact quota/check-in semantics, dashboard boundary, and
rehearsal evidence.
Expand Down
7 changes: 6 additions & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ and partial publication or cleanup failures.
- GitHub issue/base state is rechecked before publication.
- Publisher uses an isolated Git HOME, disabled hooks/credential helpers, an ephemeral askpass script,
and a token held only in its subprocess environment.
- The first-party Codex CLI dry-run backend accepts no user CLI flags or environment pass-through,
disables automatic instruction/config/rule/hook/app/network surfaces, uses stage-specific
least-privilege permission profiles, and converts only closed-schema output and bounded usage
telemetry. Repository-local Codex skills are refused, execution uses an empty isolated home, and
ambient GitHub, provider-token, SSH-agent, and cloud credentials are not forwarded.
- Publisher identity must match configured expected login and immutable GitHub user ID before writes.
- Container removal requires exact managed/job/stage labels and a post-removal absence check;
workspace deletion runs only afterward and requires a managed marker, expected prefix, and
Expand Down Expand Up @@ -60,7 +65,7 @@ Do not describe these as solved:
human accepts the supply-chain/exfiltration risk.
- Agent provider authentication is deployment-specific. Baking credentials into an image is unsafe.
Prefer a model/tool broker or a provider CLI whose own sandbox keeps credentials outside tool
reach. The host backend is lower assurance.
reach. Host and Codex CLI backends are lower assurance and cannot publish.
- Secret regexes are not proof of absence. Production should add a dedicated scanner and entropy/
historical-secret checks.
- Sensitive-issue label and text matching is a conservative gate, not semantic proof that an issue
Expand Down
2 changes: 2 additions & 0 deletions config/leftovers.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ tmpfs_size = "512m"

[agent]
backend = "container"
# For the guided first-party Codex CLI backend, generate a separate owner-only config with
# `leftovers --config config/leftovers.toml setup codex`; do not hand-copy saved auth into this file.
# Build a provider-specific derivative of sandbox/Dockerfile that exposes this command and writes
# strict JSON to LEFTOVERS_RESULT_PATH. Never add GitHub credentials to that image.
command = ["your-agent-cli", "--prompt-stdin"]
Expand Down
35 changes: 27 additions & 8 deletions docs/AGENT_ADAPTERS.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
# Agent adapters

Leftovers v0.1 defines a provider-neutral process contract; it does **not** ship a runnable OpenAI,
Anthropic, local-model, or other provider adapter. The stock sandbox image supplies the execution
environment only. A deployment must build and review its own adapter before `run --execute` can
complete.
Leftovers defines a provider-neutral process contract and ships one first-party execute-only
integration for Codex CLI. Anthropic, local-model, and other providers still require a deployment to
build and review its own adapter. The stock sandbox image supplies the execution environment only.

## First-party Codex CLI backend

`agent.backend = "codex-cli"` invokes only the configured Codex executable; extra user-supplied
arguments and `pass_environment` entries are rejected. The controller selects the model and builds
all noninteractive, structured-output, permission, feature-disable, and result-path arguments.
Planning and review are read-only; implementation can write only the temporary workspace. Model-run
commands have no network and do not inherit the Codex process environment.

The Codex process receives only the small host environment needed to find its saved login. GitHub,
OpenAI API, Codex access-token, SSH-agent, cloud, and arbitrary variables are not forwarded. User
config and automatic project instruction injection are disabled, as are project rules, hooks, apps,
web search, subagents, and remote plugins. Exact final usage is converted from Codex JSONL into the
normal adapter telemetry protocol. The execution uses an empty isolated `HOME`, denies `.agents` and
`.codex` reads, and refuses a repository-local `.agents/skills` tree so repository skills cannot
become a higher-priority instruction channel.

This backend requires Codex CLI 0.145.0 or newer and a model present in its bundled catalog. It is a
lower-assurance host process and is rejected in `draft-pr` mode. Use `leftovers setup codex` and see
[`CODEX_CLI.md`](CODEX_CLI.md) for activation and limitations.

## Process contract

Expand Down Expand Up @@ -54,10 +73,10 @@ container, and a networked stage could expose the secret.

For higher assurance, use an external model/tool broker that keeps provider credentials outside the
worker and exposes only the minimum inference operation. A provider CLI on the host may keep its
credential outside the repository container, but `agent.backend = "host"` is the lower-assurance
profile and cannot be used with v0.1 draft publication. Direct provider credentials plus bridge
networking should be limited to curated, explicitly risk-accepted dry runs; `network = "none"`
cannot reach a hosted model API.
credential outside the repository container, but `host` and `codex-cli` are lower-assurance profiles
and cannot be used with draft publication. Direct provider credentials plus bridge networking
should be limited to curated, explicitly risk-accepted dry runs; `network = "none"` cannot reach a
hosted model API from a generic container adapter.

Do not claim autonomous operation until the chosen adapter, credential topology, image digest,
network policy, and all stage outputs have been exercised in execute-only runs with no remote write.
103 changes: 103 additions & 0 deletions docs/CODEX_CLI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Codex CLI backend

Leftovers includes a controller-owned `codex-cli` backend for execute-only dry runs using an
operator's saved Codex CLI login. It is the shortest supported path from a ChatGPT Codex plan to a
locally verified candidate patch. It is not a plan-balance scraper, shared quota pool, remote worker,
or automatic PR publisher.

## Prerequisites

- Python 3.11 or newer, Git, and Leftovers;
- Codex CLI 0.145.0 or newer;
- a saved Codex login (`codex login`, then `codex login status`);
- a read-only public-repository token in `GITHUB_TOKEN` for live scouting;
- Docker or Podman plus a locally built `leftovers-sandbox:latest` image for offline test execution
and cleanup proof; and
- `gh` only for a future, separately reviewed publication path.

ChatGPT sign-in uses included subscription access when the account and workspace support it. API-key
login uses separately billed API usage. Leftovers does not pass `OPENAI_API_KEY`, `CODEX_API_KEY`,
`CODEX_ACCESS_TOKEN`, GitHub credentials, SSH agent sockets, or arbitrary environment values into
the agent process. Prefer OS keyring credential storage and treat file-based `auth.json` as a
password. See the official [Codex authentication](https://learn.chatgpt.com/docs/auth) documentation.

## Guided setup

For an interactive owner-only configuration wizard:

```sh
leftovers --config config/leftovers.toml setup codex
```

The wizard asks for one allowlisted `owner/name` repository, a reviewed SPDX license, an HTTPS
source showing that AI-assisted contributions are permitted, one or more offline test argv arrays,
and an explicit daily or weekly token envelope. It writes a new mode-`0600` config in `dry-run` mode
and refuses to overwrite any existing file or symlink.

A non-interactive example is:

```sh
leftovers --config config/leftovers.toml setup codex \
--repository owner/project \
--ai-policy-url https://github.com/owner/project/blob/main/CONTRIBUTING.md \
--ai-policy-reviewed \
--allowed-license MIT \
--test-command-json '["python","-m","pytest","-q"]' \
--allocated-tokens 150000
```

Setup only diagnoses prerequisites. It does not install host packages, copy a token, log in on the
operator's behalf, build the sandbox image, enable publication, or install a scheduler. Review every
generated repository field before running a live scout.

## Execution boundary

For each model stage, Leftovers constructs `codex exec` arguments itself and uses ephemeral,
noninteractive, strict structured output. The adapter:

- selects the configured model explicitly;
- disables approval prompts while keeping a least-privilege permission profile;
- grants model-run commands only minimal runtime reads and the temporary repository;
- keeps planning/review read-only and grants workspace write only during implementation;
- disables model-command network, web search, user config, automatic `AGENTS.md` injection,
execution rules, hooks, apps, memories, goals, subagents, remote plugins, and shell snapshots;
- uses an empty isolated `HOME` for repository execution while retaining only `CODEX_HOME` for the
CLI's own saved authentication;
- denies `.agents`, `.codex`, common `.env`, PEM, and key-file reads inside the workspace, and
refuses repositories that contain a discoverable `.agents/skills` tree;
- captures exact final usage from Codex JSONL and validates it through the existing telemetry
protocol; and
- writes the final JSON through a closed, stage-specific schema outside the model's workspace.

The controller then checks Git metadata and the canonical diff, runs only operator-curated offline
commands inside the hardened container, performs a fresh review, and proves label-scoped container
cleanup before deleting the workspace. The coding process never receives GitHub publication
credentials. The official [`codex exec`](https://learn.chatgpt.com/docs/developer-commands?surface=cli#cli-codex-exec)
and [permission profiles](https://learn.chatgpt.com/docs/permissions) documentation describe the
underlying Codex controls.

## Activation

Run these in order:

```sh
leftovers --config config/leftovers.toml validate
leftovers --config config/leftovers.toml doctor
leftovers --config config/leftovers.toml scout
leftovers --config config/leftovers.toml run --execute
```

Inspect the hash-chained journal and cleanup receipt after every execute-only run. Complete at least
three successful dry runs before considering any publication work.

## Limits

- Codex still runs as a local process under the operator account. Permission profiles materially
reduce model-command access, but this is not equivalent to a disposable VM/microVM.
- A container runtime remains mandatory because setup and verification commands do not run on the
host.
- The configured token envelope is local admission control. It is not an exact view of remaining
ChatGPT plan allowance and cannot force a provider-side cutoff.
- `codex-cli` is rejected in `draft-pr` mode. Publication remains a separate future hardening step.
- The selected model must remain available in the installed Codex CLI's bundled catalog; `doctor`
fails closed when the CLI, login, version, or model check fails.
6 changes: 4 additions & 2 deletions docs/OPERATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

## First activation

1. Create `config/leftovers.toml` from the example.
1. For Codex CLI, run `leftovers --config config/leftovers.toml setup codex`; for a generic adapter,
create `config/leftovers.toml` from the example.
2. Curate a small repository allowlist and record current licenses, contribution rules, AI policy,
default branch, forbidden paths, and exact offline checks. If AI contributions are allowed, record
the policy's HTTPS source and the date it was actually checked.
3. Build a provider-specific agent image from `sandbox/Dockerfile` without GitHub credentials.
3. Build the sandbox image used for offline verification. Generic container agents also need a
provider-specific derivative of `sandbox/Dockerfile` without GitHub credentials.
4. Run `validate`, `doctor`, fixture scout, the OCI training cycle, live scout, and at least three
execute-only dry runs.
5. Inspect audit journals and confirm every temporary workspace is gone.
Expand Down
Loading