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
4 changes: 3 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,9 @@ version-specific CLI exports and distinguish them from the client SDK snapshot.
Do not install or bundle vendor Codex binaries. Keep generated schema provenance.

Use Swift Testing. Run strict swift-format lint, swift build, swift test, schema
drift checks, and an isolated standard MCP client before handoff. Logs must never
drift checks, and an isolated standard MCP client before handoff. Use `Documentation/Reference/Release.md` for packaged runtime acceptance through
the installed host; run `Scripts/check-host.py --help` and its Python unit tests
when changing that driver. Logs must never
write to the protocol stdout. Do not publish repositories or releases implicitly.

## Brand delivery
Expand Down
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@

## Unreleased

### Added

- Public-host runtime acceptance for the packaged adapter and installed Codex,
including native permissions, lifecycle recovery, thread handoff, authenticated
model execution and exact owned-process cleanup.
- Runtime operations, diagnostics, ownership and troubleshooting guidance in the
plugin manual.

### Changed

- Adapter databases initialize from one complete schema. Unknown migration
histories fail explicitly and require a new state directory.

### Removed

- Windows support; the plugin ships only for macOS.
- Offline domain-state migration command and import workflow.

### Fixed

- Valid upstream Exec session identifiers are accepted by release builds.
45 changes: 44 additions & 1 deletion Documentation/Architecture/Package.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,12 @@ processes before declaring an uncoordinated owner gone.
`CodexDatabase` stores approvals, runtime leases, thread ownership,
reconciliation receipts, acceptance runs, worktree leases and managed-worktree receipts using their
existing row and JSON representations.
It reuses GRDB transactions and lease-state compatibility handling; it does
It uses one initial domain schema and GRDB transactions; it does
not store host profiles, credentials, workspace registrations or audit.
Unknown migration identifiers fail before either the domain or shared-lease
store is initialized. Use a fresh adapter state directory for an incompatible
schema. The separate shared-lease database initializes only its lease table and
index.
Host-launched storage is partitioned by verified subject, profile and registered
workspace, not a transient connection or channel. Reconnection retains this
identity. Worktree lease facts use one transactional store per subject and
Expand Down Expand Up @@ -233,6 +237,45 @@ retrying metadata only. Provision rollback preserves Git content when host
cleanup is unconfirmed; it never represents that case as a complete rollback.
See [Host integration](../Reference/HostIntegration.md) for the operator contract.

## Runtime generations and teardown

Each workspace connection owns a lazy App Server runtime with a stable
`runtime_id`. Its current connection has a separate generation, process group,
App Server PID, supervisor PID, parent PID, timestamps, exit status, signal and
termination escalation. Concurrent first calls share startup. Notifications
and server requests belong to their exact generation; reconnecting does not
transfer ownership of earlier work.

Shutdown joins notification/request consumers, performs bounded unsubscription,
marks pending approval records interrupted, and closes the transport. Teardown
closes stdin, waits for graceful exit, sends TERM to the exact owned process
group if necessary, then KILL after another bounded interval and records reaping.
A private supervisor watches the owner's death and applies the same cleanup.
No process is selected by executable name or a machine-wide search.

The normal request timeout covers startup, workspace validation, the native
RPC and at most one fresh-generation read-only retry. `app/list` has a dedicated
budget for its potentially large directory snapshot and never restarts to retry
that snapshot. A timed-out generation must be retired and reaped before retry.
Concurrent closes share retirement, including back-pressured stdin. Runtime
lifecycle, connection state, process state, active-request count, last request
failure and terminal shutdown reason are independent; a request timeout does
not itself mean the runtime stopped.

Recent-thread supervision reads native state read-only, validates the canonical
workspace and rollout root, and scans a bounded tail. Snapshot-bound cursors,
page and Goal-scan bytes, record count, output bytes and elapsed scan budget are
reported. Native thread/Goal persistence remains separate from adapter ownership.

A native Goal, an adapter acceptance run and a completed turn have distinct
lifetimes. Official Desktop, IDE, CLI and Remote connections own their own
processes and authority. The adapter cannot unsubscribe or stop those clients.
Native approvals preserve correlation, deadlines and terminal states; a lost
connection never becomes consent or permission to replay. Account/configuration,
marketplace and remote-pairing operations require the appropriate local control
scope. Retained diagnostic data is bounded and credential-redacted; native
payload preservation does not make raw output safe to publish.

## API and verification scope

The Exec and App Server runtime tests execute in this package.
Expand Down
7 changes: 5 additions & 2 deletions Documentation/Architecture/VersioningAndRelease.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ immutable CI candidate artifact. Check the relocated candidate with a standard
MCP client and `Scripts/check-workflow.py --adapter … --codex …`. The latter
uses an isolated home and fixed loopback model for native approvals, turns,
cancellation, reconnection and owned-process cleanup. It does not prove real
model authentication. Host integration uses the Computer MCP repository's fixed
installed-gateway checks against the exact adapter bytes.
model authentication. Host integration uses this repository's `Scripts/check-host.py` against the
installed Computer MCP CLI, relocated adapter bytes and installed vendor. Full
acceptance includes authenticated model execution; fixture-only evidence cannot
replace it. [Release](../Reference/Release.md#runtime-acceptance) owns the commands
and prerequisites.

Accept the complete host/plugin/SDK combination before delivery. Create a formal
signed tag only for the accepted commit; `release.yml` promotes the
Expand Down
4 changes: 1 addition & 3 deletions Documentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
- [Host integration](Reference/HostIntegration.md): scoped callbacks, host authorization, managed registrations and failure recovery.
- [Installation](Reference/Installation.md): relocatable artifacts, host settings,
update/rollback/removal, and distribution boundaries.
- [State migration](Reference/StateMigration.md): offline transfer of
adapter-owned records from a Computer MCP snapshot.
- [Release](Reference/Release.md): publishing a release and notifying the
- [Release](Reference/Release.md): runtime acceptance, publishing a release and notifying the
plugin catalog.

The [root README](../README.md) is the public setup and command manual.
80 changes: 80 additions & 0 deletions Documentation/Reference/HostIntegration.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,83 @@ The host permits 1–1000 requested records and bounds the complete service resu
Reduce `limit` when the response would exceed the byte limit. Inspection does not
start Codex or a model. Real vendor/model authentication and GUI permissions are
separate checks from the host callback protocol.

Use the host's generic tool command with the exported name. The examples assume
an empty MCP registration prefix; prepend the configured prefix when present.
IDs come from the registered workspace and returned native thread:

```sh
computer-mcp tools call codex.app.handoff.diagnose --arguments-json \
'{"workspace_id":"<workspace-id>","thread_id":"<thread-id>","observed_error":"<message from the other client>"}'
computer-mcp tools call codex.diagnostics.snapshot --arguments-json \
'{"workspace_id":"<workspace-id>","limit":100}'
computer-mcp tools call codex.app.thread.release --arguments-json \
'{"workspace_id":"<workspace-id>","thread_id":"<thread-id>"}'
computer-mcp tools call codex.app.thread.recent --arguments-json \
'{"workspace_id":"<workspace-id>","thread_id":"<thread-id>"}'
```

When calling indirectly with `mcp.tools.call`, put `workspace_id` beside
`server`, `tool` and `arguments`; only native plugin arguments go inside
`arguments`. Native names and exported host names need not be identical.

The handoff diagnosis distinguishes these classifications:

| Classification | Operator action |
| --- | --- |
| `computer_mcp_owned` | Inspect the exact reported runtime and resolve pending approval/input. Release the thread; stop the exact runtime only when all its work should end. |
| `released_persisted` | No live adapter writer is reported. Open the persisted thread in the intended client. |
| `persisted_or_external` | No live adapter owner is verified. Reclaim only when the adapter should deliberately become the writer. |
| `external_writer_or_unfinished_watchdog` | Review stale receipts and allow bounded owned-process shutdown to finish. An external owner is inferred, never signalled. |

A successful unsubscribe alone does not prove release. Require the final
`released_persisted` classification, `externally_claimable: true` and
`computer_mcp_writer_ownership_remaining: false`. If a loaded receipt remains
once its exact runtime and process are gone, preview ownership reconciliation
and apply the reviewed digest through local control. A writer conflict in
another client must be resolved through that client's controls. Never use
`killall` or delete session files to bypass ownership.

### Execution or permissions fail

Inspect App Server with `codex.app.status` and Exec with `codex.exec.list`
independently. The host's provider/package doctor checks availability; it does
not prove model authentication. Verify the selected executable and native
configuration, including personal provider, MCP, Skills and hooks settings.
A slow or broken personal integration can delay startup. Diagnose credentials
in Codex's own store rather than copying them into host configuration.
An unavailable custom program fails explicitly; it never falls back to a
different executable. For a non-Git initial directory, select Exec's native
`options.skip_git_repo_check` explicitly.

Thread and turn responses report applied native permissions. Omitted settings
inherit Codex configuration; an explicit override can change the sandbox or
approval policy. A host profile name is not evidence of effective Full Access.
A host denial prevents invocation; it never silently chooses a narrower native
mode. Full Access cannot grant host callbacks extra capabilities, workspace
access, tickets or macOS privacy permissions.

The installed vendor must support the requested stable or explicitly enabled
experimental API. Incompatible methods fail explicitly. App Server failure
does not silently switch execution to Exec.

### Slow history or directory requests

Use the bounded history pages in [Workflows](Workflows.md#reading-long-threads),
or `thread.recent` for a persisted tail. Its `bounds` report page and Goal-scan
I/O, output bytes, elapsed scan and cooperative budget exhaustion;
`full_history_loaded` is false. Follow `next_before_cursor` only for older
context and restart from the newest page if the rollout identity changed.

`app/list` has its own configured deadline and uses one connection generation;
other calls use the normal end-to-end request budget. A directory HTTP 403
reported by `codex.app.request_failed` is an upstream response, not evidence
that local workspace content or the host was classified as hostile. It remains
a failed acceptance check. Inspect network and account availability separately.

If Safari or interactive Codex works but the adapter's directory request fails,
check fixed macOS HTTP/HTTPS/SOCKS proxy settings and restart the owned adapter
connection. Explicit inherited proxy values are preserved; otherwise the adapter
maps fixed system proxies to conventional uppercase/lowercase child variables
with loopback bypass. Derived proxy values are not persisted or logged. PAC
scripts are not evaluated.
8 changes: 0 additions & 8 deletions Documentation/Reference/Installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,3 @@ when operating a disposable test host. Without it these commands target the
normal App. Preserve the configured adapter state directory during an update
or rollback; uninstalling a package artifact does not authorize deleting
independently configured execution records or vendor state.

## Domain-state migration

Use the explicit [offline state migration](StateMigration.md) command to preview
and import prior Codex domain records. Installation and ordinary adapter startup
do not read or migrate the host database. The migration command has its own
snapshot, conflict, transaction and recovery requirements; it does not perform
the host-service cutover.
77 changes: 77 additions & 0 deletions Documentation/Reference/Release.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,83 @@ This guide covers publishing an accepted release and notifying the official
plugin catalog. [Versioning and Release](../Architecture/VersioningAndRelease.md)
owns the version, acceptance and immutability rules.

## Runtime acceptance

Use macOS with the selected installed `computer-mcp` CLI, a separately installed
vendor Codex, Python 3.11 or newer, Git and the verified release archive. The
adapter must be the executable extracted from that archive. Record the host,
plugin and vendor combination; a package doctor proves configuration and files,
not model execution. Run the ordinary checks in [Contributing](../../CONTRIBUTING.md)
first.

```sh
python3 Scripts/check-package.py --archive <archive.zip> --receipt <receipt.json> \
--destination .build/accepted-package
python3 Scripts/check-workflow.py \
--adapter "$PWD/.build/accepted-package/bin/codex-mcp-adapter" \
--codex /absolute/path/to/codex
python3 Scripts/check-host.py \
--host /absolute/path/to/computer-mcp \
--adapter "$PWD/.build/accepted-package/bin/codex-mcp-adapter" \
--codex /absolute/path/to/codex \
--output-directory "$PWD/.build/host-acceptance" \
--mode full --auth-file /absolute/path/to/vendor/auth.json --model <model-id>
```

`check-host.py` uses only the host's public `serve stdio` command and standard
MCP. It starts private host instances with explicit workspace selection, host
configuration and databases. It does not contact the normal App control socket
or an existing App Server. The model fixture and all native generations are
owned by the run. The selected output directory must be new; after inspecting
its receipt and confirming cleanup, remove its disposable state before reusing
that location.

Full mode needs a vendor file-store login authorized for the selected model.
The supplied `auth.json` is copied with mode `0600` into the private vendor home
and deleted on exit; the original is never changed. Keychain-only credentials
are not imported. The real-model checks make bounded text-only App Server and
Exec requests, including Exec resume, using a read-only native sandbox.
Model use may incur the account's ordinary usage charges. Keep the output
private because native histories and diagnostic evidence can include account
metadata. Never publish the authentication file or raw runtime state.

For a deterministic native check without credentials, use `--mode fixture` and
omit `--auth-file` and `--model`. This still needs the installed host and real
vendor executable. It tests catalog/diagnostic laziness, explicit Skills
directories and app-list deadlines, inherited and explicit Full Access, a native
read-only override, Git hooks, loopback and outside-workspace access, workspace
process isolation, three-connection thread/Goal handoff, vendor/adapter crash
recovery without replay, native approval, fork/review/steer/interruption, Exec
options/events/results/resume/cancellation/release, and exact thread archiving.
A separate disposable App Server protocol peer exercises native host callbacks:
workspace/recursion denial, Git dry-run index preservation, prepare without
mutation, exact single-use host tickets, a complete hooked file/Git commit, and
rejection of a pending local-approval ticket. The standalone host's configured
policy authorizes the successful ticket path; local App approval resolution is
verified by the host's generic tests, not simulated as an App UI check here.
It cannot prove real authentication or model availability.

The driver writes `report.json` with step results, binary versions/digests,
fixture digest, authentication status and cleanup errors. It separately records
bounded protocol evidence. A nonzero exit, upstream directory failure, missing
step, changed binary digest or unconfirmed cleanup fails acceptance; no network
challenge is treated as an expected success. Failure injection verifies ancestry
before signalling an exact owned PID. Unknown write outcomes are never retried.
Thread archival accepts only success or an exact missing-rollout error for the
owned thread; unrelated errors remain failures.

The release candidate requires the full report to pass for its exact executable
bytes, in addition to source tests and archive verification. Host plugin
installation, grants, local approval and uninstall remain the host's generic
acceptance responsibility; this driver validates the native runtime through a
public host registration. Keep those host checks with the accepted combination.

Pure driver logic and argument validation run without a host or vendor:

```sh
python3 -m unittest discover -s Tests -p 'test_host_acceptance.py' -v
```

## Publish

1. Confirm that `version` in `computer-mcp-plugin.toml` has not been released
Expand Down
Loading
Loading