Skip to content

docs: plan the Route 3 projector for issue #239 - #251

Merged
serina-mcfall merged 1 commit into
launchpadfrom
docs/plan-issue-239
Aug 20, 2026
Merged

docs: plan the Route 3 projector for issue #239#251
serina-mcfall merged 1 commit into
launchpadfrom
docs/plan-issue-239

Conversation

@serina-mcfall

Copy link
Copy Markdown

Summary

Scoping plan for #239 (the Route 3 projector) — resolves what's actually in the repo today (resolve_pack() unused everywhere, buzz-acp's single-MCP-server cap, goose's write-capability being a config-file toggle with no merge-write logic anywhere) into a 10-step plan, and states the scope recommendation #239's own DoD requires.

Related issue

Refs #239

Issue type

Task


Agent provenance

Field Value
Harness / provider Claude Code
Model claude-sonnet-5
Session reference N/A - harness does not expose a stable run id/URL for this session
Initiating human @serina-mcfall

Objective

A right-sized implementation plan for #239, grounded in the actual state of resolve_pack(), buzz-acp's config surface, and goose's config-file format — not assumed from the issue text alone.

Impacted components

launchpad/plans/2026-08-20-issue-239-route-3-projector.md

Approach and rejected alternatives

Read the actual code (buzz-persona::resolve, buzz-acp::config/lib.rs::build_mcp_servers, the desktop app's read-only goose config-bridge) before planning, rather than planning from the issue text and the design doc alone — this surfaced three concrete findings the issue text didn't state: (1) resolve_pack() has zero callers outside buzz pack inspect/tests, (2) buzz-acp is capped at exactly one MCP server even though the protocol and persona-resolution layer both already support many, (3) no merge-write logic for goose's config.yaml exists anywhere in the repo, so enabling the developer extension needs new read-merge-write logic built from scratch, not a config toggle.

Considered building the projector as a script hardcoded to The Professor's own pack; rejected because the underlying mechanism (pack → runtime env vars, pack → goose config patch) is not persona-specific at all, and hardcoding it would mean rewriting it for the next pack (#211, The Librarian) rather than reusing it.

Considered re-parsing persona YAML directly in the projector script instead of adding --format json to buzz pack inspect; rejected because it would duplicate resolve_pack()'s precedence-resolution logic in a second language, and the two would drift the first time either changed — the same reasoning already established in this repo for why buzz pack inspect reuses resolve_pack() rather than re-deriving it.

Verification

Command run:

cargo test -p buzz-persona

Raw output (tail):

test result: ok. 127 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s
...
test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
...
test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

145 tests total, 0 failed — confirms the resolve_pack()/ResolvedPersona surface this plan builds on behaves exactly as described (list-shaped mcp_servers, env-var projection, etc.).

  • Tests or checks were run and the raw output is pasted above
  • The diff is confined to the scope of the linked issue
  • No secrets, keys, tokens or hostnames were added to tracked files

Not verified

Whether buzz pack inspect --format json (step 1 of the plan) is achievable exactly as sketched without further design once implementation starts — the plan states the shape it expects but the field hasn't been built yet. Also not verified: goose's actual runtime behavior when extensions.developer.enabled: true is set by an external process rather than through goose's own UI/CLI — the plan assumes this works based on the config-bridge's own parsing of that exact shape, but nothing in this repo exercises writing it, only reading it.

Security implications

This plan recommends enabling a real shell/file-write capability for an LLM-driven agent for the first time in this pack's history — a materially larger blast radius than the five read-only MCP tools #9 shipped. The plan does not implement this; it flags the two open decisions this raises (OPEN items 1-2 in the plan: the scope recommendation, and who arbitrates whether the developer extension is safe enough for a live/unattended run later) rather than deciding them, and explicitly scopes the end-to-end proof to a throwaway local relay and a human-triggered session under BYOK, matching #9's own precedent and #239's own stated out-of-scope boundary for live cohort deployment.

Escalations

Both OPEN items in the plan (the handbook-only scope recommendation, and who arbitrates future live-enablement safety) were raised as open questions rather than decided — #239's own DoD explicitly requires the scope question be answered on the record, not left silent either way.

Scopes #239 against the real repository rather than the issue text alone:
resolve_pack() already exists, is tested, and is called by nothing except
buzz pack validate/inspect (human-facing, println!-only, no JSON) -- zero
callers in buzz-acp, buzz-agent, or the desktop app. buzz-acp's own spawn
config is capped at exactly one MCP server (Config.mcp_command: String),
narrower than the protocol or the persona-resolution layer, both already
Vec-shaped -- named as a real, separate limitation rather than worked around.
Goose's write/shell capability is a config-file toggle (extensions.developer
in config.yaml), not an env var, and no merge-write logic for that file
exists anywhere in the repo -- confirmed by reading the entire (read-only)
goose config-bridge module.

The plan recommends handbook-only scope for this first pass (not the
broader any-codebase scribe role), states that recommendation explicitly
per #239's own DoD requirement that silence is not acceptable, and builds
the projector generic rather than Professor-specific so the broader role
can reuse it later without a rewrite.

10 steps: a --format json addition to buzz pack inspect, the generic
projector script, the goose-config merge-write logic (built from scratch),
a temporary-trigger-enabled local proof reusing #9's own throwaway-relay
precedent, a revert of that temporary change, and a README update -- with
the multi-MCP-server cap and live/unattended enablement explicitly left out
as separate, real engineering.

Verified: cargo test -p buzz-persona passes (145 tests, 0 failed) --
confirms the resolve_pack() surface this plan builds on is exactly as
described.

Signed-off-by: Serina Mcfall <serina.mcfall@gmail.com>
@serina-mcfall serina-mcfall added the by:agent Filed or authored by an AI agent, not a human label Aug 20, 2026
@serina-mcfall
serina-mcfall marked this pull request as ready for review August 20, 2026 07:44
@serina-mcfall
serina-mcfall enabled auto-merge (squash) August 20, 2026 07:53
@serina-mcfall
serina-mcfall disabled auto-merge August 20, 2026 07:53

@benmitchell11 benmitchell11 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independently verified all three headline findings against the actual code rather than trusting the summary:

  • resolve_pack(): confirmed via grep it's only called from buzz-cli/src/commands/pack.rs (the pack inspect/validate command) plus buzz-persona's own tests — no caller in buzz-acp, buzz-agent, or desktop/src-tauri.
  • The one-MCP-server cap: confirmed build_mcp_servers() in buzz-acp/src/lib.rs is driven by Config.mcp_command: String (singular) and can only ever return vec![] or a one-element vec, even though NewSessionRequest.mcp_servers and ResolvedPersona.mcp_servers are both already Vec — the cap is real and exactly where the plan says it is.
  • No goose config write logic: found ConfigWriteMechanism::GooseNativeConfigWrite in config_bridge/types.rs, which could look like a contradiction at a glance — but its own doc comment says "Reserved for tier 1a — blocked on upstream goose PR landing. Not yet constructed by any reader," confirming it's an unimplemented placeholder, not existing logic. The plan's claim holds.

The security-implications section is appropriately blunt about this being the first shell/file-write capability granted to an LLM agent in this pack's history, and correctly routes the two real open questions (scope, future live-enablement arbitration) to Escalations rather than deciding them unilaterally in a planning doc. Approving.

@serina-mcfall
serina-mcfall merged commit 6655f72 into launchpad Aug 20, 2026
27 checks passed
@serina-mcfall
serina-mcfall deleted the docs/plan-issue-239 branch August 20, 2026 19:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

by:agent Filed or authored by an AI agent, not a human

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants