Task body profiles
Human guide to the section contracts in profiles/task-body/. Profiles tell humans and AI
which ## sections a planning task should include, what each section means, and which are
required.
Machine-readable definitions live in the YAML files. This document explains how to use them in practice.
For the single-task intake workflow (plan → review → apply), see task-authoring.md.
What profiles are (and are not)
| Profiles are | Profiles are not |
|---|---|
| Section structure contracts | The recorded task artifact |
| Validation rules for draft JSON and markdown bodies | A replacement for planning/tasks/*.md |
| Guidance for AI structured output | Full prose specifications inside YAML |
Recorded tasks are always Markdown + YAML front matter under planning/tasks/. Section
values are markdown fragments (lists, subheadings, code fences). Profiles only define the
envelope: section keys, headings, order, and required vs optional.
profiles/task-body/feature-expanded.yaml ← terse contract (machine)
docs/task-body-profiles.md ← this guide (human)
schemas/task-draft.schema.json ← JSON import envelope
planning/tasks/TASK-1.md ← canonical artifact on disk
Profile variants
| Profile id | When to use | Required sections |
|---|---|---|
feature-minimal | Small features, decomposition tasks, quick intake | Summary, Acceptance criteria |
feature-expanded | Large or AI-brainstormed features where intent must not be lost | Summary, Context, Goal, Assumptions, Scope (core + CLI), Boundaries, Tests, Documentation, Acceptance criteria |
bug | Defect reports (--type bug) | Summary, Observed behavior, Expected behavior, Steps to reproduce, Environment, Acceptance criteria |
Choosing a profile
- Default feature work →
feature-minimal - Milestone-style implementation specs (many constraints, cross-package scope) →
feature-expanded - Bug reports →
bug(also auto-detected when both Observed behavior and Expected behavior headings are present in a monolithicbody)
Epic decomposition always validates against feature-minimal unless a task draft explicitly
sets another profile in JSON.
Authoring shapes
Task draft JSON supports two equivalent input shapes. Both compose to the same markdown body before apply.
1. Monolithic body (markdown string)
{
"title": "Add health check endpoint",
"status": "todo",
"body": "## Summary\n\n...\n\n## Acceptance criteria\n\n- ..."
}
Best for: simple tasks, LLM output, copy-paste from templates/planning/task-template.md.
2. Structured sections (keyed markdown fragments)
{
"title": "M9 — Historical delivery metrics collection",
"epic_id": "EPIC-9",
"profile": "feature-expanded",
"sections": {
"summary": "Implement Milestone M9...",
"context": "A2C already provides...",
"goal": "Add a metrics collection layer...",
"acceptance_criteria": "- Models defined\n- CLI commands work"
}
}
Best for: AI structured output, reviewable JSON diffs, tooling that edits one section at a time.
Rules:
- Provide
bodyorsections, not both profileis optional; defaults tofeature-minimalwhen usingsectionswithout a profile- Section object keys match profile
keyfields (e.g.acceptance_criteria,scope_a2c_core) - Composed output uses profile
headingvalues as##titles
Companion .body.md workflow
For large bodies, edit a companion markdown file and sync to JSON:
python scripts/sync_task_fixture_json.py \
tests/fixtures/workflows/task_m9_historical_delivery_metrics.body.md \
tests/fixtures/workflows/task_m9_historical_delivery_metrics.json \
--title "M9 — Historical delivery metrics collection" \
--epic-id EPIC-9 \
--profile feature-expanded \
--format sections
Use --format body to keep a monolithic body field (backward compatible).
Preview the applied task markdown:
pytest tests/test_task_m9_markdown_preview.py -v -s
Section reference — feature-minimal
Use for tasks that need a clear outcome and definition of done, without a full implementation brief.
Summary (required)
One short paragraph: what will be delivered, what is in scope, and what is explicitly out of scope for this task.
Good:
Add a read-only
a2c metrics showcommand that prints aggregate counts from.a2c/metrics/after collection. Dashboards and git-augmented timestamps are out of scope.
Avoid: implementation steps, file paths only, or acceptance criteria duplicated verbatim.
Acceptance criteria (required)
Checklist items that are objectively verifiable. Prefer observable outcomes over activity descriptions.
Good:
a2c metrics showprints throughput and average cycle time when metrics exist- Exits non-zero with a clear message when
.a2c/metrics/is missing
Notes (optional)
Implementation hints, links to epics or ADRs, deferred follow-ups. Not required for validation.
Section reference — feature-expanded
Use when the task is an implementation contract — especially after AI brainstorming — and downstream readers (human or agent) need context, assumptions, and boundaries preserved.
Canonical example in this repository:
- Profile:
feature-expanded - Body source:
tests/fixtures/workflows/task_m9_historical_delivery_metrics.body.md - JSON fixture:
tests/fixtures/workflows/task_m9_historical_delivery_metrics.json
Summary (required)
Compressed version of the whole task: milestone name, packages touched, and primary non-goals.
Context (required)
What exists today, what gap this task closes, and motivating questions the work should eventually answer. Bullet lists are fine.
Ask: If someone reads only this section, do they understand why the task exists?
Goal (required)
Outcomes and deliverables: data sources, storage locations, consumers (CLI, AI workflows, visualizations). Focus on what the system will do, not class names.
Definitions (optional)
Domain terms, metric formulas, API names. Use when ambiguity would cause rework. Headings may
include a suffix (e.g. ## Definitions (M9 first pass)); validation accepts headings that
start with the profile heading.
Assumptions (required)
Explicit proxies and defaults: timestamp fields, optional git use, front matter fields, idempotent behavior. State what you will implement when history is unavailable.
Scope — a2c_core (required)
Core package responsibilities only: data models, collection APIs, serialization, validation.
Use ### subheadings for sub-areas (data model, collection logic).
Scope — a2c_cli (required)
CLI commands, flags, exit codes, example output. CLI should orchestrate core, not duplicate domain logic.
Boundaries (required)
Non-goals, dependency direction (no core → CLI), exclusions (no dashboards in M9). Prevents scope creep during implementation.
Tests (required)
Synthetic repo scenarios and CLI behaviors to verify. Name concrete cases: done vs todo tasks, missing metrics directory, aggregation windows.
Documentation (required)
What docs must be updated, what to explain to users, known limitations to call out.
Acceptance criteria (required)
Definition of done as a checklist. May overlap with Tests at a high level; criteria should be outcome-oriented, Tests section can be more scenario-specific.
Notes (optional)
Deferred milestones, consumption guidance (e.g. “AI should read .a2c/metrics/ files, not
scrape CLI output”).
Section reference — bug
Use with a2c plan create-task --type bug or when importing bug-shaped JSON.
Summary (required)
One or two sentences: what is broken and user impact.
Observed behavior (required)
What actually happens — errors, wrong UI, incorrect data. Include messages or status codes when known.
Expected behavior (required)
Correct behavior from the user or specification perspective.
Steps to reproduce (required)
Numbered, minimal steps. Should be reliable enough for a developer to trigger the issue.
Environment (required)
OS, app version, config flags, deployment target — whatever is needed to reproduce.
Acceptance criteria (required)
How we know the fix is complete (regression test, manual check, log absence).
Notes (optional)
Workarounds, log excerpts, related task ids, suspected root cause (if known).
Validation behavior
At plan create-task and apply draft-task, a2c_core:
- Resolves a profile (
profilefield, or inference from body headings) - Ensures all required profile sections are present
- For
sectionsinput, rejects unknown section keys for the selected profile - Composes
sections→ markdownbodybefore caching and apply
Validation checks heading presence (and non-empty section keys for JSON), not semantic quality. Writing good content is a human/AI responsibility; profiles enforce structure.
Relaxed heading match: a body heading matches a profile section when it equals the profile
heading (case-insensitive) or starts with that heading followed by a space or ( — so
## Definitions (M9 first pass) satisfies the Definitions section in feature-expanded.
Tips for AI-assisted authoring
When prompting an AI to produce task draft JSON:
- Name the profile explicitly:
"profile": "feature-expanded" - Prefer
sectionsover one largebodystring for multi-section features - Ask for markdown inside each section value (lists, code blocks allowed)
- Do not ask for
id— A2C allocates task ids at apply time unless you set an explicit import hint - Point to
schemas/task-draft.schema.jsonand this document as the contract
Example prompt fragment:
Return a single JSON object with
title,status,epic_id,profile, andsectionskeyed perprofiles/task-body/feature-expanded.yaml. Each section value is markdown without the##heading line.
Customizing profiles
To adapt profiles for a consuming project:
- Copy or override files under
profiles/task-body/in your repository - Keep profile
idstable if JSON fixtures reference it - Add optional sections with
required: falsebefore making new sections required - Update this guide (or a project-specific copy) when section meaning changes — keep YAML descriptions short
Bundled fallbacks ship in src/a2c_core/profiles/data/task-body/ for installed a2c-core
packages; repository profiles take precedence when present.
Related
- task-authoring.md — plan / review / apply workflow
- profiles/task-body/README.md — profile index
- schemas/task-draft.schema.json — JSON import schema
- templates/planning/task-template.md — minimal markdown starter