## 0.1.52: publication diagnostics and candidate cleanup

Publication failures report fixed `publication_step` and `LOCAL_FIX_*` codes;
completion rejection reports fixed reason counts. Rejected text, paths and values
are excluded. Validation and approval limits remain unchanged.

`max_diff_bytes` currently bounds the serialized full-file before/after delta,
not a line-based patch. Even a small edit can exceed it. The runner rejects that
candidate before staging; this release does not increase a contract's budget.

Owned temporary snapshot copies are removed after finalization settles, while
publication journals and source recovery state remain. An unknown remote outcome
or cleanup failure after remote publication requires reconciliation, not another
model run. Pre-existing forensic candidates are not swept automatically.

## 0.1.51: open a session for an ask no session can show

Sometimes no live session can show an AI Gateway ask or answer soon: there is no live session, no human prompt for 30
minutes, an idle Codex session, or an idle Claude session that cannot be woken. The runner then opens a session in the
person's own AI app instead of only showing a notification (Work Item e1c08b33, Work Decision 3ea5c197).

It opens only when all of these hold:

- the Mac had keyboard or pointer input in the last 5 minutes;
- the delivery was never opened;
- no session opened in the last 15 minutes still waits;
- fewer than 3 sessions were opened in the past hour.

The runner reads the idle time from `ioreg`, which needs no permission. When the person is away, they get today's
notification, and the runner checks again every 30 seconds while a delivery waits.

The session opens in the app of the most recent human prompt, or else in Claude, or else in the Codex app.
`/usr/bin/open -g` keeps the app in the background. The prompt is one of three fixed texts that carry no ids. For asks,
it tells the AI to read them with `work_inbox` and not to decide, review or answer until the person says so; for
answers, to read them and continue the work they were waiting for. Nothing runs until Enter. With the integration
installed in that app, that Enter makes the delivery seen. An ask shown only at the start of a session nobody types in
is shown again at a prompt in another session.

A failed open is not tried again for its deliveries, which get today's notification, and no other open is tried for 15
minutes. Only one open runs at a time, and none starts once the daemon begins to stop.

The notification sent with an open names the app. The runner logs `ask_session_opened` and `ask_session_open_failed`,
with codes only. Nothing changes until the Gateway's AI-first switch is on for a pilot actor. The Gateway now waits 30
minutes before an unseen ask goes to Slack.

## 0.1.49: one push transport instead of two long-polls

The daemon no longer long-polls the Gateway (Work Item 25d8ea74). It keeps one Pusher protocol 7 WebSocket to the
ELSA development Reverb server, which only rings, and calls `local_agent_runner_sync` once, with no wait: on start,
after each subscribe, on each signal, every 30 s while subscribed, and every 8 s while the socket is down or the
Gateway gives no push block. A job is claimed with `local_agent_jobs_wait` at `wait_seconds` 0, and only when the
sync says one is claimable. Session opens, ask deliveries and closures arrive on the sync result, and a closure is
acknowledged on the next sync. The full heartbeat goes out on a change or every 10 minutes. While the daemon takes no
jobs (reconciling at start, or suspended for recovery), it reports every adapter blocked with
`RUNNER_NOT_ACCEPTING_JOBS`, so the Gateway routes no job to it.

The socket sends `User-Agent: mtec-ai-local-runner/<version>`; the server's firewall refuses an upgrade without one.
The runner needs a Gateway with `local_agent_runner_sync` and `local_agent_runner_channel_auth`, so deploy the
Gateway before upgrading a runner. Push stays off until the Gateway's push switch names the employee; until then the
runner syncs every 8 s.

## 0.1.48: local_edit takes the complete file, not a patch

Read the existing file first, then pass its complete desired new contents in
`local_edit.content`, including unchanged text. The operation replaces the whole
file or creates it; it never applies a diff. Recognizable apply_patch directives,
unified hunk lines and diff headers return `DENIED_PATCH_CONTENT` before a write.
The isolated writer enforces the same guard. Literal patch blocks in a document
are also rejected by this conservative API; ordinary source string literals and
YAML separators remain accepted. No partial old/new edit tool is introduced.

Gateway and Runner must agree on the new tool inventory hash. Package runtime
receipts change, while the reviewed Codex CLI release manifest identity stays
unchanged. Keep existing -2G allowed paths; deploy the matching Gateway registry
and exact runtime pins before switching a daemon. The candidate contains the
newer development ask/messenger code documented below and
the 0.1.46/0.1.47 fixes; no integration is installed merely by preparing it.

### Also in 0.1.48: AI-first ask delivery and messenger mode (disabled)

The runner can put an AI Gateway ask (a Work Decision, a named review or a work request), and the answer to it,
into the employee's own running Claude Code or Codex session before any Slack message is sent (Work Item e1c08b33,
owner Work Decision 266f9475, option A). Deliveries arrive as ids only on the existing session-open wait. The daemon
keeps them in `asks.json` (mode 0600) and reports `received`, `shown`, `seen` or `dropped` with
`local_agent_ask_delivery_report`; the runner sends the Gateway no session id, cwd, prompt or text. Hooks reach the
daemon through `hub.sock` (0600, in the 0700 state root) and the stable shim `bin/gateway-hook`, which runs a small
hook client that prints nothing unless the daemon answers within 300 ms.

Only a session that a person is attending is served. A Claude Code session counts when `CLAUDE_CODE_SESSION_ATTENDED`
is `1` or, where Claude Code does not export that variable, when `CLAUDE_CODE_ENTRYPOINT` names a terminal, the Claude
desktop app or the VS Code extension. A headless `claude -p` or Agent SDK run gets nothing and is never counted as
having seen an ask. Codex exports no such marker, so every Codex hook session counts. The runner's own jobs never
count: a hook whose `HOME` is under `<stateRoot>/claude-jobs/` (where every Claude job runs) is refused, and Codex jobs
run with `features.hooks=false`, so they run no hook at all.

An ask is shown at a session start, at the next prompt (where it also counts as seen), at a turn end, or by waking an
idle Claude session through an `asyncRewake` Stop watcher. An ask shown at a session start, at a turn end or by a wake
counts as seen at the next prompt in that same session. A session is woken only within 30 minutes of a human prompt,
and at most 6 times an hour. With no such session the ask becomes one macOS notification, which gives up after 3
seconds and logs only an error code, and the ask waits for the next session start or prompt. Hook text is fixed and
carries validated ids only; the AI reads the ask itself with the Gateway show tools, which mark its text as untrusted.

The Gateway sends the ask keys on the wait only while asks are on for this runner. When a wait result comes without
them, every stored delivery ends: it is dropped from `asks.json` with no report, and the Gateway's Slack fallback
covers it. A stored delivery is forgotten an hour after it arrived, by which time the fallback (at most 15 minutes) has
long run.

Integrations are installed only on request, with `setup --integrations` or `integrations install`; setup never asks
about them. An app already installed in the directory the environment names is skipped and reported installed, without
rewriting its files:

```bash
npx mtech-ai-local-runner setup --integrations claude,codex
npx mtech-ai-local-runner integrations status
npx mtech-ai-local-runner integrations install codex
npx mtech-ai-local-runner integrations remove claude
```

Claude Code gets the skills-directory plugin `~/.claude/skills/mtec-ai-gateway-asks/`, which loads as
`mtec-ai-gateway-asks@skills-dir` in a new session or after `/reload-plugins`; `settings.json` is not touched. Codex gets
four handlers appended to `~/.codex/hooks.json` after a backup of that file; trust them once with `/hooks`. A
`hooks.json` that is not valid JSON, or whose hooks do not have the shape Codex reads, is left as it is and the install
reports `CODEX_HOOKS_JSON_INVALID`. `uninstall` removes both integrations, the shim, `asks.json` and any temporary
`asks.json.*.tmp` file a crash left behind, and it also works on a setup that never finished.

`CLAUDE_CONFIG_DIR` and `CODEX_HOME` are honoured. The LaunchAgent that runs the daemon gets only `PATH`, so every
install adds the directory it used to a list per app in `integrations.json` in the state root, and the daemon,
`doctor`, `integrations remove` and `uninstall` look in every recorded directory as well as in the environment. A
directory leaves the list only when nothing of the runner's is left in it, so installing into a second directory never
orphans the first, and the shim stays while any directory still has the hooks. When no absolute home directory can be
found, the command reports `INTEGRATION_HOME_UNKNOWN` for that app and writes nothing; set `HOME`, or `CLAUDE_CONFIG_DIR`
and `CODEX_HOME`.

On a fresh Mac without an admitted executor, or one already set up as a messenger, `setup` now completes in messenger
mode. It registers with no adapter capability and stores `mode: "messenger"` in `config.json`. The daemon then runs only
the session-open loop, for session opens and asks, and sends its own heartbeat at start, every 600 seconds and whenever
the installed integrations change. It has no jobs loop, no adapter probe and no PreToolUse self-test, and `manual-codex`
and `publication-recover` are refused with `MESSENGER_MODE_HAS_NO_EXECUTOR`. A full runner works as before and now
reports `mode: "full"` in its heartbeat. `doctor` reports the mode, the hub and each integration, including whether
Claude Code loads the plugin; for a messenger it requires neither an adapter nor the PreToolUse self-test.

Setup never turns a Mac set up as a full runner into a messenger. With no usable adapter it fails as 0.1.47 did, before
the login, and leaves `config.json`, the registration and the LaunchAgent as they were. Fix the adapter, or run
`uninstall` and then `setup` to set the Mac up as a messenger.

No ask is delivered until the Gateway's `AI_OPS_GATEWAY_WORK_ASK_AI_FIRST_ENABLED` switch is on and the employee is on
its pilot list. Until then an existing runner works as before: setup never turns a full runner into a messenger and
installs no integration it was not asked for. The one change without the switch is that setup on a fresh Mac without an
admitted executor completes as a messenger instead of failing. Deploy the Gateway receivers before upgrading a runner.

## 0.1.47: Claude security host wiring remains gated

Claude now shares the job security session and checks a live opaque executable
identity before launch. Account/control overlaps and aliases fail before control
creation; preparation failure and cancellation revoke authority. A trusted
host/probe/identity tuple is an in-process composition seam, not an environment
switch or a receipt loaded from disk. Fake-data tests do not enable production:
exact-release/native-policy, managed-input and credential/IPC/network evidence
and production verifier registration remain outstanding. Existing login, settings
and executable path are preserved. This release neither upgrades nor starts an
installed daemon. See `docs/ai-ops-gateway/claude-execution-admission-remaining.md`
in the Gateway repository for the consolidated verification boundary.

## 0.1.46: login and execution are separate

A locally logged-in account may still be blocked by security admission. New
`login_status`, `execution_status` and `execution_reason_codes` show those facts
separately; the legacy `authenticated` field remains an eligibility conjunction.
Malformed/unreadable Claude auth output is unknown, not a request to log in again.
Claude also rechecks task source identity after MCP preparation before spawning.
This release does not enable Claude execution, update an installed daemon or
change existing account settings. See the Gateway repository's
`docs/ai-ops-gateway/claude-execution-admission-remaining.md` for remaining gates.

## 0.1.45: pin official Codex alpha.11 outside the app

Manual and daemon Codex registration now require the reviewed official standalone
`codex-cli 0.163.0-alpha.11` (SHA256
`80df47f6ca9d316c732014bc5f6e6514696fafb5593e08e064332a1d3718b466`) at
`<employee-home>/.local/share/mtec-ai-local-runner/codex/0.163.0-alpha.11/<sha256>/codex`.
There is no ChatGPT app, PATH or environment fallback. A missing, changed,
symlinked, foreign-owned or group/world-writable installation blocks Codex.
Existing login/settings, the Claude path, policy observer and execution limits
are unchanged. This package does not install the standalone automatically;
provisioning, exact Gateway runtime pins and daemon transition need their own
reviewed delivery plan. A package update alone is not a successful transition.

Executable integrity checks still hash every byte on every call, with a bounded
1 MiB read buffer to reduce repeated filesystem dispatch. Tests separate
independent scenarios and distinguish completion output from actual target exit.
No timeout was expanded. The historical MCP startup timeout is not declared fixed.

### Interactive LaunchAgent

`setup` writes the runner LaunchAgent with `ProcessType` `Interactive`. The `Background` class kept the daemon, Codex and
every verification command at priority 4 on the efficiency cores, so P1 verification took 12.5 minutes on a busy Mac;
`Standard` was barely faster. An installed agent changes class only when its plist is rewritten and reloaded;
`launchctl print gui/$(id -u)/com.mtec.ai-local-runner` should then show `spawn type = interactive (4)`.

## 0.1.44: stop repeating whole-checkout checks in P1 verification

The P1 verifier rereads the whole model checkout for every source check and every candidate check. On the AI
Gateway repository (3,781 files) the live pilot spent about 12.5 minutes in `p1_verify`, and part of that was the same
check run twice with nothing in between. Each command is now bracketed by one fresh source check and one fresh
candidate check: before the first command, between commands and after the last. A source re-check compares the Git
listings and every file's mode and sha256 with the values recorded at the seal instead of rereading every base blob,
and an object already present in the private checkout is verified without being compressed again. Every file is
still read and hashed at each check, so the same changes are rejected as before.

## 0.1.43: give whole-checkout snapshots whole-checkout bounds

The P1 verifier snapshots the whole model checkout before it runs the reviewed commands. It passed the candidate limits
(`max_file_bytes` and `max_diff_bytes`, 16 KiB in the pilot contract) as the snapshot's own per-file and whole-tree
bounds, so any real project failed with `SNAPSHOT_REJECTED`: the AI Gateway checkout has 3,781 files, 48.5 MB and 588
files above 16 KiB. The snapshot now takes the same 128 MiB whole-tree memory bound as the publication hosts. The
candidate limits still apply to the changed files: their count, the diff size and, newly explicit, each changed file's
before and after size. Local Fix had the same defect, and Local Fix → PR could not publish on the AI Gateway repository because
an unchanged 1.09 MB file exceeds the 1 MiB `max_file_bytes` cap. Its production and server-CI snapshots and its Git
publication transport now use the same shared `SNAPSHOT_TREE_MAX_BYTES`. Changed files are still bounded by
`max_file_bytes`.

## 0.1.42: keep the guardian's reports when a late terminate fails

The owned guardian now reports to the host on its own pipe (fd3) and takes the host's commands on another (fd5);
fd4 stays parent liveness, and none of them reaches the executor. Before, one control socket carried both. When
Codex exited by itself and the guardian confirmed and exited while the daemon was busy, the daemon's late terminate
write failed on that socket, Node destroyed it, and the unread `root_exit` and `cleaned` reports were lost. 0.1.41
recovered the cleanup confirmation from the exit code, but the lost root exit outcome still failed the P1 publication
freeze with `OWNED_PROCESS_EXIT_UNCONFIRMED`. A failed command write now leaves the report pipe intact, so the host reads
every report to its end. Cleanup is again confirmed only by `cleaned`; the exit-code fallback is removed.

## 0.1.41: confirm a cleanup the guardian finished before a late terminate

When Codex exits by itself, the owned guardian confirms the cleanup and exits. A busy daemon could then write its
terminate request to the closed control socket before reading `cleaned`. That write error turned a confirmed cleanup
into an unconfirmed one and suspended the job. A control socket error alone no longer does that: cleanup is
confirmed by `cleaned` or by the guardian's exit code 0, which it uses only after sending `cleaned`. Timeouts,
liveness errors, malformed messages and `unconfirmed` reports still fail closed.

## 0.1.40: say why the owned guardian could not confirm cleanup

When the owned guardian reports an unconfirmed cleanup, the `executor_cleanup` diagnostic now carries fixed
`cleanup_guardian_*` observations: what started the cleanup, how TERM and KILL went, whether the executor group was
still alive and its pipes still open, whether the root had exited, and whether the host's deadline passed. Cleanup
decisions, deadlines and recovery are unchanged.

## 0.1.39: keep the first failure when executor cleanup is unconfirmed

A job whose Codex executor could not confirm its cleanup was suspended with only `EXECUTION_UNACKNOWLEDGED` in the
daemon log: the unconfirmed stop was rethrown before the failure was logged. The daemon now writes the stage that
failed first (P1 runs use `p1_freeze`, `p1_verify` and `p1_receipts`) and a second `execution_failed` line with
stage `executor_cleanup`, whose fixed `cleanup_*` observations name the cleanup step that failed or was still
pending at the deadline. Suspension and manual reconciliation are unchanged.

## 0.1.38: find the Codex app shipped as ChatGPT.app

0.1.37 looked only for `Codex.app`, so a Mac whose Codex app is the ChatGPT app (`/Applications/ChatGPT.app`,
bundle id `com.openai.codex`) reported `chatgpt: null` and got no [Open in ChatGPT] button. The runner now also
takes `ChatGPT.app`, in `/Applications` or `~/Applications`, when its Info.plist registers the `codex` URL
scheme. It reads the plist with `/usr/bin/plutil` (no shell, five-second timeout). The plain ChatGPT chat app
registers no `codex` scheme and is still not taken. Nothing else changes.

## 0.1.37: open my AI session from Slack

The daemon runs a second loop beside the job poller. When its employee presses [Open in Claude] or
[Open in ChatGPT] on an AI Gateway ask card, or [Continue in …] on an answer, the Gateway queues a
session open with ids only. The runner claims it with `local_agent_session_opens_wait`, builds the
prompt from its bundled templates, and opens the Claude desktop app (`claude://code/new`), Claude Code
(`claude-cli://open`) or the Codex app (`codex://new`) through `execFile('/usr/bin/open', [url])`. The
prompt only fills the prompt box: nothing runs until the person presses Enter. No folder, path or Git
remote URL goes into a link. Heartbeats report the installed apps in `session_open`. While the Gateway's
session open switch is off, the loop waits as long as the Gateway asks (`retry_after_seconds`) instead of
long-polling. Concurrent callers now share one OAuth refresh, so a rotated refresh token is never spent twice.

This release also carries the P1 pilot host composition (disabled), approved in Work Decision 071676a2. At
start the daemon builds the P1 verifier host only when the running Node and the host's Git match the bundled
reviewed binding by exact path and sha256, and logs one `p1_host` line with a status and a profile id. Any
other host leaves P1 off. The Gateway runner receipts flag stays off, so no P1 contract can be compiled yet.

Owner Work Decision 371c8b00 (option A) approved this local action. It needs no contract or launch
approval and does not change job execution, permissions or tools. Package integrity, runtime pins, a
daemon update and the owner-private `local-fix-host.json` regeneration remain separate approvals.

## 0.1.36: reviewed Codex CLI 0.163.0-alpha.11

The ChatGPT desktop app replaced its bundled Codex CLI with
`codex-cli 0.163.0-alpha.11`, so the daemon reported Codex as unauthenticated:
the installed binary no longer matched the single reviewed release. This patch
replaces that reviewed release with alpha.11 (binary SHA256
`8a6dc3938a2f5d30cc19c50b9ccad83a5aa2ca4a2e3411665430bb78a917220a`) in the
manual and daemon registrations and in the matching Gateway manifests.

The review repeats the alpha.10.2 evidence classes: OpenAI signature and
notarization, official archive digest and pre-signature payload match, and the
fake-account no-model native composition fixture. Managed-scope and auth-backend
evidence is inherited: it does not depend on the Codex binary, and the Codex auth
storage sources are identical between the two tags. Permissions, tools,
model IDs and residual risks are unchanged. Package integrity, runtime pins, a
daemon update and a separately approved exact contract/launch remain required
before any Codex run.

## 0.1.35: exact approved source paths in Codex instructions

Codex receives the approved checkout-relative paths, revision, access mode and
blocked-path list from its binding bundle. A denial for an unlisted path does
not imply that another approved file is unavailable. Scope descriptions exclude
repository transport coordinates and write leases. Unregistered commands remain
unavailable, and missing validation stays not_run/unverified.

This patch does not expand source or tool permissions, change the Claude path,
or authorize a new execution. Package integrity, runtime pins and a separately
approved exact contract/launch remain required for the next Fix attempt.

## 0.1.34: pinned writable Fix HEAD preparation

Accept a linked worktree's symbolic HEAD only for the exact approved writable
Fix branch and commit. Detached read-only checkouts retain their existing policy.
Bounded, no-follow metadata reads reject ref chains, traversal, symlinks and
post-preparation path changes. Preparation errors retain a safe substage code.
This patch does not grant another execution: package/runtime pins, installation
review and exact Gateway contract/launch approval remain required. Model work
limits, personal login/settings and the Claude execution path are unchanged.

## Unreleased: P1 runner-observed evidence (disabled)

P1 adds candidate-bound command receipts and changed-path evidence for explicitly
reviewed Codex Node/file-only profiles. It verifies a private exact-base candidate
after the owned model stops; model test claims cannot satisfy the Loop criteria.
P1 defaults off, the Gateway profile registry is empty, and the runtime P1 host
is absent by default. Source package `0.1.33` is inherited from upstream; this is
not a P1 package release or live acceptance. See the [P1 implementation and
delivery record](../../docs/superpowers/plans/2026-10-17-local-runner-p1-runner-observed-evidence.md)
for local verification results and separate deployment, runner-update and
activation gates.

## Unreleased: P0 terminal safety baseline (local verification only)

The upstream source package is `0.1.31`; P0 does not bump or publish a version.
Deploy a compatible Gateway receiver before upgrading any runner. Publication,
installation, restart, flag activation and live acceptance require their own
delivery gates; this local change authorizes none of them. See the repository
runbook at `docs/ai-ops-gateway/runbooks/local-agent-daemon-rollout.md`.

Pause/replan now report Runtime `cancelled` and Job `cancelled`. Blocked reports,
required questions and scope conflicts report Runtime `failed` and Job `blocked`,
with bounded useful diagnostics. Gateway retains compatibility with historical
blocked pause/replan receipts. Claude revision messages preserve actual
`acceptance_criteria` and `required_changes`. Unsupported active Codex controls
stop the owned launch and acknowledge transport; that ACK does not mean the
requested revision was performed. No automatic relaunch or grant reuse occurs.

Terminal receipts are retained and replayed exactly. On restart, claimed/shadow
attempts report failed `runner_restarted`; binding/binding_uncertain attempts
report blocked `binding_outcome_unknown`. Running/reconciling attempts stay
manually suspended because previous OS cleanup is unknown. Server expiry closure
records failed provenance; it does not kill a process, complete a Loop or attest
client evidence. Minimal fsynced recovery markers and invalid state (including
JSON null) are preserved. Do not delete dirty workspaces, recovery or audit state
to resume claims. State-store mutations are serialized and save/suspend/clear
snapshot their input before queuing; a hung filesystem can leave durable recovery
pending, without a false acknowledgement or new claims.

A model-free guardian owns each newly created executor group and observes a
private parent-liveness pipe. Parent EOF invokes TERM, a 2-second grace, then
KILL for surviving owned processes. The 6-second cleanup-confirmation bound is
not a model-runtime budget. Guardian death or descendants escaping the group
remain an unconfirmed-cleanup/manual-reconciliation gap; local tests do not
establish Task 7/P0 operational acceptance.

Tracked diff hashing streams UTF-8-compatible input and retains only hashes and
manifest metadata; collection is abort-fenced. Preparation immediately renews the
Job lease with a single-flight heartbeat, checking exact job ID, generation,
status and expiry. The existing 900000 ms deadline bounds preparation only.
Transient retries use 1/2/4-second backoff, at most three, only within the last
confirmed lease and deadline. Authentication (401/403), fingerprint and fence
failures are fatal. Git workspace preparation has no abort API: late audit
workspaces are retained, but late completion cannot launch a downstream model.
OAuth policy, admission and manual pause behavior remain unchanged.

Running execution has an independent watchdog for the last server-confirmed Job
lease. Hung startup, control, heartbeat, stream, evidence or event-response waits
cannot defer cancellation past that lease. Late responses cannot renew host
authority, acknowledge a command or advance reporting/state after fence loss;
an unknown remote append remains uncertain for reconciliation. Healthy validated
renewals extend execution without a fixed model-runtime limit.

Local-fix preparation, owned freeze, publication finalization and server cursor
synchronization share that fence. A stopped or expired attempt cannot regain
publication authority through a late response. Once publication may have taken
effect, retain `publication_pending` recovery instead of falsely completing,
failing or restarting the attempt. Canonical publication approval remains required.

Component, shadow admission, installed-package and live-provider evidence are
separate. Historical 0.1.10 hook behavior below is not current Claude admission;
Claude parity requires the actual current isolation/admission gate to pass.
No live push/hook probe or real CLI/model run is part of this verification.

## 0.1.30: governed local alert investigation evidence

The Gateway candidate offers explicit Local Codex Runner or Local Claude Runner
selection for read-only Sentry investigation. It binds the chosen adapter/model
and employee device to the exact approved launch; it never falls back to another
adapter. Each adapter retains authenticated host-owned bounded read observations
through completion and cleanup. These counts are employee-runner evidence, not
independent root-cause verification.

This release does not remove Claude's current unsupported host-admission gate.
An installed or authenticated CLI alone is not execution permission. Gateway
deployment, feature activation and actual execution approvals remain separate.

## 0.1.29: reviewed daemon Codex admission

This candidate connects the installed, hash-pinned root policy observer to the
existing employee-privileged Codex CLI adapter. The observer accepts only its
fixed employee UID and runs only a fixed read-only machine-policy command; it
never runs a model or reads credentials. A fresh per-job inventory and local
forced-policy checks are required. Managed, partial, stale and unknown evidence
block execution. This snapshot is not continuous machine-policy monitoring.

The package alone does not install or start the privileged service. Deployment
and employee-daemon upgrade remain separately approved operations. The daemon
advertises Codex only when the installed observer and supported binary/account
checks pass; the current account settings and Claude path are retained. Existing
manual releases remain separately registered. Already approved foreground Codex
acceptance is not daemon acceptance.

Terminal completion requests are persisted before delivery and replayed with
the original generation, lease and result after an unknown acknowledgement;
this never reruns a model. Admitted task duration/count remain unbounded. The
preparation, lease, cancellation, path and authenticated-MCP checks remain.

Starting the upgraded employee daemon can refresh Gateway OAuth credentials.
Future actual Codex execution may refresh its original shared account tokens.
Neither effect is part of no-model local verification. See the repository
`docs/ai-ops-gateway/codex-daemon-admission-validation.md` for exact evidence and
remaining acceptance gates.

# MTEC AI Local Runner

Install and configure the employee-bound macOS daemon:

```bash
npx mtech-ai-local-runner setup
```

The package stores safe runner configuration locally and keeps OAuth refresh credentials in macOS Keychain when available.

Public npm installation requires no npm account or publishing OTP. Setup requires
the employee's own Gateway OAuth login and, for a full runner, a supported,
authenticated selected CLI. Since the AI-first ask delivery release (Unreleased,
above), a fresh Mac without an admitted executor is set up as a messenger
instead; a Mac already set up as a full runner still fails setup without one.
Codex uses the employee's ChatGPT account. Claude requires its own login
and a separately verified host admission; it is currently not admitted.

For the current unattended Codex pilot, an administrator must separately install
the reviewed, employee-UID-bound policy observer on that Mac. The npm setup
command does not install that privileged service. A fresh employee computer is
not ready merely because npm installation succeeds.

## 0.1.28: completion receipt wire compatibility

Completion transport separates local timing/process observations from the strict
official-exec v2/v3 security receipt without changing its authority fields or
Gateway validation. Other receipt protocols and the original caller result are
unchanged. The existing 0.1.27 two-document actual acceptance and its same-Job
completion recovery are recorded separately; installing this patch does not
rerun Codex, alter personal login/settings or update the daemon.

## 0.1.27: explicit job MCP exposure

The job-local MCP omits deferred and Code Mode surfaces so the inspected ordinary
MCP path keeps its tools directly available. Server authentication, enabled tools
and scoped read-only/private-path checks remain unchanged. Exact-binary no-model
inspection accepted the configuration and registered four synthetic tools;
the subsequent separately approved actual run read both documents successfully.
The initial model-request tool list was not captured; observed scoped reads are
distinct evidence from a complete model-catalog inspection.
Foreground installation does not run Codex or update the daemon.

## 0.1.26: compiled private-file denial compatibility

The compiled `.env.*` blocked-path rule now denies that private-file family
without rejecting unrelated scoped reads. Private files at all depths,
read-only access and unsupported-pattern rejection remain enforced. Shared
Claude/Codex policy and actual MCP fake-data regressions use the full compiled
path combination. Foreground installation does not rerun Codex or update the
daemon; actual document acceptance still requires a separately approved run.

## 0.1.25: scoped reads and blocked diagnostics

Codex receives explicit file-scoped ai_local read/search guidance; launch and
Gateway reporting remain host duties. Valid blocked reports now retain bounded
report counts and identity comparisons in events and terminal results. They
remain blocked, and multiple reports still fail closed. Fake-data integration
checks generated settings with the actual scoped server; native model-visible
tool exposure still needs a separately approved actual attempt. Foreground
installation does not run Codex or update the daemon.

## 0.1.24: bounded report identity diagnostics

Failed report validation records pair counts for same/different wire item IDs
and exact text, using at most 64 transient keyed samples. Raw IDs, text, keys
and hashes are never included in these diagnostics. Sampling does not limit
actual task duration or messages. Multiple reports still fail; none are chosen,
merged or deduplicated.

These observations distinguish wire-output patterns, not model-generation
identity: the inspected exec serializer assigns fresh CLI IDs. Earlier failures
cannot be reclassified without missing identity evidence. Publication and
foreground installation do not rerun Codex or update the daemon.

## 0.1.23: separate progress from the final report

Codex receives native-message instructions: optional progress is plain text and
the structured completed/blocked report is emitted once at the end. The Runner
derives lifecycle events; Codex is no longer asked to author normalized progress
or checkpoint events. Claude's existing instructions are unchanged.

Strict report uniqueness and final-message validation remain in force. Fake
tests reproduce the observed multiple-report failure, but do not prove why the
historical model emitted three reports or guarantee future model compliance.
Publication and foreground installation do not rerun Codex or update the daemon.

## 0.1.22: completion report classification and terminal diagnostics

Report validation distinguishes missing messages, zero valid reports, multiple
valid reports, an invalid final message and an incomplete turn. Runtime events
and terminal Job results retain only fixed codes and consistent message/report
counts, never raw provider output. Structured blocked reports use the same
bounded single-fence envelope rules as completed reports and remain blocked.

Exactly one valid final report and successful turn completion remain required;
multiple reports are never picked or merged. Existing evidence, scope, identity,
cancellation and unlimited admitted employee work remain unchanged. Earlier
0.1.21 report failure cannot be reclassified without its missing original
counts. Publication and foreground installation do not update the daemon or
rerun Codex. See [completion report validation](https://bitbucket.org/mtechbal/api-cloud-service-ai-gateway/src/development/docs/ai-ops-gateway/codex-completion-report-validation.md).

## 0.1.21: exclude personal history from isolated job startup

The job-only Codex wrapper denies reads of the original account's `sessions`
and `archived_sessions`. A fresh private job database therefore cannot re-index
unrelated personal rollouts before MCP startup. Existing CLI/login paths,
personal settings, required authenticated MCP and unlimited admitted employee
work remain unchanged. Nothing is removed from the original history.

Pinned native fake-data comparison verified zero imported personal-history rows
and successful MCP initialization with this restriction. Real-account no-model
evidence remains partial because the private collector did not confirm its
owned exit/cleanup; real model completion is not established. Publication and
foreground installation do not update the daemon or authorize an execution.
See [local host comparison](https://bitbucket.org/mtechbal/api-cloud-service-ai-gateway/src/development/docs/ai-ops-gateway/codex-local-host-comparison.md).

## 0.1.20: distinguish owned wrapper and target startup

Add bounded, read-only process-name/state/wait hints for the exact owned
wrapper PID. At most seven one-second queries run during preparation and stop
at admission, failure, cancellation or exit. Fixed categories exclude raw names,
paths, process IDs, arguments and environment. Cancellation hard-stops only its
owned query. Local logging receives a deep diagnostic copy so it cannot mutate
the evidence later reported to Gateway.

These are direct-child hints, not executable identity, native function or
historical cause proof; forked descendants are not inspected. Preparation
deadlines, authenticated MCP/tool gates and unlimited admitted employee work
remain unchanged. Installation does not update the daemon or run Codex.
See [owned launch observation](https://bitbucket.org/mtechbal/api-cloud-service-ai-gateway/src/development/docs/ai-ops-gateway/codex-owned-launch-observation.md).

## 0.1.19: bounded preparation phase timing

Record fixed host milestones with monotonic elapsed milliseconds and remaining
original 30-second budget: inspection, before-spawn checks, spawn request/return,
prompt write/end request/return, MCP wait/discovery and authorization/failure.
Safe timing survives cleanup into local diagnostics, failed events and terminal
results; successful admission also retains it in the security receipt. No prompts,
arguments, paths, URLs, credentials or raw provider text are included.

This separates pre-spawn budget consumption from post-spawn MCP waiting. Spawn
return and pipe-call return do not prove native start or stdin consumption, and
these timings do not establish the historical native wait's cause. The deadline,
tool/identity checks and unlimited admitted employee work are unchanged. No
sampler, extra permission, retry, real account run or daemon update is implied.
See [phase timing and remaining conditions](https://bitbucket.org/mtechbal/api-cloud-service-ai-gateway/src/development/docs/ai-ops-gateway/codex-preparation-phase-timing.md).

## 0.1.18: preparation deadline enforcement

The overall 30-second preparation budget also covers release inspection. A
synchronous metadata check can delay JavaScript timer callbacks. Local guards
now use a monotonic deadline after inspection and at spawn/input/admission
boundaries, refusing expired preparation even when its timer has not run. The
budget is not reset or extended; admitted employee work remains unbounded.
Fake callbacks reproduce the late-admission defect. Existing 0.1.17 receipts do
not contain phase timing, so this is not proof of the historical native wait's
cause or successful real-account connectivity. No new native stack sampler,
account operation, daemon change or actual CLI run is part of this correction.

## 0.1.17: owned startup, pipe and transport observations

An owned-process collector marker distinguishes available diagnostics from a
missing collector. Fixed observations separate spawn, stdin write/end requests,
OS pipe finish, stdout/stderr activity/EOF, selected JSON event type names, exit,
and MCP TCP connection from authenticated HTTP discovery. No event payload is
copied into diagnostics. Pipe finish does **not** prove the CLI consumed stdin;
TCP activity does **not** prove the connection belongs to Codex or authorize tools.
Provider event type observations are not attestations of policy or model use.
The legacy `Reading prompt from stdin...` marker is not emitted for forced
`exec -` input in the inspected release source; its absence cannot locate a wait.
Failure snapshots are captured before owned cleanup. Existing preparation limits,
actual employee task limits, credentials, permissions and tool gates are unchanged.
This is local diagnostic coverage, not proof of the previous account failure's
cause or a successful real-account run. No automatic stack sampler is enabled.

## 0.1.16: bounded startup and MCP failure observations

Failed Codex preparation now preserves fixed native error markers and separates
local MCP request arrival, rejected credentials/Origin/Host, and authenticated
initialize receipt. Raw stderr, tokens, request bodies, paths and URLs are not
included. Observations do not authorize tools, attest native policy, or prove a
root cause. A missing successful initialize response does not prove that the
client sent no HTTP request. Existing trusted failure stages/codes remain intact,
including when new observations are added to an already classified gate error.

This patch fixes diagnostic evidence loss. It does not establish successful
real-account MCP connectivity, change permissions/deadlines/task limits, update
the daemon, or authorize another actual model attempt. Publication and verified
foreground installation are separate from a subsequently approved execution.

## 0.1.15: startup output before MCP readiness

The process host drains stdout from spawn, before the adapter starts consuming
events after authenticated MCP discovery. A bounded queue prevents the child
from blocking on ordinary startup output; overflow stops only its owned process
group. This changes no tool permissions, preparation deadlines or task limits.
Fake-process tests reproduce the defect, but do not prove the cause of a previous
real-account failure or successful account/MCP acceptance. Publication and a
foreground installation do not update the daemon or authorize a model run.

## 0.1.14: foreground administrator authentication wait

The manual Codex pilot waits for administrator authentication before starting
the 60-second profile inventory deadline. Cancelling the execution aborts its
owned pending query. Fixed error codes identify authentication and query failures
without exposing native stderr. This patch does not update a running daemon or
establish successful real-account Codex execution.

## 0.1.10: enforced PreToolUse hook

Earlier releases configured a hook command that the shell could not run, so Claude
Code ran tool calls without the hook policy. This release runs the hook through
Node. Unless the packaged hook denies a `git push origin HEAD` probe, `setup` and
the daemon stop and `doctor` reports `hook_not_enforcing`.

## 0.1.9: gated Codex foundation and shared CLI security

This package includes the production Codex host/probe and common authenticated
four-tool policy, command/dependency pins, owned cancellation, retained-session
checks and security receipts. The source-reviewed Codex release registry is empty:
Codex cannot advertise or execute until an exact binary, model, policy and release
manifest have been genuinely reviewed. Do not enable a Gateway flag to bypass it.

**Upgrade limitation:** this package also closes the Claude adapter until its
reviewed native evidence is available. Do not replace a working 0.1.8 daemon as
part of the Codex-disabled Gateway delivery. Gateway retains the legacy Claude
prepare/launch and approval payloads unless an explicit Claude security manifest
is configured; Codex always requires the new security descriptor. Publication is
separate from an authorized daemon upgrade or actual account/model acceptance.

The Codex probe only reads the original supported file-backend login status and
never runs vendor login/status, refreshes tokens, writes credentials or switches
backends. Keychain-only/unknown backends remain unavailable rather than being
migrated. Native CLI startup can still perform vendor-managed refresh; a no-model
inspection is not a no-refresh guarantee. Keep the existing login and obtain the
separate account/activation approval before actual CLI startup.

The supported policy mode acknowledges vendor runtime/authentication/extension/
IPC/network trust; it does not claim total broker-only isolation. Synthetic test
receipts never authorize production. The repository report `docs/ai-ops-gateway/codex-production-host-validation.md`
records the tested scope and remaining rollout gates.

The intended employee request after rollout is: “Use my local Codex for Billing.
Inspect the payment entry points without editing files, and return the findings
and verification here.” Gateway OAuth signs the employee into Gateway; a separate
`codex login` using ChatGPT authorizes Codex. An OpenAI API key is not a fallback.
If both executors are usable, select one before approval; changing the executor
or server-resolved model requires a new launch approval.

Source operations use authenticated job-only tools. Registered test programs need
exact executable/argv and explicit dependency-file read grants; source writes,
network, ambient credentials and child process creation are denied to those test
programs. Broad npm/project test runners are not automatically supported. Missing
grants produce a visible blocked result. Actual employee-local task duration and
count remain unbounded; preparation retains the 0.1.8 limits.

## 0.1.8

- Report safe preparation stage/tool/error categories and settle known failures instead of silently reclaiming the same job forever.
- Bound preparation to 15 minutes, retain terminal receipts across connection failures, and halt on unknown binding outcomes until reconciled.
- Pair with Gateway cancellation propagation and three-delivery preparation bounds. Actual approved unbounded employee-local Claude execution remains unbounded.
- npm publication and daemon upgrade are separate actions. Keep a stopped runner stopped until its cancelled job is confirmed terminal on Gateway.

## 0.1.7

- Accept one fenced final JSON report after an explanatory preamble while preserving status, evidence, length and pending-work validation. Reject ambiguous multiple code blocks.

## 0.1.6

- Require a final JSON report with actual findings, nonempty evidence and no pending work before reporting completion. Incomplete or missing reports fail without a successful investigation artifact.
- Explicitly restrict available built-in tools and ignore child messages as executor completion evidence.
- Preserve employee-local duration/count policy and Gateway model selection. Structured assertions remain client-reported and require separate semantic review.

## 0.1.5

- Authenticate local MCP relay callers with a random per-job bearer capability.
- Forward only the job-selected Gateway tools; filter tool discovery and reject other MCP methods, batches, browser origins and foreign Host headers.
- Revoke capabilities and remove private MCP configs when jobs settle or the runtime closes normally.
- Update uuid to patched version 11.1.1.

The relay binds only to loopback. Local capabilities are stored in private mode-0600 config files, never URLs or command arguments. Gateway OAuth tokens stay in the runner. Abrupt process termination may leave a private config file; its capability is inert after the relay dies and is never reused by a new process. These controls do not sandbox malicious programs already running as the same macOS user.

## 0.1.4

- Independently verify the approved contract payload and task-package fingerprints before creating a runtime binding.
- Include actual diff and changed-file manifest hashes in terminal events, with a final checkpoint before completion.
- Fail closed on missing terminal events, failed launches, unavailable evidence, or rejected event reports.
- Read and acknowledge supervisor controls; preserve the terminal status when reconciling a daemon restart.

Existing employees can upgrade their installed daemon with:

```bash
npx mtech-ai-local-runner setup
npx mtech-ai-local-runner doctor
```

### Cancellation and preparation failures

Cancelling a Work Loop also cancels its non-terminal local jobs. Repeating the
cancellation repairs jobs left by an earlier Gateway version; terminal results
are preserved. Claim/reclaim and lease-gated launch checks reject cancelled
Loops. An active adapter stops on a failed heartbeat or expiry of its last
confirmed Job lease, even when the current request never responds. Cancellation
is not an immediate process-kill acknowledgement.

Before binding, the Gateway permits at most three queue deliveries and a
15-minute preparation window from the first claim. The daemon also bounds its
workspace/probe/shadow/binding preparation to 15 minutes. A known preparation
failure is reported as `blocked` immediately, with a safe stage, tool name when
available, and error category. Tokens, grants, arguments and raw error responses
are excluded from these diagnostics. Unacknowledged terminal receipts remain in
private state for reconciliation before polling continues.

A binding request whose outcome is unknown is retained as `binding_uncertain`;
the daemon stops polling and requires authoritative reconciliation of the
recorded job/generation and deterministic binding reference before restart.
It neither repeats the binding request nor assumes the server did not create it.
Do not delete that state to force another execution.

These preparation controls end at binding and do not impose time, turn, token
or cost termination limits on an approved unbounded employee-local Claude run.
Existing generation fencing, scope restrictions, cancellation and audit remain
in force.

### MCP startup failure diagnostics (0.1.13)

Codex startup now distinguishes an owned process exiting before admission,
preparation timeout, explicit abort and rejected MCP discovery. A fixed `detail`
reports whether initialize, initialized notification or tool inventory is still
missing (or discovery completed). The first issued cause survives cleanup and
outer catches and reaches both the failed event and terminal Job result.
Raw provider stderr remains excluded. These diagnostics do not establish the
historical failure cause or prove whether provider inference occurred.

The preparation deadline and mandatory authenticated MCP checks are unchanged.
There is no automatic model retry or task duration/count cap. Installing this
patch does not authorize another actual Codex attempt or change login/settings.

### Post-binding execution diagnostics (0.1.12)

The manual command and daemon log an `execution_failed` diagnostic (the manual
command uses `manual_execution_failed`) before attempting Gateway failure
reporting. Failed events and completion results carry `execution_failure` with
a fixed `stage` and `code`. Inner host-issued diagnostics survive outer catches;
unknown errors use a generic code. Credential values, raw exceptions, causes,
stacks, filesystem paths and provider stderr are not included. These diagnostics
do not prove whether provider inference occurred. A Gateway reporting outage
retains the local diagnostic and does not turn an unacknowledged terminal event
into a completed job. Existing reconciliation rules still apply.

### Manual Codex pilot (0.1.11)

The foreground inventory separates human authentication wait from the bounded
query and evidence freshness. Its query deadline starts only after the fixed
root-identity check completes, not while the administrator prompt is waiting.
Cancellation revokes the pending query and rejects late results; authentication,
query timeout, command and validation failures use distinct safe codes. The
inventory must still be fresh at Codex spawn. No automatic retry is performed.

The reviewed manual Codex path preserves the existing CLI and ChatGPT login. It is separate from unattended daemon readiness. After the exact CLI/native reader and Gateway release are installed, an employee-authorized foreground pilot uses `mtec-ai-local-runner manual-codex --job-id=<approved Job UUID>`. It refuses a running daemon, unresolved recovery state, unknown release/account or a different Job. It does not stop services or alter personal settings. A direct administrator policy inventory occurs just before the approved execution; historical inventory is not continuous MDM monitoring. The Gateway OAuth client refuses refresh in this manual command. Actual vendor account startup may still refresh shared credentials and requires disclosure in the exact launch approval.


### Local Fix with disclosed validation

The existing daemon can use a reviewed `gateway_publish_v1` installation for
approved local Codex fixes. It freezes the owned model and sends only sealed,
bounded changed text files to Gateway's existing publication service. Server
credentials create the generated branch and canonical development PR; no local
Git token, ECR, new CI installation or native PHP verifier is required.

Validation is explicitly **UNVERIFIED** in this mode, with CI **not run**.
Executor-reported checks, failures and checks not run stay attributed to the
executor in the PR, Work Item and Slack result. No new test/shell tool is granted.
A PR-created result is not a test-pass claim. Existing read-only Claude/Codex
investigation and the optional strict CI-required mode keep their prior behavior.

Only an exact reviewed v2 installation with matching mode/profile/runtime hashes
advertises `local_fix_gateway_publish_v1`. Publishing/installation/DEV activation
and an exact approved Fix contract/launch are still required before real use.
An unresolved canonical PR approval or publication receipt pauses delivery; do
not rerun the model or delete recovery state to force a PR.

### Login and execution diagnostics

`login_status` reports local account evidence (`authenticated`, `unauthenticated`,
`unknown`); it does not certify remote token validity. `execution_status` reports
`ready` or `blocked`, with bounded `execution_reason_codes`. For compatibility,
the older `authenticated` field still means execution eligibility. A logged-in
Claude account can remain blocked by unverified security admission. Do not log out
or change credentials just because that legacy field is false. Unknown status is
not evidence of logout. These diagnostics do not bypass per-job admission.

### 0.1.50: small edits and publication-only Fix

Use `local_replace({path, old, new})` for a small approved edit after reading the file: `old` must be nonempty and match exactly once, including whitespace. Zero or overlapping/multiple matches are rejected with distinct errors and no write. Replacement text must not be a patch; the result retains the same scoped write, size, link and revocation protections as `local_edit`. `local_edit` remains a complete-file replacement API.

Both CLI adapters require the five-tool inventory. Gateway tools descriptors and runtime pins must match this release; CLI release manifests and the standalone binary stay fixed. In `gateway_publish_v1`, missing registered tests is expected: report not_run/unverified, apply only the smallest source-evidenced correction, disclose uncertainty and seal for a human-reviewed Gateway PR. Historical contracts and attempts are not edited. Reverb 0.1.49 is retained; installation, deployment and real model execution remain separate approvals.
