feat(goal): add the /goal durable objective ledger and gauntlet loop - #4
Draft
Nuropunk wants to merge 1 commit into
Draft
feat(goal): add the /goal durable objective ledger and gauntlet loop#4Nuropunk wants to merge 1 commit into
Nuropunk wants to merge 1 commit into
Conversation
An objective that spans many sessions has had nowhere durable to live: the backlog tracks work items, and anything larger survived only in conversation memory. bin/fm-goal.sh gives such an objective a record of its own - objective text, an ordered stage list, an append-only journal, and a set of executable gates - so it survives a restart, a crash, and a change of harness. Completion is a verdict computed from evidence rather than a claim. close refuses until every registered gate has a current pass, and a goal with no gates can never pass. Gates are content-bound, which is the property an unattended loop depends on. gate-add records a gate's exact bytes; edited bytes report UNBOUND and refuse to run, and a re-registered gate must be re-proven because a result recorded against superseded bytes stops counting. A loop that can quietly rewrite its own success condition is not a verification loop. The default stage list - ingest, verify, interpret, merge, render, evaluate, improve, archive - is a complete cycle and is configurable per goal. Reaching the last stage wraps and journals a completed pass. The skill owns the judgement: when a goal is the right shape rather than a backlog item, how to design a gate that fails closed, and the narrow rules for handing a goal to a recurring trigger without compounding damage on top of automation that is already running.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this adds
An objective that spans many sessions has had nowhere durable to live. The backlog tracks work items, and anything larger than a work item survived only in conversation memory - so it did not survive a context reset, a crash, or a change of harness.
/goalgives such an objective a record of its own:bin/fm-goal.sh- the durable ledger and loop driver.agents/skills/goal/SKILL.md- the judgement layer (when a goal is the right shape, how to design a gate, the automation handoff rules)tests/fm-goal.test.sh- 12 behavior testsAGENTS.mdsection 10, one row in the README skill table, one inventory entryThe design decisions worth reviewing
Completion is a verdict, not a claim.
closerefuses until every registered gate has a current pass, and a goal with no gates can never pass. The point is that "done" gets computed from evidence rather than asserted by whoever finished last.Gates are content-bound.
gate-addrecords a gate's exact bytes. Edited bytes reportUNBOUNDand refuse to run, and a re-registered gate must be re-proven because a result recorded against superseded bytes stops counting. This is the property the whole thing rests on: an unattended loop that can quietly rewrite its own success condition is not a verification loop. Both cases are covered by tests.The loop is circular by design. The default stage list -
ingest, verify, interpret, merge, render, evaluate, improve, archive- is a complete cycle and is configurable per goal with--stages. Reaching the last stage wraps to the first and journals a completed pass, because a goal that is not yet closed always has another pass to run.Records are line-oriented, not JSON.
goal.metaiskey=valueandjournal.logis TSV, matching the existingstate/<id>.metaconvention and avoiding JSON escaping in shell.export-jsonis a separate command so the human-facing output stays free to change independently of the machine-readable one.Scope boundaries
fm-goal.shreaches no network, spawns no agent, and writes nothing outside the goal directory. It keeps the record; the caller does the work. The skill's automation section deliberately refuses to let an automated pass merge, push to a default branch, discard unlanded work, or answer an escalated decision.Verification
bin/fm-lint.shon the changed filestests/fm-goal.test.shbin/fm-test-run.sh --check-coverageportable-serialby derivation, no lane edit needed)bin/fm-doc-audience-check.shTwo defects were found and fixed during development rather than shipped: a re-registered gate could inherit the previous version's pass (fixed by recording the gate hash in each result and requiring it to match the bytes on disk), and
export-jsonraised aBrokenPipeErrorwhen piped intohead(fixed by restoring default SIGPIPE handling). Both now have regression coverage.Not included
No
docs/page. The script header owns the mechanics and the skill owns the judgement; a third prose surface would be the duplication the one-owner rule exists to prevent.Generated by Claude Code