diff --git a/java/sdk/src/test/java/com/github/copilot/e2e/InProcessTransportIT.java b/java/sdk/src/test/java/com/github/copilot/e2e/InProcessTransportIT.java
index 83d45a85d2..1b8595401a 100644
--- a/java/sdk/src/test/java/com/github/copilot/e2e/InProcessTransportIT.java
+++ b/java/sdk/src/test/java/com/github/copilot/e2e/InProcessTransportIT.java
@@ -43,7 +43,8 @@
* in-process.
*
*
- * Run with {@code mvn verify -Pinprocess} from {@code java/sdk}, which sets
+ * Run with {@code mvn verify -Pinprocess} from the {@code java} reactor root,
+ * which builds the {@code copilot-sdk-java-runtime} artifact and sets
* {@code COPILOT_CLI_PATH} to the pinned CLI whose sibling {@code runtime.node}
* this test loads, and forces {@code forkCount=1} because the FFI host and env
* guard mutate process-global state.
diff --git a/java/sdk/src/test/java/com/github/copilot/ffi/InProcessEnvGuard.java b/java/sdk/src/test/java/com/github/copilot/ffi/InProcessEnvGuard.java
index f23d4b7553..8217d25d2e 100644
--- a/java/sdk/src/test/java/com/github/copilot/ffi/InProcessEnvGuard.java
+++ b/java/sdk/src/test/java/com/github/copilot/ffi/InProcessEnvGuard.java
@@ -60,6 +60,8 @@ public final class InProcessEnvGuard implements AutoCloseable {
*/
private interface Kernel32Env extends Library {
boolean SetEnvironmentVariableW(WString lpName, WString lpValue);
+
+ int GetEnvironmentVariableW(WString lpName, char[] lpBuffer, int nSize);
}
/** POSIX libc: sets or deletes a variable in the process environment block. */
@@ -67,8 +69,16 @@ private interface LibcEnv extends Library {
int setenv(String name, String value, int overwrite);
int unsetenv(String name);
+
+ /** Returns null if the variable is not set. */
+ String getenv(String name);
}
+ /**
+ * Sentinel indicating the variable was not set (distinct from empty string).
+ */
+ private static final String ABSENT_SENTINEL = new String("\0ABSENT\0");
+
/**
* name -> previous value ({@code null} means the variable was not set before).
*/
@@ -88,7 +98,7 @@ public InProcessEnvGuard(Map applyEnv) {
apply(entry.getKey(), entry.getValue());
}
for (String key : SUPPRESSED_KEYS) {
- String previous = System.getenv(key);
+ String previous = nativeGetEnv(key);
if (previous != null && !previous.isEmpty()) {
apply(key, null);
}
@@ -96,8 +106,8 @@ public InProcessEnvGuard(Map applyEnv) {
}
private void apply(String name, String value) {
- String previous = System.getenv(name);
- saved.add(Map.entry(name, previous == null ? "" : previous));
+ String previous = nativeGetEnv(name);
+ saved.add(Map.entry(name, previous == null ? ABSENT_SENTINEL : previous));
nativeSetEnv(name, value);
}
@@ -110,10 +120,35 @@ public void close() {
List> reversed = new ArrayList<>(saved);
Collections.reverse(reversed);
for (Map.Entry entry : reversed) {
- nativeSetEnv(entry.getKey(), entry.getValue().isEmpty() ? null : entry.getValue());
+ String restoreValue = entry.getValue() == ABSENT_SENTINEL ? null : entry.getValue();
+ nativeSetEnv(entry.getKey(), restoreValue);
}
}
+ private static String nativeGetEnv(String name) {
+ if (isWindows()) {
+ return nativeGetEnvWindows(name);
+ } else {
+ return nativeGetEnvUnix(name);
+ }
+ }
+
+ private static String nativeGetEnvWindows(String name) {
+ Kernel32Env kernel32 = Native.load("kernel32", Kernel32Env.class);
+ char[] buffer = new char[32767];
+ int len = kernel32.GetEnvironmentVariableW(new WString(name), buffer, buffer.length);
+ if (len == 0) {
+ // Variable not set (or error — treat as absent)
+ return null;
+ }
+ return new String(buffer, 0, len);
+ }
+
+ private static String nativeGetEnvUnix(String name) {
+ LibcEnv libc = Native.load("c", LibcEnv.class);
+ return libc.getenv(name);
+ }
+
private static void nativeSetEnv(String name, String value) {
if (isWindows()) {
nativeSetEnvWindows(name, value);
From eb7243006221cbdc0a02ed897d2bc8d44c126070 Mon Sep 17 00:00:00 2001
From: Ed Burns
Date: Tue, 4 Aug 2026 00:29:35 +0000
Subject: [PATCH 6/6] Scope -Pinprocess Failsafe includes to
InProcessTransportIT only
Existing ITs set Environment/Cwd options incompatible with InProcess
transport. Restrict the profile to only the in-process smoke test until
the full in-process E2E suite is implemented.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
java/sdk/pom.xml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/java/sdk/pom.xml b/java/sdk/pom.xml
index c408840486..9bfe76a4b8 100644
--- a/java/sdk/pom.xml
+++ b/java/sdk/pom.xml
@@ -626,6 +626,9 @@ did not produce the multi-release output. Re-build on JDK 25+ and verify the
1
none
+
+ **/InProcessTransportIT.java
+
${copilot.inprocess.cli.path}
inprocess