create-agent-room 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +229 -0
  2. package/bin/cli.js +186 -0
  3. package/examples/python-project/.agent-room.json +14 -0
  4. package/examples/python-project/AGENTS.md +32 -0
  5. package/examples/rust-project/.agent-room.json +12 -0
  6. package/examples/rust-project/AGENTS.md +32 -0
  7. package/lib/color.js +31 -0
  8. package/lib/fsutil.js +218 -0
  9. package/lib/init.js +660 -0
  10. package/lib/lint-sessions.js +278 -0
  11. package/lib/metrics.js +190 -0
  12. package/lib/pr.js +176 -0
  13. package/lib/prompt.js +20 -0
  14. package/lib/session-utils.js +213 -0
  15. package/lib/sync.js +138 -0
  16. package/lib/validate.js +179 -0
  17. package/package.json +48 -0
  18. package/templates/.agent-room/anti-patterns.md +22 -0
  19. package/templates/.agent-room/coordination/handoff-protocol.md +60 -0
  20. package/templates/.agent-room/coordination/scope-boundaries.md +57 -0
  21. package/templates/.agent-room/coordination/session-log-format.md +62 -0
  22. package/templates/.agent-room/decisions.md +17 -0
  23. package/templates/.agent-room/guardrails.json +23 -0
  24. package/templates/.agent-room/guardrails.md +56 -0
  25. package/templates/.agent-room/principles.md +306 -0
  26. package/templates/.agent-room/sessions/.gitkeep +4 -0
  27. package/templates/.agent-room/skills/brainstorming.md +64 -0
  28. package/templates/.agent-room/skills/closing-the-loop.md +67 -0
  29. package/templates/.agent-room/skills/systematic-debugging.md +85 -0
  30. package/templates/.agent-room/skills/test-driven-development.md +100 -0
  31. package/templates/.agent-room/skills/verification-before-completion.md +56 -0
  32. package/templates/.agent-room/skills/writing-plans.md +87 -0
  33. package/templates/.agent-room/workflow-classifier.md +127 -0
  34. package/templates/AGENTS.md.tmpl +85 -0
  35. package/templates/adapters/CLAUDE.md.tmpl +38 -0
  36. package/templates/adapters/claude-hooks/close-the-loop-check.js +96 -0
  37. package/templates/adapters/clinerules.tmpl +14 -0
  38. package/templates/adapters/codexrules.tmpl +45 -0
  39. package/templates/adapters/cursorrules.tmpl +14 -0
  40. package/templates/adapters/git-hooks/guardrails-check.js +140 -0
  41. package/templates/adapters/git-hooks/pre-commit.tmpl +43 -0
  42. package/templates/adapters/windsurfrules.tmpl +14 -0
  43. package/templates/docs/plans/.gitkeep +0 -0
  44. package/templates/skill-packs/api-design/api-design.md +152 -0
  45. package/templates/skill-packs/code-review/code-review.md +113 -0
  46. package/templates/skill-packs/database/database-migrations.md +123 -0
  47. package/templates/skill-packs/documentation/documentation.md +155 -0
  48. package/templates/skill-packs/observability/observability.md +128 -0
  49. package/templates/skill-packs/performance/performance-optimization.md +150 -0
  50. package/templates/skill-packs/release/release-management.md +145 -0
  51. package/templates/skill-packs/security/security-principles.md +127 -0
  52. package/templates/skill-packs/testing/integration-testing.md +127 -0
  53. package/templates/stacks/python/.agent-room/skills/python-testing.md +59 -0
  54. package/templates/stacks/python/AGENTS.md.tmpl +35 -0
  55. package/templates/stacks/react/.agent-room/skills/react-component-testing.md +76 -0
  56. package/templates/stacks/react/AGENTS.md.tmpl +37 -0
  57. package/templates/stacks/typescript/.agent-room/skills/typescript-testing.md +63 -0
  58. package/templates/stacks/typescript/AGENTS.md.tmpl +36 -0
@@ -0,0 +1,14 @@
1
+ # Cline rules — {{PROJECT_NAME}}
2
+
3
+ Read [`AGENTS.md`](AGENTS.md) and everything under
4
+ [`.agent-room/`](.agent-room/) before making non-trivial changes:
5
+
6
+ - `.agent-room/principles.md` — how to get reliable output from the model.
7
+ - `.agent-room/workflow-classifier.md` — size the process to the work
8
+ (Bug / Enhancement / Feature / Product).
9
+ - `.agent-room/skills/` — brainstorming, writing-plans, TDD, systematic
10
+ debugging, verification-before-completion. Follow these as procedures,
11
+ not suggestions.
12
+ - `.agent-room/anti-patterns.md` and `.agent-room/decisions.md` — check
13
+ before repeating a past mistake; append after a new one or a notable
14
+ decision.
@@ -0,0 +1,45 @@
1
+ # Codex rules — {{PROJECT_NAME}}
2
+
3
+ Read [`AGENTS.md`](AGENTS.md) and everything under
4
+ [`.agent-room/`](.agent-room/) before making non-trivial changes:
5
+
6
+ - `.agent-room/principles.md` — how to get reliable output from the model.
7
+ - `.agent-room/workflow-classifier.md` — size the process to the work
8
+ (Bug / Enhancement / Feature / Product).
9
+ - `.agent-room/skills/` — brainstorming, writing-plans, TDD, systematic
10
+ debugging, verification-before-completion. Follow these as procedures,
11
+ not suggestions.
12
+ - `.agent-room/anti-patterns.md` and `.agent-room/decisions.md` — check
13
+ before repeating a past mistake; append after a new one or a notable
14
+ decision.
15
+
16
+ ## Core rules
17
+
18
+ 1. **Always read AGENTS.md first.** It's the entry point for any coder.
19
+
20
+ 2. **Classify the work:** Use `.agent-room/workflow-classifier.md` to size
21
+ the process (bug fix ≠ feature ≠ enhancement). Don't over-engineer.
22
+
23
+ 3. **Brainstorm before coding:** For any non-trivial change, brainstorm
24
+ 2-3 approaches with tradeoffs before writing code.
25
+
26
+ 4. **Write tests first (TDD):** Failing test → implementation → passing test.
27
+ Then refactor. This catches bugs early.
28
+
29
+ 5. **Verify before handing off:** Run the full test suite and checks before
30
+ marking work complete. Leave the codebase in a shippable state.
31
+
32
+ 6. **Close the loop:** Before ending a session, append decisions and
33
+ anti-patterns to `.agent-room/decisions.md` and `.agent-room/anti-patterns.md`.
34
+ Document what you learned.
35
+
36
+ ## Guardrails
37
+
38
+ Review `.agent-room/guardrails.md` for protected paths, approval requirements,
39
+ and forbidden actions. Some changes require human review.
40
+
41
+ ## Session logs
42
+
43
+ Save a session log to `.agent-room/sessions/` following the format in
44
+ `.agent-room/coordination/session-log-format.md`. Include goal, actions,
45
+ decisions, and outcome.
@@ -0,0 +1,14 @@
1
+ # Cursor rules — {{PROJECT_NAME}}
2
+
3
+ Read [`AGENTS.md`](../AGENTS.md) and everything under
4
+ [`.agent-room/`](../.agent-room/) before making non-trivial changes:
5
+
6
+ - `.agent-room/principles.md` — how to get reliable output from the model.
7
+ - `.agent-room/workflow-classifier.md` — size the process to the work
8
+ (Bug / Enhancement / Feature / Product).
9
+ - `.agent-room/skills/` — brainstorming, writing-plans, TDD, systematic
10
+ debugging, verification-before-completion. Follow these as procedures,
11
+ not suggestions.
12
+ - `.agent-room/anti-patterns.md` and `.agent-room/decisions.md` — check
13
+ before repeating a past mistake; append after a new one or a notable
14
+ decision.
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Pre-commit hook for guardrails enforcement
6
+ * Prevents commits that violate project guardrails
7
+ *
8
+ * Checks:
9
+ * - Protected paths: blocks commits to paths requiring approval
10
+ * - Forbidden actions: blocks commits containing dangerous patterns (e.g., hard-coded credentials)
11
+ * - Minimum checks before merge
12
+ */
13
+
14
+ const fs = require('fs');
15
+ const path = require('path');
16
+ const { execSync } = require('child_process');
17
+
18
+ const projectRoot = process.cwd();
19
+ const guardrailsPath = path.join(projectRoot, '.agent-room', 'guardrails.json');
20
+
21
+ // Allow override via env variable
22
+ const ALLOW_GUARDRAILS_BYPASS = process.env.GUARDRAILS_BYPASS || process.env.SKIP_GUARDRAILS_CHECK;
23
+
24
+ if (!fs.existsSync(guardrailsPath)) {
25
+ // No guardrails file, allow commit
26
+ process.exit(0);
27
+ }
28
+
29
+ let guardrails = {};
30
+ try {
31
+ guardrails = JSON.parse(fs.readFileSync(guardrailsPath, 'utf8'));
32
+ } catch (err) {
33
+ console.error(`⚠️ Failed to parse guardrails.json: ${err.message}`);
34
+ process.exit(0);
35
+ }
36
+
37
+ // Get staged files
38
+ let stagedFiles = [];
39
+ try {
40
+ const output = execSync('git diff --cached --name-only', { encoding: 'utf8' });
41
+ stagedFiles = output.trim().split('\n').filter(Boolean);
42
+ } catch (err) {
43
+ // Not a git repo or no staged files
44
+ process.exit(0);
45
+ }
46
+
47
+ const protectedPaths = guardrails.protectedPaths || [];
48
+ const forbiddenPatterns = guardrails.forbiddenActions || [];
49
+
50
+ let violations = [];
51
+
52
+ // Check protected paths
53
+ for (const file of stagedFiles) {
54
+ for (const protectedPath of protectedPaths) {
55
+ if (isPathProtected(file, protectedPath)) {
56
+ violations.push(`Protected path violation: ${file}`);
57
+ }
58
+ }
59
+ }
60
+
61
+ // Check for forbidden patterns in staged content
62
+ for (const file of stagedFiles) {
63
+ if (!fs.existsSync(file)) continue;
64
+
65
+ // Skip binary files and very large files
66
+ if (isBinaryFile(file) || fs.statSync(file).size > 1_000_000) {
67
+ continue;
68
+ }
69
+
70
+ try {
71
+ // Get staged content (not working tree)
72
+ const stagedContent = execSync(`git show :${file}`, { encoding: 'utf8' });
73
+
74
+ for (const pattern of forbiddenPatterns) {
75
+ if (pattern.match(/^\/.*\/[gimuy]*$/) || pattern.startsWith('(?:') || pattern.includes('(?:')) {
76
+ // It's a regex
77
+ try {
78
+ const regex = new RegExp(pattern);
79
+ if (regex.test(stagedContent)) {
80
+ violations.push(`Forbidden pattern found in ${file}: ${pattern}`);
81
+ }
82
+ } catch (regexErr) {
83
+ // Invalid regex, skip
84
+ }
85
+ } else {
86
+ // Literal string
87
+ if (stagedContent.includes(pattern)) {
88
+ violations.push(`Forbidden pattern found in ${file}: ${pattern}`);
89
+ }
90
+ }
91
+ }
92
+ } catch (err) {
93
+ // File might not exist in index yet
94
+ }
95
+ }
96
+
97
+ if (violations.length > 0) {
98
+ console.error('');
99
+ console.error('❌ Guardrails Check Failed: Commit violates project guardrails');
100
+ console.error('');
101
+ for (const violation of violations) {
102
+ console.error(` - ${violation}`);
103
+ }
104
+ console.error('');
105
+ console.error('To bypass guardrails (requires approval), use:');
106
+ console.error(' GUARDRAILS_BYPASS=1 git commit');
107
+ console.error('');
108
+
109
+ if (!ALLOW_GUARDRAILS_BYPASS) {
110
+ process.exit(1);
111
+ }
112
+
113
+ console.warn('⚠️ Guardrails bypass enabled - proceeding with commit');
114
+ }
115
+
116
+ process.exit(0);
117
+
118
+ function isPathProtected(filePath, protectedPattern) {
119
+ // Normalize paths for comparison
120
+ const normalized = filePath.replace(/\\/g, '/');
121
+ const pattern = protectedPattern.replace(/\\/g, '/');
122
+
123
+ // Handle glob patterns
124
+ if (pattern.includes('*')) {
125
+ const regexPattern = pattern
126
+ .split('*')
127
+ .map((part) => part.replace(/[.+?^${}()|[\]\\]/g, '\\$&'))
128
+ .join('.*');
129
+ return new RegExp(`^${regexPattern}$`).test(normalized);
130
+ }
131
+
132
+ // Direct match or prefix match
133
+ return normalized === pattern || normalized.startsWith(pattern + '/');
134
+ }
135
+
136
+ function isBinaryFile(filePath) {
137
+ const ext = path.extname(filePath).toLowerCase();
138
+ const binaryExts = ['.png', '.jpg', '.jpeg', '.gif', '.pdf', '.zip', '.tar', '.exe', '.dll', '.so', '.bin'];
139
+ return binaryExts.includes(ext);
140
+ }
@@ -0,0 +1,43 @@
1
+ #!/bin/sh
2
+ # Git pre-commit hook generated by create-agent-room
3
+ # Enforces the closing-the-loop discipline and guardrails checks for all commits.
4
+
5
+ if ! [ -d ".agent-room" ]; then
6
+ exit 0
7
+ fi
8
+
9
+ # First, run guardrails check
10
+ if [ -f ".agent-room/hooks/guardrails-check.js" ]; then
11
+ node ".agent-room/hooks/guardrails-check.js"
12
+ if [ $? -ne 0 ]; then
13
+ exit 1
14
+ fi
15
+ fi
16
+
17
+ # List of changed files staged for commit
18
+ STAGED_FILES=$(git diff --cached --name-only)
19
+
20
+ # Check if there are non-scaffold files changed
21
+ HAS_SOURCE_CHANGES=false
22
+ HAS_LOG_TOUCHED=false
23
+
24
+ for file in $STAGED_FILES; do
25
+ case "$file" in
26
+ .agent-room/anti-patterns.md|.agent-room/decisions.md)
27
+ HAS_LOG_TOUCHED=true
28
+ ;;
29
+ AGENTS.md|CLAUDE.md|.claude/*|.cursor/*|.windsurfrules|.clinerules|docs/plans/*)
30
+ # Skip scaffold/plan updates
31
+ ;;
32
+ *)
33
+ HAS_SOURCE_CHANGES=true
34
+ ;;
35
+ esac
36
+ done
37
+
38
+ if [ "$HAS_SOURCE_CHANGES" = true ] && [ "$HAS_LOG_TOUCHED" = false ]; then
39
+ echo "ERROR: Close-the-loop check failed." >&2
40
+ echo "You changed source files but did not update .agent-room/anti-patterns.md or .agent-room/decisions.md." >&2
41
+ echo "To bypass, append a waiver to decisions.md, or commit with 'git commit --no-verify' (use with caution)." >&2
42
+ exit 1
43
+ fi
@@ -0,0 +1,14 @@
1
+ # Windsurf rules — {{PROJECT_NAME}}
2
+
3
+ Read [`AGENTS.md`](AGENTS.md) and everything under
4
+ [`.agent-room/`](.agent-room/) before making non-trivial changes:
5
+
6
+ - `.agent-room/principles.md` — how to get reliable output from the model.
7
+ - `.agent-room/workflow-classifier.md` — size the process to the work
8
+ (Bug / Enhancement / Feature / Product).
9
+ - `.agent-room/skills/` — brainstorming, writing-plans, TDD, systematic
10
+ debugging, verification-before-completion. Follow these as procedures,
11
+ not suggestions.
12
+ - `.agent-room/anti-patterns.md` and `.agent-room/decisions.md` — check
13
+ before repeating a past mistake; append after a new one or a notable
14
+ decision.
File without changes
@@ -0,0 +1,152 @@
1
+ ---
2
+ name: api-design
3
+ description: "Use when designing, implementing, or modifying REST APIs, GraphQL schemas, or any service interface that other systems or clients consume."
4
+ ---
5
+
6
+ # API Design
7
+
8
+ ## Overview
9
+
10
+ An API is a contract. Unlike internal code, changing an API breaks other
11
+ people's code. Design for clarity, consistency, and evolution from the
12
+ start — retrofitting these qualities is expensive and disruptive.
13
+
14
+ ## The iron law
15
+
16
+ ```
17
+ BREAKING CHANGES REQUIRE A VERSIONED MIGRATION PATH
18
+ ```
19
+
20
+ Never remove, rename, or change the type of an existing field, endpoint,
21
+ or response shape without a deprecation period and a documented migration
22
+ path. "Nobody uses this endpoint" is not evidence — check access logs.
23
+
24
+ ## Resource naming
25
+
26
+ - Use nouns, not verbs: `/users`, not `/getUsers`.
27
+ - Use plural nouns: `/orders`, not `/order`.
28
+ - Use kebab-case for multi-word resources: `/order-items`, not
29
+ `/orderItems` or `/order_items`.
30
+ - Nest for relationships: `/users/{id}/orders`, not `/getUserOrders`.
31
+ - Keep nesting shallow (max 2 levels). Deep nesting creates rigid
32
+ coupling: `/users/{id}/orders/{oid}/items/{iid}/comments` is a sign
33
+ the resource model needs rethinking.
34
+
35
+ ## HTTP verb semantics
36
+
37
+ | Verb | Meaning | Idempotent | Safe |
38
+ | --- | --- | --- | --- |
39
+ | GET | Retrieve a resource | Yes | Yes |
40
+ | POST | Create a new resource | No | No |
41
+ | PUT | Replace a resource entirely | Yes | No |
42
+ | PATCH | Partially update a resource | No* | No |
43
+ | DELETE | Remove a resource | Yes | No |
44
+
45
+ *PATCH is not inherently idempotent but can be designed to be.
46
+
47
+ **Common agent mistakes:**
48
+ - Using POST for everything (including fetches and updates).
49
+ - Using GET with a request body (not universally supported).
50
+ - Using DELETE to "soft delete" without documenting the behavior.
51
+
52
+ ## Error response contract
53
+
54
+ Every API should return errors in a **consistent shape**. Don't invent a
55
+ new error format per endpoint.
56
+
57
+ ```json
58
+ {
59
+ "error": {
60
+ "code": "VALIDATION_FAILED",
61
+ "message": "Email address is not valid.",
62
+ "details": [
63
+ {
64
+ "field": "email",
65
+ "reason": "Must be a valid email address.",
66
+ "value": "not-an-email"
67
+ }
68
+ ]
69
+ }
70
+ }
71
+ ```
72
+
73
+ Rules:
74
+ - `code` is machine-readable (constant string, not a sentence).
75
+ - `message` is human-readable (for debugging, not for end users).
76
+ - `details` is optional, for validation errors with multiple fields.
77
+ - HTTP status code matches the error type (see table below).
78
+
79
+ | Status | When to use |
80
+ | --- | --- |
81
+ | 400 | Client sent invalid data (validation, malformed JSON) |
82
+ | 401 | No valid authentication credentials |
83
+ | 403 | Authenticated but not authorized for this resource |
84
+ | 404 | Resource does not exist |
85
+ | 409 | Conflict (duplicate email, version mismatch) |
86
+ | 422 | Request is syntactically valid but semantically wrong |
87
+ | 429 | Rate limit exceeded |
88
+ | 500 | Server error (never expose internal details to the client) |
89
+
90
+ ## Pagination
91
+
92
+ Never return unbounded lists. Every list endpoint must support pagination.
93
+
94
+ **Cursor-based (recommended for large datasets):**
95
+ ```
96
+ GET /orders?cursor=eyJpZCI6MTIzfQ&limit=20
97
+ ```
98
+ Returns a `nextCursor` in the response. Stable under insertions/deletions.
99
+
100
+ **Offset-based (simpler, less stable):**
101
+ ```
102
+ GET /orders?offset=40&limit=20
103
+ ```
104
+ Breaks when items are inserted or deleted during pagination. Acceptable
105
+ for small, slowly-changing datasets.
106
+
107
+ **Always include pagination metadata in the response:**
108
+ ```json
109
+ {
110
+ "data": [...],
111
+ "pagination": {
112
+ "nextCursor": "eyJpZCI6MTQzfQ",
113
+ "hasMore": true
114
+ }
115
+ }
116
+ ```
117
+
118
+ ## Versioning
119
+
120
+ When a breaking change is unavoidable:
121
+
122
+ 1. **URL versioning** (`/api/v2/users`) — simple, explicit, easy to route.
123
+ 2. **Header versioning** (`Accept: application/vnd.api.v2+json`) — cleaner
124
+ URLs but harder to test in a browser.
125
+
126
+ **Deprecation protocol:**
127
+ 1. Add a `Sunset` header to the old endpoint with the removal date.
128
+ 2. Log usage of deprecated endpoints (so you can notify consumers).
129
+ 3. Maintain the old version for at least one release cycle (minimum 30
130
+ days for internal APIs, 90 days for public APIs).
131
+ 4. Document migration steps in the changelog.
132
+
133
+ ## Breaking change detection
134
+
135
+ Before modifying an existing endpoint, check:
136
+
137
+ - [ ] Am I removing or renaming a field in the response? → Breaking.
138
+ - [ ] Am I changing a field's type (string → number)? → Breaking.
139
+ - [ ] Am I adding a new required field to the request? → Breaking.
140
+ - [ ] Am I changing the HTTP status code for an existing error? → Breaking.
141
+ - [ ] Am I changing the URL path or query parameter names? → Breaking.
142
+
143
+ If any answer is "yes," use the versioning and deprecation protocol above.
144
+ Adding new optional fields to responses or requests is generally safe.
145
+
146
+ ## Red flags — stop and redesign
147
+
148
+ Endpoints that accept 20+ query parameters · response shapes that change
149
+ based on the caller's role (use separate endpoints instead) · error
150
+ responses that return HTML instead of JSON · list endpoints without
151
+ pagination · APIs that expose internal database IDs without obfuscation ·
152
+ PUT endpoints that silently ignore unknown fields.
@@ -0,0 +1,113 @@
1
+ ---
2
+ name: code-review
3
+ description: "Use when reviewing pull requests, diffs, or code changes — whether as the reviewer or when preparing code for review."
4
+ ---
5
+
6
+ # Code Review
7
+
8
+ ## Overview
9
+
10
+ Code review is not proofreading — it's a systematic evaluation of whether
11
+ a change is correct, safe, maintainable, and appropriately scoped. An
12
+ agent reviewing code must follow a consistent priority order, not scan
13
+ for whatever catches its eye first.
14
+
15
+ ## The iron law
16
+
17
+ ```
18
+ REVIEW IN PRIORITY ORDER: SECURITY → CORRECTNESS → PERFORMANCE → STYLE
19
+ ```
20
+
21
+ Security bugs that slip through review cause incidents. Correctness bugs
22
+ cause regressions. Performance issues cause gradual degradation. Style
23
+ issues cause friction. Review in order of impact.
24
+
25
+ ## The review process
26
+
27
+ ### 1. Understand the intent first
28
+
29
+ Before reading a single line of code:
30
+ - Read the PR description, linked issue, or design doc.
31
+ - Understand what the change is *supposed* to do.
32
+ - If the intent is unclear, ask before reviewing the implementation.
33
+
34
+ ### 2. Review in priority order
35
+
36
+ **Security (blocking):**
37
+ - Does user input flow into queries, commands, or markup unsanitized?
38
+ - Are secrets hardcoded or logged?
39
+ - Are authorization checks present at the data layer, not just the route?
40
+ - Does the change introduce new attack surface (new endpoints, new file
41
+ uploads, new auth flows)?
42
+
43
+ **Correctness (blocking):**
44
+ - Does the code actually implement the stated intent?
45
+ - Are edge cases handled (empty input, null, boundary values, concurrency)?
46
+ - Are error paths handled (what happens when the network call fails, the
47
+ file doesn't exist, the database is down)?
48
+ - Does it have tests? Do the tests cover the meaningful behaviors?
49
+
50
+ **Performance (blocking if severe, otherwise non-blocking):**
51
+ - N+1 queries in loops?
52
+ - Unbounded data fetches (no pagination, no LIMIT)?
53
+ - Large allocations in hot paths?
54
+ - Missing indexes for new query patterns?
55
+
56
+ **Style and maintainability (non-blocking):**
57
+ - Naming clarity (would a new team member understand the intent?).
58
+ - Duplication that could be extracted.
59
+ - Comments that explain "why" not "what."
60
+
61
+ ### 3. Check scope
62
+
63
+ A PR should do one thing. Red flags for scope creep:
64
+ - The PR title says "fix login bug" but also refactors the auth module.
65
+ - More than 500 lines changed for what should be a small fix.
66
+ - Unrelated formatting changes mixed with functional changes.
67
+
68
+ If scope is too broad, ask the author to split the PR. Don't review a
69
+ kitchen-sink PR — it's impossible to verify correctness when 5 concerns
70
+ are interleaved.
71
+
72
+ ## Writing review comments
73
+
74
+ ### Good comments are actionable
75
+
76
+ ```
77
+ BAD: "This could be better."
78
+ GOOD: "This query fetches all users without pagination. With 100K users
79
+ this will OOM the server. Add LIMIT/OFFSET or cursor pagination."
80
+ ```
81
+
82
+ ### Distinguish blocking from non-blocking
83
+
84
+ - **Blocking:** Must be fixed before merge. Security issues, correctness
85
+ bugs, missing tests for new behavior.
86
+ - **Non-blocking (nit):** Prefix with "nit:" — style suggestions, minor
87
+ naming improvements, optional refactors. These should not block merge.
88
+
89
+ ### Explain the "why," not just the "what"
90
+
91
+ ```
92
+ BAD: "Use a Map instead of an Object."
93
+ GOOD: "nit: Consider a Map here — the keys are user-provided strings,
94
+ and Object prototype pollution is a risk if keys like '__proto__'
95
+ are possible. Not blocking if input is validated upstream."
96
+ ```
97
+
98
+ ## Self-review before requesting review
99
+
100
+ Before submitting code for review, run your own checklist:
101
+
102
+ - [ ] Does every new function/endpoint have tests?
103
+ - [ ] Did I remove all debugging artifacts (`console.log`, `debugger`)?
104
+ - [ ] Are there any TODOs that should be resolved before merge?
105
+ - [ ] Is the diff minimal? (No unrelated formatting, no leftover experiments.)
106
+ - [ ] Does the PR description explain what changed and why?
107
+
108
+ ## Red flags — request changes immediately
109
+
110
+ Hardcoded credentials · missing auth checks on new endpoints · raw SQL
111
+ with string interpolation · `eval()` or `Function()` with external input ·
112
+ tests that assert the implementation rather than the behavior ·
113
+ catch-and-swallow error handling · PRs with no tests for new behavior.
@@ -0,0 +1,123 @@
1
+ ---
2
+ name: database-migrations
3
+ description: "Use when writing database schema changes, data migrations, creating indexes, or modifying existing tables in production-facing systems."
4
+ ---
5
+
6
+ # Database Migrations
7
+
8
+ ## Overview
9
+
10
+ Database migrations are the riskiest part of most releases. Unlike code,
11
+ a bad migration can't be reverted by redeploying the previous version —
12
+ the data has already changed. Every migration must be backward-compatible,
13
+ tested, and paired with a rollback plan.
14
+
15
+ ## The iron law
16
+
17
+ ```
18
+ EVERY MIGRATION MUST BE BACKWARD-COMPATIBLE WITH THE CURRENTLY DEPLOYED CODE
19
+ ```
20
+
21
+ Deploy the migration first, then deploy the new code. If the migration
22
+ breaks the old code, you can't roll back the code deployment without also
23
+ rolling back the migration — and data migrations often can't be rolled back.
24
+
25
+ ## Safe vs. unsafe operations
26
+
27
+ | Operation | Safe? | Notes |
28
+ | --- | --- | --- |
29
+ | Add a new table | ✅ Yes | No existing code references it |
30
+ | Add a nullable column | ✅ Yes | Old code ignores it |
31
+ | Add a column with a default | ✅ Yes* | *Check if your DB locks the table during ALTER |
32
+ | Add an index | ⚠️ Careful | Use CONCURRENTLY (Postgres) or equivalent |
33
+ | Rename a column | ❌ No | Old code uses the old name |
34
+ | Remove a column | ❌ No | Old code reads the old column |
35
+ | Change a column type | ❌ No | Old code expects the old type |
36
+ | Add a NOT NULL constraint | ❌ No | Existing rows may violate it |
37
+
38
+ ## The multi-step pattern for unsafe changes
39
+
40
+ Unsafe operations must be split across multiple releases:
41
+
42
+ ### Renaming a column (3 releases)
43
+
44
+ 1. **Release 1:** Add the new column. Write to both old and new. Read
45
+ from old.
46
+ 2. **Release 2:** Backfill the new column from the old. Switch reads to
47
+ the new column. Stop writing to old.
48
+ 3. **Release 3:** Drop the old column.
49
+
50
+ ### Removing a column (2 releases)
51
+
52
+ 1. **Release 1:** Stop reading from the column in code. Stop writing to
53
+ it. (The column still exists in the database.)
54
+ 2. **Release 2:** Drop the column via migration.
55
+
56
+ ### Adding a NOT NULL constraint (2 releases)
57
+
58
+ 1. **Release 1:** Backfill all NULL values. Add application-level
59
+ validation to prevent new NULLs.
60
+ 2. **Release 2:** Add the database-level NOT NULL constraint.
61
+
62
+ ## Index creation
63
+
64
+ Large indexes on production tables can lock writes for minutes or hours.
65
+
66
+ - **PostgreSQL:** Always use `CREATE INDEX CONCURRENTLY`. It takes longer
67
+ but doesn't lock the table.
68
+ - **MySQL:** Use `ALTER TABLE ... ADD INDEX` with `ALGORITHM=INPLACE,
69
+ LOCK=NONE` where supported.
70
+ - **Measure impact:** On large tables (>1M rows), test the index creation
71
+ on a staging copy first. Note the time and lock behavior.
72
+ - **Don't create indexes speculatively.** Add an index when you have a
73
+ slow query that needs it, not "in case someone queries this column
74
+ later."
75
+
76
+ ## Data backfill strategies
77
+
78
+ When migrating data between columns or formats:
79
+
80
+ 1. **Batch, don't bulk.** Process 1,000-10,000 rows at a time, not the
81
+ entire table in one statement. Bulk updates lock rows and can cause
82
+ replication lag.
83
+ 2. **Idempotent backfills.** The backfill script should be safe to run
84
+ multiple times. Use `WHERE new_column IS NULL` to skip already-migrated
85
+ rows.
86
+ 3. **Monitor progress.** Log how many rows are processed, how many remain,
87
+ and the estimated time to completion.
88
+ 4. **Run during low-traffic windows** if the table is large and heavily
89
+ written to.
90
+
91
+ ## Migration testing
92
+
93
+ Before deploying a migration to production:
94
+
95
+ - [ ] Run the migration against a copy of production data (or a
96
+ representative staging dataset).
97
+ - [ ] Verify the old code still works after the migration runs.
98
+ - [ ] Verify the new code works after the migration runs.
99
+ - [ ] Measure execution time. If it takes more than 30 seconds, consider
100
+ breaking it into smaller steps.
101
+ - [ ] Write and test the reverse migration. If the migration is
102
+ irreversible, document the manual recovery procedure.
103
+
104
+ ## Rollback plan
105
+
106
+ Every migration must document its rollback before deployment:
107
+
108
+ - **Reversible migrations:** Include a `down` migration that undoes the
109
+ change. Test it.
110
+ - **Irreversible migrations** (dropped columns, data transformations):
111
+ Document what data is lost and the manual recovery procedure. Consider
112
+ whether a backup should be taken before running.
113
+ - **If in doubt, take a table snapshot** before running destructive
114
+ migrations. Storage is cheap; data loss is not.
115
+
116
+ ## Red flags — stop and reassess
117
+
118
+ Migrations that take more than 5 minutes on staging · ALTER TABLE on a
119
+ table with active write traffic without testing lock behavior · backfills
120
+ that process the entire table in one transaction · migrations without a
121
+ tested reverse migration · dropping a column that's still referenced in
122
+ deployed code · adding a foreign key constraint to a large table without
123
+ validating existing data first.