From b9b70efd3aef204b84769125b2f97ac26a41945c Mon Sep 17 00:00:00 2001 From: Wild Wind Date: Sat, 2 May 2026 01:54:56 -0700 Subject: [PATCH 1/2] Refresh architecture docs and memory map --- docs/local_agent_loop.md | 36 ++++++++++++++++++------ src/coding_review_agent_loop/cli.py | 2 +- src/coding_review_agent_loop/memory.py | 38 ++++++++++++++++++++++++-- tests/test_agent_loop.py | 5 ++++ 4 files changed, 69 insertions(+), 12 deletions(-) diff --git a/docs/local_agent_loop.md b/docs/local_agent_loop.md index ed9fb54..bd1b0cb 100644 --- a/docs/local_agent_loop.md +++ b/docs/local_agent_loop.md @@ -14,22 +14,29 @@ The default coder is Claude and the default reviewer is Codex. Reverse the direc ## Architecture The tool is a local orchestrator. It does not call model APIs directly; it shells -out to locally authenticated agent and GitHub CLIs from separate checkouts. +out to locally authenticated agent and GitHub CLIs from separate checkouts. The +only durable state it creates is local: agent logs in the active coder checkout +and optional advisory memory in a repo-scoped cache directory. ```mermaid flowchart LR User[Developer terminal] --> CLI[agent-loop CLI
cli.py] - CLI --> Config[Config and workdir setup
config.py / workdirs.py] + CLI --> Config[Config validation
config.py] CLI --> Orchestrator[Issue, task, and PR loops
orchestrator.py] - Config --> Workdirs[(Agent checkouts
Claude / Codex / Gemini)] - Config --> Logs[(.agent-loop-logs)] + Config --> Workdirs[Workdir setup and validation
workdirs.py / git / gh repo clone] + Config --> Memory[Agent memory preparation
memory.py] + Config --> Logs[(Agent logs
.agent-loop-logs)] + + Workdirs --> AgentDirs[(Separate agent checkouts
Claude / Codex / Gemini)] + Memory --> MemoryCache[(Repo-scoped memory cache
summary / architecture / tests)] Orchestrator --> Prompts[Prompt builders
prompts.py] - Orchestrator --> Protocol[Marker parsing
protocol.py] + Orchestrator --> Protocol[Marker and follow-up parsing
protocol.py] Orchestrator --> Registry[Agent registry
agents/registry.py] Orchestrator --> GitHubOps[GitHub operations
github.py] - Orchestrator --> OptionalTests[Optional local test command] + Orchestrator --> OptionalTests[Optional local test command
--test-command] + Orchestrator --> Followups[Approved follow-up handling
summaries / issues / same-PR fixes] Registry --> Claude[Claude backend
claude] Registry --> Codex[Codex backend
codex exec] @@ -44,10 +51,11 @@ flowchart LR Runner --> AgentCLIs[Local agent CLIs] Runner --> GhCLI[gh CLI] Runner --> TestCmd[Local test process] + Runner --> Logs - AgentCLIs --> Workdirs - AgentCLIs --> Logs + AgentCLIs --> AgentDirs GhCLI --> GitHub[(GitHub repo
issues / PRs / comments / checks)] + Followups --> GitHubOps ``` At runtime, the orchestrator drives one of three entrypoints: @@ -57,12 +65,15 @@ sequenceDiagram participant User as Developer participant CLI as agent-loop CLI participant Orch as Orchestrator + participant Memory as Agent memory participant Coder as Coder agent CLI participant Reviewer as Reviewer agent CLI(s) participant GH as GitHub via gh User->>CLI: agent-loop issue | task | pr - CLI->>Orch: validated config and workdirs + CLI->>Orch: validated config + Orch->>Orch: ensure active agent workdirs + Orch->>Memory: prepare advisory repo memory alt issue or task Orch->>Coder: create or update PR Coder-->>Orch: output with AGENT_PR marker @@ -79,7 +90,14 @@ sequenceDiagram Orch->>Coder: address combined feedback Coder-->>Orch: AGENT_STATE blocking Orch->>GH: post coder update + else approved review has same-PR follow-ups in a fix-and mode + Orch->>Coder: address same-PR follow-ups + Coder-->>Orch: AGENT_STATE blocking + Orch->>GH: post coder update else all approved + opt future follow-ups requested + Orch->>GH: summarize follow-ups or create issues + end Orch->>Orch: run optional local tests opt auto-merge enabled Orch->>GH: wait for configured check and merge diff --git a/src/coding_review_agent_loop/cli.py b/src/coding_review_agent_loop/cli.py index 383708e..a6c1418 100644 --- a/src/coding_review_agent_loop/cli.py +++ b/src/coding_review_agent_loop/cli.py @@ -192,7 +192,7 @@ def add_common(subparser: argparse.ArgumentParser) -> None: "--no-agent-memory", dest="agent_memory", action="store_false", - help="Disable repo-local advisory agent memory.", + help="Disable repo-scoped advisory agent memory.", ) subparser.add_argument( "--refresh-agent-memory", diff --git a/src/coding_review_agent_loop/memory.py b/src/coding_review_agent_loop/memory.py index 9c237ee..10464df 100644 --- a/src/coding_review_agent_loop/memory.py +++ b/src/coding_review_agent_loop/memory.py @@ -1,4 +1,4 @@ -"""Repo-local advisory memory for repeated agent loop runs.""" +"""Repo-scoped advisory memory for repeated agent loop runs.""" from __future__ import annotations @@ -232,10 +232,44 @@ def _write_architecture_map(path: Path, tracked_files: list[str]) -> None: for file in tracked_files: head = file.split("/", 1)[0] buckets.setdefault(head, []).append(file) - lines = ["# Architecture Map", ""] + lines = [ + "# Architecture Map", + "", + "## Top-level Layout", + "", + ] for head in sorted(buckets): examples = ", ".join(buckets[head][:8]) lines.append(f"- `{head}`: {len(buckets[head])} tracked file(s); examples: {examples}") + + python_files = [ + file for file in tracked_files if file.startswith("src/") and file.endswith(".py") + ] + if python_files: + lines.extend(["", "## Python Modules", ""]) + module_buckets: dict[str, list[str]] = {} + for file in python_files: + parts = file.split("/") + if len(parts) >= 4: + module = "/".join(parts[:3]) + else: + module = "/".join(parts[:-1]) or "src" + module_buckets.setdefault(module, []).append(file) + for module in sorted(module_buckets): + examples = ", ".join(module_buckets[module][:8]) + lines.append(f"- `{module}`: {len(module_buckets[module])} file(s); examples: {examples}") + + docs = [file for file in tracked_files if file == "README.md" or file.startswith("docs/")] + tests = [file for file in tracked_files if file.startswith("tests/")] + workflows = [file for file in tracked_files if file.startswith(".github/workflows/")] + if docs or tests or workflows: + lines.extend(["", "## Supporting Surfaces", ""]) + if docs: + lines.append(f"- Docs: {', '.join(docs[:8])}") + if tests: + lines.append(f"- Tests: {', '.join(tests[:8])}") + if workflows: + lines.append(f"- GitHub Actions: {', '.join(workflows[:8])}") path.write_text("\n".join(lines) + "\n", encoding="utf-8") diff --git a/tests/test_agent_loop.py b/tests/test_agent_loop.py index f2dd060..89567f1 100644 --- a/tests/test_agent_loop.py +++ b/tests/test_agent_loop.py @@ -704,6 +704,11 @@ def test_agent_memory_is_created_and_added_to_review_prompt(tmp_path): assert (memory_dir / "test-profile.md").exists() assert (memory_dir / "toolchain.json").exists() assert (memory_dir / "last-analyzed-commit").read_text(encoding="utf-8") == "abc123\n" + architecture_map = (memory_dir / "architecture-map.md").read_text(encoding="utf-8") + assert "## Top-level Layout" in architecture_map + assert "## Python Modules" in architecture_map + assert "## Supporting Surfaces" in architecture_map + assert "`src/coding_review_agent_loop`" in architecture_map prompt = next(cmd[-1] for cmd, _cwd in runner.commands if cmd[:2] == ["codex", "exec"]) assert "Agent memory context:" in prompt From cb9a981a2f8189879453c05b71050b860ad8cbc3 Mon Sep 17 00:00:00 2001 From: Wild Wind Date: Sat, 2 May 2026 02:00:31 -0700 Subject: [PATCH 2/2] Fix architecture flowchart control flow --- docs/local_agent_loop.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/local_agent_loop.md b/docs/local_agent_loop.md index bd1b0cb..8b8f7f3 100644 --- a/docs/local_agent_loop.md +++ b/docs/local_agent_loop.md @@ -22,11 +22,10 @@ and optional advisory memory in a repo-scoped cache directory. flowchart LR User[Developer terminal] --> CLI[agent-loop CLI
cli.py] CLI --> Config[Config validation
config.py] - CLI --> Orchestrator[Issue, task, and PR loops
orchestrator.py] + Config --> Orchestrator[Issue, task, and PR loops
orchestrator.py] - Config --> Workdirs[Workdir setup and validation
workdirs.py / git / gh repo clone] - Config --> Memory[Agent memory preparation
memory.py] - Config --> Logs[(Agent logs
.agent-loop-logs)] + Orchestrator --> Workdirs[Workdir setup and validation
workdirs.py / git / gh repo clone] + Orchestrator --> Memory[Agent memory preparation
memory.py] Workdirs --> AgentDirs[(Separate agent checkouts
Claude / Codex / Gemini)] Memory --> MemoryCache[(Repo-scoped memory cache
summary / architecture / tests)]