From 869f02e97345fa3769424f94bb8b316bfa9643d4 Mon Sep 17 00:00:00 2001 From: Lex Christopherson Date: Thu, 15 Jan 2026 09:34:43 -0600 Subject: [PATCH] docs: add goal-backward planning reference Explains working backwards from desired outcome to concrete tasks. Co-Authored-By: Claude --- get-shit-done/references/goal-backward.md | 286 ++++++++++++++++++++++ 1 file changed, 286 insertions(+) create mode 100644 get-shit-done/references/goal-backward.md diff --git a/get-shit-done/references/goal-backward.md b/get-shit-done/references/goal-backward.md new file mode 100644 index 000000000..03cd6ec9e --- /dev/null +++ b/get-shit-done/references/goal-backward.md @@ -0,0 +1,286 @@ +# Goal-Backward Planning + +How to derive requirements by working backwards from the goal, not forwards from tasks. + + +**Forward planning asks:** "What should we build?" +**Goal-backward planning asks:** "What must be TRUE for the goal to be achieved?" + +Forward planning produces tasks. Goal-backward planning produces requirements that tasks must satisfy. + + + +Forward planning fails silently. A task like "create chat component" can be marked complete when the component is a placeholder. The task was done—a component was created—but the goal "working chat interface" was not achieved. + +Goal-backward planning starts from "user can chat" and works backwards: +- What must be TRUE for a user to chat? +- What must EXIST for those truths to hold? +- What must be WIRED for those artifacts to function? + +This produces must-haves that are verifiable. Either a user CAN chat, or they can't. No ambiguity. + + + + +## Step 1: State the Goal + +Take the phase goal from ROADMAP.md. This is the outcome, not the work. + +**Examples:** +- "Working chat interface" (not "build chat components") +- "Users can authenticate" (not "implement auth system") +- "Products display with prices" (not "create product pages") + +If the roadmap goal is task-shaped ("implement X"), reframe it as outcome-shaped ("X works"). + +## Step 2: Derive Observable Truths + +Ask: **"What must be TRUE for this goal to be achieved?"** + +List 3-7 truths from the USER's perspective. These are observable behaviors, not implementation details. + +**For "working chat interface":** +- User can see existing messages +- User can type a new message +- User can send the message +- Sent message appears in the list +- Messages persist across page refresh + +**For "users can authenticate":** +- User can reach login page +- User can enter credentials +- Valid credentials grant access +- Invalid credentials show error +- Session persists across refresh +- User can log out + +**Test:** Each truth should be verifiable by a human using the application. If you can't test it by clicking around, it's not observable. + +## Step 3: Derive Required Artifacts + +For each truth, ask: **"What must EXIST for this to be true?"** + +Map truths to concrete artifacts (files, routes, schemas, components). + +**"User can see existing messages" requires:** +- Message list component (renders Message[]) +- Messages state (loaded from somewhere) +- API route or data source (provides messages) +- Message type definition (shapes the data) + +**"Valid credentials grant access" requires:** +- Login form component (captures credentials) +- Auth API route (validates credentials) +- Session/token mechanism (persists auth state) +- User record in database (to validate against) + +**Test:** Each artifact should be a specific file or database object. If you can't point to where it lives, it's too abstract. + +## Step 4: Derive Required Wiring + +For each artifact, ask: **"What must be CONNECTED for this artifact to function?"** + +Wiring is where most failures hide. The pieces exist but don't talk to each other. + +**Message list component wiring:** +- Imports Message type (not using `any`) +- Receives messages prop or fetches from API +- Maps over messages to render (not hardcoded) +- Handles empty state (not just crashes) + +**Auth API route wiring:** +- Imports database client +- Queries users table (not placeholder) +- Compares password hash (not plaintext) +- Returns session token (not empty response) + +**Test:** Wiring is verified by tracing data flow. Does A actually call B? Does B actually return to A? Does A actually use what B returned? + +## Step 5: Identify Key Links + +Ask: **"Where is this most likely to break?"** + +Key links are the critical connections that, if missing, cause cascading failures. + +**For chat interface:** +- Input onSubmit → API call (if broken: typing works but sending doesn't) +- API save → database (if broken: appears to send but doesn't persist) +- Component → real data (if broken: shows placeholder, not messages) + +**For authentication:** +- Form submit → API (if broken: form works but auth doesn't) +- API → database query (if broken: accepts any password) +- Session → protected routes (if broken: logged in but can't access anything) + +Key links get extra verification attention. These are where stubs and placeholders hide. + + + + +The derive_must_haves step produces a structured list for PLAN.md frontmatter: + +```yaml +must_haves: + truths: + - "User can see existing messages" + - "User can send a message" + - "Messages persist across refresh" + artifacts: + - path: "src/components/Chat.tsx" + provides: "Message list rendering" + - path: "src/app/api/chat/route.ts" + provides: "Message CRUD operations" + - path: "prisma/schema.prisma" + provides: "Message model" + key_links: + - from: "Chat.tsx" + to: "api/chat" + via: "fetch in useEffect" + - from: "api/chat POST" + to: "database" + via: "prisma.message.create" +``` + +This structure is machine-readable for verification after execution. + + + + +## Example 1: E-commerce Product Page + +**Goal:** "Products display with prices and add-to-cart" + +**Truths:** +- User can see product image +- User can see product name and description +- User can see product price +- User can click "Add to Cart" +- Cart updates when product added + +**Artifacts:** +- `src/components/ProductCard.tsx` - displays product info +- `src/components/AddToCart.tsx` - button with cart logic +- `src/app/products/[id]/page.tsx` - product detail page +- `src/hooks/useCart.ts` - cart state management +- `prisma/schema.prisma` - Product model with price field + +**Key Links:** +- ProductCard receives product data (not hardcoded) +- AddToCart calls cart hook (not just console.log) +- useCart persists to localStorage or API (not just memory) +- Price displays from product.price (not placeholder "$XX.XX") + +--- + +## Example 2: User Settings Page + +**Goal:** "Users can update their profile settings" + +**Truths:** +- User can see current settings values +- User can edit each setting field +- User can save changes +- Saved changes persist +- User sees confirmation of save + +**Artifacts:** +- `src/app/settings/page.tsx` - settings page +- `src/components/SettingsForm.tsx` - form with fields +- `src/app/api/settings/route.ts` - GET and PUT endpoints +- `prisma/schema.prisma` - User model with settings fields + +**Key Links:** +- Form loads current values on mount (not empty defaults) +- Submit calls API with form data (not console.log) +- API updates database (not just returns success) +- Success triggers UI feedback (not silent) + +--- + +## Example 3: Real-time Notifications + +**Goal:** "Users receive notifications in real-time" + +**Truths:** +- User sees notification badge/indicator +- New notifications appear without refresh +- User can view notification list +- User can mark notifications as read +- Read state persists + +**Artifacts:** +- `src/components/NotificationBell.tsx` - badge/indicator +- `src/components/NotificationList.tsx` - dropdown/panel +- `src/app/api/notifications/route.ts` - CRUD endpoints +- `src/hooks/useNotifications.ts` - real-time subscription +- `prisma/schema.prisma` - Notification model + +**Key Links:** +- useNotifications connects to WebSocket/SSE (not polling placeholder) +- NotificationBell shows actual unread count (not hardcoded) +- Mark-as-read calls API (not just local state) +- API broadcasts to other clients (if multi-device) + + + + + +## Failure: Truths Too Vague + +**Bad:** "User can use chat" +**Good:** "User can see messages", "User can send message", "Messages persist" + +Vague truths can't be verified. Break them into specific, observable behaviors. + +## Failure: Artifacts Too Abstract + +**Bad:** "Chat system", "Auth module" +**Good:** "src/components/Chat.tsx", "src/app/api/auth/login/route.ts" + +Abstract artifacts can't be checked. Point to specific files. + +## Failure: Missing Wiring + +**Bad:** Listing components without how they connect +**Good:** "Chat.tsx fetches from /api/chat via useEffect on mount" + +Artifacts existing isn't enough. The connections between them are where stubs hide. + +## Failure: Skipping Key Links + +**Bad:** Assuming "if files exist, it works" +**Good:** Identifying the 2-3 critical connections that make-or-break the goal + +Key links are verification priorities. Without them, you check everything equally (inefficient) or check nothing deeply (ineffective). + + + + + +## In plan-phase.md + +The `derive_must_haves` step runs after gathering context, before breaking into tasks. + +Output: `must_haves` structure written to PLAN.md frontmatter. + +Tasks are then designed to CREATE the artifacts and ESTABLISH the wiring. + +## In execute-phase.md + +The `verify_phase_goal` step runs after all plans execute, before updating roadmap. + +Input: `must_haves` from PLAN.md frontmatter (or derived from goal if missing). + +Process: Check each truth against codebase, verify artifacts exist and aren't stubs, trace key links. + +Output: VERIFICATION.md with pass/fail per item, fix recommendations if gaps found. + +## The Loop + +``` +derive_must_haves → tasks → execute → verify → [gaps?] → fix plans → execute → verify → pass +``` + +Must-haves are derived once, verified as many times as needed until all pass. + +