diff --git a/docs/superpowers/plans/2026-05-17-bug-reporting.md b/docs/superpowers/plans/2026-05-17-bug-reporting.md
new file mode 100644
index 0000000..c37a848
--- /dev/null
+++ b/docs/superpowers/plans/2026-05-17-bug-reporting.md
@@ -0,0 +1,653 @@
+# Bug Reporting Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Add a "Report a Bug" footer link that opens the Bugpin screenshot widget (forwards to GitHub Issues), plus auto error capture via Bugsink (Sentry-compatible) on every page.
+
+**Architecture:** Two independent flows. Bugpin = user-initiated, lazy-loaded `
+```
+
+with:
+
+```astro
+
+```
+
+- [ ] **Step 5: Add CSS so the button matches the surrounding links**
+
+Open `src/ui/crt.css` and grep for `.mystery-footer` to find the existing footer styles. Add a rule that makes the button look identical to the footer anchors. Append this block at the end of the existing `.mystery-footer` rules (search for `.mystery-footer a` and add directly after that selector's rule):
+
+```css
+.mystery-footer-bug-report {
+ background: none;
+ border: none;
+ padding: 0;
+ margin: 0;
+ font: inherit;
+ color: inherit;
+ text-decoration: underline;
+ cursor: pointer;
+}
+.mystery-footer-bug-report:hover,
+.mystery-footer-bug-report:focus-visible {
+ text-decoration: none;
+}
+.mystery-footer-bug-report:disabled {
+ opacity: 0.5;
+ cursor: progress;
+}
+```
+
+If `.mystery-footer a` styles its anchors differently (e.g. specific color, no underline by default), match those properties instead. Look at the actual `a` rule and copy its `color`/`text-decoration` declarations into `.mystery-footer-bug-report` so the two render visually identically.
+
+- [ ] **Step 6: Run the full type check and build**
+
+```
+npx astro check
+npm run build
+```
+
+Expected: 0 errors, build succeeds.
+
+- [ ] **Step 7: Commit**
+
+```
+git add src/pages/index.astro src/ui/crt.css
+git commit -m "feat(ui): add Report a Bug footer button and wire bug tracking modules"
+```
+
+---
+
+## Task 8: Update TODOs
+
+**Files:**
+- Modify: `src/world/TODOs.md:45`
+
+- [ ] **Step 1: Rewrite the TODO line**
+
+Replace line 45 of `src/world/TODOs.md`:
+
+```
+- [ ] Set up BugPin as a self-hosted visual bug reporter for the site, then have incoming reports create markdown files under `src/world/bugs/` via a webhook or API bridge so bugs can be tracked in git alongside the game content. Include screenshot/annotation metadata in the markdown and decide whether these bug docs stay outside the world loader or get their own loader later.
+```
+
+with:
+
+```
+- [ ] Add a "Report a Bug" footer link backed by Bugpin (widget at bugpin.half.st → forwards to GitHub Issues). Add Bugsink (@sentry/browser → bugsink.half.st) for automatic JS error capture. Mark complete after manual verification: a test report appears in the Bugpin portal AND a GitHub issue is created AND a thrown error appears in the Bugsink portal.
+```
+
+- [ ] **Step 2: Commit**
+
+```
+git add src/world/TODOs.md
+git commit -m "docs: rewrite TODO 45 to reflect Bugpin/Bugsink approach"
+```
+
+---
+
+## Task 9: Manual smoke test
+
+**Pre-req:** the Bugpin GitHub integration must be configured server-side before user reports will create issues. See spec §5. Steps below test the widget plumbing regardless.
+
+- [ ] **Step 1: Start dev server**
+
+```
+npm run dev
+```
+
+Open the URL it prints (default `http://localhost:4321`).
+
+- [ ] **Step 2: Verify the footer button renders**
+
+In the rendered footer at the bottom of the page, confirm "Report a Bug" appears after "Source Code", styled like the surrounding links.
+
+- [ ] **Step 3: Verify the widget lazy-loads**
+
+Open DevTools → Network. Filter for `widget.js`. Confirm NO request to `bugpin.half.st/widget.js` on cold page load.
+
+Click "Report a Bug". Confirm:
+- A single GET to `https://bugpin.half.st/widget.js` (status 200).
+- The Bugpin dialog opens.
+- Take a screenshot, write "smoke test" in the note, submit.
+- The dialog closes / shows a success state.
+
+Re-click "Report a Bug". Confirm NO second `widget.js` request — only the dialog re-opens.
+
+- [ ] **Step 4: Verify Bugpin received the report**
+
+Open `https://bugpin.half.st/portal`. Confirm the "smoke test" report appears with the screenshot attached.
+
+If the GitHub integration is configured: confirm a matching issue appears in the halfstreet GitHub repo.
+
+- [ ] **Step 5: Verify Bugsink captures an uncaught error**
+
+In the dev server's running page, open DevTools console and run:
+
+```js
+setTimeout(() => { throw new Error('bugsink smoke test') }, 0)
+```
+
+Open `https://bugsink.half.st`. Confirm a "bugsink smoke test" event appears within ~30 seconds.
+
+- [ ] **Step 6: Verify the launcher styling is acceptable**
+
+After step 3, the Bugpin widget's built-in floating launcher may now also be visible on the page. If its presence is visually objectionable, add a CSS rule to `src/ui/crt.css` targeting the Bugpin host element (inspect the DOM to find the selector — Bugpin uses Shadow DOM with a custom-element host like `` or similar). Example:
+
+```css
+bugpin-widget,
+[data-bugpin-launcher] {
+ display: none !important;
+}
+```
+
+If this turns out to be needed, commit the CSS as `style(ui): hide bugpin built-in launcher (we have our own trigger)`. If the launcher's appearance is fine as-is, skip this step.
+
+- [ ] **Step 7: Mark TODO #45 complete**
+
+Once steps 1–5 all pass, edit `src/world/TODOs.md` line 45, change `- [ ]` to `- [x]`, and commit:
+
+```
+git add src/world/TODOs.md
+git commit -m "chore: mark TODO 45 complete"
+```
+
+---
+
+## Done criteria
+
+All of the following are true:
+
+- `npm test` passes.
+- `npx astro check` reports 0 errors.
+- `npm run build` succeeds.
+- Manual smoke (Task 9 steps 1–5) all pass.
+- TODO #45 is `[x]`.