Branch Outcomes & Wiki

Two metadata subsystems that label your work without cluttering it: branch outcomes attach a one-sentence capability statement to each branch, and the wiki generator auto-builds per-subsystem reference articles from the code graph.

Branch outcomes

A branch's outcome is the user-facing capability the branch delivers — distinct from the commit subjects or task titles inside it. Where a commit log says "fix null deref in exporter" and "add CSV column," the outcome says what the user gets:

Allow users to export reports as CSV

Each outcome is one short sentence (aimed at ≤ 15 words — these are tree-row labels, not paragraphs), stored per (project, branch) with the author (draftedBy) and an updatedAt timestamp. The UI uses it to label branches in the git panel without forcing that prose into commit messages.

Outcomes are persisted in the branch_metadata table as an idempotent upsert keyed by (project_id, branch_name) — re-setting an outcome overwrites the prior value. Branch names keep their / (the project's task/<id> convention) because the branch name travels in the request body/query, never as a URL path segment.

Drafting vs. setting

Drafting and setting are deliberately separate steps. Drafting fetches the originating task's title and description plus a prompt hint; the calling agent rewrites that into the one-sentence capability. Setting persists the final text. The draft endpoint never writes — it only gathers context, and it treats task fields strictly as untrusted data.

Branch-outcome MCP tools

ToolPurpose
draft_branch_outcomeFetch the originating task's title/description + prompt hint so the agent can compose a one-sentence outcome. Read-only.
set_branch_outcomeUpsert the final outcome text for a (project, branch) pair.
get_branch_outcomesList all stored outcomes for a project.

Branch-outcome REST endpoints

All under /api/branch-metadata on http://localhost:5050. The projectId must be a registered project; arbitrary ids are rejected to prevent phantom rows and cross-project leakage.

# Draft context for an outcome (read-only)
GET /api/branch-metadata/{projectId}/draft-context?branch=task/c0ce8037

# Persist an outcome (branchName in the body so "/" round-trips)
POST /api/branch-metadata/{projectId}/outcome
{
  "branchName": "task/c0ce8037",
  "outcome": "Allow users to export reports as CSV",
  "draftedBy": "agent"
}

# List all outcomes for a project
GET /api/branch-metadata/{projectId}/outcomes

A successful set returns the saved row:

{
  "projectId": "proj-123",
  "branchName": "task/c0ce8037",
  "outcome": "Allow users to export reports as CSV",
  "draftedBy": "agent",
  "updatedAt": "2026-06-27T10:30:00Z"
}

Saving an outcome fires a BranchOutcomeUpdated event, which prompts the HUD git renderer to refresh its branch labels.

Wiki generator

The wiki generator builds per-subsystem markdown articles from the code graph, the code digests, and parsed controller routes — then writes them under .claude/wiki/. A subsystem is a coherent module that spans several files (e.g. "Messaging" = Message.cs + MessageBroker.cs + MessagingController.cs + the chat panel).

The point is targeted session-start context: load a ~200-token index.md at the start of a session and fetch a specific ~500-token subsystem article only when you touch that area, instead of re-deriving structure from raw source every time.

Each generated article aggregates:

  • Key files with line counts and a one-line purpose pulled from the file's code digest.
  • Key classes & methods (public/internal) with file:line references from the code graph.
  • Routes parsed from controller [HttpGet]/[Route] attributes.
  • External callers — symbols outside the subsystem that call into it, derived from the call graph.
  • Gotchas aggregated from the root files' code digests.

Prerequisite: an indexed code graph

Articles are assembled from the code graph and code digests, so index the project first (see the Code Graph guide). Without an index, articles still render from the manifest but key classes, methods, routes, and callers will be sparse.

Wiki MCP tools

ToolPurpose
generate_wikiRegenerate all articles for a project (or one, when a subsystem id is given). Writes .claude/wiki/*.md + index.md.
list_wiki_articlesList the articles currently on disk for a project (id, name, description, tags, generated timestamp) without regenerating.
get_wiki_articleFetch the markdown body of a single article by id.

Wiki REST endpoints

All under /api/wiki on http://localhost:5050. The projectRoot must resolve to an existing directory; subsystem ids are restricted to ^[A-Za-z0-9_-]{1,64}$ so they round-trip safely through the filesystem.

# Regenerate every article (omit subsystemId for "all")
POST /api/wiki/generate
{
  "projectRoot": "H:\\DevLaptop\\...\\MultiTerminal",
  "projectId": "proj-123",
  "subsystemId": null
}

# List articles on disk
GET /api/wiki/articles?projectRoot=H%3A%5CDevLaptop%5C...%5CMultiTerminal

# Fetch one article's markdown
GET /api/wiki/articles/{id}?projectRoot=H%3A%5CDevLaptop%5C...%5CMultiTerminal

A full generate returns a per-article summary:

{
  "success": true,
  "count": 12,
  "articles": [
    {
      "id": "messaging",
      "name": "Messaging",
      "classCount": 4,
      "methodCount": 18,
      "routeCount": 6,
      "fileCount": 4,
      "markdownBytes": 5120
    }
  ]
}

The wiki manifest

The generator is driven by .claude/wiki/wiki-manifest.json, which declares each subsystem: its id, display name, description, tags, root files, and an optional controller glob. The manifest is a trusted, in-repo artifact (authored by maintainers, not request bodies). If no manifest exists, generate_wiki reports that none was found rather than guessing the project's structure.

Generated articles and the index.md are plain markdown — diff-able, committable, and meant to be read by agents at session start.