Skip to content

status: a truncated ACTIVE_GOAL_STATE.md reports healthy with zero Todos #6870

Open

Description

@BiBoyang

What happens

ACTIVE_GOAL_STATE.md truncated at a section boundary (e.g. everything from
## Agent Todo onward removed) is read as a goal with no Todos:

healthy: {"status_exit":0,"status_ok":true,"todo_index_total":2,"attention":"[P1] implement the thing","todo_total":2}
wounded: {"status_exit":0,"status_ok":true,"todo_index_total":0,"attention":"run the first read-only adapter tick and save a compact run record","todo_total":0}

Both loopx status --format json and loopx todo list --format json exit 0
with ok:true, and the attention line silently degrades from the real P1 item
to the generic first-tick advice. 5/5 runs.

Why this path is taken

parse_active_state_todos iterates only the regions it finds
(loopx/control_plane/todos/active_state_todo_parser.py:36), and a missing
section is legal — only unterminated frontmatter or malformed/orphan markers
raise (machine_region.py:53-58,86,103). A present-but-truncated file is
therefore indistinguishable from a goal that genuinely has no Todos.

Trigger honesty

The state writer is atomic (runtime/document_io.py, temp + fsync + replace),
so this is not a same-version torn write. It models disk corruption after a
crash, a partial backup/restore, or a bad manual/merge edit of a file that is
present.

Relationship to #6799

#6799 is about a missing state file letting the quota gate authorize turns.
This is the sibling case: the file exists, its earlier sections parse, and the
Todo section is simply gone — so a missing-file guard would not fire, and the
quota gate sees a goal with no open work.

Expected

A state file that parses but lost a section it used to have should not read as
"no open work". Options: require the ## Agent Todo region; compare a revision
or section inventory against the last known good state; or surface a
state_incomplete warning on status/todo list.

Reproduced

Snapshot 105c4bc1; unchanged on main at 1c7b258cb. Fixture: one goal with
exactly two Agent Todos; the wounded copy is the same fixture with the state
file cut at 377 → 235 bytes (before ## Agent Todo). The script asserts the
healthy control first (2 Todos, P1 attention) and fails if the wounded side does
not match.

Activity

  1. JasonBuildAI commented on Oct 19, 2026

    @JasonBuildAI
    Contributor

    Claiming this issue. I'll verify the truncated-state path on current main, implement the narrowest fail-closed/readback fix, and open a PR that references this issue. Any AI-assisted change will be disclosed in the PR.

  2. JasonBuildAI commented on Oct 19, 2026

    @JasonBuildAI
    Contributor

    Opened a fix in #6921: #6921

    Final head: fa29f297e50e3066376ef0d77516947a33240723; base is loopx-project/loopx:main.

    The change treats a readable legacy Markdown active state without the required ## Agent Todo heading (or an accepted alias) as state_incomplete instead of a healthy zero-Todo goal. On a synthetic truncated fixture:

    • status now exits 1 with state_incomplete and restore guidance instead of exit 0 with generic first-tick advice.
    • todo list now exits 1 with error_code=state_incomplete instead of ok:true with zero Todos.
    • quota should-run returns should_run:false, state:blocked_health, and the same restore guidance.
    • Restoring an Agent Todo section returns all three commands to success with the Todo visible.
    • Present-but-empty Agent Todo sections remain valid; canonical provider authority is unaffected.

    Validation on the final head:

    • tests/control_plane/test_truncated_active_state_todos.py: 6 passed, including direct CLI regression coverage for status, todo list, and quota should-run.
    • tests/control_plane/test_canonical_status_todos.py: 156 passed; 4 pre-existing Windows GBK subprocess-decoding failures, and those same 4 cases pass with PYTHONUTF8=1.
    • Ruff and git diff --check passed; semantic inventory found no supported new vocabulary carriers.
    • Independent review found no P0/P1. Its documentation and CLI-coverage notes were addressed in fa29f297e; truncation after the heading but before its items remains outside the selected heading-presence strategy and is documented as a residual boundary.

    AI disclosure: this change was drafted with AI assistance at my request, under my direction and review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions