Tracker

July 31, 2026 · View on GitHub

This folder is the single source of truth for what needs doing, what was decided, and what got done. Documents elsewhere (a docs/ folder) explain and discuss; records in tracker/ have IDs, status, and a lifecycle. The test for what belongs here: does it have a lifecycle? If it must change state or rot, it's a record and lives here. If it's finished the moment it's written (a guide, an analysis, a transcript), it's a doc and lives in docs/.

Layout

tracker/
  readme.md        this file — the process
  config.json      areas + paths (the only repo-specific config)
  BACKLOG.md       GENERATED index of open items — never hand-edit; run `python tools/track.py index`
  DONE.md          append-only log of completed/dropped items, newest first (written by `track.py close`)
  issues/          one file per tracked item — the frontmatter here is the SOURCE OF TRUTH
  decisions/       Architecture Decision Records (ADRs) — dated, immutable, occasionally superseded

Issue frontmatter is the database; BACKLOG.md is a generated view of it (any grouping, ordering, or filtering is a query — python tools/track.py list --help). DONE.md is an event log, not a cache: the outcome text lives only there.

Tooling

  • python tools/track.py new --title "..." --area <area> [--type ...] [--sprint NAME] — allocates the next id, writes the issue file, regenerates BACKLOG.md.
  • python tools/track.py set <id> --status ready --priority p1 ... [--sprint NAME|none] — the ONLY way to change status/priority/effort/risk/sprint (updates frontmatter + regenerates index).
  • python tools/track.py list [--open] [--status S] [--area A] [--type T] [--sprint N] [--sort priority|id|status|sprint|created] [--format table|csv] — query views.
  • python tools/track.py close <id> [--outcome "done (sha)"] [--dropped] — closes the issue, logs to DONE.md, regenerates index.
  • python tools/track.py report [--html PATH] [--md PATH] — renders a shareable point-in-time snapshot (open items grouped by status, plus recent DONE) as a standalone HTML file and/or Markdown; with no path, prints Markdown to stdout. Read-only: never writes into the tracker's own data.
  • python tools/track.py index — regenerate BACKLOG.md (normally automatic).
  • python tools/track.py next-id — peek at the next number.
  • /track-idea, /track-issue, /track-backlog — Claude Code skills (.claude/skills/) that drive the script and elaborate: assumptions, design decisions, related-work links, approaches, simplest implementation. See each skill for details.

Issues

One file per item: issues/<id>.md where id = <area>-<number> (e.g. core-015). Next number = highest existing number across all areas + 1 (numbers are globally unique; the area prefix is just a hint). Areas are configured in tracker/config.json. In a monorepo, use one area per subproject; add a repo/infra area for cross-cutting process work.

Frontmatter (see issues/_template.md):

---
id: core-015
title: Faster widget codegen
type: feature | debt | bug | idea | problem | retire
status: idea | ready | in-progress | done | dropped
priority: p1 | p2 | p3 | "?"
effort: S | M | L | "?"
risk: low | med | high | "?"
area: core
sprint:            # working-set name (e.g. 2026-01-A), empty = not in a sprint
created: 2026-01-01
closed:            # date, when done/dropped
links: []          # related docs, plans, discussions, other issues
---

Status semantics: idea = captured, untriaged. ready = triaged (real priority/effort/risk, plus a ## Done means section — 2–5 verifiable acceptance criteria — required for feature/debt/bug) — an agent may pick it up. Promotion idea→ready happens via track.py set during triage. A sprint is a working set, not a time-box: the batch selected for parallel execution now — big rocks + little rocks, chosen for impact/risk balance and non-colliding areas (see /track-backlog sprint plan).

Body: motivation, acceptance criteria, pointers to discussion. Terse is fine; a title alone is enough for an idea.

Types:

  • feature — new capability
  • debt — technical debt to pay down
  • bug — defect
  • idea — captured thought, not yet triaged (default type for quick capture)
  • problem — open design question that needs an answer. Closing a problem usually produces an ADR plus follow-up issues.
  • retire — code/doc/feature that should be deleted or deprecated

Lifecycle

  1. Capture. New idea → new issue file with status: idea + one line in BACKLOG.md. Never a new loose doc for trackable work.
  2. Triage. Periodically (weekly, ~10 min) sweep BACKLOG.md: set priority/effort/risk, promote ideaready, drop dead ones.
  3. Plan. Substantial work gets a plan doc; the plan links to the issue and the issue links back. Set status: in-progress when work starts.
  4. Close. When work lands (or is abandoned): python tools/track.py close <id> --outcome "done (sha)" (sets status + closed date, logs to DONE.md, regenerates the index), and mark any executed plan doc with a banner at the top: > **EXECUTED <date>** — see tracker issue <id>. Historical record; do not execute. then move it to an archive folder.

Decisions (ADRs)

decisions/YYYY-MM-DD-<slug>.md — context, decision, rationale, alternatives rejected, links. See decisions/_template.md. Write one only when a decision is expensive to reverse or likely to be re-litigated (~1–2/week max). Never edit an ADR's substance after the fact; supersede it with a new one and add superseded-by: to the old.

Rules for agents

  • Check status before executing any plan. A plan doc without a live linked issue in in-progress/ready state, or carrying an EXECUTED banner, is historical — ask before acting on it.

  • File what you find. Out-of-scope debt, bugs, or retire candidates discovered mid-task: create an issue file + BACKLOG line, don't fix inline and don't let it evaporate.

  • Commit tracker changes immediately. Every time you create or update an issue, regenerate BACKLOG.md if it changed (new/set/close already do this), then git add both the issue file(s) and BACKLOG.md and commit them together. Never leave an issue file or a stale BACKLOG.md uncommitted, and never commit one without the other.

  • Name the item in the commit. Any commit doing work on a tracked item names that item's id in the Conventional-Commits scope — fix(studio-149): atomic menu clear+rebuild. This is the join key between git history and tracker state. Tracker bookkeeping commits (docs(tracker):, chore(tracker):) are not work commits and never count as progress on an item.

  • Mark progress at the commit that makes it — close what you finish, when you finish it. In the same commit that lands work, tick every ## Done means checkbox that commit satisfies. Progress is read from those boxes; there is no stored progress field or percentage.

    • If every box is now ticked, close immediately: python tools/track.py close <id> --outcome "done (<work-commit-sha>)", then commit that tracker change. The sha only exists once the work commit is made, so the close is the immediately-following commit — not an end-of-session chore that gets forgotten.
    • If any box is unticked, the item stays in-progress, and you say which box is outstanding. A landed fix awaiting verification is not done.

    Never infer completion from commit history alone: an unticked box is the item stating it is not finished. At close, banner + archive the executed plan doc. This replaces per-session report docs.

  • Ideas from the user ("we should someday…") get captured as type: idea issues immediately.

  • Don't re-litigate ADRs. Check decisions/ before proposing architecture changes; if you disagree with a decision, propose a superseding ADR rather than silently diverging.


This tracker is powered by WorkQuarry. This file is installed from the WorkQuarry source — edit it there, not here.