Skip to content

Add a runtime jar dependency closure test and agent skills for runtime deps - #549

Open
ludoch wants to merge 4 commits into
mainfrom
agent-skills-runtime-deps
Open

ludoch wants to merge 4 commits into
mainfrom
agent-skills-runtime-deps

Conversation

@ludoch

@ludoch ludoch commented Oct 24, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #548 → #547. Only the last commit is new. The closure test needs the runtime jars from #547/#548 to pass, so retarget to main after they are merged.

RuntimeJarDependencyClosureTest (CI guard)

runtime/test/src/test/java/com/google/apphosting/runtime/RuntimeJarDependencyClosureTest.java, parameterized over runtime-impl-jetty12.jar and runtime-impl-jetty121.jar:

  • Runs jdeps -verbose:class (through ToolProvider) on the jar from the runtime deployment, with runtime-main.jar and the runtime-shared-*.jar on the class path.
  • Walks every class reachable from com.google.appengine.* / com.google.apphosting.* through the bundled libraries.
  • Fails on any missing class outside a short KNOWN_MISSING_PACKAGES list. The listed exceptions are pre-existing, on unused paths, each with a reason: antlr for the borgcron Groc parser, google-api-client for the Cloud Datastore v1 client, io.grpc.alts (DirectPath), Jetty ALPN, and JNDI transactions.
  • The failure message lists each missing class with the reference chain, e.g. com.google.auth.Credentials <- com.google.appengine.api.taskqueue.CloudTasksClientWrapper.
  • Skipped (assumption) if jdeps isn't available (JRE only). It takes about 4 s per jar.

Verified:

  • With the jars of this branch, both pass.
  • With the jars built from main: both fail, 88 missing classes per jar (Cloud Tasks v2/v2beta3, gRPC, gax, com.google.auth, and com.google.api.client.http used by the Cloud Datastore v1 client).

Agent skills (Antigravity and Claude Code)

The skills live in .agent/skills/<name>/SKILL.md (Antigravity's workspace skills location). .claude/skills is a symlink to ../.agent/skills, so Claude Code reads the same files. Both use the same SKILL.md format (YAML name/description + Markdown).

Skill Triggers on Covers
runtime-jar-deps Changes to API classes bundled in the runtime jars, or to the runtime_impl shade config Why the runtime class loader needs its own bundled libraries, running the closure test, fixing the artifactSet, ServicesResourceTransformer, internal BUILD note
internal-runtime-usage Changes to public API classes or their feature flags Finding runtime callers (DeferredDatastoreSessionStore, DeferredTaskServlet, SweeperServlet, ...), e2e testing with the flag on (CloudTasksSessionTest as template), internal BUILD note
pom-dependency-change Removing/adding dependencies, includes, relocations; version bumps and Dependabot PRs git log -S history, dependency trees, which shaded jar to check, guarded pins like okio.version, scripts/jar_size_diff.sh for the PR size report
runtime-e2e-tests Building/running runtime/test Build commands (-pl runtime/deployment,runtime/test -am -DskipITs), full-JDK requirement, JDK-dependent test parameters, local failures that are not regressions, Cloud Tasks calling the real endpoint

Verified in both tools:

  • Claude Code: the four skills are discovered through the .claude/skills symlink and listed as available skills.
  • Antigravity (agy CLI): the skills in .agent/skills/ are discovered and loaded automatically; following runtime-jar-deps, RuntimeJarDependencyClosureTest passed (2 tests, 0 failures); scripts/jar_size_diff.sh runs (see this comment).

All new files carry the Apache copyright header; in SKILL.md it follows the YAML frontmatter, which must come first for both tools to read the skill's name and description.

On Windows checkouts without symlink support, .claude/skills is a plain file; Antigravity is unaffected.

@ludoch

ludoch commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator Author

Verified that the new skills in .agent/skills/ are picked up and work as expected in Antigravity (agy CLI) as well:

  • Skills (runtime-jar-deps, pom-dependency-change, internal-runtime-usage, runtime-e2e-tests) are discovered and loaded into the agent context automatically.
  • Executed the verification workflow specified in runtime-jar-deps by running RuntimeJarDependencyClosureTest (passed cleanly: 2 tests run, 0 failures).
  • Verified the companion script .agent/skills/pom-dependency-change/scripts/jar_size_diff.sh is executable and functional.

The Cloud Tasks client bundled in runtime_impl_jetty12/121 only needs a gRPC
transport found through the ManagedChannelProvider SPI; nothing in gax,
gax-grpc, grpc-auth or the Cloud Tasks stubs references netty directly.
Replace grpc-netty-shaded (about 4 MB compressed in each jar) with
grpc-okhttp.

grpc-okhttp depends on okio 3.x, which is written in Kotlin and pulls in
kotlin-stdlib (another 1.5 MB). Exclude it and use okio 1.17.6 (pure Java,
92 KB) instead: every okio method and field referenced by grpc-okhttp 1.85.0
exists in okio 1.17.6, which also has the fix for CVE-2023-3635.

runtime-impl-jetty121.jar: 33.7 MB with netty -> 29.3 MB.
The runtime jars bundle grpc-okhttp with the pure Java okio 1.17.6. okio 2+
is written in Kotlin and needs kotlin-stdlib, which the runtime jars don't
bundle (the shade artifactSet is an allowlist), so an okio upgrade would
break the Cloud Tasks client at runtime.

- Move the okio version to an okio.version property in the root pom.
- Add a maven-enforcer requireProperty rule to the runtime_impl poms that
  fails the build, with an explanation, unless okio.version is 1.x.
- Tell Dependabot to ignore okio >= 2.0.0. Majors are already ignored
  globally; this makes the okio case explicit. Mirror it in the (disabled)
  renovate.json.
…e deps

RuntimeJarDependencyClosureTest runs jdeps on runtime-impl-jetty12.jar and
runtime-impl-jetty121.jar, with the other runtime deployment jars on the class
path, follows every reference from com.google.appengine / com.google.apphosting
classes through the bundled libraries, and fails on any missing class that is
not a known, unused optional dependency. It reports the chain that reaches each
missing class. On the main branch it reports 88 classes per jar, including
com.google.auth.Credentials <- CloudTasksClientWrapper.

Agent skills in .agent/skills (read by Antigravity; .claude/skills is a symlink
to it for Claude Code):
- runtime-jar-deps: keep the runtime jars' bundled libraries complete.
- internal-runtime-usage: find API calls made by the runtime itself and test
  them end to end, including behind feature flags.
- pom-dependency-change: check history, dependency trees, shaded jars and size
  before changing pom dependencies (with scripts/jar_size_diff.sh).
- runtime-e2e-tests: build and run runtime/test, and known local pitfalls.
SKILL.md must start with its YAML frontmatter for Claude Code and Antigravity
to read the skill name and description, so the header follows the frontmatter.
@ludoch
ludoch force-pushed the cloudtasks-runtime-okhttp branch from 73920f3 to e8f9158 Compare October 24, 2026 15:48
@ludoch
ludoch force-pushed the agent-skills-runtime-deps branch from 539240e to 8537760 Compare October 24, 2026 15:48
@ludoch
ludoch changed the base branch from cloudtasks-runtime-okhttp to main October 24, 2026 15:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants