pstack
FetchUpstream v0.2.0
Publisher description
From the marketplace listing
An unofficial ChatGPT port of pstack, providing rigorous reusable workflows for engineering, reasoning, review, and writing.
Language: English · Automatically detected from descriptions.
Publisher keywords
Search terms declared by the publisher.
Files & skills
File archives
Skill instructions
architect9.44 KB
--- name: architect description: "Design types, interfaces, module boundaries, data flow, and ownership before implementation. Use for 'architect this', 'design this', API or domain modeling, refactors, new subsystems, or non-trivial changes where choosing the wrong shape would make the implementation harder." --- # Architect Design the shape before writing the implementation. Work out the types, ownership, interfaces, module boundaries, and data flow first. The design should make the implementation more obvious, not move complexity into vague abstractions. Use this skill for: * new subsystems * non-trivial features * API design * domain modeling * refactors that change ownership * service boundaries * persistence boundaries * event-driven flows * changes where several reasonable designs exist * code that keeps fighting its current architecture For a small mechanical change with an obvious shape, skip this skill. ## Understand the existing system first Do not design around a codebase you have not understood. Use the `how` skill on the parts the change touches. Work out: * what owns the current behavior * where state lives * what the runtime flow is * which boundaries already exist * what callers depend on * which invariants the current code enforces If the new design changes an existing boundary, ownership rule, or strange-looking constraint, use `why` before removing it. The current design may be accidental. It may also encode a constraint that is invisible in the code. Treat verified history as a design input. For greenfield work, skip the existing-system investigation and start from the requirements. ## Start with usage Design from the caller inward. Write the important usage before defining the internals. For example: ```text session = parking.open_session(entry) payment = session.pay(method) decision = session.request_exit(exit_event) ``` The exact syntax does not matter yet. The point is to see what the caller needs to know. If normal usage requires the caller to understand several internal steps, internal state transitions, or storage details, the design is probably exposing too much. Ask: * What should the caller provide? * What should the caller receive? * What should stay hidden? * Which invalid operations should be impossible or difficult to express? Use the answers to shape the API. ## Model the domain Name the real concepts in the problem. Do not create types just because the existing code has classes with those names. Look for: * entities with identity * values with rules * state transitions * commands * events * policies * external systems * ownership boundaries Give each rule one clear owner. If two modules both decide whether the same operation is valid, ownership is unclear. Prefer types that prevent invalid states instead of objects full of optional fields plus comments explaining which combinations are legal. Use the `principle-model-the-domain` and `principle-type-system-discipline` skills when they apply. ## Decide where the boundaries are A useful module owns something. It may own: * a business rule * a state transition * persistence * communication with an external system * a protocol * a set of invariants A module that only forwards arguments to another module probably does not justify the extra layer. Keep framework, transport, and persistence details at their boundaries when possible. The domain should not need to know that a request arrived through HTTP or that an entity happens to be stored in SQLite unless those facts are part of the domain. Use `principle-boundary-discipline` when deciding where parsing, validation, and external representations stop. ## Sketch the design For a small change, sketch: * the important types * their fields * function or method signatures * ownership * the main data flow For a larger change, also sketch: * module boundaries * dependencies between modules * persistence ownership * external integrations * events or messages * failure paths Use pseudocode or incomplete declarations. Do not fill in implementation details yet. A sketch should expose the decisions without burying them under working code. ## Design more than one shape when the decision matters For a meaningful architectural choice, produce at least two structurally different designs before choosing one. Changing a method name does not count as another design. The alternatives should disagree about something real, such as: * which component owns state * synchronous calls versus events * one service versus separate responsibilities * where validation occurs * whether a concept is stored or derived * whether callers coordinate several operations or call one higher-level operation Do not create alternatives just to reach a quota. Use this when there is a real design choice. Apply `principle-exhaust-the-design-space`. ## Compare the designs Judge each design by what the caller must understand and what the system can enforce. Prefer the design that: * gives each rule one owner * hides implementation details * keeps dependencies pointed toward the domain * makes invalid states harder to represent * keeps common operations short * isolates external systems * makes important behavior testable * handles concurrency without casual shared mutation * has fewer special cases Do not choose the design with the most layers. Do not choose the most abstract design. A good abstraction removes knowledge from its callers. If an abstraction adds concepts without hiding anything, remove it. Apply `principle-subtract-before-you-add`. ## Check the design against real scenarios Walk real cases through the proposed API. Use the common path first. Then test the cases that are likely to expose a bad shape. Examples include: * duplicate requests * retries * partial failure * stale state * concurrent operations * missing data * an operation arriving in the wrong order * an external dependency being unavailable * a new domain variant Do not solve every hypothetical edge case. Use cases that come from the requirements, current code, bugs, or realistic behavior of the system. If an ordinary scenario needs a workaround, the design needs another pass. ## Check the dependency direction For each module, ask what it knows about. Domain code should usually know domain concepts. Adapters may know the domain and an external system. The domain should not depend on an adapter merely because the adapter currently provides the data. Look for dependencies that force business logic to know about: * HTTP * database rows * JSON payloads * UI components * vendor SDKs * queue-specific message formats Move those translations to the boundary when possible. ## Write the decision down For the chosen design, show: ### Usage How the main caller uses it. ### Types The important domain types and states. ### Interfaces The functions or methods that form the contract. ### Ownership Which component owns each important rule or state transition. ### Module map Where the pieces live and which direction dependencies point. ### Flow What happens through the system for the main case. ### Alternatives The meaningful designs considered and why they lost. ### Risks The assumptions most likely to prove the design wrong. Keep this proportional to the task. A three-function refactor does not need an architecture document. ## Separate design from implementation If the user asked only for architecture, stop at the design. If they also asked for implementation, treat the chosen sketch as the starting contract. Do not silently change the architecture halfway through coding because a local implementation choice is easier. When implementation needs something the sketch did not anticipate, treat that as evidence. Ask what changed: * Was a requirement missed? * Was the domain model wrong? * Is ownership in the wrong place? * Is the implementation leaking a detail that should stay hidden? Small corrections are normal. Repeated corrections of the same kind are not. ## Know when to throw the design away Do not keep patching a bad design because work has already gone into it. Warning signs include: * the same workaround appearing in several places * unrelated edge cases all needing special branches * types needing repeated casts or escape hatches * optional fields that are actually required in certain hidden states * callers needing to know internal sequencing rules * several modules enforcing the same invariant * locks appearing because ownership was never made clear * repeated changes to the contract during implementation One awkward case does not prove the architecture is wrong. Look for a pattern. If the pattern is real, go back to the requirements and the lessons from implementation. Redesign as if those facts had been known from the start. Apply `principle-redesign-from-first-principles` and `principle-fix-root-causes`. Do not preserve the old shape merely because it already exists. ## Evidence When designing against an existing project, tie claims about the current system to source you inspected. Do not claim a constraint exists because the code looks like it might. Use `how` for current behavior. Use `why` for historical intent. Keep requirements, verified constraints, and your own design judgment distinct. ## Writing Apply `unslop` to the answer. Use concrete domain names. Do not hide a weak design behind architecture vocabulary. Show the caller's usage early. Then show the types and ownership that make that usage possible. The reply should contain the design itself, not a description of the design process.
blast-radius12.4 KB
--- name: blast-radius description: "Find what a code change could break outside the diff by tracing callers, contracts, shared data, external integrations, lifecycle behavior, and downstream consumers. Use for 'blast radius of X', 'what could this break', risky PR reviews, regression analysis, and checking whether a small change is actually isolated." --- # Blast radius Find what a change could break somewhere else. Do not stop at the diff or a list of direct callers. The useful part is finding effects that are separated from the changed code by data, timing, configuration, persistence, events, or another system. Use this skill for questions like: * "What could this break?" * "What's the blast radius of this PR?" * "Is this change actually isolated?" * "What else depends on this?" * "Could this cause a regression elsewhere?" * "Review this small diff. I don't trust it." Use `how` when you first need to understand the behavior being changed. Use `why` when an odd constraint or workaround may exist for a historical reason. ## Read the change first Inspect the actual change when it is available. That may be: * a PR * a diff * a commit * a patch * changed files supplied by the user * a proposed change described in the conversation Work out what behavior changes, not just which lines change. Identify: * symbols added * symbols changed * symbols deleted * types whose shape changed * persisted data that changed * messages or API contracts that changed * configuration that changed * lifecycle or ordering changes * behavior removed implicitly A ten-line diff can change a contract used by the whole system. A hundred-line internal refactor may change nothing outside one module. Judge the behavior, not the size. ## Find the safety fact Most changes depend on a small number of facts being true. Find them. For example: ```text This is safe only if every caller already handles a missing value. ``` Or: ```text This is safe only if this field is never read after the session closes. ``` Or: ```text This is safe only if no other service consumes this JSON field. ``` Or: ```text This is safe only if duplicate delivery is already handled downstream. ``` Write the safety fact plainly. If several independent facts must all hold, list them separately. Do not bury them inside a long risk report. ## Check the obvious references Find direct dependencies first. Look for: * callers * imports * implementations * interface consumers * subclasses * tests * configuration references * constructors * dependency injection wiring This establishes the immediate scope. It does not establish the whole blast radius. ## Look where symbol search stops Many regressions happen through relationships that do not share a symbol name. Trace the changed behavior through the system. Check for these when relevant. ### Data Follow data that crosses a boundary. Look for: * JSON properties * database columns * serialized types * cache keys * files * generated code * environment variables * configuration keys * message payloads * shared schemas A field rename can break code in another service that never imports the changed module. ### Persistence If stored data changes, check who reads old and new records. Ask: * Can old records still be loaded? * Can new code read data written by the previous version? * Can the previous version read data written by the new version? * Does a migration need to happen before deployment? * Are defaults different for existing rows? * Does a derived value now mean something different? Treat compatibility across deployments as part of the change. ### APIs and messages Check consumers of: * HTTP requests * HTTP responses * webhooks * events * queues * topics * RPC calls * command payloads * file formats Look beyond the repository when the contract crosses repository boundaries. Do not assume an API is private because there are no callers in the current repo. ### Lifecycle and timing A change can preserve the same types and still change behavior through timing. Check: * initialization * cleanup * mount and unmount * connection setup * retries * timeouts * asynchronous callbacks * event ordering * transaction boundaries * shutdown * background jobs * concurrent access Ask whether something now happens earlier, later, more often, less often, or more than once. ### Shared state Find state read or written by more than one part of the system. Look for: * database rows * cache entries * files * global state * shared objects * branches or versioned state * distributed locks * counters * queues A local-looking write may change behavior far away. Apply `principle-separate-before-serializing-shared-state` when concurrent writers are involved. ### Configuration Check whether the path changes according to: * feature flags * tenant settings * environment * deployment mode * product tier * runtime configuration * platform * version A path that looks dead in one configuration may be active in another. ### External libraries If safety depends on library behavior, inspect the version the project actually uses. Do not rely on memory of how the library usually behaves. Check: * the pinned version * the library documentation for that version * source when available * local wrappers * patches * version-specific behavior Treat library behavior you cannot verify as an assumption. ## Follow effects downstream Do not stop when the changed function returns. Ask what happens to its result. Trace: ```text change -> caller -> state change -> serialized data -> downstream consumer -> user-visible effect ``` The important regression may be several steps away from the changed line. For event-driven systems, follow the event to its consumers. For UI changes, follow state through rendering and cleanup. For persistence changes, follow the stored value to later reads. For APIs, follow the response or request into its consumer when that source is available. ## Check deletion carefully Removed code deserves its own search. When a symbol, field, endpoint, branch, or behavior disappears, look for: * direct references * dynamic references * serialized names * configuration * documentation that drives external clients * tests * migrations * scripts * another repository * operational tooling A search that finds no direct references is useful evidence. It is not proof that no external consumer exists. ## Rate each real risk Do not return a page of hypothetical failures. Keep risks that have a credible path from the change to a failure. For each risk, state: * what breaks * how the change reaches it * the evidence * likelihood * impact * what would prove or disprove it Use simple likelihood labels: * low * medium * high Use simple impact labels: * low * medium * high Do not invent numeric probabilities without data. ## Separate risks from cleared concerns A concern you investigated and disproved is useful. Put it under `Cleared`. For example: ```text Cleared Older sessions can still be loaded. The new field has a default and the deserializer accepts records where the field is absent. ``` This prevents someone else from repeating the same investigation. Do not leave cleared concerns mixed into the active risk list. ## Evidence levels Say how strongly each important safety fact has been checked. Use these levels. ### 1. Assumption The claim sounds plausible but has not been verified in the available source. Do not call the change safe based on this. ### 2. Source evidence Concrete code, documentation, configuration, or contract supports the claim. Cite the source. ### 3. Path traced You followed the relevant behavior through its callers, state changes, boundaries, or consumers and could not reach the failure case. Explain the path. ### 4. Automated evidence An existing test, CI result, recorded reproduction, or other executable evidence directly exercises the safety fact. Inspect the test or result before relying on it. A passing build is not enough when the relevant behavior is not tested. ### 5. Runtime evidence A recorded runtime reproduction, production observation, integration result, or equivalent evidence demonstrates the behavior in the real system. Use this only when that evidence is actually available. Do not claim a higher level than the evidence supports. ## Do not pretend ChatGPT ran the code This skill may be used in a chat where code execution is unavailable. Never say: * "I tested this" * "I reproduced this" * "This passes" * "I verified this at runtime" unless an available tool actually produced that evidence. Existing CI or test results may count as evidence when you can inspect what ran and whether it covers the claim. If the safety fact needs execution and you cannot execute it, mark it: ```text Unproven ``` Then give the smallest test or reproduction that would settle it. For example: ```text Unproven: whether duplicate delivery can create two payments. Test before merge: deliver the same payment event twice with the same event ID and assert that only one payment record exists. ``` That is better than pretending static analysis settled a runtime question. ## Review the test coverage that matters Do not ask whether the project "has tests." Find whether a test covers the exact safety fact. A useful test should fail if your concern is real. If changing the risky behavior would leave the test green, that test does not prove the behavior. When existing tests do not cover the risk, describe the smallest useful test. Do not demand broad test suites when one focused regression test would settle the question. ## Handle cross-repository changes When a contract leaves the repository, inspect connected repositories when they are available. Search for: * endpoint paths * event names * JSON properties * schema names * database contracts * package versions * protobuf fields * GraphQL fields * shared type packages If you cannot access likely consumers, state the limitation. Do not write: ```text No other consumers exist. ``` when all you know is: ```text No other consumers were found in this repository. ``` ## Handle PR reviews For a PR, inspect more than the patch when the source is available. Useful evidence includes: * PR description * changed files * review discussion * linked issues * relevant commits * tests changed with the PR * CI results * surrounding implementation * consumers outside the diff A reviewer who reads only the changed lines sees the author's framing of the change. Blast-radius review checks whether the rest of the system agrees. ## Output Keep the report focused. Use this shape for a meaningful change. ### What changed Explain the behavioral change in a few sentences. Include behavior that is easy to miss from the diff. ### Safety facts State the facts that must hold for the change to be safe. For each one, give its evidence level. Example: ```text Safety fact All exit attempts already tolerate a missing payment record. Evidence level: Path traced. The exit handler treats a missing payment as unpaid and refuses the exit. Both camera and manual exit paths use the same handler. ``` ### Risks Include only credible risks. For each one give: ```text Risk How it breaks Evidence Likelihood Impact How to settle it ``` Use prose when that reads better than a template. ### Cleared List concerns you checked and ruled out. Say why they are safe. ### Before merge Give the smallest tests, checks, or reproductions that would settle anything still unproven. If everything important is already supported by strong evidence, say so instead of inventing more work. ## When the change is small Do not force the full report onto a tiny diff. A small answer may be: ```text This change has one meaningful dependency outside the diff. The new nullable value reaches `createInvoice`, but that function already handles absence by skipping invoice creation. I traced both callers and found no serialized or external use of the field. The remaining unknown is the mobile client. It consumes the same API but its repository is not available here, so compatibility with that client is unproven. ``` That is enough. ## Writing Apply `unslop` to the answer. Cite real source. State what you checked and what remains unknown. Do not turn possibilities into bugs. Do not turn absence of evidence into proof of safety. Do not pad the answer with every caller you found. Find the few facts the change depends on and test those facts as far as the available evidence allows. Reply with the blast-radius analysis itself.
bro267 Bytes
--- name: bro description: Restate the last message in plain human language, with no jargon. disable-model-invocation: true --- Restate your last message. Stop using jargon and speak coherently. State it more simply and concisely, like one human talking to another.
how7.28 KB
--- name: how description: "Explain how a codebase, subsystem, feature, API, or technical artifact works by inspecting the available source. Use for 'how does X work', code walkthroughs, runtime flows, architecture questions, ownership questions, and 'where should this live'." --- # How Explain how the target actually works. Build a useful mental model from the source. Do not produce an annotated file listing, guess from filenames, or describe how this kind of system usually works. Use this skill for questions like: - "How does this work?" - "Walk me through this feature." - "What happens when this request comes in?" - "How is this subsystem structured?" - "Where does this logic belong?" - "Which component owns this?" - "Is this the right layer?" - "What is wrong with this architecture?" ## Get the source first Use the best source available in the conversation. Prefer: 1. Connected GitHub repositories, PRs, issues, diffs, and files. 2. Files the user attached. 3. Other connected sources with relevant implementation or technical documentation. 4. Public source when the target is public. If the user names a repository, PR, issue, file, class, function, or subsystem that you can access, inspect it before answering. If the conversation already contains enough source, use it. Do not ask the user to paste information you can already access. If you cannot access the source needed to answer, say what is missing. Do not fill gaps with guesses. ## Decide what you are explaining Pin down the target before exploring. It may be: - one function or class - a request path - a UI flow - an event flow - a service - a feature spread across several modules - a persistence model - an integration - a package or module boundary - ownership of a domain concept If the question is slightly ambiguous, use the most likely interpretation from the conversation and proceed. State the interpretation only when it matters. ## Start where the behavior starts Find the real entry point. Common entry points include: - an HTTP route - a controller - a UI event handler - a command - a message consumer - a scheduled job - a public service method - application startup - an external callback Do not start by collecting every file that mentions the same word. Find what triggers the behavior, then follow it. ## Trace the flow Follow the implementation from trigger to result. Work out: 1. What starts the flow? 2. What data enters? 3. Where is it parsed or validated? 4. Which business rules run? 5. What state is read? 6. What state changes? 7. Which external systems are called? 8. What response, event, write, or other side effect comes out? Follow real callers and callees when the source lets you. For asynchronous systems, include queues, events, callbacks, retries, and later consumers when they affect the result. For UI code, follow the path from the user action through state changes to the rendered result. For data-heavy flows, show where the representation changes. For example: ```text raw request -> transport type -> domain type -> persistence model -> response ``` Stop exploring when you can explain the relevant path without skipping a material step. ## Find the concepts that matter Pull out only the concepts needed to understand the flow. These may include: - domain entities - state owners - services - repositories - adapters - coordinators - protocols - queues - tables - configuration - important invariants Explain what each one owns. Do not turn the answer into a catalogue of classes and files. ## Explain ownership When the question is about placement or architecture, work out: - who owns the behavior - which layer implements it - what depends on that layer - what that layer depends on - where data crosses system boundaries - whether framework, transport, persistence, and domain concerns are mixed - what callers need to know about the implementation Keep current state and recommendations separate. Say: ```text Today this lives in X. ``` before: ```text I would move it to Y because... ``` Do not describe your preferred design as though it already exists. ## Call out the parts people get wrong Include non-obvious behavior that would matter to someone changing the code. Examples: - state is owned somewhere unexpected - a call that looks synchronous continues through an event - a value is calculated rather than stored - retries can execute the same operation more than once - configuration changes the path - the same concept has two representations - ordering matters - a write happens indirectly - a path that looks unused is reached dynamically - an abstraction requires callers to know its internal rules Only include these when the source supports them. ## Explain mode Use this by default. Start with a short explanation of what the target is and what job it performs. Then explain the actual flow in order. Include the important concepts as they become relevant rather than dumping definitions up front. Reference concrete files, functions, types, PRs, or other source locations when useful. For a larger subsystem, a compact file map can help: ```text api/ request entry point domain/ business rules storage/ persistence events/ asynchronous follow-up ``` Do not list every related file. Finish with the few gotchas that matter. The structure should fit the question. A small function does not need five sections. ## Critique mode Use this when the user asks what is wrong, what should change, or where something should live. Understand the current system first. Then critique it. Look for concrete problems such as: - unclear ownership - dependencies pointing the wrong way - the same business rule implemented in several places - framework code mixed with business logic - database or transport types leaking through domain APIs - shared mutable state - unnecessary coupling - abstractions that expose their internal rules - layers that only pass calls through - one concept split across unrelated lifecycle modules - validation repeated deep inside trusted code - data structures that allow impossible states Do not manufacture problems because the user asked for a critique. Group findings only when useful: - Act on: worth changing. - Consider: a real tradeoff, but not an obvious change. - Noted: useful context, no change needed. - Dismissed: looked suspicious but the source shows it is fine. For anything worth changing, say what is wrong, where it happens, why it matters, and the smallest useful correction. ## Evidence Tie factual claims to source you inspected. Cite files, symbols, PRs, issues, or connected-source results when citations are available. If something is an inference, say so. Never claim you read, searched, ran, or verified something you could not access. Code is good evidence for what the system does. It is weak evidence for why somebody originally designed it that way. Use the `why` skill for historical rationale when it is available. ## Writing Apply the `unslop` skill to the answer. Use the same name for the same concept throughout the explanation. Prefer concrete mechanisms over architecture jargon. Explain the path a value, request, event, or state change takes. Do not narrate the investigation unless the user asks. Do not paste large blocks of source when naming the relevant symbol is enough. Reply with the explanation, not a report about how you produced it.
principle-boundary-discipline1.87 KB
--- name: principle-boundary-discipline description: "Apply when wiring validation, error handling, or framework adapters. Concentrate guards at system boundaries (CLI, config, network, external APIs); trust internal types and keep business logic in pure functions." disable-model-invocation: true --- # Boundary Discipline Place validation, type narrowing, and error handling at system boundaries. Trust internal code unconditionally. Business logic lives in pure functions; the shell is thin and mechanical. **Why:** Scattered validation is noisy, redundant, and gives a false sense of safety. Validate data once at the boundary. Keep logic out of framework wiring so it can be tested without the framework. **The pattern:** - **At boundaries** (CLI args, config files, external APIs, network protocols): validate, return errors, handle defensively. - **Inside the system:** typed data, error propagation, no re-validation. Trust the types. - **Across the boundary.** Expose domain concepts, not the boundary's private representation. Keep general-purpose mechanism inside and special-purpose policy at the edge. **Applications:** Validation and error handling: - Validate config at parse time (the boundary), not inside business logic - Parse raw data into domain types at the boundary - Do not re-export transport, storage, framework, or wire types through the public surface - No redundant nil checks deep in call chains if the boundary already validated Code organization: - Business logic in pure functions with no framework dependencies - Parse functions: pure transforms from raw bytes to typed state - Prompt construction: structured state in, string out - Scoring and assessment: pure transforms from state to results **The tests:** - "Is this data crossing a system boundary right now?" If not, validation is redundant. - "Can this be a pure function that the shell just calls?" If yes, extract it.
principle-build-the-lever2.59 KB
--- name: principle-build-the-lever description: "Apply to any non-trivial work, not just bulk work: edits, migrations, analyses, checks. Build the tool that does it or proves it (codemod, script, generator, or a skill your subagents follow) instead of working by hand. The tool is the artifact a reviewer can rerun." disable-model-invocation: true --- # Build the Lever When the work isn't trivial, build the tool that does it instead of doing it by hand. **Why:** Two payoffs. Throughput: a codemod, generator, or script does the work the same way every time and reruns for free. Confidence: the tool is one artifact a reviewer can read and rerun to check the work. Hand-done changes can only be re-verified by redoing them. A deterministic script turns "trust me" into "run this". **Pattern:** Default to building the lever. Skip it only when the task is genuinely trivial, a couple of obvious edits you can see at a glance. - Do the first unit by hand to learn the recipe, then build the tool. Prove it by rerunning it on that unit and diffing against your hand-done version. Make the lever safe to rerun. A reviewer will. - Codemod or script for edits, generator for repetitive files, a dump-to-sqlite query for analysis, a rerunnable check for verification. - A deterministic lever beats fan-out. If the tool can process every unit in one pass, run it yourself; don't fan out delegates to hand-apply what a script can do. - When you fan work out to subagents, write the lever as a skill they all read: the recipe, the verification contract, and the do-not-touch fences in one artifact, so every delegate inherits the same hardened version instead of re-explaining it per prompt and watching each one drift. Keep it outside the delegates' write scope so they can't quietly edit the contract. - Applying this principle produces a file. If you cited it and there is no codemod, script, generator, or delegate skill in the diff, you didn't apply it. - Commit the lever when the work outlives the session, so the next run reruns it instead of redoing it. **Balance:** The bar is triviality, not repetition. A one-off still earns a lever when the lever is what makes the work checkable. Per the [Laziness Protocol](../principle-laziness-protocol/SKILL.md), build the smallest script that does or proves the job, never a framework. Distinct from [Encode Lessons in Structure](../principle-encode-lessons-in-structure/SKILL.md), which makes a recurring instruction a durable guardrail. This is throughput and reviewability on the work in front of you. For scripting the verification itself, see [Prove It Works](../principle-prove-it-works/SKILL.md).
principle-encode-lessons-in-structure2.19 KB
---
name: principle-encode-lessons-in-structure
description: "Apply when you catch yourself writing the same instruction a second time, or notice a recurring correction. Encode the rule as a lint, metadata flag, runtime check, or script instead of more text."
disable-model-invocation: true
---
# Encode Lessons in Structure
Encode recurring fixes in mechanisms (tools, code, metadata, automation) instead of textual instructions. Every error, human correction, and unexpected outcome is a learning signal. Capture it, route it, and close the loop.
**Why:** Textual instructions are easy to miss. They require the reader to notice, remember, and comply. Structural mechanisms (lint rules, metadata flags, runtime checks, automation scripts) enforce the rule without cooperation.
**Pattern:**
When you catch yourself writing the same instruction a second time:
1. Ask: can this be a lint rule, a metadata flag, a runtime check, or a script?
2. If yes, encode it. Delete the instruction
3. If no (genuinely requires judgment), make the instruction more prominent and add an example of the failure mode
**Pick the strongest rung.** When more than one mechanism would work, choose the strongest the situation allows (an unrepresentable state that cannot compile, then a lint or banned API that fails CI, then a canonical helper, then a runtime check), because agents copy whatever the surrounding code already does and a weaker guard becomes the next template.
**Corollary:** Don't paper over symptoms. If the fix is structural, ONLY use the structural fix. The instruction IS the symptom.
**Feedback loop:**
- **Capture every correction.** When the human intervenes or tests fail, decide if it's a one-off or a pattern.
- **Route to the right layer.** One-off -> brain note. Recurring fix -> skill or lint rule. Systemic issue -> principle.
- **Close the loop.** Don't just record. Apply now or create a concrete todo.
**Anti-patterns:**
- Acknowledging without recording ("I'll keep that in mind" does not persist)
- Recording without routing (a brain note about a lint rule that should exist is wasted unless the lint rule gets implemented)
- Fixing without generalizing (fixing one instance while leaving the recurring pattern intact)
principle-exhaust-the-design-space1.13 KB
--- name: principle-exhaust-the-design-space description: "Apply when facing a novel UI interaction or architectural decision with no precedent in the codebase. Build 2-3 competing prototypes and compare side by side before committing." disable-model-invocation: true --- # Exhaust the Design Space When a novel interaction or architectural decision has no established precedent, explore several concrete alternatives before implementation. Building the wrong thing costs more than exploring three options. **The rule.** When the right answer is not obvious, build 2-3 competing prototypes or sketches. Compare them side by side. Only then commit. Design it twice is this rule by another name. A second flavor of the first shape does not count. **When it applies:** - Novel UI interactions (no prior art in the codebase) - Architectural choices with multiple viable approaches - Product design decisions where user experience depends on feel, not logic **When it doesn't:** - Mechanical implementation where the pattern is established - Bug fixes or refactors with a clear target state - Changes where constraints dictate a single viable approach
principle-experience-first1.28 KB
--- name: principle-experience-first description: "Apply when product, UX, or feature-scope tradeoffs come up. Choose user delight over implementation convenience; ship fewer polished features over more rough ones." disable-model-invocation: true --- # Experience First The product is the experience. Every technical decision either helps or hurts it. When implementation convenience conflicts with user delight, choose delight. - Say no to 1,000 things (every feature, control, and option must earn its place) - Ship less, ship better (polished experience with three features beats rough one with ten) - Prototype before committing (design decisions are cheaper in throwaway HTML than production code) - Sweat the details (transitions, alignment, spacing, feedback, error states) - Tighten the core loop (every feature should serve the central workflow or get out of the way) The user is whoever consumes the work. For a UI that is the end user. For a library or an internal API it is the colleague who imports it. The engineer who maintains the code next is a user too. Weigh their experience the same way, and explain impact from their seat. Foundations should serve the experience, not the other way around. Foundational thinking governs the *sequence* of work; this principle governs the *target*.
principle-fix-root-causes1.33 KB
--- name: principle-fix-root-causes description: "Apply when debugging. Trace each symptom to its root cause and fix it there; reproduce first, ask why until you reach it, resist nil-check guards that silence crashes." disable-model-invocation: true --- # Fix Root Causes When debugging, do not paper over symptoms. Trace every problem to its root cause and fix it there. **Why:** Symptom fixes accumulate. Each workaround makes the system harder to reason about, and the real bug remains. Root-cause fixes are slower upfront but reduce total debugging time. **Pattern:** - Reproduce first (if you can't reproduce it, you can't verify your fix) - Ask "why" until you hit the root cause - Resist the urge to add guards (adding a nil check to silence a crash is a symptom fix) - If a workaround needs a paragraph-long comment to justify it, the code is wrong (fix the code, not the comment) - Check for the pattern, not just the instance (grep for the same pattern, fix all instances) - When stuck, instrument. Don't guess (add logging, read the actual error) **Restart bugs: suspect state before code** Code doesn't change between runs. State does. When something "fails after restart," suspect stale persistent state first: config files, caches, lock files, serialized state. If clearing a state file restores behavior, prioritize state validation as the fix.
principle-foundational-thinking1.74 KB
--- name: principle-foundational-thinking description: "Apply before writing logic: choosing core types and data structures, sequencing scaffold-vs-feature work, asking what concurrent actors share. Get the data structures right so downstream code becomes obvious." disable-model-invocation: true --- # Foundational Thinking **Structural decisions** protect option value. **Code-level decisions** protect simplicity. Over-engineering is often a premature decision that closes doors. The right foundational data structure keeps doors open. **Data structures first.** Get the data shape right before writing logic. The right shape makes downstream code obvious. Define core types early, trace every access pattern, and choose structures that match the dominant paths. A data-structure change late is a rewrite. Early, it is often a one-line diff. At code level, DRY the structure, not every line. Types and data models should converge. Three similar statements still beat a premature abstraction. Prefer explicit over clever. Test behavior and edge cases, not line counts. **Concurrency corollary.** Before sharing state between actors, ask "what happens if another actor modifies this concurrently?" If not "nothing", isolate. **Scaffold first.** If something helps every later phase, do it first. Ask "does every subsequent phase benefit from this existing?" CI, linting, test infrastructure, and shared types are scaffold. Sequence for option value: setup before features, tests before fixes. Keep commits small and single-purpose. Each increment should land a coherent abstraction or deepen one that exists. Do not spread a new capability across callers as special-case coordination. Subtraction comes before scaffolding: remove dead weight first, then lay foundations.
principle-make-operations-idempotent1.36 KB
--- name: principle-make-operations-idempotent description: "Apply when designing commands, lifecycle steps, or processing loops that run amid crashes, restarts, and retries. Converge to the same end state regardless of partial prior runs." disable-model-invocation: true --- # Make Operations Idempotent Design operations so they converge to the correct state regardless of how many times they run or where they start from. Every state-mutating operation should answer: "What happens if this runs twice? What happens if the previous run crashed halfway?" **Why:** Commands, lifecycle operations, and processing loops run where crashes, restarts, and retries are normal. If partial state changes the next run's outcome, every restart becomes a debugging session. **The pattern:** - Convergent startup: scan for existing state, clean stale artifacts, adopt live sessions - Content-based cleanup: compare by content equivalence, not creation order - Self-healing locks: use PID-based stale lock detection - Idempotent scheduling: failed work respawns cleanly, fresh input regenerated after each cycle **The test:** 1. What happens if this runs twice in a row? 2. What happens if the previous run crashed at every possible point? 3. Does re-execution converge to the same end state? If any answer is "it depends on what state was left behind," the operation needs a reconciliation step.
principle-migrate-callers-then-delete-legacy-apis1.13 KB
--- name: principle-migrate-callers-then-delete-legacy-apis description: "Apply when introducing a new internal API while old callers still exist. Migrate callers and delete the old API in the same wave instead of preserving compatibility layers." disable-model-invocation: true --- # Migrate Callers Then Delete Legacy APIs When we decide a new API is the right design, migrate callers and remove the old API in the same refactor wave instead of preserving compatibility layers. **Rule:** - Do not keep legacy API paths alive only because internal callers still exist - Inventory callers, migrate them, and delete the old API immediately - Treat temporary adapters as exceptional and time-boxed, not default architecture - Update tests to assert the new contract, and delete tests that only protect pre-refactor implementation details **When this applies:** - No external users depend on backward compatibility - The project can absorb coordinated breaking changes - The new API is part of a simplification or refactor initiative Keeping both old and new APIs creates dual-path complexity, slows cleanup, and makes the codebase feel append-only.
principle-minimize-reader-load2.05 KB
--- name: principle-minimize-reader-load description: "Apply when reviewing or shaping code that's hard to trace. Count layers between question and answer, and hidden state in the reader's head; collapse one-caller wrappers and shrink mutable scope." disable-model-invocation: true --- # Minimize Reader Load Maintainability is the work a reader must do to understand code. Track two axes: 1. **Layers to trace.** How many indirections sit between the question and the answer. 2. **State to hold.** How much hidden or mutable context the reader must keep in their head. **Why:** Code is read far more than it is written. LOC, cyclomatic complexity, and "clean architecture" are proxies. Reader load is the thing that matters. The two axes are independent. A flat file with 50 globals can be as hard to reason about as a 6-layer adapter stack. Guard both. This is the human analog of [Guard the Context Window](../principle-guard-the-context-window/SKILL.md): working memory is finite for readers too. **The pattern:** - **Collapse layers** that do not earn their keep: wrappers with one caller, adapters with no second implementation, indirection introduced for a future that never came. Inline them. - **Make adjacent layers change the abstraction.** A layer that repeats the same methods and arguments adds reader load without compression. Collapse pass-through layers. - **Demand interface compression.** A broad interface that hides little complexity makes readers learn both the surface and the implementation. Prefer boundaries that hide meaningful decisions. - **Shrink state scope:** prefer pure functions (returns over mutations), locals over fields, fields over module state, and module state over globals. Derive instead of sync. - **Name the invariant at the boundary,** not in every consumer, so the reader learns it once. - Before adding a layer or a piece of state, ask: does this reduce reader load somewhere else by at least as much? **The test:** Can a new reader answer "where does X come from?" and "what can change X?" in under 30 seconds? If not, cut layers or cut state.
principle-model-the-domain2.08 KB
--- name: principle-model-the-domain description: "Apply when writing stateful logic, or when code branches a lot or repeats a shape assumption across files. Encode the domain in a structure instead of scattered conditionals." disable-model-invocation: true --- # Model the Domain Encode the real domain in a data structure instead of scattering it across conditionals. **Why:** Scattered booleans, repeated shape assumptions, and branching spread across files are accidental complexity. A structure that matches the domain makes invalid states unrepresentable and deletes branches. Choosing it at write time is cheap; recovering it later reads as a refactor and gets deferred. **Reach for structures like these:** - A state machine instead of scattered booleans, phases, or lifecycle checks. - A typed object/model instead of loose parameters or repeated shape assumptions. - A map, registry, lookup table, or discriminated union instead of branching spread across files. - A reducer or command/event model instead of ad hoc state mutations. - A module organized around one body of domain knowledge instead of a sequence such as load, validate, transform, and save. Execution order is not ownership. - A small module boundary that gathers repeated behavior, ownership, or invariants. - A queue, cache, index, graph/tree, or normalized collection where the data access pattern calls for it. - Any other structure that fits. The list above covers the common cases only. When none fits, work out what the code must never allow and how the data gets read, then find the structure that encodes exactly that. Do not force an abstraction. Prefer boring code if the current shape is already clear, local, and unlikely to grow. Be skeptical of an abstraction that adds indirection without removing branches, duplicated rules, invalid states, or lifecycle risk. The tell that you skipped this is a new feature that grows an existing if/else chain by one more branch, or a second boolean that must stay in sync with the first. Temporal decomposition is another tell. Phase-named modules repeat the same domain rules across steps.
principle-prove-it-works2.02 KB
--- name: principle-prove-it-works description: "Apply after completing a task, before declaring done. Verify against the real artifact (run the feature, read the actual value, inspect the diff), not a proxy, self-report, or 'it compiles.'" disable-model-invocation: true --- # Prove It Works Verify every task output by checking the real thing directly. Do not infer from proxies, self-reports, or "it compiles." **Why:** Unverified work has unknown correctness. Indirect verification (file mtimes, output freshness, agent self-reports, cached screenshots) feels cheaper than direct observation. Acting on a wrong inference costs far more than checking the source. **Pattern:** After completing any task, ask: "how do I prove this actually works?" Check the real thing, not a proxy: - Check process liveness directly, not indirectly through derived state - Read the actual value, not a cached or derived representation - When verification fails, suspect the observation method before suspecting the system Code and features: 1. Build it (necessary but not sufficient) 2. Run it and exercise the actual feature path 3. Check the full chain: does data flow from input to output? 4. For integrations, test the full communication path end-to-end Delegation: trust artifacts, not self-reports. When verifying delegated work, inspect the actual output artifact (git diff, file contents, runtime behavior), not the delegate's summary. Agents report what they intended, not always what happened. ## Script the check when you can The strongest proof is a deterministic script that re-runs the same comparison, not a one-time eyeball. Write the script, run it, and keep its output as an artifact a reviewer can re-run instead of trusting your word. A script comparing the old and new compiled output catches what a glance misses. Keep the artifact visible for the human. Commit it only for large or complex work where the trail has to be auditable later, like a big port or migration (the **show-me-your-work** skill). Most work just needs it visible, not committed.
principle-redesign-from-first-principles943 Bytes
--- name: principle-redesign-from-first-principles description: "Apply when integrating a new requirement into an existing design. Redesign as if the requirement had been a foundational assumption from day one, instead of bolting it on." disable-model-invocation: true --- # Redesign From First Principles When integrating a change, don't bolt it onto the existing design. Redesign as if the requirement had been there from the start. The result should look like what we would have built if we'd known on day one. - Read all affected files and understand the current design holistically - Ask: "if we were writing this from scratch with this new requirement, what would we build?" - Propagate the change through every reference: types, docs, examples, rationale sections - Think about the redesign holistically, then deliver it incrementally This is the method for preserving option value when integrating changes into an existing design.
principle-separate-before-serializing-shared-state1.59 KB
--- name: principle-separate-before-serializing-shared-state description: "Apply when concurrent actors might write to the same file, branch, key, or state object. Eliminate the sharing first; serialize structurally only when one shared writer is a real invariant." disable-model-invocation: true --- # Separate Before Serializing Shared State When concurrent actors might share mutable state, first ask whether they truly need the same mutable object. If not, eliminate the sharing. When sharing is real, enforce serialization structurally: lockfiles, sequential phases, exclusive ownership. Instructions and conventions are not concurrency control. **Why:** Concurrent writes to shared state create race conditions that are intermittent, hard to reproduce, and expensive to debug. Telling agents or goroutines to "take turns" does not work. **Pattern:** 1. **Identify shared mutable state** (files both read and write, branches both push to, APIs both define and consume). 2. **Default: eliminate the shared write target.** Ask: do these actors need one canonical object, or are they publishing independent facts? Give each actor its own owned file, key, branch, or state directory, and merge only at the read/reporting boundary. Two workers writing their own `lastX` field into one `state.json` is still shared mutation; `indexer-state.json` + `metrics-state.json` is not. 3. **Only when one shared write target is a real invariant, serialize access structurally** (lockfiles, sequential phases, single-writer actor, or atomic compare-and-swap). Treat "we need a lock" as a design smell to check, not as the default answer.
principle-subtract-before-you-add1.31 KB
--- name: principle-subtract-before-you-add description: "Apply when sequencing an addition, refactor, or rewrite. Remove dead weight, redundant validators, and stub references first, then build on the simpler base." disable-model-invocation: true --- # Subtract Before You Add When evolving a system, remove complexity first, then build. Deletion gives you a simpler base, which makes the next addition smaller and less brittle. **Why:** Adding to a complex system compounds complexity. Removing first cuts the surface area, reveals the essential structure, and usually makes the next design obvious. Default to subtraction. Make simplification a continual investment. Leave the design slightly simpler and more capable behind the same or smaller surface than you found it. **The pattern:** - Sequence removal before construction - Cut before you polish (get to the minimum before investing in quality) - Design for observed usage, not speculative edge cases - No speculative validators, parsers, or guards beyond what the spec demands - Out-of-spec features drag validators behind them. Persistence, retry-on-startup, and schema migration each need guards to defend their inputs. - Simplify prompts (remove redundant instructions, excessive templates) - When a reference has no novel content, delete it rather than leaving a stub
principle-type-system-discipline4.98 KB
---
name: principle-type-system-discipline
description: "Apply when designing types, reviewing a function signature, or writing code in any statically-typed language. Make illegal states unrepresentable, brand semantic primitives, parse external data at boundaries, refuse to lie to the compiler, exhaust variants, derive from authoritative schemas."
disable-model-invocation: true
---
# Type System Discipline
The type checker is a proof assistant. Use it to eliminate impossible states, mismatched primitives, and unhandled variants at compile time. A case the types let you ignore becomes a runtime failure the compiler could have stopped. Prefer defining errors and special cases out of existence over proliferating handlers; unrepresentable states, total functions, and interface redesign (the patterns below) are the tools.
Applies to any typed language. Skills like `typescript-best-practices` ground it in specific syntax.
**The patterns:**
- **Make illegal states unrepresentable.** Model variants as sum types: discriminated unions in TypeScript, enums with payloads in Rust/Swift/Kotlin, sealed classes in Scala, ADTs in Haskell/OCaml. Don't model state as a bag of optional fields where contradictory combinations compile. A subtle anti-pattern worth naming: `{ completed: boolean; completedAt?: Date }` admits `completed: true; completedAt: undefined`, which is meaningless. Derive the boolean from a single source like `completedAt !== null`, or model the variants explicitly as `{ kind: 'open' } | { kind: 'done'; at: Date }`. If a bug forces the question "wait, can this combination actually happen?", the type is too loose.
- **Types are constructions, not restrictions.** Build the type up from the values you want instead of carving them out of a looser type with checks. The invariant that seems to need a refinement type is usually a construction away. A non-empty list is a head plus a rest, not a list with a length check. A valid time range is a start plus a duration, not two timestamps you must keep ordered. No representation is privileged. A list of pairs is an even-length list if you interpret it that way, so choose the shape that cannot build the illegal value and expose the interface callers need on top.
- **Brand semantic primitives.** `UserId` and `OrderId` are strings underneath but should not be interchangeable. Newtypes in Rust, opaque types in Swift, value classes in Kotlin, phantom types in Haskell, branded intersections in TypeScript. Validate once at creation, trust the type downstream.
- **External data is untyped until parsed.** RPC payloads, JSON, IPC messages, CLI args, config files, environment variables, database rows. Have a parse function at every boundary that turns unstructured input into the typed model. See the **boundary-discipline** principle skill for where to put validation.
- **Don't lie to the type system.** Casts, unsafe coercions, and assertion functions that bypass the compiler are runtime crashes waiting to happen. If the compiler can't prove a fact, prove it (validate, narrow, refine the model) or accept that the cast is a hazard. The cast you bury today is the postmortem you write next week.
- **Exhaustive matching is the compiler's job.** When you match on a sum type, the compiler must fail compilation if a new variant is added without handling. Use the idiom your language provides: `never`-typed binding in TypeScript, unannotated `match` in Rust, `-Wincomplete-patterns` in Haskell, sealed-class match exhaustiveness in Kotlin.
- **Derive types from authoritative schemas.** When a protocol buffer, OpenAPI spec, GraphQL schema, database migration, or design-system token file defines a shape, derive from it instead of hand-rolling a parallel type. Manual duplication drifts. See the **encode-lessons-in-structure** principle skill.
- **Strengthen a type only where partiality appears.** A runtime assertion, null check, or "this should never happen" throw marks the place a type is too weak. Push that check up into the type. Then stop. The type system's job is to track the cases each use site must handle, not to describe the data as precisely as possible. Prefer total functions. `sum` of an empty list is 0, so it takes the plain list. `head` of an empty list has no answer, so it demands the non-empty one. Extra precision costs reuse and ceremony and buys no safety.
**The tests:**
- "Can I write a comment explaining when this combination of fields is valid?" If yes, the type is too loose. Split it into a sum type.
- "Do two of my function arguments share a primitive type but mean different things?" Brand them.
- "Where did this `any`, this `as`, this `assertNotNull` come from?" Trace it to the boundary and validate there instead.
- "If a new variant is added next month, will the compiler tell the next agent where to add a case?" If no, the match isn't exhaustive.
- "Is this type duplicating a shape another file owns?" Derive instead.
- "Am I strengthening this type to keep an operation total, or just to be more precise?" If nothing would otherwise panic, keep the plain type.
recall9.75 KB
--- name: recall description: "Reconstruct recent working context from prior conversations, remembered context, and connected project sources, then give a concise current-state brief. Use for 'recall my work on X', 'catch me up', 'what have I been working on', 'where did I leave off', or before resuming earlier work." --- # Recall Reconstruct the user's working context before they resume something. The goal is not a transcript summary. Work out what the user was trying to achieve, what changed, what is true now, what remains unresolved, and what they should do next. Use this skill for questions like: * "Recall my work on X." * "Catch me up." * "Where did I leave off?" * "What have I been working on?" * "What was the state of this project?" * "What should I pick up next?" * "We worked on this before. Where were we?" Keep the answer focused on the requested work. ## Use the context ChatGPT actually has Use the best available evidence. This may include: * the current conversation * relevant prior conversation context available to ChatGPT * remembered user context * connected GitHub repositories * issues and pull requests * connected project trackers * documents * email or team communication when relevant and available * other connected sources that contain the current state Do not pretend you can access a conversation, repository, document, or service that is unavailable. If the user already supplied a good state summary, use it instead of reconstructing the same information again. Do not ask them to repeat details that are already available. ## Work out what kind of recall they want There are two common cases. ### Project recall The user names a project, feature, bug, ticket, repository, or other target. Examples: * "Catch me up on Parking Edge." * "Where did we leave MFO-347?" * "Recall the pricing work." * "What happened with that authentication bug?" For project recall, combine previous working context with the current project state. ### Activity recall The user asks what they have been doing over a period. Examples: * "What did I work on this week?" * "What have I been doing lately?" * "Catch me up on yesterday." For activity recall, focus on the user's work history during that period. Do not drag unrelated project history into an activity recap. ## Set the scope Respect the scope the user gives you. That may include: * a project * a feature * a ticket * a repository * a time period * a particular problem If they say "recent", use roughly the last seven days unless the conversation makes another range more sensible. If they say "all", do not silently reduce it to recent activity. If the topic is clear, proceed without asking for clarification. If several unrelated projects share the same name or reference, clarify only when choosing the wrong one would materially change the answer. ## Reconstruct the working thread Find the important pieces of the previous work. For each relevant thread, recover: * what the user wanted * decisions that were made * work that was completed * work that was started but not finished * problems encountered * corrections to earlier assumptions * rejected approaches * PRs, tickets, branches, documents, or other artifacts * the last meaningful state Do not reproduce the conversation turn by turn. Compress repeated discussion into the decision that survived. If the user changed direction, use the later decision as the current one and mention the earlier approach only when it explains something important. ## Check the shared project record When the user names a feature, bug, repository, issue, PR, or subsystem, previous conversation history is only part of the answer. Check connected project sources when available. Useful sources include: * GitHub PRs * GitHub issues * commits * Linear or another tracker * design documents * incident reports * relevant team discussion * CI or deployment state Look for what happened after the previous conversation too. A PR may have merged. A ticket may have closed. A fix may have been reverted. A new bug may have appeared. Someone else may have changed the same code. Use the `why` skill when the shared record needs deeper historical investigation. ## Distinguish history from current state Something being true in an old conversation does not make it true now. Treat these as history: * "PR is open." * "Ticket is in progress." * "Branch has not merged." * "We still need to implement X." * "This bug is unresolved." When the answer matters and a connected source can verify the current state, check it. Prefer current project state over remembered status. For example: ```text Previous state: PR #42 was waiting for review. Current state: PR #42 has since merged. ``` Do not present stale history as current truth. ## Preserve decisions A useful recall answer tells the user what was decided. Examples: ```text Use Ubuntu Server, not Desktop. ``` ```text Mender handles production OTA. Cloudsmith is optional for package distribution. ``` ```text The POS records cash or card but does not integrate with a payment terminal in the MVP. ``` Do not bury decisions inside a chronological retelling. If a decision was tentative, say so. If it was later reversed, give the current decision. ## Preserve corrections Corrections matter because they stop the user from repeating dead ends. Include them when relevant. For example: ```text Originally we planned to modify the existing sidebar. That was changed. The ticket now requires a brand-new sidebar component with feature parity. ``` Or: ```text The first fix was merged but did not solve the production issue, so a new ticket replaced it. ``` Do not include every disagreement. Keep corrections that affect the next piece of work. ## Find unresolved work Separate finished work from open work. Look for: * unmerged PRs * open tickets * unanswered questions * known bugs * deferred decisions * follow-up work * dependencies * tests or verification that still need to happen Do not revive something merely because it appeared in an older conversation. If later evidence shows it was completed, treat it as completed. ## Identify the next move End with one concrete next action when there is a clear one. Good: ```text Next: start MFO-331. Its dependencies are merged and the ticket is ready. ``` Good: ```text Next: upload the updated plugin bundle and verify that the six adapted skills pass scanning. ``` Weak: ```text Next: continue development. ``` If several tasks can start independently and the user asked what is available, list those instead. Do not manufacture a next step when the work is already finished. ## Handle incomplete memory Sometimes the available context is not enough. Say what you can establish and what you cannot. For example: ```text I can recover the design decision and the open PR, but I do not have access to the conversation where the migration plan was finalized. ``` Then use available connected sources to fill the gap when possible. Do not invent missing decisions because they fit the surrounding story. ## Resolve contradictions Previous conversations and current project sources may disagree. When they do, prefer current evidence for current state. Preserve the contradiction if it explains how the project changed. For example: ```text We originally treated #21 as the next implementation ticket. That is stale. It has since merged, and #24 is now the first unblocked ticket. ``` If two current sources disagree, show the disagreement rather than choosing one without evidence. ## Keep adjacent work out A nearby ticket, feature, or project does not belong in the recall unless it: * blocks the requested work * changed the requested work * explains a decision * is the obvious next step The user asked to recover a working context, not everything you know about them. ## Output For a substantial project recall, use this shape when it helps. ### Capsule At most five bullets. Cover: * what the work is * the goal * the important design decisions * where it currently stands ### Threads Give one compact line for each active or recently completed thread. Use a status when you can establish one, such as: ```text [merged #35] [open PR #41] [in progress] [done] [blocked] [planned] [reverted] ``` Do not invent PR numbers, branches, or statuses. ### Problems Include only recurring or unresolved problems that matter to resuming the work. Preserve failed fixes or reverted approaches when repeating them would waste time. Keep this short. ### Next move Give the single most useful next action. For a simple recall question, do not force this structure. A few paragraphs may be enough. ## Activity recap For questions like "what did I work on this week?", group related work rather than recounting every conversation. Prefer: ```text Parking Edge You finished the paid-exit flow, worked through the POS and rate-card tickets, then moved onto deployment and fleet management. The deployment direction settled on Ubuntu Server with Mender. ``` over: ```text Monday you asked X. Then you asked Y. Then on Tuesday you asked Z. ``` Mention dates only when they help establish sequence or scope. ## Evidence Use concrete references when available. Examples: * PR number * issue number * Linear ticket * commit * document * prior decision * connected-source citation Do not expose private internal context that the user did not ask for. Do not claim a status is current unless you have current evidence or make clear that it comes from previous context. ## Writing Apply `unslop` to the answer. Keep the recap compact. Use the project's real names and terminology. Prefer decisions and current state over chronology. Do not narrate how you searched for the context. Do not repeat the user's entire history. Give them enough context to continue working without reopening old conversations. Reply with the brief itself.
teach7.53 KB
---
name: teach
description: "Explain a codebase, subsystem, feature, change, or technical idea so the user actually understands it. Use for 'teach me this', 'help me understand X', 'explain this change', 'walk me through this', or when the user wants more than a reference answer."
---
# Teach
Explain the thing so the user understands it well enough to work with it.
Do not produce a reference manual, dump implementation details, or list every symbol involved.
Teach what it is, how it works, and why it is built that way.
Use this skill for questions like:
- "Teach me how this works."
- "Help me understand this subsystem."
- "Explain this PR to me."
- "Walk me through this architecture."
- "I need to understand this before I change it."
- "Explain this like I'm new to the codebase."
## Start with what the user needs
Work out why they are asking.
They may be:
- about to change the code
- reviewing a PR
- debugging a problem
- onboarding to a project
- comparing designs
- trying to understand a technical concept
Use the conversation to judge what they already know.
Do not quiz them before explaining something you can explain directly.
Skip concepts they clearly understand. Spend time on the part their question is actually about.
## Get the facts first
If the explanation depends on a codebase, PR, issue, file, or other technical artifact, inspect the available source before teaching it.
Use the `how` skill to understand what the system does and how the parts fit together.
Use the `why` skill when the explanation depends on design history, intent, constraints, or tradeoffs.
Do not invent a simple story to make the explanation easier.
A clear explanation still has to be true.
## Give the smallest complete explanation first
Start with one or two paragraphs that answer:
- What is this?
- What job does it do?
That first explanation should be enough for the user to decide whether they need more detail.
Do not open with a table of contents, roadmap, or "here is what we are going to cover."
Start explaining.
## Build from concrete behavior
After the short definition, explain what actually happens.
For software, follow the path through the system.
For example:
```text
user action
-> request
-> validation
-> domain logic
-> database write
-> response
```
Explain what each step does and why it exists.
Do not replace an explanation with function names.
Bad:
```text
CreateOrder calls OrderService, then OrderRepository.
```
Better:
```text
The request handler turns the incoming JSON into an order command. The domain service checks whether the order is allowed, then the repository stores the accepted order.
```
Name the actual functions and files when they help the user find the code, but explain the mechanism first.
## Introduce concepts when they become necessary
Do not front-load ten definitions.
Introduce a concept when the explanation reaches the point where the user needs it.
If a queue matters only halfway through the flow, explain the queue halfway through the flow.
If a type exists only to prevent an invalid state, explain it when that invalid state becomes relevant.
This keeps the explanation attached to something concrete.
## Explain why the shape matters
When there is evidence for the design reason, connect the mechanism to that reason.
For example:
```text
The payment state lives on the session rather than the exit event because payment can happen before the camera sees the vehicle leave.
```
If the reason comes from historical evidence, use the `why` skill and preserve its confidence.
If you only know what the code does, do not turn that into a claim about why the team chose it.
Say:
```text
The code is structured this way. I could not verify whether that was the original reason for the design.
```
when that distinction matters.
## Use examples that match the real system
A good example should make the actual mechanism easier to see.
Prefer:
- a real request
- a real entity
- a real event
- a real state transition
- a small concrete input and output
Avoid generic examples when the source gives you a better one.
If the system manages parking sessions, explain it with a parking session.
If it processes fuel orders, explain it with a fuel order.
Do not switch domains just to create an analogy.
## Draw when the relationships are hard to hold in prose
Use a small text diagram when several parts interact.
Keep it simple.
Start with the main path:
```text
Browser -> API -> Service -> Database
```
Then add another part only if it matters:
```text
Browser -> API -> Service -> Database
|
v
Event bus
```
Do not create one giant diagram containing every component in the system.
A diagram should reduce the amount the user has to remember, not create another thing they need explained.
## Teach flows in order
When the thing has a lifecycle, walk through it in the order it happens.
For example:
```text
1. Vehicle enters.
2. The camera emits an ANPR event.
3. Parking Edge creates a session.
4. The teller marks the session paid.
5. The vehicle reaches the exit.
6. Parking Edge checks the payment and grace period.
7. The gate may open.
```
Then explain the important decisions inside that flow.
Chronological explanations are usually easier to understand than explanations grouped by source file.
## Show boundaries
For architecture, explain who owns what.
The user should be able to answer questions like:
- Where does this behavior start?
- Which component owns the rule?
- Where is the state stored?
- Which component is allowed to change it?
- What crosses the network?
- What happens asynchronously?
- What can fail independently?
If they cannot answer those after the explanation, the architecture probably has not been explained yet.
## Call out the surprising part
Most systems have one or two things that a newcomer will assume incorrectly.
Name them.
Examples:
- the API does not actually perform the work synchronously
- the displayed value is calculated rather than stored
- an exit event does not close a session unless payment is valid
- two modules use different representations of the same entity
- a retry can cause the same message to arrive twice
These details are often more useful than another page of normal behavior.
Only include surprises supported by the source.
## Match the depth to the conversation
Do not give the full subsystem lecture when the user asks about one function.
Do not stop at a two-sentence summary when they asked for a deep walkthrough.
Start small. Go deeper as the question requires.
If the user asks a follow-up about one part, stay on that part instead of restarting the whole explanation.
## Do not hide complexity
Make the explanation easy to follow, but do not pretend the system is simpler than it is.
If two mechanisms interact, explain both.
If the evidence is incomplete, say so.
If the architecture has an awkward exception, include it when the exception changes the user's mental model.
Clarity means removing unnecessary difficulty, not removing facts.
## Writing
Apply the `unslop` skill to every response.
Use plain technical English.
Use one name for each concept and keep using it.
Prefer short paragraphs.
Mix sentence lengths naturally.
Avoid filler, motivational framing, and teaching theatre.
Do not say:
- "The key thing to remember is..."
- "Here's where it gets interesting..."
- "Let's break this down..."
- "Don't worry, this is simpler than it looks."
- "At its core..."
Just explain the thing.
Do not end with a generic summary that repeats what you already said.
Reply with the explanation itself.technical-writing11.3 KB
---
name: technical-writing
description: "Layered technical-writing standard: Diátaxis structure, Google developer style sentences, STE instruction rules, Global English syntax. Use for /technical-writing or when writing or reviewing docs, RFCs, readmes, PR descriptions, or commit messages."
disable-model-invocation: true
---
# Technical writing
The goal is writing a tired engineer understands on the first read. Four layers get you there, one question each: what kind of document is this, how do sentences address the reader, how much does each sentence carry, and can any sentence be read two ways. Apply all four.
Three rules sit above the layers:
- **Cut every word that does no work.** If the sentence survives without a word, the word goes. "In order to" is "to". "It is important to note that" is nothing.
- **Use the short, everyday word.** "Use", not "utilize". "Help", not "facilitate". "Do", not "perform". A long word has to buy its length with precision.
- **When a rule makes a sentence worse, fix the sentence another way or leave it alone.** The rules serve the reader. A sentence that follows every rule and sounds like a machine wrote it has failed.
The codebase is the word list. Write the real symbol, file, flag, or command name, not a synonym or a description of it.
Don't invent jargon. Use the words a developer would say out loud: "move", "delete", "a budget that only decreases", not "evacuate", "ratchet", or "endgame". A named pattern is fine when the doc says what it means the first time. Add new offenders to `unslop`'s abstract-metaphor rule with their replacement.
## Vary the rhythm
The layers decide what a document says and how much each sentence carries. A doc can obey all of them and still read machine-written: every sentence clipped short, no view anywhere, nothing specific.
- Mix sentence lengths on purpose. Short sentences land a point. Longer ones that take their time carry a fact with its condition or consequence.
- One thought per sentence does not mean one length per sentence. Split the sentence that carries two thoughts. Keep the long sentence that carries one.
- Have a view where the mode allows it. Explanation weighs trade-offs, so say what you make of them instead of listing pros and cons. Reference stays dry.
- Be specific over sterile. Not "schema changes can cause issues" but "a column rename fails the build".
## Pick the mode first (Diátaxis)
One document, one mode. Two questions pick it: does the content inform action (doing) or understanding (thinking), and does it serve learning or work?
- Action + learning: **tutorial**.
- Action + work: **how-to**.
- Understanding + work: **reference**.
- Understanding + learning: **explanation**.
Use the compass on a whole document or on one sentence. Reach for it whenever you feel unsure what you are writing. Gut feel is often wrong here.
**Tutorial: learning by doing.** You are the teacher. The learner's success is your job, not theirs. Open by saying what the learner will build, not what they will "learn". Every step produces a visible result, early and often. Tell them what they should see: the expected output, the prompt change, the log line. Cut explanation to one clause and a link. Teaching pauses break the lesson. Stay concrete. Write as "we", in commands: "First, do x. Now, do y."
**How-to: steps to a goal.** Solve a problem a person has, not an operation the machine can perform. Assume competence. Skip teaching. Action only: no digressions, no background, no completeness for its own sake. Link those instead. Allow forks and judgment: "If you want x, do y." Name the guide by the task: "How to calibrate the radar array", not "Radar array calibration".
**Reference: facts for lookup.** Describe. Only describe. No instruction, no persuasion, no opinion. Be dry, complete, and sure: state facts, options, limits, and errors with no hedging. Mirror the structure of the thing described, so code and docs can be navigated together. Put material where readers expect it. Generate from code where possible, so it stays true.
**Explanation: understanding and why.** One bounded topic, readable away from the product. Each title should tolerate an implicit "About..." in front. Anchor on a real why question. Give context: design decisions, history, constraints, alternatives. Opinion is allowed here and nowhere else.
Don't mix modes: no reference tables inside a tutorial, no tutorial hand-holding inside reference, no arguing inside a how-to. Split and link instead.
Source: diataxis.fr, fetched 2026-07-18.
## Write sentences to the reader (Google developer style)
- Talk to the reader as "you", in the present tense. "Will" only for things that genuinely happen later.
- Say who does what: "the compiler checks", not "is checked". Passive is fine only when the actor is unknown or beside the point.
- Write instructions as commands: "Click Submit." State facts plainly. Never "should be done".
- Put the condition before the instruction: "To delete the document, click Delete." The reader skips what does not apply.
- Put the common case first. Exceptions after.
- Sound like a knowledgeable friend. No buzzwords, no figurative language, no "please" in instructions, and never "simply", "easy", or "quickly" in a procedure. If it were simple, the reader would not be here.
- Don't pre-announce ("we will soon support...") and don't start consecutive sentences with the same phrase.
- Read the awkward sentence aloud. If it stays awkward, rewrite it.
- Link with words that say where the link goes: the page title or a short description. Never "click here". Prefer a sentence of context on the page over a link off it.
- Headings carry the point, not just the topic ("Pick the mode first", not "Modes"). Sentence case. A task heading is a bare verb phrase ("Create an instance"). A concept heading is a noun phrase. One h1 per page, no skipped levels.
- Numbered lists for sequences, bullets for everything else. Introduce a list with a complete sentence. Keep items parallel.
- Code goes in code font. UI elements go in bold. Use serial commas. Drop "etc." and say up front that a list is partial.
Source: developers.google.com/style, fetched 2026-07-18.
## Make statements load one at a time (STE rules)
- One instruction per sentence. One thought per sentence everywhere else.
- Split instructions longer than about 20 words and other sentences longer than about 25.
- Put the warning or condition before the step it guards: "If hot oil touches your skin, injuries can occur."
- Keep "the" and "a": "Remove backup file" reads two ways. "Remove the backup file" reads one.
- Give each word one meaning and one job, then keep it. If "check" means inspect, don't also use it for restrain.
- Pick one word per action and stick to it: "start", not "start" here and "initiate" there.
- Write procedures as direct commands, never as narration and never in the passive: "Install the component", not "the component must be installed".
- Avoid "-ing" words where you can. They take too many grammatical jobs and breed misreadings.
Source: asd-ste100.org (Issue 9, 2025), fetched 2026-07-18. The numbered rules and dictionary live in the spec PDF. The principles above are the transferable core.
## Leave no sentence open to two readings (Global English)
- Keep words like "only" and "not" next to the word they change: "only fails on growth" and "fails only on growth" say different things.
- Break up long noun strings: "the proto import budget check script" becomes "the script that checks the proto-import budget".
- Make every "it", "they", and "this" point at one obvious thing. Repeat the noun when in doubt. Never use "this" or "which" to point at a whole clause.
- Don't drop verbs: "Phase 1 moves the converters and Phase 2 the runtime" leaves Phase 2 without one. Give it one.
- Keep the small words that show structure. "Ensure that the switch is off" keeps "that" because it makes the sentence parse one way. Never trade clarity for word count.
- Repeat the article in a series when it prevents a misread: "the client and the host", not "the client and host", when they are two things.
- Say which parts "and" or "or" joins when a sentence can group two ways. "Both...and", "either...or", and "if...then" are free disambiguators.
- Use periods, not semicolons. Replace an em dash with a new sentence.
- Make text in parentheses a full grammatical unit or its own sentence. Never form plurals with "(s)".
- No slashes: write "a, b, or both" instead of "a/b" or "and/or".
- Call each thing by one name, everywhere. A doc that says "the gate", "the ratchet", and "the budget check" for one thing teaches three things. Rewording an unchanged sentence between edits costs the same way: don't churn what didn't change.
- Skip idioms, colloquialisms, Latin abbreviations, and metaphors. A non-native reader, a translator, and an agent all parse plain constructions best.
Source: Kohl, The Global English Style Guide (SAS Press). Guideline text fetched from the Internet Archive and the SAS sample chapter, 2026-07-18.
## Voice and repo specifics
- Apply the **unslop** skill to every doc this skill touches. That skill owns the slop-pattern catalog: AI vocabulary, filler, hedging, formatting tells.
- PR descriptions and commit messages are writing too. Every layer except Diátaxis applies to them.
- Product UI strings are not documentation. Use your product's copy guidelines for those.
- Indent code snippets with tabs. Write real paths and real symbols. Make every count or tree claim true at the commit that lands it, and include the command that regenerates it.
## Worked example
Before:
> Configuration of the proto import ratchet budget script parameters is performed via budget.json. Note that it's important to remember that running with --write, which updates the committed budget to reflect the current count, should only be done when lowering it. If exceeded, CI fails.
After:
> `budget.mjs` reads the committed budget from `budget.json` and counts the files that import protos. If the count exceeds the budget, CI fails. Run `budget.mjs --write` only to lower the budget.
The fixes, by layer: "configuration is performed" becomes "`budget.mjs` reads", so someone does something (Google). "Ratchet" goes away. The script's real filename does the naming (jargon rule). The five-noun string breaks up into plain clauses (Global English). The hedge "note that it's important to remember" is deleted (cut every word that does no work). The failure condition moves ahead of the step it explains (STE). The buried "should only be done when lowering" becomes a command with "only" next to its verb (STE). "If exceeded" gets a subject: the count (Global English).
## Review checklist
Apply to any prose this skill covers. Item 1 applies only to document sets:
1. Is each file one Diátaxis mode, with links where modes meet?
2. Is every instruction written as a command, with its condition in front?
3. Does any sentence carry two instructions or two thoughts? Split it.
4. Can any word be cut without losing meaning? Cut it.
5. Is "only" next to the word it changes? Does every "it" point at one thing? Does every clause keep its verb?
6. Does each thing have exactly one name across the docs?
7. Would a developer say these words out loud? Replace invented metaphors and fancy synonyms with the plain word or the real symbol name.
8. Are all symbols, paths, and counts real at this commit, with the commands that regenerate the counts?
typescript-best-practices2.39 KB
---
name: typescript-best-practices
description: TypeScript best practices. Use when reading or editing any .ts or .tsx file.
---
# TypeScript best practices
Apply the **type-system-discipline** principle skill first; this skill grounds it in TypeScript syntax.
| Rule | Summary |
|------|---------|
| Discriminated unions | Model variants with a `kind` literal discriminant so impossible states can't be represented. No optional-field bags. |
| Branded types | Brand primitives with `& { readonly __brand: "X" }` so they can't be mixed up. Validate once at creation. |
| Constructive modeling | Build the shape so the illegal value can't be constructed. `[T, ...T[]]` for non-empty, `[T, T][]` for even length, `start` plus `duration` for a range. Not a runtime guard, not a wish for refinement types. |
| Simplest total type | Keep `T[]` while every operation on it stays total. Strengthen to `NonEmpty<T>` only where the loose type forces `!`, a cast, or a "should never happen" throw. |
| `unknown` over `any` | External data is `unknown`. `any` disables type checking everywhere it touches. |
| No `as` casts | Every `as` is a runtime crash waiting. Cast only after validation. |
| Narrowing hierarchy | Discriminant switch > `in` operator > `typeof`/`instanceof` > user-defined type guard > `as`. |
| Type guards | Must verify the claim. A lying guard is worse than `as` because the bug hides behind a name that says it's safe. Name them `isX` or `hasX`. |
| Exhaustiveness | Inline `const _exhaustive: never = x;` in default arms so the compiler errors when a new variant is added. |
| `satisfies` over `as` | Validates the value without widening literal types. |
| Boundary validation | Validate where data crosses in; trust types inside. See the **boundary-discipline** principle skill. |
| Schema-derived types | Reach for `Pick`/`Omit`/`Parameters`/`ReturnType`/`Awaited`/`typeof` before declaring a new interface. |
| Object args | Pass objects, not positional, so argument order is self-documenting. Skip on hot paths (per-frame render, tokenizers, parsers). |
| Real tests | Don't mock what you can run. Prefer the framework's real test primitives with leak/disposable checks, and verify UI in a running build. Mock only what you can't run locally. |
| Structured telemetry | Prefer structured logger diagnostics with enough context to debug from an id. No `console.log` in shipped code. |
Examples: `references/patterns.md`.
Referenced files: 1
unslop6.44 KB
---
name: unslop
description: Cut AI tells from any writing. Must always apply.
---
# Unslop
Edit text to remove AI patterns and add human voice.
## Process
1. Scan for the patterns below.
2. Rewrite. Preserve meaning, match intended tone.
3. Add soul (see next section).
4. Self-audit: "What makes this obviously AI generated?" Fix remaining tells.
## Adding soul
Removing patterns is half the job. Sterile, voiceless writing is just as obvious.
- **Have opinions.** React to facts instead of neutrally listing pros and cons.
- **Vary rhythm.** Short sentences. Then longer ones that take their time. Mix it up.
- **Acknowledge complexity.** "Impressive but also kind of unsettling" beats "impressive."
- **Use "I" when it fits.** First person isn't unprofessional.
- **Let some mess in.** Perfect structure looks machine-made.
- **Be specific.** Not "this is concerning" but "there's something unsettling about agents churning away at 3am."
## Patterns to detect and fix
### Content
1. **Puffery.** "pivotal moment", "testament to", "evolving landscape", "setting the stage for", "indelible mark", "deeply rooted". Cut puffery, state what happened.
2. **Name-dropping.** Listing media outlets without context. Pick one, say what was said.
3. **Superficial -ing phrases.** "highlighting...", "ensuring...", "reflecting...", "showcasing...", "fostering...". Delete or expand with real sources.
4. **Promotional language.** "nestled", "vibrant", "breathtaking", "groundbreaking", "renowned", "stunning", "must-visit". Use neutral descriptions.
5. **Vague attributions.** "Experts believe", "Industry reports suggest", "Some critics argue". Name the source or delete.
6. **Formulaic challenges.** "Despite challenges... continues to thrive." Replace with specific facts.
### Language
7. **AI vocabulary.** Additionally, crucial, delve, enduring, enhance, fostering, garner, interplay, intricate, landscape (abstract), pivotal, showcase, tapestry (abstract), testament, underscore, vibrant. Replace with plain words.
8. **Fancy ways to say "is".** "serves as", "stands as", "boasts", "features". Just say "is" or "has".
9. **"Not just X, but Y."** State the point directly instead.
10. **Rule of three.** Forcing ideas into groups of three. Use the natural number.
11. **Synonym cycling.** Protagonist, main character, central figure, hero all in one paragraph. Pick one, repeat it.
12. **False ranges.** "from X to Y" where X and Y aren't on a meaningful scale. List topics directly.
### Style
13. **Em dash overuse.** Avoid em dashes entirely. Use periods or commas only (no parentheses, no en dashes, no hyphen-as-dash substitutes). Em dashes are an AI tell, and reaching for parentheses instead just trades one tell for another. If a thought needs separation, end the sentence or use a comma.
14. **Colon overuse.** Colons are fine before a list or example. Not as mid-sentence connectors. "If you're coming from traditional automation: instead of registering event handlers, you describe conditions" adds nothing with the colon. Rewrite to let the point stand on its own without comparison framing. "Describing when the scheduler should fire works best as plain English." Same meaning, no crutch punctuation.
15. **Boldface overuse.** Don't bold every proper noun or acronym.
16. **Inline-header lists.** The tell is a bold label and colon that restates the line: "**Performance:** Performance improved...". Convert those to prose. A bold lead-in that ends in a period, names the item, and is followed by genuinely new detail ("**Schema in TypeScript.** Tables live in one file.") is fine, not a tell.
17. **Title case headings.** Use sentence case.
18. **Decorative emojis.** Remove from headings and bullets.
19. **Curly quotes.** Replace with straight quotes.
### Communication artifacts
20. **Chatbot phrases.** "I hope this helps!", "Let me know if...", "Of course!", "Certainly!", "Found the smoking gun!" Remove.
21. **Cutoff disclaimers.** "While specific details are limited..." Find sources or remove.
22. **Sycophantic tone.** "Great question! You're absolutely right!" Respond directly.
### Filler
23. **Filler phrases.** "In order to" becomes "To". "Due to the fact that" becomes "Because". "It is important to note that" gets deleted.
24. **Excessive hedging.** "could potentially possibly be argued that it might" becomes "may".
25. **Generic conclusions.** "The future looks bright." State specific plans or facts.
### Jargon
26. **Abstract metaphor nouns.** Substrate, wedge, vector, locus, vantage, nexus, primitive (as noun), harness (as metaphor), surface (as in "API surface"), bedrock, scaffolding (as metaphor), modality, paradigm, gold-plating, ratchet (as metaphor), evacuate (for moving code), endgame, north star, flywheel. These read as technical but usually have a plainer concrete word. "Substrate" becomes "base". "Wedge in" becomes "add". "Vector" becomes "way" or "method". "Gold-plating" becomes "more than the job needs". "Ratchet" becomes the mechanism's real name or "a limit that only tightens". "Evacuate" becomes "move out". "Endgame" becomes "the last phase". Pick the concrete word.
### Plain speech
27. **Say what it does, not how it feels.** "the database stays close at hand", "SQL you can read", "types that follow your schema" name a feeling. The fix names the mechanism or a number: "`.toSQL()` returns the exact string sent to the database", "a column rename fails the build". Ask what the sentence tells the reader to do or know, then write that. If you can't restate it as a concrete instruction, fact, or number, cut it. One more check: if the sentence could appear unchanged in another project's docs, it says nothing about this one. Cut it.
28. **Shorten or split dense sentences.** If the reader has to backtrack to parse a sentence, break it in two or drop clauses. One idea per sentence.
29. **Active voice.** Prefer it. Catch "is/are/was/were + past participle" and name the actor: "queries are validated" becomes "the compiler validates queries", "the file is parsed by the loader" becomes "the loader parses the file". Passive is fine only when the actor is unknown or genuinely doesn't matter.
30. **Cut adverbs, or use a stronger verb.** "runs quickly" becomes "is fast" or the number. "significantly improves" becomes the measured delta. An adverb propping up a weak verb means the verb is wrong.
31. **Prefer the plain word.** "utilize" becomes "use", "leverage" becomes "use", "facilitate" becomes "help", "numerous" becomes "many", "in the event that" becomes "if". The fancier synonym is rarely clearer.
why10.4 KB
--- name: why description: "Investigate why a codebase, feature, design decision, threshold, workaround, or architectural choice exists by tracing evidence across the sources available to ChatGPT. Use for 'why does X work this way', 'why did we choose Y', design rationale, regressions, postmortems, historical context, and tradeoff questions." --- # Why Investigate why something exists or works the way it does. The goal is to recover the evidence behind a decision, not invent a plausible explanation from the current code. Use this skill for questions like: * "Why was this designed this way?" * "Why do we use X instead of Y?" * "Why does this workaround exist?" * "Why is this limit 500?" * "What caused this regression?" * "What led to this architecture?" * "Was this added for a customer, incident, or technical constraint?" * "What alternatives did we consider?" Use `how` when the question is about what the system does or how it runs. Use `why` when the question is about intent, history, constraints, or tradeoffs. ## Evidence before explanation Do not infer historical intent from the shape of the current code unless no better evidence exists. Look for direct evidence first. Useful sources include: * Git history * commits * pull requests * review comments * GitHub issues * Linear or another issue tracker * design documents * RFCs * ADRs * project notes * team chat * incident reports * error tracking * observability data * product analytics * code comments and tests when they record a constraint Use whatever sources ChatGPT can access in the current conversation. If the user names a repository, ticket, PR, document, incident, or other source that is accessible, inspect it before answering. Do not ask the user to paste information that is already available through a connected source. ## Start with the target Pin down what decision you are investigating. The target may be: * a function * a class * a configuration value * a feature * an API * an architectural pattern * a guard or workaround * a database field * a retry policy * a timeout * a threshold * a deleted or legacy path * a change in behavior Find the concrete code or artifact first when one exists. Record the important names that can lead you into the history: * file paths * symbols * configuration keys * commit hashes * PR numbers * issue IDs * feature names * error messages * customer or project names already present in the source These are search terms, not conclusions. ## Follow the evidence trail Start with the source closest to the implementation. For code, this usually means: 1. Find the relevant file and symbol. 2. Find commits that changed it. 3. Find the PRs connected to those commits. 4. Read the PR description and discussion. 5. Follow linked issues, tickets, documents, and incidents. 6. Search other connected sources using the concrete names you found. A useful clue should lead to the next source. For example: ```text code -> commit -> PR -> Linear ticket -> design document -> incident ``` Do not search every source using only the broad feature name when a commit, ticket ID, error string, or exact symbol gives you a better query. ## Search the sources that matter Use available connected sources when they can contain part of the answer. ### Source control Look for: * commit messages * PR descriptions * review comments * linked issues * reverted changes * earlier implementations * tests added with the change * comments that name a constraint Source control is often the strongest evidence because it sits close to the change that shipped. ### Issue trackers Look for: * the original problem statement * acceptance criteria * customer requests * scope changes * parent initiatives * bug reports * linked incidents * implementation discussion Tickets often explain the product or business reason better than the code does. ### Long-form documents Look for: * RFCs * ADRs * design docs * PRDs * postmortems * meeting notes * architecture documents These are especially useful for alternatives considered and rejected. ### Team chat When available, look for: * the feature name * PR links * ticket IDs * error messages * discussion near the date of the change * incident channels * conversations involving the authors or reviewers Chat often contains decisions that never made it into the formal record. ### Error and observability data Use these when the target looks like a response to runtime behavior. Examples include: * retries * timeouts * circuit breakers * null guards * rate limits * memory limits * backoff * defensive checks * feature flags Look for errors, incidents, metric changes, or release correlations that line up with the code change. ### Product data Use product analytics when a threshold, rollout, experiment, or user behavior may have shaped the decision. Look for evidence such as: * usage distributions * experiment results * feature adoption * traffic levels * data volumes * rollout dates Do not invent a data-driven rationale just because a number looks deliberate. ## Treat missing evidence as missing evidence A search that finds nothing is useful. Say which source you checked and that it did not contain evidence for the decision. Do not turn an empty search into: "therefore the decision was probably made informally." That is still an inference. The correct answer may be: "We can see when this changed and what it does, but I could not find a recorded reason for choosing this design." That is better than a convincing story with no source behind it. ## Separate fact from inference Keep three levels clear. ### Direct evidence The source explicitly states the reason. Examples: * a PR says the old implementation caused duplicate charges * a ticket says a customer requires a 15 minute grace period * a postmortem says retries caused duplicate writes State these confidently and cite the source. ### Strong inference Several pieces of evidence point to the same conclusion, but nobody states it directly. Say: * "This appears to have been..." * "The evidence suggests..." * "The most likely reason is..." Then explain the evidence. ### Unknown The record does not support an answer. Say so. Do not promote an inference to fact because it sounds sensible. ## Check chronology Dates matter. Build the smallest useful timeline when several sources are involved. For example: ```text 12 May production errors increase 14 May ticket created 16 May PR opened 18 May fix merged 19 May errors stop ``` Chronology can support a conclusion, but correlation alone does not prove intent. A change merging after an incident does not automatically mean the incident caused it. Look for the link in a PR, ticket, comment, or document. ## Look for alternatives When the question asks why X instead of Y, find evidence that Y was actually considered. Do not manufacture rejected alternatives from your own architecture knowledge. Distinguish: * an alternative the team explicitly considered * an alternative that existed in an earlier implementation * an alternative you think would have been possible Only the first two are historical evidence. You may discuss the third as your own analysis, but label it separately. ## Surface contradictions History is messy. A ticket may say one thing while the merged PR does another. A design document may describe an approach that was abandoned during implementation. A comment may claim a workaround is temporary even though it became permanent. When sources disagree, show the disagreement. Do not silently choose the cleaner story. Prefer the source closest to the final decision when judging what actually shipped, but preserve earlier sources when they explain how the decision changed. ## Handle current code carefully The current implementation can tell you: * what exists now * what behavior survived * what assumptions are encoded * what constraints tests enforce It cannot reliably tell you why those choices were originally made. Do not write: "The code uses a queue because the team wanted loose coupling." unless a source says that. The safe version is: "The current design uses a queue between X and Y. I found no source that records why that choice was made." ## For regressions and incidents When investigating a regression, answer a slightly different question. Find: * the last known good behavior * the change that altered it * what that change was trying to achieve * the failure it introduced * when the failure became visible * whether earlier fixes were attempted * whether any fix was reverted * what remains unresolved Keep cause and motivation separate. A PR may have had a valid goal and still introduced the regression. ## For thresholds and constants When investigating a number such as a timeout, limit, grace period, or batch size, search for the number itself as well as the symbol that contains it. Look in: * git history * PR discussion * tickets * documents * incidents * dashboards * analytics If you cannot find where the number came from, say that the value is unexplained. Do not reverse-engineer a neat justification from the number. ## Answer structure Lead with the best-supported answer. For a small question, a few paragraphs may be enough. For a larger investigation, use this shape when it helps. ### What we know State the reason supported by direct evidence. ### Evidence Walk through the important sources in chronological or causal order. Do not dump every search result. ### What changed Explain how the decision evolved when the record shows more than one design. ### Confidence Say whether the conclusion is: * directly documented * strongly supported * plausible but unproven * unknown Explain the gap when confidence is limited. ### Open questions Include only unresolved questions that materially affect the conclusion. ## Citations Cite the source behind claims about intent. Prefer specific references such as: * PR number * issue or ticket ID * commit * document * chat thread * incident * error-tracker issue When ChatGPT can provide a native citation, use it. A reader should be able to trace the important claims back to evidence. ## Writing Apply the `unslop` skill to the final answer. Use plain language. Do not turn the investigation into detective-roleplay. Do not pad weak evidence with confident prose. Do not narrate every search you performed. Give the user the reason, the evidence, the uncertainty, and any contradiction that matters. Reply with the investigation itself, not a report about the workflow.
Package details
Publisher declarations from the archived package. These are separate from our research and the live service's terms.
- Package license
- MIT
- Package author
- FetchUpstream
- Keywords
- See publisher keywords
Package observed Oct 3, 2026.
Technical details
- First seen
- Sep 30, 2026 · 22:02 UTC
- Last seen
- Oct 3, 2026 · 18:00 UTC
- Collection status
- Collected
plugins_6a85a87df50c8191bd7f010bb7b17794
Download plugin data (JSON)Before you connect pstack
How do I connect it?
Open the publisher's marketplace listing to check current availability and follow its connection instructions. This directory does not install plugins. Check the requested access and any account requirements before connecting.
Check marketplace availability ↗
Does it require paid access?
We have not established the pricing or subscription requirements for this plugin. An absent price does not mean free access.
Compare researched pricing and access models →
How can I evaluate it?
Check the declared skills and available files, then try a small task whose result you can verify. Our archived descriptions and instructions establish publisher claims, not tested runtime quality. Review sources and coverage limits.