Integration Guide — Epic-Awareness Across the Pipeline
Integration Guide — Epic-Awareness Across the Pipeline
Section titled “Integration Guide — Epic-Awareness Across the Pipeline”Epic Orchestration is woven into the existing forge pipeline as conditional,
membership-gated behavior. The thread through every stage is the same: resolve
the feature directory centrally, and if the feature has an epic back-pointer,
add epic behavior — otherwise do exactly what was done before.
This guide walks each touchpoint. The two shared building blocks live in
references/shared-conventions.md.
Shared Building Blocks
Section titled “Shared Building Blocks”Feature Directory Resolution
Section titled “Feature Directory Resolution”Every stage skill obtains the feature directory by calling
epic-manifest.py resolve <name> instead of hardcoding {specsDir}/{feature}/.
The returned directory ({resolvedFeatureDir}) is used everywhere the skill
previously wrote the flat path. Standalone features resolve to their flat path
unchanged; nested epic members resolve to {specsDir}/{epic}/{feature}/. On an
ambiguous/missing/unsafe name the skill stops and surfaces the helper’s finding
verbatim — it never falls back to a guessed path.
Epic Context Injection
Section titled “Epic Context Injection”After resolving, the skill checks the feature’s .pipeline-state.json for an
epic back-pointer.
- Absent → skip entirely (standalone behavior unchanged).
- Present → load exactly, and nothing transitive:
{specsDir}/{epic}/EPIC.md— narrative + per-feature Contracts sections.- This feature’s charter + its
exposes/consumesfrom the manifest (its contract obligations). - Direct completed dependencies only — for each
nameindependsOn, load that sibling’sPRD.mdandtech-spec.mdonly if it is complete for orchestration.
Transitive (indirect) dependencies are surfaced only through the direct deps’
Contracts sections in EPIC.md, never by loading their specs. This bounds
context size and keeps the injected set deterministic. The skill obtains the
contracts and live completion status of each dependency in one call via
render-status.
Branch Inheritance
Section titled “Branch Inheritance”An epic and all its members live on one branch. forge-0-epic invokes the
shared Branch Setup block with {scope} = epic and creates
{branchPrefix}{epic} (e.g. forge/auth-overhaul) when you start from the
default branch. Every member’s forge-1-prd then hits the same Branch Setup
block’s epic-member inheritance arm: because the resolved feature has an
epic back-pointer, the prompt is skipped and the member simply inherits the
current branch. The whole epic — manifest, EPIC.md, and every member’s specs
— therefore accumulates on that single branch and is reviewable as one unit.
This makes the branch you are on load-bearing at member-mint time. If you run a
member’s forge-1-prd from the default branch, or from a branch cut before
the epic-manifest commit, the epic’s subtree isn’t present, so the member’s
directory doesn’t resolve as nested — resolution returns not-found and forge
would otherwise mint it as a flat, detached standalone ({specsDir}/{feature}/)
with no epic back-pointer. That disjoint copy is a split-brain epic
(Issue #125). Two guards prevent it:
- Mint guard (
forge-1-prd). On anot-foundresolution, the skill runsforge-session.py discover-feature <name>— which now tags every candidate withepic/isEpicMember— and hard-stops if the name is a known epic member discoverable on another branch, pointing at that member’s home branch. An explicit--force-standaloneflag (distinct from--force) forks a standalone anyway when that is genuinely intended. - Base guard (
forge-1-prd..forge-4-backlog). Even when a member does resolve nested, the Epic-Member Base Guard block runsforge-session.py check-epic-base, which emitswarn-detached-basewhen the epic’sepic-manifest.jsonis absent on the current branch (a base that predates or lacks the manifest). The stage stops with a home-branch pointer;--forceoverrides. Both guards are a no-op for standalone features.
To recover an epic that already split, see
docs/recovery-detached-epic-member.md (a scripted “adopt into epic” command is
tracked as a follow-up).
Stage-by-Stage
Section titled “Stage-by-Stage”forge-0-epic — creation & edit (new stage)
Section titled “forge-0-epic — creation & edit (new stage)”skills/forge-0-epic/SKILL.md handles both modes in one skill:
- Creation (no manifest yet): an AskUserQuestion-driven decomposition
interview produces the manifest +
EPIC.md+ one charter per feature (short scope + contract obligations only — no full PRDs). Member subdirectories are created empty, each with a.pipeline-state.jsoncarrying theepicback-pointer, so the navigator and resolver can see them. - Edit (manifest exists): add / remove / reorder features and change deps via the helper’s atomic mutators, each re-validated for acyclicity, with a warning when a change affects in-flight or completed features.
After creation and after each edit, the git-commit-after-stage protocol commits
{specsDir}/{epic}/ (manifest + EPIC.md + member state) atomically.
forge-1-prd / forge-2-tech / forge-3-specs — context injection
Section titled “forge-1-prd / forge-2-tech / forge-3-specs — context injection”All three resolve the directory centrally and inject epic context (above) before authoring:
- forge-1-prd: inject before the interview.
- forge-2-tech: inject after reading the PRD; add epic paths to the
forge-researcherdispatch; widen the cross-feature glob to also match depth-2 ({specsDir}/*/*/tech-spec.md). - forge-3-specs: inject after reading PRD + tech-spec; thread the relevant
EPIC.mdsections and direct-dep tech-specs into eachforge-spec-writerprompt; widen the spec glob to depth-2.
Glob scoping: the widened depth-2 globs are constrained to feature-shaped
directories (those containing a sibling .pipeline-state.json), so they never
match non-feature subtrees that happen to hold matching filenames (e.g.
tests/fixtures/.../tech-spec.md, a numbered file under .verification/).
forge-4-backlog — backlog path composition
Section titled “forge-4-backlog — backlog path composition”Resolves the directory centrally. With backlogDir unset (default), the
backlog lives at {resolvedFeatureDir}/backlog.json — unchanged for flat and
nested features. With backlogDir configured, forge-4 composes a per-feature
subpath {backlogDir}/{feature}/ so each epic member’s backlog stays
independent (a bare shared backlogDir would collide across members). The loop
runner (rauf) itself is unchanged.
forge-5-loop — dependency gate + handoff
Section titled “forge-5-loop — dependency gate + handoff”Two epic-only additions bracket the existing loop:
- Dependency gate (new Step 1b-epic, before the runner version gate): if the
feature is an epic member, read the manifest, compute unmet deps via the
completion rule, and if any are unmet,
AskUserQuestion-warn with the list and require explicit confirmation to proceed. No back-pointer → gate skips. - Handoff (new Step 6, after pipeline state is written
complete): runrender-status, announce completion, offer to runforge-verifyimpl on the just-finished feature (recommended, skippable), then present the actionable next feature(s) viaAskUserQuestion— offering to author the chosen one’s PRD if absent. Selection is serial when several are unblocked; there is no autonomous chaining. The completion write and anyupdatedAtbump are committed via the git-commit-after-stage protocol.
forge-6-docs — epic-level doc offer
Section titled “forge-6-docs — epic-level doc offer”After the per-feature completeness check, if the feature is an epic member and
all members are complete, offer to synthesize an epic-level architecture
document at {docsDir}/{epic}/ in addition to per-feature docs, sourced from
EPIC.md, the per-feature docs, and the manifest contracts. Per-feature
behavior is unchanged. (For a standalone feature — like epic-orchestration
itself — this offer never fires.)
forge navigator — dashboard & discovery
Section titled “forge navigator — dashboard & discovery”- Named-epic argument → epic dashboard rendered from
render-status(graph, per-feature stage/status, blocked vs actionable, next command). - No-arg discovery → 2-tier listing: epics (with a
complete/totalrollup) above standalone features. Epic directories are recognized by the presence ofepic-manifest.json; their nested.pipeline-state.jsonfiles are attributed to the epic, not listed as standalone. - Lifecycle verbs (
pause/resume/abandon) extend to epics. Pausing or abandoning an epic does not silently mutate member features’ own states — the relationship is surfaced explicitly.
forge-verify — epic mode
Section titled “forge-verify — epic mode”A new epic mode loads the manifest + EPIC.md + each member
.pipeline-state.json, runs CHECK-E01..E08 via a single forge-verifier, writes
{specsDir}/{epic}/.verification/VERIFY-epic-{date}.md, and records
stages.forge-verify-epic. Checks: valid manifest schema (E01), acyclic graph
(E02), no dangling dependsOn (E03), charter coverage (E04), non-empty
exposes/consumes per feature (E05), EPIC.md-vs-manifest contract drift for
completed features (E06), back-pointer ↔ manifest consistency (E07), global name
uniqueness (E08). E01/E02/E03/E08 delegate to epic-manifest.py validate;
E04/E05/E06/E07 are verifier judgment.
forge-fix
Section titled “forge-fix”Resolves the directory centrally; otherwise unchanged.
The Loop Runner (rauf) Is Untouched
Section titled “The Loop Runner (rauf) Is Untouched”Backlogs remain per-feature and independent; dependencies are resolved only at feature granularity, before the loop launches. No rauf change, no backlog-schema change. This is what keeps epic support purely additive at the execution layer.
End-to-End Walkthrough
Section titled “End-to-End Walkthrough”/feature-forge:forge-0-epic auth-overhaul → interview → manifest + EPIC.md + charters + empty member dirs (committed)
/feature-forge:forge-1-prd config-store # no deps → actionable immediately/feature-forge:forge-2-tech config-store # epic context injected each stage…/feature-forge:forge-5-loop config-store → completion handoff: offers impl-verify, identifies `token-service` as newly actionable, offers to author its PRD
/feature-forge:forge token-service # blocked earlier, now actionable → forge-5-loop token-service shows NO dependency warning (config-store done)
/feature-forge:forge # dashboard: 2/4 complete, next command
# Meanwhile, a standalone feature elsewhere in specs/ behaves exactly as before —# no epic context, no gate, no handoff.