{
  "schemaVersion": "1.0",
  "id": "pr-architecture-diff",
  "title": "Visual architecture diffs in pull requests",
  "slug": "pr-architecture-diff",
  "diagramFamily": "architecture",
  "goal": "Surface architectural impact during PR review by deriving the architecture state from the PR's diff, comparing it to the architecture on main, and posting the visual diff back to the PR - so reviewers see what services and dependencies a PR adds or removes without re-reading the change set.",
  "inputs": [
    "PR diff (list of changed files in the PR)",
    "Repository checkout at the PR head AND at the merge-base",
    "Existing Zindex scene id storing the architecture on main (long-lived, never recreated)",
    "Zindex API key with scene-write scope"
  ],
  "outputs": [
    "Two transient revisions - 'before' (= main's revision) and 'after' (= main + PR changes)",
    "Rendered before-after diagrams as separate SVGs (or a single side-by-side composite)",
    "Structural diff JSON listing added / removed / changed elements",
    "PR comment with the diff summary + rendered diagrams, idempotently re-posted as the PR evolves"
  ],
  "mcpTools": [
    "dsp_get_scene",
    "dsp_apply_ops",
    "dsp_diff_scene",
    "dsp_render_scene"
  ],
  "httpEndpoints": [
    "GET /v1/scenes/:id",
    "POST /v1/scenes/:id/applyOps",
    "GET /v1/scenes/:id/diff",
    "POST /v1/scenes/:id/render"
  ],
  "steps": [
    {
      "id": "fetch_main_scene",
      "label": "Fetch the architecture scene on main",
      "description": "Get the persisted scene representing the architecture on the default branch. Note the current revision number - that's the 'before' baseline.",
      "mcp": "dsp_get_scene",
      "http": {
        "method": "GET",
        "path": "/v1/scenes/${SCENE_ID}"
      }
    },
    {
      "id": "scan_pr_head",
      "label": "Scan the repository at the PR head",
      "description": "Check out the PR branch. Run the same component-detection logic that the living-architecture workflow uses, but against the PR's tree. Emit the (component, edge) tuple that represents what the architecture *would be* if this PR merged.",
      "mcp": null,
      "http": null
    },
    {
      "id": "compute_after_ops",
      "label": "Compute the operation batch that would update main",
      "description": "Diff the PR-head scan against the persisted main scene. Emit a hypothetical applyOps batch (createNode for new services, deleteElement for removed ones, createEdge / deleteElement for changed dependencies). Do NOT apply this batch to the production scene - this is a what-if comparison, not a merge.",
      "mcp": null,
      "http": null
    },
    {
      "id": "apply_ops_to_branch_revision",
      "label": "Apply ops to a transient branch revision",
      "description": "Apply the computed ops to the persisted scene with a revision message tagged with the PR number - `pr-1234: hypothetical post-merge state`. This creates a new revision; you'll diff against it and then leave it. (Optional: tag the revision with the PR id so you can clean up old branch revisions on PR close.)",
      "mcp": "dsp_apply_ops",
      "http": {
        "method": "POST",
        "path": "/v1/scenes/${SCENE_ID}/ops"
      }
    },
    {
      "id": "diff_revisions",
      "label": "Diff main's revision against the PR's hypothetical revision",
      "description": "Call dsp_diff_scene with from = main's revision, to = the PR's branch revision. The output describes precisely what the PR adds and removes from the architecture - far more reviewable than re-reading source files.",
      "mcp": "dsp_diff_scene",
      "http": {
        "method": "GET",
        "path": "/v1/scenes/${SCENE_ID}/diff?from=${MAIN_REVISION}&to=${PR_REVISION}"
      }
    },
    {
      "id": "render_before_after",
      "label": "Render before-and-after diagrams",
      "description": "Render the scene at main's revision (before) and at the PR's revision (after). Both watermarks include the revision number so the reviewer can verify exactly which state each diagram represents.",
      "mcp": "dsp_render_scene",
      "http": {
        "method": "POST",
        "path": "/v1/scenes/${SCENE_ID}/render"
      }
    },
    {
      "id": "post_pr_comment",
      "label": "Post the architectural diff to the PR",
      "description": "Comment on the PR with both rendered SVGs (or a side-by-side composite) and the structural diff summary. Re-post idempotently as new commits land on the PR - overwrite the previous comment rather than appending. On PR merge, the next scheduled living-architecture run will pick up the merged change and the branch revision is no longer authoritative.",
      "mcp": null,
      "http": null
    },
    {
      "id": "cleanup_branch_revision",
      "label": "Optional: roll back the branch revision on PR close",
      "description": "If the PR closes without merging, the branch revision in the persisted scene no longer represents reality. Either delete the revision (if revision deletion is supported in your environment) or rely on the next scheduled main-branch sync to overwrite it. Most teams just leave branch revisions in place - the revision history then doubles as a record of architectural proposals, accepted and rejected.",
      "mcp": null,
      "http": null
    }
  ]
}