From 0429148e985b72fc5b54a270a7629aa19fa348e8 Mon Sep 17 00:00:00 2001 From: Dustin VanKrimpen Date: Sat, 18 Jul 2026 17:30:24 -0400 Subject: [PATCH 1/4] wherefore: add plan skill and wire the sibling skills to it Add a plan skill under /wherefore:plan for the wherefore/plan/ collection: one verb with four intents (open, advance, drop, read), spikes via an optional answers key, and the full P-NNN frontmatter contract. Open breaks work into checkboxes; advance and read tolerate prose-only bodies. Wire the siblings around it, read-only or hand-off, so plan stays the sole writer of plan/: - capture surfaces plan links for approval and hands off to plan (advance to close, open for implied work); it never writes plan/ and never auto-closes on inference. - ask surfaces spikes (answers) alongside open questions. - resolve reports unblocked and answered items and skips dropped ones. - supersede flags plan items whose decision_ref points at a retired decision, read-only. Driver suppression both directions (capture drives advance, plan drives resolve) prevents handoff loops. seed scaffolds plan/ and its README on a fresh repo. The frontmatter contract is documented consistently across the plan skill, capture, seed, AGENTS.md, and CLAUDE.md. Both project rules (no em dashes; never delete under a wherefore/ data dir) now appear in all five skills. Fix next-ID allocation in capture and plan to read the authoritative id from frontmatter instead of scanning filenames, which is how two Q-008s were allocated; renumber the newer duplicate (ibm-plex) to Q-011. Dogfood records: the capture-does-not-write-plan-items decision, plan items P-004 through P-010, and questions Q-010 and Q-011. Co-Authored-By: Claude Opus 4.8 (1M context) --- AGENTS.md | 44 ++- CLAUDE.md | 9 +- plugins/wherefore/commands/seed.md | 94 ++++++- plugins/wherefore/skills/ask/SKILL.md | 23 ++ plugins/wherefore/skills/capture/SKILL.md | 28 +- plugins/wherefore/skills/plan/SKILL.md | 265 ++++++++++++++++++ plugins/wherefore/skills/resolve/SKILL.md | 21 ++ plugins/wherefore/skills/supersede/SKILL.md | 15 + wherefore/ROADMAP.md | 63 +++++ .../2026-07-03-entry-view-theming-and-css.md | 45 +++ ...07-18-capture-does-not-write-plan-items.md | 40 +++ wherefore/plan/P-001-ship-0-1-1-patch.md | 13 + wherefore/plan/P-002-add-plan-collection.md | 14 + wherefore/plan/P-003-saas-extension.md | 15 + wherefore/plan/P-004-author-plan-skill.md | 22 ++ wherefore/plan/P-005-capture-plan-handoffs.md | 17 ++ .../plan/P-006-ask-resolve-plan-links.md | 18 ++ .../plan/P-007-scaffold-plan-and-docs.md | 17 ++ wherefore/plan/P-008-refine-plan-contract.md | 22 ++ wherefore/plan/P-009-fix-sibling-skills.md | 21 ++ .../P-010-allocate-id-from-frontmatter.md | 19 ++ wherefore/plan/README.md | 83 ++++++ .../Q-010-capture-restates-supersession.md | 32 +++ .../questions/Q-011-ibm-plex-preconnect.md | 10 + 24 files changed, 944 insertions(+), 6 deletions(-) create mode 100644 plugins/wherefore/skills/plan/SKILL.md create mode 100644 wherefore/ROADMAP.md create mode 100644 wherefore/log/2026-07-03-entry-view-theming-and-css.md create mode 100644 wherefore/log/2026-07-18-capture-does-not-write-plan-items.md create mode 100644 wherefore/plan/P-001-ship-0-1-1-patch.md create mode 100644 wherefore/plan/P-002-add-plan-collection.md create mode 100644 wherefore/plan/P-003-saas-extension.md create mode 100644 wherefore/plan/P-004-author-plan-skill.md create mode 100644 wherefore/plan/P-005-capture-plan-handoffs.md create mode 100644 wherefore/plan/P-006-ask-resolve-plan-links.md create mode 100644 wherefore/plan/P-007-scaffold-plan-and-docs.md create mode 100644 wherefore/plan/P-008-refine-plan-contract.md create mode 100644 wherefore/plan/P-009-fix-sibling-skills.md create mode 100644 wherefore/plan/P-010-allocate-id-from-frontmatter.md create mode 100644 wherefore/plan/README.md create mode 100644 wherefore/questions/Q-010-capture-restates-supersession.md create mode 100644 wherefore/questions/Q-011-ibm-plex-preconnect.md diff --git a/AGENTS.md b/AGENTS.md index 64b1c03..9e88960 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,7 +12,7 @@ wherefore/ topics.md controlled tag vocabulary: Areas and Topics log/YYYY-MM-DD-short-slug.md one decision per file questions/Q-NNN-short-slug.md one question per file (ID prefix + scannable slug) - plan/short-slug.md forward-looking plans and roadmaps, one per file + plan/P-NNN-short-slug.md forward-looking plan items, one per file ``` If `wherefore/` does not exist, create it plus `log/`, `questions/`, a starter @@ -127,6 +127,48 @@ To resolve: set the Q-file `status: resolved`, fill `resolution` (one sentence) `resolution_slug` (source slug, or blank if standalone). The frontmatter is the only place the status lives. +## Plan items + +Forward-looking work items live in `wherefore/plan/P-NNN-short-slug.md`, one per file, a +separate collection from decisions. A plan item is a committed intention; a decision is a +resolved ruling. Do not create plan items for work a decision merely implies unless a human +asks; commitments nobody chose are noise. + +Next P-ID = (highest `id:` across `wherefore/plan/P-*.md`) + 1; IDs are sequential and never +reused, including numbers freed by dropped items. The `id:` field is authoritative; the +filename slug is only for human scanning. Use this frontmatter: + +```markdown +--- +id: P-NNN +title: Short human title +status: todo # todo | doing | done | dropped +created: YYYY-MM-DD +updated: # YYYY-MM-DD, set on ANY write: status change or body edit, including a checkbox toggle +area: # single area from topics.md, or omit +topics: [] # cross-cutting topics from topics.md, or omit +milestone: # M1, defined in wherefore/ROADMAP.md, or omit +decision_ref: # one or more YYYY-MM-DD decision slugs, comma-separated, no .md; or omit +question_ref: # a single Q-NNN this item is blocked on, or omit +answers: # a single Q-NNN this item is the work of answering (a spike), or omit +dropped_reason: # short why, used when status: dropped +--- +``` + +Body: break the work into `- [ ]` checkboxes concrete enough to check off; prose is valid too. + +- Status flow is `todo -> doing -> done`; any move to `dropped` is abandonment and requires a + `dropped_reason` or a `decision_ref`. Dropped items are kept, never deleted; the dropped item + plus its reason IS the plan-change record. +- `blocked` is never written. It is derived: an item is blocked while it carries a + `question_ref` to an open question. At most one blocking question per item. +- `answers` is a single `Q-NNN` a spike is the work of answering. It is the opposite of + `question_ref` (blocked by) and does not make the item blocked. Never point `answers` and + `question_ref` at the same `Q-NNN`. +- Plan status is a separate state machine from decision status. Never put + `active`/`superseded`/`obsolete` on a plan item, or `todo`/`doing`/`done`/`dropped` on a + decision. Retiring or replacing a decision is a supersession on the decision, not a plan edit. + ## Conventions - All frontmatter keys use underscore style (superseded_by, superseded_date, diff --git a/CLAUDE.md b/CLAUDE.md index d19ea06..6de7935 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,7 +6,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## What this repo is -A Claude Code plugin marketplace. It hosts the `wherefore` plugin, which ships four skills and a command for capturing technical decisions into a repo-committed wherefore log, querying them later, closing out open questions, and retiring superseded or obsolete decisions. The marketplace itself has no build system, tests, or runtime -- the only "code" is JSON manifests, Markdown skill/command definitions, and a GitHub Actions CI workflow. +A Claude Code plugin marketplace. It hosts the `wherefore` plugin, which ships five skills and a command for capturing technical decisions into a repo-committed wherefore log, querying them later, closing out open questions, retiring superseded or obsolete decisions, and tracking forward-looking plan items. The marketplace itself has no build system, tests, or runtime -- the only "code" is JSON manifests, Markdown skill/command definitions, and a GitHub Actions CI workflow. ## Validation @@ -61,6 +61,10 @@ plugins/wherefore/ skills/supersede/ SKILL.md # marks an entry superseded (with pointer to # replacement) or obsolete via its frontmatter + skills/plan/ + SKILL.md # manages wherefore/plan/ items (open, advance, + # drop, read): one verb, four intents; never + # writes log/ or questions/, hands off instead ``` The `wherefore/` directory itself is **not** in this repo -- it lives in each consuming project's repo, created by the skills on first use. @@ -71,6 +75,7 @@ The `wherefore/` directory itself is **not** in this repo -- it lives in each co - **Command `.md`** front matter: `description`, `argument-hint`, `allowed-tools`. - All skills use a two-facet tag system: **areas** (feature slices: WHAT) and **topics** (cross-cutting concerns: HOW), drawn from the consuming project's `wherefore/topics.md`. Keep this separation consistent if extending the skills. - Entry and question frontmatter is the single source of truth: `ask` derives its shortlist by reading only the leading frontmatter block of each file. Derive on read; do not add a generated index. -- `capture` is write-heavy (creates/edits files); a single discussion may produce multiple entry files when it covers independently-queryable threads. `ask` is read-only. `resolve` edits only the `questions/Q-NNN-short-slug.md` file (and optionally the source entry). `supersede` edits an existing entry file's frontmatter and adds a banner. `seed` is read-first, write-only-after-confirmation -- preserve this ask-before-write pattern for any new commands. +- `capture` is write-heavy (creates/edits files); a single discussion may produce multiple entry files when it covers independently-queryable threads. `ask` is read-only. `resolve` edits only the `questions/Q-NNN-short-slug.md` file (and optionally the source entry). `supersede` edits an existing entry file's frontmatter and adds a banner. `plan` is the only writer of `wherefore/plan/`: it opens, advances, drops, and reads plan items and never writes `log/` or `questions/` (it hands off to `capture` and `ask` instead). `capture` never creates plan items; when a decision resolves or implies work it hands off to `plan`. `seed` is read-first, write-only-after-confirmation -- preserve this ask-before-write pattern for any new commands. - Entry filenames: `YYYY-MM-DD-short-slug.md`; the entry frontmatter (`date`, `title`, `areas`, `topics`, `stories`, `status`, `supersedes`, `superseded_by`, `superseded_date`) is what readers shortlist on. - Question files: `questions/Q-NNN-short-slug.md` (the `Q-NNN` prefix is the zero-padded ID; the slug is a short, lowercase, hyphenated summary of the question, same style as a log slug and only for human scanning). One per question, with `id`, `question`, `status`, `areas`, `asked_date`, `asked_slug`, `resolution`, `resolution_slug` frontmatter. The `id:` field is the authoritative ID (the dashboard keys off it, not the filename). IDs are sequential and never reused; the next ID is (highest existing `id:`) + 1. +- Plan items: `plan/P-NNN-short-slug.md` (the `P-NNN` prefix is the zero-padded ID; the `id:` field is authoritative, and the loader globs `plan/P-*.md` so `plan/README.md` is never collected). Frontmatter: `id`, `title`, `status` (todo|doing|done|dropped), `created`, `updated` (bumped on any write, including a checkbox toggle), plus optional `area` (single, not the plural `areas` decisions use), `topics`, `milestone`, `decision_ref`, `question_ref`, `answers` (a single `Q-NNN` a spike is the work of answering, the opposite of `question_ref` and not a blocker), `dropped_reason`. Plan status is a separate state machine from decision status: `capture` never creates or mutates plan items, and plan transitions never touch a decision's status (that stays with `supersede`). `blocked` is derived from an open `question_ref` (at most one per item), never written. IDs are sequential and never reused; the next ID is (highest existing `id:`) + 1. diff --git a/plugins/wherefore/commands/seed.md b/plugins/wherefore/commands/seed.md index 569d763..20ecc8b 100644 --- a/plugins/wherefore/commands/seed.md +++ b/plugins/wherefore/commands/seed.md @@ -58,9 +58,101 @@ approval; wait for their reply before writing anything. - If `wherefore/topics.md` does NOT exist: create the `wherefore/` directory and write the confirmed vocabulary as `wherefore/topics.md` in the two-section format - above. The `capture` skill scaffolds the rest of the directory on first use. + above. The `capture` skill scaffolds `log/`, `questions/`, and the top-level + `README.md` on first use. - If it DOES exist: treat the existing file as the source of truth and MERGE: append only the new, confirmed tags under the correct section, and never remove or rename anything already there. Report exactly which tags you added. +- When creating `wherefore/` fresh (or when `wherefore/` exists but `wherefore/plan/` + does not), scaffold the `plan/` collection: create `wherefore/plan/` and write + `wherefore/plan/README.md` with exactly the content below. The loader globs + `plan/P-*.md`, so this `README.md` is never collected as an item. Do NOT write any + P-item; opening items is the `plan` skill's job. + + ````markdown + # Plan collection (`wherefore/plan/`) + + Plan items are a first-class collection under `wherefore/`, parallel to `questions/`. + They track forward-looking work and its state (todo / doing / done / dropped) and + preserve plan-change history by keeping dropped items rather than deleting them. This + collection is durable and retire-don't-delete, the same as the rest of `wherefore/`. + + Plan status is a separate state machine from decision status. Do not reuse active / + superseded / obsolete here, and do not put todo / doing / done / dropped on decisions. + + ## Files + + - Path: `wherefore/plan/P-NNN-slug.md`. The slug is browsability sugar. + - The `id` field in frontmatter is authoritative and drives the item's identity, + exactly like `Q-NNN`. Filename casing cannot cause collisions. + - The loader globs `plan/P-*.md`, so only plan-item files are collected. This + `README.md` is ignored. + - Next ID = (highest `id:` across the P-*.md files) + 1. IDs are sequential and never + reused, including numbers freed by dropped items. + + ## Frontmatter + + | key | req | type | notes | + |-----------------|-----|-------------------|-------------------------------------------------------------| + | `id` | yes | `P-NNN` | authoritative, drives the item id | + | `title` | yes | string | short human title | + | `status` | yes | enum | `todo` / `doing` / `done` / `dropped` | + | `created` | yes | `YYYY-MM-DD` | creation date | + | `updated` | no | `YYYY-MM-DD` | set on any write (status change or body edit, including a checkbox toggle); this IS the plan-change timestamp | + | `area` | no | string | single area, reuse existing area vocabulary | + | `topics` | no | list | reuse existing cross-cutting topics | + | `milestone` | no | `M1` | milestone this item serves, defined in `wherefore/ROADMAP.md`| + | `decision_ref` | no | slug or slug list | originating or superseding decision(s), `supersedes` format | + | `question_ref` | no | `Q-NNN` | a single open question this item is blocked on | + | `answers` | no | `Q-NNN` | a single question this item is the work of answering (spike)| + | `dropped_reason`| no | string | lightweight why, used when `status: dropped` | + + Body: freeform. The `plan` skill breaks the work into `- [ ]` checkboxes by default + (steps concrete enough to check off); prose stays valid, and older items may be + prose-only. + + ## Status vocabulary + + `todo` -> `doing` -> `done` is the normal flow. Any transition to `dropped` is + abandonment. `dropped` is terminal but kept: a dropped item, with `updated` marking + when and `dropped_reason` or `decision_ref` marking why, IS the plan-change record. + + `blocked` is derived, not a status. An item is blocked if it carries a `question_ref` + to an open question. It never lives in frontmatter. An item carrying `answers` (a spike + investigating a question) is not blocked; `answers` is the opposite relationship. + + ## Linking conventions + + - `milestone`: a single milestone ID (`M1`) defined in `wherefore/ROADMAP.md`. One-way: + the item points up at the milestone. + - `decision_ref`: one or more decision log slugs in `YYYY-MM-DD-slug` form (no `.md`), + comma-separated for multiple, mirroring the `supersedes` convention. + - `question_ref`: a single `Q-NNN` the item waits on. By deliberate choice an item is + blocked by at most one question. + - `answers`: a single `Q-NNN` this item investigates (a spike). The opposite of + `question_ref`: an item that `answers` a question is not blocked by it. An item may + carry both (rare but legal); never point them at the same `Q-NNN`. + + ## Key casing + + Single-word keys are bare (`id`, `title`, `status`, `created`, `updated`, `area`, + `topics`, `milestone`, `answers`). Compound keys use underscore (`decision_ref`, + `question_ref`, `dropped_reason`). A hyphen in a compound key parses silently and drops + the link. + + ## Boundaries + + - The `plan` skill writes only `wherefore/plan/*`. Never `log/`, never `questions/`, + never `ROADMAP.md`. + - Durable why belongs in the decision layer: when a plan item's rationale is really a + decision, that is a `capture`; when a direction changes for a reason worth keeping, + that is a `supersede` on the decision, and the plan item flips to `dropped` carrying + `decision_ref` to it. + - `capture` never creates plan items and never writes plan status directly; it may hand + off to the `plan` skill. The `plan` skill records that something changed; the decision + layer owns the durable why. + + Maintained by the [wherefore](https://github.com/DustinVK/wherefore) plan skill. + ```` Finish with a one-line summary of what was written and where. diff --git a/plugins/wherefore/skills/ask/SKILL.md b/plugins/wherefore/skills/ask/SKILL.md index 78ec87a..75f2b1e 100644 --- a/plugins/wherefore/skills/ask/SKILL.md +++ b/plugins/wherefore/skills/ask/SKILL.md @@ -19,6 +19,10 @@ they actually say. The cardinal rule: **ground every answer in entries that exist.** If the wherefore has nothing on the topic, say so: a confident answer assembled from nothing is worse than "I didn't find anything about that." +No em dashes. Periods, commas, colons, semicolons, or parentheses instead. Firm project rule. + +Never delete anything under a `wherefore/` data dir. Retire, do not delete. + ## Storage layout The wherefore lives under a repo-relative `wherefore/` directory: @@ -121,6 +125,25 @@ fabricate an answer. Only show open questions; skip resolved ones unless the user explicitly asks (e.g. "what was Q-007?" or "show resolved questions too"). If no open questions match, omit the section entirely; do not add noise. + When you dump the question frontmatter, also dump `wherefore/plan/P-*.md` frontmatter + and cross-check `answers`: if a plan item carries `answers: `, the question + is being actively investigated (a spike), not sitting untouched. Note it inline, e.g. + "Q-007 (P-012 is investigating this, status doing)". That is exactly when the user needs + to know work is already underway. Read-only; `ask` still writes nothing. + +8. **Offer to link a blocking question to a plan item.** When a question surfaced + above (or one the user just raised) blocks work in flight, offer to attach it as a + `question_ref` on the relevant plan item. The link is one-way, from the plan item + to the question. Making the attachment is a `plan` operation (its advance intent); + `ask` only offers it and does not write `plan/` itself. Optionally, when the user + is clearly asking about in-flight work, surface matching plan items alongside the + open questions, still read-only, by dumping `wherefore/plan/P-*.md` frontmatter the + same cheap way and filtering on `area` and status. + + Plan fields `ask` relies on: `status` (to tell in-flight from untouched), `question_ref` + (blocked is derived from it and never stored), and `answers` (the opposite direction, a + spike investigating the question). `ask` never writes plan files, so it needs none of the + plan key order or quoting rules. ## Answering style diff --git a/plugins/wherefore/skills/capture/SKILL.md b/plugins/wherefore/skills/capture/SKILL.md index 42223be..0772a1c 100644 --- a/plugins/wherefore/skills/capture/SKILL.md +++ b/plugins/wherefore/skills/capture/SKILL.md @@ -18,6 +18,10 @@ Preserve the useful residue (what was decided, why, and what was rejected), not transcript. Months later, someone asking "why did we build it this way?" should get the answer in a few sentences. +No em dashes. Periods, commas, colons, semicolons, or parentheses instead. Firm project rule. + +Never delete anything under a `wherefore/` data dir. Retire, do not delete. + ## Writing style The record must read well as a raw markdown file, not just in the dashboard. Editors @@ -143,7 +147,12 @@ scalar to a one-line summary and move the detail into a body section. 8. Write `wherefore/log/YYYY-MM-DD-short-slug.md`. Slug short, lowercase, hyphenated, recognizable (`oauth-token-refresh`, not `discussion-about-the-auth-stuff`). If the name exists, add a short suffix; never overwrite. 9. Register open questions. For each genuine unresolved item: - - Next Q-ID = (highest `id:` across `wherefore/questions/Q-*.md`) + 1. Derive it from the files, e.g. `ls wherefore/questions/Q-*.md 2>/dev/null | sed -E 's|.*/Q-0*([0-9]+).*|\1|' | sort -n | tail -1`. If the directory is empty or absent, start at Q-001. IDs are sequential and never reused. (The regex tolerates both the legacy `Q-NNN.md` and the current `Q-NNN-slug.md` naming.) + - Next Q-ID = (highest `id:` across `wherefore/questions/Q-*.md`) + 1. Read the authoritative `id:` from each file's frontmatter, not the filename: `id:` is the source of truth and the filename slug is only browsability sugar, so allocating off filenames is how duplicate IDs get created. + ```bash + for f in wherefore/questions/Q-*.md; do awk -F': *' '/^id:/{print $2; exit}' "$f"; done 2>/dev/null \ + | sed -E 's/Q-0*([0-9]+)/\1/' | sort -n | tail -1 + ``` + If the directory is empty or absent, start at Q-001. IDs are sequential and never reused. - Prefix the entry's item with the ID: `- Q-001: How should we ...` - Create `wherefore/questions/Q-NNN-short-slug.md`, leaving `resolution` and `resolution_slug` blank. Name it like a log entry: `Q-` + the zero-padded ID + a short, lowercase, hyphenated slug distilled from the question (`Q-001-eu-buyer-tax`, not `Q-001-question-about-tax-stuff`). The `Q-NNN` prefix keeps questions sorted and greppable by number; the slug is for human scanning; the authoritative ID is always the `id:` frontmatter field. ``` @@ -166,7 +175,22 @@ scalar to a one-line summary and move the detail into a body section. - For each confirmed: set the Q file `status: resolved`, fill `resolution` (one quoted sentence), set `resolution_slug` to the new slug. Report closures. - No match: skip silently. -11. Report back. Show the title, assigned areas and topics (flag any new tag), linked stories, any supersession applied, and any Q-IDs assigned or closed. This is the approval moment: you distilled and tagged on the user's behalf, so let them correct it before it ossifies. `ask` derives everything from the frontmatter you just wrote. +11. Report back and confirm. This is the approval moment. Show the title, assigned areas and topics (flag any new tag), linked stories, any supersession applied, and any Q-IDs assigned or closed. Then fold plan links into the same approval: dump plan frontmatter the cheap way and shortlist by area overlap, exactly as step 10 shortlists questions. + ```bash + for f in wherefore/plan/P-*.md; do + awk -v F="$f" 'BEGIN{print "=== " F " ==="} + /^---[[:space:]]*$/ { n++; if (n==2) exit; next } + n==1 { print }' "$f" + done + ``` + - If the decision plainly resolves a shortlisted open plan item, name it as a candidate to close. Do not close on inference; plan items get the same ask-first standard step 10 gives questions. + - If the decision implies new work, name the pieces you would open. + You distilled, tagged, and propose these plan links on the user's behalf, so let them correct all of it before it ossifies. `ask` derives everything from the frontmatter you just wrote. + +12. Act on the confirmed plan links, but never create or mutate `plan/` from here; hand off to the `plan` skill. Capture owns `log/`, `plan` owns `plan/`. + - Confirmed close: hand off to `plan` advance to set that item `status: done` and add `decision_ref: `. The handoff marks capture as the driver, so `plan` advance suppresses its return capture offer (this decision is already being captured) and the path does not loop. Safe because it resolves a commitment already made, it does not invent one. + - Confirmed new work: hand off to `plan` open, with `decision_ref: ` set on each item. + On no confirmation, write nothing to `plan/`. Never auto-emit plan items and never auto-close them: manufacturing or silently closing commitments nobody chose is the rot the plan collection exists to avoid (decision `2026-07-18-capture-does-not-write-plan-items`). ## Examples diff --git a/plugins/wherefore/skills/plan/SKILL.md b/plugins/wherefore/skills/plan/SKILL.md new file mode 100644 index 0000000..34903a5 --- /dev/null +++ b/plugins/wherefore/skills/plan/SKILL.md @@ -0,0 +1,265 @@ +--- +name: plan +description: > + Manage forward-looking plan items in the team's wherefore plan collection. Use + whenever the user wants to open a new plan item, advance one along (todo to doing + to done), drop one, or ask what they are working on, e.g. "add a plan item for X", + "start on P-101", "mark P-102 done", "what's on the plan", "what am I working on", + "drop P-103, we're not doing it", or invoke "/wherefore:plan". Detects the intent + from the request rather than taking subcommands. Breaks work into concrete + checkboxes on open; never bulk-generates plan items from a vague prompt. +--- + +# Wherefore: plan + +Operate the wherefore plan collection: forward-looking work items, one file each, +tracking what is committed and how far along it is. A plan item is a commitment, not +a decision. Decisions (the why) live in `log/` and are owned by `capture`; open +questions live in `questions/`. This skill writes only `wherefore/plan/`, never +`log/` or `questions/`. + +The skill is one verb with four intents, read from the request: open a new item, +advance one, drop one, or read what is in flight. The real work of open is +decomposition: break the item into checkboxes concrete enough to actually check off, +and push the user for specifics rather than writing vague steps. A plan item nobody +can act on is worse than none. + +No em dashes. Periods, commas, colons, semicolons, or parentheses instead. Firm project rule. + +Never delete anything under a `wherefore/` data dir. Retire, do not delete. + +## Storage layout + +Plan items live under a repo-relative `wherefore/` directory: + +``` +wherefore/ +├── topics.md # controlled tag vocabulary (areas + topics) +└── plan/ + ├── README.md # the item format (not an item; ignored by the loader) + └── P-NNN-short-slug.md # one file per plan item (ID prefix + scannable slug) +``` + +The loader globs `plan/P-*.md`, so only P-item files are collected; `README.md` and +any other doc in `plan/` is ignored. The `id` frontmatter field is authoritative and +drives the item's identity, exactly like `Q-NNN`; the filename slug is browsability +sugar and cannot cause a collision. If `wherefore/plan/` does not exist, create it +(the `seed` command scaffolds `plan/` and its `README.md` on a fresh repo); never +invent a second location. + +## Frontmatter + +Write every item with this frontmatter, in this key order (matching `plan/README.md` +so diffs stay clean). Omit optional keys that have no value rather than emitting them +blank. + +```yaml +--- +id: P-001 # authoritative, P + zero-padded number +title: Ship the 0.1.1 patch # short human title +status: todo # todo | doing | done | dropped +created: 2026-06-20 # YYYY-MM-DD, set once on open +updated: 2026-07-03 # YYYY-MM-DD, set on ANY write to the item (see below) +area: dashboard # single area, reuse topics.md Areas; optional +topics: [release] # inline flow list, reuse topics.md Topics; omit when empty +milestone: M1 # milestone this serves, defined in wherefore/ROADMAP.md; optional +decision_ref: 2026-07-03-companion-plan-collection # originating/superseding decision(s); optional +question_ref: Q-007 # a single open question this item is blocked on; optional +answers: Q-009 # a single question this item is the work of answering (spike); optional +dropped_reason: > # why, when status is dropped; optional + Short reason kept for history. +--- +``` + +- `status` is a separate state machine from decision status. Never put + `active`/`superseded`/`obsolete` on a plan item, and never put + `todo`/`doing`/`done`/`dropped` on a decision. +- `updated` is set to today on ANY write to the item: a status change OR a body edit, + including checking or unchecking a single box. It is the plan-change timestamp and + must not lie. A brand-new `todo` item that has never been touched again has no + `updated` key. +- `blocked` is NOT a status. It is derived: an item is blocked when it carries a + `question_ref` to an open question. Never write `blocked`. +- `question_ref` is a single `Q-NNN`. By deliberate choice an item is blocked by at + most one question; this is a fixed constraint, not an unstated limit. +- `answers` is a single `Q-NNN` this item is the work of answering (a spike). It is the + semantic opposite of `question_ref`: `question_ref` means blocked by that question, + `answers` means investigating it, so an item carrying `answers` is NOT blocked. An item + may carry both, answering one question while blocked on another: rare but legal. Never + point `answers` and `question_ref` at the same `Q-NNN`; an item cannot be both blocked on + a question and the work of answering it. If asked to, refuse and say why. +- `decision_ref` is one or more `YYYY-MM-DD` decision slugs, comma-separated, with no + `.md` extension. This mirrors the `supersedes` convention, so there is one linking + format across the repo. +- `area` is singular here (a plan item has one area), unlike the plural `areas` list + on decisions. Reuse the vocabulary in `topics.md`; if an existing item uses a tag + not in `topics.md`, keep it, do not rewrite it. + +Compound keys use underscores (`decision_ref`, `question_ref`, `dropped_reason`). A +hyphen parses silently and drops the link. + +## Frontmatter safety + +Emit the free-text scalars `title` and `dropped_reason` safely. Quote `title` as a +double-quoted single-line string when it contains a `: ` (colon-space) or a leading +`-`, `#`, `[`, `{`, or `"`, escaping embedded `"` as `\"` and `\` as `\\`; a plain +title (`Ship the 0.1.1 patch`) needs no quotes, and existing unquoted titles must not +be rewritten. If `dropped_reason` runs long, a folded block scalar (`>`) over indented +lines is fine (P-003 uses one). Controlled fields (`id`, `status`, `created`, +`updated`, slugs, the `topics` list) never need quotes. + +## Workflow + +First, read the request and decide which intent it is: open (create a new item), +advance (move one along), drop (retire one), or read (report what is in flight). When +it is ambiguous, ask. Read `wherefore/topics.md` once if you will write `area`/`topics`. + +To list or find items cheaply, dump only the leading frontmatter of each item: + +```bash +for f in wherefore/plan/P-*.md; do + awk -v F="$f" 'BEGIN{print "=== " F " ==="} + /^---[[:space:]]*$/ { n++; if (n==2) exit; next } + n==1 { print }' "$f" +done +``` + +### Intent: open (create a new item) + +1. Allocate the next P-NNN: highest `id` across `plan/P-*.md` plus one. Read the + authoritative `id:` from each file's frontmatter, not the filename (the filename slug is + only browsability sugar, so allocating off filenames is how duplicate IDs get created): + ```bash + for f in wherefore/plan/P-*.md; do awk -F': *' '/^id:/{print $2; exit}' "$f"; done 2>/dev/null \ + | sed -E 's/P-0*([0-9]+)/\1/' | sort -n | tail -1 + ``` + Empty or absent dir starts at P-001. IDs are sequential and never reused, including + numbers freed by dropped items. +2. Break the work into checkboxes. This is the point of the skill. Turn the plan into + `- [ ]` steps concrete enough to check off. If the user's description is vague, push + for specifics ("what are the actual steps?") rather than writing filler. Never + bulk-generate items from a vague prompt: a plan item is a commitment, and + manufacturing commitments in bulk is the failure this collection exists to avoid. +3. Set frontmatter: `id`, `title`, `status: todo`, `created` today. Add `area`/`topics` + from `topics.md` if the item has them; add `milestone`, `question_ref`, or + `decision_ref` if the user gives them. Do not set `updated` on a brand-new item. +4. Write `wherefore/plan/P-NNN-short-slug.md` (slug short, lowercase, hyphenated). If + the name exists, add a suffix; never overwrite. +5. Report the id, title, tags, any refs, and the checkbox count. + +### Intent: advance (move an item along) + +1. Find the item (glob by id: `ls wherefore/plan/P-004-*.md`). Open it. +2. Move `status`. The normal flow is `todo -> doing -> done`. Reopening is allowed: + `done -> doing` when work resumes. It bumps `updated` and unchecks nothing + automatically; the user says which boxes reopen. Check or uncheck the body boxes to + match progress. +3. Set `updated` to today. This applies to ANY write, including toggling a single + checkbox, not only a status change. +4. Tolerate a prose-only body: an older or hand-written item may have no checkboxes. + That is fine; just make the status change. +5. Advancing a blocked item: if the item carries a `question_ref` to a question still + open, allow the move to `doing` but warn. Report that the item is still blocked on + Q-NNN and ask whether that question should be resolved via `resolve` first. Do not + refuse the transition. +6. On reaching `done`, decide the handoff by who drove the transition: + - A human asked to mark it done: ask whether there is a decision worth capturing + (the why behind finishing this way), and hand off to the `capture` skill if yes. + Do not write `log/` yourself. + - The `capture` skill drove this advance (it invoked advance to mark an item done + and set `decision_ref` because a captured decision resolved the item): suppress + the offer. The decision that would be captured is the one that just called in; + offering to capture it would loop. + - If the item carries `answers: Q-NNN` (a spike), the capture offer above still + applies, and additionally offer to resolve that answered question via `resolve`. Do + not resolve it silently; finishing the investigation is not the same as having an + answer. This handoff marks `plan` as the driver, so `resolve` suppresses its return + offer to advance this item, the same way capture-driven advance suppresses its capture + offer. +7. To block an item, attach a `question_ref` to the open question it waits on. If that + question does not exist yet, create it via the `ask` skill first, then set the ref. + Never write a `blocked` status; blocked is derived from the ref. +8. Report the transition, the `updated` date, any boxes toggled, and any handoff. + +### Intent: drop (retire an item) + +1. Find and open the item. +2. Require a reason: either a `dropped_reason` (a short why) or a `decision_ref` to the + decision that killed it. If the user gives neither, ask for the reason; refuse to + drop without one. +3. Set `status: dropped`, set `updated` to today, and add `dropped_reason` and/or + `decision_ref`. The dropped item plus its reason IS the plan-change record. +4. Never delete the file. Never delete anything under a `wherefore/` data dir. A + dropped item is kept for history. +5. Report what was dropped and why. + +### Intent: read (what am I working on) + +1. Dump the item frontmatter (loop above) and report by status: `doing` first (in + flight), then `todo`, then blocked (items carrying a `question_ref` to an open + question), then recently `done`, then `dropped` if asked. +2. To classify blocked accurately, read MAY take one narrow cross-collection peek: the + `status` of a referenced question, to tell whether an attached `question_ref` is still + open. Read only that one frontmatter field. Reporting any `question_ref` as blocked + without checking would show stale blocks after a `resolve`, the exact drift that makes a + view untrustworthy. +3. That status peek is the only exception. Do not pull in question bodies, open questions + at large, or anything from `log/`; a cross-collection status view is a separate concern, + not this skill. +4. If `plan/` is empty or absent, say so plainly. + +## Spikes + +A spike is an open-ended research item: the unknown is what to do, so the steps are not +known up front. It is a plan item, not a new type, and needs no type field. Two rules: + +- Body: the checkboxes are the questions to answer, not steps to take. Push for the + specific unknowns ("does the vendor API support batching?", "what is the p99 under + load?") rather than writing "research X" as a single box. +- Termination: a spike ends by producing a decision (hand off to `capture`) or new + questions (hand off to `ask`). Finishing the investigation is not the same as having an + answer. + +If the spike is the work of answering a tracked question, set `answers: Q-NNN` on it, not +`question_ref` (which would render the spike as blocked in the read view). On advancing a +spike with `answers` to `done`, the capture-handoff offer applies and you additionally +offer to resolve that question via `resolve`. + +## Examples + +Open. User: "Add a plan item to migrate the auth flow to OAuth." Allocate the next +P-NNN, then push for the concrete steps ("which providers, what has to change?") and +write them as checkboxes. Report: "Opened P-101 (migrate-auth-to-oauth), status todo, +5 steps." + +Advance, human-driven. User: "Mark P-101 done." Set `status: done`, set `updated` to +today, check the remaining boxes, then ask: "Anything decided here worth capturing as a +decision?" If yes, hand off to `capture`. + +Advance, capture-driven. The `capture` skill logs a decision that resolves P-102 and +invokes advance to set it done with `decision_ref`. Advance sets `status: done`, adds +the `decision_ref`, bumps `updated`, and suppresses the capture offer, because capture +is the caller. + +Reopen. User: "Actually P-101 is not done, the error states are missing." Set `status` +back to `doing`, bump `updated`, and uncheck only the boxes the user names; leave the +rest checked. + +Block. User: "P-101 is stuck until we decide the token store." If no question tracks +that, create one via `ask` (Q-NNN), then set `question_ref: Q-NNN` on P-101. Report it +as blocked; do not write a `blocked` status. + +Spike. User: "Open a spike on whether we can drop the Redis cache." Open it with the +unknowns as checkboxes (`- [ ] measure the cache hit rate`, `- [ ] test cold-start +latency without it`, `- [ ] list which endpoints depend on it`). If a question already +tracks this, set `answers: Q-018` (not `question_ref`, which would render it blocked). +When the spike is done, offer to capture the decision and to resolve Q-018. + +Drop with a reason. User: "Drop P-103." Ask for the reason if none given. On "superseded +by the new pipeline, not worth finishing," set `status: dropped`, `updated` today, +`dropped_reason` to that. Never delete the file. + +Read. User: "What am I working on?" Dump the item frontmatter and list `doing` first, +then `todo`, then blocked (checking each `question_ref`'s status to skip ones already +resolved), citing ids and titles. Do not reach into `log/` or `questions/` beyond that +one status check. diff --git a/plugins/wherefore/skills/resolve/SKILL.md b/plugins/wherefore/skills/resolve/SKILL.md index db9947f..0b6df75 100644 --- a/plugins/wherefore/skills/resolve/SKILL.md +++ b/plugins/wherefore/skills/resolve/SKILL.md @@ -15,6 +15,10 @@ Close out an open question by updating its individual file in any) contains the full context. The file's frontmatter is the single source of truth. +No em dashes. Periods, commas, colons, semicolons, or parentheses instead. Firm project rule. + +Never delete anything under a `wherefore/` data dir. Retire, do not delete. + ## Frontmatter safety When you fill `resolution`, emit it as a double-quoted, single-line string, escaping @@ -71,6 +75,23 @@ summary and move detail into a `## Resolution` body section. `status` and - Which files were touched - Whether any related questions still `open` share the same areas (dump the question frontmatter to check), as a nudge; don't resolve them automatically + - Plan items this resolution touches. Dump `wherefore/plan/P-*.md` frontmatter + (`resolve` reads only `question_ref`, `answers`, and `status` and writes nothing to + `plan/`). Skip any item whose `status` is `dropped`; a dropped item is not waiting on + anything. Then: + - Unblocked: items whose `question_ref` is the ID you just resolved just became + unblocked. Tell the user; do not change their status. The item stays where it is + until someone advances it through the `plan` skill. + - Answered: items whose `answers` is that ID just accomplished their purpose (the + spike that was investigating it). Report them and offer to advance them to `done` + through the `plan` skill. Do not advance them silently, and do not advance them + here yourself. + - Break the loop: if the `plan` skill drove this resolve (its advance intent handed + off here to close the question a finishing spike answered), suppress the offer to + advance those items. `plan` is already advancing the item; offering to advance it + back would loop. This mirrors how `plan` advance suppresses its capture offer when + capture is the driver. Reading `plan/` here does not compromise `plan`'s sole + ownership of it; nothing is written. ## Examples diff --git a/plugins/wherefore/skills/supersede/SKILL.md b/plugins/wherefore/skills/supersede/SKILL.md index e8901f1..e100c96 100644 --- a/plugins/wherefore/skills/supersede/SKILL.md +++ b/plugins/wherefore/skills/supersede/SKILL.md @@ -17,6 +17,15 @@ file and adds a visible banner, so neither the `ask` skill nor a human skimming raw files is left guessing. The entry's frontmatter is the single source of truth. +This skill is the only writer of decision status. Plan items have their own status +machine (`todo`/`doing`/`done`/`dropped`) that never touches a decision's status; if +any plan flow needs to retire or replace a decision, it routes here, not through the +`plan` skill. + +No em dashes. Periods, commas, colons, semicolons, or parentheses instead. Firm project rule. + +Never delete anything under a `wherefore/` data dir. Retire, do not delete. + ## Workflow 1. **Find the target entry.** Locate `wherefore/log/.md` directly. If you only @@ -72,6 +81,12 @@ truth. 6. **Report back.** List every file touched. If the replacement entry isn't logged yet, say so and suggest running the `capture` skill to log it. + Then flag plan items pointing at the retired decision: dump `wherefore/plan/P-*.md` + frontmatter and find any item whose `decision_ref` includes the slug you just + superseded or marked obsolete, and tell the user which ones. Do not mutate them: the + ref is still accurate history, and the chain is followable through `superseded_by`. + This reads `decision_ref` only and writes nothing to `plan/`, so it does not compromise + this skill's standing as the sole writer of decision status. ## Examples diff --git a/wherefore/ROADMAP.md b/wherefore/ROADMAP.md new file mode 100644 index 0000000..5ef37ae --- /dev/null +++ b/wherefore/ROADMAP.md @@ -0,0 +1,63 @@ +# wherefore roadmap + +High-level goals and milestones. Goals are the durable north stars. Milestones are +dated targets that group work. Individual plan items (`wherefore/plan/P-NNN-slug.md`) +reference a milestone via a `milestone: M1` frontmatter key. + +This file is the source of truth for goal and milestone definitions and their status. +Git history is the record of how it changed. Do not hand-list plan items under a +milestone here; that list rots. The dashboard rolls items up from each item's +`milestone` field. + +Milestone status vocabulary (its own small set, separate from plan-item and decision +states): `planned`, `active`, `done`, `held` (intentionally gated), `cut` (abandoned +but kept). + +## Goals + +**G1: The why, in plain markdown, in your repo.** +An open, inspectable, human-readable record of why the code is the way it is. No cloud, +no database, no lock-in. + +**G2: Two honest halves, one data interface.** +A capture plugin and a static dashboard that both speak the same plain-markdown +`wherefore/` format, each useful without the other. + +**G3: A focused, credible open-source launch.** +Ship narrow, stand alone, earn the Show HN on the strength of real dogfooding. + +## Milestones + +### M1: Dashboard MVP published +Status: done. Serves: G2. +0.1.0 published (MIT) and verified working from a clean external install. + +### M2: 0.1.1 polish patch +Status: active. Serves: G2. +README rewrite, build-command preview-locally hint, Vite `server.fs.allow` fix for the +cross-directory dev errors, tsconfig plus @types/node (done). Deferred: blurry 16px +favicon. Confirm against `npm view` whether this has already shipped, and flip to done +if so. + +### M3: Thin launcher published +Status: planned. Serves: G1. +Publish `wherefore` 1.0.1 forwarding argv to the scoped package bin, so the bare name +runs the real tool while `@dustinvk/wherefore-dashboard` stays the versioned source of +truth. + +### M4: Plan layer shipped +Status: active. Serves: G2. +The `P-NNN` plan collection, the `/wherefore:plan` verb, dashboard rendering of plan +items, and this roadmap. Currently dogfooding the frontmatter contract by hand before +wiring the loader and the skill. + +### M5: Live demo at wherefore.dev +Status: planned. Serves: G3. +Deploy the dashboard rendering wherefore's own decision log. A dogfooding asset, not a +marketing site. + +### M6: Cross-agent skill publishing +Status: planned. Serves: G1. +Publish the skills across agent platforms (Copilot, Codex, Cursor, Gemini CLI) on the +SKILL.md standard. Scaffolding needed: `marketplace.json`, plugin manifests, +cross-tool skills layout. diff --git a/wherefore/log/2026-07-03-entry-view-theming-and-css.md b/wherefore/log/2026-07-03-entry-view-theming-and-css.md new file mode 100644 index 0000000..a383e78 --- /dev/null +++ b/wherefore/log/2026-07-03-entry-view-theming-and-css.md @@ -0,0 +1,45 @@ +--- +date: 2026-07-03 +title: "Entry view theming and stylesheet consolidation" +areas: [dashboard] +topics: [ui, visual-identity] +stories: [] +status: active +supersedes: +superseded_by: +superseded_date: +--- + +## Summary +The 1A decision-entry view stayed dark when the app was toggled to light. Its `--wf-*` +color tokens were defined only on `:root` with dark values and three text colors were +hardcoded outside the token system, so the app theme never reached the card. We wired the +light palette to the app's `data-theme` signal, folded the standalone `wherefore-1A.css` +into `global.css`, and kept IBM Plex on the Google Fonts CDN rather than self-hosting. + +## Decisions / outcomes +- Bind the entry-view light palette to `:root[data-theme="light"]`, the signal `Base.astro`'s toggle already sets. Mirror `global.css` exactly: the explicit selector plus a `prefers-color-scheme: light` fallback gated on `:root:not([data-theme="dark"])` for the no-JS path. +- Route every entry-view color through `--wf-*` tokens. The three hardcoded text colors became `--wf-text` and `--wf-strong`, so the card re-themes with no per-element overrides. +- Fold `wherefore-1A.css` into `global.css` and delete the standalone file. The import in `log/[slug].astro` is removed; the `.wf-*` rules and the IBM Plex `@import` now live in the single global sheet. +- Keep IBM Plex on the Google Fonts CDN; do not self-host. + +## Why +Fixing the token wiring once is the right altitude: the card and all children already read +color only through `var(--wf-*)`, so binding those tokens to `data-theme` (and matching +`global.css`'s fallback) makes the entry flip in lockstep with the header and list, JS or +not. Consolidating removed a second stylesheet that only the detail page loaded; one sheet +is easier to reason about. The cost is that IBM Plex now loads on every page, but the +`.wf-*` rules only apply where the entry markup exists, so nothing else changes visually. +On fonts, self-hosting latin-only IBM Plex measured about 232 KB of binary woff2 (the single +largest thing in a roughly 427 KB repo) for no user benefit: browsers already fetch the same +files from Google, only the latin subset loads per page, and the CDN path matches how Space +Grotesk, Inter, and JetBrains Mono already load. Verified by build plus toggling a detail +page: dark (#12161c / #e6e9ee) and light (#ffffff / #2b3138, teal #0c8f80) both render. + +## Alternatives considered +- Self-host the IBM Plex woff2 files, rejected because it adds 232 KB (latin) to 769 KB (all subsets) of binary blobs to git for no bandwidth win, since visitors download the same files either way and only the latin subset loads. +- Keep `wherefore-1A.css` as its own stylesheet, rejected in favor of a single global sheet to cut clutter. +- Hand-edit color values or add per-element light overrides, rejected in favor of fixing the token wiring once. + +## Open questions / follow-ups +- Q-011: Should IBM Plex get preconnect hints and font-display tuning like the other three fonts, or is the extra `@import` latency acceptable? \ No newline at end of file diff --git a/wherefore/log/2026-07-18-capture-does-not-write-plan-items.md b/wherefore/log/2026-07-18-capture-does-not-write-plan-items.md new file mode 100644 index 0000000..7b93dc7 --- /dev/null +++ b/wherefore/log/2026-07-18-capture-does-not-write-plan-items.md @@ -0,0 +1,40 @@ +--- +date: 2026-07-18 +title: "Capture does not write plan items" +areas: [plugin] +topics: [skill-structure, data-model] +stories: [] +status: active +supersedes: +superseded_by: +superseded_date: +--- + +## Summary +A new plan skill now owns wherefore/plan/. This settles what capture may and may not do to +that collection: capture never creates plan items, and never writes plan status directly. + +## Decisions / outcomes +- Capture never creates plan items. It may surface work a decision implies and offer to hand off to plan open, but writes nothing to plan/ on silence or no. +- Plan owns plan/, capture owns log/, supersede owns decision status. One verb does not own two collections. +- Flipping an already committed item to done routes through plan advance, not a direct capture write. +- The capture to advance handoff is one-directional. When capture drives the flip, plan advance suppresses its own capture offer, so the path does not loop back to capture the decision that just triggered it. Plan advance offers a capture handoff only when a human drove the transition. +- blocked is never written. It is derived from an open question_ref on the item. + +## Why +A decision is a resolved ruling; a plan item is a committed intention. If capture auto-emitted +plan items for the work a decision implies, plan/ fills with todo items nobody chose, and once +it holds twenty such items "up next" is noise and the dashboard stops being trusted. Rot +arrives as records nobody chose to make. Keeping one writer per collection mirrors supersede +being the single writer of decision status, and stops the auto and manual paths from drifting. +Flipping an existing item to done is safe because it resolves a commitment already made; it +does not invent one. Plan-item checkboxes decompose a plan already committed to; they are not +the standalone task-manager feature ruled out in 2026-06-25-todo-list-out-of-scope. + +## Alternatives considered +- Capture auto-emits plan items for implied work. Rejected: commitments nobody made, sitting at todo forever. +- Capture writes plan status directly. Rejected: a second writer of plan/, the drift the one-verb-one-collection rule exists to prevent. + +## Open questions / follow-ups +- Does the one-verb-one-collection boundary hold when the forthcoming brief skill arrives, given that brief reads all three collections (log/, questions/, plan/) by design? Register as a Q-NNN if it firms up. +- Does the answers frontmatter key earn its place, or is a body mention of the investigated question enough? It was added ahead of hand-writing a spike item against it, which inverts the usual do-not-build-tooling-before-feeling-the-pain rule; this open question is the hedge. Revisit after the first real investigation runs through it. diff --git a/wherefore/plan/P-001-ship-0-1-1-patch.md b/wherefore/plan/P-001-ship-0-1-1-patch.md new file mode 100644 index 0000000..067d506 --- /dev/null +++ b/wherefore/plan/P-001-ship-0-1-1-patch.md @@ -0,0 +1,13 @@ +--- +id: P-001 +title: Ship 0.1.1 patch +status: doing +created: 2026-06-20 +updated: 2026-07-03 +area: dashboard +topics: [release] +--- + +README rewrite, build-command "preview locally" hint, Vite server.fs.allow fix for the +"outside of Vite serving allow list" dev errors, tsconfig plus @types/node (done). +Deferred: blurry 16px favicon. diff --git a/wherefore/plan/P-002-add-plan-collection.md b/wherefore/plan/P-002-add-plan-collection.md new file mode 100644 index 0000000..b50ed85 --- /dev/null +++ b/wherefore/plan/P-002-add-plan-collection.md @@ -0,0 +1,14 @@ +--- +id: P-002 +title: Add plan collection to the dashboard +status: todo +created: 2026-07-03 +area: dashboard +topics: [astro, schema] +decision_ref: 2026-07-03-companion-plan-collection +--- + +Astro loader plus route for wherefore/plan/, mirroring the questions collection. Derive +IDs from the id field, not the filename. Test with --src pointing outside the package +(cross-directory false-pass risk). Preceded by stabilizing this frontmatter contract on +a few hand-written files. diff --git a/wherefore/plan/P-003-saas-extension.md b/wherefore/plan/P-003-saas-extension.md new file mode 100644 index 0000000..bcee9db --- /dev/null +++ b/wherefore/plan/P-003-saas-extension.md @@ -0,0 +1,15 @@ +--- +id: P-003 +title: SaaS extension (transcript to decision capture) +status: dropped +created: 2026-05-10 +updated: 2026-06-15 +area: product +decision_ref: 2026-06-15-focus-on-technical-wedge +dropped_reason: > + Lifecycle-aware decision artifacts resonate with technical users, not a non-technical + SaaS audience, and transcription-to-decisions is already served by incumbents. +--- + +Explored a meeting-transcript-to-decision pipeline with Teams integration. Set aside to +keep focus on the plain-markdown technical wedge. diff --git a/wherefore/plan/P-004-author-plan-skill.md b/wherefore/plan/P-004-author-plan-skill.md new file mode 100644 index 0000000..05843e4 --- /dev/null +++ b/wherefore/plan/P-004-author-plan-skill.md @@ -0,0 +1,22 @@ +--- +id: P-004 +title: Author the plan skill +status: done +created: 2026-07-18 +updated: 2026-07-18 +area: plugin +topics: [skill-structure] +decision_ref: 2026-07-03-plan-directory, 2026-07-18-capture-does-not-write-plan-items +--- + +Build the wherefore plan skill: one verb, four intents detected from the request, not +subcommands. Mirror the sibling skills in structure and tone. + +- [x] SKILL.md frontmatter (name plus folded description) and a 3 to 5 line mission, no allowed-tools, matching capture/ask/resolve/supersede. +- [x] open intent: allocate the next P-NNN by scanning plan/, write P-NNN-slug.md, break the work into concrete checkboxes, push for specifics, never bulk-generate from a vague prompt. +- [x] advance intent: transition todo to doing to done, check and uncheck body boxes, bump updated on any write including a checkbox toggle. +- [x] advance handoff: on a human-driven done, offer a capture handoff; suppress that offer when capture drove the transition; never write log/ directly. +- [x] advance blocking: attach a single question_ref (create the question via ask if it does not exist); never write a blocked status. +- [x] drop intent: set status dropped plus updated, require dropped_reason or decision_ref, refuse to drop without one, never delete the file. +- [x] read intent: report plan/ only, grouped by status, with no cross-collection reach. +- [x] round-trip: accept prose-only bodies and off-vocab area/topics; verify against P-001, P-002, P-003. diff --git a/wherefore/plan/P-005-capture-plan-handoffs.md b/wherefore/plan/P-005-capture-plan-handoffs.md new file mode 100644 index 0000000..620773f --- /dev/null +++ b/wherefore/plan/P-005-capture-plan-handoffs.md @@ -0,0 +1,17 @@ +--- +id: P-005 +title: Wire capture's plan handoffs +status: done +created: 2026-07-18 +updated: 2026-07-18 +area: plugin +topics: [skill-structure] +decision_ref: 2026-07-18-capture-does-not-write-plan-items +--- + +After capture writes a decision, link it to plan/ without capture ever writing plan/ itself. + +- [x] Resolved-item detection: when a decision plainly resolves an existing plan item, hand off to plan advance to set done and add decision_ref; the handoff marks capture as the driver so advance suppresses its return offer. +- [x] Implied-work surfacing: offer "this implies these pieces of work, want me to open plan items?"; on yes, hand off to plan open with decision_ref set on each new item. +- [x] On silence or no, write nothing to plan/. +- [x] Add a one-line note in capture that it never creates or directly mutates plan items. diff --git a/wherefore/plan/P-006-ask-resolve-plan-links.md b/wherefore/plan/P-006-ask-resolve-plan-links.md new file mode 100644 index 0000000..f46840d --- /dev/null +++ b/wherefore/plan/P-006-ask-resolve-plan-links.md @@ -0,0 +1,18 @@ +--- +id: P-006 +title: Wire ask and resolve plan links +status: done +created: 2026-07-18 +updated: 2026-07-18 +area: plugin +topics: [skill-structure] +decision_ref: 2026-07-18-capture-does-not-write-plan-items +--- + +Cross-link the read and resolve paths to plan items, one way only, and confirm supersede's +boundary. + +- [x] ask: when a surfaced or newly asked question blocks work in flight, offer to attach it as a question_ref on the relevant plan item; the link is one-way, plan to question. +- [x] ask: optionally surface in-area plan items alongside open questions, read-only. +- [x] resolve: after resolving a question, report plan items carrying that question_ref as newly unblocked, without changing their status. +- [x] supersede: add one line affirming it stays the only writer of decision status. diff --git a/wherefore/plan/P-007-scaffold-plan-and-docs.md b/wherefore/plan/P-007-scaffold-plan-and-docs.md new file mode 100644 index 0000000..ba55d2f --- /dev/null +++ b/wherefore/plan/P-007-scaffold-plan-and-docs.md @@ -0,0 +1,17 @@ +--- +id: P-007 +title: Scaffold plan in seed and update docs +status: done +created: 2026-07-18 +updated: 2026-07-18 +area: plugin +topics: [skill-structure, docs] +decision_ref: 2026-07-18-capture-does-not-write-plan-items +--- + +Make a fresh repo scaffold plan/ and document the collection at the cross-tool floor. + +- [x] seed: scaffold plan/ and a plan/README.md describing the P-NNN format, the four statuses, blocked derived from question_ref, and checkboxes-by-default-prose-valid bodies. Keep the ask-before-write pattern. +- [x] Update the data-dir wherefore/plan/README.md so the updated row reads "any write" and the body line allows checkboxes by default. +- [x] AGENTS.md: fix plan/short-slug.md to plan/P-NNN-short-slug.md and add a Plan items floor section. +- [x] CLAUDE.md: add skills/plan/SKILL.md to the structure tree and plan-item conventions to the authoring section. diff --git a/wherefore/plan/P-008-refine-plan-contract.md b/wherefore/plan/P-008-refine-plan-contract.md new file mode 100644 index 0000000..1f93d88 --- /dev/null +++ b/wherefore/plan/P-008-refine-plan-contract.md @@ -0,0 +1,22 @@ +--- +id: P-008 +title: Refine the plan skill contract (spikes, reopening, read peek) +status: done +created: 2026-07-18 +updated: 2026-07-18 +area: plugin +topics: [skill-structure, data-model] +decision_ref: 2026-07-03-plan-directory +--- + +Contract refinements to the plan skill, on top of P-004 which authors it. Kept separate +because this is a contract change, not the initial authoring. + +- [x] read intent: allow a narrow question-status peek to classify blocked; forbid question bodies and log/. +- [x] advance: document done -> doing reopening (bumps updated, unchecks nothing automatically; the user names which boxes reopen). +- [x] advance: allow advancing a blocked item to doing with a warning and a resolve-first prompt; never refuse. +- [x] drop example: use a fictional id, not a live record. +- [x] spikes: add a section; for a spike the checkboxes are the questions to answer; terminate via capture or ask. +- [x] new optional key answers: Q-NNN, adjacent to question_ref; blocked stays derived from question_ref only; never both at the same Q-NNN. +- [x] propagate the answers contract to plan/README.md, seed's embedded README, the AGENTS.md Plan items section, and CLAUDE.md. +- [x] decision record: add the open question on whether answers earns its place. diff --git a/wherefore/plan/P-009-fix-sibling-skills.md b/wherefore/plan/P-009-fix-sibling-skills.md new file mode 100644 index 0000000..8f51e95 --- /dev/null +++ b/wherefore/plan/P-009-fix-sibling-skills.md @@ -0,0 +1,21 @@ +--- +id: P-009 +title: Fix up the sibling skills for the plan cross-links +status: done +created: 2026-07-18 +updated: 2026-07-18 +area: plugin +topics: [skill-structure] +decision_ref: 2026-07-03-plan-directory +--- + +Two passes over the sibling skills after plan landed: cross-skill review findings, then a +frontmatter-documentation consistency sweep. No settled ruling changes. + +- [x] capture: confirm before closing a plan item (ask-first, matching the question standard); add the plan frontmatter dump plus area shortlist; fold plan links into the step 11 approval moment. +- [x] ask: when listing open questions, surface any plan item that answers one (spike underway), inline and read-only. +- [x] resolve: also report items whose answers matches the resolved id and offer to advance them via plan; skip dropped items; suppress the advance offer when plan drove the resolve. +- [x] supersede: report plan items whose decision_ref includes the retired slug; read-only, do not mutate, note it does not break the sole-writer boundary. +- [x] confirm name plus description frontmatter on all five skills (ask and supersede already have it). +- [x] reader/writer split: writers keep the full contract; ask, resolve, supersede get short "fields I rely on" notes only. +- [x] both project rules verbatim in all five: no em dashes, and never delete under a wherefore/ data dir. diff --git a/wherefore/plan/P-010-allocate-id-from-frontmatter.md b/wherefore/plan/P-010-allocate-id-from-frontmatter.md new file mode 100644 index 0000000..8cf96a1 --- /dev/null +++ b/wherefore/plan/P-010-allocate-id-from-frontmatter.md @@ -0,0 +1,19 @@ +--- +id: P-010 +title: Allocate next ID from frontmatter, not filenames +status: done +created: 2026-07-18 +updated: 2026-07-18 +area: plugin +topics: [skill-structure, data-model] +--- + +Next-ID allocation read the filename via an ls | sed scan while identity reads the +authoritative id: field. The two sources agree until they do not, which is how two Q-008s +were allocated (fixed directly by renumbering the newer one to Q-011). Fix the cause in both +scanners so allocation and identity read the same source, the frontmatter dump every other +operation already uses. + +- [x] capture step 9: replace the ls | sed next-Q-ID scan with a frontmatter id: dump that takes the max. +- [x] plan open intent: replace the ls | sed next-P-NNN scan with a frontmatter id: dump that takes the max (this bug was inherited before the collection had a single item). +- [x] confirm both read id: from the leading frontmatter block, matching the awk dump pattern the read paths use. diff --git a/wherefore/plan/README.md b/wherefore/plan/README.md new file mode 100644 index 0000000..30e2c33 --- /dev/null +++ b/wherefore/plan/README.md @@ -0,0 +1,83 @@ +# Plan collection (`wherefore/plan/`) + +Plan items are a first-class collection under `wherefore/`, parallel to `questions/`. +They track forward-looking work and its state (todo / doing / done / dropped) and +preserve plan-change history by keeping dropped items rather than deleting them. This +collection is durable and retire-don't-delete, the same as the rest of `wherefore/`. + +Plan status is a separate state machine from decision status. Do not reuse active / +superseded / obsolete here, and do not put todo / doing / done / dropped on decisions. + +## Files + +- Path: `wherefore/plan/P-NNN-slug.md`. The slug is browsability sugar. +- The `id` field in frontmatter is authoritative and drives the item's identity, + exactly like `Q-NNN`. Filename casing cannot cause collisions. +- The loader globs `plan/P-*.md`, so only plan-item files are collected. This + `README.md` is ignored. +- Next ID = (highest `id:` across the P-*.md files) + 1. IDs are sequential and never + reused, including numbers freed by dropped items. + +## Frontmatter + +| key | req | type | notes | +|-----------------|-----|-------------------|-------------------------------------------------------------| +| `id` | yes | `P-NNN` | authoritative, drives the item id | +| `title` | yes | string | short human title | +| `status` | yes | enum | `todo` / `doing` / `done` / `dropped` | +| `created` | yes | `YYYY-MM-DD` | creation date | +| `updated` | no | `YYYY-MM-DD` | set on any write (status change or body edit, including a checkbox toggle); this IS the plan-change timestamp | +| `area` | no | string | single area, reuse existing area vocabulary | +| `topics` | no | list | reuse existing cross-cutting topics | +| `milestone` | no | `M1` | milestone this item serves, defined in `wherefore/ROADMAP.md`| +| `decision_ref` | no | slug or slug list | originating or superseding decision(s), `supersedes` format | +| `question_ref` | no | `Q-NNN` | a single open question this item is blocked on | +| `answers` | no | `Q-NNN` | a single question this item is the work of answering (spike)| +| `dropped_reason`| no | string | lightweight why, used when `status: dropped` | + +Body: freeform. The `plan` skill breaks the work into `- [ ]` checkboxes by default +(steps concrete enough to check off); prose stays valid, and older items may be +prose-only. + +## Status vocabulary + +`todo` -> `doing` -> `done` is the normal flow. Any transition to `dropped` is +abandonment. `dropped` is terminal but kept: a dropped item, with `updated` marking +when and `dropped_reason` or `decision_ref` marking why, IS the plan-change record. + +`blocked` is derived, not a status. An item is blocked if it carries a `question_ref` +to an open question. It never lives in frontmatter. An item carrying `answers` (a spike +investigating a question) is not blocked; `answers` is the opposite relationship. + +## Linking conventions + +- `milestone`: a single milestone ID (`M1`) defined in `wherefore/ROADMAP.md`. One-way: + the item points up at the milestone. +- `decision_ref`: one or more decision log slugs in `YYYY-MM-DD-slug` form (no `.md`), + comma-separated for multiple, mirroring the `supersedes` convention. +- `question_ref`: a single `Q-NNN` the item waits on. By deliberate choice an item is + blocked by at most one question. +- `answers`: a single `Q-NNN` this item investigates (a spike). The opposite of + `question_ref`: an item that `answers` a question is not blocked by it. An item may + carry both (rare but legal); never point them at the same `Q-NNN`. + +## Key casing + +Single-word keys are bare (`id`, `title`, `status`, `created`, `updated`, `area`, +`topics`, `milestone`, `answers`). Compound keys use underscore (`decision_ref`, +`question_ref`, `dropped_reason`). A hyphen in a compound key parses silently and drops +the link. + +## Boundaries + +- The `plan` skill writes only `wherefore/plan/*`. Never `log/`, never `questions/`, + never `ROADMAP.md`. +- Durable why belongs in the decision layer: when a plan item's rationale is really a + decision, that is a `capture`; when a direction changes for a reason worth keeping, + that is a `supersede` on the decision, and the plan item flips to `dropped` carrying + `decision_ref` to it. +- `capture` never creates plan items and never writes plan status directly; it may hand + off to the `plan` skill. The `plan` skill records that something changed; the decision + layer owns the durable why. + +Maintained by the [wherefore](https://github.com/DustinVK/wherefore) plan skill. diff --git a/wherefore/questions/Q-010-capture-restates-supersession.md b/wherefore/questions/Q-010-capture-restates-supersession.md new file mode 100644 index 0000000..9205acf --- /dev/null +++ b/wherefore/questions/Q-010-capture-restates-supersession.md @@ -0,0 +1,32 @@ +--- +id: Q-010 +question: "Does capture restating the supersession mutation steps violate the sole-writer rule, or is it fine?" +status: open +areas: [plugin] +asked_date: 2026-07-18 +asked_slug: 2026-06-24-supersede-separate-skill +resolution: +resolution_slug: +--- + +## Context + +capture step 7 restates the supersession mutation inline (sets `status: superseded`, +`superseded_by`, `superseded_date`, and writes the banner) when a captured discussion is a +confirmed reversal. supersede is meant to be the single writer of decision status +(2026-06-24-supersede-separate-skill). Two readings, which resolve differently: + +- Duplication reading: the concern is two copies of the same instructions drifting apart. + If so, this is the ships-to-other-repos problem again, and the duplication may be correct, + since each skill must be self-contained. No change needed. +- Boundary reading: the concern is two skills both mutating decision status. If so, it is a + real breach of the sole-writer rule, and capture should call supersede rather than restate + the steps. + +Current lean is the boundary reading. The same mutation living in two code paths is exactly +the failure the sole-writer rule exists to prevent, and capture already routes question +closure through resolve and plan closure through plan. Supersession is the one place capture +still does the work itself, which makes it the odd one out. + +If this resolves toward "yes, tighten it," resolve closes this question and plan opens the +item to make capture delegate to supersede. diff --git a/wherefore/questions/Q-011-ibm-plex-preconnect.md b/wherefore/questions/Q-011-ibm-plex-preconnect.md new file mode 100644 index 0000000..a3d289e --- /dev/null +++ b/wherefore/questions/Q-011-ibm-plex-preconnect.md @@ -0,0 +1,10 @@ +--- +id: Q-011 +question: "Should IBM Plex get preconnect hints and font-display tuning like the other three fonts, or is the @import latency acceptable?" +status: open +areas: [dashboard] +asked_date: 2026-07-03 +asked_slug: 2026-07-03-entry-view-theming-and-css +resolution: +resolution_slug: +--- \ No newline at end of file From 0348dbef0c5bda90b507e40c607519388fd475a4 Mon Sep 17 00:00:00 2001 From: Dustin VanKrimpen Date: Sat, 18 Jul 2026 22:08:12 -0400 Subject: [PATCH 2/4] wherefore: document the plan skill in the main README Add the plan skill everywhere the README enumerates the plugin: the summary bullet, the skills list (open/advance/drop/read, owns plan/, hands off to capture and ask), the AGENTS.md workflow line, a Plan lifecycle note, and both directory trees. Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 961cc49..0749d6f 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,8 @@ just files in your repo, any tool or any person can read it. There are a few ways to work with it: - **A Claude Code plugin** (the richest experience): skills that capture, query, - resolve, and supersede decisions, with Claude handling the tagging and bookkeeping - so the log actually gets maintained. + resolve, and supersede decisions and track forward-looking plan items, with Claude + handling the tagging and bookkeeping so the log actually gets maintained. - **The `wherefore` CLI** ([`wherefore`](https://www.npmjs.com/package/wherefore) on npm): `npx wherefore init` scaffolds the log and an `AGENTS.md`, and `npx wherefore dashboard` launches the dashboard. It can also install the skills for @@ -88,6 +88,13 @@ maintained. replacement) or obsolete, without requiring a new discussion to be captured. Updates the entry file and adds a visible banner so both the `ask` skill and human readers see it is retired. +- **`plan`** -- tracks forward-looking work items in `wherefore/plan/`, one file per + item (`P-NNN-short-slug.md`). One verb, four intents detected from your request: + open a new item (broken into concrete checkboxes), advance one along + `todo -> doing -> done`, drop one you've abandoned (with a reason, never deleted), + or read back what's on the plan. It owns `plan/` and hands off to `capture` and + `ask` rather than writing decisions or questions itself, so the plan never fills + with commitments nobody made. - **`/wherefore:seed`** -- inspects the codebase and proposes a starter set of areas and topics for `wherefore/topics.md`, with a short justification for each tag. Confirm or edit its proposal and it writes (or merges into) the file. @@ -100,9 +107,10 @@ consuming project's repo, version-controlled and PR-reviewable next to the code. ## Other coding agents The `wherefore/` log is plain markdown, so it is not tied to any one tool. An -`AGENTS.md` at the repo root describes the format and the capture, supersede, and -question workflows, so coding agents that read AGENTS.md (Codex, GitHub Copilot, -Cursor, Gemini, and others) can read and maintain the log by following the spec. +`AGENTS.md` at the repo root describes the format and the capture, supersede, +question, and plan workflows, so coding agents that read AGENTS.md (Codex, GitHub +Copilot, Cursor, Gemini, and others) can read and maintain the log by following the +spec. The Claude Code plugin remains the richest experience: it handles tagging, supersession detection, multi-thread splitting, and the question lifecycle for you. @@ -232,6 +240,10 @@ file and annotates the source entry so the audit trail is complete. `supersede` retires entries after the fact, `ask` follows chains to the active answer. +**Plan lifecycle:** `plan` opens forward-looking items, advances them +`todo -> doing -> done`, and drops the ones you abandon; `capture` hands off to it +when a decision implies committed work, rather than inventing plan items itself. + ## Repo layout ``` @@ -261,8 +273,10 @@ wherefore/ │ │ └── SKILL.md # query skill │ ├── resolve/ │ │ └── SKILL.md # close out open questions -│ └── supersede/ -│ └── SKILL.md # retire decisions (superseded or obsolete) +│ ├── supersede/ +│ │ └── SKILL.md # retire decisions (superseded or obsolete) +│ └── plan/ +│ └── SKILL.md # track forward-looking plan items └── README.md ``` @@ -272,10 +286,12 @@ Each consuming project's log lives in its own repo, not here: / └── wherefore/ ├── topics.md # controlled tag vocabulary (areas + topics) + ├── log/ + │ └── YYYY-MM-DD-short-slug.md # one file per independently-queryable thread ├── questions/ │ └── Q-NNN-short-slug.md # one file per question (ID prefix + scannable slug) - └── log/ - └── YYYY-MM-DD-short-slug.md # one file per independently-queryable thread + └── plan/ + └── P-NNN-short-slug.md # one file per forward-looking plan item ``` Entry and question frontmatter is the single source of truth, and the skills From 9b7c7e10be22dca52a845720242972ff3d8d989b Mon Sep 17 00:00:00 2001 From: Dustin VanKrimpen Date: Sat, 18 Jul 2026 22:32:43 -0400 Subject: [PATCH 3/4] wherefore: rename the plan skill to slate The skill verb `plan` competed with Claude Code's built-in plan mode for triggering. Rename the verb to `slate`; the collection, the P-NNN scheme, the frontmatter contract, and every settled ruling stay exactly as they were (a verb and the collection it writes are allowed to diverge, as capture writes log/ and resolve writes questions/). - skills/plan/ -> skills/slate/: name, H1, and a description that leads with the collection (operating items in wherefore/plan/) with artifact-centered triggers and /wherefore:slate. - Update every sibling cross-reference (capture, ask, resolve, supersede) to slate, keeping the driver-suppression symmetry intact. - seed embed, CLAUDE.md, README.md, and the ROADMAP verb reference updated. - Dogfood: capture the rename as a decision; update P-004's text to slate. AGENTS.md is unchanged: it is the tool-neutral floor and names the collection, not the skill verb. Co-Authored-By: Claude Opus 4.8 (1M context) --- CLAUDE.md | 4 +- README.md | 6 +-- plugins/wherefore/commands/seed.md | 10 ++--- plugins/wherefore/skills/ask/SKILL.md | 2 +- plugins/wherefore/skills/capture/SKILL.md | 6 +-- plugins/wherefore/skills/resolve/SKILL.md | 12 +++--- .../wherefore/skills/{plan => slate}/SKILL.md | 21 ++++----- plugins/wherefore/skills/supersede/SKILL.md | 4 +- wherefore/ROADMAP.md | 2 +- .../2026-07-18-rename-plan-skill-to-slate.md | 43 +++++++++++++++++++ wherefore/plan/P-004-author-plan-skill.md | 4 +- 11 files changed, 79 insertions(+), 35 deletions(-) rename plugins/wherefore/skills/{plan => slate}/SKILL.md (95%) create mode 100644 wherefore/log/2026-07-18-rename-plan-skill-to-slate.md diff --git a/CLAUDE.md b/CLAUDE.md index 6de7935..eba7422 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -61,7 +61,7 @@ plugins/wherefore/ skills/supersede/ SKILL.md # marks an entry superseded (with pointer to # replacement) or obsolete via its frontmatter - skills/plan/ + skills/slate/ SKILL.md # manages wherefore/plan/ items (open, advance, # drop, read): one verb, four intents; never # writes log/ or questions/, hands off instead @@ -75,7 +75,7 @@ The `wherefore/` directory itself is **not** in this repo -- it lives in each co - **Command `.md`** front matter: `description`, `argument-hint`, `allowed-tools`. - All skills use a two-facet tag system: **areas** (feature slices: WHAT) and **topics** (cross-cutting concerns: HOW), drawn from the consuming project's `wherefore/topics.md`. Keep this separation consistent if extending the skills. - Entry and question frontmatter is the single source of truth: `ask` derives its shortlist by reading only the leading frontmatter block of each file. Derive on read; do not add a generated index. -- `capture` is write-heavy (creates/edits files); a single discussion may produce multiple entry files when it covers independently-queryable threads. `ask` is read-only. `resolve` edits only the `questions/Q-NNN-short-slug.md` file (and optionally the source entry). `supersede` edits an existing entry file's frontmatter and adds a banner. `plan` is the only writer of `wherefore/plan/`: it opens, advances, drops, and reads plan items and never writes `log/` or `questions/` (it hands off to `capture` and `ask` instead). `capture` never creates plan items; when a decision resolves or implies work it hands off to `plan`. `seed` is read-first, write-only-after-confirmation -- preserve this ask-before-write pattern for any new commands. +- `capture` is write-heavy (creates/edits files); a single discussion may produce multiple entry files when it covers independently-queryable threads. `ask` is read-only. `resolve` edits only the `questions/Q-NNN-short-slug.md` file (and optionally the source entry). `supersede` edits an existing entry file's frontmatter and adds a banner. `slate` is the only writer of `wherefore/plan/`: it opens, advances, drops, and reads plan items and never writes `log/` or `questions/` (it hands off to `capture` and `ask` instead). `capture` never creates plan items; when a decision resolves or implies work it hands off to `slate`. `seed` is read-first, write-only-after-confirmation -- preserve this ask-before-write pattern for any new commands. - Entry filenames: `YYYY-MM-DD-short-slug.md`; the entry frontmatter (`date`, `title`, `areas`, `topics`, `stories`, `status`, `supersedes`, `superseded_by`, `superseded_date`) is what readers shortlist on. - Question files: `questions/Q-NNN-short-slug.md` (the `Q-NNN` prefix is the zero-padded ID; the slug is a short, lowercase, hyphenated summary of the question, same style as a log slug and only for human scanning). One per question, with `id`, `question`, `status`, `areas`, `asked_date`, `asked_slug`, `resolution`, `resolution_slug` frontmatter. The `id:` field is the authoritative ID (the dashboard keys off it, not the filename). IDs are sequential and never reused; the next ID is (highest existing `id:`) + 1. - Plan items: `plan/P-NNN-short-slug.md` (the `P-NNN` prefix is the zero-padded ID; the `id:` field is authoritative, and the loader globs `plan/P-*.md` so `plan/README.md` is never collected). Frontmatter: `id`, `title`, `status` (todo|doing|done|dropped), `created`, `updated` (bumped on any write, including a checkbox toggle), plus optional `area` (single, not the plural `areas` decisions use), `topics`, `milestone`, `decision_ref`, `question_ref`, `answers` (a single `Q-NNN` a spike is the work of answering, the opposite of `question_ref` and not a blocker), `dropped_reason`. Plan status is a separate state machine from decision status: `capture` never creates or mutates plan items, and plan transitions never touch a decision's status (that stays with `supersede`). `blocked` is derived from an open `question_ref` (at most one per item), never written. IDs are sequential and never reused; the next ID is (highest existing `id:`) + 1. diff --git a/README.md b/README.md index 0749d6f..459fa08 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ maintained. replacement) or obsolete, without requiring a new discussion to be captured. Updates the entry file and adds a visible banner so both the `ask` skill and human readers see it is retired. -- **`plan`** -- tracks forward-looking work items in `wherefore/plan/`, one file per +- **`slate`** -- tracks forward-looking work items in `wherefore/plan/`, one file per item (`P-NNN-short-slug.md`). One verb, four intents detected from your request: open a new item (broken into concrete checkboxes), advance one along `todo -> doing -> done`, drop one you've abandoned (with a reason, never deleted), @@ -240,7 +240,7 @@ file and annotates the source entry so the audit trail is complete. `supersede` retires entries after the fact, `ask` follows chains to the active answer. -**Plan lifecycle:** `plan` opens forward-looking items, advances them +**Plan lifecycle:** `slate` opens forward-looking items, advances them `todo -> doing -> done`, and drops the ones you abandon; `capture` hands off to it when a decision implies committed work, rather than inventing plan items itself. @@ -275,7 +275,7 @@ wherefore/ │ │ └── SKILL.md # close out open questions │ ├── supersede/ │ │ └── SKILL.md # retire decisions (superseded or obsolete) -│ └── plan/ +│ └── slate/ │ └── SKILL.md # track forward-looking plan items └── README.md ``` diff --git a/plugins/wherefore/commands/seed.md b/plugins/wherefore/commands/seed.md index 20ecc8b..f9aac9d 100644 --- a/plugins/wherefore/commands/seed.md +++ b/plugins/wherefore/commands/seed.md @@ -67,7 +67,7 @@ approval; wait for their reply before writing anything. does not), scaffold the `plan/` collection: create `wherefore/plan/` and write `wherefore/plan/README.md` with exactly the content below. The loader globs `plan/P-*.md`, so this `README.md` is never collected as an item. Do NOT write any - P-item; opening items is the `plan` skill's job. + P-item; opening items is the `slate` skill's job. ````markdown # Plan collection (`wherefore/plan/`) @@ -107,7 +107,7 @@ approval; wait for their reply before writing anything. | `answers` | no | `Q-NNN` | a single question this item is the work of answering (spike)| | `dropped_reason`| no | string | lightweight why, used when `status: dropped` | - Body: freeform. The `plan` skill breaks the work into `- [ ]` checkboxes by default + Body: freeform. The `slate` skill breaks the work into `- [ ]` checkboxes by default (steps concrete enough to check off); prose stays valid, and older items may be prose-only. @@ -142,17 +142,17 @@ approval; wait for their reply before writing anything. ## Boundaries - - The `plan` skill writes only `wherefore/plan/*`. Never `log/`, never `questions/`, + - The `slate` skill writes only `wherefore/plan/*`. Never `log/`, never `questions/`, never `ROADMAP.md`. - Durable why belongs in the decision layer: when a plan item's rationale is really a decision, that is a `capture`; when a direction changes for a reason worth keeping, that is a `supersede` on the decision, and the plan item flips to `dropped` carrying `decision_ref` to it. - `capture` never creates plan items and never writes plan status directly; it may hand - off to the `plan` skill. The `plan` skill records that something changed; the decision + off to the `slate` skill. The `slate` skill records that something changed; the decision layer owns the durable why. - Maintained by the [wherefore](https://github.com/DustinVK/wherefore) plan skill. + Maintained by the [wherefore](https://github.com/DustinVK/wherefore) slate skill. ```` Finish with a one-line summary of what was written and where. diff --git a/plugins/wherefore/skills/ask/SKILL.md b/plugins/wherefore/skills/ask/SKILL.md index 75f2b1e..386765b 100644 --- a/plugins/wherefore/skills/ask/SKILL.md +++ b/plugins/wherefore/skills/ask/SKILL.md @@ -134,7 +134,7 @@ fabricate an answer. 8. **Offer to link a blocking question to a plan item.** When a question surfaced above (or one the user just raised) blocks work in flight, offer to attach it as a `question_ref` on the relevant plan item. The link is one-way, from the plan item - to the question. Making the attachment is a `plan` operation (its advance intent); + to the question. Making the attachment is a `slate` operation (its advance intent); `ask` only offers it and does not write `plan/` itself. Optionally, when the user is clearly asking about in-flight work, surface matching plan items alongside the open questions, still read-only, by dumping `wherefore/plan/P-*.md` frontmatter the diff --git a/plugins/wherefore/skills/capture/SKILL.md b/plugins/wherefore/skills/capture/SKILL.md index 0772a1c..a8a2344 100644 --- a/plugins/wherefore/skills/capture/SKILL.md +++ b/plugins/wherefore/skills/capture/SKILL.md @@ -187,9 +187,9 @@ scalar to a one-line summary and move the detail into a body section. - If the decision implies new work, name the pieces you would open. You distilled, tagged, and propose these plan links on the user's behalf, so let them correct all of it before it ossifies. `ask` derives everything from the frontmatter you just wrote. -12. Act on the confirmed plan links, but never create or mutate `plan/` from here; hand off to the `plan` skill. Capture owns `log/`, `plan` owns `plan/`. - - Confirmed close: hand off to `plan` advance to set that item `status: done` and add `decision_ref: `. The handoff marks capture as the driver, so `plan` advance suppresses its return capture offer (this decision is already being captured) and the path does not loop. Safe because it resolves a commitment already made, it does not invent one. - - Confirmed new work: hand off to `plan` open, with `decision_ref: ` set on each item. +12. Act on the confirmed plan links, but never create or mutate `plan/` from here; hand off to the `slate` skill. Capture owns `log/`, `slate` owns `plan/`. + - Confirmed close: hand off to `slate` advance to set that item `status: done` and add `decision_ref: `. The handoff marks capture as the driver, so `slate` advance suppresses its return capture offer (this decision is already being captured) and the path does not loop. Safe because it resolves a commitment already made, it does not invent one. + - Confirmed new work: hand off to `slate` open, with `decision_ref: ` set on each item. On no confirmation, write nothing to `plan/`. Never auto-emit plan items and never auto-close them: manufacturing or silently closing commitments nobody chose is the rot the plan collection exists to avoid (decision `2026-07-18-capture-does-not-write-plan-items`). ## Examples diff --git a/plugins/wherefore/skills/resolve/SKILL.md b/plugins/wherefore/skills/resolve/SKILL.md index 0b6df75..f60d0ab 100644 --- a/plugins/wherefore/skills/resolve/SKILL.md +++ b/plugins/wherefore/skills/resolve/SKILL.md @@ -81,16 +81,16 @@ summary and move detail into a `## Resolution` body section. `status` and anything. Then: - Unblocked: items whose `question_ref` is the ID you just resolved just became unblocked. Tell the user; do not change their status. The item stays where it is - until someone advances it through the `plan` skill. + until someone advances it through the `slate` skill. - Answered: items whose `answers` is that ID just accomplished their purpose (the spike that was investigating it). Report them and offer to advance them to `done` - through the `plan` skill. Do not advance them silently, and do not advance them + through the `slate` skill. Do not advance them silently, and do not advance them here yourself. - - Break the loop: if the `plan` skill drove this resolve (its advance intent handed + - Break the loop: if the `slate` skill drove this resolve (its advance intent handed off here to close the question a finishing spike answered), suppress the offer to - advance those items. `plan` is already advancing the item; offering to advance it - back would loop. This mirrors how `plan` advance suppresses its capture offer when - capture is the driver. Reading `plan/` here does not compromise `plan`'s sole + advance those items. `slate` is already advancing the item; offering to advance it + back would loop. This mirrors how `slate` advance suppresses its capture offer when + capture is the driver. Reading `plan/` here does not compromise `slate`'s sole ownership of it; nothing is written. ## Examples diff --git a/plugins/wherefore/skills/plan/SKILL.md b/plugins/wherefore/skills/slate/SKILL.md similarity index 95% rename from plugins/wherefore/skills/plan/SKILL.md rename to plugins/wherefore/skills/slate/SKILL.md index 34903a5..4c8c690 100644 --- a/plugins/wherefore/skills/plan/SKILL.md +++ b/plugins/wherefore/skills/slate/SKILL.md @@ -1,16 +1,17 @@ --- -name: plan +name: slate description: > - Manage forward-looking plan items in the team's wherefore plan collection. Use - whenever the user wants to open a new plan item, advance one along (todo to doing - to done), drop one, or ask what they are working on, e.g. "add a plan item for X", - "start on P-101", "mark P-102 done", "what's on the plan", "what am I working on", - "drop P-103, we're not doing it", or invoke "/wherefore:plan". Detects the intent - from the request rather than taking subcommands. Breaks work into concrete - checkboxes on open; never bulk-generates plan items from a vague prompt. + Operate the wherefore plan collection: the forward-looking work items in + wherefore/plan/. Use whenever the user wants to open a new plan item, move one + along (todo to doing to done), drop one, or see what is in flight, e.g. "add a + plan item for X", "open a plan item to migrate auth", "start on P-011", "mark + P-012 done", "what am I working on", "what is on the plan", "drop P-007, we're not + doing it", or invoke "/wherefore:slate". Detects the intent from the request rather + than taking subcommands. Breaks work into concrete checkboxes on open; never + bulk-generates items from a vague prompt. --- -# Wherefore: plan +# Wherefore: slate Operate the wherefore plan collection: forward-looking work items, one file each, tracking what is committed and how far along it is. A plan item is a commitment, not @@ -173,7 +174,7 @@ done - If the item carries `answers: Q-NNN` (a spike), the capture offer above still applies, and additionally offer to resolve that answered question via `resolve`. Do not resolve it silently; finishing the investigation is not the same as having an - answer. This handoff marks `plan` as the driver, so `resolve` suppresses its return + answer. This handoff marks `slate` as the driver, so `resolve` suppresses its return offer to advance this item, the same way capture-driven advance suppresses its capture offer. 7. To block an item, attach a `question_ref` to the open question it waits on. If that diff --git a/plugins/wherefore/skills/supersede/SKILL.md b/plugins/wherefore/skills/supersede/SKILL.md index e100c96..ff21ea2 100644 --- a/plugins/wherefore/skills/supersede/SKILL.md +++ b/plugins/wherefore/skills/supersede/SKILL.md @@ -19,8 +19,8 @@ truth. This skill is the only writer of decision status. Plan items have their own status machine (`todo`/`doing`/`done`/`dropped`) that never touches a decision's status; if -any plan flow needs to retire or replace a decision, it routes here, not through the -`plan` skill. +work in the `slate` skill needs to retire or replace a decision, it routes here, not +through `slate`. No em dashes. Periods, commas, colons, semicolons, or parentheses instead. Firm project rule. diff --git a/wherefore/ROADMAP.md b/wherefore/ROADMAP.md index 5ef37ae..622d800 100644 --- a/wherefore/ROADMAP.md +++ b/wherefore/ROADMAP.md @@ -47,7 +47,7 @@ truth. ### M4: Plan layer shipped Status: active. Serves: G2. -The `P-NNN` plan collection, the `/wherefore:plan` verb, dashboard rendering of plan +The `P-NNN` plan collection, the `/wherefore:slate` verb, dashboard rendering of plan items, and this roadmap. Currently dogfooding the frontmatter contract by hand before wiring the loader and the skill. diff --git a/wherefore/log/2026-07-18-rename-plan-skill-to-slate.md b/wherefore/log/2026-07-18-rename-plan-skill-to-slate.md new file mode 100644 index 0000000..9a9c502 --- /dev/null +++ b/wherefore/log/2026-07-18-rename-plan-skill-to-slate.md @@ -0,0 +1,43 @@ +--- +date: 2026-07-18 +title: "Rename the plan skill to slate" +areas: [plugin] +topics: [skill-structure] +stories: [] +status: active +supersedes: +superseded_by: +superseded_date: +--- + +## Summary +The skill that operates `wherefore/plan/` is renamed from `plan` to `slate`. Only the +verb changes: the directory, the `P-NNN` scheme, the frontmatter contract, and every +settled ruling stay exactly as they were. + +## Decisions / outcomes +- The skill verb is `slate`, invoked as `/wherefore:slate`. +- A skill verb and the collection it writes are allowed to diverge. `capture` writes + `log/`, `resolve` writes `questions/`, and now `slate` writes `plan/`. The verb names + the action, not the folder. +- The description leads with the collection (operating the items in `wherefore/plan/`), + not with the activity of planning. Trigger phrases center on the artifacts ("open a + plan item", "mark P-012 done", "what am I working on", "drop P-007"). +- The collection keeps its name. `wherefore/plan/`, `plan/README.md`, the `P-NNN` ids, + and the "Plan items" doc sections are unchanged. + +## Why +`plan` as a verb collides with Claude Code's built-in plan mode. The namespaced command +`/wherefore:plan` resolves, but the skill description competed for triggering whenever +someone said something like "plan the auth migration," and that ambiguity is reason +enough to move. Leading the description with the collection rather than the activity is +what actually keeps the two apart: `slate` reads as operating existing items, not as a +request to plan work. + +## Alternatives considered +- `track`, rejected for dragging in issue-tracker connotations the collection does not + want. +- `commit`, rejected for colliding with git. + +## Open questions / follow-ups +- None. diff --git a/wherefore/plan/P-004-author-plan-skill.md b/wherefore/plan/P-004-author-plan-skill.md index 05843e4..ad79c94 100644 --- a/wherefore/plan/P-004-author-plan-skill.md +++ b/wherefore/plan/P-004-author-plan-skill.md @@ -1,6 +1,6 @@ --- id: P-004 -title: Author the plan skill +title: Author the slate skill status: done created: 2026-07-18 updated: 2026-07-18 @@ -9,7 +9,7 @@ topics: [skill-structure] decision_ref: 2026-07-03-plan-directory, 2026-07-18-capture-does-not-write-plan-items --- -Build the wherefore plan skill: one verb, four intents detected from the request, not +Build the wherefore slate skill: one verb, four intents detected from the request, not subcommands. Mirror the sibling skills in structure and tone. - [x] SKILL.md frontmatter (name plus folded description) and a 3 to 5 line mission, no allowed-tools, matching capture/ask/resolve/supersede. From 5df6dbddfe5fc6475426dc29c7650f3ac8d323c3 Mon Sep 17 00:00:00 2001 From: Dustin VanKrimpen Date: Sat, 18 Jul 2026 22:40:46 -0400 Subject: [PATCH 4/4] wherefore: bump plugin to 0.2.0 for the new slate skill Adding a fifth skill (slate) is an additive feature, so bump the minor version. Co-Authored-By: Claude Opus 4.8 (1M context) --- plugins/wherefore/.claude-plugin/plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wherefore/.claude-plugin/plugin.json b/plugins/wherefore/.claude-plugin/plugin.json index a74ab56..6cbebff 100644 --- a/plugins/wherefore/.claude-plugin/plugin.json +++ b/plugins/wherefore/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "wherefore", "description": "Distill technical discussions into compact, tagged decision entries with a live registry of open questions, all version-controlled in your repo and queryable by Claude.", - "version": "0.1.3", + "version": "0.2.0", "author": { "name": "Dustin VanKrimpen" },