diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json deleted file mode 100644 index 224097e..0000000 --- a/.agents/plugins/marketplace.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "propulsion", - "interface": { - "displayName": "Propulsion", - "developerName": "Moon Pixels" - }, - "plugins": [ - { - "name": "propulsion", - "source": { - "source": "url", - "url": "https://github.com/moonpixels/propulsion.git", - "ref": "main" - }, - "policy": { - "installation": "AVAILABLE", - "authentication": "ON_INSTALL" - }, - "category": "Coding" - } - ] -} diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json deleted file mode 100644 index 7e56420..0000000 --- a/.codex-plugin/plugin.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "propulsion", - "version": "1.2.0", - "description": "Opinionated agentic coding workflow that guides software work from exploration and planning through execution and review.", - "author": { - "name": "Moon Pixels" - }, - "homepage": "https://github.com/moonpixels/propulsion", - "repository": "https://github.com/moonpixels/propulsion", - "license": "MIT", - "keywords": [ - "propulsion", - "agentic-coding", - "software-development", - "skills", - "workflow", - "exploration", - "planning", - "execution", - "review", - "brainstorm", - "interrogate", - "plan", - "execute", - "debug", - "tdd", - "debugging", - "prd", - "developer-tools" - ], - "skills": "./skills/", - "hooks": "./hooks/hooks.json", - "interface": { - "displayName": "Propulsion", - "shortDescription": "Opinionated workflow for agentic software development.", - "longDescription": "Propulsion automatically guides ordinary software requests through an opinionated agentic coding workflow: explore the codebase, resolve scope, create a plan, execute in focused slices, and review the result before handoff. It keeps agents grounded in repo context, explicit decisions, tests, and review loops.", - "developerName": "Moon Pixels", - "category": "Coding", - "capabilities": ["Interactive", "Read", "Write"], - "websiteURL": "https://github.com/moonpixels/propulsion", - "defaultPrompt": [ - "Implement social auth with Google and GitHub", - "Update the app to support team workspaces and role-based access", - "Fix the bug causing saved settings to reset after refresh" - ], - "brandColor": "#FF4F00", - "composerIcon": "./assets/propulsion_icon_square.png", - "logo": "./assets/propulsion_icon_square.png", - "screenshots": [] - } -} diff --git a/.gitignore b/.gitignore index 7092f6e..fe21d4d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ .DS_Store .idea /node_modules -/docs/propulsion \ No newline at end of file +/docs \ No newline at end of file diff --git a/.oxfmtrc.json b/.oxfmtrc.json index 398f676..553cf6c 100644 --- a/.oxfmtrc.json +++ b/.oxfmtrc.json @@ -2,6 +2,7 @@ "$schema": "./node_modules/oxfmt/configuration_schema.json", "ignorePatterns": ["node_modules/**", ".opencode/node_modules/**"], "printWidth": 80, + "proseWrap": "never", "tabWidth": 4, "singleQuote": true, "sortImports": { diff --git a/AGENTS.md b/AGENTS.md index 1e63dad..38f53f3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,3 +1,3 @@ - When the user corrects you with a reusable, global rule, ask if they want it added to `AGENTS.md`. +- When authoring or reviewing a skill, justify its behaviour using only context available to the agent at runtime. - After implementing changes run `bun run checks` before handoff. -- When raising a PR, update `package.json` to the appropriate semantic version for the PR contents and keep mirrored manifest versions in sync. diff --git a/CONTEXT.md b/CONTEXT.md new file mode 100644 index 0000000..ecd1e63 --- /dev/null +++ b/CONTEXT.md @@ -0,0 +1,135 @@ +# Propulsion + +Propulsion is an agentic coding workflow composed of skills that steer a coding agent through repeatable engineering work. + +## Language + +**Predictability**: The degree to which a skill makes the agent follow the same process on every run, without requiring the same output.\ +_Avoid_: Consistency, output determinism + +**User-invoked skill**: A skill the user selects explicitly. This is the default skill type in Propulsion.\ +_Avoid_: Manual skill, command + +**Model-invoked skill**: A skill the agent may select autonomously or invoke from another skill. Use this exception only when autonomous discovery would naturally help during ordinary coding work often enough to earn its permanent context cost.\ +_Avoid_: Automatic skill + +**Invocation policy**: Client-specific metadata within a skill bundle that controls whether an agent may select that skill implicitly. The same intent may require different policy fields in different clients.\ +_Avoid_: Invocation flag, frontmatter setting + +**Skill-only distribution**: Distributing Propulsion directly as Agent Skills, using the skills installer for remote sources and filesystem links for local sources. Propulsion does not require client-specific plugin packaging.\ +_Avoid_: Plugin distribution + +**Elicitation**: Requirements elicitation adapted to establish discoverable facts, resolve a dependency-ordered decision tree with the user, and confirm shared understanding before downstream action.\ +_Avoid_: Interrogation, clarification + +**Theoretical saturation**: The point at which further elicitation within the agreed scope reveals no new material decisions, allowing the shared understanding to be presented for confirmation.\ +_Avoid_: Question limit, exhaustive questioning + +**Main success scenario**: The representative invocation path that delivers a skill's intended outcome and remains dominant during design, refinement, and forward testing.\ +_Avoid_: Every possible path, exhaustive scenario set + +**Material exception**: A non-common path that earns explicit skill behaviour because representative evidence, the main success scenario, or a necessary safety or permission boundary requires it. Speculative variation remains agent judgement.\ +_Avoid_: Edge case, hypothetical branch + +### Skill anatomy + +**Authoring workflow**: A skill that guides an agent through creating or updating another skill with an explicit process. It makes execution predictable without prescribing the authored skill's outcome.\ +_Avoid_: Design guide, skill reference + +**Composable skill**: An independently useful skill that may be invoked alone or coordinated by another skill without requiring the rest of a prescribed workflow.\ +_Avoid_: Workflow stage, mandatory step + +**Router skill**: A lightweight skill that invokes other skills to produce a combined outcome. It contains only coordination unique to that outcome; called skills remain authoritative and the router neither repeats nor overrides their context.\ +_Avoid_: Pipeline skill + +**Implement skill**: The user-invoked workflow that uses tracer bullets to deliver a clear implementation request in verified slices, applying TDD when appropriate. It remediates code-review findings until verified and elicits user intent when a finding would change behaviour, contracts, architecture, or scope. + +**TDD skill**: The model-invoked workflow that applies red-green-refactor when an existing runnable test suite can exercise the behaviour change through a stable public seam. It uses Test Desiderata to favour valuable tests that respond to behaviour without coupling to code structure. + +**Code-review skill**: The model-invoked workflow that assesses a scoped code change independently for requirements and code health, then reports evidence-validated findings including code smells and refactor opportunities without changing the code.\ +_Avoid_: Review skill + +**Review-architecture skill**: The user-invoked workflow that analyses a project's architecture and produces an HTML report of high-value, context-aware redesign opportunities without changing the implementation.\ +_Avoid_: Improve-architecture skill + +**Architecture review report**: A single-file interactive artifact named `docs/architecture/YYYYMMDD-{scope}-architecture-review.html` that guides the user through a small set of prioritised recommendations in concise plain language. It uses visualisation and progressive disclosure to explain affected architecture, expected improvements, evidence, and trade-offs without presenting a wall of technical detail. Verified CDN dependencies may supply scripts, styles, fonts, and diagram libraries.\ +_Avoid_: Static architecture audit + +**Architecture module**: A cohesive capability with a small explicit contract and a hidden implementation. Other modules depend on the contract rather than its internal classes, adapters, or framework wiring.\ +_Avoid_: Directory, namespace + +**Deep module**: An architecture module whose small, stable interface hides substantial cohesive implementation. The implementation may be decomposed into focused internal actions for reuse and maintainability without exposing that decomposition to consumers.\ +_Avoid_: Large class, shallow module + +**Debug skill**: The model-invoked workflow that reproduces a code issue, establishes its root cause, applies the smallest correction, and verifies the result. An explicit diagnosis-only request stops before mutation.\ +_Avoid_: Diagnose skill + +**Maintain-agents skill**: The user-invoked workflow that creates or aggressively compresses the root `AGENTS.md` into project-wide runtime guidance and one canonical completion check. It removes narrower workflows from permanent context and reports their appropriate destinations. + +**Define-product skill**: The user-invoked workflow that inspects existing product knowledge, composes contextual elicitation and conditional research, and maintains a root `PRODUCT.md` plus canonical language in `CONTEXT.md`. Concise strategic framing leads into a journey-organised catalogue of high-level feature descriptions without becoming a delivery plan. + +**Primary source**: Original high-trust evidence such as official documentation, source code, standards, publications, first-party APIs, or first-party data. Secondary sources may aid discovery but findings trace their claims back to primary evidence.\ +_Avoid_: Trusted write-up + +**Research report**: A cited Markdown snapshot named `docs/research/YYYYMMDD-{research-title}.md` that answers a research question from primary evidence and records its scope, findings, and unresolved limitations. Substantive re-research creates a linked superseding snapshot; minor corrections update the existing report and its metadata.\ +_Avoid_: Research answer + +**Research skill**: The model-invoked rapid evidence assessment workflow that gives a fresh agent ownership of primary-source discovery, appraisal, synthesis, and report writing. The caller verifies the cited research report and receives its concise findings; other skills invoke it only when the evidence warrants that durable record.\ +_Avoid_: Web search + +**Description**: A concise statement of what a skill does and the conditions under which it should be invoked.\ +_Avoid_: Summary, tagline + +**Skill name**: A short command that states the skill's action and fits naturally into a user instruction. Prefer one imperative verb, then a short imperative phrase, with established nouns reserved for operations they already name clearly.\ +_Avoid_: Title, label + +**Branch**: A distinct route through a skill for a particular use case or condition. Branches share the skill's common process without duplicating it.\ +_Avoid_: Separate workflow, mode + +**Process section**: The required `## Process` section that contains a skill's instructions. It uses numbered subheadings only when order matters and descriptive subheadings or direct prose otherwise.\ +_Avoid_: Steps section, instructions section + +**Leading word**: A recognised term from an established method, principle, theory, or technique, specific enough to invoke the agent's existing knowledge without further explanation. A skill explains only its context-specific adaptation or constraints.\ +_Avoid_: Coined term, theme, slogan + +**Governing methodology**: An established methodology selected through research to determine a skill's process when one credibly fits. Research may conclude that none is suitable; a selected methodology appears by canonical name in the skill without source attribution.\ +_Avoid_: Core concept, main theme + +**Supporting concept**: An established principle, theory, or technique that reinforces the governing methodology for a distinct concern without competing with it.\ +_Avoid_: Secondary concept + +**Skills plan**: The self-contained high-level handoff for Propulsion's fixed v1 skill suite. It records suite principles, the skill catalogue and standard briefs, composition and invocation, implementation order, and acceptance criteria without carrying source citations, discarded scope, or finished skill instructions.\ +_Avoid_: Skill specification, backlog + +**Lossless compression**: Reducing a skill to the fewest words and structures that preserve its behaviour, conditions, constraints, and technical meaning.\ +_Avoid_: Trimming, shortening, minimalism + +**Degrees of freedom**: The amount of judgement a skill leaves to the agent. Match it to the work's fragility so the process is predictable without predetermining valid outcomes.\ +_Avoid_: Flexibility, strictness + +**Ironic process theory**: The tendency for a negated concept to become more salient. Skills state the positive target behaviour and pair an essential safety boundary with the safe action that satisfies it.\ +_Avoid_: Prohibition-only rule, negative prompting + +**Prerequisite**: A condition that must be true before a skill can begin. Its failure stops the skill or routes the work elsewhere.\ +_Avoid_: Setup step, pre-flight check + +**Step**: A numbered subheading used when actions within a process or branch must occur in order. It isolates one coherent behavioural concern, describes the action, and ends in an observable postcondition.\ +_Avoid_: Instruction, rule + +**Postcondition**: An observable state that marks a step complete without requiring a separate completion section.\ +_Avoid_: Completion criterion, completion gate + +**Rule**: A cross-cutting invariant that constrains multiple instructions or the finished output.\ +_Avoid_: Step, reminder + +**Handoff**: A transfer or route that becomes available after the skill's process is complete.\ +_Avoid_: Next step, final step + +**Reference**: Conditional or extensive runtime guidance linked once beside a precise loading condition. The agent loads it only when that branch or decision needs the additional depth.\ +_Avoid_: Background, resource + +**Acceptance testing**: A semantic validation that traces every elicited invocation through a finished skill's branches, resource pointers, and observable postconditions.\ +_Avoid_: Checklist, structural validation + +**Characterization testing**: Capturing an existing skill's observable invocation and process before improvement so intentional changes remain distinct from regressions.\ +_Avoid_: Snapshot, preservation rule diff --git a/README.md b/README.md index 667f266..5bc3e80 100644 --- a/README.md +++ b/README.md @@ -6,54 +6,72 @@ Propulsion is a compact skill set for agentic coding. It gives coding agents a s ## Installation -### Codex CLI +### Remote -Add the Propulsion marketplace: +Install Propulsion from GitHub with the skills installer: ```sh -codex plugin marketplace add moonpixels/propulsion +bunx skills@latest add moonpixels/propulsion ``` -Open Codex, run `/plugins`, select the Propulsion marketplace, install -Propulsion, then restart Codex. +Choose the skills and coding agents you want when prompted. -To update: +### Local + +When developing Propulsion from a local clone, link each skill you want to use into the shared Agent Skills directory: ```sh -codex plugin marketplace upgrade propulsion +mkdir -p ~/.agents/skills +ln -s /absolute/path/to/propulsion/skills/elicit ~/.agents/skills/elicit ``` -### Codex Desktop +Repeat the link for each selected skill. Codex and OpenCode both discover skills from `~/.agents/skills`; edits in the clone are available through the links without reinstalling or publishing a new version. -Add the Propulsion marketplace with the Codex CLI: +## Usage -```sh -codex plugin marketplace add moonpixels/propulsion -``` +Propulsion skills are independently invocable. For most feature and change requests, use this recommended workflow: -Open the desktop app's Plugins page, select the Propulsion marketplace, install -Propulsion, then restart the app. +1. Shape the idea with `$elicit-with-context` until the request is understood and confirmed. -To update: + ```text + $elicit-with-context Help me work through an idea for . + ``` -```sh -codex plugin marketplace upgrade propulsion +2. Implement the confirmed request with `$implement`. + + ```text + $implement the request we just confirmed. + ``` + +3. Review the working-tree changes yourself. Ask the agent to explain or adjust anything necessary, and repeat until you are satisfied with the result. + +4. Commit the reviewed changes, then create the pull request. + + ```text + $commit the reviewed changes. + Create a $pr for the current branch. + ``` + +### Alternative entry points + +For a bug, start with `$debug` instead of elicitation and implementation: + +```text +$debug Fix . ``` -### OpenCode +After the repair, rejoin the recommended workflow at human review, followed by `$commit` and `$pr`. -Add Propulsion to `opencode.json`: +For codebase improvements, start with `$review-architecture` to produce an architecture report: -```json -{ - "$schema": "https://opencode.ai/config.json", - "plugin": ["propulsion@git+https://github.com/moonpixels/propulsion.git"] -} +```text +$review-architecture Review for high-value architecture improvements. ``` +Review the report, then take each accepted recommendation through the recommended workflow separately, beginning with `$elicit-with-context`. + ## Acknowledgements Propulsion is heavily inspired by: -- [obra/superpowers](https://github.com/obra/superpowers) for workflow discipline, review loops, debugging process, and OpenCode plugin ideas - [mattpocock/skills](https://github.com/mattpocock/skills) for brevity, wording discipline, and the question-by-question discovery style diff --git a/bun.lock b/bun.lock index 24e4053..050f596 100644 --- a/bun.lock +++ b/bun.lock @@ -5,106 +5,106 @@ "": { "name": "propulsion", "devDependencies": { - "oxfmt": "^0.44.0", - "oxlint": "^1.62.0", - "oxlint-tsgolint": "^0.20.0", + "oxfmt": "^0.59.0", + "oxlint": "^1.74.0", + "oxlint-tsgolint": "^0.24.0", }, }, }, "packages": { - "@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.44.0", "", { "os": "android", "cpu": "arm" }, "sha512-5UvghMd9SA/yvKTWCAxMAPXS1d2i054UeOf4iFjZjfayTwCINcC3oaSXjtbZfCaEpxgJod7XiOjTtby5yEv/BQ=="], + "@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.59.0", "", { "os": "android", "cpu": "arm" }, "sha512-bNTnfbuG7sAwb2PakMNaDukx5kXeW9duXOBeWtTOiLz3fXz3q2DlWguufPZ+c2IHEVrRXHD+M4aUgEWm841LDA=="], - "@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.44.0", "", { "os": "android", "cpu": "arm64" }, "sha512-IVudM1BWfvrYO++Khtzr8q9n5Rxu7msUvoFMqzGJVdX7HfUXUDHwaH2zHZNB58svx2J56pmCUzophyaPFkcG/A=="], + "@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.59.0", "", { "os": "android", "cpu": "arm64" }, "sha512-R/Sn7z52QtdAKNqQLLY0EK7hVMjXiz3XUlvoCFCm/60jgIzAnQtiqLKBCFaBkimCQL5rs2ezPMcicpjCsrl54Q=="], - "@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.44.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-eWCLAIKAHfx88EqEP1Ga2yz7qVcqDU5lemn4xck+07bH182hDdprOHjbogyk0In1Djys3T0/pO2JepFnRJ41Mg=="], + "@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.59.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-vm/ynUqE4HjC0ZIEjmXv1UJu1/GngccQ+T+TJudTMxUxm6r+GQTg1TO3E5jJfI71pBaXxSzs1+vWHIwuilGHhw=="], - "@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.44.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-eHTBznHLM49++dwz07MblQ2cOXyIgeedmE3Wgy4ptUESj38/qYZyRi1MPwC9olQJWssMeY6WI3UZ7YmU5ggvyQ=="], + "@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.59.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-uTtYDpLN/obfKVWGpgEc8BqYlLZBQTPz2uYEvLRy3HPZxjZ34wiFzukUBU2bf64JuCYZI//GTV1EOMmWlPjf/w=="], - "@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.44.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jLMmbj0u0Ft43QpkUVr/0v1ZfQCGWAvU+WznEHcN3wZC/q6ox7XeSJtk9P36CCpiDSUf3sGnzbIuG1KdEMEDJQ=="], + "@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.59.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-e2UnxL/ifStSPy8ffBCDbdy595SYsGy+U1pur4G65TuMmWxAMBzYGG7atZo/3mp515p8rZdsflxVD/E1FAdPLQ=="], - "@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.44.0", "", { "os": "linux", "cpu": "arm" }, "sha512-n+A/u/ByK1qV8FVGOwyaSpw5NPNl0qlZfgTBqHeGIqr8Qzq1tyWZ4lAaxPoe5mZqE3w88vn3+jZtMxriHPE7tg=="], + "@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-LtdeZ1l0urxte3VNi3g8cocZwv1xGM1NKHSgF/fJEEVhyQmlgGh7WFWKFd/pNuO7djfvPNtNO1+MS+FEWkgVSA=="], - "@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.44.0", "", { "os": "linux", "cpu": "arm" }, "sha512-5eax+FkxyCqAi3Rw0mrZFr7+KTt/XweFsbALR+B5ljWBLBl8nHe4ADrUnb1gLEfQCJLl+Ca5FIVD4xEt95AwIw=="], + "@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-dBTciSsj9GTMl7p+h2gMSI0hoPn2ijfc/dUsbnWsP0RbwgPl2r0C/5zkMb3Pb+gGj17LH7f1o4qLo9aes/pAvA=="], - "@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.44.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-58l8JaHxSGOmOMOG2CIrNsnkRJAj0YcHQCmvNACniOa/vd1iRHhlPajczegzS5jwMENlqgreyiTR9iNlke8qCw=="], + "@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-tXVdJ/JINsNWdponPHN0OuKHtC+HdpyoS9sd6IDPNiiEYsRki8b7tefRZ1iMnRkdbyT4SEbguWsr6o+5awvbPQ=="], - "@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.44.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-AlObQIXyVRZ96LbtVljtFq0JqH5B92NU+BQeDFrXWBUWlCKAM0wF5GLfIhCLT5kQ3Sl+U0YjRJ7Alqj5hGQaCg=="], + "@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-RRTq38i2zT5fnw6XGHjvT6w2mh6x/G3m6AZcAZ56OTDTT/lsOeYnG3SVjwmH40z5kPqF+lf+o35e6m6PpKy9Dw=="], - "@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.44.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-YcFE8/q/BbrCiIiM5piwbkA6GwJc5QqhMQp2yDrqQ2fuVkZ7CInb1aIijZ/k8EXc72qXMSwKpVlBv1w/MsGO/A=="], + "@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-lD3k7glAJSaXW0D6xzu8VOZbYbosvy+0ktOVkfLEoQF5HJlMSxTQ2KNW0JO+08ccP/1ElOKktVEMI0fqRbVB4w=="], - "@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.44.0", "", { "os": "linux", "cpu": "none" }, "sha512-eOdzs6RqkRzuqNHUX5C8ISN5xfGh4xDww8OEd9YAmc3OWN8oAe5bmlIqQ+rrHLpv58/0BuU48bxkhnIGjA/ATQ=="], + "@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-WH5ZP1RbuHKBO/yfPRQKpNO/ijHcEDNbnmC4VPf/Bcd3+mbMAZpRiJWRa1PL5bREdIZZHo343mk3sqlc9x7Usw=="], - "@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.44.0", "", { "os": "linux", "cpu": "none" }, "sha512-YBgNTxntD/QvlFUfgvh8bEdwOhXiquX8gaofZJAwYa/Xp1S1DQrFVZEeck7GFktr24DztsSp8N8WtWCBwxs0Hw=="], + "@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-743wOiaI9RZY4QVGkWkfGRavD5ZJUJ6gscFjVrVu1dP8AZh9jM+a6v3NhlR+OIzHdS6DhLM96w+gcVskskz7rw=="], - "@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.44.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-GLIh1R6WHWshl/i4QQDNgj0WtT25aRO4HNUWEoitxiywyRdhTFmFEYT2rXlcl9U6/26vhmOqG5cRlMLG3ocaIA=="], + "@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.59.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-xjRXQsRnrRZCcCkIEnbd2lmsQNobtwwkJxdy2bWXhZ1lIN0ouZwsBXRsoovW3yATuziAYwr9HMiQuR/Cc75NIw=="], - "@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.44.0", "", { "os": "linux", "cpu": "x64" }, "sha512-gZOpgTlOsLcLfAF9qgpTr7FIIFSKnQN3hDf/0JvQ4CIwMY7h+eilNjxq/CorqvYcEOu+LRt1W4ZS7KccEHLOdA=="], + "@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-4hNjqq/Rbr9B+StY9zMMAfm72+mtM4v80xYL5Qkb59Qd72g2vJMI0iFlPj3kf6miMsie/yJ7rt4urJT292HBgA=="], - "@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.44.0", "", { "os": "linux", "cpu": "x64" }, "sha512-1CyS9JTB+pCUFYFI6pkQGGZaT/AY5gnhHVrQQLhFba6idP9AzVYm1xbdWfywoldTYvjxQJV6x4SuduCIfP3W+A=="], + "@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-NH579iN8EVQYsWowUB8B5vFchcylJtwPVJ7NmUAqEQHNLfhPbDT3K56KrECNAkUN4QpF4qiMgN2vsfZwVvjm7g=="], - "@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.44.0", "", { "os": "none", "cpu": "arm64" }, "sha512-bmEv70Ak6jLr1xotCbF5TxIKjsmQaiX+jFRtnGtfA03tJPf6VG3cKh96S21boAt3JZc+Vjx8PYcDuLj39vM2Pw=="], + "@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.59.0", "", { "os": "none", "cpu": "arm64" }, "sha512-mzZy3Z5Aj1D75Aq9FVlmoRQH5ei8Ga4o/NZmlXkKyeZ5EmPrUXRR7c6BMBteV1ZuZ/356UYDuLRLjAMxTDTiBA=="], - "@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.44.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-yWzB+oCpSnP/dmw85eFLAT5o35Ve5pkGS2uF/UCISpIwDqf1xa7OpmtomiqY/Vzg8VyvMbuf6vroF2khF/+1Vg=="], + "@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.59.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-0CpDJ1gE3jN1Gk6xms1Ie6LPfPcOtY4FAtoOmVLHQoAf8DvO2wd0DW2dIX2f7YTp5dxrr0ND8JeUEjm3DP3k5g=="], - "@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.44.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-TcWpo18xEIE3AmIG2kpr3kz5IEhQgnx0lazl2+8L+3eTopOAUevQcmlr4nhguImNWz0OMeOZrYZOhJNCf16nlQ=="], + "@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.59.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-zwdKBu3pt87uW0bRcywZb0oGMS7C6n87qogwRYFUgmk44T90ZzYlPjtlFYXs/DnBFrgNCvlHwCuWKfVWLeE7kw=="], - "@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.44.0", "", { "os": "win32", "cpu": "x64" }, "sha512-oj8aLkPJZppIM4CMQNsyir9ybM1Xw/CfGPTSsTnzpVGyljgfbdP0EVUlURiGM0BDrmw5psQ6ArmGCcUY/yABaQ=="], + "@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-dUUbZkKgWrmAeI/puzv4bxN8lzcYaFnQVwFTFtwO2Gp8M7lZGSE2qJjC58g518+1bltJ8mizjYwD0BGHym0l/w=="], - "@oxlint-tsgolint/darwin-arm64": ["@oxlint-tsgolint/darwin-arm64@0.20.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-KKQcIHZHMxqpHUA1VXIbOG6chNCFkUWbQy6M+AFVtPKkA/3xAeJkJ3njoV66bfzwPHRcWQO+kcj5XqtbkjakoA=="], + "@oxlint-tsgolint/darwin-arm64": ["@oxlint-tsgolint/darwin-arm64@0.24.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-C2uMmwK5Bc4ri4ysZ6sA8Rcu+A5zBQTp6ml2u0CLLbRZp4kMFPV3yWk8B5DK9Aw7y9bbjogIm75tUwGLFzlsYQ=="], - "@oxlint-tsgolint/darwin-x64": ["@oxlint-tsgolint/darwin-x64@0.20.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-7HeVMuclGfG+NLZi2ybY0T4fMI7/XxO/208rJk+zEIloKkVnlh11Wd241JMGwgNFXn+MLJbOqOfojDb2Dt4L1g=="], + "@oxlint-tsgolint/darwin-x64": ["@oxlint-tsgolint/darwin-x64@0.24.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Wgvt/1lRbDxmoNqWQKKcL+UIiqLmdJ+EWLpQa1qzoNVAfNB0PJpa82/8dH1twT/3rSs4zrP5TXPWl4juB71WuQ=="], - "@oxlint-tsgolint/linux-arm64": ["@oxlint-tsgolint/linux-arm64@0.20.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-zxhUwz+WSxE6oWlZLK2z2ps9yC6ebmgoYmjAl0Oa48+GqkZ56NVgo+wb8DURNv6xrggzHStQxqQxe3mK51HZag=="], + "@oxlint-tsgolint/linux-arm64": ["@oxlint-tsgolint/linux-arm64@0.24.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-PB1rxII7KV83+ASY4sSkXtqvpij6ME66+QCRL49uksi/ofs2Rf/UVboYr095n0Rkbl2wgvlsHGl6DHC361jQUQ=="], - "@oxlint-tsgolint/linux-x64": ["@oxlint-tsgolint/linux-x64@0.20.0", "", { "os": "linux", "cpu": "x64" }, "sha512-/1l6FnahC9im8PK+Ekkx/V3yetO/PzZnJegE2FXcv/iXEhbeVxP/ouiTYcUQu9shT1FWJCSNti1VJHH+21Y1dg=="], + "@oxlint-tsgolint/linux-x64": ["@oxlint-tsgolint/linux-x64@0.24.0", "", { "os": "linux", "cpu": "x64" }, "sha512-xcz3CxKmjTQLREtE/UShh+ruWmm9nAb7UM9zKcD65BStiuYgOakAKkPHl4YS5DztpVcDrE0+HqbOolTlRKYWmw=="], - "@oxlint-tsgolint/win32-arm64": ["@oxlint-tsgolint/win32-arm64@0.20.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-oPZ5Yz8sVdo7P/5q+i3IKeix31eFZ55JAPa1+RGPoe9PoaYVsdMvR6Jvib6YtrqoJnFPlg3fjEjlEPL8VBKYJA=="], + "@oxlint-tsgolint/win32-arm64": ["@oxlint-tsgolint/win32-arm64@0.24.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-A2i6ZGBec3i20S7RaxkgHc6r3HYtD5Mn7j/mb22NkTz14u0JuudvTu6JggAnbGMcv8+dBKQI//EasxSPJLD8pw=="], - "@oxlint-tsgolint/win32-x64": ["@oxlint-tsgolint/win32-x64@0.20.0", "", { "os": "win32", "cpu": "x64" }, "sha512-4stx8RHj3SP9vQyRF/yZbz5igtPvYMEUR8CUoha4BVNZihi39DpCR8qkU7lpjB5Ga1DRMo2pHaA4bdTOMaY4mw=="], + "@oxlint-tsgolint/win32-x64": ["@oxlint-tsgolint/win32-x64@0.24.0", "", { "os": "win32", "cpu": "x64" }, "sha512-0ZbGd9qRB6zs82moekaKdEvncRANq49EAwfNX62JpTS46feXUhKAuoyVDvZMj6Rywejylrmmu79Wo6faYCo4Ew=="], - "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.62.0", "", { "os": "android", "cpu": "arm" }, "sha512-pKsthNECyvJh8lPTICz6VcwVy2jOqdhhsp1rlxCkhgZR47aKvXPmaRWQDv+zlXpRae4qm1MaaTnutkaOk5aofg=="], + "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.74.0", "", { "os": "android", "cpu": "arm" }, "sha512-+gHd12muVI9ZLBaWLPkHt3Fj7jihFjgQ1MGtBaRL8vWrWrI0P7dLUty/cHrHS0oqPYIRgQUJsPu2CExQuMcwNw=="], - "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.62.0", "", { "os": "android", "cpu": "arm64" }, "sha512-b1AUNViByvgmR2xJDubvLIr+dSuu3uraG7bsAoKo+xrpspPvu6RIn6Fhr2JUhobfep3jwUTy18Huco6GkwdvGQ=="], + "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.74.0", "", { "os": "android", "cpu": "arm64" }, "sha512-xjKdoMB+H+RCOByv/7l7nfIGW9mlOisqYdcyC75UqYuQecLpReAeEYUf2CNeDEI3KtmUgxpRw/+c63y4AeF/Bw=="], - "@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.62.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-iG+Tvf70UJ6otfwFYIHk36Sjq9cpPP5YLxkoggANNRtzgi3Tj3g8q6Ybqi6AtkU3+yg9QwF7bDCkCS6bbL4PCg=="], + "@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.74.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-iUK7wvc6sejMKsC+Pt67mntoF5weFcyEunhZfLJceU6gL419mexz5wBkSx/EnkFBExMLNtOi9fnDSc5xfK0IzQ=="], - "@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.62.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-oOWI6YPPr5AJUx+yIDlxmuUbQjS5gZX3OH3QisawYvsZgLiQVvZtR0rPBcJTxLWqt2ClrWg0DlSrlUiG5SQNHg=="], + "@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.74.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-ggKc/tn5SJ1u2yG2izC6VKODfYKV8MQ2AicJlNzOjuyrC29udvOef6/JzK2r32xqCnBDLFouR1VCkjzEI0/N9Q=="], - "@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.62.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dLP33T7VLCmLVv4cvjkVX+rmkcwNk2UfxmsZPNur/7BQHoQR60zJ7XLiRvNUawlzn0u8ngCa3itjEG73MAMa/w=="], + "@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.74.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-u++dH/43jy9hTLbneaWlS0gla/Bp1JdwJ2zgevCl8nDFUh6qRCGMxcL0f0lb7By3A9p/LfFr+7cG4HU1hG856g=="], - "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.62.0", "", { "os": "linux", "cpu": "arm" }, "sha512-fl//LWNks6qo9chNY60UDYyIwtp7a5cEx4Y/rHPjaarhuwqx6jtbzEpD5V5AqmdL4a6Y5D8zeXg5HF2Cr0QmSQ=="], + "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.74.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Sj1zmtFDVTPeIbIz4ZfcXAbFHqCmKCXdCUlAJzvTF7I20NTH1RDpoF2PhkqNODutJzVhJYmm3oz0GwgY+tvE2g=="], - "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.62.0", "", { "os": "linux", "cpu": "arm" }, "sha512-i5vkAuxvueTODV3J2dL61/TXewDHhMFKvtD156cIsk7GsdfiAu7zW7kY0NJXhKeFHeiMZIh7eFNjkPYH6J47HQ=="], + "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.74.0", "", { "os": "linux", "cpu": "arm" }, "sha512-//PKyQb/tQXcHArx2f7z+oVI/eMS2Jpv+edNuAtOrgIhWdGcpHxogveAxzmF2rpH1AIHp4Hq04RF/rgJdiICnQ=="], - "@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.62.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-QwN19LLuIGuOjEflSeJkZmOTfBdBMlTmW8xbMf8TZhjd//cxVNYQPq75q7oKZBJc6hRx3gY7sX0Egc8cEIFZYg=="], + "@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.74.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-/k1Me+aX2tjuH10K62mLS0y8cLkJBHX6Ce0xPK+eWeel4bSdEGZ8dv4+hYMzg0GrSmjwy4yAYsDPeEeKBft/2w=="], - "@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.62.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-8eCy3FCDuWUM5hWujAv6heMvfZPbcCOU3SdQUAkixZLu5bSzOkNfirJiLGoQFO943xceOKkiQRMQNzH++jM3WA=="], + "@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.74.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-3tFSjBxc5D8/zvjEuLvOqcA8ZXKD0+6NuaVO/edeamNc49MoAsbfaC9s1UiwODwgF6slGaF8yJA2TPkukd77tg=="], - "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.62.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NjQ7K7tpTPDe9J+yq8p/s/J0E7lRCkK2uDBDqvT4XIT6f4Z0tlnr59OBg/WcrmVHER1AbrcfyxhGTXgcG8ytWg=="], + "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.74.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9QggtPkSPXOCTu8Szis7auOK/sC7KdQaN+/TujP7YVVhzCAOhgdRfgv8uEz0r2tk5xdgus5rLYUrCDoZNtiRUw=="], - "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.62.0", "", { "os": "linux", "cpu": "none" }, "sha512-oKZed9gmSwze29dEt3/Wnsv6l/Ygw/FUst+8Kfpv2SGeS/glEoTGZAMQw37SVyzFV76UTHJN2snGgxK2t2+8ow=="], + "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.74.0", "", { "os": "linux", "cpu": "none" }, "sha512-VM5VPUJ4DJIWiK+AZn8FScUqMr6OFrCAYybMYjEEi7W13ParI64MByiXTkKMqZpBmvQ9zxl9Ebq2VUOiZRJYUg=="], - "@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.62.0", "", { "os": "linux", "cpu": "none" }, "sha512-gBjBxQ+9lGpAYq+ELqw0w8QXsBnkZclFc7GRX2r0LnEVn3ZTEqeIKpKcGjucmp76Q53bvJD0i4qBWBhcfhSfGA=="], + "@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.74.0", "", { "os": "linux", "cpu": "none" }, "sha512-SaDY1gh9rOA592J54g+gu5hkOFFQBZsMmIYHs+NRHG+Uq0OxtuuCXMWQ3vu1830Eugv5uMXyjG+bv2Z9y4IXjw=="], - "@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.62.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-Ew2Kxs9EQ9/mbAIJ2hvocMC0wsOu6YKzStI2eFBDt+Td5O8seVC/oxgRIHqCcl5sf5ratA1nozQBAuv7tphkHg=="], + "@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.74.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-ZATQeHZCyr6MbDveg0obD5sxLHFOghtOdC5jwVwYlvFWqtFOxctgFEG6Ef/64hYvZrWyhyCckB10AelqLopeDA=="], - "@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.62.0", "", { "os": "linux", "cpu": "x64" }, "sha512-5z25jcAA0gfKyVwz71A0VXgaPlocPoTAxhlv/hgoK6tlCrfoNuw7haWbDHvGMfjXhdic4EqVXGRv5XsTqFnbRQ=="], + "@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.74.0", "", { "os": "linux", "cpu": "x64" }, "sha512-+aIvJyrdeD7LwCQ2WYLMUWNmnbeDRSPb40aBYtPjD9+PTqUwgJnk+HK5yLfSMeqXrMrDhE9uTmtt2y50tvjhHw=="], - "@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.62.0", "", { "os": "linux", "cpu": "x64" }, "sha512-IWpHmMB6ZDllPvqWDkG6AmXrN7JF5e/c4g/0PuURsmlK+vHoYZPB70rr4u1bn3I4LsKCSpqqfveyx6UCOC8wdg=="], + "@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.74.0", "", { "os": "linux", "cpu": "x64" }, "sha512-XyktaR8lhK2qWiCK0Tk8oYD+/cgn+oHA6ddRnxSSXUKkkojkV78CmShZUxQF+yrBFs0SuW+JBOPG6hecyc/iZg=="], - "@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.62.0", "", { "os": "none", "cpu": "arm64" }, "sha512-fjlSxxrD5pA594vkyikCS9MnPRjQawW6/BLgyTYkO+73wwPlYjkcZ7LSd974l0Q2zkHQmu4DPvJFLYA7o8xrxQ=="], + "@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.74.0", "", { "os": "none", "cpu": "arm64" }, "sha512-mzbjrPl4neaVUiJ1fUiEUxTGaSZBoiKtaoB6jmIpz9S+VOA2vDYmJpihQ82w6178V5jxziclTg8Cgj5yF6tTDg=="], - "@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.62.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-EiFXr8loNS0Ul3Gu80+9nr1T8jRmnKocqmHHg16tj5ZqTgUXyb97l2rrspVHdDluyFn9JfR4PoJFdNzw4paHww=="], + "@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.74.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-vUAe9okpS2Oa5+lX67lqHMuNUvfkleRKwrUDJ/WJBsgmddvZ1mrsh2HVmuFDRzqFELhaJhFaCNOuR6a7L3rtIA=="], - "@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.62.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-IgOFvL73li1bFgab+hThXYA0N2Xms2kV2MvZN95cebV+fmrZ9AVui1JSxfeeqRLo3CpPxKZlzhyq4G0cnaAvIw=="], + "@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.74.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-yyXXJyYYSXL4I8K8jAWjJs+J3fa9gH2JmEbo4f5adm+1tNC9itseicBNuwK7BDHvqQ5J534s+yDULu89vYL2ZQ=="], - "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.62.0", "", { "os": "win32", "cpu": "x64" }, "sha512-6hMpyDWQ2zGA1OXFKBrdYMUveUCO8UJhkO6JdwZPd78xIdHZNhjx+pib+4fC2Cljuhjyl0QwA2F3df/bs4Bp6A=="], + "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.74.0", "", { "os": "win32", "cpu": "x64" }, "sha512-VTC9IYTIMrVUk/i6Ms1ohzzDKZFkWn0KU2OBbPBzgmVZ2V30165T/zK4LztTr0Xgp9fZ1qQZ1rsZAu/rEmySlA=="], - "oxfmt": ["oxfmt@0.44.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.44.0", "@oxfmt/binding-android-arm64": "0.44.0", "@oxfmt/binding-darwin-arm64": "0.44.0", "@oxfmt/binding-darwin-x64": "0.44.0", "@oxfmt/binding-freebsd-x64": "0.44.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.44.0", "@oxfmt/binding-linux-arm-musleabihf": "0.44.0", "@oxfmt/binding-linux-arm64-gnu": "0.44.0", "@oxfmt/binding-linux-arm64-musl": "0.44.0", "@oxfmt/binding-linux-ppc64-gnu": "0.44.0", "@oxfmt/binding-linux-riscv64-gnu": "0.44.0", "@oxfmt/binding-linux-riscv64-musl": "0.44.0", "@oxfmt/binding-linux-s390x-gnu": "0.44.0", "@oxfmt/binding-linux-x64-gnu": "0.44.0", "@oxfmt/binding-linux-x64-musl": "0.44.0", "@oxfmt/binding-openharmony-arm64": "0.44.0", "@oxfmt/binding-win32-arm64-msvc": "0.44.0", "@oxfmt/binding-win32-ia32-msvc": "0.44.0", "@oxfmt/binding-win32-x64-msvc": "0.44.0" }, "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-lnncqvHewyRvaqdrnntVIrZV2tEddz8lbvPsQzG/zlkfvgZkwy0HP1p/2u1aCDToeg1jb9zBpbJdfkV73Itw+w=="], + "oxfmt": ["oxfmt@0.59.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.59.0", "@oxfmt/binding-android-arm64": "0.59.0", "@oxfmt/binding-darwin-arm64": "0.59.0", "@oxfmt/binding-darwin-x64": "0.59.0", "@oxfmt/binding-freebsd-x64": "0.59.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.59.0", "@oxfmt/binding-linux-arm-musleabihf": "0.59.0", "@oxfmt/binding-linux-arm64-gnu": "0.59.0", "@oxfmt/binding-linux-arm64-musl": "0.59.0", "@oxfmt/binding-linux-ppc64-gnu": "0.59.0", "@oxfmt/binding-linux-riscv64-gnu": "0.59.0", "@oxfmt/binding-linux-riscv64-musl": "0.59.0", "@oxfmt/binding-linux-s390x-gnu": "0.59.0", "@oxfmt/binding-linux-x64-gnu": "0.59.0", "@oxfmt/binding-linux-x64-musl": "0.59.0", "@oxfmt/binding-openharmony-arm64": "0.59.0", "@oxfmt/binding-win32-arm64-msvc": "0.59.0", "@oxfmt/binding-win32-ia32-msvc": "0.59.0", "@oxfmt/binding-win32-x64-msvc": "0.59.0" }, "peerDependencies": { "svelte": "^5.0.0", "vite-plus": "*" }, "optionalPeers": ["svelte", "vite-plus"], "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-Xqk6cPZS1yMvVa7OAuenaDZUsgMDutvvbZ9/L5gSvAfW64+WN4HVhgipLj5rVERbYQt8fLs9TopyZ1rU1XEG/w=="], - "oxlint": ["oxlint@1.62.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.62.0", "@oxlint/binding-android-arm64": "1.62.0", "@oxlint/binding-darwin-arm64": "1.62.0", "@oxlint/binding-darwin-x64": "1.62.0", "@oxlint/binding-freebsd-x64": "1.62.0", "@oxlint/binding-linux-arm-gnueabihf": "1.62.0", "@oxlint/binding-linux-arm-musleabihf": "1.62.0", "@oxlint/binding-linux-arm64-gnu": "1.62.0", "@oxlint/binding-linux-arm64-musl": "1.62.0", "@oxlint/binding-linux-ppc64-gnu": "1.62.0", "@oxlint/binding-linux-riscv64-gnu": "1.62.0", "@oxlint/binding-linux-riscv64-musl": "1.62.0", "@oxlint/binding-linux-s390x-gnu": "1.62.0", "@oxlint/binding-linux-x64-gnu": "1.62.0", "@oxlint/binding-linux-x64-musl": "1.62.0", "@oxlint/binding-openharmony-arm64": "1.62.0", "@oxlint/binding-win32-arm64-msvc": "1.62.0", "@oxlint/binding-win32-ia32-msvc": "1.62.0", "@oxlint/binding-win32-x64-msvc": "1.62.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.18.0" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-1uFkg6HakjsGIpW9wNdeW4/2LOHW9MEkoWjZUTUfQtIHyLIZPYt00w3Sg+H3lH+206FgBPHBbW5dVE5l2ExECQ=="], + "oxlint": ["oxlint@1.74.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.74.0", "@oxlint/binding-android-arm64": "1.74.0", "@oxlint/binding-darwin-arm64": "1.74.0", "@oxlint/binding-darwin-x64": "1.74.0", "@oxlint/binding-freebsd-x64": "1.74.0", "@oxlint/binding-linux-arm-gnueabihf": "1.74.0", "@oxlint/binding-linux-arm-musleabihf": "1.74.0", "@oxlint/binding-linux-arm64-gnu": "1.74.0", "@oxlint/binding-linux-arm64-musl": "1.74.0", "@oxlint/binding-linux-ppc64-gnu": "1.74.0", "@oxlint/binding-linux-riscv64-gnu": "1.74.0", "@oxlint/binding-linux-riscv64-musl": "1.74.0", "@oxlint/binding-linux-s390x-gnu": "1.74.0", "@oxlint/binding-linux-x64-gnu": "1.74.0", "@oxlint/binding-linux-x64-musl": "1.74.0", "@oxlint/binding-openharmony-arm64": "1.74.0", "@oxlint/binding-win32-arm64-msvc": "1.74.0", "@oxlint/binding-win32-ia32-msvc": "1.74.0", "@oxlint/binding-win32-x64-msvc": "1.74.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.24.0", "vite-plus": "*" }, "optionalPeers": ["oxlint-tsgolint", "vite-plus"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-odGl2s2x5IOJoj3A0v1k0PGBXVFBZeZ2+AK/+K2MJur7Ghi3bkyX5NuLUWHKqa4js1wjep3hJeuTQJOlr+4+dA=="], - "oxlint-tsgolint": ["oxlint-tsgolint@0.20.0", "", { "optionalDependencies": { "@oxlint-tsgolint/darwin-arm64": "0.20.0", "@oxlint-tsgolint/darwin-x64": "0.20.0", "@oxlint-tsgolint/linux-arm64": "0.20.0", "@oxlint-tsgolint/linux-x64": "0.20.0", "@oxlint-tsgolint/win32-arm64": "0.20.0", "@oxlint-tsgolint/win32-x64": "0.20.0" }, "bin": { "tsgolint": "bin/tsgolint.js" } }, "sha512-/Uc9TQyN1l8w9QNvXtVHYtz+SzDJHKpb5X0UnHodl0BVzijUPk0LPlDOHAvogd1UI+iy9ZSF6gQxEqfzUxCULQ=="], + "oxlint-tsgolint": ["oxlint-tsgolint@0.24.0", "", { "optionalDependencies": { "@oxlint-tsgolint/darwin-arm64": "0.24.0", "@oxlint-tsgolint/darwin-x64": "0.24.0", "@oxlint-tsgolint/linux-arm64": "0.24.0", "@oxlint-tsgolint/linux-x64": "0.24.0", "@oxlint-tsgolint/win32-arm64": "0.24.0", "@oxlint-tsgolint/win32-x64": "0.24.0" }, "bin": { "tsgolint": "bin/tsgolint.js" } }, "sha512-giCk5sEvG02d5tzPmFMX3hem8ndzEEu1xvGYS5OwNfO2WGl6ZVxt5LjE0yiMDoz94INI7XkXwgFAQiydPvVHDw=="], "tinypool": ["tinypool@2.1.0", "", {}, "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw=="], } diff --git a/hooks/hooks.json b/hooks/hooks.json deleted file mode 100644 index 499e20f..0000000 --- a/hooks/hooks.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "hooks": { - "SessionStart": [ - { - "matcher": "startup|clear|compact|resume", - "hooks": [ - { - "type": "command", - "command": "\"${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-}}/hooks/run-hook.cmd\" session-start", - "timeout": 10, - "statusMessage": "Loading Propulsion workflow" - } - ] - } - ] - } -} diff --git a/hooks/run-hook.cmd b/hooks/run-hook.cmd deleted file mode 100755 index 8041bfd..0000000 --- a/hooks/run-hook.cmd +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -set -eu - -script_name="${1:?missing hook script name}" -script_dir="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)" - -exec "$script_dir/$script_name" diff --git a/hooks/session-start b/hooks/session-start deleted file mode 100755 index f27cd64..0000000 --- a/hooks/session-start +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -set -eu - -plugin_dir="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)" -PLUGIN_DIR="$plugin_dir" node <<'JS' -const { PROPULSION_BOOTSTRAP_GUIDANCE } = require(`${process.env.PLUGIN_DIR}/lib/bootstrap-guidance.js`); - -process.stdout.write(JSON.stringify({ - hookSpecificOutput: { - hookEventName: 'SessionStart', - additionalContext: PROPULSION_BOOTSTRAP_GUIDANCE, - }, -})); -JS diff --git a/index.mjs b/index.mjs deleted file mode 100644 index d4f3f13..0000000 --- a/index.mjs +++ /dev/null @@ -1,54 +0,0 @@ -import { createRequire } from 'node:module'; -import { dirname, join } from 'node:path'; -import { fileURLToPath } from 'node:url'; - -const require = createRequire(import.meta.url); -const { - getPropulsionBootstrapGuidance, -} = require('./lib/bootstrap-guidance.js'); -const PROPULSION_SKILLS_DIR = join( - dirname(fileURLToPath(import.meta.url)), - 'skills', -); - -async function PropulsionPlugin() { - return { - config: async (config) => { - config.skills = config.skills || {}; - config.skills.paths = config.skills.paths || []; - - if (!config.skills.paths.includes(PROPULSION_SKILLS_DIR)) { - config.skills.paths.push(PROPULSION_SKILLS_DIR); - } - }, - 'experimental.chat.messages.transform': async (_input, output) => { - const bootstrap = getPropulsionBootstrapGuidance(); - const firstUser = output.messages?.find( - (message) => message.info.role === 'user', - ); - - if (!firstUser?.parts?.length) { - return; - } - - if ( - firstUser.parts.some( - (part) => - part.type === 'text' && - part.text.includes(''), - ) - ) { - return; - } - - const ref = firstUser.parts[0]; - firstUser.parts.unshift({ - ...ref, - type: 'text', - text: bootstrap, - }); - }, - }; -} - -export default { server: PropulsionPlugin }; diff --git a/lib/bootstrap-guidance.js b/lib/bootstrap-guidance.js deleted file mode 100644 index 6f3f8b3..0000000 --- a/lib/bootstrap-guidance.js +++ /dev/null @@ -1,32 +0,0 @@ -const { readFileSync } = require('node:fs'); -const { join } = require('node:path'); - -const PROPULSION_SKILL_PATH = join( - __dirname, - '..', - 'skills', - 'propulsion', - 'SKILL.md', -); - -function buildPropulsionBootstrapGuidance() { - const propulsionSkill = readFileSync(PROPULSION_SKILL_PATH, 'utf8').trim(); - - return ` -Propulsion workflow entry point: load and follow the propulsion skill when the request is software work. -Route software work through Propulsion before downstream stages. - -${propulsionSkill} -`; -} - -const PROPULSION_BOOTSTRAP_GUIDANCE = buildPropulsionBootstrapGuidance(); - -function getPropulsionBootstrapGuidance() { - return PROPULSION_BOOTSTRAP_GUIDANCE; -} - -module.exports = { - PROPULSION_BOOTSTRAP_GUIDANCE, - getPropulsionBootstrapGuidance, -}; diff --git a/opencode.json b/opencode.json deleted file mode 100644 index 7fc46d3..0000000 --- a/opencode.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://opencode.ai/config.json", - "default_agent": "plan" -} diff --git a/package.json b/package.json index 58e68cc..55f6f9c 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,17 @@ { "name": "propulsion", - "version": "1.2.0", - "main": "./index.mjs", - "exports": "./index.mjs", + "private": true, "scripts": { - "checks": "bun run lint && bun run format && bun run test", + "checks": "bun run lint && bun run format && bun run validate:skills", "format": "oxfmt .", "format:check": "oxfmt --check .", - "lint": "oxlint", - "test": "bun test ./tests", - "test:unit": "bun test ./tests" + "lint": "oxlint --no-error-on-unmatched-pattern", + "validate:skills": "bun scripts/validate-skills.js" }, "devDependencies": { - "oxfmt": "^0.44.0", - "oxlint": "^1.62.0", - "oxlint-tsgolint": "^0.20.0" + "oxfmt": "^0.59.0", + "oxlint": "^1.74.0", + "oxlint-tsgolint": "^0.24.0" }, "packageManager": "bun@1.3.11" } diff --git a/scripts/validate-skills.js b/scripts/validate-skills.js new file mode 100644 index 0000000..de37439 --- /dev/null +++ b/scripts/validate-skills.js @@ -0,0 +1,30 @@ +#!/usr/bin/env bun + +import { spawnSync } from 'node:child_process'; +import { readdirSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; + +const skillRoot = fileURLToPath(new URL('../skills/', import.meta.url)); +const validator = fileURLToPath( + new URL('../skills/write-skill/scripts/validate-skill.js', import.meta.url), +); +const skillDirectories = readdirSync(skillRoot, { withFileTypes: true }) + .filter((entry) => entry.isDirectory()) + .map((entry) => + fileURLToPath( + new URL(`${entry.name}/`, new URL('../skills/', import.meta.url)), + ), + ) + .toSorted(); + +let valid = true; + +for (const skillDirectory of skillDirectories) { + const result = spawnSync(process.execPath, [validator, skillDirectory], { + stdio: 'inherit', + }); + + if (result.status !== 0) valid = false; +} + +process.exitCode = valid ? 0 : 1; diff --git a/skills/brainstorm/SKILL.md b/skills/brainstorm/SKILL.md deleted file mode 100644 index d509c66..0000000 --- a/skills/brainstorm/SKILL.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -name: brainstorm -description: Create an approved PRD through repo inspection and interrogation. Use when scope, UX, constraints, or success criteria are unclear, or when user needs a PRD. ---- - -# Brainstorm - -Turn feature, UX, API, product-scope, or requirements work into an approved PRD. - -## Prerequisites - -ALL prerequisites MUST be satisfied BEFORE following this skill. - -- If user provides an approved `docs/propulsion/.../prd.md`, STOP. Enter the `plan` skill. -- If the request is greenfield project discovery and no target-root `project-brief.md` exists, STOP. Enter the `discover-project` skill. -- If an approved target-root `project-brief.md` exists, read it before interrogation and treat approved discovery decisions as durable PRD inputs. - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Load `interrogate` skill and interview the user about their request. -2. Write `docs/propulsion/{yyyymmdd}-{feature-name}/prd.md` from [references/prd-template.md](references/prd-template.md). -3. Meticulously sanity-check `prd.md` against the conversation and add any missing decisions, facts, constraints, behaviours, or success criteria. -4. Ask the user to review and approve `prd.md`. -5. After explicit approval, enter the `plan` skill. - -## Rules - -These rules are MANDATORY. - -- ALWAYS use `interrogate` skill to reach shared understanding BEFORE writing the PRD. -- ALWAYS use the PRD template for structure and section order. -- MUST keep the PRD product-facing and record durable implementation and testing decisions. -- MUST preserve approved discovery decisions from target-root `project-brief.md` unless the user asks to revise them. -- ENSURE the PRD includes ALL relevant decisions, even if they seem obvious or minor. -- USE supporting documents such as `docs/propulsion/.../diagrams.md` if needed. -- If you cannot write files, STOP, ask the user to enable write mode before continuing the PRD. -- NEVER print the full PRD in the chat, ONLY write it to the file. - -## Completion Gate - -Do NOT leave this skill until ALL items are complete. - -- [ ] Used `interrogate` skill to gather every last detail about the request. -- [ ] Written PRD to `docs/propulsion/.../prd.md`. -- [ ] Compared PRD against conversation and added any missing content. -- [ ] User has explicitly approved `prd.md`. - -## Next Steps - -Once the completion gate is fully checked: - -- If `prd.md` is approved, enter the `plan` skill. - -## References - -Use these references when you need detail. - -- [references/prd-template.md](references/prd-template.md) - PRD shape and output path. diff --git a/skills/brainstorm/references/prd-template.md b/skills/brainstorm/references/prd-template.md deleted file mode 100644 index 7c14716..0000000 --- a/skills/brainstorm/references/prd-template.md +++ /dev/null @@ -1,86 +0,0 @@ -# PRD Template - -Write `docs/propulsion/{yyyymmdd}-{feature-name}/prd.md` using this exact section order. - -```md -# PRD - -## Problem Statement - -State the problem in user language. - -## Solution - -Describe the proposed behaviour end-to-end from the user's perspective. - -## Goals - -- Goal - -## Non-Goals - -- Explicit non-goal - -## User Stories - -| ID | User Story | -| ------ | ---------------------------------------------------- | -| US-001 | As a , I want , so that . | - -## Functional Requirements - -| ID | Requirement | -| ------ | -------------------------------------------- | -| FR-001 | When , the system must . | - -## Non-Functional Requirements - -| ID | Category | Requirement | -| ------- | ----------- | --------------------------------------------- | -| NFR-001 | Performance | must complete within . | - -## Implementation Decisions - -- Durable module or boundary decisions -- Data shape or API contract decisions -- Interaction rules that the `plan` skill should not re-litigate - -## Implementation Inputs - -- External links, tickets, docs, or references -- Business rules or constraints - -## Testing Decisions - -- What public behaviour matters -- Which modules or seams deserve tests -- Prior art worth copying from the repo - -## Out Of Scope - -- Deferred idea -- Thing that must not be implemented - -## Notes - -- Any further notes about the feature -``` - -## Rules - -These rules are MANDATORY. - -- ALWAYS follow the template structure and section order exactly as specified. -- MUST use the following non-functional requirement categories: - - Performance: response times, throughput, resource use. - - Reliability: availability, fault tolerance, recovery. - - Security: data protection, authn/authz, compliance. - - Usability: UX, accessibility, ease of use. - - Scalability: growth in load, users, or data. - - Maintainability: code quality, docs, future changes. - - Compatibility: platform, browser, integration support. - - Portability: deployment across environments. - - Compliance: standards, regulations, policies. - - Monitoring: observability, logging, alerting. -- MUST ensure user stories, functional requirements, and non-functional requirements cover all feature aspects. -- DO create supporting documents with mermaid diagrams, data models, or other relevant artefacts if they help clarify the feature or implementation. diff --git a/skills/code-review/SKILL.md b/skills/code-review/SKILL.md new file mode 100644 index 0000000..083740b --- /dev/null +++ b/skills/code-review/SKILL.md @@ -0,0 +1,63 @@ +--- +name: code-review +description: Reviews scoped code changes against a specification and applicable standards. Use when assessing a diff, branch, pull request, or completed implementation. +metadata: + invocation: model +disable-model-invocation: false +--- + +# Code Review + +**Tailored software formal inspection** prepares fixed evidence packets for independent Standards and Spec inspectors, then presents their diagnostic findings without changing the reviewed work. + +## Process + +### 1. Fix the inspection scope + +Use the caller-supplied scope, whether uncommitted work, a revision range, a branch comparison, a pull request, or another exact change set. Resolve every revision, capture the patch and changed-path list once through read-only inspection, and include the complete contents of in-scope untracked files. Confirm that the captured change set is non-empty. Ask the user when the scope is missing or ambiguous; report the exact blocker and stop when it is invalid or empty. The inspection has one fixed work product. + +### 2. Resolve the inspection sources + +Find the specification from caller context, supplied paths or tickets, issue references and change history, then relevant repository documentation. When none is found, ask the user; omit the Spec inspection only after the user confirms that no specification exists. Independently identify applicable repository instructions, architecture decisions, coding standards, language policies, configured checks, and local conventions. Read the changed files in full, relevant tests, and enough surrounding code to judge the patch. The specification and Standards authorities are explicit. + +### 3. Prepare the work aids + +Create one self-contained packet per applicable axis with the fixed patch, changed paths, relevant source context, authority sources, priority definitions, output schema, and read-only verification boundary. Exclude conversation history and the other inspector's materials. + +The Spec packet applies **bidirectional requirements traceability**: trace every applicable requirement into the changed implementation and relevant tests, and every introduced behaviour back to specification authority. It investigates missing, partial, incorrect, conflicting, and unrequested behaviour and relevant unhandled cases. + +The Standards packet applies repository standards first, then residual **Google code-review criteria** across whole-change understanding, correctness and concurrency risks, test presence and validity, comments, and affected documentation. Include the complete [Fowler code-smell work aid](references/CODE-SMELLS.md). Add **Test Desiderata** when tests change; the relevant **ISO/IEC 25010:2023** characteristic when the repository adopts it or the change exposes a concrete residual product-quality concern; an applicable **SEI CERT** rule when supported-language code exposes its construct; and the relevant frozen **OWASP ASVS 5.0.0** requirement when Web code crosses that security boundary. Load only the implicated part of a conditional benchmark. + +When the fixed change alters modular architecture, invoke `$modular-design` and include the applicable standard in the Standards packet. + +Within Standards, repository rules and demonstrably configured tooling govern the concerns they cover. General work aids fill uncovered diagnostic roles and yield to an explicit repository choice. A smell or benchmark cue begins an investigation; it becomes a finding only when the scoped code supplies exact evidence and a concrete consequence. + +### 4. Assign the inspections + +Give each packet to a separate fresh agent and run the Standards and Spec inspections in parallel when both apply. Each inspector owns candidate discovery, **falsification**, authority and code-evidence validation, consequence analysis, and priority validation for its axis. It may run a targeted check only when the command and execution boundary demonstrate that it cannot mutate the checkout, repository state, external systems, or durable project data; otherwise it records the limitation. Each inspector returns only findings that survive its validation. + +Use **risk-based prioritisation** within each axis: `critical` for immediate data loss, security compromise, or production failure; `high` for incorrect requirements or major behaviour, security, reliability, or maintenance risk; `medium` for a concrete defect or significant code, design, or test weakness; and `low` for a local but worthwhile issue. + +### 5. Present the inspection report + +Check that each assigned packet produced the required output fields, returning an incomplete report to its originating inspector for completion from the same packet. Present the Standards and Spec outputs separately without substantive re-review, merging, deduplication, or cross-axis reranking. Preserve each inspector's findings and ordering. The caller receives the two independent inspection results. + +## Rules + +- Keep the inspection read-only and return evidence for the caller's implementation process. +- Report only issues introduced by or materially relevant to the fixed change. +- Prefer specification, repository, and code evidence over general guidance or personal preference. +- Hold structural, test, security, and product-quality findings to the same evidence, consequence, and priority standard as behavioural defects. + +## Handoff + +State the exact scope, specification source or user-confirmed absence, Standards sources, and any check that could not run. Return `## Standards` and `## Spec`; use `No findings.` for a clean axis and state when the Spec inspection was omitted. Format each finding as: + +```markdown +### [priority] Concise finding + +- Evidence: exact code `path:line`, applicable authority, and observed fact +- Consequence: concrete behaviour or code-health impact +``` + +End with `## Summary` and the finding count for each axis. When neither axis contains a material finding, say the fixed change is clean plainly. diff --git a/skills/code-review/agents/openai.yaml b/skills/code-review/agents/openai.yaml new file mode 100644 index 0000000..a243ba1 --- /dev/null +++ b/skills/code-review/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: 'Code Review' + short_description: 'Review code against standards and specification' +policy: + allow_implicit_invocation: true diff --git a/skills/code-review/references/CODE-SMELLS.md b/skills/code-review/references/CODE-SMELLS.md new file mode 100644 index 0000000..38e2b5d --- /dev/null +++ b/skills/code-review/references/CODE-SMELLS.md @@ -0,0 +1,28 @@ +# Fowler Code Smells + +Use this complete second-edition catalogue as a diagnostic work aid for the Standards inspection. Each cue identifies a code shape to investigate, not a finding by itself. Test the relevant benign interpretation against the scoped code, repository authorities, and concrete consequence. + +1. **Mysterious Name** — An identifier does not communicate its role, meaning, or unit in the surrounding domain. A repository-defined term or tightly conventional local name may already be precise. +2. **Duplicated Code** — Materially similar behaviour appears in multiple locations that may need to evolve together. Superficially similar code may represent different responsibilities or change for different reasons. +3. **Long Function** — A function contains enough distinct steps, branches, or levels of abstraction to obscure its purpose or invariants. A cohesive linear workflow may be clearer when read together. +4. **Long Parameter List** — Numerous inputs or recurring groups of related values make a callable's contract hard to understand or use safely. A boundary function may intentionally expose independent dependencies. +5. **Global Data** — Broadly accessible data creates hidden dependencies across consumers. Immutable constants or configuration with explicit ownership may not carry that risk. +6. **Mutable Data** — In-place changes or aliases make state transitions and observers difficult to reason about. Mutation with a tight owner, lifetime, and invariant may remain local and explicit. +7. **Divergent Change** — One module changes for several unrelated responsibilities within the scoped work. Multiple edits may still serve one cohesive responsibility. +8. **Shotgun Surgery** — One conceptual change requires coordinated edits scattered across many locations. Layer-specific or generated representations may legitimately change together. +9. **Feature Envy** — Behaviour depends more on another object's data or decisions than on its own owner. Orchestration, presentation, and adapter code may properly coordinate across a boundary. +10. **Data Clumps** — The same group of values repeatedly travels or appears together as an implicit concept. Coincidental co-occurrence or a constrained public boundary may not establish one shared abstraction. +11. **Primitive Obsession** — Primitive values repeatedly carry domain states, units, validation, or rules that callers must remember. Simple, local, already-constrained values may remain unambiguous. +12. **Repeated Switches** — Conditional dispatch over the same discriminator recurs across the change. A single exhaustive boundary mapping may keep variation explicit without scattering it. +13. **Loops** — Imperative iteration obscures the transformation, selection, or control intent being performed. Stateful traversal, early exit, or measured performance constraints may make the loop the clearest form. +14. **Lazy Element** — An abstraction carries little distinct behaviour, policy, or information. A small named boundary may still express a domain concept or preserve a necessary interface seam. +15. **Speculative Generality** — Flexibility, parameters, hooks, or abstractions serve only hypothetical requirements. A current specification, compatibility contract, or demonstrated extension point may make the flexibility concrete. +16. **Temporary Field** — An object's field is meaningful only during particular modes or phases, leaving other states uncertain. An explicit lifecycle with guarded access may make those states intentional. +17. **Message Chains** — A caller navigates through a sequence of collaborators and therefore depends on their internal structure. A stable data traversal or intentional fluent interface may expose that chain as its contract. +18. **Middle Man** — An element mostly forwards requests without contributing policy, translation, or information. A boundary may still provide isolation, authorisation, observability, or compatibility. +19. **Insider Trading** — Modules rely on each other's internal knowledge or backchannels beyond their stated contracts. A deliberately shared internal protocol may have clear ownership and stability. +20. **Large Class** — A class accumulates enough unrelated state or behaviour to obscure its responsibility and invariants. A cohesive aggregate may need central ownership to protect one invariant boundary. +21. **Alternative Classes with Different Interfaces** — Types serving the same conceptual role expose unnecessarily different contracts. Similar-looking types may instead represent distinct domain roles. +22. **Data Class** — A type mainly stores data while its rules or meaningful behaviour live elsewhere. A transfer object, event, or serialisation record may be intentionally data-only. +23. **Refused Bequest** — A subtype rejects, ignores, or cannot honour a substantial part of its inherited contract. A narrow implementation may still fully honour the interface actually promised. +24. **Comments** — Comments compensate for code whose intent or structure is unclear, or merely restate what it does. Rationale, safety constraints, protocol details, and public contracts may require commentary beyond the code. diff --git a/skills/commit/SKILL.md b/skills/commit/SKILL.md index 666db3b..8756033 100644 --- a/skills/commit/SKILL.md +++ b/skills/commit/SKILL.md @@ -1,54 +1,29 @@ --- name: commit -description: Create one safe local git commit from current changes. Use when asked to commit, save changes, or make a local checkpoint. +description: Creates coherent Conventional Commits from eligible changed work. Use to commit reviewed changes. +metadata: + invocation: user +disable-model-invocation: true --- # Commit -Create one safe local git commit and report the result. +**Conventional Commits** turns eligible changed work into coherent commits whose messages state each change's intent. -## Prerequisites +## Process -ALL prerequisites MUST be satisfied BEFORE following this skill. +### 1. Inspect the changed work -- The current directory is inside a git repository with a writable index. +Inspect repository instructions, the current Git state, staged, unstaged, and untracked changes, and recent commit subjects. Apply any requested scope or message constraint. When no eligible change remains, report it and stop; otherwise the complete candidate work is explicit. -## Instructions +### 2. Group coherent changes -Follow these steps IN ORDER. Do NOT skip steps. +Partition the candidate work into **atomic commits** by coherent intent. Keep changes together when they serve the same purpose and leave unrelated or ambiguous work untouched. Each group has one explainable purpose. -1. Inspect state with `git status --short`, `git diff HEAD`, and `git branch --show-current`. -2. Stage all local changes with `git add -A`, including untracked files. -3. Unstage every staged secret-like file matching [references/workflow.md](references/workflow.md). -4. Check staged changes after exclusions; if none remain, stop and output exactly `No changes to commit.` -5. Generate a one-line imperative commit subject from the staged diff. -6. Create exactly one local commit with that subject. -7. Run `git status --short` before the final response. -8. Report the result using the exact success format in [references/workflow.md](references/workflow.md). +### 3. Create the commits -## Rules +For each group, stage its exact files or hunks, inspect the staged diff, and commit it with an accurate `type[(scope)][!]: description` message using the repository's Git setup. Ask before altering ambiguous user-staged work. On failure, preserve the resulting Git state and report the blocker. -These rules are MANDATORY. +### 4. Verify the result -- MUST create exactly one local commit when committable changes remain after exclusions. -- MUST stage with `git add -A` before applying exclusions. -- MUST unstage secret-like files before committing when they are staged. -- MUST stop with exactly `No changes to commit.` when exclusions leave no committable changes. -- NEVER commit secret-like files. -- NEVER push, open pull requests, amend, reset, force, or run destructive git commands unless user explicitly instructs. - -## Completion Gate - -Do NOT leave this skill until ALL items are complete. - -- [ ] `git add -A` was run. -- [ ] Secret-like staged files were unstaged or none were present. -- [ ] Exactly one local commit was created, or `No changes to commit.` was returned. -- [ ] No push, pull request, amend, reset, force, or destructive git command was run. -- [ ] Final output matches the required contract. - -## References - -Use these references when you need detail. - -- [references/workflow.md](references/workflow.md) - Secret-like exclusion patterns, commit message rules, and output contract. +Verify each created commit and inspect the remaining status. Return each hash and subject plus any work left uncommitted. diff --git a/skills/commit/agents/openai.yaml b/skills/commit/agents/openai.yaml new file mode 100644 index 0000000..9eca7b4 --- /dev/null +++ b/skills/commit/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: 'Commit' + short_description: 'Create coherent conventional commits' +policy: + allow_implicit_invocation: false diff --git a/skills/commit/references/workflow.md b/skills/commit/references/workflow.md deleted file mode 100644 index 937f71d..0000000 --- a/skills/commit/references/workflow.md +++ /dev/null @@ -1,48 +0,0 @@ -# Commit Workflow Reference - -## Inputs - -- Current git status: `git status --short` -- Current git diff, staged and unstaged: `git diff HEAD` -- Current branch: `git branch --show-current` - -## Secret-Like Exclusions - -Never commit likely secret files. Always unstage these patterns before committing: - -- `.env` -- `*.pem` -- `*.key` -- `*.p12` -- `*.pfx` -- `credentials.json` -- `*credentials*` -- `*secret*` -- `*token*` -- `.ssh/*` - -## Commit Message - -Use a normal imperative commit subject: - -- one line only -- short, descriptive, imperative, natural wording -- no trailing punctuation - -## No Committable Changes Output - -If no staged changes remain after exclusions, stop and output exactly: - -```md -No changes to commit. -``` - -## Success Output - -Run `git status --short` before producing the final response. When the commit succeeds, output exactly: - -```md -Commit created: -Message: -Excluded secret-like files: -``` diff --git a/skills/debug/SKILL.md b/skills/debug/SKILL.md index cc663dc..0e125e7 100644 --- a/skills/debug/SKILL.md +++ b/skills/debug/SKILL.md @@ -1,66 +1,37 @@ --- name: debug -description: Handle concrete failures through intake, diagnosis, one-hypothesis fixes, review, reset, and escalation. Use when bugs or failures need repair. +description: Reproduces, isolates, repairs, and verifies code issues. Use when debugging failures, regressions, runtime errors, or incorrect behaviour. +metadata: + invocation: model +disable-model-invocation: false --- # Debug -Diagnose concrete failures before one evidence-backed fix loop. +**Scientific debugging** turns a repeatable failing signal into a verified causal repair through falsifiable hypotheses, predicted observations, and discriminating experiments. -## Prerequisites +## Process -ALL prerequisites MUST be satisfied BEFORE following this skill. +### 1. Establish a repeatable signal -- The request is a concrete failure: bug, regression, crash, failing test/build, incorrect output, flaky behaviour, or runtime error. -- If the request is feature-shaped, product-scope work, expected-behaviour design, refactor, optimisation, or enhancement, STOP and load `brainstorm`. +Read repository instructions and establish the authorised scope, expected behaviour, observed behaviour, and exact verdict that distinguishes them. Run the smallest reliable reproduction and record its invocation or probe, input, environment, expected verdict, and observed verdict. A failing test, benchmark, trace, log pattern, captured artefact, or targeted external probe may supply the signal when a local reproduction cannot. Use [Debugging Techniques](references/TECHNIQUES.md) when the signal or next experiment is not obvious; for an intermittent or concurrent fault, component or production boundary, or performance regression, load [Nondeterministic Faults](references/NONDETERMINISTIC.md), [Boundary Evidence](references/BOUNDARY-EVIDENCE.md), or [Performance Faults](references/PERFORMANCE.md) respectively. Preserve pre-existing user work and identify the mutation boundary for later repair attempts. When no reliable signal can be established, leave the implementation unchanged and report the evidence, blocker, and next discriminating experiment. The original fault has a repeatable red signal or an explicit evidence boundary. -## Instructions +### 2. Isolate the root cause -Follow these steps IN ORDER. Do NOT skip steps. +Gather evidence and state falsifiable causal hypotheses in evidence-supported order. For the leading hypothesis, state the observation it predicts, then run the cheapest experiment that distinguishes it from the credible alternatives. Change one variable and record the hypothesis, prediction, experiment, and observation. Treat an observation that does not discriminate as an incomplete experiment and sharpen it before continuing. Repeat until the evidence supports one leading cause strongly enough to justify a minimal repair experiment. The cause, causal mechanism, and evidence against symptom-level alternatives are explicit. -1. Create or resume `docs/propulsion/{yyyymmdd}-{bug-slug}/debug.md` from [references/debug-template.md](references/debug-template.md) before diagnosis work. -2. Record provenance, expected and actual behaviour, impact, environment, reproduction, prior attempts, and blockers in `debug.md`. -3. Load `interrogate` ONLY when missing user-answerable intake blocks expected behaviour, reproduction, impact, or environment; record answers and resolved decisions in `debug.md`. -4. Explore only relevant code, tests, logs, recent changes, ownership, and likely boundaries; record facts and limits in `debug.md`. -5. Use [references/investigation-loop.md](references/investigation-loop.md) to reproduce, read the full error, reduce, compare working examples, isolate the first bad boundary, and test one diagnosis hypothesis at a time. -6. Gate fix dispatch until `debug.md` has grounded diagnosis evidence, the first bad state or divergence, fix constraints, a falsifier, and one chosen fix hypothesis. -7. Dispatch one fresh bug-worker with [references/bug-worker-prompt.md](references/bug-worker-prompt.md), then dispatch one fresh reviewer with [references/bug-reviewer-prompt.md](references/bug-reviewer-prompt.md). -8. If review rejects the fix and diagnosis still holds, return findings to the active worker with [references/bug-feedback-prompt.md](references/bug-feedback-prompt.md). -9. If verification, review, or new evidence contradicts the diagnosis, reset to investigation and record the contradicted evidence before any new fix attempt. -10. After 3 failed fix loops, reassess architecture and patterns, record it, then escalate with evidence and next options. -11. Close only when fixed and verified, blocked by missing intake, no-repro after documented attempts, or escalated after the 3-loop reassessment path. +### 3. Test one repair -## Rules +When the user requested diagnosis only, stop before mutation and follow the Handoff. Invoke `$modular-design` when the supported repair changes modular architecture. Invoke `$tdd` when its runnable-suite and stable-seam prerequisite applies; preserve the established reproduction as its Red signal and let it own the minimal Green repair and regression protection. When TDD is not applicable, apply one smallest change that would repair the leading cause if the hypothesis is correct. Keep the attempt within the authorised mutation boundary and leave unrelated cleanup or refactoring outside it. One evidence-led repair is ready for a causal verdict. -These rules are MANDATORY. +### 4. Accept or revert the repair -- MUST keep `debug.md` current from entry through closure. -- MUST diagnose before fixing; NEVER make permanent production-code edits in the controller stage. -- MUST use `interrogate` only for missing user-answerable intake, not repo facts the agent can inspect. -- MUST reset when evidence contradicts the diagnosis or chosen fix hypothesis. -- EVERY fix loop MUST target one chosen fix hypothesis and start with a failing regression test unless `tdd` declares no valuable test. -- MUST record failed hypotheses, blocked/no-repro status, rejected reviews, resets, failed loops, verification, escalation, and closure. +Run the original signal. When it changes as predicted, retain the repair provisionally and continue to verification. When it remains red or changes for a different reason, record the contradictory evidence and revert only the production, configuration, and throwaway-test changes introduced by that attempt; preserve the established reproduction and all pre-existing user work. Reconsider the hypotheses, experiment, system boundary, or architecture whenever the observations no longer support the causal model, then return to isolation without stacking another repair onto the failed one. The working tree contains either one supported repair or no residue from an unsuccessful attempt. -## Completion Gate +### 5. Verify and clean up -Do NOT leave this skill until ALL items are complete. +Re-run the original unminimised reproduction, focused regression coverage, relevant nearby checks, and the repository-prescribed wider checks. Remove temporary instrumentation and throwaway harnesses, or retain them deliberately as documented diagnostics. Separate unrelated pre-existing failures from repair regressions. The original fault and causal account are confirmed by the evidence, the smallest supported repair remains, and relevant checks pass; otherwise the exact remaining failure and uncertainty are explicit. -- [ ] `debug.md` exists or is resumed at `docs/propulsion/{yyyymmdd}-{bug-slug}/debug.md`. -- [ ] Intake, user-answerable `interrogate` decisions if any, targeted exploration, reproduction or no-repro attempts, full error reading, reduction, evidence, hypotheses, diagnosis gate, fix loops, reviews, resets, and verification are recorded. -- [ ] Outcome is one of: fixed and verified; blocked on missing intake; no-repro with documented attempts; reset to diagnosis with contradicted evidence; review-rejected and returned to worker; escalated after 3 failed loops plus architecture and pattern reassessment. +## Handoff -## Next Steps - -Once the completion gate is fully checked: - -- Return a concise status with the `debug.md` path, final outcome, checks run, and any user decision needed. - -## References - -Use these references when you need detail. - -- [references/debug-template.md](references/debug-template.md) - Living `debug.md` template for the bug dossier. -- [references/investigation-loop.md](references/investigation-loop.md) - Evidence-first reproduce, reduce, isolate, diagnose, reset, and escalate loop. -- [references/bug-worker-prompt.md](references/bug-worker-prompt.md) - Prompt template for one diagnosis-gated TDD fix attempt. -- [references/bug-reviewer-prompt.md](references/bug-reviewer-prompt.md) - Prompt template for independent review of one bug fix attempt. -- [references/bug-feedback-prompt.md](references/bug-feedback-prompt.md) - Prompt template for returning review findings to the active worker. +Report the expected and observed behaviour, original failing signal, hypotheses, predictions, experiments and observations, root cause and causal mechanism, reverted attempts, retained change, regression protection, verification commands and results, and any blocker or unresolved uncertainty. For diagnosis-only work, state plainly that no implementation was changed. diff --git a/skills/debug/agents/openai.yaml b/skills/debug/agents/openai.yaml new file mode 100644 index 0000000..bac6c82 --- /dev/null +++ b/skills/debug/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: 'Debug' + short_description: 'Debug issues through verified repair' +policy: + allow_implicit_invocation: true diff --git a/skills/debug/references/BOUNDARY-EVIDENCE.md b/skills/debug/references/BOUNDARY-EVIDENCE.md new file mode 100644 index 0000000..35ad9aa --- /dev/null +++ b/skills/debug/references/BOUNDARY-EVIDENCE.md @@ -0,0 +1,23 @@ +# Boundary Evidence + +Use this reference when the fault crosses components, processes, services, environments, or an authorised production boundary. The goal is to identify the earliest boundary whose observed output or invariant diverges, using the least sensitive evidence that distinguishes the hypotheses. + +## Trace one event + +Map the smallest relevant path and select one request, event, job, or transaction. Preserve its correlation identifier and environment or version context. At only the boundaries that distinguish the leading hypotheses, record applicable input, output, state, configuration, timing, status, and correlation. + +Apply **backward causal tracing** from the symptom until the earliest invalid transition is visible. Continue inside that component rather than widening instrumentation across the whole system. Treat missing, sampled, or uncorrelated telemetry as an evidence limitation rather than a healthy verdict. + +## Capture and replay safely + +Capture the smallest authorised request, event, trace, payload, or state slice. Redact secrets and unnecessary personal or production data before retaining it; preserve an external pointer or correlation identifier when the workspace is not authorised to store the artefact. + +Replay at the nearest stable seam only when the replay preserves the hypothesis-relevant environment, ordering, dependencies, identity, and state. Record every fidelity gap. When replay would erase the suspected cause, prefer a targeted external probe or temporary boundary instrumentation within the user's authority. + +When the next discriminating observation requires new access, privileged instrumentation, or production mutation, leave implementation unchanged and report the required evidence and authority as a blocker. + +## Clean up and verify + +Tag temporary probes so they can be found mechanically. Remove them after diagnosis, or retain them deliberately as documented diagnostics with an explicit data and access boundary. Re-run the original correlated event or nearest faithful reproduction after repair, then verify focused regression and repository checks. + +If a repair does not move the earliest divergent boundary as predicted, record the result and revert the attempt before revising the causal path. diff --git a/skills/debug/references/NONDETERMINISTIC.md b/skills/debug/references/NONDETERMINISTIC.md new file mode 100644 index 0000000..ab0ac8d --- /dev/null +++ b/skills/debug/references/NONDETERMINISTIC.md @@ -0,0 +1,37 @@ +# Nondeterministic Faults + +Use this reference for intermittent, flaky, timing-sensitive, order-dependent, or concurrent faults. The goal is a controlled failure rate or replayable causal execution, not one passing retry. + +## Measure the fault + +Run the exact trigger repeatedly and record attempts, failures, seed, order, clock, load, resources, environment, and any captured schedule. A useful signal either reproduces at a stable enough rate to compare experiments or preserves the execution that failed. + +Partition the likely nondeterminism before changing code: + +- randomness or generated input; +- test order, shared state, or leaked resources; +- clock, timeout, asynchronous condition, or event order; +- concurrent access or scheduling; +- load, resource pressure, network, filesystem, or environment. + +Vary one dimension and compare the failure rate or execution. Preserve every failing seed, order, input, and schedule that improves repeatability. + +## Select the experiment + +| Evidence | Technique | Causal evidence | +| --- | --- | --- | +| A seed or generated input controls the failure | Seed replay and counterexample reduction | The same input fails repeatedly and a minimised input preserves the verdict. | +| Test order or shared state is suspected | Order permutation and isolation probe | A specific predecessor, state, or unreleased resource changes the rate. | +| An asynchronous condition is suspected | Condition instrumentation and controlled perturbation | An observable state transition, rather than elapsed delay alone, determines success. | +| Unsynchronised access is possible | Repository-supported **race detector** | Conflicting accesses and their call paths identify the shared state to investigate. | +| A particular interleaving is suspected | Systematic, controlled, or recorded schedule | The captured schedule replays the failure and an alternative schedule discriminates the hypothesis. | + +Use stress, injected delay, parallelism, or load only to amplify and capture a failure. Stress without a retained input, schedule, trace, or invariant violation does not prove a cause, and a long passing run does not prove absence. + +Replace guessed delays with **condition-based waiting** only after evidence identifies the condition whose ordering is causal. A longer timeout that merely reduces the observed rate is not a confirmed repair. + +## Verify the repair + +Run the preserved failing seed, order, schedule, or trace first. Then repeat the original trigger under the same controls and compare failures per attempts; keep attempt counts proportionate to the prior rate and report the remaining uncertainty. Run focused regression and repository checks after the causal signal changes as predicted. + +If a repair does not change the preserved execution or measured rate as predicted, record the result and revert the attempt before testing the next hypothesis. diff --git a/skills/debug/references/PERFORMANCE.md b/skills/debug/references/PERFORMANCE.md new file mode 100644 index 0000000..d648a72 --- /dev/null +++ b/skills/debug/references/PERFORMANCE.md @@ -0,0 +1,28 @@ +# Performance Faults + +Use this reference for latency, throughput, resource, query, or scale regressions. Measure a representative workload before selecting a profiler or changing code. + +## Establish the regression + +Define the workload, environment, expected threshold or known-good baseline, measured outcome, and variance that distinguishes the fault. Control input size, data shape, concurrency, cache state, runtime version, machine resources, and other material conditions. Warm up when the runtime requires it, repeat the measurement, and report the distribution rather than one timing. + +When known-good and known-bad states exist, use automated **bisection** with the same stable classifier. Treat noisy or untestable states explicitly; route a flaky classifier through [Nondeterministic Faults](NONDETERMINISTIC.md) before trusting its boundary. + +## Locate responsible work + +After the controlled benchmark proves the regression, choose the smallest instrument that distinguishes the hypotheses: + +| Suspected cost | Technique | Discriminating observation | +| --- | --- | --- | +| CPU or call-path work | Sampling or instrumenting profiler | The responsible stack or operation accounts for the measured difference. | +| Memory, allocation, I/O, lock, or network pressure | Resource counter or targeted trace | The relevant resource changes with the regression under the same workload. | +| Database work | Query plan and execution measurement | The plan, cardinality, I/O, lock, or execution step explains the difference. | +| Version or configuration change | Bisection or differential benchmark | The first ordered boundary preserves the same performance verdict. | + +Record measurement overhead and side effects. Use transactions or inert fixtures when an execution plan can mutate data. Profile the controlled workload; a profile from a different workload does not explain the measured regression. + +## Repair and verify + +Make one minimal change to the responsible work. Remeasure the identical workload and controls, compare the result and variance with the original baseline, then run functional regression and repository checks. A faster result that changes behaviour, workload, or environment does not verify the repair. + +If the measurement does not change as predicted, record the result and revert the attempt before revising the performance hypothesis. diff --git a/skills/debug/references/TECHNIQUES.md b/skills/debug/references/TECHNIQUES.md new file mode 100644 index 0000000..9cd3d5c --- /dev/null +++ b/skills/debug/references/TECHNIQUES.md @@ -0,0 +1,52 @@ +# Debugging Techniques + +Use this reference when the repeatable failing signal or next discriminating experiment is not obvious. Identify the runtime situation, select the smallest technique that predicts a discriminating observation, retain its evidence, then return to the scientific-debugging loop. Combine techniques only when each settles a distinct question. + +## Tighten the Signal + +Run the signal at least once and record its command or probe, input, environment, expected verdict, and observed verdict. A useful signal is: + +- **specific:** it reaches the relevant path and asserts the reported symptom, rather than merely completing without an error; +- **repeatable:** it records the fixture, environment, seed, order, schedule, or captured artefact needed to reproduce the verdict; +- **measurable:** it is deterministic, or reports failures per attempts for a nondeterministic fault; +- **tight:** it removes unrelated setup and runs quickly enough to guide the next experiment; +- **runnable:** the agent can execute it unattended when the environment permits; otherwise it uses repeatable captured evidence or a targeted external probe; +- **safe:** production artefacts are minimised, redacted, and handled within the user's permissions. + +A passing retry does not turn an intermittent failure green. Use [Nondeterministic Faults](NONDETERMINISTIC.md) to control and compare the measured failure rate. + +## Construct a Signal + +| Situation | Technique | Observable verdict and retained artefact | +| --- | --- | --- | +| A stable test seam reaches the fault | Focused failing test or minimal harness | Assert the exact behaviour and preserve the smallest fixture. If retained as regression coverage, `$tdd` remains authoritative. | +| The fault is at an HTTP boundary | HTTP request script | Assert the relevant status, body, and headers; retain a redacted request and response rather than relying only on process exit. | +| The fault is a CLI contract | CLI invocation with fixture input | Assert exit status, stdout, and stderr as applicable; record flags, working directory, and relevant environment. | +| Only a production request or event exposes the fault | Capture and replay | Use [Boundary Evidence](BOUNDARY-EVIDENCE.md) to capture the smallest authorised event and assess replay fidelity. | +| The bad input is unknown or combinatorial | Property or fuzz loop | State an executable invariant, preserve the seed and failing input, then minimise the counterexample before diagnosis. | +| The failure is intermittent, order-dependent, concurrent, or timing-sensitive | Repetition, race detector, or controlled schedule | Use [Nondeterministic Faults](NONDETERMINISTIC.md) to measure the rate, partition nondeterminism, and capture a causal execution. | +| The fault crosses components or environments | Correlated boundary probe | Use [Boundary Evidence](BOUNDARY-EVIDENCE.md) to observe only the boundaries that distinguish the hypotheses. | +| The fault is performance | Controlled benchmark | Use [Performance Faults](PERFORMANCE.md) to establish a representative baseline and threshold before profiling. | +| The fault requires browser behaviour | Headless browser assertion or trace | Assert the relevant DOM, accessibility, console, request, response, screenshot, or timing outcome; retain the smallest trace and fixture. Use a structured human-in-the-loop transcript only when automation cannot perform or observe the essential step. | + +## Select an Experiment + +| Evidence | Experiment | Discriminating result | +| --- | --- | --- | +| A failing input, configuration, or sequence can be reduced | **Minimal reproducible example** or **delta debugging** | Remove partitions while preserving the exact verdict; the remaining elements bound the causal search space. | +| Known-good and known-bad states form an ordered space | **Binary search** or automated bisection | Use a stable good, bad, and untestable classifier across commits, versions, datasets, inputs, or configurations; record the first boundary found. | +| A comparable case works | **Differential testing** | Run the same input through both cases and isolate the smallest output, state, dependency, or configuration difference. Treat a difference as evidence to test, not proof by itself. | +| The symptom appears far from the bad value or action | **Backward causal tracing** | Follow the call and data flow from symptom to the earliest divergence, recording where the value entered and which invariant first failed. | +| The system crosses process or component boundaries | **Boundary instrumentation** | Follow [Boundary Evidence](BOUNDARY-EVIDENCE.md) and record hypothesis-relevant observations at the few boundaries that distinguish the candidates. | +| A value changes unexpectedly during execution | **Breakpoint**, **watchpoint**, or targeted trace | Pause at the earliest mutation or invariant violation and capture the responsible call path and state. | +| Timing, order, or scheduling is suspected | Controlled perturbation | Follow [Nondeterministic Faults](NONDETERMINISTIC.md) and vary one dimension while comparing the measured rate or captured schedule. | +| A controlled benchmark proves a regression | Profiler, query plan, or resource trace | Follow [Performance Faults](PERFORMANCE.md), identify the responsible work, and remeasure the identical workload after repair. | + +An experiment is complete when its observation confirms or rejects a stated hypothesis. If it only produces more data, sharpen the prediction or choose a different experiment. + +## Preserve Useful Evidence + +- Promote a minimised reproducer to regression protection at the strongest stable seam when appropriate; keep `$tdd` authoritative for the test and repair cycle. +- Remove temporary instrumentation and throwaway harnesses after use, or retain them deliberately as documented diagnostics. Tag temporary probes so cleanup is mechanically checkable. +- Store only sanitised captures and fixtures that the repository is authorised to retain. Report external artefacts without copying sensitive data into the workspace. +- Preserve the original reproduction across repair attempts. When a repair fails its prediction, retain the observation but revert the attempt before testing the next hypothesis. diff --git a/skills/debug/references/bug-feedback-prompt.md b/skills/debug/references/bug-feedback-prompt.md deleted file mode 100644 index ab042f6..0000000 --- a/skills/debug/references/bug-feedback-prompt.md +++ /dev/null @@ -1,76 +0,0 @@ -# Bug Feedback Prompt Template - -Use this template when returning reviewer findings to the active bug-worker during a bug-fix loop in `debug`. - -````markdown -**You are a subagent completing work in the Propulsion workflow.** - -Your bug-fix attempt was independently reviewed. Treat review items as technical claims to verify. - -## Review Report - - - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Read the review report, current `debug.md`, and active diff. -2. Triage every reviewer finding as `valid`, `invalid`, or `unclear` before changing code. -3. If any finding is `unclear`, STOP and report `Status: unclear` with the missing evidence; do not change code. -4. Confirm each `valid` finding fits the active hypothesis and does not require a new one. -5. If a valid finding or new evidence contradicts diagnosis, hypothesis, or constraints, STOP, update `debug.md`, and reset to diagnosis. -6. For each valid in-scope finding, make the minimal correction within the active hypothesis only. -7. Preserve regression-test-first for any code change; if no new test is valuable, record the `tdd` rationale and fallback proof. -8. Re-run relevant checks and update `debug.md` with triage, code changes, verification, and diagnosis status. -9. Return an implementation report in the exact format defined below. - -## Output - -Use this exact format for your output. - -```markdown -# Implementation Report - -**Status**: - -**What Changed**: - -- - -**Checks Run**: - -- : -- : - -**Files Changed**: - -- - -**Diagnosis Status**: - -- - - Evidence: - -**Review Feedback Triage**: - -- - - Classification: - - Resolution: - - Evidence: -``` - -## Rules - -These rules are MANDATORY. - -- Preserve the diagnosis reset and one-hypothesis discipline. -- Triage every finding before changing code. -- Do not continue coding once the diagnosis is contradicted. -- Preserve one-hypothesis, one-fix-loop discipline. -- Do not start a second fix hypothesis inside feedback handling; if one is required, update `debug.md` and reset to diagnosis. -- Do not broaden the active fix beyond reviewer findings that fit the chosen fix hypothesis. -- Update `debug.md` before handing control back to `debug`. -- MUST return exactly one `Status:` field with `done`, `blocked`, or `unclear`. -- Follow the output format EXACTLY as defined above. -```` diff --git a/skills/debug/references/bug-reviewer-prompt.md b/skills/debug/references/bug-reviewer-prompt.md deleted file mode 100644 index ef3ddf1..0000000 --- a/skills/debug/references/bug-reviewer-prompt.md +++ /dev/null @@ -1,135 +0,0 @@ -# Bug Reviewer Prompt Template - -Use this template when starting a fresh bug-reviewer subagent for one bug-fix loop in `debug`. - -````markdown -**You are a subagent completing work in the Propulsion workflow.** - -You are a sceptical implementation reviewer for one bug-fix attempt under the `debug` skill. - -Review the bug-fix attempt like a senior engineer: verify the actual implementation against `debug.md`, the original bug behaviour, diagnosis evidence, tests, maintainability, security, reliability, and regression risk. - -## Inputs - -- **Debug artifact**: `` - -## Implementation Report - -This is the bug-worker report. **Treat it as context, not proof; verify every claim.** - - - -## Review Criteria - -| Category | Verify | -| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Diagnosis Integrity | `debug.md` has the required diagnosis evidence before production-code changes, and the evidence still explains the original bug without contradictions. | -| Original Bug Correctness | The implementation fixes the reported bug behaviour itself, not only adjacent symptoms or the worker's preferred repro path. | -| Hypothesis / Constraints Fit | The change stays within the chosen hypothesis, fix constraints, affected boundaries, and prior reset evidence in `debug.md`; speculative or symptom-masking changes are rejected. | -| Tests / Verification | Regression-test-first proof is present: failing result for the expected bug before the fix and passing result after, or `tdd` accepted no valuable test with sufficient fallback proof. | -| Maintainability / Refactoring | The fix is clear, cohesive, minimal, and avoids unnecessary complexity, duplicated logic, or hidden changes outside the bug scope. | -| Security / Trust Boundaries | Inputs, permissions, secrets, file access, external calls, prompt boundaries, and other trust boundaries remain safe. | -| Performance / Reliability | The fix avoids avoidable latency, resource waste, flaky behaviour, races, brittle state, or reliability regressions. | -| Integration / Regression Risk | Surrounding APIs, workflows, tests, prompts, feedback loops, and affected boundaries remain compatible. | -| Output Usefulness | Rejections are actionable, evidence-backed, and clear enough for the debug controller or next bug-worker to continue without reinterpretation. | - -Required diagnosis evidence includes exact symptom, reduced repro or flaky classification, full error reading and conclusion, recent-change conclusion, working example or explicit N/A, boundary tracing, first bad boundary and divergence, fix constraints, chosen hypothesis, fail-then-pass proof, and prior-loop reset evidence when applicable. - -Flag only real issues supported by `debug.md`, worker report, code, tests, diff, checks, prompts, or workflow rules. - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Read the current `debug.md` and implementation report in full. -2. Inspect the real code, tests, current diff, and check output yourself; do not trust the worker report. -3. Verify the diagnosis gate was complete before the fix and that current evidence has not contradicted it. -4. Verify the test failed first for the expected bug reason, then passed; `debug.md` must show both. If no test, verify `tdd` declared no valuable test and fallback proof is sufficient. -5. Verify the change stays within the chosen hypothesis/constraints, with no symptom masking or unexplained evidence hidden by the patch. -6. Verify checks cover the reported behaviour and affected boundaries. -7. Use the criteria table to evaluate every criterion with evidence. -8. Approve only if gate, hypothesis fit, regression-first proof or accepted no-test rationale, diagnosis status, verification, and every criterion all hold. -9. If anything fails or is unclear, reject the attempt and state whether `debug` must reset back to diagnosis. -10. Return the implementation review report in the exact format below. - -## Output - -Use this exact format for your output. - -```markdown -# Implementation Review Report - -**Status**: - -**Criteria Results** - -- : - - Evidence: - -**Diagnosis Status** - -- - - Evidence: - -**Verification Status** - -- Regression-test-first requirement: - - Evidence: -- Failing result before fix and passing result after fix: - - Evidence: -- Chosen fix hypothesis respected: - - Evidence: -- Verification sufficient for bug behaviour: - - Evidence: - - - -**Findings** - -- [] - - Location: - - Issue: - - Impact: - - Evidence: - - Fix: - - - -**Reset Guidance** - -- Reset to diagnosis: - - Reason: -``` - -## Rules - -These rules are MANDATORY. - -- NEVER approve from the worker report alone; review `debug.md`, real code, tests, current diff, and check output. -- NEVER make code changes; review only. -- ENSURE every review criterion is evaluated as `met`, `not met`, or `unclear`, with evidence. -- RETURN exactly one `Status:` line with either `approved` or `rejected`. -- Status CAN be `approved` only when every criterion is `met`, diagnosis still holds, verification is met, and there are no blocking findings. -- Status MUST be `rejected` if any criterion, diagnosis, or verification item is `not met` or `unclear`. -- TREAT `critical`, `high`, `medium`, and `low` findings as blocking. -- TREAT `nitpick` findings as non-blocking only when every criterion, diagnosis, and verification item is met and no blocking findings exist. -- INCLUDE at least one actionable finding when using `rejected`. -- ORDER findings by severity, highest first, with `nitpick` findings last. -- If rejected, say whether the result should reset back to diagnosis. -- If diagnosis, hypothesis fit, or verification is unclear or contradicted, use evidence-backed `Diagnosis Status`, `Verification Status`, and `Reset Guidance` to preserve the debug control-loop decision. -- ALWAYS follow the output structure and section order exactly as specified. - -## Completion Gate - -Do NOT output your response until ALL items are complete. - -- [ ] Current `debug.md` reviewed in full. -- [ ] Worker implementation report reviewed as context, not proof. -- [ ] Real implementation inspected in the repo, including relevant code, tests, current diff, and check output. -- [ ] Every review criterion evaluated with evidence. -- [ ] Diagnosis status and verification status evaluated with evidence. -- [ ] Findings categorised with the required severity rules. -- [ ] Reset guidance provided when diagnosis, hypothesis fit, or verification is unclear or contradicted. -- [ ] Approval decision set to `approved` or `rejected` according to criteria, diagnosis, verification, and finding severity rules. -- [ ] Output implementation review report in the exact format specified. -```` diff --git a/skills/debug/references/bug-worker-prompt.md b/skills/debug/references/bug-worker-prompt.md deleted file mode 100644 index 627fe2a..0000000 --- a/skills/debug/references/bug-worker-prompt.md +++ /dev/null @@ -1,72 +0,0 @@ -# Bug Worker Prompt Template - -Use this template when starting a fresh bug-worker subagent for one bug-fix loop in `debug`. - -````markdown -**You are a subagent completing work in the Propulsion workflow.** - -Implement exactly one diagnosis-gated bug-fix attempt under the `debug` skill. - -## Bug Context - -- **Debug artifact**: `` -- **Chosen fix hypothesis**: `` -- **Fix constraints**: `` - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Review context; ask if the diagnosis gate, chosen hypothesis, fix constraints, or repo state is unclear. -2. Verify `debug.md` has: exact symptom, reduced repro or flaky classification, full error reading, recent-change conclusion, working example or explicit N/A, boundary tracing, first bad boundary/divergence, fix constraints, chosen fix hypothesis, falsifier, and prior-loop reset evidence if any. -3. If the gate is incomplete, contradicted, or not tied to the hypothesis, STOP and report `Status: blocked` or `Status: unclear`; do not edit production code. -4. Load the `tdd` skill NOW and follow it before any production-code change. -5. Add/update the smallest valuable regression test first and verify the expected failure. If `tdd` declares no valuable test, record the rationale plus strongest fallback verification in `debug.md` before fixing. -6. Implement one minimal fix for the chosen hypothesis within constraints. -7. Re-run regression proof and relevant checks. -8. Update `debug.md` with gate verification, regression-first evidence or no-test rationale, fix attempt, verification, and contradictions. -9. Return an implementation report in the exact format defined below. - -## Output - -Use this exact format for your output. - -```markdown -# Implementation Report - -**Status**: - -**What Changed**: - -- - -**Checks Run**: - -- : -- : - -**Files Changed**: - -- - -**Diagnosis Status**: - -- - - Evidence: -``` - -## Rules - -These rules are MANDATORY. - -- MUST return exactly one `Status:` field with `done`, `blocked`, or `unclear`. -- ALWAYS load and follow the `tdd` skill. -- ALWAYS check for relevant non-Propulsion skills and load them IMMEDIATELY. -- Propulsion skills and workflow MUST take precedence over any conflicting non-Propulsion skill UNLESS the user instructions state otherwise. -- NO PRODUCTION CODE before a failing regression test unless `tdd` declares no valuable test and `debug.md` records rationale plus fallback verification. -- Only bug-worker subagents make permanent code changes; debug controller diagnostic edits must be recorded and reverted before fix handoff. -- Work only on the chosen fix hypothesis for this loop; do not broaden or replace it. -- Make one minimal fix attempt only; do not stack speculative fixes. -- If evidence contradicts the diagnosis or chosen hypothesis, STOP, update `debug.md`, and reset back to diagnosis. -- Follow the output format EXACTLY as defined above. -```` diff --git a/skills/debug/references/debug-template.md b/skills/debug/references/debug-template.md deleted file mode 100644 index baff84e..0000000 --- a/skills/debug/references/debug-template.md +++ /dev/null @@ -1,145 +0,0 @@ -# Debug Template - -Create or resume one living `docs/propulsion/{yyyymmdd}-{bug-slug}/debug.md` dossier. Keep it concise, evidence-backed, and append-only for failed hypotheses, resets, diagnostic edits, and fix loops. - -```md -# Debug Note: - -## Intake - -- Source/time: `` -- Original report: `` -- Exact symptom: `` -- Expected behaviour: `` -- Actual behaviour: `` -- Impact: `` -- Environment: `` -- Questions answered: `` -- Open blockers: `` - -## Targeted Exploration - -- Areas inspected: `` -- Relevant tests/commands/logs: `` -- Ownership/prior context: `` -- Likely seams: `` -- Exploration limits: `` - -## Reproduction / No-Repro - -- Status: `` -- Exact command/path: `` -- Expected vs actual: `` -- Full output: `` -- Reduced repro: `` -- No-repro/blocking rationale: `` - -## Full Error Reading - -- Complete error: `` -- First meaningful frame/signal: `` -- Surrounding context: `` -- Conclusion: `` - -## Environment And Recent Changes - -- Revision/build: `` -- Runtime/config/data: `` -- Worktree/staged diff: `` -- Recent delta: `` -- Change conclusion: `` - -## Reduction And Comparison - -- Smallest failing case: `` -- Variables removed/controlled: `` -- Working example: `` -- Broken vs working diff: `` -- First observed divergence: `` - -## Boundary Tracing - -- Boundary map: `` -- Handoff observations: `` -- Config/data/state propagation: `` -- First bad boundary: `` - -## Diagnostic Edits - -- Temporary edits: `` -- Revert status: `` -- Outcome: `` - -## Evidence - -- E1. `` -- E2. `` - -## Hypotheses And Experiments - -- H1. `` - - Evidence for: `` - - Strongest alternative: `` - - Experiment: `` - - Expected result: `` - - Actual result: `` - - Falsifier: `` - - Conclusion: `` -- H2. `` - -## Diagnosis Gate - -- First bad state/divergence: `` -- Root cause: ` caused because ` -- Falsifier: `` -- Fix constraints: `` -- Gate status: `` - -## Regression Test - -- Test location: `` -- Behaviour under test: `` -- Failing proof before fix: `` -- Passing proof after fix: `` - -## Fix Attempts - -- Attempt 1: `` - - Files changed: `` - - Verification: `` - - Review result: `` - - Outcome: `` -- Attempt 2: `` - -## Verification - -- Targeted checks: `` -- Wider regression checks: `` -- Remaining unexplained evidence: `` - -## Reassessment - -- Trigger: `` -- Failed loop summary: `` -- Architecture/pattern reassessment: `` -- Next direction/escalation: `` - -## Closure - -- Final status: `` -- Resolution: `` -- Closure evidence: `` -- Follow-ups: `` -``` - -## Rules - -- `debug.md` is the single audit trail from intake through closure. -- Reproduce before theorising; read the full error before summarising; reduce before widening search. -- If expected behaviour, reproduction, or environment is unknowable, record the blocker and do not dispatch a fix. -- Ground the diagnosis gate before any production-code change or fix dispatch. -- Use one hypothesis, one experiment, and one fix at a time; record expected experiment results before running them. -- Use the same sections for flaky, no-repro, regression-window, performance, environment/config, data-dependent, concurrency, and multi-component evidence. -- Record diagnostic edits with file, purpose, marker when relevant, observation, and revert status; revert them before fix handoff. -- Preserve failed hypotheses, contradicted evidence, rejected reviews, reset reasons, failed fix loops, and escalations. -- After 3 failed fix loops, reassess architecture and patterns before escalating. diff --git a/skills/debug/references/investigation-loop.md b/skills/debug/references/investigation-loop.md deleted file mode 100644 index 0a0b2a9..0000000 --- a/skills/debug/references/investigation-loop.md +++ /dev/null @@ -1,84 +0,0 @@ -# Investigation Loop - -Use this loop to keep `debug.md` evidence-first and block fixes before root cause is grounded. - -## Loop - -1. Capture the feedback signal. - -- Record the exact symptom: failing command, assertion, crash, wrong output, visible behaviour, alert, metric. -- Record expected versus actual behaviour and the user impact. -- Freeze relevant environment facts: revision, runtime, platform, flags, config, inputs, time/locale, dataset, tenant, CI/prod scope. - -2. Reproduce or block. - -- Reproduce before theorising using one command, script, URL, or manual path. -- If it will not reproduce, record no-repro attempts, environment gaps, and the next needed signal before blocking or asking. -- For flaky failures, prove pass/fail variation, capture run counts, freeze seed/time/order where possible, and record changing factors. - -3. Read the failure fully. - -- Read the complete error, stack, warning, assertion, logs, exit code, and first meaningful frame before summarising. -- Separate what the output proves from what it merely suggests. - -4. Scan recent changes. - -- Check working tree diff, staged diff, recent commits, dependencies, config, environment, CI, runtime drift, release delta before broad code reading. -- If a good/bad window exists, record the smallest credible window and isolate it before guessing. - -5. Reduce the case. - -- Remove fixtures, services, flags, data, timing, and setup while preserving the same symptom. -- If the symptom changes, record that the problem changed and reset the reduction. -- For performance/resource failures, reduce to the threshold and boundary where cost first diverges from a good baseline. -- For data-dependent failures, shrink to the smallest input, fixture, stored state, or tenant dataset that still fails. - -6. Compare with working evidence. - -- Compare against a passing test, adjacent feature, prior release, reference implementation, known-good trace, good environment. -- For environment/config failures, compare runtime, flags, env, and config propagation at each boundary. -- Record the first meaningful broken-versus-working difference. - -7. Isolate the first bad boundary. - -- Trace ingress, egress, config propagation, data, state, and timing at each component handoff. -- For concurrency/order bugs, serialise when possible, use logpoints/watchpoints, and capture the first ordering change that turns good into bad. -- For multi-component failures, inspect each handoff until the earliest bad boundary is visible. - -8. Hypothesize one cause. - -- Keep one current best hypothesis plus the strongest alternative and unexplained evidence. -- Define the falsifier and one discriminating experiment before running it. -- Prefer logs, traces, dumps, breakpoints, logpoints, watchpoints, and debugger inspection before mutating code. - -9. Experiment once. - -- Run one experiment at a time and record expected result, actual result, and conclusion. -- Temporary diagnostic edits are allowed only for investigation; record file, purpose, tag/comment marker when relevant, observation, revert status in `debug.md`. -- Revert temporary diagnostic edits before fix handoff. - -10. Diagnose and gate the fix. - -- Ground the diagnosis only when evidence explains the earliest bad state or divergence, not just late symptoms. -- Record root cause, falsifier, fix constraints, and one chosen fix hypothesis. -- Dispatch one fix at a time; if evidence no longer fits, reset diagnosis instead of pushing through. - -11. Reset or escalate. - -- If verification, review, or new evidence contradicts the model, return to the earliest loop step affected and record the reset reason. -- After 3 failed fix loops, reassess architecture and patterns before escalating to the user. -- Escalate with reproduced facts, failed hypotheses, experiments, fix attempts, reassessment, and the exact decision or access needed. - -## Rules - -- No permanent production-code changes in the controller before a grounded diagnosis. -- Reproduce before theorising. -- Read full errors before summarising. -- Scan changes and reduce before widening search. -- Isolate before fixing. -- Use one hypothesis, one experiment, and one fix at a time. -- Record expected experiment results before running experiments. -- Record, tag where relevant, and revert temporary diagnostic edits before fix handoff. -- Treat flaky, regression-window, performance, environment/config, data-dependent, concurrency, and multi-component cases as evidence patterns, not shortcuts to a fix. -- Reset when evidence breaks the current model. -- Reassess architecture and patterns after 3 failed fix loops before user escalation. diff --git a/skills/define-product/SKILL.md b/skills/define-product/SKILL.md new file mode 100644 index 0000000..32d42b0 --- /dev/null +++ b/skills/define-product/SKILL.md @@ -0,0 +1,41 @@ +--- +name: define-product +description: Discovers and maintains a durable product definition centred on high-level feature descriptions. Use when externalising a new product idea or refining an existing product. +metadata: + invocation: user +disable-model-invocation: true +--- + +# Define Product + +A product definition externalises product knowledge into a durable reference for later planning and development. Concise strategic framing leads into a complete catalogue of high-level features without becoming a delivery plan. + +## Process + +### 1. Inspect existing knowledge + +Inspect the request, root `PRODUCT.md` and `CONTEXT.md`, applicable research and decisions, and the smallest representative repository evidence. Treat code and tests as evidence of current behaviour and the user as the authority on intent; surface contradictions between them. Derive available facts before questioning so the user supplies decisions and knowledge the existing material cannot establish. The known product and unresolved discovery surface are explicit. + +### 2. Frame the product + +Invoke `$elicit-with-context` and use the **Product Vision Board** dimensions to confirm the executive summary, vision, intended users and needs, value proposition, market position, business model, goals, success signals, pricing, boundaries, and non-goals. Invoke `$research` when external evidence could materially inform a decision about competitors, market conditions, pricing, regulation, or another product claim; keep its report authoritative and link applicable findings. When a framing dimension stalls, load only the relevant section of [Discovery Techniques](references/DISCOVERY.md). The concise product frame is user-confirmed and externally supported where material. + +### 3. Map the whole product + +Use **User Story Mapping's big-picture techniques** without adopting its backlog or delivery workflow. Map the product mile-wide and inch-deep: inventory the known user-facing areas and candidate features before exploring any one feature in depth. Arrange the areas as a narrative backbone following the natural user journey; place a genuinely cross-cutting feature in the smallest coherent user-facing area rather than inventing a false sequence. Include observed features, confirmed direction, and product ideas from the inspected material and the user. Load the feature-mapping guidance in [Discovery Techniques](references/DISCOVERY.md) when the product surface is difficult to expose. The whole feature surface is visible at low resolution. + +### 4. Explore each feature + +Work through the mapped features with `$elicit-with-context`, asking only for unresolved knowledge. For each feature, confirm its user value, high-level behaviour, meaningful boundaries, and one status: `Current` for observed product behaviour, `Confirmed direction` for intended behaviour the user has decided, or `Idea` for direction retained without commitment. Stop at the information needed for a concise feature description; leave prioritisation, sequencing, release slicing, estimates, tickets, architecture, implementation, user-story decomposition, and acceptance criteria to downstream work. Each feature is ready to become a self-contained mini-brief. + +### 5. Walk the catalogue + +Narrate the complete product journey area by area with the user. Correct missing, duplicate, misplaced, or contradictory features and resolve every exposed question through `$elicit-with-context`; represent genuine uncertainty through `Idea` and contextual product language rather than an unanswered-questions inventory. Obtain final confirmation of the strategic frame and complete feature catalogue. The product definition is coherent and ready to persist. + +### 6. Write the product definition + +After final confirmation, create or update the single root `PRODUCT.md` from the [Product Definition Template](assets/product-template.md). Write the executive summary beneath the title, then the strategic sections, followed by feature areas as `##` headings and individual features as `###` headings. Give every feature its status and concise prose covering user value, high-level behaviour, and meaningful boundaries. Present user-confirmed decisions as ordinary product prose, cite useful repository evidence for current claims, and link external claims to their research reports. Preserve canonical language from `CONTEXT.md` and one authoritative meaning for each statement. The durable document makes the product and its features easy to understand and use in later work. + +### 7. Verify the definition + +Verify useful `Current` claims against repository evidence, intended direction against user confirmation, `Idea` statuses against the confirmed catalogue, and external claims against linked research. Check that every mapped feature has one mini-brief, the feature order tells a coherent product story, and excluded delivery detail has stayed downstream. Reconcile the finished document with `CONTEXT.md` and applicable decisions, then return changed files, supporting research, and any limitations in repository verification. The user receives a complete product foundation ready to inform feature planning. diff --git a/skills/define-product/agents/openai.yaml b/skills/define-product/agents/openai.yaml new file mode 100644 index 0000000..b14341f --- /dev/null +++ b/skills/define-product/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: 'Define Product' + short_description: 'Discover and document a product direction' +policy: + allow_implicit_invocation: false diff --git a/skills/define-product/assets/product-template.md b/skills/define-product/assets/product-template.md new file mode 100644 index 0000000..f6ff06f --- /dev/null +++ b/skills/define-product/assets/product-template.md @@ -0,0 +1,35 @@ +# {Product name} + +{Concise executive summary stating who the product serves, the outcome it enables, and what distinguishes its approach. Include overall product maturity only when it materially improves orientation.} + +## Vision + +{The product's enduring purpose and positive change, independent of a particular implementation.} + +## Intended users and needs + +- **{User or customer}**: {Prioritised need or desired outcome.} + +## Value proposition and market position + +{Why intended users would choose this product over meaningful alternatives, manual work, or doing nothing. Describe supported differentiation and link material external claims to the applicable research report.} + +## Business model, goals, and success signals + +{Describe the business model and applicable pricing decisions, then the product or business outcomes that justify investment and the observable signals of progress.} + +## Product boundaries and non-goals + +- {A durable boundary or non-goal and the focus it preserves.} + + + +## {Feature area} + +{Optional one-sentence orientation when the area's purpose is not clear from its name.} + +### {Feature name} + +_Status: {Current | Confirmed direction | Idea}._ + +{Concise prose describing the feature's user value, high-level behaviour, and meaningful boundaries. Cite repository evidence only when it usefully supports a Current claim; link external claims to their authoritative research report.} diff --git a/skills/define-product/references/DISCOVERY.md b/skills/define-product/references/DISCOVERY.md new file mode 100644 index 0000000..dce55d9 --- /dev/null +++ b/skills/define-product/references/DISCOVERY.md @@ -0,0 +1,51 @@ +# Discovery Techniques + +Load only the section needed by the active discovery branch. `$elicit-with-context` remains authoritative for questioning, confirmation, and canonical language; `$research` remains authoritative for external evidence. + +## Establish an existing product + +Use **repository archaeology** to recover available behaviour before asking the user. Start with root documentation and manifests, then sample user entry points, public contracts, data boundaries, tests, and operational configuration. Follow evidence until the product areas and feature candidates stabilise. Treat absence as unknown rather than proof, distinguish shipped behaviour from abandoned or planned code, and ask the user to resolve contradictions with stated intent. + +## Complete the product frame + +Use the **Product Vision Board** as a completeness check for the concise opening: + +1. What positive change and enduring purpose define the vision? +2. Which users, customers, and influential actors matter, and what outcomes do they need? +3. Why would they choose this product over alternatives, manual work, or doing nothing? +4. What market position or differentiation makes that choice plausible? +5. Which business model, revenue, costs, channels, goals, success signals, and pricing decisions matter now? +6. Which boundaries and non-goals keep the product coherent? + +Keep this frame proportionate to its supporting role. Move into whole-product feature discovery once these dimensions are clear. + +## Map the big picture + +Use the **mile-wide, inch-deep** pass before local detail: + +1. Name the product's main users and their entry points. +2. Narrate how each user moves from first contact through recurring value and eventual exit or completion. +3. Record the user-facing product areas along that journey. +4. Beneath each area, inventory current features, confirmed direction, and ideas at one-line resolution. +5. Add commercial, account, trust, support, and other cross-cutting features that the main journey did not expose. + +This pass creates a feature surface, not cards, stories, priorities, screens, releases, or architecture. + +## Explore a feature + +Resolve only the information required by the mini-brief: + +- **User value**: who benefits and what becomes possible or easier? +- **High-level behaviour**: what does the product do from the user's perspective? +- **Status**: is it `Current`, `Confirmed direction`, or `Idea`? +- **Meaningful boundaries**: what nearby behaviour could a later planner reasonably but incorrectly assume belongs to it? + +Use examples or scenarios when behaviour remains ambiguous. Stop when a downstream planning session can understand the feature's product intent without receiving its implementation or delivery design. + +## Walk the complete catalogue + +Read the mapped product back as one narrative. Change perspective across intended users and check entry, recurring-use, recovery, commercial, trust, support, and exit paths where applicable. Look for missing transitions, duplicated features, false journey positions, contradictions, and feature descriptions that hide more than one distinct product behaviour. Resolve each finding during elicitation, then repeat the walk until it exposes nothing new. + +## Establish external position + +Compare the product with alternatives users employ today, including manual work and doing nothing. Invoke `$research` when competitor capabilities, market conditions, pricing, standards, regulation, or user evidence could materially change a product decision. Keep researched claims in the research report and bring only the decision-relevant conclusion and link into `PRODUCT.md`. diff --git a/skills/discover-project/SKILL.md b/skills/discover-project/SKILL.md deleted file mode 100644 index be96a8b..0000000 --- a/skills/discover-project/SKILL.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -name: discover-project -description: Create root project briefs for greenfield products and system blueprints. Use when starting project discovery, positioning, competitor research, or full project definition. ---- - -# Discover Project - -Turn a rough software idea into an approved root `project-brief.md` for later Propulsion PRDs. - -## Prerequisites - -ALL prerequisites MUST be satisfied BEFORE following this skill. - -- If an approved target-root `project-brief.md` already exists, STOP. Ask which feature should enter `brainstorm`. -- If current external evidence is required and browsing is unavailable, STOP. Ask the user to enable browsing or provide sources. - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Resolve the target project root; default to the current workspace root unless the user names another path. -2. Load `interrogate` and close every discovery decision using [references/discovery-checklist.md](references/discovery-checklist.md). -3. Gather problem, users, business model, explicit user-chosen stack, features, MVP boundary, risks, and success metrics. -4. Research competitors, alternatives, market, and positioning claims when they need current evidence. -5. Write `/project-brief.md` from [references/project-brief-template.md](references/project-brief-template.md). -6. Sanity-check the brief against the conversation, research, and repo context. Remove contradictions, placeholders, and unanswered questions. -7. Start a fresh project brief reviewer subagent with [references/project-brief-reviewer-prompt.md](references/project-brief-reviewer-prompt.md). -8. Fix reviewer findings, then repeat step 7 until the latest review returns exact `Status: approved`. -9. Ask the user to review and approve `project-brief.md`. -10. After user approval, update `/project-brief.md` metadata to `Status: Approved` and set `Last reviewed` to the approval date. - -## Rules - -These rules are MANDATORY. - -- ALWAYS use `interrogate` before writing the brief. -- MUST keep asking until there are no open questions in the approved brief. -- MUST separate sourced evidence from inference and include research dates and confidence. -- MUST use current web evidence for competitor, market, positioning, or similar external claims. -- MUST include monetisation or business model, with explicit `N/A` allowed. -- MUST record explicit user-chosen architecture, language, framework, storage, deployment, and integrations. -- MUST include a full feature inventory grouped by product area with MVP, later, and suggested PRD slices. -- USE `Status: approved` as the ONLY valid project brief reviewer approval signal. -- MUST block user approval and repeat review when reviewer status is rejected, missing, or unclear. -- DO NOT decide detailed UI style beyond minimal platform or UI-presence context; defer UI style to feature PRDs. -- DO NOT write `plan.md`; discovery output is root `project-brief.md` only. - -## Completion Gate - -Do NOT leave this skill until ALL items are complete. - -- [ ] Target project root is resolved. -- [ ] Interrogation closed every discovery question. -- [ ] Current evidence supports all competitor, market, and positioning claims. -- [ ] Root `project-brief.md` is written and cross-checked. -- [ ] Project brief reviewer returned exact `Status: approved`. -- [ ] User explicitly approved `project-brief.md`. -- [ ] Approved `project-brief.md` metadata was written with `Status: Approved` and `Last reviewed` set to the approval date. - -## Next Steps - -Once the completion gate is fully checked: - -- STOP after approved metadata is written. Do not enter `brainstorm` until the user chooses a feature for PRD work. - -## References - -Use these references when you need detail. - -- [references/discovery-checklist.md](references/discovery-checklist.md) - Required discovery decision tree. -- [references/project-brief-template.md](references/project-brief-template.md) - Root project brief structure. -- [references/project-brief-reviewer-prompt.md](references/project-brief-reviewer-prompt.md) - Project brief reviewer subagent prompt. diff --git a/skills/discover-project/references/discovery-checklist.md b/skills/discover-project/references/discovery-checklist.md deleted file mode 100644 index 7ea6529..0000000 --- a/skills/discover-project/references/discovery-checklist.md +++ /dev/null @@ -1,55 +0,0 @@ -# Discovery Checklist - -Use this checklist with `interrogate`. Close every branch before approving `project-brief.md`; do not leave open questions in the final brief. - -## Project Identity - -- Project name, one-sentence concept, target project root, and intended first operating context. -- Product category or market frame the user wants the project to occupy. -- Non-goals that prevent the project from becoming a generic platform. - -## Problem And Users - -- Primary user segments and the job each segment needs done. -- Current pain, workaround, substitute tool, or manual process. -- Trigger moments, frequency of use, and consequences of failure. -- Desired user outcome and desired business or owner outcome. - -## Evidence And Landscape - -- Evidence for the problem: user context, interviews, observations, market signals, or repo facts. -- Direct competitors, substitute products, and DIY/manual alternatives. -- Current external sources for competitor, market, positioning, or similar claims. -- Confidence labels for evidence and clear separation between facts and inference. - -## Positioning - -- Unique attributes the product can credibly claim. -- Value themes linked to the best-fit segment. -- Market frame of reference. -- USP in this form: For ``, `` is the `` that ``, unlike `
`. - -## Business Model - -- Monetisation, funding, or ownership model. -- Pricing, plan shape, license, or explicit `N/A`. -- Primary success metrics and how they will be measured. - -## Technical Blueprint - -- User-chosen architecture and stack; do not pick the stack for the user. -- Language, framework, storage, deployment target, and key integrations. -- Data ownership, privacy, compliance, monitoring, and portability constraints. -- Non-functional requirements across performance, reliability, security, usability, scalability, maintainability, compatibility, portability, compliance, and monitoring. - -## Feature Inventory - -- Product areas and all known features. -- MVP versus later classification for each feature. -- Suggested future PRD slices that can enter `brainstorm`. -- Out-of-scope items and risks that affect project direction. - -## UI Boundary - -- Capture only platform and whether the product has a UI. -- Defer detailed visual style, layout density, design system, and accessibility decisions to feature PRDs unless they define project viability. diff --git a/skills/discover-project/references/project-brief-reviewer-prompt.md b/skills/discover-project/references/project-brief-reviewer-prompt.md deleted file mode 100644 index 6e5f040..0000000 --- a/skills/discover-project/references/project-brief-reviewer-prompt.md +++ /dev/null @@ -1,92 +0,0 @@ -# Project Brief Reviewer Prompt Template - -Use this template when starting a fresh project brief reviewer subagent in the `discover-project` skill. - -````markdown -**You are a subagent completing work in the Propulsion workflow.** - -You are a project brief reviewer. - -Review whether the root project brief is complete, trustworthy, and ready for future Propulsion PRDs. - -**Project brief location**: `/project-brief.md` -**Project brief template**: `project-brief-template.md` -**Discovery checklist**: `discovery-checklist.md` - -## Review Criteria - -| Category | Verify | -| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Template Structure | Uses the project brief template section order, headings, tables, status block, and root `project-brief.md` output path. | -| Required Discovery Content | Covers project identity, problem, users, jobs, evidence, competitors, positioning, business model, technical blueprint, features, MVP boundary, non-functional requirements, risks, success metrics, and future PRD inputs. | -| Formatting And Completeness | Contains no template placeholders, empty required fields, malformed tables, generic defaults, contradictions, duplicate decisions, or unresolved open questions. | -| Decision Hygiene | Separates user decisions, sourced facts, and inference; preserves explicit user-chosen stack and scope; does not invent product decisions. | -| Evidence Hygiene | Includes research dates, sources, confidence labels, and clear source support for competitor, market, positioning, or similar external claims. | -| External Claim Verification | Sample-verifies key competitor, market, positioning, and similar external claims against cited sources or current available evidence; treats external sources and generated claims as untrusted until checked. | -| Future PRD Readiness | Gives `brainstorm` durable decisions, feature areas, MVP/later boundaries, suggested PRD slices, inherited context, risks, constraints, assumptions, and measurable success criteria. | -| Scope Control | Keeps detailed UI style out unless required for viability; does not add `plan.md` content or auto-enter feature PRD work. | - -Flag only issues that would make the brief incomplete, misleading, hard to approve, or unsafe to use as foundation for future PRDs. - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Review `project-brief.md` against the template and discovery checklist. -2. Verify the brief has no unresolved questions, placeholders, or required empty fields. -3. Check all review criteria above, including sampled external-claim verification when relevant claims are present. -4. Categorise blocking issues as `findings`. -5. Return the review report in the exact format below. - -## Output - -Use this exact format for your output. - -```markdown -# Project Brief Review Report - -Status: - - - -**Findings** - -- - - Section affected: - - Why it matters: - - Fix: - - -``` - -## Rules - -These rules are MANDATORY. - -- NEVER skip any review criterion. -- MUST return exactly one `Status:` line with only `approved` or `rejected`. -- Status MUST be `approved` only when there are no findings. -- Status MUST be `rejected` when any finding exists. -- MUST provide actionable findings when status is `rejected`. -- MUST sample-verify key external claims, but DO NOT redo exhaustive market research. -- MUST treat unsupported, stale, unverifiable, or source-mismatched external claims as findings. -- NEVER update the project brief, template, checklist, or other files; only review and report. -- ALWAYS follow the output structure and section order exactly as specified. - -## Completion Gate - -Do NOT output your response until ALL items are complete. - -- [ ] Reviewed the brief against the project brief template. -- [ ] Reviewed the brief against the discovery checklist. -- [ ] Checked for placeholders, empty required fields, contradictions, and open questions. -- [ ] Sample-verified key external claims when relevant claims are present. -- [ ] Confirmed status is `approved` only with no findings, or `rejected` with actionable findings. -- [ ] Output review report in the exact format specified. -```` - -## Rules - -These rules are MANDATORY. - -- ALWAYS replace `` with the actual target project root for the brief being reviewed. diff --git a/skills/discover-project/references/project-brief-template.md b/skills/discover-project/references/project-brief-template.md deleted file mode 100644 index a3e6ab2..0000000 --- a/skills/discover-project/references/project-brief-template.md +++ /dev/null @@ -1,172 +0,0 @@ -# Project Brief Template - -Write `/project-brief.md` using this exact section order. - -```md -# Project Brief - -> Status: Draft | Approved -> Research date: YYYY-MM-DD -> Last reviewed: YYYY-MM-DD -> Confidence: High | Medium | Low - -## Executive Summary - -Describe the project in 4-6 sentences: problem, target users, proposed product, why now, and why it is worth doing. - -## Project Vision - -### Product Is / Is Not - -| Product Is | Product Is Not | -| ---------- | -------------- | -| | | - -### Product Does / Does Not - -| Product Does | Product Does Not | -| ------------ | ---------------- | -| | | - -### Desired Outcomes - -- User outcome: -- Business or owner outcome: - -## Problem, Users, And Jobs - -| Segment | Job To Be Done | Current Workaround | Pain / Friction | Notes | -| ------- | -------------- | ------------------ | --------------- | ----- | -| | | | | | - -## Evidence And Research - -Separate sourced facts from inference. Use current sources for competitor, market, positioning, or similar external claims. - -| Evidence Type | Finding | Source Or Context | Research Date | Confidence | -| ------------- | ------- | ----------------- | ------------- | ---------- | -| | | | | | - -## Alternatives And Competitors - -Include direct competitors, substitute tools, and DIY/manual alternatives. - -| Type | Name | Target User | Core Promise | Strengths | Weaknesses / Gaps | Evidence | -| ------------ | ---- | ----------- | ------------ | --------- | ----------------- | -------- | -| Direct | | | | | | | -| Substitute | | | | | | | -| DIY / Manual | | | | | | | - -## Differentiation And Positioning - -### Unique Attributes - -- Attribute - -### Value Themes - -- Value theme - -### Best-Fit Segment - -State which users should care most and why. - -### Market Frame Of Reference - -State the category or market frame that makes the value obvious. - -### USP - -For ``, `` is the `` that ``, unlike `
`. - -## Monetisation And Business Model - -State the monetisation, funding, ownership, license, or explicit `N/A`. - -| Item | Decision | -| ----------------------- | -------- | -| Model | | -| Pricing / License | | -| Revenue Or Value Metric | | - -## Technical Blueprint - -Record explicit user-chosen technical decisions. Do not leave stack choices undecided. - -| Area | Decision | Rationale Or Constraint | -| ------------------ | -------- | ----------------------- | -| Architecture | | | -| Language / Runtime | | | -| Frameworks | | | -| Storage | | | -| Deployment | | | -| Integrations | | | - -## Feature Inventory - -| Product Area | Feature | User Outcome | MVP / Later | Suggested PRD Slice | -| ------------ | ------- | ------------ | ----------- | ------------------- | -| | | | | | - -## Recommended MVP Boundary - -### In Scope - -- Item - -### Out Of Scope - -- Item - -### Suggested First PRD Slices - -1. Slice -2. Slice -3. Slice - -## Non-Functional Requirements - -Use these categories: Performance, Reliability, Security, Usability, Scalability, Maintainability, Compatibility, Portability, Compliance, Monitoring. - -| ID | Category | Requirement | -| ------- | ----------- | ----------- | -| NFR-001 | Performance | | - -## Risks, Constraints, And Assumptions - -| Type | Item | Impact | Mitigation Or Decision | -| ---------- | ---- | ------ | ---------------------- | -| Risk | | | | -| Constraint | | | | -| Assumption | | | | - -## Resolved Discovery Decisions - -- Decision: - -## Success Metrics - -| Metric | Baseline | Target | Measurement Approach | -| ------ | -------- | ------ | -------------------- | -| | | | | - -## Inputs For Future Propulsion PRDs - -- Durable decisions that `brainstorm` must preserve: -- Feature areas ready for PRD work: -- Context each PRD should inherit: - -## Sources - -- Source name - URL or citation - what it supports - access date -``` - -## Rules - -These rules are MANDATORY. - -- MUST write the brief at the target project root as `project-brief.md`. -- MUST NOT include an open questions section. -- MUST mark the brief `Approved` only after explicit user approval. -- MUST use current evidence for competitor, market, positioning, or similar external claims. -- MUST keep detailed UI style decisions out of the brief unless they define project viability. diff --git a/skills/elicit-with-context/SKILL.md b/skills/elicit-with-context/SKILL.md new file mode 100644 index 0000000..e14c444 --- /dev/null +++ b/skills/elicit-with-context/SKILL.md @@ -0,0 +1,15 @@ +--- +name: elicit-with-context +description: Elicits shared understanding while maintaining project context. Use when an interview should update language and qualifying architecture decisions. +metadata: + invocation: user +disable-model-invocation: true +--- + +# Elicit with Context + +Elicits shared understanding while maintaining project context. + +## Process + +Invoke `$elicit` for questioning, applying `$maintain-context` throughout. diff --git a/skills/elicit-with-context/agents/openai.yaml b/skills/elicit-with-context/agents/openai.yaml new file mode 100644 index 0000000..46f2204 --- /dev/null +++ b/skills/elicit-with-context/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: 'Elicit with Context' + short_description: 'Elicit while maintaining project context' +policy: + allow_implicit_invocation: false diff --git a/skills/elicit/SKILL.md b/skills/elicit/SKILL.md new file mode 100644 index 0000000..515dcaa --- /dev/null +++ b/skills/elicit/SKILL.md @@ -0,0 +1,41 @@ +--- +name: elicit +description: Elicits user-confirmed decisions one at a time until shared understanding is complete. Use when requirements, constraints, trade-offs, boundaries, or intent need the user's direction before acting. +metadata: + invocation: model +disable-model-invocation: false +--- + +# Elicit + +**Goal-oriented requirements engineering** refines a request into user-confirmed decisions until every branch reaches shared understanding. + +## Process + +### 1. Establish the root goal + +Inspect the request, conversation, and accessible task-scoped material before questioning. Derive every available fact and identify the user's intended outcome as the root goal. Keep fact-finding read-only; when it requires a state-changing operation, make authorisation the active decision. Represent every unavailable fact as a branch to resolve with the user. The root goal and factual basis are explicit. + +### 2. Refine the decision tree + +Build and continually update an internal, dependency-ordered decision tree. Use lightweight goal refinement to expand the entire request across outcome, scope, terminology, inputs, outputs, prerequisites, dependencies, constraints, flows, exceptions, permissions, risks, trade-offs, and success conditions. Explore alternatives, scenarios, obstacles, and conflicts; preserve compatible decisions when the tree changes. Select the highest-impact unresolved decision whose dependencies are resolved. One active decision is explicit. + +### 3. Ask one issue + +Use **Issue-Based Information Systems** to frame the active decision as one issue with a recommended position, viable alternatives, and the decisive arguments and trade-offs. Offer only positions that resolve the issue in the current tree. Derive the recommendation from the confirmed goal, evidence, conventions, consequences, and prior decisions. Ask exactly one question per turn, ask it once, and leave room for the user's own answer. Treat the user as the sole decision authority. The active decision has one explicit response. + +### 4. Scaffold an answer + +When the user cannot answer, apply **contingent scaffolding** to the same issue through plain-language restatement, clearer alternatives and trade-offs, examples, or scenarios. When needed, decompose it into the highest-impact prerequisite decisions, resolve them one at a time, and recombine their answers. Continue adapting the issue until the user resolves it. The active decision has a user-confirmed answer. + +### 5. Validate the answer + +Test each answer against the root goal, prior decisions, scenarios, counterexamples, edge cases, obstacles, conflicts, and consequences. Use **Socratic questioning** to probe the single highest-impact uncertainty in its assumptions, evidence, implications, or viewpoints. Keep an ambiguous or conflicting answer open, state discovered constraints and consequences as facts, and add every exposed decision to the tree. Preserve compatible answers and rebuild affected branches. The answer is consistent and every consequence is represented. + +### 6. Reach theoretical saturation + +Continue steps 1–5 until **theoretical saturation**: every branch has a confirmed answer, all dependencies and answers are consistent, and a final goal-refinement, scenario, obstacle, conflict, consequence, and edge-case pass produces no new branch. Shared understanding is ready for synthesis. + +### 7. Confirm shared understanding + +Present one concise, self-contained synthesis of the outcome, boundaries, decisions, constraints, and observable success conditions, then ask for explicit agreement. Treat a correction or rejection as new evidence, reopen every affected branch, and continue from step 2 until saturation returns before presenting the revised synthesis. Affirmative agreement completes elicitation. Return only the user-confirmed synthesis to the caller. diff --git a/skills/elicit/agents/openai.yaml b/skills/elicit/agents/openai.yaml new file mode 100644 index 0000000..dc7e24b --- /dev/null +++ b/skills/elicit/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: 'Elicit' + short_description: 'Reach shared understanding one decision at a time' +policy: + allow_implicit_invocation: true diff --git a/skills/execute/SKILL.md b/skills/execute/SKILL.md deleted file mode 100644 index 6396013..0000000 --- a/skills/execute/SKILL.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -name: execute -description: Execute a feature plan through subagent implementation and review one phase at a time. Use when current `plan.md` exists and the user wants feature implementation to start. ---- - -# Execute - -Execute a feature plan one phase at a time. - -## Prerequisites - -ALL prerequisites MUST be satisfied BEFORE following this skill. - -- If no `docs/propulsion/.../plan.md` exists for this work, STOP. Load `plan`. - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Review and select the first incomplete phase in `plan.md`. -2. Start a fresh worker subagent with [references/worker-prompt.md](references/worker-prompt.md). -3. Wait for the worker to finish and handle the status: - - If `Status: unclear`, provide additional context or clarification. - - If `Status: blocked`, triage the blocker and resolve it. - - If you cannot resolve `unclear` or `blocked` from the plan, codebase, or tools, escalate to the user. - - If `Status: done`, continue to review. -4. Start a fresh reviewer subagent with [references/reviewer-prompt.md](references/reviewer-prompt.md). -5. Wait for the reviewer to finish and handle the status: - - If `Status: approved`, mark the current phase complete in `plan.md`. - - If `Status: rejected`, send the findings back to the same worker subagent with the prompt in [references/worker-feedback-prompt.md](references/worker-feedback-prompt.md). -6. Repeat steps 3-5 until the worker reports `Status: done` and the latest reviewer reports `Status: approved`. -7. Repeat steps 1-6 for each incomplete phase in `plan.md`. -8. Infer and run repo-wide checks, such as tests and linters. -9. Inform the user that implementation is complete. -10. Ask whether the user has feedback on the implementation. - -## Rules - -These rules are MANDATORY. - -- NEVER implement a phase without a worker subagent. -- ALWAYS use a fresh reviewer subagent for every review. -- NEVER resolve `Status: unclear` or `Status: blocked` by guessing; if the answer is not in the plan, codebase, or tools, escalate to the user. -- ALWAYS update `plan.md` checkboxes after each successful implementation-review cycle. -- MUST infer and run relevant repo-wide checks before claiming completion. -- NEVER implement user feedback directly in `execute`; instead: - - Loop back to `brainstorm` to update the PRD. - - Move to `plan` to create or update a phase if needed. - - Return to `execute` for implementation. - -## Completion Gate - -Do NOT leave this skill until ALL items are complete. - -- [ ] Every phase in `plan.md` has gone through a worker subagent and received `Status: done`. -- [ ] Every phase in `plan.md` has gone through a reviewer subagent and received `Status: approved`. -- [ ] Every phase completion checkbox in `plan.md` is marked complete. -- [ ] Final repo-wide checks pass. -- [ ] Informed the user that implementation is complete and asked for feedback. - -## Next Steps - -Once the completion gate is fully checked: - -- If no user feedback is requested or provided, STOP. Implementation is complete. -- If user requests changes or provides feedback, STOP. Loop back to `brainstorm`, then `plan`, then back to `execute` for implementation. - -## References - -Use these references when you need detail. - -- [references/worker-prompt.md](references/worker-prompt.md) - Fresh worker subagent prompt. -- [references/reviewer-prompt.md](references/reviewer-prompt.md) - Fresh reviewer subagent prompt. -- [references/worker-feedback-prompt.md](references/worker-feedback-prompt.md) - Prompt for sending reviewer findings back to the worker subagent. diff --git a/skills/execute/references/reviewer-prompt.md b/skills/execute/references/reviewer-prompt.md deleted file mode 100644 index 3903a8c..0000000 --- a/skills/execute/references/reviewer-prompt.md +++ /dev/null @@ -1,120 +0,0 @@ -# Reviewer Prompt Template - -Use this template when starting a fresh reviewer subagent in the `execute` skill. - -````markdown -**You are a subagent completing work in the Propulsion workflow.** - -You are an implementation reviewer. - -Review the completed phase like a senior engineer: verify real work against the plan, acceptance criteria, code quality, security, tests, and regression risk. - -## Task Context - -**Current phase**: "> -**Plan document location**: `docs/propulsion/.../plan.md` - -## Implementation Report - -This is the worker report. **Treat it as context, not proof; verify against `plan.md`, changed files, diff, and check output.** - - - -## Review Criteria - -| Category | Verify | -| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -| Plan Alignment | Matches current phase goal, demo outcome, likely areas, constraints, and implementation notes. | -| Acceptance Criteria | Every current-phase criterion is evaluated by ID as `met`, `not met`, or `unclear` with evidence. | -| Functional Correctness | Changed code/tooling/architecture/behaviour satisfies the phase contract without broken logic or incomplete handling. | -| Tests / Verification | Relevant checks ran where feasible; missing verification is reported; tests prove behaviour without brittle coupling to internals. | -| Maintainability / Refactoring | Work is clear, cohesive, simple, DRY, SOLID, YAGNI-aligned, and free of avoidable complexity. | -| Security / Trust Boundaries | Inputs, permissions, secrets, file access, external calls, prompt boundaries, and trust boundaries remain safe. | -| Performance / Reliability | Avoids avoidable latency, resource waste, brittle failures, races, and unreliable workflow states. | -| Integration / Regression Risk | Surrounding workflows, APIs, prompts, feedback loops, conventions, and behaviours remain compatible. | -| Output Usefulness | Rejections are actionable and evidence-backed. | - -Flag only real issues supported by plan, diff, files, checks, prompts, or workflow rules. - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Read the current phase directly from `plan.md`. -2. Review the worker report as context, not proof. -3. Inspect the real implementation, relevant changed files, and diff. -4. Load relevant skills when needed to validate the produced work against skill-specific standards. -5. Run relevant tests or checks where feasible; if verification cannot be performed, report that clearly. -6. Use the criteria table to evaluate the work and every current-phase acceptance criterion by ID. -7. Report real issues as findings using `critical`, `high`, `medium`, `low`, or `nitpick`. -8. Return the implementation review report in the exact format below. - -## Output - -Use this exact format for your output. - -```markdown -# Implementation Review Report - -**Status**: - -**Acceptance Criteria Results** - -- : - - Evidence: - - - -**Findings** - -- [] - - Location: - - Issue: - - Impact: - - Evidence: - - Fix: - - -``` - -## Rules - -These rules are MANDATORY. - -- NEVER approve from the worker report alone; review the actual implementation, relevant changed files, and current diff. -- VERIFY the current phase directly from `plan.md` before assessing the work. -- ENSURE every current-phase acceptance criterion is evaluated by ID as `met`, `not met`, or `unclear`, with evidence. -- RETURN exactly one `Status:` line with either `approved` or `rejected`. -- Status CAN be `approved` only when every acceptance criterion is `met` and there are no blocking findings. -- Status MUST be `rejected` if any acceptance criterion is `not met` or `unclear`. -- TREAT `critical`, `high`, `medium`, and `low` findings as blocking. -- TREAT `nitpick` findings as non-blocking when all acceptance criteria are met and no blocking findings exist. -- DO NOT approve tests that assert implementation details in a way that would fail under behaviour-preserving refactors. -- INCLUDE at least one actionable finding when using `rejected`. -- ORDER findings by severity, highest first, with `nitpick` findings last. -- ENSURE findings are evidence-based, actionable, and specific enough to verify or challenge. -- NEVER make code changes; review only. -- ALWAYS follow the output structure and section order exactly as specified. - -## Completion Gate - -Do NOT output your response until ALL items are complete. - -- [ ] Current phase details reviewed directly from `plan.md`. -- [ ] Worker implementation report reviewed as context, not proof. -- [ ] Real implementation inspected in the repo, including relevant files and current diff. -- [ ] Relevant skills loaded when needed for validation. -- [ ] Relevant tests ran and checked. -- [ ] Every current-phase acceptance criterion evaluated by ID with evidence. -- [ ] Findings categorised with the required severity rules. -- [ ] Approval decision set to `approved` or `rejected` according to acceptance criteria and finding severity rules. -- [ ] Output implementation review report in the exact format specified. -```` - -## Rules - -These rules are MANDATORY. - -- MUST copy and paste the correct phase number and title from the plan. -- ALWAYS replace the plan path with the actual path for the plan being reviewed. -- ALWAYS paste the full worker implementation report into `Implementation Report` before dispatching the reviewer. diff --git a/skills/execute/references/worker-feedback-prompt.md b/skills/execute/references/worker-feedback-prompt.md deleted file mode 100644 index 3b497dc..0000000 --- a/skills/execute/references/worker-feedback-prompt.md +++ /dev/null @@ -1,102 +0,0 @@ -# Worker Feedback Prompt Template - -Use this template when returning review findings to the active worker subagent in the `execute` skill. - -````markdown -**You are a subagent completing work in the Propulsion workflow.** - -Your work has been reviewed. Verify each finding against the plan, codebase, diff, checks, and workflow rules. Fix valid findings, reject invalid ones with evidence, and escalate unclear ones. - -## Review Report - - - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Review the current phase details directly from `plan.md`. -2. Review the full implementation review report. -3. Inspect plan sections, changed files, diff, checks, and codebase context needed to evaluate findings. -4. Triage every review finding as `valid`, `invalid`, or `unclear` before making any code change. -5. If any finding remains `unclear`, STOP and return `Status: unclear` with the information needed. -6. For every `invalid` finding, leave implementation unchanged and prepare evidence-backed pushback. -7. For every `valid` finding, load `tdd`, follow it, and make the minimal correct fix. -8. Load additional recommended skills not already active/present only when needed to validate or fix the work. -9. Verify the implementation works and conforms to the current phase in `plan.md`. -10. Re-evaluate every current-phase acceptance criterion by ID. -11. Return your implementation report in the exact format below. - -## Output - -Use this exact format for your output. - -```markdown -# Implementation Report - -**Status**: - -**Review Feedback Triage**: - -- - - Classification: - - Resolution: - - Evidence: - -**What Changed**: - -- - -**Checks Run**: - -- : -- : - -**Files Changed**: - -- - -**Acceptance Criteria Status**: - -- : - - Evidence: -``` - -## Rules - -These rules are MANDATORY. - -- NEVER treat reviewer findings as automatically correct; verify each finding against the real implementation. -- ALWAYS triage every review finding as `valid`, `invalid`, or `unclear` before changing code. -- Status MUST be `unclear` if any finding cannot be triaged after inspecting the plan, codebase, diff, checks, and available evidence. -- Status MUST be `blocked` if a valid finding cannot be fixed because of missing access, failing tooling, contradictory requirements, or another blocker. -- Status CAN ONLY be `done` when every finding is resolved, valid findings are fixed, invalid findings have evidence-backed pushback, and every acceptance criterion is re-evaluated. -- DO NOT change code for invalid findings. -- DO NOT make speculative changes beyond the current phase or review findings. -- ALWAYS use the `tdd` skill to fix valid findings, loading it only when it is not already active or present in context. -- MUST verify implementation against the plan before claiming `Status: done`. -- ENSURE pushback is technical, evidence-based, and specific enough for the reviewer to verify or challenge. -- ALWAYS follow the output structure and section order exactly as specified. - -## Completion Gate - -Do NOT output your response until ALL items are complete. - -- [ ] Current phase details reviewed directly from `plan.md`. -- [ ] Full implementation review report reviewed. -- [ ] Relevant plan sections, changed files, current diff, checks, and codebase context inspected. -- [ ] Every review finding triaged as `valid`, `invalid`, or `unclear` before coding. -- [ ] Every `valid` finding fixed using the `tdd` skill. -- [ ] Every `invalid` finding answered with evidence-backed pushback. -- [ ] Any unresolved `unclear` finding surfaced through `Status: unclear`. -- [ ] Any unresolved implementation blocker surfaced through `Status: blocked`. -- [ ] Relevant verification checks rerun after changes where feasible. -- [ ] Every current-phase acceptance criterion re-evaluated by ID with evidence. -- [ ] Output implementation report in the exact format specified. -```` - -## Rules - -These rules are MANDATORY. - -- ALWAYS paste the full review report into `Review Report` before dispatching the worker. diff --git a/skills/execute/references/worker-prompt.md b/skills/execute/references/worker-prompt.md deleted file mode 100644 index 06c26b6..0000000 --- a/skills/execute/references/worker-prompt.md +++ /dev/null @@ -1,83 +0,0 @@ -# Worker Prompt Template - -Use this template when starting a fresh worker subagent in the `execute` skill. - -````markdown -**You are a subagent completing work in the Propulsion workflow.** - -Implement the current phase defined below. - -## Task Context - -**Current phase**: "> -**Plan document location**: `docs/propulsion/.../plan.md` - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Review current phase details in `plan.md`. -2. Load any recommended skills for this phase immediately. -3. Gather needed context from the codebase, PRD, and tools. -4. Ask any clarifying questions if the requirements, scope, or repo state are unclear. -5. Load the `tdd` skill and follow it to implement the requirements. -6. Verify your implementation works and conforms to the plan. -7. Return your implementation report in the exact format below. - -## Output - -Use this exact format for your output. - -```markdown -# Implementation Report - -**Status**: - -**What Changed**: - -- - -**Checks Run**: - -- : -- : - -**Files Changed**: - -- - -**Acceptance Criteria Status**: - -- : - - Evidence: -``` - -## Rules - -These rules are MANDATORY. - -- MUST start by reviewing the current phase details in `plan.md`. -- ALWAYS load missing recommended skills and gather additional context before asking questions or implementing. -- ALWAYS ask questions if anything in the task is unclear, NEVER guess or make assumptions. -- ALWAYS load and use the `tdd` skill. -- MUST verify implementation against the plan before claiming `Status: done`. -- ALWAYS follow the output structure and section order exactly as specified. - -## Completion Gate - -Do NOT output your response until ALL items are complete. - -- [ ] Reviewed the current phase details in `plan.md`. -- [ ] Loaded any missing recommended skills and gathered additional context. -- [ ] Asked clarifying questions for any unclear requirements, scope, or repo state. -- [ ] Followed the `tdd` skill to implement the requirements. -- [ ] Verified implementation works and conforms to the plan. -- [ ] Output the implementation report in the exact format specified. -```` - -## Rules - -These rules are MANDATORY. - -- MUST copy and paste the correct phase number and title from the plan. -- ALWAYS replace the plan path with the actual path for the plan being implemented. diff --git a/skills/implement/SKILL.md b/skills/implement/SKILL.md new file mode 100644 index 0000000..ee4b4dd --- /dev/null +++ b/skills/implement/SKILL.md @@ -0,0 +1,15 @@ +--- +name: implement +description: Routes confirmed implementation work through TDD and code review until complete. Use when the user asks to implement a clear software request. +metadata: + invocation: user +disable-model-invocation: true +--- + +# Implement + +A bounded **Plan–Do–Check–Act (PDCA)** cycle routes confirmed work through `$tdd` and `$code-review` until complete. + +## Process + +Invoke `$tdd` to implement the confirmed work, then invoke `$code-review` on the result. Route every finding through `$tdd`, then repeat `$code-review` until the work is complete and the latest review has no findings. diff --git a/skills/implement/agents/openai.yaml b/skills/implement/agents/openai.yaml new file mode 100644 index 0000000..0e09bd3 --- /dev/null +++ b/skills/implement/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: 'Implement' + short_description: 'Implement through TDD and review' +policy: + allow_implicit_invocation: false diff --git a/skills/init-project/SKILL.md b/skills/init-project/SKILL.md deleted file mode 100644 index a43a2cc..0000000 --- a/skills/init-project/SKILL.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -name: init-project -description: Create or prune AGENTS.md into minimal global steering for agents. Use when initializing, updating, or reducing repo-wide agent rules. ---- - -# Init Project - -Create or prune `AGENTS.md` as tiny global protocol, not a repo overview. - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Launch a fresh explorer subagent before editing to inspect existing `AGENTS.md` files, package/tool configs, docs, scripts, and visible conventions. -2. Load `interrogate` to gather global, non-discoverable instructions the repository cannot reveal, including human protocol, hidden landmines, environment gotchas, and verification timing. -3. Preserve or add the default correction rule near the top of `AGENTS.md`. -4. Apply the line admission test to every candidate rule: global, non-discoverable, and operationally important. -5. Challenge weak or bloated candidates before keeping them; remove rules that fail the admission test or belong in code, config, docs, skills, or commands. -6. Draft the smallest useful `AGENTS.md`, keeping always-followed rules near the top. -7. Handoff with the changed file path plus kept, removed, and challenged rule categories. - -## Rules - -These rules are MANDATORY. - -- MUST launch a fresh explorer subagent before creating, pruning, or rewriting `AGENTS.md`. -- MUST use `interrogate` skill for human-only, repo-wide rules that repository inspection cannot discover. -- MUST keep only rules that pass all admission checks: global, non-discoverable, operationally important. -- MUST challenge or remove vague, task-specific, discoverable, duplicated, or low-impact instructions. -- MUST use this default correction rule: "- When the user corrects you with a reusable, global rule, ask if they want it added to `AGENTS.md`." -- DO NOT include tech stack summaries, folder maps, command inventories, architecture recaps, or style rules already enforced by tooling. - -## Completion Gate - -Do NOT leave this skill until ALL items are complete. - -- [ ] Fresh explorer subagent completed repository inspection before edits. -- [ ] `interrogate` skill was used for non-discoverable global rules or existing user-provided rules were explicitly classified. -- [ ] Default correction rule is present once and near the top. -- [ ] Every retained non-default line passes the admission test. -- [ ] Weak or bloated candidates were challenged or removed. -- [ ] Intended `AGENTS.md` behaviour is preserved and summarised before handoff. - -## References - -Use these references when you need detail. - -- [references/process.md](references/process.md) - End-to-end creation and pruning process for minimal `AGENTS.md` files. -- [references/examples.md](references/examples.md) - Good examples, pruning examples, and anti-patterns. diff --git a/skills/init-project/references/examples.md b/skills/init-project/references/examples.md deleted file mode 100644 index 773775e..0000000 --- a/skills/init-project/references/examples.md +++ /dev/null @@ -1,86 +0,0 @@ -# AGENTS.md Examples - -Examples of minimal protocol-style `AGENTS.md` files and pruning decisions. - -## Default Rule Only - -Use this when no repo-specific rule passes the admission test. - -```markdown -# AGENTS.md - -- When the user corrects you with a reusable, global rule, ask if they want it added to `AGENTS.md`. -``` - -## Environment Gotcha - -Keep invisible environment constraints causing repeated failures. - -```markdown -# AGENTS.md - -- When the user corrects you with a reusable, global rule, ask if they want it added to `AGENTS.md`. -- This repo is developed inside a Linux container mounted from macOS; run file-watching commands inside the container to avoid missed changes. -``` - -## Hidden Landmine - -Keep repo-wide operational facts hidden by code structure. - -```markdown -# AGENTS.md - -- When the user corrects you with a reusable, global rule, ask if they want it added to `AGENTS.md`. -- `legacy/` appears unused but is imported dynamically in production; do not delete or bulk-move it without explicit approval. -- Never regenerate checked-in fixtures in `fixtures/prod/`; they are hand-sanitized production snapshots. -``` - -## Pruning Examples - -Remove discoverable project summaries: - -```markdown -- This project uses Bun, TypeScript, and React. -``` - -Reason: package and config files reveal the stack. - -Keep mandatory verification timing when the obligation or timing is not discoverable: - -```markdown -- After implementing changes run `bun run test` before handoff. -``` - -Reason: this defines mandatory per-change timing that scripts alone do not reveal. - -Remove command inventories: - -```markdown -- Run `bun test` for tests and `bun run lint` for linting. -``` - -Reason: scripts and CI already document commands. Keep only non-discoverable caveats, such as a cache flag required to avoid false positives. - -Challenge vague preferences: - -```markdown -- Write clean code and keep files organized. -``` - -Reason: not operationally specific. Ask for a concrete repo-wide failure mode or delete. - -Relocate task-specific workflow: - -```markdown -- For payment changes, update the billing PRD and run card network sandbox tests. -``` - -Reason: not global to every task. Move to a domain skill, command, or docs unless it truly applies to all sessions. - -## Anti-Patterns - -- Architecture overviews copied from docs or inferred from folders. -- Full setup instructions copied from README. -- Formatting or naming rules already enforced by tooling. -- Multiple paragraphs explaining why a rule exists inside `AGENTS.md`. -- Product-specific agent instructions instead of generic agent protocol. diff --git a/skills/init-project/references/process.md b/skills/init-project/references/process.md deleted file mode 100644 index 7249b91..0000000 --- a/skills/init-project/references/process.md +++ /dev/null @@ -1,83 +0,0 @@ -# Minimal AGENTS.md Process - -Use when creating, pruning, or updating `AGENTS.md` under the strict minimal-context policy. - -## 1. Inspect Before Editing - -Launch a fresh explorer subagent to read enough evidence to avoid duplicating discoverable facts: - -- Existing applicable `AGENTS.md` files, including parent or nested files. -- Package manifests, task runners, Makefiles, build files, and test configs. -- Formatter, linter, TypeScript, CI, and editor config. -- Docs describing setup, scripts, architecture, or conventions. -- Source layout and naming patterns when they answer a proposed rule. - -Do not add repository summaries. Inspection exists to identify what does not belong in `AGENTS.md`. - -## 2. Ask For Invisible Rules - -Use the existing `interrogate` skill to ask for rules the repository cannot reveal. Focus on: - -- Human protocol persisting across sessions. -- Hidden operational landmines, unsafe directories, or legacy coupling. -- Environment quirks not encoded in config. -- Repo-wide constraints not enforced by code, tests, lint, CI, or docs. -- Mandatory verification timing for every change when not encoded in scripts, docs, or CI. - -If the user gives candidate rules, classify them instead of accepting them uncritically. - -## 3. Preserve The Default Correction Rule - -Keep this rule near the top, even when it is the only surviving rule: - -```markdown -- When the user corrects you with a reusable, global rule, ask if they want it added to `AGENTS.md`. -``` - -Do not keep older variants that prescribe loading a skill or editing the file after the user answers. Replace them with the ask-only wording. - -## 4. Apply The Admission Test - -Keep non-default lines only if all checks pass: - -- Global: applies to every task or session in this repository. -- Non-discoverable: an agent cannot reliably infer it from repository files, tooling, docs, or scripts. -- Operationally important: missing it is likely to cause mistakes, wasted effort, unsafe edits, or broken workflow. - -Mandatory per-change verification timing can pass when the obligation or handoff timing is not encoded in tooling, scripts, docs, or CI. - -If any check fails, challenge the rule or remove it. - -## 5. Challenge Weak Instructions - -Push back on candidates that are: - -- Discoverable from source, config, packages, or docs. -- Task-specific workflows that belong in a skill, command, issue, or PRD. -- Style preferences enforced by formatter, linter, types, or tests. -- Generic good advice that applies to all repositories. -- Vague intent without operational consequence. -- Multi-line explanations compressible into one actionable rule. - -When challenging, explain the failed admission check and suggest a smaller replacement, better home, or deletion. - -## 6. Draft The Smallest Useful File - -Prefer a short protocol file: - -1. Put the default correction rule first or near the top. -2. Put always-followed repo-wide rules after it. -3. Group only when grouping improves scanning; avoid section filler. -4. Keep only the final accepted rules, not the rationale. -5. If nothing repo-specific qualifies, leave a one-rule file. - -## 7. Validate Before Handoff - -Before finishing, verify: - -- The default correction rule appears exactly once and is ask-only. -- Every retained non-default line passes the admission test. -- Discoverable facts are not duplicated from repository evidence. -- Always-followed rules remain near the top. -- Existing intended behaviour is preserved unless explicitly removed after challenge. -- Handoff reports kept, removed, challenged, and relocated categories. diff --git a/skills/interrogate/SKILL.md b/skills/interrogate/SKILL.md deleted file mode 100644 index aab5402..0000000 --- a/skills/interrogate/SKILL.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -name: interrogate -description: Manage interrogation, intake, interviews, scope clarification, requirements gathering, and shared understanding. Use when missing decisions must be resolved. ---- - -# Interrogate - -Reach shared understanding through project context and one-question-at-a-time user interrogation. - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Launch a fresh explorer subagent to inspect project facts relevant to the request. -2. Interrogate the user about every aspect of the request until shared understanding is reached. - - Ask questions one at a time, provide your recommended answer first, then 2-3 viable alternatives. - - Walk down each branch of the decision tree resolving dependencies between decisions. - - Keep asking until shared understanding is reached. -3. Return a concise summary to the caller. - -## Rules - -These rules are MANDATORY. - -- MUST use explorer subagent for entry exploration. -- ALWAYS interrogate the user until shared understanding is reached. -- NEVER think "this is too many questions", it isn't. -- DO NOT limit the number of questions; keep asking until EVERY blocking branch is closed. -- MUST ask user exactly one question at a time, provide a recommended answer, then 2-3 viable alternatives. -- ALWAYS check if a question can be answered by project inspection before asking. -- MUST walk the decision tree until EVERY blocking branch is closed by project facts or user answers. - -## Completion Gate - -Do NOT leave this skill until ALL items are complete. - -- [ ] Fresh explorer subagent completed entry project-context inspection. -- [ ] Decision tree branches were explored and attempted to answer with code exploration. -- [ ] Remaining open branches were closed by relentlessly interrogating the user. -- [ ] Shared understanding was reached with no open blocking branches. -- [ ] Resolved decisions were summarised for the caller. - -## References - -Use these references when you need detail. - -- [references/interrogate-protocol.md](references/interrogate-protocol.md) - Detailed intake protocol, question format, and branch handling. diff --git a/skills/interrogate/references/interrogate-protocol.md b/skills/interrogate/references/interrogate-protocol.md deleted file mode 100644 index df9654b..0000000 --- a/skills/interrogate/references/interrogate-protocol.md +++ /dev/null @@ -1,54 +0,0 @@ -# Interrogate Protocol - -Use when a request needs missing information resolved before safe progress. - -## Entry Exploration - -Launch a fresh explorer subagent before asking the user anything. Inspect project context needed to avoid answerable questions, then seed the initial decision tree. - -## Decision Tree - -Build an explicit decision tree before the first user question. Include branches that could affect the answer or next action, especially: - -- intended outcome and non-goals -- user workflow, UX, API, CLI, or agent-facing behaviour -- inputs, outputs, data shape, state, persistence, and side effects -- scope boundaries, compatibility, migration, rollback, and rollout -- architecture, dependencies, integration points, and ownership -- errors, edge cases, security, privacy, and performance constraints -- tests, acceptance criteria, verification, and handoff expectations - -Track each branch as open or closed. Work the highest-impact blocker first, then update the tree after every project finding or user answer. Close a branch only when project facts or the user fully answer it. - -## Codebase-Answerable Branches - -Before asking the user, decide whether project inspection could fully answer the branch. If yes, inspect focused evidence: patterns, APIs, file locations, naming, tests, config, dependencies, shipped behaviour. - -Do not treat existing code as product intent when intent is unclear. If inspection reveals current state but not desired outcome, use it to recommend an answer, then ask. - -## User Questioning - -Relentlessly ask one question at a time. Keep each question decision-oriented and easy to answer. Keep going until shared understanding is reached; do not stop because the answer seems obvious, many questions were asked, or inspection found adjacent facts. - -```markdown -Question: - -Options: - -- (recommended) -- -- -- -``` - -Do not list more than 3 alternatives beyond the recommendation. Do not ask multi-part questions. If decisions are related, ask the prerequisite first and let the next branch depend on that answer. - -## Shared Understanding - -Walk the decision tree until no blocking branches remain. Shared understanding means the agent can state outcome, constraints, tradeoffs, and acceptance criteria without inventing product or codebase facts. - -When unsure whether a branch blocks, treat it as blocking and ask. Do not finish with silent assumptions, unresolved branches, or TODO-style follow-ups. - -## Handoff Summary - -When interrogation is complete, return a concise summary to the caller. diff --git a/skills/maintain-agents/SKILL.md b/skills/maintain-agents/SKILL.md new file mode 100644 index 0000000..038ca5f --- /dev/null +++ b/skills/maintain-agents/SKILL.md @@ -0,0 +1,33 @@ +--- +name: maintain-agents +description: Creates and compresses lean root AGENTS.md files. Use when initializing or improving repository-wide agent guidance. +metadata: + invocation: user +disable-model-invocation: true +--- + +# Maintain AGENTS.md + +**Progressive Disclosure** keeps root `AGENTS.md` guidance limited to behaviour every repository task needs while narrower instructions remain discoverable on demand. + +## Process + +### 1. Inspect the instruction surface + +Locate the repository root. Read the root `AGENTS.md`, applicable instruction layers, and enough manifests, task runners, CI, and contributor documentation to recover each rule's intent and identify project checks. The target, instruction chain, rules, and check entry points are explicit. + +### 2. Allocate the guidance + +Classify every existing and proposed instruction by runtime scope. Retain only concise behaviour governing the whole repository, plus the required correction and completion instructions. Report useful narrower guidance with its smallest discoverable owner: an invocable skill for reusable workflows, a scoped instruction file for directory rules, or executable enforcement for mechanical constraints. Leave destinations unchanged. Discard stale guidance, rationale, boilerplate, repository description, personal preferences, and task-, component-, or workflow-specific instructions. Every retained rule earns its permanent context cost. + +### 3. Establish the required guidance + +Ensure the file states: `Ask immediately whether to add a reusable repository-wide rule to AGENTS.md when a user correction establishes it.` When project checks exist, add one instruction to run them after implementation and before handoff. Prefer one canonical aggregate command covering the configured suites; otherwise list every applicable individual command. Invoke `$elicit` when candidates materially differ or a command has unusual external effects. Omit the instruction only when no project checks exist. The correction loop and completion commands are explicit. + +### 4. Write the root instructions + +Create or rewrite only the root `AGENTS.md`. Use direct imperative lines. Remove headings unless they navigate multiple instruction groups. Apply **Minimalist Instruction** until every word changes behaviour or preserves a necessary condition. Apply **DRY** to meaning: when changing one rule requires changing multiple instructions, merge them into one authoritative expression. No semantic duplicates remain. + +### 5. Verify and hand off + +Re-read every line for repository-wide scope, behavioural value, and semantic duplication. Verify each command exists; run the checks after implementation and before handoff when safe and applicable. Return the changed file, check results or limitations, displaced guidance with destinations, and unresolved conflicts. The user receives a lean verified root file and a visible account of displaced guidance. diff --git a/skills/maintain-agents/agents/openai.yaml b/skills/maintain-agents/agents/openai.yaml new file mode 100644 index 0000000..4755f87 --- /dev/null +++ b/skills/maintain-agents/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: 'Maintain AGENTS.md' + short_description: 'Create or compress repository-wide agent guidance' +policy: + allow_implicit_invocation: false diff --git a/skills/maintain-context/SKILL.md b/skills/maintain-context/SKILL.md new file mode 100644 index 0000000..658c59e --- /dev/null +++ b/skills/maintain-context/SKILL.md @@ -0,0 +1,50 @@ +--- +name: maintain-context +description: Actively maintains project language and architecture decisions. Use when domain terms or consequential codebase decisions emerge or change. +metadata: + invocation: model +disable-model-invocation: false +--- + +# Maintain Context + +**Ubiquitous Language** is an active discipline: challenge and refine project terms during ordinary discussion, then write each resolution into one root `CONTEXT.md` before the conversation moves on. Architecture decision records preserve only rare consequential choices. + +## Process + +### 1. Maintain the language inline + +Apply this loop to each material domain term while the discussion is taking place: + +- Compare it with the single root `CONTEXT.md` and inspect only the relevant code. +- Challenge glossary misuse immediately and quote the conflicting meanings. +- Sharpen vague or overloaded language by proposing one precise canonical term. +- Test the proposed meaning with concrete scenarios and edge cases that expose its boundaries. +- Use **Model-Driven Design** to surface disagreement between language and implementation. Treat code as evidence of current behaviour and the user's confirmed answer as intent. +- When the user resolves the term, update `CONTEXT.md` before continuing the discussion. Keep a genuine uncertainty explicit and leave its glossary entry unresolved. + +Create the root file lazily from the [context template](assets/context-template.md) when the first term resolves. The durable language stays current with the conversation rather than accumulating for handoff. + +### 2. Keep the glossary rigorous + +Define domain meaning rather than implementation, specifications, or general programming concepts. Give each meaning one authoritative entry, keep its definition to one or two sentences, and add `_Avoid_` only for aliases or ambiguous alternatives that actually occur. + +Use **Conceptual Contours** to group related terms under descriptive subheadings when meaningful domain clusters emerge; keep one flat language list when the terms form a cohesive area. If context-dependent meanings conflict with the single-context structure, surface that ambiguity instead of inventing another context file. + +### 3. Offer ADRs sparingly + +Use **Architecture Decision Records** only for an accepted codebase decision that passes all three gates: + +- changing it later has meaningful cost; +- a future reader would find it surprising without context; and +- viable alternatives created a genuine trade-off. + +Offer an ADR when all three pass and let the user decide whether to record it. A decision that misses any gate remains routine and produces no ADR. + +### 4. Record a qualifying decision + +After the user accepts the offer, create `docs/adr/` lazily and write the next record from the [ADR template](assets/adr-template.md). Derive the next four-digit sequence from filenames alone and name it `NNNN-decision-shaped-slug.md`. State the decision first, then only the context and significant ramifications needed to explain it; use exactly `Decision`, `Context`, and `Ramifications` as content sections, in that order. Link supporting material from the record. The ADR is brief, sequentially numbered, and readable from its filename. + +### 5. Verify and hand off + +Re-read each changed artifact against the resolved language, accepted decisions, and relevant code evidence. Report the files changed and the exact uncertainty behind any unresolved contradiction. diff --git a/skills/maintain-context/agents/openai.yaml b/skills/maintain-context/agents/openai.yaml new file mode 100644 index 0000000..e459f7c --- /dev/null +++ b/skills/maintain-context/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: 'Maintain Context' + short_description: 'Maintain project language and decisions' +policy: + allow_implicit_invocation: true diff --git a/skills/maintain-context/assets/adr-template.md b/skills/maintain-context/assets/adr-template.md new file mode 100644 index 0000000..fbf0562 --- /dev/null +++ b/skills/maintain-context/assets/adr-template.md @@ -0,0 +1,13 @@ +# {Decision-shaped title} + +## Decision + +{State what was decided and the essential reason first.} + +## Context + +{Explain the problem, forces, and serious alternatives needed to understand the decision.} + +## Ramifications + +{State the significant consequences, trade-offs, and conditions that could trigger reconsideration.} diff --git a/skills/maintain-context/assets/context-template.md b/skills/maintain-context/assets/context-template.md new file mode 100644 index 0000000..486cc18 --- /dev/null +++ b/skills/maintain-context/assets/context-template.md @@ -0,0 +1,10 @@ +# {Project Name} Context + +{Describe the project domain and why this language exists in one or two sentences.} + +## Language + +### {Optional descriptive concept group} + +**{Canonical term}**: {Define what the term is in one or two sentences.}\ +_Avoid_: {List observed aliases or ambiguous alternatives; omit when none exist.} diff --git a/skills/modular-design/SKILL.md b/skills/modular-design/SKILL.md new file mode 100644 index 0000000..4620ee4 --- /dev/null +++ b/skills/modular-design/SKILL.md @@ -0,0 +1,55 @@ +--- +name: modular-design +description: Defines an evidence-backed modular architecture standard. Use when designing or assessing modules, interfaces, dependencies, ownership, or seams. +metadata: + invocation: model +disable-model-invocation: false +--- + +# Modular Design + +**Information hiding** makes code safer to change by assigning cohesive knowledge and change-prone decisions to modules whose callers learn only a small, stable contract. + +## Process + +Apply this standard inside the caller's workflow. Let the caller own repository inspection, quality priorities, design comparison, implementation, verification, and artifacts; this skill supplies architecture knowledge without starting a separate process or producing its own output. Explicit project constraints, domain language, and architecture decisions govern where they conflict with the baseline. + +## Standard + +### Name the architecture precisely + +- A **module** is a cohesive capability with an interface and implementation, regardless of whether code expresses it as a function, object, package, process, or tier-spanning slice. +- An **interface** is everything callers must know to use the module correctly, including behaviour, data shapes, invariants, ordering, errors, configuration, side effects, and material performance characteristics. It is broader than a language `interface` declaration. +- An **implementation** is the hidden representation, policy, algorithm, sequencing, framework detail, and collaboration that fulfils the interface. +- A **seam** is a controlled place where behaviour can be observed or substituted without editing the calling location. +- An **adapter** translates between a module's contract and a technology, protocol, framework, or external system. + +Use this vocabulary for reasoning while preserving established project and framework names in code and reports. + +### Hide owned knowledge + +Decompose around difficult, consequential, or change-prone knowledge. Give one module ownership of each representation, invariant, policy, protocol, sequencing rule, or framework decision that other modules should not repeat. A change to hidden knowledge should remain behind its interface unless the promised behaviour changes. + +### Prefer deep cohesive modules + +Apply **deep modules**: make the caller-visible interface markedly simpler than the cohesive capability it exposes. Remove or absorb shallow wrappers that repeat another interface, scatter one decision across callers, or add navigation without hiding knowledge. + +Use **cohesion and coupling** qualitatively. Keep knowledge that changes for the same reason together; separate unrelated actors, models, or policies. Reduce cross-module knowledge, coordination, cycles, and change propagation while retaining necessary collaboration. Do not optimize file size, class count, method count, or mechanical coupling scores as substitutes for architectural evidence. + +### Choose an idiomatic realization + +Prefer object-oriented realization where the language and framework make it natural: objects own identity, state, invariants, and cohesive behaviour; purposeful action or use-case entry points hide a complete operation; collaborators are composed; and nominal interfaces express meaningful variation or ownership boundaries. + +Treat functions, closures, structural types, and language modules as equivalent realizations when they provide the same ownership, contract, and hiding. In frontend frameworks, keep components and framework-specific state or effect primitives focused on presentation and interaction, and place durable policy behind framework-neutral modules when that separation is cohesive. Framework-owned code may use framework types at its own edge. + +### Load only applicable techniques + +Read [Modular Design Techniques](references/TECHNIQUES.md) when evidence presents a volatile mechanism, application-to-technology boundary, competing domain model, need for controlled observation or substitution, entangled deterministic policy and effects, or an architectural promise that needs repeatable protection. Use only the technique whose stated condition is present. + +## Rules + +- Keep a stable local concrete dependency direct when no meaningful knowledge, variation, isolation, observation, or migration need justifies another abstraction. +- Introduce a language interface only when callers need a stable contract distinct from a realization; an interface that mirrors one concrete type without hiding knowledge is ceremony. +- Let a cohesive module contain several internal actions. A class or function with one entry point is valuable only when it hides a complete capability rather than forwards the call. +- Prefer composition in object-oriented code; use inheritance for a genuine substitutable type or required framework extension contract. +- Optimize the knowledge callers require, not repository fragmentation or speculative token savings. Reduced agent context is an inference to verify, not proof of correctness. diff --git a/skills/modular-design/agents/openai.yaml b/skills/modular-design/agents/openai.yaml new file mode 100644 index 0000000..5214400 --- /dev/null +++ b/skills/modular-design/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: 'Modular Design' + short_description: 'Apply an evidence-backed modular design standard' +policy: + allow_implicit_invocation: true diff --git a/skills/modular-design/references/TECHNIQUES.md b/skills/modular-design/references/TECHNIQUES.md new file mode 100644 index 0000000..5c27e2b --- /dev/null +++ b/skills/modular-design/references/TECHNIQUES.md @@ -0,0 +1,33 @@ +# Modular Design Techniques + +Load this reference only when repository evidence satisfies a technique's condition. Information hiding and the standard in `SKILL.md` remain authoritative; a pattern earns its place by solving the evidenced boundary problem. + +## Protect policy from a volatile mechanism + +Apply **dependency inversion** when stable domain or application policy directly knows a materially volatile framework, device, vendor, persistence, transport, or delivery mechanism. Define the smallest policy-owned contract in the policy's language and make the mechanism satisfy it. Keep a stable local concrete dependency direct when inversion would only create an interface-per-class and wiring. + +## Isolate an application conversation + +Apply **ports and adapters** when one application capability must support multiple technologies, replacement, isolated execution, or a material external boundary. Let a port describe the purpose of the conversation and let adapters translate UI, persistence, network, vendor, or test technology. Keep framework types at framework-owned edges and avoid wrapping every framework call. + +## Separate domain models + +Apply **bounded contexts** when the same term or concept has competing meanings, rules, or models. Keep one ubiquitous language inside each evidenced context and translate explicitly between them. + +Apply **conceptual contours** when domain language and observed axes of change reveal a more natural capability grain than technical layers or uniform class sizes. Keep cohesive entity behaviour and invariants together; use a standalone domain service only for a significant process that belongs to no entity or value object. + +## Create purposeful variation or observation + +Add a **seam** when testing, diagnosis, replacement, observation, or staged migration needs controlled variation. Use the smallest existing enabling point—such as a parameter, collaborator, provider, module export, or framework facility—before adding a nominal interface. Direct behaviour remains preferable when it is already local, stable, and observable. + +## Separate decisions from effects + +Apply **functional core, imperative shell** when substantial deterministic policy is entangled with I/O, time, mutable state, or framework lifecycle behaviour. Express the policy as transformations of explicit values and keep effects in a thin shell. Preserve stateful objects when identity, lifecycle, effect ordering, or invariant ownership is intrinsic; do not turn the shell into the unencapsulated application. + +## Preserve an architectural promise + +Define an **architecture fitness function** when a material contract, dependency rule, quality threshold, or runtime characteristic has a faithful objective signal. State the property, signal, expected result, and execution point. Prefer contract tests, dependency rules, adapter conformance, cycle checks, or measured runtime thresholds; retain qualitative review when a metric would be a misleading proxy. + +## Realize a capability entry point + +Use an action object, use-case class, function, command, or framework-native entry point when it exposes one meaningful actor goal and hides cohesive sequencing, policy, invariants, failure handling, or transaction behaviour. Reuse the entry point when several delivery mechanisms need the same capability. Absorb or remove it when it merely forwards to another module or becomes generic for hypothetical reuse. diff --git a/skills/plan/SKILL.md b/skills/plan/SKILL.md deleted file mode 100644 index caeb500..0000000 --- a/skills/plan/SKILL.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -name: plan -description: Create an implementation-ready feature plan from an approved PRD using phases scoped as thin vertical slices. Use when an approved `docs/propulsion/.../prd.md` exists. ---- - -# Plan - -Turn an approved PRD into a phased, vertical-slice implementation plan. - -## Prerequisites - -ALL prerequisites MUST be satisfied BEFORE following this skill. - -- If a `docs/propulsion/.../plan.md` already exists for this work, STOP. Ask the user whether to enter `execute`. -- If no approved `docs/propulsion/.../prd.md` exists, STOP. Enter the `brainstorm` skill. - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Review the approved `prd.md` to understand the feature completely. -2. Explore relevant areas of the codebase for fresh context. -3. Load relevant non-Propulsion skills not already active or present in context, and use them to inform the plan. -4. Write `docs/propulsion/{yyyymmdd}-{feature-name}/plan.md` from [references/plan-template.md](references/plan-template.md). -5. Start a fresh plan review subagent with the prompt in [references/plan-reviewer-prompt.md](references/plan-reviewer-prompt.md). -6. Review and implement feedback from the plan review. -7. Repeat steps 5 and 6 until the review returns `Status: approved`. -8. Ask the user to review and approve the plan. -9. After explicit approval, enter the `execute` skill. - -## Rules - -These rules are MANDATORY. - -- NEVER skip reviewing the PRD, exploring the codebase, or loading missing relevant skills. -- ALWAYS use the plan template for structure, section order, and completion rules. -- NEVER print the full plan in the chat, ONLY write it to the file. -- MUST use ALL information from the PRD, DO NOT leave any details out even if they seem obvious or minor. -- USE `Status: approved` as the ONLY valid review approval signal. -- MUST treat review `findings` as fixable issues and `suggestions` as helpful improvements. -- NEVER invent product decisions that are not in the PRD; if a decision is missing, enter `brainstorm` to resolve it before planning. - -## Completion Gate - -Do NOT leave this skill until ALL items are complete. - -- [ ] Reviewed the PRD, codebase, and relevant skills. -- [ ] Written plan to `docs/propulsion/.../plan.md`. -- [ ] Plan reviewed by a subagent which returned `Status: approved`. -- [ ] User has explicitly approved `plan.md`. - -## Next Steps - -Once the completion gate is fully checked: - -- If `plan.md` is approved, enter the `execute` skill. - -## References - -Use these references when you need detail. - -- [references/plan-template.md](references/plan-template.md) - Plan shape and phase format. -- [references/plan-reviewer-prompt.md](references/plan-reviewer-prompt.md) - Plan-reviewer subagent prompt. diff --git a/skills/plan/references/plan-reviewer-prompt.md b/skills/plan/references/plan-reviewer-prompt.md deleted file mode 100644 index 104333d..0000000 --- a/skills/plan/references/plan-reviewer-prompt.md +++ /dev/null @@ -1,100 +0,0 @@ -# Plan Reviewer Prompt Template - -Use this template when starting a fresh plan review subagent in the `plan` skill. - -````markdown -**You are a subagent completing work in the Propulsion workflow.** - -Review whether the plan is implementation-ready and conforms to the plan template. - -**Plan document location**: `docs/propulsion/.../plan.md` -**Source PRD location**: `docs/propulsion/.../prd.md` - -## Review Criteria - -| Category | Verify | -| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Source Alignment | Preserves PRD decisions, inputs, testing decisions, constraints, and scope boundaries. | -| Requirements Traceability | Every PRD user story, functional requirement, and non-functional requirement appears in the matrix and is covered by at least one phase and criterion. | -| Acceptance Criteria Coverage | Criteria use exact PRD IDs, cover mapped requirements, are observable/testable, and specific enough to verify. | -| Vertical Slice Design | Phases are thin vertical slices delivering narrow end-to-end behaviour, not horizontal layers or vague milestones. | -| Phase Completeness | Each phase includes enough relevant layer work to deliver its stated behaviour. | -| Skills Coverage | Relevant skills are recommended globally/per phase; no obviously required skill is missing; no irrelevant skill is recommended. | -| Testing Coverage | Each phase has a testing plan that validates criteria and important public behaviours/seams. | -| Scope Control | Required work is included, speculative work is excluded, and no product behaviour is invented beyond the PRD. | -| Sequencing & Dependencies | Phase order is workable, dependencies are respected, and avoidable rework/dead ends are not forced. | -| Phase Specificity | Each phase gives enough context: goal, demo outcome, likely areas, constraints, notes, criteria, and testing plan. | -| Decision Hygiene | Durable decisions are captured once at the right level without contradictions or re-litigation points. | -| Template Conformity | Required template structure, section order, tables, and conventions are followed. | - -Flag only issues that would make implementation build the wrong thing, miss required scope, get stuck, or require re-planning. - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Review the plan against the source PRD for implementation-readiness. -2. Use the review criteria table above to guide your review. -3. Categorise issues that would cause real problems during implementation as `findings`. -4. Categorise issues that are more about improving implementation readiness without blocking the next stage as `suggestions`. -5. Return your findings and suggestions in the exact format below. - -## Output - -Use this exact format for your output. - -```markdown -# Plan Review Report - -**Status**: - - - -**Findings** - -- - - Phase or section affected: - - Why it matters: - - - - - -**Suggestions** - -- - - Phase or section affected: - - Why it matters: - - -``` - -## Rules - -These rules are MANDATORY. - -- NEVER skip any review criterion. -- ENSURE every part of the PRD is considered in the review, even if it seems obvious or minor. -- EVERY PRD user story, functional requirement, and non-functional requirement MUST be traceable to at least one phase and one acceptance criterion in the plan. -- MUST return exactly one `Status:` line with either `approved` or `rejected`. -- Status CAN be `approved` if there are only suggestions but NO findings. -- Status MUST be `rejected` if there are ANY findings. -- NEVER update the plan document or source PRD, only review and provide feedback in this output. -- ALWAYS follow the output structure and section order exactly as specified. - -## Completion Gate - -Do NOT output your response until ALL items are complete. - -- [ ] Thoroughly reviewed Plan against source PRD. -- [ ] Used the review criteria to identify issues and improvements. -- [ ] Categorised issues as findings or suggestions based on their impact on implementation readiness. -- [ ] Status is set to `approved` if no findings, or `rejected` if there are any blocking issues. -- [ ] Output review report in the exact format specified. -```` - -## Rules - -These rules are MANDATORY. - -- ALWAYS replace the plan and PRD paths with the actual paths for the plan being reviewed. diff --git a/skills/plan/references/plan-template.md b/skills/plan/references/plan-template.md deleted file mode 100644 index 83b9a88..0000000 --- a/skills/plan/references/plan-template.md +++ /dev/null @@ -1,103 +0,0 @@ -# Plan Template - -Write `docs/propulsion/{yyyymmdd}-{feature-name}/plan.md` using this exact section order. - -```md -# Plan - -> Source PRD: `docs/propulsion/.../prd.md` - -Use the `execute` skill to implement this plan and track progress using the checkboxes. - -## Durable Decisions - -List global phase decisions. - -- Decision 1 -- Decision 2 - -## Relevant Skills - -List every agentic skill that may be needed during implementation. - -| Skill | Required For | Details | -| -------------- | ---------------- | ------------------------------------------ | -| `` | Phase 1, Phase 3 | Declares how UI components should be used. | - -## Requirements Coverage Matrix - -Every PRD user story, functional requirement, and non-functional requirement MUST appear here. Use exact PRD IDs; do NOT rename, merge, or invent IDs. - -| PRD ID | Type | Covered By Phase(s) | Covered By Acceptance Criteria | Notes | -| ------- | -------------------------- | ------------------- | ------------------------------ | ----- | -| US-001 | User Story | Phase 1 | AC-001, AC-002 | | -| FR-001 | Functional Requirement | Phase 1 | AC-001 | | -| NFR-001 | Non-Functional Requirement | Phase 1 | AC-002 | | - -## Phase 1: - -**Status**: [ ] Phase complete - -**Goal**: Describe the narrow end-to-end behaviour this phase implements as a complete user-visible, system-visible, or test-verifiable outcome. - -**Demo / Verification Outcome**: Describe exactly how someone can verify this phase is complete without inspecting implementation details. - -**Skills To Load**: - -| Skill | Why This Phase Needs It | -| -------------- | ----------------------- | -| `` | `` | - -**Likely Areas**: - -Use exact paths only when durable and important. Prefer directories or modules when files may change. - -- `src/...` -- `tests/...` - -**Constraints**: - -List durable constraints this phase MUST respect. - -- Constraint 1 -- Constraint 2 - -**Implementation Notes**: - -Provide enough context to start without rediscovering scope. Do NOT invent product decisions absent from the PRD. - -- Note 1 -- Note 2 - -**Acceptance Criteria**: - -Each acceptance criterion MUST reference at least one PRD user story, functional requirement, or non-functional requirement unless purely functional with no NFR. - -| ID | Acceptance Criterion | User Story ID(s) | Functional Requirement ID(s) | Non-Functional Requirement ID(s) | -| ------ | ---------------------------------------------------------- | ---------------- | ---------------------------- | -------------------------------- | -| AC-001 | Given , when , then . | US-001 | FR-001 | NFR-001 | - -**Testing Plan**: - -Describe public behaviours and seams that MUST be tested for this phase. - -| Test Level | Required Coverage | -| --------------------- | ----------------- | -| Unit | | -| Feature / Integration | | -| Browser / UI | | -| Regression | | -| Manual Verification | | -``` - -## Rules - -These rules are MANDATORY. - -- MUST decompose the approved PRD into thin vertical slices (tracer bullets). -- Each phase MUST cut through every integration layer needed for that behaviour. -- PREFER many thin vertical phases over few thick phases. -- ONLY identify skills relevant to each phase by their description, DO NOT load the skills now. -- ENSURE every PRD user story, functional requirement, and non-functional requirement is covered in the Requirements Coverage Matrix. -- NEVER invent product decisions, business rules, UX behaviour, or edge-case handling not present in the approved PRD. -- EVERY acceptance criterion MUST have a unique ID. diff --git a/skills/pr/SKILL.md b/skills/pr/SKILL.md index 7d66933..475567d 100644 --- a/skills/pr/SKILL.md +++ b/skills/pr/SKILL.md @@ -1,59 +1,29 @@ --- name: pr -description: Create or reuse a GitHub pull request from the current branch with safe commit and push. Use when opening, updating, or reporting a PR. +description: Publishes the current branch and creates or updates its pull request. Use when committed work is ready for review. +metadata: + invocation: user +disable-model-invocation: true --- # Pull Request -Create or reuse one GitHub pull request and report the verified result. +Publish the current branch through the repository's available setup and represent its complete work in one pull request. -## Prerequisites +## Process -ALL prerequisites MUST be satisfied BEFORE following this skill. +### 1. Inspect the repository setup -- GitHub CLI `gh` is installed and authenticated for the target repository (may need to run outside sandbox). -- The current directory is a git repository with an `origin` remote. +Inspect repository instructions, Git status, the current branch, its remote and base, available publication tooling, and any existing pull request for the branch. Use the user-supplied base or the repository default. When no usable publication path exists, report the blocker; otherwise the publication context is explicit. -## Instructions +### 2. Establish the grouped work -Follow these steps IN ORDER. Do NOT skip steps. +Invoke `$commit` when eligible changed work remains, then inspect the commit history and **whole-branch change scope** against the base. When the branch has no publishable change, report it and stop; otherwise the complete pull-request scope is explicit. -1. Resolve the base branch from optional user input, or default to the repo's main development branch. -2. Collect context first with [references/workflow.md](references/workflow.md). -3. If the current branch equals the base branch, stop and ask the user to confirm the intended base. -4. If the worktree is dirty, load and invoke the `commit` skill with no extra instructions, then refresh branch context before PR metadata. -5. Push safely: use `git push -u origin ` when no upstream exists; otherwise use `git push`. -6. Check for an existing open PR for the current head branch. -7. If an open PR exists with a different base, stop and ask whether to update it; only if confirmed, run `gh pr edit --base ` before title or body refresh. -8. If an open PR exists on the chosen base, reuse it unchanged when no commit delta exists; otherwise ask whether to refresh title and body, then use `gh pr edit` only after explicit confirmation. -9. If no open PR exists and no commit delta exists, output exactly `No PR changes to open.` -10. Generate a Conventional Commit PR title and summary body from the complete `...HEAD` history and diff. -11. Create the PR with `gh pr create --base --title "" --body "<body>"` when no reusable open PR exists. -12. Verify the final PR with `gh pr view --json url,number,title,baseRefName,headRefName,state` and return the output contract. +### 3. Write the pull request -## Rules +Write a `type[(scope)][!]: description` title that summarizes the complete grouped work. Apply **BLUF** by writing one succinct paragraph that begins directly with what the grouped work changes and why. Follow additional repository requirements only when they explicitly mandate them. -These rules are MANDATORY. +### 4. Publish and verify -- ALWAYS collect context before committing, pushing, creating, editing, or reusing a PR. -- MUST use the complete branch history and diff, not only the latest commit, for title and body. -- MUST keep the PR title a valid Conventional Commit subject suitable for squash merge history. -- NEVER force push, reset, amend older commits, change git config, or bypass hooks. -- ALWAYS stop and report the failing command plus one unblock action for GitHub CLI auth, permission, or remote access failures. - -## Completion Gate - -Do NOT leave this skill until ALL items are complete. - -- [ ] Base branch, current branch, status, history, diff, and diff stat were collected. -- [ ] Dirty worktree was handled through the `commit` skill, or no dirty work existed. -- [ ] Push completed without force, or the workflow stopped for auth, permission, or access action. -- [ ] Existing PR reuse or refresh rules were followed, or a new PR was created. -- [ ] Final PR state was verified with `gh pr view`. -- [ ] Final response matches the required contract in [references/workflow.md](references/workflow.md). - -## References - -Use these references when you need detail. - -- [references/workflow.md](references/workflow.md) - Commands, PR metadata rules, body shape, and output contract. +Use the available repository mechanism to publish the current branch without rewriting remote history and create or update its one pull request. Make it ready for review unless the user requested a draft. Verify the head, base, title, body, and review state, then return the pull-request URL. diff --git a/skills/pr/agents/openai.yaml b/skills/pr/agents/openai.yaml new file mode 100644 index 0000000..b844df6 --- /dev/null +++ b/skills/pr/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: 'Pull Request' + short_description: 'Publish a concise pull request' +policy: + allow_implicit_invocation: false diff --git a/skills/pr/references/workflow.md b/skills/pr/references/workflow.md deleted file mode 100644 index 0c8da32..0000000 --- a/skills/pr/references/workflow.md +++ /dev/null @@ -1,106 +0,0 @@ -# Pull Request Workflow Reference - -## Inputs - -- Treat any explicit user-provided branch name as `<base>`. -- If no base is provided, use the repo's main development branch, such as `main` or `origin/HEAD`. - -## Context Commands - -Collect context before any mutation: - -- `git status --short` -- `git branch --show-current` -- `git log --oneline <base>...HEAD` -- `git diff <base>...HEAD` -- `git diff --stat <base>...HEAD` - -After invoking the `commit` skill for a dirty worktree, refresh: - -- `git status --short` -- `git log --oneline <base>...HEAD` -- `git diff <base>...HEAD` -- `git diff --stat <base>...HEAD` - -## Existing PR Handling - -Check for an open PR for the current head branch: - -```sh -gh pr list --head <branch> --state open --json url,number,title,body,baseRefName,headRefName -``` - -- If the PR base differs from `<base>`, stop and ask whether to correct the PR base. -- If the user explicitly agrees, update the base before any title or body refresh: `gh pr edit --base <base>`. -- If the user declines or gives an unclear answer, stop and ask them to rerun the PR skill with the intended base branch. -- If the PR base matches `<base>` and no commit delta exists, reuse unchanged, verify, and report success output. -- If the PR base matches `<base>` and a commit delta exists, show the URL and ask whether to refresh title and summary. -- If the user explicitly agrees, update only title and body with `gh pr edit --title "<title>" --body "<body>"`. -- If the user declines or gives an unclear answer, reuse unchanged, verify, and report success output. - -## Push Safety - -- If the branch has no upstream, run `git push -u origin <branch>`. -- If the branch has an upstream, run `git push`. -- Never force push. -- If push fails due to auth, permissions, or remote access, stop and report the failing command plus one concrete unblock action. - -## PR Metadata - -Infer title and summary from the full `<base>...HEAD` commit history, diff, and diff stat. - -Allowed Conventional Commit title types: - -- `build`: production dependencies or build-system changes -- `chore`: maintenance, admin, or dev-only dependency work -- `ci`: CI or automation pipeline changes -- `docs`: documentation-only changes -- `feat`: a new feature or functionality -- `fix`: a bug fix for incorrect behaviour -- `perf`: a performance improvement -- `refactor`: code changes without behaviour changes -- `revert`: reverts an earlier change -- `style`: formatting or style-only clean-up -- `test`: adds or updates tests - -Make the title a valid Conventional Commit subject suitable for squash merge history. - -Use this exact PR body shape: - -```md -## Summary - -- <bullet derived from the full PR scope> -``` - -If no open PR exists, create one with: - -```sh -gh pr create --base <base> --title "<title>" --body "<body>" -``` - -Verify the final PR with: - -```sh -gh pr view --json url,number,title,baseRefName,headRefName,state -``` - -## No Changes Output - -If no open PR exists and no commit delta exists against the base branch, output exactly: - -```md -No PR changes to open. -``` - -## Success Output - -When PR creation or reuse succeeds, output exactly: - -```md -PR URL: <url> -Title: <final PR title> -Base branch: <base> -Head branch: <head> -State: <state> -``` diff --git a/skills/propulsion/SKILL.md b/skills/propulsion/SKILL.md deleted file mode 100644 index da1e9e7..0000000 --- a/skills/propulsion/SKILL.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -name: propulsion -description: Execute structured AI software development from planning through execution. Use when implementing or updating code, debugging issues, or starting software work. ---- - -# Propulsion - -Route software-work requests into the right Propulsion entry stage before any other action. - -<SUBAGENT_STOP> -If you were dispatched as a subagent to execute a specific task, SKIP THIS SKILL. -</SUBAGENT_STOP> - -<EXTREMELY_IMPORTANT> -ONCE YOU ARE FOLLOWING PROPULSION WORKFLOW, DO NOT LEAVE IT UNTIL COMPLETION. DO NOT SKIP STEPS. FOLLOW THE RULES OF EACH SKILL. -</EXTREMELY_IMPORTANT> - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Determine whether the request is software work. -2. If it is not software work, ignore Propulsion and respond normally. -3. If it is a concrete failure, emit `Propulsion workflow enabled, routing to debug...`, then load and follow `debug` skill. -4. If it is a greenfield project, new product idea, project discovery, competitor research, positioning, or full system blueprint request, emit `Propulsion workflow enabled, routing to discover-project...`, then load and follow `discover-project` skill. -5. If it is mature feature or product-scope work, emit `Propulsion workflow enabled, routing to brainstorm...`, then load and follow `brainstorm` skill. -6. The loaded Propulsion skill now owns the workflow stage. - -## Rules - -These rules are MANDATORY. - -- ALWAYS follow instructions in this order: - 1. User instructions are the highest priority (Direct requests or AGENTS.md, CLAUDE.md). - 2. Propulsion skills override default system behaviour. - 3. Default system behaviour is the lowest priority. -- NEVER route non-software-work request to Propulsion. -- ONLY route concrete failures to `debug` (bug reports, regressions, failing tests, failing builds, runtime errors, crashes). -- MUST route greenfield products, project discovery, competitor research, positioning, or full system blueprint work to `discover-project`. -- MUST route mature feature and product-scope work to `brainstorm` (new features in an existing project, unclear feature scope, UX/product shaping, requirements discovery, behaviour changes, refactors, optimisations). -- ALWAYS fall back to `brainstorm` if the request is ambiguous. -- DO NOT leave a Propulsion skill until ALL completion gate items are complete. -- NEVER reload skills (Propulsion or non-Propulsion) that are already active or present in context; continue following the loaded copy instead. -- NEVER rationalise skipping Propulsion with thoughts like: - - "I need more context first" - - "I'll inspect the repo first" - - "This is too small for Propulsion" - -## Completion Gate - -Do NOT leave this skill until ALL items are complete. - -- [ ] Determined whether the request is software work. -- [ ] Kept non-software-work outside Propulsion. -- [ ] Routed concrete failures to `debug`. -- [ ] Routed greenfield discovery work to `discover-project`. -- [ ] Routed mature feature and product-scope work to `brainstorm`. -- [ ] Emitted the route-specific required response before any other user-visible text. - -## References - -Use these references when you need detail. diff --git a/skills/research/SKILL.md b/skills/research/SKILL.md new file mode 100644 index 0000000..c6c4cfc --- /dev/null +++ b/skills/research/SKILL.md @@ -0,0 +1,37 @@ +--- +name: research +description: Researches questions against high-trust primary sources and persists cited reports. Use when a durable evidence-backed answer is needed. +metadata: + invocation: model +disable-model-invocation: false +--- + +# Research + +**Rapid evidence assessment** turns a scoped question into an auditable report grounded in high-trust primary sources. + +## Process + +### 1. Define the research contract + +Define the research question, intended use, scope, exclusions, currency needs, and source hierarchy. Inspect task-relevant repository context and `docs/research/` for related reports before searching. Resolve ambiguity that could materially change the investigation. The research contract and applicable prior evidence are explicit. + +### 2. Assign the investigation + +Give a fresh agent the complete research contract, relevant repository context, primary-source standard, and output contract. One fresh agent owns source discovery, appraisal, synthesis, and report writing; the caller verifies the finished report. + +### 3. Discover and appraise primary evidence + +Discover the strongest applicable primary evidence, including official documentation, source code, standards, original publications, first-party APIs, and first-party data. Use secondary sources only as discovery leads, then apply **backward citation searching** to trace material claims to their originals. Critically appraise authority and access, validity, currency, applicability, completeness, and bias. Primary-source status sets the hierarchy; appraisal determines the trust warranted. The evidence set is relevant, current enough for the question, and traceable. + +### 4. Synthesize the findings + +Compare independent evidence through **triangulation**, treating sources that repeat the same upstream claim as one evidence route. Test emerging conclusions through **falsification** by seeking contrary evidence and plausible alternatives. Distinguish direct evidence, inference, conflict, and unknowns; narrow or qualify conclusions when the evidence cannot support a stronger answer. Stop discovery when each material claim is supported or explicitly unresolved and further primary-source work is unlikely to change the answer. Every material finding is proportionate to the evidence. + +### 5. Write the research report + +Persist the result at `docs/research/YYYYMMDD-{research-title}.md` using [the research report template](assets/research-report-template.md). Use a concise lowercase hyphenated title and claim-level links to primary evidence. Replace every placeholder, retain only applicable lifecycle fields, and complete every applicable section. Record the research date, material search locations or approaches, appraisal basis, and synthesis method for **auditability** without retaining the raw search trail. When related research already exists, apply [the research report lifecycle](references/REPORT-LIFECYCLE.md). The report is concise, auditable, and proportionate to its evidence. + +### 6. Verify and hand off + +Verify that each material claim is supported by its cited primary source, evidence routes are genuinely independent, every link and relative report path resolves, conflicts and uncertainty are visible, and the recorded method makes the investigation auditable. Return the report path, concise concrete findings, and unresolved limitations to the caller. The caller receives a validated durable result without the raw search context. diff --git a/skills/research/agents/openai.yaml b/skills/research/agents/openai.yaml new file mode 100644 index 0000000..0f9f9ed --- /dev/null +++ b/skills/research/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: 'Research' + short_description: 'Research primary sources into cited reports' +policy: + allow_implicit_invocation: true diff --git a/skills/research/assets/research-report-template.md b/skills/research/assets/research-report-template.md new file mode 100644 index 0000000..8e382bd --- /dev/null +++ b/skills/research/assets/research-report-template.md @@ -0,0 +1,45 @@ +--- +title: '{research title}' +createdAt: YYYY-MM-DD +updatedAt: YYYY-MM-DD +status: current +# Retain each applicable relationship and remove this guidance. +# supersedes: './YYYYMMDD-research-title.md' +# supersededBy: './YYYYMMDD-research-title.md' +--- + +# {Research title} + +## Research question and scope + +**Question:** {The question this report answers} + +**Intended use:** {The decision or caller this evidence informs} + +**Scope:** {Included and excluded concerns, applicable versions or environments, and evidence currency} + +## Conclusion + +{The concise answer, qualified to match the strength of the evidence} + +## Findings + +### {Finding} + +{Material claims with direct links to supporting primary sources. Identify inferences explicitly.} + +## Conflicts + +{Conflicting evidence and its effect on the conclusion, or "None found."} + +## Limitations + +{Unresolved uncertainty, evidence gaps, and freshness risks, or "None known."} + +## Method + +{The research date, material search locations, terms or approaches, appraisal basis, triangulation and falsification method, and auditability constraints without the raw search trail.} + +## Primary sources + +- [{Source title}]({URL or repository-relative path}) — {publisher or owner, version or publication date, accessed YYYY-MM-DD, and relevance} diff --git a/skills/research/references/REPORT-LIFECYCLE.md b/skills/research/references/REPORT-LIFECYCLE.md new file mode 100644 index 0000000..c01349d --- /dev/null +++ b/skills/research/references/REPORT-LIFECYCLE.md @@ -0,0 +1,15 @@ +# Research Report Lifecycle + +Use this reference only when `docs/research/` already contains research related to the current question. + +## Correct the current report + +Update a report in place only to repair wording, formatting, or a link to the same evidence without changing a material claim. Retain `createdAt` and change `updatedAt`. The corrected report remains the current snapshot. + +## Create a substantive refresh + +New evidence, changed scope, or a materially changed finding creates a new dated snapshot with a relative `supersedes` link. Mark the previous snapshot `superseded`, add its relative `supersededBy` link, and preserve its historical findings. The report history distinguishes correction from substantive refresh. + +## Resolve a dated-path collision + +When a distinct report already occupies the dated path, append `-2` to the filename slug and increment it until an unused path is available. Keep the frontmatter title and H1 unchanged. diff --git a/skills/review-architecture/SKILL.md b/skills/review-architecture/SKILL.md new file mode 100644 index 0000000..910f9bb --- /dev/null +++ b/skills/review-architecture/SKILL.md @@ -0,0 +1,33 @@ +--- +name: review-architecture +description: Reviews a codebase or scope for high-value modular redesigns, persists a Markdown review, and opens a disposable visual HTML shortlist. Use when modular architecture needs assessment. +metadata: + invocation: user +disable-model-invocation: true +--- + +# Review Architecture + +The **visual information-seeking mantra** turns an evidence-backed modular review into an impact-grouped overview for people and a durable implementation reference for agents. + +## Process + +### 1. Establish the review + +Use the user's explicit scope or the whole repository with the slug `full-codebase`. Inspect applicable project context, architecture decisions, source, tests, contracts, schemas, dependencies, runtime configuration, and documentation. Exclude generated output, vendored dependencies, caches, and binaries unless they participate in a material boundary. Invoke `$modular-design` as the architecture authority. The scope, exclusions, project constraints, and modular baseline are explicit. + +### 2. Select the redesigns + +Read [Architecture Analysis](references/architecture-analysis.md). Recover confirmed and inferred quality drivers, map the current capabilities and contracts, and trace material architecture pressure to precise repository locations. Apply **design it twice** to every serious candidate and load `$modular-design` techniques only when their conditions fit. Invoke `$research` only when a recommendation materially depends on an external claim requiring durable verification. Retain every redesign that clears the evidence threshold, assign stable two-digit IDs in ranked order, and group the set by explained `high`, `medium`, or `low` impact. Zero recommendations is valid. + +### 3. Persist the review + +Write the canonical report to `docs/architecture/YYYYMMDD-{scope}-architecture-review.md`; preserve an existing path with `-2`, `-3`, and so on unless replacement is explicit. For each recommendation, make the issue, fix, benefit, affected architecture, current and target design, evidence, rejected alternative, costs, risks, dependencies, migration route, smallest useful slice, containment, and fitness checks independently understandable. Record coverage without a qualifying redesign and material limitations. Stop before implementation or a file-by-file plan. + +### 4. Present the visual shortlist + +Read [Report Design](references/report-design.md), then create a disposable `architecture-review-{timestamp}.html` in the operating system's temporary directory and open it for the user. Give it the same recommendation IDs, ordering, conclusions, and technical substance as the Markdown report. Show the complete set as `High impact`, `Medium impact`, and `Low impact`; make each collapsed card understandable through an aligned before-and-after visual and plain-language `Issue`, `Fix`, and `Benefit`, with technical depth available on demand. Add filters only when they materially improve navigation. + +### 5. Verify and hand off + +Verify the Markdown paths, links, structure, and implementation sufficiency, then compare both artifacts for matching IDs and claims. Inspect the HTML at desktop and narrow widths, exercising disclosure, applicable filters, pointer and keyboard operation, focus, overflow, external dependencies, and print output. Correct material defects; when browser inspection is unavailable, mark visual acceptance incomplete. Return both report paths, scope and exclusions, recommendation IDs and count, invoked research, validation performed, and unresolved limitations. Preserve the reviewed implementation unchanged. diff --git a/skills/review-architecture/agents/openai.yaml b/skills/review-architecture/agents/openai.yaml new file mode 100644 index 0000000..9ea18e8 --- /dev/null +++ b/skills/review-architecture/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: 'Review Architecture' + short_description: 'Review architecture and explain redesigns' +policy: + allow_implicit_invocation: false diff --git a/skills/review-architecture/references/architecture-analysis.md b/skills/review-architecture/references/architecture-analysis.md new file mode 100644 index 0000000..fb21338 --- /dev/null +++ b/skills/review-architecture/references/architecture-analysis.md @@ -0,0 +1,46 @@ +# Architecture Analysis + +Load this reference while selecting and ranking redesigns. `$modular-design` owns architecture vocabulary, information hiding, deep modules, realization, and conditional techniques; this reference owns review-specific evidence and judgment. + +## Quality Priority + +Apply the first evidenced priority in this order: + +1. Safety, correctness, security, and data integrity constraints. +2. Explicit project quality drivers. +3. Qualities defined by `$modular-design`. +4. Testability and migration safety. +5. Operability, reliability, performance, scalability, and portability when material to the system. + +Recover drivers from product and domain context, architecture decisions, public promises, tests, operational configuration, incidents, recurring changes, and repository history when available. Express a material driver as a scenario with a stimulus, affected capability, expected response, and observable measure. Label inference and confidence; ask the user only when an unavailable priority would materially change qualification or rank. + +## Evidence and Comparison + +Map capabilities rather than assuming directories, classes, packages, services, or deployment units are architecture modules. For each material pressure, trace the owned knowledge, public contract, consumers, dependencies, runtime boundaries, verification seams, and repeated change propagation to repository-relative paths and precise locations. Separate observations, supported conclusions, and uncertainty. Metrics may locate candidates but cannot prove a redesign. + +For every serious candidate compare at least two materially different capability boundaries. State each contract, hidden knowledge, dependency direction, quality effects, framework and runtime fit, migration seam, first useful slice, containment, costs, and risks. A naming, file-placement, or interface-syntax variation is not a second design. Prefer the alternative that hides more consequential knowledge behind the simpler stable contract while satisfying the higher-priority evidence. + +## Qualification and Rank + +A recommendation qualifies only when it: + +- materially improves a priority quality; +- traces its problem and expected improvement to repository evidence; +- hides or realigns architectural knowledge rather than rearranging code locally; +- has a credible incremental route with visible dependencies and risks; and +- is supported strongly enough to recommend with material uncertainty exposed. + +Retain every qualifying redesign and none below the threshold. Record non-qualifying areas only as review coverage. Assign labels with a one-sentence evidence rationale: + +- **Impact:** `high` changes a constraint or explicit driver, or removes repeated high-reach pressure; `medium` materially improves a bounded capability; `low` produces a worthwhile but contained architectural gain. +- **Effort:** `high` crosses several boundaries or requires staged data, contract, or deployment work; `medium` needs coordinated changes; `low` is contained behind an existing seam. +- **Risk:** `high` threatens behaviour, data, security, public contracts, or runtime continuity; `medium` needs managed integration; `low` is isolated and readily reversible. +- **Confidence:** `high` follows direct repeated evidence and executable verification; `medium` combines credible evidence with limited inference; `low` depends materially on missing context. + +Do not calculate a composite score. Order impact groups `high`, `medium`, then `low`; rank within a group by quality priority, evidence reach, confidence, and migration feasibility. Assign `01`, `02`, and onward after ranking, and preserve those IDs across both reports regardless of filtering. + +## Migration and Fitness + +Define stages that keep the system operable and verifiable: prerequisites, smallest independently useful slice, old/new coexistence, data or contract transition, containment or rollback, and superseded-path removal. Replace a high-risk boundary incrementally; replace a safe local boundary atomically. Stop before a file-by-file implementation plan. + +Pair each claimed benefit with observable fitness evidence. State the signal, expected result, and where it should run, using existing contract tests, dependency checks, change-impact checks, adapter conformance, runtime thresholds, telemetry, or deployment signals when they prove the quality. Propose new machinery only when existing verification cannot. diff --git a/skills/review-architecture/references/report-design.md b/skills/review-architecture/references/report-design.md new file mode 100644 index 0000000..dc07cd7 --- /dev/null +++ b/skills/review-architecture/references/report-design.md @@ -0,0 +1,52 @@ +# Architecture Review Report Design + +Load this reference after the recommendation set is complete. The Markdown report is the durable implementation record; the disposable HTML is its visual decision view. They adapt presentation to their readers without changing recommendation IDs, order, claims, or technical substance. + +## Markdown Record + +Use this reading order: + +1. Title, date, scope, exclusions, one-sentence outcome, and recommendation index. +2. `High impact`, `Medium impact`, and `Low impact` recommendation groups, omitting empty groups. +3. Review coverage and evidence limitations. +4. Method, invoked research reports, and validation status. + +Name each recommendation `{ID}. {action-led title}`. Lead with three plain-language fields: + +- **Issue:** the present architecture friction and consequence. +- **Fix:** the ownership, contract, or dependency change. +- **Benefit:** the concrete quality improvement. + +Then preserve the affected modules and contracts, current and target design, repository evidence with precise locations, before-and-after explanation, rejected alternative, framework and runtime fit, costs, risks, uncertainty, dependencies, migration and coexistence stages, containment or rollback, smallest useful slice, and fitness checks. A downstream agent must be able to receive the Markdown path plus an ID and understand the bounded change without reopening the review. + +## HTML Shortlist + +Apply overview first and details on demand. The initial viewport identifies the review and exposes the impact-grouped recommendation set without introductory prose. Each card shows its ID, title, impact, before-and-after visual, `Issue`, `Fix`, and `Benefit`. Put evidence, alternatives, effort, risk, confidence, migration, and fitness checks in native disclosure. Show a direct zero-result state when no redesign qualifies. + +Use filters only when the set is large enough that impact groups alone do not support comparison. Filtering changes visibility, never IDs, ranking, or report content; show the visible count and a clear reset. + +## Visual Language + +Apply **visual juxtaposition**: give every recommendation an aligned current/target pair that answers one question about changed ownership, hidden knowledge, dependency direction, runtime flow, or migration. Keep corresponding concepts in corresponding positions with consistent names, shapes, direction, and scale. At narrow widths, stack the pair while preserving that visual grammar. Simplify the visual rather than shrinking an unreadable whole-system map. + +Choose the smallest useful form: a boundary or dependency graph, quality-scenario flow, ownership sketch, cross-section, or staged migration. Mermaid, inline SVG, and semantic HTML/CSS are all valid. Mix techniques when the evidence benefits; avoid ornamental diagrams. Give every visual an accessible name and adjacent textual explanation. + +Use strong hierarchy, generous spacing, readable line lengths, restrained colour, and consistent cards. Paths and contracts may use monospace. Colour reinforces words and shapes rather than carrying meaning. Prefer semantic controls, visible focus, and native disclosure; interactions remain keyboard-operable. Provide responsive and print styles that preserve all content and expand technical details for printing. + +Scripts, styles, fonts, and diagram libraries may load from verified CDNs when useful. Keep the generated artifact in one HTML file apart from those dependencies, escape repository-derived text for its destination context, and verify every selected dependency at generation time. + +## Plain Language + +Use **plain language** for `Issue`, `Fix`, and `Benefit`: state the point first, use active verbs and familiar concrete words, and keep one idea in each field. Preserve established domain, project, framework, and architecture terms when they are more precise. Move substantiation into disclosure instead of weakening or repeating the summary. A collapsed card succeeds when it is concise and distinguishable from every other recommendation. + +## Visual QA + +Inspect the actual temporary file with network access: + +1. Confirm external dependencies and every before-and-after visual render. +2. Compare recommendation IDs, order, labels, and claims with the Markdown record. +3. Exercise disclosure and applicable filters by pointer and keyboard; verify focus, state, count, and reset. +4. Inspect desktop, narrow, zero-result, and print states for hierarchy, wrapping, overflow, clipping, and content loss. +5. Confirm the report remains understandable without colour and that evidence paths remain legible. + +Correct material defects and rerun affected checks. When browser inspection is unavailable, complete structural and source checks, then mark visual acceptance incomplete in both artifacts and the handoff. diff --git a/skills/review/SKILL.md b/skills/review/SKILL.md deleted file mode 100644 index 2255386..0000000 --- a/skills/review/SKILL.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -name: review -description: Review PRs and ref ranges with senior-level findings, validation, and exact reports. Use when reviewing PRs or base...head changes. ---- - -# Review - -Review a PR or ref range and return a validated senior-engineer report. - -## Prerequisites - -ALL prerequisites MUST be satisfied BEFORE following this skill. - -- If review scope is unclear, STOP. Ask for a PR number, PR URL, or `base...head` ref range. -- GitHub CLI `gh` is installed and authenticated when reviewing a PR number or PR URL. - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Resolve review scope and allowed context with [references/mode-selection.md](references/mode-selection.md); stop and ask for a PR number, PR URL, or `base...head` when scope is unclear. -2. Dispatch fresh reviewer subagents in parallel with [references/reviewer-prompt.md](references/reviewer-prompt.md). Cover the axes in [references/review-axes.md](references/review-axes.md). -3. Dispatch fresh validator subagents with [references/validator-prompt.md](references/validator-prompt.md). Discard anything unconfirmed. -4. Produce the final report exactly as defined in [references/report-format.md](references/report-format.md). Use only `approve`, `approve-with-comments`, `request-changes`, or `needs-clarification`. - -## Rules - -These rules are MANDATORY. - -- MUST accept only `#<pr-number>`, PR URLs, or `base...head`. -- MUST require installed and authenticated `gh` only for PR review scopes. -- ALWAYS validate both refs before reviewing `base...head`; do not guess missing refs. -- ALWAYS use merge-base diff semantics for `base...head`. -- ALWAYS use a severity-first model: `critical`, `high`, `medium`, `low`, `nitpick`, `question`. -- ALWAYS report only validated findings or validated missing-context questions with concrete evidence and exact `file:line` refs when code is involved. -- DO keep findings issue-focused. DO NOT add a positive-notes section. -- DO NOT keep style nits, speculative risks, weak evidence, pre-existing issues, or linter-catch comments. -- DO treat blocking findings as validated `critical` and `high` findings that would materially harm production, security, UX, or maintenance if shipped. - -## Completion Gate - -Do NOT leave this skill until ALL items are complete. - -- [ ] Scope was resolved as a PR number, PR URL, or `base...head`. -- [ ] PR scopes used GitHub PR metadata, or range scopes validated both refs and reviewed the merge-base diff. -- [ ] Reviewer and validator passes completed before the final report. -- [ ] Final response matches [references/report-format.md](references/report-format.md). - -## References - -Use these references when you need detail. - -- [references/mode-selection.md](references/mode-selection.md) - Scope parsing, validation, and allowed context. -- [references/review-axes.md](references/review-axes.md) - Parallel reviewer-pass contracts. -- [references/reviewer-prompt.md](references/reviewer-prompt.md) - Prompt template for one reviewer pass. -- [references/issue-schema.md](references/issue-schema.md) - Candidate finding and question schema. -- [references/validator-prompt.md](references/validator-prompt.md) - Prompt template for one validator pass. -- [references/validation-rubric.md](references/validation-rubric.md) - Disprove-first validation rules. -- [references/report-format.md](references/report-format.md) - Exact final report shape and decision rules. diff --git a/skills/review/references/issue-schema.md b/skills/review/references/issue-schema.md deleted file mode 100644 index 4b8ea45..0000000 --- a/skills/review/references/issue-schema.md +++ /dev/null @@ -1,54 +0,0 @@ -# Issue Schema - -Use when normalising candidate findings and questions before validation. - -```json -{ - "kind": "finding", - "file": "src/path/file.ts", - "line": 42, - "severity": "high", - "category": "duplication", - "summary": "Short issue title", - "evidence": "Quoted diff, exact rule text, quoted precedent snippet, concrete principle-backed code evidence, or explicit intent evidence", - "evidence_type": "intent-context", - "impact": "Why this matters in this codebase", - "confidence": 88, - "blocking": true, - "rule_source": "AGENTS.md:18", - "precedent_refs": ["src/example.ts:10", "src/example.ts:44"], - "intent_refs": ["PR description", "docs/propulsion/example-plan.md:12-18"], - "principle_basis": "DRY|single-source-of-truth|separation-of-concerns|ownership-boundary|test-protection|cohesion|encapsulation|complexity-management|abstraction-leakage|SOLID|YAGNI", - "open_question": "What missing context prevents a reliable decision?", - "validator_verdict": "pending|confirmed|rejected" -} -``` - -## Required rules - -- `kind`, `severity`, `category`, `summary`, `evidence`, `evidence_type`, `impact`, `confidence`, and `validator_verdict` are mandatory. -- `kind` MUST be `finding` or `question`. -- `file` and `line` are required for code-based findings; omit them only for pure intent or rule questions. -- `severity` MUST be one of `critical`, `high`, `medium`, `low`, `nitpick`, `question`. -- `category` MUST be one of `rule-violation`, `skill-contract-violation`, `bug`, `compile-break`, `logic-error`, `security`, `performance`, `architecture`, `maintainability`, `duplication`, `test-gap`, `requirement-drift`, or `consistency-drift`. -- `evidence` MUST be concrete and tied to changed code, scoped rule text, or cited precedent. -- `evidence_type` MUST be `diff`, `rule-text`, `precedent`, `principle`, or `intent-context`. -- `confidence` MUST be integer `0-100`. -- `blocking` is required for findings; set `true` only for material production, security, UX, or maintenance risk. -- `rule_source` is required for `rule-violation` and `skill-contract-violation`. -- `precedent_refs` is required for `consistency-drift` and any precedent-backed finding. -- `intent_refs` is required for `requirement-drift` and any intent-backed finding. -- `principle_basis` is required for any principle-backed finding. -- `open_question` is required for `kind: question` and should explain the exact missing context. -- DO use `principle` evidence only when the finding names the violated code-health principle and the impact is specific to the changed code. - -## Deduplication key - -Use `(kind, file, line, severity, category, normalised summary)`. - -Only one final finding per dedupe key. - -## Rules - -- ALWAYS normalise every candidate before validation. -- DO omit fields only when these rules explicitly allow omission. diff --git a/skills/review/references/mode-selection.md b/skills/review/references/mode-selection.md deleted file mode 100644 index b7c5db9..0000000 --- a/skills/review/references/mode-selection.md +++ /dev/null @@ -1,40 +0,0 @@ -# Mode Selection - -Use when resolving review scope. - -## Accepted Forms - -- `#<pr-number>` -- PR URL -- `base...head` - -No other scope forms are supported. - -## PR Scope - -- Confirm explicit PR numbers match `#<number>`. -- Accept GitHub PR URLs as explicit PR scope. -- Require `gh` installed, authenticated, and able to access the repository only for PR scopes. -- Resolve PR scope with `gh pr view <number-or-url> --json number,title,body,baseRefName,headRefName,headRefOid,baseRefOid,files,url`. -- Use PR metadata for base/head refs, changed files, title, body, and linked artefact discovery. -- If lookup fails, ask one corrective follow-up for a valid PR number or URL; do not guess another PR. - -## Range Scope - -- Confirm range input contains exactly one `...` separator with non-empty `base` and `head` refs. -- Validate both refs with `git rev-parse --verify <ref>^{commit}` before reviewing. -- If either ref is missing/invalid, ask one corrective follow-up for a valid `base...head` range; do not substitute another ref. -- Review the merge-base diff for the exact range, equivalent to `git diff <base>...<head>`. -- Use changed files from the exact merge-base diff. -- Use explicit user-stated review goals when intent context is needed. - -## Validation Checks - -- If scope is missing or unclear, ask the user for a PR number, PR URL, or `base...head` before review begins. -- If the resolved scope has no reviewable file changes, still return the standard review report and state that the scope was empty. - -## Rules - -- DO accept only the documented scope forms. -- DO NOT infer scope from the current checkout. -- DO NOT require GitHub CLI for `base...head` range review. diff --git a/skills/review/references/report-format.md b/skills/review/references/report-format.md deleted file mode 100644 index 62ad012..0000000 --- a/skills/review/references/report-format.md +++ /dev/null @@ -1,97 +0,0 @@ -# Report Format - -Use this exact final report shape for PR and `base...head` reviews, including empty scopes. - -```markdown -# Review Report - -**Scope**: <PR #123 | PR URL | base...head> - -**Intent Summary**: <1-3 sentences describing the change goal from PR context or explicit user intent> - -**Final Decision**: <approve | approve-with-comments | request-changes | needs-clarification> - -**Critical Findings** - -- None - -<or> - -- <short title> - - Location: <path:line | scope area> - - Why it matters: <concrete impact on correctness, security, UX, performance, or maintenance> - - Evidence: <quoted diff, rule text, precedent, or intent evidence> - - Recommended action: <smallest safe improvement> - -**High Findings** - -- None - -<or same finding item shape as Critical> - -**Medium Findings** - -- None - -<or same finding item shape as Critical> - -**Low Findings** - -- None - -<or same finding item shape as Critical> - -**Nitpicks** - -- None - -<or> - -- <short title> - - Location: <path:line | scope area> - - Why it matters: <why this polish is still worth mentioning> - - Evidence: <quoted diff or precedent> - - Recommended action: <smallest safe improvement> - -**Questions** - -- None - -<or> - -- <short title> - - Missing context: <exact artefact, assumption, or behaviour still needed> - - Why it matters: <how this blocks a reliable decision or severity> - - Evidence checked: <what was already inspected> - -**Residual Risk** - -- None - -<or> - -- <short risk> - - Why it remains: <what could not be fully verified after allowed review steps> -``` - -## Decision rules - -- `approve`: no validated findings and no unanswered blocking questions. -- `approve-with-comments`: only non-blocking validated findings remain. -- `request-changes`: at least one validated blocking finding remains. -- `needs-clarification`: missing context prevents a reliable recommendation. - -## Section rules - -- Use the exact section names shown above. -- Keep findings grouped by severity in descending order. -- Each finding must include short title, `Location`, `Why it matters`, `Evidence`, and `Recommended action`. -- If the resolved review scope is empty, set `**Final Decision**` to `approve`, explain the empty scope in `**Intent Summary**`, and keep all finding sections as `- None`. -- Put unresolved missing-context items only in `**Questions**`, not in severity groups. -- `**Residual Risk**` covers what could not be fully verified after the allowed review steps, even if no question remains. -- Do not add a positive-notes or praise section. - -## Rules - -- ALWAYS use this exact section order. -- DO NOT add extra top-level sections. diff --git a/skills/review/references/review-axes.md b/skills/review/references/review-axes.md deleted file mode 100644 index af3136f..0000000 --- a/skills/review/references/review-axes.md +++ /dev/null @@ -1,47 +0,0 @@ -# Review Axes - -Use when dispatching focused reviewer passes. - -## Focused reviewer passes - -- Correctness: changed behaviour vs stated intent, edge cases, failure paths, state transitions, data flow, and dependency changes. -- Security / trust boundaries: auth, authorization, validation, injection surfaces, secrets, config, logging, file handling, and integration boundaries. -- Maintainability / architecture: wrong-layer ownership, second sources of truth, duplicated business logic, concrete refactoring opportunities, abstraction leakage, coupling, unnecessary complexity, and unnecessary indirection. Apply named principles only when impact is concrete in changed code. -- Tests / verification: changed behaviour protected by tests or other verification, including realistic failure modes and regressions. -- Intent / rule alignment: diff vs PR intent, linked planning artefacts, scoped `AGENTS.md` / `CLAUDE.md`, touched command/skill contracts, and dominant local precedent when consistency matters. - -## Alignment rules - -- Review like a senior PR reviewer, not a lint pass. -- Improve code health; do not seek perfection. -- Prefer concrete, merge-relevant issues the author would fix. -- Read code in context, not only diff hunks. -- Treat tests and trust-boundary changes as first-class review scope. -- Use exact evidence, quoted rules, and nearby precedent before broad principles. - -## Named principles allowed for principle-backed findings - -- `DRY` -- `single-source-of-truth` -- `separation-of-concerns` -- `ownership-boundary` -- `test-protection` -- `cohesion` -- `encapsulation` -- `complexity-management` -- `abstraction-leakage` -- `SOLID` -- `YAGNI` - -## Reject candidates when - -- The complaint is aesthetic or stylistic. -- The claim depends on hidden requirements. -- The issue is too small for a final report finding. -- Multiple local patterns exist and no dominant precedent is clear. -- The suggestion is speculative future-proofing instead of a concrete fix for this diff. - -## Rules - -- EACH pass returns only candidates, NEVER final report text. -- DO stay inside the allowed review scope and gathered context. diff --git a/skills/review/references/reviewer-prompt.md b/skills/review/references/reviewer-prompt.md deleted file mode 100644 index 23b4f76..0000000 --- a/skills/review/references/reviewer-prompt.md +++ /dev/null @@ -1,59 +0,0 @@ -# Reviewer Prompt Template - -Use this reference when dispatching a fresh reviewer subagent for one review axis. - -````markdown -You review exactly one axis in a PR-style code review. - -## Inputs - -- **Review axis**: `<correctness | security/trust boundaries | maintainability/architecture | tests/verification | intent/rule alignment>` -- **Scope summary**: `<resolved review scope>` -- **Intent context**: `<PR title/description and linked artefacts, or explicit user-stated review goal>` -- **Changed files**: `<list of changed files in scope>` -- **Allowed context**: `<scoped rules/contracts, allowed adjacent files, precedent refs, and linked artefacts>` - -## Review Focus - -| Axis | Look for | Do not report | -| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | -| Correctness | Broken logic, wrong branches, unsafe state transitions, dependency regressions, deterministic runtime failures | Style nits, unevidenced hypothetical failures | -| Security / trust boundaries | Auth/authz mistakes, missing validation, injection surfaces, secrets/config leaks, unsafe integrations | Generic security advice not triggered by the diff | -| Maintainability / architecture | Wrong ownership, second sources of truth, duplicated business logic, concrete refactoring opportunities, abstraction leakage, harmful complexity, unnecessary indirection | Broad refactor wishes, future-proofing speculation | -| Tests / verification | Missing protection for changed behaviour, realistic regressions, weak failure-path coverage | Complaints not tied to changed behaviour | -| Intent / rule alignment | Drift from PR intent, linked artefacts, scoped rules, or dominant precedent | Hidden requirements or unstated preferences | - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Review only the assigned axis. -2. Inspect changed files and only allowed context. -3. Compare the diff against the assigned axis; keep only merge-relevant candidates. -4. Normalise every candidate using `references/issue-schema.md`. -5. Return candidates only. Do not write final review prose. - -## Output - -Use this exact format for your output. - -```json -[ - <Replace with the exact JSON object shape from `references/issue-schema.md`>, - <Repeat for each candidate found in this review pass> -] -``` - -Return `[]` when no candidates survive the reviewer pass. - -## Rules - -These rules are MANDATORY. - -- ALWAYS stay inside the assigned axis. -- ALWAYS stay inside the allowed review scope and allowed context. -- DO return only normalised candidates. -- MUST replace the output placeholders with the exact JSON object shape from `references/issue-schema.md` before dispatching the reviewer. -- DO NOT write final report sections, verdicts, or fix patches. -- DO NOT keep stylistic, speculative, or low-value complaints. -```` diff --git a/skills/review/references/validation-rubric.md b/skills/review/references/validation-rubric.md deleted file mode 100644 index 51c321c..0000000 --- a/skills/review/references/validation-rubric.md +++ /dev/null @@ -1,62 +0,0 @@ -# Validation Rubric - -Use when validating candidate findings and questions before final report generation. - -## Disprove-first flow - -1. Assume the finding is wrong. -2. Search diff, changed files, scoped rules/contracts, and gathered adjacent context for counter-evidence. -3. Reject if evidence is incomplete, ambiguous, pre-existing, or out of scope. -4. Confirm only if objective evidence supports the claim and the issue is one the PR author would fix. - -## Candidate types - -- Validate `finding` candidates and `question` candidates separately. -- A `question` is valid only when missing context materially blocks final decision or severity and cites the exact missing artefact, assumption, or unresolved behaviour. - -## Severity confirmation requirements - -- `critical` - - Deterministic breakage, material security exposure, or an explicit rule/contract violation that should block merge. - - Confidence `>= 90`. -- `high` - - Strongly evidenced bug, trust-boundary failure, requirement drift, test gap, or architecture regression with material merge risk. - - Confidence `>= 85`. -- `medium` - - Meaningful maintainability, performance, or verification issue that should likely be fixed before or immediately after merge. - - Confidence `>= 80`. -- `low` - - Real but lower-risk maintainability or consistency drag with a clear alignment path. - - Confidence `>= 75`. -- `nitpick` - - Minor non-blocking cleanup worth mentioning only when strongly evidenced and clearly useful. - - Confidence `>= 70`. -- `question` - - Missing context that prevents a reliable decision. Do not use when the reviewer can resolve the uncertainty from allowed context. - - Confidence `>= 80` that the context gap is real. - -## Evidence requirements - -- Evidence must come from changed code, scoped rules/contracts, allowed adjacent context, nearby precedent, or linked intent artefacts. -- Rule/contract violations quote exact text and source path; consistency claims cite dominant local precedent. -- Principle-backed claims name the principle and concrete maintenance, ownership, testing, or correctness cost. -- Test-gap claims tie directly to changed behaviour and realistic failure modes. - -## Automatic reject conditions - -- Style-only or subjective guidance without strong precedent or principle evidence. -- Potential issues requiring context beyond the sanctioned review window: changed files, scoped rules/contracts, allowed adjacent files, and explicitly linked PR artefacts. -- Pre-existing issues not introduced by reviewed diff. -- Linter-catch issues. -- Consistency findings when multiple equally accepted patterns exist. -- Missing `rule_source` for rule/contract violations. -- Missing `precedent_refs` for consistency findings. -- Principle-backed maintainability or architecture claims with no concrete impact. -- Test-gap claims that do not tie to changed behaviour or realistic failure modes. -- Questions that ask for context the review was already allowed to inspect. -- Questions that do not change the likely decision, severity, or recommended action. - -## Rules - -- ALWAYS try to disprove every candidate before confirming it. -- DO report only candidates that survive every applicable validation rule. diff --git a/skills/review/references/validator-prompt.md b/skills/review/references/validator-prompt.md deleted file mode 100644 index 50b751d..0000000 --- a/skills/review/references/validator-prompt.md +++ /dev/null @@ -1,48 +0,0 @@ -# Validator Prompt Template - -Use when dispatching a fresh validator subagent for one normalised candidate. - -````markdown -You validate one candidate finding or question from a senior PR review workflow. - -## Inputs - -- **Candidate**: `<full normalised candidate JSON>` -- **Scope summary**: `<resolved review scope>` -- **Intent context**: `<PR title/description and linked artefacts, or explicit user-stated review goal>` -- **Allowed context**: `<changed files, scoped rules/contracts, allowed adjacent files, precedent refs, and linked artefacts>` - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Apply `references/validation-rubric.md` exactly. -2. Start by assuming the candidate is wrong. -3. Search for counter-evidence in the allowed context. -4. Confirm the candidate only if the evidence and impact survive the full rubric. -5. Return a verdict for this candidate only. - -## Output - -Use this exact format for your output. - -```json -{ - "summary": "Short issue title", - "validator_verdict": "confirmed", - "confidence": 88, - "blocking": true, - "reason": "Brief evidence-backed explanation" -} -``` - -Use `validator_verdict: "rejected"` when the candidate does not survive validation. - -## Rules - -- ALWAYS try to disprove the candidate first. -- DO confirm only one candidate per validation run. -- DO keep the verdict evidence-based and concise. -- DO NOT widen scope beyond the allowed context. -- DO NOT rewrite the candidate into final report prose. -```` diff --git a/skills/tdd/SKILL.md b/skills/tdd/SKILL.md index d3d665a..3a365b8 100644 --- a/skills/tdd/SKILL.md +++ b/skills/tdd/SKILL.md @@ -1,59 +1,39 @@ --- name: tdd -description: Execute TDD red-green-refactor for behaviour changes. Use when changing observable behaviour, public contracts, or durable business logic. +description: Implements observable features and bug fixes through red-green-refactor. Use when an existing runnable test suite can exercise the change at a stable public seam. +metadata: + invocation: model +disable-model-invocation: false --- -# TDD +# Test-Driven Development -Drive behaviour changes with one failing behavioural test, minimal green code, then safe refactor. +**Classicist TDD** builds one observable behaviour at a time through red-green-refactor, testing the narrowest stable public seam with real internal collaborators and doubling only uncontrollable boundaries. -## Prerequisites +## Prerequisite -ALL prerequisites MUST be satisfied BEFORE following this skill. +TDD applies when an existing runnable test suite can exercise the requested behaviour through a stable public seam. Otherwise return control with the missing condition; the caller owns any decision to create a test harness or reshape a public contract. Apply TDD to observable behaviour, including configuration with observable effects; leave documentation, configuration-only maintenance, and behaviour-preserving refactors with the caller. -- The task changes observable behaviour, a public contract, or durable business logic. -- A local test runner and relevant test command are available. If not, STOP and ask whether adding or fixing the test path is in scope. -- Maintenance-only work is invalid for TDD. STOP for docs/comments/prompts/spec text, styling-only UI changes, copy-only edits unless copy is the contract, config/build/dev-tool text edits, dependency bumps, generated files, data/schema migrations without logic changes, or pure refactors. -- If work mixes behaviour change with maintenance, apply TDD ONLY to the behaviour-changing slice. +## Process -## Instructions +### 1. Establish the baseline -Follow these steps IN ORDER. Do NOT skip steps. +Read repository instructions, identify the relevant test command, and run the existing suite. Use **tracer bullets** to select the smallest end-to-end behaviour that advances the request, then choose the narrowest stable public seam that can observe the slice without exposing hidden structure. Invoke `$modular-design` when the slice changes modular architecture. Identify a **test oracle**—a requirement, worked example, invariant, contract, trusted reference, accepted prior behaviour, or explicit domain decision—capable of distinguishing the expected outcome from the implementation. Consult [Test Quality](references/TEST-QUALITY.md) when the seam, oracle, or proposed assertion could couple to representation. The baseline, behaviour, seam, oracle, and applicable modular constraints are explicit. -1. Choose the smallest thin vertical slice that delivers one observable behaviour end-to-end; state the interface, expected outcome, and narrowest test command. -2. Apply [references/testing-patterns.md](references/testing-patterns.md). If no valuable behavioural test exists, record the no-test rationale and strongest fallback verification before changing code. -3. Write ONE failing test through a public interface or stable seam for the next behaviour only. -4. Run the narrowest test command and confirm the test fails for the expected reason. -5. Write minimum passing production code; keep fixtures small and mock only real external, slow, unstable, or nondeterministic boundaries. -6. Re-run the narrowest test command and confirm green. -7. Review refactor candidates only after green using [references/refactor-candidates.md](references/refactor-candidates.md); refactor in small behaviour-preserving steps and rerun checks. -8. Repeat slice by slice until the requested behaviour is complete. +### 2. Red -## Rules +Use **Arrange-Act-Assert** to add one focused test. Apply the **Test Desiderata**, especially behavioural sensitivity, structure insensitivity, specificity, determinism, readability, and production prediction. Keep internal collaborators real. When an uncontrollable boundary must be controlled or observed, choose the least powerful **Test Double** that supplies the required evidence; consult [Test Doubles](references/TEST-DOUBLES.md) before introducing a double or interaction assertion. -These rules are MANDATORY. +For a bug, reproduce the incorrect behaviour; adopt an already-failing regression test only when it independently specifies the desired behaviour. Run the focused test and confirm that it fails for the expected behavioural reason. When it fails because of the test or environment, remain in Red: correct an in-scope defect or report the blocker, then rerun until the intended failure is observed. Meaningful red evidence exists before Green begins. -- NEVER write production code before a failing test when a valuable behavioural test exists. -- ALWAYS test observable behaviour through a public interface or stable seam. -- NEVER add source-text checks, private-structure checks, internal call choreography, broad snapshots, speculative tests, or implementation-detail tests as behavioural proof. -- DO NOT over-mock; ONLY mock real boundaries that are external, slow, unstable, nondeterministic, or too expensive for the selected test scope. -- STOP and ask if the behaviour, acceptance rule, stable seam, or relevant test command is unclear. -- NEVER refactor while red. -- ALWAYS prefer a regression test first for bug fixes. +### 3. Green -## Completion Gate +Implement only enough production code to satisfy the behaviour, then run the focused test and relevant nearby tests. The new behaviour passes without speculative production code or hidden baseline failures. -Do NOT leave this skill until ALL items are complete. +### 4. Refactor -- [ ] Work was implemented in thin vertical slices. -- [ ] Each testable slice has red proof that failed for the expected reason, then green proof after the smallest implementation. -- [ ] Tests prove behaviour through a public interface or stable seam, with no brittle, speculative, implementation-detail, or over-mocked tests kept. -- [ ] No-test fallback rationale was documented only where no valuable behavioural test exists. -- [ ] Refactor opportunities were reviewed after green, and refactors happened only while checks were green. +Improve the test and production code while keeping behaviour fixed. Preserve the test across changes to algorithms, collaborators, storage, rendering, or other hidden structure; when structure alone breaks it, move the observation back to the public outcome. Run the focused tests after each material change until the design is clear and green. The cycle ends without a refactor regression. -## References +### 5. Complete the cycles -Use these references when you need detail. - -- [references/testing-patterns.md](references/testing-patterns.md) - Test scope, behavioural seams, mocks, anti-patterns, fallback verification, and concise templates. -- [references/refactor-candidates.md](references/refactor-candidates.md) - Safe refactor candidates and post-green refactor gates. +Repeat Red, Green, and Refactor for each remaining behaviour, then run the complete relevant suite. Report the behaviours delivered, red and green evidence, refactors, commands, results, and unresolved baseline failures. The requested behaviour and retained tests are verified. diff --git a/skills/tdd/agents/openai.yaml b/skills/tdd/agents/openai.yaml new file mode 100644 index 0000000..1386203 --- /dev/null +++ b/skills/tdd/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: 'Test-Driven Development' + short_description: 'Build behaviour with red-green-refactor' +policy: + allow_implicit_invocation: true diff --git a/skills/tdd/references/TEST-DOUBLES.md b/skills/tdd/references/TEST-DOUBLES.md new file mode 100644 index 0000000..ded54f2 --- /dev/null +++ b/skills/tdd/references/TEST-DOUBLES.md @@ -0,0 +1,59 @@ +# Test Doubles + +Use this guide before replacing a collaborator or asserting calls. Keep collaborators inside the system real; substitute a boundary when the real dependency is slow, unavailable, non-deterministic, externally mutating, or otherwise uncontrollable in the test. + +## Choose the least powerful double + +Start with the real collaborator, then introduce only the capability the test needs: + +| Double | Use it to | Verification | +| --- | --- | --- | +| Dummy | Fill an unused required parameter | None | +| Stub | Supply a controlled indirect input | Assert the public outcome | +| Fake | Run a working, simplified boundary implementation | Assert the public outcome or recorded public effect | +| Spy | Record an otherwise invisible boundary effect | Inspect only promised boundary facts | +| Mock | Specify a required external interaction protocol | Verify only contractually material calls | + +Prefer state verification: act through the public seam, then inspect its result or a recorded boundary effect. Use interaction verification when the interaction is itself observable behaviour, such as one idempotency-keyed payment request or committing only after a durable write. + +## Keep the contract visible + +Specify the external fact that matters and leave the internal route free to change. + +```typescript +// Couples the test to internal delegation. +expect(pricingService.lookup).toHaveBeenCalledTimes(1); +expect(discountCalculator.apply).toHaveBeenCalledBefore(taxCalculator.apply); + +// Observes the public result with real internal collaborators. +expect(await quoteOrder(order)).toEqual({ total: 108, currency: 'GBP' }); +``` + +At an uncontrollable boundary, record the promised effect without specifying internal calls: + +```typescript +const mailer = new RecordingMailer(); +await registerUser({ email: 'ada@example.com' }, { mailer }); + +expect(mailer.sent).toEqual([{ to: 'ada@example.com', template: 'welcome' }]); +``` + +Use an expectation mock when the external protocol is the outcome: + +```typescript +await submitPayment(order, paymentGateway); + +expect(paymentGateway.charge).toHaveBeenCalledOnceWith({ + amount: 108, + currency: 'GBP', + idempotencyKey: order.id, +}); +``` + +Here the amount, currency, single request, and idempotency key are provider-facing promises. Do not add expectations for logging, helper calls, object construction, or other internal routing. + +## Preserve boundary fidelity + +A double can make an impossible system look correct. Keep its behaviour smaller than the production boundary and derive responses from the provider contract rather than copied client logic. Where feasible, run focused contract tests against the real boundary to confirm that the fake, stub, or recorded request still matches it. Otherwise report the unverified fidelity as a limitation. + +Control time and randomness by injecting a clock or deterministic source at the system boundary. Prefer a real test database or filesystem in an isolated disposable environment when its semantics are material; use a fake only when its behavioural differences cannot invalidate the test's claim. diff --git a/skills/tdd/references/TEST-QUALITY.md b/skills/tdd/references/TEST-QUALITY.md new file mode 100644 index 0000000..1a53249 --- /dev/null +++ b/skills/tdd/references/TEST-QUALITY.md @@ -0,0 +1,83 @@ +# Test Quality + +Use this guide when choosing a seam or oracle, or when an assertion may couple the test to representation rather than promised behaviour. + +## Choose the test seam + +Test the narrowest boundary that satisfies all three conditions: + +- **Observable:** it exposes the requested return value, public state, error, emitted effect, persistence, navigation, or user-perceivable result. +- **Stable:** it hides algorithms, collaborator graphs, storage layouts, rendering wrappers, generated selectors, and other decisions that may change while behaviour remains fixed. +- **Predictive:** exercising it provides credible evidence that the behaviour will work in production. + +Use a coarser companion test only when the narrow seam cannot predict a material integration outcome. A substitutable private hook is not a suitable assertion boundary merely because it is convenient to replace. + +## Construct the oracle + +Derive the expected outcome before implementing Green. Prefer, in order: + +1. A requirement, accepted example, published protocol, or explicit domain decision. +2. A law, invariant, or contract independent of the production algorithm. +3. A trusted external reference or separately implemented model. +4. Prior accepted behaviour when preserving that behaviour is the requirement. + +Encode the oracle as an independently reasoned literal or predicate. A small calculation is suitable when it expresses a different trusted rule; reusing the production helper or repeating its algorithm can only reproduce the same defect. + +```typescript +// Repeats the implementation's likely algorithm. +const expected = items.reduce((sum, item) => sum + item.price, 0); +expect(calculateTotal(items)).toBe(expected); + +// Uses the accepted worked example as an independent oracle. +expect(calculateTotal([{ price: 10 }, { price: 5 }])).toBe(15); +``` + +When no credible oracle exists, return the missing behavioural decision instead of inventing the expected result. Treat output captured from the current implementation as characterization, not proof of correctness. + +## Structure one behaviour + +Use Arrange-Act-Assert: + +1. **Arrange** only the state and collaborators needed for the behaviour. +2. **Act** once through the selected public seam. +3. **Assert** the complete promised outcome and material unchanged state. + +One behaviour may require several cohesive assertions. Split a test when it contains multiple independent Acts or when its name cannot state one behavioural rule. Clean up resources or external state acquired by the test. + +## Apply the Test Desiderata + +Retain tests that are isolated, composable, deterministic, fast, writable, readable, behavioural, structure-insensitive, automated, specific, predictive, and inspiring. Treat the properties as trade-offs: a slower test can earn its cost through prediction, while a faster test still needs credible production evidence. + +Use two counterfactuals: + +- If promised behaviour changed, would the test result change? +- If only hidden structure changed, would the test and result remain unchanged? + +A useful test answers yes to both. Move a structure-sensitive observation outward to the supported result; move a behaviour-insensitive assertion toward the actual promise. + +## Observe promised outcomes + +| Concern | Durable observation | Replace structure coupling with | Representation is valid when | +| --- | --- | --- | --- | +| Domain result | Public operation against an independently justified example or invariant | A literal, contract, or independently reasoned predicate instead of the production algorithm | The representation is part of the domain contract | +| Public state | Supported command followed by a documented query or return value | Public state instead of private fields, methods, or patched internals | Diagnostic state is an intentional supported interface | +| Error | Caller-visible type, code, material message, and promised recovery or unchanged state | Stable error meaning instead of a private branch, stack shape, or helper call | Exact wording is a documented user or API contract | +| UI | Role, label, text, displayed value, accessible state, focus, or navigation | User-perceivable outcome instead of classes, wrapper tags, child indexes, or DOM depth | Visual appearance or semantic markup is the promised behaviour | +| Persistence | Write and read through supported interfaces, with reload or restart when durability matters | Public retrieval instead of private tables, columns, ORM calls, or storage layout | The schema is a published integration contract | +| External effect | Recorded boundary request or fake mailbox, queue, or provider outcome | Promised payload and result instead of internal delegation | Count, order, or arguments are part of the external protocol | +| Snapshot or serialization | Small reviewed public artifact or selected semantic fields | Focused compatibility facts instead of broad structural snapshots | Exact bytes, markup, or object shape are the published format | +| Configuration | Configured system exercised through its observable effect | Runtime result instead of parser calls or incidental internal objects | Generated configuration text is itself the public artifact | + +For UI behaviour, interact as a user would and assert what a user or assistive technology can perceive: + +```typescript +// Couples the test to generated styling and DOM structure. +expect(button.className).toBe('btn btn-primary px-4'); +expect(container.children[0]).toBe(button); + +// Observes the supported interaction and visible result. +await user.click(screen.getByRole('button', { name: 'Save' })); +expect(screen.getByText('Changes saved')).toBeVisible(); +``` + +For side effects, observe the system boundary rather than the internal route. Assert call count or order only when duplicate suppression, transaction ordering, or protocol sequencing is the behaviour. See [Test Doubles](TEST-DOUBLES.md) for boundary substitutes and interaction assertions. diff --git a/skills/tdd/references/refactor-candidates.md b/skills/tdd/references/refactor-candidates.md deleted file mode 100644 index 7012a35..0000000 --- a/skills/tdd/references/refactor-candidates.md +++ /dev/null @@ -1,84 +0,0 @@ -# Refactor Candidates - -Use only after red-green is green. Refactor to remove present design pressure while preserving behaviour. - -## When To Refactor - -Refactor when checks are green and you can name a real improvement. Good reasons: - -- the next change is harder than it should be; -- a rule is duplicated and starting to drift; -- names hide the behaviour proven by tests; -- setup or tests are noisy because responsibilities are misplaced; -- branches or data shapes obscure the domain rule; -- a small move would reduce current risk or confusion. - -Do one structural idea at a time; stop when current pain is removed. - -## When Not To Refactor - -Do not refactor when: - -- tests or fallback checks are red; -- the improvement is hypothetical; -- the abstraction has one caller and no present pressure; -- you cannot describe the behaviour-preserving move; -- the code is awkward but isolated and not blocking current work; -- the refactor would expand scope beyond the requested slice. - -Use YAGNI: reject abstractions for futures the code does not need today. - -## Signals To Spot - -### Duplicated Knowledge - -Look for the same decision, validation, calculation, workflow, or domain phrase in multiple places. Copies drift and fixes land in one place. Improve by extracting the shared rule, moving it to the owner, or introducing a small abstraction only after real call sites need it. - -### Mixed Responsibilities - -Look for one function/module that validates, calculates, persists, formats, and coordinates. Unrelated changes collide and tests need excessive setup. Improve by separating orchestration from decisions, moving behaviour to the strongest owner, and keeping coordinators thin. - -### Poor Names - -Look for placeholders, abbreviations, stale names, or tests named for mechanics instead of behaviour. Unclear names hide intent and slow changes. Rename variables, functions, types, files, and tests to match domain meaning. - -### Long Or Tangled Flow - -Look for deep nesting, repeated conditions, order-sensitive branches, or methods that require scrolling. Bugs hide in unreadable paths. Improve with guard clauses, predicates, named steps, or split cases; use polymorphism only after duplication makes cases real. - -### Feature Envy - -Look for logic repeatedly pulling fields from another object to decide for it. Move behaviour closer to the data or replace field chains with messages to the owner. - -### Primitive Obsession - -Look for strings, booleans, numbers, or loose parameter groups repeatedly encoding a domain concept. Use a small value object, enum, named type, or parameter object when the concept has behaviour or repeated validation. - -### Test Friction - -Look for tests needing heavy setup, many mocks, private seams, or fragile assertions for simple behaviour. Test pain often exposes design pain; improve production design when valuable, not test-only seams. - -## Safe Moves - -Prefer small behaviour-preserving moves: - -- rename; -- extract function or predicate; -- inline unnecessary indirection; -- move behaviour to its owner; -- split orchestration from domain rules; -- replace magic values with named concepts; -- collapse duplicated rules; -- simplify conditionals; -- replace partial mocks with realistic fakes when it improves design pressure. - -Run the narrowest relevant check after each meaningful move. If it fails, fix or revert the last refactor step before continuing. - -## Filters - -Use these filters before changing structure: - -- DRY: remove repeated knowledge, not every repeated line. -- SOLID: improve ownership only where current design already shows pressure. -- YAGNI: do not build for imagined futures. -- Refactor-safe tests: existing tests should still prove the same behaviour after the move. diff --git a/skills/tdd/references/testing-patterns.md b/skills/tdd/references/testing-patterns.md deleted file mode 100644 index dfbe5eb..0000000 --- a/skills/tdd/references/testing-patterns.md +++ /dev/null @@ -1,112 +0,0 @@ -# Testing Patterns - -Use before writing or keeping a TDD test. Keep tests behavioural, refactor-safe, and cheap enough for red-green. - -## When TDD Applies - -Use TDD for observable behaviour, public contracts, or durable business logic. Do not force it for prose-only docs, comments, prompts, formatting, config text, dependency bumps, generated files, or pure refactors; record no-test rationale and run fallback verification. If work mixes behaviour and maintenance, TDD only the behaviour-changing slice. - -## Test Type Choice - -Choose the highest-level quick, deterministic test that proves behaviour. - -1. Prefer feature or integration tests first. Test the public path a caller, user, endpoint, CLI, message handler, or upstream module uses. -2. Use unit tests second for isolated important logic, especially rules with many cases, edge conditions, or awkward setup through the full path. -3. Use browser or end-to-end tests sparingly for UI interaction patterns, smoke coverage, or behaviour that lower-level tests cannot prove. - -Drop lower only when the higher-level path is slow, flaky, too broad, or expensive to control; use a stable domain seam, not a private helper. - -## Red-Green Test Quality - -Write one failing test for one missing behaviour. - -Good red tests name caller-visible behaviour, fail for the expected reason before production changes, imply the next smallest code change, assert observable outcomes, and avoid future requirements. - -Weak red tests assert helper calls, call order, source text, hook names, class names, or private state; require large mock choreography; fail when internals move but behaviour stays; or cover hypothetical edge cases. - -## Refactor-Safe Tests - -Refactor-safe tests keep passing when internals change but behaviour does not. Assert through public interfaces or stable seams: - -- returned values; -- persisted state through supported reads; -- visible UI or announced accessibility output; -- emitted domain events; -- externally visible side effects. - -Avoid private helpers, hidden fields, internal modules, source-string checks, AST shape, broad snapshots, and internal call choreography. - -```typescript -// Good: public behaviour -test('rejects checkout when the cart is empty', async () => { - const result = await checkout(emptyCart()); - - assertEqual(result.ok, false); - assertEqual(result.error, 'Cart is empty'); -}); - -// Bad: implementation detail -test('calls validateCart before createOrder', async () => { - const calls = recordCallOrder( - cartModule, - 'validateCart', - orderModule, - 'createOrder', - ); - - await checkout(emptyCart()); - - assertSequence(calls, ['validateCart', 'createOrder']); -}); -``` - -## Good Tests - -Good tests prove a depended-on behaviour through exported functions, endpoints, commands, UI interactions, handlers, or stable domain seams. Keep setup small and realistic; use multiple assertions only for one outcome from one cause; prefer cheap builders, fixtures, in-memory adapters, and real collaborators; make failures describe broken behaviour. - -Examples: `login(email, password)` rejects invalid credentials; `publishPost()` makes the post visible in `listPublishedPosts()`; clicking `Save` shows a success message. - -## Bad Tests - -Reject structure tests: `checkout()` calls `paymentService.charge()` once; `login()` calls `validatePasswordHash()`; source text contains `aria-label`; a broad snapshot proves a menu opens; a test exists only because an edge case might matter later. - -Replace bad tests with behavioural assertions. If none exists, do not keep a weak test; document the no-test rationale and run fallback verification. - -## Mocks And Doubles - -Mock only real boundaries that are external, slow, unstable, nondeterministic, or too expensive for the selected scope. Good targets: - -- payment gateways; -- clocks and time; -- UUID/randomness; -- network calls; -- file systems; -- third-party APIs. - -Keep core logic real. Prefer behaviour-preserving fakes, such as an in-memory repository or mailer. If mock setup dominates, the test likely proves mocks agree. If mock data is required, mirror enough real schema to avoid accidental reliance on missing fields. - -## Anti-Patterns - -Do not keep these as behavioural proof: - -- source-string checks; -- private-structure checks; -- internal call counts or order; -- broad snapshots for dynamic markup; -- test-only production flags or methods; -- partial hand-waved mocks; -- tests for speculative requirements; -- mocking away the behaviour under test. - -## Gate Questions - -Ask before writing or keeping a test: - -1. What behaviour does this prove for a caller or user? -2. Would it pass after an internal rewrite with the same behaviour? -3. Is the assertion through a public interface or stable domain seam? -4. Is every mock isolating a real boundary? -5. Is this the next required behaviour, not a future guess? -6. Will failure point to broken behaviour rather than changed structure? - -If any answer is no, rewrite the test. If no valuable behavioural test remains, document why and run the strongest fallback verification: existing related tests, typecheck, lint, build, CLI smoke check, browser check, or manual reproduction. diff --git a/skills/write-skill/SKILL.md b/skills/write-skill/SKILL.md index a264ee4..f6f1c34 100644 --- a/skills/write-skill/SKILL.md +++ b/skills/write-skill/SKILL.md @@ -1,53 +1,53 @@ --- name: write-skill -description: Create or improve reusable skills with compact progressive-disclosure artefacts. Use when authoring, updating, or migrating any skill. +description: Creates and updates predictable agent skills through confirmed behavioural contracts, evidence-backed concepts, and forward testing. Use when authoring or revising a skill. +metadata: + invocation: user +disable-model-invocation: true --- # Write Skill -Create concise skills for repeatable workflows without bloating context. +**Minimalist instruction** turns confirmed behaviours into the smallest skill bundle that reliably teaches them. -## Instructions +## Process -Follow these steps IN ORDER. Do NOT skip steps. +### 1. Establish the behavioural contract -1. Load `interrogate` to gather the skill's job, use cases, expected inputs, expected outputs, and trigger phrases before drafting. -2. Choose the default output path `.agents/skills/{skill-name}/`; keep `name` equal to the directory name. -3. Draft or update `SKILL.md` using [assets/skill-template.md](assets/skill-template.md). -4. Put only essential workflow in `SKILL.md`; move supporting artefacts into appropriate directories. -5. Put templates/static resources in `assets/`, executable helpers in `scripts/`, and detailed docs in `references/`. -6. Validate the result with [scripts/validate-skill.js](scripts/validate-skill.js), then fix every blocking issue. +Inspect the request, complete target bundle, discoverable callers, and host conventions. Invoke `$elicit` and use the **main success scenario** to confirm the skill's purpose, trigger, primary behaviour, required inputs, observable result, and resource needs. Apply **YAGNI** to speculative branches: retain an exception only when representative evidence, the primary behaviour, or a necessary safety or permission boundary requires it. Existing and new skills reach one explicit behavioural contract with a dominant thread and only its material exceptions. -## Rules +### 2. Compare governing methodologies -These rules are MANDATORY. +Use the confirmed behavioural contract as the fixed scope and decision authority for both research passes; evidence selects how to teach the confirmed behaviour. Invoke `$research` to compare credible governing methodologies, then **design it twice**: continue until at least two credible options emerge or the evidence reaches saturation. Present the supported options, behavioural consequences, and recommendation for the user to choose. Offer only evidence-supported alternatives; when one methodology survives, compare it with a methodology-free process. The user's selection or evidence-backed absence is explicit. -- Required authored-skill sections are title, one-line purpose, `## Instructions`, and `## References`. -- Optional sections become REQUIRED when prerequisites, durable rules, completion gates, or next steps exist. -- MUST use only canonical H2 sections in order; `## References` must be the final H2. -- MUST keep `SKILL.md` compact: target about 50 body lines and never exceed 80 body lines. -- MUST make `description` one line, triggerable, and clear about when the skill should be used. -- MUST place artefacts directly under `assets/`, `references/`, or `scripts/` and link each from final references as `- [path](path) - text`. -- MUST use progressive disclosure: metadata first, essential instructions second, artefacts as needed. -- MUST write short, direct, instructional prose: remove filler, pleasantries, hedging, and verbose phrases while preserving exact technical meaning. -- MUST review [references/checklist.md](references/checklist.md) and run [scripts/validate-skill.js](scripts/validate-skill.js) before handoff. +### 3. Select supporting concepts -## Completion Gate +Invoke `$research` to find established principles, theories, methods, or techniques that reinforce distinct concerns without competing with the selected governor. Explain each candidate's intended behavioural effect and let the user decide; let the evidence determine the count. Every retained concept earns a distinct role. -Do NOT leave this skill until ALL items are complete. +### 4. Confirm the design -- [ ] Skill path and frontmatter name match. -- [ ] Used `interrogate` skill to resolve the skill job, use cases, expected inputs, expected outputs, and trigger phrases before drafting. -- [ ] `SKILL.md` contains only essential workflow and required sections. -- [ ] Skill wording is concise, no-fluff, and technically precise. -- [ ] Supporting artefacts are placed under `assets/`, `references/`, or `scripts/` by purpose. -- [ ] Checklist review is complete with blocking issues fixed. -- [ ] Validator has been run against the skill and all errors are fixed. +Present one complete synthesis of the behavioural contract, selected concepts, structure, resources, main success scenario, material exceptions, and observable success conditions. Obtain explicit confirmation before following the remaining process. -## References +### 5. Write the bundle -Use these references when you need detail. +Create or update through one path. Treat the confirmed design as closed: encode its main success scenario and retained material exceptions without adding new behaviour during drafting. Give every `SKILL.md` frontmatter, one H1, a concise introduction, and exactly one `## Process`; place a selected governing methodology in bold where it fits naturally in the introduction. Bold each supporting concept at its first behaviour-governing use. Consult [Skill Sections](references/SECTIONS.md) when invocation metadata, optional sections, or resource placement needs detail. The bundle expresses the confirmed design. -- [assets/skill-template.md](assets/skill-template.md) - Section-by-section authoring template. -- [references/checklist.md](references/checklist.md) - Skill quality and validation checklist. -- [scripts/validate-skill.js](scripts/validate-skill.js) - Bun validator for skill metadata, body limits, and artefacts. +### 6. Separate the concerns + +Apply **separation of concerns** so each step or subsection carries one coherent behavioural idea and observable outcome. Split independently actionable instructions, concepts, or completion criteria; keep sentences together when they jointly govern the same action. Consult [Skill Craft](references/CRAFT.md) when the split, vocabulary, emphasis, or disclosure boundary is unclear. Every section remains focused and substantial. + +### 7. Compress the language + +Apply minimalist instruction and **DRY** until every remaining word changes behaviour, preserves a condition, or improves navigation. Replace explanations with canonical leading words when the agent already knows the concept and keep each meaning in one authoritative location. Use **ironic process theory** as a salience check: state the positive target behaviour and pair an essential prohibition with the safe action that satisfies it. Consult [Skill Craft](references/CRAFT.md) when negative framing or semantic duplication remains unclear. Every remaining instruction is behaviourally necessary, authoritative, and positively framed. + +### 8. Validate the mechanics + +Run [scripts/validate-skill.js](scripts/validate-skill.js), inspect every bundled script, and execute each within a disposable filesystem using inert fixtures, isolated credentials, and an environment incapable of external mutation. When that boundary is unavailable, leave the script unexecuted and report the limitation. The mechanical contract passes within the safe execution boundary. + +### 9. Forward-test the behaviour + +Give a fresh agent only the finished bundle and a realistic main-success invocation, then compare its observable process and result with the confirmed contract. Add the smallest scenario for each retained material exception. Consult [Forward Testing](references/TESTING.md) when scenario selection, isolation, or pass evidence needs detail. Repair, recompress, revalidate, and retest until the skill reliably invokes the intended behaviour. + +### 10. Report the result + +Return the changed files, research evidence, mechanical results, forward-test scenarios and outcomes, unexecuted scripts, and remaining uncertainty. The user receives the finished bundle and evidence that its contract holds. diff --git a/skills/write-skill/agents/openai.yaml b/skills/write-skill/agents/openai.yaml new file mode 100644 index 0000000..2223e0f --- /dev/null +++ b/skills/write-skill/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: 'Write Skill' + short_description: 'Create and update predictable agent skills' +policy: + allow_implicit_invocation: false diff --git a/skills/write-skill/assets/skill-template.md b/skills/write-skill/assets/skill-template.md deleted file mode 100644 index 5d765c4..0000000 --- a/skills/write-skill/assets/skill-template.md +++ /dev/null @@ -1,97 +0,0 @@ -# Skill Authoring Template - -Use for skills written to `.agents/skills/{skill-name}/SKILL.md` unless the user asks for another supported location. - -```markdown ---- -name: {skill-name} -description: {One-line action-oriented summary with the main use case and trigger words early}. Use when {specific trigger context}. ---- - -# {Skill Title} - -{One-line purpose: what repeatable job this skill performs.} - -## Prerequisites - -ALL prerequisites MUST be satisfied BEFORE following this skill. - -- {Only include when the skill must stop, route, or require a condition before work starts.} - -## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. {First required action, including expected inputs when relevant.} -2. {Next required action, including expected outputs and artefacts when relevant.} -3. {Final action that completes the workflow.} - -## Rules - -These rules are MANDATORY. - -- {Durable rule that must always apply, using control words like MUST, DO NOT, NEVER, ONLY, STOP, or ALWAYS.} - -## Completion Gate - -Do NOT leave this skill until ALL items are complete. - -- [ ] {Observable completion check.} - -## Next Steps - -Once the completion gate is fully checked: - -- {Only include when the workflow must route or hand off after completion.} - -## References - -Use these references when you need detail. - -- [references/{file}.md](references/{file}.md) - {Specific purpose.} -``` - -## Section Instructions - -- `name`: use lowercase alphanumeric words joined by single hyphens; match the parent directory exactly. -- `name`: keep to 64 characters or fewer. -- `description`: keep one YAML line, action-oriented, third person, triggerable with `Use when`, `Use for`, or `Use to`. -- `description`: front-load the main use case and trigger words because crowded skill lists can shorten descriptions. -- `description`: validator warns over 200 characters and errors over 300 characters. -- Title: use a short human-readable H1 that matches the workflow, not necessarily the exact `name`. -- One-line purpose: state the repeatable job and outcome in plain language. -- H2 sections must use this canonical order and no other names: `## Prerequisites`, `## Instructions`, `## Rules`, `## Completion Gate`, `## Next Steps`, `## References`. -- `## Instructions` and `## References` are required. -- Each included H2 must start with its template intro sentence; extra text may follow on the same line. -- `## Instructions`: name expected inputs, outputs, and artefacts when relevant. -- `## Prerequisites`: optional; include only when conditions can block, redirect, or define valid use. -- `## Rules`: optional; include when durable constraints must override improvisation; use strong UPPERCASE control words like `MUST`, `DO NOT`, `NEVER`, `ONLY`, `STOP`, or `ALWAYS`. -- `## Completion Gate`: optional; include when the agent must verify explicit end-state checks before leaving. -- `## Next Steps`: optional; include only when a workflow handoff, routing choice, or post-completion action exists. -- `## References` must be the final H2. -- Reference bullets for artefacts must be exactly `- [path](path) - text`; link text must match href and include the short description. -- Only links in the final `## References` section count for artefact coverage. - -## Prose Style - -- Write commands, not essays: use direct verbs like Load, Check, Run, Fix, Stop, or Return. -- Delete filler, pleasantries, hedging, and setup phrases such as just, really, basically, actually, simply, please, likely, may want to, and happy to. -- Prefer short concrete words over verbose phrasing: use fix instead of implement a solution for, use check instead of perform validation of. -- Preserve exact technical meaning: required keywords, paths, commands, API names, error text, safety warnings, and ordering constraints. -- Use fragments when clear, but expand any sentence where compression could hide a condition, risk, or handoff. - -## Artefact Placement - -- `assets/`: templates, starter files, static examples, images, prompts, resources copied/adapted into outputs. -- `references/`: checklists, rubrics, explanations, examples, and long context outside `SKILL.md`. -- `scripts/`: executable validation, generation, migration, or inspection helpers. -- Prefer instructions over scripts unless deterministic behavior or external tooling is needed; scripts must be self-contained, dependency-light, and actionable. -- Place artefacts directly under `assets/`, `references/`, or `scripts/`; nested artefact paths are not allowed. - -Keep `SKILL.md` around 50 body lines and under 80 body lines. Move detail here or into `references/` instead of expanding the main skill. - -## Validator CLI - -- Run as `bun scripts/validate-skill.js <skill-path>` from the skill directory, or `bun path/to/validate-skill.js <skill-path>` from elsewhere. -- The validator requires exactly one skill directory path, not a file path. -- The validator always writes JSON to stdout and exits non-zero when `valid` is `false`. diff --git a/skills/write-skill/references/CRAFT.md b/skills/write-skill/references/CRAFT.md new file mode 100644 index 0000000..d55e740 --- /dev/null +++ b/skills/write-skill/references/CRAFT.md @@ -0,0 +1,45 @@ +# Skill Craft + +Use this reference when a methodology, supporting concept, section boundary, leading word, or disclosure decision remains unclear. + +## Compare methodologies + +Research methods against the confirmed behaviour rather than selecting one for familiarity. Use **design it twice** to compare credible candidates through: + +- the process each method would impose; +- the behaviours it strengthens or suppresses; +- its fit across the main success scenario and retained material exceptions; +- the local adaptations it would require; and +- the evidence supporting its published meaning. + +Continue until multiple credible choices emerge or further research is unlikely to change the set. Recommend the strongest fit and expose its trade-offs. When only one survives, compare it with a methodology-free process. + +## Select supporting concepts + +A supporting concept earns inclusion only when it governs a concern the selected methodology leaves unresolved. Name its behavioural job in one sentence and test whether removing it changes the instructions. Use the governor and plain language alone when they already determine the behaviour; retain as many concepts as distinct concerns require. + +## Choose leading words + +Prefer the canonical name of a recognised method, principle, theory, or technique already present in the agent's knowledge. A leading word earns its place when it replaces explanation and sharpens a decision, action, or stopping condition. Remove or replace a term that forward testing shows to be decorative. + +Bold the governing methodology naturally within the introduction when one was selected. Bold a supporting concept where it first governs behaviour, then use plain text unless renewed emphasis changes the instruction. + +## Separate concerns + +Give a step or subsection one coherent behavioural idea and one observable outcome. Split it when any sentence could be acted on, tested, reordered, or completed independently. Keep supporting detail together when separating it would make the action harder to understand or create headings without meaningful content. + +## Disclose depth + +Keep knowledge inline when every invocation needs it to act correctly. Move a retained exception to a reference when its detail would obscure the common path. Write every pointer as the precise loading condition. Pull must-have material back inline when forward tests show that a sharper pointer still misses the behaviour. + +## Remove no-ops + +Test each sentence in isolation: would deleting it change agent behaviour, preserve a necessary condition, or impair navigation? Delete the whole sentence when the answer is no. Prefer a stronger canonical term over several weak adjectives, and prefer one checkable bound over exhortations to be careful or thorough. + +## Remove duplication + +Apply **DRY** to meaning rather than tokens. Give each behaviour, rule, and definition one authoritative expression. Repeating a canonical term can focus attention; repeating its explanation inflates prominence and creates competing authorities. + +## State positive behaviour + +Use ironic process theory as a salience check during final compression. Describe the action the agent should perform, replace avoidable negative framing with that target, and reserve prohibitions for essential safety boundaries that cannot be expressed positively. Pair each retained prohibition with the safe action that satisfies it. The instruction keeps the intended behaviour most salient. diff --git a/skills/write-skill/references/SECTIONS.md b/skills/write-skill/references/SECTIONS.md new file mode 100644 index 0000000..572f708 --- /dev/null +++ b/skills/write-skill/references/SECTIONS.md @@ -0,0 +1,50 @@ +# Skill Sections + +Use this reference when invocation metadata, optional sections, or bundled resource placement needs more detail than the fixed skill spine. + +## Frontmatter + +Include the skill's discovery and invocation contract: + +- `name` matches its directory, uses lowercase letters, digits, and single hyphens, and reads naturally when invoked. +- `description` is one action-oriented line containing the capability and natural trigger conditions. +- `metadata.invocation` records `user` or `model`. +- `disable-model-invocation` and `agents/openai.yaml` use the matching policy. + +Use user invocation by default. Use model invocation only when autonomous discovery would naturally help during ordinary coding work often enough to earn the permanent description context. + +| Invocation | `disable-model-invocation` | `policy.allow_implicit_invocation` | +| ---------- | -------------------------- | ---------------------------------- | +| `user` | `true` | `false` | +| `model` | `false` | `true` | + +Add `agents/openai.yaml` with a human-readable `interface.display_name`, a 25–64-character `interface.short_description`, and the matching policy. + +## Introduction + +The fixed spine and emphasis rules in the main workflow are authoritative. Use the introduction to explain only the selected methodology's context-specific adaptation. + +## Process details + +Within `## Process`, use numbered H3 headings when order matters, descriptive H3 headings for distinct non-sequential concerns, or direct prose for a truly thin process. For branches, use descriptive H3 headings and numbered H4 steps only when the nested sequence improves execution. Each section carries one coherent behavioural idea; each ordered step ends in an observable postcondition. + +## Optional sections + +Add an H2 when it communicates the content more clearly than placement beside the process instruction it governs: + +- `## Prerequisites` states external conditions and the safe route when absent. +- `## Rules` holds invariants that constrain multiple instructions or the finished result. +- `## Handoff` states a meaningful transfer, its evidence, and unresolved uncertainty. + +Rename or combine optional sections when that improves the confirmed behaviour. Every optional section earns its place through clearer execution. + +## Bundled resources + +Use **progressive disclosure** as an information hierarchy: + +- Keep the common execution path in `SKILL.md`. +- Put conditional or extensive runtime guidance in `references/`. +- Put files consumed or copied into generated output in `assets/`. +- Put deterministic, repeated, or fragile operations in `scripts/`. + +Add a resource when a retained material exception or other conditional depth improves execution. Link every resource directly from `SKILL.md` beside a precise condition that tells the agent when it may help. Keep references one level deep and each meaning in one authoritative location. References contain runtime guidance rather than general concept explanations. diff --git a/skills/write-skill/references/TESTING.md b/skills/write-skill/references/TESTING.md new file mode 100644 index 0000000..263937e --- /dev/null +++ b/skills/write-skill/references/TESTING.md @@ -0,0 +1,29 @@ +# Forward Testing + +Use this reference when scenario selection, context isolation, or observable pass evidence needs more detail than the main success scenario. + +## Preserve the evaluation boundary + +Give the fresh agent the finished bundle and a realistic user request. Keep the intended answer, design rationale, suspected failure, and prior test output outside the evaluation context. Use an inert workspace or read-only artifacts; permit safe local writes only when the scenario requires them. A test demonstrates transferable steering when the finished bundle and task-local evidence supply the result. + +## Select scenarios + +Run the main success scenario for every created or rewritten skill. Add the smallest scenario for a retained material exception when it distinguishes: + +- an evidenced invocation that changes the required process or result; +- a necessary safety, permission, or prerequisite boundary; +- an optional reference needed by the retained exception; +- a fragile script or deterministic output contract; or +- wording whose effect depends on a leading word. + +Prefer one scenario that distinguishes several competing behaviours when its failure remains diagnosable. The scenario set contains only confirmed behaviour or material risk rather than hypothetical combinations. + +## Define evidence + +Translate the confirmed contract into observable pass conditions before reading the result. Inspect the agent's actions, resource reads, decisions, output, and postconditions. Pass only when the skill invokes the confirmed process, loads relevant context, follows every required branch, and derives its result from the evaluation boundary. + +## Repair the smallest cause + +Trace each failure to the smallest instruction, pointer, section boundary, or missing resource that explains it. Repair that cause, then rerun the failed scenario and a common-path scenario. Recompress and mechanically revalidate after every material change. + +Stop when every confirmed scenario passes or reducing the remaining variance would change the confirmed contract. Report unresolved variance plainly. diff --git a/skills/write-skill/references/checklist.md b/skills/write-skill/references/checklist.md deleted file mode 100644 index f920e5d..0000000 --- a/skills/write-skill/references/checklist.md +++ /dev/null @@ -1,76 +0,0 @@ -# Skill Checklist - -Use this checklist before handing off a new or updated skill. - -## Frontmatter - -- [ ] `name` is lowercase with single hyphen separators. -- [ ] `name` is 1-64 characters. -- [ ] `name` matches the parent directory name. -- [ ] `name` matches `^[a-z0-9]+(-[a-z0-9]+)*$`. -- [ ] `description` is one line only. -- [ ] `description` is 200 characters or fewer to avoid validator warnings. -- [ ] `description` is 300 characters or fewer to avoid validator errors. -- [ ] `description` includes what the skill does. -- [ ] `description` includes `Use when`, `Use for`, or `Use to`. -- [ ] `description` front-loads the main use case and trigger words because crowded skill lists can shorten descriptions. -- [ ] `description` includes natural trigger keywords a user would say. -- [ ] `description` is third person and action-oriented. -- [ ] `description` starts with a strong action verb such as Create, Validate, Review, Manage, or Execute. - -## Artefact Layout - -- [ ] Repository skill path defaults to `.agents/skills/{skill-name}/SKILL.md`. -- [ ] `SKILL.md` has required `name` and `description` frontmatter. -- [ ] `assets/` contains only reusable templates or static resources. -- [ ] `references/` contains detailed documentation, examples, rubrics, or checklists. -- [ ] `scripts/` contains only executable helpers and documents how to run them. -- [ ] Scripts are used only when deterministic behavior or external tooling is needed. -- [ ] Scripts are self-contained, dependency-light, and report actionable errors. -- [ ] Artefacts are directly under `assets/`, `references/`, or `scripts/`; no nested artefact paths exist. -- [ ] No unnecessary README, changelog, or duplicate auxiliary files were added. - -## SKILL.md Body - -- [ ] Includes a title and one-line purpose. -- [ ] Includes required `## Instructions` and `## References` sections. -- [ ] Uses only allowed H2 sections: `## Prerequisites`, `## Instructions`, `## Rules`, `## Completion Gate`, `## Next Steps`, `## References`. -- [ ] H2 sections follow the canonical order exactly when present. -- [ ] `## References` is the final H2 section. -- [ ] Each included H2 starts with its required intro sentence from the template; extra text may follow on the same line. -- [ ] Includes `## Prerequisites` when the skill can be invalid, blocked, or must route elsewhere. -- [ ] Includes `## Rules` when durable instructions must always apply. -- [ ] Includes `## Completion Gate` when explicit finish checks are needed. -- [ ] Includes `## Next Steps` when a handoff or post-completion route exists. -- [ ] Uses ordered steps for workflows that must run in sequence. -- [ ] Instructions name expected inputs, outputs, and artefacts when relevant. -- [ ] `## Rules` uses strong control words such as `MUST`, `DO NOT`, `NEVER`, `ONLY`, `STOP`, or `ALWAYS`. -- [ ] Body stays at or below 50 non-empty lines to avoid validator warnings. -- [ ] Body stays at or below 80 non-empty lines to avoid validator errors. - -## Language Quality - -- [ ] Removes filler: just, really, basically, actually, simply. -- [ ] Removes pleasantries/chatty setup: sure, certainly, happy to, please. -- [ ] Removes hedging from required instructions: likely, maybe, should probably, may want to. -- [ ] Replaces verbose phrasing with short direct wording without changing meaning. -- [ ] Preserves exact commands, paths, APIs, error text, safety warnings, conditions, and ordering constraints. - -## Progressive Disclosure - -- [ ] Level 1 metadata is enough to decide whether to load the skill. -- [ ] Level 2 `SKILL.md` contains only essential workflow and durable rules. -- [ ] Level 3 artefacts hold examples, templates, explanations, and long checklists. -- [ ] All linked references resolve from `SKILL.md` using relative paths. -- [ ] Every `assets/`, `references/`, and `scripts/` artefact is linked from the final `## References` section. -- [ ] Reference bullets use exactly `- [path](path) - text`. -- [ ] Reference bullet link text matches the href exactly. -- [ ] Reference bullets include a short description after the separator in `- [path](path) - text`. -- [ ] No orphaned reference, asset, or script files exist. - -## Validation - -- [ ] Manually verify frontmatter, line count, links, and artefact placement. -- [ ] Run the dedicated validator with exactly one skill directory path. -- [ ] Do not pass validator options or a file path. -- [ ] Read validator output as JSON on both success and failure. diff --git a/skills/write-skill/scripts/validate-skill.js b/skills/write-skill/scripts/validate-skill.js index 8de4681..0878316 100644 --- a/skills/write-skill/scripts/validate-skill.js +++ b/skills/write-skill/scripts/validate-skill.js @@ -1,426 +1,328 @@ #!/usr/bin/env bun -import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'; -import { basename, join, relative, resolve } from 'node:path'; -const args = process.argv.slice(2); +import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs'; +import { basename, join, relative, resolve, sep } from 'node:path'; + const errors = []; const warnings = []; -const allowedSections = [ - 'Prerequisites', - 'Instructions', - 'Rules', - 'Completion Gate', - 'Next Steps', - 'References', -]; -const sectionIntroLines = { - Prerequisites: - 'ALL prerequisites MUST be satisfied BEFORE following this skill.', - Instructions: 'Follow these steps IN ORDER. Do NOT skip steps.', - Rules: 'These rules are MANDATORY.', - 'Completion Gate': 'Do NOT leave this skill until ALL items are complete.', - 'Next Steps': 'Once the completion gate is fully checked:', - References: 'Use these references when you need detail.', -}; function addError(message) { errors.push(message); } -function addWarning(message) { - warnings.push(message); +function isRecord(value) { + return value !== null && typeof value === 'object' && !Array.isArray(value); } -function report(path, stats = null) { - return { - path, - valid: errors.length === 0, - errors, - warnings, - stats, - }; +function parseYaml(raw, label) { + try { + const value = Bun.YAML.parse(raw); + + if (!isRecord(value)) { + addError(`Make ${label} a YAML mapping.`); + return {}; + } + + return value; + } catch (error) { + addError(`Parse ${label} as valid YAML: ${error.message}`); + return {}; + } } function parseFrontmatter(content) { const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/); - if (!match) { - addError( - 'Add YAML frontmatter with name and description at the top of SKILL.md.', - ); - return { name: null, description: null, body: content, raw: '' }; - } - - const raw = match[1]; - const name = raw.match(/^name:\s*(.+)$/m)?.[1]?.trim() || null; - const description = readDescription(raw); - - return { name, description, body: content.slice(match[0].length), raw }; -} -function readDescription(raw) { - const lines = raw.split(/\r?\n/); - const index = lines.findIndex((line) => line.startsWith('description:')); - if (index === -1) return null; - - const firstValue = lines[index].replace(/^description:\s*/, '').trim(); - if (firstValue === '|' || firstValue === '>') { - return lines - .slice(index + 1) - .filter((line) => /^\s+\S/.test(line)) - .map((line) => line.trim()) - .join(' '); + if (!match) { + addError('Add YAML frontmatter at the start of SKILL.md.'); + return { body: content, data: {}, raw: '' }; } - return firstValue || null; + return { + body: content.slice(match[0].length), + data: parseYaml(match[1], 'SKILL.md frontmatter'), + raw: match[1], + }; } -function hasMultilineDescription(raw) { - const lines = raw.split(/\r?\n/); - const index = lines.findIndex((line) => line.startsWith('description:')); - if (index === -1) return false; - const firstValue = lines[index].replace(/^description:\s*/, '').trim(); - if (firstValue === '|' || firstValue === '>') return true; - - return lines.slice(index + 1).some((line) => /^\s+\S/.test(line)); -} +function validateName(frontmatter, skillPath) { + const { name } = frontmatter; -function validateName(name, dirName) { - if (!name) { - addError( - 'Add frontmatter name and set it to the skill directory name.', - ); + if (typeof name !== 'string' || !name) { + addError('Add the skill name to frontmatter.'); return; } - if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(name)) { + + if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name)) { addError( - `Fix frontmatter name "${name}" to match ^[a-z0-9]+(-[a-z0-9]+)*$.`, + `Use lowercase letters, digits, and single hyphens for name: ${name}`, ); } + if (name.length > 64) { - addError( - `Shorten frontmatter name "${name}" to 64 characters or fewer.`, - ); + addError(`Keep name at most 64 characters; found ${name.length}.`); } - if (name !== dirName) { - addError( - `Set frontmatter name to "${dirName}" so it matches the skill directory.`, - ); + + if (name !== basename(skillPath)) { + addError(`Match name "${name}" to directory "${basename(skillPath)}".`); } } -function validateDescription(description, raw) { - if (!description) { - addError( - 'Add a one-line frontmatter description with Use when, Use for, or Use to.', - ); +function validateDescription(frontmatter, raw) { + const { description } = frontmatter; + const descriptionLine = raw + .split(/\r?\n/) + .find((line) => line.startsWith('description:')); + + if (typeof description !== 'string' || !description) { + addError('Add a one-line description to frontmatter.'); return; } - if (hasMultilineDescription(raw)) { - addError('Rewrite frontmatter description as a single YAML line.'); + + if (descriptionLine?.match(/^description:\s*[|>]/)) { + addError('Write description on one YAML line.'); } - if (description.length > 300) { + + if (description.length > 200) { addError( - `Shorten description to 300 characters or fewer. Current length: ${description.length}.`, - ); - } else if (description.length > 200) { - addWarning( - `Shorten description to 200 characters or fewer for easier skill selection. Current length: ${description.length}.`, + `Keep description at most 200 characters; found ${description.length}.`, ); } - if (!/\bUse (when|for|to)\b/.test(description)) { + + if (!/\bUse (?:when|for|to)\b/.test(description)) { addError( - 'Add Use when, Use for, or Use to to the one-line description so agents know when to load the skill.', - ); - } - if (/\b(I|me|my|mine|we|us|our|ours)\b/i.test(description)) { - addWarning( - 'Rewrite description in third person; avoid first-person wording like I, me, my, we, or our.', + 'State invocation conditions with Use when, Use for, or Use to.', ); } - if ( - !/^(Create|Build|Design|Analyze|Test|Validate|Generate|Process|Manage|Execute|Handle|Provide|Review|Write|Author|Migrate|Improve|Add|Update|Check)\b/.test( - description, - ) - ) { - addWarning( - 'Start description with a strong action verb such as Create, Validate, Review, Manage, or Execute.', + + if (/\b(?:I|me|my|mine|we|us|our|ours)\b/i.test(description)) { + addError( + 'Write description in third-person, action-oriented language.', ); } } -function validateBody(body) { - const lines = body.split(/\r?\n/); - const nonEmpty = lines - .map((line, index) => ({ line: line.trim(), index })) - .filter(({ line }) => line); - const bodyLines = nonEmpty.length; +function validateInvocation(frontmatter, openai) { + const invocation = isRecord(frontmatter.metadata) + ? frontmatter.metadata.invocation + : null; + const disableModel = frontmatter['disable-model-invocation']; + const allowImplicit = isRecord(openai.policy) + ? openai.policy.allow_implicit_invocation + : null; + + if (!['user', 'model'].includes(invocation)) { + addError('Set metadata.invocation to user or model.'); + return; + } + + const expectedDisable = invocation === 'user'; + const expectedImplicit = invocation === 'model'; - if (bodyLines > 80) { + if (disableModel !== expectedDisable) { addError( - `Move detail out of SKILL.md; body has ${bodyLines} non-empty lines and must stay at or below 80.`, - ); - } else if (bodyLines > 50) { - addWarning( - `Move detail out of SKILL.md; body has ${bodyLines} non-empty lines and should stay at or below 50.`, + `Set disable-model-invocation to ${expectedDisable} for ${invocation} invocation.`, ); } - const first = nonEmpty[0]; - if (!first || !/^#\s+\S/.test(first.line)) { + if (allowImplicit !== expectedImplicit) { addError( - 'Make the first non-empty body line an H1 title, for example: # Skill Name.', + `Set policy.allow_implicit_invocation to ${expectedImplicit} for ${invocation} invocation.`, ); } +} - const firstH2Index = lines.findIndex((line) => - /^##\s+\S/.test(line.trim()), - ); - const titleIndex = first?.index ?? -1; - const purpose = lines - .slice( - titleIndex + 1, - firstH2Index === -1 ? lines.length : firstH2Index, - ) - .map((line) => line.trim()) - .find((line) => line); - if (!purpose || purpose.startsWith('#')) { +function validateOpenaiYaml(skillPath, frontmatter) { + const openaiPath = join(skillPath, 'agents', 'openai.yaml'); + + if (!existsSync(openaiPath)) { + addError('Add agents/openai.yaml.'); + return ''; + } + + const openaiRaw = readFileSync(openaiPath, 'utf8'); + const openai = parseYaml(openaiRaw, 'agents/openai.yaml'); + const skillInterface = isRecord(openai.interface) ? openai.interface : {}; + const displayName = skillInterface.display_name; + const shortDescription = skillInterface.short_description; + + if (typeof displayName !== 'string' || !displayName) + addError('Set interface.display_name in agents/openai.yaml.'); + + if (typeof shortDescription !== 'string' || !shortDescription) { + addError('Set interface.short_description in agents/openai.yaml.'); + } else if (shortDescription.length < 25 || shortDescription.length > 64) { addError( - 'Add one non-empty, non-heading purpose line immediately after the H1 title and before the first H2.', + `Keep interface.short_description between 25 and 64 characters; found ${shortDescription.length}.`, ); } - const h2Sections = nonEmpty - .filter(({ line }) => /^##\s+\S/.test(line)) - .map(({ line, index }) => ({ - title: line.replace(/^##\s+/, '').trim(), - index, - })); - validateSections(h2Sections, lines); - - return { bodyLines, h2Sections: h2Sections.length }; + validateInvocation(frontmatter, openai); + return openai; } -function validateSections(h2Sections, lines) { - const titles = h2Sections.map(({ title }) => title); - for (const required of ['Instructions', 'References']) { - if (!titles.includes(required)) - addError(`Add required section ## ${required}.`); - } +function collectMarkdownHeadings(lines) { + const headings = []; + let fence = null; + + for (const line of lines) { + const trimmed = line.trim(); + const fenceMatch = trimmed.match(/^(`{3,}|~{3,})/); + + if (fenceMatch) { + const marker = fenceMatch[1]; + + if (fence === null) { + fence = marker; + } else if ( + marker[0] === fence[0] && + marker.length >= fence.length + ) { + fence = null; + } - let lastAllowedIndex = -1; - for (const title of titles) { - const allowedIndex = allowedSections.indexOf(title); - if (allowedIndex === -1) { - addError( - `Remove unsupported H2 section ## ${title}. Allowed H2 sections are ${allowedSections.map((section) => `## ${section}`).join(', ')}.`, - ); continue; } - if (allowedIndex < lastAllowedIndex) { - addError( - `Move ## ${title} before ## ${allowedSections[lastAllowedIndex]} to match the canonical section order.`, - ); - } else { - lastAllowedIndex = allowedIndex; + + if (fence === null && /^#{1,6}\s+\S/.test(trimmed)) { + headings.push(trimmed); } } - const final = titles[titles.length - 1]; - if (titles.includes('References') && final !== 'References') { - addError('Move ## References to the final H2 section.'); - } + return headings; +} - for (let index = 0; index < h2Sections.length; index++) { - const { title, index: lineIndex } = h2Sections[index]; - const requiredIntro = sectionIntroLines[title]; - if (!requiredIntro) continue; +function validateBody(body) { + const lines = body.split(/\r?\n/); + const headings = collectMarkdownHeadings(lines); + const firstContentIndex = lines.findIndex((line) => line.trim()); + const firstContent = lines[firstContentIndex]?.trim(); - const nextSectionIndex = h2Sections[index + 1]?.index ?? lines.length; - const firstContentLine = lines - .slice(lineIndex + 1, nextSectionIndex) - .map((line) => line.trim()) - .find((line) => line); + if (!firstContent?.match(/^#\s+\S/)) { + addError('Start the skill body with a human-readable H1.'); + return; + } - if (!firstContentLine?.startsWith(requiredIntro)) { - addError(`Start ## ${title} with: ${requiredIntro}`); - } + const h1Headings = headings.filter((line) => /^#\s+\S/.test(line)); + + if (h1Headings.length !== 1) { + addError('Add exactly one H1 heading to the skill body.'); } -} -function collectArtifacts(skillPath) { - const artifacts = []; - for (const dir of ['assets', 'references', 'scripts']) { - const dirPath = join(skillPath, dir); - if (!existsSync(dirPath)) continue; - - for (const entry of readdirSync(dirPath, { withFileTypes: true })) { - const artifactPath = `${dir}/${entry.name}`; - if (entry.isFile()) { - artifacts.push(artifactPath); - continue; - } - if (entry.isDirectory()) { - for (const nested of collectNestedFiles( - join(dirPath, entry.name), - artifactPath, - )) { - addError( - `Move nested artifact ${nested} directly under ${dir}/; nested artifact files are not allowed.`, - ); - } - } - } + const firstH2Index = lines.findIndex((line) => + /^##\s+\S/.test(line.trim()), + ); + const introEnd = firstH2Index === -1 ? lines.length : firstH2Index; + const introduction = lines + .slice(firstContentIndex + 1, introEnd) + .map((line) => line.trim()) + .find((line) => line && !line.startsWith('#')); + + if (!introduction) { + addError('Follow the H1 with a concise introductory paragraph.'); } - return artifacts; -} -function collectNestedFiles(dirPath, prefix) { - const files = []; - for (const entry of readdirSync(dirPath, { withFileTypes: true })) { - const nestedPath = `${prefix}/${entry.name}`; - if (entry.isFile()) files.push(nestedPath); - if (entry.isDirectory()) - files.push( - ...collectNestedFiles(join(dirPath, entry.name), nestedPath), - ); + const processHeadings = headings.filter((line) => line === '## Process'); + + if (processHeadings.length !== 1) { + addError('Add exactly one ## Process heading to the skill body.'); } - return files; } -function finalReferencesSection(body) { - const lines = body.split(/\r?\n/); - const start = lines.findIndex((line) => line.trim() === '## References'); - if (start === -1) return ''; +function collectFiles(directory, prefix) { + if (!existsSync(directory)) return []; + + return readdirSync(directory, { withFileTypes: true }).flatMap((entry) => { + const absolute = join(directory, entry.name); + const relativePath = `${prefix}/${entry.name}`; - const rest = lines.slice(start + 1); - const nextH2 = rest.findIndex((line) => /^##\s+\S/.test(line.trim())); - return (nextH2 === -1 ? rest : rest.slice(0, nextH2)).join('\n'); + return entry.isDirectory() + ? collectFiles(absolute, relativePath) + : [relativePath]; + }); } -function validateArtifacts(skillPath, body) { - const artifacts = collectArtifacts(skillPath); +function validateResources(skillPath, body) { + const resources = ['references', 'assets', 'scripts'].flatMap((directory) => + collectFiles(join(skillPath, directory), directory), + ); const linked = new Set(); - const references = finalReferencesSection(body); - const artifactLink = - /\[(assets|references|scripts)\/[^\]]+\]\((assets|references|scripts)\/[^)]+\)/; + const linkPattern = /\[[^\]]*\]\(([^)]+)\)/g; - for (const rawLine of references.split(/\r?\n/)) { - const line = rawLine.trimStart(); - if (!artifactLink.test(line)) continue; + for (const match of body.matchAll(linkPattern)) { + const rawTarget = match[1].split('#')[0]; + const target = rawTarget.startsWith('./') + ? rawTarget.slice(2) + : rawTarget; + const normalized = target.split('/').join(sep); - const match = line.match( - /^- \[((?:assets|references|scripts)\/[^\]]+)\]\(((?:assets|references|scripts)\/[^)]+)\) - (.*)$/, - ); - const emptyDescriptionMatch = line.match( - /^- \[((?:assets|references|scripts)\/[^\]]+)\]\(((?:assets|references|scripts)\/[^)]+)\) -\s*$/, - ); - const text = match?.[1]; - const href = match?.[2]; - const description = match?.[3]?.trim(); - const path = href ?? text; - - if ( - !match && - emptyDescriptionMatch?.[1] === emptyDescriptionMatch?.[2] - ) { - linked.add(emptyDescriptionMatch[2]); - addError( - `Add a short description after " - " for artifact reference ${emptyDescriptionMatch[2]}.`, - ); - if (!existsSync(join(skillPath, emptyDescriptionMatch[2]))) { - addError( - `Create linked artifact ${emptyDescriptionMatch[2]} or remove its References bullet.`, - ); - } - continue; - } + if (!/^(?:references|assets|scripts)\//.test(target)) continue; - if (!match || text !== href) { - const expected = text ?? path ?? 'artifact/path'; - addError( - `Reference artifact ${expected} with matching text and href: - [${expected}](${expected}) - short description.`, - ); - continue; - } - - linked.add(href); - if (!description) { - addError( - `Add a short description after " - " for artifact reference ${href}.`, - ); - } - if (!existsSync(join(skillPath, href))) { - addError( - `Create linked artifact ${href} or remove its References bullet.`, - ); + linked.add(target); + if (!existsSync(join(skillPath, normalized))) { + addError(`Create linked resource ${target} or update its pointer.`); } } - for (const artifact of artifacts) { - if (!linked.has(artifact)) { + for (const resource of resources) { + if (!linked.has(resource)) { addError( - `Link artifact ${artifact} from the final ## References section.`, + `Link ${resource} beside the step or branch that uses it.`, ); } } - return artifacts.length; + return resources.length; } function validateSkill(skillPath) { if (!existsSync(skillPath)) { - addError( - `Create the skill directory or fix the path; not found: ${skillPath}`, - ); + addError(`Provide an existing skill directory: ${skillPath}`); return null; } + if (!statSync(skillPath).isDirectory()) { - addError(`Provide a skill directory, not a file: ${skillPath}`); + addError(`Provide a skill directory: ${skillPath}`); return null; } - const skillMdPath = join(skillPath, 'SKILL.md'); - if (!existsSync(skillMdPath)) { + const skillFile = join(skillPath, 'SKILL.md'); + if (!existsSync(skillFile)) { addError('Add SKILL.md to the skill directory.'); return null; } - const content = readFileSync(skillMdPath, 'utf8'); - const { name, description, body, raw } = parseFrontmatter(content); - validateName(name, basename(skillPath)); - validateDescription(description, raw); - const bodyStats = validateBody(body); - const artifacts = validateArtifacts(skillPath, body); + const content = readFileSync(skillFile, 'utf8'); + const { body, data, raw } = parseFrontmatter(content); - return { ...bodyStats, artifacts }; -} + validateName(data, skillPath); + validateDescription(data, raw); + validateOpenaiYaml(skillPath, data); + validateBody(body); + const resourceCount = validateResources(skillPath, body); -let targetArg = null; -for (const arg of args) { - if (arg.startsWith('--')) { - addError( - `Unsupported option ${arg}. Provide only a skill directory path.`, - ); - } else if (targetArg) { - addError('Provide only one skill directory path.'); - } else { - targetArg = arg; - } + return { + resources: resourceCount, + }; } -if (!targetArg && errors.length === 0) { - addError( - 'Provide a skill directory path: bun validate-skill.js <skill-path>', - ); +const cliArguments = process.argv.slice(2); +let target = null; + +if (cliArguments.length !== 1 || cliArguments[0].startsWith('--')) { + addError('Run bun validate-skill.js <skill-directory>.'); +} else { + target = resolve(cliArguments[0]); } -const targetPath = targetArg ? resolve(targetArg) : null; -const stats = - targetPath && errors.length === 0 ? validateSkill(targetPath) : null; -const displayPath = targetPath - ? relative(process.cwd(), targetPath) || targetPath - : null; -const output = report(displayPath, stats); +const stats = target ? validateSkill(target) : null; +const result = { + path: target ? relative(process.cwd(), target) || '.' : null, + valid: errors.length === 0, + errors, + warnings, + stats, +}; -console.log(JSON.stringify(output, null, 2)); -process.exit(output.valid ? 0 : 1); +console.log(JSON.stringify(result, null, 2)); +process.exitCode = result.valid ? 0 : 1; diff --git a/tests/codex-hook.test.js b/tests/codex-hook.test.js deleted file mode 100644 index a2cbad0..0000000 --- a/tests/codex-hook.test.js +++ /dev/null @@ -1,111 +0,0 @@ -import { describe, expect, test } from 'bun:test'; -import { readFile } from 'node:fs/promises'; - -import { - PROPULSION_BOOTSTRAP_GUIDANCE, - getPropulsionBootstrapGuidance, -} from '../lib/bootstrap-guidance.js'; - -async function readJson(path) { - return JSON.parse(await readFile(path, 'utf8')); -} - -async function runConfiguredHook(env) { - const config = await readJson('hooks/hooks.json'); - const command = config.hooks.SessionStart[0].hooks[0].command; - - const result = Bun.spawnSync({ - cmd: ['sh', '-c', command], - cwd: '/private/tmp', - env: { - ...process.env, - ...env, - }, - stdout: 'pipe', - stderr: 'pipe', - }); - - expect(result.exitCode).toBe(0); - - const output = new TextDecoder().decode(result.stdout).trim(); - return JSON.parse(output); -} - -describe('Codex Propulsion bootstrap guidance', () => { - test('uses the shared Propulsion bootstrap contract', () => { - expect(getPropulsionBootstrapGuidance()).toBe( - PROPULSION_BOOTSTRAP_GUIDANCE, - ); - }); - - test('registers a plugin-root session-start hook matcher', async () => { - const config = await readJson('hooks/hooks.json'); - - expect(config.hooks.SessionStart).toEqual([ - { - matcher: 'startup|clear|compact|resume', - hooks: [ - { - type: 'command', - command: - '"${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-}}/hooks/run-hook.cmd" session-start', - timeout: 10, - statusMessage: 'Loading Propulsion workflow', - }, - ], - }, - ]); - }); - - test('runs configured hook command with CODEX_PLUGIN_ROOT', async () => { - const payload = await runConfiguredHook({ - CODEX_PLUGIN_ROOT: process.cwd(), - }); - - expect(payload.hookSpecificOutput).toEqual({ - hookEventName: 'SessionStart', - additionalContext: PROPULSION_BOOTSTRAP_GUIDANCE, - }); - }); - - test('runs configured hook command with CLAUDE_PLUGIN_ROOT fallback', async () => { - const payload = await runConfiguredHook({ - CODEX_PLUGIN_ROOT: '', - CLAUDE_PLUGIN_ROOT: process.cwd(), - }); - - expect(payload.hookSpecificOutput).toEqual({ - hookEventName: 'SessionStart', - additionalContext: PROPULSION_BOOTSTRAP_GUIDANCE, - }); - }); - - test('prints Codex SessionStart additional context as parseable JSON', async () => { - const result = Bun.spawnSync({ - cmd: ['./hooks/run-hook.cmd', 'session-start'], - stdout: 'pipe', - stderr: 'pipe', - }); - - expect(result.exitCode).toBe(0); - - const output = new TextDecoder().decode(result.stdout).trim(); - const payload = JSON.parse(output); - - expect(payload).toEqual({ - hookSpecificOutput: { - hookEventName: 'SessionStart', - additionalContext: PROPULSION_BOOTSTRAP_GUIDANCE, - }, - }); - expect(payload.hookSpecificOutput.additionalContext).toContain( - '<EXTREMELY_IMPORTANT>', - ); - expect(payload.hookSpecificOutput.additionalContext).toContain( - 'Propulsion workflow entry point: load and follow the propulsion skill when the request is software work.', - ); - expect(payload.hookSpecificOutput.additionalContext).toContain( - 'Route software work through Propulsion before downstream stages.', - ); - }); -}); diff --git a/tests/opencode-plugin.test.js b/tests/opencode-plugin.test.js deleted file mode 100644 index ed195d4..0000000 --- a/tests/opencode-plugin.test.js +++ /dev/null @@ -1,117 +0,0 @@ -import { describe, expect, test } from 'bun:test'; -import { readFile } from 'node:fs/promises'; -import { dirname, join } from 'node:path'; -import { fileURLToPath } from 'node:url'; - -import { getPropulsionBootstrapGuidance } from '../lib/bootstrap-guidance.js'; - -describe('OpenCode Propulsion bootstrap guidance', () => { - test('exposes the root package entry for OpenCode package loading', async () => { - const manifest = JSON.parse(await readFile('package.json', 'utf8')); - const rootExports = await import('../index.mjs'); - - expect(manifest.main).toBe('./index.mjs'); - expect(manifest.exports).toBe('./index.mjs'); - expect( - Object.values(rootExports).every( - (value) => - typeof value === 'function' || - (typeof value === 'object' && - value !== null && - typeof value.server === 'function'), - ), - ).toBe(true); - }); - - test('registers bundled skills with OpenCode config', async () => { - const pluginPackage = (await import('../index.mjs')).default; - const PropulsionPlugin = pluginPackage.server; - const hooks = await PropulsionPlugin({}); - const config = {}; - const skillsDir = join( - dirname(fileURLToPath(import.meta.url)), - '..', - 'skills', - ); - - expect(hooks).toEqual( - expect.objectContaining({ - config: expect.any(Function), - }), - ); - - await hooks.config(config); - await hooks.config(config); - - expect(config.skills.paths).toEqual([skillsDir]); - await expect( - readFile(join(skillsDir, 'debug', 'SKILL.md'), 'utf8'), - ).resolves.toContain('# Debug'); - }); - - test('provides high-priority Propulsion routing guidance', () => { - const guidance = getPropulsionBootstrapGuidance(); - - expect(guidance).toContain('<EXTREMELY_IMPORTANT>'); - expect(guidance).toContain('</EXTREMELY_IMPORTANT>'); - expect(guidance).toContain('propulsion'); - expect(guidance).toContain( - 'Route software work through Propulsion before downstream stages.', - ); - expect(guidance).toContain( - 'Route software-work requests into the right Propulsion entry stage before any other action.', - ); - }); - - test('registers an OpenCode messages transform that injects Propulsion guidance into the first user message', async () => { - const pluginPackage = (await import('../index.mjs')).default; - const PropulsionPlugin = pluginPackage.server; - const hooks = await PropulsionPlugin({}); - const userPart = { - id: 'part-user', - type: 'text', - text: 'Build the thing', - }; - const output = { - system: ['existing system prompt'], - messages: [ - { - info: { role: 'assistant' }, - parts: [ - { - id: 'part-assistant', - type: 'text', - text: 'Ready', - }, - ], - }, - { - info: { role: 'user' }, - parts: [userPart], - }, - ], - }; - - expect(hooks).toEqual( - expect.objectContaining({ - 'experimental.chat.messages.transform': expect.any(Function), - }), - ); - expect(hooks).not.toHaveProperty('experimental.chat.system.transform'); - - await hooks['experimental.chat.messages.transform']({}, output); - await hooks['experimental.chat.messages.transform']({}, output); - - expect(output.system).toEqual(['existing system prompt']); - expect(output.messages).toHaveLength(2); - expect(output.messages[0].info.role).toBe('assistant'); - expect(output.messages[1].parts).toEqual([ - { - ...userPart, - type: 'text', - text: getPropulsionBootstrapGuidance(), - }, - userPart, - ]); - }); -}); diff --git a/tests/write-skill-validator.test.js b/tests/write-skill-validator.test.js deleted file mode 100644 index 257bd32..0000000 --- a/tests/write-skill-validator.test.js +++ /dev/null @@ -1,513 +0,0 @@ -import { describe, expect, test } from 'bun:test'; -import { spawnSync } from 'node:child_process'; -import { - existsSync, - mkdirSync, - mkdtempSync, - readdirSync, - writeFileSync, -} from 'node:fs'; -import { tmpdir } from 'node:os'; -import { join } from 'node:path'; - -const repoRoot = join(import.meta.dir, '..'); -const validatorPath = join( - repoRoot, - 'skills/write-skill/scripts/validate-skill.js', -); -const shippedSkillsPath = join(repoRoot, 'skills'); - -function runValidator(args = []) { - const result = spawnSync('bun', [validatorPath, ...args], { - cwd: repoRoot, - encoding: 'utf8', - }); - - return { - ...result, - report: JSON.parse(result.stdout), - }; -} - -function shippedSkillPaths() { - return readdirSync(shippedSkillsPath, { withFileTypes: true }) - .filter((entry) => entry.isDirectory()) - .map((entry) => `skills/${entry.name}`) - .toSorted(); -} - -function validatorOutput(result) { - const details = []; - - if (result.stdout.trim()) { - details.push(`stdout:\n${result.stdout.trim()}`); - } - - if (result.stderr.trim()) { - details.push(`stderr:\n${result.stderr.trim()}`); - } - - return details.join('\n\n') || 'Validator produced no stdout or stderr.'; -} - -function validSkillMd(overrides = {}) { - const name = overrides.name ?? 'good-skill'; - const description = - overrides.description ?? - 'Validate reusable workflow skills. Use when checking authored skill structure.'; - const sections = - overrides.sections ?? - `## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Validate the skill. - -## References - -Use these references when you need detail. -`; - - return `--- -name: ${name} -description: ${description} ---- - -# ${overrides.title ?? 'Good Skill'} - -${overrides.purpose ?? 'Validate reusable skill structure before handoff.'} - -${sections}`; -} - -function createSkill(name, skillMd = validSkillMd({ name }), files = {}) { - const root = mkdtempSync(join(tmpdir(), 'writing-skill-validator-')); - const skillPath = join(root, name); - mkdirSync(skillPath); - writeFileSync(join(skillPath, 'SKILL.md'), skillMd); - - for (const [filePath, content] of Object.entries(files)) { - const parts = filePath.split('/'); - parts.pop(); - if (parts.length > 0) { - mkdirSync(join(skillPath, ...parts), { recursive: true }); - } - writeFileSync(join(skillPath, filePath), content); - } - - return skillPath; -} - -describe('write-skill validator', () => { - test('ships a standalone JavaScript validator', () => { - expect(existsSync(validatorPath)).toBe(true); - }); - - test('requires a skill path and always outputs JSON', () => { - const result = runValidator(); - - expect(result.status).toBe(1); - expect(result.report).toMatchObject({ - path: null, - valid: false, - warnings: [], - stats: null, - }); - expect(result.report.errors).toContain( - 'Provide a skill directory path: bun validate-skill.js <skill-path>', - ); - }); - - test('accepts the write-skill skill as JSON', () => { - const result = runValidator(['skills/write-skill']); - - expect(result.status).toBe(0); - expect(result.report.valid).toBe(true); - expect(result.report).toEqual({ - path: 'skills/write-skill', - valid: true, - errors: [], - warnings: [], - stats: expect.objectContaining({ - bodyLines: expect.any(Number), - artifacts: expect.any(Number), - }), - }); - }); - - test('validates every shipped skill', () => { - const skillPaths = shippedSkillPaths(); - - expect(skillPaths.length).toBeGreaterThan(0); - - for (const skillPath of skillPaths) { - const result = runValidator([skillPath]); - - if (result.status !== 0) { - throw new Error( - `Validator failed for ${skillPath}.\n\n${validatorOutput(result)}`, - ); - } - } - }); - - test('rejects unknown flags instead of supporting legacy options', () => { - const result = runValidator(['--unknown']); - - expect(result.status).toBe(1); - expect(result.report.errors).toContain( - 'Unsupported option --unknown. Provide only a skill directory path.', - ); - }); - - test('validates name requirements', () => { - const longName = `Bad-${'x'.repeat(65)}`; - const skillPath = createSkill( - 'expected-name', - validSkillMd({ name: longName }), - ); - - const result = runValidator([skillPath]); - - expect(result.status).toBe(1); - expect(result.report.errors).toContain( - `Fix frontmatter name "${longName}" to match ^[a-z0-9]+(-[a-z0-9]+)*$.`, - ); - expect(result.report.errors).toContain( - `Shorten frontmatter name "${longName}" to 64 characters or fewer.`, - ); - expect(result.report.errors).toContain( - 'Set frontmatter name to "expected-name" so it matches the skill directory.', - ); - }); - - test('validates description requirements and warnings', () => { - const longFirstPersonDescription = - 'I help agents with reusable skill review language that is intentionally long enough to cross the warning threshold while still remaining under the hard maximum for metadata checks. '.padEnd( - 220, - 'x', - ); - const skillPath = createSkill( - 'description-skill', - validSkillMd({ - name: 'description-skill', - description: longFirstPersonDescription, - }), - ); - - const result = runValidator([skillPath]); - - expect(result.status).toBe(1); - expect(result.report.errors).toContain( - 'Add Use when, Use for, or Use to to the one-line description so agents know when to load the skill.', - ); - expect(result.report.warnings).toContain( - 'Shorten description to 200 characters or fewer for easier skill selection. Current length: 220.', - ); - expect(result.report.warnings).toContain( - 'Rewrite description in third person; avoid first-person wording like I, me, my, we, or our.', - ); - expect(result.report.warnings).toContain( - 'Start description with a strong action verb such as Create, Validate, Review, Manage, or Execute.', - ); - }); - - test('errors when description is missing', () => { - const skillPath = createSkill( - 'missing-description', - `--- -name: missing-description ---- - -# Missing Description - -Validate missing description metadata before handoff. - -## Instructions - -1. Validate descriptions. - -## References -`, - ); - - const result = runValidator([skillPath]); - - expect(result.status).toBe(1); - expect(result.report.errors).toContain( - 'Add a one-line frontmatter description with Use when, Use for, or Use to.', - ); - }); - - test('errors when description is multiline or over 300 chars', () => { - const skillPath = createSkill( - 'description-errors', - `--- -name: description-errors -description: | - ${'Validate metadata. Use when checking descriptions.'.padEnd(301, 'x')} ---- - -# Description Errors - -Validate description metadata before handoff. - -## Instructions - -1. Validate descriptions. - -## References -`, - ); - - const result = runValidator([skillPath]); - - expect(result.status).toBe(1); - expect(result.report.errors).toContain( - 'Rewrite frontmatter description as a single YAML line.', - ); - expect(result.report.errors).toContain( - 'Shorten description to 300 characters or fewer. Current length: 301.', - ); - }); - - test('validates title, purpose, required sections, heading order, and final references', () => { - const skillPath = createSkill( - 'bad-body', - `--- -name: bad-body -description: Validate skill body structure. Use when checking headings and purpose. ---- - -Intro before title. - -## References - -## Rules - -## Extra -`, - ); - - const result = runValidator([skillPath]); - - expect(result.status).toBe(1); - expect(result.report.errors).toContain( - 'Make the first non-empty body line an H1 title, for example: # Skill Name.', - ); - expect(result.report.errors).toContain( - 'Add one non-empty, non-heading purpose line immediately after the H1 title and before the first H2.', - ); - expect(result.report.errors).toContain( - 'Add required section ## Instructions.', - ); - expect(result.report.errors).toContain( - 'Remove unsupported H2 section ## Extra. Allowed H2 sections are ## Prerequisites, ## Instructions, ## Rules, ## Completion Gate, ## Next Steps, ## References.', - ); - expect(result.report.errors).toContain( - 'Move ## Rules before ## References to match the canonical section order.', - ); - expect(result.report.errors).toContain( - 'Move ## References to the final H2 section.', - ); - }); - - test('errors when included canonical sections do not start with required intro lines', () => { - const skillPath = createSkill( - 'bad-intros', - validSkillMd({ - name: 'bad-intros', - sections: `## Prerequisites - -## Instructions - -Start with another instruction explanation. - -1. Validate intros. - -## Rules - -Start with another rules explanation. - -- MUST validate intros. - -## Completion Gate - -Start with another completion explanation. - -- [ ] Intros were validated. - -## Next Steps - -Start with another next step explanation. - -- Continue after validation. - -## References - -Start with another reference explanation. -`, - }), - ); - - const result = runValidator([skillPath]); - - expect(result.status).toBe(1); - expect(result.report.errors).toContain( - 'Start ## Prerequisites with: ALL prerequisites MUST be satisfied BEFORE following this skill.', - ); - expect(result.report.errors).toContain( - 'Start ## Instructions with: Follow these steps IN ORDER. Do NOT skip steps.', - ); - expect(result.report.errors).toContain( - 'Start ## Rules with: These rules are MANDATORY.', - ); - expect(result.report.errors).toContain( - 'Start ## Completion Gate with: Do NOT leave this skill until ALL items are complete.', - ); - expect(result.report.errors).toContain( - 'Start ## Next Steps with: Once the completion gate is fully checked:', - ); - expect(result.report.errors).toContain( - 'Start ## References with: Use these references when you need detail.', - ); - }); - - test('allows extra text after required intro lines and checks only present sections', () => { - const skillPath = createSkill( - 'extra-intro-text', - validSkillMd({ - name: 'extra-intro-text', - sections: `## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. Extra same-line guidance is allowed. - -1. Validate intros. - -## References - -Use these references when you need detail. Extra same-line guidance is allowed. -`, - }), - ); - - const result = runValidator([skillPath]); - - expect(result.status).toBe(0); - expect(result.report.valid).toBe(true); - expect(result.report.errors).toEqual([]); - }); - - test('warns over 50 body lines and exits 0 when only warnings exist', () => { - const bodyLines = Array.from( - { length: 44 }, - (_, index) => `Extra body line ${index + 1}`, - ).join('\n'); - const skillPath = createSkill( - 'warning-skill', - validSkillMd({ - name: 'warning-skill', - sections: `## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Validate warnings. - -${bodyLines} - -## References - -Use these references when you need detail. -`, - }), - ); - - const result = runValidator([skillPath]); - - expect(result.status).toBe(0); - expect(result.report.valid).toBe(true); - expect(result.report.warnings).toContain( - 'Move detail out of SKILL.md; body has 51 non-empty lines and should stay at or below 50.', - ); - }); - - test('errors over 80 body lines', () => { - const bodyLines = Array.from( - { length: 74 }, - (_, index) => `Extra body line ${index + 1}`, - ).join('\n'); - const skillPath = createSkill( - 'long-skill', - validSkillMd({ - name: 'long-skill', - sections: `## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Validate length. - -${bodyLines} - -## References - -Use these references when you need detail. -`, - }), - ); - - const result = runValidator([skillPath]); - - expect(result.status).toBe(1); - expect(result.report.errors).toContain( - 'Move detail out of SKILL.md; body has 81 non-empty lines and must stay at or below 80.', - ); - }); - - test('validates artifact placement and final references bullets', () => { - const skillPath = createSkill( - 'artifact-checks', - validSkillMd({ - name: 'artifact-checks', - sections: `## Instructions - -Follow these steps IN ORDER. Do NOT skip steps. - -1. Use [ignored outside references](assets/linked-outside.md). - -## References - -Use these references when you need detail. - -- [assets/template.md](assets/wrong.md) - Template file. -- [references/missing.md](references/missing.md) - Missing file. -- [scripts/helper.js](scripts/helper.js) - -`, - }), - { - 'assets/linked-outside.md': 'outside link only', - 'assets/template.md': 'template', - 'references/nested/example.md': 'nested', - 'scripts/helper.js': 'helper', - }, - ); - - const result = runValidator([skillPath]); - - expect(result.status).toBe(1); - expect(result.report.errors).toContain( - 'Move nested artifact references/nested/example.md directly under references/; nested artifact files are not allowed.', - ); - expect(result.report.errors).toContain( - 'Reference artifact assets/template.md with matching text and href: - [assets/template.md](assets/template.md) - short description.', - ); - expect(result.report.errors).toContain( - 'Create linked artifact references/missing.md or remove its References bullet.', - ); - expect(result.report.errors).toContain( - 'Add a short description after " - " for artifact reference scripts/helper.js.', - ); - expect(result.report.errors).toContain( - 'Link artifact assets/linked-outside.md from the final ## References section.', - ); - }); -});