diff --git a/CLAUDE.md b/CLAUDE.md index f903f34..b77a4ea 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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` @@ -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--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 @@ -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_` 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. diff --git a/MEMORY.md b/MEMORY.md new file mode 100644 index 0000000..c1da5fb --- /dev/null +++ b/MEMORY.md @@ -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=`/`## ` 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. diff --git a/README.md b/README.md index 4c516c2..f48ffb9 100644 --- a/README.md +++ b/README.md @@ -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