Skip to main content

ADR-0008: Task lifecycle sidecar and immutable task spec

  • Status: Accepted
  • Date: 2026-06-11
  • Deciders: Michel Gillet

Context

Milestone 9 introduced historical delivery metrics derived from planning task front matter (created_at, updated_at, status, etc.). That approach assumes lifecycle timestamps already exist on planning/tasks/<id>.md, but does not define how status transitions are recorded while work is in progress.

We need lifecycle data that is:

  • Portable — visible on any machine after git pull (not local-only cache)
  • Fast to aggregate — metrics collection should not walk full git history per task
  • Separated from the task spec — implementation work should not repeatedly rewrite the human-readable task definition (summary, acceptance criteria, scope) during delivery

Embedding a full status_history in task front matter on every transition satisfies portability and read speed, but mixes spec (what the task is) with telemetry (what happened). Reviewers then see planning markdown churn alongside code changes.

Decision

Each task may have a lifecycle sidecar alongside its planning artifact:

ArtifactPathRole
Task specplanning/tasks/<id>.mdImmutable specification — summary, acceptance criteria, scope, links. Status and timestamp fields on this file are not updated during active implementation unless the spec itself changes.
Lifecycle sidecarplanning/tasks/<id>.events.ndjsonAppend-only event log — status transitions and other delivery events, one JSON object per line (NDJSON).

Sidecar format

Each line is a self-contained JSON object. Minimum event shape:

{
"task_id": "TASK-42",
"event": "status_changed",
"from": "todo",
"to": "in_progress",
"at": "2026-06-11T14:30:00Z"
}

Additional fields (e.g. actor, source, note) may be added in later schema versions. The sidecar file is machine-oriented by design.

Repository and portability

  • The sidecar is a committed file under planning/tasks/, versioned like any other planning artifact.
  • Events are not stored in local-only .a2c/cache/ for lifecycle purposes.
  • Git merge strategy (merge commit, squash, rebase, etc.) is out of scope for this ADR. The sidecar model does not depend on a particular trunk-integration workflow.

Metrics collection

Future a2c_core metrics collection should read lifecycle data from the sidecar when present, and derive work_started_at, completed_at, lead time, and cycle time from recorded events rather than coarse proxies on the task spec file.

Front-matter-only collection remains valid as a fallback when no sidecar exists.

Tooling expectations (future)

  • Record events via core API / CLI (append to <id>.events.ndjson).
  • Validate sidecar schema and task id consistency.
  • Do not require rewriting <id>.md on each status transition.

Rationale

  • Spec vs telemetry — keeps planning/tasks/<id>.md stable for humans and AI during implementation; lifecycle noise lives in NDJSON reviewers can skim.
  • Fast readsa2c metrics collect scans task files and sidecars in O(tasks), not git history.
  • Portable — committed sidecar syncs across machines without a separate event store.
  • NDJSON — append-friendly, supports structured fields (tags, actors) without CSV pain.

Alternatives considered

AlternativeVerdictReason
Lifecycle only in task front matter (status_history, repeated updated_at edits)Rejected as primaryFast to read but pollutes the spec file and review diffs
Lifecycle only in git commits (parse git log per task file)Rejected as primaryPortable but slow for repo-wide metrics; better as optional augmentation
Local-only .a2c/events/RejectedNot portable across machines
Flush sidecar into task.md at mergeOptionalValid variant but not required; sidecar may remain the canonical lifecycle store on trunk

Consequences

Positive

  • Clear separation between task definition and task delivery history
  • Metrics can be accurate without mutating the spec artifact during implementation
  • Sidecar diffs are clearly machine-oriented in review
  • Aligns with repo-first planning under planning/tasks/

Negative

  • Two files per task when lifecycle tracking is enabled
  • Loaders and validators must recognize *.events.ndjson naming convention
  • Sidecar-aware metrics derivation is follow-on work (not part of this ADR)
  • Immutability of the spec is a convention — tooling should discourage spec edits for status-only updates, but cannot enforce without hooks

Migration

  1. Document sidecar convention in planning artifact docs.
  2. Implement event record API and sidecar-aware metrics derivation (follow-on milestone).
  3. Optionally add schema task-events.schema.json for sidecar lines.
  4. Existing tasks without sidecars may continue using front-matter timestamp proxies.

Relationship to other ADRs

ADR / docRelationship
planning-artifact-format.mdComplements — adds sidecar naming next to task Markdown

References

  • docs/task-body-profiles.md — task spec sections (sidecar is not a profile variant)
  • Milestone 9 task fixture: tests/fixtures/workflows/task_m9_historical_delivery_metrics.body.md

Supersedes

  • (none)

Superseded by

  • (none)