a dotfile but it's really big
0
fork

Configure Feed

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

opencode/skills: more skill writing

karitham fdde0d1f 1b2464c0

+248 -59
+97 -28
modules/opencode/skills/code-writing/SKILL.md
··· 1 1 --- 2 2 name: code-writing 3 - description: Enforces clean coding conventions for any implementation task. Covers guard clauses and early returns, happy-path left-alignment, pure functions separated from I/O, hexagonal architecture, error handling without panics, input validation at boundaries, parameterized queries, no hardcoded secrets, removing dead code, matching existing project patterns, and keeping functions small and single-responsibility. Use when writing new code, refactoring, fixing bugs, or reviewing code for quality. 3 + description: > 4 + Enforces clean coding conventions for any implementation task. Covers guard 5 + clauses, extract method, pure functions, immutability, define errors out of 6 + existence, and interface comments before implementation. Use when writing, 7 + editing, fixing, implementing, or reviewing code at the function or file level. 8 + Do NOT use for API design, module boundaries, or service structure — use 9 + software-architecture instead. 4 10 --- 5 11 6 12 ## Guard Clauses ··· 39 45 - MUST return on edge cases before the main work 40 46 - Good code reads top-to-bottom without jumping between branches 41 47 48 + ## Extract Method 49 + 50 + Fowler, _Refactoring_: "Extract Method" when a fragment of code needs a name to 51 + explain its purpose, or when the fragment is too long to read at a glance. 52 + 53 + - If a function does two things, split it. 54 + - If a block of code needs a comment to explain what it does, extract it into a 55 + function whose name replaces the comment. 56 + - Small functions are easier to test, reuse, and reason about. 57 + 58 + ## Consolidate Conditional Expression 59 + 60 + Fowler, _Refactoring_: "Consolidate Conditional Expression" 61 + 62 + When a series of conditionals all produce the same result, combine them into a 63 + single conditional with a well-named function. The function name documents the 64 + intent. 65 + 66 + BAD: 67 + 68 + if employee.seniority < 2 { return 0 } 69 + if employee.monthsDisabled > 12 { return 0 } 70 + if !employee.isPartTime { return 0 } 71 + 72 + GOOD: 73 + 74 + if notEligibleForBonus(employee) { return 0 } 75 + 76 + ## Introduce Parameter Object 77 + 78 + Fowler, _Refactoring_: "Introduce Parameter Object" 79 + 80 + When a function has too many parameters, or a group of parameters naturally 81 + belong together, replace them with a single object. This reduces parameter count 82 + and makes the grouping explicit. 83 + 42 84 ## Pure Functions Preferred 43 85 44 86 Evans, _Domain-Driven Design_: Domain logic should not depend on infrastructure. ··· 46 88 - SHOULD separate I/O from computation 47 89 - SHOULD push effects to function boundaries 48 90 - MUST NOT mix database calls, HTTP requests, or file I/O with business logic 49 - in the same function, because this makes the logic harder to test and reason 50 - about in isolation. 91 + in the same function 92 + 93 + ## Immutability 94 + 95 + Prefer immutable data. When a value does not change after construction, the 96 + reader can trust it forever. Mutable state forces the reader to track every 97 + assignment. 98 + 99 + - SHOULD use const/readonly/final where possible 100 + - SHOULD return new values rather than modifying inputs 101 + - MUST NOT mutate shared state without explicit synchronization 102 + 103 + ## Variable Scope Minimization 104 + 105 + Ousterhout, _A Philosophy of Software Design_: Reduce the scope of every 106 + variable to the smallest possible range. The fewer variables visible at any 107 + point, the less the reader must track. 108 + 109 + - Declare variables as close to first use as possible 110 + - Prefer narrow scope over reuse across unrelated operations 111 + - A variable used in one block MUST NOT leak to the enclosing function 51 112 52 - ## I/O at Edges 113 + ## Naming as Abstraction 53 114 54 - Cockburn, Hexagonal Architecture: Core logic in the center, adapters at the edges. 115 + Ousterhout, _A Philosophy of Software Design_: A good name is an abstraction. If 116 + a name eliminates the need for a comment, it has done its job. 117 + 118 + - Names MUST describe what, not how 119 + - If a name needs a comment to explain it, the name is wrong 120 + - Single-letter names are acceptable only for loop indices and math conventions 121 + 122 + ## Define Errors Out of Existence 123 + 124 + Ousterhout, _A Philosophy of Software Design_: The best way to handle an 125 + exceptional condition is to redefine the problem so the condition cannot occur. 55 126 56 - - **Edge layer**: handlers, CLI, HTTP - performs I/O, calls core 57 - - **Core layer**: pure functions, business rules - no I/O, testable in isolation 127 + - SHOULD design APIs where error cases are unrepresentable 128 + - MUST NOT propagate errors that could be eliminated by better design 129 + - SHOULD use sum types / enums instead of multiple dependent booleans 58 130 59 - ## Read Before Write 131 + ## Interface Comments Before Implementation 60 132 61 - MUST read a file before editing it. Blind edits create duplicates, miss context, 62 - and break subtle invariants. 133 + Ousterhout, _A Philosophy of Software Design_: Interface comments describe the 134 + abstraction — what it does and how to use it — NOT how it is implemented. 135 + 136 + - MUST write interface comments before implementing the function 137 + - If a clean interface comment cannot be written, the design is likely wrong 138 + - Implementation comments MUST only appear when the code cannot express intent 63 139 64 140 ## Error Handling 65 141 66 - MUST NOT panic or crash on bad input, because panics bypass error handling and 67 - make recovery impossible. Return errors, validate boundaries, fail gracefully. 142 + MUST NOT panic or crash on bad input. Return errors, validate boundaries, fail 143 + gracefully. 68 144 69 145 ## Security 70 146 71 147 - MUST validate inputs at system boundaries 72 - - MUST use parameterized queries - MUST NOT use string interpolation for SQL, 73 - because this creates SQL injection vulnerabilities. 74 - - MUST NOT hardcode secrets or credentials, because secrets in source code are 75 - leaked through version control and code sharing. 148 + - MUST use parameterized queries 149 + - MUST NOT hardcode secrets or credentials 76 150 77 151 ## No Dead Code 78 152 79 - MUST remove or complete incomplete code. Half-written branches and unused imports 80 - create confusion because readers cannot distinguish between intentional partial 81 - implementations and abandoned work. 153 + MUST remove or complete incomplete code. Half-written branches and unused 154 + imports create confusion. 82 155 83 156 ## Familiar Code 84 157 85 - MUST write code that is familiar to other writers of the codebase. 158 + MUST match the project's existing style. Reuse existing patterns. MUST NOT 159 + introduce novelty without reason. 86 160 87 - - Reuse existing patterns 88 - - Match the project's style 89 - - MUST NOT introduce novelty without reason, because unfamiliar patterns slow 90 - down readers and increase maintenance burden. 161 + ## Read Before Write 91 162 92 - ## Small Functions 93 - 94 - MUST keep functions short and focused on a single responsibility. If a function 95 - does two things, split it. 163 + MUST read a file before editing it. Blind edits create duplicates and break 164 + subtle invariants.
+151 -31
modules/opencode/skills/software-architecture/SKILL.md
··· 1 1 --- 2 2 name: software-architecture 3 3 description: > 4 - Technical protocol for designing and refactoring non-trivial software. Focuses on the Impure-Pure-Impure sandwich, lifting I/O, and resource-aware orchestration. Use when the user asks to "design a component," "structure code," "refactor a service," or "handle side effects." Keywords: functional core, imperative shell, dependency rejection, deep modules, short-circuiting. 4 + Technical protocol for designing and structuring non-trivial software. Covers 5 + the impure-pure-impure sandwich, bounded contexts, event-driven patterns, 6 + dataflow modeling, and dependency rejection. Use when designing APIs, adding 7 + endpoints, defining module boundaries, structuring services, handling side 8 + effects, or deciding what should be public vs internal. Keywords: functional 9 + core, imperative shell, bounded context, event sourcing, CQRS, data pipeline, 10 + idempotency, short-circuiting. Do NOT use for function-level code style or 11 + refactoring within a single file — use code-writing instead. 5 12 --- 6 13 7 14 # Software Architecture Protocol 8 15 9 - This skill provides a systematic framework for managing complexity and side effects in software systems. 16 + This skill provides a systematic framework for managing complexity and side 17 + effects in software systems. 10 18 11 - ## 1. The "Impure-Pure-Impure" Sandwich Pattern 19 + ## 0. Continuous Improvement 12 20 13 - All non-trivial operations MUST follow this sequential workflow to isolate side effects from business logic. 21 + The goal of software architecture is to make the code more resilient to change 22 + over time. You MUST suggest architectural improvements even when you cannot 23 + implement them directly (e.g., out of scope for the current task, too large a 24 + change, or outside the current file). 25 + 26 + - Flag architectural debt when you see it, even if you are only fixing a bug. 27 + - Suggest the ideal structure alongside the pragmatic fix. 28 + - Small improvements compound: a single well-placed extraction or boundary is 29 + better than waiting for a perfect refactor. 30 + 31 + ## 1. Design Protocol 32 + 33 + When approaching any architecture decision, follow this sequence: 34 + 35 + 1. **Identify the boundary.** What is public vs internal? Who calls this? What 36 + does it depend on? 37 + 2. **Gather constraints.** Latency requirements, consistency needs, failure 38 + modes, team ownership. 39 + 3. **Propose the simplest structure.** Start with a deep module: simple 40 + interface, hidden complexity. 41 + 4. **Check against patterns.** Does the impure-pure-impure sandwich apply? Are 42 + bounded contexts clear? Is dataflow linear? 43 + 5. **Flag what you cannot fix.** If the current structure violates these 44 + principles, suggest the ideal alongside the pragmatic path. 45 + 46 + ## 2. The Impure-Pure-Impure Sandwich 47 + 48 + All non-trivial operations MUST follow this sequential workflow to isolate side 49 + effects from business logic. 14 50 15 51 ### Workflow 16 52 17 - 1. **Gather (Impure Boundary):** Fetch all external state required for the decision. 18 - - _Examples:_ DB queries, API calls, reading system time, generating UUIDs. 19 - 2. **Process (Functional Core):** Pass the gathered data into a pure function. 20 - - _Constraint:_ This function MUST be deterministic. It MUST NOT perform I/O or access global state. It MUST return data or a "Result" struct. 21 - 3. **Commit (Impure Boundary):** Persist the output of the Functional Core. 22 - - _Examples:_ DB writes, sending HTTP responses, logging. 53 + 1. **Gather (Impure Boundary):** Fetch all external state required for the 54 + decision. Examples: DB queries, API calls, reading system time, generating 55 + UUIDs. 56 + 2. **Process (Functional Core):** Pass the gathered data into a pure function. 57 + This function MUST be deterministic. It MUST NOT perform I/O or access global 58 + state. It MUST return data or a Result struct. 59 + 3. **Commit (Impure Boundary):** Persist the output of the Functional Core. 60 + Examples: DB writes, sending HTTP responses, logging. 23 61 24 - ## 2. Resource-Aware Orchestration 62 + ## 3. Bounded Contexts 25 63 26 - Operations MUST be ordered to minimize the surface area of high-latency or locking operations. 64 + Evans, _Domain-Driven Design_: A bounded context is a boundary within which a 65 + particular model is defined and applicable. 27 66 28 - - **Short-Circuiting:** Cheap local checks (logic/time guards) MUST occur before expensive remote checks (Network/API). 29 - - **Lock Minimization:** Database transactions (`WithTx`) SHOULD only wrap the final "Commit" phase. 30 - - **Dependency Rejection:** Business logic SHOULD accept raw data structures (e.g., `[]int`) rather than behavioral interfaces (e.g., `UserStore`) to avoid unnecessary "Interface Soup." 67 + - Each service or module MUST own its model. Shared models across boundaries 68 + create coupling. 69 + - The same real-world concept (e.g., "Customer") can have different models in 70 + different contexts. This is correct, not duplication. 71 + - Translation between contexts happens at the boundary, not in the core. 31 72 32 - ## 3. Structural Standards 73 + ## 4. Dataflow and Pipelines 33 74 34 - ### Module Depth (Ousterhout's Principle) 75 + Kleppmann, _Designing Data-Intensive Applications_: Think of a system as a 76 + pipeline of data transformations, not as a collection of services calling each 77 + other. 35 78 36 - - Modules MUST be "Deep": simple interfaces hiding significant internal complexity. 37 - - If an interface is as complex as its implementation, the abstraction SHOULD be removed (Compression-Oriented Design). 79 + - Each step transforms data and passes it to the next. The pipeline is the 80 + architecture. 81 + - Idempotent operations allow safe retries and reprocessing. Design every 82 + write operation to be idempotent where possible. 83 + - Derived data (caches, indexes, materialized views) should be reproducible 84 + from the source of truth. 38 85 39 - ### State Integrity (Parse, Don't Validate) 86 + ## 5. Event-Driven Patterns 40 87 41 - - Invariants MUST be enforced via the type system (e.g., `NewUserID(string)` vs a raw `string`). 42 - - Invalid states SHOULD be unrepresentable. Use Enums/Sum types instead of multiple dependent Booleans. 88 + Kleppmann, _DDIA_ / Newman, _Building Microservices_: Events decouple producers 89 + from consumers in time and space. 43 90 44 - ## 4. Feedback Loop: Refactoring Pattern 91 + - Event sourcing: persist state changes as a sequence of immutable events. The 92 + current state is a projection of the event log. 93 + - CQRS: separate read and write models when they have different scaling or 94 + consistency requirements. 95 + - Consumers MUST NOT assume event ordering unless the system guarantees it. 96 + - Events describe what happened, not what to do. Commands describe what to do. 97 + 98 + ## 6. Resource-Aware Orchestration 99 + 100 + Operations MUST be ordered to minimize the surface area of high-latency or 101 + locking operations. 102 + 103 + - **Short-Circuiting:** Cheap local checks MUST occur before expensive remote 104 + checks. 105 + - **Lock Minimization:** Database transactions SHOULD only wrap the final 106 + commit phase. 107 + - **Dependency Rejection:** Business logic SHOULD accept raw data structures 108 + rather than behavioral interfaces to avoid unnecessary coupling. 109 + 110 + ## 7. Structural Standards 111 + 112 + ### Information Hiding (Ousterhout) 113 + 114 + The primary purpose of a module is to hide complexity. Design modules so that 115 + most of their knowledge is internal and invisible to callers. When information 116 + leaks across boundaries, every caller becomes coupled to implementation details. 117 + 118 + ### Deep Modules (Ousterhout) 119 + 120 + Modules MUST be deep: simple interfaces hiding significant internal complexity. 121 + If an interface is as complex as its implementation, the abstraction SHOULD be 122 + removed. 123 + 124 + ### State Integrity 125 + 126 + Invariants MUST be enforced via the type system. Invalid states SHOULD be 127 + unrepresentable. 128 + 129 + ### Compression-Oriented Design 130 + 131 + Do not abstract prematurely. Extract a shared abstraction only after the second 132 + use case appears and the commonality is clear. 133 + 134 + ### Database Per Service 135 + 136 + Newman, _Building Microservices_: Each service owns its data. No other service 137 + MUST access another service's database directly. Data sharing happens through 138 + APIs or events. 139 + 140 + ### API Backward Compatibility 141 + 142 + Evolve APIs without breaking consumers. Additive changes only (new optional 143 + fields, new endpoints). Deprecation requires a migration window, not an 144 + immediate breaking change. 145 + 146 + ### Resilience Patterns 147 + 148 + Kleppmann, _DDIA_: Services fail. The system must survive. 149 + 150 + - Circuit breaker: stop calling a failing service after repeated failures. 151 + - Retry with backoff: transient failures are normal, but retry storms are not. 152 + - Bulkhead isolation: isolate components so failure in one does not cascade. 153 + 154 + ## 8. Feedback Loop: Refactoring Pattern 45 155 46 156 When refactoring existing code to this standard: 47 157 48 - 1. **Identify Side Effects:** Find all hidden I/O (e.g., `time.Now()`, `db.Get`). 49 - 2. **Lift I/O:** Move those calls to the caller or the entry point of the function. 50 - 3. **Purify:** Convert the remaining logic into a pure function that accepts the lifted data as parameters. 51 - 4. **Verify:** The core logic MUST be unit-testable without a mocking framework. 158 + 1. **Identify Side Effects:** Find all hidden I/O (e.g., `time.Now()`, 159 + `db.Get`). 160 + 2. **Lift I/O:** Move those calls to the caller or the entry point of the 161 + function. 162 + 3. **Purify:** Convert the remaining logic into a pure function that accepts 163 + the lifted data as parameters. 164 + 4. **Verify:** The core logic MUST be unit-testable without a mocking framework. 52 165 53 166 --- 54 167 55 168 ## Validation Checklist 56 169 57 170 - [ ] **Sandwich:** Is there a clear line where I/O ends and logic begins? 58 - - [ ] **Purity:** Does any business logic function take a `Context` or an interface that performs I/O? (It shouldn't). 59 - - [ ] **Ordering:** Are network calls happening inside a database transaction? (They shouldn't). 60 - - [ ] **Guard Clauses:** Is the code calling an external API before checking simple local requirements? 61 - - [ ] **Types:** Are we using primitives where a domain-specific type could prevent a bug? 171 + - [ ] **Purity:** Does any business logic function take a Context or an 172 + interface that performs I/O? (It shouldn't.) 173 + - [ ] **Ordering:** Are network calls happening inside a database transaction? 174 + (They shouldn't.) 175 + - [ ] **Boundaries:** Does each module own its model, or is there a shared 176 + model leaking across contexts? 177 + - [ ] **Idempotency:** Can writes be safely retried? 178 + - [ ] **Depth:** Is the module deep, or is it a pass-through adding no 179 + abstraction? 180 + - [ ] **Types:** Are we using primitives where a domain-specific type could 181 + prevent a bug? 62 182 - [ ] **Mocks:** Can this logic be tested with simple value assertions?