Skip to content

plan: add item 8 to post-Tier-1B follow-ups (PR-E3 \u2014 intra-JVM CALLS invariant guard)#21

Merged
HumanBean17 merged 2 commits into
masterfrom
plan/post-tier1b-add-item8
May 5, 2026
Merged

plan: add item 8 to post-Tier-1B follow-ups (PR-E3 \u2014 intra-JVM CALLS invariant guard)#21
HumanBean17 merged 2 commits into
masterfrom
plan/post-tier1b-add-item8

Conversation

@HumanBean17
Copy link
Copy Markdown
Owner

What

Adds item 8 to plans/PLAN-POST-TIER1B-FOLLOWUPS.md: an intra-JVM CALLS invariant guard for pass3_calls. Originated as a deferred catch from the PR-E1 review reply.

Also bumps the file's status header to reflect that PR-E1 shipped and PR-E2 / PR-E3 are outstanding.

Why

CALLS edges represent intra-JVM method dispatch \u2014 by Java's runtime model, a method call cannot leave the JVM. Anything crossing a microservice boundary must be HTTP_CALLS or ASYNC_CALLS.

Today's clean state is empirically verified but incidental:

fixture: tests/fixtures/cross_service_smoke
Total CALLS edges: 9
Cross-microservice CALLS edges: 0

Pass3 has no caller.microservice == callee.microservice filter. The cleanliness comes from the structural fact that real Maven/Gradle modules don't share classpaths and fixtures replicate that. But the invariant is implicit, not enforced.

Failure modes the guard would catch:

  1. FQN collision across services \u2014 two services declaring the same FQN (shared DTO copy-paste) hit the overload_ambiguous branch at build_ast_graph.py:1119.
  2. Brownfield supertype/role overrides \u2014 future Layer-4 / Enhanced Role Recognition work could in principle introduce a phantom resolution that crosses the boundary.
  3. Refactors of _resolve_and_emit_call \u2014 a future contributor could add a fallback resolution path that doesn't realise the implicit invariant exists.

What's in the new PR-E3 spec

  • ~10-line guard in pass3 candidate-emit branches
  • New CallResolutionStats.skipped_cross_service counter
  • New graph_meta.pass3_skipped_cross_service field
  • New tests/fixtures/fqn_collision_smoke/ (two services declaring the same FQN, third file calls it)
  • One test asserting (a) guard fires \u2265 1 time and (b) zero cross-service CALLS edges in the resulting graph
  • Existing fixtures continue to show counter == 0 (verified by extending one existing meta assertion)

Estimated size: tiny. ~10 production lines + one Java fixture pair + one test. Safe to ship before or after PR-E2 \u2014 they touch different files.

Tests

No code changes \u2014 plan-only. Tier 1B baseline (262 passed, 4 skipped after PR-E1) preserved.

Files

  • plans/PLAN-POST-TIER1B-FOLLOWUPS.md \u2014 added row 8 to the origin table; added PR-E3 section with background / failure modes / resolution / tests / DoD / risk; bumped status header; refreshed PR-boundaries section.

Captures the deferred catch from the PR-E1 review reply (#19): pass3
doesn't enforce that CALLS edges stay within a single microservice.
Today's clean state on cross_service_smoke (9 CALLS edges, 0 cross)
is incidental \u2014 no caller.microservice == callee.microservice guard
exists. FQN collisions across services or future brownfield supertype
overrides could break the invariant silently.

PR-E3 spec:
- ~10-line guard in pass3_calls candidate-emit branches
- new CallResolutionStats.skipped_cross_service counter
- new graph_meta.pass3_skipped_cross_service field
- new fqn_collision_smoke fixture
- one test asserting guard fires + zero cross-service CALLS edges
- existing fixtures continue to show counter == 0

Also flips the status header to reflect PR-E1 shipped + PR-E2/PR-E3
outstanding, and bumps the PR-boundaries section.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant