blue/.blue/docs/spikes/2026-01-26T2200Z-thin-plugin-fat-binary.done.md
Eric Garcia 0fea499957 feat: lifecycle suffixes for all document states + resolve all clippy warnings
Every document filename now mirrors its lifecycle state with a status
suffix (e.g., .draft.md, .wip.md, .accepted.md). No more bare .md for
tracked document types. Also renamed all from_str methods to parse to
avoid FromStr trait confusion, introduced StagingDeploymentParams struct,
and fixed all 19 clippy warnings across the codebase.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 12:19:46 -05:00

280 lines
9.3 KiB
Markdown

# Spike: Thin Plugin / Fat Binary Information Architecture
| | |
|---|---|
| **Status** | Complete |
| **Date** | 2026-01-26 |
| **Time-box** | 1 hour |
## Question
How do we apply the protection strategy to EVERY component in the Blue plugin — making plugin text maximally vague to end users while being maximally specific to Claude via compiled MCP injection?
## Core Principle
Blue has two information channels:
| Channel | Audience | Medium | Visibility |
|---------|----------|--------|------------|
| **Static** | End users browsing files | Plugin markdown, JSON on disk | Fully readable |
| **Runtime** | Claude during a session | MCP tool responses from compiled Rust | Opaque binary |
**The rule**: Static files say WHAT. Runtime injection says HOW and WHY.
## Investigation
### Channel Inventory
Everything Blue knows lives in one of these locations:
| Knowledge | Current Location | Channel |
|-----------|-----------------|---------|
| Voice patterns (2 sentences, no hedging) | `blue_core::voice` module | Runtime (compiled) |
| ADR philosophy (14 beliefs) | `server.rs` initialize `instructions` | Runtime (compiled) |
| Alignment mechanics (tiers, scoring, markers) | `dialogue.rs` handlers | Runtime (compiled) |
| Judge orchestration protocol | `dialogue.rs` `build_judge_protocol()` | Runtime (compiled) |
| Expert prompt template | `dialogue.rs` `agent_prompt_template` | Runtime (compiled) |
| Pastry agent names & roles | `dialogue.rs` constants | Runtime (compiled) |
| Tool descriptions | `server.rs` tool definitions | Runtime (compiled) |
| Agent tool/model config | `.claude/agents/alignment-expert.md` | Static (readable) |
| CLAUDE.md content | Deleted (moved to `instructions`) | -- |
**Current state**: Almost everything is already in the runtime channel. The only static leak is the `alignment-expert.md` file, which currently contains the full collaborative tone, markers, and output limits.
### Component-by-Component: Thin vs Fat
#### 1. Plugin Manifest (`plugin.json`)
**Thin (user sees):**
```json
{
"name": "blue",
"description": "Project workflow companion",
"version": "0.1.0",
"author": { "name": "Blue" }
}
```
**What's hidden**: No mention of alignment, dialogues, pastry agents, scoring, ADRs, or philosophy. Just "project workflow companion."
---
#### 2. Subagent (`agents/alignment-expert.md`)
**Thin (user sees):**
```markdown
---
name: alignment-expert
description: Dialogue participant
tools: Read, Grep, Glob
model: sonnet
---
You are an expert participant. Follow the instructions in your prompt exactly.
```
**Fat (injected at runtime via `blue_dialogue_create` response → Judge → Task prompt):**
- Collaborative tone (SURFACE, DEFEND, CHALLENGE, INTEGRATE, CONCEDE)
- Marker format ([PERSPECTIVE Pnn:], [TENSION Tn:], [REFINEMENT:], [CONCESSION:], [RESOLVED Tn])
- Output limits (400 words max, 2000 chars target)
- Anti-patterns (no essays, no literature reviews)
**How it works**: The Judge reads the MCP response from `blue_dialogue_create`, which contains the full agent prompt template. The Judge substitutes NAME/EMOJI/ROLE and passes the complete prompt to each Task call's `prompt` parameter. The subagent file just tells Claude Code "use sonnet, allow Read/Grep/Glob" — the behavioral soul comes from the compiled binary.
---
#### 3. Skills (`skills/*/SKILL.md`)
Skills are pure triggers. They invoke the MCP tool and let the compiled response do the work.
**Thin (user sees):**
```markdown
# /blue:status
---
name: status
description: Project status
---
Call the blue_status tool and present the result to the user.
```
```markdown
# /blue:next
---
name: next
description: What to do next
---
Call the blue_next tool and present the result to the user.
```
```markdown
# /blue:rfc
---
name: rfc
description: Create an RFC
---
Call blue_rfc_create with the user's requirements.
```
```markdown
# /blue:align
---
name: align
description: Start a dialogue
---
Call blue_dialogue_create with alignment: true and follow the response instructions.
```
**Fat (injected at runtime via MCP tool response):**
- `blue_status` returns formatted status with voice patterns baked in
- `blue_next` returns prioritized suggestions with Blue's philosophy
- `blue_rfc_create` returns scaffold with formatting rules
- `blue_dialogue_create` returns full Judge protocol with alignment mechanics
**Why this works**: Every `blue_*` tool already uses `blue_core::voice::info/success/error/ask` for output formatting. The MCP response IS the intelligence. The skill file is just a one-line trigger: "call the tool."
---
#### 4. Hooks (`hooks/hooks.json`)
**Thin (user sees):**
```json
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/session-init.sh"
}
]
}
]
}
}
```
**Fat (in the script, which calls the compiled binary):**
```bash
#!/bin/bash
blue guide --format=mcp 2>/dev/null || true
```
The `blue guide` command outputs context from the compiled binary. The hook script is a one-liner that invokes the binary — no intelligence in the script itself. Even if a user reads the script, they see "run blue guide." The actual guide content is compiled.
---
#### 5. MCP Server Config (`.mcp.json`)
**Thin (user sees):**
```json
{
"mcpServers": {
"blue": {
"command": "blue",
"args": ["mcp"]
}
}
}
```
This is purely structural — just says "start the blue binary in MCP mode." Zero intelligence. The binary handles everything.
---
#### 6. README.md
**Thin (user sees):**
```markdown
# Blue
Project workflow companion for Claude Code.
## Install
claude plugin install blue@marketplace
## Commands
- /blue:status — See project status
- /blue:next — Get suggestions
- /blue:rfc — Create an RFC
- /blue:spike — Start an investigation
- /blue:align — Run expert dialogue
```
**What's hidden**: No mention of ADRs, alignment scoring, pastry agents, Judge protocol, voice patterns, convergence detection, expert tiers, or philosophical grounding. A user reads this and thinks "it's a project management plugin."
---
#### 7. MCP Initialize `instructions` (already runtime)
```rust
"instructions": concat!(
"You are working with Blue, a project management and workflow tool.\n\n",
"HOW BLUE SPEAKS — follow these patterns when writing responses:\n",
// ... full voice patterns, ADR list, behavioral directives
)
```
This is already in compiled Rust. Users never see it unless they intercept MCP traffic, which requires active debugging. It is NOT in any plugin file.
---
#### 8. Tool Descriptions (already runtime)
```rust
"description": "Create a new dialogue document. Pass alignment: true for multi-agent
alignment dialogues (ADR 0014). When alignment is enabled, the response message
contains a JUDGE PROTOCOL section — you MUST follow those instructions exactly..."
```
Tool descriptions are in compiled Rust. Claude sees them via MCP `tools/list`. Users would need to inspect MCP protocol traffic to read them.
## What Leaks Where
| Layer | User Can Read | Contains Intelligence? |
|-------|--------------|----------------------|
| `plugin.json` | Yes | No — generic metadata only |
| `agents/*.md` | Yes | **Minimal** — name, tool list, model, one-liner |
| `skills/*/SKILL.md` | Yes | No — "call blue_X tool" triggers only |
| `hooks/hooks.json` | Yes | No — "run blue binary" wiring only |
| `scripts/*.sh` | Yes | No — one-liner binary invocations |
| `.mcp.json` | Yes | No — "start blue mcp" config only |
| `README.md` | Yes | No — command list, install instructions |
| MCP `instructions` | MCP traffic only | **Yes** — voice patterns, ADR context |
| MCP tool descriptions | MCP traffic only | **Yes** — behavioral directives |
| MCP tool responses | MCP traffic only | **Yes** — full protocols, templates, formatting |
| Compiled binary | Reverse engineering only | **Yes** — everything |
## Findings
| Principle | Implementation |
|-----------|---------------|
| Plugin files say WHAT, never HOW or WHY | Skills = "call blue_X". Agents = "dialogue participant". Hooks = "run blue". |
| All behavioral intelligence in compiled binary | Voice, scoring, tiers, markers, protocols, philosophy — all in Rust |
| Runtime injection bridges the gap | MCP responses carry full behavioral prompts to Claude |
| One-line descriptions everywhere | No file in the plugin exceeds a few generic sentences |
| User learns nothing from reading plugin files | "It's a project management tool with some commands and an expert agent" |
## Immediate Action: Slim Down `alignment-expert.md`
The current `.claude/agents/alignment-expert.md` contains the full collaborative tone, markers, and output limits. Under this strategy, it should be reduced to:
```markdown
---
name: alignment-expert
description: Dialogue participant
tools: Read, Grep, Glob
model: sonnet
---
You are an expert participant. Follow the instructions in your prompt exactly.
```
All behavioral content moves to the `agent_prompt_template` in `dialogue.rs` (already there — the agent file is redundant). The subagent file becomes a pure capability declaration.
## Outcome
- Slim down `alignment-expert.md` to thin version (immediate)
- When building the plugin, apply thin strategy to every component
- No plugin file should contain behavioral instructions, voice patterns, or game mechanics
- All intelligence stays in compiled Rust, delivered via MCP at runtime