Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 27 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ Guidance for developing **this** repository (a single-file, zero-dependency
`TASKS.md` task tracker). Read `README.md` for user-facing usage; this file is
for contributors and AI sessions working on the tool itself.

**Read order for a fresh session:** `README.md` (what the tool does) → this file
(rules) → `MEMORY.md` (session-to-session state: what just happened, what's next)
→ `LEARNINGS.md` (why past decisions went the way they did). `MEMORY.md` ranks
*below* this file — if they disagree, this file wins and the loser gets fixed.

## What this is

`tasks.py` is a self-contained CLI that manages a plain-text `TASKS.md`
Expand All @@ -30,9 +35,13 @@ exists — no install, no PATH, no network.
| Path | What |
|---|---|
| `tasks.py` | The engine — commands, parser, validator, `version`/`selfupdate`. |
| `tests/test_tasks_e2e.sh` | The conformance gate (155 scenarios). |
| `tests/test_tasks_e2e.sh` | The conformance gate (54 scenarios / 298 assertions as of v1.4.0 — `make test` prints the live count; don't trust doc numbers over the runner). |
| `hooks/tasks-md-guard.sh` | Optional PostToolUse hook nudging edits through the CLI. |
| `schema.md` | `TASKS.md` format quick-reference (full spec = the docstring). |
| `docs/superpowers/specs/` | Committed design docs (`YYYY-MM-DD-<topic>-design.md`) for larger features — the decisions *and their why*, written before implementation. ("superpowers" = the brainstorm/TDD workflow tooling used in AI sessions; the docs are plain markdown.) |
| `LEARNINGS.md` | Insight/decision ledger, newest first — read before repeating a class of change. |
| `MEMORY.md` | Maintainer session-to-session state (resume point, off-repo context, bootstrap). |
| `CHANGELOG.md` | Per-release record (entries are history — don't rewrite old ones). |
| `Makefile` · `.github/workflows/ci.yml` | Dev runner + CI (Python matrix). |

## Development workflow
Expand Down Expand Up @@ -81,12 +90,24 @@ Vendored copies on older versions pick up the new release via
- Commands are dispatched from `main()` (an `if/elif` chain on `argv[1]`); add a
command by writing `cmd_<name>` and a branch, and document it in the docstring
command list.
- Commit messages: clear and imperative; one concern per commit.
- Commit messages: clear and imperative; one concern per commit. No
"Generated with" / "Co-Authored-By" trailers.
- All changes land via feature branch → PR → CI green → squash-merge; never
commit to `main` directly.
- Number references: in `CHANGELOG.md`, `LEARNINGS.md`, and spec prose, `#N`
cites a **GitHub issue**; the `(#N)` suffix on a squash-merge commit subject
is the **PR** number. They are different sequences on the same tracker.
- New behavior is developed test-first: add the e2e scenario, watch it fail for
the right reason, then implement. Larger features get a design doc in
`docs/superpowers/specs/` committed with the same PR.

## Roadmap / known items

- **The living roadmap is the GitHub issue tracker** (budhash/tasks). Triage
comments on the issues carry the agreed scope; the current queue order and
resume point are pinned in `MEMORY.md` (updated with each release).
- **Type hints.** Some internal annotations are loose (a strict checker flags a
few `Optional` narrowing sites). Runtime behavior is covered by the e2e suite;
tightening these is a welcome incremental cleanup.
- Possible enhancements: a bridge to editor/agent task tooling, schema
versioning + migration, and a multi-project rollup view.
few `Optional` narrowing sites — known and accepted). Runtime behavior is
covered by the e2e suite; tightening these is a welcome incremental cleanup.
- Longer-horizon ideas (no issue yet): a bridge to editor/agent task tooling,
schema versioning + migration, and a multi-project rollup view.
83 changes: 83 additions & 0 deletions MEMORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# MEMORY.md — successor briefing

> **Rank:** this file ranks BELOW `CLAUDE.md`. If they disagree, `CLAUDE.md` wins —
> then fix the loser. It carries only what the code and the other docs can't say:
> what just happened, off-repo context, and the pinned resume point.
> **Maintenance:** update "Now / next" and "What just happened" in the same PR as any
> release or roadmap-changing merge; delete lines that stop being true.

## Now / next (the resume point)

- **Nothing is in flight.** `main` is the complete, released state (v1.4.0,
2026-07-15). No open PRs; the only branch is `main`.
- **Next up, if told "continue where we left off": issue #14 — `validate --refs`**,
a reference-integrity check. Agreed shape (triage comment on the issue): v1 detects
*dangling* refs only (`@deps=`/`@rel=`/`## <ID>` notes header pointing at an ID
that no longer exists), opt-in flag, read-only report — the same
"detect, don't rewrite" template as `renumber --refs`. `_report_external_refs()`
in `tasks.py` is already half the engine; short-form IDs (`T-12` ≡ `T-0012`) must
be handled (see the v1.3.0 LEARNINGS entry). Fold #25 (validate silently ignores
unknown args) into the same round — that bug becomes dangerous the moment
`validate` grows its first flag.
- Queue after #14 (recommended order, from the issue-triage comments): #16 (CLI verb
for the `# Milestones` registry), #11's remaining half (`note ID` verb — retitle
shipped in v1.2.0), #6 (refuse mutating commands on main), #5 (docs: CLI-only vs
manual edits), #15 (merge-driver discussion — deliberately sequenced last).
- Open but unsequenced June backlog — priority is the **user's** call, don't
self-assign: #2 (`rm` verb), #3 (`--tags-add`/`--tags-rm`), #4 (validate
`@pr`/`@branch` freshness). #13's `reserve N` stays deferred unless a real gap is
observed (recorded on the issue).

## What just happened (2026-06-21 → 2026-07-15)

Six releases, each driven by real usage in consumer repos; every design decision and
its *why* is in `LEARNINGS.md` and `docs/superpowers/specs/`:
v1.1.0 milestones → v1.1.1 trailing-tag-region parsing (#9) → v1.1.2 shadow-sync
field edits (#17) → v1.2.0 `set --title` (#18) → v1.3.0 `renumber` (#12) →
v1.4.0 `new --id`/`--base` (#13). The through-line: a three-way ID collision
(`T-2006`, three parallel branches) in a consumer repo produced the
fix/prevent/detect triad — #12 shipped (fix), #13 shipped (prevent), #14 open
(detect).

## Off-repo context a fresh machine won't have

- **Consumers:** the tool is vendored as `tools/tasks.py` into private sibling
projects (`taxjot`, `byteorb`, `stead` — checkouts lived next to this repo on the
old machine; they are NOT required for developing this repo). The milestone
feature's spec originated in taxjot; the ID-collision incident happened in byteorb.
Consumers pick up releases via `./tools/tasks.py selfupdate`.
- **Standing user rule (upstream/mirror):** when a tasks bug or need surfaces while
working in a consumer repo — file the GitHub issue upstream here FIRST, then mirror
it as one P2 task in that consumer's `TASKS.md` referencing the issue URL. Defer
adding mirror tasks while other `TASKS.md` PRs are in flight (ID churn); prefer one
umbrella task over many mirrors.
- **Pending deferred action from that rule:** byteorb still needs an umbrella P2 task
"track budhash/tasks #12–#15" on its next `TASKS.md`-touching PR (was deferred
behind byteorb's #291).
- **The issue tracker is the roadmap** (GitHub, budhash/tasks); triage comments on
#11–#16 carry the agreed scopes. A new machine needs `gh auth login` for that work.

## New-machine bootstrap

```bash
git clone https://github.com/budhash/tasks.git && cd tasks
make check # py_compile + full e2e suite; must be green before anything else
gh auth login # only needed for issue/PR/release work
```

Requirements: python3 ≥ 3.8, bash, git; `gh` for GitHub work. No install, no deps.
A root `TASKS.md` here is gitignored dev scratch (the tool's own playground), not
project state.

## Process facts that bit us before (details in LEARNINGS.md)

- Release = bump `__version__` + `CHANGELOG.md` entry + `make check` green →
squash-merge → `git tag -a vX.Y.Z && git push origin vX.Y.Z` (the tag push IS the
release) → `gh release create vX.Y.Z`.
- TDD is the norm: failing e2e scenario first, watched failing *for the right
reason*; design docs to `docs/superpowers/specs/` in the same PR.
- Real-world verification: before releasing format-adjacent changes, run the
read-only commands against a copy of a real consumer `TASKS.md` (byte-for-byte
round-trip, cf. e2e scenario 31).
- Known accepted Pyright loose-typing diagnostics in `tasks.py` (see CLAUDE.md
roadmap) — don't chase them casually.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,10 @@ overwrites the running script, it is deliberately conservative:
| `tasks.py` | The engine — task commands, `validate`, `version`, `selfupdate`. |
| `examples/TASKS.md` | A populated sample file. |
| `hooks/tasks-md-guard.sh` | Optional PostToolUse hook nudging edits through the CLI. |
| `tests/test_tasks_e2e.sh` | Conformance suite (155 scenarios). |
| `tests/test_tasks_e2e.sh` | Behavioral conformance suite (54 scenarios / 298 assertions as of v1.4.0; `make test` prints the live count). |
| `schema.md` | `TASKS.md` format quick-reference (full spec in `tasks.py help`). |
| `docs/superpowers/specs/` | Committed design docs for the larger features (the *why* behind them). |
| `LEARNINGS.md` · `MEMORY.md` | Decision/insight ledger · maintainer session-to-session state. |
| `CHANGELOG.md` · `CONTRIBUTING.md` · `CLAUDE.md` | History · contributing · dev guide. |

## Develop
Expand Down
Loading