singularity-forge/ARCHITECTURE.md
Mikael Hugo 6f877b61ab feat: harness scaffold, runtime pattern sync, and ARCHITECTURE injection
- Add harness/ directory to SF repo (specs/, evals/, graders/ with AGENTS.md)
  and seed harness/specs/bootstrap.md (agent-legibility verification)
- Extend agentic-docs-scaffold.ts: new repos get harness/ + ADR-TEMPLATE.md
  and just adr / just spec / just harness-spec recipes via justfile
- Sync SF_RUNTIME_PATTERNS (gitignore.ts canonical) → git-service.ts and
  worktree-manager.ts: add audit/, exec/, model-benchmarks/, reports/,
  notifications.jsonl, routing-history.json, self-feedback.jsonl, repo-meta.json,
  and milestone continue-marker patterns
- Inject ARCHITECTURE.md into system prompt via loadArchitectureBlock() in
  system-context.ts (capped at 8 000 chars, after KNOWLEDGE block)
- Write real ARCHITECTURE.md for this repo (system map, .sf/ layout, key flows)
- Add ADR-TEMPLATE.md to docs/design-docs/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 22:46:28 +02:00

4.5 KiB

Architecture

Purpose

Singularity Forge (SF) is an autonomous agent orchestration system. It runs long-horizon coding work as a state machine: milestones → slices → tasks. Each dispatch unit runs a fresh AI context, writes its output to disk, then terminates. A deterministic controller (not an LLM) reads disk state and decides what to dispatch next. The user is the end-gate — autonomous mode delivers work to human review, it does not merge to production unattended.

Codemap

Path Purpose
src/loader.ts Entry point — initializes resources, registers extension
src/headless.ts Non-interactive (headless) mode driver — exit codes 0/1/10/11/12
src/headless-events.ts Transcript event parsing and notification routing
src/extension-registry.ts Registers SF as a Pi coding-agent extension
src/resources/extensions/sf/ All SF extension source (TypeScript)
src/resources/extensions/sf/auto/ Autonomous workflow orchestrator (state machine, dispatch, planning)
src/resources/extensions/sf/bootstrap/ Context injection, system prompt assembly
src/resources/extensions/sf/prompts/ Prompt templates (.md, loaded by prompt-loader.ts)
src/resources/extensions/sf/tests/ Unit and integration tests
dist/resources/extensions/sf/ Compiled JS (rebuilt by npm run copy-resources)
~/.sf/agent/extensions/sf/ Installed copy (synced from dist on startup)
docs/ Durable product, design, plan, reliability, and security context
harness/ Specs (behavior contracts), evals (model-output tests), graders

State layout (.sf/)

.sf/ can be a symlink (external state, ~/.sf/projects/<hash>/) or a local directory (tracking-enabled per ADR-001).

Tracked in git (travel with the branch, per ADR-001):

.sf/milestones/     — roadmaps, plans, summaries, task plans
.sf/PROJECT.md      — project overview
.sf/DECISIONS.md    — architectural decisions register
.sf/REQUIREMENTS.md — requirements register
.sf/QUEUE.md        — work queue / backlog
.sf/KNOWLEDGE.md    — project-specific rules for agents

Gitignored (runtime/ephemeral — managed by ensureGitInfoExclude() in .git/info/exclude):

.sf/activity/       — JSONL session dumps
.sf/audit/          — audit trail entries
.sf/exec/           — in-flight execution state
.sf/forensics/      — crash forensics
.sf/journal/        — SF journal entries
.sf/model-benchmarks/ — model benchmark results
.sf/parallel/       — parallel dispatch coordination
.sf/reports/        — generated reports
.sf/runtime/        — dispatch records, timeout tracking
.sf/worktrees/      — git worktree working directories
.sf/auto.lock       — crash detection sentinel
.sf/metrics.json    — token/cost accumulator
.sf/sf.db*          — SQLite cache (rebuilt from markdown by importers)
.sf/STATE.md        — derived state cache
.sf/notifications.jsonl, .sf/routing-history.json, .sf/self-feedback.jsonl, .sf/repo-meta.json

The symlink case uses a blanket .sf gitignore pattern (git cannot traverse symlinks). The directory case uses granular patterns so planning artifacts remain trackable.

Key flows

Autonomous dispatch loop (src/resources/extensions/sf/auto/):

  1. deriveState() reads disk and produces a typed state snapshot
  2. Controller selects the next dispatch unit (research, plan, implement, verify, etc.)
  3. A fresh agent context is started with the task plan injected via system-context.ts
  4. Agent writes artifacts to disk, commits, exits
  5. Loop repeats until milestone completes or a gate fails

System context assembly (bootstrap/system-context.ts): PREFERENCES.mdKNOWLEDGE.mdARCHITECTURE.mdCODEBASE.md → code intelligence → memories → worktree/VCS blocks

Write gate (bootstrap/write-gate.ts): All file writes in autonomous mode pass through a gate. Protected files (CLAUDE.md, CODEBASE.md, certain spec files) require explicit override.

Invariants

  • The state machine (controller) is pure TypeScript — no LLM decisions in the dispatch loop itself.
  • Each dispatch unit runs in a fresh context — no cross-turn state accumulation.
  • Planning artifacts are tracked in git; runtime artifacts are never committed.
  • SF_RUNTIME_PATTERNS in gitignore.ts is the canonical source of truth for runtime paths. git-service.ts (RUNTIME_EXCLUSION_PATHS) and worktree-manager.ts (SKIP_* arrays) must stay synchronized with it.
  • The user is the end-gate. SF delivers for review, not to production.