Run macroscope codereview --raw for machine-readable output

The CLI now launches an interactive TUI when attached to a terminal; `--raw`
forces the streamed `issue_event=` records the parser consumes, regardless of
how the host spawns the subprocess. Verified end-to-end against the current
CLI build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bill Easton
2026-07-20 10:21:57 -05:00
co-authored by Claude Opus 4.8
parent ba447822aa
commit 31a34ebae0
4 changed files with 16 additions and 4 deletions
+4
View File
@@ -41,6 +41,10 @@ missing, the tool returns the install command; if a review never starts
(usually because you are not signed in), the tool tells the agent to run
`macroscope` to finish setup.
The tool invokes `macroscope codereview --raw` for machine-readable streaming
output, which needs a recent CLI build. The installer fetches the latest and the
CLI self-updates on use, so a fresh install satisfies this.
## The tool
| Tool | Purpose |
+4
View File
@@ -49,6 +49,10 @@ authenticate on your behalf, so do this once on the host:
This writes `~/.macroscope/config.yaml`.
The tool invokes `macroscope codereview --raw` for machine-readable streaming
output, which needs a recent CLI build. The installer fetches the latest and the
CLI self-updates on use, so a fresh install satisfies this.
If the binary is missing, the tool returns the install command. If a review never
starts (usually because you are not signed in), the tool tells the agent to run
`macroscope` to finish setup.
+5 -1
View File
@@ -135,7 +135,11 @@ class MacroscopeToolset(FunctionToolset[AgentDepsT]):
"""
if shutil.which(self._command) is None:
raise ModelRetry(_INSTALL_HINT)
args = [self._command, 'codereview']
# `--raw` forces the machine-readable `issue_event=` stream instead of the interactive
# TUI the CLI shows on a terminal, so parsing works regardless of whether the host
# attaches a pty to the subprocess. Needs a recent macroscope build (the CLI added the
# flag mid-2026 and self-updates on invocation).
args = [self._command, 'codereview', '--raw']
base_ref = base if base is not None else self._base
if base_ref is not None:
args += ['--base', base_ref]
+3 -3
View File
@@ -100,7 +100,7 @@ class TestRunReview:
assert review.review_id == 'rev-1'
assert review.status == 'completed'
assert len(review.issues) == 1
assert _recorded_args(command) == ['codereview', '--base', 'main']
assert _recorded_args(command) == ['codereview', '--raw', '--base', 'main']
async def test_clean_review_has_no_issues(self, tmp_path: Path) -> None:
command = _fake_cli(tmp_path, ['review_id=rev-2', 'issue_status=completed'])
@@ -110,7 +110,7 @@ class TestRunReview:
async def test_per_call_base_overrides_configured_base(self, tmp_path: Path) -> None:
command = _fake_cli(tmp_path, ['review_id=rev-3', 'issue_status=completed'])
await _toolset(command, tmp_path, base='develop').run_macroscope_review(base='release')
assert _recorded_args(command) == ['codereview', '--base', 'release']
assert _recorded_args(command) == ['codereview', '--raw', '--base', 'release']
async def test_missing_binary_raises_model_retry(self, tmp_path: Path) -> None:
toolset = _toolset('pai-harness-macroscope-absent', tmp_path)
@@ -137,7 +137,7 @@ class TestRunReview:
# With no configured or per-call base, `--base` is dropped so the CLI picks the base itself.
command = _fake_cli(tmp_path, ['review_id=rev-5', 'issue_status=completed'])
await _toolset(command, tmp_path, base=None).run_macroscope_review()
assert _recorded_args(command) == ['codereview']
assert _recorded_args(command) == ['codereview', '--raw']
class TestCapability: