diff --git a/docs/superpowers/plans/2026-03-24-v2-fix-gaps.md b/docs/superpowers/plans/2026-03-24-v2-fix-gaps.md
new file mode 100644
index 0000000..6fd2c5a
--- /dev/null
+++ b/docs/superpowers/plans/2026-03-24-v2-fix-gaps.md
@@ -0,0 +1,847 @@
+# V2 Gap Fix Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Fix 7 gaps (P0+P1) so the graph visualization shows grouped layout, real status colors, working document edges, rich detail panel, legend, back button, and edit shortcut.
+
+**Architecture:** Backend changes add `parent` field to `GraphNode`, status mapping from `FileStatusEntry`, and document nodes with proper edge resolution. Frontend changes replace the single-center D3 layout with per-group forceX/forceY, add compound document view toggle, enrich the detail panel with API calls, and add legend/back-button UI.
+
+**Tech Stack:** Python 3.12 / FastAPI / dataclasses (backend), Vue 3 / TypeScript / D3.js v7 / Pinia (frontend), pytest (backend tests)
+
+**Spec:** `docs/superpowers/specs/2026-03-24-v2-fix-gaps-design.md`
+
+---
+
+## File Structure
+
+### Files to Modify
+| File | Responsibility | Tasks |
+|------|---------------|-------|
+| `backend/app/modules/graph/domain/entities.py` | GraphNode dataclass — add `parent` field | 1 |
+| `backend/app/modules/graph/application/services.py` | build_panorama — status mapping, document nodes, edge fix | 2, 3 |
+| `backend/app/modules/graph/interfaces/http/router.py` | Pass `design_dir` to build_panorama | 4 |
+| `backend/tests/test_graph_service.py` | Update existing tests + add new tests | 1, 2, 3, 4 |
+| `frontend/src/shared/types/api.ts` | Add `parent` to GraphNode interface | 5 |
+| `frontend/src/modules/graph/components/GraphPanorama.vue` | Group layout, compound layout, toggle, back button | 6, 8 |
+| `frontend/src/modules/graph/components/GraphDetail.vue` | Rich detail panel, edit button | 7 |
+
+### Files to Create
+| File | Responsibility | Tasks |
+|------|---------------|-------|
+| `frontend/src/modules/graph/components/GraphLegend.vue` | Legend component | 9 |
+
+---
+
+### Task 1: Domain — Add `parent` field to GraphNode
+
+**Files:**
+- Modify: `backend/app/modules/graph/domain/entities.py:4-10`
+- Test: `backend/tests/test_graph_service.py`
+
+- [ ] **Step 1: Write the failing test**
+
+Add to `backend/tests/test_graph_service.py`:
+
+```python
+def test_graph_node_has_parent_field(graph_service, scan_result):
+ view = graph_service.build_panorama(scan_result)
+ # All nodes should have a parent attribute (None for most, doc_id for some)
+ for node in view.nodes:
+ assert hasattr(node, 'parent')
+```
+
+- [ ] **Step 2: Run test to verify it fails**
+
+Run: `cd /workspace/arch-design-agent-skill-dashboard/backend && python -m pytest tests/test_graph_service.py::test_graph_node_has_parent_field -v`
+Expected: FAIL — `GraphNode` has no `parent` attribute
+
+- [ ] **Step 3: Add `parent` field to GraphNode**
+
+Edit `backend/app/modules/graph/domain/entities.py` — add to the GraphNode dataclass:
+
+```python
+@dataclass
+class GraphNode:
+ id: str
+ type: str # capability, module, entity, runtime_component, document
+ label: str
+ status: str # FileStatus value or "unknown"
+ group_id: str
+ parent: str | None = None # doc_id of containing document, if any
+```
+
+- [ ] **Step 4: Run test to verify it passes**
+
+Run: `cd /workspace/arch-design-agent-skill-dashboard/backend && python -m pytest tests/test_graph_service.py::test_graph_node_has_parent_field -v`
+Expected: PASS
+
+- [ ] **Step 5: Run all existing graph tests to verify no regression**
+
+Run: `cd /workspace/arch-design-agent-skill-dashboard/backend && python -m pytest tests/test_graph_service.py -v`
+Expected: All 9 tests PASS (existing 8 + new 1)
+
+- [ ] **Step 6: Commit**
+
+```bash
+git add backend/app/modules/graph/domain/entities.py backend/tests/test_graph_service.py
+git commit -m "feat(graph): add parent field to GraphNode domain entity"
+```
+
+---
+
+### Task 2: Application — Status mapping in build_panorama (GAP-B1)
+
+**Files:**
+- Modify: `backend/app/modules/graph/application/services.py:22-77`
+- Test: `backend/tests/test_graph_service.py`
+
+- [ ] **Step 1: Add design_dir fixture and write the failing tests**
+
+First, add a `design_dir` fixture to `backend/tests/test_graph_service.py` (will be used by all subsequent tests):
+
+```python
+@pytest.fixture
+def design_dir():
+ return "/workspace/arch-design-agent-skill-dashboard/design"
+```
+
+Then add the new tests (note: all new tests from this point forward take `design_dir` and pass it to `build_panorama`):
+
+```python
+def test_panorama_nodes_have_real_status(graph_service, scan_result, design_dir):
+ view = graph_service.build_panorama(scan_result, design_dir=design_dir)
+ statuses = {n.status for n in view.nodes}
+ # At least some nodes should NOT be "unknown" since we have real file statuses
+ assert statuses != {"unknown"}, "All nodes still have status='unknown' — status mapping not working"
+
+
+def test_panorama_status_values_are_valid(graph_service, scan_result, design_dir):
+ view = graph_service.build_panorama(scan_result, design_dir=design_dir)
+ valid_statuses = {"ok", "sparse", "missing", "template-residue", "placeholder-heavy", "unknown"}
+ for node in view.nodes:
+ assert node.status in valid_statuses, f"Node {node.id} has invalid status '{node.status}'"
+```
+
+- [ ] **Step 2: Run tests to verify they fail**
+
+Run: `cd /workspace/arch-design-agent-skill-dashboard/backend && python -m pytest tests/test_graph_service.py::test_panorama_nodes_have_real_status tests/test_graph_service.py::test_panorama_status_values_are_valid -v`
+Expected: `test_panorama_nodes_have_real_status` FAILS (all statuses are "unknown")
+
+- [ ] **Step 3: Implement status mapping**
+
+Edit `backend/app/modules/graph/application/services.py`. Add the `_SOURCE_FILES` constant after `_GROUPS` and modify `build_panorama` to build the file status map:
+
+```python
+_SOURCE_FILES: dict[str, str] = {
+ "capability": "business-architecture/02-capability-map.csv",
+ "module": "application-architecture/02-modules.csv",
+ "entity": "data-architecture/01-entities.csv",
+ "runtime_component": "technology-architecture/01-runtime-components.csv",
+}
+```
+
+At the top of `build_panorama()`, add `design_dir` parameter with default so existing tests still work:
+```python
+def build_panorama(self, scan_result: ScanResult, design_dir: str = "") -> GraphView:
+ # Build file path -> status mapping
+ file_status_map: dict[str, str] = {
+ fs.path: fs.status.value for fs in scan_result.file_statuses
+ }
+```
+
+Replace each `status="unknown"` with:
+```python
+status=file_status_map.get(_SOURCE_FILES.get("capability", ""), "unknown"), # for caps
+status=file_status_map.get(_SOURCE_FILES.get("module", ""), "unknown"), # for modules
+status=file_status_map.get(_SOURCE_FILES.get("entity", ""), "unknown"), # for entities
+status=file_status_map.get(_SOURCE_FILES.get("runtime_component", ""), "unknown"), # for runtime
+```
+
+- [ ] **Step 4: Run tests to verify they pass**
+
+Run: `cd /workspace/arch-design-agent-skill-dashboard/backend && python -m pytest tests/test_graph_service.py -v`
+Expected: All tests PASS including the two new status tests
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add backend/app/modules/graph/application/services.py backend/tests/test_graph_service.py
+git commit -m "feat(graph): map node status from FileStatus via source_file (GAP-B1)"
+```
+
+---
+
+### Task 3: Application — Document nodes + doc→doc edges (GAP-B3)
+
+**Files:**
+- Modify: `backend/app/modules/graph/application/services.py`
+- Test: `backend/tests/test_graph_service.py`
+
+- [ ] **Step 1: Write the failing tests**
+
+Add to `backend/tests/test_graph_service.py`:
+
+```python
+def test_panorama_has_document_nodes(graph_service, scan_result, design_dir):
+ view = graph_service.build_panorama(scan_result, design_dir=design_dir)
+ doc_nodes = [n for n in view.nodes if n.type == "document"]
+ assert len(doc_nodes) > 0, "No document nodes found"
+ assert all(n.group_id == "cross-layer" for n in doc_nodes)
+
+
+def test_panorama_document_edges(graph_service, scan_result, design_dir):
+ view = graph_service.build_panorama(scan_result, design_dir=design_dir)
+ doc_edges = [e for e in view.edges if e.relation == "documents"]
+ assert len(doc_edges) > 0, "No document edges found"
+
+
+def test_panorama_capability_nodes_have_parent(graph_service, scan_result, design_dir):
+ view = graph_service.build_panorama(scan_result, design_dir=design_dir)
+ cap_nodes = [n for n in view.nodes if n.type == "capability"]
+ # Capability nodes should have parent pointing to a document
+ nodes_with_parent = [n for n in cap_nodes if n.parent is not None]
+ assert len(nodes_with_parent) > 0, "No capability nodes have a parent document"
+```
+
+- [ ] **Step 2: Run tests to verify they fail**
+
+Run: `cd /workspace/arch-design-agent-skill-dashboard/backend && python -m pytest tests/test_graph_service.py::test_panorama_has_document_nodes tests/test_graph_service.py::test_panorama_document_edges tests/test_graph_service.py::test_panorama_capability_nodes_have_parent -v`
+Expected: All 3 FAIL
+
+- [ ] **Step 3: Implement document nodes and edge resolution**
+
+Edit `backend/app/modules/graph/application/services.py`.
+
+Add path helper functions before the class:
+
+```python
+from pathlib import PurePosixPath
+
+
+def _to_rel_path(doc_file_path: str, design_dir: str) -> str:
+ """Convert absolute doc.file_path to design-dir-relative path."""
+ try:
+ return str(PurePosixPath(doc_file_path).relative_to(design_dir))
+ except ValueError:
+ return doc_file_path
+
+
+def _resolve_ref_path(ref_path: str, doc_rel_path: str) -> str:
+ """Resolve a relative upstream/downstream ref against the doc's directory."""
+ doc_dir = str(PurePosixPath(doc_rel_path).parent)
+ resolved = str(PurePosixPath(doc_dir) / ref_path)
+ parts: list[str] = []
+ for part in PurePosixPath(resolved).parts:
+ if part == '..':
+ if parts:
+ parts.pop()
+ else:
+ parts.append(part)
+ return str(PurePosixPath(*parts)) if parts else ""
+```
+
+**Important ordering:** Build `file_to_doc` mapping BEFORE Steps 2-5 so entity nodes can get their `parent`. Restructure `build_panorama` to:
+
+1. Build `file_status_map` (already done in Task 2)
+2. Build `file_to_doc` from `scan_result.design_documents` + create document nodes
+3. Then create entity nodes (Steps 2-5) with `parent` set via `file_to_doc`
+4. Then create edges (Steps 6-9) with fixed Step 9
+
+Step 5.5 (now moved before Steps 2-5):
+```python
+ # Build document node mapping first (needed for parent refs)
+ file_to_doc: dict[str, str] = {}
+ for doc in scan_result.design_documents:
+ doc_rel = _to_rel_path(doc.file_path, design_dir)
+ file_to_doc[doc_rel] = doc.doc_id
+ nodes.append(GraphNode(
+ id=doc.doc_id,
+ type="document",
+ label=doc.title or doc.doc_id,
+ status=file_status_map.get(doc_rel, "unknown"),
+ group_id="cross-layer",
+ ))
+ node_ids.add(doc.doc_id)
+```
+
+In each entity creation (Steps 2-5), add parent:
+```python
+ # e.g. for capability:
+ parent_doc_id = file_to_doc.get(_SOURCE_FILES.get("capability"))
+ nodes.append(GraphNode(
+ id=node_id, type="capability", label=cap.name,
+ status=file_status_map.get(_SOURCE_FILES.get("capability", ""), "unknown"),
+ group_id="business",
+ parent=parent_doc_id,
+ ))
+```
+
+Replace Step 9 with path resolution + deduplication:
+```python
+ # Step 9: DesignDocument.downstream → doc-to-doc edges (deduplicated)
+ path_to_doc: dict[str, str] = {}
+ doc_rel_paths: dict[str, str] = {}
+ for doc in scan_result.design_documents:
+ doc_rel = _to_rel_path(doc.file_path, design_dir)
+ path_to_doc[doc_rel] = doc.doc_id
+ doc_rel_paths[doc.doc_id] = doc_rel
+
+ seen_edges: set[tuple[str, str]] = set()
+ for doc in scan_result.design_documents:
+ doc_rel = doc_rel_paths[doc.doc_id]
+ for down_path in doc.downstream:
+ resolved = _resolve_ref_path(down_path, doc_rel)
+ down_doc_id = path_to_doc.get(resolved)
+ if down_doc_id and down_doc_id in node_ids:
+ edge_key = (doc.doc_id, down_doc_id)
+ if edge_key not in seen_edges:
+ seen_edges.add(edge_key)
+ edges.append(GraphEdge(
+ source=doc.doc_id, target=down_doc_id,
+ relation="documents",
+ ))
+```
+
+- [ ] **Step 4: Run new tests to verify they pass**
+
+Run: `cd /workspace/arch-design-agent-skill-dashboard/backend && python -m pytest tests/test_graph_service.py::test_panorama_has_document_nodes tests/test_graph_service.py::test_panorama_document_edges tests/test_graph_service.py::test_panorama_capability_nodes_have_parent -v`
+Expected: All 3 PASS
+
+- [ ] **Step 5: Run ALL graph tests to check no regression**
+
+Run: `cd /workspace/arch-design-agent-skill-dashboard/backend && python -m pytest tests/test_graph_service.py tests/test_api_graph.py -v`
+Expected: All tests PASS
+
+- [ ] **Step 6: Commit**
+
+```bash
+git add backend/app/modules/graph/application/services.py backend/tests/test_graph_service.py
+git commit -m "feat(graph): add document nodes, parent refs, and fixed doc edges (GAP-B3)"
+```
+
+---
+
+### Task 4: Interfaces — Pass design_dir from router to build_panorama
+
+**Files:**
+- Modify: `backend/app/modules/graph/interfaces/http/router.py:40-56`
+- Test: `backend/tests/test_api_graph.py`
+
+- [ ] **Step 1: Update the router to pass design_dir**
+
+Edit `backend/app/modules/graph/interfaces/http/router.py`:
+
+In `get_graph()`:
+```python
+@router.get("")
+def get_graph(project_id: str):
+ """Build and return the full panorama graph for a project."""
+ project = _project_service.get_project(project_id)
+ scan_result = _get_or_trigger_scan(project_id)
+ view = _graph_service.build_panorama(scan_result, design_dir=project.design_dir)
+ return asdict(view)
+```
+
+In `get_neighbors()`:
+```python
+@router.get("/nodes/{node_id}/neighbors")
+def get_neighbors(project_id: str, node_id: str):
+ """Return the subgraph of neighbors for a given node."""
+ project = _project_service.get_project(project_id)
+ scan_result = _get_or_trigger_scan(project_id)
+ view = _graph_service.build_panorama(scan_result, design_dir=project.design_dir)
+ neighbors = _graph_service.get_neighbors(view, node_id)
+ return asdict(neighbors)
+```
+
+- [ ] **Step 2: Update test_graph_service.py to pass design_dir**
+
+Add a `design_dir` fixture and update all `build_panorama` calls:
+
+```python
+@pytest.fixture
+def design_dir():
+ return "/workspace/arch-design-agent-skill-dashboard/design"
+```
+
+Update all test function signatures to include `design_dir` parameter. Update all calls from:
+```python
+view = graph_service.build_panorama(scan_result)
+```
+to:
+```python
+view = graph_service.build_panorama(scan_result, design_dir=design_dir)
+```
+
+- [ ] **Step 3: Run ALL backend tests**
+
+Run: `cd /workspace/arch-design-agent-skill-dashboard/backend && python -m pytest tests/ -v`
+Expected: All tests PASS
+
+- [ ] **Step 4: Commit**
+
+```bash
+git add backend/app/modules/graph/interfaces/http/router.py backend/tests/test_graph_service.py
+git commit -m "feat(graph): pass design_dir from router to build_panorama"
+```
+
+---
+
+### Task 5: Frontend types — Add `parent` to GraphNode interface
+
+**Files:**
+- Modify: `frontend/src/shared/types/api.ts:31-37`
+
+- [ ] **Step 1: Add parent field**
+
+Edit `frontend/src/shared/types/api.ts`:
+
+```typescript
+export interface GraphNode {
+ id: string
+ type: string
+ label: string
+ status: string
+ group_id: string
+ parent: string | null
+}
+```
+
+- [ ] **Step 2: Run type check**
+
+Run: `cd /workspace/arch-design-agent-skill-dashboard/frontend && npx vue-tsc --noEmit`
+Expected: No errors
+
+- [ ] **Step 3: Commit**
+
+```bash
+git add frontend/src/shared/types/api.ts
+git commit -m "feat(graph): add parent field to GraphNode TypeScript interface"
+```
+
+---
+
+### Task 6: Frontend — Group-partitioned layout + compound layout + toggle (GAP-F1)
+
+**Files:**
+- Modify: `frontend/src/modules/graph/components/GraphPanorama.vue`
+
+This is the largest task. The entire `drawGraph()` function needs rewriting.
+
+- [ ] **Step 1: Add state variables and update constants**
+
+Add after existing refs in `
+
+
+```
+
+- [ ] **Step 2: Import GraphLegend in GraphPanorama.vue**
+
+Add import:
+```typescript
+import GraphLegend from './GraphLegend.vue'
+```
+
+Add to template (inside `.graph-panorama` div, after `