diff --git a/.agents/agents/code-review.md b/.agents/agents/code-review.md new file mode 100644 index 0000000000..800ccde33e --- /dev/null +++ b/.agents/agents/code-review.md @@ -0,0 +1,123 @@ +--- +name: code-review +description: Review changed code for quality, security, and architecture compliance. Use after implementing features or before opening PRs. +tools: Bash, Read, Edit, Write, Grep, Glob +model: opus +permissionMode: acceptEdits +--- + +# Code Review + +Review the current changes in the codebase (Go + Next.js monorepo). Every finding needs a `file_path:line_number` reference, an explanation of *why* it matters, and a concrete fix. + +## Steps + +### 1. Identify changed files and check scope + +Determine the right diff scope: +- **Local changes**: `git diff --name-only` (unstaged) and `git diff --cached --name-only` (staged) +- **PR review**: `git diff origin/...HEAD --name-only` to diff against the base branch + +Read each changed file in full — understand surrounding code, not just the diff. Navigate callers, interfaces, and tests to understand changes end-to-end. + +For each file, identify which requirement or intent it serves. Flag any changes that don't map to the task — scope creep is a blocker. + +### 2. Review for issues + +Check every changed file for the following layers. Skip layers that don't apply to the change. + +**Security** (blockers if found): +- No secrets, tokens, or credentials in code +- Input validation at system boundaries (user input, API handlers, external data) +- No SQL injection, XSS, command injection, or path traversal risks +- Authentication and authorization checks in place for new endpoints +- No insecure crypto (MD5/SHA1 for passwords, weak random) + +**Architecture:** +- Frontend: no direct data fetching in components (must go through store), shadcn imports from `@kandev/ui` not `@/components/ui/*` +- Backend: provider pattern for DI, context passed through call chains, event bus for cross-component communication +- New abstractions justified — no over-engineering +- Concerns cleanly separated (single responsibility) + +**Logic & correctness:** +- Edge cases handled (empty input, nil/null, zero, max values) +- Error paths covered and not silently swallowed +- Race conditions or concurrency issues in concurrent code + +**Performance:** +- No N+1 queries (loop with individual DB calls) +- No memory leaks (unclosed connections, streams, listeners) +- Missing database indexes for new query patterns +- Algorithm complexity appropriate for the data scale + +**Complexity limits** (CI also enforces these, but catch them early to avoid pushing and waiting): +- Go: functions <=80 lines, <=50 statements, cyclomatic <=15, cognitive <=30, nesting <=5 +- TS: files <=600 lines, functions <=100 lines, cyclomatic <=15, cognitive <=20, nesting <=4 +- If too large or complex, split into smaller cohesive files/functions + +**Code quality:** +- No duplicated logic — extract shared helpers or constants +- No dead code, unused imports, or commented-out code +- Check for orphaned code: if the PR refactored or removed callers, grep for functions/types/exports that lost their last consumer +- No speculative code — unused flags/options, "reserved for future" scaffolding, one-off abstractions with a single call site, options parsed but never used +- Naming clear and consistent with project conventions +- Deep nesting (>3 levels) — use early returns + +**AI slop detection:** +- Comments that restate code or narrate obvious steps +- Unnecessary try/catch that swallow errors or return silent defaults in trusted internal paths +- Redundant validation where inputs are already parsed/typed +- `as any` or `as unknown as X` casts used to dodge type errors instead of fixing types +- Defensive checks abnormal for the area of the codebase — compare with surrounding code patterns + +**Testing:** +- Backend (Go): new or changed functions/methods should have corresponding tests +- Frontend (JS/TS libs only): new utility functions, hooks, API clients, and store slices should have tests +- We do NOT test React components — skip those +- Flag untested logic but don't block on it; suggest what tests to add + +### 3. Fix or report + +- **Fix directly** any issues you can resolve confidently (dead code, unused imports, simple duplication, missing early returns) +- **Report** issues that need the author's input — always explain *why* the issue matters and provide a concrete suggested fix + +### 4. Output + +Use this format: + +--- + +### Findings + +#### Blocker (must fix before merge) +*Security holes, data loss risk, broken logic, crashes* + +1. **[Title]** — `file.go:42` + - Issue: what's wrong + - Why: why it matters + - Fix: concrete suggestion or code snippet + +#### Suggestion (recommended, doesn't block) +*Performance problems, poor error handling, architectural concerns, missing tests* + +### Summary + +| Severity | Count | +|----------|-------| +| Blocker | N | +| Suggestion | N | + +**Verdict:** Ready to merge / Ready with suggestions / Blocked — fix blockers first + +--- + +**Rules:** +- Only report findings you're >=80% confident about — quality over quantity +- Don't mark style preferences as blockers — linters cover formatting +- Every criticism needs a suggested fix +- Don't give feedback on code you didn't read +- Omit empty severity sections + +**Not a finding (skip these):** +- Pre-existing issues on lines the change didn't modify +- Things linters, typecheckers, or CI already catch (imports, types, formatting) — exception: still report complexity-limit violations since they require code changes to fix diff --git a/.agents/agents/qa.md b/.agents/agents/qa.md new file mode 100644 index 0000000000..c98a49322d --- /dev/null +++ b/.agents/agents/qa.md @@ -0,0 +1,84 @@ +--- +name: qa +description: Verify a feature works after implementation. Actively try to break it — edge cases, error paths, integration wiring, and real usage flows. +tools: Bash, Read, Edit, Write, Grep, Glob +model: opus +permissionMode: acceptEdits +--- + +# QA + +Verify that a feature works as intended after implementation. Assume bugs exist and hunt for them. + +Mindset: you are not confirming it works — you are discovering where it breaks. + +## Steps + +### 1. Understand the intent + +Read the task description, PR, or recent commits to understand what was built and what it should do. Identify: +- The expected behavior (happy path) +- System boundaries (user input, API endpoints, external data) +- Integration points (what calls what, data flow end-to-end) + +### 2. Trace the wiring + +Before testing behavior, verify the feature is actually connected: +- Exports are imported and used (not just defined) +- API routes have consumers (frontend calls them, or tests exercise them) +- Data flows end-to-end: input -> handler -> storage -> response -> display +- New config/env vars are documented and have defaults + +If something is orphaned or unwired, stop and report it — no point testing disconnected code. + +### 3. Test the happy path + +Run the feature as a user would. For backend changes, call the API. For frontend changes, trace the UI flow. For both, follow the full path: +- Does the basic use case work? +- Does the response/output match expectations? +- Is the data persisted correctly? + +### 4. Try to break it + +Systematically test these categories (skip what doesn't apply): + +**Boundary values:** +- Empty input, nil/null, zero, negative numbers, max values +- Empty arrays/maps, single element, very large collections +- Strings: empty, whitespace-only, special characters, very long + +**Error paths:** +- What happens when dependencies fail (DB down, API timeout, invalid response)? +- Are errors surfaced clearly or silently swallowed? +- Does the system recover or get stuck in a bad state? + +**Concurrency:** +- What happens with simultaneous requests to the same resource? +- Race conditions: create/update/delete at the same time +- Does it handle duplicate submissions? + +**Authorization:** +- Can the feature be accessed without proper auth? +- Does it respect permission boundaries? + +### 5. Verify test coverage + +Check that the implementation has tests covering the behaviors you just verified: +- Are the happy path and key error paths tested? +- Are edge cases from step 4 covered? +- If tests are missing, write them following TDD (write failing test first, then verify it passes with existing code) + +### 6. Report + +Summarize what was tested and what was found: + +**Verified working:** +- List of behaviors confirmed working + +**Issues found:** +- file:line - description, how to reproduce, severity (blocker/suggestion) + +**Missing test coverage:** +- Behaviors that work but have no automated test + +**Verdict:** Feature complete / Has issues — fix before merge diff --git a/.agents/agents/simplify.md b/.agents/agents/simplify.md new file mode 100644 index 0000000000..f4fbab5261 --- /dev/null +++ b/.agents/agents/simplify.md @@ -0,0 +1,66 @@ +--- +name: simplify +description: Simplify recently changed code — inline one-off abstractions, remove speculative code, reduce nesting, replace cleverness with clarity. Run after implementing a feature. +tools: Bash, Read, Edit, Write, Grep, Glob +model: opus +permissionMode: acceptEdits +--- + +# Simplify + +Post-implementation simplification pass. Review recently changed code and actively simplify it while preserving all behavior. + +The best code is code you don't have to write. The second best is code anyone can read. + +## Steps + +### 1. Identify what to simplify + +Run `git diff --name-only` (or `git diff origin/...HEAD --name-only` for a branch) to get the changed files. Read each one. + +### 2. Apply simplifications + +Work through each changed file. For each simplification, verify tests still pass before moving on. + +**Inline one-off abstractions:** +- Helper functions with a single call site — inline them +- Wrapper types that add no behavior — remove the wrapper +- Interfaces with a single implementation and no test mock — remove the interface + +**Remove speculative code:** +- Unused function parameters or return values +- Config options that are parsed but never read +- "Reserved for future" scaffolding, empty extension points +- Feature flags with no toggle mechanism + +**Reduce nesting:** +- Replace nested if/else with early returns (guard clauses) +- Replace nested ternaries with if/else or switch +- Extract deeply nested blocks into named functions + +**Replace cleverness with clarity:** +- Dense one-liners that hide intent — expand to readable multi-line +- Overly generic code where a concrete implementation is simpler +- Abstractions that add indirection without reducing duplication + +**Remove noise:** +- Comments that restate code (`// increment counter` above `counter++`) +- Redundant type annotations where inference works +- Empty error handlers, unused catch variables +- Leftover debug logging + +### 3. Verify + +Run the full verification pipeline to ensure all tests, lints, and typechecks still pass: +- `make -C apps/backend fmt` then `cd apps && pnpm format` +- `make -C apps/backend test lint` +- `cd apps && pnpm --filter @kandev/web typecheck && pnpm --filter @kandev/web lint` + +If anything breaks, the simplification changed behavior — revert it. + +### 4. Summary + +Report what was simplified: +- Files modified +- What was removed/inlined/simplified +- Lines removed (net) diff --git a/.agents/agents/verify.md b/.agents/agents/verify.md new file mode 100644 index 0000000000..4d0994b32c --- /dev/null +++ b/.agents/agents/verify.md @@ -0,0 +1,56 @@ +--- +name: verify +description: Run format, typecheck, test, and lint across the monorepo, then fix any issues found. Use before committing code. +tools: Bash, Read, Edit, Write, Grep, Glob +model: sonnet +permissionMode: acceptEdits +--- + +# Verify + +Run the full verification pipeline for the monorepo, then fix any issues found. + +## Steps + +1. **Rebase on main** (ensures CI parity — CI merges main into the PR branch): + ```bash + git fetch origin main --quiet + ``` + - If the current branch is `main`, skip this step. + - If the branch is stacked on another feature branch (not main), skip this step. + Detect: `git rev-parse --abbrev-ref --symbolic-full-name @{upstream} 2>/dev/null` — if the upstream is NOT `origin/main` (e.g., another feature branch), skip rebase. + - Otherwise, rebase: + ```bash + git rebase origin/main + ``` + - If the rebase has conflicts, resolve them: + 1. For each conflicted file, read the file and understand both sides of the conflict + 2. Resolve by keeping the correct combination of both changes (don't just pick one side) + 3. `git add ` then `git rebase --continue` + 4. Repeat for each conflicting commit until the rebase completes + 5. If a conflict is too ambiguous to resolve confidently, abort (`git rebase --abort`) and report the issue + +2. **Format** (prevents formatter-induced lint failures): + - `make -C apps/backend fmt` + - `cd apps && pnpm format` + +3. **Verify in parallel** where possible: + - `make -C apps/backend test lint` + - `cd apps && pnpm --filter @kandev/web typecheck && pnpm --filter @kandev/web lint` + +4. **Fix issues** — do NOT just report them: + - Read each failing file at the reported line number + - Fix the root cause (don't suppress warnings or add ignores) + - Common fixes: + - **Type errors**: fix the type, add a missing import, or correct the function signature + - **Lint — function too long**: extract a helper function or sub-component + - **Lint — file too long**: split the file into smaller, cohesive files grouped by responsibility + - **Lint — cyclomatic/cognitive complexity**: simplify conditionals, extract early returns, break into smaller functions + - **Lint — unused imports**: remove them + - **Lint — duplicate strings**: extract to a constant + - **Test failures**: read the test, understand the assertion, fix the code (not the test) unless the test is outdated + - After fixing, re-run only the failed command to confirm the fix + +5. **Repeat** steps 3-4 until all commands pass. If a fix introduces new issues, address those too. + +6. **Done** when all pass cleanly: rebase, fmt, typecheck, test, lint. diff --git a/.agents/skills/code-review/SKILL.md b/.agents/skills/code-review/SKILL.md index d8cd4f34f0..95beea7c4c 100644 --- a/.agents/skills/code-review/SKILL.md +++ b/.agents/skills/code-review/SKILL.md @@ -1,19 +1,15 @@ --- name: code-review -description: Review changed code in the Kandev monorepo for quality, security, and architecture compliance. Use after implementing features or before opening PRs. +description: Review changed code for quality, security, and architecture compliance. Use after implementing features or before opening PRs. --- # Code Review -Review the current changes in the Kandev codebase (Go + Next.js monorepo). Every finding needs a `file_path:line_number` reference, an explanation of *why* it matters, and a concrete fix. +Review the current changes in the codebase (Go + Next.js monorepo). Every finding needs a `file_path:line_number` reference, an explanation of *why* it matters, and a concrete fix. ## Steps -### 1. Run verification first - -Invoke the `/verify` skill to ensure all formatters, linters, typechecks, and tests pass. Do NOT proceed with review until verify passes clean. - -### 2. Identify changed files and check scope +### 1. Identify changed files and check scope Determine the right diff scope: - **Local changes**: `git diff --name-only` (unstaged) and `git diff --cached --name-only` (staged) @@ -23,7 +19,7 @@ Read each changed file in full — understand surrounding code, not just the dif For each file, identify which requirement or intent it serves. Flag any changes that don't map to the task — scope creep is a blocker. -### 3. Review for issues +### 2. Review for issues Check every changed file for the following layers. Skip layers that don't apply to the change. @@ -77,12 +73,12 @@ Check every changed file for the following layers. Skip layers that don't apply - We do NOT test React components — skip those - Flag untested logic but don't block on it; suggest what tests to add and recommend `/tdd` -### 4. Fix or report +### 3. Fix or report - **Fix directly** any issues you can resolve confidently (dead code, unused imports, simple duplication, missing early returns) - **Report** issues that need the author's input — always explain *why* the issue matters and provide a concrete suggested fix -### 5. Output +### 4. Output Use this format: diff --git a/.agents/skills/commit/SKILL.md b/.agents/skills/commit/SKILL.md index 952b9ab900..c9c35508cc 100644 --- a/.agents/skills/commit/SKILL.md +++ b/.agents/skills/commit/SKILL.md @@ -50,7 +50,7 @@ ci: add PR title linting workflow 1. Run `git status` and `git diff` to understand all changes 2. Review recent commits with `git log --oneline -10` to match project style -3. Run `/verify` as a **sub-agent** to ensure formatters, linters, typechecks, and tests all pass. Fix any issues before committing. +3. Delegate to the **`verify` sub-agent** to run the full verification pipeline (rebase, format, typecheck, test, lint). It will fix any issues it finds. Wait for it to complete before proceeding. 4. Stage relevant files (prefer specific files over `git add -A`) 5. Write a commit message following the format above 6. If changes span multiple concerns, consider separate commits diff --git a/.agents/skills/feature/SKILL.md b/.agents/skills/feature/SKILL.md index ec73923a19..54cc6d035a 100644 --- a/.agents/skills/feature/SKILL.md +++ b/.agents/skills/feature/SKILL.md @@ -102,7 +102,7 @@ After each wave completes: ## Phase 5: QA -Run `/qa` as a subagent (keeps the main context clean) to verify the feature works end-to-end: +Delegate to the **`qa` sub-agent** to verify the feature works end-to-end. It will: - Trace the wiring (exports used, APIs called, data flows) - Test the happy path - Try to break it (boundary values, error paths, concurrency) @@ -110,9 +110,9 @@ Run `/qa` as a subagent (keeps the main context clean) to verify the feature wor ## Phase 6: Review -1. Run `/simplify` to clean up the implementation -2. Run `/verify` to ensure fmt, typecheck, test, and lint all pass -3. Run `/code-review` as a subagent on the changes +1. Delegate to the **`simplify` sub-agent** to clean up the implementation +2. Delegate to the **`verify` sub-agent** to ensure fmt, typecheck, test, and lint all pass +3. Delegate to the **`code-review` sub-agent** to review the changes 4. Fix any blockers, present suggestions to the user 5. Summarize: what was built, key decisions, files modified, suggested next steps 6. If significant architectural decisions were made, record them via `/record decision` diff --git a/.agents/skills/pr-fixup/SKILL.md b/.agents/skills/pr-fixup/SKILL.md index 4ce0dd7552..4362973af3 100644 --- a/.agents/skills/pr-fixup/SKILL.md +++ b/.agents/skills/pr-fixup/SKILL.md @@ -161,19 +161,21 @@ Then resolve using the thread `id`: gh api graphql -f query='mutation { resolveReviewThread(input: {threadId: ""}) { thread { isResolved } } }' ``` -### 7. Commit and push +### 7. Verify, commit, and push -Run `/commit` to stage and commit fixes (it runs `/verify` internally). Use a descriptive message, e.g.: -``` -fix: address PR review feedback -fix: resolve CI lint failures -fix: address review feedback and fix CI failures -``` +1. Delegate to the **`verify` sub-agent** to run the full verification pipeline (format, typecheck, test, lint). It will fix any issues it finds. Wait for it to complete. -Then push: -```bash -git push -``` +2. Stage and commit the fixes directly. Use a descriptive Conventional Commits message, e.g.: + ``` + fix: address PR review feedback + fix: resolve CI lint failures + fix: address review feedback and fix CI failures + ``` + +3. Push: + ```bash + git push + ``` ### 8. Summary diff --git a/.agents/skills/simplify/SKILL.md b/.agents/skills/simplify/SKILL.md index 43dc6130fb..eaf80877f9 100644 --- a/.agents/skills/simplify/SKILL.md +++ b/.agents/skills/simplify/SKILL.md @@ -48,7 +48,7 @@ Work through each changed file. For each simplification, verify tests still pass ### 3. Verify -Run `/verify` to ensure all tests, lints, and typechecks still pass. If anything breaks, the simplification changed behavior — revert it. +Delegate to the **`verify` sub-agent** to ensure all tests, lints, and typechecks still pass. If anything breaks, the simplification changed behavior — revert it. ### 4. Summary diff --git a/.agents/skills/verify/SKILL.md b/.agents/skills/verify/SKILL.md index 005af6dc41..b14182d7a8 100644 --- a/.agents/skills/verify/SKILL.md +++ b/.agents/skills/verify/SKILL.md @@ -5,7 +5,7 @@ description: Run format, typecheck, test, and lint across the monorepo. Use afte # Verify -Run the full verification pipeline for the Kandev monorepo, then fix any issues found. +Run the full verification pipeline for the monorepo, then fix any issues found. ## Steps @@ -15,8 +15,7 @@ Run the full verification pipeline for the Kandev monorepo, then fix any issues ``` - If the current branch is `main`, skip this step. - If the branch is stacked on another feature branch (not main), skip this step. - Detect: `git log --oneline --first-parent origin/main..HEAD | tail -1` — if the first commit's parent is not on `origin/main`, it's stacked. - Simpler heuristic: check `git merge-base --is-ancestor origin/main HEAD` — if false, the branch diverged from a non-main base; skip rebase. + Detect: `git rev-parse --abbrev-ref --symbolic-full-name @{upstream} 2>/dev/null` — if the upstream is NOT `origin/main` (e.g., another feature branch), skip rebase. - Otherwise, rebase: ```bash git rebase origin/main diff --git a/.claude/agents b/.claude/agents new file mode 120000 index 0000000000..4c8a5fc93d --- /dev/null +++ b/.claude/agents @@ -0,0 +1 @@ +../.agents/agents \ No newline at end of file diff --git a/apps/backend/cmd/mock-agent/main.go b/apps/backend/cmd/mock-agent/main.go index f4312f95a4..a1a780aae2 100644 --- a/apps/backend/cmd/mock-agent/main.go +++ b/apps/backend/cmd/mock-agent/main.go @@ -30,11 +30,11 @@ var mcpServers map[string]mcpServerDef // mockAgent implements the acp.Agent interface for the mock agent. type mockAgent struct { - conn *acp.AgentSideConnection - model string - sessions map[acp.SessionId]bool - commandsEmitted map[acp.SessionId]bool - mu sync.Mutex + conn *acp.AgentSideConnection + model string + sessions map[acp.SessionId]bool + commandsEmitted map[acp.SessionId]bool + mu sync.Mutex } func main() {