Skip to content
Open

V8 #26

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
451 commits
Select commit Hold shift + click to select a range
c788121
Simplify client-only SPA bun server route handling
qodesmith Mar 30, 2026
614bcf8
Remove reference to tsconfig base file
qodesmith Mar 30, 2026
4904d0a
Avoid stack overflow in checking for localhost
qodesmith Mar 31, 2026
5f7151b
Provide upper bound when finding a dev server port
qodesmith Mar 31, 2026
94c663a
More targeted string replacement for index.html
qodesmith Mar 31, 2026
cd7f81f
Guard against JSON.parse throwing
qodesmith Mar 31, 2026
e44fcf6
Allow users to zoom the site (WCAG friendly)
qodesmith Mar 31, 2026
9b61ba0
Typo
qodesmith Mar 31, 2026
9afdf67
Remove deprecated baseUrl field from tsconfig files
qodesmith Apr 7, 2026
aac5e20
Avoid linting errors when importing css files
qodesmith Apr 7, 2026
7c893fc
Added tsc check to package.json files
qodesmith Apr 7, 2026
4e2eec3
Added github ci/cd workflow to projects
qodesmith Apr 7, 2026
3c08709
Adding .env.example files that remain checked into version control
qodesmith Apr 7, 2026
ec3bbc1
Removed useMemo from sonner component
qodesmith Apr 7, 2026
1648360
Added comments for context on theme atoms
qodesmith Apr 7, 2026
8252091
Improving server security with headers
qodesmith Apr 8, 2026
0b00d1b
Bug fix: Last name
qodesmith Apr 8, 2026
af2f096
Derive domain name from env var
qodesmith Apr 8, 2026
2fab682
Bug fix - Dockerfile.local should also have the {{PROJECT_NAME}} temp…
qodesmith Apr 8, 2026
50c50ff
Improving is0000 handling in fullstack app
qodesmith Apr 10, 2026
5a13ec3
The client-only dev server doesn't need to guard against production env
qodesmith Apr 10, 2026
1669cba
Update dockerfiles across the board
qodesmith Apr 10, 2026
7edc618
Refactor fullstack nested tsconfig - works with Bun runtime and satis…
qodesmith Apr 10, 2026
3040170
Fixed tsconfig setup for fullstack app
qodesmith Apr 11, 2026
9c22984
Added comment to give context on fly volumes
qodesmith Apr 11, 2026
971b4a3
Added biome as a vscode recommended extension
qodesmith Apr 11, 2026
37840a7
Improving build - variable name and Bun.write
qodesmith Apr 11, 2026
20a2a46
Avoid fly.io warnings about proxy
qodesmith Apr 11, 2026
dc19210
Fixed bundling sharp & dockerizing it correctly
qodesmith Apr 11, 2026
a50228b
Read and serve index.html contents in production
qodesmith Apr 11, 2026
54ce2bd
Including fly.io url in accepted domains
qodesmith Apr 11, 2026
c09146a
Sike - it doesn't stop fly.io proxy warnings
qodesmith Apr 11, 2026
54714c5
Reordered Dockerfile env vars
qodesmith Apr 12, 2026
7a9ef70
Woops
qodesmith Apr 12, 2026
8113f7c
Added deploy script to fullstack app
qodesmith Apr 12, 2026
a6d057d
Update deps
qodesmith Apr 12, 2026
5b03fd2
Updated vscode settings
qodesmith Apr 12, 2026
339b9e4
Extracted shared skills into folder
qodesmith Apr 12, 2026
f6fe7ef
Simplified getFilesRecursive using Bun apis
qodesmith Apr 12, 2026
dc498cb
Copying shared content into generated projects
qodesmith Apr 12, 2026
fe4c5dd
Clean up dockerfiles and package.json scripts a bit
qodesmith Apr 12, 2026
acdf48f
Don't log better auth secret to console when creating it
qodesmith Apr 12, 2026
5c4b8e2
Open up SQLite pragmas to dev as well
qodesmith Apr 12, 2026
98067c7
Fix VACUUM INTO with sql.raw and quotes
qodesmith Apr 12, 2026
8fc792e
Adding secure headers to Bun server; added comment on CSP headers
qodesmith Apr 12, 2026
269de6c
Using alias imports for consistency
qodesmith Apr 12, 2026
53fe244
Added comment about why we don't have rate limit middleware in dev
qodesmith Apr 12, 2026
b979f2d
403 is the appropriate response status for noDirectRequestMiddleware
qodesmith Apr 12, 2026
9a35ffa
Reorder how we get ip addresses in rateLimitMiddleware
qodesmith Apr 12, 2026
c4f88fe
Log client error for failed signin
qodesmith Apr 12, 2026
9cfd0bc
Avoid infinite loop with avatar processing by introducing a floor on …
qodesmith Apr 12, 2026
8aea9e9
appSchema using timestamp_ms to match authSchema
qodesmith Apr 13, 2026
eb2823b
appSchema use onUpdate to be consistent with authSchema
qodesmith Apr 13, 2026
4d52bc9
Fix - added error context for changing email
qodesmith Apr 13, 2026
9c4146a
Using reduce syntax since that's what it looked like the original int…
qodesmith Apr 13, 2026
8093f48
Removed unnecessary wrapping of cors middleware
qodesmith Apr 13, 2026
59f3a9b
Use same regex on client for name as server
qodesmith Apr 13, 2026
d339b45
Removed todos
qodesmith Apr 13, 2026
dff6c62
Renamed variable
qodesmith Apr 13, 2026
3fe856c
Typo
qodesmith Apr 13, 2026
9e37d3b
Use fly.io header for ipaddress instead of cloudflare; throw when no …
qodesmith Apr 13, 2026
b8cec44
Improve getEnvVar with TypeScript overloads
qodesmith Apr 13, 2026
e025d1d
Adding comment about type casting for context
qodesmith Apr 13, 2026
3b6e37f
Fix Dockerfile.local for fullstack app
qodesmith Apr 13, 2026
f15c156
Refactored notFound to avoid double requests
qodesmith Apr 13, 2026
f3f5277
Added link to github issue for why sendChangeEmailVerification is com…
qodesmith Apr 13, 2026
f9a9ed8
Implemented account deletion
qodesmith Apr 15, 2026
752a042
Remove session cookie cache; revalidate session on window/tab change
qodesmith Apr 15, 2026
7c47c67
PasswordManagerHint hidden form field
qodesmith Apr 15, 2026
ff36694
Added context comment
qodesmith Apr 15, 2026
09748c8
dbHash.ts => genDbHash.ts
qodesmith Apr 15, 2026
7507782
Consistent api error returning
qodesmith Apr 15, 2026
304f34f
Added admin audit logs to admin endpoints
qodesmith Apr 16, 2026
4b76ada
Explicit variable name
qodesmith Apr 16, 2026
043cbfe
Added db.transaction to add-api-endpoint skill
qodesmith Apr 16, 2026
8386799
Added back the tdd skill - it's referenced by the add-test skill
qodesmith Apr 16, 2026
7cec069
Updating skills
qodesmith Apr 16, 2026
249c6e5
Updated description for bestEffort
qodesmith Apr 16, 2026
0f761e4
Updated signin page to log signin rejection; removed unused union values
qodesmith Apr 16, 2026
5d126a7
Sign in with passkey - client code
qodesmith Apr 16, 2026
4730571
Nice separators on the signin page for the passkey signin
qodesmith Apr 17, 2026
84f7b33
Hono server - avoid infinite fetch index.html loops; dev always fetch…
qodesmith Apr 17, 2026
b7e93b5
Refactored bunServer a bit
qodesmith Apr 17, 2026
bff091f
Db seed script should be scoped to development
qodesmith Apr 18, 2026
d23de03
Use id for aria-controls in input component
qodesmith Apr 18, 2026
c159351
AudioLoader - memoize value to avoid parent re-renders re-randomizing…
qodesmith Apr 18, 2026
e2cbd50
Fix api clients typing as any - use Biome to enforce relative imports…
qodesmith Apr 18, 2026
7546800
Ensure blobPreviewUrl is cleaned up on unmount
qodesmith Apr 18, 2026
5d9f4a9
Avoid stale avatars when uploading a new one
qodesmith Apr 18, 2026
97d6feb
Safely create an authClient singleton (safe for SSR)
qodesmith Apr 18, 2026
6dde6ca
Reworking the tsconfig / import setup; much better for actually check…
qodesmith Apr 18, 2026
739d9a8
createApiClient is more accurate than getApiClient
qodesmith Apr 18, 2026
57368e7
Reuse name regex and error message between client and server
qodesmith Apr 18, 2026
e6ea5dd
Use a state initializer fxn instead of mutating a ref
qodesmith Apr 18, 2026
7389719
Log db backup admin audit after db export
qodesmith Apr 18, 2026
5ea4d14
Improved Prettify type utility
qodesmith Apr 18, 2026
ee4dc91
Rely on types from Tanstack form
qodesmith Apr 18, 2026
ee7203f
Simplified userRoles - just use a damn frozen object; removed unused …
qodesmith Apr 18, 2026
01d2e4a
Prevent errors from drizzle if there is an empy drizzle/meta folder -…
qodesmith Apr 18, 2026
8df5b7f
Replaced Better Auth monkey patching with use of Better Auth's public…
qodesmith Apr 18, 2026
44c71c8
Further tsconfig cleanup
qodesmith Apr 18, 2026
18934be
Refactored bun-env.d.ts files
qodesmith Apr 18, 2026
d6cbc79
Updated deps
qodesmith Apr 18, 2026
70caf0e
bestEffort from @qodestack/utils
qodesmith Apr 18, 2026
5b41bad
Updated deps
qodesmith Apr 18, 2026
24c1ee5
logClientError => useLogClientError
qodesmith Apr 19, 2026
99634cf
Updated comment above /avatar route
qodesmith Apr 19, 2026
af07f16
Type ctx.body to avoid casting each individual value
qodesmith Apr 19, 2026
dde9904
Added systemAuditLogsTable; reworked dbCleanup of stale entities
qodesmith Apr 19, 2026
6f21cf4
Added docker ignore files
qodesmith Apr 19, 2026
ba4edd1
Only render a single toast when multiple form errors are found
qodesmith Apr 19, 2026
00d3470
TW intellisense is wrong. THIS is the correct class to use
qodesmith Apr 19, 2026
19d36a1
In this case, if/else > ternary
qodesmith Apr 19, 2026
1605a1e
Refactoring Passkeys.tsx with Tanstack Query
qodesmith Apr 19, 2026
874e405
Added noreferrer to pair with noopener
qodesmith Apr 19, 2026
697d081
lastName is required - no need for optional checks
qodesmith Apr 19, 2026
0938c5a
derive delete dialog open state from deleteTarget
qodesmith Apr 19, 2026
7132da4
Correcting process.exit() => process.exit(1)
qodesmith Apr 19, 2026
cedefc3
fix: guard killAllTheThings against re-entry from overlapping exit si…
qodesmith Apr 19, 2026
4c635b1
Typos
qodesmith Apr 19, 2026
ee53fff
Added engines.bun to package.json as well as preinstall script to ens…
qodesmith Apr 19, 2026
940e3f5
Named variable
qodesmith Apr 19, 2026
722664e
Move sqlite tables check to startDev.ts to avoid triggering double co…
qodesmith Apr 19, 2026
26c42c7
Added missing db terminator calls
qodesmith Apr 20, 2026
90812be
Cookie cache is explicitly disabled
qodesmith Apr 20, 2026
d1dc3b1
Custom bun-plugin-tailwind - original is not maintained, no source co…
qodesmith Apr 20, 2026
82a2d22
1-liners are hard to read
qodesmith Apr 20, 2026
c2b9e18
Remove session from being returned in beforeLoad - we can add it if w…
qodesmith Apr 20, 2026
a1dce10
Refactoring truthy checks
qodesmith Apr 20, 2026
420d98b
Guard against db inserts throwing
qodesmith Apr 20, 2026
f2e3a62
Added db probe to /health endpoint
qodesmith Apr 20, 2026
065b1cd
Improve avatar perf with the sharp library
qodesmith Apr 20, 2026
78da527
Safeguard against malformed file names
qodesmith Apr 20, 2026
caddf97
Add userId to Passkey queryKey
qodesmith Apr 20, 2026
c1daa3e
Purge errors older than 90 days
qodesmith Apr 20, 2026
d9211ba
Purging stale admin and system records
qodesmith Apr 20, 2026
e4fba45
Not doing account linking
qodesmith Apr 20, 2026
a9d5d48
Double check we're deployed on fly.io before relying on fly-client-ip…
qodesmith Apr 20, 2026
cce0c8a
Use hono context to return html
qodesmith Apr 20, 2026
c4f8316
Increase email token expiration to 15 minutes
qodesmith Apr 20, 2026
1cbac30
consider 400 range of responses
qodesmith Apr 20, 2026
0efb149
Typo
qodesmith Apr 20, 2026
e712033
1 req/s for errors
qodesmith Apr 20, 2026
8b89434
Comment for context
qodesmith Apr 20, 2026
b9646f7
Typo
qodesmith Apr 20, 2026
0464d1f
Oxford comma
qodesmith Apr 20, 2026
ddcc81c
Removed unused ErrorContext union value
qodesmith Apr 27, 2026
7703960
Add 3rd arg to arktypeValidator to return similar error object as han…
qodesmith Apr 27, 2026
91c2bc1
All errors returned from the API should be non-2xx
qodesmith Apr 27, 2026
302866b
Refactor apiAuthClient call to use parseResponse for improved error h…
qodesmith Apr 27, 2026
d97e271
Ok, IN FACT, don't use the 3rd arg to arktypeValidator - it already r…
qodesmith Apr 27, 2026
bba0433
Fixed bug where HMR was not picking up class names changes when savin…
qodesmith Apr 28, 2026
c5b37da
Added LoadingButton custom component
qodesmith Apr 28, 2026
ef12f2b
Show on the client max avatar upload size
qodesmith Apr 29, 2026
e7a9ee1
Updated LoadingButton to take children instead of text
qodesmith Apr 29, 2026
3fc0cbe
Installed Matt Pocock's AI skills - https://github.com/mattpocock/skills
qodesmith May 3, 2026
14ed874
Completed setup of Matt Pocock's AI skills
qodesmith May 3, 2026
069004f
Architecture deepening: workspaces, generator seams, resolver collaps…
qodesmith May 4, 2026
2dc5882
Refresh apk index and clean cache in fullstack Dockerfile
qodesmith May 4, 2026
ddcbb4d
Improved Hono middleware typing
qodesmith May 7, 2026
406d94f
Added SSR-safe context in a comment above client atoms
qodesmith May 8, 2026
aea9ff6
Replacing isSignedInAtom with userAtom; adding user avatar to header
qodesmith May 8, 2026
54a8600
Syncing avatar changes with userAvatarVersionAtom
qodesmith May 8, 2026
d46c33b
Change ErrorContext format to <service>:<operation>:<suffix>
qodesmith May 8, 2026
22f8793
Cleaning up previous run with Matt Pocock's workflow
qodesmith May 11, 2026
dbf3dfe
Removed old planning doc
qodesmith May 11, 2026
3116614
Removed positioning for vanilla and library templates
qodesmith May 11, 2026
08f9673
Created the README.md
qodesmith May 11, 2026
106ea1e
Add minimumReleaseAge = 3 days to bunfig.toml everywhere
qodesmith May 12, 2026
e65f479
Preserve binary template assets byte-for-byte during scaffolding
qodesmith May 12, 2026
3aa6280
Checking for Bun when running create-new-app / cna
qodesmith May 12, 2026
23cb9af
Drop package-manager enforcement; add publish and local-test docs
qodesmith May 12, 2026
19c5c07
Improvements for Windows
qodesmith May 13, 2026
c6fa978
Removed rate limiting
qodesmith May 13, 2026
e7f05c5
Logging rejection errors on the server - avoid rountrip of server => …
qodesmith May 13, 2026
71a49ef
Correct inaccuracies with index page
qodesmith May 13, 2026
b9efe85
Strongly types Better Auth endpoint union
qodesmith May 13, 2026
80eb8fb
Fixed inaccuracies with index page. Replaced tsconfig section with Bi…
qodesmith May 13, 2026
d9e2f80
More updates to index pages
qodesmith May 13, 2026
b840887
Strongly typed better auth endpoints
qodesmith May 14, 2026
6f77939
Scope error toasts to prevent stale toasts after navigation
qodesmith May 14, 2026
d472866
Handle password change with no actual change
qodesmith May 14, 2026
becaa05
Validate password change on server
qodesmith May 14, 2026
106004d
Server validation of password on /reset-password better auth route
qodesmith May 15, 2026
aa6acaa
Resetting form on password reset dialog when dialog closes
qodesmith May 15, 2026
680a782
Updated deps
qodesmith May 15, 2026
a16aacb
Updated deps for projects
qodesmith May 15, 2026
027a098
Updagrading to @better-auth/drizzle-adapter package
qodesmith May 15, 2026
77c0c1b
Changd Tanstack Query quip
qodesmith May 15, 2026
c063b96
Upgrading to @better-auth/drizzle-adapter
qodesmith May 15, 2026
7be612a
Ensure Cards using BorderBeam don't overflow, causing layout shift as…
qodesmith May 17, 2026
24fec36
Updating change email process to a 2-step process, based on Better Au…
qodesmith May 18, 2026
716a5ea
Updated deps
qodesmith May 18, 2026
65cf370
Updated verbiage for confirmation email
qodesmith May 18, 2026
bf46103
Fix step 2 email verification url construction by setting the `callba…
qodesmith May 18, 2026
450fd40
Custom "success scenario" for sendChangeEmailConfirmation - append a …
qodesmith May 18, 2026
490ef14
Fix the custom success scenario for email validation
qodesmith May 19, 2026
fb55c84
Updating Avatar and related components
qodesmith May 19, 2026
b2afff5
Adding all aliases to root tsconfig - this will ensure Shadcn install…
qodesmith May 19, 2026
70a794e
Adjusting fullstack tsconfig files
qodesmith May 19, 2026
3dac5f1
Updated shadcn badge
qodesmith May 19, 2026
bd8ff21
Updated shadcn button
qodesmith May 19, 2026
36f1421
Updated shadcn dialog
qodesmith May 19, 2026
c1d6a20
Updated shadcn hover-card
qodesmith May 19, 2026
7cbc428
Allow list my own packages for updating from npm
qodesmith May 20, 2026
6f039d2
Updated deps
qodesmith May 20, 2026
c4efcf5
Updating dep
qodesmith May 20, 2026
fd674cf
Allowlist my own packages from minimum release age
qodesmith May 20, 2026
821c848
Consistent form naming across the codebase
qodesmith May 20, 2026
3361394
Autofucs the email field on the signin page
qodesmith May 20, 2026
91dd7b3
Refactoring PasswordInput component & usage
qodesmith May 20, 2026
6e2c1ce
Trading padding for flex gap
qodesmith May 20, 2026
6540703
Making the rest of the forms consistent; updated skills to capture us…
qodesmith May 20, 2026
abc9dcd
Fixing Docker related issues
qodesmith May 21, 2026
33cb158
Improving protected static asset handling - now mirrors on-disk folde…
qodesmith May 23, 2026
56ea2fc
Replace string-based index.html rewrite with HTMLRewriter
qodesmith May 23, 2026
259500a
Support long emails
qodesmith May 24, 2026
5495977
Added ability to change name
qodesmith May 24, 2026
0893fe9
Improving Delete account card - destructive border and border beam
qodesmith May 24, 2026
18a290b
Replaced sharp with Bun.Image api
qodesmith May 24, 2026
dbfff44
Better copy layout for Passkeys card
qodesmith May 24, 2026
609e5dd
Add avatar crop dialog with pan and zoom before upload
qodesmith May 24, 2026
c296d14
Added SonarPulse to projects
qodesmith May 25, 2026
ae1a3a4
Use a span as the container for AudioLoader so it can go inside compo…
qodesmith May 25, 2026
0aa302d
Better layout for LoadingButton
qodesmith May 25, 2026
63afb8f
Better control over border color for border-beam component
qodesmith May 25, 2026
824a000
Get rid of the dark destructive color in dark mode - the regular vers…
qodesmith May 25, 2026
6d6d8be
Admin portal; database backup revised
qodesmith May 26, 2026
caeac5c
Skip purge audit log when nothing was purged
qodesmith May 26, 2026
2a2334f
prettyStack is meant for printing to the console, not saving to the db
qodesmith May 26, 2026
44e6a20
Fix @/client alias resolution in shared and server tsconfigs
qodesmith May 26, 2026
1a5eb1c
Add admin portal feature plan (00-07)
qodesmith May 26, 2026
2ac58a4
Admin page redesign foundation (plan 00)
qodesmith May 26, 2026
deba2fe
Users table for /admin (plan 01)
qodesmith May 26, 2026
34f4ed0
User CRUD for /admin (plan 02)
qodesmith May 26, 2026
13d5532
User impersonation for /admin (plan 03)
qodesmith May 26, 2026
2b1dce3
Ban / unban users for /admin (plan 04)
qodesmith May 26, 2026
547d1e0
Role management for /admin (plan 05)
qodesmith May 26, 2026
975c57d
Session management for /admin (plan 06)
qodesmith May 26, 2026
197c7db
Set user password for /admin (plan 07)
qodesmith May 26, 2026
2d95cea
Removing admin plan markdown files
qodesmith May 26, 2026
da95c58
Tidying up components
qodesmith May 26, 2026
e0c300c
Share getUserInitials helper across atom and admin table
qodesmith May 26, 2026
4544bd9
Surface server auth validation messages safely on the client
qodesmith May 30, 2026
d2fcc5b
Extract SortDirection to shared types
qodesmith May 30, 2026
6f99f60
Fix column sort cycling to support asc | desc | unsorted
qodesmith May 30, 2026
a29bdc8
Add useDebouncedValue hook with change-only onDebounced callback
qodesmith May 30, 2026
f9ff8da
Installed react table
qodesmith May 30, 2026
0424fe6
Mask delete-account password field to dodge password managers
qodesmith Jun 9, 2026
eabb888
Add admin & system audit log tables to the admin console
qodesmith Jun 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
49 changes: 49 additions & 0 deletions .agents/skills/caveman/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
name: caveman
description: >
Ultra-compressed communication mode. Cuts token usage ~75% by dropping
filler, articles, and pleasantries while keeping full technical accuracy.
Use when user says "caveman mode", "talk like caveman", "use caveman",
"less tokens", "be brief", or invokes /caveman.
---

Respond terse like smart caveman. All technical substance stay. Only fluff die.

## Persistence

ACTIVE EVERY RESPONSE once triggered. No revert after many turns. No filler drift. Still active if unsure. Off only when user says "stop caveman" or "normal mode".

## Rules

Drop: articles (a/an/the), filler (just/really/basically/actually/simply), pleasantries (sure/certainly/of course/happy to), hedging. Fragments OK. Short synonyms (big not extensive, fix not "implement a solution for"). Abbreviate common terms (DB/auth/config/req/res/fn/impl). Strip conjunctions. Use arrows for causality (X -> Y). One word when one word enough.

Technical terms stay exact. Code blocks unchanged. Errors quoted exact.

Pattern: `[thing] [action] [reason]. [next step].`

Not: "Sure! I'd be happy to help you with that. The issue you're experiencing is likely caused by..."
Yes: "Bug in auth middleware. Token expiry check use `<` not `<=`. Fix:"

### Examples

**"Why React component re-render?"**

> Inline obj prop -> new ref -> re-render. `useMemo`.

**"Explain database connection pooling."**

> Pool = reuse DB conn. Skip handshake -> fast under load.

## Auto-Clarity Exception

Drop caveman temporarily for: security warnings, irreversible action confirmations, multi-step sequences where fragment order risks misread, user asks to clarify or repeats question. Resume caveman after clear part done.

Example -- destructive op:

> **Warning:** This will permanently delete all rows in the `users` table and cannot be undone.
>
> ```sql
> DROP TABLE users;
> ```
>
> Caveman resume. Verify backup exist first.
117 changes: 117 additions & 0 deletions .agents/skills/diagnose/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
---
name: diagnose
description: Disciplined diagnosis loop for hard bugs and performance regressions. Reproduce → minimise → hypothesise → instrument → fix → regression-test. Use when user says "diagnose this" / "debug this", reports a bug, says something is broken/throwing/failing, or describes a performance regression.
---

# Diagnose

A discipline for hard bugs. Skip phases only when explicitly justified.

When exploring the codebase, use the project's domain glossary to get a clear mental model of the relevant modules, and check ADRs in the area you're touching.

## Phase 1 — Build a feedback loop

**This is the skill.** Everything else is mechanical. If you have a fast, deterministic, agent-runnable pass/fail signal for the bug, you will find the cause — bisection, hypothesis-testing, and instrumentation all just consume that signal. If you don't have one, no amount of staring at code will save you.

Spend disproportionate effort here. **Be aggressive. Be creative. Refuse to give up.**

### Ways to construct one — try them in roughly this order

1. **Failing test** at whatever seam reaches the bug — unit, integration, e2e.
2. **Curl / HTTP script** against a running dev server.
3. **CLI invocation** with a fixture input, diffing stdout against a known-good snapshot.
4. **Headless browser script** (Playwright / Puppeteer) — drives the UI, asserts on DOM/console/network.
5. **Replay a captured trace.** Save a real network request / payload / event log to disk; replay it through the code path in isolation.
6. **Throwaway harness.** Spin up a minimal subset of the system (one service, mocked deps) that exercises the bug code path with a single function call.
7. **Property / fuzz loop.** If the bug is "sometimes wrong output", run 1000 random inputs and look for the failure mode.
8. **Bisection harness.** If the bug appeared between two known states (commit, dataset, version), automate "boot at state X, check, repeat" so you can `git bisect run` it.
9. **Differential loop.** Run the same input through old-version vs new-version (or two configs) and diff outputs.
10. **HITL bash script.** Last resort. If a human must click, drive _them_ with `scripts/hitl-loop.template.sh` so the loop is still structured. Captured output feeds back to you.

Build the right feedback loop, and the bug is 90% fixed.

### Iterate on the loop itself

Treat the loop as a product. Once you have _a_ loop, ask:

- Can I make it faster? (Cache setup, skip unrelated init, narrow the test scope.)
- Can I make the signal sharper? (Assert on the specific symptom, not "didn't crash".)
- Can I make it more deterministic? (Pin time, seed RNG, isolate filesystem, freeze network.)

A 30-second flaky loop is barely better than no loop. A 2-second deterministic loop is a debugging superpower.

### Non-deterministic bugs

The goal is not a clean repro but a **higher reproduction rate**. Loop the trigger 100×, parallelise, add stress, narrow timing windows, inject sleeps. A 50%-flake bug is debuggable; 1% is not — keep raising the rate until it's debuggable.

### When you genuinely cannot build a loop

Stop and say so explicitly. List what you tried. Ask the user for: (a) access to whatever environment reproduces it, (b) a captured artifact (HAR file, log dump, core dump, screen recording with timestamps), or (c) permission to add temporary production instrumentation. Do **not** proceed to hypothesise without a loop.

Do not proceed to Phase 2 until you have a loop you believe in.

## Phase 2 — Reproduce

Run the loop. Watch the bug appear.

Confirm:

- [ ] The loop produces the failure mode the **user** described — not a different failure that happens to be nearby. Wrong bug = wrong fix.
- [ ] The failure is reproducible across multiple runs (or, for non-deterministic bugs, reproducible at a high enough rate to debug against).
- [ ] You have captured the exact symptom (error message, wrong output, slow timing) so later phases can verify the fix actually addresses it.

Do not proceed until you reproduce the bug.

## Phase 3 — Hypothesise

Generate **3–5 ranked hypotheses** before testing any of them. Single-hypothesis generation anchors on the first plausible idea.

Each hypothesis must be **falsifiable**: state the prediction it makes.

> Format: "If <X> is the cause, then <changing Y> will make the bug disappear / <changing Z> will make it worse."

If you cannot state the prediction, the hypothesis is a vibe — discard or sharpen it.

**Show the ranked list to the user before testing.** They often have domain knowledge that re-ranks instantly ("we just deployed a change to #3"), or know hypotheses they've already ruled out. Cheap checkpoint, big time saver. Don't block on it — proceed with your ranking if the user is AFK.

## Phase 4 — Instrument

Each probe must map to a specific prediction from Phase 3. **Change one variable at a time.**

Tool preference:

1. **Debugger / REPL inspection** if the env supports it. One breakpoint beats ten logs.
2. **Targeted logs** at the boundaries that distinguish hypotheses.
3. Never "log everything and grep".

**Tag every debug log** with a unique prefix, e.g. `[DEBUG-a4f2]`. Cleanup at the end becomes a single grep. Untagged logs survive; tagged logs die.

**Perf branch.** For performance regressions, logs are usually wrong. Instead: establish a baseline measurement (timing harness, `performance.now()`, profiler, query plan), then bisect. Measure first, fix second.

## Phase 5 — Fix + regression test

Write the regression test **before the fix** — but only if there is a **correct seam** for it.

A correct seam is one where the test exercises the **real bug pattern** as it occurs at the call site. If the only available seam is too shallow (single-caller test when the bug needs multiple callers, unit test that can't replicate the chain that triggered the bug), a regression test there gives false confidence.

**If no correct seam exists, that itself is the finding.** Note it. The codebase architecture is preventing the bug from being locked down. Flag this for the next phase.

If a correct seam exists:

1. Turn the minimised repro into a failing test at that seam.
2. Watch it fail.
3. Apply the fix.
4. Watch it pass.
5. Re-run the Phase 1 feedback loop against the original (un-minimised) scenario.

## Phase 6 — Cleanup + post-mortem

Required before declaring done:

- [ ] Original repro no longer reproduces (re-run the Phase 1 loop)
- [ ] Regression test passes (or absence of seam is documented)
- [ ] All `[DEBUG-...]` instrumentation removed (`grep` the prefix)
- [ ] Throwaway prototypes deleted (or moved to a clearly-marked debug location)
- [ ] The hypothesis that turned out correct is stated in the commit / PR message — so the next debugger learns

**Then ask: what would have prevented this bug?** If the answer involves architectural change (no good test seam, tangled callers, hidden coupling) hand off to the `/improve-codebase-architecture` skill with the specifics. Make the recommendation **after** the fix is in, not before — you have more information now than when you started.
41 changes: 41 additions & 0 deletions .agents/skills/diagnose/scripts/hitl-loop.template.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env bash
# Human-in-the-loop reproduction loop.
# Copy this file, edit the steps below, and run it.
# The agent runs the script; the user follows prompts in their terminal.
#
# Usage:
# bash hitl-loop.template.sh
#
# Two helpers:
# step "<instruction>" → show instruction, wait for Enter
# capture VAR "<question>" → show question, read response into VAR
#
# At the end, captured values are printed as KEY=VALUE for the agent to parse.

set -euo pipefail

step() {
printf '\n>>> %s\n' "$1"
read -r -p " [Enter when done] " _
}

capture() {
local var="$1" question="$2" answer
printf '\n>>> %s\n' "$question"
read -r -p " > " answer
printf -v "$var" '%s' "$answer"
}

# --- edit below ---------------------------------------------------------

step "Open the app at http://localhost:3000 and sign in."

capture ERRORED "Click the 'Export' button. Did it throw an error? (y/n)"

capture ERROR_MSG "Paste the error message (or 'none'):"

# --- edit above ---------------------------------------------------------

printf '\n--- Captured ---\n'
printf 'ERRORED=%s\n' "$ERRORED"
printf 'ERROR_MSG=%s\n' "$ERROR_MSG"
10 changes: 10 additions & 0 deletions .agents/skills/grill-me/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
name: grill-me
description: Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions "grill me".
---

Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer.

Ask the questions one at a time.

If a question can be answered by exploring the codebase, explore the codebase instead.
47 changes: 47 additions & 0 deletions .agents/skills/grill-with-docs/ADR-FORMAT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# ADR Format

ADRs live in `docs/adr/` and use sequential numbering: `0001-slug.md`, `0002-slug.md`, etc.

Create the `docs/adr/` directory lazily — only when the first ADR is needed.

## Template

```md
# {Short title of the decision}

{1-3 sentences: what's the context, what did we decide, and why.}
```

That's it. An ADR can be a single paragraph. The value is in recording *that* a decision was made and *why* — not in filling out sections.

## Optional sections

Only include these when they add genuine value. Most ADRs won't need them.

- **Status** frontmatter (`proposed | accepted | deprecated | superseded by ADR-NNNN`) — useful when decisions are revisited
- **Considered Options** — only when the rejected alternatives are worth remembering
- **Consequences** — only when non-obvious downstream effects need to be called out

## Numbering

Scan `docs/adr/` for the highest existing number and increment by one.

## When to offer an ADR

All three of these must be true:

1. **Hard to reverse** — the cost of changing your mind later is meaningful
2. **Surprising without context** — a future reader will look at the code and wonder "why on earth did they do it this way?"
3. **The result of a real trade-off** — there were genuine alternatives and you picked one for specific reasons

If a decision is easy to reverse, skip it — you'll just reverse it. If it's not surprising, nobody will wonder why. If there was no real alternative, there's nothing to record beyond "we did the obvious thing."

### What qualifies

- **Architectural shape.** "We're using a monorepo." "The write model is event-sourced, the read model is projected into Postgres."
- **Integration patterns between contexts.** "Ordering and Billing communicate via domain events, not synchronous HTTP."
- **Technology choices that carry lock-in.** Database, message bus, auth provider, deployment target. Not every library — just the ones that would take a quarter to swap out.
- **Boundary and scope decisions.** "Customer data is owned by the Customer context; other contexts reference it by ID only." The explicit no-s are as valuable as the yes-s.
- **Deliberate deviations from the obvious path.** "We're using manual SQL instead of an ORM because X." Anything where a reasonable reader would assume the opposite. These stop the next engineer from "fixing" something that was deliberate.
- **Constraints not visible in the code.** "We can't use AWS because of compliance requirements." "Response times must be under 200ms because of the partner API contract."
- **Rejected alternatives when the rejection is non-obvious.** If you considered GraphQL and picked REST for subtle reasons, record it — otherwise someone will suggest GraphQL again in six months.
77 changes: 77 additions & 0 deletions .agents/skills/grill-with-docs/CONTEXT-FORMAT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# CONTEXT.md Format

## Structure

```md
# {Context Name}

{One or two sentence description of what this context is and why it exists.}

## Language

**Order**:
{A concise description of the term}
_Avoid_: Purchase, transaction

**Invoice**:
A request for payment sent to a customer after delivery.
_Avoid_: Bill, payment request

**Customer**:
A person or organization that places orders.
_Avoid_: Client, buyer, account

## Relationships

- An **Order** produces one or more **Invoices**
- An **Invoice** belongs to exactly one **Customer**

## Example dialogue

> **Dev:** "When a **Customer** places an **Order**, do we create the **Invoice** immediately?"
> **Domain expert:** "No — an **Invoice** is only generated once a **Fulfillment** is confirmed."

## Flagged ambiguities

- "account" was used to mean both **Customer** and **User** — resolved: these are distinct concepts.
```

## Rules

- **Be opinionated.** When multiple words exist for the same concept, pick the best one and list the others as aliases to avoid.
- **Flag conflicts explicitly.** If a term is used ambiguously, call it out in "Flagged ambiguities" with a clear resolution.
- **Keep definitions tight.** One sentence max. Define what it IS, not what it does.
- **Show relationships.** Use bold term names and express cardinality where obvious.
- **Only include terms specific to this project's context.** General programming concepts (timeouts, error types, utility patterns) don't belong even if the project uses them extensively. Before adding a term, ask: is this a concept unique to this context, or a general programming concept? Only the former belongs.
- **Group terms under subheadings** when natural clusters emerge. If all terms belong to a single cohesive area, a flat list is fine.
- **Write an example dialogue.** A conversation between a dev and a domain expert that demonstrates how the terms interact naturally and clarifies boundaries between related concepts.

## Single vs multi-context repos

**Single context (most repos):** One `CONTEXT.md` at the repo root.

**Multiple contexts:** A `CONTEXT-MAP.md` at the repo root lists the contexts, where they live, and how they relate to each other:

```md
# Context Map

## Contexts

- [Ordering](./src/ordering/CONTEXT.md) — receives and tracks customer orders
- [Billing](./src/billing/CONTEXT.md) — generates invoices and processes payments
- [Fulfillment](./src/fulfillment/CONTEXT.md) — manages warehouse picking and shipping

## Relationships

- **Ordering → Fulfillment**: Ordering emits `OrderPlaced` events; Fulfillment consumes them to start picking
- **Fulfillment → Billing**: Fulfillment emits `ShipmentDispatched` events; Billing consumes them to generate invoices
- **Ordering ↔ Billing**: Shared types for `CustomerId` and `Money`
```

The skill infers which structure applies:

- If `CONTEXT-MAP.md` exists, read it to find contexts
- If only a root `CONTEXT.md` exists, single context
- If neither exists, create a root `CONTEXT.md` lazily when the first term is resolved

When multiple contexts exist, infer which one the current topic relates to. If unclear, ask.
Loading