The Hoijof Process is a structured, documentation-first software development methodology for AI-assisted projects driven from a terminal agent (e.g. Claude Code CLI). Its goal is to deliver complex, multi-phase work systematically — with high test coverage, transparent decisions, and a state that survives any single context window.
One sentence: treat the filesystem as the agent's long-term memory and the context window as RAM — and manage the boundary between them deliberately.
What this process does not promise: it does not "eliminate hallucinations." Grounding the agent in good, current documentation measurably reduces context drift and confident-wrong work. It does not replace human judgment, and stale docs are worse than no docs — which is why reconciliation (§5) is a first-class step, not an afterthought.
- Genesis (Phase 0): Bootstrap the project, choose a Stack Profile (
STACK.md), and generate global agent rules (CLAUDE.md). - Check the Roadmap: Read the current
phaseX-roadmap.md"Current Status" + Goal to find the next priority. - Design (@Architect): Write the "What" and "Why" (
pX-feature-design.md) before any code. Get explicit userAPPROVED. - Implement (@TDD-Builder): Strict red→green→refactor, task by task. Verify the red. Commit atomically.
- Get unstuck (Stuck-Loop Protocol): On a repeating failure, STOP, run a structured-debugging pass, write
DEBUG.md, escalate only if it's a spec/architecture question. - Reconcile & close out (@Reviewer): Run the real test suite +
git log, reconcile the roadmap against reality, distill durable facts intoARCHITECTURE.md, prep the next roadmap. Run @Reviewer in an independent context (subagent or fresh session) so it isn't grading its own homework. - Manage context: Let native auto-compaction work by default. Use a deliberate fresh context at phase boundaries; re-prime from
ARCHITECTURE.md→ roadmap → next plan.
The process is stack-agnostic. Everything stack-specific lives in STACK.md and can be swapped without touching the rest.
/
├── CLAUDE.md # Global agent rules (process + pointer to STACK.md)
├── STACK.md # Swappable stack profile: tooling, commands, conventions
├── ARCHITECTURE.md # Distilled, lossy, living architecture (the "warm" memory tier)
└── /plans
├── /Phase0
│ └── genesis.md # Bootstrap commands for the chosen stack
├── /Phase1
│ ├── phase1-roadmap.md # Live plan: status, tasks, deps, memory (hot tier)
│ ├── p1.2-feature-design.md # @Architect output (the "What"/"Why")
│ ├── p1.2-feature-exec.md # @TDD-Builder execution plan (the "How")
│ └── phase1-final-status.md # @Reviewer close-out + reconciliation report
└── /archive
└── phase1-milestones.md # Cold tier: completed milestone detail, paged out
| File | Tier | Purpose |
|---|---|---|
CLAUDE.md |
always loaded | Global rules, the process, syntax. Points to STACK.md. |
STACK.md |
always loaded | The only stack-coupled file: install/test/lint/build commands, framework conventions. |
ARCHITECTURE.md |
warm | Distilled system architecture. Lossy by design. The thing the agent re-reads forever. |
phaseX-roadmap.md |
hot | The live plan for the active phase. Loaded on every re-prime. |
/archive/* |
cold | Completed milestone detail + old memory. Not loaded by default; referenced on demand. |
Before Phase 1, initialize the project deliberately.
- Pick a Stack Profile (
STACK.md). This is the only place stack choices live. It records the exact commands the agent must use:
# Stack Profile
- Language/Runtime: <e.g. TypeScript / Node 22>
- Framework: <e.g. Next.js App Router>
- Test (unit): <command, e.g. `pnpm vitest run`>
- Test (e2e): <command, e.g. `pnpm playwright test`>
- Lint/format: <command>
- Build: <command>
- Conventions: <framework-specific rules the agent must follow>Swapping stacks (Python service, Rust CLI, data pipeline) means rewriting this file only. The process below is unchanged.
- Blueprint (
plans/Phase0/genesis.md): the scaffolding commands for the chosen stack. - Generate
CLAUDE.md****: the agent's first action. It codifies this process, points toSTACK.mdfor all commands, and never hardcodes stack commands inline (so they have one source of truth).
Work is organized into themed Phases. Each phase has one phaseX-roadmap.md in the format below. The roadmap is the hot memory tier: it's what the agent reads first after any context reset, so it must always reflect reality (see §5, Reconciliation).
# Phase X — Title & Subtitle
Status: NOT STARTED | IN PROGRESS | COMPLETE
## Current Status (YYYY-MM-DD)
Short snapshot: what's done, what's in progress, what's next. This is the
single most-read paragraph in the whole project — keep it accurate and tight.
## Goal
Concise statement of the phase objective and focus areas.
## Tasks
(Grouped by domain/category, NOT by abstract P1/P2 priority tiers —
categories map to how work actually flows.)
### Category Name (e.g. Design System, Infrastructure, Auth)
- [x] P1.1: Task title — DONE
- [ ] P1.2: Task title
- [ ] P1.3: Task title ⟶ POSTPONED to Phase 2
### Backlog & Moonshots
- [ ] B1: Future idea, not committed to this phase
---
## Milestone Details
(Only ACTIVE and recently-completed tasks live here. When a task has been
done and stable for a while, move its detail block to /archive and leave a
one-line pointer. This bounds the file — see "Tiered Memory" below.)
### P1.2: Task title — <status>
- **Goal:** one line — what this achieves.
- Implementation notes / key technical decisions.
- **Key files:** `path/to/file`, `path/to/other`
- **Depends on:** P1.1 (or "Nothing")
- **Complexity:** Low | Medium | High | Very High
- **Verification:** how we know it works (the test/command that proves it).
---
## Dependency Graph
(Text diagram of relationships and parallel tracks.)Auth: P1.1 ── P1.2
Infrastructure: P1.3
**Critical path:** P1.1 → P1.2 (reason)
**Parallel tracks:** (1) Auth: P1.1, P1.2 (2) Infra: P1.3 — independent, parallelizable
---
## Recommended Implementation Order
**Wave 1:** P1.1, P1.3 (independent — can run as parallel subagents/worktrees)
**Wave 2:** P1.2 (depends on P1.1)
---
## Key Architecture Notes
1. Numbered, durable decisions + rationale. Candidates for promotion to ARCHITECTURE.md.
## Memory (windowed, append-only)
- Append-only WITHIN a phase, using absolute dates (YYYY-MM-DD).
- This is the "hot" running log. On phase close-out, distill the durable
facts into ARCHITECTURE.md and archive the rest. The log does not grow
across all phases forever — it is reset/archived per phase.
- Category grouping, not priority tiers. Group by domain. Maps to how work flows and to parallel tracks.
- Stable, globally-unique, never-renumbered IDs. Use
P<phase>.<n>(e.g.P1.2,P2.7). Once assigned, an ID is permanent — never reused, never renumbered — so cross-references never rot. Postponed work keeps its ID and moves phase in a note. - Milestone Details cover active + recent only. Completed-and-stable detail blocks get archived (cold tier), not deleted, with a one-line pointer left behind. This is the fix for v2's unbounded roadmap growth.
- Every milestone has a
Verificationline. Not a raw test count — the command or test that proves the task works. (See "On metrics" below.)
v2 tracked cumulative test counts ("1929 total"). v3 does not elevate test count to a tracked KPI: it measures the wrong thing (says nothing about branch coverage or test quality) and, once it's a target, it gets gamed (Goodhart). Track critical-path coverage instead — "the auth flow, payment path, and data-write path each have a failing-then-passing test." A test-count trend is fine as a rough health signal; it is never a goal.
Documentation consumes the same scarce resource — context — that the process is trying to protect. So memory is tiered, and only the hot tier is loaded by default:
- Hot —
phaseX-roadmap.md****: the live plan + per-phase Memory log. Loaded on every re-prime. Kept tight; active tasks only. - Warm —
ARCHITECTURE.md****: the distilled, intentionally lossy system summary. This is the "rolling summary." It is rewritten (not appended) at each phase close-out to absorb the durable facts and forget the ephemeral ones. This resolves v2's contradiction between "append-only" and "rolling summary" — the log appends within a phase; the architecture doc rolls across phases. - Cold —
/archive****: completed milestone detail and superseded memory. Preserved for history, not loaded by default, fetched only when a specific past decision is in question.
Rule of thumb: if re-priming the agent from hot+warm tiers costs more than a small fraction of the context window, the hot/warm tiers have grown too large — distill and archive.
Three personas keep planning, building, and judging distinct. v3's change from v2: a persona's real value is its context boundary, not its label. A label inside one conversation lets design reasoning bleed into implementation and lets the reviewer rationalize the code it just wrote.
| Persona | Job | Context boundary |
|---|---|---|
| @Architect | The "What" & "Why": data models, contracts, test strategy. Forbidden to write implementation code. | Main session — it's collaborative with you and ends at the APPROVED gate. |
| @TDD-Builder | The "How": execute the approved plan via strict TDD. | Main session — needs continuity across the red/green loop. |
| @Reviewer | Audit, reconcile docs vs. reality, close out. | Independent context — a dispatched subagent or a fresh session. Never the same context that wrote the code. |
Before code, produce pX-feature-design.md: data models, API contracts, testing strategy, open questions. Gate: proceed only on an explicit Status: APPROVED from the user. For genuinely trivial changes (one-liners, copy fixes), the design doc may be a single paragraph — scale the ceremony to the risk, don't skip the gate.
When the dependency graph shows independent tracks (Wave 1 above), dispatch them as parallel subagents, and use git worktrees when they touch files concurrently. The roadmap's tracks/waves exist precisely to make this safe.
Once APPROVED, @TDD-Builder works the pX-feature-exec.md plan task by task:
- Red: write the failing test.
- Verify the red in terminal output. (Do not skip — this is what catches tests that pass for the wrong reason or never run.)
- Green: write the minimum implementation to pass.
- Verify the green by running the suite.
- Refactor with the suite green.
- Atomic commit:
feat(p1.2): add auth toast(one logical change per commit).
v2 stopped after 3 consecutive failures and asked the user for architectural clarification. v3 fixes the trigger and the response:
Trigger — stop when any of these is true (3 consecutive failures is the hard backstop, not the only signal):
- the same hypothesis class has now failed twice (you're repeating yourself), or
- the diff is growing without the error changing (blast radius expanding, no progress), or
- 3 consecutive red runs (backstop).
Response — do NOT keep coding. Run a structured-debugging pass first:
- Reproduce the failure in the smallest possible case.
- Read the actual error — the real message and stack, not your assumption about it.
- List 2–3 competing hypotheses for the root cause.
- Run the cheapest test that discriminates between them.
- Write findings to a temporary
DEBUG.md(externalize the reasoning; it's an artifact for you or for the human).
Escalate to the human only if the debugging pass concludes the blocker is a spec or architecture ambiguity. Most stuck-loops are mundane (a wrong mock, an async race, a stale build, a bad fixture) — resolve those yourself and continue. Don't assume the spec is wrong just because you're stuck.
When a milestone or phase completes, @Reviewer takes over in an independent context and does four things — reconciliation first, because a roadmap that lies is worse than no roadmap:
- Reconcile docs vs. reality (the v3 addition). Run the real test suite and read
git log. Confirm every[x] DONEtask is actually done, every "Key file" exists, and the "Current Status" paragraph is true. Flag and fix any drift before anything else. - Audit. Technical debt, edge-case coverage, anything that passed tests but is fragile.
- Write
phaseX-final-status.mdincluding the reconciliation result (what drifted, what was corrected). - Distill into
ARCHITECTURE.md****. Rewrite (don't append) the warm tier so a future phase understands the core data flows. Archive completed milestone detail to the cold tier. Seed the nextphaseX-roadmap.md.