4 min
devops
February 8, 2026

Forge Review: Prioritized Fix Plan & Recommendations

Forge — Prioritized Fix Plan & Strategic Recommendations

Based on a full code review of ~5,500 lines across 30+ source files, 104 passing tests, and 5 TypeScript errors. This article provides an actionable fix order and strategic guidance.


Immediate Fixes (Week 1)

These are blocking issues that must be resolved before any real-world usage.

1. Eliminate Command Injection Vectors

Files: src/agents/planner.ts, src/agents/implementer.ts

ToolVulnerabilityFix
glob (planner)execAsync(\find . -name "${input.pattern}"`)`Use Bun.Glob API or Bun.spawn(['find', '.', '-name', pattern])
git_create_branch\git checkout -b ${branchName}``Bun.spawn(['git', 'checkout', '-b', branchName])
git_commit\git commit -m "${message}"``Bun.spawn(['git', 'commit', '-m', message])

Pattern: Replace all template-literal shell commands with array-argument Bun.spawn(). This prevents argument escaping attacks entirely.

2. Fix SQL Injection in Checkpoint Storage

File: src/orchestrator/checkpoint.ts:95-104

Replace string interpolation with parameterized queries:

typescript
// BEFORE (vulnerable) this.db.exec(`INSERT INTO checkpoints VALUES ('${cp.id}', '${cp.traceId}', ...)`); // AFTER (safe) this.db.prepare('INSERT INTO checkpoints VALUES (?, ?, ?, ?, ?)').run( cp.id, cp.traceId, cp.phase, JSON.stringify(cp.state), cp.timestamp.toISOString() );

3. Fix TypeScript Compilation Errors

File: src/safety/breakers.ts — 5 errors at lines 207, 336, 337, 366, 388

All are noUncheckedIndexedAccess issues. Fix with optional chaining or non-null assertions where the index is guaranteed.

4. Fix Sort Direction Bug

File: src/events/bus.ts:242

Change ORDER BY timestamp ASC to ORDER BY timestamp DESC in getLatestCheckpoint().


Short-Term Improvements (Weeks 2-3)

5. Wire CLI to Real Pipeline

File: src/cli/index.ts

Replace simulatePhase() calls with actual Pipeline execution:

typescript
// Replace lines 168-194 with: const { Pipeline } = await import('../orchestrator/pipeline.ts'); const pipeline = new Pipeline(task, generateTraceId(), { usePiAgentCore: options.usePiCore, llmConfig: config.llm, }); const result = await pipeline.run();

6. Consolidate Duplicate Types

  • Delete error classes from src/types/index.ts
  • Use src/core/errors.ts hierarchy everywhere
  • Split src/types/index.ts into domain-specific files

7. Unify EventBus Implementations

Create a factory that returns the appropriate implementation:

typescript
export function createEventBus(config: { persist: boolean; dbPath?: string }): EventBus { return config.persist ? new SqliteEventBus(config.dbPath) : new InMemoryEventBus(); }

8. Fix Config Merge Bug

File: src/core/config.ts:90

typescript
breakers: { ...defaults.safety.breakers, ...overrides.safety?.breakers }

9. Wire Deployer Events

File: src/agents/deployer.ts:666-668

typescript
private async emit(type: string, data: Record<string, unknown>): Promise<void> { await this.context.bus.emit({ traceId: this.traceId, source: 'deployer', type: `deployer.${type}`, payload: data, }); }

Medium-Term Architecture (Weeks 4-6)

10. Centralize Tool Execution

Migrate inline tools from all 5 agents to the ToolRegistry:

  1. Register all tools in src/tools/ with proper categories
  2. Agents request tools by name from registry
  3. Execute through a sandboxed runner with timeouts and resource limits
  4. Log all tool invocations to the event bus for audit

11. Replace better-sqlite3 with bun:sqlite

Per CLAUDE.md: prefer built-in bun:sqlite. This affects:

  • src/events/bus.ts
  • src/orchestrator/checkpoint.ts
  • src/memory/store.ts

12. Add Integration Tests

The 104 existing tests are all unit tests. Add:

  • Pipeline end-to-end test (plan → impl → review → test) with mock LLM
  • Bounce-back test (review rejects → impl → review approves)
  • Checkpoint save/resume round-trip
  • Beads pipeline with mock bd CLI

13. Improve Memory Retrieval

Replace keyword-based DefaultMemoryStore.search() with:

  • TF-IDF scoring as a minimum improvement
  • Embedding-based similarity when an LLM with embedding support is configured

Strategic Recommendations

Architecture

  1. Adopt the pi-agent-core path as primary — the PiAgentAdapter is more robust than the BaseAgent loop, with better event bridging and cost tracking. Consider deprecating the BaseAgent path after the adapter is battle-tested.

  2. Make the ToolRegistry the single source of truth — every tool should be registered, versioned, and executed through the registry. This enables sandboxing, rate limiting, and audit trails.

  3. Add structured LLM output — agents currently parse free-text LLM responses with fragile regex. Use JSON mode or function calling to get structured outputs.

Security

  1. Audit all Bun.spawn() and exec() calls — there are ~15 places where tools shell out. Each must use array arguments, not template strings.

  2. Add input validation at tool boundaries — even though Zod schemas exist, the actual tool execution functions don't always validate before shelling out.

Developer Experience

  1. Add a --json output mode to CLI — enables piping forge output to other tools.

  2. Standardize on ULID for all IDs — already a dependency, just not used consistently.

  3. Add a forge doctor command — checks for LLM API keys, bd CLI availability, SQLite, and other prerequisites.


Effort Estimates

PriorityItemsEstimated Effort
Immediate (Week 1)Injection fixes, TS errors, sort bug1-2 days
Short-term (Weeks 2-3)CLI wiring, type consolidation, EventBus unification3-5 days
Medium-term (Weeks 4-6)Tool centralization, bun:sqlite migration, integration tests1-2 weeks
Strategicpi-agent-core primary, structured output, DX improvementsOngoing

Test & Quality Snapshot

MetricValue
Tests104 passing / 0 failing
Test files6
Test runtime670ms
TypeScript errors5 (all in breakers.ts)
Source files~30
Total LoC~5,500
Dependencies14 runtime + 4 dev