Task file format: parallel flag and story link¶
This document describes the per-task fields the planner sets so the orchestrator can schedule parallel batches and roll back at the user-story level. See also orchestration/task-dag.md for the DAG walker and CLI.
Fields¶
| Field | Default | Meaning |
|---|---|---|
parallel_safe | false | Task may run concurrently with other parallel-safe tasks whose dependencies are also satisfied. Absence is treated as serial-only. |
story_id | null | User-story slice this task belongs to. All tasks sharing a story_id form one rollback unit. |
Both fields are persisted on the Task dataclass and round-trip through Task.from_dict.
Required backlog file format¶
Files under .sdd/backlog/open/ (and .sdd/backlog/issues/) must be one of two shapes so the orchestrator can extract a title and route the task:
- YAML frontmatter - a
---delimited block at the top of the file (see YAML frontmatter below). - Markdown fields - a
#heading for the title plus optional**Role:**/**Priority:**/**Scope:**/**Complexity:**lines.
A file that is neither (for example a plain YAML file with no --- block and no # heading) cannot be parsed as a ticket. It is skipped rather than spawned, and bernstein --dry-run prints a warning naming the file so the gap is visible instead of silent.
YAML frontmatter (Ticket Format v1)¶
---
id: T001
title: Add YAML loader
role: backend
parallel_safe: true
story_id: US1
context_files:
- docs/adr/0007-retries.md
---
Context files¶
context_files names the reference files (worktree-relative) the worker on this task should read. The declaration reaches the worker: the parser carries it in the task payload under metadata["context_files"], the stored task keeps it, and at spawn the orchestrator lists the files in the worker's task-specific CLAUDE.md.
The attachment is recorded, not just copied. At dispatch each declared path is resolved in declared order against the worker's worktree and content-addressed as (path, order, sha256); the resolved set is recorded in the run journal as a context.files_attached event next to agent_spawned, so which reference material the worker saw - at which content - is answerable offline, and a verifier can recompute the digests from the files and match. A path that does not resolve keeps its position in the record with a reason code (missing, is_directory, unreadable, outside_root, or invalid for a path the filesystem cannot represent at all) and a log warning instead of being silently skipped; it does not abort the spawn. Crash-recovery resumes record the same event, re-resolved against the preserved worktree, so a resumed worker's context is pinned as it exists after the crashed agent's edits. Tickets that declare nothing produce byte-identical payloads and records as before.
ticket_type and affected_paths ride in the same payload metadata mapping when set. depends_on in frontmatter still refers to ticket ids and is not forwarded to the server (task-id resolution is a separate concern).
Plans declare the same thing at the top level; see architecture/plans.md.
Markdown checkbox DAG¶
For hand-authored multi-task plans, use one checkbox per task:
| Marker | Effect |
|---|---|
[T<id>] | Required identifier. |
[P] | Sets parallel_safe = true. Absence keeps the default serial-only behaviour. |
[US<n>] | Sets story_id to the user-story slice. |
-> T###, T### | Trailing arrow declares inline dependencies. |
Scheduler behaviour¶
The scheduler resolves parallel-safety in this order:
- Declarative wins. If both candidate tasks have
parallel_safeset, the boolean answer is exact: bothTrueallows concurrency; eitherFalseforces serial. - Legacy fallback. Tasks lacking the attribute (older entries from a stale store) fall through to the file-overlap heuristic on
owned_files.
Rollback semantics¶
When every task in a story_id group completes, the orchestrator surfaces "story <id> complete" as a single milestone. A story-scoped revert reverses only the changes attributed to that story id - sibling stories remain intact. Tasks without a story_id participate in milestone reporting individually and are not bundled.
Out of scope¶
- Full DAG dependency editor UI.
- Cross-story dependency inference.