forgedev 1.1.0 → 1.2.0

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 (64) hide show
  1. package/README.md +80 -7
  2. package/bin/devforge.js +11 -1
  3. package/docs/00-README.md +310 -0
  4. package/docs/01-universal-prompt-library.md +1049 -0
  5. package/docs/02-claude-code-mastery-playbook.md +283 -0
  6. package/docs/03-multi-agent-verification.md +565 -0
  7. package/docs/04-errata-and-verification-checklist.md +284 -0
  8. package/docs/05-universal-scaffolder-vision.md +452 -0
  9. package/docs/06-confidence-assessment-and-repo-prompt.md +407 -0
  10. package/docs/errata.md +58 -0
  11. package/docs/multi-agent-verification.md +66 -0
  12. package/docs/plans/.gitkeep +0 -0
  13. package/docs/playbook.md +95 -0
  14. package/docs/prompt-library.md +160 -0
  15. package/docs/uat/UAT_CHECKLIST.csv +9 -0
  16. package/docs/uat/UAT_TEMPLATE.md +163 -0
  17. package/package.json +10 -2
  18. package/src/claude-configurator.js +2 -0
  19. package/src/cli.js +16 -5
  20. package/src/doctor-prompts.js +9 -2
  21. package/src/doctor.js +19 -0
  22. package/src/index.js +7 -0
  23. package/src/update-check.js +49 -0
  24. package/src/update.js +33 -0
  25. package/src/utils.js +1 -1
  26. package/templates/auth/jwt-custom/backend/app/core/security.py.template +4 -1
  27. package/templates/backend/fastapi/backend/app/core/config.py.template +2 -2
  28. package/templates/base/docs/plans/.gitkeep +0 -0
  29. package/templates/base/docs/uat/UAT_CHECKLIST.csv.template +2 -0
  30. package/templates/base/docs/uat/UAT_TEMPLATE.md.template +22 -0
  31. package/templates/claude-code/agents/build-error-resolver.md +4 -4
  32. package/templates/claude-code/agents/code-quality-reviewer.md +1 -1
  33. package/templates/claude-code/agents/database-reviewer.md +2 -2
  34. package/templates/claude-code/agents/doc-updater.md +1 -1
  35. package/templates/claude-code/agents/harness-optimizer.md +26 -0
  36. package/templates/claude-code/agents/loop-operator.md +1 -1
  37. package/templates/claude-code/agents/product-strategist.md +124 -0
  38. package/templates/claude-code/agents/security-reviewer.md +1 -0
  39. package/templates/claude-code/agents/spec-validator.md +31 -1
  40. package/templates/claude-code/agents/uat-validator.md +6 -1
  41. package/templates/claude-code/claude-md/base.md +3 -2
  42. package/templates/claude-code/claude-md/nextjs.md +1 -1
  43. package/templates/claude-code/commands/build-fix.md +1 -1
  44. package/templates/claude-code/commands/code-review.md +6 -1
  45. package/templates/claude-code/commands/full-audit.md +61 -0
  46. package/templates/claude-code/commands/workflows.md +4 -0
  47. package/templates/claude-code/hooks/scripts/autofix-polyglot.mjs +28 -10
  48. package/templates/claude-code/hooks/scripts/autofix-python.mjs +11 -4
  49. package/templates/claude-code/hooks/scripts/autofix-typescript.mjs +11 -3
  50. package/templates/claude-code/hooks/scripts/guard-protected-files.mjs +2 -2
  51. package/templates/claude-code/skills/ai-prompts/SKILL.md +1 -0
  52. package/templates/claude-code/skills/fastapi/SKILL.md +1 -1
  53. package/templates/claude-code/skills/git-workflow/SKILL.md +3 -3
  54. package/templates/claude-code/skills/nextjs/SKILL.md +1 -1
  55. package/templates/claude-code/skills/playwright/SKILL.md +8 -7
  56. package/templates/claude-code/skills/security-api/SKILL.md +2 -2
  57. package/templates/claude-code/skills/security-web/SKILL.md +1 -0
  58. package/templates/database/sqlalchemy-postgres/.env.example +1 -0
  59. package/templates/infra/github-actions/.github/workflows/ci.yml.template +49 -0
  60. package/templates/testing/pytest/backend/tests/__init__.py +0 -0
  61. package/templates/testing/pytest/backend/tests/conftest.py.template +11 -0
  62. package/templates/testing/pytest/backend/tests/test_health.py.template +10 -0
  63. package/templates/testing/vitest/vitest.config.ts.template +18 -0
  64. package/CLAUDE.md +0 -38
@@ -0,0 +1,160 @@
1
+ # DevForge Prompt Library
2
+
3
+ 8 workflow guides for developing DevForge. Each workflow includes the exact prompts to use.
4
+
5
+ ---
6
+
7
+ ## Flow 1: Add a New Stack
8
+
9
+ When you want to add support for a new tech stack (e.g., Hono, React+Vite, Express).
10
+
11
+ **Step 1: Plan**
12
+ ```
13
+ I want to add [stack] support to DevForge. Enter plan mode. Research:
14
+ 1. What files/directories are needed for a typical [stack] project
15
+ 2. What dependencies go in package.json / requirements.txt
16
+ 3. What the recommender decision tree should look like
17
+ Write a plan to docs/plans/add-[stack].md
18
+ ```
19
+
20
+ **Step 2: Templates**
21
+ ```
22
+ Following the plan in docs/plans/add-[stack].md, create template files in
23
+ templates/[category]/[stack]/. Use {{VARIABLE_NAME}} for substitution.
24
+ Follow the patterns in existing templates like templates/frontend/nextjs/.
25
+ ```
26
+
27
+ **Step 3: Recommender**
28
+ ```
29
+ Update src/recommender.js to route to the new [stack] templates.
30
+ Add the new templateModules paths. Update formatStackSummary.
31
+ ```
32
+
33
+ **Step 4: Test**
34
+ ```
35
+ Add tests in tests/recommender.test.js for the new stack routing.
36
+ Run npx vitest run to verify all tests pass.
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Flow 2: Create a New Template
42
+
43
+ When adding individual template files to an existing stack.
44
+
45
+ ```
46
+ I want to add a [template] to the [stack] stack. Create the template file at
47
+ templates/[category]/[stack]/[path]. Use {{VARIABLE_NAME}} placeholders where
48
+ the project name, description, or config values should go. Check
49
+ src/composer.js buildVariables() for available variables.
50
+ ```
51
+
52
+ ---
53
+
54
+ ## Flow 3: Fix a Bug
55
+
56
+ **Step 1: Reproduce**
57
+ ```
58
+ There's a bug: [describe]. Write a failing test in tests/ that reproduces it.
59
+ Run npx vitest run to confirm the test fails.
60
+ ```
61
+
62
+ **Step 2: Fix**
63
+ ```
64
+ Fix the bug that causes [test name] to fail. Run npx vitest run to confirm
65
+ the fix and that no other tests break.
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Flow 4: Refactor
71
+
72
+ ```
73
+ I want to refactor [module/function]. Enter plan mode. First:
74
+ 1. Check test coverage for the code being refactored
75
+ 2. Add tests for any uncovered behavior
76
+ 3. Plan the refactoring steps (each should keep tests green)
77
+ Write a plan to docs/plans/refactor-[module].md
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Flow 5: Add a Feature
83
+
84
+ For features that touch multiple modules (prompts, recommender, composer, configurator).
85
+
86
+ **Step 1: Plan**
87
+ ```
88
+ I want to add [feature] to DevForge. Enter plan mode. Trace through:
89
+ - src/prompts.js — does the user need to be asked anything new?
90
+ - src/recommender.js — does the decision tree change?
91
+ - src/composer.js — are new template variables needed?
92
+ - src/claude-configurator.js — does the generated infrastructure change?
93
+ - src/uat-generator.js — do UAT scenarios need updating?
94
+ Write a plan to docs/plans/[feature].md
95
+ ```
96
+
97
+ **Step 2: Implement**
98
+ ```
99
+ Following docs/plans/[feature].md, implement the feature. Work module by module.
100
+ Run npx vitest run after each module change.
101
+ ```
102
+
103
+ ---
104
+
105
+ ## Flow 6: Verification
106
+
107
+ ```
108
+ Run /project:verify-all
109
+ ```
110
+
111
+ This launches all 5 agents (code-quality, security, spec-validator, production-readiness, uat-validator) and runs tests.
112
+
113
+ ---
114
+
115
+ ## Flow 7: Pre-PR
116
+
117
+ ```
118
+ Run /project:pre-pr
119
+ ```
120
+
121
+ This runs tests, smoke test, code quality review, security review, and checks for staged secrets.
122
+
123
+ ---
124
+
125
+ ## Flow 8: UAT
126
+
127
+ ```
128
+ Run /project:run-uat
129
+ ```
130
+
131
+ This reads docs/uat/UAT_TEMPLATE.md, maps scenarios to tests, runs them, and updates UAT_CHECKLIST.csv.
132
+
133
+ ---
134
+
135
+ ## Utility Prompts
136
+
137
+ ### "I'm lost"
138
+ ```
139
+ Read CLAUDE.md, git log --oneline -10, and git status. Tell me where I am,
140
+ what I was working on, and what I should do next.
141
+ ```
142
+
143
+ ### "Is this right?"
144
+ ```
145
+ Review my changes (git diff). Check if they follow DevForge patterns:
146
+ ESM imports with .js extensions, chalk for output, path.join for paths,
147
+ {{VARIABLE}} for templates. Flag anything that looks wrong.
148
+ ```
149
+
150
+ ### "Before I PR"
151
+ ```
152
+ Run /project:pre-pr
153
+ ```
154
+
155
+ ### "Explain this code"
156
+ ```
157
+ Read [file] and explain what it does, how it fits into the DevForge pipeline
158
+ (prompts → recommender → composer → configurator → uat-generator), and what
159
+ calls it.
160
+ ```
@@ -0,0 +1,9 @@
1
+ UAT_ID,Scenario,Priority,Automated,Test_File,Status,Last_Run,Notes
2
+ UAT-001,Scaffold Next.js Full-Stack,P0,PARTIAL,tests/composer.test.js,NOT RUN,,Manual smoke test required
3
+ UAT-002,Scaffold FastAPI Backend,P0,PARTIAL,tests/composer.test.js,NOT RUN,,Manual smoke test required
4
+ UAT-003,Scaffold Polyglot Full-Stack,P0,PARTIAL,tests/composer.test.js,NOT RUN,,Manual smoke test required
5
+ UAT-004,Recommender Selects Correct Stack,P0,YES,tests/recommender.test.js,NOT RUN,,
6
+ UAT-005,Template Variable Substitution,P0,YES,tests/composer.test.js,NOT RUN,,
7
+ UAT-006,Claude Code Infrastructure Generated,P1,YES,tests/claude-configurator.test.js,NOT RUN,,
8
+ UAT-007,Invalid Input Handling,P1,NO,,NOT RUN,,Manual test required
9
+ UAT-008,Unsupported Stack Selection,P1,PARTIAL,tests/recommender.test.js,NOT RUN,,
@@ -0,0 +1,163 @@
1
+ # UAT Scenario Pack: DevForge
2
+
3
+ ## Pre-Conditions
4
+ - [ ] Node.js >= 18 installed
5
+ - [ ] npm available
6
+ - [ ] DevForge dependencies installed (`npm install`)
7
+ - [ ] No existing `test-output/` directory
8
+
9
+ ## Scenarios
10
+
11
+ ### UAT-001: Scaffold Next.js Full-Stack Project — Happy Path
12
+ **Priority:** P0
13
+ **Preconditions:** Clean environment, no test-output/ directory
14
+ **Steps:**
15
+ 1. Run `node bin/devforge.js test-output`
16
+ 2. Select "Full-stack app"
17
+ 3. Select "TypeScript" for language
18
+ 4. Select "Yes" for authentication
19
+ 5. Select "No" for AI integration
20
+ 6. Select "Docker" for deployment
21
+ 7. Confirm the recommended stack
22
+ **Expected Result:**
23
+ - `test-output/` directory created
24
+ - Contains `package.json` with Next.js, React, TypeScript, Tailwind, Prisma, NextAuth dependencies
25
+ - Contains `src/app/layout.tsx`, `src/app/page.tsx`
26
+ - Contains `src/app/api/health/route.ts` (health check endpoint)
27
+ - Contains `prisma/schema.prisma`
28
+ - Contains `.claude/` directory with hooks, agents, commands
29
+ - Contains `CLAUDE.md` with Next.js-specific rules
30
+ - Contains `docs/uat/UAT_TEMPLATE.md`
31
+ **Actual Result:** ___
32
+ **Status:** NOT RUN
33
+ **Tester:** ___
34
+ **Date:** ___
35
+ **Notes:** ___
36
+
37
+ ### UAT-002: Scaffold FastAPI Backend Project — Happy Path
38
+ **Priority:** P0
39
+ **Preconditions:** Clean environment, no test-output/ directory
40
+ **Steps:**
41
+ 1. Run `node bin/devforge.js test-output`
42
+ 2. Select "API / backend service"
43
+ 3. Select "Python" for language
44
+ 4. Select "Yes" for authentication
45
+ 5. Select "No" for AI integration
46
+ 6. Select "Docker" for deployment
47
+ 7. Confirm the recommended stack
48
+ **Expected Result:**
49
+ - `test-output/` directory created
50
+ - Contains `backend/requirements.txt` with FastAPI, SQLAlchemy, Pydantic
51
+ - Contains `backend/app/main.py` with health endpoint and graceful shutdown
52
+ - Contains `backend/app/api/health.py`
53
+ - Contains `backend/app/core/config.py`, `errors.py`, `retry.py`
54
+ - Contains `backend/tests/` with pytest fixtures
55
+ - Contains `.claude/` directory with Python-specific hooks
56
+ - Contains `CLAUDE.md` with FastAPI-specific rules
57
+ **Actual Result:** ___
58
+ **Status:** NOT RUN
59
+ **Tester:** ___
60
+ **Date:** ___
61
+ **Notes:** ___
62
+
63
+ ### UAT-003: Scaffold Polyglot Full-Stack Project — Happy Path
64
+ **Priority:** P0
65
+ **Preconditions:** Clean environment, no test-output/ directory
66
+ **Steps:**
67
+ 1. Run `node bin/devforge.js test-output`
68
+ 2. Select "Full-stack app"
69
+ 3. Select "TypeScript" and "Python" for language
70
+ 4. Select "Yes" for authentication
71
+ 5. Select "Yes" for AI integration
72
+ 6. Select "Docker" for deployment
73
+ 7. Confirm the recommended stack
74
+ **Expected Result:**
75
+ - `test-output/` directory created
76
+ - Contains both `frontend/` and `backend/` directories
77
+ - Contains `docker-compose.yml` at root
78
+ - Contains Next.js frontend and FastAPI backend
79
+ - Contains both Prisma and SQLAlchemy database configs
80
+ - Contains polyglot Claude Code hooks (TypeScript + Python)
81
+ **Actual Result:** ___
82
+ **Status:** NOT RUN
83
+ **Tester:** ___
84
+ **Date:** ___
85
+ **Notes:** ___
86
+
87
+ ### UAT-004: Recommender Selects Correct Stack
88
+ **Priority:** P0
89
+ **Preconditions:** None
90
+ **Steps:**
91
+ 1. Run `npx vitest run tests/recommender.test.js`
92
+ 2. Verify all test cases pass
93
+ 3. Verify: web_app + TypeScript → Next.js full-stack
94
+ 4. Verify: api_service + Python → FastAPI backend
95
+ 5. Verify: full_stack + TS + Python → polyglot
96
+ 6. Verify: unsupported combos return helpful error
97
+ **Expected Result:** All recommender tests pass, all 3 stacks correctly selected
98
+ **Actual Result:** ___
99
+ **Status:** NOT RUN
100
+ **Tester:** ___
101
+ **Date:** ___
102
+ **Notes:** ___
103
+
104
+ ### UAT-005: Template Variable Substitution
105
+ **Priority:** P0
106
+ **Preconditions:** None
107
+ **Steps:**
108
+ 1. Run `npx vitest run tests/composer.test.js`
109
+ 2. Verify `{{PROJECT_NAME}}` replaced in all .template files
110
+ 3. Verify non-.template files copied without modification
111
+ 4. Verify .gitkeep files preserved
112
+ 5. Verify no `{{` patterns remain in output
113
+ **Expected Result:** All composer tests pass, variables correctly substituted
114
+ **Actual Result:** ___
115
+ **Status:** NOT RUN
116
+ **Tester:** ___
117
+ **Date:** ___
118
+ **Notes:** ___
119
+
120
+ ### UAT-006: Claude Code Infrastructure Generated
121
+ **Priority:** P1
122
+ **Preconditions:** Scaffold a project first
123
+ **Steps:**
124
+ 1. Run `npx vitest run tests/claude-configurator.test.js`
125
+ 2. Verify `.claude/settings.json` created with correct hooks
126
+ 3. Verify CLAUDE.md generated with stack-specific content
127
+ 4. Verify agents copied (5 agents)
128
+ 5. Verify skills copied (filtered by stack)
129
+ 6. Verify commands copied (6 commands)
130
+ **Expected Result:** All claude-configurator tests pass, infrastructure complete
131
+ **Actual Result:** ___
132
+ **Status:** NOT RUN
133
+ **Tester:** ___
134
+ **Date:** ___
135
+ **Notes:** ___
136
+
137
+ ### UAT-007: Invalid Input Handling
138
+ **Priority:** P1
139
+ **Preconditions:** None
140
+ **Steps:**
141
+ 1. Run `node bin/devforge.js` (no project name) — should show error
142
+ 2. Run `node bin/devforge.js .` (invalid name) — should show error
143
+ 3. Create `test-output/` dir, then run `node bin/devforge.js test-output` — should warn about existing dir
144
+ **Expected Result:** Clear error messages, no crashes, exit code 1
145
+ **Actual Result:** ___
146
+ **Status:** NOT RUN
147
+ **Tester:** ___
148
+ **Date:** ___
149
+ **Notes:** ___
150
+
151
+ ### UAT-008: Unsupported Stack Selection
152
+ **Priority:** P1
153
+ **Preconditions:** None
154
+ **Steps:**
155
+ 1. Run `node bin/devforge.js test-output`
156
+ 2. Select "Mobile app" or "Desktop app"
157
+ 3. Observe the recommendation
158
+ **Expected Result:** Displays message that the stack is not yet supported in V1, suggests closest supported option
159
+ **Actual Result:** ___
160
+ **Status:** NOT RUN
161
+ **Tester:** ___
162
+ **Date:** ___
163
+ **Notes:** ___
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forgedev",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Universal, AI-first project scaffolding CLI with Claude Code infrastructure",
5
5
  "type": "module",
6
6
  "bin": {
@@ -29,5 +29,13 @@
29
29
  },
30
30
  "engines": {
31
31
  "node": ">=18.0.0"
32
- }
32
+ },
33
+ "files": [
34
+ "bin/",
35
+ "src/",
36
+ "templates/",
37
+ "docs/",
38
+ "LICENSE",
39
+ "README.md"
40
+ ]
33
41
  }
@@ -226,6 +226,7 @@ function generateAgents(outputDir, config, vars) {
226
226
  'chief-of-staff.md',
227
227
  'loop-operator.md',
228
228
  'harness-optimizer.md',
229
+ 'product-strategist.md',
229
230
  ];
230
231
 
231
232
  for (const agent of agents) {
@@ -260,6 +261,7 @@ function generateCommands(outputDir, config, vars) {
260
261
  'tdd.md',
261
262
  'save-session.md',
262
263
  'resume-session.md',
264
+ 'full-audit.md',
263
265
  ];
264
266
 
265
267
  for (const cmd of commands) {
package/src/cli.js CHANGED
@@ -46,15 +46,21 @@ export async function parseCommand(args) {
46
46
  return;
47
47
  }
48
48
 
49
+ if (command === 'update') {
50
+ const { runUpdate } = await import('./update.js');
51
+ await runUpdate();
52
+ return;
53
+ }
54
+
49
55
  // Shorthand: devforge my-app → devforge new my-app
50
56
  if (!command.startsWith('-')) {
51
57
  const targetDir = path.resolve(process.cwd(), command);
52
58
  if (fs.existsSync(targetDir)) {
53
- console.log('');
59
+ console.error('');
54
60
  log.warn(`"${command}" already exists. Did you mean:`);
55
- console.log(` ${chalk.bold('devforge init')} Add dev guardrails to current project`);
56
- console.log(` ${chalk.bold('devforge doctor')} Diagnose and optimize current project`);
57
- console.log('');
61
+ console.error(` ${chalk.bold('devforge init')} Add dev guardrails to current project`);
62
+ console.error(` ${chalk.bold('devforge doctor')} Diagnose and optimize current project`);
63
+ console.error('');
58
64
  process.exit(1);
59
65
  }
60
66
  const { runNew } = await import('./index.js');
@@ -73,13 +79,14 @@ function showUsage() {
73
79
  devforge new <name> Create a new project
74
80
  devforge init Add dev guardrails to current project
75
81
  devforge doctor Diagnose and optimize current project
82
+ devforge update Check for newer version
76
83
  devforge <name> Shorthand for ${chalk.dim('devforge new <name>')}
77
84
 
78
85
  ${chalk.bold('Options:')}
79
86
  -h, --help Show this help message
80
87
  -v, --version Show version number
81
88
 
82
- Run ${chalk.cyan('devforge new --help')} for more details.
89
+ Run ${chalk.cyan('devforge --help')} for more details.
83
90
  `);
84
91
  }
85
92
 
@@ -105,6 +112,10 @@ function showHelp() {
105
112
  flaky tests, dead code, duplicate code, and more.
106
113
  Generates Claude Code prompts to fix each issue.
107
114
 
115
+ ${chalk.bold('devforge update')}
116
+ Check if a newer version of DevForge is available.
117
+ Shows upgrade instructions if an update exists.
118
+
108
119
  ${chalk.bold('Supported stacks (V1):')}
109
120
  - Next.js full-stack (TypeScript + Prisma + PostgreSQL)
110
121
  - FastAPI backend (Python + SQLAlchemy + PostgreSQL)
@@ -176,6 +176,15 @@ ${fileList}
176
176
 
177
177
  Extract all prompts into a dedicated prompts file (e.g., src/lib/prompts.ts or prompts/). This makes prompts easier to version, A/B test, and iterate on without changing application code.`;
178
178
  },
179
+
180
+ DEVFORGE_UPDATE: (issue) => {
181
+ return `A newer version of DevForge is available.
182
+
183
+ Run: npm install -g forgedev@latest
184
+ Then re-run: npx forgedev init
185
+
186
+ This will update your project's agents, commands, skills, and hooks to the latest version.`;
187
+ },
179
188
  };
180
189
 
181
190
  export function generatePrompt(issue) {
@@ -223,8 +232,6 @@ export function generateReport(issues, projectName) {
223
232
  const critical = issues.filter(i => i.severity === 'critical');
224
233
  const warnings = issues.filter(i => i.severity === 'warning');
225
234
  const info = issues.filter(i => i.severity === 'info');
226
- const healthy = []; // Could be populated by passing in good checks
227
-
228
235
  let report = `# DevForge Doctor Report — ${projectName}
229
236
  Generated: ${new Date().toISOString().split('T')[0]}
230
237
 
package/src/doctor.js CHANGED
@@ -29,6 +29,25 @@ export async function runDoctor(projectDir) {
29
29
  // Run all checks
30
30
  const issues = runAllChecks(projectDir, scan);
31
31
 
32
+ // Check for DevForge updates (5s timeout, won't crash on failure)
33
+ try {
34
+ const { checkForUpdate } = await import('./update-check.js');
35
+ const updateResult = await checkForUpdate();
36
+ if (updateResult?.updateAvailable) {
37
+ issues.push({
38
+ severity: 'info',
39
+ title: `DevForge update available: ${updateResult.current} → ${updateResult.latest}`,
40
+ impact: 'Newer version may include improved agents, commands, and bug fixes',
41
+ files: [],
42
+ autoFixable: false,
43
+ promptId: 'DEVFORGE_UPDATE',
44
+ effort: 'quick',
45
+ });
46
+ }
47
+ } catch {
48
+ // Silently ignore — network issues shouldn't block doctor
49
+ }
50
+
32
51
  if (issues.length === 0) {
33
52
  console.log(chalk.green(' ✓ Your project looks healthy! No issues found.'));
34
53
  console.log('');
package/src/index.js CHANGED
@@ -11,6 +11,13 @@ import { generateUAT } from './uat-generator.js';
11
11
 
12
12
  export async function runNew(projectName) {
13
13
  const safeName = toKebabCase(projectName);
14
+
15
+ // Validate project name — must be a clean kebab-case identifier
16
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(safeName)) {
17
+ log.error('Project name must start with a letter or number and contain only lowercase letters, numbers, and hyphens.');
18
+ process.exit(1);
19
+ }
20
+
14
21
  const outputDir = path.resolve(process.cwd(), safeName);
15
22
 
16
23
  if (fs.existsSync(outputDir)) {
@@ -0,0 +1,49 @@
1
+ import fs from 'node:fs';
2
+
3
+ const PACKAGE_NAME = 'forgedev';
4
+
5
+ /**
6
+ * Compare two semver strings (major.minor.patch).
7
+ * Returns 1 if a > b, -1 if a < b, 0 if equal.
8
+ */
9
+ export function compareVersions(a, b) {
10
+ const pa = a.split('.').map(Number);
11
+ const pb = b.split('.').map(Number);
12
+ for (let i = 0; i < 3; i++) {
13
+ if ((pa[i] || 0) > (pb[i] || 0)) return 1;
14
+ if ((pa[i] || 0) < (pb[i] || 0)) return -1;
15
+ }
16
+ return 0;
17
+ }
18
+
19
+ /**
20
+ * Check npm registry for a newer version of forgedev.
21
+ * Returns { current, latest, updateAvailable } or null on failure.
22
+ */
23
+ export async function checkForUpdate() {
24
+ const pkg = JSON.parse(
25
+ fs.readFileSync(new URL('../package.json', import.meta.url), 'utf-8')
26
+ );
27
+ const currentVersion = pkg.version;
28
+
29
+ try {
30
+ const response = await fetch(
31
+ `https://registry.npmjs.org/${PACKAGE_NAME}/latest`,
32
+ { signal: AbortSignal.timeout(5000) }
33
+ );
34
+ if (!response.ok) return null;
35
+ const data = await response.json();
36
+ const latestVersion = data.version;
37
+
38
+ // Validate version format before trusting registry response
39
+ if (!/^\d+\.\d+\.\d+/.test(latestVersion)) return null;
40
+
41
+ return {
42
+ current: currentVersion,
43
+ latest: latestVersion,
44
+ updateAvailable: compareVersions(latestVersion, currentVersion) > 0,
45
+ };
46
+ } catch {
47
+ return null;
48
+ }
49
+ }
package/src/update.js ADDED
@@ -0,0 +1,33 @@
1
+ import chalk from 'chalk';
2
+ import { log } from './utils.js';
3
+ import { checkForUpdate } from './update-check.js';
4
+
5
+ export async function runUpdate() {
6
+ console.log('');
7
+ console.log(chalk.bold.cyan(' DevForge') + chalk.dim(' — Checking for updates...'));
8
+ console.log('');
9
+
10
+ const result = await checkForUpdate();
11
+
12
+ if (result === null) {
13
+ log.warn(' Could not reach the npm registry. Check your internet connection.');
14
+ console.log('');
15
+ return;
16
+ }
17
+
18
+ if (!result.updateAvailable) {
19
+ log.success(` ✓ You're on the latest version (${result.current})`);
20
+ console.log('');
21
+ return;
22
+ }
23
+
24
+ log.warn(` Update available: ${result.current} → ${result.latest}`);
25
+ console.log('');
26
+ console.log(' To update:');
27
+ console.log(` ${chalk.bold('npm install -g forgedev@latest')} ${chalk.dim('(if installed globally)')}`);
28
+ console.log(` ${chalk.bold('npx forgedev@latest new my-app')} ${chalk.dim('(one-time use)')}`);
29
+ console.log('');
30
+ log.dim(' To update an existing project\'s Claude Code infrastructure:');
31
+ log.dim(' cd my-project && npx forgedev@latest init');
32
+ console.log('');
33
+ }
package/src/utils.js CHANGED
@@ -11,7 +11,7 @@ export const ROOT_DIR = path.resolve(__dirname, '..');
11
11
  export const log = {
12
12
  info: (msg) => console.log(chalk.cyan(msg)),
13
13
  success: (msg) => console.log(chalk.green(msg)),
14
- warn: (msg) => console.log(chalk.yellow(msg)),
14
+ warn: (msg) => console.error(chalk.yellow(msg)),
15
15
  error: (msg) => console.error(chalk.red(msg)),
16
16
  step: (n, total, msg) => console.log(chalk.blue(`[${n}/${total}] ${msg}`)),
17
17
  dim: (msg) => console.log(chalk.dim(msg)),
@@ -1,3 +1,4 @@
1
+ import os
1
2
  from datetime import datetime, timedelta, timezone
2
3
 
3
4
  from jose import JWTError, jwt
@@ -7,7 +8,9 @@ from app.core.config import settings
7
8
 
8
9
  pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
9
10
 
10
- SECRET_KEY = "change-me-in-production" # TODO: Move to settings/env
11
+ SECRET_KEY = os.environ.get("JWT_SECRET_KEY")
12
+ if not SECRET_KEY:
13
+ raise RuntimeError("JWT_SECRET_KEY environment variable is required. Set it in your .env file.")
11
14
  ALGORITHM = "HS256"
12
15
  ACCESS_TOKEN_EXPIRE_MINUTES = 30
13
16
 
@@ -6,8 +6,8 @@ class Settings(BaseSettings):
6
6
  app_name: str = "{{PROJECT_NAME_PASCAL}}"
7
7
  debug: bool = False
8
8
 
9
- # Database
10
- database_url: str = "postgresql+asyncpg://postgres:postgres@localhost:5432/{{PROJECT_NAME_SNAKE}}"
9
+ # Database — no default: must be set via .env or environment
10
+ database_url: str
11
11
 
12
12
  # CORS
13
13
  cors_origins: list[str] = ["http://localhost:3000"]
File without changes
@@ -0,0 +1,2 @@
1
+ UAT_ID,Feature,Priority,Status,Tester,Date,Defect_ID,Notes
2
+ UAT-001,Health Check,P0,NOT RUN,,,,
@@ -0,0 +1,22 @@
1
+ # UAT Scenario Pack: {{PROJECT_NAME}}
2
+
3
+ ## Pre-Conditions
4
+ - [ ] Application is deployed to staging
5
+ - [ ] Test accounts are created
6
+ - [ ] Test data is seeded
7
+
8
+ ## Scenarios
9
+
10
+ ### UAT-001: Health Check — Happy Path
11
+ **Priority:** P0
12
+ **Preconditions:** Application is running
13
+ **Steps:**
14
+ 1. Send GET request to /health (or /api/health)
15
+ 2. Verify response status is 200
16
+ 3. Verify response body contains status: "ok"
17
+ **Expected Result:** Health endpoint responds with 200 and status ok
18
+ **Actual Result:** ___
19
+ **Status:** NOT RUN
20
+ **Tester:** ___
21
+ **Date:** ___
22
+ **Notes:** ___
@@ -8,19 +8,19 @@ You are a build error resolution specialist. Your job is to fix build/type/lint
8
8
 
9
9
  1. **Collect errors** — Run `{{BUILD_COMMAND}}`, `{{LINT_COMMAND}}`, and `{{TYPE_CHECK_COMMAND}}` to capture all errors
10
10
  2. **Group by file** — Sort errors by file path, fix in dependency order (imports/types before logic)
11
- 3. **Fix one at a time** — Read the file, diagnose root cause, apply minimal edit, re-run build
12
- 4. **Verify** — After each fix, confirm the error is gone and no new errors were introduced
11
+ 3. **Fix one error at a time** — Read the file, diagnose root cause, apply minimal edit
12
+ 4. **Verify** — After each fix, re-run all three commands to confirm the error is gone and no new errors were introduced
13
13
 
14
14
  ## Common Fix Patterns
15
15
 
16
16
  | Error Type | Fix |
17
17
  |-----------|-----|
18
18
  | Missing import | Add the import statement |
19
- | Type mismatch | Add type annotation or assertion |
19
+ | Type mismatch | Add correct type annotation, adjust code to match expected types, or fix the actual type |
20
20
  | Undefined variable | Check spelling, add declaration, or fix import |
21
21
  | Missing dependency | Suggest install command (`npm install X` or `pip install X`) |
22
22
  | Config error | Compare with known working defaults |
23
- | Circular dependency | Identify the cycle, suggest extraction to shared module |
23
+ | Circular dependency | Identify the cycle, report to user with suggested breaking strategies |
24
24
 
25
25
  ## Rules
26
26
 
@@ -38,4 +38,4 @@ Stack: {{STACK_SUMMARY}}
38
38
  - [ ] Functions are reasonably sized (< 50 lines)
39
39
 
40
40
  ## Output
41
- For each issue: **File** | **Line** | **Severity** (critical/warning/info) | **Issue** | **Fix**
41
+ For each issue: **File** | **Line** | **Severity** (critical/high/medium/low) | **Issue** | **Fix**