diff --git a/.github/instructions/bug-fixing.instructions.md b/.github/instructions/bug-fixing.instructions.md index 3771171..49d6961 100644 --- a/.github/instructions/bug-fixing.instructions.md +++ b/.github/instructions/bug-fixing.instructions.md @@ -5,6 +5,8 @@ excludeAgent: "code-review" # Bug fixing — instructions for Copilot coding agent +> **Skill reference:** for the extended symptom → module diagnostic table, test-first patterns and minimal fix principles read `.github/skills/bug-fixing.md` first. + Follow these steps when fixing a bug in this repository. ## 1. Reproduce the bug before writing any fix diff --git a/.github/instructions/documentation.instructions.md b/.github/instructions/documentation.instructions.md index 198e0fc..8ec039e 100644 --- a/.github/instructions/documentation.instructions.md +++ b/.github/instructions/documentation.instructions.md @@ -4,6 +4,8 @@ applyTo: "docs/**" # Documentation — instructions for Copilot coding agent +> **Skill reference:** for deep domain knowledge (VitePress theme architecture, CSS variables, accessibility patterns, responsive patterns, full validation commands) read `.github/skills/documentation.md` first. + Follow these conventions when writing or editing pages in the `docs/` directory. ## 1. Tool & rendering pipeline @@ -93,9 +95,20 @@ docs/ Before opening a PR for any docs change: ```bash -bun run docs:build # must complete without errors -bun run format:check # oxfmt — no formatting diff +bun run docs:build # must complete without errors or dead-link warnings +bun run format:check # oxfmt — no formatting diff ``` - All internal links must resolve (VitePress reports dead links on build). - No new `bun run knip` violations (docs/\*\* is excluded but `package.json` changes are not). + +If the PR modifies any Vue component, CSS, or page layout, also run the accessibility and responsive suites: + +```bash +bun run docs:build:a11y +bun run docs:preview -- --port 4173 & +bun run docs:a11y # pa11y-ci WCAG 2.1 AA — must report 0 errors +bun run docs:test:responsive # Playwright — 20/20 tests green (4 viewports × 5 pages) +``` + +See `.github/skills/documentation.md` for pa11y configuration details, WCAG contrast rules, accessible component patterns, and responsive breakpoint guidance. diff --git a/.github/instructions/implement-feature.instructions.md b/.github/instructions/implement-feature.instructions.md index 82d392c..5dbdb82 100644 --- a/.github/instructions/implement-feature.instructions.md +++ b/.github/instructions/implement-feature.instructions.md @@ -5,6 +5,8 @@ excludeAgent: "code-review" # Implement feature — instructions for Copilot coding agent +> **Skill reference:** for the full architectural layer map, type-first design patterns, CLI option conventions, render sub-module extension playbook and test strategies read `.github/skills/feature.md` first. + Follow these steps when implementing a new feature in this repository. ## 1. Understand the task scope before writing code diff --git a/.github/instructions/refactoring.instructions.md b/.github/instructions/refactoring.instructions.md index 04ed5f6..efd5ef5 100644 --- a/.github/instructions/refactoring.instructions.md +++ b/.github/instructions/refactoring.instructions.md @@ -5,6 +5,8 @@ excludeAgent: "code-review" # Refactoring — instructions for Copilot coding agent +> **Skill reference:** for architectural invariants, safe rename playbook, module extraction patterns, characterisation test strategy and `knip` output interpretation read `.github/skills/refactoring.md` first. + Follow these steps when refactoring existing code in this repository. ## 1. Define the goal and scope diff --git a/.github/instructions/release.instructions.md b/.github/instructions/release.instructions.md index 77ce7f6..3e24ba9 100644 --- a/.github/instructions/release.instructions.md +++ b/.github/instructions/release.instructions.md @@ -5,6 +5,8 @@ excludeAgent: "code-review" # Release — instructions for Copilot coding agent +> **Skill reference:** for the semver decision guide, CD pipeline mechanics, binary targets, blog post format reference and versioned docs snapshot details read `.github/skills/release.md` first. + Follow these steps when cutting a new release of `github-code-search`. ## 1. Determine the version bump diff --git a/.github/skills/bug-fixing.md b/.github/skills/bug-fixing.md new file mode 100644 index 0000000..14b107e --- /dev/null +++ b/.github/skills/bug-fixing.md @@ -0,0 +1,125 @@ +# Bug fixing skill — github-code-search + +Deep reference for diagnosing and fixing bugs in this codebase. +This skill complements `.github/instructions/bug-fixing.instructions.md`. + +--- + +## Symptom → module diagnostic table + +| Symptom | Primary suspect | Secondary suspect | +| ----------------------------------------------------------- | ----------------------------------------------- | --------------------------------- | +| Results missing or duplicated | `src/aggregate.ts` | `src/api.ts` (pagination) | +| Wrong repository grouping | `src/group.ts` | `src/aggregate.ts` | +| `--exclude-repositories` / `--exclude-extracts` not working | `src/aggregate.ts` | `github-code-search.ts` (parsing) | +| Markdown output malformed | `src/output.ts` | — | +| JSON output missing fields or wrong shape | `src/output.ts` | `src/types.ts` (interface) | +| Syntax highlighting wrong colour / wrong language | `src/render/highlight.ts` | — | +| Row navigation skips or wraps incorrectly | `src/render/rows.ts` | `src/tui.ts` (key handler) | +| Select-all / select-none inconsistent | `src/render/selection.ts` | `src/tui.ts` | +| Filter count / stats incorrect | `src/render/filter.ts`, `src/render/summary.ts` | — | +| Path filter (`/regex/`) doesn't match expected | `src/render/filter-match.ts` | `src/tui.ts` (filter state) | +| API returns 0 results or stops paginating | `src/api.ts` | `src/api-utils.ts` | +| Rate limit hit / 429 not retried | `src/api-utils.ts` (`fetchWithRetry`) | — | +| TUI shows blank screen or wrong row | `src/tui.ts` | `src/render/rows.ts` | +| Help overlay doesn't appear / has wrong keys | `src/render.ts` (`renderHelpOverlay`) | `src/tui.ts` | +| Upgrade fails or replaces wrong binary | `src/upgrade.ts` | — | +| Completion script wrong content | `src/completions.ts` | — | +| Completion file written to wrong path | `src/completions.ts` (`getCompletionFilePath`) | env vars (`XDG_*`, `ZDOTDIR`) | +| Completion not refreshed after upgrade | `src/upgrade.ts` (`refreshCompletions`) | — | +| `--version` shows wrong info | `build.ts` (SHA injection) | — | +| CLI option ignored or parsed wrong | `github-code-search.ts` | `src/types.ts` (`OutputType`) | + +--- + +## Reproducing a bug + +A complete bug report must have: + +1. **Exact command** (redact `GITHUB_TOKEN` with `***`): + ``` + GITHUB_TOKEN=*** github-code-search query "pattern" --org acme + ``` +2. **Observed output** vs **expected output**. +3. **Version string**: `github-code-search --version` → e.g. `1.8.0 (a1b2c3d · darwin/arm64)`. +4. **Bun version** (when running from source): `bun --version`. + +If the report is missing items 1 or 3, read the relevant module(s) to hypothesise the root cause before asking for more info. + +--- + +## Test-first patterns for bugs + +### Pure function bug (aggregate, group, output, render/\*) + +```typescript +// src/aggregate.test.ts +describe("applyFiltersAndExclusions — bug #N", () => { + it("excludes org-prefixed repo names correctly", () => { + const result = applyFiltersAndExclusions(matches, { + excludeRepositories: ["acme/my-repo"], // the previously broken form + }); + expect(result).not.toContainEqual(expect.objectContaining({ repo: "acme/my-repo" })); + }); +}); +``` + +The test must **fail** with the current code before the fix. Commit the test, then fix. + +### api-utils bug (retry / pagination) + +```typescript +// src/api-utils.test.ts +it("retries on 429 with Retry-After header", async () => { + let callCount = 0; + globalThis.fetch = async () => { + callCount++; + if (callCount === 1) { + return new Response(null, { + status: 429, + headers: { "Retry-After": "0" }, + }); + } + return new Response(JSON.stringify({ ok: true }), { status: 200 }); + }; + await fetchWithRetry("https://api.github.com/test"); + expect(callCount).toBe(2); +}); +``` + +### Side-effectful bug (tui, api) — no unit test possible + +Document manual repro steps in the PR description: + +```markdown +## Steps to reproduce (before fix) + +1. `GITHUB_TOKEN=... github-code-search query "foo" --org acme` +2. Press `↓` past the last result +3. Expected: cursor stays on last row / Expected: wraps to first row +4. Observed: cursor jumps to blank row +``` + +--- + +## Minimal fix principles + +- **Touch only the root cause.** Do not opportunistically refactor neighbouring code in the same PR — it makes the fix harder to review and risks introducing new bugs. +- **Respect pure/IO layering**: a fix in `aggregate.ts` must not add a `console.log` call. +- **Type changes cascade**: if `src/types.ts` must change, run `bun run knip` to find all affected consumers and update them all in the same PR. +- **Regression comment**: if the root cause is non-obvious, add one line above the fix: + ```typescript + // Fix: short names ("repo") and qualified names ("org/repo") must both match — see issue #N + ``` + +--- + +## Validation after fix + +```bash +bun test # the previously failing test now passes; full suite still green +bun run lint # oxlint — zero errors +bun run format:check # oxfmt — no formatting diff +bun run knip # no unused exports or imports +bun run build.ts # binary compiles without errors +``` diff --git a/.github/skills/documentation.md b/.github/skills/documentation.md new file mode 100644 index 0000000..e0c1578 --- /dev/null +++ b/.github/skills/documentation.md @@ -0,0 +1,162 @@ +# Documentation skill — github-code-search + +Deep reference for writing and maintaining VitePress documentation in this project. +This skill complements `.github/instructions/documentation.instructions.md` (the step-by-step workflow). + +--- + +## VitePress theme architecture + +Custom components live in `docs/.vitepress/theme/`: + +| File / folder | Role | +| ------------------------- | ------------------------------------------------------------------ | +| `index.ts` | Theme entry point — imports components and global CSS | +| `custom.css` | All CSS overrides — brand colours, typography, responsive, a11y | +| `Layout.vue` | Root layout wrapper (adds `RichFooter`, manages slot injection) | +| `TerminalDemo.vue` | Animated terminal on the hero — `aria-hidden="true"` (decorative) | +| `ComparisonTable.vue` | Feature comparison table with responsive 3-column layout | +| `UseCaseTabs.vue` | WAI-ARIA Tabs pattern (roving tabindex, ArrowLeft/Right/Home/End) | +| `InstallSection.vue` | Install command snippets with OS tabs | +| `HowItWorks.vue` | 3-step explainer with responsive card layout | +| `TestimonialsSection.vue` | Community testimonials carousel | +| `ProductionCta.vue` | "Used in production?" CTA banner (`
`) | +| `VersionBadge.vue` | Release badge — reads `version` from `package.json` at build time | +| `RichFooter.vue` | Custom footer replacing VitePress default | + +**Extending a component:** + +1. Locate the `.vue` file above. +2. Follow the existing scoped ` diff --git a/docs/.vitepress/theme/HowItWorks.vue b/docs/.vitepress/theme/HowItWorks.vue index b14884f..a42498b 100644 --- a/docs/.vitepress/theme/HowItWorks.vue +++ b/docs/.vitepress/theme/HowItWorks.vue @@ -1,7 +1,7 @@