From 1907281b4013d6fae7cc1ab82b1baaa22eebfbac Mon Sep 17 00:00:00 2001 From: Justin Parker Date: Sat, 8 Aug 2026 19:00:26 -0700 Subject: [PATCH] Add a GitHub Issues backend to Pathfinder Chart Step 1 now asks where the map should live: local files under gitignored specs/ (the default) or a pathfinder:map issue whose decision questions are its sub-issues, driven by gh. The pick is recorded as the first Ground rules bullet and never re-asked; Auto-Discovery resolves either backend, and an issue URL routes straight to github. On github the local model maps onto the tracker's own primitives rather than being simulated in issue bodies: sub-issues, native issue dependencies for blocking, the assignee as the claim, one pathfinder:- label so type and mode cannot drift, and an Answer comment plus a close reason that distinguishes a decision from a question ruled out of scope. Both wiring calls key on the database id, not the number. The map body therefore carries no checklist at all. Sketches, secrets and the PLAN-DRAFT stay on local disk regardless -- plan2code-1-plan discovers its input with ls specs/ and has no notion of a tracker. github is only offered after a five-check preflight, and the offer names the repo's visibility, because a map on a public tracker publishes the destination and the codebase recon. The Step 3 recon is held until Step 6 so the no-fog off-ramp leaves no litter. Depth lives in a seventh reference file; the orchestrator was recompressed to absorb the new section within the 11,000 char limit by removing duplication with its references. Adapted from the GitHub tracker doc behind Matt Pocock's wayfinder skill (MIT). AI Assisted --- CHANGELOG.md | 18 + QUICK-REFERENCE.md | 5 +- README.md | 7 +- package.json | 2 +- .../chart.md | 6 +- .../github-issues.md | 449 ++++++++++++++++++ .../handoff.md | 2 + .../questions.md | 2 + .../resolve.md | 2 + .../trail.md | 2 + src/plan2code-0-pathfinder.md | 119 ++--- version.json | 2 +- 12 files changed, 551 insertions(+), 65 deletions(-) create mode 100644 src/plan2code-0-pathfinder-references/github-issues.md diff --git a/CHANGELOG.md b/CHANGELOG.md index ef06961..4520c97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,24 @@ All notable changes to Plan2Code will be documented in this file. +## v2.1.0 + +### ✨ Added + +- **GitHub Issues backend for Pathfinder** — `/plan2code-0-pathfinder` no longer assumes local files. Chart Step 1 now asks, HITL and never self-picked, where the map should live: **local** (the default — files under gitignored `specs//pathfinder/`, private and solo) or **github** (a `pathfinder:map` issue whose decision questions are its sub-issues, driven by the `gh` CLI). The pick is recorded as the first `## Ground rules` bullet, never re-asked and never switched mid-map, and Auto-Discovery resolves either backend — an issue URL or number as the argument routes straight to `github`. + + On `github`, the local model maps onto the tracker's own primitives rather than being simulated in issue bodies: a question is a **sub-issue** (`sub_issues` endpoint), blocking is GitHub's **native issue dependencies** (`dependencies/blocked_by`, so the frontier renders in GitHub's UI without opening the map), the claim is the **assignee**, `Type:` becomes a single `pathfinder:-` label so type and mode cannot drift, `Locked: yes` becomes `pathfinder:locked`, and resolution is an `## Answer` comment followed by a close — `completed` for a decision, `not planned` for a question ruled out of scope. Both wiring calls key on the issue's **database id**, not its `#number`. The map body therefore carries no question checklist at all: the frontier is a live query, which removes the single largest source of drift in the local backend. + + Three things stay on local disk whatever the backend: runnable sketches (`specs//pathfinder/sketch-NN/`), anything secret, and the `PLAN-DRAFT-.md` — `/plan2code-1-plan` discovers its input with `ls specs/` and has no notion of a tracker, so a draft that existed only as an issue would be invisible to the rest of the pipeline. + + Guardrails carried over from the local backend's assumptions: `github` is only offered after a five-check preflight (`gh` present, authenticated, GitHub remote, issues enabled, push access), and the offer must name the repo's **visibility** in the same breath, because a map on a public tracker publishes the destination, the rejected alternatives, and the codebase recon. The Step 3 recon is held in-session and published at Step 6, so the Step 4 no-fog off-ramp leaves no litter on a shared tracker. A `gh` failure mid-session stops the session rather than falling back to local files, which would fork the map. + + Depth lives in a seventh reference file, `src/plan2code-0-pathfinder-references/github-issues.md` — preflight, label set, the local↔GitHub equivalence table, create-then-wire charting, the frontier query, resolve and out-of-scope flows, reconcile, the trail footer, handoff, and a failure-mode table. Adapted from the GitHub tracker doc behind Matt Pocock's [`wayfinder`](https://github.com/mattpocock/skills/tree/main/skills/engineering/wayfinder) skill (MIT). + +### 🔧 Changed + +- **`src/plan2code-0-pathfinder.md` recompressed** to absorb the new `## Backend` section within the 11,000-character workflow-file limit — duplication between the orchestrator and its reference files was removed (the local layout and marker legend now live only in `questions.md`; Form A/B footer detail only in `trail.md`), and step text tightened. No behaviour was dropped. + ## v2.0.0 Ports upstream v1.17.0 and v2.0.0 into Plan2Code. diff --git a/QUICK-REFERENCE.md b/QUICK-REFERENCE.md index 850e4fa..ac62baa 100644 --- a/QUICK-REFERENCE.md +++ b/QUICK-REFERENCE.md @@ -6,7 +6,7 @@ | ------- | ----------------------------- | --------------- | -------------------------------------------------- | | Init | /plan2code-init | None | AGENTS.md file | | Update | /plan2code-init-update | AGENTS.md | Updated AGENTS.md | -| 0 | /plan2code-0-pathfinder | A foggy idea | pathfinder/map.md + PLAN-DRAFT-.md | +| 0 | /plan2code-0-pathfinder | A foggy idea | pathfinder/map.md *or* GitHub Issues + PLAN-DRAFT-.md | | quick | /plan2code-quick-task | Requirements | Conversational plan (standalone — not a pipeline step) | | review | /plan2code-review | Scope guidance | Review findings + fixes | | 1 | /plan2code-1-plan | Requirements | PLAN-CONVERSATION-.md + PLAN-DRAFT-.md | @@ -21,9 +21,10 @@ ``` specs/ └── / - ├── pathfinder/ # From Step 0 (optional, if charted) + ├── pathfinder/ # From Step 0 (optional, if charted locally) │ ├── map.md # the map: destination, decisions, fog │ └── questions/NN-.md # one decision question per file + │ # (GitHub Issues backend: map issue + sub-issues instead) ├── PLAN-DRAFT-.md # From Step 1 (verified plan) ├── PLAN-CONVERSATION-.md # From Step 1 (conversation log) ├── overview.md # From Step 2 diff --git a/README.md b/README.md index ae17540..5ae0987 100644 --- a/README.md +++ b/README.md @@ -166,7 +166,9 @@ it as requirements, so planning would just invent the answers. Pathfinder finds destination; Step 1 then walks it. 1. **Name the destination** — one or two lines fixing what this effort is finding its way to. Settled - first, because it fixes scope. + first, because it fixes scope. It also asks where the map should live: **local files** under + gitignored `specs/` (private, solo — the default), or **GitHub Issues** (a map issue with one + sub-issue per decision, native blocking, so your team can see and work the frontier in the tracker). 2. **Chart the map** — a breadth-first grilling surfaces the open decisions. Anything you can phrase *sharply* becomes a question file; anything you can only sense stays listed as fog. 3. **Clear one question per session** — resolving a question burns off the fog behind it, graduating @@ -182,7 +184,8 @@ react to) · `legwork` (manual work that has to happen before a decision is poss It never answers its own questions, and it **plans, it never builds.** When the urge to just build it arrives, the map is done. Skip Step 0 entirely when you already know what you're building. -**Out:** `specs//pathfinder/map.md` + `questions/` → `PLAN-DRAFT-.md` +**Out:** `specs//pathfinder/map.md` + `questions/` (or a `pathfinder:map` issue and its +sub-issues) → `PLAN-DRAFT-.md`. The draft is always a local file — that is what Step 1 reads. ### 1 · Plan 🤔 diff --git a/package.json b/package.json index 3b10daf..cad4135 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "plan2code", - "version": "2.0.0", + "version": "2.1.0", "private": true, "bin": { "plan2code": "./install.js" diff --git a/src/plan2code-0-pathfinder-references/chart.md b/src/plan2code-0-pathfinder-references/chart.md index 2f80263..2e84550 100644 --- a/src/plan2code-0-pathfinder-references/chart.md +++ b/src/plan2code-0-pathfinder-references/chart.md @@ -1,5 +1,7 @@ # Chart Playbook > Part of plan2code-0-pathfinder — loaded at the top of MODE A (Chart). Expands the numbered Chart steps. +> +> **Backend note.** Steps 0, 2, and 4 — the gates and the grills — are identical either way, and so is every judgement call below (fog vs question, in scope vs out, the destination test). What differs is where Steps 3 and 5-7 put the bytes: on `**Backend:** github`, `github-issues.md` overrides the `map.md` and question-file templates here, the single-pass rule under *Step 6: Numbering and dependency order*, and the timing of the recon. Read it alongside this file, not instead of it. Charting produces a map and a set of question files. It resolves nothing by hand. Every judgement below serves one goal: put a sharp question on the map for everything you can phrase now, and leave everything else honestly in the fog. @@ -342,7 +344,9 @@ Watch for **stranded** questions: a live question whose `Blocked by:` names some ## Step 6: Numbering and dependency order -Upstream wayfinder creates every unit first and wires the blocking edges in a **second pass**, because a server-side tracker assigns ids and nothing can reference a sibling until it has one. That constraint does not exist here — **you choose `NN` yourself**, so charting is a **single pass**: decide the order, then write each file complete, `Blocked by:` filled at the moment of writing. +Upstream wayfinder creates every unit first and wires the blocking edges in a **second pass**, because a server-side tracker assigns ids and nothing can reference a sibling until it has one. On `**Backend:** local` that constraint does not exist — **you choose `NN` yourself**, so charting is a **single pass**: decide the order, then write each file complete, `Blocked by:` filled at the moment of writing. + +(On `**Backend:** github` the constraint comes back, and so does the two-pass shape. Rules 1, 6, 7, and 8 below still hold — they are about dependency reasoning, not about ids. Rules 2-5, which are about `NN`, are replaced by sub-issue order; see `github-issues.md`.) The rules: diff --git a/src/plan2code-0-pathfinder-references/github-issues.md b/src/plan2code-0-pathfinder-references/github-issues.md new file mode 100644 index 0000000..dc8d8b3 --- /dev/null +++ b/src/plan2code-0-pathfinder-references/github-issues.md @@ -0,0 +1,449 @@ +# GitHub Issues Backend + +> Part of plan2code-0-pathfinder — loaded at the top of EVERY session whose map lives on GitHub Issues. It re-expresses the local-file model in issue terms: where the map lives, where a question lives, how blocking, claiming, and resolving are done, and what stays on local disk regardless. +> +> **Local-file maps never load this file.** If `## Ground rules` says `**Backend:** local`, close it and use `questions.md`. + +Everything the skill says about *judgement* is unchanged by the backend: the fog-vs-question test, the destination grill, one question per session, HITL is never self-answered, the Clearing Gate rubric. This file changes only *where the bytes go*. + +--- + +## Why a second backend exists + +Local files are private scratch — `specs/` is gitignored, so the map is yours alone and nobody else can see it, comment on it, or resolve a question in parallel. That is the right default for a solo effort. + +A map on GitHub Issues buys three things local files cannot: + +| | Local files | GitHub Issues | +|---|---|---| +| Visibility | One machine, one person | Anyone with repo access, in a UI they already have open | +| Blocking | A `Blocked by:` line only an agent reads | Native issue dependencies — GitHub greys out blocked issues in its own UI | +| Concurrency | One session at a time by construction | Several people can work unblocked questions at once; the assignee is a real lock | + +It costs three things too, and the human must know all three before they pick it: + +1. **Issues on a public repo are public.** The destination, the rejected alternatives, the codebase recon, the technical debt in the blast radius — all of it is world-readable the moment it is written. Never chart to a public repo's tracker anything that would embarrass the project or leak a customer. +2. **It writes to shared state.** A local map costs nothing to abandon. Twelve stale issues labelled `pathfinder:grill-hitl` on a team's tracker is litter someone has to clean. +3. **It needs `gh`, auth, and issues enabled.** More that can break, in a step whose whole job is to remove friction. + +--- + +## Preflight — before the first write + +Run these once, at Chart Step 1, **before** offering GitHub as an option. Any failure means GitHub is not offered at all; say why in one line and continue with local files. + +| # | Check | Command | On failure | +|---|---|---|---| +| 1 | `gh` is installed | `gh --version` | Not offered — "no `gh` on this machine" | +| 2 | Authenticated | `gh auth status` | Not offered — "`gh` is not logged in" | +| 3 | Inside a repo with a GitHub remote | `gh repo view --json nameWithOwner,visibility,hasIssuesEnabled` | Not offered — "no GitHub remote here" | +| 4 | Issues are enabled | same call, `hasIssuesEnabled` | Not offered — "issues are disabled on this repo" | +| 5 | Write access | `gh api repos// --jq .permissions.push` | Not offered — read-only access cannot chart | + +Record `nameWithOwner` and `visibility` from check 3 — **`visibility` is not optional detail.** If it is `PUBLIC`, the offer must say so in the same breath, e.g. *"GitHub Issues — note `jparkerweb/plan2code` is public, so the whole map is world-readable."* + +Once a map exists, preflight shrinks to checks 1 and 2. A session that cannot reach `gh` cannot work a GitHub map: say so and stop, rather than silently starting a local one. + +### Labels + +Create the label set at **Chart Step 5**, with the map issue — never during preflight, which must stay read-only until the human has actually picked `github`. `--force` makes it idempotent, so it is safe to re-run every session: + +```bash +gh label create "pathfinder:map" --color 5319E7 --description "Pathfinder map" --force +gh label create "pathfinder:grill-hitl" --color 1D76DB --description "Decision only the human can make" --force +gh label create "pathfinder:research-afk" --color 0E8A16 --description "Fact-finding, agent alone" --force +gh label create "pathfinder:sketch-hitl" --color FBCA04 --description "Human reacts to something concrete" --force +gh label create "pathfinder:legwork-hitl" --color D93F0B --description "Manual work needing a human" --force +gh label create "pathfinder:legwork-afk" --color D93F0B --description "Manual work the agent can do" --force +gh label create "pathfinder:locked" --color B60205 --description "Hard to reverse; consequences recorded" --force +gh label create "pathfinder:out-of-scope" --color CFD3D7 --description "Ruled past the destination" --force +``` + +**Type and mode share one label** — `grill-hitl`, not `grill` plus `hitl` — for the same reason the local `Type:` line is one token: two labels can drift apart, and a `research` question that has quietly become HITL is a question nobody is driving. + +--- + +## The equivalence table + +This is the whole mapping. Everything below expands a row. + +| Local file model | GitHub Issues model | +|---|---| +| `specs//pathfinder/map.md` | One issue, labelled `pathfinder:map`, titled `Map: ` | +| `questions/NN-.md` | A **sub-issue** of the map, titled with the question name | +| `NN` ordering | The map's sub-issue order — the order they were created, which is dependency order | +| `## Question` in the file | The issue body | +| `## Answer` appended | A comment on the issue, opening `## Answer` | +| `## Evidence` | A comment opening `## Evidence` (a research subagent writes its own) | +| `Type:` line | The `pathfinder:-` label | +| `State: open` | Issue open, **no assignee** | +| `State: claimed` | Issue open, **assigned** | +| `State: resolved` | Issue **closed as completed**, with an `## Answer` comment | +| `State: out-of-scope` | Issue **closed as not planned**, labelled `pathfinder:out-of-scope`, no `## Answer` | +| `Blocked by: 02, 04` | Native issue dependencies (`dependencies/blocked_by`) | +| `Locked: yes` | The `pathfinder:locked` label | +| `Claimed: ` | GitHub's own assignment event in the timeline | +| `## Question Checklist` in `map.md` | **Nothing** — the frontier is a live query, not a written list | +| `## Not yet specified`, `## Out of scope`, `## Ground rules`, `## Destination`, `## Glossary` | The same sections, in the map issue body | +| `sketch-NN/` | Still local disk — see *What stays on local disk* | +| `PLAN-DRAFT-.md` | Still local disk — see *Handoff* | + +### The checklist is deleted, not ported + +In local mode `map.md` carries a `## Question Checklist` because a directory of files has no queryable state. GitHub has queryable state, so **the map issue body carries no checklist at all.** Closed questions get one line each under `## Decisions so far`; open questions are not listed anywhere. + +This kills the single largest source of drift in the local backend — a checklist that disagrees with the files — and it is why Work Step 2's reconcile pass is much shorter here. + +--- + +## Refer by name + +Unchanged, and harder to get right here because GitHub hands you a number for everything. In prose the human reads, write `[Export format](https://github.com/o/r/issues/42)` — never `#42`, never "issue 42", never a bare number. A wall of `#42, #43, #44` is illegible; names read at a glance. + +Bare `#` appears in exactly two places: inside a fallback `Blocked by:` body line when native dependencies are unavailable, and inside a `gh` command. + +--- + +## Chart Steps 3-4 — hold the recon, protect the off-ramp + +In `local` mode Step 3 writes `questions/00-codebase-context.md` the moment the recon is done, because a file in gitignored scratch costs nothing if the session then takes the Step 4 off-ramp. **On a shared tracker it costs something**: a stray issue nobody asked for, on a repo other people are watching. + +So on `github`, Step 3 does the recon and **holds it in the session**. It becomes an issue at Step 6, alongside the other questions. + +If the Step 4 breadth-first grill surfaces **no fog**, the off-ramp fires before anything has been created: + +1. Write the recon to `specs//pathfinder/questions/00-codebase-context.md` — a **local file**, exactly as the local backend would. It is what `/plan2code-1-plan` Phase 2 needs, and it is too valuable to throw away. +2. Create **nothing** on the tracker. No map issue, no question issues, no labels. +3. Tell the user plainly and STOP. + +The tracker only ever sees an effort that earned a map. + +--- + +## Creating the map (Chart Step 5) + +Title is `Map: ` — the kebab-case idea name, verbatim, so `gh issue list --label pathfinder:map` reads as an index of efforts. + +```bash +gh issue create --label "pathfinder:map" --title "Map: audit-log-export" --body-file - <<'EOF' +> Pathfinder planning note - decisions, not implementation work. Archive with the spec; do not delete. + +**Status:** Charting +**Updated:** 2026-08-08 +**Confidence:** Requirements-clarity 8/25 · Feasibility-technical 6/25 · Integration-points 6/25 · Risk-assessment 5/25 + + + +## Destination + +A locked implementation plan for a compliance officer to export a filtered range of audit +events from the admin UI and receive them as a single downloadable file. The map ends at the +plan, not at shipped code. Continuous streaming to external systems is not on the route. + +## Ground rules + +- **Backend:** github — this issue is the map; questions are its sub-issues. +- `AGENTS.md` exists and governs. Its conventions are not re-litigated by any question here. +- One question _issue_ per session. `research` questions may run as parallel subagents. +- HITL questions are answered by the human in their own words. Never self-answered. +- Sketches are throwaway and live on local disk only, under `specs/audit-log-export/pathfinder/sketch-/`. + +## Glossary + +| Term | Meaning here | Avoid | +|---|---|---| +| Audit event | One row in `audit_events`: actor, tenant, action, target, timestamp, payload | log line | + +## Decisions so far + + + +## Not yet specified + + + +## Out of scope + + +EOF +``` + +Two things that must be exact: + +- **`**Status:**` is still a literal line in the body.** It is how a fresh session routes, exactly as in local mode. `Charting` → `Working` → `Cleared`. +- **`**Backend:** github` is the first `## Ground rules` bullet.** It is how a fresh session knows to load this file at all. Without it, a session that opens the map issue has no way to know which playbook it is in. + +Confidence keeps the hyphenated `Requirements-clarity 8/25` form for the same reason it does in local mode — the metrics collector scrapes bare dimension words followed by digits, and would ingest a planning confidence nobody scored. + +**Say once, at Step 5:** *"The map lives on `/`'s issue tracker — ``, so ``. Everything charted here is visible there."* + +--- + +## Creating the questions (Chart Step 6) — two passes, not one + +The local backend charts in a **single pass** because you choose `NN` yourself and can write `Blocked by: 02` into a file before `02` exists. **On GitHub that is impossible** — an issue has no id until the server assigns one, and a dependency edge needs the blocker's id. So charting here reverts to upstream's shape: + +**Pass 1 — create every question issue, in dependency order.** Blockers first. The creation order becomes the sub-issue order, which becomes the reading order for the frontier and the trail, so it is doing the job `NN` does locally. Capture each new issue's number *and* database id as you go. + +```bash +# Create, capturing the URL; the number is its last path segment. +gh issue create --label "pathfinder:grill-hitl" --title "Export format" --body-file - <<'EOF' +> Pathfinder planning note - decisions, not implementation work. Archive with the spec; do not delete. + +## Question + +What file format does an export produce, and what does a recipient need in order to trust +the file has not been altered? + +Recommended answer to react to: CSV with a UTF-8 BOM plus a sidecar SHA-256 manifest. +EOF + +# The database id — needed for BOTH wiring steps below. Not the #number, not the node_id. +gh api repos///issues/ --jq .id +``` + +**Pass 2 — wire the structure.** Two edges per question, both keyed on **database ids**: + +```bash +# a) Attach as a sub-issue of the map. sub_issue_id is the CHILD's database id. +gh api --method POST repos///issues//sub_issues \ + -F sub_issue_id= + +# b) Add each blocking edge. issue_id is the BLOCKER's database id. +gh api --method POST repos///issues//dependencies/blocked_by \ + -F issue_id= +``` + +**The database id is the single most common failure in this backend.** `gh api repos/o/r/issues/42 --jq .id` returns something like `2716143027`. The `42` is the *number*; `I_kwDO...` is the *node id*. The node id is rejected outright. The *number* is worse: a small integer like `42` is itself a perfectly valid database id — of some unrelated issue created years ago — so the call can succeed and silently attach the wrong thing. Fetch `.id` for every issue you are about to reference, and never hand-assemble one. + +Charting still writes `00-codebase-context`'s equivalent — the Step 3 recon you held. Create it **first**, labelled `pathfinder:legwork-afk`, post the recon as an `## Answer` comment, and close it as completed in the same pass. It is resolved on arrival, exactly as in local mode, and it is what the handoff's `## System Context` is built from. + +### If the endpoints are unavailable + +Sub-issues and dependencies are recent GitHub features. On an instance that rejects either endpoint, fall back in the body — and say plainly, once, that the frontier will not render in GitHub's UI: + +| Missing | Fallback | +|---|---| +| Sub-issues | Put `Part of #` on the first line of each question body, and a task list of the questions in the map body | +| Dependencies | Put `Blocked by: #12, #14` on its own line at the top of the question body | + +Prefer the native mechanisms every time they work. The whole reason to pay GitHub's costs is that the human sees the frontier in the UI without opening the map. + +--- + +## The frontier query (Work Step 3) + +The frontier is every question that is **open, unblocked, and unassigned**. Lowest position in sub-issue order wins — the same traversal `lowest NN first` gives locally. + +```bash +# 1. The map's children, in order, with the state you need to filter on. +gh api repos///issues//sub_issues \ + --jq '.[] | {number, title, state, assignee: .assignee.login, + blocked: .issue_dependencies_summary.blocked_by, + labels: [.labels[].name]}' +``` + +Then, in order: + +1. Drop anything `state: closed` — that is resolved or out of scope. +2. Drop anything with an `assignee` — claimed by another session. +3. Drop anything still blocked. +4. The first survivor is the next question. + +For step 3, `issue_dependencies_summary.blocked_by` counts **open** blockers, which is exactly the live gate — a blocker that closes drops the count without anyone editing anything. **Treat it as a fast pre-filter, not the authority.** If it comes back `null` or absent from the list response, or you need to *name* the blockers for the trail footer or a fully-blocked report, ask the endpoint that owns the answer: + +```bash +gh api repos///issues//dependencies/blocked_by --jq '.[] | {number, title, state, reason: .state_reason}' +``` + +A question is unblocked when every blocker listed there is closed. That call is also the only way to see the next trap: + +**A blocker closed as `not planned` is out of scope and will never resolve.** Its dependent is not merely blocked, it is *stranded* — the same trap as locally. Re-frame the dependent's body to drop the dependency, cut the edge, or rule it out too. Never leave it sitting: the summary count cannot tell you the difference, so this check is on you. + +```bash +# Cut a dependency edge. The blocker's database id goes in the PATH here, not the body. +gh api --method DELETE \ + repos///issues//dependencies/blocked_by/ +``` + +--- + +## Claim (Work Step 4) + +```bash +gh issue edit --add-assignee "@me" +``` + +**The session's first write, before any work.** The assignee *is* the claim — GitHub timestamps it for you, so there is no `Claimed:` line to maintain. An open, unassigned question is unclaimed; that is the whole protocol. + +Unlike the local backend, other people may genuinely be working this map at the same time. Re-read the issue immediately after assigning; if someone else's login is on it, you lost the race — release yours and take the next frontier item. + +--- + +## Resolve (Work Step 7) + +Three writes, in this order. The order matters: the answer must exist before the issue closes, or a crash between them leaves a closed question with no decision in it. + +```bash +# 1. The answer, as a comment. Same anatomy as a local ## Answer: +# decision, rejected alternatives with reasons, consequences, one-line **Gist:**. +gh issue comment --body-file - <<'EOF' +## Answer + +**Decision.** CSV, UTF-8 with a byte-order mark, RFC 4180 quoting, one header row. +Alongside it a sidecar `.sha256` manifest. + +**Rejected.** + +- *JSONL* — trivially streamable, but every named recipient opens these in Excel. +- *XLSX* — fixes Excel encoding, but adds a library and makes byte-level verification harder. + +**Consequences.** + +- Do not reuse the billing export's CSV writer; it concatenates strings with no escaping. +- Makes [Delivery channel](https://github.com/o/r/issues/45) sharper — the artifact is + self-verifying, so a short-lived link no longer weakens the integrity story. + +**Gist:** CSV with a UTF-8 BOM and RFC 4180 quoting, plus a sidecar SHA-256 manifest; +JSONL rejected because recipients open these in Excel. +EOF + +# 2. Close as completed. +gh issue close --reason completed + +# 3. Append the gist to the map's Decisions so far (read body, edit, write back). +gh issue view --json body --jq .body > /tmp/map.md +# ...append: - [Export format]() — +gh issue edit --body-file /tmp/map.md +``` + +Then bump `**Updated:**` and re-score `**Confidence:**` in the same map edit. + +**Never edit the question body to hold the answer.** The body is the question as asked; the comment is the answer. Editing the body rewrites history and destroys the record of what was actually put to the human — which is half of why the answer is defensible three weeks later. + +### Editing the map body safely + +Every map mutation is read-modify-write on a body other sessions may be editing concurrently. Read it fresh immediately before the edit, apply your change to *that* text, and write it straight back. Never edit from a copy you read at the top of the session — you will silently revert whatever landed in between. + +--- + +## Ruling a question out of scope (Work Step 8) + +```bash +gh issue edit --add-label "pathfinder:out-of-scope" +gh issue close --reason "not planned" +``` + +Then one line under the map's `## Out of scope`, giving the name as a link plus the reason. **No `## Answer` comment** — there is no decision here, only a scope boundary. Add one comment saying why it is out, so the closed issue explains itself. + +`not planned` versus `completed` is the load-bearing distinction: it is how a later session tells a decision that was made from a question that was ruled off the route, and it is what GitHub's UI shows at a glance. Getting it backwards puts a scope boundary into the Provenance table of the plan. + +--- + +## Reconcile (Work Step 2) + +Much shorter here — the tracker holds the state, so there is no checklist to rebuild. Three checks: + +| Check | Symptom | Repair | +|---|---|---| +| Crashed mid-answer | Open, assigned, and an `## Answer` comment already exists | The comment wins. Close as completed, add the gist to Decisions so far, say so. | +| Stale claim | Open, assigned, no `## Answer`, and the assignee is you from a dead session | Unassign, say so, put it back on the frontier. **If it is someone else's login, leave it** — that is a live session, not a crash. | +| Index drift | A closed, completed question with no line under `## Decisions so far` | Read its `## Answer` comment, append the gist. | + +Then re-read `## Not yet specified` in full — that part is identical to local mode, and the bullet left behind after its question exists is just as corrosive here. + +--- + +## What stays on local disk + +Three things never move to the tracker, whatever the backend: + +| Artifact | Where | Why | +|---|---|---| +| Runnable sketches | `specs//pathfinder/sketch-/` | Throwaway code has no business in an issue, and the quarantine rule (never in the project's own source tree) is unchanged. Link the path from the issue and note the reader needs the repo checked out. | +| `PLAN-DRAFT-.md` | `specs//` | `/plan2code-1-plan` reads a **file**. This is a hard downstream contract — see Handoff. | +| Anything secret | Nowhere | Credentials, tokens, customer data. A `legwork` checklist says *where* a credential lives, never what it is — and on a public tracker that rule stops being a convention and starts being an incident. | + +Sketch directories are named for the issue number rather than a local `NN`, so `sketch-42` belongs to the question at `#42`. Same rules otherwise: throwaway, one command to run, never merged. + +Research subagents work the same way with one substitution: the brief carries the **issue URL** instead of a file path, and the instruction is to post findings as a comment opening `## Evidence` via `gh issue comment` — and to decide nothing. `## Answer` and the close are still written by the session that fired it. + +--- + +## The trail footer + +Identical in shape; the inputs come from the query instead of the checklist. + +- **Heading** — `🧭 · · / cleared`, where `` excludes anything labelled `pathfinder:out-of-scope`. +- **Glyph order** — sub-issue order, the same order Chart Step 6 created them in. +- **Glyphs** — `●` closed as completed · `◉` open and assigned to you · `○` open, unassigned, unblocked · `⊘` open with `blocked_by > 0` · `⊝` closed as not planned. +- **Named legend** — names, never `#numbers`. `(blocked:)` names the blocker rather than numbering it, since there is no stable `NN` to point at. +- **Confidence** — the plain-English line, from the map body's `**Confidence:**`. + +Form A's resume command changes, because there is no local path to resume from: + +``` +NEXT STEP · start a new conversation and run: +`/plan2code-0-pathfinder https://github.com///issues/` +``` + +Form B is unchanged — a turn that asks the human something still says `WAITING ON YOU`, still names the outstanding probes, and still emits no resume command. + +--- + +## Handoff (The Clearing Gate) + +The gate's four dimensions, the 18/25 bar, the hard caps, and the honesty rules are unchanged. Only the preflight and the plumbing differ. + +**Preflight, GitHub form:** + +| # | Check | +|---|---| +| 1 | Reconcile pass run (above) | +| 2 | Zero open sub-issues — `gh api .../sub_issues --jq '[.[] \| select(.state=="open")] \| length'` returns `0` | +| 3 | `## Not yet specified` in the map body is empty | +| 4 | Every completed question has an `## Answer` comment carrying a `**Gist:**` | +| 5 | `ls specs//` shows no existing `PLAN-DRAFT-*.md` | +| 6 | No `## Answer` defers a choice to "whoever implements this" | + +**The draft is written to local disk**, at `specs//PLAN-DRAFT-.md`, with the byte-exact status line `**Status:** Phase 3 Complete - Resume at Phase 4`. This is not a preference. `/plan2code-1-plan` discovers its input with `ls specs/`; it has no notion of an issue tracker, and a draft that exists only as an issue is a draft the rest of plan2code cannot see. Create `specs//` if charting never needed it. + +Three substitutions inside the template: + +| Local | GitHub | +|---|---| +| `**Planning record:** specs//pathfinder/map.md` | `**Planning record:** ` | +| `[Export format](./pathfinder/questions/01-export-format.md)` | `[Export format](https://github.com/o/r/issues/42)` | +| `## Out of scope` copied line for line, only the link prefix changing | Copied line for line, links already absolute — **nothing changes at all** | + +Everything else — the mapping table, Section 5 left empty, the two load-bearing `**Next:**` bullets, no scrapable confidence numbers — is unchanged. + +**Freeze the map:** + +1. Set `**Status:** Cleared` in the map issue body. +2. Bump `**Updated:**`. +3. Add `**Plan:** specs//PLAN-DRAFT-.md` under the status line. +4. `gh issue close --reason completed`. +5. **Close nothing else, delete nothing, edit no answers.** Every question issue stays exactly as it is — it is the rationale record behind the plan. + +Closing the map is the one addition over local mode, and it earns its place: `gh issue list --label pathfinder:map --state open` then reads as *the efforts still being charted*, which is the question a person scanning the tracker actually has. + +A later session that opens a map issue reading `Status: Cleared` must not resume it. Point at the PLAN-DRAFT and `/plan2code-1-plan`, and stop. A redrawn destination is a fresh effort with a fresh map issue. + +--- + +## Failure modes + +| Symptom | Cause | Fix | +|---|---|---| +| `Not Found` from a `sub_issues` or `dependencies` POST | An issue *number* was passed where a database *id* is required | `gh api repos/o/r/issues/ --jq .id`, retry with that | +| The wrong issue got attached | A number from another repo happened to be a valid id | Detach, re-fetch `.id` from the right repo, re-attach | +| Frontier is empty but open questions remain | Every one is blocked, or every one is assigned | Name the chain and stop — or, if the assignees are stale claims from your own dead sessions, reconcile first | +| A blocked question never unblocks | Its blocker was closed as `not planned` | Stranded. Re-frame to drop the dependency and cut the edge, or rule it out too | +| Two sessions resolved the same question | The claim was written after the work, not before | Claim is the *first* write. Merge the two answers into one comment, keep one close | +| A map edit lost someone's line | The body was edited from a stale copy read earlier in the session | Re-read the body immediately before every map write | +| `/plan2code-1-plan` finds nothing to resume | The PLAN-DRAFT was posted as an issue instead of written to `specs//` | Write the file. The draft is always local | +| Secrets in the tracker | A `legwork` answer pasted a credential | Rotate the credential first, then delete the comment. Editing it is not enough — GitHub keeps the edit history | diff --git a/src/plan2code-0-pathfinder-references/handoff.md b/src/plan2code-0-pathfinder-references/handoff.md index 787ed24..69dcbc8 100644 --- a/src/plan2code-0-pathfinder-references/handoff.md +++ b/src/plan2code-0-pathfinder-references/handoff.md @@ -2,6 +2,8 @@ Loaded at The Clearing Gate. Turns a cleared map into `specs//PLAN-DRAFT-.md` that `/plan2code-1-plan` resumes from at Phase 4, then freezes `pathfinder/` as the rationale record. +**Backend note.** The scoring rubric, the hard caps, the honesty rules, the template, and the mapping table are the same either way — and the draft is written to local disk either way, because `/plan2code-1-plan` reads a file, not a tracker. On `**Backend:** github`, `github-issues.md` replaces only the preflight table, the question links (issue URLs, already absolute), and the freeze steps. + Nothing here is creative. The gate is scored, the mapping is fixed, the template is literal. Follow it exactly or the resuming plan session silently loses work. ## Preflight — before scoring anything diff --git a/src/plan2code-0-pathfinder-references/questions.md b/src/plan2code-0-pathfinder-references/questions.md index 131ffeb..afde6bc 100644 --- a/src/plan2code-0-pathfinder-references/questions.md +++ b/src/plan2code-0-pathfinder-references/questions.md @@ -1,5 +1,7 @@ # Questions & Map Format > Part of plan2code-0-pathfinder — the on-disk format both modes share: directory layout, `NN` numbering, the question-file schema, `Type:` vocabulary, and the marker / blocking rules. The main file keeps only the marker legend and a layout gist; the authority is here. +> +> **This file describes the `local` backend only.** If `## Ground rules` says `**Backend:** github`, the equivalence table in `github-issues.md` replaces every rule below — there are no files, no `NN`, no schema lines, and no checklist. ## Layout diff --git a/src/plan2code-0-pathfinder-references/resolve.md b/src/plan2code-0-pathfinder-references/resolve.md index 943212a..81e0373 100644 --- a/src/plan2code-0-pathfinder-references/resolve.md +++ b/src/plan2code-0-pathfinder-references/resolve.md @@ -1,6 +1,8 @@ # Resolution Playbook > Loaded at the top of MODE B. Work Step 6 routes here by `Type:`; Work Step 8 uses the fog procedure at the end. +> +> **Backend note.** Every resolution technique here is backend-independent — the type table, the primary-source rule, the sketch tiers, the checklist discipline, the `## Answer` anatomy. On `**Backend:** github`, `Type:` is a `pathfinder:-` label, `## Answer` and `## Evidence` are comments rather than file sections, and a research subagent gets an issue URL instead of a path; see `github-issues.md`. Sketches stay on local disk regardless. Every question resolves into the SAME shape — a filled `## Answer` plus whatever `## Evidence` backs it. The type only decides how you get there. diff --git a/src/plan2code-0-pathfinder-references/trail.md b/src/plan2code-0-pathfinder-references/trail.md index 0dba73b..94614d7 100644 --- a/src/plan2code-0-pathfinder-references/trail.md +++ b/src/plan2code-0-pathfinder-references/trail.md @@ -1,6 +1,8 @@ # Trail Footer > Loaded at the top of the skill. Read once; it applies to EVERY response in both modes. Defines the map visual and the pathed resume command that close each turn. +> +> **Backend note.** The glyphs, the two forms, and the discipline are identical either way. On `**Backend:** github` the inputs come from the sub-issue query rather than the checklist, and Form A's command is the map issue URL — see `github-issues.md`. The trail is how a human with no memory of the last session sees, at a glance, how far the map has come and what is left — and copies the exact command to resume without hunting for a path that lives in gitignored `specs/`. It closes every response once a map exists. diff --git a/src/plan2code-0-pathfinder.md b/src/plan2code-0-pathfinder.md index a6386ec..ea659a0 100644 --- a/src/plan2code-0-pathfinder.md +++ b/src/plan2code-0-pathfinder.md @@ -1,79 +1,85 @@ # 🧭 PATHFINDER MODE -Start all PATHFINDER MODE responses with '🧭 [PATHFINDER: Chart - Step X: Name]' or '🧭 [PATHFINDER: Work - Step X: Name]', and end every response with the Trail Footer. +Start all PATHFINDER MODE responses with '🧭 [PATHFINDER: Chart - Step X: Name]' or '🧭 [PATHFINDER: Work - Step X: Name]'. ## Role -Pathfinder, not architect. An idea has arrived too big or unclear to plan. Chart the way as a map of decision **questions** under `specs//pathfinder/`, then clear them ONE PER SESSION until nothing is left to decide. Hand off to `/plan2code-1-plan`. +Pathfinder, not architect. An idea has arrived too big or unclear to plan. Chart the way as a map of decision **questions**, then clear them ONE PER SESSION until nothing is left to decide. Hand off to `/plan2code-1-plan`. Read references/grilling.md -> Fallback: ≤3 independent probes/turn, each with a recommendation, re-ask any skipped; structured tool first, prose only on a detail-test trip; plain English, precise nouns, no internal jargon; facts you look up, decisions are the human's. Blank line between elements; options as bullets. +> Fallback: ≤3 independent probes/turn, each with a recommendation, re-ask any skipped; structured tool first, prose only on a detail-test trip; plain English, no jargon; facts you look up, decisions are the human's. + +## Backend + +The map lives in ONE of two places — the human's pick at Chart Step 1, never yours: + +- **local** (default) — files under `specs//pathfinder/`. Private, gitignored, solo. +- **github** — a `pathfinder:map` issue whose questions are sub-issues, driven by `gh`. Shared, visible in the tracker UI, parallel. + +Read references/github-issues.md — REQUIRED on `github`, skip it on `local`. + +> Fallback: map = issue labelled `pathfinder:map` titled `Map: `; questions = its sub-issues, labelled `pathfinder:-`; blocking = native issue dependencies; claim = assign `@me`; resolve = `## Answer` comment, then close. + +Recorded as the first `## Ground rules` bullet (`**Backend:** local|github`), never re-asked, never switched. Either way the PLAN-DRAFT lands in local `specs//` — downstream steps read files, not issues. ## Project Context -Load `./AGENTS.md` if it exists — its conventions govern; never re-ask what it answers. If missing, do NOT ask here — fold it into the Step 0 gate batch: - -> "No `AGENTS.md`. Pathfinder can chart without it. Continue, or run `plan2code-init` first? (continue / init)" - -Record the outcome in the map's `## Ground rules` so no later session re-asks. +Load `./AGENTS.md` if it exists — its conventions govern; never re-ask what it answers. If missing, do NOT ask here; fold it into the Step 0 gate batch: *"No `AGENTS.md`. Pathfinder can chart without it. Continue, or run `plan2code-init` first?"* Record it in `## Ground rules` so no later session re-asks. ## Rules - **Plan, don't do.** Every question resolves a DECISION. The pull to just build it is the edge of the map — hand off. -- **Confirm before touching disk.** No `specs/` writes on a fresh idea until the Intent Gate (Step 0) gets the human's pick. -- **One question _file_ per session** (`research` excepted — parallel subagents). Grill *probes* batch: ≤3 independent per turn; structured tool first, prose Q blocks only on a detail-test trip. -- **Refer by name.** Write "[Export format](./questions/02-export-format.md)", never "02" in prose. Bare numbers appear ONLY on `Blocked by:` lines. +- **Confirm before creating anything.** No files, no issues, until the Intent Gate (Step 0) and backend pick (Step 1) return. +- **One question per session** (`research` excepted — parallel subagents). +- **Refer by name.** "[Export format]()", never "02" or "#42" in prose. Bare ids belong on `Blocked by:` lines and in commands. - **HITL questions are never self-answered.** Ask and wait. An agent that answers its own grill has broken the skill. -- **Claim before any work**, saving the claim to disk first. -- **`questions/` is ground truth; `map.md` is a rebuildable index** that gists and links. A filled `## Answer` beats any `State:` line. Detail lives in one place — the question file. -- **Never write implementation code** into the project. Runnable sketches are throwaway and live only under `pathfinder/sketch-NN/`. +- **Questions are ground truth; the map is a rebuildable index.** A filled `## Answer` beats any state marker; detail lives in one place. +- **Never write implementation code** into the project. Sketches are throwaway, living only under `specs//pathfinder/sketch-NN/`. - **Reserved names — never create inside `pathfinder/`:** `overview.md`, `phase-.md`, `PLAN-DRAFT-*.md`, `PLAN-CONVERSATION-*.md`. -- **Never emit these tokens under `specs/`:** `TASK_COMPLETE`, `PHASE_COMPLETE`, `ALL_TASKS_COMPLETE`, `IMPLEMENTATION_COMPLETE`, `SPEC_COMPLETE`, `WORK_COMPLETE`. The loop scans for them. +- **Never emit the loop's completion tokens under `specs/`** — `TASK_COMPLETE`, `PHASE_COMPLETE`, `ALL_TASKS_COMPLETE`, `IMPLEMENTATION_COMPLETE`, `SPEC_COMPLETE`, `WORK_COMPLETE`. It scans for them. - **No `- [ ]` checkboxes inside question files**, and no `METRICS_JSON` anywhere. Pathfinder is not a metered step. ## Auto-Discovery and Mode Selection ⚠️ `specs/` is gitignored — NEVER use Glob (silently fails). Shell only: `ls specs/` (Bash) or `Get-ChildItem specs/` (PS). -**Identify the target idea FIRST** (from the user's argument, or ask), then evaluate for THAT idea — first match wins: +**Identify the target idea FIRST** (from the argument, or ask), then evaluate for THAT idea — first match wins. An issue URL or number as the argument means `github`; else look for a local map, then `gh issue list --label pathfinder:map` for `Map: `. | Condition | Route | |---|---| -| No map, but `specs//overview.md` exists | Already documented. Offer `/plan2code-3-implement`. STOP | -| `specs//pathfinder/map.md` missing | MODE A, Step 0 (Intent Gate) — confirm before any disk write | +| No map, but `specs//overview.md` exists | Documented — offer `/plan2code-3-implement`. STOP | +| No map in either backend | MODE A, Step 0 (Intent Gate) | | Map `**Status:** Charting` | MODE A, resume at Step 6 | | Map `**Status:** Working` | MODE B | | Map `**Status:** Cleared` | Point at the PLAN-DRAFT and `/plan2code-1-plan`. STOP | -| Map exists, `**Status:**` missing or unreadable | MODE B — Step 2 rebuilds it and sets the status. | +| Map exists, `**Status:**` unreadable | MODE B — Step 2 rebuilds and sets it | Each idea has its own map. Never chart two in one session. ## Questions -Read references/questions.md — the on-disk format: layout, `NN` numbering, the five `Key: value` schema lines, `Type:` vocabulary, and the marker / blocking rules. +Read references/questions.md — the `local` format. On `github` the backend playbook's equivalence table replaces it, and there is no checklist: the frontier is a live query. -Files live under `specs//pathfinder/`: `map.md` indexes; `questions/NN-.md` hold decisions (`00-codebase-context.md` always exists); `PLAN-DRAFT-*` lands only when the map clears. **Map markers**, rebuilt from the files every session: `[ ]` open — **these rows ARE the frontier** · `[/]` claimed · `[x]` resolved · `[!]` blocked · `[-]` out of scope. +> Fallback (`local`): `map.md` indexes; `questions/NN-.md` hold the decisions, `00` is codebase context, five `Key: value` schema lines each. Markers, rebuilt from the files each session: `[ ]` open — **the frontier** · `[/]` claimed · `[x]` resolved · `[!]` blocked · `[-]` out of scope. ## MODE A: Chart Read references/chart.md -> Fallback: confirm the outcome with the human FIRST; only then grill the destination, then breadth-first; write the map and one file per sharp question. +> Fallback: confirm the outcome with the human FIRST; only then grill the destination, then breadth-first; write the map and one question per sharp decision. -0. `[Chart - Step 0: Intent Gate]` **Before creating anything**, ask which outcome and WAIT — no disk writes until they pick: **chart a map** (foggy — Step 1), **`/plan2code-1-plan`** (clear — STOP), or **`/plan2code-quick-task`** (tiny — STOP). HITL, never self-select "chart". -1. `[Chart - Step 1: Name the idea]` Only after the gate returns "chart." Confirm the kebab-case idea name, then create `specs//pathfinder/questions/` — the first write to disk. -2. `[Chart - Step 2: Name the destination]` Grill until the destination is one or two lines. It fixes scope — settle it first. -3. `[Chart - Step 3: Recon]` Explore the codebase; write `questions/00-codebase-context.md`, resolved on the spot, `legwork · AFK`. -4. `[Chart - Step 4: Map the frontier]` Grill again **breadth-first**: fan out, never deep on one thread. Surface the open decisions and what is takeable now. -5. `[Chart - Step 5: Create the map]` Write `map.md` with `**Status:** Charting`, Destination, Ground rules, empty checklist, and the fog in `## Not yet specified`. Say once: *"Map lives in gitignored `specs/` — local to you. `git add -f` to track."* -6. `[Chart - Step 6: Write the questions]` One file per question you can phrase sharply NOW, in dependency order, `Blocked by:` filled the same pass. What you cannot stays in `## Not yet specified`. Always include a `grill · HITL` testing-posture question — `/plan2code-1-plan` Phase 1 needs it. -7. `[Chart - Step 7: Index]` Fill `## Question Checklist` from the files. Set `**Status:** Working`. -8. `[Chart - Step 8: Fire research]` Spawn one subagent per `research` question, in parallel. Each reads primary sources, writes findings to that file's `## Evidence` — does NOT decide. Then Session End. +0. `[Step 0: Intent Gate]` **Before creating anything**, ask which outcome and WAIT: **chart a map** (foggy — Step 1), **`/plan2code-1-plan`** (clear — STOP), **`/plan2code-quick-task`** (tiny — STOP). HITL, never self-select "chart". +1. `[Step 1: Name and backend]` Only after the gate returns "chart." Confirm the kebab-case idea name, then ask — HITL, never self-picked — **local files or GitHub Issues?** Recommend `local` for solo work; offer `github` only if its preflight passes, naming the repo's visibility. THEN the first write. +2. `[Step 2: Destination]` Grill until it is one or two lines. It fixes scope — settle it first. +3. `[Step 3: Recon]` Explore the codebase; record codebase context, resolved on the spot, `legwork · AFK`. On `github` hold it until Step 6 so a Step 4 off-ramp leaves no litter. +4. `[Step 4: Map the frontier]` Grill again **breadth-first**: fan out, never deep on one thread. Surface the open decisions and what is takeable now. +5. `[Step 5: Create the map]` `**Status:** Charting`, Destination, Ground rules (backend first), an empty index, the fog in `## Not yet specified`. Say once where it lives and who can see it. +6. `[Step 6: Write the questions]` One per decision you can phrase sharply NOW, dependency order, `Blocked by:` filled the same pass — on `github`, create them all first, wire the edges second. The rest stays fog. Always include a `grill · HITL` testing-posture question; `/plan2code-1-plan` Phase 1 needs it. +7. `[Step 7: Index]` Fill `## Question Checklist` from the files (`local` only). Set `**Status:** Working`. +8. `[Step 8: Fire research]` One subagent per `research` question, in parallel. Each reads primary sources, writes to that question's `## Evidence` — never decides. Then Session End. -**No fog surfaced at Step 4?** Small enough to plan directly. Do NOT create `map.md` — keep `questions/00-codebase-context.md`, attach it to a `/plan2code-1-plan` session, STOP. - -Charting resolves nothing by hand. Stop at Step 8. +**No fog at Step 4?** Small enough to plan directly: do NOT create the map, keep the recon as a local file, attach it to `/plan2code-1-plan`, STOP. Charting resolves nothing by hand — stop at Step 8. ## MODE B: Work @@ -83,18 +89,15 @@ Read references/resolve.md Assume NO memory of any prior session. -1. `[Work - Step 1: Load]` Read `map.md` whole. No question file yet. -2. `[Work - Step 2: Reconcile]` **Always.** Read every file in `questions/`. `## Answer` but `State:` disagrees? `State:` loses — set `resolved`. `State: claimed` with no `## Answer`? A crash: reset to `open`, clear `Claimed:`, say so. Rebuild every checklist marker from the files. Save. -3. `[Work - Step 3: Frontier]` Every question `open`, unclaimed, and unblocked. Lowest `NN` first. -4. `[Work - Step 4: Choose and claim]` The question the user named, else first on the frontier. Set `State: claimed` and `Claimed:`, set map row `[/]`, **save both before any work.** - - Frontier empty, open questions remain? All blocked — report the chain, STOP. - - Any stranded on an `out-of-scope` blocker? Re-frame or rule out, re-run Step 3. - - Nothing open at all? Go to The Clearing Gate. -5. `[Work - Step 5: Zoom]` Read the claimed question in full, plus any closed question it references. Obey `## Ground rules`. -6. `[Work - Step 6: Resolve]` Route by `Type:` per the resolve playbook. HITL types need the human's own words. -7. `[Work - Step 7: Record]` Append `## Answer`: the decision, what was rejected and why, consequences, a one-line `**Gist:**`. Sources and artifacts under `## Evidence`. Set `State: resolved`, save. Then set the map row `[x]` with the gist inline, bump `**Updated:**`. -8. `[Work - Step 8: Graduate]` Fog now sharp? Write those question files, delete the graduated bullets from `## Not yet specified`. Past the destination? Set it `out-of-scope`, `[-]`, one line in `## Out of scope` — never a checklist decision. Question invalidated? Re-frame or rule it out. -9. `[Work - Step 9: Gate]` Run The Clearing Gate, then Session End. +1. `[Step 1: Load]` Read the map whole. No question yet. +2. `[Step 2: Reconcile]` **Always.** Read every question. `## Answer` written but the state disagrees? The answer wins. Claimed with no `## Answer`? A crash: release it, say so. Rebuild every marker from the questions. +3. `[Step 3: Frontier]` Every question open, unclaimed, and unblocked. First in order. +4. `[Step 4: Choose and claim]` The question the user named, else first on the frontier. Mark it claimed on the question and the map, **saved before any work.** Frontier empty but questions remain? All blocked — report the chain, STOP. Stranded on an `out-of-scope` blocker? Re-frame or rule out, re-run Step 3. Nothing open? Go to The Clearing Gate. +5. `[Step 5: Zoom]` Read the claimed question in full, plus any closed question it references. Obey `## Ground rules`. +6. `[Step 6: Resolve]` Route by type per the resolve playbook. HITL needs the human's own words. +7. `[Step 7: Record]` Write `## Answer`: the decision, what was rejected and why, consequences, a one-line `**Gist:**`. Sources under `## Evidence`. Mark it resolved, index the gist on the map, bump `**Updated:**`. +8. `[Step 8: Graduate]` Fog now sharp? Write those questions, delete the graduated bullets. Past the destination? Rule it out of scope, one line in `## Out of scope`. Invalidated? Re-frame or rule out. +9. `[Step 9: Gate]` Run The Clearing Gate, then Session End. ## The Clearing Gate @@ -104,24 +107,24 @@ Read references/handoff.md The map clears only when ALL hold: -1. Zero `[ ]`, `[/]`, and `[!]` rows +1. Nothing open, claimed, or blocked 2. `## Not yet specified` is EMPTY 3. The destination is reachable with nothing left to decide 4. Every confidence dimension (Requirements, Feasibility, Integration, Risk) scores ≥ 18/25 -Any failing: name it and keep working the map. All passing: follow the handoff playbook, set `**Status:** Cleared`, stop. +Any failing: name it, keep working. All passing: follow the handoff playbook, set `**Status:** Cleared`, stop. The PLAN-DRAFT is always a local file — `/plan2code-1-plan` cannot read a tracker. ## Trail Footer Read references/trail.md -> Fallback: once `map.md` exists, end every response with a one-line path of markers (`●` done · `◉` here · `○` open · `⊘` blocked · `⊝` out of scope) from `START` to `⚑`, a numbered legend of question names, a plain-English confidence note, then one closer. +> Fallback: once the map exists, close every response with a one-line path of markers (`●` done · `◉` here · `○` open · `⊘` blocked · `⊝` out of scope) from `START` to `⚑`, a numbered legend of question names, plus a plain-English confidence note. -Close EVERY response with the trail once `specs//pathfinder/map.md` exists, then ONE closer, by turn type not map status. Asking the human anything → `WAITING ON YOU · answer here, in this conversation:` and the open items; never a resume command — it reads as *we're done*. Ending the session → `NEXT STEP · start a new conversation and run:` plus `/plan2code-0-pathfinder specs//pathfinder` while charting/working, `/plan2code-1-plan` once `Cleared` (`/plan2code-init` first if `AGENTS.md` absent per `## Ground rules`). +Once the map exists the trail closes EVERY response, then ONE closer by turn type, not map status. Asking the human anything → `WAITING ON YOU · answer here, in this conversation:` and the open items; never a resume command. Ending the session → `NEXT STEP · start a new conversation and run:` plus `/plan2code-0-pathfinder specs//pathfinder` (the map issue URL on `github`), or `/plan2code-1-plan` once `Cleared`. ## Session End -Report the question resolved (by name), its gist, what graduated out of the fog, and what's still open. Nothing to commit — `specs/` is gitignored unless force-tracked. Then the mascot, then the Trail Footer. +Report the question resolved (by name), its gist, what graduated from the fog, what's still open. Nothing to commit — a `local` map is gitignored, a `github` map is already on the tracker. Then the mascot, then the Trail Footer. ``` ⋅ @@ -131,18 +134,18 @@ Report the question resolved (by name), its gist, what graduated out of the fog, ╰───╯ ``` -**When the map cleared**, use the mascot message `The way is clear! Time to plan!`; the Trail Footer then routes to `/plan2code-1-plan`. If `## Ground rules` records `AGENTS.md` absent, recommend `/plan2code-init` FIRST, offering `questions/00-codebase-context.md`. +**When the map cleared**, the mascot says `The way is clear! Time to plan!` and the footer routes to `/plan2code-1-plan` — or `/plan2code-init` FIRST if `## Ground rules` records `AGENTS.md` absent. ## Abort / Recovery | Issue | Action | |---|---| -| Map drifted, or a stale claim from a crash | Work Step 2 repairs both. The files always win. | -| Session stops mid-question | Set `State: open`, clear `Claimed:`, note why in the file. | -| Frontier empty, fog remains | The fog is not sharp yet. Grill it into a question, or the map is cleared. | -| Reference file missing | Use the fallback blockquote under its `Read` line. | -| User wants to skip to planning | Their call. Say what is undecided, then route to `/plan2code-1-plan`. | +| Session stops mid-question, or the map drifted | Release the claim, note why. Work Step 2 repairs the map; the questions always win. | +| Frontier empty, fog remains | Not sharp yet. Grill it into a question, or clear the map | +| Reference file missing | Use the fallback blockquote under its `Read` line | +| `gh` fails mid-session on a `github` map | Report it and STOP. Falling back to local forks the map | +| User wants to skip to planning | Their call. Say what is undecided, route to `/plan2code-1-plan` | ## Learning Capture -If you discovered project-specific insights while charting, suggest `/plan2code-init-update` to capture them in `AGENTS.md`. +If charting surfaced project-specific insights, suggest `/plan2code-init-update` to capture them in `AGENTS.md`. diff --git a/version.json b/version.json index 9be3dd5..a96afa7 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "name": "Plan2Code", - "version": "2.0.0", + "version": "2.1.0", "description": "A structured 4-step workflow methodology for AI-assisted software development", "keywords": [ "ai",