You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up from the codex review of #570, which relocated the resume config-change baseline (trusted_config_digest) out of state.json into the run's out-of-tree state dir per the recorded 2026-08-08 decision on #498.
The residual
#570 closes the incidental silencing path: the pin is no longer a project file, so nothing a session does in the ordinary course of rewriting the tree can collaterally blank it. That is the case the advisory is documented to catch ("it catches the incidental change, not a deliberate one").
It does not close the deliberate path, and the review is right that this deserves stating plainly rather than as a footnote:
Every shipped profile launches with permission bypass — claude.toml--permission-mode bypassPermissions, codex.toml--dangerously-bypass-approvals-and-sandbox, gemini.toml--approval-mode=yolo, copilot.toml--allow-all-tools --allow-all-paths, antigravity.toml--dangerously-skip-permissions. This is the default operating mode, not an edge case; it is what an unattended loop is.
The session is handed BMAD_LOOP_EVENTS_DIR (engine.py), whose parent is the run's state dir. dirname() yields config-digest.
So a session that goes looking can still silence the warning; it just has to be deliberate about it rather than blanking a field it was already editing.
Not an oversight — there is no sound fix at equal privilege, and the half-measures each cost something:
Treat absent/empty as tampering. Requires distinguishing "this run should have a baseline" from "genuinely legacy run". Any marker carrying that distinction has to live somewhere the same session cannot reach — and at equal privilege no such place exists. Put it in state.json and the session edits both; put it in the state dir and it is deleted with the file.
Warn whenever there is no baseline at all. Fires a false alarm on every genuinely legacy run's first resume, on a warning whose whole value is that it is rare. Training operators to ignore it is worse than the hole.
Hide the path. The run id and the state root are both derivable from the events dir the session must be given. A secret in the filename would have to be stored where resume (a fresh process) can find it — i.e. in-tree.
The direction that would actually work
Privilege separation on the state root, not a better hiding place: the control plane owned by a principal the driven session does not run as (separate user/service account, or ACLs that grant the session no write to the state dir while the orchestrator retains it), with the session given only what it must have — write access to events/ and nothing else in the state dir.
That is a real design change with real portability cost (POSIX ownership/ACLs vs Windows ACLs vs the WSL-UNC seam already tracked in #536/#552), and it would also harden the events channel, which today has the identical exposure — a session can delete events/ and stall its own run. Worth deciding as one piece rather than bolting a marker onto the digest.
Meanwhile
#570 states the limit explicitly in runs.config_digest_path_for's docstring and in the CHANGELOG entry, so the claim on record matches what the code delivers.
Follow-up from the codex review of #570, which relocated the resume config-change baseline (
trusted_config_digest) out ofstate.jsoninto the run's out-of-tree state dir per the recorded 2026-08-08 decision on #498.The residual
#570 closes the incidental silencing path: the pin is no longer a project file, so nothing a session does in the ordinary course of rewriting the tree can collaterally blank it. That is the case the advisory is documented to catch ("it catches the incidental change, not a deliberate one").
It does not close the deliberate path, and the review is right that this deserves stating plainly rather than as a footnote:
claude.toml--permission-mode bypassPermissions,codex.toml--dangerously-bypass-approvals-and-sandbox,gemini.toml--approval-mode=yolo,copilot.toml--allow-all-tools --allow-all-paths,antigravity.toml--dangerously-skip-permissions. This is the default operating mode, not an edge case; it is what an unattended loop is.BMAD_LOOP_EVENTS_DIR(engine.py), whose parent is the run's state dir.dirname()yieldsconfig-digest.None→ the legacy fallback readsstate.json's field, which is""for any run started after fix(resume): move the config-change baseline out of the agent-writable tree (#498) #570 →bool(pinned)false → no warning. Truncating it answers""→ same.So a session that goes looking can still silence the warning; it just has to be deliberate about it rather than blanking a field it was already editing.
Why #570 did not fix it
Not an oversight — there is no sound fix at equal privilege, and the half-measures each cost something:
state.jsonand the session edits both; put it in the state dir and it is deleted with the file.The direction that would actually work
Privilege separation on the state root, not a better hiding place: the control plane owned by a principal the driven session does not run as (separate user/service account, or ACLs that grant the session no write to the state dir while the orchestrator retains it), with the session given only what it must have — write access to
events/and nothing else in the state dir.That is a real design change with real portability cost (POSIX ownership/ACLs vs Windows ACLs vs the WSL-UNC seam already tracked in #536/#552), and it would also harden the events channel, which today has the identical exposure — a session can delete
events/and stall its own run. Worth deciding as one piece rather than bolting a marker onto the digest.Meanwhile
#570 states the limit explicitly in
runs.config_digest_path_for's docstring and in the CHANGELOG entry, so the claim on record matches what the code delivers.Related
initvendors the hook relay into the agent-writable workspace, turning a file-write primitive into unattended persistent code execution #461 point 4 — where the digest and the auto-sweep gate came from. The gate is unaffected: it compares against an in-memory closure baseline that nothing on disk can reach.