feat(desktop): two-layer agent prompts + dynamic AGENTS.md + MCP gating + harness-agnostic skill path#584
Merged
Merged
Conversation
wesbillman
reviewed
May 14, 2026
wesbillman
reviewed
May 14, 2026
23b4eb0 to
035d4c0
Compare
wpfleger96
added a commit
that referenced
this pull request
May 15, 2026
…uplication base_prompt.md (injected every turn via [Base]) already has a comprehensive CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's dynamic section now focuses on what's unique to it: active agents and workspace info. Also bumps personas.rs file size override from 900 to 950 to accommodate the merge_personas inequality checks added in the review-fix commit.
350aa8a to
95515fd
Compare
wpfleger96
added a commit
that referenced
this pull request
May 18, 2026
…uplication base_prompt.md (injected every turn via [Base]) already has a comprehensive CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's dynamic section now focuses on what's unique to it: active agents and workspace info. Also bumps personas.rs file size override from 900 to 950 to accommodate the merge_personas inequality checks added in the review-fix commit.
95515fd to
8505a9e
Compare
wpfleger96
added a commit
that referenced
this pull request
May 18, 2026
…uplication base_prompt.md (injected every turn via [Base]) already has a comprehensive CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's dynamic section now focuses on what's unique to it: active agents and workspace info. Also bumps personas.rs file size override from 900 to 950 to accommodate the merge_personas inequality checks added in the review-fix commit.
8505a9e to
00c1a38
Compare
wpfleger96
added a commit
that referenced
this pull request
May 18, 2026
…uplication base_prompt.md (injected every turn via [Base]) already has a comprehensive CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's dynamic section now focuses on what's unique to it: active agents and workspace info. Also bumps personas.rs file size override from 900 to 950 to accommodate the merge_personas inequality checks added in the review-fix commit.
00c1a38 to
58a3ace
Compare
wpfleger96
added a commit
that referenced
this pull request
May 18, 2026
…uplication base_prompt.md (injected every turn via [Base]) already has a comprehensive CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's dynamic section now focuses on what's unique to it: active agents and workspace info. Also bumps personas.rs file size override from 900 to 950 to accommodate the merge_personas inequality checks added in the review-fix commit.
58a3ace to
6db3ab4
Compare
wpfleger96
added a commit
that referenced
this pull request
May 18, 2026
…uplication base_prompt.md (injected every turn via [Base]) already has a comprehensive CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's dynamic section now focuses on what's unique to it: active agents and workspace info. Also bumps personas.rs file size override from 900 to 950 to accommodate the merge_personas inequality checks added in the review-fix commit.
6db3ab4 to
bd11938
Compare
bd11938 to
682d8fe
Compare
wpfleger96
added a commit
that referenced
this pull request
May 19, 2026
…uplication base_prompt.md (injected every turn via [Base]) already has a comprehensive CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's dynamic section now focuses on what's unique to it: active agents and workspace info. Also bumps personas.rs file size override from 900 to 950 to accommodate the merge_personas inequality checks added in the review-fix commit.
wpfleger96
added a commit
that referenced
this pull request
May 20, 2026
…uplication base_prompt.md (injected every turn via [Base]) already has a comprehensive CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's dynamic section now focuses on what's unique to it: active agents and workspace info. Also bumps personas.rs file size override from 900 to 950 to accommodate the merge_personas inequality checks added in the review-fix commit.
76c6997 to
42c04f0
Compare
wpfleger96
added a commit
that referenced
this pull request
May 20, 2026
…uplication base_prompt.md (injected every turn via [Base]) already has a comprehensive CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's dynamic section now focuses on what's unique to it: active agents and workspace info. Also bumps personas.rs file size override from 900 to 950 to accommodate the merge_personas inequality checks added in the review-fix commit.
BackendKind and RespondTo are only used in test helper constructors.
Fixes identified by crossfire review (Codex + Gemini) and plan author: - Use tempfile::NamedTempFile for atomic writes instead of deterministic .tmp path that races under concurrent regeneration triggers - Enforce ordered BEGIN/END marker search with line-start anchoring to prevent inverted slicing when markers are out of order or mid-line - Strip orphan BEGIN markers before appending new managed section - Escape pipe and newline characters in agent/persona names to prevent Markdown table corruption - Rename "Role" column to "Persona" (display_name is a name, not a role) - Move regenerate_nest_context calls outside lock scope in all mutation hooks to reduce lock hold time and eliminate future deadlock risk - Add 7 adversarial unit tests: marker ordering, orphan cleanup, duplicates, code-block false positives, pipe/newline escaping, idempotency
nest.rs grew to 770 lines with regenerate_nest_context, marker helpers, and 19 unit tests. The 500-line default is too tight for this file — override to 800 following the established pattern.
…uplication base_prompt.md (injected every turn via [Base]) already has a comprehensive CLI reference table covering all 11 command groups. The CLI_QUICK_REFERENCE constant in nest.rs was a less complete duplicate (4 commands). AGENTS.md's dynamic section now focuses on what's unique to it: active agents and workspace info. Also bumps personas.rs file size override from 900 to 950 to accommodate the merge_personas inequality checks added in the review-fix commit.
Review surfaced 10 findings across 5 independent sources (3 Claude specialists + Codex + Gemini). Key changes: - Fix incorrect CLI syntax in base_prompt.md (missing --channel flag, positional arg that should be named) and stale nest_agents.md reference - Apply line-start validation to END_MARKER in find_managed_markers, matching the BEGIN_MARKER contract documented in the function comment - Extract prepend_base_prompt helper to deduplicate [Base] injection across format_prompt, dispatch_heartbeat, and initial_message paths - Move base_prompt_file read from main.rs panic to Config::from_cli with proper ConfigError propagation and 1 MB size guard - Extract try_regenerate_nest helper to consolidate 11 identical error-handling blocks across command files - Sanitize relay_url before AGENTS.md injection (strip CR/LF) - Fix greedy newline strip in strip_orphan_begin_marker - Add doc comments for PromptContext.base_prompt lifetime constraint
rustfmt fixes after rebase onto main (extra blank lines in lib.rs and nest.rs). Bump nest.rs file size override from 800 to 960 to account for skill file init code merged from #613. Signed-off-by: Will Pfleger <wpfleger@block.xyz>
Agent-facing prompts (base prompt, context hints, heartbeat, AGENTS.md template) still referenced MCP function-call syntax despite the CLI migration. Additionally, existing users never received template updates because nest files used write-once semantics. Strip all MCP references from the four agent-facing sources compiled into the binary. Add version-gated refresh to ensure_nest_at so AGENTS.md static content (above managed markers) and SKILL.md are updated on binary upgrades while preserving the dynamic agent table. # Conflicts: # desktop/scripts/check-file-sizes.mjs
upsert_managed_section always wrote via NamedTempFile even when the new content was identical, bumping mtime on every app launch. Add an early return when content matches to make the function truly idempotent at the filesystem level.
…c skill path Agents whose provider declares mcp_command: None (goose, Claude Code, Codex) were getting sprout-mcp-server injected via the ACP session, giving them callable MCP tools that override text-based CLI instructions. Reinterpret None as "no MCP needed" and gate at creation time (empty string stored) and spawn time (empty env var -> empty vec from build_mcp_servers). Only sprout-agent retains its sprout-dev-mcp. Move SKILL.md from .claude/skills/sprout-cli/ to the open-standard .agents/skills/sprout-cli/ with a relative symlink for Claude Code compat. Migrate pre-existing real directories, preserving user-edited content. Remove duplicate @mention guideline from nest AGENTS.md (already in base_prompt.md). Bump version constants to 3 to trigger refresh.
Only Claude Code got a symlink for skill discovery; Goose, Codex, and future harnesses were ignored. Add a skill_dir field to KnownAcpProvider so each harness declares its own skill path, then loop over all providers to create relative symlinks from each harness dir to the canonical .agents/skills/sprout-cli. Moves the real SKILL.md to .agents/skills/sprout-cli (agent-neutral canonical path) with symlinks at .goose/skills/, .claude/skills/, and .codex/skills/. # Conflicts: # desktop/src-tauri/src/managed_agents/discovery.rs
Doc comment on SPROUT_CLI_SKILL_MD still said "Claude Code skill" and the ensure_nest_at docstring used .claude/skills as an inline example rather than describing the generic provider pattern.
ensure_skill_symlinks_skip_real_directory assumed no migration path; refresh_skill_md_if_stale converts real dirs at .claude/skills/sprout-cli to symlinks, so the test was updated to match the actual merged behavior. Bump nest.rs file-size override to accommodate new provider symlink tests.
Fixes cargo fmt violation at nest.rs:165 — extra blank line between refresh_skill_md_if_stale and the permissions comment block.
726139e to
7f39683
Compare
wpfleger96
added a commit
that referenced
this pull request
May 26, 2026
Existing agents created before #584 have mcp_command = "sprout-mcp-server" stored in managed-agents.json. At spawn, this registers the full 49-tool messaging MCP server — goose prefers live tools over CLI instructions. On every launch, reconcile_provider_mcp_commands() reads the JSON, looks up each agent_command in the discovery table, and patches mcp_command to the canonical value (empty string for goose/claude/codex, "sprout-dev-mcp" for sprout-agent). Unknown/custom agents are left untouched. Signed-off-by: Will Pfleger <wpfleger@block.xyz>
wpfleger96
added a commit
that referenced
this pull request
May 26, 2026
Existing agents created before #584 have mcp_command = "sprout-mcp-server" stored in managed-agents.json. At spawn, this registers the full 49-tool messaging MCP server — goose prefers live tools over CLI instructions. On every launch, reconcile_provider_mcp_commands() reads the JSON, looks up each agent_command in the discovery table, and patches mcp_command to the canonical value (empty string for goose/claude/codex, "sprout-dev-mcp" for sprout-agent). Unknown/custom agents are left untouched. Signed-off-by: Will Pfleger <wpfleger@block.xyz>
wpfleger96
added a commit
that referenced
this pull request
May 26, 2026
Existing agents created before #584 have mcp_command = "sprout-mcp-server" stored in managed-agents.json. At spawn, this registers the full 49-tool messaging MCP server — goose prefers live tools over CLI instructions. On every launch, reconcile_provider_mcp_commands() reads the JSON, looks up each agent_command in the discovery table, and patches mcp_command to the canonical value (empty string for goose/claude/codex, "sprout-dev-mcp" for sprout-agent). Unknown/custom agents are left untouched. Signed-off-by: Will Pfleger <wpfleger@block.xyz>
wpfleger96
added a commit
that referenced
this pull request
May 26, 2026
Existing agents created before #584 have mcp_command = "sprout-mcp-server" stored in managed-agents.json. At spawn, this registers the full 49-tool messaging MCP server — goose prefers live tools over CLI instructions. On every launch, reconcile_provider_mcp_commands() reads the JSON, looks up each agent_command in the discovery table, and patches mcp_command to the canonical value (empty string for goose/claude/codex, "sprout-dev-mcp" for sprout-agent). Unknown/custom agents are left untouched. Signed-off-by: Will Pfleger <wpfleger@block.xyz>
wpfleger96
added a commit
that referenced
this pull request
May 27, 2026
Existing agents created before #584 have mcp_command = "sprout-mcp-server" stored in managed-agents.json. At spawn, this registers the full 49-tool messaging MCP server — goose prefers live tools over CLI instructions. On every launch, reconcile_provider_mcp_commands() reads the JSON, looks up each agent_command in the discovery table, and patches mcp_command to the canonical value (empty string for goose/claude/codex, "sprout-dev-mcp" for sprout-agent). Unknown/custom agents are left untouched. Signed-off-by: Will Pfleger <wpfleger@block.xyz>
wpfleger96
added a commit
that referenced
this pull request
May 27, 2026
Existing agents created before #584 have mcp_command = "sprout-mcp-server" stored in managed-agents.json. At spawn, this registers the full 49-tool messaging MCP server — goose prefers live tools over CLI instructions. On every launch, reconcile_provider_mcp_commands() reads the JSON, looks up each agent_command in the discovery table, and patches mcp_command to the canonical value (empty string for goose/claude/codex, "sprout-dev-mcp" for sprout-agent). Unknown/custom agents are left untouched. Signed-off-by: Will Pfleger <wpfleger@block.xyz>
wpfleger96
added a commit
that referenced
this pull request
May 27, 2026
Existing agents created before #584 have mcp_command = "sprout-mcp-server" stored in managed-agents.json. At spawn, this registers the full 49-tool messaging MCP server — goose prefers live tools over CLI instructions. On every launch, reconcile_provider_mcp_commands() reads the JSON, looks up each agent_command in the discovery table, and patches mcp_command to the canonical value (empty string for goose/claude/codex, "sprout-dev-mcp" for sprout-agent). Unknown/custom agents are left untouched. Signed-off-by: Will Pfleger <wpfleger@block.xyz>
wpfleger96
added a commit
that referenced
this pull request
May 27, 2026
Existing agents created before #584 have mcp_command = "sprout-mcp-server" stored in managed-agents.json. At spawn, this registers the full 49-tool messaging MCP server — goose prefers live tools over CLI instructions. On every launch, reconcile_provider_mcp_commands() reads the JSON, looks up each agent_command in the discovery table, and patches mcp_command to the canonical value (empty string for goose/claude/codex, "sprout-dev-mcp" for sprout-agent). Unknown/custom agents are left untouched. Signed-off-by: Will Pfleger <wpfleger@block.xyz>
This was referenced May 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Four changes that give managed agents reliable, CLI-first Sprout platform awareness and fix MCP tool injection for non-sprout-agent harnesses.
1. Two-layer prompt architecture
Adds a shared
[Base]prompt layer injected by the ACP harness on every turn — Sprout CLI reference, communication patterns, startup recovery, and workspace context. Every agent gets platform orientation without duplicating it across personas.base_prompt.mdcompiled in viainclude_str!(), prepended as[Base]before[System](persona) on all turns including heartbeats and initial messagesFormatPromptArgsstruct replaces positional params onformat_prompt()SPROUT_ACP_NO_BASE_PROMPTdisables it;SPROUT_ACP_BASE_PROMPT_FILEoverrides the compiled-in defaultmodel/providerreverted toNone2. Dynamic AGENTS.md regeneration
~/.sprout/AGENTS.mdnow dynamically reflects workspace state. A managed section between<!-- BEGIN/END SPROUT MANAGED -->markers is regenerated whenever agents, personas, or workspace config change.regenerate_nest_context()renders an active agents table into the managed sectiontry_regenerate_nest()hooks in 10 Tauri command functions — all outside lock scopetempfile::NamedTempFile; app-startup hook for first-launch currency3. CLI-first agent prompts + versioned nest file refresh
Completes the MCP-to-CLI migration for all agent-facing content compiled into the binary. Adds a version-gated refresh mechanism so existing installs receive template updates on upgrade.
base_prompt.md,nest_agents.md, context hints inqueue.rs, and heartbeat prompt inlib.rs— agents now exclusively referencesproutCLI commandsnest_agents.mdtrimmed from 80 to 55 lines: removed sections now covered bybase_prompt.mdandSKILL.mdNEST_AGENTS_VERSION/NEST_SKILL_VERSIONconstants gate a startup refresh inensure_nest_at— stale static content is atomically overwritten when the binary ships newer templates4. MCP server gating + harness-agnostic skill path
Fixes MCP tool injection so only providers that explicitly declare an MCP server get one. Moves the skill file to the open-standard
.agents/skills/path with data-driven symlinks for all known harnesses.mcp_command: None(goose, Claude Code, Codex) no longer getsprout-mcp-serverinjected — empty string propagates through the creation/spawn/ACP chain to produce zero MCP serverssprout-agent(mcp_command: Some("sprout-dev-mcp")) retains MCP tools.claude/skills/sprout-cli/to.agents/skills/sprout-cli/(canonical path); relative symlinks created for each known harness (.claude/skills/,.goose/skills/,.codex/skills/) viaKnownAcpProvider.skill_dir@mentionformatting guideline fromnest_agents.md(already inbase_prompt.md)