refactor(a2a): update test files for ACP to A2A rename #737
No reviewers
Labels
No labels
auto/needs-reevaluation
controller-managed
auto/blocked-by-deps
auto/ci-timeout
auto/claimed-implementer
auto/claimed-merge
auto/claimed-reviewer
auto/driver-down
auto/invariant-violation
auto/last-attempt-tier-0
auto/last-attempt-tier-1
auto/last-attempt-tier-2
auto/last-attempt-tier-min
Automation Tracking
auto/needs-conflict-resolution
auto/needs-implementer
auto/postmortem
auto/ready-to-merge
auto/restart-throttled
auto/revert
auto/sentinel
auto/stale-inactivity
auto/unstable
Blocked
Bounty
$100
Bounty
$1000
Bounty
$10000
Bounty
$20
Bounty
$2000
Bounty
$250
Bounty
$50
Bounty
$500
Bounty
$5000
Bounty
$750
MoSCoW
Could have
MoSCoW
Must have
MoSCoW
Should have
Needs Feedback
Points
1
Points
13
Points
2
Points
21
Points
3
Points
34
Points
5
Points
55
Points
8
Points
88
Priority
Backlog
Priority
CI Blocker
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Signed-off: Owner
Signed-off: Scrum Master
Signed-off: Tech Lead
Spike
State
Completed
State
Duplicate
State
In Progress
State
In Review
State
Paused
State
Unverified
State
Verified
State
Wont Do
Type
Automation
Type
Bug
Type
Discussion
Type
Documentation
Type
Epic
Type
Feature
Type
Legendary
Type
Refactor
Type
Support
Type
Task
Type
Testing
No project
No assignees
4 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
cleveragents/cleveragents-core!737
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "refactor/m7-acp-to-a2a-tests"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
vulture_whitelist.py(lines 633, 957) that were missed by the source rename in PR #705Audit Results
All 6 acceptance criteria from Issue #689 are satisfied on
origin/master:Only remaining gaps were 2 stale comments in
vulture_whitelist.py, fixed in this PR.Closes #689
Code Review Report -- PR #737 / Branch
refactor/m7-acp-to-a2a-testsScope: Full review of the ACP-to-A2A rename (PR #705 commit
ec0b7631, PR #737 commit54e52b57), cross-referenced againstdocs/specification.mdand issue #689 acceptance criteria.Review cycles: 3 global passes covering bugs, security, specification compliance, test flaws, test coverage gaps, test isolation, and performance.
Rename status: The ACP-to-A2A rename in source code, test files, feature files, Robot files, and JSON fixtures is complete. Zero stale
Acp*class names,acp.*structlog events, oracp_versionfield names remain in code. The vulture whitelist comment fix in this PR is correct.Summary Table
HIGH Severity
SC-1. Error codes are strings, not JSON-RPC 2.0 integers
File:
src/cleveragents/a2a/errors.py:32-39,src/cleveragents/a2a/models.py:53The specification (
specification.md:43211-43229) requires JSON-RPC 2.0 integer error codes:The implementation uses string codes (
"NOT_FOUND","PLAN_ERROR", etc.) andA2aErrorDetail.codeis typed asstr. Clients dispatching on integer codes per the spec will break.SC-2.
map_domain_errormissing 2 spec-required exception mappingsFile:
src/cleveragents/a2a/errors.py:100-139The specification maps
DuplicateEntityErrorto-32005andBudgetExceededErrorto-32006. Neither exception type appears inmap_domain_error. These will silently fall through to the genericINTERNAL_ERRORcatch-all.TC-1.
map_domain_error-- 3 of 8 exception branches untestedFile:
src/cleveragents/a2a/errors.py:131-136No test exercises:
AuthenticationError->AUTH_ERRORAuthorizationError->FORBIDDENConfigurationError->CONFIGURATION_ERRORThese are production error paths with zero coverage.
MEDIUM Severity
B-1.
publish()iterates subscription dict directly -- re-entrancy crashFile:
src/cleveragents/a2a/events.py:56If any callback calls
subscribe_local(),unsubscribe(), orclose(), the dict is mutated during iteration, raisingRuntimeError: dictionary changed size during iteration. This is a single-threaded re-entrancy bug, not just a threading concern.Fix:
for sub_id, callback in list(self._subscriptions.items()):B-2.
subscribe_local()succeeds on a closed queueFile:
src/cleveragents/a2a/events.py:65-72After
close()sets_is_closed = Trueand clears_subscriptions, callingsubscribe_local()silently adds a new entry to the cleared dict. The subscription will never receive events. No guard checks_is_closed.SC-3. Operation names don't match specification convention
File:
src/cleveragents/a2a/facade.py:57-69The specification (
specification.md:43091-43116) defines standard operations assession/new,session/load,session/prompt, etc. and extensions as_cleveragents/plan/use,_cleveragents/plan/execute, etc. The implementation uses a different naming convention (session.create,plan.create,plan.execute, etc.) that doesn't align with either.SC-4. No Agent Card model or
/.well-known/agent.jsondiscoveryThe specification (
specification.md:43187-43207) requires Agent Card discovery. NoAgentCardmodel or discovery endpoint exists anywhere in the codebase.SC-5.
A2A-VersionHTTP header not implementedFile:
src/cleveragents/a2a/versioning.pyVersion negotiation logic exists but is not wired to the HTTP transport layer. The specification (
specification.md:43234) requiresA2A-Versionheader on requests/responses.TC-2. 5
A2aEventQueueinput validation guards untestedFile:
src/cleveragents/a2a/events.py:48-49, 67-68, 76-77, 85-86, 111-112Guards for
publish()with non-A2aEvent,subscribe_local()with non-callable,unsubscribe()with empty string,get_events()with invalid limit, andsubscribe_remote()with empty endpoint are all untested.TC-3.
_cleanup_session_devcontainersnot tested via facadeFile:
src/cleveragents/a2a/facade.py:252-279The
session.closehandler calls_cleanup_session_devcontainers()which dynamically importsCleanupService. This entire code path (deferred import, try/except, logging) is never exercised by any A2A test.TC-4.
A2aHttpTransportandA2aVersionNegotiatorinput guards untestedFiles:
src/cleveragents/a2a/transport.py:30-31, 47-48,src/cleveragents/a2a/versioning.py:31-32, 44-45Validation guards for
send()with non-A2aRequest,connect()with empty URL,negotiate()with empty string, andis_supported()with empty string have zero test coverage.TC-5.
map_domain_errorcatch-all paths untestedFile:
src/cleveragents/a2a/errors.py:120-121, 137-139The
TypeErrorguard for non-Exception input (line 120), the genericCleverAgentsErrorfallback (line 137), and the plainExceptioncatch-all (line 139) are untested.TC-6. Weak error assertions -- no error code validation
File:
features/a2a_facade_wiring.feature:23-26, 39-42session.closeandplan.createvalidation failure tests only assertstatus == "error"without checking the error code or message. A bug that returns the wrong error code would pass.P-1. Unbounded
_eventslist growth -- memory leakFile:
src/cleveragents/a2a/events.py:31, 50self._eventsgrows without limit. No max size, TTL, or eviction policy. In a long-running process, this accumulates all events forever.TF-1. No-op assertion --
step_service_registeredalways passesFile:
features/steps/a2a_facade_steps.py:57-59Should assert the service is actually registered in the facade's service dict.
TI-1. Benchmark queue grows unboundedly across iterations
File:
benchmarks/a2a_facade_bench.py:107-118time_publish_singleandtime_publish_100append to the queue across ASV iterations without clearing. Memory bloats andget_events()becomes progressively slower, producing non-representative benchmark results.TI-2. Benchmark subscriber accumulation
File:
benchmarks/a2a_facade_bench.py:117-118time_subscribe_localadds a new subscriber per ASV iteration. After thousands of iterations, everypublish()call fans out to thousands of callbacks, completely skewing timing results.LOW Severity
B-3. 6 facade stub handlers skip validation
File:
src/cleveragents/a2a/facade.py:242, 288, 303, 313, 328, 342When services are
None, stub handlers forsession.close,plan.create,plan.execute,plan.status,plan.diff, andplan.applyreturn success responses without validating required parameters. The service-present paths validate. This creates behavioral divergence between modes -- tests written against stubs accept emptyplan_id/session_idthat would fail with real services.B-4.
A2aOperationNotFoundErrorbypasses error response wrappingFile:
src/cleveragents/a2a/facade.py:138-139All other exceptions get wrapped in
A2aResponse(status="error"). This error is re-raised directly, forcing callers to handle two different error shapes.S-1. No length/charset constraint on operation name
File:
src/cleveragents/a2a/models.py:76-81The
_operation_non_emptyvalidator only checks non-empty. An operation string with\ncharacters could inject fake log lines via structlog output. Recommend:re.match(r'^[a-z][a-z0-9_.]{0,63}$', value).S-2.
paramsandauthfields accept arbitrary unvalidated dataFile:
src/cleveragents/a2a/models.py:73-74auth: dict[str, Any] | Nonehas no schema or key constraints. Low risk in local mode but a deserialization concern if the model handles external HTTP input.S-3. No SSRF protection on
server_urlFile:
src/cleveragents/a2a/server_config.py:34-42Validates http/https scheme but accepts
http://169.254.169.254/,http://localhost:6379/, etc. Design gap to fix before server mode goes live.S-4.
str(exc)in error mapping could leak sensitive infoFile:
src/cleveragents/a2a/errors.py:124-139If domain exceptions include tokens/credentials in their message strings,
str(exc)propagates them intoA2aResponse.error.messageand into logs atfacade.py:155.SC-6. 2 stale ADR filenames (outside PR scope but related)
docs/adr/ADR-047-acp-standard-adoption.mdshould beADR-047-a2a-standard-adoption.mddocs/adr/ADR-026-agent-client-protocol.mdshould beADR-026-agent-to-agent-protocol.mdmkdocs.yml:70andspecification.mdat lines 55, 23304, 23373, 42992, 43253TF-2. Trivially true assertions in facade steps
File:
features/steps/a2a_facade_steps.py:399-401, 425-427assert context.response is not Noneandassert context.error_detail is not Nonecan never fail once the preceding step assigns them.TF-3. Type-coercing assertion hides type mismatch
File:
features/a2a_facade_wiring.feature:93, step ata2a_facade_wiring_steps.py:213-215Uses
str(actual) == valuewhich convertsTrue(bool) to"True"(string), masking type-correctness issues. Compare torobot/helper_a2a_facade_wiring.py:196which correctly usesis True.TF-4. Tautological protocol-default-body tests
File:
features/steps/a2a_clients_coverage_boost_steps.py:133-137Protocol default bodies are
...(Ellipsis) which is a no-op. Testing "no exception was thrown" is trivially guaranteed for 7 scenarios.TF-5. Hardcoded magic number 11 for operation count
File:
robot/helper_a2a_facade.py:95-96len(ops) == 11breaks silently if_SUPPORTED_OPERATIONSchanges. Should derive from source of truth.TF-6. Mock
deletenot verified with correct argumentFile:
features/steps/a2a_facade_wiring_steps.py:77-81session.closetest doesn't assertsvc.delete.assert_called_once_with("MOCK-SESSION-001"). A bug that passes the wrongsession_idwould be undetected.TC-7 through TC-13. Additional coverage gaps (low priority)
plan.execute/status/diff/applywithout service) untestednamespace,type_name) untestedclose()double-call idempotency untestedmap_domain_errorwith genericRuntimeErroruntestedTI-3. Triplicated mock infrastructure
Files:
a2a_facade_coverage_boost_steps.py:34-54,a2a_facade_wiring_steps.py:42-90,robot/helper_a2a_facade_wiring.py:36-95Three files define near-identical
_MockPlanIdentity,_MockPlan, and builder functions. Divergence risk on service contract changes.P-2.
disconnect()raises in teardown contextsFile:
src/cleveragents/a2a/transport.py:41-47A2aHttpTransport.disconnect()raisesA2aNotAvailableError. If called in afinallyblock, this masks the original exception. Consider returning silently likeis_connected()returnsFalse.Positive Findings
server.py,lsp.py, andlsp/server.pyall have correct A2A imports and no stale references.CleanupServiceimport infacade.pyis safe.register_serviceis correctly implemented.CleverAgentsErrorpattern correctly.Reviewed by automated code review agent. 3 global review cycles performed across all categories (bugs, security, spec compliance, test flaws, test coverage, test isolation, performance). Cross-referenced against
docs/specification.md(sections 43087-43248 for A2A architecture) and issue #689 acceptance criteria.Review — PR #737: refactor(a2a): update stale ACP comments in vulture whitelist
Diff Summary
vulture_whitelist.py)Commit Message Compliance
refactor(a2a): update test files for ACP to A2A renamerefactor(a2a): update stale ACP comments in vulture whitelistrefactor(a2a): update test files for ACP to A2A renamebut the PR commit uses a different message. Per CONTRIBUTING.md, the commit message first line must match the issue metadata's Commit Message field exactly.I understand the PR only covers the final 2 stale comments (the bulk of the rename was done in PR #705), so the commit message is more descriptively accurate for this PR's scope. However, the project convention requires it to match the issue metadata. Options:
Closes Keyword
ISSUES CLOSED: #689❌ — This is not a standard Forgejo auto-close keyword. Forgejo recognizes:close,closes,closed,fix,fixes,fixed,resolve,resolves,resolved(followed by#N). Please change toCloses #689.Label Compliance
Type/TaskPriority/Medium)MoSCoW/Must have)Code Quality
vulture_whitelist.py.Required Changes
ISSUES CLOSED: #689withCloses #689in the PR body.Priority/MediumandMoSCoW/Must have.54e52b574c0038b737c1refactor(a2a): update stale ACP comments in vulture whitelistto refactor(a2a): update test files for ACP to A2A renameFollow-up Issues from Code Review
The review by @CoreRasurae identified several pre-existing bugs and spec compliance gaps in the A2A module (
src/cleveragents/a2a/). These are outside the scope of this PR (#689 — ACP→A2A test rename) and should be tracked as separate issues.All findings below have been validated against the source code and
docs/specification.md.HIGH — Spec Compliance
1. Error codes are strings, not JSON-RPC 2.0 integers
errors.py:32-39defines codes as"NOT_FOUND","PLAN_ERROR", etc.models.py:53typesA2aErrorDetail.codeasstrspecification.md:43211-43229) requires integer codes:-32001(entity not found) through-32008(plan error), plus reserved-32600to-32603int, changeA2aErrorDetail.code: int, updatemap_domain_errorreturn type totuple[int, str]2.
map_domain_errormissing spec-required exception mappingsDuplicateEntityError→-32005andBudgetExceededError→-32006src/cleveragents/core/exceptions.pyerrors.py:100-139core/exceptions.py, add branches inmap_domain_error3. 3 of 8 exception branches in
map_domain_erroruntestedAuthenticationError→AUTH_ERROR,AuthorizationError→FORBIDDEN,ConfigurationError→CONFIGURATION_ERRORhave zero test coveragerobot/helper_a2a_facade_wiring.py:216-232)HIGH — Bugs
4.
publish()re-entrancy crashevents.py:56:for sub_id, callback in self._subscriptions.items()iterates dict directlysubscribe_local(),unsubscribe(), orclose(), raisesRuntimeError: dictionary changed size during iterationlist(self._subscriptions.items())5.
subscribe_local()succeeds on a closed queueevents.py:65-72: no_is_closedguard — silently adds subscriptions that will never firepublish()has the guard (line 46),subscribe_local()doesn'tif self._is_closed: raise RuntimeError(...)guardMEDIUM — Spec Compliance
6. Operation names don't match spec convention
facade.py:57-69uses dot-delimited names:session.create,plan.execute, etc.specification.md:23422-23433, 43107-43114) uses slash-delimited with_cleveragents/prefix:_cleveragents/plan/use,_cleveragents/plan/execute,_cleveragents/registry/{entity}/list, etc.MEDIUM — Performance
7. Unbounded
_eventslist growthevents.py:31,50:_eventsgrows without limit;get_events()never removes; no max size/TTL/evictionclose()clears — in a long-running process, memory grows indefinitelymax_sizeparameter with oldest-event eviction on overflowLOW — Test Quality
8. No-op step assertion
a2a_facade_steps.py:57-59:step_service_registeredbody ispass— asserts nothing0038b737c18b1dfe8510Code Review — PR #737: refactor(a2a): update test files for ACP to A2A rename
Reviewer: @brent.edwards
Commit reviewed:
8b1dfe85Review cycles: 2 full passes + 4 parallel verification threads (ACP reference audit, vulture whitelist accuracy, issue #689 acceptance criteria, CONTRIBUTING.md compliance)
Verification of Previous Requested Changes (@freemo)
All three items from @freemo's REQUEST_CHANGES review (commit
54e52b57) have been addressed in the force-pushed commit8b1dfe85:refactor(a2a): update test files for ACP to A2A renameISSUES CLOSED: #689withCloses #689in PR bodyCloses #689Priority/MediumandMoSCoW/Must havelabelsCode Correctness
Diff scope: 1 file changed (
vulture_whitelist.py), +2/−2 lines. Both changes are comment-only.Change 1 (line 633):
ACP→A2Ain facade wiring section headerVerified correct. The error codes and facade wiring symbols referenced by this section (
NOT_FOUND,VALIDATION_ERROR,INVALID_STATE,PLAN_ERROR,AUTH_ERROR,FORBIDDEN,CONFIGURATION_ERROR,INTERNAL_ERROR,map_domain_error,_session_service,_plan_lifecycle_service,_tool_registry,_resource_registry_service,_event_queue,_cleanup_session_devcontainers) all live insrc/cleveragents/a2a/errors.pyandsrc/cleveragents/a2a/facade.py. All 15 whitelist entries below this comment are valid.Change 2 (line 957):
ACP→A2Ain LspServer facade property commentVerified correct.
src/cleveragents/lsp/server.pydefinesLspServer.facadeas a lazy property that creates anA2aLocalFacadeinstance (imported fromcleveragents.a2a.facade). The module docstring and property docstring both reference "A2A". The old "ACP" comment was stale.Rename Completeness (Issue #689 Acceptance Criteria)
Exhaustive audit across
features/,robot/,benchmarks/, andfeatures/fixtures/confirms all 6 statically verifiable acceptance criteria are satisfied:a2a_*files found, zeroacp_*filescleveragents.acp→cleveragents.a2a)a2aimport lines found, zeroacpimportsa2a_facade_flows.jsonuses A2A namingThe bulk of the rename was completed in PR #705 (already on master). This PR correctly fixes the only 2 remaining stale comments in
vulture_whitelist.py. After this PR merges, zeroacp/ACPreferences will remain in any code or test file (only legitimate historical references in ADR docs andspecification.md).PR Metadata Compliance
Closes #689)Type/Tasklabel presentv3.6.0matches issue232ef965)Findings
P3:nit — No changelog entry
CONTRIBUTING.md PR requirement #6 requires a changelog update for every PR. This is a 2-line comment-only change with zero user-facing impact, so a changelog entry is arguably unnecessary. Noting for completeness — author's discretion.
P3:nit — Verify Forgejo dependency link direction
CONTRIBUTING.md requires the PR to be configured as "blocking" issue #689 (and issue #689 to "depend on" this PR). Please confirm this dependency link is set with the correct direction.
Verdict
APPROVED. The code change is trivially correct, the ACP→A2A rename is verified complete across all test infrastructure, and all of @freemo's requested changes have been addressed. Only P3 nits remain, which are at the author's discretion per the review playbook.
Note: @freemo's REQUEST_CHANGES review from the previous commit is still active and will need to be re-approved or dismissed before merge.
Reviewed by @brent.edwards. 2 review cycles + 4 parallel verification threads (ACP reference audit, vulture whitelist symbol verification, issue #689 acceptance criteria, CONTRIBUTING.md compliance).
Approve
8b1dfe85104133c46aff