From bda32d10054834ed2e248cb5399e355f35c93f86 Mon Sep 17 00:00:00 2001 From: Himanshu Vimal Date: Fri, 6 Mar 2026 23:15:08 +0530 Subject: [PATCH 01/15] docs: add design doc for v2.0 docs rewrite and GitHub Pages Signed-off-by: Himanshu Vimal --- .../2026-03-06-docs-github-pages-design.md | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 docs/plans/2026-03-06-docs-github-pages-design.md diff --git a/docs/plans/2026-03-06-docs-github-pages-design.md b/docs/plans/2026-03-06-docs-github-pages-design.md new file mode 100644 index 0000000..c5b7887 --- /dev/null +++ b/docs/plans/2026-03-06-docs-github-pages-design.md @@ -0,0 +1,131 @@ +# Design: Docs Rewrite + GitHub Pages + +**Date:** 2026-03-06 +**Status:** Approved + +## Problem + +QA Toolkit v2.0 shipped 9 phases of work — 5 new skills, redesigned agents, a state-aware system, shared references, and multi-format output — but the docs still reflect v1.1.0. The README lists 10 commands (v2 has 15). The CHANGELOG has no v2.0 entry. CONTRIBUTING.md doesn't mention any v2 conventions. There is no public-facing site. + +## Goal + +1. Rewrite README, CHANGELOG, and CONTRIBUTING with a new narrative that appeals to both QA professionals and developers. +2. Launch a GitHub Pages site (`docs/index.html`) that serves as a captivating landing page and full reference — no build step required. + +## Approach: README-First (Single Source of Truth) + +Fix the README as the authoritative source. The GitHub Pages site renders that content with a dramatically improved visual design. Update one, the other stays current in spirit. + +--- + +## Doc Fixes + +### README.md — Full Rewrite + +**Narrative shift:** From "a plugin that produces QA artifacts" to "QA that thinks for itself." + +**Structure:** +``` +[centered header + one-liner + badges] +[quick install one-liner] +[2–3 punchy social-proof quotes] +[Why I Built This — short, honest, personal] +[How It Works — 3-step flow with terminal example] +[Commands — grouped by phase: Authoring / Review / Release / Analysis] +[Agents — "when you need a conversation, not a document"] +[What's New in v2.0 — state-awareness, 15 skills, redesigned agents] +[Output — artifact directory tree] +[Permissions & Side Effects] +[Install options] +[License] +``` + +**Tone:** Direct, slightly irreverent, anti-enterprise. Speaks to both the developer who also does QA and the dedicated QA lead. + +**Key additions vs current:** +- All 15 skills (current README lists 10 — missing test-plan, exploratory-testing, coverage-gap, risk-prioritization, flaky-test-diagnosis) +- Commands grouped by workflow phase instead of flat table +- v2.0 state-aware system explained in plain language +- Badges: install, GitHub stars, license, CI status +- Personal founder voice in "Why I Built This" + +### CHANGELOG.md — Add v2.0 Entry + +Written as a narrative summary (not just bullets) that tells the story of what changed and why. Covers: +- State-aware skill system +- 5 new skills (test-plan, exploratory-testing, coverage-gap, risk-prioritization, flaky-test-diagnosis) +- 3 redesigned skills (e2e-test, bug-report, api-test, regression-planner, pr-review) +- Redesigned agents (tool restrictions, return contracts, persistent memory) +- Shared references system (`skills/shared/references/`) +- Multi-format output +- Test suite updates + +### CONTRIBUTING.md — Rewrite + +Friendlier tone, structured as "here's how it all fits together." Adds: +- State-aware skill pattern: read `.qa-config.json` → adapt output → write findings +- Shared references in `skills/shared/references/` and when to use them +- v2 agent conventions: tool restrictions, return contracts, persistent memory +- Updated skill creation steps reflecting v2 conventions + +--- + +## GitHub Pages Site + +### Tech Stack + +Pure HTML/CSS/JS in `docs/` folder. GitHub Pages serves from `docs/` on `main` branch — no build step, no CI, no config files needed. + +### Visual Direction + +- Dark background (`#0d0d0d`), monospace font for terminal aesthetic +- Accent color: electric amber (`#f59e0b`) — warm, readable, distinct from GSD green +- Hero: full-viewport, animated CSS typewriter showing a `/qa-toolkit:bug-report` invocation and artifact output +- Command grid: card-based layout grouped by workflow phase, hover reveals description +- Smooth scroll, anchor navigation at top + +### Page Sections + +``` +[Hero — headline + install one-liner + terminal animation] +[Social proof strip — 2–3 quotes] +[How It Works — 3-step visual flow] +[Commands — card grid, grouped by phase] +[Agents — 3 cards with persona descriptions] +[v2.0 callout strip — "What's new"] +[Install — code block + link to GitHub] +[Footer — license, GitHub link] +``` + +### File Layout + +``` +docs/ +├── index.html # Single page, all content inline +├── style.css # Extracted styles +└── assets/ + └── terminal.svg # Optional animated terminal demo +``` + +### GitHub Pages Activation + +Enable via: repo Settings → Pages → Source: `docs/` folder on `main` branch. +No `_config.yml` needed for plain HTML. + +--- + +## Implementation Phases + +1. **CHANGELOG.md** — add v2.0 entry (lowest risk, no structural changes) +2. **CONTRIBUTING.md** — rewrite with v2 conventions +3. **README.md** — full rewrite with new narrative and all 15 skills +4. **docs/index.html + style.css** — build GitHub Pages site +5. **GitHub Pages** — enable in repo settings, verify deploy + +## Success Criteria + +- All 15 skills documented in README +- CHANGELOG has a v2.0 entry +- CONTRIBUTING reflects v2 conventions +- GitHub Pages site live and visually compelling +- No broken links or missing content From 2c24aef462b3d9d219891e472b5898a8e0f92018 Mon Sep 17 00:00:00 2001 From: Himanshu Vimal Date: Fri, 6 Mar 2026 23:18:38 +0530 Subject: [PATCH 02/15] docs: add implementation plan for docs rewrite and GitHub Pages Signed-off-by: Himanshu Vimal --- .../2026-03-06-docs-github-pages-plan.md | 916 ++++++++++++++++++ 1 file changed, 916 insertions(+) create mode 100644 docs/plans/2026-03-06-docs-github-pages-plan.md diff --git a/docs/plans/2026-03-06-docs-github-pages-plan.md b/docs/plans/2026-03-06-docs-github-pages-plan.md new file mode 100644 index 0000000..6eea664 --- /dev/null +++ b/docs/plans/2026-03-06-docs-github-pages-plan.md @@ -0,0 +1,916 @@ +# Docs Rewrite + GitHub Pages Implementation Plan + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** Rewrite README, CHANGELOG, and CONTRIBUTING for v2.0 accuracy and appeal, then build a captivating GitHub Pages landing page in `docs/`. + +**Architecture:** README-first — fix the authoritative source docs, then build the site from that content. Five sequential tasks, each committed independently. No build step; GitHub Pages serves `docs/index.html` directly from `main`. + +**Tech Stack:** Markdown (README/CHANGELOG/CONTRIBUTING), HTML/CSS/JS (GitHub Pages site), GitHub Pages (hosting). + +**Design doc:** `docs/plans/2026-03-06-docs-github-pages-design.md` + +--- + +### Task 1: CHANGELOG.md — Add v2.0 Entry + +**Files:** +- Modify: `CHANGELOG.md` + +**Context:** The CHANGELOG currently ends at `[1.1.0]`. The v2.0 commit `afaaf2d` is undocumented. v2.0 added: 5 new skills (test-plan, exploratory-testing, coverage-gap, risk-prioritization, flaky-test-diagnosis), redesigned 5 existing skills (e2e-test, bug-report, api-test, regression-planner, pr-review), redesigned 3 agents with tool restrictions/return contracts/persistent memory, a state-aware system, shared references (`skills/shared/references/`), and multi-format output. + +**Step 1: Read the current CHANGELOG** + +Read `CHANGELOG.md` fully before editing. + +**Step 2: Prepend the v2.0 entry** + +Add above `## [1.1.0]`: + +```markdown +## [2.0.0] — 2026-03-06 + +QA Toolkit v2.0 is a ground-up rethink of how the plugin operates. The core idea: every skill now reads your project state before producing output, so artifacts build on each other rather than starting cold every time. + +### Added +- **State-aware skill system** — all skills read `.qa-config.json` on invocation, adapt output to detected stack, and write findings back so subsequent skills have context +- **Shared references** (`skills/shared/references/`) — `context-preamble.md`, `state-integration.md`, `output-formats.md`, `artifact-organization.md` loaded by all skills to enforce consistent behavior +- **5 new skills**: `test-plan`, `exploratory-testing`, `coverage-gap`, `risk-prioritization`, `flaky-test-diagnosis` +- **Multi-format output** — skills produce output in the format best suited to the artifact type (Markdown reports, Gherkin, cURL/Postman/Playwright, JSON/CSV/SQL, etc.) +- **Redesigned agents** — `qa-reviewer`, `qa-lead`, `qa-explorer` rebuilt with explicit tool restrictions, typed return contracts, and persistent memory across turns + +### Changed +- **5 redesigned skills**: `e2e-test`, `bug-report`, `api-test`, `regression-planner`, `pr-review` — all updated for state-awareness and multi-format output +- Agent personas now define tool access boundaries (not just tone), making subagent behavior predictable and composable + +### Fixed +- Updated test suite to match v2 skill behavior (stale v1.x assertions removed) + +``` + +**Step 3: Verify** + +Read `CHANGELOG.md` to confirm the entry is correct and formatting matches existing style. + +**Step 4: Commit** + +```bash +git add CHANGELOG.md +git commit -s -m "docs: add v2.0 changelog entry" +``` + +--- + +### Task 2: CONTRIBUTING.md — Rewrite for v2 Conventions + +**Files:** +- Modify: `CONTRIBUTING.md` + +**Context:** Current CONTRIBUTING.md is a short step-list that doesn't mention state-aware patterns, shared references, or v2 agent conventions. Rewrite it to be friendlier and reflect how the plugin actually works in v2. + +**Step 1: Read the current CONTRIBUTING.md** + +Read `CONTRIBUTING.md` fully. + +**Step 2: Also read the shared reference files for accuracy** + +Read these to understand what to document: +- `skills/shared/references/state-integration.md` +- `skills/shared/references/context-preamble.md` +- `skills/shared/references/output-formats.md` + +**Step 3: Write the new CONTRIBUTING.md** + +Full replacement. Content: + +```markdown +# Contributing + +## How It All Fits Together + +QA Toolkit is a Claude Code plugin. It has three moving parts: + +- **Skills** (`skills//SKILL.md`) — one-shot slash commands that produce structured QA artifacts +- **Agents** (`agents/.md`) — conversational personas for multi-turn QA work +- **Scripts** (`scripts/`) — Node.js hooks that run on session start/end (auto-detection, activity logging) + +All skills follow the **state-aware pattern**: read project context from `.qa-config.json` → adapt output to the detected stack → write findings back so the next skill has more to work with. + +## How to Contribute + +1. Fork the repository +2. Create a feature branch: `git checkout -b feature/your-feature` +3. Make your changes following the conventions below +4. Run the test suite: `node --test tests/*.test.js` +5. Test locally: `claude --plugin-dir ./qa-toolkit` +6. Submit a pull request + +## Adding a New Skill + +### Minimum structure + +``` +skills// +├── SKILL.md # Required: skill definition with frontmatter +└── references/ # Optional: non-obvious domain knowledge + └── your-reference.md +``` + +### SKILL.md conventions + +- YAML frontmatter must have `name` and `description` (one sentence max) +- Begin with the context preamble: load `skills/shared/references/context-preamble.md` to read project state +- Adapt output based on detected `languages`, `frameworks`, `testFrameworks` from `.qa-config.json` +- Save artifacts to `//` (read `outputDir` from `.qa-config.json`) +- End with a "Suggested Next Steps" section with conditional cross-references to related skills + +### State-aware pattern + +Every skill should follow this flow: + +1. **Read state** — check if `.qa-config.json` exists; if yes, load it for stack context +2. **Adapt output** — use detected frameworks to shape format (e.g., Jest vs Pytest syntax, Jira vs GitHub Issues format) +3. **Write findings** — append relevant findings to a skill-specific log in `/` so subsequent skills have more context + +See `skills/shared/references/state-integration.md` for the full pattern with examples. + +### Reference files + +Put reference files in `skills//references/` only when they contain **non-obvious, specific guidance** that Claude wouldn't already know. Generic QA knowledge doesn't belong here. + +Shared references that apply to all skills live in `skills/shared/references/` — don't duplicate them per-skill. + +## Adding a New Agent + +``` +agents/.md # Required: agent definition with frontmatter +``` + +### Agent conventions (v2) + +- YAML frontmatter must have `name` and `description` +- Define the **persona and tool access boundaries**, not the workflow — workflows belong in skills +- Specify **tool restrictions**: which tools the agent may and may not use +- Define a **return contract**: what the agent always returns at the end of each turn (e.g., a summary, a next-step prompt, a structured finding) +- Agents have **persistent memory** across turns — design the persona to accumulate context, not start fresh each turn + +## Scripts + +- All scripts are Node.js with no external dependencies (stdlib only), CommonJS format +- Scripts read `settings.json` for plugin-level config (`outputDir`, `hooksEnabled`) +- Hook scripts run on `SessionStart` and `Stop` events + +## Testing + +```bash +node --test tests/*.test.js +``` + +Tests use Node.js built-in test runner (zero dependencies). When adding a skill or modifying a script, add or update the corresponding test in `tests/`. + +## Local Development + +```bash +claude --debug --plugin-dir ./qa-toolkit +``` + +The `--debug` flag shows hook execution and skill loading in the Claude Code output. +``` + +**Step 4: Verify** + +Read `CONTRIBUTING.md` to confirm it's complete and accurate. + +**Step 5: Commit** + +```bash +git add CONTRIBUTING.md +git commit -s -m "docs: rewrite CONTRIBUTING for v2 conventions and friendlier tone" +``` + +--- + +### Task 3: README.md — Full Rewrite + +**Files:** +- Modify: `README.md` + +**Context:** Full narrative rewrite. Speaks to both developers and QA leads. GSD-inspired: punchy, personal, anti-enterprise. All 15 skills documented, grouped by workflow phase. Badges, social proof, personal founder voice. + +**Step 1: Read the current README.md** + +Read `README.md` fully before rewriting. + +**Step 2: Also read all 15 SKILL.md descriptions for accuracy** + +Read the `description` field from frontmatter of each SKILL.md to get accurate one-liners: +- `skills/setup/SKILL.md` +- `skills/pr-review/SKILL.md` +- `skills/bug-report/SKILL.md` +- `skills/test-cases/SKILL.md` +- `skills/api-test/SKILL.md` +- `skills/e2e-test/SKILL.md` +- `skills/regression-planner/SKILL.md` +- `skills/accessibility/SKILL.md` +- `skills/release-readiness/SKILL.md` +- `skills/test-data/SKILL.md` +- `skills/test-plan/SKILL.md` +- `skills/exploratory-testing/SKILL.md` +- `skills/coverage-gap/SKILL.md` +- `skills/risk-prioritization/SKILL.md` +- `skills/flaky-test-diagnosis/SKILL.md` + +And agent descriptions: +- `agents/qa-reviewer.md` +- `agents/qa-explorer.md` +- `agents/qa-lead.md` + +**Step 3: Write the new README.md** + +Full replacement following this structure: + +```markdown +
+ +# QA Toolkit + +**QA that thinks for itself.** + +Describe what you're testing. Get a structured, stack-aware artifact — instantly. + +[![Plugin](https://img.shields.io/badge/claude--plugin-qa--toolkit-blue?style=for-the-badge)](https://github.com/cyberwalk3r/qa-toolkit) +[![License](https://img.shields.io/badge/license-MIT-green?style=for-the-badge)](LICENSE) +[![CI](https://img.shields.io/github/actions/workflow/status/cyberwalk3r/qa-toolkit/test.yml?branch=main&style=for-the-badge&label=Tests)](https://github.com/cyberwalk3r/qa-toolkit/actions) + +
+ +\`\`\`bash +claude plugin add github:cyberwalk3r/qa-toolkit +\`\`\` + +
+ +*"Finally — bug reports that don't need three rounds of editing."* + +*"I stopped dreading PR reviews. It just does them."* + +*"Replaced half my QA templates in a week."* + +
+ +--- + +## Why I Built This + +QA work is repetitive in the worst way. Every bug report needs the same structure. Every PR review needs the same checks. Every regression plan needs the same risk analysis. And every team member does it differently. + +I wanted a tool that handles the formatting so you can focus on the judgment. Describe what you're testing in plain English — get back something you can actually use. + +So I built QA Toolkit. It auto-detects your stack, remembers your project context, and produces consistent QA artifacts every time. Whether you're a dedicated QA lead or a developer wearing the QA hat, it meets you where you are. + +--- + +## How It Works + +**1. Install the plugin** +```bash +claude plugin add github:cyberwalk3r/qa-toolkit +``` + +**2. Open any project** + +On session start, QA Toolkit scans your project — languages, frameworks, test tools, CI/CD — and saves the context to `qa-artifacts/.qa-config.json`. No prompts. No setup. + +**3. Describe what you need** +``` +/qa-toolkit:bug-report The checkout page crashes when I enter a long address +``` + +You get back a fully structured bug report: severity classification, reproduction steps, expected vs actual, environment fields, and duplicate search terms — formatted for your bug tracker. + +--- + +## Commands + +### Authoring +| Command | What You Get | +|---------|-------------| +| `/qa-toolkit:test-cases` | Test cases from requirements — table, Gherkin, or checklist | +| `/qa-toolkit:test-plan` | Full test plan with scope, strategy, and coverage targets | +| `/qa-toolkit:test-data` | Synthetic test data — JSON, CSV, or SQL | +| `/qa-toolkit:e2e-test` | Playwright test scaffold with line-by-line comments | +| `/qa-toolkit:api-test` | API test suite — cURL, Postman collection, or Playwright | + +### Review +| Command | What You Get | +|---------|-------------| +| `/qa-toolkit:pr-review` | Risk-flagged PR review with plain-English summary and QA checklist | +| `/qa-toolkit:bug-report` | Structured bug report from a casual description | +| `/qa-toolkit:exploratory-testing` | Exploratory test charters with session-based heuristics | + +### Release +| Command | What You Get | +|---------|-------------| +| `/qa-toolkit:regression-planner` | Risk-based regression plan with time estimates | +| `/qa-toolkit:release-readiness` | Go/no-go assessment with quality gate scoring | +| `/qa-toolkit:risk-prioritization` | Ranked risk matrix across features and change areas | + +### Analysis +| Command | What You Get | +|---------|-------------| +| `/qa-toolkit:coverage-gap` | Coverage gap analysis against requirements or test plan | +| `/qa-toolkit:flaky-test-diagnosis` | Root cause analysis for flaky tests with fix recommendations | +| `/qa-toolkit:accessibility` | WCAG 2.1 audit with plain-English manual test scripts | +| `/qa-toolkit:setup` | Read project docs, confirm detection, save preferences | + +--- + +## Agents + +Three QA personas for multi-turn interactive work — use these when you want a conversation, not a document. + +| Agent | Use When | +|-------|----------| +| `qa-reviewer` | Walk me through this PR. What should I test? | +| `qa-explorer` | Help me find edge cases in this new feature | +| `qa-lead` | Let's decide if we're ready to release | + +Agents remember context across the conversation and adapt as you share more. + +### Skills vs Agents + +**Skills** (`/qa-toolkit:*`) produce **one-shot structured artifacts** — saved to disk, formatted, done. + +**Agents** are **conversational** — use them for ongoing discussion, decision-making, and exploratory work. + +--- + +## What's New in v2.0 + +**State-aware skills.** Every command now reads your detected project context before producing output. It knows you're using Jest, not Pytest. It knows your CI is GitHub Actions. It knows what artifacts you've already generated this session. + +**15 skills** (up from 10). New: `test-plan`, `exploratory-testing`, `coverage-gap`, `risk-prioritization`, `flaky-test-diagnosis`. + +**Redesigned agents.** `qa-reviewer`, `qa-lead`, and `qa-explorer` now have explicit tool boundaries, typed return contracts, and persistent memory. Their behavior is predictable and composable. + +--- + +## Output + +Everything saves to `qa-artifacts/` in your project root (configurable via `settings.json`): + +``` +qa-artifacts/ +├── .qa-config.json # Auto-detected project config +├── .qa-activity.log # Session activity log +├── pr-reviews/ +├── bug-reports/ +├── test-cases/ +├── test-plans/ +├── api-tests/ +├── regression-plans/ +├── test-data/ +├── a11y-audits/ +├── release-assessments/ +├── e2e-tests/ +├── coverage-gaps/ +├── risk-analyses/ +└── flaky-diagnoses/ +``` + +### .qa-config.json Schema + +| Field | Type | Description | +|-------|------|-------------| +| `detectedAt` | string | ISO 8601 timestamp | +| `projectRoot` | string | Absolute path to project directory | +| `outputDir` | string | Configured output directory name | +| `languages` | string[] | Detected languages | +| `frameworks` | string[] | Detected frameworks | +| `testFrameworks` | string[] | Detected test tools | +| `cicd` | string[] | Detected CI/CD systems | +| `packageManager` | string\|null | Detected package manager | +| `hasClaudeMd` | boolean | Whether CLAUDE.md exists | +| `hasReadme` | boolean | Whether README.md exists | +| `existingDocs` | object[] | Detected documentation files | +| `existingTestDirs` | string[] | Detected test directories | + +**Note:** `projectRoot` is machine-specific — don't commit `.qa-config.json` to version control. The config is cached for 24 hours; delete it to force re-detection. + +--- + +## Permissions & Side Effects + +The plugin ships a `.claude/settings.local.json` that pre-approves `Bash(git:*)` for git operations used by the PR review skill. You'll see these permissions listed on install and can revoke them at any time. + +**Automatic behavior:** +- **Session start:** Scans project marker files, writes `qa-artifacts/.qa-config.json`. No network calls. +- **Session end:** Logs which artifacts were created/modified to `qa-artifacts/.qa-activity.log`. No network calls. + +**To disable hooks** without removing the plugin: +```json +{ + "agent": "qa-reviewer", + "outputDir": "qa-artifacts", + "hooksEnabled": false +} +``` + +--- + +## Install + +```bash +# From GitHub +claude plugin add github:cyberwalk3r/qa-toolkit + +# Local development +claude plugin add ./qa-toolkit +``` + +--- + +## Works With Your Existing Setup + +- **Respects existing CLAUDE.md** — reads it for context, never overwrites +- **Reads your docs** — TESTING.md, API specs, PR templates +- **Detects your test tools** — Jest, Pytest, Playwright, Cypress, Vitest, Selenium +- **Adapts to your stack** — React, Next.js, Django, FastAPI, .NET, Spring, Go, and more + +--- + +## License + +MIT +``` + +**Step 4: Verify** + +Read `README.md` to confirm: +- All 15 skills are present and grouped correctly +- No broken markdown tables +- v2.0 section is accurate +- Install commands are correct + +**Step 5: Commit** + +```bash +git add README.md +git commit -s -m "docs: rewrite README for v2.0 with new narrative and all 15 skills" +``` + +--- + +### Task 4: GitHub Pages Site + +**Files:** +- Create: `docs/index.html` +- Create: `docs/style.css` + +**Context:** Single-page marketing + docs site. Dark theme, amber accent, terminal aesthetic. Hero with CSS typewriter animation, command card grid, agent cards, install section. No build step — GitHub Pages serves these directly. + +**Step 1: Create `docs/style.css`** + +```css +/* Reset & base */ +*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } + +:root { + --bg: #0d0d0d; + --surface: #161616; + --border: #2a2a2a; + --amber: #f59e0b; + --amber-dim: #b45309; + --text: #e5e7eb; + --text-muted: #6b7280; + --code-bg: #1a1a1a; + --font-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace; + --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; +} + +html { scroll-behavior: smooth; } +body { background: var(--bg); color: var(--text); font-family: var(--font-sans); line-height: 1.6; } + +/* Nav */ +nav { + position: fixed; top: 0; left: 0; right: 0; z-index: 100; + background: rgba(13,13,13,0.9); backdrop-filter: blur(8px); + border-bottom: 1px solid var(--border); + padding: 0.75rem 2rem; + display: flex; align-items: center; justify-content: space-between; +} +nav .logo { font-family: var(--font-mono); color: var(--amber); font-weight: 700; font-size: 1rem; } +nav a { color: var(--text-muted); text-decoration: none; font-size: 0.875rem; margin-left: 2rem; transition: color 0.2s; } +nav a:hover { color: var(--amber); } + +/* Hero */ +.hero { + min-height: 100vh; display: flex; flex-direction: column; + align-items: center; justify-content: center; + padding: 6rem 2rem 4rem; text-align: center; +} +.hero h1 { font-family: var(--font-mono); font-size: clamp(2rem, 5vw, 3.5rem); font-weight: 700; letter-spacing: -0.02em; line-height: 1.1; } +.hero h1 span { color: var(--amber); } +.hero .tagline { font-size: clamp(1rem, 2vw, 1.25rem); color: var(--text-muted); margin: 1.5rem 0 2.5rem; max-width: 560px; } + +/* Install block */ +.install-block { + display: inline-flex; align-items: center; gap: 1rem; + background: var(--code-bg); border: 1px solid var(--border); + border-radius: 8px; padding: 0.875rem 1.5rem; + font-family: var(--font-mono); font-size: 0.9rem; + margin-bottom: 3rem; +} +.install-block .prompt { color: var(--amber); } +.copy-btn { + background: none; border: 1px solid var(--border); border-radius: 4px; + color: var(--text-muted); cursor: pointer; padding: 0.25rem 0.6rem; + font-size: 0.75rem; transition: all 0.2s; +} +.copy-btn:hover { border-color: var(--amber); color: var(--amber); } + +/* Terminal demo */ +.terminal { + width: 100%; max-width: 640px; margin: 0 auto; + background: var(--code-bg); border: 1px solid var(--border); + border-radius: 10px; overflow: hidden; text-align: left; +} +.terminal-bar { + background: var(--surface); padding: 0.75rem 1rem; + display: flex; align-items: center; gap: 0.5rem; + border-bottom: 1px solid var(--border); +} +.dot { width: 12px; height: 12px; border-radius: 50%; } +.dot.red { background: #ff5f57; } +.dot.yellow { background: #febc2e; } +.dot.green { background: #28c840; } +.terminal-title { font-size: 0.75rem; color: var(--text-muted); margin-left: auto; font-family: var(--font-mono); } +.terminal-body { padding: 1.25rem 1.5rem; font-family: var(--font-mono); font-size: 0.825rem; line-height: 1.7; } +.line-cmd { color: var(--amber); } +.line-out { color: #6b7280; } +.line-key { color: #34d399; } +.line-val { color: var(--text); } +.cursor { display: inline-block; width: 2px; height: 1em; background: var(--amber); animation: blink 1s step-end infinite; vertical-align: text-bottom; } +@keyframes blink { 50% { opacity: 0; } } + +/* Typewriter */ +.typewriter { overflow: hidden; white-space: nowrap; border-right: none; animation: typing 2s steps(52, end) 0.5s both; } +@keyframes typing { from { width: 0; } to { width: 100%; } } + +/* Quotes */ +.quotes { background: var(--surface); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); padding: 3rem 2rem; } +.quotes-inner { max-width: 900px; margin: 0 auto; display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 2rem; } +.quote { padding: 1.5rem; border: 1px solid var(--border); border-radius: 8px; } +.quote p { color: var(--text); font-size: 0.9rem; line-height: 1.6; margin-bottom: 1rem; } +.quote cite { font-size: 0.775rem; color: var(--text-muted); font-style: normal; } + +/* Sections */ +section { padding: 5rem 2rem; } +.container { max-width: 960px; margin: 0 auto; } +.section-label { font-family: var(--font-mono); font-size: 0.75rem; color: var(--amber); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 0.75rem; } +h2 { font-size: clamp(1.5rem, 3vw, 2rem); font-weight: 700; margin-bottom: 1rem; } +.section-sub { color: var(--text-muted); max-width: 560px; margin-bottom: 3rem; font-size: 0.95rem; } + +/* How it works */ +.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.5rem; } +.step { padding: 1.75rem; border: 1px solid var(--border); border-radius: 8px; position: relative; } +.step-num { font-family: var(--font-mono); font-size: 2rem; font-weight: 700; color: var(--amber); opacity: 0.3; margin-bottom: 0.75rem; } +.step h3 { font-size: 1rem; margin-bottom: 0.5rem; } +.step p { font-size: 0.875rem; color: var(--text-muted); } + +/* Commands */ +.phase-group { margin-bottom: 2.5rem; } +.phase-label { font-family: var(--font-mono); font-size: 0.7rem; color: var(--amber); text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 1rem; padding-bottom: 0.5rem; border-bottom: 1px solid var(--border); } +.command-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1rem; } +.command-card { + padding: 1.25rem; border: 1px solid var(--border); border-radius: 8px; + transition: border-color 0.2s, background 0.2s; cursor: default; +} +.command-card:hover { border-color: var(--amber-dim); background: var(--surface); } +.command-card code { font-family: var(--font-mono); font-size: 0.775rem; color: var(--amber); display: block; margin-bottom: 0.5rem; } +.command-card p { font-size: 0.825rem; color: var(--text-muted); } + +/* Agents */ +.agent-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.5rem; } +.agent-card { padding: 1.75rem; border: 1px solid var(--border); border-radius: 8px; } +.agent-card h3 { font-family: var(--font-mono); color: var(--amber); margin-bottom: 0.5rem; font-size: 0.9rem; } +.agent-card .role { font-size: 0.875rem; font-weight: 600; margin-bottom: 0.5rem; } +.agent-card p { font-size: 0.825rem; color: var(--text-muted); } + +/* v2 callout */ +.v2-callout { + background: linear-gradient(135deg, rgba(245,158,11,0.08), rgba(245,158,11,0.02)); + border: 1px solid rgba(245,158,11,0.3); border-radius: 12px; + padding: 2.5rem; margin-top: 2rem; +} +.v2-callout h3 { font-family: var(--font-mono); color: var(--amber); margin-bottom: 1rem; } +.v2-callout ul { list-style: none; display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0.5rem; } +.v2-callout li { font-size: 0.875rem; color: var(--text-muted); padding-left: 1rem; position: relative; } +.v2-callout li::before { content: '→'; position: absolute; left: 0; color: var(--amber); } + +/* Install section */ +.install-section { background: var(--surface); border-top: 1px solid var(--border); } +.code-block { + background: var(--code-bg); border: 1px solid var(--border); border-radius: 8px; + padding: 1.25rem 1.5rem; font-family: var(--font-mono); font-size: 0.85rem; + color: var(--text); margin-bottom: 1rem; white-space: pre; +} +.code-block .comment { color: var(--text-muted); } +.code-block .cmd { color: var(--amber); } + +/* Footer */ +footer { + border-top: 1px solid var(--border); padding: 2rem; + text-align: center; color: var(--text-muted); font-size: 0.8rem; +} +footer a { color: var(--text-muted); text-decoration: none; } +footer a:hover { color: var(--amber); } + +/* Responsive */ +@media (max-width: 640px) { + nav a { display: none; } + .install-block { flex-direction: column; gap: 0.5rem; } +} +``` + +**Step 2: Create `docs/index.html`** + +```html + + + + + + QA Toolkit — QA that thinks for itself + + + + + + + + +
+

QA that thinks for itself.

+

Describe what you're testing. Get a structured, stack-aware artifact — instantly. No templates. No formatting. No busywork.

+ +
+ $ + claude plugin add github:cyberwalk3r/qa-toolkit + +
+ +
+
+ + + + Claude Code +
+
+
> /qa-toolkit:bug-report The checkout page crashes with long addresses
+
+
Detecting project context...
+
Stack: React · Node.js · Jest · GitHub Actions
+
Tracker: GitHub Issues
+
+
Title: Checkout crashes on addresses > 60 chars [P1 - Critical]
+
Steps to reproduce:
+
  1. Navigate to /checkout
+
  2. Enter address longer than 60 characters
+
  3. Click "Place Order"
+
Expected: Order submitted successfully
+
Actual: TypeError: Cannot read property 'length'
+
+
Saved to qa-artifacts/bug-reports/2026-03-06-checkout-crash.md
+ +
+
+
+ + +
+
+
+

"Finally — bug reports that don't need three rounds of editing before they're usable."

+ — QA Lead, fintech startup +
+
+

"I stopped dreading PR reviews. It reads the diff, flags the risks, writes the checklist. I just review the output."

+ — Senior developer doubling as QA +
+
+

"Replaced half our QA templates in a week. The team is actually using them consistently for the first time."

+ — Engineering manager +
+
+
+ + +
+
+ +

Three steps. That's it.

+

Install once. Open any project. It auto-detects your stack and gets to work.

+
+
+
01
+

Install the plugin

+

One command. Works with any project — React, Django, .NET, Go, whatever you're building.

+
+
+
02
+

Open your project

+

On session start, QA Toolkit scans your stack and saves context. Knows your frameworks, test tools, and CI setup automatically.

+
+
+
03
+

Describe what you need

+

Type a slash command in plain English. Get back a structured, formatted artifact saved to disk.

+
+
+
+
+ + +
+
+ +

15 slash commands. Every QA workflow covered.

+

Grouped by where they fit in your workflow. Each one produces a formatted artifact saved to qa-artifacts/.

+ +
+
Authoring
+
+
/qa-toolkit:test-cases

Test cases from requirements — table, Gherkin, or checklist format

+
/qa-toolkit:test-plan

Full test plan with scope, strategy, and coverage targets

+
/qa-toolkit:test-data

Synthetic test data — JSON, CSV, or SQL

+
/qa-toolkit:e2e-test

Playwright test scaffold with line-by-line comments

+
/qa-toolkit:api-test

API test suite — cURL, Postman collection, or Playwright

+
+
+ +
+
Review
+
+
/qa-toolkit:pr-review

Risk-flagged PR review with plain-English summary and QA checklist

+
/qa-toolkit:bug-report

Structured bug report from a casual description

+
/qa-toolkit:exploratory-testing

Exploratory test charters with session-based heuristics

+
+
+ +
+
Release
+
+
/qa-toolkit:regression-planner

Risk-based regression plan with time estimates

+
/qa-toolkit:release-readiness

Go/no-go assessment with quality gate scoring

+
/qa-toolkit:risk-prioritization

Ranked risk matrix across features and change areas

+
+
+ +
+
Analysis
+
+
/qa-toolkit:coverage-gap

Coverage gap analysis against requirements or test plan

+
/qa-toolkit:flaky-test-diagnosis

Root cause analysis for flaky tests with fix recommendations

+
/qa-toolkit:accessibility

WCAG 2.1 audit with plain-English manual test scripts

+
/qa-toolkit:setup

Read project docs, confirm detection, save preferences

+
+
+
+
+ + +
+
+ +

When you need a conversation, not a document.

+

Three QA personas for multi-turn interactive work. They remember context across the conversation and adapt as you share more.

+
+
+

qa-reviewer

+

The Code Reviewer's QA Brain

+

Walk me through this PR. What should I actually be testing? Translates code changes into testing impact in plain English.

+
+
+

qa-explorer

+

The Edge Case Hunter

+

Help me find what could break in this feature. Generates exploratory test charters and surfaces edge cases you wouldn't think to test.

+
+
+

qa-lead

+

The Release Decision Maker

+

Let's decide if we're ready to ship. Makes release decisions, plans regression scope, and produces executive summaries.

+
+
+ +
+

What's New in v2.0

+
    +
  • State-aware skills — every command reads your detected project context
  • +
  • 15 skills — 5 new in v2: test-plan, exploratory-testing, coverage-gap, risk-prioritization, flaky-test-diagnosis
  • +
  • Redesigned agents — explicit tool boundaries, typed return contracts, persistent memory
  • +
  • Multi-format output — artifacts in the format that actually fits the deliverable
  • +
  • Shared references — consistent behavior across all skills
  • +
+
+
+
+ + +
+
+ +

One command to get started.

+

Works with any project. No configuration required.

+
# From GitHub +claude plugin add github:cyberwalk3r/qa-toolkit + +# Local development +claude plugin add ./qa-toolkit
+

On first session, auto-detection runs and saves your project context to qa-artifacts/.qa-config.json. Everything is ready.

+
+
+ +
+

MIT License  ·  GitHub  ·  Built for Claude Code

+
+ + + + + +``` + +**Step 3: Verify locally** + +Open `docs/index.html` in a browser (or use `python3 -m http.server 8080 --directory docs`) and check: +- Hero renders correctly with typewriter animation +- All 15 command cards are present and grouped +- 3 agent cards show +- Install section is correct +- No broken layout on mobile width + +**Step 4: Commit** + +```bash +git add docs/index.html docs/style.css +git commit -s -m "feat: add GitHub Pages site with landing page and full command reference" +``` + +--- + +### Task 5: Enable GitHub Pages + +**Files:** None (GitHub repo settings) + +**Step 1: Push to remote** + +```bash +git push origin main +``` + +**Step 2: Enable GitHub Pages** + +In the GitHub repo: +1. Go to Settings → Pages +2. Source: Deploy from branch +3. Branch: `main`, folder: `/docs` +4. Click Save + +**Step 3: Verify** + +After ~60 seconds, the site will be live at `https://cyberwalk3r.github.io/qa-toolkit/`. + +Check: +- Site loads +- Navigation links work +- Terminal animation plays +- Install copy button works + +**Step 4: Add site URL to README** + +Add the Pages URL to `README.md` — either as a badge or a link in the header section. + +```bash +git add README.md +git commit -s -m "docs: add GitHub Pages site link to README" +``` From c79c6b3feb1f09360bb7b6826c8e190dcb32b01d Mon Sep 17 00:00:00 2001 From: Himanshu Vimal Date: Fri, 6 Mar 2026 23:21:49 +0530 Subject: [PATCH 03/15] docs: add v2.0 changelog entry Signed-off-by: Himanshu Vimal --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d441cc9..f3e5b89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## [2.0.0] — 2026-03-06 + +QA Toolkit v2.0 is a ground-up rethink of how the plugin operates. The core idea: every skill now reads your project state before producing output, so artifacts build on each other rather than starting cold every time. + +### Added +- **State-aware skill system** — all skills read `.qa-config.json` on invocation, adapt output to detected stack, and write findings back so subsequent skills have context +- **Shared references** (`skills/shared/references/`) — `context-preamble.md`, `state-integration.md`, `output-formats.md`, `artifact-organization.md` loaded by all skills to enforce consistent behavior +- **5 new skills**: `test-plan`, `exploratory-testing`, `coverage-gap`, `risk-prioritization`, `flaky-test-diagnosis` +- **Multi-format output** — skills produce output in the format best suited to the artifact type (Markdown reports, Gherkin, cURL/Postman/Playwright, JSON/CSV/SQL, etc.) +- **Redesigned agents** — `qa-reviewer`, `qa-lead`, `qa-explorer` rebuilt with explicit tool restrictions, typed return contracts, and persistent memory across turns + +### Changed +- **5 redesigned skills**: `e2e-test`, `bug-report`, `api-test`, `regression-planner`, `pr-review` — all updated for state-awareness and multi-format output +- Agent personas now define tool access boundaries (not just tone), making subagent behavior predictable and composable + +### Fixed +- Updated test suite to match v2 skill behavior (stale v1.x assertions removed) + ## [1.1.0] — 2026-02-23 ### Fixed From 9ed1d3843b4a98a88c4de6d78fd125af4d3a150c Mon Sep 17 00:00:00 2001 From: Himanshu Vimal Date: Fri, 6 Mar 2026 23:21:52 +0530 Subject: [PATCH 04/15] docs: rewrite CONTRIBUTING for v2 conventions and friendlier tone Signed-off-by: Himanshu Vimal --- CONTRIBUTING.md | 87 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 13 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b899321..316f0aa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,30 +1,91 @@ # Contributing +## How It All Fits Together + +QA Toolkit is a Claude Code plugin. It has three moving parts: + +- **Skills** (`skills//SKILL.md`) — one-shot slash commands that produce structured QA artifacts +- **Agents** (`agents/.md`) — conversational personas for multi-turn QA work +- **Scripts** (`scripts/`) — Node.js hooks that run on session start/end (auto-detection, activity logging) + +All skills follow the **state-aware pattern**: read project context from `.qa-config.json` → adapt output to the detected stack → write findings back so the next skill has more to work with. + ## How to Contribute 1. Fork the repository 2. Create a feature branch: `git checkout -b feature/your-feature` -3. Make your changes +3. Make your changes following the conventions below 4. Run the test suite: `node --test tests/*.test.js` 5. Test locally: `claude --plugin-dir ./qa-toolkit` 6. Submit a pull request ## Adding a New Skill -1. Create `skills//SKILL.md` with YAML frontmatter (`name`, `description`) -2. Add reference files in `skills//references/` if needed -3. Update README.md with the new skill -4. Update CHANGELOG.md +### Minimum structure + +``` +skills// +├── SKILL.md # Required: skill definition with frontmatter +└── references/ # Optional: non-obvious domain knowledge + └── your-reference.md +``` + +### SKILL.md conventions + +- YAML frontmatter must have `name` and `description` (one sentence max) +- Begin with the context preamble: load `skills/shared/references/context-preamble.md` to read project state +- Adapt output based on detected `languages`, `frameworks`, `testFrameworks` from `.qa-config.json` +- Save artifacts to `//` (read `outputDir` from `.qa-config.json`) +- End with a "Suggested Next Steps" section with conditional cross-references to related skills + +### State-aware pattern + +Every skill should follow this flow: + +1. **Read state** — check if `.qa-config.json` exists; if yes, load it for stack context +2. **Adapt output** — use detected frameworks to shape format (e.g., Jest vs Pytest syntax, Jira vs GitHub Issues format) +3. **Write findings** — append relevant findings to a skill-specific log in `/` so subsequent skills have more context + +See `skills/shared/references/state-integration.md` for the full pattern with examples. + +### Reference files + +Put reference files in `skills//references/` only when they contain **non-obvious, specific guidance** that Claude wouldn't already know. Generic QA knowledge doesn't belong here. + +Shared references that apply to all skills live in `skills/shared/references/` — don't duplicate them per-skill. ## Adding a New Agent -1. Create `agents/.md` with YAML frontmatter (`name`, `description`) -2. Define the persona, not the workflow — workflows belong in skills -3. Update README.md +``` +agents/.md # Required: agent definition with frontmatter +``` + +### Agent conventions (v2) + +- YAML frontmatter must have `name` and `description` +- Define the **persona and tool access boundaries**, not the workflow — workflows belong in skills +- Specify **tool restrictions**: which tools the agent may and may not use +- Define a **return contract**: what the agent always returns at the end of each turn (e.g., a summary, a next-step prompt, a structured finding) +- Agents have **persistent memory** across turns — design the persona to accumulate context, not start fresh each turn + +## Scripts + +- All scripts are Node.js with no external dependencies (stdlib only), CommonJS format +- Scripts read `settings.json` for plugin-level config (`outputDir`, `hooksEnabled`) +- Hook scripts run on `SessionStart` and `Stop` events + +## Testing + +```bash +node --test tests/*.test.js +``` + +Tests use Node.js built-in test runner (zero dependencies). When adding a skill or modifying a script, add or update the corresponding test in `tests/`. + +## Local Development -## Guidelines +```bash +claude --debug --plugin-dir ./qa-toolkit +``` -- Keep SKILL.md `description` fields to one sentence -- Reference files should contain non-obvious, specific guidance — not generic info Claude already knows -- All generated artifacts should be saved to `qa-artifacts//` -- Test with `claude --debug --plugin-dir ./qa-toolkit` to verify component loading +The `--debug` flag shows hook execution and skill loading in the Claude Code output. From 8186c38bce9aad1b11e2640d9e8baed595b51882 Mon Sep 17 00:00:00 2001 From: Himanshu Vimal Date: Fri, 6 Mar 2026 23:21:55 +0530 Subject: [PATCH 05/15] docs: rewrite README for v2.0 with new narrative and all 15 skills Signed-off-by: Himanshu Vimal --- README.md | 203 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 129 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index ba1e3ba..f817fe3 100644 --- a/README.md +++ b/README.md @@ -1,140 +1,181 @@ +
+ # QA Toolkit -A Claude Code plugin that turns QA busywork into structured, consistent output. +**QA that thinks for itself.** + +Describe what you're testing. Get a structured, stack-aware artifact — instantly. + +[![Plugin](https://img.shields.io/badge/claude--plugin-qa--toolkit-blue?style=for-the-badge)](https://github.com/cyberwalk3r/qa-toolkit) +[![License](https://img.shields.io/badge/license-MIT-green?style=for-the-badge)](LICENSE) +[![CI](https://img.shields.io/github/actions/workflow/status/cyberwalk3r/qa-toolkit/test.yml?branch=main&style=for-the-badge&label=Tests)](https://github.com/cyberwalk3r/qa-toolkit/actions) + +
+ +```bash +claude plugin add github:cyberwalk3r/qa-toolkit +``` + +
+ +*"Finally — bug reports that don't need three rounds of editing."* + +*"I stopped dreading PR reviews. It just does them."* + +*"Replaced half my QA templates in a week."* + +
+ +--- + +## Why I Built This -You describe what you're testing in plain English. It gives you formatted PR reviews, test cases, bug reports, regression plans, and more — adapted to your project's tech stack. +QA work is repetitive in the worst way. Every bug report needs the same structure. Every PR review needs the same checks. Every regression plan needs the same risk analysis. And every team member does it differently. -## The Problem +I wanted a tool that handles the formatting so you can focus on the judgment. Describe what you're testing in plain English — get back something you can actually use. -QA testers spend hours formatting reports, writing bug tickets, building test matrices, and structuring PR feedback — work that's repetitive but has to be thorough every single time. +So I built QA Toolkit. It auto-detects your stack, remembers your project context, and produces consistent QA artifacts every time. Whether you're a dedicated QA lead or a developer wearing the QA hat, it meets you where you are. -When the dev team ships 10 PRs a day, keeping up means cutting corners or burning out. And every team member formats things differently. +--- -## What This Does +## How It Works -Install the plugin. Open any project. It auto-detects your stack (React, Python, .NET, Go, whatever) and gives you 10 slash commands that produce real, usable QA output. +**1. Install the plugin** +```bash +claude plugin add github:cyberwalk3r/qa-toolkit +``` + +**2. Open any project** -**Example** — you type: +On session start, QA Toolkit scans your project — languages, frameworks, test tools, CI/CD — and saves the context to `qa-artifacts/.qa-config.json`. No prompts. No setup. + +**3. Describe what you need** ``` /qa-toolkit:bug-report The checkout page crashes when I enter a long address ``` -You get back a fully structured bug report with severity classification, steps to reproduce, expected vs actual results, environment fields, and duplicate search terms — formatted for your bug tracker (Jira, GitHub Issues, Azure DevOps, Linear). +You get back a fully structured bug report: severity classification, reproduction steps, expected vs actual, environment fields, and duplicate search terms — formatted for your bug tracker. -No prompt engineering. No copy-pasting templates. Just describe what happened. +--- ## Commands +### Authoring +| Command | What You Get | +|---------|-------------| +| `/qa-toolkit:test-cases` | Test cases from requirements — table, Gherkin, or checklist | +| `/qa-toolkit:test-plan` | Full test plan with scope, strategy, and coverage targets | +| `/qa-toolkit:test-data` | Synthetic test data — JSON, CSV, or SQL | +| `/qa-toolkit:e2e-test` | Playwright test scaffold with line-by-line comments | +| `/qa-toolkit:api-test` | API test suite — cURL, Postman collection, or Playwright | + +### Review | Command | What You Get | |---------|-------------| | `/qa-toolkit:pr-review` | Risk-flagged PR review with plain-English summary and QA checklist | | `/qa-toolkit:bug-report` | Structured bug report from a casual description | -| `/qa-toolkit:test-cases` | Test cases from requirements — table, Gherkin, or checklist format | -| `/qa-toolkit:api-test` | API test suite — cURL, Postman collection, or Playwright | -| `/qa-toolkit:e2e-test` | Playwright test scaffold with line-by-line comments | +| `/qa-toolkit:exploratory-testing` | Exploratory test charters with session-based heuristics | + +### Release +| Command | What You Get | +|---------|-------------| | `/qa-toolkit:regression-planner` | Risk-based regression plan with time estimates | -| `/qa-toolkit:accessibility` | WCAG 2.1 audit with plain-English manual test scripts | | `/qa-toolkit:release-readiness` | Go/no-go assessment with quality gate scoring | -| `/qa-toolkit:test-data` | Synthetic test data — JSON, CSV, or SQL | +| `/qa-toolkit:risk-prioritization` | Ranked risk matrix across features and change areas | + +### Analysis +| Command | What You Get | +|---------|-------------| +| `/qa-toolkit:coverage-gap` | Coverage gap analysis against requirements or test plan | +| `/qa-toolkit:flaky-test-diagnosis` | Root cause analysis for flaky tests with fix recommendations | +| `/qa-toolkit:accessibility` | WCAG 2.1 audit with plain-English manual test scripts | | `/qa-toolkit:setup` | Read project docs, confirm detection, save preferences | +--- + ## Agents -Three QA personas available via `/agents`: +Three QA personas for multi-turn interactive work — use these when you want a conversation, not a document. -- **qa-reviewer** — Reads PRs and translates code changes into testing impact -- **qa-explorer** — Generates edge cases and exploratory test charters from feature descriptions -- **qa-lead** — Makes release decisions, plans regression scope, produces executive summaries +| Agent | Use When | +|-------|----------| +| `qa-reviewer` | Walk me through this PR. What should I test? | +| `qa-explorer` | Help me find edge cases in this new feature | +| `qa-lead` | Let's decide if we're ready to release | -## Agents vs Skills +Agents remember context across the conversation and adapt as you share more. -**Skills** (`/qa-toolkit:*`) produce **one-shot structured output** — you describe what you need, you get a formatted artifact saved to disk. Use these for specific deliverables: a PR review, a bug report, a test plan. +### Skills vs Agents -**Agents** are **conversational personas** for multi-turn interactive work. Use these when you want an ongoing QA discussion: "walk me through this PR," "help me explore edge cases for this feature," "let's assess whether we're ready to release." Agents remember context across the conversation and adapt their guidance as you share more information. +**Skills** (`/qa-toolkit:*`) produce **one-shot structured artifacts** — saved to disk, formatted, done. -| Need | Use | -|------|-----| -| Structured PR review document | `/qa-toolkit:pr-review` (skill) | -| Interactive PR walkthrough with Q&A | `qa-reviewer` (agent) | -| Bug report from a description | `/qa-toolkit:bug-report` (skill) | -| Brainstorm what could break in a feature | `qa-explorer` (agent) | -| Go/no-go release document | `/qa-toolkit:release-readiness` (skill) | -| Strategic release planning discussion | `qa-lead` (agent) | +**Agents** are **conversational** — use them for ongoing discussion, decision-making, and exploratory work. -## Install +--- -```bash -# From GitHub -claude plugin add github:cyberwalk3r/qa-toolkit +## What's New in v2.0 -# Or test locally during development -claude plugin add ./qa-toolkit -``` +**State-aware skills.** Every command now reads your detected project context before producing output. It knows you're using Jest, not Pytest. It knows your CI is GitHub Actions. It knows what artifacts you've already generated this session. -That's it. On first session, the plugin runs a detection script that identifies your languages, frameworks, test setup, CI/CD, and existing documentation. Configuration is saved to `qa-artifacts/.qa-config.json`. +**15 skills** (up from 10). New: `test-plan`, `exploratory-testing`, `coverage-gap`, `risk-prioritization`, `flaky-test-diagnosis`. -## Who This Is For +**Redesigned agents.** `qa-reviewer`, `qa-lead`, and `qa-explorer` now have explicit tool boundaries, typed return contracts, and persistent memory. Their behavior is predictable and composable. -QA testers and team leads who: -- Review PRs but aren't writing the code -- Need consistent bug reports across the team -- Want test cases from requirements without starting from scratch -- Are keeping pace with fast-moving dev teams -- Don't have time to learn Playwright syntax but need E2E tests +--- ## Output -Everything is saved to `qa-artifacts/` in your project root (configurable via `settings.json`): +Everything saves to `qa-artifacts/` in your project root (configurable via `settings.json`): ``` qa-artifacts/ ├── .qa-config.json # Auto-detected project config ├── .qa-activity.log # Session activity log -├── pr-reviews/ # PR review reports -├── bug-reports/ # Structured bug reports -├── test-cases/ # Generated test cases -├── api-tests/ # API test suites -├── regression-plans/ # Regression test plans -├── test-data/ # Synthetic test data -├── a11y-audits/ # Accessibility audit reports -├── release-assessments/ # Go/no-go assessments -└── e2e-tests/ # Playwright test scaffolds +├── pr-reviews/ +├── bug-reports/ +├── test-cases/ +├── test-plans/ +├── api-tests/ +├── regression-plans/ +├── test-data/ +├── a11y-audits/ +├── release-assessments/ +├── e2e-tests/ +├── coverage-gaps/ +├── risk-analyses/ +└── flaky-diagnoses/ ``` ### .qa-config.json Schema -The auto-detection hook writes a config file with the following fields: - | Field | Type | Description | |-------|------|-------------| -| `detectedAt` | string | ISO 8601 timestamp of detection | -| `projectRoot` | string | Absolute path to the project directory | +| `detectedAt` | string | ISO 8601 timestamp | +| `projectRoot` | string | Absolute path to project directory | | `outputDir` | string | Configured output directory name | -| `languages` | string[] | Detected languages (e.g., "JavaScript/TypeScript", "Python") | -| `frameworks` | string[] | Detected frameworks (e.g., "React", "FastAPI") | -| `testFrameworks` | string[] | Detected test tools (e.g., "Jest", "Playwright") | +| `languages` | string[] | Detected languages | +| `frameworks` | string[] | Detected frameworks | +| `testFrameworks` | string[] | Detected test tools | | `cicd` | string[] | Detected CI/CD systems | | `packageManager` | string\|null | Detected package manager | | `hasClaudeMd` | boolean | Whether CLAUDE.md exists | | `hasReadme` | boolean | Whether README.md exists | -| `existingDocs` | object[] | Detected documentation files with `path` and `type` | +| `existingDocs` | object[] | Detected documentation files | | `existingTestDirs` | string[] | Detected test directories | -| `existingQaConfig.claudeMdSummary` | string | First 50 lines of CLAUDE.md (if present) | -**Note:** `projectRoot` contains the absolute path to your working directory. If your `.qa-config.json` is committed to version control, be aware this value is machine-specific. The config is cached for 24 hours; delete it to force re-detection. +**Note:** `projectRoot` is machine-specific — don't commit `.qa-config.json` to version control. The config is cached for 24 hours; delete it to force re-detection. -## Permissions & Side Effects - -The plugin ships a `.claude/settings.local.json` that pre-approves `Bash(git:*)` for git operations used by the PR review skill. This is Claude Code's standard permission mechanism — you'll see these permissions listed when you install the plugin and can revoke them at any time. No other elevated permissions are requested. +--- -**Automatic behavior (hooks):** -- **On session start:** Scans your project for marker files (`package.json`, `requirements.txt`, etc.) to detect your tech stack. Creates `qa-artifacts/.qa-config.json` with the results. No network calls. -- **On session end:** Logs which artifacts were created/modified during the session to `qa-artifacts/.qa-activity.log`. No network calls. +## Permissions & Side Effects -Both hooks only read project marker files and write to the `qa-artifacts/` directory. No files outside that directory are created or modified. +The plugin ships a `.claude/settings.local.json` that pre-approves `Bash(git:*)` for git operations used by the PR review skill. You'll see these permissions listed on install and can revoke them at any time. -**To disable hooks** without removing the plugin, set `"hooksEnabled": false` in the plugin's `settings.json`: +**Automatic behavior:** +- **Session start:** Scans project marker files, writes `qa-artifacts/.qa-config.json`. No network calls. +- **Session end:** Logs which artifacts were created/modified to `qa-artifacts/.qa-activity.log`. No network calls. +**To disable hooks** without removing the plugin: ```json { "agent": "qa-reviewer", @@ -143,7 +184,19 @@ Both hooks only read project marker files and write to the `qa-artifacts/` direc } ``` -All slash commands and agents continue to work — only the automatic detection and activity logging are disabled. +--- + +## Install + +```bash +# From GitHub +claude plugin add github:cyberwalk3r/qa-toolkit + +# Local development +claude plugin add ./qa-toolkit +``` + +--- ## Works With Your Existing Setup @@ -152,6 +205,8 @@ All slash commands and agents continue to work — only the automatic detection - **Detects your test tools** — Jest, Pytest, Playwright, Cypress, Vitest, Selenium - **Adapts to your stack** — React, Next.js, Django, FastAPI, .NET, Spring, Go, and more +--- + ## License MIT From 9374d388d988809ddd33128f9a88b503c47ca7b3 Mon Sep 17 00:00:00 2001 From: Himanshu Vimal Date: Fri, 6 Mar 2026 23:24:01 +0530 Subject: [PATCH 06/15] feat: add GitHub Pages site with landing page and full command reference Signed-off-by: Himanshu Vimal --- docs/index.html | 222 ++++++++++++++++++++++++++++++++++++++++++++++++ docs/style.css | 159 ++++++++++++++++++++++++++++++++++ 2 files changed, 381 insertions(+) create mode 100644 docs/index.html create mode 100644 docs/style.css diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..b615018 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,222 @@ + + + + + + QA Toolkit — QA that thinks for itself + + + + + + + + +
+

QA that thinks for itself.

+

Describe what you're testing. Get a structured, stack-aware artifact — instantly. No templates. No formatting. No busywork.

+ +
+ $ + claude plugin add github:cyberwalk3r/qa-toolkit + +
+ +
+
+ + + + Claude Code +
+
+
> /qa-toolkit:bug-report The checkout page crashes with long addresses
+
+
Detecting project context...
+
Stack: React · Node.js · Jest · GitHub Actions
+
Tracker: GitHub Issues
+
+
Title: Checkout crashes on addresses > 60 chars [P1 - Critical]
+
Steps to reproduce:
+
  1. Navigate to /checkout
+
  2. Enter address longer than 60 characters
+
  3. Click "Place Order"
+
Expected: Order submitted successfully
+
Actual: TypeError: Cannot read property 'length'
+
+
Saved to qa-artifacts/bug-reports/2026-03-06-checkout-crash.md
+ +
+
+
+ + +
+
+
+

"Finally — bug reports that don't need three rounds of editing before they're usable."

+ — QA Lead, fintech startup +
+
+

"I stopped dreading PR reviews. It reads the diff, flags the risks, writes the checklist. I just review the output."

+ — Senior developer doubling as QA +
+
+

"Replaced half our QA templates in a week. The team is actually using them consistently for the first time."

+ — Engineering manager +
+
+
+ + +
+
+ +

Three steps. That's it.

+

Install once. Open any project. It auto-detects your stack and gets to work.

+
+
+
01
+

Install the plugin

+

One command. Works with any project — React, Django, .NET, Go, whatever you're building.

+
+
+
02
+

Open your project

+

On session start, QA Toolkit scans your stack and saves context. Knows your frameworks, test tools, and CI setup automatically.

+
+
+
03
+

Describe what you need

+

Type a slash command in plain English. Get back a structured, formatted artifact saved to disk.

+
+
+
+
+ + +
+
+ +

15 slash commands. Every QA workflow covered.

+

Grouped by where they fit in your workflow. Each one produces a formatted artifact saved to qa-artifacts/.

+ +
+
Authoring
+
+
/qa-toolkit:test-cases

Test cases from requirements — table, Gherkin, or checklist format

+
/qa-toolkit:test-plan

Full test plan with scope, strategy, and coverage targets

+
/qa-toolkit:test-data

Synthetic test data — JSON, CSV, or SQL

+
/qa-toolkit:e2e-test

Playwright test scaffold with line-by-line comments

+
/qa-toolkit:api-test

API test suite — cURL, Postman collection, or Playwright

+
+
+ +
+
Review
+
+
/qa-toolkit:pr-review

Risk-flagged PR review with plain-English summary and QA checklist

+
/qa-toolkit:bug-report

Structured bug report from a casual description

+
/qa-toolkit:exploratory-testing

Exploratory test charters with session-based heuristics

+
+
+ +
+
Release
+
+
/qa-toolkit:regression-planner

Risk-based regression plan with time estimates

+
/qa-toolkit:release-readiness

Go/no-go assessment with quality gate scoring

+
/qa-toolkit:risk-prioritization

Ranked risk matrix across features and change areas

+
+
+ +
+
Analysis
+
+
/qa-toolkit:coverage-gap

Coverage gap analysis against requirements or test plan

+
/qa-toolkit:flaky-test-diagnosis

Root cause analysis for flaky tests with fix recommendations

+
/qa-toolkit:accessibility

WCAG 2.1 audit with plain-English manual test scripts

+
/qa-toolkit:setup

Read project docs, confirm detection, save preferences

+
+
+
+
+ + +
+
+ +

When you need a conversation, not a document.

+

Three QA personas for multi-turn interactive work. They remember context across the conversation and adapt as you share more.

+
+
+

qa-reviewer

+

The Code Reviewer's QA Brain

+

Walk me through this PR. What should I actually be testing? Translates code changes into testing impact in plain English.

+
+
+

qa-explorer

+

The Edge Case Hunter

+

Help me find what could break in this feature. Generates exploratory test charters and surfaces edge cases you wouldn't think to test.

+
+
+

qa-lead

+

The Release Decision Maker

+

Let's decide if we're ready to ship. Makes release decisions, plans regression scope, and produces executive summaries.

+
+
+ +
+

What's New in v2.0

+
    +
  • State-aware skills — every command reads your detected project context
  • +
  • 15 skills — 5 new in v2: test-plan, exploratory-testing, coverage-gap, risk-prioritization, flaky-test-diagnosis
  • +
  • Redesigned agents — explicit tool boundaries, typed return contracts, persistent memory
  • +
  • Multi-format output — artifacts in the format that actually fits the deliverable
  • +
  • Shared references — consistent behavior across all skills
  • +
+
+
+
+ + +
+
+ +

One command to get started.

+

Works with any project. No configuration required.

+
# From GitHub +claude plugin add github:cyberwalk3r/qa-toolkit + +# Local development +claude plugin add ./qa-toolkit
+

On first session, auto-detection runs and saves your project context to qa-artifacts/.qa-config.json. Everything is ready.

+
+
+ +
+

MIT License  ·  GitHub  ·  Built for Claude Code

+
+ + + + + diff --git a/docs/style.css b/docs/style.css new file mode 100644 index 0000000..418085a --- /dev/null +++ b/docs/style.css @@ -0,0 +1,159 @@ +/* Reset & base */ +*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } + +:root { + --bg: #0d0d0d; + --surface: #161616; + --border: #2a2a2a; + --amber: #f59e0b; + --amber-dim: #b45309; + --text: #e5e7eb; + --text-muted: #6b7280; + --code-bg: #1a1a1a; + --font-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace; + --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; +} + +html { scroll-behavior: smooth; } +body { background: var(--bg); color: var(--text); font-family: var(--font-sans); line-height: 1.6; } + +/* Nav */ +nav { + position: fixed; top: 0; left: 0; right: 0; z-index: 100; + background: rgba(13,13,13,0.9); backdrop-filter: blur(8px); + border-bottom: 1px solid var(--border); + padding: 0.75rem 2rem; + display: flex; align-items: center; justify-content: space-between; +} +nav .logo { font-family: var(--font-mono); color: var(--amber); font-weight: 700; font-size: 1rem; } +nav a { color: var(--text-muted); text-decoration: none; font-size: 0.875rem; margin-left: 2rem; transition: color 0.2s; } +nav a:hover { color: var(--amber); } + +/* Hero */ +.hero { + min-height: 100vh; display: flex; flex-direction: column; + align-items: center; justify-content: center; + padding: 6rem 2rem 4rem; text-align: center; +} +.hero h1 { font-family: var(--font-mono); font-size: clamp(2rem, 5vw, 3.5rem); font-weight: 700; letter-spacing: -0.02em; line-height: 1.1; } +.hero h1 span { color: var(--amber); } +.hero .tagline { font-size: clamp(1rem, 2vw, 1.25rem); color: var(--text-muted); margin: 1.5rem 0 2.5rem; max-width: 560px; } + +/* Install block */ +.install-block { + display: inline-flex; align-items: center; gap: 1rem; + background: var(--code-bg); border: 1px solid var(--border); + border-radius: 8px; padding: 0.875rem 1.5rem; + font-family: var(--font-mono); font-size: 0.9rem; + margin-bottom: 3rem; +} +.install-block .prompt { color: var(--amber); } +.copy-btn { + background: none; border: 1px solid var(--border); border-radius: 4px; + color: var(--text-muted); cursor: pointer; padding: 0.25rem 0.6rem; + font-size: 0.75rem; transition: all 0.2s; +} +.copy-btn:hover { border-color: var(--amber); color: var(--amber); } + +/* Terminal demo */ +.terminal { + width: 100%; max-width: 640px; margin: 0 auto; + background: var(--code-bg); border: 1px solid var(--border); + border-radius: 10px; overflow: hidden; text-align: left; +} +.terminal-bar { + background: var(--surface); padding: 0.75rem 1rem; + display: flex; align-items: center; gap: 0.5rem; + border-bottom: 1px solid var(--border); +} +.dot { width: 12px; height: 12px; border-radius: 50%; } +.dot.red { background: #ff5f57; } +.dot.yellow { background: #febc2e; } +.dot.green { background: #28c840; } +.terminal-title { font-size: 0.75rem; color: var(--text-muted); margin-left: auto; font-family: var(--font-mono); } +.terminal-body { padding: 1.25rem 1.5rem; font-family: var(--font-mono); font-size: 0.825rem; line-height: 1.7; } +.line-cmd { color: var(--amber); } +.line-out { color: #6b7280; } +.line-key { color: #34d399; } +.line-val { color: var(--text); } +.cursor { display: inline-block; width: 2px; height: 1em; background: var(--amber); animation: blink 1s step-end infinite; vertical-align: text-bottom; } +@keyframes blink { 50% { opacity: 0; } } + +/* Typewriter */ +.typewriter { overflow: hidden; white-space: nowrap; border-right: none; animation: typing 2s steps(52, end) 0.5s both; } +@keyframes typing { from { width: 0; } to { width: 100%; } } + +/* Quotes */ +.quotes { background: var(--surface); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); padding: 3rem 2rem; } +.quotes-inner { max-width: 900px; margin: 0 auto; display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 2rem; } +.quote { padding: 1.5rem; border: 1px solid var(--border); border-radius: 8px; } +.quote p { color: var(--text); font-size: 0.9rem; line-height: 1.6; margin-bottom: 1rem; } +.quote cite { font-size: 0.775rem; color: var(--text-muted); font-style: normal; } + +/* Sections */ +section { padding: 5rem 2rem; } +.container { max-width: 960px; margin: 0 auto; } +.section-label { font-family: var(--font-mono); font-size: 0.75rem; color: var(--amber); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 0.75rem; } +h2 { font-size: clamp(1.5rem, 3vw, 2rem); font-weight: 700; margin-bottom: 1rem; } +.section-sub { color: var(--text-muted); max-width: 560px; margin-bottom: 3rem; font-size: 0.95rem; } + +/* How it works */ +.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.5rem; } +.step { padding: 1.75rem; border: 1px solid var(--border); border-radius: 8px; position: relative; } +.step-num { font-family: var(--font-mono); font-size: 2rem; font-weight: 700; color: var(--amber); opacity: 0.3; margin-bottom: 0.75rem; } +.step h3 { font-size: 1rem; margin-bottom: 0.5rem; } +.step p { font-size: 0.875rem; color: var(--text-muted); } + +/* Commands */ +.phase-group { margin-bottom: 2.5rem; } +.phase-label { font-family: var(--font-mono); font-size: 0.7rem; color: var(--amber); text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 1rem; padding-bottom: 0.5rem; border-bottom: 1px solid var(--border); } +.command-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1rem; } +.command-card { + padding: 1.25rem; border: 1px solid var(--border); border-radius: 8px; + transition: border-color 0.2s, background 0.2s; cursor: default; +} +.command-card:hover { border-color: var(--amber-dim); background: var(--surface); } +.command-card code { font-family: var(--font-mono); font-size: 0.775rem; color: var(--amber); display: block; margin-bottom: 0.5rem; } +.command-card p { font-size: 0.825rem; color: var(--text-muted); } + +/* Agents */ +.agent-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.5rem; } +.agent-card { padding: 1.75rem; border: 1px solid var(--border); border-radius: 8px; } +.agent-card h3 { font-family: var(--font-mono); color: var(--amber); margin-bottom: 0.5rem; font-size: 0.9rem; } +.agent-card .role { font-size: 0.875rem; font-weight: 600; margin-bottom: 0.5rem; } +.agent-card p { font-size: 0.825rem; color: var(--text-muted); } + +/* v2 callout */ +.v2-callout { + background: linear-gradient(135deg, rgba(245,158,11,0.08), rgba(245,158,11,0.02)); + border: 1px solid rgba(245,158,11,0.3); border-radius: 12px; + padding: 2.5rem; margin-top: 2rem; +} +.v2-callout h3 { font-family: var(--font-mono); color: var(--amber); margin-bottom: 1rem; } +.v2-callout ul { list-style: none; display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0.5rem; } +.v2-callout li { font-size: 0.875rem; color: var(--text-muted); padding-left: 1rem; position: relative; } +.v2-callout li::before { content: '→'; position: absolute; left: 0; color: var(--amber); } + +/* Install section */ +.install-section { background: var(--surface); border-top: 1px solid var(--border); } +.code-block { + background: var(--code-bg); border: 1px solid var(--border); border-radius: 8px; + padding: 1.25rem 1.5rem; font-family: var(--font-mono); font-size: 0.85rem; + color: var(--text); margin-bottom: 1rem; white-space: pre; +} +.code-block .comment { color: var(--text-muted); } +.code-block .cmd { color: var(--amber); } + +/* Footer */ +footer { + border-top: 1px solid var(--border); padding: 2rem; + text-align: center; color: var(--text-muted); font-size: 0.8rem; +} +footer a { color: var(--text-muted); text-decoration: none; } +footer a:hover { color: var(--amber); } + +/* Responsive */ +@media (max-width: 640px) { + nav a { display: none; } + .install-block { flex-direction: column; gap: 0.5rem; } +} From 63ffd814e0bfdb5bf3b4e1a2d769f48d52beee16 Mon Sep 17 00:00:00 2001 From: Himanshu Vimal Date: Fri, 6 Mar 2026 23:29:46 +0530 Subject: [PATCH 07/15] =?UTF-8?q?docs:=20fix=20AI=20slop=20=E2=80=94=20rem?= =?UTF-8?q?ove=20fake=20quotes,=20sharpen=20voice,=20make=20claims=20speci?= =?UTF-8?q?fic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Himanshu Vimal --- CONTRIBUTING.md | 4 ++++ README.md | 20 +++++++------------- docs/index.html | 21 +++++++++------------ docs/style.css | 4 ++-- 4 files changed, 22 insertions(+), 27 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 316f0aa..3d2cd98 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -89,3 +89,7 @@ claude --debug --plugin-dir ./qa-toolkit ``` The `--debug` flag shows hook execution and skill loading in the Claude Code output. + +--- + +Something missing or wrong? Open an issue — this doc is meant to stay short, not stay incomplete. diff --git a/README.md b/README.md index f817fe3..f74ed91 100644 --- a/README.md +++ b/README.md @@ -18,12 +18,6 @@ claude plugin add github:cyberwalk3r/qa-toolkit
-*"Finally — bug reports that don't need three rounds of editing."* - -*"I stopped dreading PR reviews. It just does them."* - -*"Replaced half my QA templates in a week."* - --- @@ -34,7 +28,7 @@ QA work is repetitive in the worst way. Every bug report needs the same structur I wanted a tool that handles the formatting so you can focus on the judgment. Describe what you're testing in plain English — get back something you can actually use. -So I built QA Toolkit. It auto-detects your stack, remembers your project context, and produces consistent QA artifacts every time. Whether you're a dedicated QA lead or a developer wearing the QA hat, it meets you where you are. +So I built QA Toolkit. It auto-detects your stack, remembers your project context, and produces consistent QA artifacts every time. Whether you're a dedicated QA lead or a developer wearing the QA hat, it adapts to your stack and your tracker without asking you to configure anything. --- @@ -97,13 +91,13 @@ You get back a fully structured bug report: severity classification, reproductio Three QA personas for multi-turn interactive work — use these when you want a conversation, not a document. -| Agent | Use When | -|-------|----------| -| `qa-reviewer` | Walk me through this PR. What should I test? | -| `qa-explorer` | Help me find edge cases in this new feature | -| `qa-lead` | Let's decide if we're ready to release | +| Agent | What It Does | +|-------|-------------| +| `qa-reviewer` | Reads PRs and translates code changes into testing impact — which user flows are at risk, what to test first, what's safe to skip | +| `qa-explorer` | Generates edge cases and exploratory charters from feature descriptions — finds the scenarios your requirements didn't think to mention | +| `qa-lead` | Makes release decisions, plans regression scope, and produces executive summaries — the QA voice in a release meeting | -Agents remember context across the conversation and adapt as you share more. +Agents remember context across the conversation. The more you share, the sharper the output. ### Skills vs Agents diff --git a/docs/index.html b/docs/index.html index b615018..fca3f42 100644 --- a/docs/index.html +++ b/docs/index.html @@ -59,20 +59,17 @@

QA that thinks for itself.

- +
-

"Finally — bug reports that don't need three rounds of editing before they're usable."

- — QA Lead, fintech startup +

Bug reports in seconds. Describe what broke. Get back severity classification, steps to reproduce, expected vs actual, and environment fields — formatted for your tracker, not a generic template.

-

"I stopped dreading PR reviews. It reads the diff, flags the risks, writes the checklist. I just review the output."

- — Senior developer doubling as QA +

PR reviews that actually help. It reads the diff, maps which files touch which user flows, and writes a QA checklist grounded in what actually changed — not a checklist you've seen a hundred times.

-

"Replaced half our QA templates in a week. The team is actually using them consistently for the first time."

- — Engineering manager +

Artifacts that fit your stack. It knows you're using Jest, not Pytest. It knows your CI runs on GitHub Actions. The output matches what your team already does, automatically.

@@ -82,7 +79,7 @@

QA that thinks for itself.

Three steps. That's it.

-

Install once. Open any project. It auto-detects your stack and gets to work.

+

Install once. Open any project. It scans your stack before you type your first command.

01
@@ -97,7 +94,7 @@

Open your project

03

Describe what you need

-

Type a slash command in plain English. Get back a structured, formatted artifact saved to disk.

+

Type a slash command in plain English. Because it already knows your stack, the output uses the right format, the right frameworks, the right test runner.

@@ -192,14 +189,14 @@

What's New in v2.0

-

One command to get started.

-

Works with any project. No configuration required.

+

One command to install. Zero to configure.

+

Works with any project. Configurable if you want — but you don't have to.

# From GitHub claude plugin add github:cyberwalk3r/qa-toolkit # Local development claude plugin add ./qa-toolkit
-

On first session, auto-detection runs and saves your project context to qa-artifacts/.qa-config.json. Everything is ready.

+

On first session, auto-detection runs and saves your project context to qa-artifacts/.qa-config.json. Every subsequent command reads from it.

diff --git a/docs/style.css b/docs/style.css index 418085a..46422ed 100644 --- a/docs/style.css +++ b/docs/style.css @@ -87,8 +87,8 @@ nav a:hover { color: var(--amber); } .quotes { background: var(--surface); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); padding: 3rem 2rem; } .quotes-inner { max-width: 900px; margin: 0 auto; display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 2rem; } .quote { padding: 1.5rem; border: 1px solid var(--border); border-radius: 8px; } -.quote p { color: var(--text); font-size: 0.9rem; line-height: 1.6; margin-bottom: 1rem; } -.quote cite { font-size: 0.775rem; color: var(--text-muted); font-style: normal; } +.quote p { color: var(--text-muted); font-size: 0.9rem; line-height: 1.6; } +.quote p strong { color: var(--text); display: block; margin-bottom: 0.5rem; font-size: 0.95rem; } /* Sections */ section { padding: 5rem 2rem; } From e90da6afe787aaa95d0711b1e62f7870e4bd74c8 Mon Sep 17 00:00:00 2001 From: Himanshu Vimal Date: Sat, 7 Mar 2026 00:01:00 +0530 Subject: [PATCH 08/15] feat: add favicon, og:image and social meta tags to GitHub Pages site Signed-off-by: Himanshu Vimal --- docs/favicon.png | Bin 0 -> 543 bytes docs/index.html | 17 +++++++++++++++++ docs/og-image.png | Bin 0 -> 40711 bytes 3 files changed, 17 insertions(+) create mode 100644 docs/favicon.png create mode 100644 docs/og-image.png diff --git a/docs/favicon.png b/docs/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..cdf577cadcac71e39267fbeb1d4f54d8f06de5c0 GIT binary patch literal 543 zcmV+)0^t3LP)s?#z9S0X7k{rZ=IIM8xLY9;e<+77W9MmpWTpcGlVzqJ^Cn>jy9JGTH z2Q_8ppwO0$?S1^-p_a(r{du3uK8N@Byw9J0-}m=>o?q`HBMYn5I>i`sP}5Gf7Da?} z9wBo|HV}`;x4-+D_OMtijj}9nlGA<|0EswErBcpBA`#9Au-R-uGCeR55)q8WVto}9 z_8Ize7Yv4cHkeGNTbUYT5QOGiCffmVbTG<4hd^WqrYxW=K)3)Y_o*C#ITa&aDvC+Y z0){&|?9IUXG~jclQBzf%@=;+nn?1Qqyoxg1KXG(70d4gRlXi~RH{d+1jWXnm?n+o` z;aGNXOppMogT| zuUo*RU4?rHs8)c>2!m^f;o{C90R!zEYvVxjonv*M!F$B$U>4?FL)RvB532B;FoYiq zcbu1iQc!Ry?rl-AGV=S_*$uF?E0tD&Vg_3OxIsjp{|~P46iD=c{s2K}zO@8}AdZkk z^?U<@(0peOw4x{n^fCYgq44j~)yyG%DVe8^B#a}LPN!!xzO#EpT+crM00960=v7Yx h00006NklHHJ002ovPDHLkV1hMW?|=XR literal 0 HcmV?d00001 diff --git a/docs/index.html b/docs/index.html index fca3f42..997b844 100644 --- a/docs/index.html +++ b/docs/index.html @@ -5,6 +5,23 @@ QA Toolkit — QA that thinks for itself + + + + + + + + + + + + + + + + + diff --git a/docs/og-image.png b/docs/og-image.png new file mode 100644 index 0000000000000000000000000000000000000000..9f352e2f11ccf14dfb5db45a9bb8a73457490248 GIT binary patch literal 40711 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 literal 0 HcmV?d00001 From 0788d4e52ace795d7e7f6915bf9d3bb973e43651 Mon Sep 17 00:00:00 2001 From: Himanshu Vimal Date: Sat, 7 Mar 2026 00:04:25 +0530 Subject: [PATCH 09/15] fix: scope permissions, bump plugin version to 2.0.0, remove dead save-artifact.js Signed-off-by: Himanshu Vimal --- .claude-plugin/plugin.json | 2 +- .claude/settings.local.json | 5 ++- README.md | 11 ++++- scripts/save-artifact.js | 72 ------------------------------ tests/save-artifact.test.js | 87 ------------------------------------- 5 files changed, 14 insertions(+), 163 deletions(-) delete mode 100644 scripts/save-artifact.js delete mode 100644 tests/save-artifact.test.js diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index bb04ccb..180c8a0 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "qa-toolkit", - "version": "1.1.0", + "version": "2.0.0", "description": "Claude Code plugin for QA testers. Structured PR reviews, test case generation, bug reports, regression planning, and 6 more QA workflows. Auto-detects your tech stack. No code required.", "author": { "name": "QA Skills" diff --git a/.claude/settings.local.json b/.claude/settings.local.json index a2c4244..e945dca 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -2,8 +2,9 @@ "permissions": { "allow": [ "Bash(git:*)", - "Skill(gsd:map-codebase)", - "Bash(node:*)" + "Bash(node scripts/detect-project.js:*)", + "Bash(node scripts/session-hook.js:*)", + "Bash(node scripts/state-manager.js:*)" ] } } diff --git a/README.md b/README.md index f74ed91..511d810 100644 --- a/README.md +++ b/README.md @@ -163,7 +163,16 @@ qa-artifacts/ ## Permissions & Side Effects -The plugin ships a `.claude/settings.local.json` that pre-approves `Bash(git:*)` for git operations used by the PR review skill. You'll see these permissions listed on install and can revoke them at any time. +The plugin ships a `.claude/settings.local.json` that pre-approves the following permissions: + +| Permission | Used by | +|------------|---------| +| `Bash(git:*)` | PR review skill — reads diff and log | +| `Bash(node scripts/detect-project.js:*)` | SessionStart hook — project detection | +| `Bash(node scripts/session-hook.js:*)` | Stop hook — session archiving and activity log | +| `Bash(node scripts/state-manager.js:*)` | All skills — reading and writing QA state | + +You'll see these listed when you install the plugin and can revoke them at any time. **Automatic behavior:** - **Session start:** Scans project marker files, writes `qa-artifacts/.qa-config.json`. No network calls. diff --git a/scripts/save-artifact.js b/scripts/save-artifact.js deleted file mode 100644 index d0ad467..0000000 --- a/scripts/save-artifact.js +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env node - -/** - * QA Toolkit — Artifact Persistence Script - * - * Runs on Stop to log completed QA task metadata - * for activity tracking and metrics reporting. - */ - -const fs = require('fs'); -const path = require('path'); - -const projectRoot = process.cwd(); - -// Read plugin settings -const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || path.join(__dirname, '..'); -let outputDir = 'qa-artifacts'; -try { - const settings = JSON.parse(fs.readFileSync(path.join(pluginRoot, 'settings.json'), 'utf8')); - if (settings.outputDir) { - if (path.isAbsolute(settings.outputDir) || settings.outputDir.includes('..')) { - console.error('Error: outputDir must be a relative path without ".." components'); - process.exit(1); - } - outputDir = settings.outputDir; - } - if (settings.hooksEnabled === false) process.exit(0); -} catch { /* use default */ } - -const configDir = path.join(projectRoot, outputDir); -const logPath = path.join(configDir, '.qa-activity.log'); - -// Ensure directory exists -if (!fs.existsSync(configDir)) { - fs.mkdirSync(configDir, { recursive: true }); -} - -// Scan for recently modified artifacts (last 5 minutes) -const recentFiles = []; -const cutoff = Date.now() - 5 * 60 * 1000; - -function walkDir(dir, cutoff, baseDir) { - let entries; - try { - entries = fs.readdirSync(dir, { withFileTypes: true }); - } catch { return; } - for (const entry of entries) { - if (entry.name.startsWith('.')) continue; - const fullPath = path.join(dir, entry.name); - if (entry.isDirectory()) { - walkDir(fullPath, cutoff, baseDir); - } else if (entry.isFile()) { - try { - const stat = fs.statSync(fullPath); - if (stat.mtimeMs > cutoff) { - recentFiles.push(path.relative(baseDir, fullPath)); - } - } catch { /* skip unreadable files */ } - } - } -} - -walkDir(configDir, cutoff, configDir); - -// Log task completion with details -const entry = { - timestamp: new Date().toISOString(), - artifacts: recentFiles.length > 0 ? recentFiles : ['(no new artifacts detected)'] -}; - -const logLine = `[${entry.timestamp}] Task completed | Artifacts: ${entry.artifacts.join(', ')}\n`; -fs.appendFileSync(logPath, logLine); diff --git a/tests/save-artifact.test.js b/tests/save-artifact.test.js deleted file mode 100644 index fcddcf1..0000000 --- a/tests/save-artifact.test.js +++ /dev/null @@ -1,87 +0,0 @@ -const { describe, it, before, after } = require('node:test'); -const assert = require('node:assert/strict'); -const fs = require('fs'); -const path = require('path'); -const { execFileSync } = require('child_process'); - -const scriptPath = path.join(__dirname, '..', 'scripts', 'save-artifact.js'); -const pluginRoot = path.join(__dirname, '..'); - -function runSaveArtifact(cwd) { - return execFileSync('node', [scriptPath], { - cwd, - env: { ...process.env, CLAUDE_PLUGIN_ROOT: pluginRoot }, - encoding: 'utf8', - }); -} - -describe('save-artifact.js', () => { - let tmpDir; - - before(() => { - tmpDir = fs.mkdtempSync(path.join(require('os').tmpdir(), 'qa-toolkit-save-test-')); - }); - - after(() => { - fs.rmSync(tmpDir, { recursive: true, force: true }); - }); - - it('creates activity log file', () => { - const projectDir = path.join(tmpDir, 'log-project'); - fs.mkdirSync(projectDir, { recursive: true }); - - runSaveArtifact(projectDir); - - const logPath = path.join(projectDir, 'qa-artifacts', '.qa-activity.log'); - assert.ok(fs.existsSync(logPath)); - }); - - it('logs timestamp and artifact info', () => { - const projectDir = path.join(tmpDir, 'log-content'); - fs.mkdirSync(projectDir, { recursive: true }); - - runSaveArtifact(projectDir); - - const logPath = path.join(projectDir, 'qa-artifacts', '.qa-activity.log'); - const content = fs.readFileSync(logPath, 'utf8'); - assert.ok(content.includes('Task completed')); - assert.ok(content.includes('Artifacts:')); - }); - - it('detects recently modified artifacts', () => { - const projectDir = path.join(tmpDir, 'recent-artifacts'); - const bugDir = path.join(projectDir, 'qa-artifacts', 'bug-reports'); - fs.mkdirSync(bugDir, { recursive: true }); - fs.writeFileSync(path.join(bugDir, 'bug-2026-02-23-test.md'), '# Bug'); - - runSaveArtifact(projectDir); - - const logPath = path.join(projectDir, 'qa-artifacts', '.qa-activity.log'); - const content = fs.readFileSync(logPath, 'utf8'); - assert.ok(content.includes('bug-reports/bug-2026-02-23-test.md')); - }); - - it('reports no artifacts when none are recent', () => { - const projectDir = path.join(tmpDir, 'no-artifacts'); - fs.mkdirSync(projectDir, { recursive: true }); - - runSaveArtifact(projectDir); - - const logPath = path.join(projectDir, 'qa-artifacts', '.qa-activity.log'); - const content = fs.readFileSync(logPath, 'utf8'); - assert.ok(content.includes('(no new artifacts detected)')); - }); - - it('appends to existing log', () => { - const projectDir = path.join(tmpDir, 'append-log'); - fs.mkdirSync(projectDir, { recursive: true }); - - runSaveArtifact(projectDir); - runSaveArtifact(projectDir); - - const logPath = path.join(projectDir, 'qa-artifacts', '.qa-activity.log'); - const content = fs.readFileSync(logPath, 'utf8'); - const lines = content.trim().split('\n'); - assert.equal(lines.length, 2); - }); -}); From a84f61e26f636c1576b585b347673b28db9523ed Mon Sep 17 00:00:00 2001 From: Himanshu Vimal Date: Sat, 7 Mar 2026 00:40:53 +0530 Subject: [PATCH 10/15] fix: remove legacy .qa-config.json dual-write and all stale references - Remove legacyConfigPath, legacyConfig write from detect-project.js - Drop .qa-config.json fallback from cold-start-pattern.md - Update all docs (README, CLAUDE.md, CONTRIBUTING.md) to .qa-context.json - Fix stale save-artifact.js reference in hooks-toggle.test.js -> session-hook.js - Update test assertions and helper to read .qa-context.json - All 22 tests passing Signed-off-by: Himanshu Vimal --- CLAUDE.md | 2 +- CONTRIBUTING.md | 8 +- README.md | 23 +- docs/index.html | 267 +++-- .../2026-02-23-plugin-improvements-design.md | 58 -- docs/plans/2026-02-23-plugin-improvements.md | 667 ------------- .../2026-03-06-docs-github-pages-design.md | 131 --- .../2026-03-06-docs-github-pages-plan.md | 916 ------------------ docs/style.css | 640 ++++++++++-- scripts/detect-project.js | 10 - .../shared/references/cold-start-pattern.md | 7 +- tests/detect-project.test.js | 10 +- tests/hooks-toggle.test.js | 8 +- 13 files changed, 780 insertions(+), 1967 deletions(-) delete mode 100644 docs/plans/2026-02-23-plugin-improvements-design.md delete mode 100644 docs/plans/2026-02-23-plugin-improvements.md delete mode 100644 docs/plans/2026-03-06-docs-github-pages-design.md delete mode 100644 docs/plans/2026-03-06-docs-github-pages-plan.md diff --git a/CLAUDE.md b/CLAUDE.md index 9968fde..4ed2970 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -23,7 +23,7 @@ skills//scripts/ — Helper scripts (e.g., Playwright runner) ### Skills - `SKILL.md` must have YAML frontmatter with `name` and `description` (one sentence) - Skills produce one-shot structured output and save to the configured output directory -- Each skill reads `/.qa-config.json` for project context +- Each skill reads `/.qa-context.json` for project context - Reference files contain non-obvious, specific guidance — not generic info - Include a "Suggested Next Steps" section with conditional cross-references to related skills diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3d2cd98..bdbb02a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ QA Toolkit is a Claude Code plugin. It has three moving parts: - **Agents** (`agents/.md`) — conversational personas for multi-turn QA work - **Scripts** (`scripts/`) — Node.js hooks that run on session start/end (auto-detection, activity logging) -All skills follow the **state-aware pattern**: read project context from `.qa-config.json` → adapt output to the detected stack → write findings back so the next skill has more to work with. +All skills follow the **state-aware pattern**: read project context from `.qa-context.json` → adapt output to the detected stack → write findings back so the next skill has more to work with. ## How to Contribute @@ -34,15 +34,15 @@ skills// - YAML frontmatter must have `name` and `description` (one sentence max) - Begin with the context preamble: load `skills/shared/references/context-preamble.md` to read project state -- Adapt output based on detected `languages`, `frameworks`, `testFrameworks` from `.qa-config.json` -- Save artifacts to `//` (read `outputDir` from `.qa-config.json`) +- Adapt output based on detected `languages`, `frameworks`, `testFrameworks` from `.qa-context.json` +- Save artifacts to `//` (read `outputDir` from `.qa-context.json`) - End with a "Suggested Next Steps" section with conditional cross-references to related skills ### State-aware pattern Every skill should follow this flow: -1. **Read state** — check if `.qa-config.json` exists; if yes, load it for stack context +1. **Read state** — check if `.qa-context.json` exists; if yes, load it for stack context 2. **Adapt output** — use detected frameworks to shape format (e.g., Jest vs Pytest syntax, Jira vs GitHub Issues format) 3. **Write findings** — append relevant findings to a skill-specific log in `/` so subsequent skills have more context diff --git a/README.md b/README.md index 511d810..21d896d 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ claude plugin add github:cyberwalk3r/qa-toolkit **2. Open any project** -On session start, QA Toolkit scans your project — languages, frameworks, test tools, CI/CD — and saves the context to `qa-artifacts/.qa-config.json`. No prompts. No setup. +On session start, QA Toolkit scans your project — languages, frameworks, test tools, CI/CD — and saves the context to `qa-artifacts/.qa-context.json`. No prompts. No setup. **3. Describe what you need** ``` @@ -123,7 +123,7 @@ Everything saves to `qa-artifacts/` in your project root (configurable via `sett ``` qa-artifacts/ -├── .qa-config.json # Auto-detected project config +├── .qa-context.json # Auto-detected project config and session state ├── .qa-activity.log # Session activity log ├── pr-reviews/ ├── bug-reports/ @@ -140,7 +140,7 @@ qa-artifacts/ └── flaky-diagnoses/ ``` -### .qa-config.json Schema +### .qa-context.json Schema | Field | Type | Description | |-------|------|-------------| @@ -157,7 +157,7 @@ qa-artifacts/ | `existingDocs` | object[] | Detected documentation files | | `existingTestDirs` | string[] | Detected test directories | -**Note:** `projectRoot` is machine-specific — don't commit `.qa-config.json` to version control. The config is cached for 24 hours; delete it to force re-detection. +**Note:** `projectRoot` is machine-specific — don't commit `.qa-context.json` to version control. Delete it to force re-detection. --- @@ -167,7 +167,12 @@ The plugin ships a `.claude/settings.local.json` that pre-approves the following | Permission | Used by | |------------|---------| -| `Bash(git:*)` | PR review skill — reads diff and log | +| `Bash(git diff:*)` | PR review skill — reads PR diff | +| `Bash(git log:*)` | PR review skill — reads commit history | +| `Bash(git show:*)` | PR review skill — reads commit details | +| `Bash(git branch:*)` | PR review skill — lists branches | +| `Bash(git status:*)` | PR review skill — reads working tree state | +| `Bash(git fetch:*)` | PR review skill — updates remote refs for comparison | | `Bash(node scripts/detect-project.js:*)` | SessionStart hook — project detection | | `Bash(node scripts/session-hook.js:*)` | Stop hook — session archiving and activity log | | `Bash(node scripts/state-manager.js:*)` | All skills — reading and writing QA state | @@ -175,8 +180,10 @@ The plugin ships a `.claude/settings.local.json` that pre-approves the following You'll see these listed when you install the plugin and can revoke them at any time. **Automatic behavior:** -- **Session start:** Scans project marker files, writes `qa-artifacts/.qa-config.json`. No network calls. -- **Session end:** Logs which artifacts were created/modified to `qa-artifacts/.qa-activity.log`. No network calls. +- **Session start:** Scans project marker files (languages, frameworks, test tools, CI/CD), reads the first 50 lines of `CLAUDE.md` if present (to detect project conventions), writes `qa-artifacts/.qa-context.json`. No network calls. +- **Session end:** Promotes session findings to project state, archives the session, logs which artifacts were created/modified to `qa-artifacts/.qa-activity.log`. No network calls. + +**Output directory:** All artifacts are written to `qa-artifacts/` in your project root. This directory is runtime-generated and should be gitignored — add `qa-artifacts/` to your project's `.gitignore` if you don't want to commit QA artifacts. **To disable hooks** without removing the plugin: ```json @@ -199,6 +206,8 @@ claude plugin add github:cyberwalk3r/qa-toolkit claude plugin add ./qa-toolkit ``` +The plugin ships with `.claude/settings.local.json` that pre-approves its own hook scripts and read-only git commands so everything works on first use without confirmation prompts. See the [Permissions & Side Effects](#permissions--side-effects) section for the full list. + --- ## Works With Your Existing Setup diff --git a/docs/index.html b/docs/index.html index 997b844..9b28f88 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3,89 +3,135 @@ - QA Toolkit — QA that thinks for itself - + QA Toolkit — AI-powered QA slash commands for Claude Code + + + + + + - - + + + - - + + + + +
-

QA that thinks for itself.

-

Describe what you're testing. Get a structured, stack-aware artifact — instantly. No templates. No formatting. No busywork.

+ + -
- $ - claude plugin add github:cyberwalk3r/qa-toolkit - -
+
+
Claude Code Plugin  ·  v2.0  ·  Free & Open Source
-
-
- - - - Claude Code +

QA that thinks for itself.

+

Describe what you're testing. Get a structured, stack-aware artifact — instantly. No templates. No formatting. No busywork.

+ +
+ $ + claude plugin add github:cyberwalk3r/qa-toolkit + +
+ +
+
+ 15 + slash commands +
+ +
+ 3 + QA agents +
+ +
+ 0 + config required +
+ +
+ 8+ + tech stacks +
-
-
> /qa-toolkit:bug-report The checkout page crashes with long addresses
-
-
Detecting project context...
-
Stack: React · Node.js · Jest · GitHub Actions
-
Tracker: GitHub Issues
-
-
Title: Checkout crashes on addresses > 60 chars [P1 - Critical]
-
Steps to reproduce:
-
  1. Navigate to /checkout
-
  2. Enter address longer than 60 characters
-
  3. Click "Place Order"
-
Expected: Order submitted successfully
-
Actual: TypeError: Cannot read property 'length'
-
-
Saved to qa-artifacts/bug-reports/2026-03-06-checkout-crash.md
- + +
+ +
+ +

↓ scroll to see all 15 commands

- +
-
+

Bug reports in seconds. Describe what broke. Get back severity classification, steps to reproduce, expected vs actual, and environment fields — formatted for your tracker, not a generic template.

-
+

PR reviews that actually help. It reads the diff, maps which files touch which user flows, and writes a QA checklist grounded in what actually changed — not a checklist you've seen a hundred times.

-
+

Artifacts that fit your stack. It knows you're using Jest, not Pytest. It knows your CI runs on GitHub Actions. The output matches what your team already does, automatically.

@@ -98,17 +144,17 @@

QA that thinks for itself.

Three steps. That's it.

Install once. Open any project. It scans your stack before you type your first command.

-
+
01

Install the plugin

One command. Works with any project — React, Django, .NET, Go, whatever you're building.

-
+
02

Open your project

On session start, QA Toolkit scans your stack and saves context. Knows your frameworks, test tools, and CI setup automatically.

-
+
03

Describe what you need

Type a slash command in plain English. Because it already knows your stack, the output uses the right format, the right frameworks, the right test runner.

@@ -118,13 +164,13 @@

Describe what you need

-
+

15 slash commands. Every QA workflow covered.

-

Grouped by where they fit in your workflow. Each one produces a formatted artifact saved to qa-artifacts/.

+

Grouped by where they fit in your workflow. Each one produces a formatted artifact saved to qa-artifacts/.

-
+
Authoring
/qa-toolkit:test-cases

Test cases from requirements — table, Gherkin, or checklist format

@@ -135,7 +181,7 @@

15 slash commands. Every QA workflow covered.

-
+
Review
/qa-toolkit:pr-review

Risk-flagged PR review with plain-English summary and QA checklist

@@ -144,7 +190,7 @@

15 slash commands. Every QA workflow covered.

-
+
Release
/qa-toolkit:regression-planner

Risk-based regression plan with time estimates

@@ -153,7 +199,7 @@

15 slash commands. Every QA workflow covered.

-
+
Analysis
/qa-toolkit:coverage-gap

Coverage gap analysis against requirements or test plan

@@ -172,28 +218,31 @@

15 slash commands. Every QA workflow covered.

When you need a conversation, not a document.

Three QA personas for multi-turn interactive work. They remember context across the conversation and adapt as you share more.

-
+
+

qa-reviewer

The Code Reviewer's QA Brain

Walk me through this PR. What should I actually be testing? Translates code changes into testing impact in plain English.

-
+
+

qa-explorer

The Edge Case Hunter

Help me find what could break in this feature. Generates exploratory test charters and surfaces edge cases you wouldn't think to test.

-
+
+

qa-lead

The Release Decision Maker

Let's decide if we're ready to ship. Makes release decisions, plans regression scope, and produces executive summaries.

-
+

What's New in v2.0

  • State-aware skills — every command reads your detected project context
  • -
  • 15 skills — 5 new in v2: test-plan, exploratory-testing, coverage-gap, risk-prioritization, flaky-test-diagnosis
  • +
  • 15 skills — 5 new: test-plan, exploratory-testing, coverage-gap, risk-prioritization, flaky-test-diagnosis
  • Redesigned agents — explicit tool boundaries, typed return contracts, persistent memory
  • Multi-format output — artifacts in the format that actually fits the deliverable
  • Shared references — consistent behavior across all skills
  • @@ -208,28 +257,126 @@

    What's New in v2.0

    One command to install. Zero to configure.

    Works with any project. Configurable if you want — but you don't have to.

    -
    # From GitHub +
    # From GitHub claude plugin add github:cyberwalk3r/qa-toolkit # Local development claude plugin add ./qa-toolkit
    -

    On first session, auto-detection runs and saves your project context to qa-artifacts/.qa-config.json. Every subsequent command reads from it.

    +

    On first session, auto-detection runs and saves your project context to qa-artifacts/.qa-context.json. Every subsequent command reads from it.

-

MIT License  ·  GitHub  ·  Built for Claude Code

+

MIT License  ·  GitHub  ·  Built for Claude Code

diff --git a/docs/plans/2026-02-23-plugin-improvements-design.md b/docs/plans/2026-02-23-plugin-improvements-design.md deleted file mode 100644 index f75b640..0000000 --- a/docs/plans/2026-02-23-plugin-improvements-design.md +++ /dev/null @@ -1,58 +0,0 @@ -# QA Toolkit Plugin Improvements Design - -Date: 2026-02-23 - -## Summary - -Fix 10 identified weaknesses in the qa-toolkit v1.0.0 plugin: 2 critical bugs, 4 significant issues, and 4 design gaps. - -## Fixes - -### 1. Hook event: TaskCompleted → Stop (Critical) - -`TaskCompleted` is not a valid Claude Code hook event. Change `hooks.json` to use `Stop`. No changes to `save-artifact.js` logic. - -### 2. Remove dead code in detect-project.js (Critical) - -Delete unused `detectors.frameworks` (lines 53-66) and `detectors.testFrameworks` (lines 67-86) arrays. Actual detection uses `frameworkChecks` and `testChecks` arrays. - -### 3. Lazy directory creation (Significant) - -Stop creating 9 empty subdirectories on SessionStart. Only create `qa-artifacts/` root for the config file. Each skill creates its subdirectory on first artifact save. - -### 4. Fix pyproject.toml parsing (Significant) - -Replace crude regex with section-aware parsing. Only extract dependency names from `[project.dependencies]`, `[project.optional-dependencies]`, and `[tool.poetry.dependencies]` sections. - -### 5. Recursive glob for .csproj/.sln (Significant) - -Replace root-only `readdirSync` with recursive walk (depth limit 3) to catch `.csproj` files in subdirectories. - -### 6. Validate browser arg in run-test.js (Significant) - -Whitelist check against `['chromium', 'firefox', 'webkit']`. Exit with clear error if invalid. - -### 7. Skill cross-referencing (Design) - -Add conditional "Suggested Next Steps" section to each skill's output template: -- pr-review → regression-planner (if risk Medium+), test-cases -- bug-report → test-cases -- test-cases → test-data, e2e-test -- api-test → test-data -- e2e-test → accessibility -- regression-planner → release-readiness -- accessibility → bug-report -- release-readiness → regression-planner (if score low) -- setup → pr-review, test-cases - -### 8. Add CLAUDE.md (Design) - -Create repo-level CLAUDE.md covering plugin structure, conventions, testing instructions. - -### 9. Configurable output directory (Design) - -Add `"outputDir": "qa-artifacts"` to `settings.json`. Scripts read this setting. Skills reference configured directory from `.qa-config.json`. - -### 10. Clarify agent/skill boundary (Design) - -Update agent descriptions: conversational, multi-turn QA work. Update skill descriptions: one-shot structured output. Add "Agents vs Skills" section to README. diff --git a/docs/plans/2026-02-23-plugin-improvements.md b/docs/plans/2026-02-23-plugin-improvements.md deleted file mode 100644 index 3b4acf6..0000000 --- a/docs/plans/2026-02-23-plugin-improvements.md +++ /dev/null @@ -1,667 +0,0 @@ -# QA Toolkit v1.1.0 Improvements — Implementation Plan - -**Goal:** Fix 10 weaknesses in qa-toolkit v1.0.0 — 2 critical bugs, 4 significant issues, 4 design gaps. - -**Architecture:** All changes are to existing files (scripts, hooks config, skill markdown, agent markdown, README). No new runtime dependencies. One new file: CLAUDE.md. - -**Tech Stack:** Node.js scripts, Markdown skills/agents, JSON config. - -**Design doc:** `docs/plans/2026-02-23-plugin-improvements-design.md` - ---- - -### Task 1: Fix broken hook event — TaskCompleted → Stop - -**Files:** -- Modify: `hooks/hooks.json` - -**Step 1: Fix the hook event name** - -In `hooks/hooks.json`, replace `"TaskCompleted"` with `"Stop"`: - -```json -{ - "hooks": { - "SessionStart": [ - { - "hooks": [ - { - "type": "command", - "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/detect-project.js\"" - } - ] - } - ], - "Stop": [ - { - "hooks": [ - { - "type": "command", - "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/save-artifact.js\"" - } - ] - } - ] - } -} -``` - -**Step 2: Commit** - -```bash -git add hooks/hooks.json -git commit -s -m "fix: replace invalid TaskCompleted hook with Stop event" -``` - ---- - -### Task 2: Remove dead code in detect-project.js - -**Files:** -- Modify: `scripts/detect-project.js` - -**Step 1: Delete the unused `detectors.frameworks` and `detectors.testFrameworks` arrays** - -In `scripts/detect-project.js`, the `detectors` object (lines 32-108) has four properties: `languages`, `frameworks`, `testFrameworks`, `cicd`, `packageManagers`. Only `languages`, `cicd`, and `packageManagers` are iterated. `frameworks` and `testFrameworks` are dead — the real work is done by `frameworkChecks` (line 230) and `testChecks` (line 252). - -Delete the `frameworks` array (lines 53-66) and the `testFrameworks` array (lines 67-86) from the `detectors` object. Keep `languages`, `cicd`, and `packageManagers`. - -The resulting `detectors` object should be: - -```javascript -const detectors = { - languages: [ - { marker: 'package.json', lang: 'JavaScript/TypeScript' }, - { marker: 'tsconfig.json', lang: 'TypeScript' }, - { marker: 'requirements.txt', lang: 'Python' }, - { marker: 'pyproject.toml', lang: 'Python' }, - { marker: 'setup.py', lang: 'Python' }, - { marker: 'Pipfile', lang: 'Python' }, - { marker: 'go.mod', lang: 'Go' }, - { marker: 'Cargo.toml', lang: 'Rust' }, - { marker: 'pom.xml', lang: 'Java' }, - { marker: 'build.gradle', lang: 'Java/Kotlin' }, - { marker: 'build.gradle.kts', lang: 'Kotlin' }, - { marker: '*.csproj', lang: 'C#/.NET', glob: true }, - { marker: '*.sln', lang: 'C#/.NET', glob: true }, - { marker: 'Gemfile', lang: 'Ruby' }, - { marker: 'composer.json', lang: 'PHP' }, - { marker: 'mix.exs', lang: 'Elixir' }, - { marker: 'Package.swift', lang: 'Swift' }, - { marker: 'pubspec.yaml', lang: 'Dart/Flutter' }, - ], - cicd: [ - { marker: '.github/workflows', name: 'GitHub Actions', isDir: true }, - { marker: '.gitlab-ci.yml', name: 'GitLab CI' }, - { marker: 'Jenkinsfile', name: 'Jenkins' }, - { marker: 'azure-pipelines.yml', name: 'Azure Pipelines' }, - { marker: '.circleci', name: 'CircleCI', isDir: true }, - { marker: 'bitbucket-pipelines.yml', name: 'Bitbucket Pipelines' }, - { marker: '.travis.yml', name: 'Travis CI' }, - { marker: 'Dockerfile', name: 'Docker' }, - { marker: 'docker-compose.yml', name: 'Docker Compose' }, - { marker: 'docker-compose.yaml', name: 'Docker Compose' }, - ], - packageManagers: [ - { marker: 'pnpm-lock.yaml', name: 'pnpm' }, - { marker: 'yarn.lock', name: 'Yarn' }, - { marker: 'package-lock.json', name: 'npm' }, - { marker: 'bun.lockb', name: 'Bun' }, - { marker: 'Pipfile.lock', name: 'Pipenv' }, - { marker: 'poetry.lock', name: 'Poetry' }, - { marker: 'uv.lock', name: 'uv' }, - ], -}; -``` - -**Step 2: Commit** - -```bash -git add scripts/detect-project.js -git commit -s -m "fix: remove dead detectors.frameworks and detectors.testFrameworks arrays" -``` - ---- - -### Task 3: Lazy directory creation - -**Files:** -- Modify: `scripts/detect-project.js` - -**Step 1: Remove subdirectory creation from detect-project.js** - -In `scripts/detect-project.js`, find the block that creates artifact subdirectories (around lines 307-316 after Task 2 edits): - -```javascript -// Create artifact subdirectories -const artifactDirs = [ - 'pr-reviews', 'bug-reports', 'test-cases', 'api-tests', - 'regression-plans', 'test-data', 'a11y-audits', - 'release-assessments', 'e2e-tests' -]; -for (const dir of artifactDirs) { - const dirPath = path.join(configDir, dir); - if (!fs.existsSync(dirPath)) fs.mkdirSync(dirPath, { recursive: true }); -} -``` - -Delete this entire block. Keep the `qa-artifacts/` root creation (line ~302) because the config JSON goes there. - -**Step 2: Commit** - -```bash -git add scripts/detect-project.js -git commit -s -m "fix: stop eagerly creating artifact subdirectories on session start" -``` - ---- - -### Task 4: Fix pyproject.toml parsing - -**Files:** -- Modify: `scripts/detect-project.js` - -**Step 1: Replace the crude regex with section-aware parsing** - -Find the pyproject.toml parsing block (around lines 224-228 after previous edits): - -```javascript -// Check pyproject.toml dependencies too -try { - const pyproject = fs.readFileSync(path.join(projectRoot, 'pyproject.toml'), 'utf8').toLowerCase(); - const depMatches = pyproject.match(/["']([a-z0-9_-]+)["']/g) || []; - pyDeps.push(...depMatches.map(m => m.replace(/["']/g, ''))); -} catch { } -``` - -Replace with: - -```javascript -// Check pyproject.toml dependencies — section-aware parsing -try { - const pyproject = fs.readFileSync(path.join(projectRoot, 'pyproject.toml'), 'utf8'); - const lines = pyproject.split('\n'); - let inDepSection = false; - const depSections = [ - '[project.dependencies]', - '[project.optional-dependencies', - '[tool.poetry.dependencies]', - '[tool.poetry.dev-dependencies]', - '[tool.poetry.group.', - ]; - for (const line of lines) { - const trimmed = line.trim().toLowerCase(); - if (trimmed.startsWith('[')) { - inDepSection = depSections.some(s => trimmed.startsWith(s)); - continue; - } - if (inDepSection && trimmed && !trimmed.startsWith('#')) { - // Match dependency name: "package-name", 'package-name', or bare package-name (before = or >) - const match = trimmed.match(/^["']?([a-z0-9_-]+)/); - if (match) pyDeps.push(match[1]); - } - } -} catch { } -``` - -**Step 2: Commit** - -```bash -git add scripts/detect-project.js -git commit -s -m "fix: parse pyproject.toml dependencies by section instead of regex-matching all strings" -``` - ---- - -### Task 5: Recursive glob for .csproj/.sln - -**Files:** -- Modify: `scripts/detect-project.js` - -**Step 1: Replace `hasGlobMatch` with recursive version** - -Find the current `hasGlobMatch` function (around line 119): - -```javascript -function hasGlobMatch(pattern) { - try { - const ext = pattern.replace('*', ''); - const files = fs.readdirSync(projectRoot); - return files.some(f => f.endsWith(ext)); - } catch { return false; } -} -``` - -Replace with: - -```javascript -function hasGlobMatch(pattern) { - const ext = pattern.replace('*', ''); - function search(dir, depth) { - if (depth > 3) return false; - try { - const entries = fs.readdirSync(dir, { withFileTypes: true }); - for (const entry of entries) { - if (entry.name.startsWith('.') || entry.name === 'node_modules') continue; - if (entry.isFile() && entry.name.endsWith(ext)) return true; - if (entry.isDirectory() && search(path.join(dir, entry.name), depth + 1)) return true; - } - } catch { /* skip unreadable dirs */ } - return false; - } - return search(projectRoot, 0); -} -``` - -**Step 2: Commit** - -```bash -git add scripts/detect-project.js -git commit -s -m "fix: recursive glob matching (depth 3) for .csproj/.sln detection" -``` - ---- - -### Task 6: Validate browser arg in run-test.js - -**Files:** -- Modify: `skills/e2e-test/scripts/run-test.js` - -**Step 1: Add browser validation after flag parsing** - -Find the browser parsing line (around line 55): - -```javascript -const browser = browserIdx >= 0 ? args[browserIdx + 1] : 'chromium'; -``` - -Add validation immediately after: - -```javascript -const validBrowsers = ['chromium', 'firefox', 'webkit']; -if (!validBrowsers.includes(browser)) { - console.error(`Error: Invalid browser "${browser}". Must be one of: ${validBrowsers.join(', ')}`); - process.exit(1); -} -``` - -**Step 2: Commit** - -```bash -git add skills/e2e-test/scripts/run-test.js -git commit -s -m "fix: validate --browser arg against chromium/firefox/webkit whitelist" -``` - ---- - -### Task 7: Add configurable output directory - -**Files:** -- Modify: `settings.json` -- Modify: `scripts/detect-project.js` -- Modify: `scripts/save-artifact.js` - -**Step 1: Add outputDir to settings.json** - -Replace the full content of `settings.json`: - -```json -{ - "agent": "qa-reviewer", - "outputDir": "qa-artifacts" -} -``` - -**Step 2: Update detect-project.js to read outputDir from settings** - -At the top of `scripts/detect-project.js`, after the existing `const projectRoot` line, find: - -```javascript -const projectRoot = process.cwd(); -const configDir = path.join(projectRoot, 'qa-artifacts'); -``` - -Replace with: - -```javascript -const projectRoot = process.cwd(); - -// Read output directory from plugin settings -let outputDir = 'qa-artifacts'; -try { - const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || path.join(__dirname, '..'); - const settings = JSON.parse(fs.readFileSync(path.join(pluginRoot, 'settings.json'), 'utf8')); - if (settings.outputDir) outputDir = settings.outputDir; -} catch { /* use default */ } - -const configDir = path.join(projectRoot, outputDir); -``` - -Also update the `outputContext` function — find the line: - -```javascript - lines.push(`Config: qa-artifacts/.qa-config.json`); -``` - -Replace with: - -```javascript - lines.push(`Config: ${outputDir}/.qa-config.json`); - lines.push(`Output Directory: ${outputDir}/`); -``` - -Also in the config object, add the outputDir so skills can read it: - -Find: - -```javascript -const config = { - detectedAt: new Date().toISOString(), - projectRoot, -``` - -Replace with: - -```javascript -const config = { - detectedAt: new Date().toISOString(), - projectRoot, - outputDir, -``` - -**Step 3: Update save-artifact.js to read outputDir** - -In `scripts/save-artifact.js`, find: - -```javascript -const projectRoot = process.cwd(); -const configDir = path.join(projectRoot, 'qa-artifacts'); -``` - -Replace with: - -```javascript -const projectRoot = process.cwd(); - -// Read output directory from config or default -let outputDir = 'qa-artifacts'; -try { - const configPath = path.join(projectRoot, 'qa-artifacts', '.qa-config.json'); - const config = JSON.parse(fs.readFileSync(configPath, 'utf8')); - if (config.outputDir) outputDir = config.outputDir; -} catch { /* use default */ } - -const configDir = path.join(projectRoot, outputDir); -``` - -**Step 4: Commit** - -```bash -git add settings.json scripts/detect-project.js scripts/save-artifact.js -git commit -s -m "feat: configurable output directory via settings.json outputDir" -``` - ---- - -### Task 8: Add skill cross-referencing - -**Files:** -- Modify: `skills/pr-review/SKILL.md` -- Modify: `skills/bug-report/SKILL.md` -- Modify: `skills/test-cases/SKILL.md` -- Modify: `skills/api-test/SKILL.md` -- Modify: `skills/e2e-test/SKILL.md` -- Modify: `skills/regression-planner/SKILL.md` -- Modify: `skills/accessibility/SKILL.md` -- Modify: `skills/release-readiness/SKILL.md` -- Modify: `skills/test-data/SKILL.md` -- Modify: `skills/setup/SKILL.md` - -**Step 1: Add "Suggested Next Steps" section to each skill** - -Append to the end of each SKILL.md (before any existing final section or at the very end): - -**`skills/pr-review/SKILL.md`** — append: - -```markdown -## Suggested Next Steps -After generating the review, suggest based on results: -- If Risk Level is **Medium or higher**: "Consider running `/qa-toolkit:regression-planner` to map the impact radius and plan targeted regression testing." -- Always: "Generate test cases for the changed functionality with `/qa-toolkit:test-cases`." -``` - -**`skills/bug-report/SKILL.md`** — append: - -```markdown -## Suggested Next Steps -After generating the bug report, suggest: -- "Create test cases to cover this bug scenario and prevent regression with `/qa-toolkit:test-cases`." -``` - -**`skills/test-cases/SKILL.md`** — append: - -```markdown -## Suggested Next Steps -After generating test cases, suggest: -- "Generate synthetic test data for these scenarios with `/qa-toolkit:test-data`." -- "Automate the P0/P1 cases as Playwright E2E tests with `/qa-toolkit:e2e-test`." -``` - -**`skills/api-test/SKILL.md`** — append: - -```markdown -## Suggested Next Steps -After generating API tests, suggest: -- "Generate realistic test payloads with `/qa-toolkit:test-data`." -``` - -**`skills/e2e-test/SKILL.md`** — append: - -```markdown -## Suggested Next Steps -After generating E2E tests, suggest: -- "Run an accessibility audit on the same pages with `/qa-toolkit:accessibility`." -``` - -**`skills/regression-planner/SKILL.md`** — append: - -```markdown -## Suggested Next Steps -After generating the regression plan, suggest: -- "When regression testing is complete, assess release readiness with `/qa-toolkit:release-readiness`." -``` - -**`skills/accessibility/SKILL.md`** — append: - -```markdown -## Suggested Next Steps -After generating the audit, suggest: -- "File each critical/major finding as a bug report with `/qa-toolkit:bug-report`." -``` - -**`skills/release-readiness/SKILL.md`** — append: - -```markdown -## Suggested Next Steps -After generating the assessment, suggest based on results: -- If verdict is **NO-GO** or Regression Score is below 70: "Plan targeted regression testing with `/qa-toolkit:regression-planner`." -``` - -**`skills/test-data/SKILL.md`** — no cross-reference needed, skip. - -**`skills/setup/SKILL.md`** — append: - -```markdown -## Suggested Next Steps -After setup is complete, suggest: -- "Start with a PR review (`/qa-toolkit:pr-review`) or generate test cases from your requirements (`/qa-toolkit:test-cases`)." -``` - -**Step 2: Commit** - -```bash -git add skills/*/SKILL.md -git commit -s -m "feat: add contextual Suggested Next Steps cross-references to all skills" -``` - ---- - -### Task 9: Add CLAUDE.md for the plugin repo - -**Files:** -- Create: `CLAUDE.md` - -**Step 1: Create CLAUDE.md at repo root** - -```markdown -# QA Toolkit — Development Guide - -## What This Is - -A Claude Code plugin providing 10 QA skills (slash commands) and 3 agent personas. Auto-detects project tech stack and produces structured QA artifacts. - -## Project Structure - -``` -.claude-plugin/plugin.json — Plugin manifest (name, version, metadata) -settings.json — Default agent and plugin settings -hooks/hooks.json — Event hooks (SessionStart, Stop) -scripts/detect-project.js — Auto-detection script (runs on SessionStart) -scripts/save-artifact.js — Activity logger (runs on Stop) -agents/.md — Agent persona definitions (conversational, multi-turn) -skills//SKILL.md — Skill definitions (one-shot structured output) -skills//references/ — Domain-specific knowledge files -skills//scripts/ — Helper scripts (e.g., Playwright runner) -``` - -## Conventions - -### Skills -- `SKILL.md` must have YAML frontmatter with `name` and `description` (one sentence) -- Skills produce one-shot structured output and save to the configured output directory -- Each skill reads `/.qa-config.json` for project context -- Reference files contain non-obvious, specific guidance — not generic info -- Include a "Suggested Next Steps" section with conditional cross-references to related skills - -### Agents -- Agent `.md` files have YAML frontmatter with `name` and `description` -- Agents define personas for conversational, multi-turn QA work (ongoing review sessions, exploratory discussions) -- Agents define tone and expertise, not workflows — workflows belong in skills - -### Scripts -- All scripts are Node.js with no external dependencies (stdlib only) -- Scripts read `settings.json` for plugin-level config (e.g., `outputDir`) -- The output directory defaults to `qa-artifacts/` and is configurable via `settings.json` - -## Testing Locally - -```bash -claude plugin add ./qa-toolkit -claude --debug --plugin-dir ./qa-toolkit -``` - -## Output Directory - -All generated artifacts save to `/` (default: `qa-artifacts/`) in the target project. Subdirectories are created lazily on first artifact save, not eagerly on session start. -``` - -**Step 2: Commit** - -```bash -git add CLAUDE.md -git commit -s -m "docs: add CLAUDE.md with plugin development conventions" -``` - ---- - -### Task 10: Clarify agent/skill boundary - -**Files:** -- Modify: `agents/qa-reviewer.md` -- Modify: `agents/qa-explorer.md` -- Modify: `agents/qa-lead.md` -- Modify: `README.md` - -**Step 1: Update agent frontmatter descriptions to clarify they're for multi-turn work** - -**`agents/qa-reviewer.md`** — change the frontmatter `description` to: - -```yaml -description: Conversational QA reviewer for multi-turn PR review sessions — translates code changes into testing impact through interactive discussion -``` - -**`agents/qa-explorer.md`** — change the frontmatter `description` to: - -```yaml -description: Conversational exploratory testing persona for multi-turn sessions — generates edge cases and test scenarios through interactive discussion -``` - -**`agents/qa-lead.md`** — change the frontmatter `description` to: - -```yaml -description: Conversational QA lead for multi-turn strategic sessions — release decisions, quality metrics, and test planning through interactive discussion -``` - -**Step 2: Add "Agents vs Skills" section to README.md** - -After the "## Agents" section and before "## Install", add: - -```markdown -## Agents vs Skills - -**Skills** (`/qa-toolkit:*`) produce **one-shot structured output** — you describe what you need, you get a formatted artifact saved to disk. Use these for specific deliverables: a PR review, a bug report, a test plan. - -**Agents** are **conversational personas** for multi-turn interactive work. Use these when you want an ongoing QA discussion: "walk me through this PR," "help me explore edge cases for this feature," "let's assess whether we're ready to release." Agents remember context across the conversation and adapt their guidance as you share more information. - -| Need | Use | -|------|-----| -| Structured PR review document | `/qa-toolkit:pr-review` (skill) | -| Interactive PR walkthrough with Q&A | `qa-reviewer` (agent) | -| Bug report from a description | `/qa-toolkit:bug-report` (skill) | -| Brainstorm what could break in a feature | `qa-explorer` (agent) | -| Go/no-go release document | `/qa-toolkit:release-readiness` (skill) | -| Strategic release planning discussion | `qa-lead` (agent) | -``` - -**Step 3: Commit** - -```bash -git add agents/*.md README.md -git commit -s -m "docs: clarify agent vs skill boundary — agents are conversational, skills are one-shot" -``` - ---- - -### Task 11: Update CHANGELOG.md - -**Files:** -- Modify: `CHANGELOG.md` - -**Step 1: Add v1.1.0 entry** - -Prepend to `CHANGELOG.md` after the `# Changelog` header: - -```markdown -## [1.1.0] — 2026-02-23 - -### Fixed -- Replace invalid `TaskCompleted` hook event with `Stop` — activity logging now works -- Remove dead `detectors.frameworks` and `detectors.testFrameworks` arrays in detect-project.js -- Stop eagerly creating 9 empty artifact subdirectories on session start -- Parse pyproject.toml dependencies by TOML section instead of regex-matching all quoted strings -- Recursive glob matching (depth 3) for .csproj/.sln detection in subdirectories -- Validate `--browser` argument in run-test.js against chromium/firefox/webkit - -### Added -- Configurable output directory via `settings.json` `outputDir` field -- Contextual "Suggested Next Steps" cross-references in all skills -- CLAUDE.md with plugin development conventions -- "Agents vs Skills" section in README clarifying when to use each -``` - -**Step 2: Commit** - -```bash -git add CHANGELOG.md -git commit -s -m "docs: add v1.1.0 changelog entry" -``` diff --git a/docs/plans/2026-03-06-docs-github-pages-design.md b/docs/plans/2026-03-06-docs-github-pages-design.md deleted file mode 100644 index c5b7887..0000000 --- a/docs/plans/2026-03-06-docs-github-pages-design.md +++ /dev/null @@ -1,131 +0,0 @@ -# Design: Docs Rewrite + GitHub Pages - -**Date:** 2026-03-06 -**Status:** Approved - -## Problem - -QA Toolkit v2.0 shipped 9 phases of work — 5 new skills, redesigned agents, a state-aware system, shared references, and multi-format output — but the docs still reflect v1.1.0. The README lists 10 commands (v2 has 15). The CHANGELOG has no v2.0 entry. CONTRIBUTING.md doesn't mention any v2 conventions. There is no public-facing site. - -## Goal - -1. Rewrite README, CHANGELOG, and CONTRIBUTING with a new narrative that appeals to both QA professionals and developers. -2. Launch a GitHub Pages site (`docs/index.html`) that serves as a captivating landing page and full reference — no build step required. - -## Approach: README-First (Single Source of Truth) - -Fix the README as the authoritative source. The GitHub Pages site renders that content with a dramatically improved visual design. Update one, the other stays current in spirit. - ---- - -## Doc Fixes - -### README.md — Full Rewrite - -**Narrative shift:** From "a plugin that produces QA artifacts" to "QA that thinks for itself." - -**Structure:** -``` -[centered header + one-liner + badges] -[quick install one-liner] -[2–3 punchy social-proof quotes] -[Why I Built This — short, honest, personal] -[How It Works — 3-step flow with terminal example] -[Commands — grouped by phase: Authoring / Review / Release / Analysis] -[Agents — "when you need a conversation, not a document"] -[What's New in v2.0 — state-awareness, 15 skills, redesigned agents] -[Output — artifact directory tree] -[Permissions & Side Effects] -[Install options] -[License] -``` - -**Tone:** Direct, slightly irreverent, anti-enterprise. Speaks to both the developer who also does QA and the dedicated QA lead. - -**Key additions vs current:** -- All 15 skills (current README lists 10 — missing test-plan, exploratory-testing, coverage-gap, risk-prioritization, flaky-test-diagnosis) -- Commands grouped by workflow phase instead of flat table -- v2.0 state-aware system explained in plain language -- Badges: install, GitHub stars, license, CI status -- Personal founder voice in "Why I Built This" - -### CHANGELOG.md — Add v2.0 Entry - -Written as a narrative summary (not just bullets) that tells the story of what changed and why. Covers: -- State-aware skill system -- 5 new skills (test-plan, exploratory-testing, coverage-gap, risk-prioritization, flaky-test-diagnosis) -- 3 redesigned skills (e2e-test, bug-report, api-test, regression-planner, pr-review) -- Redesigned agents (tool restrictions, return contracts, persistent memory) -- Shared references system (`skills/shared/references/`) -- Multi-format output -- Test suite updates - -### CONTRIBUTING.md — Rewrite - -Friendlier tone, structured as "here's how it all fits together." Adds: -- State-aware skill pattern: read `.qa-config.json` → adapt output → write findings -- Shared references in `skills/shared/references/` and when to use them -- v2 agent conventions: tool restrictions, return contracts, persistent memory -- Updated skill creation steps reflecting v2 conventions - ---- - -## GitHub Pages Site - -### Tech Stack - -Pure HTML/CSS/JS in `docs/` folder. GitHub Pages serves from `docs/` on `main` branch — no build step, no CI, no config files needed. - -### Visual Direction - -- Dark background (`#0d0d0d`), monospace font for terminal aesthetic -- Accent color: electric amber (`#f59e0b`) — warm, readable, distinct from GSD green -- Hero: full-viewport, animated CSS typewriter showing a `/qa-toolkit:bug-report` invocation and artifact output -- Command grid: card-based layout grouped by workflow phase, hover reveals description -- Smooth scroll, anchor navigation at top - -### Page Sections - -``` -[Hero — headline + install one-liner + terminal animation] -[Social proof strip — 2–3 quotes] -[How It Works — 3-step visual flow] -[Commands — card grid, grouped by phase] -[Agents — 3 cards with persona descriptions] -[v2.0 callout strip — "What's new"] -[Install — code block + link to GitHub] -[Footer — license, GitHub link] -``` - -### File Layout - -``` -docs/ -├── index.html # Single page, all content inline -├── style.css # Extracted styles -└── assets/ - └── terminal.svg # Optional animated terminal demo -``` - -### GitHub Pages Activation - -Enable via: repo Settings → Pages → Source: `docs/` folder on `main` branch. -No `_config.yml` needed for plain HTML. - ---- - -## Implementation Phases - -1. **CHANGELOG.md** — add v2.0 entry (lowest risk, no structural changes) -2. **CONTRIBUTING.md** — rewrite with v2 conventions -3. **README.md** — full rewrite with new narrative and all 15 skills -4. **docs/index.html + style.css** — build GitHub Pages site -5. **GitHub Pages** — enable in repo settings, verify deploy - -## Success Criteria - -- All 15 skills documented in README -- CHANGELOG has a v2.0 entry -- CONTRIBUTING reflects v2 conventions -- GitHub Pages site live and visually compelling -- No broken links or missing content diff --git a/docs/plans/2026-03-06-docs-github-pages-plan.md b/docs/plans/2026-03-06-docs-github-pages-plan.md deleted file mode 100644 index 6eea664..0000000 --- a/docs/plans/2026-03-06-docs-github-pages-plan.md +++ /dev/null @@ -1,916 +0,0 @@ -# Docs Rewrite + GitHub Pages Implementation Plan - -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. - -**Goal:** Rewrite README, CHANGELOG, and CONTRIBUTING for v2.0 accuracy and appeal, then build a captivating GitHub Pages landing page in `docs/`. - -**Architecture:** README-first — fix the authoritative source docs, then build the site from that content. Five sequential tasks, each committed independently. No build step; GitHub Pages serves `docs/index.html` directly from `main`. - -**Tech Stack:** Markdown (README/CHANGELOG/CONTRIBUTING), HTML/CSS/JS (GitHub Pages site), GitHub Pages (hosting). - -**Design doc:** `docs/plans/2026-03-06-docs-github-pages-design.md` - ---- - -### Task 1: CHANGELOG.md — Add v2.0 Entry - -**Files:** -- Modify: `CHANGELOG.md` - -**Context:** The CHANGELOG currently ends at `[1.1.0]`. The v2.0 commit `afaaf2d` is undocumented. v2.0 added: 5 new skills (test-plan, exploratory-testing, coverage-gap, risk-prioritization, flaky-test-diagnosis), redesigned 5 existing skills (e2e-test, bug-report, api-test, regression-planner, pr-review), redesigned 3 agents with tool restrictions/return contracts/persistent memory, a state-aware system, shared references (`skills/shared/references/`), and multi-format output. - -**Step 1: Read the current CHANGELOG** - -Read `CHANGELOG.md` fully before editing. - -**Step 2: Prepend the v2.0 entry** - -Add above `## [1.1.0]`: - -```markdown -## [2.0.0] — 2026-03-06 - -QA Toolkit v2.0 is a ground-up rethink of how the plugin operates. The core idea: every skill now reads your project state before producing output, so artifacts build on each other rather than starting cold every time. - -### Added -- **State-aware skill system** — all skills read `.qa-config.json` on invocation, adapt output to detected stack, and write findings back so subsequent skills have context -- **Shared references** (`skills/shared/references/`) — `context-preamble.md`, `state-integration.md`, `output-formats.md`, `artifact-organization.md` loaded by all skills to enforce consistent behavior -- **5 new skills**: `test-plan`, `exploratory-testing`, `coverage-gap`, `risk-prioritization`, `flaky-test-diagnosis` -- **Multi-format output** — skills produce output in the format best suited to the artifact type (Markdown reports, Gherkin, cURL/Postman/Playwright, JSON/CSV/SQL, etc.) -- **Redesigned agents** — `qa-reviewer`, `qa-lead`, `qa-explorer` rebuilt with explicit tool restrictions, typed return contracts, and persistent memory across turns - -### Changed -- **5 redesigned skills**: `e2e-test`, `bug-report`, `api-test`, `regression-planner`, `pr-review` — all updated for state-awareness and multi-format output -- Agent personas now define tool access boundaries (not just tone), making subagent behavior predictable and composable - -### Fixed -- Updated test suite to match v2 skill behavior (stale v1.x assertions removed) - -``` - -**Step 3: Verify** - -Read `CHANGELOG.md` to confirm the entry is correct and formatting matches existing style. - -**Step 4: Commit** - -```bash -git add CHANGELOG.md -git commit -s -m "docs: add v2.0 changelog entry" -``` - ---- - -### Task 2: CONTRIBUTING.md — Rewrite for v2 Conventions - -**Files:** -- Modify: `CONTRIBUTING.md` - -**Context:** Current CONTRIBUTING.md is a short step-list that doesn't mention state-aware patterns, shared references, or v2 agent conventions. Rewrite it to be friendlier and reflect how the plugin actually works in v2. - -**Step 1: Read the current CONTRIBUTING.md** - -Read `CONTRIBUTING.md` fully. - -**Step 2: Also read the shared reference files for accuracy** - -Read these to understand what to document: -- `skills/shared/references/state-integration.md` -- `skills/shared/references/context-preamble.md` -- `skills/shared/references/output-formats.md` - -**Step 3: Write the new CONTRIBUTING.md** - -Full replacement. Content: - -```markdown -# Contributing - -## How It All Fits Together - -QA Toolkit is a Claude Code plugin. It has three moving parts: - -- **Skills** (`skills//SKILL.md`) — one-shot slash commands that produce structured QA artifacts -- **Agents** (`agents/.md`) — conversational personas for multi-turn QA work -- **Scripts** (`scripts/`) — Node.js hooks that run on session start/end (auto-detection, activity logging) - -All skills follow the **state-aware pattern**: read project context from `.qa-config.json` → adapt output to the detected stack → write findings back so the next skill has more to work with. - -## How to Contribute - -1. Fork the repository -2. Create a feature branch: `git checkout -b feature/your-feature` -3. Make your changes following the conventions below -4. Run the test suite: `node --test tests/*.test.js` -5. Test locally: `claude --plugin-dir ./qa-toolkit` -6. Submit a pull request - -## Adding a New Skill - -### Minimum structure - -``` -skills// -├── SKILL.md # Required: skill definition with frontmatter -└── references/ # Optional: non-obvious domain knowledge - └── your-reference.md -``` - -### SKILL.md conventions - -- YAML frontmatter must have `name` and `description` (one sentence max) -- Begin with the context preamble: load `skills/shared/references/context-preamble.md` to read project state -- Adapt output based on detected `languages`, `frameworks`, `testFrameworks` from `.qa-config.json` -- Save artifacts to `//` (read `outputDir` from `.qa-config.json`) -- End with a "Suggested Next Steps" section with conditional cross-references to related skills - -### State-aware pattern - -Every skill should follow this flow: - -1. **Read state** — check if `.qa-config.json` exists; if yes, load it for stack context -2. **Adapt output** — use detected frameworks to shape format (e.g., Jest vs Pytest syntax, Jira vs GitHub Issues format) -3. **Write findings** — append relevant findings to a skill-specific log in `/` so subsequent skills have more context - -See `skills/shared/references/state-integration.md` for the full pattern with examples. - -### Reference files - -Put reference files in `skills//references/` only when they contain **non-obvious, specific guidance** that Claude wouldn't already know. Generic QA knowledge doesn't belong here. - -Shared references that apply to all skills live in `skills/shared/references/` — don't duplicate them per-skill. - -## Adding a New Agent - -``` -agents/.md # Required: agent definition with frontmatter -``` - -### Agent conventions (v2) - -- YAML frontmatter must have `name` and `description` -- Define the **persona and tool access boundaries**, not the workflow — workflows belong in skills -- Specify **tool restrictions**: which tools the agent may and may not use -- Define a **return contract**: what the agent always returns at the end of each turn (e.g., a summary, a next-step prompt, a structured finding) -- Agents have **persistent memory** across turns — design the persona to accumulate context, not start fresh each turn - -## Scripts - -- All scripts are Node.js with no external dependencies (stdlib only), CommonJS format -- Scripts read `settings.json` for plugin-level config (`outputDir`, `hooksEnabled`) -- Hook scripts run on `SessionStart` and `Stop` events - -## Testing - -```bash -node --test tests/*.test.js -``` - -Tests use Node.js built-in test runner (zero dependencies). When adding a skill or modifying a script, add or update the corresponding test in `tests/`. - -## Local Development - -```bash -claude --debug --plugin-dir ./qa-toolkit -``` - -The `--debug` flag shows hook execution and skill loading in the Claude Code output. -``` - -**Step 4: Verify** - -Read `CONTRIBUTING.md` to confirm it's complete and accurate. - -**Step 5: Commit** - -```bash -git add CONTRIBUTING.md -git commit -s -m "docs: rewrite CONTRIBUTING for v2 conventions and friendlier tone" -``` - ---- - -### Task 3: README.md — Full Rewrite - -**Files:** -- Modify: `README.md` - -**Context:** Full narrative rewrite. Speaks to both developers and QA leads. GSD-inspired: punchy, personal, anti-enterprise. All 15 skills documented, grouped by workflow phase. Badges, social proof, personal founder voice. - -**Step 1: Read the current README.md** - -Read `README.md` fully before rewriting. - -**Step 2: Also read all 15 SKILL.md descriptions for accuracy** - -Read the `description` field from frontmatter of each SKILL.md to get accurate one-liners: -- `skills/setup/SKILL.md` -- `skills/pr-review/SKILL.md` -- `skills/bug-report/SKILL.md` -- `skills/test-cases/SKILL.md` -- `skills/api-test/SKILL.md` -- `skills/e2e-test/SKILL.md` -- `skills/regression-planner/SKILL.md` -- `skills/accessibility/SKILL.md` -- `skills/release-readiness/SKILL.md` -- `skills/test-data/SKILL.md` -- `skills/test-plan/SKILL.md` -- `skills/exploratory-testing/SKILL.md` -- `skills/coverage-gap/SKILL.md` -- `skills/risk-prioritization/SKILL.md` -- `skills/flaky-test-diagnosis/SKILL.md` - -And agent descriptions: -- `agents/qa-reviewer.md` -- `agents/qa-explorer.md` -- `agents/qa-lead.md` - -**Step 3: Write the new README.md** - -Full replacement following this structure: - -```markdown -
- -# QA Toolkit - -**QA that thinks for itself.** - -Describe what you're testing. Get a structured, stack-aware artifact — instantly. - -[![Plugin](https://img.shields.io/badge/claude--plugin-qa--toolkit-blue?style=for-the-badge)](https://github.com/cyberwalk3r/qa-toolkit) -[![License](https://img.shields.io/badge/license-MIT-green?style=for-the-badge)](LICENSE) -[![CI](https://img.shields.io/github/actions/workflow/status/cyberwalk3r/qa-toolkit/test.yml?branch=main&style=for-the-badge&label=Tests)](https://github.com/cyberwalk3r/qa-toolkit/actions) - -
- -\`\`\`bash -claude plugin add github:cyberwalk3r/qa-toolkit -\`\`\` - -
- -*"Finally — bug reports that don't need three rounds of editing."* - -*"I stopped dreading PR reviews. It just does them."* - -*"Replaced half my QA templates in a week."* - -
- ---- - -## Why I Built This - -QA work is repetitive in the worst way. Every bug report needs the same structure. Every PR review needs the same checks. Every regression plan needs the same risk analysis. And every team member does it differently. - -I wanted a tool that handles the formatting so you can focus on the judgment. Describe what you're testing in plain English — get back something you can actually use. - -So I built QA Toolkit. It auto-detects your stack, remembers your project context, and produces consistent QA artifacts every time. Whether you're a dedicated QA lead or a developer wearing the QA hat, it meets you where you are. - ---- - -## How It Works - -**1. Install the plugin** -```bash -claude plugin add github:cyberwalk3r/qa-toolkit -``` - -**2. Open any project** - -On session start, QA Toolkit scans your project — languages, frameworks, test tools, CI/CD — and saves the context to `qa-artifacts/.qa-config.json`. No prompts. No setup. - -**3. Describe what you need** -``` -/qa-toolkit:bug-report The checkout page crashes when I enter a long address -``` - -You get back a fully structured bug report: severity classification, reproduction steps, expected vs actual, environment fields, and duplicate search terms — formatted for your bug tracker. - ---- - -## Commands - -### Authoring -| Command | What You Get | -|---------|-------------| -| `/qa-toolkit:test-cases` | Test cases from requirements — table, Gherkin, or checklist | -| `/qa-toolkit:test-plan` | Full test plan with scope, strategy, and coverage targets | -| `/qa-toolkit:test-data` | Synthetic test data — JSON, CSV, or SQL | -| `/qa-toolkit:e2e-test` | Playwright test scaffold with line-by-line comments | -| `/qa-toolkit:api-test` | API test suite — cURL, Postman collection, or Playwright | - -### Review -| Command | What You Get | -|---------|-------------| -| `/qa-toolkit:pr-review` | Risk-flagged PR review with plain-English summary and QA checklist | -| `/qa-toolkit:bug-report` | Structured bug report from a casual description | -| `/qa-toolkit:exploratory-testing` | Exploratory test charters with session-based heuristics | - -### Release -| Command | What You Get | -|---------|-------------| -| `/qa-toolkit:regression-planner` | Risk-based regression plan with time estimates | -| `/qa-toolkit:release-readiness` | Go/no-go assessment with quality gate scoring | -| `/qa-toolkit:risk-prioritization` | Ranked risk matrix across features and change areas | - -### Analysis -| Command | What You Get | -|---------|-------------| -| `/qa-toolkit:coverage-gap` | Coverage gap analysis against requirements or test plan | -| `/qa-toolkit:flaky-test-diagnosis` | Root cause analysis for flaky tests with fix recommendations | -| `/qa-toolkit:accessibility` | WCAG 2.1 audit with plain-English manual test scripts | -| `/qa-toolkit:setup` | Read project docs, confirm detection, save preferences | - ---- - -## Agents - -Three QA personas for multi-turn interactive work — use these when you want a conversation, not a document. - -| Agent | Use When | -|-------|----------| -| `qa-reviewer` | Walk me through this PR. What should I test? | -| `qa-explorer` | Help me find edge cases in this new feature | -| `qa-lead` | Let's decide if we're ready to release | - -Agents remember context across the conversation and adapt as you share more. - -### Skills vs Agents - -**Skills** (`/qa-toolkit:*`) produce **one-shot structured artifacts** — saved to disk, formatted, done. - -**Agents** are **conversational** — use them for ongoing discussion, decision-making, and exploratory work. - ---- - -## What's New in v2.0 - -**State-aware skills.** Every command now reads your detected project context before producing output. It knows you're using Jest, not Pytest. It knows your CI is GitHub Actions. It knows what artifacts you've already generated this session. - -**15 skills** (up from 10). New: `test-plan`, `exploratory-testing`, `coverage-gap`, `risk-prioritization`, `flaky-test-diagnosis`. - -**Redesigned agents.** `qa-reviewer`, `qa-lead`, and `qa-explorer` now have explicit tool boundaries, typed return contracts, and persistent memory. Their behavior is predictable and composable. - ---- - -## Output - -Everything saves to `qa-artifacts/` in your project root (configurable via `settings.json`): - -``` -qa-artifacts/ -├── .qa-config.json # Auto-detected project config -├── .qa-activity.log # Session activity log -├── pr-reviews/ -├── bug-reports/ -├── test-cases/ -├── test-plans/ -├── api-tests/ -├── regression-plans/ -├── test-data/ -├── a11y-audits/ -├── release-assessments/ -├── e2e-tests/ -├── coverage-gaps/ -├── risk-analyses/ -└── flaky-diagnoses/ -``` - -### .qa-config.json Schema - -| Field | Type | Description | -|-------|------|-------------| -| `detectedAt` | string | ISO 8601 timestamp | -| `projectRoot` | string | Absolute path to project directory | -| `outputDir` | string | Configured output directory name | -| `languages` | string[] | Detected languages | -| `frameworks` | string[] | Detected frameworks | -| `testFrameworks` | string[] | Detected test tools | -| `cicd` | string[] | Detected CI/CD systems | -| `packageManager` | string\|null | Detected package manager | -| `hasClaudeMd` | boolean | Whether CLAUDE.md exists | -| `hasReadme` | boolean | Whether README.md exists | -| `existingDocs` | object[] | Detected documentation files | -| `existingTestDirs` | string[] | Detected test directories | - -**Note:** `projectRoot` is machine-specific — don't commit `.qa-config.json` to version control. The config is cached for 24 hours; delete it to force re-detection. - ---- - -## Permissions & Side Effects - -The plugin ships a `.claude/settings.local.json` that pre-approves `Bash(git:*)` for git operations used by the PR review skill. You'll see these permissions listed on install and can revoke them at any time. - -**Automatic behavior:** -- **Session start:** Scans project marker files, writes `qa-artifacts/.qa-config.json`. No network calls. -- **Session end:** Logs which artifacts were created/modified to `qa-artifacts/.qa-activity.log`. No network calls. - -**To disable hooks** without removing the plugin: -```json -{ - "agent": "qa-reviewer", - "outputDir": "qa-artifacts", - "hooksEnabled": false -} -``` - ---- - -## Install - -```bash -# From GitHub -claude plugin add github:cyberwalk3r/qa-toolkit - -# Local development -claude plugin add ./qa-toolkit -``` - ---- - -## Works With Your Existing Setup - -- **Respects existing CLAUDE.md** — reads it for context, never overwrites -- **Reads your docs** — TESTING.md, API specs, PR templates -- **Detects your test tools** — Jest, Pytest, Playwright, Cypress, Vitest, Selenium -- **Adapts to your stack** — React, Next.js, Django, FastAPI, .NET, Spring, Go, and more - ---- - -## License - -MIT -``` - -**Step 4: Verify** - -Read `README.md` to confirm: -- All 15 skills are present and grouped correctly -- No broken markdown tables -- v2.0 section is accurate -- Install commands are correct - -**Step 5: Commit** - -```bash -git add README.md -git commit -s -m "docs: rewrite README for v2.0 with new narrative and all 15 skills" -``` - ---- - -### Task 4: GitHub Pages Site - -**Files:** -- Create: `docs/index.html` -- Create: `docs/style.css` - -**Context:** Single-page marketing + docs site. Dark theme, amber accent, terminal aesthetic. Hero with CSS typewriter animation, command card grid, agent cards, install section. No build step — GitHub Pages serves these directly. - -**Step 1: Create `docs/style.css`** - -```css -/* Reset & base */ -*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } - -:root { - --bg: #0d0d0d; - --surface: #161616; - --border: #2a2a2a; - --amber: #f59e0b; - --amber-dim: #b45309; - --text: #e5e7eb; - --text-muted: #6b7280; - --code-bg: #1a1a1a; - --font-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace; - --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; -} - -html { scroll-behavior: smooth; } -body { background: var(--bg); color: var(--text); font-family: var(--font-sans); line-height: 1.6; } - -/* Nav */ -nav { - position: fixed; top: 0; left: 0; right: 0; z-index: 100; - background: rgba(13,13,13,0.9); backdrop-filter: blur(8px); - border-bottom: 1px solid var(--border); - padding: 0.75rem 2rem; - display: flex; align-items: center; justify-content: space-between; -} -nav .logo { font-family: var(--font-mono); color: var(--amber); font-weight: 700; font-size: 1rem; } -nav a { color: var(--text-muted); text-decoration: none; font-size: 0.875rem; margin-left: 2rem; transition: color 0.2s; } -nav a:hover { color: var(--amber); } - -/* Hero */ -.hero { - min-height: 100vh; display: flex; flex-direction: column; - align-items: center; justify-content: center; - padding: 6rem 2rem 4rem; text-align: center; -} -.hero h1 { font-family: var(--font-mono); font-size: clamp(2rem, 5vw, 3.5rem); font-weight: 700; letter-spacing: -0.02em; line-height: 1.1; } -.hero h1 span { color: var(--amber); } -.hero .tagline { font-size: clamp(1rem, 2vw, 1.25rem); color: var(--text-muted); margin: 1.5rem 0 2.5rem; max-width: 560px; } - -/* Install block */ -.install-block { - display: inline-flex; align-items: center; gap: 1rem; - background: var(--code-bg); border: 1px solid var(--border); - border-radius: 8px; padding: 0.875rem 1.5rem; - font-family: var(--font-mono); font-size: 0.9rem; - margin-bottom: 3rem; -} -.install-block .prompt { color: var(--amber); } -.copy-btn { - background: none; border: 1px solid var(--border); border-radius: 4px; - color: var(--text-muted); cursor: pointer; padding: 0.25rem 0.6rem; - font-size: 0.75rem; transition: all 0.2s; -} -.copy-btn:hover { border-color: var(--amber); color: var(--amber); } - -/* Terminal demo */ -.terminal { - width: 100%; max-width: 640px; margin: 0 auto; - background: var(--code-bg); border: 1px solid var(--border); - border-radius: 10px; overflow: hidden; text-align: left; -} -.terminal-bar { - background: var(--surface); padding: 0.75rem 1rem; - display: flex; align-items: center; gap: 0.5rem; - border-bottom: 1px solid var(--border); -} -.dot { width: 12px; height: 12px; border-radius: 50%; } -.dot.red { background: #ff5f57; } -.dot.yellow { background: #febc2e; } -.dot.green { background: #28c840; } -.terminal-title { font-size: 0.75rem; color: var(--text-muted); margin-left: auto; font-family: var(--font-mono); } -.terminal-body { padding: 1.25rem 1.5rem; font-family: var(--font-mono); font-size: 0.825rem; line-height: 1.7; } -.line-cmd { color: var(--amber); } -.line-out { color: #6b7280; } -.line-key { color: #34d399; } -.line-val { color: var(--text); } -.cursor { display: inline-block; width: 2px; height: 1em; background: var(--amber); animation: blink 1s step-end infinite; vertical-align: text-bottom; } -@keyframes blink { 50% { opacity: 0; } } - -/* Typewriter */ -.typewriter { overflow: hidden; white-space: nowrap; border-right: none; animation: typing 2s steps(52, end) 0.5s both; } -@keyframes typing { from { width: 0; } to { width: 100%; } } - -/* Quotes */ -.quotes { background: var(--surface); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); padding: 3rem 2rem; } -.quotes-inner { max-width: 900px; margin: 0 auto; display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 2rem; } -.quote { padding: 1.5rem; border: 1px solid var(--border); border-radius: 8px; } -.quote p { color: var(--text); font-size: 0.9rem; line-height: 1.6; margin-bottom: 1rem; } -.quote cite { font-size: 0.775rem; color: var(--text-muted); font-style: normal; } - -/* Sections */ -section { padding: 5rem 2rem; } -.container { max-width: 960px; margin: 0 auto; } -.section-label { font-family: var(--font-mono); font-size: 0.75rem; color: var(--amber); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 0.75rem; } -h2 { font-size: clamp(1.5rem, 3vw, 2rem); font-weight: 700; margin-bottom: 1rem; } -.section-sub { color: var(--text-muted); max-width: 560px; margin-bottom: 3rem; font-size: 0.95rem; } - -/* How it works */ -.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.5rem; } -.step { padding: 1.75rem; border: 1px solid var(--border); border-radius: 8px; position: relative; } -.step-num { font-family: var(--font-mono); font-size: 2rem; font-weight: 700; color: var(--amber); opacity: 0.3; margin-bottom: 0.75rem; } -.step h3 { font-size: 1rem; margin-bottom: 0.5rem; } -.step p { font-size: 0.875rem; color: var(--text-muted); } - -/* Commands */ -.phase-group { margin-bottom: 2.5rem; } -.phase-label { font-family: var(--font-mono); font-size: 0.7rem; color: var(--amber); text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 1rem; padding-bottom: 0.5rem; border-bottom: 1px solid var(--border); } -.command-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1rem; } -.command-card { - padding: 1.25rem; border: 1px solid var(--border); border-radius: 8px; - transition: border-color 0.2s, background 0.2s; cursor: default; -} -.command-card:hover { border-color: var(--amber-dim); background: var(--surface); } -.command-card code { font-family: var(--font-mono); font-size: 0.775rem; color: var(--amber); display: block; margin-bottom: 0.5rem; } -.command-card p { font-size: 0.825rem; color: var(--text-muted); } - -/* Agents */ -.agent-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.5rem; } -.agent-card { padding: 1.75rem; border: 1px solid var(--border); border-radius: 8px; } -.agent-card h3 { font-family: var(--font-mono); color: var(--amber); margin-bottom: 0.5rem; font-size: 0.9rem; } -.agent-card .role { font-size: 0.875rem; font-weight: 600; margin-bottom: 0.5rem; } -.agent-card p { font-size: 0.825rem; color: var(--text-muted); } - -/* v2 callout */ -.v2-callout { - background: linear-gradient(135deg, rgba(245,158,11,0.08), rgba(245,158,11,0.02)); - border: 1px solid rgba(245,158,11,0.3); border-radius: 12px; - padding: 2.5rem; margin-top: 2rem; -} -.v2-callout h3 { font-family: var(--font-mono); color: var(--amber); margin-bottom: 1rem; } -.v2-callout ul { list-style: none; display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0.5rem; } -.v2-callout li { font-size: 0.875rem; color: var(--text-muted); padding-left: 1rem; position: relative; } -.v2-callout li::before { content: '→'; position: absolute; left: 0; color: var(--amber); } - -/* Install section */ -.install-section { background: var(--surface); border-top: 1px solid var(--border); } -.code-block { - background: var(--code-bg); border: 1px solid var(--border); border-radius: 8px; - padding: 1.25rem 1.5rem; font-family: var(--font-mono); font-size: 0.85rem; - color: var(--text); margin-bottom: 1rem; white-space: pre; -} -.code-block .comment { color: var(--text-muted); } -.code-block .cmd { color: var(--amber); } - -/* Footer */ -footer { - border-top: 1px solid var(--border); padding: 2rem; - text-align: center; color: var(--text-muted); font-size: 0.8rem; -} -footer a { color: var(--text-muted); text-decoration: none; } -footer a:hover { color: var(--amber); } - -/* Responsive */ -@media (max-width: 640px) { - nav a { display: none; } - .install-block { flex-direction: column; gap: 0.5rem; } -} -``` - -**Step 2: Create `docs/index.html`** - -```html - - - - - - QA Toolkit — QA that thinks for itself - - - - - - - - -
-

QA that thinks for itself.

-

Describe what you're testing. Get a structured, stack-aware artifact — instantly. No templates. No formatting. No busywork.

- -
- $ - claude plugin add github:cyberwalk3r/qa-toolkit - -
- -
-
- - - - Claude Code -
-
-
> /qa-toolkit:bug-report The checkout page crashes with long addresses
-
-
Detecting project context...
-
Stack: React · Node.js · Jest · GitHub Actions
-
Tracker: GitHub Issues
-
-
Title: Checkout crashes on addresses > 60 chars [P1 - Critical]
-
Steps to reproduce:
-
  1. Navigate to /checkout
-
  2. Enter address longer than 60 characters
-
  3. Click "Place Order"
-
Expected: Order submitted successfully
-
Actual: TypeError: Cannot read property 'length'
-
-
Saved to qa-artifacts/bug-reports/2026-03-06-checkout-crash.md
- -
-
-
- - -
-
-
-

"Finally — bug reports that don't need three rounds of editing before they're usable."

- — QA Lead, fintech startup -
-
-

"I stopped dreading PR reviews. It reads the diff, flags the risks, writes the checklist. I just review the output."

- — Senior developer doubling as QA -
-
-

"Replaced half our QA templates in a week. The team is actually using them consistently for the first time."

- — Engineering manager -
-
-
- - -
-
- -

Three steps. That's it.

-

Install once. Open any project. It auto-detects your stack and gets to work.

-
-
-
01
-

Install the plugin

-

One command. Works with any project — React, Django, .NET, Go, whatever you're building.

-
-
-
02
-

Open your project

-

On session start, QA Toolkit scans your stack and saves context. Knows your frameworks, test tools, and CI setup automatically.

-
-
-
03
-

Describe what you need

-

Type a slash command in plain English. Get back a structured, formatted artifact saved to disk.

-
-
-
-
- - -
-
- -

15 slash commands. Every QA workflow covered.

-

Grouped by where they fit in your workflow. Each one produces a formatted artifact saved to qa-artifacts/.

- -
-
Authoring
-
-
/qa-toolkit:test-cases

Test cases from requirements — table, Gherkin, or checklist format

-
/qa-toolkit:test-plan

Full test plan with scope, strategy, and coverage targets

-
/qa-toolkit:test-data

Synthetic test data — JSON, CSV, or SQL

-
/qa-toolkit:e2e-test

Playwright test scaffold with line-by-line comments

-
/qa-toolkit:api-test

API test suite — cURL, Postman collection, or Playwright

-
-
- -
-
Review
-
-
/qa-toolkit:pr-review

Risk-flagged PR review with plain-English summary and QA checklist

-
/qa-toolkit:bug-report

Structured bug report from a casual description

-
/qa-toolkit:exploratory-testing

Exploratory test charters with session-based heuristics

-
-
- -
-
Release
-
-
/qa-toolkit:regression-planner

Risk-based regression plan with time estimates

-
/qa-toolkit:release-readiness

Go/no-go assessment with quality gate scoring

-
/qa-toolkit:risk-prioritization

Ranked risk matrix across features and change areas

-
-
- -
-
Analysis
-
-
/qa-toolkit:coverage-gap

Coverage gap analysis against requirements or test plan

-
/qa-toolkit:flaky-test-diagnosis

Root cause analysis for flaky tests with fix recommendations

-
/qa-toolkit:accessibility

WCAG 2.1 audit with plain-English manual test scripts

-
/qa-toolkit:setup

Read project docs, confirm detection, save preferences

-
-
-
-
- - -
-
- -

When you need a conversation, not a document.

-

Three QA personas for multi-turn interactive work. They remember context across the conversation and adapt as you share more.

-
-
-

qa-reviewer

-

The Code Reviewer's QA Brain

-

Walk me through this PR. What should I actually be testing? Translates code changes into testing impact in plain English.

-
-
-

qa-explorer

-

The Edge Case Hunter

-

Help me find what could break in this feature. Generates exploratory test charters and surfaces edge cases you wouldn't think to test.

-
-
-

qa-lead

-

The Release Decision Maker

-

Let's decide if we're ready to ship. Makes release decisions, plans regression scope, and produces executive summaries.

-
-
- -
-

What's New in v2.0

-
    -
  • State-aware skills — every command reads your detected project context
  • -
  • 15 skills — 5 new in v2: test-plan, exploratory-testing, coverage-gap, risk-prioritization, flaky-test-diagnosis
  • -
  • Redesigned agents — explicit tool boundaries, typed return contracts, persistent memory
  • -
  • Multi-format output — artifacts in the format that actually fits the deliverable
  • -
  • Shared references — consistent behavior across all skills
  • -
-
-
-
- - -
-
- -

One command to get started.

-

Works with any project. No configuration required.

-
# From GitHub -claude plugin add github:cyberwalk3r/qa-toolkit - -# Local development -claude plugin add ./qa-toolkit
-

On first session, auto-detection runs and saves your project context to qa-artifacts/.qa-config.json. Everything is ready.

-
-
- -
-

MIT License  ·  GitHub  ·  Built for Claude Code

-
- - - - - -``` - -**Step 3: Verify locally** - -Open `docs/index.html` in a browser (or use `python3 -m http.server 8080 --directory docs`) and check: -- Hero renders correctly with typewriter animation -- All 15 command cards are present and grouped -- 3 agent cards show -- Install section is correct -- No broken layout on mobile width - -**Step 4: Commit** - -```bash -git add docs/index.html docs/style.css -git commit -s -m "feat: add GitHub Pages site with landing page and full command reference" -``` - ---- - -### Task 5: Enable GitHub Pages - -**Files:** None (GitHub repo settings) - -**Step 1: Push to remote** - -```bash -git push origin main -``` - -**Step 2: Enable GitHub Pages** - -In the GitHub repo: -1. Go to Settings → Pages -2. Source: Deploy from branch -3. Branch: `main`, folder: `/docs` -4. Click Save - -**Step 3: Verify** - -After ~60 seconds, the site will be live at `https://cyberwalk3r.github.io/qa-toolkit/`. - -Check: -- Site loads -- Navigation links work -- Terminal animation plays -- Install copy button works - -**Step 4: Add site URL to README** - -Add the Pages URL to `README.md` — either as a badge or a link in the header section. - -```bash -git add README.md -git commit -s -m "docs: add GitHub Pages site link to README" -``` diff --git a/docs/style.css b/docs/style.css index 46422ed..57c6685 100644 --- a/docs/style.css +++ b/docs/style.css @@ -3,157 +3,597 @@ :root { --bg: #0d0d0d; - --surface: #161616; - --border: #2a2a2a; + --surface: #141414; + --surface-2: #1a1a1a; + --border: #252525; + --border-hover: rgba(245,158,11,0.45); --amber: #f59e0b; - --amber-dim: #b45309; + --amber-dim: #d97706; + --amber-glow: rgba(245,158,11,0.12); + --green: #34d399; --text: #e5e7eb; --text-muted: #6b7280; - --code-bg: #1a1a1a; + --code-bg: #111111; --font-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace; --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + --radius: 10px; + --radius-sm: 6px; + --ease: cubic-bezier(0.22, 1, 0.36, 1); } html { scroll-behavior: smooth; } -body { background: var(--bg); color: var(--text); font-family: var(--font-sans); line-height: 1.6; } +body { + background: var(--bg); + color: var(--text); + font-family: var(--font-sans); + line-height: 1.6; + overflow-x: hidden; +} -/* Nav */ +/* ===================== NAV ===================== */ nav { position: fixed; top: 0; left: 0; right: 0; z-index: 100; - background: rgba(13,13,13,0.9); backdrop-filter: blur(8px); + background: rgba(13,13,13,0.82); + backdrop-filter: blur(16px) saturate(180%); + -webkit-backdrop-filter: blur(16px) saturate(180%); border-bottom: 1px solid var(--border); padding: 0.75rem 2rem; display: flex; align-items: center; justify-content: space-between; } -nav .logo { font-family: var(--font-mono); color: var(--amber); font-weight: 700; font-size: 1rem; } -nav a { color: var(--text-muted); text-decoration: none; font-size: 0.875rem; margin-left: 2rem; transition: color 0.2s; } -nav a:hover { color: var(--amber); } +nav .logo { + font-family: var(--font-mono); + color: var(--amber); + font-weight: 700; + font-size: 1rem; + letter-spacing: -0.02em; +} +.nav-links a { + color: var(--text-muted); + text-decoration: none; + font-size: 0.875rem; + margin-left: 2rem; + transition: color 0.18s ease; +} +.nav-links a:hover { color: var(--amber); } -/* Hero */ +/* ===================== HERO ===================== */ .hero { - min-height: 100vh; display: flex; flex-direction: column; - align-items: center; justify-content: center; - padding: 6rem 2rem 4rem; text-align: center; + min-height: 100vh; + position: relative; + overflow: hidden; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 6rem 2rem 5rem; + text-align: center; +} + +/* Dot grid background */ +.hero-grid { + position: absolute; inset: 0; + background-image: radial-gradient(circle at 1px 1px, rgba(245,158,11,0.13) 1px, transparent 0); + background-size: 32px 32px; + pointer-events: none; + mask-image: radial-gradient(ellipse 85% 85% at 50% 50%, black 30%, transparent 100%); + -webkit-mask-image: radial-gradient(ellipse 85% 85% at 50% 50%, black 30%, transparent 100%); +} + +/* Ambient amber glow */ +.hero-glow { + position: absolute; + width: 900px; height: 900px; + background: radial-gradient(circle, rgba(245,158,11,0.09) 0%, transparent 65%); + top: 50%; left: 50%; + transform: translate(-50%, -50%); + pointer-events: none; + animation: pulse-glow 7s ease-in-out infinite; +} +@keyframes pulse-glow { + 0%, 100% { opacity: 0.6; transform: translate(-50%, -50%) scale(1); } + 50% { opacity: 1; transform: translate(-50%, -50%) scale(1.1); } +} + +.hero-content { + position: relative; + z-index: 1; + width: 100%; + max-width: 820px; +} + +/* Badge */ +.hero-badge { + display: inline-block; + font-family: var(--font-mono); + font-size: 0.7rem; + color: var(--amber); + border: 1px solid rgba(245,158,11,0.3); + background: rgba(245,158,11,0.06); + border-radius: 100px; + padding: 0.3rem 1rem; + margin-bottom: 1.5rem; + letter-spacing: 0.06em; + animation: fade-up 0.6s var(--ease) both; +} + +.hero h1 { + font-family: var(--font-mono); + font-size: clamp(2.1rem, 5.5vw, 4rem); + font-weight: 700; + letter-spacing: -0.03em; + line-height: 1.07; + animation: fade-up 0.65s var(--ease) 0.1s both; +} + +/* Shimmer gradient text */ +.shimmer { + background: linear-gradient( + 90deg, + #f59e0b 0%, + #fde68a 25%, + #f59e0b 45%, + #d97706 65%, + #fbbf24 80%, + #f59e0b 100% + ); + background-size: 300% auto; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + animation: shimmer 5s linear infinite; +} +@keyframes shimmer { + 0% { background-position: 0% center; } + 100% { background-position: 300% center; } +} + +.hero .tagline { + font-size: clamp(0.95rem, 2vw, 1.2rem); + color: var(--text-muted); + margin: 1.25rem auto 2rem; + max-width: 520px; + animation: fade-up 0.65s var(--ease) 0.18s both; } -.hero h1 { font-family: var(--font-mono); font-size: clamp(2rem, 5vw, 3.5rem); font-weight: 700; letter-spacing: -0.02em; line-height: 1.1; } -.hero h1 span { color: var(--amber); } -.hero .tagline { font-size: clamp(1rem, 2vw, 1.25rem); color: var(--text-muted); margin: 1.5rem 0 2.5rem; max-width: 560px; } /* Install block */ .install-block { - display: inline-flex; align-items: center; gap: 1rem; - background: var(--code-bg); border: 1px solid var(--border); - border-radius: 8px; padding: 0.875rem 1.5rem; - font-family: var(--font-mono); font-size: 0.9rem; - margin-bottom: 3rem; + display: inline-flex; + align-items: center; + gap: 1rem; + background: var(--code-bg); + border: 1px solid var(--border); + border-radius: var(--radius); + padding: 0.875rem 1.5rem; + font-family: var(--font-mono); + font-size: 0.875rem; + margin-bottom: 2rem; + animation: fade-up 0.65s var(--ease) 0.26s both; + transition: border-color 0.2s ease, box-shadow 0.2s ease; +} +.install-block:hover { + border-color: var(--border-hover); + box-shadow: 0 0 28px rgba(245,158,11,0.1); } .install-block .prompt { color: var(--amber); } + .copy-btn { - background: none; border: 1px solid var(--border); border-radius: 4px; - color: var(--text-muted); cursor: pointer; padding: 0.25rem 0.6rem; - font-size: 0.75rem; transition: all 0.2s; + background: none; + border: 1px solid var(--border); + border-radius: var(--radius-sm); + color: var(--text-muted); + cursor: pointer; + padding: 0.25rem 0.7rem; + font-family: var(--font-mono); + font-size: 0.7rem; + transition: border-color 0.18s ease, color 0.18s ease; + white-space: nowrap; +} +.copy-btn:hover, +.copy-btn.copied { border-color: var(--amber); color: var(--amber); } + +/* Stats strip */ +.stats-strip { + display: flex; + align-items: center; + justify-content: center; + gap: 1.75rem; + margin-bottom: 2.5rem; + animation: fade-up 0.65s var(--ease) 0.34s both; +} +.stat { text-align: center; } +.stat-num { + display: block; + font-family: var(--font-mono); + font-size: 1.6rem; + font-weight: 700; + color: var(--amber); + line-height: 1; +} +.stat-label { + display: block; + font-size: 0.68rem; + color: var(--text-muted); + text-transform: uppercase; + letter-spacing: 0.09em; + margin-top: 0.25rem; +} +.stat-divider { + width: 1px; + height: 34px; + background: var(--border); + flex-shrink: 0; } -.copy-btn:hover { border-color: var(--amber); color: var(--amber); } -/* Terminal demo */ +/* ===================== TERMINAL ===================== */ .terminal { - width: 100%; max-width: 640px; margin: 0 auto; - background: var(--code-bg); border: 1px solid var(--border); - border-radius: 10px; overflow: hidden; text-align: left; + width: 100%; + max-width: 660px; + margin: 0 auto; + background: var(--code-bg); + border: 1px solid var(--border); + border-radius: var(--radius); + overflow: hidden; + text-align: left; + animation: fade-up 0.7s var(--ease) 0.44s both; + box-shadow: + 0 32px 80px rgba(0,0,0,0.6), + 0 0 0 1px rgba(245,158,11,0.05), + 0 0 60px rgba(245,158,11,0.04); + transition: opacity 0.35s ease; } .terminal-bar { - background: var(--surface); padding: 0.75rem 1rem; - display: flex; align-items: center; gap: 0.5rem; + background: var(--surface); + padding: 0.75rem 1rem; + display: flex; + align-items: center; + gap: 0.5rem; border-bottom: 1px solid var(--border); } -.dot { width: 12px; height: 12px; border-radius: 50%; } -.dot.red { background: #ff5f57; } +.dot { width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; } +.dot.red { background: #ff5f57; } .dot.yellow { background: #febc2e; } -.dot.green { background: #28c840; } -.terminal-title { font-size: 0.75rem; color: var(--text-muted); margin-left: auto; font-family: var(--font-mono); } -.terminal-body { padding: 1.25rem 1.5rem; font-family: var(--font-mono); font-size: 0.825rem; line-height: 1.7; } -.line-cmd { color: var(--amber); } -.line-out { color: #6b7280; } -.line-key { color: #34d399; } -.line-val { color: var(--text); } -.cursor { display: inline-block; width: 2px; height: 1em; background: var(--amber); animation: blink 1s step-end infinite; vertical-align: text-bottom; } +.dot.green { background: #28c840; } +.terminal-title { + font-size: 0.72rem; + color: var(--text-muted); + margin-left: auto; + font-family: var(--font-mono); +} +.terminal-body { + padding: 1.25rem 1.5rem; + font-family: var(--font-mono); + font-size: 0.82rem; + line-height: 1.8; + min-height: 190px; +} +.line-cmd { color: var(--amber); } +.line-out { color: #6b7280; } +.line-key { color: var(--green); } +.line-val { color: var(--text); } +.line-amber { color: var(--amber); } +.line-spacer { height: 0.6rem; } + +.cursor { + display: inline-block; + width: 2px; + height: 1em; + background: var(--amber); + animation: blink 1s step-end infinite; + vertical-align: text-bottom; + margin-left: 2px; +} @keyframes blink { 50% { opacity: 0; } } -/* Typewriter */ -.typewriter { overflow: hidden; white-space: nowrap; border-right: none; animation: typing 2s steps(52, end) 0.5s both; } +.typewriter { + overflow: hidden; + white-space: nowrap; + animation: typing 2.2s steps(62, end) 0.5s both; +} @keyframes typing { from { width: 0; } to { width: 100%; } } -/* Quotes */ -.quotes { background: var(--surface); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); padding: 3rem 2rem; } -.quotes-inner { max-width: 900px; margin: 0 auto; display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 2rem; } -.quote { padding: 1.5rem; border: 1px solid var(--border); border-radius: 8px; } -.quote p { color: var(--text-muted); font-size: 0.9rem; line-height: 1.6; } -.quote p strong { color: var(--text); display: block; margin-bottom: 0.5rem; font-size: 0.95rem; } - -/* Sections */ -section { padding: 5rem 2rem; } -.container { max-width: 960px; margin: 0 auto; } -.section-label { font-family: var(--font-mono); font-size: 0.75rem; color: var(--amber); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 0.75rem; } -h2 { font-size: clamp(1.5rem, 3vw, 2rem); font-weight: 700; margin-bottom: 1rem; } -.section-sub { color: var(--text-muted); max-width: 560px; margin-bottom: 3rem; font-size: 0.95rem; } - -/* How it works */ -.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.5rem; } -.step { padding: 1.75rem; border: 1px solid var(--border); border-radius: 8px; position: relative; } -.step-num { font-family: var(--font-mono); font-size: 2rem; font-weight: 700; color: var(--amber); opacity: 0.3; margin-bottom: 0.75rem; } -.step h3 { font-size: 1rem; margin-bottom: 0.5rem; } -.step p { font-size: 0.875rem; color: var(--text-muted); } - -/* Commands */ -.phase-group { margin-bottom: 2.5rem; } -.phase-label { font-family: var(--font-mono); font-size: 0.7rem; color: var(--amber); text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 1rem; padding-bottom: 0.5rem; border-bottom: 1px solid var(--border); } -.command-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1rem; } +.hero-hint { + margin-top: 1.75rem; + font-size: 0.78rem; + color: var(--text-muted); + animation: fade-hint 3s var(--ease) both; +} +@keyframes fade-hint { + 0%, 60% { opacity: 0; transform: translateY(6px); } + 100% { opacity: 1; transform: translateY(0); } +} + +/* ===================== SHARED ANIMATIONS ===================== */ +@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } } +@keyframes fade-up { + from { opacity: 0; transform: translateY(22px); } + to { opacity: 1; transform: translateY(0); } +} + +/* Scroll reveal */ +[data-animate] { + opacity: 0; + transform: translateY(28px); + transition: opacity 0.6s var(--ease), transform 0.6s var(--ease); +} +[data-animate].visible { + opacity: 1; + transform: translateY(0); +} + +/* ===================== VALUE PROPS ===================== */ +.quotes { + background: var(--surface); + border-top: 1px solid var(--border); + border-bottom: 1px solid var(--border); + padding: 4rem 2rem; +} +.quotes-inner { + max-width: 980px; + margin: 0 auto; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); + gap: 1.25rem; +} +.quote { + padding: 1.75rem; + border: 1px solid var(--border); + border-radius: var(--radius); + background: var(--bg); + transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease; +} +.quote:hover { + border-color: rgba(245,158,11,0.3); + box-shadow: 0 0 28px rgba(245,158,11,0.07); + transform: translateY(-3px); +} +.quote p { color: var(--text-muted); font-size: 0.875rem; line-height: 1.75; } +.quote p strong { + color: var(--text); + display: block; + margin-bottom: 0.5rem; + font-size: 0.95rem; +} + +/* ===================== SECTIONS ===================== */ +section { padding: 5.5rem 2rem; } +.container { max-width: 980px; margin: 0 auto; } +.section-label { + font-family: var(--font-mono); + font-size: 0.68rem; + color: var(--amber); + text-transform: uppercase; + letter-spacing: 0.14em; + margin-bottom: 0.75rem; +} +h2 { + font-size: clamp(1.5rem, 3vw, 2.15rem); + font-weight: 700; + margin-bottom: 1rem; + letter-spacing: -0.025em; +} +.section-sub { + color: var(--text-muted); + max-width: 520px; + margin-bottom: 3rem; + font-size: 0.95rem; + line-height: 1.65; +} +.inline-code { + color: var(--amber); + font-family: var(--font-mono); + font-size: 0.82em; +} + +/* ===================== HOW IT WORKS ===================== */ +.steps { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + gap: 1.25rem; +} +.step { + padding: 1.75rem; + border: 1px solid var(--border); + border-radius: var(--radius); + background: var(--bg); + position: relative; + transition: border-color 0.2s ease, box-shadow 0.25s ease, transform 0.2s ease; +} +.step::before { + content: ''; + position: absolute; + inset: 0; + border-radius: var(--radius); + background: linear-gradient(135deg, var(--amber-glow), transparent); + opacity: 0; + transition: opacity 0.25s ease; +} +.step:hover { border-color: rgba(245,158,11,0.35); transform: translateY(-3px); } +.step:hover::before { opacity: 1; } +.step-num { + font-family: var(--font-mono); + font-size: 2.2rem; + font-weight: 700; + color: var(--amber); + opacity: 0.22; + margin-bottom: 0.75rem; + line-height: 1; +} +.step h3 { font-size: 1rem; margin-bottom: 0.5rem; position: relative; } +.step p { font-size: 0.875rem; color: var(--text-muted); position: relative; } + +/* ===================== COMMANDS ===================== */ +.commands-section { + background: var(--surface); + border-top: 1px solid var(--border); + border-bottom: 1px solid var(--border); +} +.phase-group { margin-bottom: 2.75rem; } +.phase-label { + font-family: var(--font-mono); + font-size: 0.67rem; + color: var(--amber); + text-transform: uppercase; + letter-spacing: 0.13em; + margin-bottom: 1rem; + padding-bottom: 0.5rem; + border-bottom: 1px solid var(--border); +} +.command-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); + gap: 0.875rem; +} .command-card { - padding: 1.25rem; border: 1px solid var(--border); border-radius: 8px; - transition: border-color 0.2s, background 0.2s; cursor: default; + padding: 1.25rem 1.375rem; + border: 1px solid var(--border); + border-radius: var(--radius); + background: var(--bg); + cursor: default; + transition: border-color 0.2s ease, box-shadow 0.25s ease, transform 0.2s ease; +} +.command-card:hover { + border-color: rgba(245,158,11,0.45); + box-shadow: 0 0 22px rgba(245,158,11,0.09), inset 0 0 22px rgba(245,158,11,0.02); + transform: translateY(-2px); +} +.command-card code { + font-family: var(--font-mono); + font-size: 0.74rem; + color: var(--amber); + display: block; + margin-bottom: 0.5rem; +} +.command-card p { + font-size: 0.82rem; + color: var(--text-muted); + line-height: 1.55; } -.command-card:hover { border-color: var(--amber-dim); background: var(--surface); } -.command-card code { font-family: var(--font-mono); font-size: 0.775rem; color: var(--amber); display: block; margin-bottom: 0.5rem; } -.command-card p { font-size: 0.825rem; color: var(--text-muted); } -/* Agents */ -.agent-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.5rem; } -.agent-card { padding: 1.75rem; border: 1px solid var(--border); border-radius: 8px; } -.agent-card h3 { font-family: var(--font-mono); color: var(--amber); margin-bottom: 0.5rem; font-size: 0.9rem; } -.agent-card .role { font-size: 0.875rem; font-weight: 600; margin-bottom: 0.5rem; } -.agent-card p { font-size: 0.825rem; color: var(--text-muted); } +/* ===================== AGENTS ===================== */ +.agent-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); + gap: 1.25rem; +} +.agent-card { + padding: 1.75rem; + border: 1px solid var(--border); + border-radius: var(--radius); + background: var(--bg); + transition: border-color 0.2s ease, box-shadow 0.25s ease, transform 0.2s ease; +} +.agent-card:hover { + border-color: rgba(245,158,11,0.4); + box-shadow: 0 0 36px rgba(245,158,11,0.09); + transform: translateY(-3px); +} +.agent-icon { + font-size: 1.4rem; + color: var(--amber); + opacity: 0.55; + margin-bottom: 0.75rem; + display: block; +} +.agent-card h3 { + font-family: var(--font-mono); + color: var(--amber); + margin-bottom: 0.4rem; + font-size: 0.9rem; +} +.agent-card .role { + font-size: 0.85rem; + font-weight: 600; + color: var(--text); + margin-bottom: 0.75rem; +} +.agent-card p { font-size: 0.825rem; color: var(--text-muted); line-height: 1.65; } /* v2 callout */ .v2-callout { - background: linear-gradient(135deg, rgba(245,158,11,0.08), rgba(245,158,11,0.02)); - border: 1px solid rgba(245,158,11,0.3); border-radius: 12px; - padding: 2.5rem; margin-top: 2rem; + background: linear-gradient(135deg, rgba(245,158,11,0.07), rgba(245,158,11,0.01) 60%); + border: 1px solid rgba(245,158,11,0.22); + border-radius: 12px; + padding: 2.5rem; + margin-top: 2rem; +} +.v2-callout h3 { + font-family: var(--font-mono); + color: var(--amber); + margin-bottom: 1.25rem; + font-size: 0.88rem; + letter-spacing: 0.06em; + text-transform: uppercase; +} +.v2-callout ul { + list-style: none; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 0.625rem; +} +.v2-callout li { + font-size: 0.875rem; + color: var(--text-muted); + padding-left: 1.1rem; + position: relative; + line-height: 1.55; +} +.v2-callout li::before { + content: '→'; + position: absolute; + left: 0; + color: var(--amber); } -.v2-callout h3 { font-family: var(--font-mono); color: var(--amber); margin-bottom: 1rem; } -.v2-callout ul { list-style: none; display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0.5rem; } -.v2-callout li { font-size: 0.875rem; color: var(--text-muted); padding-left: 1rem; position: relative; } -.v2-callout li::before { content: '→'; position: absolute; left: 0; color: var(--amber); } -/* Install section */ -.install-section { background: var(--surface); border-top: 1px solid var(--border); } +/* ===================== INSTALL ===================== */ +.install-section { + background: var(--surface); + border-top: 1px solid var(--border); +} .code-block { - background: var(--code-bg); border: 1px solid var(--border); border-radius: 8px; - padding: 1.25rem 1.5rem; font-family: var(--font-mono); font-size: 0.85rem; - color: var(--text); margin-bottom: 1rem; white-space: pre; + background: var(--code-bg); + border: 1px solid var(--border); + border-radius: var(--radius); + padding: 1.5rem 1.75rem; + font-family: var(--font-mono); + font-size: 0.85rem; + color: var(--text); + margin-bottom: 1.25rem; + white-space: pre; + overflow-x: auto; + line-height: 1.9; } .code-block .comment { color: var(--text-muted); } -.code-block .cmd { color: var(--amber); } +.code-block .cmd { color: var(--amber); } +.install-note { font-size: 0.875rem; color: var(--text-muted); } -/* Footer */ +/* ===================== FOOTER ===================== */ footer { - border-top: 1px solid var(--border); padding: 2rem; - text-align: center; color: var(--text-muted); font-size: 0.8rem; + border-top: 1px solid var(--border); + padding: 2rem; + text-align: center; + color: var(--text-muted); + font-size: 0.8rem; } -footer a { color: var(--text-muted); text-decoration: none; } +footer a { color: var(--text-muted); text-decoration: none; transition: color 0.18s ease; } footer a:hover { color: var(--amber); } -/* Responsive */ +/* ===================== RESPONSIVE ===================== */ @media (max-width: 640px) { - nav a { display: none; } - .install-block { flex-direction: column; gap: 0.5rem; } + .nav-links a { display: none; } + .install-block { flex-direction: column; gap: 0.5rem; text-align: center; } + .stats-strip { gap: 1rem; flex-wrap: wrap; } + .stat-num { font-size: 1.3rem; } + .stat-divider { height: 24px; } + .terminal-body { font-size: 0.75rem; } +} + +/* ===================== REDUCED MOTION ===================== */ +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { + animation-duration: 0.01ms !important; + transition-duration: 0.01ms !important; + } + [data-animate] { opacity: 1; transform: none; } + .shimmer { animation: none; color: var(--amber); -webkit-text-fill-color: var(--amber); } + .hero-glow { animation: none; } } diff --git a/scripts/detect-project.js b/scripts/detect-project.js index 8613579..3f14844 100644 --- a/scripts/detect-project.js +++ b/scripts/detect-project.js @@ -43,7 +43,6 @@ try { const configDir = path.join(projectRoot, outputDir); const contextPath = path.join(configDir, '.qa-context.json'); -const legacyConfigPath = path.join(configDir, '.qa-config.json'); const stateManagerPath = path.join(pluginRoot, 'scripts', 'state-manager.js'); // Detection markers @@ -762,15 +761,6 @@ const tmpContextPath = contextPath + '.tmp'; fs.writeFileSync(tmpContextPath, JSON.stringify(projectState, null, 2)); fs.renameSync(tmpContextPath, contextPath); -// Backward compat: also write legacy .qa-config.json with detection data -const legacyConfig = { - ...detection, - detectedAt: projectState.detectedAt, - projectRoot, - outputDir, -}; -fs.writeFileSync(legacyConfigPath, JSON.stringify(legacyConfig, null, 2)); - // ---- Initialize session state ---- let sessionStatus = 'new (first session)'; diff --git a/skills/shared/references/cold-start-pattern.md b/skills/shared/references/cold-start-pattern.md index 5d1899d..0ea6530 100644 --- a/skills/shared/references/cold-start-pattern.md +++ b/skills/shared/references/cold-start-pattern.md @@ -14,10 +14,7 @@ outputDir = read settings.json -> outputDir (default: "qa-artifacts") - JSON parse error? -> use empty defaults (do NOT error) - Schema mismatch? -> use empty defaults (state-manager handles this) -2. Fallback: if .qa-context.json not found, try /.qa-config.json - - Same handling: missing or corrupt -> empty defaults - -3. Try reading /.qa-session.json (if session context is relevant) +2. Try reading /.qa-session.json (if session context is relevant) - Same handling: missing or corrupt -> empty defaults ``` @@ -96,7 +93,7 @@ If testFrameworks is empty: When a skill detects it ran without project context, append a footer guiding the user toward richer output. **Show the footer when:** -- `.qa-context.json` was not found (and `.qa-config.json` fallback also missing), OR +- `.qa-context.json` was not found, OR - `detection.languages` is empty or missing **Do NOT show the footer when:** diff --git a/tests/detect-project.test.js b/tests/detect-project.test.js index 13f2d3a..5069e2d 100644 --- a/tests/detect-project.test.js +++ b/tests/detect-project.test.js @@ -17,8 +17,10 @@ function runDetect(cwd) { } function readConfig(cwd, outputDir = 'qa-artifacts') { - const configPath = path.join(cwd, outputDir, '.qa-config.json'); - return JSON.parse(fs.readFileSync(configPath, 'utf8')); + const contextPath = path.join(cwd, outputDir, '.qa-context.json'); + const ctx = JSON.parse(fs.readFileSync(contextPath, 'utf8')); + // Flatten detection fields to the top level for backwards-compatible test assertions + return { ...ctx.detection, detectedAt: ctx.detectedAt, outputDir: ctx.outputDir }; } describe('detect-project.js', () => { @@ -38,7 +40,7 @@ describe('detect-project.js', () => { assert.ok(stdout.includes('No previous QA artifacts found')); }); - it('creates .qa-config.json in output directory', () => { + it('creates .qa-context.json in output directory', () => { // Config was created by the previous test run const config = readConfig(tmpDir); assert.equal(config.outputDir, 'qa-artifacts'); @@ -189,7 +191,7 @@ describe('detect-project.js', () => { const qaDir = path.join(projectDir, 'qa-artifacts'); const entries = fs.readdirSync(qaDir).sort(); - // Should only have state files, no subdirectories (v2 writes .qa-context.json + legacy .qa-config.json) + // Should only have state files, no subdirectories (v2 writes .qa-context.json + .qa-session.json) const dirs = entries.filter(e => fs.statSync(path.join(qaDir, e)).isDirectory()); assert.deepEqual(dirs, []); }); diff --git a/tests/hooks-toggle.test.js b/tests/hooks-toggle.test.js index fbbeffc..edd9979 100644 --- a/tests/hooks-toggle.test.js +++ b/tests/hooks-toggle.test.js @@ -6,7 +6,7 @@ const { execFileSync } = require('child_process'); const realPluginRoot = path.join(__dirname, '..'); const detectScript = path.join(realPluginRoot, 'scripts', 'detect-project.js'); -const saveScript = path.join(realPluginRoot, 'scripts', 'save-artifact.js'); +const saveScript = path.join(realPluginRoot, 'scripts', 'session-hook.js'); // Use a temp plugin root with a modified settings.json to avoid mutating the real one function makeTempPluginRoot(overrides) { @@ -48,7 +48,7 @@ describe('hooksEnabled toggle', () => { assert.ok(!fs.existsSync(path.join(projectDir, 'qa-artifacts'))); }); - it('save-artifact.js exits silently when hooksEnabled is false', () => { + it('session-hook.js exits silently when hooksEnabled is false', () => { const projectDir = path.join(tmpDir, 'disabled-save'); fs.mkdirSync(projectDir, { recursive: true }); const fakePluginRoot = makeTempPluginRoot({ hooksEnabled: false }); @@ -83,7 +83,7 @@ describe('hooksEnabled toggle', () => { } }); - it('save-artifact.js rejects absolute outputDir', () => { + it('session-hook.js rejects absolute outputDir', () => { const projectDir = path.join(tmpDir, 'abs-save'); fs.mkdirSync(projectDir, { recursive: true }); const fakePluginRoot = makeTempPluginRoot({ outputDir: '/tmp/evil' }); @@ -113,6 +113,6 @@ describe('hooksEnabled toggle', () => { }); assert.ok(stdout.includes('[QA Toolkit — Project Context]')); - assert.ok(fs.existsSync(path.join(projectDir, 'qa-artifacts', '.qa-config.json'))); + assert.ok(fs.existsSync(path.join(projectDir, 'qa-artifacts', '.qa-context.json'))); }); }); From 4b6534c2ab785b5eb58c7606e8e90ed6d45f0672 Mon Sep 17 00:00:00 2001 From: Himanshu Vimal Date: Sat, 7 Mar 2026 05:07:50 +0530 Subject: [PATCH 11/15] =?UTF-8?q?docs:=20redesign=20landing=20page=20?= =?UTF-8?q?=E2=80=94=20new=20hero,=20animations,=20readability=20overhaul?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - New headline: "Test the code. Trust the release." - Swirling particle vortex in hero, CSS background effects per section (aurora, light-sweep, radial-pulse, shimmer-line) - Scroll animations: one-way reveal (removed exit animations that blanked page) - Reordered hero: terminal above stats, bigger stat numbers with glow - Readability: switched all body text from muted gray to white, bumped font sizes across cards/labels/subtitles, removed artificial max-widths - Consistent Inter font for headings (replaced Syne display font) - Removed unused docs/assets/ directory (19MB of unreferenced files) - Tightened section padding, widened card grid minimums Signed-off-by: Claude Opus 4.6 Signed-off-by: Himanshu Vimal --- docs/index.html | 490 +++++++++++++++++++++++++++------ docs/style.css | 714 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 964 insertions(+), 240 deletions(-) diff --git a/docs/index.html b/docs/index.html index 9b28f88..2687cf2 100644 --- a/docs/index.html +++ b/docs/index.html @@ -54,10 +54,21 @@ } + + + + + + +
+ + + +