fix(acp): name the adapter that spawned, not the seam - #9135
Conversation
GPT 5.6 Review (fork) — 🔴 changes requested (blocking)Reviewed 1 of 1 blocking finding(s) are security-class and were withheld from adjudication, so the blocking verdict stands. BLOCKING -- src/kiro_crew/acp/client.py:5171 -- adapter-only state changes the Kiro construction path Adjudication (Opus 4.8) — is blocking on each finding proportionate?The adjudicable block is empty (0 findings). One fenced finding, F1. F1 — H13 parity, Conditions to reach the claimed harm (adapter state affecting the Kiro label):
Behavior on the Kiro path: The [ADJUDICATION] f08ce4e total=0 uphold=0 downgrade=0 [ADJUDICATION-FENCED] f08ce4e fenced=1 flagged=1 🏷️ Fenced finding(s) machine-flagged as likely edge caseThe security fence keeps these findings blocking regardless of adjudication; the only clearance path is a human override recorded by a repository writer, who must independently verify a rationale before recording it — it is machine-authored, and a wrong override on a security-class finding ships exactly the class the fence exists to stop. (This lane's comment deliberately carries no override command.)
|
Design Review (Fable 5, fork) — ✅ PASSDesign-level review of Design-Verdict: PASS Label is derived from the resolved argv — the one authority on what launched — at the right layer, pre-wrap, with the seam prefix preserved for parsers. Suggestions
[DESIGN-REVIEWED] f08ce4e |
Opus 4.8 Review (fork) — ✅ no blocking findingsReviewed Review detailsNo findings. The sole candidate is a log-label refactor its own author scored low: [OPUS-REVIEWED] f08ce4e |
First Principles Review (Fable 5, fork) — 🟡 CONCERNSPremise-level review of All evidence gathered. Verifying the sibling claim precisely before writing the review: the kiro-cli branch's label at base First-Principles-Verdict: CONCERNS The named root cause has one counted unfixed sibling: the kiro-cli branch, overridable via Not justified as shipped
What this change shipsIntent: make the spawn and stderr log lines name the adapter that actually launched, not the seam's default — a FIX.
Watch
Subtractions
[FIRST-PRINCIPLES-REVIEWED] f08ce4e |
761b37d to
43bad8c
Compare
43bad8c to
1c90b7a
Compare
1c90b7a to
f86fc56
Compare
|
@Premshay Thanks for the detailed writeup. The defect is real and nothing on Three things before it can land, audited at 1c90b7a:
One thing worth declaring in the body: the claude stderr prefix changes from Posted from the 2026-09-08 open-PR relationship audit (read-only, one auditor per PR); reply here if any of this is wrong. |
153aede to
50d487c
Compare
50d487c to
f08ce4e
Compare
Problem / Motivation
AcpClient._spawnlogsSpawned claude-agent-acp (PID n), and_drain_stderrprefixes adapter stderr with
claude-acp, from fixed strings chosen by whichseam the session took. But both seams resolve their binary through a documented
environment override —
CLAUDE_AGENT_ACP_BIN(resolution order step 1) andCODEX_ACP_BIN— and either may point at a dispatch shim, a vendored build, ora wrapper that is not the seam's own adapter. In that configuration every log
line names a program that did not run.
Why it matters
The override exists precisely so an operator can put a different adapter behind
a seam, and these two lines are the only place the running adapter is named.
They are therefore most misleading in exactly the setup they are most needed
for: an operator reading the log to confirm which engine a session got is told
the seam's default, confidently and wrongly. Downstream automation that parses
the line reaches the same wrong conclusion, and stderr from a non-default
adapter is filed under the wrong program.
What changed (motivation → approach → change)
Symptom: the spawn and stderr labels report the seam, not the adapter.
Root cause: both labels are constants selected by
self._is_claude/self._is_codex, while the resolved command is already in scope asargvandis the only authority on what launched.
Change: each ACP seam now keeps its stable name and appends the pre-wrap
resolved command (for example,
claude-agent-acp via /path/to/index.js). Aleading
nodeorbunlauncher yields the entry-script path, avoiding theambiguous default
index.jslabel._spawnretains the adapter label for itsseparate stderr task; Claude stderr preserves its established
claude-acpprefix. The
kiro-clibranch is unchanged.Tests
test/test_acp_spawn_label.py:node/node.execarrying an entry script yields the script, not theinterpreter;
nodewith nothing after it, fall back rather thanproducing an empty label;
explicitly not as
claude-agent-acp— the regression this fixes.Manual verification
Confirmed against a live gateway whose
CLAUDE_AGENT_ACP_BINpoints at a shimthat
execs a different adapter: before the change the log readSpawned claude-agent-acpwhile the spawned process tree was the otheradapter's; the resolved argv the fix reads is the same value the process tree
shows.
Related Issues
N/A — found while diagnosing a misreported adapter in a live deployment.
Pattern harvest
Rule candidate: review-prompt
Pattern: a log label hardcoded to a branch's nominal identity while the actual
value is already in scope (a resolved argv, a resolved path, a chosen binary).
The line then reports which branch was taken rather than what was done, and is
wrong exactly when an override makes the two differ — the case the reader is
consulting it about.
Checklist
feat|fix|docs|refactor|perf|test|chore|ci|build|revert: ...)Contribution License Agreement
N/A — template placeholder; no CLA wording is supplied.