diff --git a/docs/local_agent_loop.md b/docs/local_agent_loop.md
index ed9fb54..8b8f7f3 100644
--- a/docs/local_agent_loop.md
+++ b/docs/local_agent_loop.md
@@ -14,22 +14,28 @@ 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 --> Orchestrator[Issue, task, and PR loops
orchestrator.py]
+ CLI --> Config[Config validation
config.py]
+ Config --> Orchestrator[Issue, task, and PR loops
orchestrator.py]
- Config --> Workdirs[(Agent checkouts
Claude / Codex / Gemini)]
- Config --> 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)]
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 +50,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 +64,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 +89,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