1. Disambiguation homeBranch vs mainBranch — Pipeline Merge Target vs Canonical State
  2. Killed decision Module Maps — Deprecated (Killed in Synth Rework)
  3. Meta reasoning Context Budget Management — Keeping Coordinators Lean
  4. Inclusion criteria Codebase Map Abstraction Level — What Belongs and What Doesn't
  5. Context-flow architecture Discovery Chain: Task Context Flow Through the Pipeline
Pattern: Disambiguation — two concepts that sound alike and keep getting confused

homeBranch vs mainBranch — Pipeline Merge Target vs Canonical State

Summary

Two distinct branch concepts: mainBranch (config) is canonical codebase truth used for sync/exploration/freshness. homeBranch (pipeline state) is where a specific pipeline's work merges back to, set at seal time. In worktrees, homeBranch depends on whether currentBranch matches the worktree's configured home: if yes → mainBranch (standard flow), if no → worktreeConfig.homeBranch (sub-branch merges back to worktree home).

How it works

Set at seal time: /pipe-seal stores homeBranch in pipeline state. The value depends on context.

Detection is deterministic — no user prompt. Seal compares currentBranch to worktreeConfig.homeBranch. If getWorktreeConfig fails with not-found (new worktree, no config yet), default to config.mainBranch. On any other infrastructure failure, log a warning and default to config.mainBranch.

Phase fallback rules: Recoverable phases (git-prepare, branch-create, need-fixture-update, pr-create) fall back to config.mainBranch with a stderr warning. Irreversible phases (merge-to-parent) require homeBranch and fail hard if missing — a silent fallback could merge+push to the wrong branch.

Uses homeBranch (pipeline state)Uses mainBranch (config)
git-prepare (rebase target)sync (pull canonical)
branch-create (branch from)check-map-cursor (freshness)
need-fixture-update (diff base)codemap-update (cursor)
pr-create (PR base)exploration baseline
merge-to-parent (merge target)
branch-cleanup (return to)

Worktree branch deletion gotcha

In worktrees, git branch -d may fail with "not fully merged" because: (1) fetchOrigin() with fetch.prune=true removes the stale tracking ref, (2) without an upstream, -d falls back to checking against HEAD, (3) HEAD is homeBranch, not mainBranch where the PR merged. Fix: when -d fails, verify the branch is merged into origin/mainBranch via git merge-base --is-ancestor, then force-delete with -D. Only escalates after cryptographic verification.

Rationale

The original design assumed all work merges to mainBranch. This broke when versioning introduced hotfix branches with tag-based deploys: a client-reported issue grew from hotfix into feature needing the full pipeline, but the pipeline couldn't target the hotfix branch. The fix separates "where is canonical truth" (mainBranch) from "where does THIS work go" (homeBranch). Worktrees were initially handled with a blanket homeBranch = currentBranch, which caused PRs from worktrees to target the worktree branch instead of main. Fixed by comparing currentBranch to the worktree's configured home.

Alternatives considered

Source files

Relationships

Pattern: Killed decision — things we built, shipped, and removed, with reasons intact

Module Maps — Deprecated (Killed in Synth Rework)

Summary

Module maps (per-module detail stored on MCP) were killed during the synth rework. Too expensive to produce (~15min synthesis), agents ignored them in practice. Per-module navigation detail now lives in project agents, which agents already load.

Why it was killed

Two independent failures made module maps net-negative.

Production cost was prohibitive. Module map synthesis took ~15 minutes per pipeline run. The synthesise-project-knowledge agent would scan files, run bash commands, and build per-module detail — costing more than the broad codebase exploration it was supposed to replace.

Consumers ignored them. Despite explicit instructions to call getModuleMap(moduleName) before reading files, sub-agents skipped the call and explored the codebase directly. Observed across multiple production runs. The instruction was a soft suggestion agents could skip — unlike project agent files which agents read because they're injected into their own prompt.

Injection was impossible. The alternative — injecting module maps into sub-agent prompts — was rejected because the orchestrator would need to load them first. For 5-7 chunks, repeating the same module map data would stuff ~30% of the orchestrator's context.

How per-module detail works now

Per-module navigation detail lives in project agents (config.agents.{type}.file). Sub-agents already read their own agent file — this is the one instruction they reliably follow. Loaded once per sub-agent (not repeated across chunks), already in the right context, zero orchestrator context cost.

Rationale

Module maps failed on both sides of the value equation: production was too expensive (~15min synthesis per run, agent going off-script reading files and running bash) and consumption was zero (agents ignored the instruction to call getModuleMap and explored files directly). Project agents solve the same problem without these costs. The simplification also removes a maintenance burden — one less MCP data type to keep current.

Alternatives considered

Relationships

Pattern: Meta reasoning — how we think about our own scaling constraints

Context Budget Management — Keeping Coordinators Lean

Summary

Pipeline coordinators (pipe orchestrator, implement skill) must minimise context accumulation. Strategies: delegate context loading to sub-agents, use atomic MCP updates, skip redundant verification, enforce minimal returns, drop results after status check.

Why it exists

The /pipe orchestrator runs inline — all phase dispatches, results, state updates, and narration accumulate in a single context window. For a 7-chunk implement phase, this easily reaches 50k+ tokens of coordinator overhead before review and test phases even start. An early production incident showed two 18min+ stalls caused by context bloat from verbose sub-agent returns.

The six principles

  1. Sub-agents own their context loading. Don't read files or MCP data into the coordinator just to copy into sub-agent prompts. Tell sub-agents WHERE to load. Coordinator pays ~50 tokens per path reference; sub-agent pays full cost in its own window.
  2. Atomic MCP updates over full-state writes. Chunk completion tracked by artifact existence — saveChunkArtifact + presence check, not savePipelineProgress.
  3. Trust sub-agent results. After a chunk completes, check Task status. Don't re-fetch from MCP or spot-check files. The test phase catches real issues.
  4. Minimal logging. One line per chunk: "Chunk N (name) done." Don't restate the full summary.
  5. Enforce minimal returns from all sub-agents. Every prompt ends with a minimal-return template. Implement: status, chunk name, file count. Light review: status, findings counts. Heavy review: JSON severity summary. Etc.
  6. Drop results after status check. Orchestrator discards sub-agent responses after extracting state propagation data. Prevents accumulation across 15+ phases.

Key gotchas

Rationale

Context limits are the primary scaling constraint for pipeline execution. The early production incident demonstrated the failure mode: verbose sub-agent returns accumulated across phases, causing two 18min+ stalls. Every optimisation that shifts cost from coordinator to sub-agents directly extends capacity. The lean-coordinator approach preserves user visibility while managing the budget.

Alternatives considered

Source files

Pattern: Inclusion criteria — what is allowed to live in persistent state, and what isn't

Codebase Map Abstraction Level — What Belongs and What Doesn't

Summary

The codebase map is a navigation aid for planning sessions, not a feature documentation system. Content must pass the "any feature" test: would a developer working on a completely different module need this? Excludes specific values, bug-fix details, task-specific gotchas, and feature internals. Bias toward advancing cursor without content changes on incremental updates.

Why it exists

The codebase map was drifting toward feature-level documentation. An incremental update on a real project (28 commits stale) ran for 12 minutes, consumed 96k tokens, and saved details like buffer size changes and the reasons behind them. This is the same trajectory that killed module maps — too detailed, too expensive, and ultimately ignored by the agents consuming them.

The root cause was twofold: (1) the code-explorer agent is designed for deep feature analysis and its default output guidance overrode the synthesis skill's lighter prompts; (2) the incremental path's behavioural-change filter was too loose — "update if they reveal new patterns" let almost anything through.

How it works

The "any feature" test. Applied at every content decision point: would a developer working on a COMPLETELY DIFFERENT module need to know this? If no, it doesn't belong in the map.

Explicit exclusion list:

Incremental bias: default is "advance cursor only" — content updates are the exception, reserved for genuinely structural changes (new modules, new shared base classes, new cross-cutting conventions).

Code-explorer guardrails. When launched for synthesis, code-explorer agents receive an "Abstraction Level — MAP, NOT IMPLEMENTATION" block that overrides their default deep-dive guidance with good/bad examples.

Rationale

The codebase map's value is proportional to its signal-to-noise ratio, not its completeness. A 200-line map of module boundaries and cross-cutting patterns loads in seconds and informs every planning session. A 400-line map with buffer sizes, encoding details, and per-task gotchas costs more to maintain (12min/96k tokens for one incremental update) and creates noise that obscures the structural knowledge. The "any feature" test naturally filters to the right abstraction level — project-wide architecture survives, feature internals don't.

Alternatives considered

Source files

Relationships

Pattern: Context-flow architecture — how data survives across pipeline and session boundaries

Discovery Chain: Task Context Flow Through the Pipeline

Summary

How task-specific knowledge (discoveries, plan, findings) flows from planning through sealing to implementation via MCP persistence. Discoveries are saved during planning, the plan is sealed to MCP, and both are loaded by implement, heavy-review, and e2e-gen phases — enabling context survival across /clear boundaries and auto-compaction.

Why it exists

Claude Code conversations are ephemeral — /clear wipes them, auto-compaction summarises them lossily, and session boundaries end them. But implementation phases need the technical context gathered during planning: which files to modify, which patterns to follow, which gotchas to avoid.

MCP acts as the persistence bridge. Saving discoveries and plan to MCP before the context boundary lets downstream phases load exactly what they need without re-exploring.

How it works

Planning (/breakdown):

  1. Code-explorer sub-agents explore the codebase → findings returned to main context.
  2. save-code-discoveries persists findings to MCP via saveDiscoveries(taskId, content, parentTaskId?).
  3. Parent discoveries auto-resolve: getDiscoveries(taskId) returns both task and parent content.
  4. Discoveries are purely technical — decisions stay in conversation for task-enrich to mine.

Sealing (/pipe-seal):

  1. save-plan (shell) transfers plan file → MCP at zero LLM cost.
  2. task-enrich mines conversation → pushes business context to tracker.
  3. Pipeline state created on MCP with task ID, branch, pipeline type.

Implementation (/pipe):

  1. getTaskContext(taskId) loads discoveries, findings, and chunk artifacts in one call.
  2. getPlan(taskId) or getPlanChunk loads the plan.
  3. Implement sub-agents receive task ID only — they self-load context from MCP.
  4. Sub-agents do NOT load getCodebaseMap() — the plan already distils map knowledge.
  5. Heavy-review receives the branch diff plus MCP findings for classification.

Recovery:

Key gotchas

Rationale

The discovery chain exists because the three-phase lifecycle creates deliberate context boundaries (/clear) that would otherwise destroy all planning knowledge. MCP is the structured persistence layer — each data type is saved at the natural point in the workflow where it's produced, and loaded on-demand by consumers. The self-loading pattern prevents the orchestrator from becoming a context bottleneck. Plan transfer always uses shell to keep plan content out of LLM context.

Alternatives considered

Source files

Relationships

Closing

This is 5 of ~42 entries currently in the Pipeforge knowledge base. The full KB is queryable via MCP (queryKnowledge, listKnowledgeConcepts, getKnowledgeEntry). Entries are authored during actual development — design conversations, post-incident reviews, KB audits — and follow the schema enforced by the pipeforge:kb-writer skill.