forgedev 1.0.2 → 1.1.3
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.
- package/README.md +122 -26
- package/bin/devforge.js +10 -1
- package/package.json +1 -1
- package/src/claude-configurator.js +29 -6
- package/src/cli.js +11 -0
- package/src/doctor-prompts.js +9 -2
- package/src/doctor.js +19 -0
- package/src/index.js +7 -0
- package/src/update-check.js +49 -0
- package/src/update.js +33 -0
- package/templates/auth/jwt-custom/backend/app/core/security.py.template +4 -1
- package/templates/backend/fastapi/backend/app/core/config.py.template +2 -2
- package/templates/claude-code/agents/architect.md +70 -0
- package/templates/claude-code/agents/build-error-resolver.md +30 -0
- package/templates/claude-code/agents/chief-of-staff.md +52 -0
- package/templates/claude-code/agents/database-reviewer.md +58 -0
- package/templates/claude-code/agents/doc-updater.md +39 -0
- package/templates/claude-code/agents/docs-lookup.md +51 -0
- package/templates/claude-code/agents/e2e-runner.md +57 -0
- package/templates/claude-code/agents/harness-optimizer.md +65 -0
- package/templates/claude-code/agents/loop-operator.md +52 -0
- package/templates/claude-code/agents/planner.md +60 -0
- package/templates/claude-code/agents/refactor-cleaner.md +42 -0
- package/templates/claude-code/agents/tdd-guide.md +47 -0
- package/templates/claude-code/agents/uat-validator.md +2 -1
- package/templates/claude-code/claude-md/base.md +29 -1
- package/templates/claude-code/claude-md/fastapi.md +8 -0
- package/templates/claude-code/claude-md/fullstack.md +8 -0
- package/templates/claude-code/claude-md/nextjs.md +8 -0
- package/templates/claude-code/commands/build-fix.md +43 -0
- package/templates/claude-code/commands/code-review.md +44 -0
- package/templates/claude-code/commands/full-audit.md +60 -0
- package/templates/claude-code/commands/plan.md +21 -0
- package/templates/claude-code/commands/resume-session.md +50 -0
- package/templates/claude-code/commands/save-session.md +69 -0
- package/templates/claude-code/commands/tdd.md +80 -0
- package/templates/claude-code/commands/workflows.md +12 -1
- package/templates/claude-code/hooks/polyglot.json +2 -2
- package/templates/claude-code/hooks/python.json +2 -2
- package/templates/claude-code/hooks/scripts/autofix-polyglot.mjs +44 -0
- package/templates/claude-code/hooks/scripts/autofix-python.mjs +38 -0
- package/templates/claude-code/hooks/scripts/autofix-typescript.mjs +38 -0
- package/templates/claude-code/hooks/scripts/guard-protected-files.mjs +34 -0
- package/templates/claude-code/hooks/typescript.json +2 -2
- package/templates/claude-code/skills/ai-prompts/SKILL.md +1 -0
- package/templates/claude-code/skills/fastapi/SKILL.md +1 -1
- package/templates/claude-code/skills/git-workflow/SKILL.md +64 -0
- package/templates/claude-code/skills/playwright/SKILL.md +2 -2
- package/templates/claude-code/skills/security-api/SKILL.md +2 -2
- package/templates/claude-code/skills/testing-patterns/SKILL.md +97 -0
- package/templates/database/sqlalchemy-postgres/.env.example +1 -0
- package/templates/claude-code/hooks/scripts/autofix-polyglot.sh +0 -16
- package/templates/claude-code/hooks/scripts/autofix-python.sh +0 -14
- package/templates/claude-code/hooks/scripts/autofix-typescript.sh +0 -14
- package/templates/claude-code/hooks/scripts/guard-protected-files.sh +0 -21
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Review uncommitted changes for security issues and code quality.
|
|
2
|
+
|
|
3
|
+
## Step 1: Get Changed Files
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
git diff --name-only HEAD
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Step 2: Review Each File
|
|
10
|
+
|
|
11
|
+
For each changed file, check:
|
|
12
|
+
|
|
13
|
+
**Security (CRITICAL):**
|
|
14
|
+
- Hardcoded credentials, API keys, tokens
|
|
15
|
+
- SQL injection vulnerabilities
|
|
16
|
+
- XSS vulnerabilities
|
|
17
|
+
- Missing input validation
|
|
18
|
+
- Path traversal risks
|
|
19
|
+
|
|
20
|
+
**Code Quality (HIGH):**
|
|
21
|
+
- Functions > 50 lines
|
|
22
|
+
- Files > 800 lines
|
|
23
|
+
- Nesting depth > 4 levels
|
|
24
|
+
- Missing error handling
|
|
25
|
+
- console.log / print statements left in
|
|
26
|
+
- TODO/FIXME comments without tracking
|
|
27
|
+
|
|
28
|
+
**Best Practices (MEDIUM):**
|
|
29
|
+
- Missing tests for new code
|
|
30
|
+
- Mutation of shared state (use immutable patterns)
|
|
31
|
+
- Missing accessibility attributes (a11y)
|
|
32
|
+
|
|
33
|
+
## Step 3: Generate Report
|
|
34
|
+
|
|
35
|
+
For each issue found:
|
|
36
|
+
- **Severity**: CRITICAL, HIGH, MEDIUM
|
|
37
|
+
- **File**: path and line number
|
|
38
|
+
- **Issue**: what's wrong
|
|
39
|
+
- **Fix**: how to fix it
|
|
40
|
+
## Step 4: Verdict
|
|
41
|
+
|
|
42
|
+
- If CRITICAL issues found → block commit, list required fixes
|
|
43
|
+
- If only MEDIUM/LOW → approve with suggestions
|
|
44
|
+
- Never approve code with security vulnerabilities
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
Run every audit and review agent in a single pass. Use this when you want a comprehensive project health check.
|
|
2
|
+
|
|
3
|
+
## Step 1: Build + Lint + Tests
|
|
4
|
+
|
|
5
|
+
1. Run lint: `{{LINT_COMMAND}}`
|
|
6
|
+
2. Run type check: `{{TYPE_CHECK_COMMAND}}`
|
|
7
|
+
3. Run tests: `{{TEST_COMMAND}}`
|
|
8
|
+
|
|
9
|
+
If any step fails, report the failures but continue with the remaining audits.
|
|
10
|
+
|
|
11
|
+
## Step 2: Code Review (changed files)
|
|
12
|
+
|
|
13
|
+
1. Get changed files: `git diff --name-only HEAD`
|
|
14
|
+
2. For each changed file, check for:
|
|
15
|
+
- Hardcoded credentials, API keys, tokens
|
|
16
|
+
- SQL injection, XSS, path traversal
|
|
17
|
+
- Functions > 50 lines, files > 800 lines
|
|
18
|
+
- Missing error handling, console.log left in
|
|
19
|
+
- Missing tests for new code
|
|
20
|
+
|
|
21
|
+
## Step 3: Launch Review Agents
|
|
22
|
+
|
|
23
|
+
Run these agents in sequence on the full codebase:
|
|
24
|
+
|
|
25
|
+
1. **code-quality-reviewer** — code patterns, duplication, naming
|
|
26
|
+
2. **security-reviewer** — vulnerabilities, secrets, unsafe operations
|
|
27
|
+
3. **production-readiness** — deployment readiness, error handling, health checks
|
|
28
|
+
4. **database-reviewer** — query performance, N+1, schema issues (skip if no database)
|
|
29
|
+
|
|
30
|
+
## Step 4: Structural Audits
|
|
31
|
+
|
|
32
|
+
1. **Wiring audit** — verify all API endpoints are connected between frontend and backend
|
|
33
|
+
2. **Spec audit** — if `docs/` contains a spec/PRD, validate implementation coverage
|
|
34
|
+
|
|
35
|
+
## Step 5: Claude Code Setup
|
|
36
|
+
|
|
37
|
+
1. **harness-optimizer** — check if .claude/ setup follows best practices
|
|
38
|
+
|
|
39
|
+
## Step 6: Summary Report
|
|
40
|
+
|
|
41
|
+
Compile all findings into a single report grouped by severity:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
CRITICAL (must fix before merge):
|
|
45
|
+
- [list]
|
|
46
|
+
|
|
47
|
+
HIGH (fix soon):
|
|
48
|
+
- [list]
|
|
49
|
+
|
|
50
|
+
MEDIUM (improve when possible):
|
|
51
|
+
- [list]
|
|
52
|
+
|
|
53
|
+
LOW (nice to have):
|
|
54
|
+
- [list]
|
|
55
|
+
|
|
56
|
+
PASSED:
|
|
57
|
+
- [list of checks that found no issues]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Include total counts: X critical, Y high, Z medium, W low.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Invoke the **planner** agent to create a comprehensive implementation plan before writing any code.
|
|
2
|
+
|
|
3
|
+
## Process
|
|
4
|
+
|
|
5
|
+
1. Ask the user what they want to build (or use the description they provided)
|
|
6
|
+
2. Launch the `planner` agent with the feature description
|
|
7
|
+
3. The planner will analyze the codebase, break down the work into phases, and identify risks
|
|
8
|
+
4. Present the plan and WAIT for user confirmation before proceeding
|
|
9
|
+
|
|
10
|
+
## Important
|
|
11
|
+
|
|
12
|
+
- NEVER write code until the user explicitly confirms the plan
|
|
13
|
+
- If the user wants modifications, update the plan and re-present
|
|
14
|
+
- After approval, suggest using `/tdd` to implement with test-driven development
|
|
15
|
+
|
|
16
|
+
## Integration
|
|
17
|
+
|
|
18
|
+
After planning, use these commands:
|
|
19
|
+
- `/tdd` — implement with test-driven development
|
|
20
|
+
- `/build-fix` — fix any build errors that come up
|
|
21
|
+
- `/code-review` — review the completed implementation
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
Load a saved session file and orient before doing any work.
|
|
2
|
+
|
|
3
|
+
## Process
|
|
4
|
+
|
|
5
|
+
1. **Find the session file** — Check `docs/sessions/` for the most recent `*-session.md` file
|
|
6
|
+
2. **Read the entire file** — Do not summarize yet
|
|
7
|
+
3. **Present a briefing** in this format:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
SESSION LOADED: [file path]
|
|
11
|
+
════════════════════════════════════════════════
|
|
12
|
+
|
|
13
|
+
PROJECT: [project name / topic]
|
|
14
|
+
|
|
15
|
+
WHAT WE'RE BUILDING:
|
|
16
|
+
[2-3 sentence summary in your own words]
|
|
17
|
+
|
|
18
|
+
CURRENT STATE:
|
|
19
|
+
✅ Working: [count] items confirmed
|
|
20
|
+
🔄 In Progress: [list files in progress]
|
|
21
|
+
🗒️ Not Started: [list planned but untouched]
|
|
22
|
+
|
|
23
|
+
WHAT NOT TO RETRY:
|
|
24
|
+
[list every failed approach with its reason]
|
|
25
|
+
|
|
26
|
+
OPEN QUESTIONS / BLOCKERS:
|
|
27
|
+
[list any blockers]
|
|
28
|
+
|
|
29
|
+
NEXT STEP:
|
|
30
|
+
[exact next step from the file]
|
|
31
|
+
|
|
32
|
+
════════════════════════════════════════════════
|
|
33
|
+
Ready to continue. What would you like to do?
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
4. **WAIT for the user** — Do NOT start working automatically
|
|
37
|
+
|
|
38
|
+
## Edge Cases
|
|
39
|
+
|
|
40
|
+
- **No session files found** — Tell the user to run `/save-session` first
|
|
41
|
+
- **Session references deleted files** — Note "⚠️ file.ts referenced but not found on disk"
|
|
42
|
+
- **Session is > 7 days old** — Note "⚠️ This session is N days old, things may have changed"
|
|
43
|
+
- **Empty or malformed file** — Report and suggest creating a new session
|
|
44
|
+
|
|
45
|
+
## Rules
|
|
46
|
+
|
|
47
|
+
- Never modify the session file — it's a read-only historical record
|
|
48
|
+
- Never skip the "What Not To Retry" section — it's the most important
|
|
49
|
+
- Always wait for the user before starting work
|
|
50
|
+
- If the next step is defined and the user says "continue" — proceed with that exact step
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
Save the current session state so work can be resumed in a future conversation.
|
|
2
|
+
|
|
3
|
+
## Process
|
|
4
|
+
|
|
5
|
+
1. **Gather context** — Review what was discussed, built, and decided this session
|
|
6
|
+
2. **Create folder** — `mkdir -p docs/sessions` (or `~/.claude/sessions/`)
|
|
7
|
+
3. **Write session file** — `docs/sessions/YYYY-MM-DD-session.md`
|
|
8
|
+
4. **Show to user** — Display contents and ask for corrections
|
|
9
|
+
|
|
10
|
+
## Session File Format
|
|
11
|
+
|
|
12
|
+
```markdown
|
|
13
|
+
# Session: YYYY-MM-DD
|
|
14
|
+
|
|
15
|
+
**Project:** [project name]
|
|
16
|
+
**Topic:** [one-line summary]
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## What We Are Building
|
|
21
|
+
[1-3 paragraphs with enough context for someone with zero memory of this session]
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## What WORKED (with evidence)
|
|
26
|
+
- **[thing]** — confirmed by: [specific evidence like "tests pass", "200 response"]
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## What Did NOT Work (and why)
|
|
31
|
+
- **[approach]** — failed because: [exact reason / error message]
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## What Has NOT Been Tried Yet
|
|
36
|
+
- [approach worth exploring]
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Current State of Files
|
|
41
|
+
|
|
42
|
+
| File | Status | Notes |
|
|
43
|
+
|------|--------|-------|
|
|
44
|
+
| `path/file.ts` | ✅ Complete | [what it does] |
|
|
45
|
+
| `path/file.ts` | 🔄 In Progress | [what's left] |
|
|
46
|
+
| `path/file.ts` | 🗒️ Not Started | [planned] |
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Decisions Made
|
|
51
|
+
- **[decision]** — reason: [why]
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Blockers & Open Questions
|
|
56
|
+
- [blocker or unanswered question]
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Exact Next Step
|
|
61
|
+
[The single most important thing to do when resuming]
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Rules
|
|
65
|
+
|
|
66
|
+
- Write every section honestly — "Nothing yet" is better than skipping a section
|
|
67
|
+
- The "What Did NOT Work" section is the most critical — prevents retrying failed approaches
|
|
68
|
+
- Each session gets its own file — never append to previous sessions
|
|
69
|
+
- Wait for user confirmation before closing
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
Enforce test-driven development: write failing tests FIRST, then implement.
|
|
2
|
+
|
|
3
|
+
## TDD Cycle
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
RED → GREEN → REFACTOR → REPEAT
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
1. **RED** — Write a failing test (because the code doesn't exist yet)
|
|
10
|
+
2. **GREEN** — Write the minimum code to make the test pass
|
|
11
|
+
3. **REFACTOR** — Improve the code while keeping tests green
|
|
12
|
+
4. **REPEAT** — Next scenario
|
|
13
|
+
|
|
14
|
+
## Process
|
|
15
|
+
|
|
16
|
+
1. Ask the user what feature to implement
|
|
17
|
+
2. Launch the `tdd-guide` agent
|
|
18
|
+
3. Define types/interfaces first
|
|
19
|
+
4. Write failing tests covering: happy path, edge cases, error cases
|
|
20
|
+
5. Run `{{TEST_COMMAND}}` — verify tests FAIL for the right reason
|
|
21
|
+
6. Implement minimal code to pass
|
|
22
|
+
7. Run `{{TEST_COMMAND}}` — verify tests PASS
|
|
23
|
+
8. Refactor if needed, keeping tests green
|
|
24
|
+
9. Check coverage — target 80%+ minimum
|
|
25
|
+
|
|
26
|
+
## Example
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
User: /tdd I need a function to validate email addresses
|
|
30
|
+
|
|
31
|
+
Step 1 — SCAFFOLD:
|
|
32
|
+
Create types/interfaces for input and output
|
|
33
|
+
|
|
34
|
+
Step 2 — RED (write failing tests):
|
|
35
|
+
- "should accept valid email: user@example.com"
|
|
36
|
+
- "should reject email without @"
|
|
37
|
+
- "should reject email without domain"
|
|
38
|
+
- "should reject empty string"
|
|
39
|
+
- "should handle unicode characters"
|
|
40
|
+
|
|
41
|
+
Step 3 — Run tests → all FAIL (expected, no implementation yet)
|
|
42
|
+
|
|
43
|
+
Step 4 — GREEN (implement minimal code):
|
|
44
|
+
Write just enough to pass all tests
|
|
45
|
+
|
|
46
|
+
Step 5 — Run tests → all PASS
|
|
47
|
+
|
|
48
|
+
Step 6 — REFACTOR:
|
|
49
|
+
Extract constants, improve naming, add JSDoc
|
|
50
|
+
|
|
51
|
+
Step 7 — Run tests → still PASS
|
|
52
|
+
|
|
53
|
+
Step 8 — Check coverage → 100%
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Rules
|
|
57
|
+
|
|
58
|
+
- NEVER write implementation before tests
|
|
59
|
+
- NEVER skip running tests after changes
|
|
60
|
+
- Each test should test ONE behavior
|
|
61
|
+
- Use descriptive names: "should return 404 when user not found"
|
|
62
|
+
- Test behavior, not implementation details
|
|
63
|
+
- Don't mock what you're testing
|
|
64
|
+
|
|
65
|
+
## Coverage Targets
|
|
66
|
+
|
|
67
|
+
- 80% minimum for all code
|
|
68
|
+
- 100% required for: financial calculations, auth logic, security-critical code
|
|
69
|
+
|
|
70
|
+
## Test Types to Include
|
|
71
|
+
|
|
72
|
+
- **Unit**: happy path, edge cases (null, empty, max), error conditions, boundary values
|
|
73
|
+
- **Integration**: API endpoints, database operations, auth flows
|
|
74
|
+
- **E2E**: use `/e2e` command for full user journey tests
|
|
75
|
+
|
|
76
|
+
## After TDD
|
|
77
|
+
|
|
78
|
+
- `/build-fix` — if build errors come up
|
|
79
|
+
- `/code-review` — review the implementation
|
|
80
|
+
- `/done` — verify the task is complete
|
|
@@ -2,13 +2,20 @@ Show the developer what workflows are available.
|
|
|
2
2
|
|
|
3
3
|
## Available Workflows
|
|
4
4
|
|
|
5
|
-
###
|
|
5
|
+
### Development
|
|
6
|
+
- `/plan` — Create an implementation plan before writing code
|
|
7
|
+
- `/tdd` — Write failing tests first, then implement (test-driven development)
|
|
8
|
+
- `/build-fix` — Fix build, lint, and type errors incrementally
|
|
9
|
+
- `/code-review` — Review uncommitted changes for security and quality
|
|
10
|
+
|
|
11
|
+
### Daily
|
|
6
12
|
- `/status` — Run all checks and show a project dashboard
|
|
7
13
|
- `/next` — Figure out what to work on next
|
|
8
14
|
- `/done` — Verify the current task is complete before moving on
|
|
9
15
|
|
|
10
16
|
### Verification
|
|
11
17
|
- `/verify-all` — Run lint, type check, tests, then launch all reviewers
|
|
18
|
+
- `/full-audit` — Run every audit and review agent in a single pass
|
|
12
19
|
- `/audit-spec` — Validate implementation against a spec/PRD
|
|
13
20
|
- `/audit-wiring` — Find dead or unwired features
|
|
14
21
|
- `/audit-security` — Run a security audit
|
|
@@ -22,5 +29,9 @@ Show the developer what workflows are available.
|
|
|
22
29
|
- `/generate-uat` — Generate UAT scenarios and checklists
|
|
23
30
|
- `/optimize-claude-md` — Slim down an oversized CLAUDE.md
|
|
24
31
|
|
|
32
|
+
### Session
|
|
33
|
+
- `/save-session` — Save current work context for later resumption
|
|
34
|
+
- `/resume-session` — Load a saved session and continue where you left off
|
|
35
|
+
|
|
25
36
|
## Quick Start
|
|
26
37
|
Run `/status` to see where things stand, then `/next` to pick up work.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"hooks": [
|
|
7
7
|
{
|
|
8
8
|
"type": "command",
|
|
9
|
-
"command": "
|
|
9
|
+
"command": "node .claude/hooks/guard-protected-files.mjs"
|
|
10
10
|
}
|
|
11
11
|
]
|
|
12
12
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"hooks": [
|
|
18
18
|
{
|
|
19
19
|
"type": "command",
|
|
20
|
-
"command": "
|
|
20
|
+
"command": "node .claude/hooks/autofix-polyglot.mjs"
|
|
21
21
|
}
|
|
22
22
|
]
|
|
23
23
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"hooks": [
|
|
7
7
|
{
|
|
8
8
|
"type": "command",
|
|
9
|
-
"command": "
|
|
9
|
+
"command": "node .claude/hooks/guard-protected-files.mjs"
|
|
10
10
|
}
|
|
11
11
|
]
|
|
12
12
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"hooks": [
|
|
18
18
|
{
|
|
19
19
|
"type": "command",
|
|
20
|
-
"command": "
|
|
20
|
+
"command": "node .claude/hooks/autofix-python.mjs"
|
|
21
21
|
}
|
|
22
22
|
]
|
|
23
23
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Auto-fix lint issues on saved TypeScript or Python files (polyglot)
|
|
3
|
+
|
|
4
|
+
import { execFileSync } from 'node:child_process';
|
|
5
|
+
import { resolve } from 'node:path';
|
|
6
|
+
|
|
7
|
+
let input = '';
|
|
8
|
+
process.stdin.setEncoding('utf8');
|
|
9
|
+
process.stdin.on('data', (chunk) => { input += chunk; });
|
|
10
|
+
process.stdin.on('end', () => {
|
|
11
|
+
try {
|
|
12
|
+
const data = JSON.parse(input);
|
|
13
|
+
const filePath = data?.tool_input?.file_path || '';
|
|
14
|
+
|
|
15
|
+
if (!filePath || filePath.includes('..')) {
|
|
16
|
+
process.exit(0);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Ensure path stays within the working directory
|
|
20
|
+
const resolved = resolve(filePath);
|
|
21
|
+
const cwd = resolve('.');
|
|
22
|
+
if (!resolved.startsWith(cwd)) {
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (filePath.endsWith('.ts') || filePath.endsWith('.tsx')) {
|
|
27
|
+
try {
|
|
28
|
+
execFileSync('npx', ['eslint', '--fix', filePath], { stdio: 'pipe', cwd: 'frontend' });
|
|
29
|
+
} catch {
|
|
30
|
+
// eslint may exit non-zero for unfixable issues — that's okay
|
|
31
|
+
}
|
|
32
|
+
} else if (filePath.endsWith('.py')) {
|
|
33
|
+
try {
|
|
34
|
+
execFileSync('ruff', ['check', '--fix', filePath], { stdio: 'pipe', cwd: 'backend' });
|
|
35
|
+
} catch {
|
|
36
|
+
// ruff may exit non-zero for unfixable issues — that's okay
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
process.exit(0);
|
|
41
|
+
} catch {
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Auto-fix lint issues on saved Python files
|
|
3
|
+
|
|
4
|
+
import { execFileSync } from 'node:child_process';
|
|
5
|
+
import { resolve } from 'node:path';
|
|
6
|
+
|
|
7
|
+
let input = '';
|
|
8
|
+
process.stdin.setEncoding('utf8');
|
|
9
|
+
process.stdin.on('data', (chunk) => { input += chunk; });
|
|
10
|
+
process.stdin.on('end', () => {
|
|
11
|
+
try {
|
|
12
|
+
const data = JSON.parse(input);
|
|
13
|
+
const filePath = data?.tool_input?.file_path || '';
|
|
14
|
+
|
|
15
|
+
if (!filePath || filePath.includes('..')) {
|
|
16
|
+
process.exit(0);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Ensure path stays within the working directory
|
|
20
|
+
const resolved = resolve(filePath);
|
|
21
|
+
const cwd = resolve('.');
|
|
22
|
+
if (!resolved.startsWith(cwd)) {
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (filePath.endsWith('.py')) {
|
|
27
|
+
try {
|
|
28
|
+
execFileSync('ruff', ['check', '--fix', filePath], { stdio: 'pipe', cwd: 'backend' });
|
|
29
|
+
} catch {
|
|
30
|
+
// ruff may exit non-zero for unfixable issues — that's okay
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
process.exit(0);
|
|
35
|
+
} catch {
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Auto-fix lint issues on saved TypeScript files
|
|
3
|
+
|
|
4
|
+
import { execFileSync } from 'node:child_process';
|
|
5
|
+
import { resolve } from 'node:path';
|
|
6
|
+
|
|
7
|
+
let input = '';
|
|
8
|
+
process.stdin.setEncoding('utf8');
|
|
9
|
+
process.stdin.on('data', (chunk) => { input += chunk; });
|
|
10
|
+
process.stdin.on('end', () => {
|
|
11
|
+
try {
|
|
12
|
+
const data = JSON.parse(input);
|
|
13
|
+
const filePath = data?.tool_input?.file_path || '';
|
|
14
|
+
|
|
15
|
+
if (!filePath || filePath.includes('..')) {
|
|
16
|
+
process.exit(0);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Ensure path stays within the working directory
|
|
20
|
+
const resolved = resolve(filePath);
|
|
21
|
+
const cwd = resolve('.');
|
|
22
|
+
if (!resolved.startsWith(cwd)) {
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (filePath.endsWith('.ts') || filePath.endsWith('.tsx')) {
|
|
27
|
+
try {
|
|
28
|
+
execFileSync('npx', ['eslint', '--fix', filePath], { stdio: 'pipe' });
|
|
29
|
+
} catch {
|
|
30
|
+
// eslint may exit non-zero for unfixable issues — that's okay
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
process.exit(0);
|
|
35
|
+
} catch {
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Block modifications to .env files and migration files
|
|
3
|
+
// Exit 0 = allow, Exit 2 = block
|
|
4
|
+
|
|
5
|
+
let input = '';
|
|
6
|
+
process.stdin.setEncoding('utf8');
|
|
7
|
+
process.stdin.on('data', (chunk) => { input += chunk; });
|
|
8
|
+
process.stdin.on('end', () => {
|
|
9
|
+
try {
|
|
10
|
+
const data = JSON.parse(input);
|
|
11
|
+
const filePath = data?.tool_input?.file_path || '';
|
|
12
|
+
|
|
13
|
+
if (!filePath) {
|
|
14
|
+
process.exit(0);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Block .env files
|
|
18
|
+
const basename = filePath.split('/').pop().split('\\').pop();
|
|
19
|
+
if (basename === '.env' || basename.startsWith('.env.')) {
|
|
20
|
+
process.stderr.write('BLOCKED: Do not modify .env files directly\n');
|
|
21
|
+
process.exit(2);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Block migration files
|
|
25
|
+
if (filePath.includes('prisma/migrations/') || filePath.includes('alembic/versions/')) {
|
|
26
|
+
process.stderr.write('BLOCKED: Do not modify migration files directly\n');
|
|
27
|
+
process.exit(2);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
process.exit(0);
|
|
31
|
+
} catch {
|
|
32
|
+
process.exit(0);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"hooks": [
|
|
7
7
|
{
|
|
8
8
|
"type": "command",
|
|
9
|
-
"command": "
|
|
9
|
+
"command": "node .claude/hooks/guard-protected-files.mjs"
|
|
10
10
|
}
|
|
11
11
|
]
|
|
12
12
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"hooks": [
|
|
18
18
|
{
|
|
19
19
|
"type": "command",
|
|
20
|
-
"command": "
|
|
20
|
+
"command": "node .claude/hooks/autofix-typescript.mjs"
|
|
21
21
|
}
|
|
22
22
|
]
|
|
23
23
|
}
|
|
@@ -33,6 +33,7 @@ description: AI/LLM integration patterns and best practices
|
|
|
33
33
|
## Security
|
|
34
34
|
- Never include user secrets in prompts
|
|
35
35
|
- Sanitize user input before including in prompts
|
|
36
|
+
- Protect against prompt injection attacks (delimiter tokens, input validation, output filtering)
|
|
36
37
|
- Validate and sanitize AI output before using
|
|
37
38
|
- Don't trust AI output for security decisions
|
|
38
39
|
|
|
@@ -29,7 +29,7 @@ description: FastAPI + SQLAlchemy 2.0 + Pydantic v2 patterns
|
|
|
29
29
|
- Raise `AppError` subclasses, never `HTTPException` with raw strings
|
|
30
30
|
- Global exception handler catches unhandled errors
|
|
31
31
|
- Never expose stack traces or internal details to clients
|
|
32
|
-
- Use structured error format: `{ error: { code, message } }`
|
|
32
|
+
- Use structured error format: `{ "error": { "code": "ERR_CODE", "message": "Error description" } }`
|
|
33
33
|
|
|
34
34
|
## Testing
|
|
35
35
|
- Use `httpx.AsyncClient` with `ASGITransport` for async tests
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: git-workflow
|
|
3
|
+
description: Git branching, commits, PR workflow, and conflict resolution patterns
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Branching Strategy
|
|
7
|
+
|
|
8
|
+
- `main` — production-ready code, never commit directly
|
|
9
|
+
- `feat/<name>` — new features, branch from main
|
|
10
|
+
- `fix/<name>` — bug fixes, branch from main
|
|
11
|
+
- `chore/<name>` — maintenance, config changes, dependency updates
|
|
12
|
+
|
|
13
|
+
Always create a feature branch before starting work:
|
|
14
|
+
```bash
|
|
15
|
+
git checkout -b feat/my-feature main
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Commit Conventions
|
|
19
|
+
|
|
20
|
+
Use conventional commit messages:
|
|
21
|
+
|
|
22
|
+
| Prefix | When |
|
|
23
|
+
|--------|------|
|
|
24
|
+
| `feat:` | New feature |
|
|
25
|
+
| `fix:` | Bug fix |
|
|
26
|
+
| `docs:` | Documentation only |
|
|
27
|
+
| `test:` | Adding or updating tests |
|
|
28
|
+
| `refactor:` | Code change that neither fixes nor adds |
|
|
29
|
+
| `chore:` | Build process, deps, config |
|
|
30
|
+
|
|
31
|
+
Rules:
|
|
32
|
+
- Keep subject under 72 characters
|
|
33
|
+
- Use imperative mood ("add feature" not "added feature")
|
|
34
|
+
- Body explains WHY, not WHAT (the diff shows what)
|
|
35
|
+
- Reference issue numbers: `fix: handle null user (#123)`
|
|
36
|
+
|
|
37
|
+
## Pull Request Workflow
|
|
38
|
+
|
|
39
|
+
1. Push feature branch: `git push -u origin feat/my-feature`
|
|
40
|
+
2. Create PR with clear title and description
|
|
41
|
+
3. PR description should include: what changed, why, how to test
|
|
42
|
+
4. Request review, address feedback
|
|
43
|
+
5. Squash merge to main (keeps history clean)
|
|
44
|
+
6. Delete the feature branch after merge
|
|
45
|
+
|
|
46
|
+
## Conflict Resolution
|
|
47
|
+
|
|
48
|
+
When conflicts occur:
|
|
49
|
+
1. `git fetch origin main`
|
|
50
|
+
2. `git rebase origin/main` (preferred over merge)
|
|
51
|
+
3. Resolve conflicts file by file
|
|
52
|
+
4. `git add <resolved-files>`
|
|
53
|
+
5. `git rebase --continue`
|
|
54
|
+
6. Run tests after resolving: ensure nothing broke
|
|
55
|
+
|
|
56
|
+
If rebase gets messy: `git rebase --abort` and start over.
|
|
57
|
+
|
|
58
|
+
## Common Mistakes
|
|
59
|
+
|
|
60
|
+
- Never force-push to `main`
|
|
61
|
+
- Never commit `.env` files, credentials, or large binaries
|
|
62
|
+
- Never rebase commits that have been pushed and shared
|
|
63
|
+
- Never merge main into feature branches (rebase instead)
|
|
64
|
+
- Always pull before pushing: `git pull --rebase` (pulls current branch's upstream)
|
|
@@ -25,8 +25,8 @@ description: Playwright E2E testing patterns and best practices
|
|
|
25
25
|
|
|
26
26
|
## Common Patterns
|
|
27
27
|
- Navigation: `await page.goto('/')` then assert page loaded
|
|
28
|
-
- Form filling: `await page.
|
|
29
|
-
- Clicking: `await page.
|
|
28
|
+
- Form filling: `await page.getByLabel('Email').fill('test@example.com')`
|
|
29
|
+
- Clicking: `await page.getByRole('button', { name: 'Submit' }).click()`
|
|
30
30
|
- Waiting: prefer auto-waiting over explicit waits
|
|
31
31
|
- Network: `page.waitForResponse()` for API-dependent tests
|
|
32
32
|
- Authentication: use `storageState` for persistent auth across tests
|