Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Plan Reference

A plan lives at .dgov/plans/<name>/ as a tree of TOML files. dgov compile turns the tree into a normalized _compiled.toml, and dgov run <plan-dir> recompiles current source before execution.

You can author plans by hand or generate them with dgov plan create "<goal>". Either way, the schema below applies.

Tree layout

.dgov/plans/refactor-api/
├── _root.toml         # plan-level metadata
├── _compiled.toml     # emitted by `dgov compile` (do not hand-edit)
└── tasks/
    ├── _example.toml  # scaffold (ignored — underscore-prefixed)
    └── main.toml      # one or more [tasks.<slug>] entries

A minimal example:

# _root.toml
[plan]
name = "refactor-api"
summary = "Refactor the API surface"
sections = ["tasks"]
 
# tasks/main.toml
[tasks.validate]
summary = "Inspect current endpoints"
prompt = "Review src/api.py and document the existing endpoint structure"
commit_message = "docs: endpoint inventory"
files.read = ["src/api.py"]
files.create = ["docs/api-inventory.md"]
 
[tasks.migrate]
summary = "Migrate to typed response schema"
prompt = "Refactor src/api.py to return the typed schema in src/api/types.py"
depends_on = ["validate"]
commit_message = "refactor: typed response schema"
files.edit = ["src/api.py"]
files.create = ["src/api/types.py"]

_root.toml [plan] section

FieldTypeRequiredDefaultDescription
namestringYesUnique plan identifier
summarystringNo""One-line plan summary
sectionsarray of stringsYesTop-level section directories to compile
default_agentstringNoproject defaultPlan-level model override
default_providerstringNoproject defaultPlan-level provider override

sections is the list of immediate subdirectories that dgov compile walks. Files prefixed with _ are ignored — use that prefix for scaffolds, notes, or anything you do not want compiled.

[tasks.<slug>] section

Tasks live inside section TOMLs such as tasks/main.toml.

FieldTypeRequiredDefaultDescription
slugstringYes (implicit)Task identifier (from the table key)
summarystringYesShort description used by logs and UI
promptstringWorker/researcher: YesInstructions sent to the worker
prompt_filestringNoPrompt text file, resolved relative to the compiled plan file
agentstringNoplan/project defaultModel/router override for this task
providerstringNoplan/project defaultProvider endpoint override for this task
depends_onarray of stringsNo[]Slugs that must complete first
commit_messagestringYesGit commit message on success
timeout_sintegerNo900Seconds before the task aborts
iteration_budgetintegerNoproject configPer-task worker model-turn budget
test_cmdstringNoproject configTask-specific settlement test command
sop_mappingarray of stringsNocompiler-assignedSOP names assigned during compile
rolestringNoworkerOne of worker, researcher, reviewer

Slug grammar: ^[A-Za-z0-9_-]+$. Compiled unit IDs are <section>/<file-stem>.<slug> (e.g. tasks/main.add-feature).

Task roles

RoleWorktreeWrites?SettlementMerges?
workeryesyesfull settlement gatesyes, on pass
researcheryesno (read-only)auto-pass reviewno
revieweryesno (read-only)auto-pass reviewno

reviewer tasks receive an auto-generated prompt with dependency diffs from the deploy log. The verdict goes into the done summary.

File claims [tasks.<slug>.files]

File claims enforce isolation between concurrent tasks. The kernel rejects plans where independent tasks (no dependency edge) claim overlapping paths.

FieldTypeDescription
createarray of stringsFiles the task will create
editarray of stringsFiles the task will modify
deletearray of stringsFiles the task will remove
readarray of stringsFiles the task references but does not write
toucharray of stringsFlat claim list (equivalent to files = [...])

Examples

[tasks.add_feature]
summary = "Add the auth module"
prompt = "Create auth.py with login/logout functions"
files.create = ["src/auth.py"]
 
[tasks.fix_bug]
summary = "Fix the type error in utils"
prompt = "Update the type annotation in utils.py line 42"
files.edit = ["src/utils.py"]
 
[tasks.cleanup]
summary = "Remove the deprecated module"
prompt = "Delete src/legacy_helpers.py"
files.delete = ["src/legacy_helpers.py"]
 
[tasks.audit]
summary = "Inventory the API surface"
prompt = "Read src/api.py and src/models.py, write findings to audit.md"
files.read = ["src/api.py", "src/models.py"]
files.create = ["audit.md"]

Flat shorthand

For tasks that only need to claim files without specifying the operation, use files = [...]. The shorthand is equivalent to files.touch.

[tasks.generate_config]
summary = "Generate the default config"
prompt = "Write a default config.json"
files = ["config.json"]

Prefer explicit create/edit/delete/read when the operation matters for review. Use the shorthand when it is unambiguous from context.

File-claim isolation

File claims are the foundation of deterministic concurrency:

  1. Declaration. Every task declares the files it touches.
  2. Validation. The kernel checks for conflicts at compile time.
  3. Enforcement. Independent tasks with overlapping paths fail validation.

The kernel only rejects overlap between independent tasks. Dependent tasks (B depends_on A) may touch the same files because they execute sequentially.

Invalid (concurrent overlap)

[tasks.a]
summary = "Update config"
prompt = "Change port to 8080"
files.edit = ["config.yaml"]
 
[tasks.b]
summary = "Also update config"
prompt = "Change port to 9090"
files.edit = ["config.yaml"]   # ERROR: no dependency edge to tasks.a

Valid (sequential overlap)

[tasks.a]
summary = "Update config"
files.edit = ["config.yaml"]
 
[tasks.b]
summary = "Read the updated config"
files.read = ["config.yaml"]
depends_on = ["a"]             # OK: explicit ordering

Path overlap rules

A path conflicts if it is identical to or a parent of another claimed path:

  • src/main.py overlaps src/main.py
  • src/ overlaps src/main.py
  • config.yaml does not overlap other.yaml

Full example

[plan]
name = "payment-gateway-refactor"
summary = "Migrate payment integrations to a typed schema"
sections = ["tasks"]
 
# === Phase 1: Analysis ===
 
[tasks.audit]
summary = "Audit current payment code"
prompt = """
Review src/payments/. Identify:
1. External API call sites
2. Error handling gaps
3. Missing type annotations
 
Write findings to audit_report.md.
"""
agent = "senior-reviewer"
commit_message = "docs: payment system audit"
timeout_s = 1200
files.read = [
  "src/payments/",
  "src/payments/stripe.py",
  "src/payments/paypal.py",
]
files.create = ["audit_report.md"]
 
# === Phase 2: Design ===
 
[tasks.design_schema]
summary = "Design the payment type schema"
prompt = "Using audit_report.md, design PaymentMethod and PaymentResult"
depends_on = ["audit"]
commit_message = "design: payment type schema"
files.read = ["audit_report.md"]
files.create = ["src/payments/types.py"]
 
# === Phase 3: Implementation ===
 
[tasks.refactor_stripe]
summary = "Migrate the Stripe integration"
prompt = "Refactor src/payments/stripe.py to use src/payments/types.py"
depends_on = ["design_schema"]
commit_message = "refactor: stripe → typed schema"
files.edit = ["src/payments/stripe.py"]
files.read = ["src/payments/types.py"]
 
[tasks.refactor_paypal]
summary = "Migrate the PayPal integration"
prompt = "Refactor src/payments/paypal.py to use src/payments/types.py"
depends_on = ["design_schema"]
commit_message = "refactor: paypal → typed schema"
files.edit = ["src/payments/paypal.py"]
files.read = ["src/payments/types.py"]
 
# === Phase 4: Cleanup ===
 
[tasks.remove_legacy]
summary = "Remove the legacy payment module"
prompt = "Delete src/payments/legacy.py after verifying no imports remain"
depends_on = ["refactor_stripe", "refactor_paypal"]
commit_message = "chore: remove legacy payment module"
files.read = ["src/payments/stripe.py", "src/payments/paypal.py"]
files.delete = ["src/payments/legacy.py"]

Validation

Validate a compiled plan without executing:

dgov validate .dgov/plans/payment-gateway-refactor/_compiled.toml

validate checks:

  • TOML syntax and schema
  • Every depends_on references an existing slug
  • No file-claim conflicts between independent tasks
  • Every task's agent resolves through the chain
  • Every selected provider must exist in .dgov/project.toml before dgov run