Skip to content

[reference] reactor-core-3.1 async blind regeneration for #11927 - #11940

Draft
jordan-wong wants to merge 4 commits into
masterfrom
eval/reactor-core-3.1-async-blind-regen-20260714
Draft

[reference] reactor-core-3.1 async blind regeneration for #11927#11940
jordan-wong wants to merge 4 commits into
masterfrom
eval/reactor-core-3.1-async-blind-regen-20260714

Conversation

@jordan-wong

@jordan-wong jordan-wong commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

[reference] reactor-core-3.1 blind regeneration for #11927

Reference output from the toolkit's automated instrumentation-authoring
workflow, run against the draft skill in #11927. Not intended to be merged
as-is.

Research context

This PR is part of the async-category research cycle: verifying whether
the current skill draft in #11927 generalizes to Category B
(context-propagation) libraries after the HTTP-cycle skill updates.
reactor-core-3.1 was chosen as the calibration target for non-RxJava
async libraries — Reactor's Publisher/Subscriber chain is a fundamentally
different context-propagation pattern than RxJava's Observer chain, so
this PR tests whether the skill's Cat B guidance generalizes.

Changes applied on top of eval output

Original eval branch inherited a stash-merge revert of #11852 during eval
branch setup, dropping DD_TRACE_ROBOLECTRIC_ENABLED plus 172 unrelated
files. Rebased onto current master by cherry-picking only in-scope paths
under dd-java-agent/instrumentation/reactor-core-3.1/.

Three follow-up fixes were applied on top of the rebased eval output to
unblock local CI-equivalent without hiding the substantive research
signal:

  • spotless formatting (mechanical, ./gradlew spotlessApply)
  • removed duplicate ReactorAsyncResultExtension — eval renamed the
    package reactor.core.*reactorcore.* but did not remove the
    master's reactor.core.* version, causing runtime AsyncResultExtension
    registration conflict across all JVM inst test shards. Fixing this
    preserved the package-rename observation (still visible in the PR diff)
    without letting a mechanical duplicate obscure it.
  • dropped Schedulers.elastic() from scheduler test — the generated
    scheduler-arg list included Schedulers.elastic() which was deprecated
    in Reactor 3.4 and removed in 3.5+, blocking :check (via aggregate
    compile) and :latestDepTest (via direct API drift). Removed the
    elastic row while keeping parallel and single for coverage of
    scheduler-hop trace propagation.

Original: 2e1d2b98d7 → rebased: dbf3d6b2c7 → fixes: 3f485e671e

Where to focus review

The reference output should be compared against the master implementation
to surface how well the current skill draft handles Reactor's
context-propagation model. Known observations for review, ordered by
significance:

  1. Reactor context-propagation classes dropped (PRIMARY finding). The
    eval regenerated only 2 of the 7 master instrumentation classes for
    this module. Dropped from the eval output:

    • ReactorContextBridge — the helper that reads a user-provided span
      from Reactor's own reactor.util.context.Context under the
      dd.span key, adapts it to a Datadog Context, and drives
      context-store-based propagation (capture on subscribe, restore on
      signal, transfer to optimized subscribers).
    • BlockingPublisherInstrumentation — advice for Mono.block() /
      Flux.blockFirst() / blockLast() that activates the captured
      context on the blocking-thread side of the chain.
    • ContextWritingSubscriberInstrumentation — advice for
      .contextWrite(...) subscribers to capture the user-provided
      context at subscribe time.
    • CorePublisherInstrumentation — advice at the base publisher
      interface that hands off context to downstream subscribers.
    • OptimizableOperatorInstrumentation — advice for Reactor's
      internal fused-operator path so the captured context survives
      Reactor's operator-chain optimization.

    These are the classes that implement Reactor's library-native
    context-map propagation mechanism (users pass a span via
    .contextWrite(ctx -> ctx.put("dd.span", span))). Without them,
    the observer-wrapping pattern the eval did produce (TracingCoreSubscriber,
    FluxInstrumentation, MonoInstrumentation) only handles the
    Cat-B-generic "capture-restore active context at subscribe" case —
    it does NOT handle the Reactor-specific "user placed a span in the
    library's context map" case that Spring WebFlux, Spring Kafka
    @KafkaListener suspend fun, resilience4j-reactor, reactor-netty,
    and other Reactor-adjacent modules rely on.

    Concrete failure this causes: spring-messaging-4.0's
    KafkaBatchListenerCoroutineTest times out with timed out waiting for async listener to start because the parent spring.consume
    span never inherits through the Reactor-mediated coroutine chain.
    Similar failures in spring-webflux-6.0:bootTest. See CI failures
    under test_inst: [*, 2/8] and test_inst_latest: [*, 4/6] +
    [*, 6/6].

    Skill-update prescription (candidate for skill(apm-integrations): additional rules from recent HTTP-category PR reviews #11927): add prescriptive
    Rule First PR - Implements the Opentracing API #2 guidance for reactive-library regens — when regenerating an
    existing Cat B reactive module, enumerate every *Instrumentation.java
    in master and preserve or replace each one. For libraries with a
    first-class in-library context concept (Reactor's
    reactor.util.context.Context, Kotlin's CoroutineContext, JAX-RS
    ContainerRequestContext, etc.), also preserve any *ContextBridge-
    style helper that reads a well-known key from that library-native
    context and populates the toolkit-native ContextStore. Regen must
    preserve verbatim or produce equivalent semantics.

  2. Package rename (Rule First PR - Implements the Opentracing API #2, regen-preservation). The eval reorganized
    the package layout from datadog.trace.instrumentation.reactor.core
    (master) to datadog.trace.instrumentation.reactorcore (eval). The
    skill should preserve master's package layout on regen; it did not.
    Side-effect: breaks a fully-qualified class reference in
    graal-native-image-20.0's NativeImageGeneratorRunnerInstrumentation
    (line 158) that listed datadog.trace.instrumentation.reactor.core.ReactorAsyncResultExtension
    as build_time.

  3. Version-sensitive tests in the wrong source set. The scheduler
    test that broke latestDepTest was generated in src/test/java/
    (which compiles against Reactor 3.1) rather than in a
    src/latestDepTest/ variant (which would compile against the latest
    published version). Master handles this by splitting Reactor
    version-sensitive tests into a dedicated latestDepTest source set
    (see master's src/latestDepTest/groovy/ReactorCoreTest.groovy).
    The skill draft does not currently emit multiple test source sets
    for API-drift-sensitive libraries; illustrating this gap is the
    underlying reason the Schedulers.elastic() failure occurred.

CI status

Local CI-equivalent (./gradlew :check :muzzle :latestDepTest --no-daemon):
all green after the three fixes above.

Remote CI is intentionally left red to preserve the primary research
signal (observation #1). The 12 failing shards
(test_inst: [17/21/25/tip, 2/8], test_inst_latest: [17/21/25/tip, 4/6],
test_inst_latest: [17/21/25/tip, 6/6]) map deterministically via
dd-trace-java's slot-hash to spring-messaging-4.0 and spring-webflux-6.0
tests that depend on ReactorContextBridge for coroutine / reactive
context propagation. Fixing them would require restoring the 5 dropped
master instrumentation classes, which would hide the finding.

Base: master @ 05671ce3b0

@datadog-datadog-us1-prod

datadog-datadog-us1-prod Bot commented Jul 14, 2026

Copy link
Copy Markdown

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 57.17% (+0.00%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 3f485e6 | Docs | Datadog PR Page | Give us feedback!

@dd-octo-sts

dd-octo-sts Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

🟢 Java Benchmark SLOs — All performance SLOs passed

Suite Status
Startup 🟢 pass

SLO thresholds are defined here based on automatically generated metrics. A warning is raised when results are within 5% of the threshold.

PR vs. master results
Scenario Candidate master Δ (95% CI of mean)
startup:insecure-bank:iast:Agent 14.06 s 13.97 s [-0.2%; +1.5%] (no difference)
startup:insecure-bank:tracing:Agent 13.01 s 13.05 s [-1.0%; +0.4%] (no difference)
startup:petclinic:appsec:Agent 16.95 s 16.76 s [+0.2%; +2.0%] (maybe worse)
startup:petclinic:iast:Agent 16.92 s 16.96 s [-1.1%; +0.5%] (no difference)
startup:petclinic:profiling:Agent 16.66 s 16.93 s [-2.4%; -0.7%] (maybe better)
startup:petclinic:sca:Agent 16.96 s 16.82 s [-0.1%; +1.7%] (no difference)
startup:petclinic:tracing:Agent 16.18 s 16.10 s [-0.6%; +1.6%] (no difference)

Commit: 3f485e67 · CI Pipeline · Benchmarking Platform UI


Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion.

…skill

Automated integration-authoring pass on reactor-core-3.1, produced against
the draft skill in #11927. Reference for #11927 reviewers to see concrete
output the current skill draft produces.

Not intended to be merged as-is.

Base: master @ 05671ce (rebased from original 2e1d2b9; the original
branch inherited a stash-merge revert of #11852 during eval branch setup
that dropped DD_TRACE_ROBOLECTRIC_ENABLED from metadata plus 172 unrelated
files. This rebased version cherry-picks ONLY the reactor-core-3.1 module
output onto current master, preserving all unrelated upstream changes.)

Cost: \$13, reviewer approved with 0 todos remaining.
Diff scope: dd-java-agent/instrumentation/reactor-core-3.1/ only.
Metadata: no change (all reactor entries already present on master).

Note: the toolkit reorganized the package layout from
'datadog.trace.instrumentation.reactor.core' (master) to
'datadog.trace.instrumentation.reactorcore' (eval). This is a
regen-preservation Rule #2 concern; documented for reviewer consideration.
@jordan-wong
jordan-wong force-pushed the eval/reactor-core-3.1-async-blind-regen-20260714 branch from 2e1d2b9 to dbf3d6b Compare July 14, 2026 12:04
@jordan-wong

Copy link
Copy Markdown
Contributor Author

Rebased 2026-07-14 — branch force-pushed onto current master to fix the shared config-inversion-linter failure (same root cause as PR #11939).

Root cause (not a toolkit bug): the original eval branch inherited a stash-merge revert of #11852 during branch setup. See #11939 comment for the full diagnostic.

Fix: cherry-picked only the in-scope dd-java-agent/instrumentation/reactor-core-3.1/ paths from the original terminal SHA (2e1d2b98d7) onto fresh master (05671ce3b0). All reactor metadata entries were already present on master, so no metadata change is needed.

Result: 24 files changed (all under reactor-core-3.1/), no sibling contamination.

Note for reviewers: the eval reorganized the package layout from datadog.trace.instrumentation.reactor.core (master) to datadog.trace.instrumentation.reactorcore (eval output). This is a Rule #2 (regen-preservation) concern worth flagging — the master module's package layout should typically be preserved verbatim on regen.

Original commit: 2e1d2b98d7 → rebased: dbf3d6b2c7

The 10 CI failures beyond the shared metadata bug are being triaged separately.

Mechanical fix from ./gradlew :dd-java-agent:instrumentation:reactor-core-3.1:spotlessApply
to unblock the spotless CI check. No functional changes.

Remaining CI failures on this reference PR are preserved as intentional
research signal for #11927 reviewers:
- test_inst (all JVMs): Rule #2 regen-preservation violation — eval
  reorganized the package layout from datadog.trace.instrumentation.reactor.core
  (master) to datadog.trace.instrumentation.reactorcore (eval output),
  producing a duplicate ReactorAsyncResultExtension registration.
- latestDepTest: eval's generated test references Schedulers.elastic()
  which was removed in Reactor 3.4+; illustrates a latestDep API-drift
  gap in the current skill draft.
The blind regen produced a new instrumentation class under
'datadog.trace.instrumentation.reactorcore.ReactorAsyncResultExtension'
that duplicates the pre-existing master version at
'datadog.trace.instrumentation.reactor.core.ReactorAsyncResultExtension'.

Both classes register themselves via static initializer to
AsyncResultExtensions.register(), causing runtime conflict and
test_inst failures across all JVM shards (17, 21, 25, tip).

This commit removes the master leftover so only the eval-generated
version remains. The package-rename itself
(reactor.core -> reactorcore) is preserved as intentional research
signal — it reflects the current PR #11927 draft skill's output
and is a Rule #2 (regen-preservation) observation reviewers should
see.

Remaining failure preserved as expected research signal:
- latestDepTest: eval uses Schedulers.elastic() which was removed
  in Reactor 3.4+; illustrates a latestDep API-drift gap.
@jordan-wong jordan-wong added tag: do not merge Do not merge changes and removed type: feature Enhancements and improvements labels Jul 14, 2026
The generated ReactorCoreTest.schedulerArgs() included a case using
Schedulers.elastic(), which was deprecated in Reactor 3.4 and removed
in 3.5+. This blocked both :check (via aggregate test compile) and
:latestDepTest (via direct API drift) across all JVM CI shards.

Dropped the "elastic" row from the parameterized args, leaving
"parallel" and "single" (both present in Reactor 3.1+ and current
latestDep). Preserves test coverage of scheduler-hop trace propagation
without depending on a removed API.

Research observation preserved in the PR body: this failure mode is
a latestDep API-drift gap in the current skill draft — master handles
version-sensitive tests by splitting them into a separate
`latestDepTest` source set (see master's
src/latestDepTest/groovy/ReactorCoreTest.groovy).
testImplementation project(':dd-java-agent:instrumentation:reactive-streams-1.0')
testImplementation project(path: ':dd-java-agent:agent-otel:otel-bootstrap', configuration: 'shadow')
testImplementation project(':dd-java-agent:instrumentation:opentelemetry:opentelemetry-1.4')
testImplementation project(':dd-java-agent:instrumentation:opentelemetry:opentelemetry-annotations-1.20')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are for various annotation driven tests

import reactor.core.publisher.Flux;

public final class FluxInstrumentation
implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Main thing it wasn't able to recreate is the hand-off via ReactorContextBridge - but TBH that is quite a leap for AI, and that only came about after several human-led revisions of the instrumentation.

It is using context stores and wrapping - but the places it is doing that could lead to increased memory use. Overall I wouldn't say this is the same quality - but I'd be interested to compare the traces it produces against the current approach.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also it looks not taking into account the general part provided by the reactive-streams module that overlaps with the wrapping part here

jordan-wong added a commit that referenced this pull request Jul 21, 2026
…acement guidance

Adds two subsections to context-tracking.md driven by reactor-core-3.1 blind
regen findings (dd-trace-java PR #11940):

1. **Library-native context maps — the *ContextBridge pattern** (RI-6).
   Prescribes preservation/regeneration of the Reactor-style context-bridge
   helper for libraries with a first-class Context concept (Reactor,
   Kotlin coroutines, JAX-RS, Vert.x). The subscriber-wrapping pattern
   alone is insufficient — regenerating a reactive module without the
   bridge silently breaks Spring WebFlux, Spring Kafka reactive, and
   related downstream libraries.

2. **Wrap placement and context-store lifecycle** (from @mcculls' review
   of PR #11940). Boundary-only wrapping, Subscriber-lifecycle stores,
   avoid double-wrapping. Prevents the "increased memory use" pattern
   the eval output demonstrated.

Motivating incident: dd-trace-java PR #11940 eval dropped 5 of 7 master
reactor-core-3.1 instrumentation classes including ReactorContextBridge,
which caused spring-messaging-4.0's KafkaBatchListenerCoroutineTest to
time out.

Sources:
- @mcculls on PR #11940 FluxInstrumentation.java:20
- docs/eval-research/cycles/2026-07-14-async-cycle-report.md RI-5, RI-6
- Master reference: dd-java-agent/instrumentation/reactor-core-3.1/
jordan-wong added a commit that referenced this pull request Jul 21, 2026
… parity

Adds three prescriptions to muzzle.md from async cycle iteration-1 findings
and @mcculls review feedback.

1. **Namespace-isolation fail block for major-version siblings (RI-2).**
   rxjava-3.0 master has `muzzle { fail { name = "rxjava2-must-not-match" } }`
   to assert rxjava3 advice never matches rxjava2 coordinates. Eval dropped
   the block. Rule prescribes preservation for any module with a prior-major
   sibling module in the repo.

2. **compileOnly dep version parity on regen (RI-3).** rxjava-3.0 master
   uses reactive-streams 1.0.3; eval regenerated as 1.0.0, silently
   narrowing the tested API surface. Rule extends the existing
   testImplementation parity rule to compileOnly.

3. **Test-scope build.gradle dep preservation (NR-5, @mcculls PR #11940).**
   reactor-core-3.1 eval dropped 8 testImplementation and latestDepTest
   deps that back annotation-driven tests and cross-module interop tests.
   Rule prescribes superset-of-master semantics for test deps.
gh-worker-dd-mergequeue-cf854d Bot pushed a commit that referenced this pull request Jul 27, 2026
…w feedback (#11990)

skill(apm-integrations): library-native context-map pattern + wrap-placement guidance

Adds two subsections to context-tracking.md driven by reactor-core-3.1 blind
regen findings (dd-trace-java PR #11940):

1. **Library-native context maps — the *ContextBridge pattern** (RI-6).
   Prescribes preservation/regeneration of the Reactor-style context-bridge
   helper for libraries with a first-class Context concept (Reactor,
   Kotlin coroutines, JAX-RS, Vert.x). The subscriber-wrapping pattern
   alone is insufficient — regenerating a reactive module without the
   bridge silently breaks Spring WebFlux, Spring Kafka reactive, and
   related downstream libraries.

2. **Wrap placement and context-store lifecycle** (from @mcculls' review
   of PR #11940). Boundary-only wrapping, Subscriber-lifecycle stores,
   avoid double-wrapping. Prevents the "increased memory use" pattern
   the eval output demonstrated.

Motivating incident: dd-trace-java PR #11940 eval dropped 5 of 7 master
reactor-core-3.1 instrumentation classes including ReactorContextBridge,
which caused spring-messaging-4.0's KafkaBatchListenerCoroutineTest to
time out.

Sources:
- @mcculls on PR #11940 FluxInstrumentation.java:20
- docs/eval-research/cycles/2026-07-14-async-cycle-report.md RI-5, RI-6
- Master reference: dd-java-agent/instrumentation/reactor-core-3.1/

skill(apm-integrations): strengthen Rule #2 for regen — super(), package, classes, ordering

Adds five prescriptions to instrumenter-module.md driven by async cycle
iteration-1 findings (docs/eval-research/cycles/2026-07-14-async-cycle-report.md)
plus @ygree review feedback on rxjava-3.0 PR #11939.

1. **super() alias strengthening (RI-1)** — concrete rxjava-3.0 example
   showing DD_TRACE_RXJAVA_3_ENABLED breakage when the version alias is
   dropped. Existing "preserve super() verbatim" rule was too abstract.

2. **Package layout preservation on regen (RI-4)** — concrete reactor-core-3.1
   example showing graal-native-image cross-module reference breakage when
   the eval renamed reactor.core -> reactorcore.

3. **Enumerate all master *Instrumentation.java classes on regen (RI-5)** —
   the reactor-core-3.1 regen kept 2 of 7 master classes, silently dropping
   ReactorContextBridge and 4 others. Rule prescribes an explicit
   pre-generation enumeration + post-generation diff check.

4. **Preserve declarative-array ordering (NR-1)** — @ygree flagged
   "meaningless reshuffling" in helperClassNames(). Rule: preserve
   master's ordering unless a semantic change requires reordering.

5. **Hoist repeated Class.getName() in contextStore() (NR-2)** — @ygree
   flagged five inlined copies of Context.class.getName() as a regression
   from master's hoist pattern.

Sources:
- docs/eval-research/cycles/2026-07-14-async-cycle-report.md RI-1, RI-4, RI-5
- @ygree PR #11939 comments 3591691401, 3591695153

skill(apm-integrations): namespace-isolation fail block + dep version parity

Adds three prescriptions to muzzle.md from async cycle iteration-1 findings
and @mcculls review feedback.

1. **Namespace-isolation fail block for major-version siblings (RI-2).**
   rxjava-3.0 master has `muzzle { fail { name = "rxjava2-must-not-match" } }`
   to assert rxjava3 advice never matches rxjava2 coordinates. Eval dropped
   the block. Rule prescribes preservation for any module with a prior-major
   sibling module in the repo.

2. **compileOnly dep version parity on regen (RI-3).** rxjava-3.0 master
   uses reactive-streams 1.0.3; eval regenerated as 1.0.0, silently
   narrowing the tested API surface. Rule extends the existing
   testImplementation parity rule to compileOnly.

3. **Test-scope build.gradle dep preservation (NR-5, @mcculls PR #11940).**
   reactor-core-3.1 eval dropped 8 testImplementation and latestDepTest
   deps that back annotation-driven tests and cross-module interop tests.
   Rule prescribes superset-of-master semantics for test deps.

skill(apm-integrations): latestDepTest source set + no banner comments in tests

Adds two prescriptions to tests.md from async cycle iteration-1 findings
and @ygree review feedback.

1. **latestDepTest source-set preservation (RI-7).** reactor-core-3.1
   master has src/latestDepTest/groovy/ for version-sensitive tests.
   The eval collapsed all tests into src/test/java/, which caused
   Schedulers.elastic() (removed in Reactor 3.4+) to break :latestDepTest
   compilation across all JVM shards. Rule prescribes preserving the
   split when master has it, and using it for libraries with breaking
   API changes across recent minor versions.

2. **No banner comments in test files (NR-4).** @ygree flagged
   `// --------- Successful completion ---------` style banners in
   RxJava3ResultExtensionTest.java as "distracting and don't offer much
   value because their scope is unclear." Rule: omit or extract into
   separate test classes with focused Javadoc.

skill(apm-integrations): no inline explanatory comments in Advice methods

Adds NR-3 from @ygree review of PR #11939. Advice bodies are typically
short; the wrapper/helper class is where reviewers look to understand
semantics. Duplicating the explanation as a `//`-comment at the advice
call site inflates the diff and drifts out of sync with the wrapper's
Javadoc.

Source: @ygree, PR #11939 comment on SingleInstrumentation.java:55.

skill(apm-integrations): address Copilot review on #11990 — latestDepTest nuance, find vs ls glob, muzzle fail scope, ContextStore implementation accuracy

skill(apm-integrations): address Codex review on #11990 — 5 P2 comments

- context-tracking.md: narrow ContextStore key rule — Reactor uses
  Publisher/Subscriber; JAX-RS uses ContainerRequestContext; Vert.x uses
  its own Context; coroutines use Continuation/CoroutineContext. Do not
  force Reactor's key type onto libraries that don't expose Publisher /
  Subscriber. Also broaden lifecycle-boundary examples per library shape.
- tests.md: distinguish latest-only APIs (belong in src/latestDepTest/)
  from removed-in-latest APIs (belong in src/test/, or use replacement
  API in latestDepTest). The Reactor Schedulers.elastic() removal is
  the removed-in-latest case, not the latest-only case.
- muzzle.md #1 (fail-block scope): explicitly show same-coordinate
  cases (jedis/okhttp/jetty-server) alongside different-coordinate
  cases (rxjava, jms api). The bounded 'versions' range in the fail
  block is what asserts non-overlap for same-coordinate siblings.
- muzzle.md #2 (test-dep preservation): extend the preservation list to
  cover testRuntimeOnly / latestDepTestRuntimeOnly / forkedTestRuntimeOnly.
  Runtime-only test deps do NOT trigger compile failures if dropped, so
  losing them silently removes cross-instrumentation coexistence coverage
  (e.g. rxjava-3.0's testRuntimeOnly on rxjava-2.0).
- instrumenter-module.md: broaden the pre-regen source-file enumeration
  from `src/main/java` to every production source set: src/main/java17,
  src/main/java11, src/main/groovy, src/main/scala, src/main/kotlin.
  Kafka-clients-3.8 and jetty-server-12.0 keep classes under java17;
  a `find` limited to `src/main/java` misses them.

All five findings are P2 severity per Codex classification; each corrects
a case where the iter-2 rule was too narrow and could mislead a regen.

skill(apm-integrations): condense regen-preservation content, wire new rules into SKILL.md

Feedback from @mcculls on this PR and separately from a senior engineer:
async is a hard area where AI output should be a starting point for
human+AI iteration, not held to a "perfect on first try" bar. Most of
this PR's new content was regen-specific "keep things stable when
rewriting" directives, disproportionate for a skill whose SKILL.md is
otherwise written entirely for the common case (writing a new
integration). 8 of the 12 new sections fell into this category.

Collapsed all 8 into a single "editing an existing module" note per
file (3 files), each a few sentences: read the current file, preserve
what's there unless you have a reason to change it, applies to
super()/package/class-set/ordering/dependencies/test-source-sets alike.
Kept exactly one concrete example (ReactorContextBridge — the
highest-stakes case, since dropping it silently breaks sibling modules
that reference the class by FQN) instead of one narrated failure story
per rule. Net: ~365 lines added by the PR, ~200 removed here.

The 4 sections that are genuine new async-instrumentation content
(library-native context maps / *ContextBridge pattern, wrap-placement
memory considerations, no-inline-advice-comments, no-banner-comments)
are unchanged — those aren't regen-specific, they apply to any reactive
library instrumentation, new or edited.

Also addresses the Datadog Autotest P1 finding (2026-07-21): the new
rules existed in reference files but SKILL.md's per-step pointers were
generic ("read this file") rather than pointing at the specific new
subsections. Added explicit pointers at Steps 4.1, 5, 7, and 9.2/9.3 so
a code-gen LLM sees "read the ContextBridge section" / "add the
namespace-isolation fail block" inline in its step-by-step flow instead
of needing to discover them by skimming a 200+ line reference file.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

heading fix

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

skill(apm-integrations): fix 4 factual errors from Codex review — verified against dd-trace-java source

Codex flagged (2026-07-23) that the previous fix broadening the
ContextBridge rule beyond Reactor invented plausible-sounding but
factually wrong specifics for 3 libraries. Verified each claim against
actual dd-trace-java modules before fixing:

- JAX-RS: SKILL.md listed it as needing a ContextTracking bridge, but
  AbstractRequestContextInstrumentation extends InstrumenterModule.Tracing
  — it's span-owning code, not context-tracking. Removed the JAX-RS
  mention from SKILL.md and context-tracking.md entirely.

- Kotlin coroutines: told agents to key a ContextStore by
  Continuation/CoroutineContext, but KotlinCoroutinesModule has no
  contextStore() at all — it uses ThreadContextElement
  (DatadogThreadContextElement implements ThreadContextElement<Context>).
  Corrected to point at the actual pattern.

- Vert.x: told agents to key by io.vertx.core.Context, but that type is
  shared across many handler executions on the same Vert.x context —
  existing vertx-web instrumentation keys per-request state on
  RoutingContext instead. Keying by core Context would cause
  cross-request parentage. Corrected to point at RoutingContext.

- Reactor wrap-placement: the "prefer subscriber over publisher key"
  guidance implied these were alternatives, but master's
  ReactorCoreModule.contextStore() keys BOTH Publisher (via
  HandoffContext, read before a subscriber exists) AND Subscriber (via
  Context, for the wrapping pattern) — they're complementary, not a
  choice. Reworded so the publisher-keyed store is called out as exempt
  from the "prefer bounded lifetime" optimization.

Also fixed a latestDepTest gap Codex found: the prior wording said to
put removed-in-latest-version tests in src/test/, but that's only safe
when the module uses addTestSuite('latestDepTest') with separate
sources. Modules using addTestSuiteForDir('latestDepTest', 'test')
reuse src/test/ for both suites, so a removed-API test placed there
still gets compiled against latestDepTestImplementation and fails the
same way. Split the guidance by which build.gradle wiring the module
uses.

Root cause: the earlier fix (responding to a prior Codex comment about
Reactor-only bias) generalized to other libraries from category-level
reasoning ("JAX-RS surely uses a context map like Reactor does") rather
than reading those libraries' actual dd-trace-java modules first. Fixed
per the java-eval-research skill's canonical-first rule: don't publish
a claim about library-specific behavior without checking the source.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Merge branch 'master' into feat/skill-async-iteration-2

Co-authored-by: devflow.devflow-routing-intake <devflow.devflow-routing-intake@kubernetes.us1.ddbuild.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

inst: reactor Reactor instrumentation tag: do not merge Do not merge changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants