Skip to content

feat: Read-only GitHub + filesystem tool access for Planner & Architect agents #193

@Abernaughty

Description

@Abernaughty

Summary

The Planner and Architect agents have zero tool access. When a user says "Fix issue #113", the Planner asks basic questions ("is this Svelte?", "what's the file path?") that it could answer by reading the workspace or fetching the GitHub issue. Both agents need read-only access to GitHub MCP and Filesystem MCP.

Problem

  • Planner (src/agents/planner.py) — bare ainvoke(), no tools. Asks the user for information it could look up.
  • Architect (architect_node in src/orchestrator.py) — single LLM call. Gets pre-fetched files from gather_context_node but can't explore further or fetch GitHub issues.

Solution

1. Tool filtering (src/tools/mcp_bridge.py)

Add tool_filter: set[str] | None to get_tools() with a READONLY_TOOLS constant (GitHub read + filesystem read tools). Prevents Planner/Architect from accessing write tools.

2. GitHub issue/PR pre-fetch (src/orchestrator.pygather_context_node)

Detect issue/PR references in task descriptions using patterns:

  • Issues: (?:issue|fixes?|closes?|resolves?|refs?|see|review|address|gh)\s*#(\d+) (case-insensitive)
  • PRs: (?:pr|pull\s*request|pull)\s*#(\d+) (case-insensitive)
  • Bare #N intentionally excluded to avoid false matches (markdown headings, CSS colors)

Pre-fetch via GitHub issues API (covers both issues and PRs), inject full body into gathered_context — no arbitrary truncation.

3. Planner GitHub-context flow (src/agents/planner.py)

The implementation diverged from the originally-proposed conditional tool binding. PR #195 took a deterministic pre-fetch approach instead:

  • On every turn, scan the user message for issue/PR refs (same regex family as gather_context).
  • Pre-fetch matched refs via the GitHub REST API; store summaries on TaskSpec.github_context.
  • Inject summaries into a === PRE-FETCHED GITHUB CONTEXT === block in the Planner's system messages.
  • The Planner LLM reads the block as ambient context — it never binds tools and never makes live API calls.
  • Pass-through: TaskSpec.github_context flows to the orchestrator on submit, preventing the Architect from re-fetching.

Subsequent PRs (#197, #198, #199) closed gaps discovered in manual smoke: system-prompt self-denial, anti-hallucination rules, repo-picker plumbing, git-remote auto-detection, and arbitrary body truncation.

4. Architect two-phase tool access (src/orchestrator.py)

  • Phase 1 (no tools): Run as today with pre-fetched context (now includes GitHub issues + Planner pass-through)
  • Phase 2 (tools, only if needed): If Blueprint is incomplete or references unknown files, re-invoke with bind_tools(READONLY_TOOLS) + _run_tool_loop(max_turns=4)

Most tasks won't need Phase 2, avoiding tool schema tokens on every call.

5. MCP server lifecycle

  • Planner providers closed after session submit
  • Orchestrator spawns its own (shared across Architect/Dev/QA)
  • Pass-through prevents redundant GitHub API calls

Acceptance Criteria

Shipped in

  • #194READONLY_TOOLS filter + GitHub issue/PR pre-fetch foundation
  • #195 — Planner deterministic pre-fetch + TaskSpec.github_context pass-through
  • #196 — Architect two-phase read-only tool access
  • #197 — Planner system-prompt reconciliation with pre-fetched context (fixed LLM self-denial)
  • #198github_repo plumbed end-to-end + git-remote auto-detect + anti-hallucination hardening
  • #199 — Remove arbitrary issue-body truncation in pre-fetch (caps dropped context mid-AC)

Remaining work

All acceptance criteria green after #199 merges and the "Minimum height preserved (60px existing minimum is fine)" line reaches the Planner intact. Issue can close at that point.

Out of Scope

  • Write tools for Planner/Architect
  • Changing Architect output format (still JSON Blueprint)
  • Streaming tool calls to dashboard

Depends On

Effort

Large (3+ sessions) — actual: 6 PRs across 2 sessions.


See comments for session-by-session progress notes and diagnostic details.

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions