17 min
architecture
February 8, 2026

Implementation Plan: Section 1 — Project Foundation

Implementation Plan: Section 1 — Project Foundation

Document Version: 1.0 Date: 2026-02-07 Status: Ready for Implementation Scope: Complete project initialization for Forge MVP


Overview

This plan provides step-by-step instructions to initialize the Forge project from scratch. It covers project setup, dependency selection, repository structure, TypeScript configuration, development tooling, build scripts, CI setup, and enforcement of the five design principles. By following this plan, a developer can set up the entire project skeleton without ambiguity.

Design Principles Reminder

  1. Start simple, earn complexity — Sequential pipeline first, parallel agents later
  2. Learn from everything — Every execution feeds the memory system
  3. Safe by default — Circuit breakers and human gates baked in
  4. Observable — Every decision logged with rationale, every action attributed
  5. Tool-agnostic — Swap LLM providers, CI systems, or git hosts without rewriting agents

1. Project Initialization

1.1 Prerequisites

Ensure the following are installed:

  • Bun >= 1.0.0 (curl -fsSL https://bun.sh/install | bash)
  • Git >= 2.40.0
  • Node.js >= 20 (for tooling compatibility, even though Bun is the runtime)

1.2 Create Project Directory

bash
mkdir -p forge cd forge bun init -y

This creates a basic Bun project with package.json, tsconfig.json, and README.md.

1.3 Initialize Git Repository

bash
git init echo "node_modules/" > .gitignore echo ".env" >> .gitignore echo ".forge/" >> .gitignore echo "*.db" >> .gitignore echo "*.log" >> .gitignore git add . git commit -m "chore: initialize Forge project"

1.4 Project Metadata

Edit package.json to set project metadata:

json
{ "name": "forge", "version": "0.1.0", "description": "An opinionated, buildable AI-driven SDLC orchestrator", "type": "module", "main": "./dist/index.js", "bin": { "forge": "./dist/cli/index.js" }, "scripts": { "dev": "bun --watch src/cli/index.ts", "build": "bun build src/cli/index.ts --outdir dist --target node --minify", "start": "bun dist/cli/index.js", "typecheck": "tsc --noEmit", "lint": "biome check src/", "lint:fix": "biome check --write src/", "format": "biome format --write src/", "test": "bun test", "test:watch": "bun test --watch", "db:generate": "drizzle-kit generate", "db:migrate": "bun src/scripts/migrate.ts", "db:studio": "drizzle-kit studio" }, "keywords": ["ai", "sdlc", "agent", "orchestration", "automation"], "author": "Your Name", "license": "MIT", "engines": { "bun": ">=1.0.0" } }

2. Dependency Selection

2.1 Core Dependencies

bash
bun add drizzle-orm better-sqlite3 bun add zod bun add ulid bun add dotenv

Justifications:

PackageVersionPurpose
drizzle-orm^0.36.4Type-safe SQL ORM for SQLite
better-sqlite3^11.7.0Fast synchronous SQLite driver
zod^3.24.1Runtime schema validation
ulid^2.3.0Sortable unique identifiers
dotenv^16.4.7Environment variable management

2.2 LLM Integration

bash
bun add @anthropic-ai/sdk

Justification: Official Anthropic SDK for Claude integration. Supports streaming, tool use, and message API.

2.3 Git Operations

bash
bun add simple-git

Justification: Simple wrapper for git CLI operations. Async-friendly, well-maintained.

2.4 CLI Tooling

bash
bun add commander bun add chalk bun add ora bun add prompts

Justifications:

PackagePurpose
commanderCLI argument parsing and command routing
chalkTerminal color output
oraSpinners and progress indicators
promptsInteractive CLI prompts

2.5 Development Dependencies

bash
bun add -D typescript @types/bun @types/better-sqlite3 bun add -D drizzle-kit bun add -D @biomejs/biome bun add -D @types/prompts

Justifications:

PackagePurpose
typescriptType checking
@types/*Type definitions
drizzle-kitDatabase migrations and introspection
@biomejs/biomeFast linter and formatter (replaces ESLint + Prettier)

2.6 Final package.json Dependencies Section

json
{ "dependencies": { "@anthropic-ai/sdk": "^0.34.0", "better-sqlite3": "^11.7.0", "chalk": "^5.3.0", "commander": "^12.1.0", "dotenv": "^16.4.7", "drizzle-orm": "^0.36.4", "ora": "^8.1.1", "prompts": "^2.4.2", "simple-git": "^3.27.0", "ulid": "^2.3.0", "zod": "^3.24.1" }, "devDependencies": { "@biomejs/biome": "^1.9.4", "@types/better-sqlite3": "^7.6.12", "@types/bun": "^1.1.14", "@types/prompts": "^2.4.9", "drizzle-kit": "^0.29.1", "typescript": "^5.7.3" } }

3. Repository Structure

3.1 Complete Directory Tree

forge/
├── .github/
│   └── workflows/
│       ├── ci.yml
│       └── release.yml
├── .vscode/
│   ├── settings.json
│   └── extensions.json
├── drizzle/
│   └── (auto-generated migration files)
├── src/
│   ├── core/
│   │   ├── types.ts
│   │   ├── bus.ts
│   │   ├── config.ts
│   │   └── errors.ts
│   ├── safety/
│   │   ├── breakers.ts
│   │   ├── gates.ts
│   │   └── budget.ts
│   ├── memory/
│   │   ├── schema.ts
│   │   ├── store.ts
│   │   ├── episodes.ts
│   │   ├── patterns.ts
│   │   ├── procedures.ts
│   │   └── consolidate.ts
│   ├── tools/
│   │   ├── registry.ts
│   │   ├── sandbox.ts
│   │   ├── llm.ts
│   │   ├── git.ts
│   │   ├── github.ts
│   │   ├── runner.ts
│   │   ├── linter.ts
│   │   └── test-runner.ts
│   ├── agents/
│   │   ├── base.ts
│   │   ├── planner.ts
│   │   ├── implementer.ts
│   │   ├── reviewer.ts
│   │   ├── tester.ts
│   │   └── deployer.ts
│   ├── orchestrator/
│   │   ├── pipeline.ts
│   │   ├── checkpoint.ts
│   │   └── context.ts
│   ├── cli/
│   │   ├── index.ts
│   │   ├── commands/
│   │   │   ├── run.ts
│   │   │   ├── review.ts
│   │   │   ├── test.ts
│   │   │   ├── status.ts
│   │   │   └── history.ts
│   │   └── ui.ts
│   ├── scripts/
│   │   └── migrate.ts
│   └── index.ts
├── tests/
│   ├── unit/
│   ├── integration/
│   └── fixtures/
├── .env.example
├── .gitignore
├── biome.json
├── drizzle.config.ts
├── forge.config.ts
├── package.json
├── README.md
└── tsconfig.json

3.2 Create Directory Structure

bash
mkdir -p .github/workflows mkdir -p .vscode mkdir -p src/core src/safety src/memory src/tools src/agents src/orchestrator src/cli/commands src/scripts mkdir -p tests/unit tests/integration tests/fixtures mkdir -p drizzle

3.3 Module Map Alignment

This structure matches the Module Map from SYSTEM-DESIGN.md Section 4:

Design ModuleImplementation Path
core/src/core/
safety/src/safety/
memory/src/memory/
tools/src/tools/
agents/src/agents/
orchestrator/src/orchestrator/
cli/src/cli/

4. TypeScript Configuration

4.1 tsconfig.json

json
{ "compilerOptions": { // Language and module options "target": "ES2022", "module": "ESNext", "lib": ["ES2022"], "moduleResolution": "bundler", // Emit options "outDir": "./dist", "rootDir": "./src", "declaration": true, "declarationMap": true, "sourceMap": true, "removeComments": false, "importHelpers": false, // Type checking - STRICT MODE "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "noImplicitReturns": true, "noUncheckedIndexedAccess": true, "exactOptionalPropertyTypes": true, "noPropertyAccessFromIndexSignature": true, // Module resolution "resolveJsonModule": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "forceConsistentCasingInFileNames": true, // Path aliases "baseUrl": ".", "paths": { "@/*": ["src/*"], "@core/*": ["src/core/*"], "@safety/*": ["src/safety/*"], "@memory/*": ["src/memory/*"], "@tools/*": ["src/tools/*"], "@agents/*": ["src/agents/*"], "@orchestrator/*": ["src/orchestrator/*"], "@cli/*": ["src/cli/*"] }, // Bun compatibility "types": ["bun-types"], "allowImportingTsExtensions": true, "noEmit": true }, "include": ["src/**/*", "tests/**/*"], "exclude": ["node_modules", "dist", "drizzle"] }

4.2 Strict Mode Enforcement

Design Principle Mapping: Principle #3 (Safe by default)

  • strict: true — Catches type errors at compile time
  • noUnusedLocals/Parameters — Enforces clean code
  • noUncheckedIndexedAccess — Prevents runtime undefined errors
  • exactOptionalPropertyTypes — No implicit undefined in optional props

4.3 Path Aliases

Path aliases enable clean imports:

typescript
// Before import { EventBus } from '../../../core/bus'; // After import { EventBus } from '@core/bus';

5. Development Tooling

5.1 Biome Configuration (biome.json)

Biome replaces ESLint + Prettier with a single fast tool.

json
{ "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", "organizeImports": { "enabled": true }, "linter": { "enabled": true, "rules": { "recommended": true, "complexity": { "noExtraBooleanCast": "error", "noMultipleSpacesInRegularExpressionLiterals": "error", "noUselessCatch": "error", "noUselessConstructor": "error", "noUselessLabel": "error", "noUselessRename": "error", "noUselessSwitchCase": "error", "noWith": "error" }, "correctness": { "noConstAssign": "error", "noConstantCondition": "error", "noEmptyPattern": "error", "noGlobalObjectCalls": "error", "noInnerDeclarations": "error", "noInvalidConstructorSuper": "error", "noNewSymbol": "error", "noUnreachable": "error", "noUnreachableSuper": "error", "noUnsafeFinally": "error", "noUnsafeOptionalChaining": "error", "noUnusedVariables": "error", "useValidForDirection": "error" }, "style": { "noNonNullAssertion": "warn", "useConst": "error", "useTemplate": "warn" }, "suspicious": { "noArrayIndexKey": "warn", "noAsyncPromiseExecutor": "error", "noCatchAssign": "error", "noClassAssign": "error", "noCompareNegZero": "error", "noDebugger": "error", "noDoubleEquals": "error", "noDuplicateCase": "error", "noDuplicateClassMembers": "error", "noDuplicateObjectKeys": "error", "noEmptyBlockStatements": "warn", "noExplicitAny": "warn", "noFallthroughSwitchClause": "error", "noFunctionAssign": "error", "noGlobalAssign": "error", "noImportAssign": "error", "noRedeclare": "error", "noShadowRestrictedNames": "error", "noUnsafeNegation": "error" } } }, "formatter": { "enabled": true, "formatWithErrors": false, "indentStyle": "space", "indentWidth": 2, "lineWidth": 100, "lineEnding": "lf" }, "javascript": { "formatter": { "quoteStyle": "single", "trailingCommas": "es5", "semicolons": "always", "arrowParentheses": "asNeeded" } }, "files": { "ignore": ["node_modules", "dist", "drizzle", "*.config.ts"] } }

5.2 Git Hooks (Simple Husky Alternative)

Create .husky/pre-commit:

bash
mkdir -p .husky cat > .husky/pre-commit << 'EOF' #!/bin/sh bun run typecheck && bun run lint EOF chmod +x .husky/pre-commit

Add to package.json:

json
{ "scripts": { "prepare": "husky install || true" } }

Install husky:

bash
bun add -D husky bun run prepare

5.3 VS Code Configuration

.vscode/settings.json:

json
{ "editor.formatOnSave": true, "editor.defaultFormatter": "biomejs.biome", "editor.codeActionsOnSave": { "quickfix.biome": "explicit", "source.organizeImports.biome": "explicit" }, "[typescript]": { "editor.defaultFormatter": "biomejs.biome" }, "typescript.tsdk": "node_modules/typescript/lib", "typescript.enablePromptUseWorkspaceTsdk": true }

.vscode/extensions.json:

json
{ "recommendations": [ "biomejs.biome", "oven.bun-vscode" ] }

5.4 Testing Framework

Bun has a built-in test runner. Create tests/setup.ts:

typescript
import { beforeAll, afterAll } from 'bun:test'; beforeAll(() => { // Global test setup process.env.NODE_ENV = 'test'; }); afterAll(() => { // Global test teardown });

Add to package.json:

json
{ "scripts": { "test": "bun test --preload ./tests/setup.ts", "test:watch": "bun test --watch --preload ./tests/setup.ts" } }

6. Build & Run Scripts

6.1 Development

bash
bun run dev

Runs the CLI in watch mode. Changes auto-reload.

6.2 Build

bash
bun run build

Creates optimized production bundle in dist/.

6.3 Start

bash
bun run start

Runs the built CLI from dist/.

6.4 Type Checking

bash
bun run typecheck

Runs TypeScript compiler in check-only mode.

6.5 Linting and Formatting

bash
bun run lint # Check for issues bun run lint:fix # Auto-fix issues bun run format # Format code

6.6 Database Management

bash
bun run db:generate # Generate migrations from schema bun run db:migrate # Apply migrations bun run db:studio # Open Drizzle Studio (GUI)

6.7 Testing

bash
bun run test # Run all tests bun run test:watch # Watch mode

7. CI Setup

7.1 GitHub Actions Workflow (.github/workflows/ci.yml)

yaml
name: CI on: push: branches: [main, master] pull_request: branches: [main, master] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v2 with: bun-version: latest - name: Install dependencies run: bun install --frozen-lockfile - name: Type check run: bun run typecheck - name: Lint run: bun run lint - name: Test run: bun run test - name: Build run: bun run build

7.2 Release Workflow (.github/workflows/release.yml)

yaml
name: Release on: push: tags: - 'v*' jobs: release: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v2 with: bun-version: latest - name: Install dependencies run: bun install --frozen-lockfile - name: Build run: bun run build - name: Create Release uses: softprops/action-gh-release@v2 with: files: | dist/**/* env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

8. Design Principles Enforcement

Principle 1: Start Simple, Earn Complexity

Implementation:

  • Sequential pipeline in src/orchestrator/pipeline.ts (no parallelization in MVP)
  • Single-agent execution per phase
  • Linear state machine: plan → implement → review → test → deploy

Code Pattern:

typescript
// src/orchestrator/pipeline.ts export async function executePipeline(task: string): Promise<void> { const plan = await planner.execute(task); const code = await implementer.execute(plan); const review = await reviewer.execute(code); const tests = await tester.execute(review); await deployer.execute(tests); }

Principle 2: Learn from Everything

Implementation:

  • Event bus in src/core/bus.ts captures all actions
  • Every agent emits events via ctx.bus.emit()
  • Memory store in src/memory/store.ts persists learnings
  • Post-execution reflection in agents

Code Pattern:

typescript
// Every agent action ctx.bus.emit({ type: `${this.type}.action`, source: this.id, payload: { action, result }, traceId: ctx.traceId, });

Principle 3: Safe by Default

Implementation:

  • Circuit breakers in src/safety/breakers.ts check on every iteration
  • Human gates in src/safety/gates.ts require approval for high-risk actions
  • Cost budget tracking in src/safety/budget.ts
  • Error taxonomy in src/core/errors.ts classifies all failures

Code Pattern:

typescript
// Check circuit breakers before every action const breakerResult = ctx.safety.check({ iteration, cost, elapsed }); if (breakerResult.shouldBreak) { throw new CircuitBreakerError(breakerResult); }

Principle 4: Observable

Implementation:

  • Every event logged to SQLite events table
  • traceId groups all events in one pipeline run
  • Cost tracking (tokensUsed, costUsd) on every LLM call
  • Replay function: bus.replay(traceId) reconstructs execution

Code Pattern:

typescript
// Every LLM call logs cost const response = await ctx.llm.chat({ ... }); ctx.bus.emit({ type: 'llm.call', payload: { tokens: response.usage.totalTokens }, cost: { tokens: response.usage.totalTokens, usd: response.cost }, });

Principle 5: Tool-Agnostic

Implementation:

  • LLM provider abstraction in src/tools/llm.ts
  • Git operations abstracted in src/tools/git.ts
  • GitHub API wrapped in src/tools/github.ts
  • Tool registry in src/tools/registry.ts allows swapping implementations

Code Pattern:

typescript
// src/tools/llm.ts export interface LLMProvider { chat(request: ChatRequest): Promise<ChatResponse>; } export class AnthropicProvider implements LLMProvider { ... } export class OpenAIProvider implements LLMProvider { ... }

9. Entry Points

9.1 CLI Entry Point

File: src/cli/index.ts

typescript
#!/usr/bin/env bun import { Command } from 'commander'; import { runCommand } from './commands/run'; import { reviewCommand } from './commands/review'; import { testCommand } from './commands/test'; import { statusCommand } from './commands/status'; import { historyCommand } from './commands/history'; const program = new Command(); program .name('forge') .description('AI-driven SDLC orchestrator') .version('0.1.0'); program .command('run') .description('Execute a full SDLC pipeline') .argument('<task>', 'Task description') .option('-c, --config <path>', 'Config file path', './forge.config.ts') .action(runCommand); program .command('review') .description('Review a PR or codebase') .argument('<target>', 'PR number or file path') .action(reviewCommand); program .command('test') .description('Run tests with AI analysis') .option('-s, --select', 'Use AI test selection') .action(testCommand); program .command('status') .description('Show current pipeline status') .action(statusCommand); program .command('history') .description('Show execution history') .option('-l, --limit <n>', 'Number of runs to show', '10') .action(historyCommand); program.parse();

Make it executable:

bash
chmod +x src/cli/index.ts

9.2 Library Entry Point

File: src/index.ts

typescript
// Core types export * from './core/types'; export * from './core/bus'; export * from './core/config'; export * from './core/errors'; // Safety export * from './safety/breakers'; export * from './safety/gates'; export * from './safety/budget'; // Memory export * from './memory/store'; export * from './memory/episodes'; export * from './memory/patterns'; export * from './memory/procedures'; // Tools export * from './tools/registry'; export * from './tools/llm'; export * from './tools/git'; // Agents export * from './agents/base'; export * from './agents/planner'; export * from './agents/implementer'; export * from './agents/reviewer'; export * from './agents/tester'; // Orchestrator export * from './orchestrator/pipeline'; export * from './orchestrator/context';

9.3 Usage Examples

As a CLI tool:

bash
forge run "add user authentication" forge review PR#42 forge test --select forge status

As a library:

typescript
import { executePipeline, Config } from 'forge'; const config: Config = { llm: { provider: 'anthropic', model: 'claude-sonnet-4' }, safety: { costPerRun: 50 }, }; await executePipeline('add user authentication', config);

10. Naming Conventions

10.1 File Naming

TypeConventionExample
Core moduleskebab-case.tsevent-bus.ts
Agent implementationssingular-noun.tsplanner.ts, reviewer.ts
Interfaces/typesColocated in implementationtypes.ts for shared types
Tests*.test.tsplanner.test.ts
Config files*.config.tsforge.config.ts, drizzle.config.ts

10.2 Variable Naming

typescript
// Constants: SCREAMING_SNAKE_CASE const MAX_ITERATIONS = 10; const DEFAULT_COST_BUDGET = 50; // Variables: camelCase const userName = 'Alice'; const iterationCount = 0; // Private class members: _camelCase class Agent { private _workingMemory: Memory[]; } // Boolean variables: is/has/can prefix const isComplete = false; const hasError = true; const canRetry = result.retryable;

10.3 Type Naming

typescript
// Interfaces: PascalCase, descriptive interface AgentContext { ... } interface PhaseInput { ... } interface LearningEvent { ... } // Type aliases: PascalCase type AgentType = 'planner' | 'implementer' | 'reviewer' | 'tester' | 'deployer'; type PhaseName = 'plan' | 'implement' | 'review' | 'test' | 'deploy'; // Enums: PascalCase for type, SCREAMING_SNAKE_CASE for values enum ErrorSeverity { INFO = 'INFO', WARNING = 'WARNING', ERROR = 'ERROR', CRITICAL = 'CRITICAL', } // Avoid: I-prefix for interfaces (IAgent ❌, Agent ✅)

10.4 Function Naming

typescript
// Functions: camelCase, verb-first function executeAgent(agent: Agent): Promise<Result> { ... } function parseRequirements(input: string): Requirements { ... } // Async functions: async prefix optional (rely on return type) async function fetchMemories(context: string): Promise<Memory[]> { ... } // Boolean return: is/has/can prefix function isRetryable(error: Error): boolean { ... } function hasCircuitBreakerTripped(ctx: Context): boolean { ... } // Event handlers: on-prefix function onAgentComplete(result: PhaseOutput): void { ... }

10.5 Class Naming

typescript
// Classes: PascalCase, noun-first class EventBus { ... } class BaseAgent { ... } class CircuitBreakerError extends Error { ... } // Agent classes: Agent suffix class PlannerAgent { ... } class ReviewerAgent { ... } // Avoid: suffixes like Manager, Helper, Util (be specific) // ❌ MemoryManager // ✅ MemoryStore

10.6 Module Structure

typescript
// Each module exports a primary interface/class and supporting types // src/core/bus.ts export class EventBus { ... } export interface ForgeEvent { ... } export interface EventHandler { ... } // src/memory/store.ts export class MemoryStore { ... } export interface Memory { ... } export interface MemoryQuery { ... }

11. Configuration Files

11.1 Drizzle Configuration (drizzle.config.ts)

typescript
import type { Config } from 'drizzle-kit'; export default { schema: './src/memory/schema.ts', out: './drizzle', dialect: 'sqlite', dbCredentials: { url: process.env.DB_PATH || '.forge/memory.db', }, } satisfies Config;

11.2 Environment Variables (.env.example)

bash
# LLM Provider ANTHROPIC_API_KEY=sk-ant-... # Database DB_PATH=.forge/memory.db # GitHub Integration (optional) GITHUB_TOKEN=ghp_... # Safety Limits MAX_COST_PER_RUN=50 MAX_ITERATIONS=10 # Logging LOG_LEVEL=info

11.3 Project Configuration (forge.config.ts)

typescript
import { defineConfig } from './src/core/config'; export default defineConfig({ name: 'my-app', language: 'typescript', llm: { provider: 'anthropic', model: 'claude-sonnet-4-5-20250929', fastModel: 'claude-haiku-4-5-20251001', }, tools: { testCommand: 'bun test', lintCommand: 'bun run lint', buildCommand: 'bun run build', typecheckCommand: 'bun run typecheck', }, safety: { costPerRun: 50, costPerDay: 200, automationLevel: 1, }, github: { owner: 'myorg', repo: 'my-app', reviewOnPR: true, postComments: true, }, memory: { dbPath: '.forge/memory.db', consolidateInterval: '1d', maxMemories: 10_000, }, });

12. Initial File Stubs

To complete the project skeleton, create stub files for each module.

12.1 Core Stubs

src/core/types.ts:

typescript
export interface Agent { id: string; type: AgentType; execute(input: PhaseInput, ctx: AgentContext): Promise<PhaseOutput>; } export interface ForgeEvent { id: string; traceId: string; timestamp: Date; source: string; type: string; payload: unknown; cost?: { tokens: number; usd: number }; } export interface Tool<TInput = unknown, TOutput = unknown> { name: string; description: string; schema: { input: ZodSchema<TInput>; output: ZodSchema<TOutput> }; execute(input: TInput, ctx: ToolContext): Promise<TOutput>; } export interface Phase { name: PhaseName; agent: Agent; guards: Guard[]; gates: HumanGate[]; breakers: CircuitBreaker[]; next: PhaseName | null; } export interface Memory { id: string; type: 'episodic' | 'semantic' | 'procedural'; content: string; embedding?: Float32Array; confidence: number; context: string; createdAt: Date; lastAccessed: Date; accessCount: number; } export interface Checkpoint { id: string; traceId: string; phase: PhaseName; state: Record<string, unknown>; timestamp: Date; } export type AgentType = 'planner' | 'implementer' | 'reviewer' | 'tester' | 'deployer'; export type PhaseName = 'plan' | 'implement' | 'review' | 'test' | 'deploy'; export type PhaseInput = unknown; export type PhaseOutput = unknown; export type AgentContext = unknown; export type ToolContext = unknown; export type Guard = unknown; export type HumanGate = unknown; export type CircuitBreaker = unknown; export type ZodSchema<T> = unknown;

src/core/bus.ts:

typescript
import { ForgeEvent } from './types'; export class EventBus { async emit(event: Omit<ForgeEvent, 'id' | 'timestamp'>): Promise<void> { // TODO: Implement event emission } on(type: string, handler: (event: ForgeEvent) => void): () => void { // TODO: Implement event subscription return () => {}; } async replay(traceId: string): Promise<ForgeEvent[]> { // TODO: Implement event replay return []; } }

src/core/config.ts:

typescript
export function defineConfig(config: Config): Config { return config; } export interface Config { name: string; language: string; llm: LLMConfig; tools: ToolsConfig; safety: SafetyConfig; github?: GitHubConfig; memory: MemoryConfig; } export interface LLMConfig { provider: 'anthropic' | 'openai' | 'ollama'; model: string; fastModel?: string; } export interface ToolsConfig { testCommand: string; lintCommand: string; buildCommand: string; typecheckCommand: string; } export interface SafetyConfig { costPerRun: number; costPerDay: number; automationLevel: 0 | 1 | 2 | 3 | 4; } export interface GitHubConfig { owner: string; repo: string; reviewOnPR: boolean; postComments: boolean; } export interface MemoryConfig { dbPath: string; consolidateInterval: string; maxMemories: number; }

src/core/errors.ts:

typescript
export class ForgeError extends Error { constructor( message: string, public severity: ErrorSeverity, public source: string, public recoverable: boolean ) { super(message); this.name = 'ForgeError'; } } export class CircuitBreakerError extends ForgeError { constructor(reason: string) { super(`Circuit breaker tripped: ${reason}`, 'CRITICAL', 'safety', false); } } export type ErrorSeverity = 'INFO' | 'WARNING' | 'ERROR' | 'CRITICAL';

12.2 Memory Schema (src/memory/schema.ts)

typescript
import { sqliteTable, text, integer, real, blob } from 'drizzle-orm/sqlite-core'; export const events = sqliteTable('events', { id: text('id').primaryKey(), traceId: text('trace_id').notNull(), timestamp: integer('timestamp', { mode: 'timestamp_ms' }).notNull(), source: text('source').notNull(), type: text('type').notNull(), phase: text('phase'), payload: text('payload', { mode: 'json' }), tokensUsed: integer('tokens_used'), costUsd: real('cost_usd'), durationMs: integer('duration_ms'), }); export const memories = sqliteTable('memories', { id: text('id').primaryKey(), type: text('type').notNull(), content: text('content').notNull(), context: text('context').notNull(), embedding: blob('embedding'), confidence: real('confidence').notNull(), source: text('source'), tags: text('tags', { mode: 'json' }), createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(), lastAccessed: integer('last_accessed', { mode: 'timestamp_ms' }).notNull(), accessCount: integer('access_count').notNull().default(0), }); export const patterns = sqliteTable('patterns', { id: text('id').primaryKey(), type: text('type').notNull(), trigger: text('trigger').notNull(), pattern: text('pattern').notNull(), resolution: text('resolution'), frequency: integer('frequency').notNull().default(1), successRate: real('success_rate'), confidence: real('confidence').notNull(), lastSeen: integer('last_seen', { mode: 'timestamp_ms' }).notNull(), }); export const checkpoints = sqliteTable('checkpoints', { id: text('id').primaryKey(), traceId: text('trace_id').notNull(), phase: text('phase').notNull(), state: text('state', { mode: 'json' }).notNull(), timestamp: integer('timestamp', { mode: 'timestamp_ms' }).notNull(), }); export const runs = sqliteTable('runs', { id: text('id').primaryKey(), task: text('task').notNull(), status: text('status').notNull(), currentPhase: text('current_phase'), config: text('config', { mode: 'json' }), startedAt: integer('started_at', { mode: 'timestamp_ms' }).notNull(), completedAt: integer('completed_at', { mode: 'timestamp_ms' }), totalCostUsd: real('total_cost_usd').default(0), totalTokens: integer('total_tokens').default(0), error: text('error'), }); export const findings = sqliteTable('findings', { id: text('id').primaryKey(), runId: text('run_id').notNull(), phase: text('phase').notNull(), severity: text('severity').notNull(), category: text('category').notNull(), message: text('message').notNull(), file: text('file'), line: integer('line'), confidence: real('confidence'), fixable: integer('fixable', { mode: 'boolean' }), fix: text('fix'), dismissed: integer('dismissed', { mode: 'boolean' }).default(false), dismissedBy: text('dismissed_by'), });

12.3 Database Migration Script (src/scripts/migrate.ts)

typescript
#!/usr/bin/env bun import { migrate } from 'drizzle-orm/better-sqlite3/migrator'; import { drizzle } from 'drizzle-orm/better-sqlite3'; import Database from 'better-sqlite3'; const dbPath = process.env.DB_PATH || '.forge/memory.db'; const sqlite = new Database(dbPath); const db = drizzle(sqlite); console.log('Running migrations...'); migrate(db, { migrationsFolder: './drizzle' }); console.log('Migrations complete!'); sqlite.close();

13. Validation Checklist

Before proceeding to Week 1 implementation, verify:

  • Bun installed and version >= 1.0.0
  • Project initialized with bun init
  • All dependencies installed (bun install)
  • Directory structure matches Module Map
  • tsconfig.json has strict mode enabled
  • biome.json configured
  • Git hooks set up (.husky/pre-commit)
  • CI workflow created (.github/workflows/ci.yml)
  • VS Code settings configured
  • All stub files created
  • Database schema defined (src/memory/schema.ts)
  • Migration script executable (src/scripts/migrate.ts)
  • CLI entry point executable (src/cli/index.ts)
  • Library entry point exports core types (src/index.ts)
  • Configuration files created (.env.example, forge.config.ts, drizzle.config.ts)
  • Type checking passes (bun run typecheck)
  • Linting passes (bun run lint)
  • All scripts in package.json are valid

14. Next Steps

After completing this plan:

  1. Generate initial database migration:

    bash
    bun run db:generate
  2. Run migrations to create tables:

    bash
    bun run db:migrate
  3. Verify type checking:

    bash
    bun run typecheck
  4. Commit the skeleton:

    bash
    git add . git commit -m "feat: complete project foundation"
  5. Proceed to Week 1 implementation (core skeleton + event bus).


Appendix A: Common Commands Reference

bash
# Project setup bun install # Install dependencies bun run prepare # Set up git hooks # Development bun run dev # Start CLI in watch mode bun run typecheck # Type check without building bun run lint # Check code quality bun run lint:fix # Auto-fix issues bun run format # Format code # Testing bun test # Run all tests bun test --watch # Watch mode bun test src/core/bus.test.ts # Run specific test # Database bun run db:generate # Generate migration bun run db:migrate # Apply migrations bun run db:studio # Open GUI # Build bun run build # Production build bun run start # Run built CLI # CLI usage (after build) forge run "task description" forge review PR#42 forge test --select forge status forge history --limit 5

Appendix B: Troubleshooting

Issue: bun: command not found

Solution:

bash
curl -fsSL https://bun.sh/install | bash source ~/.bashrc # or ~/.zshrc

Issue: Type errors with Bun types

Solution: Ensure @types/bun is installed and tsconfig.json includes "types": ["bun-types"].

Issue: Biome not formatting on save

Solution: Install the Biome VS Code extension and verify .vscode/settings.json is configured.

Issue: Git hooks not running

Solution:

bash
chmod +x .husky/pre-commit bun run prepare

Issue: Database migrations fail

Solution: Check drizzle.config.ts points to the correct schema file and DB_PATH is set.


End of Plan