Skip to content

goal: expand an objective into an append-only ledger before building#422

Closed
damienrch wants to merge 2 commits into
provetrail-freeze-bytesfrom
goal-ledger
Closed

goal: expand an objective into an append-only ledger before building#422
damienrch wants to merge 2 commits into
provetrail-freeze-bytesfrom
goal-ledger

Conversation

@damienrch

Copy link
Copy Markdown

F1 of the goal-mode epic: a goal expands its objective into a durable ledger of work items, all of them unproven, before any building starts.

Stacked on provetrail-freeze-bytes (#421), which this branch was cut from. Review that one first; the diff here is the single adb0f08 commit.

Task: ea96cbbc-a957-4bcb-8d3e-01268f8ed1bf
Epic: 06cb1e7e-3955-465d-9c82-bbc36971215d

gofumpt and gofmt disagree about alignment when a map key is a wide rune,
and the lint gate follows gofumpt. Whitespace only.
A goal today takes an objective and a stop condition and starts building on
step one, so "done" is only ever decided by reading prose. That fails in both
directions: a run declares victory having written nothing, and a genuinely
finished run goes undetected because its wording drifted. Neither is fixable by
parsing harder. Completion has to be a state transition on a durable record.

This adds that record and the phase that writes it.

Spec.Ledger is the objective expanded into the units of work it implies, each
item carrying its own declared way to verify it, recorded when the work is
planned rather than argued for once it is time to claim the item is done.
Status.Ledger is the per-item observation of it, and every item starts
unproven, so a run begins from a record saying nothing is done yet.

Two structural rules protect the record from the agent writing it:

Append-and-mark-only. An item may be added and its state may be marked, but no
item is ever removed or rewritten. This forecloses the failure where an agent
under completion pressure edits the definition of done: dropping an item,
narrowing a verify clause until the check it promised is no longer the check it
faces. A prompt asking the model not to do that is advisory and gets ignored
under pressure. A ledger whose prefix cannot change is not. The rule is
enforced twice, at the write and again on reconcile, so a ledger edited around
the write path stalls the goal instead of becoming the new definition of done.

Content-addressed items. An item's id is a hash of its text and verify clause,
assigned on append rather than chosen by the planner, so a rewrite is a
different id and the extension check sees it as the removal it is. A rewrite
that keeps the old id is caught by the self-addressing check.

The planning phase is a Planner port on the worker plus WithPlanning on the
reconciler: the first dispatch is a plan job, no build step goes out until the
ledger exists, and a planner that produced nothing stalls the goal rather than
letting it build against a record that never said what success was. Planning
rides the same queue, lease, crash-resume and retry ladder a build step has,
and does not spend the build budget, since it is the phase that decides what
that budget gets spent on.

Both halves are opt-in and paired in one place, because a goal gated on
planning with no planner wired would wait forever. Every goal composed before
this is unchanged, which the tests pin.

Task: ea96cbbc-a957-4bcb-8d3e-01268f8ed1bf
@damienrch
damienrch requested a review from ion-alpha-dev as a code owner July 22, 2026 05:13
@ion-alpha-dev

Copy link
Copy Markdown
Collaborator

Opened under the wrong identity. Reopening from the workspace account.

@github-actions github-actions Bot locked and limited conversation to collaborators Jul 22, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants