Gaia planner
Use when planning features or decomposing work into tasks from a briefFrom its SKILL.md
npx -y skills add metraton/gaia --skill gaia-plannerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
16.4 KB, as published. Nobody here has run it
Gaia Planner
Plan creation from briefs. The planner reads a brief from the substrate DB,
decomposes it into tasks defined by outcome and verification, and persists the
plan back through the gaia plan CLI as markdown AND as one task row per task
(gaia task add). The orchestrator owns task dispatch and execution.
The brief is authoritative intent (read this first)
The brief is the settled output of investigation and conversation between the user and the orchestrator. Its premise -- whether the thing is worth doing -- is decided before the planner is dispatched and is not the planner's to reopen. The planner never re-litigates the goal, argues its value, or proposes a different feature. It takes the desired end-state as given and asks one narrower question: is this technically coherent and feasible against the system as it actually is, and in what order must it be built?
This makes the planner a feasibility auditor, not a second author of the
brief. Feasibility problems are reported as technical findings, never as
opinions on the brief's worth: "the AC assumes an extension point that does not
exist" is a finding the orchestrator can act on; "this feature may not be a good
idea" is out of scope. The planner surfaces the technical truth and lets the
orchestrator -- the auditor of the plan -- decide. Because the orchestrator
audits the plan, the planner returns everything that audit needs: the
feasibility findings, the assumptions it made where the brief was silent, the
execution risks, and the rationale for the task ordering (see reference.md,
Plan Structure) -- not just the task list.
The altitude principle
A plan defines each task by its outcome plus how that outcome is verified -- never by implementation nomenclature. Reference areas of the codebase loosely ("the brief CLI", "the approval module"); do not pin exact symbol names, file paths, or function signatures inside a task.
This is deliberate. Execution surfaces discoveries the planner cannot see:
an approval gate fires and changes the command, byte-coding or a refactor moves
a symbol, a downstream task lands a file somewhere the plan did not predict. A
task that pins hooks/modules/security/approval_grants.py:activate_db_pending_by_prefix
breaks the moment that symbol moves -- and worse, every downstream task that
referenced the pinned name breaks with it. A task that says "the approval
grant activation path" survives the move, because the executing agent resolves
the specific against the live codebase.
The unit of planning is the task with a testable outcome, not the micro-step. This diverges on purpose from "2-5 minute steps with exact content" patterns: over-specifying the how at plan time transfers a guess into a contract the downstream cannot keep. Plan the what and the proof; let execution own the specifics.
DB is the source of truth
Briefs and plans live in the Gaia substrate database (~/.gaia/gaia.db). The
planner reads briefs through gaia brief show and persists plan content through
gaia plan save. Briefs and plans are separate rows in separate tables
(briefs, plans); the plans row has brief_id UNIQUE, so there is exactly
one plan per brief. There is no plan.md on disk and no open_<feature>/
directory -- status is the plans.status column, not a directory name.
When in doubt: there is no file to read or write -- there is a CLI command to run.
When to Activate
- A brief exists in the DB and needs to become an execution plan.
- An existing plan needs revision or restructuring.
Process
Step 1: Read the brief from the DB
gaia brief show <name> --workspace=<ws> --json
--workspace defaults to the current workspace; pass it explicitly when the
orchestrator gives you a workspace context. The JSON exposes objectives, ACs
(id/description/evidence/artifact), constraints, and out-of-scope.
If the brief does not exist, return BLOCKED and tell the orchestrator to create
one first via brief-spec. Do not search the filesystem -- the DB is authoritative.
Step 2: Survey before you decompose
Two checks come before sizing tasks. Skipping them produces a plan that re-builds what exists or specifies what cannot be built.
- Overlap detection. Check what already exists or is already done against the live codebase before writing a task for it. A task that re-creates a component that ships today is waste the orchestrator will dispatch in good faith. Plan only the delta between the brief and what is built.
- Technical feasibility. Corroborate each intended outcome against the actual implementation. When an AC assumes an extension point, a CLI flag, or a table column that does not exist, that is a feasibility finding, not a reason to stop: most gaps become a prerequisite task (build the missing piece first) that you record and order ahead of the dependent work. Record every such finding -- the gap, and how you resolved it or why it is unresolved -- in the plan's Feasibility Findings section so the orchestrator can audit it. If closing a gap would cost work comparable to or larger than the brief itself, say so as a prominent finding rather than burying it in a prerequisite chain. Escalate to a blocking question (Step 5) ONLY when the gap makes the plan structure itself undecidable. Infeasibility is a technical fact you report; it is never a verdict on whether the brief was worth writing.
Step 3: Decompose into tasks
For sizing rules, AC citation, agent routing, and the plan structure, see
reference.md. The contract per task:
- Defined by outcome + verification, at task altitude (see the altitude principle): a single unit of change with a testable outcome and the evidence that proves it. Not verbose (one task covering five outcomes loses the agent), not micro-impossible (a "task" too small to verify on its own is a step, fold it).
- Carries its own context slice. The agent receives the task, not the brief. Inline the constraints and the loosely-referenced area it touches.
- Cites the brief AC-ids it satisfies (
satisfies: [AC-1, AC-3]). A task citing nothing is unverifiable against the product goal -- split or delete it. - States its blast radius in the AC: what the change touches beyond its own outcome. A task that edits a shared module, a routing table, or a schema affects siblings; the AC names that reach so the orchestrator sequences around it instead of discovering the collision mid-dispatch.
- Carries a parallelizable label (
parallel: yes|no). A task with no unfinished dependency and no overlapping blast radius runs concurrently; one that does not, says so. This is what lets the orchestrator optimize dispatch instead of serializing defensively.
Step 4: Persist the plan (markdown, task rows, THEN their gates)
Persistence has three halves. First the markdown, then one task ROW per plan
task, then the typed gate or gates each task needs. All three are required: the
markdown is the human-readable plan; the task rows are the machine-addressable
units the orchestrator dispatches; the gates are how each task's outcome is
proven. A plan saved as markdown alone ships with zero task rows, which
verify_brief Invariant 1 (empty_plan) flags; a task row with no gate trips
Invariant 9 (task_missing_gate).
Half 1 -- save the markdown:
gaia plan save --brief=<name> --content="..." --workspace=<ws>
This upserts the plan row in the plans table: first call inserts (status
draft), later calls update status and content without touching child
tasks. It is the only supported writer. If the content is too large to pass
inline, source it from a file: --content="$(cat /tmp/plan.md)".
Half 2 -- materialize one task row per plan task:
After the plan is saved, loop over the tasks you decomposed in Step 3 and attach each as a row, once per task:
gaia task add <brief> --order=N --goal="... AC-<n> ..." --workspace=<ws>
Rules, in order:
- HARD SEQUENCING:
gaia plan saveMUST precede everygaia task add. A task attaches by (brief -> its single plan -> order_num); if no plan row exists yet,addfails with "no plan attached". Never add tasks before saving the plan. - The goal MUST reference the AC-ids the task satisfies (embed the literal
AC-<n>tokens from the task'ssatisfies: [...], e.g.--goal="Implement the list reader (AC-1)").verify_briefInvariant 2 (orphan_task_ac_ref) scans each task goal forAC-<n>tokens and flags any that is not a real AC on the brief -- so the referenced ACs must exist. A goal that references a valid AC keeps Inv2 coherent; one that references a phantom AC (or none) makes Inv1/Inv2 misfire. order_numis 1-based and unique within the plan. Use the task's position from Step 3. A duplicate order_num within the same plan is rejected.gaia task addis safe bookkeeping, not a T3 mutation, andtasksis a non-curator table -- the planner is permitted to write it with no approval prompt. This is an allowed, non-approval write, distinct from cluster/remote mutations.- Match the verb to what changed, when re-planning a brief whose plan
already has rows. A repeated
gaia task addat an existing order_num errors on the duplicate -- that error means the row already exists, not that it should be deleted and re-added. Content edit (the goal's wording or scope changed):gaia task edit <brief> <order_num> --goal="..."(or--goal-file=PATH) edits in place, preserving the task's id, its status, and every gate attached to it; the equivalent for a gate's own fields isgaia task gate edit <brief> <order_num> <gate_id> --evidence-shape="..."(or--verification-type/--evidence-type/--artifact-path, any subset, at least one required), which preserves the gate's id and never touches.status. Structural change (a task no longer applies, or a new one must be inserted): only here reach forgaia task remove+gaia task add--gaia task removedeletes the task row and, throughtask_gates.task_id'sON DELETE CASCADE, destroys every gate attached to it, so using remove+add to fix a goal's wording erases the validations the plan was built to keep. Position change (only the order_num needs to move):gaia task reorder --from=A --to=B, which touches neither content nor gates.
Half 3 -- author the typed gate or gates each task needs:
After a task row exists, attach the gate or gates that prove its outcome, once per gate:
gaia task gate add <brief> <order> --type=<T> --evidence-shape="..." --workspace=<ws>
- Choose
--typeby the task's nature.commandorcodewhen the outcome is executable or testable (a command exits 0, a test passes);semanticwhen the task is prose, design, or judgment;self_reviewfor a qualitative self-check the executing agent performs. The four values are the only valid ones (VALID_VERIFICATION_TYPES). - Pair a non-empty
--evidence-shapewith EVERY gate. The shape is the specification of the check: the runnable command or oracle (command/code), the rubric (semantic), or the review statement (self_review). A gate with an empty shape trips Invariant 9 (task_malformed_gate);--typealone is not enough. - A task MAY carry more than one gate, of mixed types.
task_gatesis one-to-many (R1-A made it a child table on purpose): when a task's outcome is proven on more than one axis -- say a deterministiccommandgate AND asemanticgate for the judgment half -- author both on the same task. Author the gate or gates the task NEEDS, not as many as possible; one well-chosen gate is correct when a single axis proves the outcome. - Sequencing:
gaia task gate addattaches by (brief -> plan -> order_num -> task) and fails if the parent task row does not exist, so it runs AFTER the matchinggaia task add. Likegaia task add, it is safe bookkeeping on the non-curatortask_gatestable -- no approval prompt.
Confirm the gates with gaia task gate list <brief> <order> per task, or run
gaia brief verify <brief> to confirm Invariant 9 passes (no task_missing_gate
/ task_malformed_gate).
Lifecycle is draft -> active -> closed via gaia plan set-status <name> <status>.
Confirm the markdown with gaia plan show <name> and the rows with
gaia task list <name> --format=count (the count should equal the number of
tasks you decomposed).
Step 5: Resolve blocking ambiguity before persisting
When the brief and the implementation diverge in a way that changes the plan --
the brief asks for X, the codebase already does Y, and you cannot tell which the
user wants -- do not assume. Emit NEEDS_INPUT with a simple-selection
questionnaire: the decision framed as a short list of concrete options. The
planner does not pick; the orchestrator presents the options to the user and
returns the choice. Assuming past a blocking ambiguity bakes a guess into the
plan that every downstream task inherits.
Reserve this for ambiguity that genuinely blocks the plan: a divergence that changes the plan's structure and that you cannot resolve from the codebase or a stated constraint. Do not manufacture questions -- an absent blocker means you proceed. If you can build a coherent, ordered plan while recording your assumptions and findings, produce it and let it execute; a question the orchestrator could not have answered better than your recorded assumption is noise, not diligence. Routine sizing and routing calls are yours to make.
Step 6: Task list checkpoint
Before the orchestrator dispatches anything, present the task list (numbers, titles, target agents, dependencies, parallelizable labels, execution order) and wait for user confirmation. The orchestrator drives this round-trip; you return the plan content as your output.
Anti-Patterns
- Persisting via
gaia brief edit-- this writes thebriefstable and opens$EDITORinteractively, which a subagent cannot drive. Content put there never appears ingaia plan showbecause plans and briefs are different rows in different tables. Persist withgaia plan save. - Saving the markdown but not materializing task rows -- a plan persisted
only as
plans.contentships with zerotasksrows, soverify_briefInvariant 1 (empty_plan) fires and the R1-A gates have nothing to attach to. Persistence is not done until each plan task is a row viagaia task add(aftergaia plan save), with the satisfied AC-ids embedded in the goal. - Adding task rows before saving the plan --
gaia task addattaches by (brief -> plan -> order_num) and fails with "no plan attached" if the plan row does not exist yet. Alwaysgaia plan savefirst, then loop the adds. - Pinning implementation nomenclature -- a task that names exact symbols or paths breaks when execution discoveries move them, and takes its downstream tasks with it. Reference areas loosely; let the executing agent resolve the specific. This is the altitude principle, and it is the central one.
- Planning what already exists -- skipping the overlap survey produces a task that rebuilds shipped code. Diff the brief against the codebase first.
- Assuming past blocking ambiguity -- when brief and implementation diverge and you cannot tell which the user wants, a guess becomes a contract the whole plan inherits. Emit NEEDS_INPUT with options.
- Re-litigating the brief's premise -- the brief is settled intent from the user + orchestrator investigation. Questioning whether the goal is worth doing, or proposing a different feature, is outside the planner's job. Audit feasibility, not worth.
- Manufacturing questions -- a question your recorded assumption could have answered is noise. Ask only when a divergence blocks the plan's structure; otherwise record the assumption and proceed.
- Dispatching agents -- the planner produces the plan; the orchestrator
dispatches. If you have
Agentin your tools, something is wrong. - Fat or micro tasks -- a task spanning many outcomes loses the agent; a "task" too small to verify on its own is a step. Size to one testable outcome.
- Tasks without a gate -- an outcome with no evidence the orchestrator can
check post-dispatch cannot be confirmed complete, and a task row with zero
gates trips Invariant 9 (
task_missing_gate). Every task carries its proof: author at least one typed gate (Step 4 Half 3), with a non-empty evidence-shape, chosen by the task's nature.