diff --git a/CHANGELOG.md b/CHANGELOG.md index 34f7a83..5d32dda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,25 @@ All notable changes to `tasks`. Format loosely follows [Keep a Changelog](https://keepachangelog.com/); this project uses [semantic versioning](https://semver.org/). +## [1.4.1] — 2026-07-16 + +Docs-only release; no behavior changes. Marks the repo "migration-ready": three +blind cold-clone audits confirmed a fresh session can resume from the repo alone. + +### Added +- `MEMORY.md` — successor briefing (resume point, off-repo context, bootstrap), + ranked below `CLAUDE.md`; referenced from the fresh-session read order. +- Docstring/`schema.md`/README: explicit note that tasks do **not** inherit + their parent feature's `@milestone=` (rollup counts task tags only). + +### Fixed +- Stale "155 scenarios" claims (actual: 54 scenarios / 298 assertions as of + v1.4.0) + an editor's note on the mislabeled v1.0.0 entry. +- Layout tables now list `LEARNINGS.md`, `MEMORY.md`, `docs/superpowers/specs/`. +- `examples/TASKS.md` now showcases milestones (registry + `@milestone=` tags). +- `CONTRIBUTING.md`/`CLAUDE.md` release + branching process aligned with actual + practice (squash-merge only; `gh release create` every release). + ## [1.4.0] — 2026-07-15 ### Added diff --git a/CLAUDE.md b/CLAUDE.md index c77a2f8..c9107cb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -98,7 +98,8 @@ Vendored copies on older versions pick up the new release via 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. + is the **PR** number. Issues and PRs share one number sequence on GitHub, so + a given `#N` is exactly one of the two — the tracker resolves it either way. - 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. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c7b27dc..9bdd651 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,13 +30,16 @@ make smoke # quick functional smoke test ## Pull requests +- All changes land via feature branch → PR → CI green → squash-merge; nothing + is committed to `main` directly. - One concern per PR; clear, imperative commit messages. - `make check` green, and the change documented in `CHANGELOG.md`. ## Releasing (maintainers) Bump `__version__` + `CHANGELOG.md`, then `git tag -a vX.Y.Z -m "tasks vX.Y.Z" -&& git push origin vX.Y.Z`. +&& git push origin vX.Y.Z`, then `gh release create vX.Y.Z` with notes (every +release since v1.1.0 has one). Full process notes: `CLAUDE.md` → Releasing. ## Known cleanup diff --git a/LEARNINGS.md b/LEARNINGS.md index 26c25bc..f996e32 100644 --- a/LEARNINGS.md +++ b/LEARNINGS.md @@ -3,6 +3,28 @@ Insights, gotchas, and decisions worth remembering — newest first. For *what* changed see `CHANGELOG.md`; this file records *why* and what it taught us. +## 2026-07-16 — v1.4.1 (migration readiness: blind-dogfood audits) + +- **Blind readers find what self-review can't.** Preparing a machine move, we ran + three rounds of "fresh agent, cold clone, zero context, answer a resume + questionnaire from the repo alone". Round 1: stale claims ("155 scenarios"), + lagging layout tables/roadmap, and no in-repo resume point. Round 2: an + overclaiming doc sentence, a flagship example file that predated the flagship + feature, and a real bug (#25: `validate` swallows unknown argv). Round 3: only + minor phrasing — converged. Each reader must be blind to the previous reports, + or later rounds just re-confirm earlier ones. +- **The highest-value probe is "continue where we left off".** It cleanly + separates "nothing is unmerged" (derivable from git) from "what would you do + next" (not derivable unless written down). `MEMORY.md` now pins the resume + point and is maintained in the same PR as any release or roadmap change. +- **Hardcoded counts in prose always rot.** Pin them to a version ("as of + v1.4.0") and point at the runner for the live number. And when a frozen + history entry (CHANGELOG) is misleading, append a dated editor's note — never + rewrite the entry. +- **Example files are docs and rot like docs.** `examples/TASKS.md` was billed + as "fully populated" but had no milestone content two releases after + milestones shipped. When a feature ships, grep the examples too. + ## 2026-07-15 — v1.4.0 (collision-resistant allocation) - **Fail closed when the flag *is* the safety.** `new --base ` exists to diff --git a/MEMORY.md b/MEMORY.md index 56ef37b..a64d3a7 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -8,8 +8,10 @@ ## 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`. +- **Nothing is in flight.** `main` is the complete state; no open PRs; the only + branch is `main`. v1.4.1 (docs-only, migration-readiness) is committed on + `main` — if no `v1.4.1` tag exists yet, tagging it is pending the owner's + confirmation (a tag push triggers the release; see CLAUDE.md → Releasing). - **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 @@ -40,7 +42,9 @@ 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). +(detect). Afterwards (2026-07-15/16), three blind cold-clone audits drove the +migration-readiness docs work (v1.4.1): MEMORY.md, corrected doc claims, and +issue #25 (found by the audit). ## Off-repo context a fresh machine won't have diff --git a/README.md b/README.md index 8f78cbf..9babe5d 100644 --- a/README.md +++ b/README.md @@ -160,8 +160,14 @@ EOF ./tools/tasks.py next --milestone m1 # next actionable task within M1 ``` +Assignment is per-item: a task does **not** inherit its parent feature's +milestone. The `milestone` rollup counts task tags only (untagged tasks stay in +the sentinel bucket) — tag tasks individually, or use `new … --milestone`, if +you want them counted under the target. + `milestone --table` gives the delivery-oriented view — each milestone, the -features assigned to it, and the milestone's status: +features assigned to it (directly or via their tagged tasks), and the +milestone's status: ``` MILESTONE FEATURES STATUS diff --git a/schema.md b/schema.md index ea87faa..b6e6066 100644 --- a/schema.md +++ b/schema.md @@ -71,7 +71,10 @@ A task may carry one `@milestone=` tag. It is fully optional and orthogonal to `@system=`/`@tags=`: files with no milestone data behave exactly as before, and a task without the tag falls into an implicit sentinel bucket named `default` (override via `TASKS_MILESTONE_SENTINEL`; it must not look like -an `M` id). The sentinel is never written into task lines. +an `M` id). The sentinel is never written into task lines. Assignment is +per-item: a task does **not** inherit its parent feature's milestone — the +`milestone` rollup counts task tags only, while `--table` attributes a feature +directly or via its tagged tasks. An optional `# Milestones` registry (its own H1 section) maps ids → alias → status → title, and powers alias resolution + rollups: diff --git a/tasks.py b/tasks.py index a25189c..af2027c 100755 --- a/tasks.py +++ b/tasks.py @@ -90,7 +90,10 @@ data behaves exactly as before, and a task without the tag resolves to an implicit sentinel bucket named "default" (configurable via the TASKS_MILESTONE_SENTINEL env var; it must not look like an M id). The -sentinel is never written into task lines. +sentinel is never written into task lines. Assignment is per-item: a task does +NOT inherit its parent feature's milestone — the `milestone` rollup counts task +tags only (untagged tasks stay in the sentinel bucket), while `milestone +--table` attributes a feature directly or via its tagged tasks. An optional "# Milestones" registry (its own H1 section) maps ids to aliases, statuses, and titles. When present it powers alias resolution (@milestone=alpha @@ -198,7 +201,7 @@ from pathlib import Path from typing import List, Tuple, Optional, Dict, Set, Iterator -__version__ = "1.4.0" +__version__ = "1.4.1" # Canonical source for `selfupdate` — the published raw URL. `selfupdate` # overwrites this very script with the fetched content, so a NON-default source