forgedev 1.3.0 → 1.4.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 (46) hide show
  1. package/bin/chainproof.js +1 -1
  2. package/bin/devforge.js +1 -1
  3. package/package.json +1 -1
  4. package/src/chainproof-bridge.js +9 -2
  5. package/src/ci-mode.js +3 -4
  6. package/src/claude-configurator.js +114 -58
  7. package/src/composer.js +17 -128
  8. package/src/doctor-checks-chainproof.js +14 -11
  9. package/src/doctor-checks.js +3 -19
  10. package/src/index.js +6 -34
  11. package/src/init-mode.js +14 -3
  12. package/src/recommender.js +319 -310
  13. package/src/uat-generator.js +105 -93
  14. package/src/update.js +56 -12
  15. package/src/utils.js +245 -116
  16. package/templates/auth/jwt-custom/backend/app/api/auth.py.template +39 -45
  17. package/templates/auth/jwt-custom/backend/app/core/security.py.template +44 -37
  18. package/templates/backend/express/package.json.template +35 -33
  19. package/templates/backend/express/src/lib/prisma.ts.template +32 -0
  20. package/templates/backend/express/src/routes/health.ts.template +35 -27
  21. package/templates/backend/fastapi/backend/app/main.py.template +67 -60
  22. package/templates/backend/fastapi/backend/requirements.txt.template +18 -16
  23. package/templates/backend/hono/package.json.template +33 -31
  24. package/templates/backend/hono/src/lib/prisma.ts.template +32 -0
  25. package/templates/backend/hono/src/routes/health.ts.template +38 -27
  26. package/templates/base/.gitignore.template +32 -29
  27. package/templates/claude-code/commands/workflows.md +52 -52
  28. package/templates/database/prisma-postgres/prisma/schema.prisma.template +19 -18
  29. package/templates/database/sqlalchemy-postgres/backend/alembic/env.py.template +39 -40
  30. package/templates/database/sqlalchemy-postgres/backend/alembic.ini.template +38 -36
  31. package/templates/database/sqlalchemy-postgres/backend/app/db/session.py.template +50 -48
  32. package/templates/frontend/nextjs/package.json.template +45 -43
  33. package/templates/frontend/remix/package.json.template +41 -39
  34. package/templates/infra/docker/.dockerignore.template +16 -0
  35. package/templates/infra/docker-compose/docker-compose.yml.template +22 -19
  36. package/templates/infra/github-actions/.github/workflows/ci.yml.template +61 -52
  37. package/templates/infra/k8s/k8s/deployment.yml.template +70 -0
  38. package/templates/infra/k8s/k8s/hpa.yml.template +24 -0
  39. package/templates/infra/k8s/k8s/ingress.yml.template +26 -0
  40. package/templates/infra/k8s/k8s/kustomization.yml.template +13 -0
  41. package/templates/infra/k8s/k8s/namespace.yml.template +4 -0
  42. package/templates/infra/k8s/k8s/networkpolicy.yml.template +41 -0
  43. package/templates/infra/k8s/k8s/secrets.yml.template +10 -0
  44. package/templates/infra/k8s/k8s/service.yml.template +15 -0
  45. package/templates/testing/load/k6/README.md.template +48 -0
  46. package/templates/testing/load/k6/load-test.js.template +57 -0
@@ -1,27 +1,35 @@
1
- import { Router } from 'express';
2
-
3
- export const healthRouter = Router();
4
-
5
- // Liveness probe — always returns ok if the process is running
6
- healthRouter.get('/health', (_req, res) => {
7
- res.json({
8
- status: 'ok',
9
- timestamp: new Date().toISOString(),
10
- uptime: process.uptime(),
11
- service: '{{PROJECT_NAME}}',
12
- });
13
- });
14
-
15
- // Readiness probe — add real dependency checks (database, cache, etc.)
16
- // before using this as a Kubernetes readiness probe
17
- healthRouter.get('/healthz', async (_req, res) => {
18
- // TODO: Replace with actual checks, e.g.:
19
- // const db = await prisma.$queryRaw`SELECT 1`;
20
- const checks: Record<string, string> = {};
21
-
22
- res.json({
23
- status: 'ok',
24
- service: '{{PROJECT_NAME}}',
25
- checks,
26
- });
27
- });
1
+ import { Router } from 'express';
2
+ import { prisma } from '../lib/prisma';
3
+
4
+ export const healthRouter = Router();
5
+
6
+ // Liveness probe always returns ok if the process is running
7
+ healthRouter.get('/health', (_req, res) => {
8
+ res.json({
9
+ status: 'ok',
10
+ timestamp: new Date().toISOString(),
11
+ uptime: process.uptime(),
12
+ service: '{{PROJECT_NAME}}',
13
+ });
14
+ });
15
+
16
+ // Readiness probe verifies database connectivity
17
+ healthRouter.get('/healthz', async (_req, res) => {
18
+ let dbStatus = 'disconnected';
19
+
20
+ try {
21
+ await prisma.$queryRaw`SELECT 1`;
22
+ dbStatus = 'connected';
23
+ } catch {
24
+ dbStatus = 'disconnected';
25
+ }
26
+
27
+ const status = dbStatus === 'connected' ? 'ok' : 'degraded';
28
+ const statusCode = dbStatus === 'connected' ? 200 : 503;
29
+
30
+ res.status(statusCode).json({
31
+ status,
32
+ service: '{{PROJECT_NAME}}',
33
+ checks: { database: dbStatus },
34
+ });
35
+ });
@@ -1,60 +1,67 @@
1
- from contextlib import asynccontextmanager
2
- from fastapi import FastAPI, Request
3
- from fastapi.middleware.cors import CORSMiddleware
4
- from fastapi.responses import JSONResponse
5
-
6
- from app.api.health import router as health_router
7
- from app.portal.router import router as portal_router
8
- from app.core.config import settings
9
- from app.core.errors import AppError
10
-
11
-
12
- @asynccontextmanager
13
- async def lifespan(app: FastAPI):
14
- # Startup: connect to database with retry
15
- from app.db.session import engine, connect_with_retry
16
-
17
- await connect_with_retry(engine)
18
- yield
19
- # Shutdown: close database connections gracefully
20
- await engine.dispose()
21
-
22
-
23
- app = FastAPI(
24
- title="{{PROJECT_NAME_PASCAL}}",
25
- version="0.1.0",
26
- lifespan=lifespan,
27
- )
28
-
29
- # CORS
30
- app.add_middleware(
31
- CORSMiddleware,
32
- allow_origins=settings.cors_origins,
33
- allow_credentials=True,
34
- allow_methods=["*"],
35
- allow_headers=["*"],
36
- )
37
-
38
- # Routes
39
- app.include_router(health_router, tags=["health"])
40
- app.include_router(portal_router)
41
-
42
-
43
- # Global exception handler - never leak stack traces
44
- @app.exception_handler(AppError)
45
- async def app_error_handler(request: Request, exc: AppError):
46
- return JSONResponse(
47
- status_code=exc.status_code,
48
- content={"error": {"code": exc.code, "message": exc.message}},
49
- )
50
-
51
-
52
- @app.exception_handler(Exception)
53
- async def global_exception_handler(request: Request, exc: Exception):
54
- import logging
55
-
56
- logging.exception("Unhandled exception")
57
- return JSONResponse(
58
- status_code=500,
59
- content={"error": {"code": "INTERNAL_ERROR", "message": "An unexpected error occurred"}},
60
- )
1
+ import logging
2
+ import sys
3
+ from contextlib import asynccontextmanager
4
+
5
+ from fastapi import FastAPI, Request
6
+ from fastapi.middleware.cors import CORSMiddleware
7
+ from fastapi.responses import JSONResponse
8
+ from pythonjsonlogger.json import JsonFormatter
9
+
10
+ from app.api.health import router as health_router
11
+ from app.portal.router import router as portal_router
12
+ from app.core.config import settings
13
+ from app.core.errors import AppError
14
+
15
+ # Structured JSON logging
16
+ handler = logging.StreamHandler(sys.stdout)
17
+ handler.setFormatter(JsonFormatter("%(asctime)s %(name)s %(levelname)s %(message)s"))
18
+ logging.basicConfig(level=logging.INFO, handlers=[handler])
19
+
20
+
21
+ @asynccontextmanager
22
+ async def lifespan(app: FastAPI):
23
+ # Startup: connect to database with retry
24
+ from app.db.session import engine, connect_with_retry
25
+
26
+ await connect_with_retry(engine)
27
+ yield
28
+ # Shutdown: close database connections gracefully
29
+ await engine.dispose()
30
+
31
+
32
+ app = FastAPI(
33
+ title="{{PROJECT_NAME_PASCAL}}",
34
+ version="0.1.0",
35
+ lifespan=lifespan,
36
+ )
37
+
38
+ # CORS
39
+ app.add_middleware(
40
+ CORSMiddleware,
41
+ allow_origins=settings.cors_origins,
42
+ allow_credentials=True,
43
+ allow_methods=["*"],
44
+ allow_headers=["*"],
45
+ )
46
+
47
+ # Routes
48
+ app.include_router(health_router, tags=["health"])
49
+ app.include_router(portal_router)
50
+
51
+
52
+ # Global exception handler - never leak stack traces
53
+ @app.exception_handler(AppError)
54
+ async def app_error_handler(request: Request, exc: AppError):
55
+ return JSONResponse(
56
+ status_code=exc.status_code,
57
+ content={"error": {"code": exc.code, "message": exc.message}},
58
+ )
59
+
60
+
61
+ @app.exception_handler(Exception)
62
+ async def global_exception_handler(request: Request, exc: Exception):
63
+ logging.exception("Unhandled exception")
64
+ return JSONResponse(
65
+ status_code=500,
66
+ content={"error": {"code": "INTERNAL_ERROR", "message": "An unexpected error occurred"}},
67
+ )
@@ -1,16 +1,18 @@
1
- fastapi>=0.115.0
2
- uvicorn[standard]>=0.34.0
3
- sqlalchemy[asyncio]>=2.0.38
4
- asyncpg>=0.30.0
5
- pydantic>=2.11.0
6
- pydantic-settings>=2.8.0
7
- alembic>=1.15.0
8
- python-jose[cryptography]>=3.4.0
9
- passlib[bcrypt]>=1.7.4
10
- httpx>=0.28.0
11
- pytest>=8.3.0
12
- pytest-asyncio>=0.25.0
13
- markdown>=3.7
14
- bleach>=6.2.0
15
- ruff>=0.11.0
16
- pyright>=1.1.400
1
+ fastapi>=0.115.0
2
+ uvicorn[standard]>=0.34.0
3
+ sqlalchemy[asyncio]>=2.0.38
4
+ asyncpg>=0.30.0
5
+ pydantic>=2.11.0
6
+ pydantic-settings>=2.8.0
7
+ alembic>=1.15.0
8
+ python-jose[cryptography]>=3.4.0
9
+ passlib[bcrypt]>=1.7.4
10
+ httpx>=0.28.0
11
+ pytest>=8.3.0
12
+ pytest-asyncio>=0.25.0
13
+ markdown>=3.7
14
+ bleach>=6.2.0
15
+ # v3 uses: from pythonjsonlogger.json import JsonFormatter (v2 used pythonjsonlogger.jsonlogger)
16
+ python-json-logger>=3.2.0
17
+ ruff>=0.11.0
18
+ pyright>=1.1.400
@@ -1,31 +1,33 @@
1
- {
2
- "name": "{{PROJECT_NAME}}",
3
- "version": "0.1.0",
4
- "private": true,
5
- "type": "module",
6
- "scripts": {
7
- "dev": "tsx watch src/index.ts",
8
- "build": "tsc",
9
- "start": "node dist/index.js",
10
- "lint": "eslint .",
11
- "typecheck": "tsc --noEmit",
12
- "test": "vitest run",
13
- "test:watch": "vitest",
14
- "db:push": "prisma db push",
15
- "db:studio": "prisma studio",
16
- "db:generate": "prisma generate"
17
- },
18
- "dependencies": {
19
- "hono": "^4.7.0",
20
- "@hono/node-server": "^1.14.0",
21
- "@prisma/client": "^6.6.0"
22
- },
23
- "devDependencies": {
24
- "typescript": "^5.8.3",
25
- "@types/node": "^22.14.0",
26
- "tsx": "^4.19.0",
27
- "eslint": "^9.25.0",
28
- "prisma": "^6.6.0",
29
- "vitest": "^3.1.1"
30
- }
31
- }
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "tsx watch src/index.ts",
8
+ "build": "tsc",
9
+ "start": "node dist/index.js",
10
+ "lint": "eslint .",
11
+ "typecheck": "tsc --noEmit",
12
+ "test": "vitest run",
13
+ "test:watch": "vitest",
14
+ "db:push": "prisma db push",
15
+ "db:migrate": "prisma migrate dev",
16
+ "db:migrate:deploy": "prisma migrate deploy",
17
+ "db:studio": "prisma studio",
18
+ "db:generate": "prisma generate"
19
+ },
20
+ "dependencies": {
21
+ "hono": "^4.7.0",
22
+ "@hono/node-server": "^1.14.0",
23
+ "@prisma/client": "^6.6.0"
24
+ },
25
+ "devDependencies": {
26
+ "typescript": "^5.8.3",
27
+ "@types/node": "^22.14.0",
28
+ "tsx": "^4.19.0",
29
+ "eslint": "^9.25.0",
30
+ "prisma": "^6.6.0",
31
+ "vitest": "^3.1.1"
32
+ }
33
+ }
@@ -0,0 +1,32 @@
1
+ import { PrismaClient } from '@prisma/client';
2
+
3
+ const MAX_RETRIES = 3;
4
+ const RETRY_DELAY_MS = 1000;
5
+
6
+ async function connectWithRetry(client: PrismaClient, retries = MAX_RETRIES): Promise<void> {
7
+ for (let attempt = 1; attempt <= retries; attempt++) {
8
+ try {
9
+ await client.$connect();
10
+ return;
11
+ } catch (error) {
12
+ if (attempt === retries) throw error;
13
+ const delay = RETRY_DELAY_MS * Math.pow(2, attempt - 1);
14
+ console.warn(`Database connection attempt ${attempt} failed. Retrying in ${delay}ms...`);
15
+ await new Promise((resolve) => setTimeout(resolve, delay));
16
+ }
17
+ }
18
+ }
19
+
20
+ export const prisma = new PrismaClient({
21
+ log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
22
+ });
23
+
24
+ // Graceful shutdown
25
+ const shutdownHandler = async () => {
26
+ await prisma.$disconnect();
27
+ };
28
+
29
+ process.on('SIGTERM', shutdownHandler);
30
+ process.on('SIGINT', shutdownHandler);
31
+
32
+ export { connectWithRetry };
@@ -1,27 +1,38 @@
1
- import { Hono } from 'hono';
2
-
3
- export const healthRoutes = new Hono();
4
-
5
- // Liveness probe — always returns ok if the process is running
6
- healthRoutes.get('/health', (c) => {
7
- return c.json({
8
- status: 'ok',
9
- timestamp: new Date().toISOString(),
10
- uptime: process.uptime(),
11
- service: '{{PROJECT_NAME}}',
12
- });
13
- });
14
-
15
- // Readiness probe — add real dependency checks (database, cache, etc.)
16
- // before using this as a Kubernetes readiness probe
17
- healthRoutes.get('/healthz', async (c) => {
18
- // TODO: Replace with actual checks, e.g.:
19
- // const db = await prisma.$queryRaw`SELECT 1`;
20
- const checks: Record<string, string> = {};
21
-
22
- return c.json({
23
- status: 'ok',
24
- service: '{{PROJECT_NAME}}',
25
- checks,
26
- });
27
- });
1
+ import { Hono } from 'hono';
2
+ import { prisma } from '../lib/prisma';
3
+
4
+ export const healthRoutes = new Hono();
5
+
6
+ // Liveness probe — always returns ok if the process is running
7
+ healthRoutes.get('/health', (c) => {
8
+ return c.json({
9
+ status: 'ok',
10
+ timestamp: new Date().toISOString(),
11
+ uptime: process.uptime(),
12
+ service: '{{PROJECT_NAME}}',
13
+ });
14
+ });
15
+
16
+ // Readiness probe verifies database connectivity
17
+ healthRoutes.get('/healthz', async (c) => {
18
+ let dbStatus = 'disconnected';
19
+
20
+ try {
21
+ await prisma.$queryRaw`SELECT 1`;
22
+ dbStatus = 'connected';
23
+ } catch {
24
+ dbStatus = 'disconnected';
25
+ }
26
+
27
+ const status = dbStatus === 'connected' ? 'ok' : 'degraded';
28
+ const statusCode = dbStatus === 'connected' ? 200 : 503;
29
+
30
+ return c.json(
31
+ {
32
+ status,
33
+ service: '{{PROJECT_NAME}}',
34
+ checks: { database: dbStatus },
35
+ },
36
+ statusCode,
37
+ );
38
+ });
@@ -1,29 +1,32 @@
1
- # Dependencies
2
- node_modules/
3
-
4
- # Environment
5
- .env
6
- .env.local
7
- .env.*.local
8
-
9
- # Build output
10
- dist/
11
- .next/
12
- out/
13
- build/
14
-
15
- # IDE
16
- .vscode/
17
- .idea/
18
- *.swp
19
- *.swo
20
-
21
- # OS
22
- .DS_Store
23
- Thumbs.db
24
-
25
- # Testing
26
- coverage/
27
- test-results/
28
- playwright-report/
29
- {{EXTRA_IGNORES}}
1
+ # Dependencies
2
+ node_modules/
3
+
4
+ # Environment
5
+ .env
6
+ .env.local
7
+ .env.*.local
8
+
9
+ # Build output
10
+ dist/
11
+ .next/
12
+ out/
13
+ build/
14
+
15
+ # IDE
16
+ .vscode/
17
+ .idea/
18
+ *.swp
19
+ *.swo
20
+
21
+ # OS
22
+ .DS_Store
23
+ Thumbs.db
24
+
25
+ # Testing
26
+ coverage/
27
+ test-results/
28
+ playwright-report/
29
+
30
+ # Kubernetes secrets (never commit real credentials)
31
+ k8s/secrets.yml
32
+ {{EXTRA_IGNORES}}
@@ -1,52 +1,52 @@
1
- Show the developer what workflows are available.
2
-
3
- ## Available Workflows
4
-
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
- - `/fix-loop` - Automated fix-review-regression loop until green
10
- - `/build-ui` - Build frontend UI with AI-powered generation (Google Stitch + UI UX Pro Max)
11
- - `/code-review` - Review changes for security and quality (required before commit)
12
- - `/simplify` - Find duplicate code, long files, and extract shared utilities
13
-
14
- ### Daily
15
- - `/help` - Not sure what to do? This guides you to the right workflow
16
- - `/status` - Run all checks and show a project dashboard
17
- - `/next` - Figure out what to work on next
18
-
19
- ### Verification
20
- - `/verify-all` - Run lint, type check, tests, then launch all reviewers
21
- - `/full-audit` - Run every audit and review agent in a single pass
22
- - `/audit-spec` - Validate implementation against a spec/PRD
23
- - `/audit-wiring` - Find dead or unwired features
24
- - `/audit-security` - Run a security audit
25
- - `/verify-intent` - Verify all agents comply with Intent Verification Protocol
26
-
27
- ### Strategy
28
- - Use `product-strategist` agent - Research competitors, evaluate project maturity, recommend improvements
29
-
30
- ### Release
31
- - `/pre-pr` - Prepare and create a pull request
32
- - `/run-uat` - Execute UAT scenarios
33
- - `/live-uat` - Run live UAT by interacting with the running application
34
-
35
- ### Generation
36
- - `/generate-prd` - Generate a PRD from the current codebase
37
- - `/generate-sdd` - Generate a Software Design Document from the codebase
38
- - `/generate-uat` - Generate UAT scenarios and checklists
39
- - `/optimize-claude-md` - Slim down an oversized CLAUDE.md
40
-
41
- ### Session
42
- - `/save-session` - Save current work context for later resumption
43
- - `/resume-session` - Load a saved session and continue where you left off
44
-
45
- ## Quality Gates (automatic)
46
-
47
- These run automatically, you don't need to remember them:
48
- - **On commit**: Pre-commit gate runs lint, tests, secrets check, and requires code review
49
- - **On stop**: Code hygiene check runs automatically
50
-
51
- ## Quick Start
52
- Run `/status` to see where things stand, then `/next` to pick up work.
1
+ Show the developer what workflows are available.
2
+
3
+ ## Available Workflows
4
+
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
+ - `/fix-loop` - Automated fix-review-regression loop until green
10
+ - `/build-ui` - Build frontend UI with AI-powered generation (Google Stitch + UI UX Pro Max)
11
+ - `/code-review` - Review changes for security and quality (required before commit)
12
+ - `/simplify` - Find duplicate code, long files, and extract shared utilities
13
+
14
+ ### Daily
15
+ - `/help` - Not sure what to do? This guides you to the right workflow
16
+ - `/status` - Run all checks and show a project dashboard
17
+ - `/next` - Figure out what to work on next
18
+
19
+ ### Verification
20
+ - `/verify-all` - Run lint, type check, tests, then launch all reviewers
21
+ - `/full-audit` - Run every audit and review agent in a single pass
22
+ - `/audit-spec` - Validate implementation against a spec/PRD
23
+ - `/audit-wiring` - Find dead or unwired features
24
+ - `/audit-security` - Run a security audit
25
+ - `/verify-intent` - Verify all agents comply with Intent Verification Protocol
26
+
27
+ ### Strategy
28
+ - `/product-strategist` - Research competitors, evaluate project maturity, recommend improvements
29
+
30
+ ### Release
31
+ - `/pre-pr` - Prepare and create a pull request
32
+ - `/run-uat` - Execute UAT scenarios
33
+ - `/live-uat` - Run live UAT by interacting with the running application
34
+
35
+ ### Generation
36
+ - `/generate-prd` - Generate a PRD from the current codebase
37
+ - `/generate-sdd` - Generate a Software Design Document from the codebase
38
+ - `/generate-uat` - Generate UAT scenarios and checklists
39
+ - `/optimize-claude-md` - Slim down an oversized CLAUDE.md
40
+
41
+ ### Session
42
+ - `/save-session` - Save current work context for later resumption
43
+ - `/resume-session` - Load a saved session and continue where you left off
44
+
45
+ ## Quality Gates (automatic)
46
+
47
+ These run automatically, you don't need to remember them:
48
+ - **On commit**: Pre-commit gate runs lint, tests, secrets check, and requires code review
49
+ - **On stop**: Code hygiene check runs automatically
50
+
51
+ ## Quick Start
52
+ Run `/status` to see where things stand, then `/next` to pick up work.
@@ -1,18 +1,19 @@
1
- generator client {
2
- provider = "prisma-client-js"
3
- }
4
-
5
- datasource db {
6
- provider = "postgresql"
7
- url = env("DATABASE_URL")
8
- }
9
-
10
- // Add your models below
11
- // Example:
12
- // model User {
13
- // id String @id @default(cuid())
14
- // email String @unique
15
- // name String?
16
- // createdAt DateTime @default(now())
17
- // updatedAt DateTime @updatedAt
18
- // }
1
+ generator client {
2
+ provider = "prisma-client-js"
3
+ }
4
+
5
+ datasource db {
6
+ provider = "postgresql"
7
+ url = env("DATABASE_URL")
8
+ }
9
+
10
+ // Starting point — modify or remove this model to match your project needs
11
+ model User {
12
+ id String @id @default(cuid())
13
+ email String @unique
14
+ name String?
15
+ createdAt DateTime @default(now())
16
+ updatedAt DateTime @updatedAt
17
+ }
18
+
19
+ // Add additional models below