From 315464ecdd57ffef7e075e3207420b5efb7ca90c Mon Sep 17 00:00:00 2001 From: "@permadeath.com" Date: Sun, 16 Aug 2026 13:45:33 -0400 Subject: [PATCH] feat(plan): a fifth status, for work that is not being pursued `declined` sits beside shipped, open, blocked and continuous, with a Not pursued table of its own. It is not `blocked`, which is waiting, and it is not an epic that has drifted to the bottom of the order: it is a question somebody could reasonably ask, answered no. Until now the register had nowhere to put an answer, so a reason lived in whichever epic happened to be adjacent to it, or nowhere at all. Co-Authored-By: Claude Opus 5 (1M context) --- plan/README.md | 22 ++++++++++++++++++++-- prek.toml | 2 +- scripts/check-plan.py | 2 +- scripts/gen-plan-readme.py | 11 ++++++++--- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/plan/README.md b/plan/README.md index 6101ab1..fd9fc57 100644 --- a/plan/README.md +++ b/plan/README.md @@ -67,9 +67,15 @@ adjacent code is open. Accessibility and copy are like this: they are never done, and pretending otherwise just produces an epic that is permanently 80% complete. +`declined` — decided against. Not `blocked`, which is waiting, and not an epic +sitting late in the order: somebody could have expected the project to do it, +and the answer is no rather than not yet. The file stays and the id stays a +valid commit scope, because the reason something is not being built is worth as +much as the reason something is. + ## The tables are generated -The four tables below are output, not source. `scripts/gen-plan-readme.py` +The five tables below are output, not source. `scripts/gen-plan-readme.py` reads every epic's frontmatter and rewrites what sits between the `` fences. Everything around them is hand-written and is passed through untouched, so prose can go anywhere except inside a fence. The @@ -83,7 +89,7 @@ that is what stops two branches each adding an epic from conflicting over rows neither of them cared about. Which table an epic lands in follows from the file as well. [complete/](complete/) -is Complete, and outside it the status picks between the other three. Shipping +is Complete, and outside it the status picks between the other four. Shipping an epic, or archiving it, is an edit to the epic and nothing else. ## Complete @@ -165,6 +171,18 @@ fix before it has been exercised than after. | [arena-image](arena-image.md) | The image is small, current and reproducible | +## Not pursued + +Answered no. What a file here holds is a list of answers rather than a line of +work: what the project is not building and why, written down so that a question +somebody has already settled is not settled again differently by the next person +to ask it. + + +| id | title | +|---|---| + + ## Where the schemas are There is no lexicon epic. A `blue.lance.*` or `games.permadeath.*` schema is a diff --git a/prek.toml b/prek.toml index f6628f7..f84a5ed 100644 --- a/prek.toml +++ b/prek.toml @@ -82,7 +82,7 @@ entry = "scripts/check-plan.py" pass_filenames = false files = '^plan/.*\.md$' -# plan/README.md's four tables are generated from that same frontmatter, so a +# plan/README.md's five tables are generated from that same frontmatter, so a # row cannot quietly stop matching the epic it points at, and adding an epic # does not mean editing tables every other branch is also editing. A failure # here means the register is stale: run scripts/gen-plan-readme.py and stage diff --git a/scripts/check-plan.py b/scripts/check-plan.py index f8faacd..49ed26b 100755 --- a/scripts/check-plan.py +++ b/scripts/check-plan.py @@ -29,7 +29,7 @@ import sys REQUIRED_KEYS = ["id", "title", "status", "repos", "dependsOn", "exitCriterion"] # Documented in plan/README.md, under "Status". -VALID_STATUS = ["shipped", "open", "blocked", "continuous"] +VALID_STATUS = ["shipped", "open", "blocked", "continuous", "declined"] LINK_RE = re.compile(r"(?