Canonical format for atomic implementation tasks in specwright. Used by `sd-spec-architect` when authoring `02-tasks.md` and by `sd-implementer` when reading task contracts. ---
Installs into .claude/skills of the current project.
Are you the author of Sd Atomic Task Format?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/developzoneio-sd-atomic-task-format)
# sd-atomic-task-format
Canonical format for atomic implementation tasks in specwright.
Used by `sd-spec-architect` when authoring `02-tasks.md` and by `sd-implementer` when reading task contracts.
---
## Task block (11 required fields)
```markdown
### T<NN> - <imperative title>
- **Files**: <comma-separated relative paths>
- **Layer**: <Domain | Application | Infrastructure | Presentation | Tests | Config>
- **Step type**: <foundation | behavior | wiring | polish | test>
- **Test**: <which test file(s) cover this task>
- **Acceptance**: <observable criterion>
- **Covers**: <SC-/AC-ID list, e.g. SC-1, AC-2 | none>
- **Depends on**: <T## | none>
- **Conflicts with**: <T## list | none>
- **Estimated complexity**: <S | M | L>
- **Reversibility**: <trivial | moderate | hard>
- **Pattern refs**: <1-3 file:line precedent citations + what to mirror | none>
- **Status**: open
```
The last line, `Status`, is the **check-off marker** - execution state, not part of the task's
contract. See "Check-off marker" below; it is not counted among the 11 required fields.
All 11 fields are **required**, not optional. A task block missing any of them is malformed.
`Pattern refs` is required on **every** task - the old "only when the task creates a new file or a
new public symbol" condition is gone. A task with no precedent worth citing writes
`Pattern refs: none` **explicitly**. The point of the field is the assertion: `none` says the
architect looked and found nothing, while an absent field says nothing at all, and the two are not
the same claim.
Reading legacy specs stays lenient. A block authored before this rule, with the field absent, is
read as `Pattern refs: none` so existing `.specs/` folders keep working. `/sd:spec validate`
reports the omission as `SL060` (WARN) - it does not block, and nothing downstream refuses the
task.
### Refactor mode adds one field
`/sd:refactor` tasks append one more field after `Pattern refs`:
```markdown
- **Parallel batch**: <batch number | "solo">
```
Tasks sharing a batch number have disjoint file sets and no `Depends on` / `Conflicts with`
relationship between them - they are safe to execute in parallel. `solo` means the task cannot
be batched with any other. Other workflow types (feature, bug, perf) do not use this field.
### Port mode constrains two fields
`/sd:port` tasks (authored by `sd-spec-architect` against a `PORT-` spec) narrow two of the 11
required fields rather than adding a new one:
- **`Pattern refs`** is never `none`. Every port task cites 1-3 snapshot member ranges in the
shape `04-artifacts/source/<path>:<first>-<last>`, never a host sibling path and never prose -
the citation IS the anti-drift precedent, not a suggestion of one.
- **`Acceptance`** carries a `Licensed deviations:` line naming the deviation-table `D<NN>` IDs
that apply to this task, or `Licensed deviations: none` when no deviation applies - explicit
`none` is compliant, an absent line is not, same convention `Pattern refs: none` already uses.
```markdown
- **Pattern refs**: 04-artifacts/source/orders/order-intake:12-58 - mirror validation order
- **Acceptance**: CheckTotals runs before the ledger write. Licensed deviations: D02
```
`/sd:spec validate` checks both (`SL061`-`SL066`) against `04-artifacts/source/MANIFEST.md` and the
spec's `## Deviation table` - see `commands/spec.md`'s "Port task-block checks".
### Re-plan adds one field
A task **regenerated by a mid-execution re-plan** (`/sd:feature`, `/sd:refactor` - see the
**sd-replan-loop** skill) carries one extra field after `Pattern refs` (or after `Parallel batch`
in refactor mode):
```markdown
- **Revised-by**: <R## - the revision entry in 01-plan.md that regenerated this task>
```
`Revised-by` is **conditional, not one of the 11 required fields**: it is present only on a task the
re-plan gate regenerated, and absent on every task authored in the original Plan phase. It ties the
task to its `## Revisions` entry in `01-plan.md`; `/sd:spec validate` checks the two agree in both
directions (`SL070`-`SL073`). A task authored at Plan phase never carries it - do not add it
speculatively.
---
## Check-off marker
`/sd:feature`, `/sd:port` and `/sd:refactor` resume from whether a task is **checked**. This
section is the only definition of what that means - commands reference it and never restate it.
### Canonical form
```markdown
- **Status**: <open | done>
```
- It is the **last line** of the block - after `Pattern refs`, and after `Parallel batch` /
`Revised-by` when those are present.
- `sd-spec-architect` writes `- **Status**: open` on **every** task it authors, including tasks a
re-plan regenerates. "Unchecked" is then an assertion on the page, not an absence.
- The main thread **checks off** a task by rewriting that one line to `- **Status**: done`. Nothing
else in the block changes. `sd-implementer` never edits `02-tasks.md`.
- Unlike the 11 contract fields, `Status` is the one value that changes after planning. It records
execution state, so it is not one of the 11 required fields.
**Why a field and not a heading prefix** (`### [x] T01 - ...`, the form a model picks unprompted):
the heading is the task's identity. `T<NN>` is cited by `Depends on`, `Conflicts with`,
`Revised-by`, `/sd:spec validate` findings, `05-retro.md` lines and `/sd:status` counters.
Rewriting the heading on check-off is the exact drift ADR 0002 recorded: `### ✅ T01` read as zero
tasks by a naive counter. A field keeps the heading stable and reuses the field label grammar
below, so there is no second parser. It also has a written-out unchecked state (`open`), while a
heading has none. And a `[x]` in a heading is not rendered as a checkbox anyway - GitHub-flavored
Markdown renders task-list boxes only on list items.
### Reading
Match the label and value with the field label grammar below; the value is case-insensitive.
Resolve each task in this order:
| Block carries | Reads as |
|---|---|
| `Status: done` | checked |
| `Status: open` | unchecked |
| `Status` with any other value | unchecked, reported as `SL067` |
| No `Status`, heading has `[x]` or `✅` before the `T<NN>` token | checked (drift), reported as `SL067` |
| No `Status`, no heading prefix | unchecked (legacy) |
When `Status` is present it decides - a heading prefix never overrides it. A heading prefix is
honoured only as a fallback so a run that checked off in a drifted form is not re-executed.
**Spec status decides first.** Task markers are read **only while the spec's frontmatter status
is `in-progress`**. A `done` or `archived` spec resolves from its frontmatter before any task row in
a resume state machine is evaluated. So a legacy spec with no markers at all (authored before this
section existed) and status `done` - e.g. `examples/fixture-project/.specs/FEAT-todo-priority` - is
never resumed into task execution, even though every one of its tasks reads as unchecked.
`/sd:spec validate` reports a non-canonical marker as `SL067` (WARN). An absent `Status` is **not**
a finding: legacy blocks read as unchecked and the rule above keeps finished specs out of resume.
---
## Field label grammar
The block above shows the **canonical form to author**. It is an example, not the parsing rule -
real specs have drifted, and a reader that accepts only the canonical form rejects valid work.
**When authoring**, always emit the canonical form:
```markdown
- **Files**: <value>
```
**When reading**, match tolerantly. A field label matches when all of the following hold:
| Aspect | Rule |
|---|---|
| Bullet marker | `-` or `*`, any leading indentation |
| Emphasis | `**` around the label is optional |
| Colon | may sit inside the emphasis (`**Files:**`) or outside it (`**Files**:`) |
| Case | label match is case-insensitive |
| Whitespace | any amount around the marker, label, colon, and value |
All three of these are the same field and must parse identically:
```markdown
- **Files**: src/Foo.cs
- Files: src/Foo.cs
- **Files:** src/Foo.cs
```
**Value extent.** A field's value runs from after the colon to the start of the next field label
or the end of the block - it is **not** limited to one line. Indented continuation lines and
nested sub-bullets belong to the field above them. `Acceptance` and `Pattern refs` are routinely
authored as multi-line values with nested bullets; a line-oriented reader that stops at the first
newline truncates them.
This grammar applies to **every** field in the block, not only to the field a given check cares
about. Anything that reads `02-tasks.md` - `/sd:spec validate`, `/sd:verify`, `sd-implementer` -
uses this one rule. Do not write a per-field matcher.
---
## Field rules
### Files
Must exist (for edits) or be a new file path consistent with project conventions. Use `Glob` to verify before writing.
### Layer
Must come from the constitution's declared layers. Do not invent layer names. If a layer is not in `constitution.md`, flag as an Open question.
### Step type
| Value | Meaning |
|---|---|
| `foundation` | New abstractions, types, interfaces, DB schema — no behavior yet |
| `behavior` | Business logic, event handlers, domain rules |
| `wiring` | DI registration, configuration, middleware, glue code |
| `polish` | Naming, comments, docs, dead-code removal |
| `test` | Test files only — no production code change |
### Acceptance
Must be **observable**: a passing test, a 201 response, a method called exactly once. "Feels right" or "code is cleaner" are not acceptable. Every acceptance criterion must be verifiable without running the full app (unit/integration test preferred). On a port task, also carries a `Licensed deviations:` line - see "Port mode constrains two fields" below.
### Covers
Comma-separated scenario (SC-<n>) and success-criterion (AC-<n>) IDs from `00-spec.md` that
this task implements or proves. `none` is allowed only for pure wiring/polish tasks that
advance no criterion directly. Every ID referenced must exist in the spec; every SC and AC in
the spec must be covered by at least one task - `/sd:verify` fails the spec otherwise. Specs
authored before this field existed (no SC/AC IDs) are handled by `/sd:verify`'s generic
checks; treat a missing field as `Covers: none` when reading legacy `02-tasks.md` files.
Spec types whose templates carry no SC-/AC-IDs (refactor, bug, perf, rca) use `Covers: none`
for every task - the coverage requirement (VF010/VF011) applies only to specs whose
`00-spec.md` declares SC-/AC-IDs, currently feature specs.
### Estimated complexity
| Value | Guideline |
|---|---|
| `S` | ≤ 30 lines changed, single file, single concept |
| `M` | 30–100 lines, up to 3 files, one concern crossing a boundary |
| `L` | > 100 lines OR multiple files OR requires design decision at implementation time |
### Reversibility
| Value | Meaning |
|---|---|
| `trivial` | Can be undone with a single revert / delete |
| `moderate` | Requires a few file reverts; no downstream migrations |
| `hard` | Data migration, public API change, or multi-service impact |
### Depends on / Conflicts with
Drive sequencing and batch planning. Tasks that **conflict** cannot run in the same parallel batch. Tasks that **depend on** a prior task cannot start until that task's acceptance criterion is met.
### Pattern refs
1-3 `file:line` citations of precedent code the implementer reads BEFORE writing, each with a one-line instruction of what to mirror (e.g. "mirror handler structure and registration", "reuse this helper - do not duplicate"). Required on every task; write `none` explicitly when there is genuinely no precedent to cite, which should be rare outside pure polish work. Verify each cited file exists before writing the ref. Discovery and adherence rules live in the **sd-pattern-discipline** skill.
---
## Atomicity rules
- **One concern per task.** If the title contains "and" connecting two distinct concerns, split into two tasks.
- **Single-file preferred.** Multi-file tasks should have a clear reason (e.g. interface + implementation pair).
- If a task feels like two changes during implementation, STOP and surface to the main thread.
---
## Anti-patterns
- Bundling interface + behavior + test into a single task — these are three tasks.
- Using vague acceptance criteria ("works correctly", "looks good").
- Listing files you haven't verified exist (for edits) or naming conventions don't match.
- Inventing layer names not declared in the constitution.
- Leaving `Depends on` / `Conflicts with` empty when sequential or conflicting relationships exist.
- Authoring a new-file task with `Pattern refs: none` - the implementer has no precedent to mirror.
- Citing Pattern refs you did not verify exist.
- Omitting `Pattern refs` instead of writing `none`. Silence is not an assertion; `SL060` flags it.
- Checking off a task by editing its heading (`### [x] T01`, `### ✅ T01`) or appending a list
checkbox. The only check-off is `Status: done` - see "Check-off marker". `SL067` flags the rest.
- Burying a precedent in prose beside the block instead of putting it in the field. `sd-implementer`
reads `TASK_DETAILS`, not the surrounding narrative - a ref outside the field does not reach it.