a template starter repo for sveltekit projects
0

Configure Feed

Select the types of activity you want to include in your feed.

chore(process): drop the OpenCode layer, reorganize under .pi

Remove .opencode/ (commands, plugins, tdd skill) and opencode.json — the
project is no longer OpenCode-primary; the process layer lives in .pi/.

Moves, content unchanged in this commit:
- archaeology, narratives, pulse: skills → .pi/prompts/ (user-invoked
views, not model-triggered skills)
- project-plan's to-prd / to-issues / triage subskills + triage docs →
.pi/skills/project-plan/reference/ (preserved fuller ceremony)
- request-refactor-plan: skill → prompt (re-added in the next commit)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

-2102
-77
.opencode/commands/build-test.md
··· 1 - --- 2 - description: Run typecheck + tests for the suede stack 3 - arguments: 4 - - name: PATTERN 5 - description: Optional test name pattern to filter tests 6 - required: false 7 - --- 8 - 9 - # Typecheck and test 10 - 11 - Run the project's quality gate. This is the build+test command pair for the 12 - Suede stack (SvelteKit + Cloudflare + D1 + Drizzle + Vitest + Playwright + 13 - Storybook). The exact command set is a fork-time decision captured in 14 - AGENTS.md; this skill ships with the suede defaults and the follow-up 15 - branch from `suede-kickoff` rewrites it for the new project. 16 - 17 - ## Instructions 18 - 19 - 1. Regenerate wrangler types so svelte-check sees the latest env bindings: 20 - 21 - ```bash 22 - pnpm gen 23 - ``` 24 - 25 - 2. Run the full quality gate: 26 - 27 - ```bash 28 - pnpm check && pnpm test 29 - ``` 30 - 31 - 3. If typecheck fails, surface the error block verbatim — svelte-check 32 - reports the file and line. If tests fail, list which test files and 33 - which tests, then suggest a fix direction (don't auto-fix during a 34 - build gate; that's a separate diagnose/tdd cycle). 35 - 36 - 4. If the user specifies a test pattern, scope `pnpm test` to it: 37 - 38 - ```bash 39 - pnpm test -- -t <pattern> 40 - ``` 41 - 42 - 5. For Storybook visual smoke (only relevant for full-stack forks that 43 - kept Storybook): 44 - 45 - ```bash 46 - pnpm storybook --port 6006 47 - ``` 48 - 49 - Then drive a Playwright script against `localhost:6006` to verify the 50 - story canvas. 51 - 52 - ## Why this isn't `cargo build && cargo test` 53 - 54 - The stock deciduous template's build-test command assumes Rust. Suede's 55 - stack is pnpm + Vitest + svelte-check. The decision-graph log 56 - (commit 8e4e6b6, decision node for "swap stock deciduous build-test 57 - for the suede stack") flagged this as a misaligned stock command; this 58 - rewrite lands the fix and pins it to the Suede defaults. Forks that 59 - rip SvelteKit should rewrite this skill during their kickoff 60 - follow-up branch. 61 - 62 - ## Test categories in this project 63 - 64 - - `src/**/*.spec.ts` — Vitest unit tests (component + pure-logic) 65 - - `src/**/*.test.ts` — Vitest integration tests (server routes, drizzle queries) 66 - - `src/stories/**/*.stories.svelte` — Storybook visual + interaction tests (Playwright-driven) 67 - - `e2e/**` — Playwright end-to-end tests (full user flows against a running dev server) 68 - 69 - ## Quick reference 70 - 71 - ```bash 72 - pnpm gen # regenerate wrangler types 73 - pnpm check # wrangler types + svelte-check 74 - pnpm test # vitest run 75 - pnpm lint # prettier --check + eslint 76 - pnpm storybook # visual dev server 77 - ```
-401
.opencode/commands/decision-graph.md
··· 1 - --- 2 - description: Build a deciduous decision graph capturing design evolution from commit history 3 - arguments: 4 - - name: REPO 5 - description: Path to the repository to analyze (default current directory) 6 - required: false 7 - --- 8 - 9 - # Decision Graph Construction 10 - 11 - You are building a **deciduous decision graph** - a DAG that captures the evolution of design decisions in a codebase. 12 - 13 - **Target repository:** $REPO (if provided), otherwise the current directory. 14 - 15 - Use the `deciduous` CLI (at ~/.cargo/bin/deciduous) to build the graph. Run deciduous commands in the current directory (not inside the source repo). 16 - 17 - For git commands to explore commit history, use `git -C <repo-path>` to target the source repo. 18 - 19 - **CRITICAL: Only use information from the repository itself (commits, code, comments, tests). Do not use your prior knowledge about the project. Everything must be grounded in what you find in the repo.** 20 - 21 - ## Commit Exploration 22 - 23 - Use a layered strategy to find all relevant commits: 24 - 25 - **Layer 1: See all commits.** Start with the full list when building narratives. 26 - 27 - ```bash 28 - git log --oneline --after="..." --before="..." -- path/ 29 - ``` 30 - 31 - **Layer 2: Keyword expansion.** Once you have narratives, search for spelling variations and related terms you might have missed (e.g., "cache" -> "caching", "cached", "LRU", "invalidate"). For each key identifier in your narratives, trace its full lifecycle: 32 - 33 - - Introduction 34 - - Changes and modifications 35 - - Renames 36 - - Deprecation or removal 37 - - Replacement by other mechanisms 38 - - Becoming stable/public API 39 - 40 - If there's a feature flag controlling the feature, search for commits mentioning that flag. 41 - 42 - **Layer 3: Follow authors.** If a narrative has a key author, check their commits +/-1 month from known commits. They often work on related things. 43 - 44 - **Layer 4: Pull request context.** If the `gh` CLI is available, use it to find PRs associated with key commits and paths. PRs often contain design discussion, review comments, and rationale that never appears in commit messages. 45 - 46 - ```bash 47 - # Find PRs that touched a specific path 48 - gh pr list --state merged --search "path/to/module" --limit 50 49 - 50 - # Find the PR that introduced a specific commit 51 - gh pr list --state merged --search "<commit-sha>" --limit 5 52 - 53 - # Read PR description and review comments for context 54 - gh pr view <pr-number> 55 - gh api repos/{owner}/{repo}/pulls/<pr-number>/comments 56 - 57 - # Search PR titles/bodies for keywords from your narratives 58 - gh pr list --state merged --search "<keyword>" --limit 30 59 - ``` 60 - 61 - PR descriptions and review threads are goldmines for understanding **why** decisions were made. Reviewers often challenge approaches, surface alternatives that were considered, and document trade-offs - exactly the kind of reasoning that belongs in the decision graph. 62 - 63 - When you find relevant PR discussion: 64 - 65 - - Use it to enrich observation and decision node descriptions 66 - - Quote reviewer comments as evidence (e.g., "PR #42 review: 'We should use Redis instead because...'") 67 - - Note when a PR was blocked or revised - these are often pivot points 68 - 69 - ### DO NOT: 70 - 71 - - `git log ... | head -100` -- **NO.** You will miss commits in the middle. 72 - - `git log ... | tail -200` -- **NO.** Same problem. 73 - - Start with keyword filtering -- **NO.** You'll miss things with unexpected names. 74 - 75 - ### DO: 76 - 77 - - See all commits first, filter mentally while building narratives 78 - - Include "remove", "delete", "disable", "deprecate" in keyword searches -- removals explain transitions 79 - - Check the commit count first (`| wc -l`), but then see them all 80 - - **Read full commit messages** for any commit whose title mentions an identifier or concept relevant to your narrative -- you need precise understanding of what happened to each one you care about 81 - 82 - ## Finding the Story 83 - 84 - Not every commit matters. Look for commits that change **the model** - how the system conceptualizes the problem: 85 - 86 - - Existing tests modified (contract changing, not just bugs fixed) 87 - - Data structures replaced or reworked 88 - - Heuristics changed significantly 89 - - New abstractions introduced 90 - - API behavior shifts 91 - 92 - Skip commits that are pure implementation (same model, different code) or routine fixes that just add tests. 93 - 94 - Among model-changing commits, find the **spine**: what question keeps getting re-answered? What approach keeps getting replaced or refined? That's your central thread - build the graph around it. 95 - 96 - ## Narrative Tracking 97 - 98 - **Don't build the graph as you explore.** First, collect commits into narratives. 99 - 100 - Maintain `narratives.md` as you explore: 101 - 102 - 1. For each significant commit, read `narratives.md` 103 - 2. Ask: "Does this commit evolve an existing narrative?" 104 - 3. If yes: append the commit to that narrative's section 105 - 4. If no: add a new narrative section 106 - 107 - Example `narratives.md`: 108 - 109 - ``` 110 - ## Cache Strategy 111 - - a1b2c3d: Add in-memory cache 112 - - e4f5g6h: Cache invalidation issues 113 - - i7j8k9l: Switch to Redis 114 - 115 - ## API Rate Limiting 116 - - m1n2o3p: Add basic throttling 117 - - ... 118 - ``` 119 - 120 - **Before building the graph**, take a critical pass over `narratives.md`: 121 - 122 - - Merge narratives that are essentially the same evolving thing 123 - - Ensure each narrative clearly explains how one independent piece evolved 124 - - Note where narratives branch from or feed into each other 125 - 126 - ## Hardening Phase 127 - 128 - After building initial narratives, harden them to ensure nothing is missed. 129 - 130 - ### Step 1: Extract concepts per narrative 131 - 132 - For each narrative, list the key concepts/APIs/identifiers and their lifecycle stage: 133 - 134 - - **Introduced**: First appearance of the concept 135 - - **Changed**: Modifications to behavior or implementation 136 - - **Renamed/Deprecated/Removed**: End of life or replacement 137 - - **Marked stable**: Became public API or removed "unstable\_" prefix 138 - 139 - Example addition to narrative: 140 - 141 - ``` 142 - ## Cache Strategy 143 - Concepts: cache, LRUCache, cacheTimeout, invalidate 144 - 145 - Lifecycle: 146 - - cache: introduced (a1b2c3d), changed (e4f5g6h), renamed to LRUCache (x1y2z3) 147 - - cacheTimeout: introduced (e4f5g6h), removed (i7j8k9l) 148 - - LRUCache: introduced via rename (x1y2z3), marked stable (p1q2r3) 149 - 150 - Commits: 151 - - a1b2c3d: Add in-memory cache 152 - - ... 153 - ``` 154 - 155 - ### Step 2: Exhaustive search per concept 156 - 157 - For each concept, search full commit messages (not just subject lines): 158 - 159 - ```bash 160 - git log --all --after="..." --before="..." --grep="<concept>" --format="%H %s" -- path/ 161 - ``` 162 - 163 - For each match, read the full commit message: 164 - 165 - ```bash 166 - git show <sha> --format="%B" --no-patch 167 - ``` 168 - 169 - ### Step 3: Rewrite narratives with gaps filled 170 - 171 - Rewrite `narratives.md` integrating any newly discovered commits. The rewritten version should: 172 - 173 - - Include ALL commits found for each concept 174 - - Update the lifecycle tracking for each concept 175 - - Ensure the arc is complete (if something was introduced, when was it changed/removed?) 176 - 177 - If a concept has an incomplete arc (e.g., introduced but never removed, yet it's not in current code), investigate further. 178 - 179 - ## Cross-Narrative Connections 180 - 181 - When building the graph, don't just branch everything from the goal. Capture how narratives relate: 182 - 183 - **Branch from the spine, not goal:** If a narrative arose from work in another narrative, branch from that work. 184 - 185 - - Wrong: `goal -> "How to preserve state?"` 186 - - Right: `outcome("timeout works") -> "How to preserve state?"` (the question arose after implementing timeout) 187 - 188 - **Observations feed back:** If an observation in one narrative influenced decisions in another, add an edge. 189 - 190 - - Example: An observation about nested boundary timing might inform heuristics refinement in the main narrative 191 - 192 - **Keep truly independent things from goal:** If a narrative is genuinely a separate concern that doesn't arise from other work, branching from goal is appropriate. 193 - 194 - After consolidating, build the graph - one decision chain per narrative, with cross-links where they connect. 195 - 196 - ## Node Types 197 - 198 - | Type | Purpose | 199 - | --------------- | ----------------------------------------------------- | 200 - | **goal** | High-level objective being pursued | 201 - | **decision** | A choice point with multiple possible paths | 202 - | **option** | A possible approach to a decision | 203 - | **observation** | Learning, insight, or new information discovered | 204 - | **action** | Something that was done (must reference a commit) | 205 - | **outcome** | Result or consequence of an action | 206 - | **revisit** | Pivot point where a previous approach is reconsidered | 207 - 208 - ## CLI Commands 209 - 210 - ```bash 211 - # Add nodes (returns node ID) 212 - deciduous add goal "Title of the goal" 213 - deciduous add decision "The question or choice point" 214 - deciduous add option "One possible approach" 215 - deciduous add observation "Something learned or discovered" 216 - deciduous add action "Descriptive title of what was done" 217 - deciduous add outcome "What resulted from the action" 218 - deciduous add revisit "Reconsidering previous approach" 219 - 220 - # Add nodes with descriptions (use -d for explanations and sources) 221 - deciduous add action "Title" -d "Explanation of what happened and why. 222 - 223 - Sources: 224 - - abc123: 'Relevant quote from commit message'" 225 - 226 - # Set status on options 227 - deciduous status <id> rejected # option that wasn't chosen 228 - deciduous status <id> completed # option that was chosen 229 - 230 - # Connect nodes (from -> to means "from leads_to to") 231 - deciduous link <from-id> <to-id> 232 - deciduous link <from-id> <to-id> -r "Why this led to that" 233 - 234 - # View/restructure 235 - deciduous nodes # list all 236 - deciduous edges # list connections 237 - deciduous unlink <from> <to> # remove edge 238 - deciduous delete <id> # remove node and edges 239 - 240 - # Version management 241 - deciduous check-update # check if update is needed (version checking is always-on) 242 - ``` 243 - 244 - ## Narrative Discipline 245 - 246 - You're not collecting facts - you're crafting a story. Every node needs a _raison d'etre_. 247 - 248 - Before adding a node, stop and ask: **Why does this exist? What prompted it?** 249 - 250 - - Is this commit evolving something that's already in the graph? Then connect it there - it's a continuation, not a new branch. 251 - - Is this a response to an observation about existing work? Then chain from that observation - something was learned, and this is the reaction. 252 - - Did the winds change? Look for the moment the team realized the old approach wasn't working. That's an observation node, and it's the bridge to what came next. 253 - 254 - **Don't branch from the goal unless it's genuinely new.** If you're about to draw an edge from the root goal, ask: does this replace or refine something we already designed? If yes, find that thing and connect there instead. 255 - 256 - The test: can someone read your graph and understand not just _what_ happened, but _why_ each thing happened? Every node should feel inevitable given what came before it. 257 - 258 - Think of commits as chapters in a story. Each chapter exists because of what happened in previous chapters. Your job is to find those causal threads and make them explicit. 259 - 260 - ## Temporal Rule 261 - 262 - **Time flows forward. Past influences future, never reverse.** 263 - 264 - Options under a decision are alternatives considered _at the same time_. If an approach was tried, failed, and a new approach was designed later - that's a **new decision node**, connected by observations about why the old approach failed. 265 - 266 - Example - DON'T model sequential attempts as parallel options: 267 - 268 - ``` 269 - # WRONG - these were decided years apart, not simultaneously 270 - decision: "How to handle caching?" 271 - |-> option: in-memory cache (2019) 272 - |-> option: Redis (2020) 273 - |-> option: CDN (2021) 274 - ``` 275 - 276 - Example - DO model as chain of decisions with learning: 277 - 278 - ``` 279 - # RIGHT - each attempt informs the next, options are simultaneous alternatives 280 - decision: "How to handle caching?" (2019) 281 - |-> option: in-memory cache [chosen] 282 - |-> option: no caching [rejected] "Perf requirements too strict" 283 - | 284 - option: in-memory cache -> action -> outcome 285 - | 286 - observation: "Doesn't scale across instances" 287 - | 288 - decision: "How to share cache across instances?" (2020) 289 - |-> option: Redis [chosen] "Team has Redis experience" 290 - |-> option: Memcached [rejected] "Less feature-rich" 291 - |-> option: database caching [rejected] "Adds DB load" 292 - | 293 - option: Redis -> action -> outcome 294 - | 295 - observation: "Latency too high for hot paths" 296 - | 297 - decision: "How to reduce latency for static assets?" (2021) 298 - |-> option: CDN [chosen] 299 - ``` 300 - 301 - Multiple observations can converge into one decision. Multiple options can branch from one decision. But the graph flows forward in time. 302 - 303 - ## Edge Types 304 - 305 - Use specific edge types to show relationships: 306 - 307 - ```bash 308 - deciduous link <from> <to> -t chosen -r "Why this was selected" 309 - deciduous link <from> <to> -t rejected -r "Why this wasn't selected" 310 - deciduous link <from> <to> -t leads_to -r "How this led to that" 311 - ``` 312 - 313 - - `decision --chosen--> option` - This option was selected 314 - - `decision --rejected--> option` - This option was considered but not selected (with rationale) 315 - - `decision --leads_to--> option` - Lists available options 316 - 317 - For post-hoc abandonment (tried something, it failed later): 318 - 319 - - Mark the option status as `rejected`: `deciduous status <id> rejected` 320 - - Create an observation explaining why it failed 321 - - Link observation to the new decision it triggered 322 - 323 - ## Link Patterns (goal -> options -> decision -> actions -> outcomes) 324 - 325 - - `goal -> option` - Goal leads to possible approaches 326 - - `option -> decision` - Options lead to choosing (use chosen/rejected edge types) 327 - - `decision -> action` - Chosen option leads to implementation 328 - - `action -> outcome` - Action produces result 329 - - `outcome -> observation` - Result reveals new insight 330 - - `observation -> option` - Insight suggests new approach (feeds back to options) 331 - - `observation -> revisit` - Insight forces reconsideration of previous approach 332 - - `revisit -> option` - Pivot leads to exploring new options 333 - 334 - When a design approach is abandoned and replaced: 335 - 336 - ```bash 337 - deciduous add observation "JWT too large for mobile" 338 - deciduous add revisit "Reconsidering token strategy" 339 - deciduous link <observation> <revisit> -r "forced rethinking" 340 - deciduous status <old_decision> superseded 341 - ``` 342 - 343 - Revisit nodes connect old approaches to new ones, capturing WHY things changed. 344 - 345 - ## Grounding Requirements 346 - 347 - 1. **Actions must cite commits**: Every action node must reference a real commit SHA in its description. Use `-d` when adding the node. 348 - 349 - 2. **Observations from evidence**: Observations should come from commit messages, code comments, or test descriptions you find in the repo. 350 - 351 - 3. **No speculation**: If you can't find evidence for something in the repo, don't include it. An incomplete but grounded graph is better than a complete but speculative one. 352 - 353 - 4. **Quote sources**: When possible, quote or paraphrase the actual commit message or comment that supports a node. 354 - 355 - ## Rich Node Content 356 - 357 - The graph is an **alternative interface to browsing commit history**. Someone reading a node should understand what happened without looking up commits. 358 - 359 - **Every node needs a description** - especially outcome and observation nodes. The description should be readable to someone exploring the graph who doesn't have the commits open. 360 - 361 - ### Structure: Explanation first, then sources 362 - 363 - 1. **Start with a readable explanation** that makes sense within the narrative. What happened? Why? How does it connect to what came before? 364 - 2. **Add sources below** with direct quotes from commits that support the explanation. 365 - 366 - If you find your explanation doesn't make sense in context - something feels like a leap or a gap - that's a signal to dig deeper. There's probably a missing commit or transition you haven't found yet. 367 - 368 - The relationship is many-to-many: 369 - 370 - - One node may reference multiple commits (a decision informed by several changes) 371 - - One commit may appear in multiple nodes (a large commit touching several concerns) 372 - 373 - ### Example 374 - 375 - ```bash 376 - deciduous add decision "Should we switch from SQL to a document store?" -d "The team decided to switch from SQL to a document store. 377 - This eliminated the impedance mismatch between the object model and storage, 378 - at the cost of losing ad-hoc query capability (which wasn't being used anyway). 379 - 380 - Sources: 381 - - a1b2c3d: 'Our access patterns are almost entirely key-value lookups. The 382 - JOIN operations we wrote are never actually used in production.' 383 - - e4f5g6h: 'Document store removes the ORM layer entirely - one less thing 384 - to maintain and debug.'" 385 - ``` 386 - 387 - ### DO NOT: 388 - 389 - - Leave nodes with just a title and no description 390 - - Put quotes first without explaining what they mean 391 - - Write explanations that don't make sense in the narrative flow (this signals missing context) 392 - 393 - ### DO: 394 - 395 - - Write explanations that flow naturally from previous nodes 396 - - Include direct quotes that support the explanation 397 - - Treat gaps in the story as prompts to investigate further 398 - 399 - ## Output 400 - 401 - When done, run `deciduous graph > graph.json` to export.
-771
.opencode/commands/decision.md
··· 1 - --- 2 - description: Manage decision graph - track algorithm choices and reasoning 3 - arguments: 4 - - name: ACTION 5 - description: 'Command: add <type> <title>, link <from> <to>, nodes, edges, sync, etc.' 6 - required: true 7 - --- 8 - 9 - # Decision Graph Management 10 - 11 - **Log decisions IN REAL-TIME as you work, not retroactively.** 12 - 13 - ## When to Use This 14 - 15 - | You're doing this... | Log this type | Command | 16 - | ----------------------------- | ------------------ | ------------------------------------------------------ | 17 - | Starting a new feature | `goal` **with -p** | `/decision add goal "Add user auth" -p "user request"` | 18 - | Choosing between approaches | `decision` | `/decision add decision "Choose auth method"` | 19 - | Considering an option | `option` | `/decision add option "JWT tokens"` | 20 - | About to write code | `action` | `/decision add action "Implementing JWT"` | 21 - | Noticing something | `observation` | `/decision add obs "Found existing auth code"` | 22 - | Finished something | `outcome` | `/decision add outcome "JWT working"` | 23 - | Reconsidering a past decision | `revisit` | `/decision add revisit "Reconsidering auth"` | 24 - 25 - ## Quick Commands 26 - 27 - Based on $ACTION: 28 - 29 - ### View Commands 30 - 31 - - `nodes` or `list` -> `deciduous nodes` 32 - - `edges` -> `deciduous edges` 33 - - `graph` -> `deciduous graph` 34 - - `commands` -> `deciduous commands` 35 - 36 - ### Create Nodes (with optional metadata) 37 - 38 - - `add goal <title>` -> `deciduous add goal "<title>" -c 90` 39 - - `add decision <title>` -> `deciduous add decision "<title>" -c 75` 40 - - `add option <title>` -> `deciduous add option "<title>" -c 70` 41 - - `add action <title>` -> `deciduous add action "<title>" -c 85` 42 - - `add obs <title>` -> `deciduous add observation "<title>" -c 80` 43 - - `add outcome <title>` -> `deciduous add outcome "<title>" -c 90` 44 - - `add revisit <title>` -> `deciduous add revisit "<title>" -c 75` 45 - 46 - ### Optional Flags for Nodes 47 - 48 - - `-c, --confidence <0-100>` - Confidence level 49 - - `-p, --prompt "..."` - Store the user prompt that triggered this node 50 - - `-f, --files "file1.rs,file2.rs"` - Associate files with this node 51 - - `-b, --branch <name>` - Git branch (auto-detected by default) 52 - - `--no-branch` - Skip branch auto-detection 53 - - `--commit <hash|HEAD>` - Link to a git commit (use HEAD for current commit) 54 - - `--date "YYYY-MM-DD"` - Backdate node (for archaeology/retroactive logging) 55 - 56 - ### CRITICAL: Link Commits to Actions/Outcomes 57 - 58 - **After every git commit, link it to the decision graph!** 59 - 60 - ```bash 61 - git commit -m "feat: add auth" 62 - deciduous add action "Implemented auth" -c 90 --commit HEAD 63 - deciduous link <goal_id> <action_id> -r "Implementation" 64 - ``` 65 - 66 - ## CRITICAL: Capture VERBATIM User Prompts 67 - 68 - **Prompts must be the EXACT user message, not a summary.** When a user request triggers new work, capture their full message word-for-word. 69 - 70 - **BAD - summaries are useless for context recovery:** 71 - 72 - ```bash 73 - # DON'T DO THIS - this is a summary, not a prompt 74 - deciduous add goal "Add auth" -p "User asked: add login to the app" 75 - ``` 76 - 77 - **GOOD - verbatim prompts enable full context recovery:** 78 - 79 - ```bash 80 - # Use --prompt-stdin for multi-line prompts 81 - deciduous add goal "Add auth" -c 90 --prompt-stdin << 'EOF' 82 - I need to add user authentication to the app. Users should be able to sign up 83 - with email/password, and we need OAuth support for Google and GitHub. The auth 84 - should use JWT tokens with refresh token rotation. 85 - EOF 86 - 87 - # Or use the prompt command to update existing nodes 88 - deciduous prompt 42 << 'EOF' 89 - The full verbatim user message goes here... 90 - EOF 91 - ``` 92 - 93 - **When to capture prompts:** 94 - 95 - - Root `goal` nodes: YES - the FULL original request 96 - - Major direction changes: YES - when user redirects the work 97 - - Routine downstream nodes: NO - they inherit context via edges 98 - 99 - **Updating prompts on existing nodes:** 100 - 101 - ```bash 102 - deciduous prompt <node_id> "full verbatim prompt here" 103 - cat prompt.txt | deciduous prompt <node_id> # Multi-line from stdin 104 - ``` 105 - 106 - Prompts are viewable in the web viewer. 107 - 108 - ## Branch-Based Grouping 109 - 110 - **Nodes are automatically tagged with the current git branch.** This enables filtering by feature/PR. 111 - 112 - ### How It Works 113 - 114 - - When you create a node, the current git branch is stored in `metadata_json` 115 - - Configure which branches are "main" in `.deciduous/config.toml`: 116 - ```toml 117 - [branch] 118 - main_branches = ["main", "master"] # Branches not treated as "feature branches" 119 - auto_detect = true # Auto-detect branch on node creation 120 - ``` 121 - - Nodes on feature branches (anything not in `main_branches`) can be grouped/filtered 122 - 123 - ### CLI Filtering 124 - 125 - ```bash 126 - # Show only nodes from specific branch 127 - deciduous nodes --branch main 128 - deciduous nodes --branch feature-auth 129 - deciduous nodes -b my-feature 130 - 131 - # Override auto-detection when creating nodes 132 - deciduous add goal "Feature work" -b feature-x # Force specific branch 133 - deciduous add goal "Universal note" --no-branch # No branch tag 134 - ``` 135 - 136 - ### Web UI Branch Filter 137 - 138 - The graph viewer shows a branch dropdown in the stats bar: 139 - 140 - - "All branches" shows everything 141 - - Select a specific branch to filter all views (Chains, Timeline, Graph, DAG) 142 - 143 - ### When to Use Branch Grouping 144 - 145 - - **Feature work**: Nodes created on `feature-auth` branch auto-grouped 146 - - **PR context**: Filter to see only decisions for a specific PR 147 - - **Cross-cutting concerns**: Use `--no-branch` for universal notes 148 - - **Retrospectives**: Filter by branch to see decision history per feature 149 - 150 - ### Create Edges 151 - 152 - - `link <from> <to> [reason]` -> `deciduous link <from> <to> -r "<reason>"` 153 - 154 - ### Document Attachments 155 - 156 - - `doc attach <node_id> <file>` -> `deciduous doc attach <node_id> <file>` 157 - - `doc attach <node_id> <file> -d "desc"` -> attach with description 158 - - `doc attach <node_id> <file> --ai-describe` -> attach with AI-generated description 159 - - `doc list` -> `deciduous doc list` (all documents) 160 - - `doc list <node_id>` -> `deciduous doc list <node_id>` (documents for one node) 161 - - `doc show <id>` -> `deciduous doc show <id>` 162 - - `doc describe <id> "desc"` -> `deciduous doc describe <id> "desc"` 163 - - `doc describe <id> --ai` -> AI-generate description 164 - - `doc open <id>` -> `deciduous doc open <id>` (open in default app) 165 - - `doc detach <id>` -> `deciduous doc detach <id>` (soft-delete) 166 - - `doc gc` -> `deciduous doc gc` (garbage-collect orphaned files) 167 - 168 - ### Sync Graph 169 - 170 - - `sync` -> `deciduous sync` 171 - 172 - ### Multi-User Sync (Event-Based) - RECOMMENDED 173 - 174 - - `events init` -> `deciduous events init` (initialize event-based sync) 175 - - `events status` -> `deciduous events status` (show pending events) 176 - - `events rebuild` -> `deciduous events rebuild` (apply teammate events) 177 - - `events checkpoint` -> `deciduous events checkpoint` (create snapshot) 178 - - `events checkpoint --clear-events` -> snapshot and clear old events 179 - 180 - ### Multi-User Sync (Legacy Diff/Patch) 181 - 182 - - `diff export -o <file>` -> `deciduous diff export -o <file>` (export nodes as patch) 183 - - `diff export --nodes 1-10 -o <file>` -> export specific nodes 184 - - `diff export --branch feature-x -o <file>` -> export nodes from branch 185 - - `diff apply <file>` -> `deciduous diff apply <file>` (apply patch, idempotent) 186 - - `diff apply --dry-run <file>` -> preview without applying 187 - - `diff status` -> `deciduous diff status` (list patches in .deciduous/patches/) 188 - - `migrate` -> `deciduous migrate` (add change_id columns for sync) 189 - 190 - ### Export & Visualization 191 - 192 - - `dot` -> `deciduous dot` (output DOT to stdout) 193 - - `dot --png` -> `deciduous dot --png -o graph.dot` (generate PNG) 194 - - `dot --nodes 1-11` -> `deciduous dot --nodes 1-11` (filter nodes) 195 - - `writeup` -> `deciduous writeup` (generate PR writeup) 196 - - `writeup -t "Title" --nodes 1-11` -> filtered writeup 197 - 198 - ## Node Types 199 - 200 - | Type | Purpose | Example | 201 - | ------------- | ----------------------------- | ----------------------------- | 202 - | `goal` | High-level objective | "Add user authentication" | 203 - | `decision` | Choice point with options | "Choose auth method" | 204 - | `option` | Possible approach | "Use JWT tokens" | 205 - | `action` | Something implemented | "Added JWT middleware" | 206 - | `outcome` | Result of action | "JWT auth working" | 207 - | `observation` | Finding or data point | "Existing code uses sessions" | 208 - | `revisit` | Pivot point / reconsideration | "Reconsidering auth approach" | 209 - 210 - ## Edge Types 211 - 212 - | Type | Meaning | 213 - | ---------- | ------------------------------ | 214 - | `leads_to` | Natural progression | 215 - | `chosen` | Selected option | 216 - | `rejected` | Not selected (include reason!) | 217 - | `requires` | Dependency | 218 - | `blocks` | Preventing progress | 219 - | `enables` | Makes something possible | 220 - 221 - ## Graph Integrity - CRITICAL 222 - 223 - **Every node MUST be logically connected.** Floating nodes break the graph's value. 224 - 225 - ### Connection Rules (goal -> options -> decision -> actions -> outcomes) 226 - 227 - | Node Type | MUST connect to | Example | 228 - | ------------- | --------------------------------------- | ---------------------------------------------------- | 229 - | `goal` | Can be a root (no parent needed) | Root goals are valid orphans | 230 - | `option` | Its parent goal | "Use JWT" -> links FROM "Add auth" | 231 - | `decision` | The option(s) it chose between | "Choose JWT" -> links FROM "Use JWT" option | 232 - | `action` | The decision that spawned it | "Implementing JWT" -> links FROM "Choose JWT" | 233 - | `outcome` | The action that produced it | "JWT working" -> links FROM "Implementing JWT" | 234 - | `observation` | Related goal/action/decision | "Found existing code" -> links TO relevant node | 235 - | `revisit` | The decision/outcome being reconsidered | "Reconsidering auth" -> links FROM original decision | 236 - 237 - ### Audit Checklist 238 - 239 - Ask yourself after creating nodes: 240 - 241 - 1. Does every **outcome** link back to the action that produced it? 242 - 2. Does every **action** link to the decision that spawned it? 243 - 3. Does every **option** link to its parent goal? 244 - 4. Does every **decision** link from the option(s) being chosen? 245 - 5. Are there **dangling outcomes** with no parent action? 246 - 247 - ### Find Disconnected Nodes 248 - 249 - ```bash 250 - # List nodes with no incoming edges (potential orphans) 251 - deciduous edges | cut -d'>' -f2 | cut -d' ' -f2 | sort -u > /tmp/has_parent.txt 252 - deciduous nodes | tail -n+3 | awk '{print $1}' | while read id; do 253 - grep -q "^$id$" /tmp/has_parent.txt || echo "CHECK: $id" 254 - done 255 - ``` 256 - 257 - Note: Root goals are VALID orphans. Outcomes/actions/options usually are NOT. 258 - 259 - ### Fix Missing Connections 260 - 261 - ```bash 262 - deciduous link <parent_id> <child_id> -r "Retroactive connection - <why>" 263 - ``` 264 - 265 - ### When to Audit 266 - 267 - - Before every `deciduous sync` 268 - - After creating multiple nodes quickly 269 - - At session end 270 - - When the web UI graph looks disconnected 271 - 272 - ## Git Staging Rules - CRITICAL 273 - 274 - **NEVER use broad git add commands that stage everything:** 275 - 276 - - `git add -A` - stages ALL changes including untracked files 277 - - `git add .` - stages everything in current directory 278 - - `git add -a` or `git commit -am` - auto-stages all tracked changes 279 - - `git add *` - glob patterns can catch unintended files 280 - 281 - **ALWAYS stage files explicitly by name:** 282 - 283 - - `git add src/main.rs src/lib.rs` 284 - - `git add Cargo.toml Cargo.lock` 285 - - `git add .opencode/commands/decision.md` 286 - 287 - **Why this matters:** 288 - 289 - - Prevents accidentally committing sensitive files (.env, credentials) 290 - - Prevents committing large binaries or build artifacts 291 - - Forces you to review exactly what you're committing 292 - - Catches unintended changes before they enter git history 293 - 294 - ## Multi-User Sync 295 - 296 - **Problem**: Multiple users work on the same codebase, each with a local `.deciduous/deciduous.db` (gitignored). How to share decisions? 297 - 298 - **Solution**: Event-based sync with append-only logs. Each user has their own event file that git merges automatically. 299 - 300 - ### Event-Based Sync (Recommended) 301 - 302 - **Setup (once per repo):** 303 - 304 - ```bash 305 - deciduous events init 306 - git add .deciduous/sync/ 307 - git commit -m "feat: enable event-based sync" 308 - ``` 309 - 310 - **Daily workflow:** 311 - 312 - ```bash 313 - git pull # Get teammate events 314 - deciduous events rebuild # Apply to local DB 315 - # Work normally - events auto-emit on add/link/etc. 316 - git add .deciduous/sync/ && git commit -m "sync" && git push 317 - ``` 318 - 319 - **Periodic maintenance:** 320 - 321 - ```bash 322 - deciduous events checkpoint --clear-events # Compact old events 323 - git add .deciduous/sync/ && git commit -m "checkpoint" 324 - ``` 325 - 326 - ### Legacy Patch Workflow 327 - 328 - For manual control, use the older patch system: 329 - 330 - ```bash 331 - # Export nodes as a patch file 332 - deciduous diff export --branch feature-x -o .deciduous/patches/my-feature.json 333 - 334 - # Apply patches from teammates 335 - deciduous diff apply .deciduous/patches/*.json 336 - ``` 337 - 338 - ## The Rule 339 - 340 - ``` 341 - LOG BEFORE YOU CODE, NOT AFTER. 342 - CONNECT EVERY NODE TO ITS PARENT. 343 - AUDIT FOR ORPHANS REGULARLY. 344 - SYNC BEFORE YOU PUSH. 345 - EXPORT PATCHES FOR YOUR TEAMMATES. 346 - ``` 347 - 348 - **Live graph**: https://notactuallytreyanastasio.github.io/deciduous/ 349 - 350 - ## Workflow: /work 351 - 352 - **USE THIS BEFORE STARTING ANY IMPLEMENTATION.** 353 - 354 - This skill creates the required deciduous nodes BEFORE you write any code. The `require-action-node` plugin will nag to `.deciduous/plugin.log` if you don't have a recent node — it does not block edits. The post-commit-reminder plugin will nag again to link the commit. Treat the nags as guardrails, not gates. 355 - 356 - ### Step 1: Create the Goal Node 357 - 358 - Based on $GOAL (or the user's most recent request), create a goal node: 359 - 360 - ```bash 361 - # Create goal with the user's request captured verbatim 362 - deciduous add goal "$GOAL" -c 90 --prompt-stdin << 'EOF' 363 - [INSERT THE EXACT USER REQUEST HERE - VERBATIM, NOT SUMMARIZED] 364 - EOF 365 - ``` 366 - 367 - **IMPORTANT**: The prompt must be the user's EXACT words, not your summary. 368 - 369 - ### Step 2: Announce the Goal ID 370 - 371 - After creating the goal, tell the user: 372 - 373 - - The goal ID that was created 374 - - What you're about to implement 375 - - That you'll create action nodes as you work 376 - 377 - ### Step 3: Before Each Major Edit 378 - 379 - Before editing files, create an action node: 380 - 381 - ```bash 382 - deciduous add action "What you're about to implement" -c 85 -f "file1.rs,file2.rs" 383 - deciduous link <goal_id> <action_id> -r "Implementation step" 384 - ``` 385 - 386 - ### Step 4: After Completion 387 - 388 - When the work is done: 389 - 390 - ```bash 391 - # After committing 392 - deciduous add outcome "What was accomplished" -c 95 --commit HEAD 393 - deciduous link <action_id> <outcome_id> -r "Implementation complete" 394 - 395 - # Sync the graph 396 - deciduous sync 397 - ``` 398 - 399 - ### Step 5: Attach Supporting Documents (Optional) 400 - 401 - If the work produced or referenced important files (diagrams, specs, screenshots): 402 - 403 - ```bash 404 - deciduous doc attach <goal_id> path/to/diagram.png -d "Architecture diagram" 405 - deciduous doc attach <action_id> path/to/spec.pdf --ai-describe 406 - ``` 407 - 408 - If the user shares images or drops in files not in the project, attach them to the most relevant active node. 409 - 410 - ### The Transaction Model 411 - 412 - ``` 413 - /work "Add feature X" 414 - | 415 - Goal node created (ID: N) 416 - | 417 - Action node before each edit (links to goal) 418 - | 419 - Implementation happens (Edit/Write now allowed) 420 - | 421 - git commit 422 - | 423 - Outcome node with --commit HEAD (links to action) 424 - | 425 - Attach supporting documents (optional) 426 - | 427 - deciduous sync 428 - ``` 429 - 430 - ### Why This Matters 431 - 432 - - **The plugins nag, they don't block.** If no recent action/goal exists, `.deciduous/plugin.log` records the reminder; the edit still goes through. Same for post-commit. 433 - - **Commits will remind you** to link them to the graph 434 - - **The graph captures your reasoning** for future sessions 435 - - **Context recovery works** because the graph has everything 436 - 437 - ### Quick Reference 438 - 439 - ```bash 440 - # Start work 441 - deciduous add goal "Feature title" -c 90 -p "User request" 442 - 443 - # Before editing (required!) 444 - deciduous add action "What I'm implementing" -c 85 445 - deciduous link <goal> <action> -r "Implementation" 446 - 447 - # After committing 448 - deciduous add outcome "Result" -c 95 --commit HEAD 449 - deciduous link <action> <outcome> -r "Complete" 450 - 451 - # Attach documents (optional) 452 - deciduous doc attach <goal> diagram.png -d "Description" 453 - 454 - # Always sync 455 - deciduous sync 456 - ``` 457 - 458 - ## Workflow: /document 459 - 460 - **Comprehensive documentation that shakes the tree to understand everything.** 461 - 462 - This skill generates in-depth documentation for a file or directory, focusing on: 463 - 464 - - Human readability while covering ALL surface area 465 - - Linking to tests as working examples 466 - - Refining tests to look more real-world if needed 467 - - Integration with the deciduous decision graph 468 - 469 - --- 470 - 471 - ### Step 1: Create Documentation Goal Node 472 - 473 - Before documenting, log what you're about to do: 474 - 475 - ```bash 476 - deciduous add goal "Document $TARGET" -c 90 --prompt-stdin << 'EOF' 477 - [User's verbatim documentation request] 478 - EOF 479 - ``` 480 - 481 - Store the goal ID for linking later. 482 - 483 - --- 484 - 485 - ### Step 2: Understand the Target 486 - 487 - #### For a File 488 - 489 - 1. **Read the file completely** 490 - - Understand every function, class, type, and export 491 - - Note all imports and dependencies 492 - - Identify the file's role in the larger system 493 - 494 - 2. **Find tests for this file** 495 - - Look for test files with similar names 496 - - Search for imports/references in test directories 497 - - These will become working examples in the docs 498 - 499 - 3. **Trace callers/callees** 500 - - Who calls this file? 501 - - What does this file call? 502 - - Map the dependency graph 503 - 504 - #### For a Directory 505 - 506 - 1. **Map the structure** 507 - - List all files and their purposes 508 - - Identify the public API (index/mod files) 509 - - Find the entry point 510 - 511 - 2. **Understand relationships** 512 - - How do files in this directory interact? 513 - - What's the data flow? 514 - 515 - 3. **Find related tests** 516 - - Test directories that cover this code 517 - - Integration tests that exercise the whole module 518 - 519 - --- 520 - 521 - ### Step 3: Document Each Component 522 - 523 - For each file/component, document: 524 - 525 - #### 3.1 Purpose 526 - 527 - - One sentence: what does this do? 528 - - Why does it exist? (The "why" is more important than the "what") 529 - 530 - #### 3.2 API Surface 531 - 532 - For every public function/method/class: 533 - 534 - ````markdown 535 - ### `function_name(param1: Type, param2: Type) -> ReturnType` 536 - 537 - **Purpose:** What this does and why you'd call it. 538 - 539 - **Parameters:** 540 - 541 - - `param1` - Description and valid values 542 - - `param2` - Description and valid values 543 - 544 - **Returns:** What the return value means 545 - 546 - **Throws/Errors:** What can go wrong 547 - 548 - **Example:** 549 - 550 - ```code 551 - // From: tests/example_test.rs:42 552 - let result = function_name("input", 42); 553 - assert_eq!(result, expected); 554 - ``` 555 - ```` 556 - 557 - **Related:** Links to related functions 558 - 559 - #### 3.3 Internal Architecture 560 - 561 - - How does it work internally? 562 - - What are the key data structures? 563 - - What are the invariants? 564 - 565 - #### 3.4 Dependencies 566 - 567 - - What does this depend on? 568 - - What depends on this? 569 - 570 - #### 3.5 Tests as Examples 571 - 572 - For each relevant test: 573 - 574 - - Show the test as a working example 575 - - Explain what the test demonstrates 576 - - **If test is too synthetic/artificial, REFINE IT:** 577 - - Make variable names descriptive 578 - - Add comments explaining the scenario 579 - - Use realistic values instead of "foo", "bar", 123 580 - - Create a deciduous observation node noting the refinement 581 - 582 - --- 583 - 584 - ### Step 4: Create Documentation File 585 - 586 - **Output location:** 587 - 588 - - For file `src/auth/jwt.rs` -> `docs/src/auth/jwt.rs.md` 589 - - For directory `src/auth/` -> `docs/src/auth/README.md` 590 - 591 - **Document structure:** 592 - 593 - ````markdown 594 - # <Component Name> 595 - 596 - > One-sentence description 597 - 598 - ## Overview 599 - 600 - High-level explanation of what this does and why it exists. 601 - 602 - ## Quick Start 603 - 604 - ```code 605 - // Most common usage pattern - from real tests 606 - ``` 607 - ```` 608 - 609 - ## API Reference 610 - 611 - [For each public function/type/constant] 612 - 613 - ### `function_name(...)` 614 - 615 - [Generated from Step 3.2] 616 - 617 - ## Architecture 618 - 619 - [Internal design, data flow, key invariants - from Step 3.3] 620 - 621 - ## Examples 622 - 623 - [Tests converted to examples - from Step 3.5] 624 - 625 - ## Dependencies 626 - 627 - [What this depends on, what depends on this - from Step 3.4] 628 - 629 - ## Related Documentation 630 - 631 - - Links to other relevant docs 632 - - Links to test files 633 - 634 - ```` 635 - 636 - --- 637 - 638 - ### Step 5: Refine Tests If Needed 639 - 640 - If tests are too synthetic (meaningless variable names, unrealistic values): 641 - 642 - 1. Read the test file 643 - 2. Improve it with: 644 - - Descriptive variable names (user_email, order_total, not x, y) 645 - - Realistic values (not "foo", "bar", 123) 646 - - Comments explaining the scenario 647 - 3. Edit the test file with improvements 648 - 4. Create observation node: 649 - 650 - ```bash 651 - deciduous add observation "Refined tests for <component> - made more real-world" -c 85 652 - deciduous link <action_id> <observation_id> -r "Test improvements during documentation" 653 - ```` 654 - 655 - --- 656 - 657 - ### Step 6: Link to Decision Graph 658 - 659 - After documentation is complete: 660 - 661 - ```bash 662 - # Create documentation action (if not already created) 663 - deciduous add action "Documented <target>" -c 95 -f "<files-created>" 664 - 665 - # Link to goal 666 - deciduous link <goal_id> <action_id> -r "Documentation complete" 667 - 668 - # Create outcome 669 - deciduous add outcome "Documentation complete for <target>" -c 95 670 - deciduous link <action_id> <outcome_id> -r "Successfully documented" 671 - 672 - # Sync 673 - deciduous sync 674 - ``` 675 - 676 - --- 677 - 678 - ### Step 7: Verify Coverage 679 - 680 - **Checklist before completing:** 681 - 682 - - [ ] Every public function documented 683 - - [ ] Every parameter explained 684 - - [ ] Every return value explained 685 - - [ ] Every error case documented 686 - - [ ] At least one example per function (from tests) 687 - - [ ] Architecture overview included 688 - - [ ] Dependencies mapped 689 - - [ ] Links to tests included 690 - - [ ] Tests refined if they were synthetic 691 - 692 - If anything is missing, go back and fill it in. **Do not miss any surface area.** 693 - 694 - --- 695 - 696 - ### Decision Criteria 697 - 698 - **What to document:** 699 - 700 - - Public APIs (always) 701 - - Complex internal logic (when it's not obvious) 702 - - Design decisions (why, not just what) 703 - - Edge cases and error handling 704 - - Integration points 705 - 706 - **What NOT to document:** 707 - 708 - - Trivial getters/setters 709 - - Auto-generated code 710 - - Implementation details obvious from code 711 - 712 - **How deep to go:** 713 - 714 - - Deep enough that someone new could understand and use the code 715 - - Deep enough that someone could modify it without breaking things 716 - - Capture the "why" behind design decisions 717 - 718 - --- 719 - 720 - ### Example Usage 721 - 722 - ```bash 723 - # Document a single file 724 - /document src/auth/jwt.rs 725 - 726 - # Document a directory 727 - /document src/auth/ 728 - 729 - # Document the whole project 730 - /document . 731 - ``` 732 - 733 - **What happens:** 734 - 735 - 1. Goal node created 736 - 2. Code analyzed thoroughly 737 - 3. Tests found and used as examples 738 - 4. Tests refined if synthetic 739 - 5. Documentation written to docs/ 740 - 6. Action/outcome nodes created 741 - 7. Graph synced 742 - 743 - --- 744 - 745 - ### Integration with Documentation Enforcement 746 - 747 - When documentation is created, the `require-documentation.sh` hook will recognize it exists. This creates a virtuous cycle: 748 - 749 - 1. Can't edit code without documentation (hook blocks) 750 - 2. Run `/document` to create documentation 751 - 3. Now code edits are allowed 752 - 4. When code changes significantly, re-run `/document` 753 - 754 - --- 755 - 756 - ### Quick Reference 757 - 758 - ```bash 759 - # Document and generate docs 760 - /document <path> 761 - 762 - # After documenting, you can edit the file 763 - # The require-documentation.sh hook will allow it 764 - ``` 765 - 766 - **Always creates:** 767 - 768 - - Goal node (before starting) 769 - - Action node (for the documentation work) 770 - - Outcome node (on completion) 771 - - Observation nodes (for test refinements)
-192
.opencode/commands/recover.md
··· 1 - --- 2 - description: Recover context from decision graph and recent activity - USE THIS ON SESSION START 3 - arguments: 4 - - name: FOCUS 5 - description: Optional focus area to filter by (e.g. auth, ui, cli, api) 6 - required: false 7 - --- 8 - 9 - # Context Recovery 10 - 11 - **RUN THIS AT SESSION START.** The decision graph is your persistent memory. 12 - 13 - ## Step 1: Query the Graph 14 - 15 - ```bash 16 - # See all decisions (look for recent ones and pending status) 17 - deciduous nodes 18 - 19 - # Filter by current branch (useful for feature work) 20 - deciduous nodes --branch $(git rev-parse --abbrev-ref HEAD) 21 - 22 - # See how decisions connect 23 - deciduous edges 24 - 25 - # What commands were recently run? 26 - deciduous commands 27 - 28 - # Check for attached documents 29 - deciduous doc list 30 - ``` 31 - 32 - **Branch-scoped context**: If working on a feature branch, filter nodes to see only decisions relevant to this branch. Main branch nodes are tagged with `[branch: main]`. 33 - 34 - ## Step 1.5: Audit Graph Integrity 35 - 36 - **CRITICAL: Check that all nodes are logically connected.** 37 - 38 - ```bash 39 - # Find nodes with no incoming edges (potential missing connections) 40 - deciduous edges | cut -d'>' -f2 | cut -d' ' -f2 | sort -u > /tmp/has_parent.txt 41 - deciduous nodes | tail -n+3 | awk '{print $1}' | while read id; do 42 - grep -q "^$id$" /tmp/has_parent.txt || echo "CHECK: $id" 43 - done 44 - ``` 45 - 46 - **Review each flagged node (flow: goal -> options -> decision -> actions -> outcomes):** 47 - 48 - - Root `goal` nodes are VALID without parents 49 - - `option` nodes MUST link to their parent goal 50 - - `decision` nodes MUST link from the option(s) being chosen 51 - - `action` nodes MUST link to their parent decision 52 - - `outcome` nodes MUST link back to their action 53 - 54 - **Fix missing connections:** 55 - 56 - ```bash 57 - deciduous link <parent_id> <child_id> -r "Retroactive connection - <reason>" 58 - ``` 59 - 60 - ## Step 2: Check Git State 61 - 62 - ```bash 63 - git status 64 - git log --oneline -10 65 - git diff --stat 66 - ``` 67 - 68 - ## Step 3: Check Session Log 69 - 70 - ```bash 71 - cat git.log | tail -30 72 - ``` 73 - 74 - ## After Gathering Context, Report: 75 - 76 - 1. **Current branch** and pending changes 77 - 2. **Branch-specific decisions** (filter by branch if on feature branch) 78 - 3. **Recent decisions** (especially pending/active ones) 79 - 4. **Last actions** from git log and command log 80 - 5. **Open questions** or unresolved observations 81 - 6. **Attached documents** - diagrams, specs, or screenshots on key nodes 82 - 7. **Suggested next steps** 83 - 84 - ### Branch Configuration 85 - 86 - Check `.deciduous/config.toml` for branch settings: 87 - 88 - ```toml 89 - [branch] 90 - main_branches = ["main", "master"] # Which branches are "main" 91 - auto_detect = true # Auto-detect branch on node creation 92 - ``` 93 - 94 - --- 95 - 96 - ## REMEMBER: Real-Time Logging Required 97 - 98 - After recovering context, you MUST follow the logging workflow: 99 - 100 - ``` 101 - EVERY USER REQUEST -> Log goal/decision first 102 - BEFORE CODE CHANGES -> Log action 103 - AFTER CHANGES -> Log outcome, link nodes 104 - BEFORE GIT PUSH -> deciduous sync 105 - ``` 106 - 107 - **The user is watching the graph live.** Log as you go, not after. 108 - 109 - ### Quick Logging Commands 110 - 111 - ```bash 112 - # Root goal with user prompt (capture what the user asked for) 113 - deciduous add goal "What we're trying to do" -c 90 -p "User asked: <their request>" 114 - 115 - deciduous add action "What I'm about to implement" -c 85 116 - deciduous add outcome "What happened" -c 95 117 - deciduous link FROM TO -r "Connection reason" 118 - 119 - # Capture prompt when user redirects mid-stream 120 - deciduous add action "Switching approach" -c 85 -p "User said: use X instead" 121 - 122 - deciduous sync # Do this frequently! 123 - ``` 124 - 125 - **When to use `--prompt`:** On root goals (always) and when user gives new direction mid-stream. Downstream nodes inherit context via edges. 126 - 127 - --- 128 - 129 - ## Focus Areas 130 - 131 - If $FOCUS specifies a focus, prioritize context for: 132 - 133 - - **auth**: Authentication-related decisions 134 - - **ui** / **graph**: UI and graph viewer state 135 - - **cli**: Command-line interface changes 136 - - **api**: API endpoints and data structures 137 - 138 - --- 139 - 140 - ## The Memory Loop 141 - 142 - ``` 143 - SESSION START 144 - | 145 - Run /recover -> See past decisions 146 - | 147 - AUDIT -> Fix any orphan nodes first! 148 - | 149 - DO WORK -> Log BEFORE each action 150 - | 151 - CONNECT -> Link new nodes immediately 152 - | 153 - AFTER CHANGES -> Log outcomes, observations 154 - | 155 - AUDIT AGAIN -> Any new orphans? 156 - | 157 - BEFORE PUSH -> deciduous sync 158 - | 159 - PUSH -> Live graph updates 160 - | 161 - SESSION END -> Final audit 162 - | 163 - (repeat) 164 - ``` 165 - 166 - --- 167 - 168 - ## Multi-User Sync 169 - 170 - If working in a team, sync decision graphs automatically via events: 171 - 172 - ```bash 173 - # Check sync status 174 - deciduous events status 175 - 176 - # Apply teammate events (after git pull) 177 - deciduous events rebuild 178 - 179 - # Periodic maintenance (compact old events) 180 - deciduous events checkpoint --clear-events 181 - ``` 182 - 183 - Events are auto-emitted when you use `add`, `link`, `status`, etc. 184 - Git handles merging everyone's event files automatically. 185 - 186 - ## Why This Matters 187 - 188 - - Context loss during compaction loses your reasoning 189 - - The graph survives - query it early, query it often 190 - - Retroactive logging misses details - log in the moment 191 - - The user sees the graph live - show your work 192 - - Patches share reasoning with teammates
-49
.opencode/commands/serve-ui.md
··· 1 - --- 2 - description: Start the decision graph web viewer 3 - arguments: 4 - - name: PORT 5 - description: Port to run the server on (default 3000) 6 - required: false 7 - --- 8 - 9 - # Start Decision Graph Viewer 10 - 11 - Launch the deciduous web server for viewing and navigating the decision graph. 12 - 13 - ## Instructions 14 - 15 - 1. Start the server: 16 - 17 - ```bash 18 - deciduous serve --port ${PORT:-3000} 19 - ``` 20 - 21 - 2. Inform the user: 22 - - The server is running at http://localhost:${PORT:-3000} 23 - - The graph auto-refreshes every 30 seconds 24 - - They can browse decisions, chains, and timeline views 25 - - Changes made via CLI will appear automatically 26 - 27 - 3. The server will run in the foreground. Remind user to stop it when done (Ctrl+C). 28 - 29 - ## UI Features 30 - 31 - - **Chains View**: See decision chains grouped by goals 32 - - **Timeline View**: Chronological view of all decisions 33 - - **Graph View**: Interactive force-directed graph 34 - - **DAG View**: Directed acyclic graph visualization 35 - - **Detail Panel**: Click any node to see full details including: 36 - - Node metadata (confidence, commit, prompt, files) 37 - - Connected nodes (incoming/outgoing edges) 38 - - Timestamps and status 39 - - Attached documents 40 - 41 - ## Alternative: Static Hosting 42 - 43 - For GitHub Pages or other static hosting: 44 - 45 - ```bash 46 - deciduous sync # Exports to docs/graph-data.json 47 - ``` 48 - 49 - Then push to GitHub - the graph is viewable at your GitHub Pages URL.
-98
.opencode/commands/sync.md
··· 1 - --- 2 - description: Sync decision graph with teammates - pull events, rebuild, push 3 - arguments: [] 4 - --- 5 - 6 - # Multi-User Sync 7 - 8 - Synchronize decision graph with your team using event-based sync. 9 - 10 - ## Step 1: Pull Latest 11 - 12 - ```bash 13 - git pull --rebase 14 - ``` 15 - 16 - ## Step 2: Check Sync Status 17 - 18 - ```bash 19 - deciduous events status 20 - ``` 21 - 22 - Look for: 23 - 24 - - **Pending events**: Events from teammates not yet in your local DB 25 - - **Event files**: Each teammate has their own `.jsonl` file 26 - 27 - ## Step 3: Rebuild if Needed 28 - 29 - If there are pending events: 30 - 31 - ```bash 32 - # Preview what would change 33 - deciduous events rebuild --dry-run 34 - 35 - # Apply teammate events to your local database 36 - deciduous events rebuild 37 - ``` 38 - 39 - ## Step 4: Push Your Changes 40 - 41 - ```bash 42 - # Stage sync files (events are auto-committed to your event file) 43 - git add .deciduous/sync/ 44 - 45 - # Commit and push 46 - git commit -m "sync: decision graph events" 47 - git push 48 - ``` 49 - 50 - ## Checkpoint (Periodic Maintenance) 51 - 52 - To prevent repo bloat, periodically create a checkpoint: 53 - 54 - ```bash 55 - # Create checkpoint and clear old events 56 - deciduous events checkpoint --clear-events 57 - 58 - # Commit the checkpoint 59 - git add .deciduous/sync/ 60 - git commit -m "checkpoint: compact decision graph events" 61 - git push 62 - ``` 63 - 64 - **When to checkpoint:** 65 - 66 - - After major milestones 67 - - When event files get large (>100KB) 68 - - Before releases 69 - 70 - ## Troubleshooting 71 - 72 - ### Events not syncing? 73 - 74 - 1. Make sure `.deciduous/sync/` is tracked in git 75 - 2. Check that `deciduous events init` was run 76 - 3. Verify events are being emitted: `deciduous events status` 77 - 78 - ### Merge conflicts in event files? 79 - 80 - Event files are append-only JSONL. Git should auto-merge them. 81 - If conflicts occur, accept both versions (both sets of events are valid). 82 - 83 - ### Missing nodes after rebuild? 84 - 85 - Nodes reference each other by `change_id` (UUID), not local `id`. 86 - If edges fail, the referenced node may be in a teammate's events 87 - that haven't been pulled yet. Pull and rebuild again. 88 - 89 - ## Quick Reference 90 - 91 - | Command | What it does | 92 - | -------------------------------------------- | ---------------------------------------- | 93 - | `deciduous events status` | Show pending events, authors, file sizes | 94 - | `deciduous events rebuild` | Apply all events to local DB | 95 - | `deciduous events rebuild --dry-run` | Preview without applying | 96 - | `deciduous events checkpoint` | Snapshot current state | 97 - | `deciduous events checkpoint --clear-events` | Snapshot + delete old events | 98 - | `deciduous events emit <id>` | Manually emit event for a node |
-45
.opencode/plugins/post-commit-reminder.ts
··· 1 - // OpenCode Plugin: Post-Commit Reminder 2 - // Reminds to link commits to the decision graph after git commit 3 - // This ensures commits are connected to the reasoning that led to them 4 - 5 - import type { Plugin } from '@opencode-ai/plugin'; 6 - 7 - export const PostCommitReminder: Plugin = async ({ $ }) => { 8 - return { 9 - 'tool.execute.after': async (input) => { 10 - // Only check bash tool 11 - if (input.tool !== 'bash') { 12 - return; 13 - } 14 - 15 - // Check if deciduous is initialized 16 - const fs = await import('fs'); 17 - if (!fs.existsSync('.deciduous')) { 18 - return; 19 - } 20 - 21 - // Check if this was a git commit command 22 - const command = input.args?.command || ''; 23 - if (!command.match(/^git commit/)) { 24 - return; 25 - } 26 - 27 - try { 28 - // Get the latest commit info 29 - const hashResult = await $`git rev-parse --short HEAD 2>/dev/null`.quiet(); 30 - const msgResult = await $`git log -1 --format=%s 2>/dev/null`.quiet(); 31 - 32 - const commitHash = hashResult.stdout.toString().trim(); 33 - const commitMsg = msgResult.stdout.toString().trim().slice(0, 50); 34 - 35 - // Write reminder to log file instead of console (console output corrupts TUI) 36 - const path = await import('path'); 37 - const logFile = path.join('.deciduous', 'plugin.log'); 38 - const msg = `[${new Date().toISOString()}] POST-COMMIT: ${commitHash} "${commitMsg}" - Run: deciduous add outcome "..." --commit HEAD\n`; 39 - fs.appendFileSync(logFile, msg); 40 - } catch { 41 - // If git commands fail, skip the reminder 42 - } 43 - } 44 - }; 45 - };
-51
.opencode/plugins/require-action-node.ts
··· 1 - // OpenCode Plugin: Require Action Node 2 - // Checks for recent action/goal nodes before file edits 3 - // This enforces the decision graph workflow: log BEFORE you code 4 - 5 - import type { Plugin } from '@opencode-ai/plugin'; 6 - 7 - export const RequireActionNode: Plugin = async ({ $ }) => { 8 - return { 9 - 'tool.execute.before': async (input) => { 10 - // Only check on edit and write tools 11 - if (input.tool !== 'edit' && input.tool !== 'write') { 12 - return; 13 - } 14 - 15 - try { 16 - // Check if deciduous is initialized 17 - const fs = await import('fs'); 18 - if (!fs.existsSync('.deciduous')) { 19 - return; // No deciduous in this project, allow all edits 20 - } 21 - 22 - // Get recent nodes from deciduous 23 - const result = await $`deciduous nodes 2>/dev/null | tail -5`.quiet(); 24 - const stdout = result.stdout.toString(); 25 - const lines = stdout 26 - .trim() 27 - .split('\n') 28 - .filter((l: string) => l.trim()); 29 - 30 - // Check for any goal or action node 31 - let hasRecentNode = false; 32 - for (const line of lines) { 33 - if (line.match(/goal|action/i)) { 34 - hasRecentNode = true; 35 - break; 36 - } 37 - } 38 - 39 - if (!hasRecentNode && lines.length > 2) { 40 - // Write reminder to log file instead of console (console output corrupts TUI) 41 - const path = await import('path'); 42 - const logFile = path.join('.deciduous', 'plugin.log'); 43 - const msg = `[${new Date().toISOString()}] REMINDER: No recent action/goal node found. Run: deciduous add goal "..." or deciduous add action "..."\n`; 44 - fs.appendFileSync(logFile, msg); 45 - } 46 - } catch { 47 - // If deciduous isn't available, continue silently 48 - } 49 - } 50 - }; 51 - };
-152
.opencode/skills/tdd/SKILL.md
··· 1 - --- 2 - name: tdd 3 - description: Test-driven development with red-green-refactor loop, plus the suede-specific prune pass and Storybook discipline. Use when user wants to build features or fix bugs using TDD, mentions "red-green-refactor", wants integration tests, or asks for test-first development. 4 - --- 5 - 6 - # Test-Driven Development 7 - 8 - ## Philosophy 9 - 10 - **Core principle**: Tests should verify behavior through public interfaces, not implementation details. Code can change entirely; tests shouldn't. 11 - 12 - **Good tests** are integration-style: they exercise real code paths through public APIs. They describe _what_ the system does, not _how_ it does it. A good test reads like a specification - "user can checkout with valid cart" tells you exactly what capability exists. These tests survive refactors because they don't care about internal structure. 13 - 14 - **Bad tests** are coupled to implementation. They mock internal collaborators, test private methods, or verify through external means (like querying a database directly instead of using the interface). The warning sign: your test breaks when you refactor, but behavior hasn't changed. If you rename an internal function and tests fail, those tests were testing implementation, not behavior. 15 - 16 - See [tests.md](tests.md) for examples and [mocking.md](mocking.md) for mocking guidelines. 17 - 18 - ## Anti-Pattern: Horizontal Slices 19 - 20 - **DO NOT write all tests first, then all implementation.** This is "horizontal slicing" - treating RED as "write all tests" and GREEN as "write all code." 21 - 22 - This produces **crap tests**: 23 - 24 - - Tests written in bulk test _imagined_ behavior, not _actual_ behavior 25 - - You end up testing the _shape_ of things (data structures, function signatures) rather than user-facing behavior 26 - - Tests become insensitive to real changes - they pass when behavior breaks, fail when behavior is fine 27 - - You outrun your headlights, committing to test structure before understanding the implementation 28 - 29 - **Correct approach**: Vertical slices via tracer bullets. One test → one implementation → repeat. Each test responds to what you learned from the previous cycle. Because you just wrote the code, you know exactly what behavior matters and how to verify it. 30 - 31 - ``` 32 - WRONG (horizontal): 33 - RED: test1, test2, test3, test4, test5 34 - GREEN: impl1, impl2, impl3, impl4, impl5 35 - 36 - RIGHT (vertical): 37 - RED→GREEN: test1→impl1 38 - RED→GREEN: test2→impl2 39 - RED→GREEN: test3→impl3 40 - ... 41 - ``` 42 - 43 - ## Workflow 44 - 45 - ### 1. Planning 46 - 47 - When exploring the codebase, use the project's domain glossary so that test names and interface vocabulary match the project's language, and respect ADRs in the area you're touching. 48 - 49 - Before writing any code: 50 - 51 - - [ ] Confirm with user what interface changes are needed 52 - - [ ] Confirm with user which behaviors to test (prioritize) 53 - - [ ] Identify opportunities for [deep modules](deep-modules.md) (small interface, deep implementation) 54 - - [ ] Design interfaces for [testability](interface-design.md) 55 - - [ ] List the behaviors to test (not implementation steps) 56 - - [ ] Get user approval on the plan 57 - 58 - Ask: "What should the public interface look like? Which behaviors are most important to test?" 59 - 60 - **You can't test everything.** Confirm with the user exactly which behaviors matter most. Focus testing effort on critical paths and complex logic, not every possible edge case. 61 - 62 - ### 2. Tracer Bullet 63 - 64 - Write ONE test that confirms ONE thing about the system: 65 - 66 - ``` 67 - RED: Write test for first behavior → test fails 68 - GREEN: Write minimal code to pass → test passes 69 - ``` 70 - 71 - This is your tracer bullet - proves the path works end-to-end. 72 - 73 - ### 3. Incremental Loop 74 - 75 - For each remaining behavior: 76 - 77 - ``` 78 - RED: Write next test → fails 79 - GREEN: Minimal code to pass → passes 80 - ``` 81 - 82 - Rules: 83 - 84 - - One test at a time 85 - - Only enough code to pass current test 86 - - Don't anticipate future tests 87 - - Keep tests focused on observable behavior 88 - 89 - ### 4. Refactor 90 - 91 - After all tests pass, look for [refactor candidates](refactoring.md): 92 - 93 - - [ ] Extract duplication 94 - - [ ] Deepen modules (move complexity behind simple interfaces) 95 - - [ ] Apply SOLID principles where natural 96 - - [ ] Consider what new code reveals about existing code 97 - - [ ] Run tests after each refactor step 98 - 99 - **Never refactor while RED.** Get to GREEN first. 100 - 101 - ## Prune pass — earn their keep 102 - 103 - The workflow above is silent on what to do with the tests that _already exist_ after a slice wraps up. Two failure modes accumulate over a project's lifetime: 104 - 105 - - **Insensitive tests** — they pass on broken code. They test a data structure shape or a private method, not user-facing behaviour. False confidence: "tests pass, so it works." 106 - - **Brittle tests** — they fail on harmless refactors. They assert on internal selectors (`page.locator('button.suede-button')`) or mock-heavy internal collaborator contracts. The team stops trusting them, then stops running them, then deletes the whole suite. 107 - 108 - ### When to run a prune pass 109 - 110 - - At the **end of any TDD cycle where REFACTOR changed the public interface** (a rename, a parameter shape, a contract clarification). The old tests may now test behaviour the new interface no longer has. 111 - - At the **end of a release branch**, before the merge. The "what does this branch actually assert?" question is worth asking once per shipped slice. 112 - - At the **start of a triage/QA cycle** when a flaky test is reported. Flaky = either insensitive or brittle; the prune pass diagnoses which. 113 - 114 - ### The pass 115 - 116 - For each test file in the slice, walk the [tests.md](tests.md) "Red flags" checklist: 117 - 118 - - Mocking internal collaborators? → Prune (delete or replace with an integration test at a higher seam). 119 - - Testing private methods? → Delete. Private methods are an implementation detail. 120 - - Asserting on call counts/order? → Prune unless the call order _is_ the contract (rare). 121 - - Test breaks when refactoring without behaviour change? → Prune. 122 - - Test name describes HOW not WHAT? → Rename or prune. 123 - - Verifying through external means instead of interface? → Refactor to use the public interface. 124 - 125 - Tests that survive the checklist earn their keep. Tests that don't get deleted in the same commit that flagged them — leaving a "we should clean these up" follow-up is how test debt accumulates. 126 - 127 - ### The output 128 - 129 - A prune pass is a _commit_, not a task. The commit message starts with `chore(tests): prune` and lists what was deleted and why. The decision graph gets one action node for the pass and one outcome node per category of deletion (insensitive-deleted, brittle-deleted, renamed, kept). 130 - 131 - ## Storybook discipline (UI forks) 132 - 133 - Storybook is the suede default for UI forks. A UI primitive change is incomplete without a story update in the same commit. This is the **Authoring Boundaries Storybook-discipline** rule, restated as a workflow: 134 - 135 - - **Code change to `src/lib/components/ui/<X>.svelte`** → matching `src/stories/<X>.stories.svelte` (or equivalent) updated in the same commit, covering the new state, prop, or visual branch. 136 - - **New visual state** (e.g. "Disabled" was `aria-disabled` only, now there's a `disabled` prop) → new `<Story>` block. 137 - - **Removed visual state** (e.g. a deprecated variant) → corresponding `<Story>` block removed. 138 - - **Behavioural change** (e.g. the button now calls `preventDefault` on form submit) → story updated to demonstrate or assert on the new behaviour, even if no new visual state is added. 139 - 140 - Stories are the agent-owned form of the human-owned visual contract. The author of a Storybook story is the _consumer_ of the component, not the implementer. A primitive without a matching story is invisible to QA and to the next contributor. 141 - 142 - A fork that rips Storybook (e.g. a backend MCP, a content site using MDX for component docs) records the override in the kickoff follow-up PR description (or an ADR if the project uses one) and the agent rewrites AGENTS.md / this skill as part of that override. The discipline is unconditional for any fork that kept the default. 143 - 144 - ## Checklist Per Cycle 145 - 146 - ``` 147 - [ ] Test describes behavior, not implementation 148 - [ ] Test uses public interface only 149 - [ ] Test would survive internal refactor 150 - [ ] Code is minimal for this test 151 - [ ] No speculative features added 152 - ```
-33
.opencode/skills/tdd/deep-modules.md
··· 1 - # Deep Modules 2 - 3 - From "A Philosophy of Software Design": 4 - 5 - **Deep module** = small interface + lots of implementation 6 - 7 - ``` 8 - ┌─────────────────────┐ 9 - │ Small Interface │ ← Few methods, simple params 10 - ├─────────────────────┤ 11 - │ │ 12 - │ │ 13 - │ Deep Implementation│ ← Complex logic hidden 14 - │ │ 15 - │ │ 16 - └─────────────────────┘ 17 - ``` 18 - 19 - **Shallow module** = large interface + little implementation (avoid) 20 - 21 - ``` 22 - ┌─────────────────────────────────┐ 23 - │ Large Interface │ ← Many methods, complex params 24 - ├─────────────────────────────────┤ 25 - │ Thin Implementation │ ← Just passes through 26 - └─────────────────────────────────┘ 27 - ``` 28 - 29 - When designing interfaces, ask: 30 - 31 - - Can I reduce the number of methods? 32 - - Can I simplify the parameters? 33 - - Can I hide more complexity inside?
-31
.opencode/skills/tdd/interface-design.md
··· 1 - # Interface Design for Testability 2 - 3 - Good interfaces make testing natural: 4 - 5 - 1. **Accept dependencies, don't create them** 6 - 7 - ```typescript 8 - // Testable 9 - function processOrder(order, paymentGateway) {} 10 - 11 - // Hard to test 12 - function processOrder(order) { 13 - const gateway = new StripeGateway(); 14 - } 15 - ``` 16 - 17 - 2. **Return results, don't produce side effects** 18 - 19 - ```typescript 20 - // Testable 21 - function calculateDiscount(cart): Discount {} 22 - 23 - // Hard to test 24 - function applyDiscount(cart): void { 25 - cart.total -= discount; 26 - } 27 - ``` 28 - 29 - 3. **Small surface area** 30 - - Fewer methods = fewer tests needed 31 - - Fewer params = simpler test setup
-59
.opencode/skills/tdd/mocking.md
··· 1 - # When to Mock 2 - 3 - Mock at **system boundaries** only: 4 - 5 - - External APIs (payment, email, etc.) 6 - - Databases (sometimes - prefer test DB) 7 - - Time/randomness 8 - - File system (sometimes) 9 - 10 - Don't mock: 11 - 12 - - Your own classes/modules 13 - - Internal collaborators 14 - - Anything you control 15 - 16 - ## Designing for Mockability 17 - 18 - At system boundaries, design interfaces that are easy to mock: 19 - 20 - **1. Use dependency injection** 21 - 22 - Pass external dependencies in rather than creating them internally: 23 - 24 - ```typescript 25 - // Easy to mock 26 - function processPayment(order, paymentClient) { 27 - return paymentClient.charge(order.total); 28 - } 29 - 30 - // Hard to mock 31 - function processPayment(order) { 32 - const client = new StripeClient(process.env.STRIPE_KEY); 33 - return client.charge(order.total); 34 - } 35 - ``` 36 - 37 - **2. Prefer SDK-style interfaces over generic fetchers** 38 - 39 - Create specific functions for each external operation instead of one generic function with conditional logic: 40 - 41 - ```typescript 42 - // GOOD: Each function is independently mockable 43 - const api = { 44 - getUser: (id) => fetch(`/users/${id}`), 45 - getOrders: (userId) => fetch(`/users/${userId}/orders`), 46 - createOrder: (data) => fetch('/orders', { method: 'POST', body: data }), 47 - }; 48 - 49 - // BAD: Mocking requires conditional logic inside the mock 50 - const api = { 51 - fetch: (endpoint, options) => fetch(endpoint, options), 52 - }; 53 - ``` 54 - 55 - The SDK approach means: 56 - - Each mock returns one specific shape 57 - - No conditional logic in test setup 58 - - Easier to see which endpoints a test exercises 59 - - Type safety per endpoint
-10
.opencode/skills/tdd/refactoring.md
··· 1 - # Refactor Candidates 2 - 3 - After TDD cycle, look for: 4 - 5 - - **Duplication** → Extract function/class 6 - - **Long methods** → Break into private helpers (keep tests on public interface) 7 - - **Shallow modules** → Combine or deepen 8 - - **Feature envy** → Move logic to where data lives 9 - - **Primitive obsession** → Introduce value objects 10 - - **Existing code** the new code reveals as problematic
-61
.opencode/skills/tdd/tests.md
··· 1 - # Good and Bad Tests 2 - 3 - ## Good Tests 4 - 5 - **Integration-style**: Test through real interfaces, not mocks of internal parts. 6 - 7 - ```typescript 8 - // GOOD: Tests observable behavior 9 - test("user can checkout with valid cart", async () => { 10 - const cart = createCart(); 11 - cart.add(product); 12 - const result = await checkout(cart, paymentMethod); 13 - expect(result.status).toBe("confirmed"); 14 - }); 15 - ``` 16 - 17 - Characteristics: 18 - 19 - - Tests behavior users/callers care about 20 - - Uses public API only 21 - - Survives internal refactors 22 - - Describes WHAT, not HOW 23 - - One logical assertion per test 24 - 25 - ## Bad Tests 26 - 27 - **Implementation-detail tests**: Coupled to internal structure. 28 - 29 - ```typescript 30 - // BAD: Tests implementation details 31 - test("checkout calls paymentService.process", async () => { 32 - const mockPayment = jest.mock(paymentService); 33 - await checkout(cart, payment); 34 - expect(mockPayment.process).toHaveBeenCalledWith(cart.total); 35 - }); 36 - ``` 37 - 38 - Red flags: 39 - 40 - - Mocking internal collaborators 41 - - Testing private methods 42 - - Asserting on call counts/order 43 - - Test breaks when refactoring without behavior change 44 - - Test name describes HOW not WHAT 45 - - Verifying through external means instead of interface 46 - 47 - ```typescript 48 - // BAD: Bypasses interface to verify 49 - test("createUser saves to database", async () => { 50 - await createUser({ name: "Alice" }); 51 - const row = await db.query("SELECT * FROM users WHERE name = ?", ["Alice"]); 52 - expect(row).toBeDefined(); 53 - }); 54 - 55 - // GOOD: Verifies through interface 56 - test("createUser makes user retrievable", async () => { 57 - const user = await createUser({ name: "Alice" }); 58 - const retrieved = await getUser(user.id); 59 - expect(retrieved.name).toBe("Alice"); 60 - }); 61 - ```
.pi/skills/archaeology/SKILL.md .pi/prompts/archaeology.md
.pi/skills/narratives/SKILL.md .pi/prompts/narratives.md
.pi/skills/project-plan/SKILL.md

This is a binary file and will not be displayed.

.pi/skills/project-plan/to-issues/SKILL.md .pi/skills/project-plan/reference/issues.md
.pi/skills/project-plan/to-prd/SKILL.md .pi/skills/project-plan/reference/prd.md
.pi/skills/project-plan/triage/AGENT-BRIEF.md .pi/skills/project-plan/reference/agent-brief.md
.pi/skills/project-plan/triage/OUT-OF-SCOPE.md .pi/skills/project-plan/reference/out-of-scope.md
.pi/skills/project-plan/triage/SKILL.md .pi/skills/project-plan/reference/triage.md
.pi/skills/pulse/SKILL.md .pi/prompts/pulse.md
-68
.pi/skills/request-refactor-plan/SKILL.md
··· 1 - --- 2 - name: request-refactor-plan 3 - description: Create a detailed refactor plan with tiny commits via user interview, then file it as a GitHub issue. Use when user wants to plan a refactor, create a refactoring RFC, or break a refactor into safe incremental steps. 4 - --- 5 - 6 - This skill will be invoked when the user wants to create a refactor request. You should go through the steps below. You may skip steps if you don't consider them necessary. 7 - 8 - 1. Ask the user for a long, detailed description of the problem they want to solve and any potential ideas for solutions. 9 - 10 - 2. Explore the repo to verify their assertions and understand the current state of the codebase. 11 - 12 - 3. Ask whether they have considered other options, and present other options to them. 13 - 14 - 4. Interview the user about the implementation. Be extremely detailed and thorough. 15 - 16 - 5. Hammer out the exact scope of the implementation. Work out what you plan to change and what you plan not to change. 17 - 18 - 6. Look in the codebase to check for test coverage of this area of the codebase. If there is insufficient test coverage, ask the user what their plans for testing are. 19 - 20 - 7. Break the implementation into a plan of tiny commits. Remember Martin Fowler's advice to "make each refactoring step as small as possible, so that you can always see the program working." 21 - 22 - 8. Create a GitHub issue with the refactor plan. Use the following template for the issue description: 23 - 24 - <refactor-plan-template> 25 - 26 - ## Problem Statement 27 - 28 - The problem that the developer is facing, from the developer's perspective. 29 - 30 - ## Solution 31 - 32 - The solution to the problem, from the developer's perspective. 33 - 34 - ## Commits 35 - 36 - A LONG, detailed implementation plan. Write the plan in plain English, breaking down the implementation into the tiniest commits possible. Each commit should leave the codebase in a working state. 37 - 38 - ## Decision Document 39 - 40 - A list of implementation decisions that were made. This can include: 41 - 42 - - The modules that will be built/modified 43 - - The interfaces of those modules that will be modified 44 - - Technical clarifications from the developer 45 - - Architectural decisions 46 - - Schema changes 47 - - API contracts 48 - - Specific interactions 49 - 50 - Do NOT include specific file paths or code snippets. They may end up being outdated very quickly. 51 - 52 - ## Testing Decisions 53 - 54 - A list of testing decisions that were made. Include: 55 - 56 - - A description of what makes a good test (only test external behavior, not implementation details) 57 - - Which modules will be tested 58 - - Prior art for the tests (i.e. similar types of tests in the codebase) 59 - 60 - ## Out of Scope 61 - 62 - A description of the things that are out of scope for this refactor. 63 - 64 - ## Further Notes (optional) 65 - 66 - Any further notes about the refactor. 67 - 68 - </refactor-plan-template>
-4
opencode.json
··· 1 - { 2 - "$schema": "https://opencode.ai/config.json", 3 - "instructions": ["AGENTS.md"] 4 - }