Skip to content

[Bulk index][Java] Export compiler and JDT workspace snapshots without query fanout #74

Open

Description

@samchon

Outcome

Export Java graph shards from the compiler invocation that already type-checks
the project, using the public javac plugin/tree/model APIs after attribution.
Preserve Gradle/Maven incremental state and use a JDT workspace route only when
the resident IDE model is the semantic owner. Do not run clean, query JDT once
per declaration, or type-check the same source a second time for enrichment.

Current master baseline

Current master registers scip-java for Java and Kotlin. For Java it publishes
semantic-index authority with contains and references. The PR #147 Gson
cold cell took 88.653 s, compared with 231.398 s through generic JDT LS
fan-out.

scip-java 0.13.x changed its architecture:

  • the project moved to scip-code/scip-java;
  • javac/kotlinc plugins emit SCIP directly rather than SemanticDB;
  • the supported floor is Java 17 and Gradle 8;
  • Scala/Zinc support was removed; and
  • the default Gradle/Maven path performs a real build and includes clean.

Its artifact remains a useful navigation fallback, but SCIP has no call role.
Imports/accesses/implementation relationships are producer-specific, and the
order-based overload/constructor discriminator churns when declarations are
inserted or reordered.

Upstream mechanism

The public JDK compiler API is enough for the build-integrated route:

  • Plugin
    is loaded by ServiceLoader on the processor path and receives the active
    JavacTask;
  • a plugin registers a
    TaskListener
    for parse/enter/analyze/generate/compilation events; and
  • Trees
    maps attributed TreePaths to Element, TypeMirror, source positions,
    scopes and declaration trees.

Elements/Types provide direct supertypes, member lookup and override checks.
No private javac AST parser is required for the initial strict provider.
Annotation-processor/generated source handling still needs lifecycle tests.

Decision: two semantic-owner lanes, one protocol

Build lane: javac plugin

Attach a versioned graph plugin to the project's ordinary Java compile tasks.
On ANALYZE completion for a compilation unit, scan its attributed tree once
and write a source shard. At final compilation completion, write the ordered
manifest/commit record only if diagnostics and the build universe satisfy the
configured policy.

Integrate through Gradle/Maven without replacing their task graph:

  • Gradle: add the plugin/processor path and -Xplugin: option to each actual
    Java source-set compile task; retain daemon, build cache, configuration cache
    and incremental compilation;
  • Maven: attach to the existing compiler execution and target directory; do not
    prepend clean; and
  • Bazel/other javac hosts: attach at the toolchain/action boundary only when the
    exact target/action inputs are nameable.

If a task is UP-TO-DATE, load the previously committed shards. Deleted source,
classpath, compiler-option, annotation-processor or generated-source changes
must invalidate the affected manifest even when no plugin invocation occurs.

Resident lane: JDT

When an Eclipse/JDT workspace already owns unsaved/resident source, expose a
narrow bulk snapshot from that workspace and its reconciled compilation units.
It must produce the same graph schema and identities as the javac route and
must freeze one workspace generation. It is a fallback/IDE lane, not a second
pass after javac.

Fact extraction

Walk attributed trees and elements:

  • declarations, visibility, nesting, packages/modules, imports/exports;
  • MethodInvocationTree and member references to resolved executable elements;
  • NewClassTree/constructor elements for instantiation;
  • identifiers/member selects plus assignment/update context for reads/writes;
  • TypeMirror and tree paths for type references;
  • direct class/interface supertypes and Elements.overrides for inheritance and
    overrides;
  • annotations with resolved annotation type and annotated target;
  • diagnostics from the same compilation task; and
  • test facts only through a named JUnit/TestNG enricher with framework
    provenance.

Virtual/interface calls identify the statically selected method. Runtime
implementations remain candidate/unresolved unless final/sealed analysis proves
one exact target.

Identity and universe

Use module/artifact coordinate plus binary owner name, item kind and a canonical
structural signature:

  • methods/constructors include erased or fully qualified parameter types,
    generic arity and return/type-parameter context as required;
  • fields, record components, enum constants and annotation elements remain
    distinct;
  • locals include source file, enclosing stable member and lexical structure;
  • anonymous/local classes include a structural owner key that does not change
    on unrelated line insertion; and
  • source/bridge/generated elements retain origin and generator/processor
    provenance.

Do not trust scip-java's +N overload ordinal as the final ID. Exact fixtures
must insert/reorder overloads and constructors without renaming unaffected
members.

The universe includes module/source set, Java release/preview flags, classpath
and module path order/content, compiler/JDK version, annotation processors and
options, generated sources, Gradle/Maven target coordinates and relevant build
properties. One multi-module build can have several target universes.

Incremental and correctness behavior

  • no-op: validate existing manifest; compiler need not run;
  • private body edit: ordinary incremental compile writes only affected source
    shards;
  • public ABI edit: build tool/compiler invalidates dependents, and the graph
    records the affected target/source closure;
  • annotation processor or classpath change: invalidate generated/consumer
    shards according to the build;
  • compiler error: publish diagnostics and either a clearly partial generation
    or retain the prior strict generation according to the common policy—never
    silently combine old and new facts;
  • delete/rename: explicit shard deletion; and
  • cancellation/crash: no commit.

Cold acceptance is relative to the same build without the graph plugin. Target
overhead is at most 25% plus serialization, with no extra compilation.

Implementation map

  1. Implement the common shard and coverage schema from [Bulk index] Replace symbol-by-symbol LSP scans with compiler-owned snapshots #63.
  2. Create a separately versioned Java exporter artifact and Gradle/Maven fixture
    integration; do not put a JVM inside the TypeScript package.
  3. Add a provider beside the existing scip-java entry and make it preferred
    only after a handshake proves target coverage.
  4. Normalize javac/JDT identities through one conformance fixture.
  5. Retain scip-java as a compatibility/navigation fallback.
  6. Add phase-separated real Gson measurement and lifecycle rows.

Acceptance

  • One compile traversal emits declarations, calls, construction,
    accesses, types, direct inheritance, overrides, annotations, diagnostics
    and source evidence.
  • No clean, no disabled Gradle daemon/configuration cache, and no second
    compiler pass.
  • Multi-module Gradle and Maven fixtures cover main/test source sets,
    JPMS, records, sealed types, overloads, constructors, generics, lambdas,
    anonymous/local classes, annotation processing and generated sources.
  • Overload insertion/reorder and multiple constructors keep stable IDs.
  • All 15 fact families have explicit coverage/unresolved rows.
  • No-op, body/API edit, create/delete/rename, classpath/config/processor
    change, error, cancel, crash and retry are atomic.
  • JDT and javac lanes agree on shared source facts and report different
    producer/universe provenance.
  • Cold overhead is measured against the native compile; warm no-op and edit
    latency are reported separately.
  • scip-java and generic JDT LS remain truthful fallbacks.
  • Focused tests, Java experiment, pnpm build, pnpm test, and
    pnpm coverage pass.

Primary references

Activity

  1. samchon commented on Jul 17, 2026

    @samchon
    OwnerAuthor

    Provider recon at graph 71e35af. This issue's premise is stale in two places, and one of its coordination notes now breaks a sibling issue.

    scip-java v0.13.0 is a breaking release

    sourcegraph/scip-java moved to scip-code/scip-java. Release v0.13.0 (2026-07-02), verbatim:

    This is the first release of scip-java under the scip-code organization, with Maven artifacts now published under the org.scip-code group and Docker images at ghcr.io/scip-code/scip-java. The project has been substantially slimmed down and modernized: the CLI is rewritten in Kotlin, the compiler plugins emit SCIP directly without the SemanticDB intermediate step, and the build now targets Java 17+ (with Java 25 supported). Support for Java 8/11, Gradle < 8, Scala indexing, and Zinc has been dropped.

    Corrections:

    1. SemanticDB is gone from the pipeline entirely. This issue's "Java output is not 'Javac SemanticDB'" framing no longer describes anything — the javac plugin emits SCIP directly. The index-semanticdb subcommand is gone; the CLI is now index, aggregate, snapshot.
    2. The "share SemanticDB/SCIP plumbing with Kotlin and Scala" coordination note is obsolete. Scala indexing was dropped (PR #883, merged 2026-05-27, deletes SbtBuildTool.scala, MillBuildTool.scala, ScalaVersion.scala). This breaks [Bulk index][Scala] Consume SemanticDB and TASTy snapshots through BSP #77's assumed dependency — see the correction there; Scala should move to BSP + direct SemanticDB ingestion instead. The shared-plumbing note now holds for Java + Kotlin only.
    3. v0.13.1 dropped the Windows launcher (PR #970). Java indexing on Windows is Docker (ghcr.io/scip-code/scip-java) or coursier only.

    Also: Java 8/11 and Gradle < 8 are no longer supported; JDK 17+ required (17/21/25), with --add-exports jdk.compiler/com.sun.tools.javac.{model,api,tree,util,code}=ALL-UNNAMED.

    scip-java index runs a real build, not an analysis pass

    Defaults: Gradle clean compileTestJava compileTestKotlin compileTestKotlinJvm; Maven --batch-mode clean verify -DskipTests. It runs the build — network dependency resolution, annotation processors, codegen — with a compiler plugin attached. This issue's "prepare dependencies without modifying tracked files" must contend with it writing to target//build/.

    Build tool matrix: Maven ✅ Java, Gradle ✅ Java, Bazel ✅ Java, Ant ❌, Buck ❌. v0.13.1 fixed "duplicate documents in Bazel index aggregation" — a caution for the Bazel path.

    The identity finding (feeds #65)

    The overload disambiguator is order-of-appearance, not signature-derived. Per the SemanticDB spec whose grammar scip-java still follows:

    Empty string for the definition that appears first. +1 for the definition that appears second. +2 for the definition that appears third.

    with the Java-specific ordering:

    non-static overloads first, following the same order as they appear in the original source, static overloads secondly, following the same order as they appear in the original source

    Consequences:

    Recommendation: derive a signature hash from SymbolInformation.signature rather than trusting +N. Note the campaign-wide asymmetry — scip-clang's disambiguator is a canonical-type hash (order-independent) while scip-java's is an ordinal; #65 cannot assume "provider-native key = stable" uniformly.

    Locals: local <id> is "unique within the underlying document, but they don't have to be unique across multiple documents", and the suffix is "implementation-dependent" → must be paired with Document.relative_path and marked generation-scoped.

    Multi-module: SCIP <package> = <manager> <package-name> <version>, so modules stay distinct without name merging. This issue's multi-module acceptance row is satisfied by the format.

    What the artifact proves

    Java is the strongest SCIP story in the campaign, but still bounded by the schema. SymbolRole has no Call role at all (see the #69 comment), so:

    • Proven: contains (descriptor chain), references.
    • Partial: imports (Import role + occurrences on import statements — the best-supported edge beyond references); accesses (ReadAccess/WriteAccess exist in the schema — verify the plugin sets them); extends/implements/overrides (is_implementation relationships; Java can be disentangled by target kind Interface vs Class and method vs type — strictly better separable than C++); tests (Test role exists and the Gradle default compiles compileTestJava, so test sources are indexed — verify the plugin sets Test per test source root, since this issue's Gson smoke requires non-zero tests).
    • Closest to provable of any language: instantiates — new Foo() yields an occurrence on the constructor symbol with Kind=Constructor. Still an inference from target kind rather than a role, but a semantic inference, not punctuation-guessing, so it survives [Bulk index] Add strict SCIP navigation-skeleton ingestion and enrichment gates #69's bar. Verify with a fixture.
    • Not provable: calls, type_ref as such, dispatches, decorates (an annotation use is just a reference to the annotation type — needs enrichment to mark it as decorates and attach the target; annotations are an acceptance row here), exports (only JPMS module-info exports anything).

    Required sidecar: extend the javac plugin org.scip-code:scip-javac — do not fork JDT — walking MethodInvocationTree/NewClassTree/MemberSelectTree/AnnotationTree, emitting facts keyed by the same SCIP symbol strings. Cheap relative to C++: it rides the compile that is already happening.

    Incremental

    Cold-only at milestone 1, as this issue already states. Per-source shards exist but shard production is not dependency invalidation; any classpath/compiler-option/AP/module change forces full. Gradle's own incremental compile could in principle be leveraged (the plugin rides javac), but the clean in both default commands explicitly defeats it — worth overriding via scip-java index -- <custom> at milestone 2.

    Full recon: .wiki/bulk-index-providers/recon-c-cpp-java.md.

  2. samchon commented on Aug 26, 2026

    @samchon
    OwnerAuthor

    Java consumer: written, fenced, and blocked on one producer staleness

    Campaign chronology, from PR #164's cycle.

    Consumer state. The route is implemented against the merged producer (samchon/scip-java 32eca21) and registered as javac-graph: pinned handshake on schema/protocol/producer identity, committed per-target generations, target-scoped identity, shard-level deltas against the previous generation, all fifteen coverage rows, machine-readable unresolved facts, and an honest decline to scip-java when the installed launcher's index --help does not publish --graph-output.

    Splitting scip-java was a precondition rather than a preference: a fallback owns the same atomic languages as the route it backs, so a Java-only strict route could take that entry as its fallback only by taking Kotlin's ownership with it. The lanes are now named for their producers — scip-java's javac plugin keeps the name, and the Kotlin facts come from the kotlinc plugin the same launcher ships, which is also what lets the Kotlin row state its own compiler instead of leaving the field empty under the Java name.

    Two contract findings worth carrying forward:

    • The protocol requires every partial coverage row to carry at least one unresolved site — "some sites are unproven" with no list reads exactly like "every site is proven". The aggregator marks six families partial as a property of the exporter rather than of any call site, so the consumer publishes a provider-gap row at the target's own coordinate for each partial family with no located site.
    • hello.compilerVersion must be non-empty, and a Gradle toolchain per source set can legitimately run two JDKs in one build. The generation publishes both, joined, rather than presenting the first shard's reading as the build's.

    Where it is blocked. The real lane reaches a real artifact and is refused at the coordinator's input fence, on the lifecycle's edit step:

    the provider read b82fc2f44ce88f0e4e69de8915e3b273a45dd6fc2288caa0f2ca1fb6b1a42c83
    while the generation was fenced at 05a4731f4cf3cccd95212ee2c8ef8cf2243f9e51594d87b2853a506183fd14fb
    and settled at   05a4731f4cf3cccd95212ee2c8ef8cf2243f9e51594d87b2853a506183fd14fb
    

    Those two digests are identified. b82fc2f4 is the pristine fixtures/maven/basic/src/main/java/com/Example.java; 05a4731f is the same file with the lifecycle's edit appended. The coordinator hashed the edited file before and after the refresh and got the same answer both times, so the checkout was stable — and the producer published a shard whose diskDigest describes the file as it was before the edit.

    So on the edit step the aggregate carries a committed generation that no longer describes the checkout, and GraphAggregateRunner.parseShard's own freshness check — which re-reads each source and compares it to the shard's diskDigest — did not catch it. Whether the build was UP-TO-DATE and re-published a stale commit, or the store returned a generation the compile never refreshed, is the producer's to say; from here it is visible only as a digest that describes bytes that no longer exist.

    The consumer's behaviour is what it should be: it refuses to publish facts bound to bytes no reader can hash, and it now names which of the four ways a source comes unbound this was. It also requires a non-empty disk digest at the adapter, so a producer that never hashed a source is declined where the producer can be named rather than three refreshes later.

    Where this leaves the issue. #74 stays open. The consumer half is written, its fixtures pass, and it publishes through buildGraphDump — the coordinator fence included — against a fake launcher. The route cannot be called serving until the real producer's committed generation survives an ordinary edit.

  3. samchon commented on Aug 27, 2026

    @samchon
    OwnerAuthor

    Correction: the fence failure was the consumer's, and it is fixed

    The previous comment attributed the edit-step fence failure to producer staleness. That was wrong, and the digests it quoted are what disprove it.

    b82fc2f4 is the pristine Example.java; 05a4731f is that file with the lifecycle's edit appended; the coordinator read the edited file both before and after the refresh. So the checkout was stable and the producer had simply never been asked to rebuild — which means nothing stale was ever published.

    The cause is in the consumer's session wiring. A registry entry's buildInputs is deliberately the build files alone: the files outside a provider's own language whose change invalidates it. A session's inputs is the fingerprint that decides whether the build has to run at all, and it must cover everything the producer compiled. Rust keeps the two apart by name — rustInputs walks the sources, rustBuildInputs does not — and the Java route used the second where the first belongs. A .java edit moved nothing, the session reused the snapshot taken before it, and the coordinator refused a generation describing bytes the file no longer had.

    Refused correctly, which is the part worth keeping: the input fence caught a route that would otherwise have served facts one edit out of date, and said so with digests precise enough to identify both files.

    The fixture is what hid it. Every lifecycle case passed its own list of sources as inputs, so the provider's real wiring was never under test. The selection case now edits a source and republishes through buildGraphDump, exercising the provider's own inputs and the coordinator fence together.

    GraphAggregateRunner and MavenGraphGenerationStore are not implicated; the retraction is filed at samchon/scip-java#1.

    #74 stays open until the real lane publishes a generation on CI, but the remaining risk is now an ordinary integration one rather than a suspected upstream defect.

  4. samchon commented on Aug 27, 2026

    @samchon
    OwnerAuthor

    What the Java route now proves, and what it does not

    The javac-graph route is implemented and its real-corpus lane is green in CI on 358bbbb. Recording the evidence against this issue's own acceptance list rather than against the general impression of progress, because most of the list is still open.

    Supported now.

    • One compile traversal. The producer is a javac plugin on the project's own compile tasks, so the facts come from the attributed trees the build already made. No clean, no second compiler pass, no disabled daemon.
    • All fifteen fact families carry explicit coverage. Every committed target publishes a complete matrix, and a family the producer calls partial with no located site publishes a provider-gap row at the target's own coordinate — so "some sites are unproven" cannot read as "every site is proven".
    • Lifecycle atomicity, on the real producer. The lane runs cold, unchanged, edit, create, rename, delete, compile failure and retry against the pinned fork, and a refused generation leaves the prior one standing byte for byte.
    • scip-java stays a truthful fallback. The registry entry was split into a Java-only scip-java and scip-kotlinc, because a fallback must own the same atomic languages as the route it backs. A launcher whose index --help does not publish --graph-output declines to that lane rather than running a whole build and finding nothing to read.
    • Gates. pnpm build, pnpm test, pnpm coverage (100% line/function/branch) and the Java experiment lane all pass.

    Still open, and each for its own reason.

    • Fixture breadth. The pinned corpus is the producer's own Maven fixture — two classes. JPMS, records, sealed types, overloads, generics, lambdas, anonymous and local classes, annotation processing and generated sources are not covered by it, and neither is a multi-module Gradle build with main and test source sets.
    • Identity stability under overload insertion and reorder is unproven; the corpus has no overloads to move.
    • The JDT lane does not exist, so nothing yet cross-checks javac facts against a second producer or contrasts their provenance.
    • Cold overhead against the native compile is unmeasured. The published benchmark row for Java is still prior scip-java fallback evidence, labelled as such.
    • Crash and cancel are exercised against the fake producer, not against a real interrupted build.

    One declared limitation, filed upstream. Restoring the original sources returns identical facts — five nodes and eight edges both times — under a different build universe, because ScipOptionBuilder.writeGraphUniverse digests the raw javac invocation and that invocation names the per-run temporary directory the launcher unpacks its plugin jar into. It is declared in the catalog as a regenerationLimitation naming the mechanism, so the lane proves everything else it owes rather than staying red on it, and it is filed at samchon/scip-java#1. The declaration comes off when that does.

    This issue stays open.

  5. samchon commented on Aug 27, 2026

    @samchon
    OwnerAuthor

    The Java lane ran, and here is what it did and did not prove

    java LSP is green at run 33030412174 on 358bbbb, against the producer merged at 32eca21. The PR body had this lane down as "CI's to confirm" because the development checkout has no JVM. It is confirmed. The result artifact, in full:

    Provenance. javac-graph, authority compiler, producer scip-java-javac-graph 0.0.0-SNAPSHOT on javac 21.0.12, schema 1, protocol 1. Capabilities coverage, diskDigests, incremental, sourceDigests, universe, unresolved.

    Lifecycle, every phase separately timed:

    phase mode ms changed outcome
    cold initial 20,951 yes 5 nodes, 8 edges
    unchanged unchanged 737 no manifest, content and universe all byte-identical
    edit reload 5,882 yes new manifest and content
    create reload 5,798 yes 8 nodes, 18 edges
    rename reload 5,796 yes 8/18
    delete incremental 4,929 yes back to 5/8
    failure reload 3,890 — rejected; malformed POM, prior generation retained
    retry reload 5,803 yes recovers to the edit content digest

    The cross-file claim the PR flagged as unverified. lifecycleCreatedEdge is instantiates, samchonGraphExperiment → Example, crossFile: true. A new file's constructor call resolves to a type declared in another file, through attributed trees, in one compile.

    Identity is target-scoped as specified: @v2/java/1aaf2fb4…#com.Example:class and @v2/java/43962d7a…#com.ExampleSuite.ExampleSuite:constructor carry different target hashes for main and test source sets.

    One honest negative: regeneration is limited, and it is upstream's

    "regeneration": {
      "status": "limited",
      "reproducedManifest": false,
      "reproducedContent": false,
      "coldNodes": 5,  "retryNodes": 5,
      "coldEdges": 8,  "retryEdges": 8,
      "limitation": "scip-java 32eca214a413d1b8a375c481f666ff8a4ec96773 digests its
       build universe from the raw javac invocation, which names the per-run
       temporary directory its embedded plugin jar is unpacked into, so an
       unchanged checkout reproduces identical facts under a different universe"
    }
    

    The facts reproduce exactly — same node and edge counts, and retryContent equals the edit phase's content digest. What does not reproduce is the universe, because the digest includes /tmp/scip-java<random>/bin/javac. That is a producer defect, not a consumer one, and it is filed on samchon/scip-java#1. The lane reports it as a named limitation rather than passing quietly or failing, which is the behaviour this issue asked for.

    Against the acceptance list

    Proven by this run and the gate:

    • Focused tests, Java experiment, pnpm build, pnpm test, pnpm coverage pass. The lane is green and the gate is 100% line/function/branch.
    • All 15 fact families have explicit coverage/unresolved rows. Enforced by pnpm provider-support against GRAPH_PROVIDERS and the experiment catalog; the provider declares 14 producible families and renders carries an unsupported row.
    • scip-java and generic JDT LS remain truthful fallbacks. scip-java is split into a Java-only lane and scip-kotlinc so a fallback owns the same atomic languages as the route it backs.
    • Warm no-op and edit latency are reported separately. 737 ms and 5,882 ms above.

    Partially proven, and I would rather say so than tick them:

    • Lifecycle atomicity covers cold, no-op, edit, create, rename, delete, error and retry. Classpath/config/processor change, cancel and crash are not in this lane.
    • Cold overhead measured against the native compile. Cold is measured at 20,951 ms; the native mvn verify baseline it should be compared against is not.

    Not proven, and each needs work this cycle did not do:

    • One traversal emitting inheritance, overrides and annotations — the fixture is 5 nodes and 8 edges and exercises contains, exports and instantiates only.
    • Multi-module Gradle and Maven fixtures: JPMS, records, sealed types, overloads, constructors, generics, lambdas, anonymous and local classes, annotation processing, generated sources.
    • Overload insertion and reorder keeping stable IDs.
    • JDT and javac lanes agreeing on shared source facts while reporting different provenance — there is no JDT lane yet.

    So the route is real, atomic and target-scoped, and the compiler-owned producer works end to end. The semantic breadth this issue specifies is still ahead of it, and #74 should stay open for that rather than close on a green lane.

  6. samchon commented on Sep 1, 2026

    @samchon
    OwnerAuthor

    Not closed by #164 (1bf9486). JavaGraphSnapshotAdapter landed and the java LSP experiment is green.

    Still unmet from this issue's Acceptance list: there is no Maven fixture in the repository at all (no pom.xml under tests/), while the acceptance requires multi-module Gradle and Maven fixtures covering main/test source sets, JPMS, records, sealed types, overloads, constructors, generics, lambdas, anonymous/local classes, annotation processing and generated sources. The JDT/javac lane agreement on shared source facts and the cold-overhead-versus-native-compile measurement are also unreported.

    Leaving this open.

  7. samchon commented on Sep 1, 2026

    @samchon
    OwnerAuthor

    Current-cycle revalidation separates the passing producer fixture from the failing Gson corpus:

    • Run 33377586889 proves the pinned javac producer on its small Maven lifecycle: 687 ms unchanged, 5,633 ms edit, atomic create/rename/delete/failure/retry, and one cross-file instantiates edge. Those observations exceed the shared no-op/edit targets and are not a native-build comparison.
    • The artifact still declares the known regeneration limitation: the producer hashes the temporary embedded-plugin path into its universe.
    • Run 33377586947 attempted the same producer on Gson and fell to scip-java. The retained error contains only benign JAVA_TOOL_OPTIONS notices because the shared batch session discards stdout whenever stderr is non-empty; [Provider diagnostics] Preserve both process streams on batch failure #169 will preserve both streams so the next run exposes the Maven cause.
    • [Experiment/index-time] Bind every cell to its intended and executed strict route #168 owns intended/actual route attribution and the real coverage/unresolved artifact summary.
    • The multi-module Gradle/Maven semantic breadth, overload stability, JDT agreement, diagnostics/cancel/crash, and native-baseline items in this issue remain unmet.

    This issue remains open.

  8. added 5 commits that reference this issue on Sep 2, 2026
    1bea468
    c58fa5b
    4d3237d
    354ccc9
    76cef95
  9. 1 remaining item

  10. added 15 commits that reference this issue on Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions