Skip to content

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

Open
ion-alpha-dev wants to merge 2 commits into
provetrail-freeze-bytesfrom
goal-ledger
Open

goal: expand an objective into an append-only ledger before building#424
ion-alpha-dev wants to merge 2 commits into
provetrail-freeze-bytesfrom
goal-ledger

Conversation

@ion-alpha-dev

@ion-alpha-dev ion-alpha-dev commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

What

F1 of the goal-mode epic. A goal expands its objective into a durable, append-only ledger of work items, all of them initially unproven, before any building starts. Single commit, adb0f08.

Why

Goal mode currently has no durable record of what a goal set out to do, so there is nothing to check progress against and nothing that survives a context reset. The ledger is the spine the rest of the epic hangs off: the evidence gate (F2) consumes ledger items, stall detection (F3) reads the ledger rather than the working tree, and the run record (F12) reports against it. Writing it append-only and unproven-by-default means a goal cannot quietly mark its own work done.

How to verify

  • go test ./goal/... covers ledger construction, the planner phase, and the reconciler.
  • The tests assert the append-only property directly: an item's proven state can be set, but items cannot be removed or rewritten.
  • CI runs the same, plus race and lint.

Notes for reviewers

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant