docs: add sprint 36-40 plans and codehealth brief

This commit is contained in:
Bill
2026-02-17 20:37:54 -07:00
parent 3dd2ef2577
commit 19880d6cbc
6 changed files with 593 additions and 0 deletions

79
sprint36_plan.md Normal file
View File

@@ -0,0 +1,79 @@
# Sprint 36 Plan: MCP Expansion — Architect Tools + Project Config
## Context
Sprint 36 exposes the Sprint 32 Architect Intake pipeline as MCP tools.
MarkdownSpecParser, TaskitemGeneratorV2, and TaskitemConfidenceAmbiguity are
fully implemented in C++ headers but not yet wired as MCP tools. Fix that,
add the `instructions` field to MCP initialize, and introduce per-project config.
Primary goals:
1. Expose architect intake + taskitem generation as callable MCP tools
2. Make Claude auto-understand the editor via the initialize instructions field
3. Per-project .whetstone.json config with CWD auto-discovery
Steps continue from Step 613 (last completed: Sprint35OperationalReadiness.h).
---
## Phase 36a: Architect Intake MCP Tools (Steps 614618)
### Step 614: `whetstone_architect_intake` MCP Tool (12 tests)
Wire MarkdownSpecParser + RequirementNormalizationConflictDetector into a single
MCP tool call. Input: markdown spec string. Output: ParsedMarkdownSpec + conflict
signals + normalized requirements JSON.
### Step 615: `whetstone_generate_taskitems` MCP Tool (12 tests)
Wire TaskitemGeneratorV2 + TaskitemConfidenceAmbiguity. Input: normalized plan
JSON (from Step 614 output). Output: array of AnnotatedTaskitem with confidence,
ambiguityCount, escalate, reasons.
### Step 616: `whetstone_queue_ready` MCP Tool (12 tests)
Wire IntakeToQueueSimulationHarness. Input: array of AnnotatedTaskitem. Output:
{ready: bool, blockers: [...], readyCount, escalateCount, queueJson}.
### Step 617: MCP initialize — add `instructions` field (12 tests)
Add an `instructions` field to the MCP `initialize` response. Content: the text
from tools/claude/system_prompt.txt. This makes Claude auto-understand the editor
without needing a CLAUDE.md file. Test: initialize response includes instructions.
### Step 618: Phase 36a Integration (8 tests)
End-to-end: paste a markdown project spec → whetstone_architect_intake →
whetstone_generate_taskitems → whetstone_queue_ready → verified queue.
---
## Phase 36b: Per-Project Config + tools.json Sync (Steps 619623)
### Step 619: `.whetstone.json` per-project config schema (12 tests)
Config file: `{workspace, defaultLanguage, agentRole, mcpWorkspaceAlias}`.
MCP server reads this on startup if present in --workspace dir. Lets different
projects have different language defaults without restart.
### Step 620: Config auto-discovery (walk up from CWD) (12 tests)
If no `--workspace` flag: walk up from CWD until .whetstone.json found. This
means `cd myproject && whetstone_mcp` just works.
### Step 621: `whetstone_set_workspace` MCP tool (12 tests)
Runtime tool: switch active workspace + language without restarting the binary.
Input: {workspace, language}. Required for HiveMind use case where one daemon
serves multiple projects.
### Step 622: tools.json refresh — add all Sprint 32-35 tools (8 tests)
Update tools/claude/tools.json to include the new Sprint 36a tools plus any
Sprint 32-35 features that have MCP-appropriate interfaces (debug session,
workflow recorder, benchmark harness). Bump version to 2.0.
### Step 623: Sprint 36 Integration + Summary (8 tests)
Validate: fresh Claude Code session + Whetstone MCP → Claude receives instructions
in initialize → calls whetstone_architect_intake on a real spec → generates queue.
---
## Step & Test Summary
| Phase | Steps | Tests | Theme |
|-------|-------|-------|-------|
| 36a | 614618 | 56 | Architect intake MCP tools |
| 36b | 619623 | 56 | Per-project config + tools.json refresh |
| **Total** | **614623** | **~112** | 10 steps |

83
sprint37_plan.md Normal file
View File

@@ -0,0 +1,83 @@
# Sprint 37 Plan: In-Editor Agent Chat Panel
## Context
Sprint 37 builds the "full window in the editor" agent UX — the plug-and-play
experience for non-technical users. Agent chat embedded directly in the ImGui
editor with live tool call visualization, mutation preview, and accept/reject
controls. No terminal required.
Primary goals:
1. Embedded chat panel with message history and streaming responses
2. Live tool call visualization and AST mutation preview
3. Human-in-the-loop accept/reject for every agent mutation
4. Context auto-injection and session persistence
---
## Phase 37a: Chat Window Core (Steps 624628)
### Step 624: Agent Chat Panel model (12 tests)
New panel: message history (scrollable), text input (multi-line), send button.
Messages: role (user/assistant/tool), content, timestamp. State lives in
AgentChatState sub-struct. Renders via ImGui but shares no state with EditorState
globals.
### Step 625: Tool call visualization (12 tests)
When Claude calls a Whetstone tool, render it inline in the chat as a collapsible
block: `[TOOL: whetstone_mutate] ▶ setProperty fn1.name → "newName"`. Show
input/output JSON. Lets user see exactly what the agent is doing.
### Step 626: AST mutation preview (12 tests)
Before applying any agent-requested mutation: show a side-by-side diff of the
generated code before vs after. User sees the change before it's committed.
Requires generating code from both old and new AST.
### Step 627: Inline accept/reject controls (12 tests)
Under each mutation preview: [Accept] [Reject] [Modify]. Accept applies the
mutation. Reject discards it and posts "rejected: <reason>" back to the agent.
Modify opens the mutation in an editable JSON view. Human-in-the-loop at every
agent action.
### Step 628: Phase 37a Integration (8 tests)
Full chat flow: user types spec → agent calls whetstone_generate_code → mutation
preview shown → user accepts → AST updated → code view refreshes.
---
## Phase 37b: Context + Persistence (Steps 629633)
### Step 629: Project context auto-injection (12 tests)
On chat start, auto-inject a context block into the system prompt: active file
name, language, AST node count, open annotations count, workspace path. The agent
starts every conversation knowing where it is.
### Step 630: Chat session persistence (12 tests)
Save/restore chat sessions per project file. Format: JSON alongside .whetstone.json.
Sessions indexed by timestamp. Reload on next open. User can continue a previous
conversation without losing context.
### Step 631: Background task slots (parallel agent work) (12 tests)
Run up to N agent tasks in parallel (N from project config). Each slot has its
own chat thread. Slots shown as tabs in the chat panel. Lets user kick off
"generate the test suite" while also asking "explain this function."
### Step 632: Agent task status overlay (12 tests)
Status bar item: `[Agent: 2 running, 1 pending]`. Click to open task panel.
Each task shows: description, elapsed time, tool calls made, current step.
Cancel button per task.
### Step 633: Sprint 37 Integration + Summary (8 tests)
Demo scenario: open hivemind project → chat panel opens → paste BS-S1-01 task
description → agent generates drone/nexus code → user accepts mutations →
code panel shows generated Rust/C++ → chat session saved.
---
## Step & Test Summary
| Phase | Steps | Tests | Theme |
|-------|-------|-------|-------|
| 37a | 624628 | 56 | Chat window core + mutation preview |
| 37b | 629633 | 56 | Context injection + session persistence |
| **Total** | **624633** | **~112** | 10 steps |

89
sprint38_plan.md Normal file
View File

@@ -0,0 +1,89 @@
# Sprint 38 Plan: HiveMind Build Support — Drone Generators + Shared Types
## Context
Sprint 38 makes Whetstone the tool that builds HiveMind. Everything is C++20
with CMake + vcpkg — the same toolchain as the editor itself. The drone binary
shares job schema types with Whetstone, and the generators produce the MQTT
client loops, SQLite schema layers, and dispatch tables that the drone needs.
Primary goals:
1. Shared C++ type library for job schemas (editor + drone use the same headers)
2. MQTT and SQLite boilerplate generators targeting C++ / paho / sqlite3
3. Full project skeleton generation from a description string
---
## Phase 38a: Shared Type Library + Drone Skeleton (Steps 634638)
### Step 634: Job schema → typed C++ structs generator (12 tests)
New MCP tool: `whetstone_schema_to_cpp`. Input: JSON schema (the nexus job
payload schema). Output: C++ structs with nlohmann-json `from_json`/`to_json`
overloads, field validation, and a CMakeLists.txt INTERFACE target so both
the drone and Whetstone editor can include the same headers.
### Step 635: Capability declaration struct generator (12 tests)
Generate the C++ types for capability graphs: NodeCapability, CapabilitySet,
EnergyContext, JobRequirements. These are shared between drone (declares
capabilities) and the orchestrator (matches jobs). Output as a header-only
library following Whetstone's existing header-only pattern.
### Step 636: Error type synthesis for drone (12 tests)
Generate C++ error hierarchies for drone operations: MqttError, NexusError,
ExecutionError, CapabilityMismatch. Uses std::error_code / std::expected
patterns (C++23-compatible). Needed for drone's error handling across the
MQTT, SQLite, and executor layers.
### Step 637: Cross-platform CMake target generator (12 tests)
New annotation: @Platform(target = "aarch64-apple-darwin") on platform-specific
code blocks. Generator emits CMake `if(CMAKE_SYSTEM_PROCESSOR MATCHES ...)` guards
and compile-time `#ifdef` blocks. Lets one drone CMakeLists.txt build correctly
on Mac M2, x86_64 Linux, and N100 without per-platform forks.
### Step 638: Phase 38a Integration (8 tests)
Generate a skeleton drone binary: CMakeLists.txt, main.cpp entry, capability
declaration, shared type headers included, all targets building cleanly on the
host platform via vcpkg.
---
## Phase 38b: Infrastructure Generators (Steps 639643)
### Step 639: `whetstone_generate_project` MCP tool (12 tests)
Generate an entire C++ project skeleton from a description string. Input: {name,
description, dependencies (vcpkg names)}. Output: CMakeLists.txt, main.cpp,
module stub headers, test scaffold following Whetstone's own architecture
conventions. The HiveMind drone bootstrap in one call.
### Step 640: MQTT pub/sub boilerplate generator (12 tests)
Given topic names + payload schemas, generate C++ MQTT client code using paho-mqtt
(already in vcpkg). Output: typed topic handler classes with nlohmann-json
deserialization, connection/reconnect logic, QoS config. Drone subscribes to
borg/energy/context, borg/jobs/pending, borg/registry/commit — one generator call.
### Step 641: SQLite schema → C++ data layer generator (12 tests)
Input: SQL CREATE TABLE statements (from hivemind/ARCHITECTURE.md nexus schema).
Output: C++ structs + sqlite3 helper classes with prepared statement wrappers,
CRUD methods, and transaction helpers. Generates the entire nexus DB layer
without hand-writing a single SQL string.
### Step 642: Job dispatch table generator (12 tests)
Input: job type registry (job_type → {required_caps, payload_schema, executor}).
Output: C++ dispatch table — std::unordered_map<std::string, ExecutorFn> with
type-safe payload parsing and executor function stubs. The drone's dispatch
table generated from one schema file.
### Step 643: Sprint 38 Integration + Summary (8 tests)
End-to-end: `whetstone_generate_project` for drone → MQTT generator → SQLite
generator → dispatch table → drone binary compiling cleanly via CMake + vcpkg
on all target platforms.
---
## Step & Test Summary
| Phase | Steps | Tests | Theme |
|-------|-------|-------|-------|
| 38a | 634638 | 56 | Shared C++ types + capability structs + platform CMake |
| 38b | 639643 | 56 | Project skeleton + MQTT + SQLite + dispatch generators |
| **Total** | **634643** | **~112** | 10 steps |

82
sprint39_plan.md Normal file
View File

@@ -0,0 +1,82 @@
# Sprint 39 Plan: Self-Hosting + Release Pipeline
## Context
Sprint 39 makes Whetstone build itself and ship as a product. Self-hosting
validates the entire constructive editing model on a real, complex C++ project.
The release pipeline (AppImage, HiveMind-push auto-update, plugin system) turns
the editor into something deployable across the drone fleet.
Primary goals:
1. Whetstone opens and navigates its own codebase
2. CMake build system generated from project AST
3. In-editor test runner replaces external build cycle
4. AppImage packaging + HiveMind auto-update mechanism
5. Plugin system for third-party language generators
---
## Phase 39a: Self-Hosting Pipeline (Steps 644648)
### Step 644: `.whetstone.json` for the editor project itself (12 tests)
The Whetstone project describes itself using its own config format. This validates
that the config system works for real C++ projects, not just toy examples.
Also: the editor can open itself and navigate its own AST.
### Step 645: CMake generator from Whetstone project description (12 tests)
Given a project AST, generate CMakeLists.txt. Supports: FetchContent deps,
vcpkg integration, test targets, install rules. Lets Whetstone regenerate its own
build system from the AST — the ultimate self-hosting test.
### Step 646: In-editor test runner (12 tests)
Run the Whetstone test suite (stepNNN_test binaries) from within the chat panel:
[Run Tests] button → streams output → shows pass/fail per step → links failures
to the relevant source file. Replaces the external build+test cycle.
### Step 647: Self-modification safety guard (12 tests)
Detect when an agent-requested mutation targets a file that is part of the running
editor binary. Block with: "Cannot mutate live binary — use a build/restart cycle."
Prevents the editor from corrupting its own running code.
### Step 648: Phase 39a Integration (8 tests)
Self-hosting demo: open whetstone_DSL project in the editor → ask agent to add a
new MCP tool → agent generates the header, wires it in CMake → in-editor test
runner validates → self-modification guard active.
---
## Phase 39b: Distribution + Plugin System (Steps 649653)
### Step 649: AppImage / .deb package generator (12 tests)
Generate packaging scripts from project metadata. Output: working AppImage build
script and debian/control. Makes `whetstone` installable as a system package.
Runs as a CI step in the project.
### Step 650: HiveMind-push auto-update mechanism (12 tests)
Drone worker type: `update_editor`. When HiveMind publishes a new editor version
to the apiary, drones on all nodes receive the update job, download the AppImage,
verify hash, replace binary, restart service. Zero-touch updates across the fleet.
### Step 651: Language generator plugin manifest (12 tests)
Define a plugin format: a .so / shared library that exports a `ProjectionGenerator`
subclass. Third parties can add new language generators without recompiling the
editor. Plugin discovery: scan workspace for whetstone-plugin-*.so.
### Step 652: Privacy-preserving local telemetry (12 tests)
Collect: session length, tool call counts, error rates, most-used generators.
Store locally in ~/.whetstone/telemetry.db. Aggregate weekly report. Never
transmits externally. Feeds the Active Inference engine's entropy scoring.
### Step 653: Sprint 39 Integration + Summary (8 tests)
Full release pipeline validated: build → package → AppImage → HiveMind deploy
→ all nodes updated. Plugin system tested with a new language generator.
---
## Step & Test Summary
| Phase | Steps | Tests | Theme |
|-------|-------|-------|-------|
| 39a | 644648 | 56 | Self-hosting + CMake generator + in-editor test runner |
| 39b | 649653 | 56 | AppImage + HiveMind auto-update + plugin system |
| **Total** | **644653** | **~112** | 10 steps |

105
sprint40_plan.md Normal file
View File

@@ -0,0 +1,105 @@
# Sprint 40 Plan: HiveMind Integration — Whetstone + Nexus as One System
## Context
Sprint 40 is the convergence sprint. Whetstone and HiveMind become one integrated
system: the editor dispatches jobs to the swarm, monitors drone status, browses
the apiary, sees the energy state, and acts as the Pilot seat. Active Inference
closes the loop — the editor detects entropy and feeds it back to the swarm.
This is the "system is complete" milestone.
Primary goals:
1. Editor dispatches jobs directly to the HiveMind nexus
2. Live swarm status, apiary browser, and energy context panels
3. Active Inference entropy scanner in the editor
4. Pilot queue panel for human-in-the-loop swarm steering
5. Cross-session context bridge: editor ↔ HiveMind ↔ drone ↔ editor
---
## Phase 40a: Nexus Integration (Steps 654658)
### Step 654: HiveMind job publisher from editor (12 tests)
New MCP tool: `whetstone_dispatch_to_hivemind`. Input: taskitem JSON (AnnotatedTaskitem
format). Writes job to nexus SQLite + publishes to borg/jobs/pending. Editor can
now feed the swarm directly — architect → Whetstone → HiveMind → drone.
### Step 655: Job status subscriber panel (12 tests)
New editor panel: "Swarm Status". Subscribes to MQTT topics for job updates.
Shows: pending jobs, claimed by which node, running duration, completed/failed.
Live refresh. Editor becomes the Pilot seat for the HiveMind.
### Step 656: Apiary browser panel (12 tests)
Browse /mnt/nas/swarm_tools/ from within the editor. Shows: tool name, version,
language, capabilities, doc summary. Click to load tool source into editor buffer.
Search by capability. Lets architect see what the swarm has already built.
### Step 657: Energy context status bar (12 tests)
Subscribe to borg/energy/context. Show current energy state in editor status bar:
`HighSolar 450W` or `Conservation 28%`. Flashes orange in conservation mode.
Agent context injection: include energy state in system prompt so agent knows
whether to suggest GPU-heavy or CPU-light implementations.
### Step 658: Phase 40a Integration (8 tests)
Full loop: architect opens editor → sees energy state → writes spec → dispatches
job to HiveMind → watches job status panel → drone completes → result appears in
apiary browser → architect loads result into buffer.
---
## Phase 40b: Active Inference Bridge (Steps 659663)
### Step 659: Entropy scanner — editor-side (12 tests)
Editor scans open workspace: detect duplicate function signatures, similar module
names, unused exports. Score: entropy count. If above threshold, suggest:
"Consider extracting common logic — generate refactor job?" User can dispatch
the suggestion directly to HiveMind.
### Step 660: `whetstone_generate_inference_job` MCP tool (12 tests)
Given an entropy observation (duplication, gap, staleness), generate a properly
formatted HiveMind Active Inference job: {type: "refactor", goal: "...", context:
{files, entropy_score}, bounty: "normal"}. Write to nexus.
### Step 661: Pilot queue panel (12 tests)
A dedicated panel showing jobs flagged for human review (escalate=true, or
ambiguity > threshold). Jobs arrive via MQTT subscription to a pilot-specific
topic. Human can: approve (dispatch to swarm), reject (discard), modify (edit
task in editor), inject strategy (add a free-text guidance note).
### Step 662: Cross-session context bridge (12 tests)
When the HiveMind dispatches an agent_task job with context_files, the drone
can launch whetstone_mcp --workspace and call whetstone_architect_intake on
those files. Output feeds back to the editor session that dispatched the job.
Closes the loop: editor ↔ HiveMind ↔ drone ↔ editor.
### Step 663: Sprint 40 Integration + Final Summary (8 tests)
The complete system: Whetstone editor + HiveMind nexus + drone workers + apiary
+ active inference + pilot seat. One integrated system. Sprint 40 is the
"system is complete" milestone.
---
## Step & Test Summary
| Phase | Steps | Tests | Theme |
|-------|-------|-------|-------|
| 40a | 654658 | 56 | Nexus dispatch + swarm status + apiary + energy |
| 40b | 659663 | 56 | Active inference + pilot queue + context bridge |
| **Total** | **654663** | **~112** | 10 steps |
---
## Program Summary: Sprints 3640
| Sprint | Steps | Theme |
|--------|-------|-------|
| 36 | 614623 | MCP expansion + architect intake tools |
| 37 | 624633 | In-editor agent chat panel |
| 38 | 634643 | HiveMind build support (Rust, MQTT, SQLite generators) |
| 39 | 644653 | Self-hosting + distribution pipeline |
| 40 | 654663 | HiveMind full integration + Pilot seat |
**Total new steps:** 50
**Total tests (est.):** ~550
**System state after Sprint 40:** Whetstone + HiveMind = one integrated agentic system

155
sprint_codehealth_A.md Normal file
View File

@@ -0,0 +1,155 @@
# Sprint Code-Health-A: Dispatch & Duplication Elimination
> **Goal:** Eliminate the worst semantic-density killers — the copy-paste dispatch chains
> and duplicated generator methods that account for ~2,000+ lines of redundant code.
>
> **Prerequisite:** None. This sprint can run independently.
> **Estimated steps:** 1215
> **Estimated tests:** 3040
---
## Context
Three major duplication sites inflate the codebase:
1. **ProjectionGenerator.h `dispatchGenerate()`** — 220-line if-else chain dispatching
~90 annotation/node types by string comparison. Every new annotation type adds 2 lines.
2. **CompactAST.h `extractSemanticSummary()`** — 340-line if-else chain doing the same
string-match + static_cast + JSON serialization for every annotation type.
3. **Generator `emitBody()` duplication** — identical 12-line function copy-pasted into
RustGenerator, JavaGenerator, JavaScriptGenerator, and every other generator.
---
## Steps
### Step 13: Annotation Self-Registration
**Goal:** Each annotation type registers itself so dispatch chains become table lookups.
**Step 1: AnnotationRegistry infrastructure**
- Create `AnnotationRegistry.h` with:
```cpp
using AnnotationFactory = std::function<ASTNode*(const std::string&)>;
using AnnotationVisitor = std::function<std::string(const ProjectionGenerator*, const ASTNode*)>;
using AnnotationSerializer = std::function<nlohmann::json(const ASTNode*)>;
class AnnotationRegistry {
static auto& visitors() { static std::unordered_map<std::string, AnnotationVisitor> m; return m; }
static auto& serializers() { static std::unordered_map<std::string, AnnotationSerializer> m; return m; }
public:
static void registerVisitor(const std::string& type, AnnotationVisitor v);
static void registerSerializer(const std::string& type, AnnotationSerializer s);
static std::string dispatch(const ProjectionGenerator* gen, const ASTNode* node);
static nlohmann::json serialize(const ASTNode* node);
};
```
- Tests: registry lookup works, unknown type returns fallback string
**Step 2: Migrate ProjectionGenerator dispatch (Part 1 — Subjects 15)**
- For each annotation in Subjects 15 (Memory, Type System, Concurrency, Scope, Shims):
add a static registration block in the annotation's own header
- Replace corresponding if-else branches in `dispatchGenerate()` with `AnnotationRegistry::dispatch()`
- Tests: all existing step tests for these annotations still pass, dispatch returns same results
**Step 3: Migrate ProjectionGenerator dispatch (Part 2 — Subjects 69 + Core + AST nodes)**
- Complete the migration for remaining subjects (Optimization, Meta, Policy, Workflow, Semantic Core)
- Migrate non-annotation AST node dispatch (ClassDeclaration, EnumDeclaration, SQL nodes, etc.)
- Delete the entire 220-line if-else chain, replace with:
```cpp
std::string dispatchGenerate(const ProjectionGenerator* gen, const ASTNode* node) {
return AnnotationRegistry::dispatch(gen, node);
}
```
- Tests: full dispatch regression (all 90+ types), empty node, unknown type
### Step 45: CompactAST Serialization Refactor
**Step 4: Add `toCompactJson()` virtual method to annotation base**
- Add virtual `nlohmann::json toCompactJson() const { return {}; }` to `ASTNode` or annotation base
- Implement for the first 20 annotation types (Subjects 13)
- Tests: round-trip: serialize → deserialize → compare for each type
**Step 5: Complete CompactAST migration**
- Implement `toCompactJson()` for remaining annotation types (Subjects 49 + Core)
- Replace `extractSemanticSummary()` 340-line chain with:
```cpp
json extractSemanticSummary(const ASTNode* node) {
json sem;
for (auto* a : node->getChildren("annotations")) {
json j = a->toCompactJson();
if (!j.empty()) sem[a->shortName()] = j;
}
return sem;
}
```
- Tests: equivalence with old output for all annotation types, empty annotations, mixed types
### Step 67: Generator Base Class Cleanup
**Step 6: Extract shared generator methods to ProjectionGenerator base**
- Move `emitBody()`, `appendIndented()`, `quoteIdentifier()` to `ProjectionGenerator` base
- Remove duplicates from RustGenerator, JavaGenerator, JavaScriptGenerator,
PythonGenerator, CppGenerator, MySQLGenerator, CommonLispGenerator, WatGenerator
- Tests: each generator produces identical output before/after for sample ASTs
**Step 7: Extract shared STUB patterns to base**
- The `"// STUB: empty AST body; user implementation required"` pattern appears in every generator
- Move to `ProjectionGenerator::emitStubBody()` with language-aware comment syntax:
- `//` for C-family, `#` for Python, `;;` for Lisp, `--` for SQL
- Tests: STUB output correct for each language, non-empty body unchanged
### Step 89: LSPClient Response Handler Dedup
**Step 8: Extract JSON response parsing helpers**
- LSPClient.h has repeated `result.is_array()` / `result.is_object()` / `result.contains("items")`
patterns for completions, symbols, definitions
- Create private helpers:
```cpp
std::vector<CompletionItem> parseCompletionItems(const nlohmann::json& result);
std::vector<DocumentSymbol> parseDocumentSymbols(const nlohmann::json& result);
DefinitionLocation parseDefinitionLocation(const nlohmann::json& result);
```
- Tests: parse array form, parse object-with-items form, empty result, malformed result
**Step 9: Simplify handleResponse dispatch**
- Replace the `if (id == lastCompletionRequestId_)` chain with a request-type map:
```cpp
std::unordered_map<int, std::function<void(const json&)>> pendingHandlers_;
```
- Each `sendRequest()` registers its handler; `handleResponse()` becomes a lookup
- Tests: concurrent requests, handler cleanup after response, unknown id ignored
### Step 1011: Headless RPC Dispatch Cleanup
**Step 10: Audit DispatchPart14.h for string-match duplication**
- These files dispatch RPC method strings to handler functions
- Assess: can these use a `std::unordered_map<string, handler>` like the LSP fix?
- If yes: refactor. If the dispatch is already small (~10 per file), leave it.
- Tests: all headless RPC methods still route correctly
**Step 11: Consolidate dispatch infrastructure**
- If AnnotationRegistry and RPC dispatch both use string→function maps,
extract a shared `StringDispatch<ReturnType>` template utility
- Tests: template works for both use cases
### Step 12: Regression & Metrics
**Step 12: Full regression + line count delta**
- Run all existing tests (615 files)
- Measure: total .h lines before vs after
- Expected savings: ~1,5002,000 lines removed
- Document in progress.md
- Tests: no regressions, line count report
---
## Success Criteria
- [ ] No if-else chain in codebase exceeds 30 lines for type dispatch
- [ ] `emitBody()` exists in exactly one place (base class)
- [ ] CompactAST `extractSemanticSummary()` is under 20 lines
- [ ] ProjectionGenerator `dispatchGenerate()` is under 10 lines
- [ ] All 615 existing tests pass
- [ ] Net line reduction: ≥1,500 lines