Managed Codex heartbeat prompt upgrades¶
Product contract¶
Default execution remains heartbeat-prompt --thin. An adopted automation
stores a small, stable bootstrap instead of a copy of the current execution
rules. At every wake, it requests the complete JSON thin prompt from the
installed LoopX, with an explicit registry, Goal, agent and host capability
binding, then follows that prompt. After a normal LoopX upgrade, the next wake
reads the new rules; no per-release Codex database rewrite is needed. An already
running wake keeps its current instructions. This is model-mediated loading,
not a guarantee that a model will obey every instruction.
The bootstrap is a transport wrapper, not a new execution mode. It does not default to full/compact prompts, contain a parallel work policy, or create another scheduler. Failure to load a complete successful response stops work and spending; it must not fall back to remembered rules. Project watches and business policy belong in LoopX state, not in this bootstrap.
The v2 wrapper distinguishes continued work, notifications and real waits: one operation does not end the work; notification silence is not execution silence; waits follow the live scheduler contract instead of unchanged polling. Local entrypoint errors may be repaired within existing authority, but an unavailable contract still forbids delivery and spending. This is not permission to bypass a gate, retry indefinitely, or disable a healthy automation.
For a one-agent trial, pass --cli-bin loopx-canary to preview and apply. The
bootstrap and the thin prompt's generated commands both use that executable;
other automations continue to use their existing runtime. Do not promote the
canary as the global default merely to test one task.
The owner is the existing heartbeat/upgrade boundary; there is no new optional capability or extension provider. SQLite/TOML handling is a local host adapter, not Todo, quota or scheduler authority.
Automatic upgrade and manual adoption¶
loopx update apply now captures an owner-only snapshot before replacing
the runtime and invokes automation-prompts sync-installed in the new
runtime afterward. Exact recognized managed bootstraps and byte-identical
prompts reproduced by the old installed generator may migrate automatically.
An automation name, matching prose or Goal id alone never authorizes adoption.
Custom instructions remain review_required; a canary executable, different
registry/home or changed preview is not silently retargeted. Binary-install
success and prompt-migration success are reported separately. upgrade_complete
is true only when runtime qualification and prompt reconciliation both succeed;
the existing ok field retains its runtime-result meaning. A successful install
and core doctor still run prompt reconciliation when an optional extension
fails its doctor, without clearing that extension failure or its repair action.
Failed installation or core doctor never starts prompt writes.
Upgrading from a CLI that predates this hook cannot retroactively capture its
old template evidence. After installation, run the new automation-prompts plan
and review/adopt the selected tasks through the App. Never interpret absence of
a migration report as proof of migration, or loosen exact-template ownership
to make a historical custom prompt appear automatically eligible.
Archive updates pinned with --ref <full-commit-SHA> download that exact archive
without a GitHub commit-API lookup. Symbolic refs still require resolution to a
full hexadecimal SHA. If the public API fails, the installer can reuse existing
gh authentication for the same GitHub repository/ref under a bounded timeout;
it neither logs in nor selects another ref. If both routes fail, retry with an
independently verified full SHA. Downloads have bounded timeouts and retries.
Exact managed v1 wrappers upgrade to v2 automatically through this path;
they do not require per-task approval. automation-prompts plan is only a
read-only preview, not the upgrade executor. Do not infer a manual-only policy
from its adoption_required status. Custom or inconsistent entries still need
review; automatic prompt migration never grants scheduler or thread authority.
Deferred upgrade hint¶
When an automatically eligible migration is deferred, reconciliation records
only its identity, old prompt digest and CLI route under the private runtime root's
automation-prompt-upgrades/ directory. Records are scoped to the registry and
Codex home; they contain no prompt body or saved host update request.
Codex App heartbeat decisions load a fixed, read-only turn-start hook from the
existing heartbeat lifecycle. It uses the existing typed capability-hook
observation and required-read contracts, without adding a standalone capability,
provider package, prompt template or scheduler action. For one unambiguous pending
entry whose old prompt and thread still match both host stores, the hook inserts
an automation-prompts plan --automation-id ... read into the existing Agent/CLI
channel. Read that fresh plan, review the prompt-only adoption through the App,
and read back the result. Repair alone spends no quota; normal work keeps its
existing decision and permission boundaries.
The active hint declares prompt_budget_bytes=1536 in its required read.
The typed hook validates this optional allowance (at most 2048 bytes per read).
Only emitted hook reads extend the envelope's 8192-byte budget and their command
projection allowance; inactive hooks contribute zero. Existing unbudgeted reads
retain their 360-character projection and the normal envelope budget. This is
prompt capacity, not execution, quota or adoption authority.
No pending entry, an adopted prompt, customization, a changed thread, ambiguous
identity or unavailable host evidence produces no adoption hint. With no pending receipt
the hook does not open the host database or dispatch a capability call.
An unrelated RRULE change does not hide a pending prompt. The next reconciliation
removes resolved records; the turn never needs a new ACK or state write.
Detection remains update-time: edits made outside LoopX between updates are not
new migration candidates. Re-run automation-prompts plan for explicit review.
On the qualified macOS heartbeat schema, direct migration requires the App
closed. The adapter holds a SQLite writer transaction through TOML delivery,
compares the entire previewed manifest, preserves every non-prompt field, and
reads both stores back. Keep the App closed through readback, then restart it.
A running App caches automation state and can overwrite both stores after a
disk-only update; a transaction or immediate readback cannot invalidate that
cache. Running hosts must use the native automation_update API. The CLI reports
that required host action instead of claiming the upgrade is complete.
This is a local storage compatibility adapter, not an official Codex API. Uncoordinated TOML writes cannot participate in the SQLite transaction; detected changes/crashes retain the private journal and require reconciliation.
Unsupported platforms/schemas, custom prompts and conflicts are reported per
task. Where an eligible task can instead use the native App writer, the report
includes a complete automation_update request with preserved fields and a
fresh-view/hash precondition. A CLI cannot invoke an in-App tool itself. Do not
blindly replay a request after a user edit. A failed runtime installation never
starts prompt migration. A pending report retains the private pre-update plan
so a selected task can be retried, without scanning another Codex home:
loopx automation-prompts sync-installed --plan-file ./private-before.json --automation-id TASK_ID --execute
The existing plan command remains read-only and explicit apply remains an
offline, reviewed path; it does not automatically adopt custom instructions.
The plan contains current and proposed prompts and is private local data.
Do not commit, upload, or paste it into public issues. The file is owner-only.
Use repeatable --automation-id selectors to narrow the plan. Discovery uses
registered Goal/agent identities only to propose candidates; it never grants
permission to overwrite them. Unrelated, ambiguous and inconsistent host
records are not adopted. Review custom instructions before replacement: move
durable project policy to its LoopX owner, or leave that task unadopted. There
is no automatic prose merge or substring-based permission to replace a prompt.
While the Codex App is running, prefer its automation_update interface:
view each selected task, verify its current prompt against the preview, update
only the prompt to desired_prompt while preserving every other field, then
read it back. Do not recreate the task or rebind its thread. A single user
request can authorize this reviewed batch; the plan itself does not execute it.
When that API is unavailable, the qualified macOS offline fallback is:
# Review the plan, then close the Codex App first.
loopx automation-prompts apply --plan-file ./private-prompt-plan.json --offline --execute
The same registry/runtime-root and Codex home must be used for preview and
apply. --codex-home explicitly selects one home; the command never searches
other homes or copies sessions between them. No new automation is created.
Schedule, pause state, model, notification preferences, thread binding and run
history are preserved. Each selected task commits independently; the command
reports partial failure instead of claiming the whole batch succeeded.
Only existing heartbeat records with matching SQLite/TOML identity, prompt, status, schedule and thread binding are eligible. Unknown schemas and stale previews fail closed. The fallback checks that the macOS App is closed; keep it closed until readback completes. Restart afterward. This adapter targets the observed local schema, not an official stable Codex storage API; no Windows/cloud support is claimed. Use the native API if the host changes its storage contract.
A legacy TOML heartbeat label with a SQLite cron row is not enough to prove
thread ownership. In particular, a missing database thread binding must not be
filled from TOML by a prompt-only migration. Such records require App-mediated
reconciliation first; the offline adapter reports that action explicitly and
does not convert scheduler kind, infer a thread, or offer an executable upgrade.
Recovery and rollback¶
The adapter stores a private per-task journal before writing. SQLite commit and TOML replacement are not one transaction: a crash can leave a mirror pending, including a new TOML prompt with a rolled-back SQLite prompt. While the App remains closed, recover that exact task:
loopx automation-prompts recover --automation-id TASK_ID --offline --execute
# Or restore the previous prompt:
loopx automation-prompts rollback --automation-id TASK_ID --offline --execute
Recovery is idempotent. It refuses to overwrite later prompt/metadata edits.
The journal remains under the selected Codex home's loopx-automation-backups
directory; do not publish it. Rollback restores only the recorded prompt,
never an entire historical database or session table. Native API migrations
should retain the reviewed previous prompt privately and use that same API
for rollback.
Disable automatic rule adoption by replacing the bootstrap with an explicitly
pinned prompt using the App, or pause the task there. LoopX runtime rollback
also changes the rules loaded on the next wake. Exact v1 wrappers remain
recognized as runtime-loaded thin prompts; automation-prompts plan proposes
v2 without writing, while the update-time exact-owned path can migrate them.
Customized wrappers are not recognized merely from their header.
Goal host loaders¶
heartbeat-prompt --bootstrap uses the same shell loader renderer as automation.
New Codex App/SSH, Codex CLI/IDE and managed-agent activations store this loader;
it preserves explicit caller policy but re-resolves registry state on each load.
Its inner command omits --bootstrap, preventing recursion. Persisting a fixed
turn-instance id is rejected. Existing saved native Goal objectives are not
rewritten through SQLite.
Claude Code stores a bound MCP loader: host_prompt returns the current inner
rules for its existing Goal and agent. Restart an existing MCP server after a
runtime upgrade; already imported Python code does not hot-reload. TraeX retains
its direct Goal projection when capabilities require a separate host surface;
the generic loader must not move those declarations into prompt text.
中文摘要¶
默认仍是 thin。一次迁移后,automation 每次唤醒读取已安装 LoopX 的最新 thin 指令;之后升级 LoopX 即可让下一轮采用新版规则,无需逐版本改 SQLite。 正在运行的轮次不热切换。启动器不是另一套执行规则,也不增加权限。
升级主流程在替换 runtime 前留存旧模板证据,升级后由新 runtime 生成并迁移。
仅完整匹配的托管指令可自动更新;自定义内容不猜测合并、不自动删除。macOS
已匹配的 heartbeat 存储支持 App 运行中直接写入,仅改 prompt,持有数据库写锁
直到 TOML 交付和读回完成。两种存储并非一个原子事务;冲突或异常保留私有日志,
不伪报成功。upgrade_complete 同时覆盖 runtime 与 prompt;可选扩展检查失败
不阻止已经通过安装和核心 doctor 的 runtime 继续迁移 prompt,扩展故障仍保留。
首次从不含迁移钩子的旧 CLI 升级,应再用新版 plan 审阅并采用旧任务,不能把
缺少迁移报告当作已迁移。完整 SHA 下载不依赖提交查询;分支查询失败可复用已有
gh 登录,仍失败则明确要求已核验 SHA,不切换分支或静默覆盖自定义指令。
日程、暂停状态、模型、线程、通知偏好和历史均不迁移。
不支持的存储仍需原生 API;运行中的本轮不热切换。普通测试不消耗模型 token,
真实模型发布资格仍需独立评测,不能由迁移成功推断。
自动升级候选未能应用时,对账只在 runtime root 的
automation-prompt-upgrades/ 中记录按 registry 和 Codex home 隔离的身份、
prompt 摘要与 CLI 路由,不保存 prompt 正文或宿主更新请求。Codex App heartbeat
固定加载现有 heartbeat 生命周期内的只读 turn-start hook,复用已有的类型化
capability-hook 观察与 required-read 契约,不新增独立 capability、provider 包、
prompt 模板或 scheduler action。只有唯一未完成项的旧 prompt 和线程仍与两个
宿主存储一致时,才在现有 Agent/CLI 通道插入指定 automation 的最新 plan 读取提示。
按最新计划审阅、通过 App 仅更新 prompt 并读回;修复本身不消耗额度,正常工作仍按
原有决策和权限执行。
无未完成项、已升级、自定义修改、线程变化、身份歧义或无法核验时不注入采纳提示;
无未完成记录时不打开宿主数据库、不调用 capability 分发器。单独的 RRULE 变化不影响提示。
完成升级即停止提示,下次对账清除记录,无需新的 ACK 或按轮状态写入。发现仍发生在
升级时;两次升级之间的外部修改不会自动成为迁移候选,可显式运行
automation-prompts plan 审阅。
激活的 hint 同时声明 prompt_budget_bytes=1536,由类型化 hook 校验(单条最多
2048 字节)。只有实际输出的 hook read 才增加 envelope 原有 8192 字节预算及该条
命令的投影空间;未激活时增加量为零。未声明预算的 read 保留原有 360 字符投影和
默认 envelope 预算。这仅增加 prompt 容量,不增加执行、额度或采纳权限。