Task YAML is the trusted local input that tells Galley what to execute, where to execute it, and how to judge completion. Repository-wide PR behavior belongs in environment.yaml.
Use the plugin skill for normal authoring. This document is the reference for reviewing or hand-writing a task file.
This template contains author-owned fields. Galley adds fixed AFK defaults and lifecycle state during validation and execution.
id: "task-20260509-example"
goal: "Implement the requested repository change with evidence."
acceptance_criteria:
- id: "AC1"
text: "When the requested behavior is exercised, the observable result matches the request."
verification: "A focused check or test demonstrates the behavior."
status: "pending"
scope:
cwd: "/path/to/repo"
allowed_paths:
- "."
forbidden_paths:
- ".env"
- ".env.local"
permission: "sandbox-full-access"
execution_policy:
loop_budget: 10
timeout_ms: 3600000
worktree:
branch: "agent/task-20260509-example"
path: "../repo.worktrees/task-20260509-example"
executor:
cli: "claude"
effort: "high"
preflight:
acceptance_skeleton:
enabled: false
decisions: []
risks: []Validate before queueing:
galley task validate ./TASK.yamlQueue after review:
galley task queue ./TASK.yaml --reason "queue for daemon"id: stable task identifier. Use letters, numbers, dot, underscore, and dash.mode: optional; defaults toafk.status: optional for authors; defaults todraftbefore validation, display, and queue eligibility. Queueing persistsqueuedthrough the normal transition.goal: concise objective for the work.acceptance_criteria[]: observable completion requirements with stable IDs such asAC1.files[]: optional user-supplied files to place in the execution workspace.scope: repository path, expected implementation paths, protected paths, and permission level.execution_policy: author-chosen attempt budget and timeout only (loop_budget,timeout_ms).worktree: isolated branch and sibling worktree location.enableddefaults to true for AFK; authors setbranchandpath.executor: optional overrides for CLI, model, and effort. Settingclimakes the task's model and effort authoritative for the run.preflight.acceptance_skeleton.enabled: optional boolean that selects the fixed skeleton preflight flow.decisions,risks: author and executor notes.supervisor,attempts,verification,pr: daemon-owned runtime state populated during lifecycle transitions. An attempt that ended in an executor interruption recordssupervisor_verdict: not_reviewedand an executor-phaseerrorwith the retained provider detail; see Troubleshooting.
execution_policy.loop_budget: non-negative attempt count;0means unlimited. Omitted values default to10.execution_policy.timeout_ms: positive per-attempt timeout in milliseconds.- Galley fixes the AFK decision policy at
choose-smallest-reversible. - Destructive-operation, missing-secret, and external-service blockers remain executor results; task YAML has no blocker switches.
executor: optional. A task that setsexecutor.cliruns with the task'smodelandeffortexactly as authored; omitted or empty values stay empty and delegate to the selected provider CLI's own defaults, soenvironment.yamlvalues for another provider never cross into a task-selected CLI. When the task omitsexecutor.cli, eachcli,model, andeffortfield resolves from the task, then currentenvironment.yaml. Onlyclihas a built-in fallback (claude). Environment values remain runtime-only.executor.cli: selectsclaude,codex,glm,grok, orkimi. GLM and Kimi use theclaudeCLI; Grok uses the logged-ingrokCLI.executor.model: optional model override passed unchanged to the effective executor CLI.executor.effort: optional effort hint. Claude,glm, andkimiacceptlow,medium,high,xhigh, andmax; Codex also acceptsminimal; Grok also acceptsnoneandminimal. Resolution follows the executor rule above; invalid provider combinations fail before executor roles run.- Prompt transport is Galley-owned. Task YAML no longer accepts
executor.prompt_profileorexecutor.prompt_mode; older files that still include those keys are ignored by the unknown-field-tolerant decoder.
| Permission | Meaning |
|---|---|
read-only |
Read, inspect, and review only. |
edit |
Normal implementation work. File edits are allowed, but broad authority is not granted. |
sandbox-full-access |
Broad operations are allowed inside an isolated worktree or sandbox. |
For AFK implementation tasks, prefer sandbox-full-access with an isolated worktree. Use read-only for investigation or review tasks.
scope.permission is an authority intent passed into the executor workflow. Actual isolation comes from the worktree, scope.forbidden_paths, the executor CLI sandbox, and local OS controls.
scope.allowed_paths is the expected implementation scope and review baseline. Executors should stay inside it when the task can be completed there, but a required acceptance criterion or pending revision request may justify a minimal outside-allowed change. Those changes are reported as scope expansions for supervisor and PR review. Allowed and reported expansion paths use case-sensitive POSIX-style worktree-relative clean paths. scope.forbidden_paths is a conservative case-insensitive protected boundary so casing changes cannot bypass it.
Use files[] for specification documents, work plans, screenshots, data samples, or other context the executor needs inside the worktree.
files:
- source: "/tmp/spec.md"
destination: "docs/input/spec.md"
description: "Feature specification"
commit: falsesourcemay be absolute or relative to the task YAML before queueing.destinationis relative to the execution workspace and must be insidescope.allowed_paths.commit: falsemarks context-only input. Galley removes those files before commit/PR finalization.
worktree.path is relative to scope.cwd and must point to a sibling path outside the source repository. galley task validate rejects absolute paths, deep parent traversal, and paths that do not start with ../.
worktree:
branch: "agent/task-20260509-example"
path: "../repo.worktrees/task-20260509-example"Galley enables this isolated worktree for every AFK task, keeping the source repository clean.
Write ACs as externally observable obligations. Good ACs name the behavior, the relevant boundary, and the evidence expected.
Use verification for evidence guidance. Required runnable checks belong in the quality profile; task-level verification explains why a check proves the AC.
Example:
- id: "AC1"
text: "When `galley task show TASK_ID` is run for a failed task, the output includes the latest failure reason and supervisor verdict."
verification: "Create or use a failed task fixture and confirm `galley task show` prints both fields."
status: "pending"preflight.acceptance_skeleton.enabled controls AC-linked test skeleton creation before the first executor attempt.
preflight:
acceptance_skeleton:
enabled: falseEnable it when an integration, cross-layer, or E2E acceptance path needs a concrete file before implementation. Leave it disabled when focused tests or required checks already define the evidence path.
When enabled:
- write paths are always
scope.allowed_paths(and remain outsidescope.forbidden_paths) - every AC must produce a skeleton output or an explicit
no_skeletonsreason - the daemon writes runtime
outputs[]back to the running task
When a task reuses its existing worktree after a requeue, Galley reuses previously completed setup and acceptance-skeleton evidence instead of running those phases again. A new worktree, or a phase with no prior successful result, still runs normal preflight.
The skeleton creator follows executor.cli and reuses executor.model and executor.effort. The daemon supervisor backend controls only review.
Required quality checks remain executor evidence for supervisor review; the skeleton stage does not add a second command-matching gate.
execution_policy.loop_budget is the maximum number of executor attempts. It accepts an integer greater than or equal to 0; 0 means unlimited.
For AFK implementation tasks, 10 is the recommended default. Values below 5 are best reserved for intentionally short, low-cost runs because they can stop useful revision loops too early. Use 0 only when the user explicitly wants an unbounded run.
Task files move through the daemon root:
tasks/queued/
tasks/running/
tasks/done/
tasks/failed/
tasks/archived/
Terminal state remains in the YAML. Use:
galley task list
galley task show TASK_ID
galley task requeue TASK_ID --reason "retry after transient failure"See Troubleshooting for the meaning of each terminal status and when to requeue instead of creating a new task.
The tolerant decoder loads removed authoring keys (execution_policy.afk_decision_policy, execution_policy.stop_on_*, and acceptance-skeleton mode, required, and allowed_paths), then drops them on save. Runtime lifecycle fields remain available to the daemon.