--- name: aep-map description: >- Decomposes a product into a system map, layered story graph, and agent topology. Use after /aep-envision, or for "break this down" and "plan the stories". --- # Map Decompose the Context Document into a system map (modules + interfaces), a layered story graph (work items + dependencies + execution slices), and an agent topology (roles + handoff contracts). This is the hardest phase — a wrong module boundary means dozens of agents produce incompatible code. **Where this fits:** ``` /aep-envision → /aep-map → /aep-scaffold → [ /aep-design → /aep-launch → /aep-build → /aep-wrap ] → /aep-reflect ▲ you are here ``` **Session:** Main, interactive with user (System Map requires human review) **Input:** Product definition from `product/index.yaml` (split mode) or `product-context.yaml` (v1 mode) **Output:** `product-context.yaml` updated with `architecture`, `stories`, `waves`, `topology`, `layer_gates`, `cost`, and `changelog` sections **YAML Schema:** See `templates/product-context-schema.yaml` for the full structure and field definitions. --- ## Before Starting Probe which mode the product context is in: ```bash ls product/index.yaml 2>/dev/null && echo "SPLIT MODE" || echo "V1 MODE" cat product-context.yaml ``` Mode semantics are canonical in `references/file-resolution.md`. Map reads the product definition (opportunity, personas, `product.*`) from `product/index.yaml` (split) or `product-context.yaml` (v1); it reads operational state from, and writes all output to, `product-context.yaml`. If product definition is missing (no `product` section in either file), run `/aep-envision` first. --- ## Step 1: System Map (Single Agent + Human Review) Produce a **System Map** (see `templates/system-map.md`) from the Context Document: - **Modules:** Major components with clear responsibility boundaries. Each module's "does not" definition is as important as its "does" definition. Set each module's `kind` (`ui` | `backend` | `shared`) — `ui` modules render user-facing surfaces, which drives the UI-facing story trigger used by `/aep-model`, dispatch, and launch. - **Interface contracts:** For every module-to-module connection, define the exact API surface — endpoints, data shapes, error contracts. These are not documentation; they are executable specifications enforced by contract tests. - **Data flow:** How information moves through the system for each user journey in the MVP contract. - **Third-party boundaries:** External service integration points with failure modes. Write the system map to the `architecture` section of `product-context.yaml`. When the System Map exposes multi-step protocols, multiple state machines, distinct failure classes, or trust boundaries crossing module lines, read `references/technical-spec-triggers.md` and suggest producing a Technical Specification before decomposition. ### Human Review Gate **The user must review and approve the System Map.** Architecture decisions have the highest error cost in the entire pipeline. Present the map and explicitly ask for approval. If the user wants changes, revise and re-present; proceed to story decomposition only after the user explicitly approves. **Postcondition:** the `architecture` section is written to `product-context.yaml` and the user has approved the System Map. --- ## Step 2: Story Decomposition (Parallel Agents) Once the System Map is confirmed, decompose into stories: - **One Decomposition Agent per module:** Receives Context Document + System Map + its module definition. Produces stories tagged with layer (0 = walking skeleton, 1+ = enrichment layers). - **One Integration Story Agent:** Looks at module connections in the System Map. Produces stories that glue modules together — the end-to-end flows crossing module boundaries. These are especially critical at Layer 0. Sharpen a vague or overlapping decomposition before adding agents — more agents amplify unclear decomposition rather than resolve it. Each story follows the **Story Spec** format (see `templates/story-spec.md`) and must include: - What changes when complete (observable behavior) - Acceptance criteria automatable as tests - Layer assignment (0 = walking skeleton, 1+ = enrichment) - Module assignment - Dependency declarations - Interface obligations (if touching module boundaries) - Files likely affected (for conflict detection) - `business_value` (1-10, or null to derive from priority) - `compile_mode` (default `single_change`; use `grouped_change` for tightly coupled stories, `shared_enabler` for infrastructure) **All stories start with `status: pending`.** Story states follow the product-context schema; `/aep-dispatch` manages transitions during execution. ### Activity Mapping After decomposition agents produce their stories, map each story to a user activity from `product.activities` (and, in split mode, set `story.capability` to the owning `capabilities[]` id — this is how dispatch/launch later locate the story's Object Map; leave null in v1/single-journey, where the default capability is the project slug): - Stories that directly enable a user-facing capability get the activity they serve (e.g., "Create presigned upload URL" → `create-profile` because it enables the user to upload a selfie). - **Infrastructure/foundation stories that don't map to any specific user activity leave `activity` as null.** These are implementation enablers — they appear in the architecture view but not in the user journey story map, which shows the user's perspective. - Integration stories use the primary user activity they validate end-to-end. ### Walking Skeleton (Layer 0) **Layer 0 is the most important layer.** It is a horizontal slice across the activity backbone — the thinnest story from each user activity, strung together so a user can complete the crudest possible end-to-end journey from the Context Document's Layer 0 MVP Contract. > "Build a skeleton that can walk before building a perfect leg." Every activity in `product.activities` with `layer_introduced: 0` should have at least one Layer 0 story. Prove the end-to-end path works before going deep into any module — depth-first before the skeleton walks is the most expensive mistake in this workflow. **Postcondition:** every story is written with a layer, a module, and `status: pending`; each `layer_introduced: 0` activity has ≥1 Layer 0 story. --- ## Step 3: Dependency Resolution & Waves (Single Agent) A dedicated agent receives all stories and produces: - **Story Graph:** A directed acyclic graph organized by layer, showing dependencies and parallelism opportunities. - **Waves (Execution Slices):** Within each layer, group stories into waves that can be dispatched as a batch. A wave is a set of stories with no mutual dependencies that can run fully in parallel. (The YAML field is `stories[].slice`; the user-facing term is "wave.") - **Critical path per layer:** The longest dependency chain, determining minimum time to complete that layer. - **Layer gates:** The integration test definition that must pass before advancing to the next layer. Each gate also lists its **planned `journeys:`** (`skills/e2e-test/journeys/.md`, one per capability area; empty when `dogfood_target == none`) — `journeys:` is the plan, `evidence.journeys` records what actually ran. Who authors those journeys and when they execute is canonical in `/aep-e2e-skill-scaffolding` → `references/layer-gate-loop.md`; the `live_policy` that prices the cost-bearing live half sits in `skills/e2e-test/policy.md`, so when proposing milestone layers, name them so they can be listed there. Write all stories to the `stories` section of `product-context.yaml`. Also populate the `waves` section grouping stories by layer + wave. ### Outcome Contracts For each layer that has an `outcome_contract` defined (see `product.layers[].outcome_contract`), ensure the layer gate test definition aligns with the success metric. If no outcome contract exists for a layer, consider adding one — Jeff Patton emphasizes that layers should be anchored in outcomes, not just feature completeness. The outcome contract is evaluated by `/aep-reflect` after layer completion. It answers: "did this layer achieve what we hypothesized?" ### Telemetry Binding (observability) This is where the project **decides its telemetry sources** — metric-driven, then inventory. Bind every quantitative `success_metric` and any monitored `health_signals` to a source per `references/telemetry-ingestion.md` (§1.5 coverage rule; §1 Source config for the `metric_map`/`endpoint`/`token_env` binding). Write the result to `topology.routing.telemetry_sources` (+ `health_signals`). `/aep-reflect`, `/aep-watch`, and `/aep-autopilot` run `coverage_check()` against this before trusting any auto path; an incomplete binding **blocks auto**, it does not silently no-op. ### Capability Maps (multi-journey products) If `product/index.yaml` exists (created by `/aep-envision` for multi-journey products), also write per-capability `map.yaml` files: - `product/maps//map.yaml` — backbone activities, layers, story stubs for this capability - Story stubs in `map.yaml` are sketches; the full stories in `product-context.yaml` are the operational versions > **Split mode note:** In split mode, the capability map's `map.yaml` story stubs are narrative sketches. The full stories are written to `product-context.yaml`, and `product/index.yaml` is NOT modified by `/aep-map` (it only reads from it). This is additive — if no capability maps exist, skip this step. ### Alignment Layers (`.5` Layers) After defining each implementation layer, plan the `.5` alignment layers that pause execution to calibrate human intent. Review `calibration.plan` (or the quality dimensions each layer touches) and read `references/alignment-layers.md` — the canonical home for the `.5`-layer concept — for the heavy-vs-light dimension rules, the layer progression, and how an approved Object Map feeds the visual-design/ux-flow briefs. Heavy dimensions get a `.5` layer with `calibration_type`-tagged stories; light dimensions get a `/aep-calibrate` checkpoint before the next integer layer. ### Object Map Drafts (UI-facing capabilities) After stories are decomposed, produce a **draft** noun-first Object Map for each UI-facing capability (declared `object-model`, `visual-design`/`ux-flow`, or user-facing stories). This bridges the verb-first story map to the UI. Read `references/object-map-drafts.md` for the ORCA derivation and the draft/approved/stale rules, then write `product/object-model.yaml` and `product/maps//object-map.yaml` with **`status: draft`** — `/aep-model` owns approval. Skip entirely for pure-backend/CLI projects with no UI-facing capability. ### Feedback Loop Decomposition agents may discover module boundaries are wrong. They submit amendment proposals to the System Map. When amendments accumulate to 3+ items or any single amendment affects an interface contract, trigger an **Architecture Review** with the user before continuing. **Postcondition:** the `stories` and `waves` sections are written; each layer has a `layer_gates` entry (with planned `journeys:`); UI-facing capabilities each have a `status: draft` object-map. --- ## Step 4: Agent Topology Design Topology is a decomposition decision — it determines how `/aep-launch` configures workspaces and what context `/aep-build` agents receive, so it is defined before execution. Define the agent roles, handoff contracts, and routing rules using the **Agent Topology** template (see `templates/agent-topology.md`). Every agent-to-agent handoff is schema-defined, not free text — ambiguity compounds exponentially across parallel agents. ### Agent Role Definition For each role in the execution pipeline, define: - **Role name:** What this agent type is called (e.g., `implementer`, `contract-verifier`, `integration-tester`) - **Responsibility boundary:** What this agent does and does not do. Single-responsibility is the rule. - **Input contract:** The exact structure of the work object this agent receives. Schema-defined, not free text. - **Output contract:** The exact structure of the artifact this agent produces. Schema-defined. - **Context window composition:** What goes into this agent's context — which sections of the Context Document, which parts of the System Map, what dependency artifacts. Irrelevant context degrades performance. - **Cost budget:** Expected token usage and time per invocation. ### Handoff Contracts For every agent-to-agent transition: - **Trigger:** What event causes the handoff - **Payload:** What artifact is passed, in what schema - **Validation:** What checks run on the payload before the receiving agent starts ### Routing Rules - **Dispatch policy:** How stories are assigned from the ready queue - **Concurrency limit:** Maximum parallel agents (start conservative: 5-10) - **Conflict detection:** Stories modifying the same files go in different slices - **Retry routing:** Same agent retry (2x) → fresh agent with failure log (1x) → human escalation Write the topology to the `topology` section of `product-context.yaml`. Also initialize the `layer_gates` and `cost` sections. **Postcondition:** the `topology` section is written, and `layer_gates` and `cost` are initialized. --- ## Output ### Before Committing: Validate YAML Validate before committing (checklist in `references/yaml-guardrails.md`): ```bash npx js-yaml product-context.yaml > /dev/null && echo "YAML OK" ``` If this fails, fix the YAML per `references/yaml-guardrails.md` before committing. ### Commit Commit and push per `/aep-git-ref` "Control-Plane Commits": `git add product-context.yaml product/`, commit (`feat: add system map, story graph, and agent topology`), and push to `$BASE` (resolve `$BASE` per `/aep-git-ref` "Resolving `$BASE`"). **Sections written:** - `architecture` — system map (modules, interfaces, data flow) - `stories` — layered story graph with waves (all stories start `status: pending`) - `waves` — stories grouped by layer + wave for batch dispatch - `topology` — agent roles, handoff contracts, routing rules - `layer_gates` — integration test definitions per layer (aligned with outcome contracts if defined), each with its planned `journeys:` (an empty list when `dogfood_target == none`). Which gates spend live dogfood is priced by `policy.md` `live_policy`, not stored here. - `cost` — initial cost budgets and tracking structure - `changelog` — append an entry recording what was added Always append to the `changelog` section. **Postcondition:** `npx js-yaml` exits 0 and the commit lands on `$BASE`. --- ## For Iteration When updating the map (triggered by `/aep-reflect` or new requirements): 1. Read the existing product definition (`product/index.yaml` in split mode, `product-context.yaml` in v1 mode) and operational state from `product-context.yaml` 2. Identify what's changed — new modules, revised interfaces, new stories 3. Update affected sections (`architecture`, `stories`, `topology`) 4. If interface contracts changed → re-verify dependent stories 5. Append to the `changelog` section 6. Commit updated version --- ## Next Step Decomposition is complete. If no project exists yet: ``` /aep-scaffold ``` If the project has UI-facing capabilities, approve the Object Map drafts before dispatching UI stories: ``` /aep-model ``` `/aep-model` presents the draft Object Map for a short human review gate and flips it to `approved`. Then start executing stories: ``` /aep-dispatch ``` `/aep-dispatch` reads the story graph from `product-context.yaml` and moves stories through the state machine, routing each through `/aep-design → /aep-launch → /aep-build → /aep-wrap`.