Skip to main content

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 areProfiles are not
Section structure contractsThe recorded task artifact
Validation rules for draft JSON and markdown bodiesA replacement for planning/tasks/*.md
Guidance for AI structured outputFull 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 idWhen to useRequired sections
feature-minimalSmall features, decomposition tasks, quick intakeSummary, Acceptance criteria
feature-expandedLarge or AI-brainstormed features where intent must not be lostSummary, Context, Goal, Assumptions, Scope (core + CLI), Boundaries, Tests, Documentation, Acceptance criteria
bugDefect 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 monolithic body)

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 body or sections, not both
  • profile is optional; defaults to feature-minimal when using sections without a profile
  • Section object keys match profile key fields (e.g. acceptance_criteria, scope_a2c_core)
  • Composed output uses profile heading values 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 show command 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 show prints 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:

  1. Resolves a profile (profile field, or inference from body headings)
  2. Ensures all required profile sections are present
  3. For sections input, rejects unknown section keys for the selected profile
  4. Composes sections → markdown body before 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:

  1. Name the profile explicitly: "profile": "feature-expanded"
  2. Prefer sections over one large body string for multi-section features
  3. Ask for markdown inside each section value (lists, code blocks allowed)
  4. Do not ask for id — A2C allocates task ids at apply time unless you set an explicit import hint
  5. Point to schemas/task-draft.schema.json and this document as the contract

Example prompt fragment:

Return a single JSON object with title, status, epic_id, profile, and sections keyed per profiles/task-body/feature-expanded.yaml. Each section value is markdown without the ## heading line.

Customizing profiles

To adapt profiles for a consuming project:

  1. Copy or override files under profiles/task-body/ in your repository
  2. Keep profile id stable if JSON fixtures reference it
  3. Add optional sections with required: false before making new sections required
  4. 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.