
Autogoal
- 78 installs
- 1.2k repo stars
- Updated August 4, 2026
- udecode/dotai
Helps with ai & agent building tasks.
About
autogoal is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- autogoal
- AI & Agent Building
- AI-coding skill
Autogoal by the numbers
- 78 all-time installs (skills.sh)
- Ranked #5,313 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/udecode/dotai --skill autogoalAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 78 |
|---|---|
| repo stars | ★ 1.2k |
| Last updated | August 4, 2026 |
| Repository | udecode/dotai ↗ |
What it does
Helps with ai & agent building tasks.
Files
Autogoal
Use this when the user asks for a durable objective, long-running autonomous work, goal setup, or when a governing repo skill requires goal setup before work starts.
This skill turns a vague "keep going" instruction into a thread-scoped completion contract: what should be true, how it is verified, what must not change, and when Codex should stop.
Core Take
A normal prompt says: do the next thing.
A goal says: keep working until this outcome is true, or until the evidence shows a real blocker.
Goals are for work where the next move depends on what Codex learns along the way: debugging, migrations, flaky tests, benchmark tuning, deep research, large refactors, prototypes, browser-proof loops, and pass-gated plans.
Goals are not a permission slip to wander. They are a scoped, evidence-checked contract.
No measurable outcome, no goal. A goal must have a verification surface and a completion threshold before create_goal is called. Prefer numbers: score, count, latency, coverage, pass count, failing-to-passing repro count, issue rows, or explicit command success. When a numeric target does not fit, use a binary artifact checklist that can be audited from files, commands, screenshots, browser proof, or source-backed citations.
Universal Boundary
autogoal is the goal lifecycle kernel. It owns:
- objective shape
- measurable completion thresholds
- evidence standards
- active goal conflict handling
- durable plan state
- blocker and completion rules
- repair routing when a goal-backed workflow misses expectations
It does not own project policy. Keep repo commands, package managers, browser tools, release rules, PR policy, scorecards, issue ledgers, and lane-specific pass schedules in derived skills or project-owned docs/plans/templates/<template>.md.
Derived skills may be stricter than autogoal; they should not duplicate the goal lifecycle. autogoal says how work remains honest. The derived skill says what the lane actually requires.
Template Composition
Goal plans are composable, but only through static materialization.
The model is:
1. one active goal 2. one concrete docs/plans plan file 3. one primary template 4. optional materialized packs
The primary template is chosen by dominant risk: task for normal execution, docs for docs-dominant work, major-task for heavyweight architecture or proposal work, and repo-specific templates for domain lanes.
Packs are chosen by touched surface. They add recurring gates without becoming parents:
docs: docs are touched but not the dominant deliverableagent-native: agent instructions, skills, hooks, commands, prompts, or
user-action tooling changed
browser: real browser, route, UI, native browser/OS, console, network, or
interaction proof is required
package-api: package exports, public API, release artifacts, package
boundaries, or package-level checks changed
Core execution and review gates belong in the primary template. Every primary template must include Autoreview as the last human-readable gate before Goal plan complete. Packs are only for optional touched surfaces that would otherwise be absent from that template.
Do not create runtime inheritance between templates. The helper copies pack rows into the generated plan's Start Gates, Work Checklist, and Completion Gates. After creation, the generated plan is the truth; the checker validates that materialized plan only.
The generated plan is the dedicated plan shell. Fill that exact file immediately after generation: replace placeholders, resolve every gate row, and mark non-applicable generated rows as N/A: <reason> with evidence. Do not delete, wholesale replace, or hand-narrow the generated plan into an ad hoc smaller plan after durable work has started. If the selected template is plainly wrong and no substantive work has started, regenerate once with the right template and record why. If work has already started, keep the generated plan and close it honestly.
The first plan checkpoint is requirement extraction. Codex output can compact and lose prompt constraints, so before implementation or broad exploration, copy every explicit user requirement into the plan as checkable rows: scope, non-goals, timing/duration, stop conditions, deliverables, final handoff sections, verification surface, and success criteria. Do not continue into implementation until this is complete or explicitly marked N/A with reason.
Use packs like this:
node .agents/skills/autogoal/scripts/create-goal-scratchpad.mjs \
--template task \
--with docs \
--with agent-native \
--title "<short task title>"Examples:
- docs-only work:
--template docs - normal code task that also changes docs:
--template task --with docs - agent workflow task:
--template task --with agent-native - browser behavior task:
--template task --with browser - public app/API or package-boundary task:
--template task --with package-api - major architecture task:
--template major-task - major architecture task that also changes docs and package API:
--template major-task --with docs --with package-api
If two packs add related gates, keep both when they protect different failure modes. If they duplicate exactly the same proof, keep the more specific pack and record the other as N/A in the plan.
Proportionality Dial
Classify goal-backed work before creating or updating a plan:
micro: one narrow, auditable outcome; no cross-file state; no meaningful
continuation loop. Use a tiny plan only when a repo rule requires it, or record the audit surface directly in the final response.
normal: multi-step work with concrete evidence and likely continuation.
Use the appropriate docs/plans template and close all relevant gates.
major: architecture, migrations, benchmarks, framework comparisons,
broad refactors, pass-gated lanes, or public API/runtime risk. Use a derived skill or project template with phases, risk rows, review gates, and explicit closure criteria.
Do not inflate a micro work item into a ceremony pile. Do not shrink a major work item into a checklist that cannot catch real risk.
Goal Flow Modes
Every goal-backed workflow chooses exactly one flow mode before durable work starts. The mode controls the human review boundary; it does not weaken the evidence or completion rules.
1. One-Shot Execution
Use this for issue-like or work-item-like work where the agent is expected to read the source, derive the local plan, implement, verify, and hand off the result without stopping for plan approval.
Rules:
- Create or continue a goal when the work is non-trivial and auditable.
- Create a plan when durable state is useful or required by the caller.
- The plan is an execution ledger, not a proposal waiting for acceptance.
- Human review happens at the final handoff or explicit user interruption.
- Do not pause merely because the plan has not been reviewed. Pause only for a
real blocker, unsafe ambiguity, or a user decision that changes scope.
2. Agent-Led Plan Hardening
Use this when the requested output is a plan and the user wants the agent to drive toward the best plan with minimal human interruption.
Rules:
- The agent owns the review loop: research, compare options, pressure-test,
revise, and improve the plan until the confidence threshold is met.
- Ask the user only for decisions that materially change intent, boundaries,
risk tolerance, or acceptance criteria.
- Record each self-review pass and plan delta as evidence.
- Stop for one major user review when the plan reaches the stated readiness
threshold.
- Do not execute implementation under the planning goal unless the caller's
governing workflow explicitly says planning and execution are the same goal.
3. Collaborative Planning
Use this when the user and agent are intentionally shaping the plan together before execution.
Rules:
- The goal outcome is an accepted plan, not implementation.
- Ask focused questions when user judgment changes the plan.
- Keep options, tradeoffs, rejected alternatives, and open decisions visible in
the plan.
- Continue revising until the user accepts the plan or a blocker remains.
- Execution starts only after explicit acceptance or a new instruction that
changes the flow mode.
Flow-mode selection belongs in the derived skill or the instantiated plan when the caller knows it. If no caller specifies a mode, default to one-shot execution for implementation tasks, agent-led plan hardening for autonomous planning/review requests, and collaborative planning when the user is actively brainstorming or asking for plan acceptance before work.
Use When
- The user asks to set a goal or asks Codex to keep working until a verifiable
end state.
- A repo skill says to use
create_goalor goal setup. - Work is long-running, iterative, and has an auditable success condition.
- The path is uncertain but the finish line is auditable.
- The user would otherwise keep saying: "continue", "try the next fix", "rerun
the benchmark", "keep going until it works".
- A pass-gated lane needs one durable objective with the pass schedule and
closure gates inside it.
- The user says
autogoal repair <expectation>after any goal-backed workflow
missed their expectation, and they want the owning rule/template repaired for future runs.
Do Not Use When
- The user asks a one-off question or wants one short answer.
- The edit is tiny and no continuation loop is useful.
- The finish line is vague: "make it better", "improve performance", "clean
this up" without a verification surface.
- The user explicitly declined goal setup or asked not to use goal tools.
- The only possible next move requires user input.
- Creating a goal would hide uncertainty instead of naming it.
- The user only wants the current artifact fixed once. Repair mode is for
recurring workflow expectation misses, not every ordinary bug in a plan file.
Tool Contract
This is agent-native. Use the goal tools directly when available:
get_goalto inspect the current thread goal.create_goalto start a new active goal.update_goal(status: complete)only when the objective is genuinely met.update_goal(status: blocked)only when no autonomous progress remains and
the same blocker has recurred enough to satisfy the tool contract.
There can be only one active goal per thread. Repeated create_goal calls fail while a goal exists. Always call get_goal first; call create_goal only when it returns no goal; use update_goal to complete or block the active goal.
Active Goal Conflict Protocol
When get_goal returns a goal, classify it before touching durable state:
same: the existing goal already describes the current requested end state.
Continue under it and keep its plan current.
same but stale plan: the goal is right but the plan is stale. Repair the
plan first, then continue.
newer user correction: the latest user message narrows, reverses, or
corrects the goal. Record the correction in the plan, follow the newest instruction, and do not call the old objective complete unless it is actually true.
different objective: the active goal is unrelated. Do not hijack it. If no
lifecycle tool can pause, resume, cancel, or replace it, say so briefly and proceed only with degraded plan state when the user explicitly says to go.
paused or externally controlled: do not fake completion or blocked status
to escape the tool. Continue only if the latest user instruction clearly authorizes the new work, and record the mismatch in the plan.
Never mark a goal complete because the user changed their mind. Completion means the objective is true. A correction changes the work path; it does not retroactively prove the old objective.
Do not invent a goal state file when a goal tool is available. If goal tools are not available, record degraded control state in the active plan only when the repo workflow requires that fallback; otherwise state that goal tools are not available and continue with the nearest safe workflow.
Goal Anatomy
A strong goal defines eight things:
1. Flow mode: one-shot execution, agent-led plan hardening, or collaborative planning. 2. Outcome: what must be true when done. 3. Completion threshold: the number, pass/fail command, artifact checklist, or explicit acceptance rows that prove done. 4. Verification surface: tests, benchmarks, logs, browser proof, generated artifact, report, issue comment, or source-backed audit. 5. Constraints: what must not regress. 6. Boundaries: files, packages, repos, tools, data, routes, issue scope, or product surfaces Codex may or may not touch. 7. Iteration policy: how to choose the next move after each attempt. 8. Blocked stop condition: when to stop and report the blocker, evidence, and next input needed.
If the user requested a timed checkpoint, the plan must also define the duration, whether it is minimum active work or an explicit hard stop, the initial confidence scorecard when no better metric exists, and how the current loop will finish cleanly after the checkpoint is reached.
The create_goal.objective field is only a short handle for the active goal. Keep it under 240 characters. Put the full contract in the goal plan, not in the tool objective.
Use this tool-objective shape:
<desired end state>; done when <short threshold>; plan <docs/plans/path>.Do not put commands, full pass schedules, long issue lists, constraints, boundaries, iteration policy, or blocked reports in create_goal.objective. Those belong in the plan sections.
Measurable Outcome Gate
Before calling create_goal, rewrite vague objectives into measurable ones, then compress the tool objective to a short handle. The plan records the full contract.
Required:
- a specific done state
- a flow mode
- a verification surface
- a completion threshold
- a constraint list or explicit
no extra constraints - a blocked condition
Quantitative examples:
p95 < 120 msscore >= 0.92 and no dimension below 0.850 accepted review findingsall 12 pass rows complete or skipped with evidencefocused repro fails before fix and passes 5 consecutive runs afterno stale symbol matches from rg
Auditable non-numeric examples:
- named file exists with required sections
- named issue rows moved to fixed/improved/related/not-claimed
- named browser route has screenshot proof and no console errors
- named API examples compile and match the accepted public shape
Reject or rewrite:
- "make better"
- "clean up"
- "finish"
- "absolute best" without score rows, pass gates, or evidence
- "review and decide" without an artifact and acceptance criteria
Timed Checkpoints
When the user gives a duration such as 30m, 1h, 2 hours, or 10h, treat it as a minimum active-work checkpoint unless they explicitly say max, stop at, budget cap, or timebox hard stop.
Timed checkpoints are not permission to stop early because the first obvious gates passed. They mean: keep increasing confidence until the duration is reached, then finish the current loop cleanly.
If the goal already has concrete metrics, use those metrics during the timed loop and keep looking for the next highest-value confidence gap until the duration elapses.
If there is no concrete metric, create an initial scorecard in the plan before substantive work. Use a simple 0-100 confidence score with dimensions that fit the task, for example correctness, proof strength, simplicity, maintainability, docs/source alignment, risk, and slop removal. Record:
- initial score and dimension scores;
- what would raise the score;
- what would lower or cap confidence;
- next improvement packet;
- final score at handoff.
After the main implementation gates close, continue with confidence-building work until the timed checkpoint is reached:
- review the diff/output against the newest prompt;
- remove slop, dead code, fake aliases, stale docs, and weak abstractions;
- refactor toward the durable owner when it reduces real complexity;
- add or repair missing tests, proof, diagnostics, and source audits;
- run focused verification again after meaningful changes;
- repair the owning skill/template when the workflow itself missed the user's
expectation.
Do not start a large risky packet near the end unless there is enough time to finish, verify, and keep/revert/quarantine it. When the requested duration is reached, finish the active loop to a clean boundary: complete the current packet, verify it, revert or quarantine unsafe partial work, update the plan, and hand off. Never leave dirty half-work merely because the clock expired.
Stop before the timed checkpoint only for a real blocker, an explicit user interruption, or an unsafe ambiguity that would make further autonomous work harmful. Passing the first checks is not a stop condition.
Completion Gate Policy
Do not make check-complete.mjs the whole goal. That only proves the plan looks closed, not that the work is true.
Use the hybrid rule for every goal:
1. The goal tool objective names the outcome, short threshold, and plan path. 2. The docs/plans goal plan records the verification surface, constraints, boundaries, blocked condition, fresh evidence, and completion threshold. 3. node .agents/skills/autogoal/scripts/check-complete.mjs <docs/plans/path> is the final mechanical gate before update_goal(status: complete).
The checker validates that the goal plan has no unchecked required checklist items, no unresolved gate rows, no open phase/pass rows, concrete verification evidence, current reboot status, and recorded risks. It does not replace tests, browser proof, source audits, benchmark output, or other named verification evidence.
Evidence Type Contract
Every completion proof should fit at least one evidence type:
command: exact command, cwd, and pass/fail result.source-audit: exact files or search query proving a static property.browser: route, interaction, screenshot or console/network caveat.artifact: generated file, report, table, PR body, issue comment, or
exported asset.
review: reviewer/tool used, accepted findings, fixes, and remaining
rejected findings with reasons.
external-source: cited URL, issue, paper, docs page, or connected app
result used as authority.
N/A:<reason>: why a recurring gate does not apply.
Evidence must name the owning workspace, package, app, route, or tool when that ownership matters. A root-level check cannot prove a sibling repo, app route, browser surface, or external tracker unless the plan explains why it is the owning surface.
Repair Mode
Trigger this mode when the arguments start with:
repair <expectation>Repair mode is self-improvement with a leash. It converts a concrete expectation miss from a goal-backed run into the smallest durable change to the owning rule, template, helper, or active plan.
Use it for misses like:
- the generated goal plan lacked a gate the user expected
- a derived skill used the wrong template or completion rule
- the skill completed too early or kept running past the intended boundary
- the final handoff omitted evidence the user expects every time
- the workflow forced too much ceremony or skipped a required review/proof step
Do not use it for:
- one-off wording preferences in a single plan
- a product/runtime bug that belongs in implementation code
- broad "make all skills better" edits
- rewriting generated
skills/*/SKILL.mdby hand
Target selection order:
1. If the prompt names a plan path, read that plan first. Use its Template:, skill name, phase table, and completion gates to identify the owner. 2. If the prompt names a skill, read skills/<skill>/SKILL.md first, then project-owned docs/plans/templates/<skill>.md when it exists. 3. If there is an active goal, read its plan path from the objective or current plan before editing anything. 4. If the miss belongs to every goal, target the dotai source package: skills/autogoal/SKILL.md and skills/autogoal/assets/templates/goal.md. Do not patch the installed .agents/skills/autogoal copy by hand. 5. If ownership is still unclear after source reads, ask one short targeting question instead of patching multiple templates.
Repair scope matrix:
| Miss | Primary repair owner |
|---|---|
| Current plan has wrong status, row, evidence, or handoff fields | active docs/plans/* plan |
| Future generated plans need a recurring section, gate, row, or placeholder | project-owned docs/plans/templates/<owner>.md or dotai source skills/autogoal/assets/templates/<owner>.md |
| Agent chose the wrong workflow, target, proof standard, or completion rule | skills/<owner>/SKILL.md |
| Prose keeps failing and the miss is mechanically checkable | dotai source skills/autogoal/scripts/* plus focused script proof |
| Derived skill adds lane-specific ceremony or policy | derived skill rule/template, not autogoal |
| Universal lifecycle rule is missing across goal-backed work | dotai source skills/autogoal/SKILL.md |
Repair workflow:
1. Restate the expectation in one sentence. 2. Identify the miss with source evidence: plan row, final response shape, missing gate, bad status, wrong template, or stale generated skill. 3. Pick exactly one primary owner. Patch secondary owners only when sync is required, such as source rule plus project template. 4. Create a repair plan with:
node .agents/skills/autogoal/scripts/create-goal-scratchpad.mjs \
--template goal-repair \
--title "<short repair title>"If a repair is truly trivial, record why no separate repair plan is needed. 5. Patch source-of-truth files only. Never hand-edit installed .agents/skills/**/SKILL.md; after changing dotai skills/**, run scripts/validate-skills. 6. Prove the repair:
- source audit with
rgfor the new rule/gate/wording - generated skill sync when
skills/**changed - instantiate the repaired template or inspect it directly when a smoke plan
would create noise
- verify unfinished generated plans still fail
check-complete.mjs - verify a completed plan can record the new expectation without editing the
template again 7. Final response says: expectation, repaired owner, verification, and any deliberate non-repair.
Safety rules:
- One expectation should produce one narrow repair. Do not turn repair mode into
a skill rewrite.
- Do not weaken completion gates just because a past run was annoying. If the
expectation conflicts with evidence safety, record the conflict and ask.
- Prefer adding a missing row or decision rule over adding a new script. Add
mechanical enforcement only when prose gates keep failing.
- A derived skill may have stricter rules than
autogoal. Repair the derived
skill when the expectation is lane-specific; repair autogoal only when the expectation should apply across goal-backed work.
- If an active goal is unrelated to the repair, do not hijack it. Ask whether to
finish/block it first or run the repair after it is closed.
Derived Skill Contract
Any skill that requires or wraps autogoal should declare:
- when it creates or continues a goal
- which flow mode it uses by default, and how the user changes it
- which project template
docs/plans/templates/<template>.mdit uses - which packs it applies by default, and which touched surfaces add more packs
- extra start gates and completion gates it owns
- evidence types it requires
- final handoff shape
- review or pressure lenses it adds
- what remains delegated to
autogoal - what it intentionally does not inherit from broader templates
Derived skills should route to autogoal for lifecycle mechanics instead of re-implementing plan creation, completion, blocked semantics, repair mode, or evidence closure.
Resume Protocol
After compaction, interruption, or a long pause:
1. Read the latest user message first. 2. Call get_goal when available. 3. Re-read the active docs/plans path named by the goal, current workflow, or latest handoff. 4. Find the latest verification evidence, open risk, and next owner. 5. Continue from the newest user instruction, not from an older stale objective. 6. Before final response, sanity-check that the answer matches the newest request and the current plan state.
If the active goal and newest request disagree, use the Active Goal Conflict Protocol before editing.
Start And Completion Gates
Project templates may define Start Gates: and Completion Gates: tables. These are template-owned audit surfaces for recurring project checks.
Keep this rule generic. Do not put project-specific commands, package-manager details, release rules, browser tooling, or repo policy in this file. Those rows belong in project-owned templates under docs/plans/templates/.
When present, gate tables must use markdown tables with these columns:
GateAppliesEvidence
They may include extra columns such as Required action. The checker treats any cell in a gate row as unresolved when it is blank, pending, TODO, or TBD.
Gate closure rules:
Appliesmust be resolved before completion.yesmeans the evidence cell names the command, artifact, proof, source
audit, or concrete result.
noorN/A: <reason>means the evidence cell explains why the gate does
not apply.
- A completion gate row should stay unresolved until the action or reason is
recorded.
check-complete.mjsenforces gate-row closure mechanically, but it does not
know what project-specific commands mean.
Start Workflow
1. Read the user's request and any named plan, issue, logs, route, test, or source-of-truth file. 2. Inspect the current goal with get_goal when available. 3. Select the flow mode: one-shot execution, agent-led plan hardening, or collaborative planning. 4. Rewrite the desired objective until it has a measurable or auditable completion threshold. 5. Choose the title, template, and docs/plans path needed by the objective. If the helper is the only reliable way to know the path, create only the static plan shell before create_goal. 6. If docs/plans/templates/ does not exist, initialize the generic templates before creating or selecting a plan:
node .agents/skills/autogoal/scripts/init-templates.mjsExisting project templates must be kept. Do not continue with only built-in fallback templates when the project template directory is missing. 7. If no active goal exists and the user or governing skill asked for a goal, create one with a short create_goal.objective handle under 240 characters. 8. If an active goal already matches the desired end state, continue under it. 9. If an active goal exists but points at a different objective, do not overwrite it. Resolve the current goal honestly before starting another one. If the tool does not allow that transition, report the mismatch and ask for the smallest decision needed. A governing lane goal may proceed only when it can honestly complete or fit within the current active goal. 10. Ensure the docs/plans goal plan exists before substantive work. 11. Fill the generated plan itself before substantive work: write the objective, threshold, verification surface, constraints, boundaries, blocked condition, flow mode, and goal plan path; resolve generated gates as yes/no/N/A instead of deleting or replacing the template output. 12. Record the output-budget strategy before exploratory commands: which searches or reads are allowed, which high-volume paths are excluded, and how large results will be capped, counted, or saved as artifacts instead of streamed into the goal context. 13. Record timed-checkpoint semantics when the prompt includes a duration. If the duration is not explicitly a hard stop, treat it as minimum active work and add the initial scorecard when no concrete metric exists. 14. Use that exact path for check-complete.mjs. 15. Do not start durable work until the goal is set, verified as already matching, or the user explicitly resolves the missing-goal path.
Set or verify the goal before mutable lane state when the workflow depends on a goal. The only exception is creating the static plan shell needed to get the path for the short objective. For pass-gated planning or accepted-plan execution lanes, the goal is the first durable action after the minimum read and optional static plan shell needed to derive the objective.
Template Init
Generic autogoal templates are project files. They live at:
docs/plans/templates/goal.md
docs/plans/templates/task.md
docs/plans/templates/docs.md
docs/plans/templates/major-task.md
docs/plans/templates/goal-repair.md
docs/plans/templates/packs/<pack>.mdWhen docs/plans/templates/ is absent, or when docs/plans/templates/goal.md or another generic template is missing, initialize the generic set before creating a goal plan:
node .agents/skills/autogoal/scripts/init-templates.mjscreate-goal-scratchpad.mjs and create-goal-template.mjs run this initialization automatically. If an agent is creating or selecting a plan without those helpers and the directory is absent, run init-templates.mjs first. Existing files are kept. Project-specific templates such as docs/plans/templates/<lane>.md stay in the project and are never moved into the skill package.
Goal Plan
Every active goal gets one durable goal plan. It is a single markdown file that absorbs the useful file-planning parts: phases, findings, progress, decisions, failed attempts, verification, and reboot status.
Path:
docs/plans/YYYY-MM-DD-<short-goal-slug>.md
docs/plans/<ticket>-<short-goal-slug>.mdUse the ticket-prefixed form for issue-backed work. Do not create task_plan.md, findings.md, progress.md, .planning/**, docs/goals/**, .tmp/goals/**, or hook state for goal work. Hooks are overkill. The active goal plus the docs/plans file are the durable state.
Create the goal plan with the source-owned helper whenever available:
node .agents/skills/autogoal/scripts/create-goal-scratchpad.mjs \
--title "<short title>" \
--template "<primary template name or path>" \
--with "<optional pack name>"The helper writes docs/plans/YYYY-MM-DD-<slug>.md or docs/plans/<ticket>-<slug>.md from a project-owned template or built-in autogoal template. The helper lives under .agents/skills/autogoal/ because it is generic rule tooling; generated SKILL.md files are not edited by hand.
Do not pass objective, threshold, verification, constraints, boundaries, or blocked condition through CLI flags. The CLI only creates the static plan shell. After creation, edit the generated docs/plans file and write the active goal objective, completion threshold, verification surface, constraints, boundaries, blocked condition, and remaining goal-specific rows into the file.
Editing the generated file means filling and resolving that materialized shell, not replacing it with a hand-made mini-plan. Keep generated sections and rows unless the row is truly irrelevant, then mark it complete with N/A: <reason>. If a template choice is wrong before work starts, regenerate with the correct template and record the replacement. If any durable work has already started, do not swap the plan out from under the work; close the generated plan with honest evidence, N/A rows, or a blocker.
The default project template is generic:
docs/plans/templates/goal.mdProject or skill-specific templates live beside it:
docs/plans/templates/<template>.mdReusable packs live under:
docs/plans/templates/packs/<pack>.mdUse templates by passing the primary template name. Add packs for touched surfaces:
node .agents/skills/autogoal/scripts/create-goal-scratchpad.mjs \
--template "<template-name>" \
--with "<pack-name>" \
--title "<short title>" \
...Repeat --with for multiple packs, or pass a comma-separated list. The helper records Primary template: and Applied packs: in the generated plan and copies pack rows into the plan's existing gate/checklist sections.
docs/plans/templates holds reusable project templates. Generic templates are seeded there by init-templates.mjs; non-generic templates stay there as project-owned workflow policy. Direct files under docs/plans are instantiated runtime goal plans. Do not store goal templates or active goal state under docs/goals.
Create a new project-owned template by copying the generic template:
node .agents/skills/autogoal/scripts/create-goal-template.mjs \
--skill "<skill-name>"Then edit the new docs/plans/templates/<skill-name>.md to add that skill or project lane's mandatory sections, checklist rows, phase schedule, evidence rows, and closure gates. Keep the generic goal template project-agnostic.
Template creation is not skill creation. Do not generate skill folders, aliases, execution handoffs, hook state, or compatibility bridges from this workflow. A project template is just a reusable static shell for a future docs/plans/* goal plan. The agent fills the real objective, threshold, verification surface, constraints, boundaries, and blocked condition inside the instantiated plan.
Before creating or updating a project template, define these inputs:
- template name and owning skill or project lane
- primary-template role and which packs should usually compose with it
- display name and purpose
- recurring failure mode the template prevents
- use cases and non-use cases
- allowed edit boundaries for plans created from it
- required read-first sources and optional read-when-relevant sources
- evidence sources and final verification surface
- measurable score, count, pass/fail command, or artifact checklist threshold
- required plan sections
- required checklist rows, including skill analysis and final goal-plan check
- phase or pass table, or an explicit reason the template needs no phases
- completion gates and score caps when score is used
- review or pressure lenses that must run before closeout
- handoff, final response, and risk rows
- blocked condition and what input would unblock it
If an input cannot be inferred from current project context, add a placeholder inside the template and label it as a generation gap. Ask the user only when the missing answer changes the template's purpose, safety model, or boundaries.
Template quality bar:
- The template must be self-contained enough to create a useful goal plan from
scratch. Do not require a sibling template to understand it.
- Sibling templates may be used for sync review, not as hidden dependencies.
- Packs may provide recurring touched-surface rows, but only after the helper
materializes them into the generated plan. Do not rely on hidden pack state.
- Domain facts must be placeholders or instructions unless live source proves
them. Do not invent current-state, before/after, API, product, or workflow facts.
- No template may let a goal finish from polished prose, score alone, or a
completed phase table without fresh evidence.
- Every primary template must include an
Autoreviewcompletion gate before
the final Goal plan complete check.
- Every required checklist item must map to evidence, an explicit N/A reason,
or a blocker.
- Every required section is either present in the template or omitted with a
recorded reason.
- Project templates that cover implementation work should include compact gates
for review target selection, workspace-authority verification, specialized agent/tooling review when those surfaces change, and a high-risk note for public API, runtime, package-boundary, browser, agent-action, or command contract changes. Do not copy a major planning lane's scorecard, issue ledger, or full pass schedule into generic execution templates.
- The template should prefer concrete commands, file paths, issue rows,
browser routes, screenshots, benchmark names, or source-audit rows over vague "review" wording.
- The generated plan remains the runtime truth. Do not put active goal state in
docs/plans/templates.
Template sync review:
- Instantiate the template once with
create-goal-scratchpad.mjsor inspect the
copied file directly when a smoke plan would create noise.
- Verify the expected headings, checklist rows, phase/pass rows, completion
gates, and blocker rows are present.
- Verify a blank or unfinished instantiated plan fails
check-complete.mjs. - Verify a completed plan can record the named evidence without editing the
template itself.
- After editing dotai
skills/autogoal/SKILL.md, runscripts/validate-skills.
Create the plan before substantive edits. Update it after every meaningful decision, finding, tradeoff, failed attempt, review fix, verification run, or scope change. Re-read it before major decisions and after compaction or interruption.
Check the goal plan before completion:
node .agents/skills/autogoal/scripts/check-complete.mjs docs/plans/<goal-plan>.mdThis is the final mechanical gate, not a substitute for the named verification surface.
The goal-plan checklist is mandatory. Its first required item is skill analysis. Do not call update_goal(status: complete) while any required checklist item remains unchecked. If an item does not apply, check it and add N/A: <reason>.
Required goal-plan sections:
# <Goal title>
Objective:
<short create_goal objective, under 240 characters>
Flow mode:
<one-shot execution | agent-led plan hardening | collaborative planning>
Goal plan:
<docs/plans/path>
Primary template:
<docs/plans/templates/name.md>
Applied packs:
- <pack or none>
Completion threshold:
- <quantitative or auditable done row>
Verification surface:
- <tests/artifacts/browser proof/source audit>
Constraints:
- <must preserve / must not touch>
Boundaries:
- <allowed files/packages/tools>
Output budget strategy:
- <how command/search output will be scoped, capped, counted, or artifacted>
Blocked condition:
- <condition that stops autonomous work>
Start Gates:
| Gate | Applies | Evidence |
Work Checklist:
- [ ] Actual work item or pass-specific requirement with evidence.
- [ ] ...
Completion Gates:
| Gate | Applies | Required action | Evidence |
Phase / pass table:
| Phase | Status | Evidence | Next |
Findings:
- <research, source reads, browser/visual findings as data>
Timeline:
- <timestamp> <action/evidence>
Decisions and tradeoffs:
- <decision> -> <reason> -> <risk>
Review fixes:
- <finding> -> <accepted/rejected> -> <change or reason>
Error attempts:
| Error / failed attempt | Count | Next different move | Resolution |
Verification evidence:
- <command/artifact> -> <result>
Reboot status:
| Where am I? | Where am I going? | What is the goal? | What learned? | What done? |
Open risks:
- <risk or none>Before update_goal(status: complete), the goal plan must include the final verification evidence, checked checklist, current reboot status, and any remaining risks.
Good Goal Handles
Performance:
Reduce checkout p95; done when p95 < 120 ms and checks pass; plan docs/plans/YYYY-MM-DD-checkout-latency.md.Bug hunt:
Fix flaky checkout test; done when repro passes 5 consecutive runs; plan docs/plans/YYYY-MM-DD-checkout-flake.md.Research:
Reproduce target paper evidence; done when every headline claim has a status row; plan docs/plans/YYYY-MM-DD-paper-repro.md.Pass-gated planning:
Close layout plan; done when score >= 0.92 and closure gates pass; plan docs/plans/YYYY-MM-DD-layout-plan.md.Weak Goal Examples
Improve performance
Make this better
Refactor the editor
Run all passes
Finish the projectThese are weak because they lack a measurable outcome, verification surface, or scope boundary.
Pass-Gated Goals
For pass-gated lanes, prefer one lane goal when the goal tool can persist across turns. Put the pass schedule in the plan, keep the goal objective short, run one pass per activation, and complete the goal only when closure gates prove no pass remains runnable.
Use this when a workflow has scheduled passes such as current-state read, issue discovery, intent boundary, research refresh, steelman, revision, verification sweep, or closure.
Rules:
- The goal objective should describe only the lane outcome, short completion
threshold, and plan path.
- The plan should describe the full pass schedule, one-pass-per-activation
policy, proof gates, and closure condition.
- Complete the current pass in the plan or progress ledger, not by closing the
goal.
- Complete the goal only when every required pass is complete or intentionally
skipped with evidence.
- Do not use separate per-pass goals; keep scheduled passes as rows in the
active plan.
- Keep pass status in the plan or progress ledger; keep goal status tied to the
whole lane.
Progress fields for pass-gated lanes:
current_pass: current-state-read
current_pass_status: in_progress
next_pass: related-issue-discovery
goal_status: activeAllowed goal_status values:
activecompleteblocked
Completion Rules
Mark a goal complete only when:
- the outcome in the goal is actually achieved
- the completion threshold is met exactly
- the verification surface named by the goal was checked
- the
docs/plansgoal plan is updated with final verification - every required goal-plan checklist item is checked or marked N/A with reason
node .agents/skills/autogoal/scripts/check-complete.mjs <docs/plans/path>passes
after the final evidence is recorded
- constraints and boundaries were respected, or deviations were explicitly
accepted
- required artifacts were created or updated
- no required owner remains runnable
- the final response reports the evidence, not just confidence
Do not mark complete because:
- tests passed but the goal also required review, browser proof, docs, or a
report
- the budget is nearly exhausted
- the current slice is done but later slices remain
- a plan was written but execution or proof remains
- the user says "nice" without accepting open risks
When calling update_goal(status: complete), include the tool's final token/time usage in the user-facing closeout when the tool returns it.
Blocked Rules
Blocked is terminal for the goal, not a normal checkpoint.
Use blocked only when:
- no autonomous next move remains
- missing evidence, access, tooling, data, or a user decision prevents progress
- repeated attempts show the same blocker, and the tool's blocked threshold is
satisfied
Do not mark blocked when:
- more investigation is possible
- a different test, smaller repro, or narrower source read is available
- the work is merely hard, slow, or broad
- a review pass found issues that can be fixed
- a gate failed and the failing owner is obvious
Blocked report shape:
Goal blocked.
Attempted:
- ...
Evidence:
- ...
Blocker:
- ...
Needed to continue:
- ...Budget Handling
Budget exhaustion is not success.
Output Budget Discipline
Goal token budgets are real work budgets, not decorative counters. A goal run that burns its budget on tool output has failed the workflow even when no app code was touched.
Oversized goal objectives are budget failures too. If the tool objective starts to read like a plan, stop and move that detail into docs/plans.
Before running exploratory commands inside an active goal:
- Prefer narrow reads over broad scans: exact files, focused
rg -npatterns,
targeted globs, and short sed -n ranges.
- Treat
tmp/**, logs, binaries, generated output, build artifacts,
node_modules, .next, .turbo, and coverage folders as excluded by default. Include them only when they are the named source of truth.
- Set explicit tool output caps for commands likely to return more than a
screenful. Keep ordinary source reads around a few thousand tokens, and justify any larger cap in the plan.
- For broad audits, first ask for counts, filenames, or top matches
(rg --count, rg --files-with-matches, --max-count, wc, head) before printing matching lines.
- If a result may be large but still matters, write it to a local artifact and
inspect slices from that artifact. Do not stream the full result into the conversation.
- Never run unbounded
rgacross the whole repo plus large generated trees, logs, or binary
outputs during a budgeted goal. Split the search by owner or exclude the noisy trees first.
- After any accidental large output, stop broad exploration immediately, record
the miss in the error-attempts row, and continue only with constrained commands.
If the system stops or warns because a goal budget is reached:
- stop substantive work
- summarize current evidence and remaining owners
- name the next useful action
- do not call the goal complete unless the original objective is already proven
Lifecycle Boundaries
Do not use update_goal for lifecycle transitions outside its contract.
The model may complete or block a goal only through update_goal when the tool contract is satisfied. Other lifecycle transitions are user/system-owned. If the user asks for a lifecycle transition and no direct tool is available, state that the current runtime does not expose that control instead of faking it with completion or blocked status.
Status Updates During Goals
Keep status short and evidence-based:
- current checkpoint
- what changed
- what was verified
- what remains
- whether blocked
- next concrete action
Avoid vague updates like "making progress" or "continuing investigation". If status gets vague, tighten the goal or checkpoint.
Research Goals
Research goals need stricter epistemic accounting.
Final reports should separate:
- confirmed findings
- approximate reconstructions
- proxy/support-only evidence
- blocked exact claims
- remaining uncertainty
Do not flatten "approximate support" into "reproduced" or "fixed". A good research goal lets Codex keep working through uncertainty while preventing overclaiming.
Closeout Template
Use this shape when closing a goal:
Goal complete.
Evidence:
- <command/artifact/source>
What changed:
- <short list>
Constraints preserved:
- <short list>
Residual risk:
- <only if real>
Usage:
- <tool-reported tokens/time, when available>For blocked:
Goal blocked.
Evidence:
- <what was tried>
Blocker:
- <why no autonomous progress remains>
Needed next:
- <specific user/tool/input>{{TITLE}}
Objective: TODO: Write the short create_goal objective, under 240 characters. Put the full docs contract in the sections below.
Goal plan: {{PLAN_PATH}}
Template: {{TEMPLATE_PATH}}
Docs source:
- type: pending
- id / link: pending
- title: pending
- acceptance criteria: pending
First checkpoint:
- Before implementation or broad exploration, copy every explicit prompt
requirement into this plan as checkable checkpoints: scope, non-goals, timing/duration, stop conditions, deliverables, final handoff sections, verification surface, and success criteria.
- Do not continue into implementation until this extraction is complete or
explicitly marked N/A with reason.
Timed checkpoint:
- requested duration: pending
- semantics: pending
- initial confidence score: pending
- improvement loop: pending
- final score / loop closure: pending
Completion threshold:
- TODO: Define the exact docs done state.
Verification surface:
- TODO: Name source audit, docs parser/build, link/demo check, preview check, or review proof.
Constraints:
- Follow nearest existing docs style.
- Write current-state docs only. No changelog voice.
- Keep examples repo-backed and copy-pasteable.
- Do not invent APIs, routes, demos, imports, components, transforms, or options.
Boundaries:
- Source of truth: TODO.
- Allowed edit scope: TODO.
- Browser surface: TODO.
- Non-goals: TODO.
Blocked condition:
- TODO: Name missing source code, docs entry, route, product choice, or command failure that stops autonomous docs work.
Completion rule:
- Do not call
update_goal(status: complete)until required checks are closed andnode .agents/skills/autogoal/scripts/check-complete.mjs {{PLAN_PATH}}passes.
Start Gates:
| Gate | Applies | Evidence |
|---|---|---|
| Prompt requirements captured before work | pending | pending |
| Timed checkpoint parsed | pending | pending |
| Active goal checked or created | pending | pending |
| Target docs read | pending | pending |
| Nearest sibling docs read | pending | pending |
| Documented source code read | pending | pending |
Work Checklist:
- [ ] First checkpoint complete: every explicit prompt requirement, scope
boundary, timing constraint, stop condition, deliverable, final handoff section, verification surface, and success criterion is copied into this plan as checkable checkpoints before implementation.
- [ ] Target docs and nearest sibling docs were read before writing.
- [ ] If a duration was requested, it is recorded as minimum active work unless
explicitly marked hard stop; when no better metric exists, initial and final confidence scores are recorded.
- [ ] Documented behavior or API was verified against current source.
- [ ] Fastest success path appears before deeper mechanics or API reference.
- [ ] Named APIs, imports, routes, options, and examples are exact and current.
- [ ] Links and anchors target real pages or are marked N/A.
Completion Gates:
| Gate | Applies | Required action | Evidence |
|---|---|---|---|
| Docs source-backed claim audit | pending | Verify docs claims against current source | pending |
| Docs links / routes / previews | pending | Verify or record N/A | pending |
| Docs parser/build | pending | Run relevant docs parser/build or record N/A | pending |
| Autoreview | pending | Review final docs against objective, constraints, source truth, and newest user request | pending |
| Timed checkpoint | pending | If duration was requested, keep improving until elapsed, then finish the current loop cleanly; otherwise N/A | pending |
| Goal plan complete | yes | Run node .agents/skills/autogoal/scripts/check-complete.mjs {{PLAN_PATH}} | pending |
Phase / pass table:
| Phase | Status | Evidence | Next |
|---|---|---|---|
| Intake and source read | in_progress | created plan | writing |
| Writing | pending | verification | |
| Verification | pending | closeout | |
| Closeout | pending | final response |
Findings:
- None yet.
Timeline:
- {{CREATED_AT}}: plan created.
Verification evidence:
- Pending.
Reboot status:
| Question | Answer |
|---|---|
| Where am I? | Intake and source read |
| Where am I going? | Writing, verification, closeout |
| What is the goal? | TODO: Fill from Objective |
| What have I learned? | See Findings |
| What have I done? | See Timeline |
Open risks:
- Pending.
{{TITLE}}
Objective: Repair a goal-backed workflow that missed an expectation.
Goal plan: {{PLAN_PATH}}
Template: {{TEMPLATE_PATH}}
Expected behavior:
- TODO: State the user expectation or governing workflow rule.
Observed miss:
- TODO: State what actually happened.
First checkpoint:
- Before implementation or broad exploration, copy every explicit prompt
requirement into this plan as checkable checkpoints: scope, non-goals, timing/duration, stop conditions, deliverables, final handoff sections, verification surface, and success criteria.
- Do not continue into implementation until this extraction is complete or
explicitly marked N/A with reason.
Timed checkpoint:
- requested duration: pending
- semantics: pending
- initial confidence score: pending
- improvement loop: pending
- final score / loop closure: pending
Completion threshold:
- TODO: Define what proves the repair is complete.
Verification surface:
- TODO: Name the source audit, regenerated artifact, command, review, or user-visible proof.
Constraints:
- Repair one expectation narrowly.
- Patch source-of-truth files, not generated skill mirrors.
- Do not weaken evidence safety or completion gates just to reduce annoyance.
- Do not broaden the repair to unrelated skills/templates.
Boundaries:
- Source of truth: latest
autogoal repair <expectation>request. - Allowed edit scope: TODO.
- Derived skill scope: TODO.
- Non-goals: TODO.
Blocked condition:
- TODO: Name the missing plan path, skill owner, expected behavior, or user decision that stops autonomous repair.
Start Gates:
| Gate | Applies | Evidence |
|---|---|---|
| Prompt requirements captured before work | pending | pending |
| Timed checkpoint parsed | pending | pending |
Work Checklist:
- [ ] First checkpoint complete: every explicit prompt requirement, scope
boundary, timing constraint, stop condition, deliverable, final handoff section, verification surface, and success criterion is copied into this plan as checkable checkpoints before implementation.
- [ ] Expected behavior and observed miss are concrete.
- [ ] If a duration was requested, it is recorded as minimum active work unless
explicitly marked hard stop; when no better metric exists, initial and final confidence scores are recorded.
- [ ] Source of truth for the missed rule is identified.
- [ ] Root cause is recorded before repair.
- [ ] Repair updates the canonical surface.
- [ ] Generated or downstream copies are refreshed only when applicable.
- [ ] Final evidence proves the missed expectation is now satisfied.
Completion Gates:
| Gate | Applies | Required action | Evidence |
|---|---|---|---|
| Root cause recorded | pending | Explain why the miss happened | pending |
| Canonical source repaired | pending | Patch the real source of truth | pending |
| Verification proof | pending | Run named proof or record blocker | pending |
| Autoreview | pending | Review repair against expected behavior, observed miss, and newest user request | pending |
| Timed checkpoint | pending | If duration was requested, keep improving until elapsed, then finish the current loop cleanly; otherwise N/A | pending |
| Goal plan complete | yes | Run node .agents/skills/autogoal/scripts/check-complete.mjs {{PLAN_PATH}} | pending |
Phase / pass table:
| Phase | Status | Evidence | Next |
|---|---|---|---|
| Intake and source read | in_progress | created plan | repair |
| Repair | pending | verification | |
| Verification | pending | closeout | |
| Closeout | pending | final response |
Timeline:
- {{CREATED_AT}}: repair plan created.
Verification evidence:
- Pending.
Reboot status:
| Question | Answer |
|---|---|
| Where am I? | Intake and source read |
| Where am I going? | Repair, verification, closeout |
| What is the goal? | TODO: Fill from Objective |
| What have I learned? | See Observed miss |
| What have I done? | See Timeline |
Open risks:
- Pending.
{{TITLE}}
Objective: TODO: Write the short create_goal objective, under 240 characters. Put the full contract in the sections below.
Goal plan: {{PLAN_PATH}}
Template: {{TEMPLATE_PATH}}
First checkpoint:
- Before implementation or broad exploration, copy every explicit prompt
requirement into this plan as checkable checkpoints: scope, non-goals, timing/duration, stop conditions, deliverables, final handoff sections, verification surface, and success criteria.
- Do not continue into implementation until this extraction is complete or
explicitly marked N/A with reason.
Timed checkpoint:
- requested duration: pending
- semantics: pending
- initial confidence score: pending
- improvement loop: pending
- final score / loop closure: pending
Completion threshold:
- TODO: Define the exact measurable or auditable done state.
Verification surface:
- TODO: Name the command, artifact, browser proof, source audit, or report that proves the threshold.
- Browser strategy: TODO. Use Browser for normal app QA; use Chrome directly
for native downloads, print/print-preview, file picker/uploads, clipboard, browser dialogs/permissions, extension/profile state, or exact Chrome rendering; use Computer Use only for native Chrome/OS UI that needs visual confirmation.
Constraints:
- TODO: List constraints or write
no extra constraints.
Boundaries:
- TODO: List allowed files, packages, tools, repos, routes, or data.
Blocked condition:
- TODO: Name the condition that stops autonomous work.
Completion rule:
- Do not call
update_goal(status: complete)while required checklist items remain unchecked. - Do not call
update_goal(status: complete)until final evidence is recorded andnode .agents/skills/autogoal/scripts/check-complete.mjs {{PLAN_PATH}}passes.
Start Gates:
| Gate | Applies | Evidence |
|---|---|---|
| Prompt requirements captured before work | pending | pending |
| Timed checkpoint parsed | pending | pending |
| Active goal checked or created | pending | pending |
| Source of truth read before edits | pending | pending |
| TDD decision before behavior change or bug fix | pending | pending |
| Browser proof decision for browser surface | pending | pending |
| Chrome/Computer decision for native browser surface | pending | pending |
Work Checklist:
- [ ] First checkpoint complete: every explicit prompt requirement, scope
boundary, timing constraint, stop condition, deliverable, final handoff section, verification surface, and success criterion is copied into this plan as checkable checkpoints before implementation.
- [ ] Objective, threshold, verification surface, constraints, boundaries, and blocked condition are concrete.
- [ ] If a duration was requested, it is recorded as minimum active work unless
explicitly marked hard stop; when no better metric exists, initial and final confidence scores are recorded.
- [ ] Work phases are updated with evidence.
- [ ] Decisions and tradeoffs are recorded.
- [ ] Failed attempts and next different moves are recorded.
Completion Gates:
| Gate | Applies | Required action | Evidence |
|---|---|---|---|
| Named verification threshold | pending | Run the named proof or record blocker | pending |
| Typecheck/build/test proof | pending | Run relevant owner checks or record N/A | pending |
| Browser proof | pending | Capture Browser proof for normal app surfaces, or Chrome/Computer proof for native browser/OS surfaces; otherwise record N/A/blocker | pending |
| Autoreview | pending | Review final diff/output against objective, constraints, and newest user request | pending |
| Timed checkpoint | pending | If duration was requested, keep improving until elapsed, then finish the current loop cleanly; otherwise N/A | pending |
| Goal plan complete | yes | Run node .agents/skills/autogoal/scripts/check-complete.mjs {{PLAN_PATH}} | pending |
Phase / pass table:
| Phase | Status | Evidence | Next |
|---|---|---|---|
| Intake and source read | in_progress | created plan | implementation |
| Implementation | pending | verification | |
| Verification | pending | closeout | |
| Closeout | pending | final response |
Findings:
- None yet.
Decisions and tradeoffs:
- None yet.
Error attempts:
| Error / failed attempt | Count | Next different move | Resolution |
|---|---|---|---|
| None yet | 0 |
Timeline:
- {{CREATED_AT}}: plan created.
Verification evidence:
- Pending.
Reboot status:
| Question | Answer |
|---|---|
| Where am I? | Intake and source read |
| Where am I going? | Implementation, verification, closeout |
| What is the goal? | TODO: Fill from Objective |
| What have I learned? | See Findings |
| What have I done? | See Timeline |
Open risks:
- Pending.
{{TITLE}}
Objective: TODO: Write the short create_goal objective, under 240 characters. Put the full major-task contract in the sections below.
Goal plan: {{PLAN_PATH}}
Template: {{TEMPLATE_PATH}}
Major source:
- type: pending
- id / link: pending
- title: pending
- decision to make: pending
- decision criteria: pending
First checkpoint:
- Before implementation or broad exploration, copy every explicit prompt
requirement into this plan as checkable checkpoints: scope, non-goals, timing/duration, stop conditions, deliverables, final handoff sections, verification surface, and success criteria.
- Do not continue into implementation until this extraction is complete or
explicitly marked N/A with reason.
Timed checkpoint:
- requested duration: pending
- semantics: pending
- initial confidence score: pending
- improvement loop: pending
- final score / loop closure: pending
Completion threshold:
- TODO: Define the decision, proposal, benchmark, architecture, or migration done state.
Verification surface:
- TODO: Name repo audit, benchmark, external-source audit, review pass, prototype, command, or plan artifact.
Constraints:
- Start from repo evidence before external claims.
- Separate measured evidence, source evidence, inference, and recommendation.
- Do not execute implementation unless this goal explicitly includes it.
Boundaries:
- Source of truth: TODO.
- Allowed edit scope: TODO.
- External sources: TODO.
- Browser surface: TODO.
- Non-goals: TODO.
Blocked condition:
- TODO: Name missing source, benchmark, access, decision, external evidence, or user judgment that stops autonomous work.
Completion rule:
- Do not call
update_goal(status: complete)until evidence is recorded andnode .agents/skills/autogoal/scripts/check-complete.mjs {{PLAN_PATH}}passes.
Start Gates:
| Gate | Applies | Evidence |
|---|---|---|
| Prompt requirements captured before work | pending | pending |
| Timed checkpoint parsed | pending | pending |
| Active goal checked or created | pending | pending |
| Source of truth read before analysis | pending | pending |
| Decision criteria stated | pending | pending |
| Existing repo patterns / prior decisions checked | pending | pending |
| External research decision recorded | pending | pending |
Work Checklist:
- [ ] First checkpoint complete: every explicit prompt requirement, scope
boundary, timing constraint, stop condition, deliverable, final handoff section, verification surface, and success criterion is copied into this plan as checkable checkpoints before implementation.
- [ ] Current state is mapped before proposing a new architecture, migration, benchmark, or plan.
- [ ] If a duration was requested, it is recorded as minimum active work unless
explicitly marked hard stop; when no better metric exists, initial and final confidence scores are recorded.
- [ ] Existing repo patterns and prior decisions are recorded before external research.
- [ ] Options, recommendation, tradeoffs, blast radius, and rejection reasons are recorded.
- [ ] Facts, inference, and recommendation are separated.
- [ ] Review or pressure passes are completed, or marked N/A with reason.
Completion Gates:
| Gate | Applies | Required action | Evidence |
|---|---|---|---|
| Decision criteria satisfied | pending | Map evidence to each criterion | pending |
| Source audit complete | pending | Record repo evidence and external evidence | pending |
| Review / pressure pass | pending | Record review lens or N/A | pending |
| Autoreview | pending | Review final artifact against objective, criteria, constraints, and newest user request | pending |
| Timed checkpoint | pending | If duration was requested, keep improving until elapsed, then finish the current loop cleanly; otherwise N/A | pending |
| Goal plan complete | yes | Run node .agents/skills/autogoal/scripts/check-complete.mjs {{PLAN_PATH}} | pending |
Phase / pass table:
| Phase | Status | Evidence | Next |
|---|---|---|---|
| Intake and source read | in_progress | created plan | research / analysis |
| Current-state map | pending | options | |
| Options and recommendation | pending | review | |
| Review / pressure pass | pending | closeout | |
| Closeout | pending | final response |
Findings:
- None yet.
Decisions and tradeoffs:
- None yet.
Timeline:
- {{CREATED_AT}}: plan created.
Verification evidence:
- Pending.
Reboot status:
| Question | Answer |
|---|---|
| Where am I? | Intake and source read |
| Where am I going? | Research / analysis, options, review, closeout |
| What is the goal? | TODO: Fill from Objective |
| What have I learned? | See Findings |
| What have I done? | See Timeline |
Open risks:
- Pending.
agent-native pack
Use this pack when work changes agent instructions, skills, hooks, commands, prompts, or user-action tooling.
Start Gates:
| Gate | Applies | Evidence |
|---|---|---|
| Agent-native pack selected | pending | pending |
| Canonical agent source identified | pending | pending |
| Validation command selected | pending | pending |
Work Checklist:
- [ ] Agent-native pack: canonical source and generated/downstream copies are identified.
- [ ] Agent-native pack: skill frontmatter and routing descriptions are checked when skills change.
- [ ] Agent-native pack: validator or install check is run where available.
Completion Gates:
| Gate | Applies | Required action | Evidence |
|---|---|---|---|
| Agent source validation | pending | Run relevant agent/skill validation command | pending |
| Generated/downstream sync | pending | Refresh or mark N/A with reason | pending |
browser pack
Use this pack when changed behavior has a real browser, route, UI, native browser/OS, visual, selection, interaction, console, or network surface.
Start Gates:
| Gate | Applies | Evidence |
|---|---|---|
| Browser pack selected | pending | pending |
| Browser route / app surface identified | pending | pending |
| Browser tool decision recorded | pending | pending |
| Chrome/Computer decision recorded for native browser surface | pending | pending |
Work Checklist:
- [ ] Browser pack: route, interaction path, and expected visible outcome are recorded before proof.
- [ ] Browser pack: Browser proof is used for normal app surfaces; Chrome proof
is used for native downloads, print/print-preview, file picker/uploads, clipboard, browser dialogs/permissions, extension/profile state, or exact Chrome rendering; Computer Use is used when native Chrome/OS UI needs visual confirmation.
- [ ] Browser pack: screenshot or visual waiver happens only after the
applicable Browser->Chrome->Computer path cannot inspect the state.
- [ ] Browser pack: console and network errors are checked or explicitly out of scope.
- [ ] Browser pack: proof uses the real affected browser surface.
Completion Gates:
| Gate | Applies | Required action | Evidence |
|---|---|---|---|
| Browser interaction proof | pending | Exercise target route/interaction with Browser for normal app surfaces or Chrome/Computer for native browser/OS surfaces; otherwise record blocker | pending |
| Browser console/network check | pending | Record console/network state or N/A | pending |
| Browser final proof artifact | pending | Record screenshot/trace/route/native proof or exact caveat | pending |
docs pack
Use this pack when docs are touched but are not the dominant deliverable. If docs are the dominant deliverable, use --template docs.
Start Gates:
| Gate | Applies | Evidence |
|---|---|---|
| Docs pack selected | pending | pending |
| Target docs and nearest sibling docs read | pending | pending |
| Documented source owner identified | pending | pending |
Work Checklist:
- [ ] Docs pack: target docs, nearest sibling docs, and source owner are recorded.
- [ ] Docs pack: named APIs, imports, options, routes, components, demos, and previews are source-backed or marked N/A.
- [ ] Docs pack: docs use current-state reference voice, not changelog voice.
Completion Gates:
| Gate | Applies | Required action | Evidence |
|---|---|---|---|
| Docs source-backed claim audit | pending | Verify docs claims against current source | pending |
| Docs links / routes / previews | pending | Verify or record N/A | pending |
| Docs parser/build | pending | Run relevant docs parser/build or record N/A | pending |
package-api pack
Use this pack when work touches public app/API shape, route contracts, package boundaries, exports, release artifacts, or package-level type/build behavior.
Start Gates:
| Gate | Applies | Evidence |
|---|---|---|
| Package/API pack selected | pending | pending |
| Public surface or package/API boundary identified | pending | pending |
| Compatibility or hard-cut decision recorded | pending | pending |
Work Checklist:
- [ ] Package/API pack: public contract, boundary, export, and release impact are recorded.
- [ ] Package/API pack: compatibility, migration, or hard-cut decision is explicit when public shape changes.
- [ ] Package/API pack: app/package/API-owned typecheck/build/test proof is recorded or marked N/A.
Completion Gates:
| Gate | Applies | Required action | Evidence |
|---|---|---|---|
| Public app/API or package boundary proof | pending | Source-audit public contract, exports, and boundary impact | pending |
| Release artifact classification | pending | Record whether this is public, internal-only, docs-only, agent-only, test-only, or no user-visible delta | pending |
| App/package/API checks | pending | Run owning checks or record N/A with reason | pending |
{{TITLE}}
Objective: TODO: Write the short create_goal objective, under 240 characters. Put the full task contract in the sections below.
Goal plan: {{PLAN_PATH}}
Template: {{TEMPLATE_PATH}}
Task source:
- type: pending
- id / link: pending
- title: pending
- acceptance criteria: pending
First checkpoint:
- Before implementation or broad exploration, copy every explicit prompt
requirement into this plan as checkable checkpoints: scope, non-goals, timing/duration, stop conditions, deliverables, final handoff sections, verification surface, and success criteria.
- Do not continue into implementation until this extraction is complete or
explicitly marked N/A with reason.
Timed checkpoint:
- requested duration: pending
- semantics: pending
- initial confidence score: pending
- improvement loop: pending
- final score / loop closure: pending
Completion threshold:
- TODO: Define the exact task done state.
Verification surface:
- TODO: Name tests, typecheck, lint, browser proof, source audit, tracker/PR sync, or other artifact proving the threshold.
- Browser strategy: TODO. Use Browser for normal app QA; use Chrome directly
for native downloads, print/print-preview, file picker/uploads, clipboard, browser dialogs/permissions, extension/profile state, or exact Chrome rendering; use Computer Use only for native Chrome/OS UI that needs visual confirmation.
Constraints:
- Preserve behavior outside scope.
- Prefer the durable ownership boundary over caller-by-caller patches.
- Do not create PRs, commits, pushes, or external comments unless requested or required.
Boundaries:
- Source of truth: TODO.
- Allowed edit scope: TODO.
- Browser surface: TODO.
- Tracker sync: TODO.
- Non-goals: TODO.
Current verdict:
- verdict: pending
- confidence: pending
- next owner: task
- reason: pending
Pre-solution issue challenge:
- reporter claim: pending
- suggested diagnosis or fix: pending
- repro ladder:
- tests / source-level repro: pending
- repo-owned automated browser or integration proof: pending
- Browser plugin for normal app-surface proof: pending
- Chrome plugin for native browser/profile/OS proof: pending
- Computer Use for native Chrome/OS visual confirmation: pending
- screenshot / visual proof: pending
- reproduction verdict: pending
- validity verdict: pending
- best long-term fix boundary: pending
- harsh honest feedback: pending
- hard-stop decision: pending
Blocked condition:
- TODO: Name the missing source context, repro, access, command, or decision that stops autonomous work.
Completion rule:
- Do not call
update_goal(status: complete)while required checklist items remain unchecked. - Do not call
update_goal(status: complete)until every completion threshold is satisfied, final evidence is recorded, andnode .agents/skills/autogoal/scripts/check-complete.mjs {{PLAN_PATH}}passes.
Start Gates:
| Gate | Applies | Evidence |
|---|---|---|
| Prompt requirements captured before work | pending | pending |
| Timed checkpoint parsed | pending | pending |
| Active goal checked or created | pending | pending |
| Source of truth read before edits | pending | pending |
| Acceptance criteria captured | pending | pending |
| Pre-solution issue challenge required | pending | pending |
| Reproduction verdict before implementation | pending | pending |
| Repro escalation ladder selected | pending | pending |
| Suggested fix reviewed against durable boundary | pending | pending |
| TDD decision before behavior change or bug fix | pending | pending |
| Browser proof decision for browser surface | pending | pending |
| Chrome/Computer decision for native browser surface | pending | pending |
Work Checklist:
- [ ] First checkpoint complete: every explicit prompt requirement, scope
boundary, timing constraint, stop condition, deliverable, final handoff section, verification surface, and success criterion is copied into this plan as checkable checkpoints before implementation.
- [ ] Short objective plus threshold, verification surface, constraints, boundaries, and blocked condition are concrete.
- [ ] If a duration was requested, it is recorded as minimum active work unless
explicitly marked hard stop; when no better metric exists, initial and final confidence scores are recorded.
- [ ] Task source and acceptance criteria are captured.
- [ ] For public tracker bug reports, behavior claims, technical diagnoses, or
suggested fixes, reporter claims are challenged before implementation with a recorded verdict: valid, not reproduced, invalid, wont-fix, partially valid, or platform limitation. Feature, docs, support, or cleanup requests with no bug claim may mark reproduction N/A with reason.
- [ ] Repro escalation ladder followed for bug/behavior claims: focused
test/source-level repro first when applicable; existing repo-owned automated browser or integration proof next when available and useful as executable coverage; the repo-approved Browser tool next for normal app-surface behavior when tests or automation cannot reproduce or cannot model the surface honestly; Chrome directly for native downloads, print/print-preview, file picker/uploads, clipboard, browser dialogs/permissions, extension/profile state, or exact Chrome rendering; Computer Use when native Chrome/OS UI needs visual confirmation; screenshot or explicit visual-proof waiver when visual/native state matters and the Browser->Chrome->Computer escalation cannot inspect it.
- [ ] Hard-stop rule followed for bug/behavior claims: no code when the issue
is not reproduced, invalid, or won't-fix; partial validity pivots to the best long-term fix and records what was wrong or incomplete in the issue's proposed path.
- [ ] Nearby implementation patterns are read before edits.
- [ ] Implementation fixes the right ownership boundary, or the narrower choice
is recorded with reason.
- [ ] Review/autoreview target selected from actual diff state for non-trivial
implementation work, or marked N/A with reason.
- [ ] Verification evidence is recorded beside each relevant gate.
Completion Gates:
| Gate | Applies | Required action | Evidence |
|---|---|---|---|
| Named verification threshold | pending | Run the named proof or record blocker | pending |
| Pre-solution issue challenge verdict | pending | Record reporter claim, suggested fix, repro verdict, validity verdict, durable boundary, and hard-stop/pivot decision before implementation | pending |
| Repro escalation ladder | pending | For bug/behavior claims, record test/source-level, automated browser/integration, Browser, Chrome, Computer Use, and screenshot/visual-proof outcomes or N/A/blocker reasons before not reproduced | pending |
| Bug reproduced before fix | pending | Record failing test/repro or N/A with reason | pending |
| Targeted behavior verification | pending | Run focused test/proof for changed behavior or record N/A | pending |
| TypeScript or typed config changed | pending | Run relevant typecheck | pending |
| Build-sensitive behavior changed | pending | Run relevant build/check | pending |
| Browser surface changed | pending | Capture Browser proof for normal app surfaces, or Chrome/Computer proof for native browser/OS surfaces | pending |
| Final lint/format | pending | Run relevant lint/format command or record N/A | pending |
| Autoreview | pending | Review final diff/output against objective, acceptance criteria, constraints, and newest user request | pending |
| Timed checkpoint | pending | If duration was requested, keep improving until elapsed, then finish the current loop cleanly; otherwise N/A | pending |
| Goal plan complete | yes | Run node .agents/skills/autogoal/scripts/check-complete.mjs {{PLAN_PATH}} | pending |
Phase / pass table:
| Phase | Status | Evidence | Next |
|---|---|---|---|
| Intake and source read | in_progress | created plan | implementation |
| Implementation | pending | verification | |
| Verification | pending | closeout | |
| Closeout | pending | final response |
Findings:
- None yet.
Decisions and tradeoffs:
- None yet.
Timeline:
- {{CREATED_AT}}: plan created.
Verification evidence:
- Pending.
Reboot status:
| Question | Answer |
|---|---|
| Where am I? | Intake and source read |
| Where am I going? | Implementation, verification, closeout |
| What is the goal? | TODO: Fill from Objective |
| What have I learned? | See Findings |
| What have I done? | See Timeline |
Open risks:
- Pending.
Autogoal
Autogoal asks Codex to write a goal-backed plan ending with autoreview.
Install
npx skills add udecode/dotai --skill autogoalUse
Use autogoal for non-trivial work with an auditable finish line:
- debugging loops
- migrations
- benchmarks
- architecture plans
- pass-gated reviews
- multi-step issue work
Skip it for one-off answers, typo fixes, or tiny edits where the final response can carry the evidence.
Flow
1. Define the outcome, completion threshold, verification surface, constraints, boundaries, and blocked condition. 2. Create or continue the active Codex goal with a short objective handle. 3. Create a plan from a built-in or project template and put the full contract there. 4. First checkpoint: copy every explicit prompt requirement into the plan as checkable rows before implementation. 5. Work in slices and record evidence as you go. 6. Run autoreview, then fix or record accepted findings. 7. Run the completion check. 8. Mark the goal complete only when the outcome is true and the plan passes.
Helpers
node .agents/skills/autogoal/scripts/create-goal-scratchpad.mjs \
--template task \
--with browser \
--title "short title"node .agents/skills/autogoal/scripts/check-complete.mjs docs/plans/<plan>.mdnode .agents/skills/autogoal/scripts/init-templates.mjsTemplates
Autogoal ships generic templates in skills/autogoal/assets/templates. Installed skills expose them under .agents/skills/autogoal/assets/templates.
Project repos can keep their own templates in docs/plans/templates; the helper prefers project templates before built-in templates.
#!/usr/bin/env node
/** biome-ignore-all lint/suspicious/noConsole: CLI scripts write command output. */
import { existsSync } from 'node:fs';
import { readFile } from 'node:fs/promises';
import path from 'node:path';
const CHECKLIST_ITEM_PATTERN = /^-\s+\[([ xX])\]\s+/;
const GATE_SECTION_NAMES = ['Start Gates', 'Completion Gates'];
const HEADING_PATTERN = /^#{1,6}\s+\S/;
const HTML_COMMENT_PATTERN = /<!--[\s\S]*?-->/g;
const NEWLINE_PATTERN = /\r?\n/;
const OPEN_STATUS_PATTERN = /^(pending|in[_ -]?progress|todo|open)$/i;
const PHASE_HEADER_PATTERN = /^phase$/i;
const PLACEHOLDER_ONLY_PATTERN = /^(?:-\s*)?(?:pending|none yet)\.?$/i;
const RULE_ONLY_LINE_PATTERN = /^\s*[-|]+\s*$/gm;
const SECTION_START_PATTERN = /^[A-Z][A-Za-z /-]+:\s*$/;
const TABLE_MARKDOWN_SEPARATOR_CELL_PATTERN = /^:?-+:?$/;
const TABLE_SEPARATOR_PATTERN = /^-+$/;
const TODO_PATTERN = /\b(TODO|TBD)\b/i;
const args = parseArgs(process.argv.slice(2));
if (args.help) {
printHelp();
process.exit(0);
}
if (args.planPath) {
const root = findRepoRoot(process.cwd());
const planPath = path.resolve(root, args.planPath);
const relativePlanPath = path.relative(root, planPath);
const failures = [];
if (
relativePlanPath.startsWith('..') ||
path.isAbsolute(relativePlanPath) ||
!relativePlanPath.startsWith(`docs${path.sep}plans${path.sep}`)
) {
failures.push('goal plan must live under docs/plans/');
}
if (existsSync(planPath)) {
const content = await readFile(planPath, 'utf8');
failures.push(...checkPlanContent(content));
} else {
failures.push(`goal plan not found: ${relativePlanPath}`);
}
if (failures.length > 0) {
console.error(`[autogoal] incomplete: ${relativePlanPath}`);
for (const failure of failures) {
console.error(`- ${failure}`);
}
process.exitCode = 1;
} else {
console.log(`[autogoal] complete: ${relativePlanPath}`);
}
} else {
printHelp();
process.exitCode = 1;
}
function parseArgs(argv) {
const parsed = {};
for (const arg of argv) {
if (arg === '--help' || arg === '-h') {
parsed.help = true;
continue;
}
if (arg.startsWith('--')) {
throw new Error(`unknown flag: ${arg}`);
}
if (parsed.planPath) {
throw new Error(`unexpected extra argument: ${arg}`);
}
parsed.planPath = arg;
}
return parsed;
}
function checkPlanContent(content) {
const failures = [];
for (const section of [
'Objective',
'Completion threshold',
'Verification surface',
'Constraints',
'Boundaries',
'Blocked condition',
]) {
const block = getSectionBlock(content, section);
if (!hasConcreteContent(block)) {
failures.push(`${section} must be present and concrete`);
}
}
const checklist = getWorkChecklist(content);
if (checklist.length === 0) {
failures.push('Work Checklist must contain checklist items');
}
const unchecked = checklist.filter((item) => item.state === ' ');
if (unchecked.length > 0) {
failures.push(
`Work Checklist has unchecked items: ${unchecked
.map((item) => `line ${item.line}`)
.join(', ')}`
);
}
failures.push(...checkGateSections(content));
const phaseStatuses = getPhaseStatuses(content);
if (phaseStatuses.length === 0) {
failures.push('Phase / pass table must contain at least one status row');
}
const openStatuses = phaseStatuses.filter((status) =>
OPEN_STATUS_PATTERN.test(status.value)
);
if (openStatuses.length > 0) {
failures.push(
`Phase / pass table still has open statuses: ${openStatuses
.map((status) => `${status.name || 'unnamed'}=${status.value}`)
.join(', ')}`
);
}
const verification = getSectionBlock(content, 'Verification evidence');
if (!hasConcreteContent(verification)) {
failures.push('Verification evidence must record fresh final evidence');
}
const rebootStatus = getSectionBlock(content, 'Reboot status');
if (!hasConcreteContent(rebootStatus)) {
failures.push('Reboot status must be current');
}
const openRisks = getSectionBlock(content, 'Open risks');
if (!hasConcreteContent(openRisks)) {
failures.push('Open risks must be recorded, even if the value is "None"');
}
return failures;
}
function checkGateSections(content) {
const failures = [];
for (const sectionName of GATE_SECTION_NAMES) {
const block = getSectionBlock(content, sectionName);
if (!block.trim()) {
continue;
}
const table = parseMarkdownTable(block);
if (table.rows.length === 0) {
failures.push(`${sectionName} must contain resolved gate table rows`);
continue;
}
for (const column of ['gate', 'applies', 'evidence']) {
if (!table.headers.includes(column)) {
failures.push(`${sectionName} table must include ${column}`);
}
}
for (const [index, row] of table.rows.entries()) {
const label = row.gate || `row ${index + 1}`;
if (!hasConcreteContent(row.gate || '')) {
failures.push(`${sectionName} row ${index + 1} must name a gate`);
}
if (!hasConcreteContent(row.applies || '')) {
failures.push(`${sectionName} ${label} must resolve Applies`);
}
if (!hasConcreteContent(row.evidence || '')) {
failures.push(`${sectionName} ${label} must record evidence or reason`);
}
for (const [column, value] of Object.entries(row)) {
if (
!['gate', 'applies', 'evidence'].includes(column) &&
!hasConcreteContent(value)
) {
failures.push(`${sectionName} ${label} has unresolved ${column}`);
}
}
}
}
return failures;
}
function getSectionBlock(content, label) {
const lines = content.split(NEWLINE_PATTERN);
const startIndex = lines.findIndex((line) => line.trim() === `${label}:`);
if (startIndex === -1) {
return '';
}
const block = [];
for (let index = startIndex + 1; index < lines.length; index += 1) {
const line = lines[index];
if (isSectionStart(line)) {
break;
}
block.push(line);
}
return block.join('\n').trim();
}
function isSectionStart(line) {
return HEADING_PATTERN.test(line) || SECTION_START_PATTERN.test(line.trim());
}
function hasConcreteContent(block) {
if (!block.trim()) {
return false;
}
const normalized = block
.replace(HTML_COMMENT_PATTERN, '')
.replace(RULE_ONLY_LINE_PATTERN, '')
.trim();
if (!normalized) {
return false;
}
if (TODO_PATTERN.test(normalized)) {
return false;
}
return !PLACEHOLDER_ONLY_PATTERN.test(normalized);
}
function getWorkChecklist(content) {
const block =
getSectionBlock(content, 'Work Checklist') ||
getSectionBlock(content, 'Required checklist');
const lines = block.split(NEWLINE_PATTERN);
const items = [];
for (let index = 0; index < lines.length; index += 1) {
const match = CHECKLIST_ITEM_PATTERN.exec(lines[index]);
if (match) {
items.push({
line: index + 1,
state: match[1],
});
}
}
return items;
}
function parseMarkdownTable(block) {
let headers = [];
const rows = [];
for (const line of block.split(NEWLINE_PATTERN)) {
if (!line.trim().startsWith('|')) {
continue;
}
const cells = getTableCells(line);
if (cells.length === 0 || isTableSeparatorRow(cells)) {
continue;
}
if (headers.length === 0) {
headers = cells.map(normalizeTableHeader);
continue;
}
const row = {};
for (const [index, header] of headers.entries()) {
if (header) {
row[header] = cells[index] ?? '';
}
}
rows.push(row);
}
return { headers, rows };
}
function getTableCells(line) {
return line
.split('|')
.slice(1, -1)
.map((cell) => cell.trim());
}
function isTableSeparatorRow(cells) {
return cells.every((cell) =>
TABLE_MARKDOWN_SEPARATOR_CELL_PATTERN.test(cell)
);
}
function normalizeTableHeader(value) {
return value
.toLowerCase()
.replace(/`/g, '')
.replace(/[^a-z0-9]+/g, '_')
.replace(/^_+|_+$/g, '');
}
function getPhaseStatuses(content) {
const block = getSectionBlock(content, 'Phase / pass table');
const statuses = [];
for (const line of block.split(NEWLINE_PATTERN)) {
if (!line.trim().startsWith('|')) {
continue;
}
const cells = line
.split('|')
.slice(1, -1)
.map((cell) => cell.trim());
if (
cells.length < 2 ||
TABLE_SEPARATOR_PATTERN.test(cells[0]) ||
PHASE_HEADER_PATTERN.test(cells[0])
) {
continue;
}
statuses.push({
name: cells[0],
value: cells[1],
});
}
return statuses;
}
function findRepoRoot(start) {
let current = path.resolve(start);
while (true) {
const marker = path.join(current, 'AGENTS.md');
if (existsSync(marker)) {
return current;
}
const parent = path.dirname(current);
if (parent === current) {
throw new Error('could not find repo root containing AGENTS.md');
}
current = parent;
}
}
function printHelp() {
console.log(`Usage:
node .agents/skills/autogoal/scripts/check-complete.mjs docs/plans/<goal-plan>.md
Validates the active goal plan before update_goal(status: complete). The check
is mechanical: it proves the checklist, phase table, verification evidence,
reboot status, risks, and any Start Gates / Completion Gates tables are
recorded. It does not replace the goal's named tests, browser proof, source
audit, or artifact verification.`);
}
#!/usr/bin/env node
/** biome-ignore-all lint/suspicious/noConsole: CLI scripts write command output. */
import { existsSync } from 'node:fs';
import { access, mkdir, readFile, readdir, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { initProjectTemplates } from './init-templates.mjs';
const ALLOWED_FLAGS = new Set([
'date',
'force',
'help',
'path',
'slug',
'template',
'ticket',
'title',
'with',
]);
const LIST_FLAGS = new Set(['with']);
const NEWLINE_PATTERN = /\r?\n/;
const LEADING_NEWLINES_PATTERN = /^\n+/;
const PACK_SECTION_NAMES = [
'Start Gates',
'Work Checklist',
'Completion Gates',
];
const PRIMARY_TEMPLATE_SECTION_PATTERN = /^Primary template:\s*$/m;
const TABLE_GATE_HEADER_PATTERN = /^gate$/i;
const SECTION_START_PATTERN = /^[A-Z][A-Za-z /-]+:\s*$/;
const HEADING_PATTERN = /^#{1,6}\s+\S/;
const TABLE_MARKDOWN_SEPARATOR_CELL_PATTERN = /^:?-+:?$/;
const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url));
const SKILL_DIR = path.dirname(SCRIPT_DIR);
const BUILTIN_TEMPLATES_DIR = path.join(SKILL_DIR, 'assets', 'templates');
const args = parseArgs(process.argv.slice(2));
if (args.help) {
printHelp();
process.exit(0);
}
if (args.title) {
const root = findRepoRoot(process.cwd());
await initProjectTemplates(root, { silent: true });
const templatePath = resolveTemplatePath(root, args.template);
const packs = resolvePackPaths(root, args.with ?? []);
const date = args.date ?? new Date().toISOString().slice(0, 10);
const slug = args.slug ?? slugify(args.title);
const fileName = args.ticket
? `${args.ticket}-${slug}.md`
: `${date}-${slug}.md`;
const scratchpadPath = args.path
? path.resolve(root, args.path)
: path.join(root, 'docs', 'plans', fileName);
const taskSourceLink = await resolveTaskSourceLink(root, args.ticket);
let content = await renderTemplate(templatePath, {
createdAt: new Date().toISOString(),
planPath: path.relative(root, scratchpadPath),
taskSourceLink,
title: args.title,
templatePath: path.relative(root, templatePath),
});
const renderedPacks = await Promise.all(
packs.map(async (pack) => ({
...pack,
content: await renderTemplate(pack.path, {
createdAt: new Date().toISOString(),
packName: pack.name,
planPath: path.relative(root, scratchpadPath),
taskSourceLink,
templatePath: path.relative(root, templatePath),
title: args.title,
}),
}))
);
content = insertCompositionMetadata(content, {
packs: renderedPacks,
root,
templatePath,
});
content = mergePackSections(content, renderedPacks);
await mkdir(path.dirname(scratchpadPath), { recursive: true });
if (!args.force && (await exists(scratchpadPath))) {
throw new Error(
`scratchpad already exists: ${path.relative(root, scratchpadPath)} (use --force to overwrite)`
);
}
await writeFile(scratchpadPath, content);
console.log(path.relative(root, scratchpadPath));
} else {
printHelp();
process.exitCode = 1;
}
function parseArgs(argv) {
const parsed = {};
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index];
if (arg === '--help' || arg === '-h') {
parsed.help = true;
continue;
}
if (arg === '--force') {
parsed.force = true;
continue;
}
if (!arg.startsWith('--')) {
throw new Error(`unexpected positional argument: ${arg}`);
}
const rawFlag = arg.slice(2);
const equalsIndex = rawFlag.indexOf('=');
const key = equalsIndex === -1 ? rawFlag : rawFlag.slice(0, equalsIndex);
if (!ALLOWED_FLAGS.has(key)) {
throw new Error(
`unsupported flag --${key}. Generate the static template first, then write goal content into the file.`
);
}
const value =
equalsIndex === -1 ? argv[index + 1] : rawFlag.slice(equalsIndex + 1);
if (equalsIndex === -1) {
index += 1;
}
if (!value || value.startsWith('--')) {
throw new Error(`missing value for --${key}`);
}
const parsedKey = toCamelCase(key);
if (LIST_FLAGS.has(key)) {
parsed[parsedKey] = [
...(parsed[parsedKey] ?? []),
...parseListValue(value),
];
} else {
parsed[parsedKey] = value;
}
}
return parsed;
}
async function renderTemplate(templatePath, values) {
const template = await readFile(templatePath, 'utf8');
return template
.replaceAll('{{TITLE}}', values.title)
.replaceAll('{{PLAN_PATH}}', values.planPath)
.replaceAll('{{PACK_NAME}}', values.packName ?? '')
.replaceAll('{{TASK_SOURCE_LINK}}', values.taskSourceLink ?? 'pending')
.replaceAll('{{CREATED_AT}}', values.createdAt)
.replaceAll('{{TEMPLATE_PATH}}', values.templatePath);
}
async function resolveTaskSourceLink(root, ticket) {
if (!ticket) {
return 'pending';
}
if (/^https?:\/\//i.test(ticket)) {
return ticket;
}
const linearWorkspaceSlug = await findLinearWorkspaceSlug(root);
if (linearWorkspaceSlug) {
return `[${ticket}](https://linear.app/${linearWorkspaceSlug}/issue/${ticket})`;
}
return ticket;
}
async function findLinearWorkspaceSlug(root) {
for (const relativePath of [
'docs/plans/templates/task.md',
'.agents/AGENTS.md',
'README.md',
]) {
const slug = await readLinearWorkspaceSlug(path.join(root, relativePath));
if (slug) {
return slug;
}
}
return findLinearWorkspaceSlugInDocs(path.join(root, 'docs', 'plans'));
}
async function findLinearWorkspaceSlugInDocs(dir, state = { readCount: 0 }) {
if (state.readCount >= 200) {
return '';
}
let entries;
try {
entries = await readdir(dir, { withFileTypes: true });
} catch {
return '';
}
for (const entry of entries) {
if (state.readCount >= 200) {
return '';
}
const entryPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
const slug = await findLinearWorkspaceSlugInDocs(entryPath, state);
if (slug) {
return slug;
}
continue;
}
if (!entry.name.endsWith('.md')) {
continue;
}
state.readCount += 1;
const slug = await readLinearWorkspaceSlug(entryPath);
if (slug) {
return slug;
}
}
return '';
}
async function readLinearWorkspaceSlug(filePath) {
try {
const content = await readFile(filePath, 'utf8');
const match = content.match(/https:\/\/linear\.app\/([^/\s)]+)\/issue\//);
return match?.[1] ?? '';
} catch {
return '';
}
}
function findRepoRoot(start) {
let current = path.resolve(start);
while (true) {
if (path.basename(current) !== '.tmp') {
const marker = path.join(current, 'AGENTS.md');
if (existsSync(marker)) {
return current;
}
}
const parent = path.dirname(current);
if (parent === current) {
throw new Error('could not find repo root containing AGENTS.md');
}
current = parent;
}
}
async function exists(filePath) {
try {
await access(filePath);
return true;
} catch {
return false;
}
}
function slugify(value) {
const slug = value
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '')
.slice(0, 80);
return slug || 'goal';
}
function resolveTemplatePath(root, template) {
if (!template) {
return resolveExistingTemplate(root, 'goal');
}
const candidates = [];
if (
template.includes('/') ||
template.includes('\\') ||
template.endsWith('.md')
) {
candidates.push(path.resolve(root, template));
} else {
candidates.push(
path.join(root, 'docs', 'plans', 'templates', `${template}.md`),
path.join(root, 'docs', 'plans', 'templates', template, 'goal.md'),
path.join(BUILTIN_TEMPLATES_DIR, `${template}.md`),
path.join(BUILTIN_TEMPLATES_DIR, template, 'goal.md')
);
}
const found = candidates.find((candidate) => existsSync(candidate));
if (found) {
return found;
}
throw new Error(
`could not resolve goal template "${template}". Tried: ${candidates
.map((candidate) => path.relative(root, candidate))
.join(', ')}`
);
}
function resolveExistingTemplate(root, template) {
return resolveTemplatePath(root, template);
}
function resolvePackPaths(root, packNames) {
const uniquePackNames = [...new Set(packNames.filter(Boolean))];
return uniquePackNames.map((packName) => {
const candidates =
packName.includes('/') ||
packName.includes('\\') ||
packName.endsWith('.md')
? [path.resolve(root, packName)]
: [
path.join(
root,
'docs',
'plans',
'templates',
'packs',
`${packName}.md`
),
path.join(BUILTIN_TEMPLATES_DIR, 'packs', `${packName}.md`),
];
const found = candidates.find((candidate) => existsSync(candidate));
if (found) {
return {
name: path.basename(packName, '.md'),
path: found,
};
}
throw new Error(
`could not resolve goal pack "${packName}". Tried: ${candidates
.map((candidate) => path.relative(root, candidate))
.join(', ')}`
);
});
}
function insertCompositionMetadata(content, { packs, root, templatePath }) {
if (PRIMARY_TEMPLATE_SECTION_PATTERN.test(content)) {
return content;
}
const primaryTemplate = path.relative(root, templatePath);
const appliedPacks =
packs.length === 0
? '- none'
: packs
.map((pack) => `- ${pack.name} (${path.relative(root, pack.path)})`)
.join('\n');
const metadata = `Primary template:
${primaryTemplate}
Applied packs:
${appliedPacks}`;
return insertAfterSection(content, 'Template', metadata);
}
function mergePackSections(content, packs) {
let merged = content;
for (const sectionName of PACK_SECTION_NAMES) {
const entries = packs.flatMap((pack) =>
getPackEntries(pack.content, sectionName)
);
if (entries.length > 0) {
merged = appendSectionEntries(merged, sectionName, entries);
}
}
return merged;
}
function getPackEntries(packContent, sectionName) {
const block = getSectionBlock(packContent, sectionName);
if (!block) {
return [];
}
if (sectionName === 'Work Checklist') {
return getChecklistEntries(block);
}
return block.split(NEWLINE_PATTERN).filter((line) => {
const trimmed = line.trim();
if (!trimmed.startsWith('|')) {
return false;
}
const cells = getTableCells(trimmed);
return (
cells.length > 0 &&
!isTableSeparatorRow(cells) &&
!isTableHeaderRow(cells)
);
});
}
function getChecklistEntries(block) {
const lines = block.split(NEWLINE_PATTERN);
const entries = [];
for (let index = 0; index < lines.length; index += 1) {
const line = lines[index];
if (!line.startsWith('- [') && !line.startsWith('- [x]')) {
continue;
}
entries.push(line);
for (let next = index + 1; next < lines.length; next += 1) {
const continuation = lines[next];
if (continuation.startsWith(' ') || continuation.startsWith(' ')) {
entries.push(continuation);
index = next;
} else {
break;
}
}
}
return entries;
}
function appendSectionEntries(content, sectionName, entries) {
const section = findSectionRange(content, sectionName);
if (!section) {
return `${content.trimEnd()}
${sectionName}:
${entries.join('\n')}
`;
}
const lines = content.split(NEWLINE_PATTERN);
const before = lines.slice(0, section.end).join('\n').trimEnd();
const after = lines
.slice(section.end)
.join('\n')
.replace(LEADING_NEWLINES_PATTERN, '');
return `${before}
${entries.join('\n')}
${after}`;
}
function insertAfterSection(content, sectionName, insertion) {
const section = findSectionRange(content, sectionName);
if (!section) {
return `${content.trimEnd()}
${insertion}
`;
}
const lines = content.split(NEWLINE_PATTERN);
const before = lines.slice(0, section.end).join('\n').trimEnd();
const after = lines
.slice(section.end)
.join('\n')
.replace(LEADING_NEWLINES_PATTERN, '');
return `${before}
${insertion}
${after}`;
}
function findSectionRange(content, sectionName) {
const lines = content.split(NEWLINE_PATTERN);
const start = lines.findIndex((line) => line.trim() === `${sectionName}:`);
if (start === -1) {
return null;
}
let end = lines.length;
for (let index = start + 1; index < lines.length; index += 1) {
if (isSectionStart(lines[index])) {
end = index;
break;
}
}
return { end, start };
}
function getSectionBlock(content, sectionName) {
const range = findSectionRange(content, sectionName);
if (!range) {
return '';
}
return content
.split(NEWLINE_PATTERN)
.slice(range.start + 1, range.end)
.join('\n')
.trim();
}
function isSectionStart(line) {
return HEADING_PATTERN.test(line) || SECTION_START_PATTERN.test(line.trim());
}
function getTableCells(line) {
return line
.split('|')
.slice(1, -1)
.map((cell) => cell.trim());
}
function isTableSeparatorRow(cells) {
return cells.every((cell) =>
TABLE_MARKDOWN_SEPARATOR_CELL_PATTERN.test(cell)
);
}
function isTableHeaderRow(cells) {
return cells.some((cell) => TABLE_GATE_HEADER_PATTERN.test(cell));
}
function parseListValue(value) {
return value
.split(',')
.map((item) => item.trim())
.filter(Boolean);
}
function toCamelCase(value) {
return value.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
}
function printHelp() {
console.log(`Usage:
node .agents/skills/autogoal/scripts/create-goal-scratchpad.mjs \\
--title "Short goal title" \\
[--slug short-slug] \\
[--template "skill-name or template path"] \\
[--with "pack-name"] \\
[--ticket "4510"] \\
[--date YYYY-MM-DD] \\
[--path docs/plans/custom.md] \\
[--force]
Creates docs/plans/YYYY-MM-DD-<slug>.md, or docs/plans/<ticket>-<slug>.md when --ticket is provided.
This command only creates the static plan shell. Do not pass objective,
threshold, verification, constraints, boundaries, or blocked condition through
the CLI. After creation, edit the generated docs/plans file and fill the
template fields there.
Before creating a plan, missing generic templates are initialized under
docs/plans/templates/. Use --template task to resolve project templates first,
then built-in templates under .agents/skills/autogoal/assets/templates/.
Use --with docs --with browser to materialize pack rows from project packs
first, then built-in packs. Runtime goal plans live under docs/plans/.`);
}
#!/usr/bin/env node
/** biome-ignore-all lint/suspicious/noConsole: CLI scripts write command output. */
import { existsSync } from 'node:fs';
import { access, mkdir, readFile, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { initProjectTemplates } from './init-templates.mjs';
const SAFE_SKILL_NAME_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url));
const SKILL_DIR = path.dirname(SCRIPT_DIR);
const BUILTIN_TEMPLATES_DIR = path.join(SKILL_DIR, 'assets', 'templates');
const args = parseArgs(process.argv.slice(2));
if (args.help) {
printHelp();
process.exit(0);
}
const root = findRepoRoot(process.cwd());
const targetPath = resolveTargetPath(root, args);
if (!targetPath && !args.print) {
printHelp();
process.exitCode = 1;
} else if (args.print) {
const sourcePath = resolveSourceTemplate(root, args.from);
const content = await readFile(sourcePath, 'utf8');
process.stdout.write(content);
} else {
await initProjectTemplates(root, { silent: true });
const sourcePath = resolveSourceTemplate(root, args.from);
const content = await readFile(sourcePath, 'utf8');
await mkdir(path.dirname(targetPath), { recursive: true });
if (!args.force && (await exists(targetPath))) {
throw new Error(
`goal template already exists: ${path.relative(root, targetPath)} (use --force to overwrite)`
);
}
await writeFile(targetPath, content);
console.log(path.relative(root, targetPath));
}
function parseArgs(argv) {
const parsed = {};
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index];
if (arg === '--help' || arg === '-h') {
parsed.help = true;
continue;
}
if (arg === '--force') {
parsed.force = true;
continue;
}
if (arg === '--print') {
parsed.print = true;
continue;
}
if (!arg.startsWith('--')) {
throw new Error(`unexpected positional argument: ${arg}`);
}
const rawFlag = arg.slice(2);
const equalsIndex = rawFlag.indexOf('=');
const key = equalsIndex === -1 ? rawFlag : rawFlag.slice(0, equalsIndex);
const value =
equalsIndex === -1 ? argv[index + 1] : rawFlag.slice(equalsIndex + 1);
if (equalsIndex === -1) {
index += 1;
}
if (!value || value.startsWith('--')) {
throw new Error(`missing value for --${key}`);
}
parsed[toCamelCase(key)] = value;
}
return parsed;
}
function resolveTargetPath(root, args) {
if (args.path) {
return path.resolve(root, args.path);
}
if (args.skill) {
assertSafeSkillName(args.skill);
return path.join(root, 'docs', 'plans', 'templates', `${args.skill}.md`);
}
return;
}
function resolveSourceTemplate(root, template) {
if (!template) {
return resolveSourceTemplate(root, 'goal');
}
const candidates = [];
if (
template.includes('/') ||
template.includes('\\') ||
template.endsWith('.md')
) {
candidates.push(path.resolve(root, template));
} else {
candidates.push(
path.join(root, 'docs', 'plans', 'templates', `${template}.md`),
path.join(root, 'docs', 'plans', 'templates', template, 'goal.md'),
path.join(BUILTIN_TEMPLATES_DIR, `${template}.md`),
path.join(BUILTIN_TEMPLATES_DIR, template, 'goal.md')
);
}
const found = candidates.find((candidate) => existsSync(candidate));
if (found) {
return found;
}
throw new Error(
`could not resolve source template "${template}". Tried: ${candidates
.map((candidate) => path.relative(root, candidate))
.join(', ')}`
);
}
function assertSafeSkillName(skill) {
if (!SAFE_SKILL_NAME_PATTERN.test(skill)) {
throw new Error(`unsafe skill name: ${skill}`);
}
}
function findRepoRoot(start) {
let current = path.resolve(start);
while (true) {
const marker = path.join(current, 'AGENTS.md');
if (existsSync(marker)) {
return current;
}
const parent = path.dirname(current);
if (parent === current) {
throw new Error('could not find repo root containing AGENTS.md');
}
current = parent;
}
}
async function exists(filePath) {
try {
await access(filePath);
return true;
} catch {
return false;
}
}
function toCamelCase(value) {
return value.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
}
function printHelp() {
console.log(`Usage:
node .agents/skills/autogoal/scripts/create-goal-template.mjs \\
--skill package-release-audit \\
[--from goal] \\
[--force]
node .agents/skills/autogoal/scripts/create-goal-template.mjs \\
--path docs/plans/templates/custom.md
Creates a project-owned reusable goal template under docs/plans/templates/.
Before writing, missing generic templates are initialized under docs/plans/templates/.
Source templates resolve from project templates first, then built-in autogoal assets.
Runtime goal plans still go in docs/plans via create-goal-scratchpad.mjs.`);
}
#!/usr/bin/env node
/** biome-ignore-all lint/suspicious/noConsole: CLI scripts write command output. */
import { existsSync } from 'node:fs';
import { mkdir, readFile, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url));
const SKILL_DIR = path.dirname(SCRIPT_DIR);
const BUILTIN_TEMPLATES_DIR = path.join(SKILL_DIR, 'assets', 'templates');
const TEMPLATE_FILES = [
'goal.md',
'task.md',
'docs.md',
'major-task.md',
'goal-repair.md',
'packs/agent-native.md',
'packs/browser.md',
'packs/docs.md',
'packs/package-api.md',
];
if (isMainModule()) {
const args = parseArgs(process.argv.slice(2));
if (args.help) {
printHelp();
process.exit(0);
}
const root = findRepoRoot(process.cwd());
const result = await initProjectTemplates(root, {
force: args.force,
silent: false,
});
if (result.created.length === 0 && result.updated.length === 0) {
console.log('autogoal templates already initialized');
}
}
export async function initProjectTemplates(root, options = {}) {
const force = options.force === true;
const silent = options.silent === true;
const created = [];
const skipped = [];
const updated = [];
for (const relativePath of TEMPLATE_FILES) {
const sourcePath = path.join(BUILTIN_TEMPLATES_DIR, relativePath);
const targetPath = path.join(
root,
'docs',
'plans',
'templates',
relativePath
);
if (!existsSync(sourcePath)) {
throw new Error(`missing built-in autogoal template: ${sourcePath}`);
}
const targetExists = existsSync(targetPath);
if (!force && targetExists) {
skipped.push(path.relative(root, targetPath));
continue;
}
await mkdir(path.dirname(targetPath), { recursive: true });
await writeFile(targetPath, await readFile(sourcePath, 'utf8'));
if (targetExists) {
updated.push(path.relative(root, targetPath));
} else {
created.push(path.relative(root, targetPath));
}
}
if (!silent) {
for (const file of created) {
console.log(`created ${file}`);
}
for (const file of updated) {
console.log(`updated ${file}`);
}
for (const file of skipped) {
console.log(`kept ${file}`);
}
}
return { created, skipped, updated };
}
function parseArgs(argv) {
const parsed = {};
for (const arg of argv) {
if (arg === '--help' || arg === '-h') {
parsed.help = true;
continue;
}
if (arg === '--force') {
parsed.force = true;
continue;
}
throw new Error(`unsupported argument: ${arg}`);
}
return parsed;
}
function findRepoRoot(start) {
let current = path.resolve(start);
while (true) {
const marker = path.join(current, 'AGENTS.md');
if (existsSync(marker)) {
return current;
}
const parent = path.dirname(current);
if (parent === current) {
throw new Error('could not find repo root containing AGENTS.md');
}
current = parent;
}
}
function isMainModule() {
return fileURLToPath(import.meta.url) === path.resolve(process.argv[1] ?? '');
}
function printHelp() {
console.log(`Usage:
node .agents/skills/autogoal/scripts/init-templates.mjs [--force]
Seeds generic autogoal templates into docs/plans/templates/.
Existing files are kept unless --force is passed.
Project-specific templates stay in docs/plans/templates/ and are never moved.`);
}