Persist paged Codex history checkpoints and bounded, acknowledged delivery.
Keep usage sources and accounting across deleted or merged sessions.
Include native Goal controls, faster peer/session queries, and release guards.
Track the complete deployed source so isolated builds cannot omit local fixes.
Validation: all typechecks pass. The full suite reports 7,997 passing tests
and 46 existing failures, each reproduced against the prior commit.
Measured on this machine: from a Background session (a plain `ssh localhost` is
enough) `security show-keychain-info` already fails with "User interaction is
not allowed" (exit 36) and codesign returns errSecInternalComponent, while the
same command in Aqua reports the keychain unlocked and codesign succeeds. So the
key's ACL is not what blocks us - the session cannot reach the keychain at all -
and granting the key "allow all applications" would not help.
Correct the guidance in sign-build.sh and docs/local-deployment.md (both added
earlier today) accordingly: run the deploy from a Terminal window, or unlock the
keychain inside the Background session with the password
(`security unlock-keychain -p`, the CI-style recipe; the interactive form cannot
prompt there). Verified the failure path still prints the new text.
A fixed path plus a pinned identity does not by itself keep TCC grants valid:
each grant stores a code requirement, and a grant created while the binary was
ad-hoc signed stays pinned to that build's cdhash. Replacing the binary at the
fixed path then matches nothing, and since a record exists macOS never prompts
again - it denies silently. Processes already running keep the cached allow
until macOS re-evaluates them, then lose ~/Documents mid-life; new processes are
unaffected. That is exactly how long-running sessions stopped answering with
"OpenCode service failure" / "getcwd: Operation not permitted" while fresh
sessions on the same machine worked.
AGENTS.md gets the short version; docs/local-deployment.md gets the csreq check
(identity-based vs cdhash), the normal re-grant through System Settings, and the
fallback used on mini on 2026-09-17 (delete the stale row, restart tccd, insert a
record copied from a machine with the same signing certificate), including the
row shape and the other two services that rot with it.
The previous revision told people to run 'security unlock-keychain' first, which
cannot work from launchd's Background domain: the command cannot prompt for the
passphrase there, and an unlocked keychain alone does not let a background
process read the private key. It also guessed the session up front from
`launchctl managername`, which flagged legitimate deploys (an SSH session that
unlocked first signs fine).
Detect nothing in advance: run codesign, and when it fails with
errSecInternalComponent / "User interaction is not allowed", print the two
remedies that actually work - run the deploy from a Terminal window on this
machine, or allow the signing key for all applications in Keychain Access.
Verified both paths with the pinned identity (real sign succeeds; a shim that
returns errSecInternalComponent prints the guidance and exits 1).
Also ignore .opencode/ (OpenCode's per-project scratch dir, ~60MB here).
codesign reads the private key from the login keychain, and only the Aqua
session can reach it: agents/daemons run in launchd's Background domain,
where codesign fails with errSecInternalComponent even while Keychain
Access shows the keychain unlocked. sign-build.sh now warns with the fix
(run from a Terminal window, or `security unlock-keychain` first), and
docs/local-deployment.md records the rule.
Versioned filenames fixed the per-path code-signature cache kill (exit 137)
but made macOS TCC treat every build as a new app: each deploy re-prompted for
Documents/media-library access, and while the prompt was unanswered every
process touching those folders (model probes, session startup) blocked -
visible as slow/timeout requests in the app.
Go back to the fixed path ~/.hapi/bin/hapi (a real file) so TCC asks once and
remembers it across deploys. Guard the signature-cache hazard with explicit
verification: back up the installed binary to ~/.hapi/bin/backups/, install
with a fresh mtime, prove it execs repeatedly (--version x3) plus
codesign --verify, restart the hub / kickstart the runner, and restore the
backup on any failure.
- deploy-local.sh / deploy-remote.sh: fixed-path install, verify, rollback
- prune-backups.sh replaces prune-versions.sh (keeps newest N backups, drops
legacy versioned binaries)
- AGENTS.md, docs/local-deployment.md and the hapi-deploy skill updated
- extract the pinned-identity signing into scripts/sign-build.sh so local and
remote deploys ship the same stable signature (macOS TCC grants key on the
signing identity, not the path)
- add scripts/deploy-remote.sh: signs locally, copies the binary to a new
versioned file on the remote host, swaps the ~/.hapi/bin/hapi symlink,
kicks the launchd job (default com.hapi.runner, override via
HAPI_REMOTE_LAUNCHD_LABEL), and verifies the runner executes the new file;
running sessions survive
- document the remote flow in AGENTS.md and docs/local-deployment.md
The runner keeps its old machine RPC handlers and capability flags until
the process restarts: compiled binaries never self-update because the
heartbeat compares the mtime of the runner's own resolved exec path,
which is fixed for the life of the process.
- scripts/deploy-local.sh runs 'HAPI_CLI_EXECUTABLE=<stable symlink> hapi
runner start' when a runner is running; skips when none; warns and
exits 1 when the refresh fails (the hub deployment stays)
- AGENTS.md and docs/local-deployment.md document the runner refresh and
the manual sequence step
Ad-hoc signatures carry a cdhash-based TCC requirement that changes on
every build, so macOS treats each local binary as a new app and re-asks
protected permissions (Documents, Downloads, media library, ...) after
every deploy.
- add scripts/deploy-local.sh: pins one Apple Development identity
(SHA-1 stored in ~/.hapi/signing-identity, override via
HAPI_SIGN_IDENTITY), signs with identifier run.hapi.cli, copies to a
new versioned file, repoints ~/.hapi/bin/hapi, restarts the hub, and
rolls back when /health fails
- document the identity step and TCC rationale in AGENTS.md and
docs/local-deployment.md; agent sessions must prune TCC-protected
folders (~/Music, ~/Pictures, ~/Movies, ~/Library) from recursive
$HOME sweeps
- drop the one-off scripts/deploy-local-capacity-retry.sh (ad-hoc)